Blob Blame History Raw
diff -up evolution-3.22.6/composer/e-composer-private.c.composer-image-insert-undo evolution-3.22.6/composer/e-composer-private.c
--- evolution-3.22.6/composer/e-composer-private.c.composer-image-insert-undo	2016-09-19 10:22:58.000000000 +0200
+++ evolution-3.22.6/composer/e-composer-private.c	2017-03-24 15:12:21.893422514 +0100
@@ -134,8 +134,6 @@ e_composer_private_constructed (EMsgComp
 	priv->disable_signature = FALSE;
 	priv->busy = FALSE;
 	priv->saved_editable = FALSE;
-	priv->drop_occured = FALSE;
-	priv->dnd_is_uri = FALSE;
 	priv->dnd_history_saved = FALSE;
 	priv->check_if_signature_is_changed = FALSE;
 	priv->ignore_next_signature_change = FALSE;
diff -up evolution-3.22.6/composer/e-composer-private.h.composer-image-insert-undo evolution-3.22.6/composer/e-composer-private.h
--- evolution-3.22.6/composer/e-composer-private.h.composer-image-insert-undo	2016-09-19 10:22:58.000000000 +0200
+++ evolution-3.22.6/composer/e-composer-private.h	2017-03-24 15:12:21.893422514 +0100
@@ -100,8 +100,6 @@ struct _EMsgComposerPrivate {
 	 * This is used to restore the previous editable state. */
 	gboolean saved_editable;
 	gboolean set_signature_from_message;
-	gboolean drop_occured;
-	gboolean dnd_is_uri;
 	gboolean is_sending_message;
 	gboolean dnd_history_saved;
 	gboolean check_if_signature_is_changed;
@@ -119,6 +117,8 @@ struct _EMsgComposerPrivate {
 	gulong notify_signature_uid_handler;
 	gulong notify_subject_handler;
 	gulong notify_subject_changed_handler;
+
+	gulong drag_data_received_handler_id;
 };
 
 void		e_composer_private_constructed	(EMsgComposer *composer);
diff -up evolution-3.22.6/composer/e-msg-composer.c.composer-image-insert-undo evolution-3.22.6/composer/e-msg-composer.c
--- evolution-3.22.6/composer/e-msg-composer.c.composer-image-insert-undo	2016-11-30 20:06:07.000000000 +0100
+++ evolution-3.22.6/composer/e-msg-composer.c	2017-03-24 15:12:21.894422514 +0100
@@ -105,24 +105,14 @@ enum {
 	LAST_SIGNAL
 };
 
-enum DndTargetType {
-	DND_TARGET_TYPE_TEXT_URI_LIST,
-	DND_TARGET_TYPE_MOZILLA_URL,
-	DND_TARGET_TYPE_TEXT_HTML,
-	DND_TARGET_TYPE_UTF8_STRING,
-	DND_TARGET_TYPE_TEXT_PLAIN,
-	DND_TARGET_TYPE_STRING,
-	DND_TARGET_TYPE_TEXT_PLAIN_UTF8
-};
-
 static GtkTargetEntry drag_dest_targets[] = {
-	{ (gchar *) "text/uri-list", 0, DND_TARGET_TYPE_TEXT_URI_LIST },
-	{ (gchar *) "_NETSCAPE_URL", 0, DND_TARGET_TYPE_MOZILLA_URL },
-	{ (gchar *) "text/html", 0, DND_TARGET_TYPE_TEXT_HTML },
-	{ (gchar *) "UTF8_STRING", 0, DND_TARGET_TYPE_UTF8_STRING },
-	{ (gchar *) "text/plain", 0, DND_TARGET_TYPE_TEXT_PLAIN },
-	{ (gchar *) "STRING", 0, DND_TARGET_TYPE_STRING },
-	{ (gchar *) "text/plain;charset=utf-8", 0, DND_TARGET_TYPE_TEXT_PLAIN_UTF8 },
+	{ (gchar *) "text/uri-list", 0, E_DND_TARGET_TYPE_TEXT_URI_LIST },
+	{ (gchar *) "_NETSCAPE_URL", 0, E_DND_TARGET_TYPE_MOZILLA_URL },
+	{ (gchar *) "text/html", 0, E_DND_TARGET_TYPE_TEXT_HTML },
+	{ (gchar *) "UTF8_STRING", 0, E_DND_TARGET_TYPE_UTF8_STRING },
+	{ (gchar *) "text/plain", 0, E_DND_TARGET_TYPE_TEXT_PLAIN },
+	{ (gchar *) "STRING", 0, E_DND_TARGET_TYPE_STRING },
+	{ (gchar *) "text/plain;charset=utf-8", 0, E_DND_TARGET_TYPE_TEXT_PLAIN_UTF8 },
 };
 
 static guint signals[LAST_SIGNAL];
@@ -1784,160 +1774,6 @@ msg_composer_paste_clipboard_cb (EConten
 
 	return TRUE;
 }
-#if 0 /* FIXME WK2 */
-static gboolean
-msg_composer_drag_motion_cb (GtkWidget *widget,
-                             GdkDragContext *context,
-                             gint x,
-                             gint y,
-                             guint time,
-                             EMsgComposer *composer)
-{
-	GtkWidget *source_widget;
-	EHTMLEditor *editor = e_msg_composer_get_editor (composer);
-	EHTMLEditorView *editor_view = e_html_editor_get_view (editor);
-
-	source_widget = gtk_drag_get_source_widget (context);
-	/* When we are doind DnD just inside the web view, the DnD is supposed
-	 * to move things around. */
-	if (E_IS_HTML_EDITOR_VIEW (source_widget)) {
-		if ((gpointer) editor_view == (gpointer) source_widget) {
-			gdk_drag_status (context, GDK_ACTION_MOVE, time);
-
-			return FALSE;
-		}
-	}
-
-	gdk_drag_status (context, GDK_ACTION_COPY, time);
-
-	return FALSE;
-}
-
-static gboolean
-msg_composer_drag_drop_cb (GtkWidget *widget,
-                           GdkDragContext *context,
-                           gint x,
-                           gint y,
-                           guint time,
-                           EMsgComposer *composer)
-{
-	GdkAtom target;
-	GtkWidget *source_widget;
-
-	/* When we are doing DnD just inside the web view, the DnD is supposed
-	 * to move things around. */
-	source_widget = gtk_drag_get_source_widget (context);
-	if (E_IS_HTML_EDITOR_VIEW (source_widget)) {
-		EHTMLEditor *editor = e_msg_composer_get_editor (composer);
-		EHTMLEditorView *editor_view = e_html_editor_get_view (editor);
-
-		if ((gpointer) editor_view == (gpointer) source_widget) {
-			GDBusProxy *web_extension;
-
-			web_extension = e_html_editor_view_get_web_extension_proxy (editor_view);
-			if (web_extension) {
-				e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-					web_extension,
-					"DOMSaveDragAndDropHistory",
-					g_variant_new (
-						"(t)",
-						webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (editor_view))),
-					NULL);
-			}
-			return FALSE;
-		}
-	}
-
-	target = gtk_drag_dest_find_target (widget, context, NULL);
-	if (target == GDK_NONE)
-		gdk_drag_status (context, 0, time);
-	else {
-		/* Prevent WebKit from pasting the URI of file into the view. Also
-		 * prevent it from inserting the text/plain or text/html content as we
-		 * want to insert it ourselves. */
-		if (composer->priv->dnd_is_uri || !E_IS_HTML_EDITOR_VIEW (source_widget))
-			g_signal_stop_emission_by_name (widget, "drag-drop");
-
-		composer->priv->dnd_is_uri = FALSE;
-
-		if (E_IS_HTML_EDITOR_VIEW (source_widget))
-			gdk_drag_status (context, GDK_ACTION_MOVE, time);
-		else
-			gdk_drag_status (context, GDK_ACTION_COPY, time);
-
-		composer->priv->drop_occured = TRUE;
-		gtk_drag_get_data (widget, context, target, time);
-
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-static void
-msg_composer_drag_data_received_after_cb (GtkWidget *widget,
-                                          GdkDragContext *context,
-                                          gint x,
-                                          gint y,
-                                          GtkSelectionData *selection,
-                                          guint info,
-                                          guint time,
-                                          EMsgComposer *composer)
-{
-	EHTMLEditor *editor;
-	EHTMLEditorView *view;
-	GDBusProxy *web_extension;
-
-	if (!composer->priv->drop_occured)
-		goto out;
-
-	/* Save just history for events handled by WebKit. */
-	if (composer->priv->dnd_history_saved)
-		goto out;
-
-	editor = e_msg_composer_get_editor (composer);
-	view = e_html_editor_get_view (editor);
-	web_extension = e_html_editor_view_get_web_extension_proxy (view);
-	if (!web_extension)
-		goto out;
-
-	e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-		web_extension,
-		"DOMCleanAfterDragAndDrop",
-		g_variant_new (
-			"(t)",
-			webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (view))),
-		NULL);
-
- out:
-	composer->priv->drop_occured = FALSE;
-	composer->priv->dnd_history_saved = FALSE;
-}
-
-static gchar *
-next_uri (guchar **uri_list,
-          gint *len,
-          gint *list_len)
-{
-	guchar *uri, *begin;
-
-	begin = *uri_list;
-	*len = 0;
-	while (**uri_list && **uri_list != '\n' && **uri_list != '\r' && *list_len) {
-		(*uri_list) ++;
-		(*len) ++;
-		(*list_len) --;
-	}
-
-	uri = (guchar *) g_strndup ((gchar *) begin, *len);
-
-	while ((!**uri_list || **uri_list == '\n' || **uri_list == '\r') && *list_len) {
-		(*uri_list) ++;
-		(*list_len) --;
-	}
-
-	return (gchar *) uri;
-}
 
 static void
 msg_composer_drag_data_received_cb (GtkWidget *widget,
@@ -1951,90 +1787,16 @@ msg_composer_drag_data_received_cb (GtkW
 {
 	EHTMLEditor *editor;
 	EContentEditor *cnt_editor;
-	gboolean html_mode, same_widget = FALSE;
-	GtkWidget *source_widget;
+	gboolean html_mode, is_move;
 
 	editor = e_msg_composer_get_editor (composer);
 	cnt_editor = e_html_editor_get_content_editor (editor);
 	html_mode = e_content_editor_get_html_mode (cnt_editor);
 
-	composer->priv->dnd_history_saved = TRUE;
-
-	/* When we are doing DnD just inside the web view, the DnD is supposed
-	 * to move things around. */
-	source_widget = gtk_drag_get_source_widget (context);
-	if (E_IS_CONTENT_EDITOR (source_widget) &&
-	    ((gpointer) cnt_editor == (gpointer) source_widget))
-		same_widget = TRUE;
-
-	/* Leave DnD inside the view on WebKit. */
-	if (composer->priv->drop_occured && same_widget) {
-		gdk_drag_status (context, 0, time);
-		return;
-	}
-
-	if (!composer->priv->drop_occured) {
-		if (!same_widget) {
-			/* Check if we are DnD'ing some URI, if so WebKit will
-			 * insert the URI into the view and we have to prevent it
-			 * from doing that. */
-			if (info == DND_TARGET_TYPE_TEXT_URI_LIST) {
-				gchar **uris;
-
-				uris = gtk_selection_data_get_uris (selection);
-				/* I don't know what regressed outside of Evo, but
-				 * this is called twice. Firstly with uris set
-				 * following by one with uris not set. */
-				if (!composer->priv->dnd_is_uri)
-					composer->priv->dnd_is_uri = uris != NULL;
-				g_strfreev (uris);
-			}
-		}
-		return;
-	}
+	g_signal_handler_disconnect (cnt_editor, composer->priv->drag_data_received_handler_id);
+	composer->priv->drag_data_received_handler_id = 0;
 
-	composer->priv->dnd_is_uri = FALSE;
-
-	/* Leave the text on WebKit to handle it. */
-	if (info == DND_TARGET_TYPE_UTF8_STRING ||
-	    info == DND_TARGET_TYPE_STRING ||
-	    info == DND_TARGET_TYPE_TEXT_PLAIN ||
-	    info == DND_TARGET_TYPE_TEXT_PLAIN_UTF8) {
-		composer->priv->dnd_history_saved = FALSE;
-		gdk_drag_status (context, 0, time);
-		return;
-	}
-
-	if (info == DND_TARGET_TYPE_TEXT_HTML) {
-		const guchar *data;
-		gint length;
-		gint list_len, len;
-		gchar *text;
-
-		data = gtk_selection_data_get_data (selection);
-		length = gtk_selection_data_get_length (selection);
-
-		if (!data || length < 0) {
-			gtk_drag_finish (context, FALSE, FALSE, time);
-			return;
-		}
-
-		e_content_editor_move_caret_on_coordinates (cnt_editor, x, y, FALSE);
-
-		list_len = length;
-		do {
-			text = next_uri ((guchar **) &data, &len, &list_len);
-			e_content_editor_insert_content (
-				cnt_editor,
-				text,
-				E_CONTENT_EDITOR_INSERT_TEXT_HTML);
-			g_free (text);
-		} while (list_len);
-
-		gtk_drag_finish (context, TRUE, FALSE, time);
-
-		return;
-	}
+	is_move = gdk_drag_context_get_selected_action (context) == GDK_ACTION_MOVE;
 
 	/* HTML mode has a few special cases for drops... */
 	/* If we're receiving URIs and -all- the URIs point to
@@ -2060,12 +1822,12 @@ msg_composer_drag_data_received_cb (GtkW
 
 		list_len = length;
 		do {
-			uri = next_uri ((guchar **) &data, &len, &list_len);
+			uri = e_util_next_uri_from_uri_list ((guchar **) &data, &len, &list_len);
 			e_content_editor_insert_image (cnt_editor, uri);
 			g_free (uri);
 		} while (list_len);
 
-		gtk_drag_finish (context, TRUE, FALSE, time);
+		gtk_drag_finish (context, TRUE, is_move, time);
 	} else {
 		EAttachmentView *attachment_view =
 			e_msg_composer_get_attachment_view (composer);
@@ -2078,7 +1840,43 @@ msg_composer_drag_data_received_cb (GtkW
 			context, x, y, selection, info, time);
 	}
 }
-#endif
+
+static gboolean
+msg_composer_drag_drop_cb (GtkWidget *widget,
+                           GdkDragContext *context,
+                           gint x,
+                           gint y,
+                           guint time,
+                           EMsgComposer *composer)
+{
+	GdkAtom target = gtk_drag_dest_find_target (widget, context, NULL);
+
+	if (target == GDK_NONE) {
+		gdk_drag_status (context, 0, time);
+	} else {
+		composer->priv->drag_data_received_handler_id = g_signal_connect (
+			E_CONTENT_EDITOR (widget), "drag-data-received",
+			G_CALLBACK (msg_composer_drag_data_received_cb), composer);
+
+		gtk_drag_get_data (widget, context, target, time);
+
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+static void
+msg_composer_drag_begin_cb (GtkWidget *widget,
+                            GdkDragContext *context,
+                            EMsgComposer *composer)
+{
+	if (composer->priv->drag_data_received_handler_id != 0) {
+		g_signal_handler_disconnect (E_CONTENT_EDITOR( widget), composer->priv->drag_data_received_handler_id);
+		composer->priv->drag_data_received_handler_id = 0;
+	}
+}
+
 static void
 msg_composer_notify_header_cb (EMsgComposer *composer)
 {
@@ -2465,28 +2263,14 @@ msg_composer_constructed (GObject *objec
 		G_CALLBACK (msg_composer_paste_primary_clipboard_cb), composer);
 
 	/* Drag-and-Drop Support */
-#if 0 /* FIXME WK2 */
-	EHTMLEditorView *view;
-
-	view = e_html_editor_get_view (editor);
-
 	g_signal_connect (
-		view, "drag-motion",
-		G_CALLBACK (msg_composer_drag_motion_cb), composer);
-
-	 g_signal_connect (
-		view, "drag-drop",
+		cnt_editor, "drag-drop",
 		G_CALLBACK (msg_composer_drag_drop_cb), composer);
 
 	g_signal_connect (
-		view, "drag-data-received",
-		G_CALLBACK (msg_composer_drag_data_received_cb), composer);
+		cnt_editor, "drag-begin",
+		G_CALLBACK (msg_composer_drag_begin_cb), composer);
 
-	/* Used for fixing various stuff after WebKit processed the DnD data. */
-	g_signal_connect_after (
-		view, "drag-data-received",
-		G_CALLBACK (msg_composer_drag_data_received_after_cb), composer);
-#endif
 	g_signal_connect (
 		composer->priv->gallery_icon_view, "drag-data-get",
 		G_CALLBACK (msg_composer_gallery_drag_data_get), NULL);
@@ -5531,8 +5315,6 @@ e_msg_composer_restore_focus_on_composer
 
 	if (E_IS_CONTENT_EDITOR (widget)) {
 		EContentEditor *cnt_editor = E_CONTENT_EDITOR (widget);
-		/* FIXME WK2
-		e_html_editor_view_force_spell_check (view);*/
 		e_content_editor_selection_restore (cnt_editor);
 	}
 
diff -up evolution-3.22.6/e-util/e-attachment-view.c.composer-image-insert-undo evolution-3.22.6/e-util/e-attachment-view.c
--- evolution-3.22.6/e-util/e-attachment-view.c.composer-image-insert-undo	2016-09-19 10:22:58.000000000 +0200
+++ evolution-3.22.6/e-util/e-attachment-view.c	2017-03-24 15:12:21.894422514 +0100
@@ -39,6 +39,7 @@ enum {
 
 /* Note: Do not use the info field. */
 static GtkTargetEntry target_table[] = {
+	{ (gchar *) "text/uri-list", 0, 0 },
 	{ (gchar *) "_NETSCAPE_URL", 0, 0 }
 };
 
@@ -428,6 +429,125 @@ attachment_view_netscape_url (EAttachmen
 }
 
 static void
+attachment_view_uri_list (EAttachmentView *view,
+                          GdkDragContext *drag_context,
+                          gint x,
+                          gint y,
+                          GtkSelectionData *selection_data,
+                          guint info,
+                          guint time)
+{
+	static GdkAtom atom = GDK_NONE;
+	EAttachmentStore *store;
+	EAttachment *attachment;
+	const gchar *data;
+	gpointer parent;
+	gint length = 0, list_length = 0, uri_length = 0;
+	gchar *uri;
+
+
+	if (G_UNLIKELY (atom == GDK_NONE))
+		atom = gdk_atom_intern_static_string ("text/uri-list");
+
+	if (gtk_selection_data_get_target (selection_data) != atom)
+		return;
+
+	g_signal_stop_emission_by_name (view, "drag-data-received");
+
+	data = (const gchar *) gtk_selection_data_get_data (selection_data);
+	length = gtk_selection_data_get_length (selection_data);
+
+	if (!data || length < 0) {
+		gtk_drag_finish (drag_context, FALSE, FALSE, time);
+		return;
+	}
+
+	store = e_attachment_view_get_store (view);
+
+	parent = gtk_widget_get_toplevel (GTK_WIDGET (view));
+	parent = gtk_widget_is_toplevel (parent) ? parent : NULL;
+
+	list_length = length;
+	do {
+		uri = e_util_next_uri_from_uri_list ((guchar **) &data, &uri_length, &list_length);
+
+		if (strstr (uri, ";base64,")) {
+			/* base64 encoded data */
+			CamelMimePart *mime_part;
+			gchar *mime_type = NULL, *filename = NULL;
+			guchar *base64_data;
+			gsize base64_data_length;
+
+			if (g_str_has_prefix (uri, "data:")) {
+				const gchar *base64 = strstr (uri, ";") + 1;
+				/* strlen ("data:") == 5 */
+				mime_type = g_strndup (uri + 5, base64 - uri - 5 - 1);
+
+				base64 = strstr (base64, ",") + 1;
+				base64_data = g_base64_decode (base64, &base64_data_length);
+			} else if (strstr (uri, ";data")) {
+				/* CID attachment from mail preview that has
+				 * the filename prefixed before the base64 data -
+				 * see EMailDisplay. */
+				const gchar *base64 = strstr (uri, ";") + 1;
+				glong filename_length, mime_type_length, base64_length;
+
+				base64_length = g_utf8_strlen (base64, -1);
+
+				filename_length = uri_length - base64_length - 1;
+				filename = g_strndup (uri, filename_length);
+
+				/* strlen ("data:") == 5 */
+				mime_type_length = base64_length - g_utf8_strlen (strstr (base64, ";"), -1) - 5;
+				mime_type = g_strndup (uri + filename_length + 5 + 1, mime_type_length);
+
+				base64 = strstr (base64, ",") + 1;
+				base64_data = g_base64_decode (base64, &base64_data_length);
+			} else {
+				g_free (uri);
+				gtk_drag_finish (drag_context, FALSE, FALSE, time);
+				return;
+			}
+
+			mime_part = camel_mime_part_new ();
+
+			camel_mime_part_set_content (mime_part, (const gchar *) base64_data, base64_data_length, mime_type);
+			camel_mime_part_set_disposition (mime_part, "inline");
+			if (filename && *filename)
+				camel_mime_part_set_filename (mime_part, filename);
+			camel_mime_part_set_encoding (mime_part, CAMEL_TRANSFER_ENCODING_BASE64);
+
+			attachment = e_attachment_new ();
+			e_attachment_set_mime_part (attachment, mime_part);
+			e_attachment_store_add_attachment (store, attachment);
+			e_attachment_load_async (
+				attachment, (GAsyncReadyCallback)
+				call_attachment_load_handle_error, parent ? g_object_ref (parent) : NULL);
+
+			g_object_unref (attachment);
+			g_object_unref (mime_part);
+			if (mime_type)
+				g_free (mime_type);
+			if (filename)
+				g_free (filename);
+			g_free (base64_data);
+		} else {
+			/* regular URIs */
+			attachment = e_attachment_new_for_uri (uri);
+			e_attachment_store_add_attachment (store, attachment);
+			e_attachment_load_async (
+				attachment, (GAsyncReadyCallback)
+				call_attachment_load_handle_error, parent ? g_object_ref (parent) : NULL);
+			g_object_unref (attachment);
+		}
+
+		g_free (uri);
+	} while (list_length);
+
+	gtk_drag_finish (drag_context, TRUE, FALSE, time);
+}
+
+static void
 attachment_view_text_calendar (EAttachmentView *view,
                                GdkDragContext *drag_context,
                                gint x,
@@ -809,6 +929,10 @@ e_attachment_view_init (EAttachmentView
 
 	g_signal_connect (
 		view, "drag-data-received",
+		G_CALLBACK (attachment_view_uri_list), NULL);
+
+	g_signal_connect (
+		view, "drag-data-received",
 		G_CALLBACK (attachment_view_text_x_vcard), NULL);
 
 	g_signal_connect (
diff -up evolution-3.22.6/e-util/e-html-editor-dialog.h.composer-image-insert-undo evolution-3.22.6/e-util/e-html-editor-dialog.h
--- evolution-3.22.6/e-util/e-html-editor-dialog.h.composer-image-insert-undo	2016-09-19 10:22:58.000000000 +0200
+++ evolution-3.22.6/e-util/e-html-editor-dialog.h	2017-03-24 15:12:21.894422514 +0100
@@ -62,16 +62,6 @@ struct _EHTMLEditorDialogClass {
 	GtkWindowClass parent_class;
 };
 
-#if 0 /* FIXME WK2 */
-struct _EContentEditorDialogInterface {
-	GTypeInterface parent_interface;
-
-	void		(*dialog_opened)		(EContentEditorDialog *dialog);
-
-	void		(*dialog_closed)		(EContentEditorDialog *dialog);
-};
-#endif
-
 GType		e_html_editor_dialog_get_type	(void) G_GNUC_CONST;
 EHTMLEditor *	e_html_editor_dialog_get_editor	(EHTMLEditorDialog *dialog);
 GtkBox *	e_html_editor_dialog_get_button_box
diff -up evolution-3.22.6/e-util/e-misc-utils.c.composer-image-insert-undo evolution-3.22.6/e-util/e-misc-utils.c
--- evolution-3.22.6/e-util/e-misc-utils.c.composer-image-insert-undo	2017-01-18 11:36:05.000000000 +0100
+++ evolution-3.22.6/e-util/e-misc-utils.c	2017-03-24 15:12:21.894422514 +0100
@@ -3908,3 +3908,38 @@ e_util_get_webkit_developer_mode_enabled
 
 	return enabled != 0;
 }
+
+/**
+ * e_util_next_uri_from_uri_list:
+ * @uri_list: array of URIs separated by new lines
+ * @len: (out): a length of the found URI
+ * @list_len: (out): a length of the array
+ *
+ * Returns: A newly allocated string with found URI.
+ *
+ * Since: 3.26
+ **/
+gchar *
+e_util_next_uri_from_uri_list (guchar **uri_list,
+                               gint *len,
+                               gint *list_len)
+{
+	guchar *uri, *begin;
+
+	begin = *uri_list;
+	*len = 0;
+	while (**uri_list && **uri_list != '\n' && **uri_list != '\r' && *list_len) {
+		(*uri_list) ++;
+		(*len) ++;
+		(*list_len) --;
+	}
+
+	uri = (guchar *) g_strndup ((gchar *) begin, *len);
+
+	while ((!**uri_list || **uri_list == '\n' || **uri_list == '\r') && *list_len) {
+		(*uri_list) ++;
+		(*list_len) --;
+	}
+
+	return (gchar *) uri;
+}
diff -up evolution-3.22.6/e-util/e-misc-utils.h.composer-image-insert-undo evolution-3.22.6/e-util/e-misc-utils.h
--- evolution-3.22.6/e-util/e-misc-utils.h.composer-image-insert-undo	2017-01-18 11:36:05.000000000 +0100
+++ evolution-3.22.6/e-util/e-misc-utils.h	2017-03-24 15:12:21.894422514 +0100
@@ -332,6 +332,9 @@ void		e_util_save_file_chooser_folder	(G
 void		e_util_load_file_chooser_folder	(GtkFileChooser *file_chooser);
 gboolean	e_util_get_webkit_developer_mode_enabled
 						(void);
+gchar *		e_util_next_uri_from_uri_list	(guchar **uri_list,
+						 gint *len,
+						 gint *list_len);
 
 G_END_DECLS
 
diff -up evolution-3.22.6/e-util/e-util-enums.h.composer-image-insert-undo evolution-3.22.6/e-util/e-util-enums.h
--- evolution-3.22.6/e-util/e-util-enums.h.composer-image-insert-undo	2016-11-28 16:56:59.000000000 +0100
+++ evolution-3.22.6/e-util/e-util-enums.h	2017-03-24 15:12:21.894422514 +0100
@@ -548,6 +548,30 @@ typedef enum {
 	E_CLIPBOARD_CAN_PASTE	= 1 << 2 */
 } EClipboardFlags;
 
+/**
+ * EDnDTargetType:
+ * DND_TARGET_TYPE_TEXT_URI_LIST: text/uri-list
+ * DND_TARGET_TYPE_MOZILLA_URL: _NETSCAPE_URL
+ * DND_TARGET_TYPE_TEXT_HTML: text/html
+ * DND_TARGET_TYPE_UTF8_STRING: UTF8_STRING
+ * DND_TARGET_TYPE_TEXT_PLAIN: text/plain
+ * DND_TARGET_TYPE_STRING: STRING
+ * DND_TARGET_TYPE_TEXT_PLAIN_UTF8: text/plain;charser=utf-8
+ *
+ * Drag and drop targets supported by EContentEditor.
+ *
+ * Since: 3.26
+ **/
+typedef enum {
+	E_DND_TARGET_TYPE_TEXT_URI_LIST = 0,
+	E_DND_TARGET_TYPE_MOZILLA_URL,
+	E_DND_TARGET_TYPE_TEXT_HTML,
+	E_DND_TARGET_TYPE_UTF8_STRING,
+	E_DND_TARGET_TYPE_TEXT_PLAIN,
+	E_DND_TARGET_TYPE_STRING,
+	E_DND_TARGET_TYPE_TEXT_PLAIN_UTF8
+} EDnDTargetType;
+
 G_END_DECLS
 
 #endif /* E_UTIL_ENUMS_H */
diff -up evolution-3.22.6/e-util/e-web-view.c.composer-image-insert-undo evolution-3.22.6/e-util/e-web-view.c
--- evolution-3.22.6/e-util/e-web-view.c.composer-image-insert-undo	2017-01-27 12:06:11.000000000 +0100
+++ evolution-3.22.6/e-util/e-web-view.c	2017-03-24 15:12:21.895422514 +0100
@@ -2386,11 +2386,7 @@ e_web_view_init (EWebView *web_view)
 	g_signal_connect (
 		web_view, "load-changed",
 		G_CALLBACK (web_view_load_changed_cb), NULL);
-/* FIXME WK2
-	g_signal_connect (
-		web_view, "document-load-finished",
-		G_CALLBACK (style_updated_cb), NULL);
-*/
+
 	g_signal_connect (
 		web_view, "style-updated",
 		G_CALLBACK (style_updated_cb), NULL);
diff -up evolution-3.22.6/e-util/test-html-editor-units.c.composer-image-insert-undo evolution-3.22.6/e-util/test-html-editor-units.c
--- evolution-3.22.6/e-util/test-html-editor-units.c.composer-image-insert-undo	2017-03-24 15:12:21.888422514 +0100
+++ evolution-3.22.6/e-util/test-html-editor-units.c	2017-03-24 15:12:21.895422514 +0100
@@ -978,6 +978,8 @@ test_image_insert (TestFixture *fixture)
 	/* Mimic what the action:insert-image does, without invoking the image chooser dialog */
 	cnt_editor = e_html_editor_get_content_editor (fixture->editor);
 	e_content_editor_insert_image (cnt_editor, uri);
+	/* Wait some time until the operation is finished */
+	test_utils_wait_milliseconds (500);
 
 	g_free (uri);
 
@@ -991,6 +993,10 @@ test_image_insert (TestFixture *fixture)
 	g_free (image_data);
 
 	if (!test_utils_run_simple_test (fixture,
+		"undo:save\n" /* 1 */
+		"undo:undo\n"
+		"undo:redo\n"
+		"undo:test:1\n"
 		"type:+after\n",
 		expected_html,
 		"before*+after"))
@@ -2663,6 +2669,48 @@ test_delete_after_quoted (TestFixture *f
 		g_test_fail ();
 }
 
+static void
+test_replace_dialog (TestFixture *fixture)
+{
+	if (!test_utils_run_simple_test (fixture,
+		"mode:plain\n"
+		"type:text to replace\n"
+		"undo:save\n"	/* 1 */
+		"seq:h\n"
+		"action:show-replace\n"
+		"type:to\t2\n"
+		"type:\t\t\t\t\t\t\n" /* Jump to 'Replace' */
+		"seq:n\n" /* Press it */
+		"seq:^\n" /* Close the dialog */
+		"undo:undo\n"
+		"undo:test:1\n"
+		"undo:redo\n",
+		HTML_PREFIX "<div style=\"width: 71ch;\">text 2 replace</div>" HTML_SUFFIX,
+		"text 2 replace"))
+		g_test_fail ();
+}
+
+static void
+test_replace_dialog_all (TestFixture *fixture)
+{
+	if (!test_utils_run_simple_test (fixture,
+		"mode:plain\n"
+		"type:text to replace\n"
+		"undo:save\n"	/* 1 */
+		"seq:h\n"
+		"action:show-replace\n"
+		"type:e\t3\n"
+		"type:\t\t\t\t\t\t\t\n" /* Jump to 'Replace All' */
+		"seq:n\n" /* Press it */
+		"seq:^\n" /* Close the dialog */
+		"undo:undo\n"
+		"undo:test:1\n"
+		"undo:redo\n",
+		HTML_PREFIX "<div style=\"width: 71ch;\">t3xt to r3plac3</div>" HTML_SUFFIX,
+		"t3xt to r3plac3"))
+		g_test_fail ();
+}
+
 gint
 main (gint argc,
       gchar *argv[])
@@ -2824,6 +2872,8 @@ main (gint argc,
 	test_utils_add_test ("/undo/link-paste/plain", test_undo_link_paste_plain);
 	test_utils_add_test ("/delete/quoted", test_delete_quoted);
 	test_utils_add_test ("/delete/after-quoted", test_delete_after_quoted);
+	test_utils_add_test ("/replace/dialog", test_replace_dialog);
+	test_utils_add_test ("/replace-all/dialog", test_replace_dialog_all);
 
 	test_add_html_editor_bug_tests ();
 
diff -up evolution-3.22.6/mail/e-mail-display.c.composer-image-insert-undo evolution-3.22.6/mail/e-mail-display.c
--- evolution-3.22.6/mail/e-mail-display.c.composer-image-insert-undo	2017-03-24 15:12:21.888422514 +0100
+++ evolution-3.22.6/mail/e-mail-display.c	2017-03-24 15:12:21.895422514 +0100
@@ -1768,7 +1768,6 @@ mail_display_uri_requested_cb (EWebView
 	}
 }
 
-#if 0 /* FIXME WK2 */
 static CamelMimePart *
 camel_mime_part_from_cid (EMailDisplay *display,
                           const gchar *uri)
@@ -1876,7 +1875,6 @@ mail_display_drag_data_get (GtkWidget *w
  out:
 	g_free (uri);
 }
-#endif
 
 static void
 e_mail_display_test_change_and_update_fonts_cb (EMailDisplay *mail_display,
@@ -1922,9 +1920,7 @@ e_mail_display_class_init (EMailDisplayC
 	widget_class->button_press_event = mail_display_button_press_event;
 
 	web_view_class = E_WEB_VIEW_CLASS (class);
-#if 0 /* FIXME WK2 */
 	web_view_class->suggest_filename = mail_display_suggest_filename;
-#endif
 	web_view_class->set_fonts = mail_display_set_fonts;
 
 	g_object_class_install_property (
@@ -2054,11 +2050,11 @@ e_mail_display_init (EMailDisplay *displ
 	g_signal_connect (
 		display, "process-mailto",
 		G_CALLBACK (mail_display_process_mailto), NULL);
-#if 0 /* FIXME WK2 */
+
 	g_signal_connect_after (
 		display, "drag-data-get",
 		G_CALLBACK (mail_display_drag_data_get), display);
-#endif
+
 	display->priv->settings = e_util_ref_settings ("org.gnome.evolution.mail");
 	g_signal_connect_swapped (
 		display->priv->settings , "changed::monospace-font",
diff -up evolution-3.22.6/modules/webkit-editor/e-webkit-editor.c.composer-image-insert-undo evolution-3.22.6/modules/webkit-editor/e-webkit-editor.c
--- evolution-3.22.6/modules/webkit-editor/e-webkit-editor.c.composer-image-insert-undo	2017-03-24 15:12:21.889422514 +0100
+++ evolution-3.22.6/modules/webkit-editor/e-webkit-editor.c	2017-03-24 15:13:40.145419038 +0100
@@ -131,6 +131,10 @@ struct _EWebKitEditorPrivate {
 	gchar *replace_with;
 	gulong found_text_handler_id;
 	gulong failed_to_find_text_handler_id;
+	gboolean current_text_not_found;
+
+	gboolean performing_drag;
+	gulong drag_data_received_handler_id;
 
 	gchar *last_hover_uri;
 };
@@ -386,6 +390,9 @@ web_extension_selection_changed_cb (GDBu
 	}
 	g_free (font_color);
 
+	g_object_notify (G_OBJECT (wk_editor), "can-undo");
+	g_object_notify (G_OBJECT (wk_editor), "can-redo");
+
 	g_object_notify (G_OBJECT (wk_editor), "alignment");
 	g_object_notify (G_OBJECT (wk_editor), "block-format");
 	g_object_notify (G_OBJECT (wk_editor), "indented");
@@ -2468,7 +2475,7 @@ webkit_editor_replace_caret_word (EConte
 		return;
 	}
 
-	e_util_invoke_g_dbus_proxy_call_with_error_check (
+	e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
 		wk_editor->priv->web_extension,
 		"DOMReplaceCaretWord",
 		g_variant_new ("(ts)", current_page_id (wk_editor), replacement),
@@ -2521,10 +2528,39 @@ find_flags_to_webkit_find_options (guint
 }
 
 static void
+webkit_editor_replace (EContentEditor *editor,
+                       const gchar *replacement)
+{
+	EWebKitEditor *wk_editor;
+
+	wk_editor = E_WEBKIT_EDITOR (editor);
+	if (!wk_editor->priv->web_extension) {
+		g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
+		return;
+	}
+
+	e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
+		wk_editor->priv->web_extension,
+		"DOMSelectionReplace",
+		g_variant_new ("(ts)", current_page_id (wk_editor), replacement),
+		wk_editor->priv->cancellable);
+}
+
+static gboolean
+search_next_on_idle (EWebKitEditor *wk_editor)
+{
+	webkit_find_controller_search_next (wk_editor->priv->find_controller);
+
+	return G_SOURCE_REMOVE;
+}
+
+static void
 webkit_find_controller_found_text_cb (WebKitFindController *find_controller,
                                       guint match_count,
                                       EWebKitEditor *wk_editor)
 {
+	wk_editor->priv->current_text_not_found = FALSE;
+
 	if (wk_editor->priv->performing_replace_all) {
 		if (!wk_editor->priv->replaced_count)
 			wk_editor->priv->replaced_count = match_count;
@@ -2532,12 +2568,13 @@ webkit_find_controller_found_text_cb (We
 		/* Repeatedly search for 'word', then replace selection by
 		 * 'replacement'. Repeat until there's at least one occurrence of
 		 * 'word' in the document */
-		e_content_editor_insert_content (
-			E_CONTENT_EDITOR (wk_editor),
-			wk_editor->priv->replace_with,
-			E_CONTENT_EDITOR_INSERT_TEXT_PLAIN);
+		e_util_invoke_g_dbus_proxy_call_with_error_check (
+			wk_editor->priv->web_extension,
+			"DOMSelectionReplace",
+			g_variant_new ("(ts)", current_page_id (wk_editor), wk_editor->priv->replace_with),
+			wk_editor->priv->cancellable);
 
-		webkit_find_controller_search_next (find_controller);
+		g_idle_add ((GSourceFunc) search_next_on_idle, wk_editor);
 	} else {
 		e_content_editor_emit_find_done (E_CONTENT_EDITOR (wk_editor), match_count);
 	}
@@ -2547,9 +2584,26 @@ static void
 webkit_find_controller_failed_to_find_text_cb (WebKitFindController *find_controller,
                                                EWebKitEditor *wk_editor)
 {
+	wk_editor->priv->current_text_not_found = TRUE;
+
 	if (wk_editor->priv->performing_replace_all) {
 		guint replaced_count = wk_editor->priv->replaced_count;
 
+		if (replaced_count > 0) {
+			if (!wk_editor->priv->web_extension) {
+				g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
+			} else {
+				e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
+					wk_editor->priv->web_extension,
+					"DOMInsertReplaceAllHistoryEvent",
+					g_variant_new ("(tss)",
+						current_page_id (wk_editor),
+						webkit_find_controller_get_search_text (find_controller),
+						wk_editor->priv->replace_with),
+					NULL);
+			}
+		}
+
 		webkit_editor_finish_search (wk_editor);
 		e_content_editor_emit_replace_all_done (E_CONTENT_EDITOR (wk_editor), replaced_count);
 	} else {
@@ -2575,6 +2629,7 @@ webkit_editor_prepare_find_controller (E
 
 	wk_editor->priv->performing_replace_all = FALSE;
 	wk_editor->priv->replaced_count = 0;
+	wk_editor->priv->current_text_not_found = FALSE;
 	g_free (wk_editor->priv->replace_with);
 	wk_editor->priv->replace_with = NULL;
 }
@@ -2613,25 +2668,6 @@ webkit_editor_find (EContentEditor *edit
 }
 
 static void
-webkit_editor_replace (EContentEditor *editor,
-                       const gchar *replacement)
-{
-	EWebKitEditor *wk_editor;
-
-	wk_editor = E_WEBKIT_EDITOR (editor);
-	if (!wk_editor->priv->web_extension) {
-		g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
-		return;
-	}
-
-	e_util_invoke_g_dbus_proxy_call_with_error_check (
-		wk_editor->priv->web_extension,
-		"DOMSelectionReplace",
-		g_variant_new ("(ts)", current_page_id (wk_editor), replacement),
-		wk_editor->priv->cancellable);
-}
-
-static void
 webkit_editor_replace_all (EContentEditor *editor,
                            guint32 flags,
                            const gchar *find_text,
@@ -2647,6 +2683,11 @@ webkit_editor_replace_all (EContentEdito
 	wk_editor = E_WEBKIT_EDITOR (editor);
 	wk_options = find_flags_to_webkit_find_options (flags);
 
+	wk_options |= WEBKIT_FIND_OPTIONS_WRAP_AROUND;
+
+	if (wk_editor->priv->current_text_not_found)
+		return;
+
 	if (!wk_editor->priv->find_controller)
 		webkit_editor_prepare_find_controller (wk_editor);
 
@@ -5770,17 +5811,111 @@ webkit_editor_context_menu_cb (EWebKitEd
 }
 
 static void
+webkit_editor_drag_begin_cb (EWebKitEditor *wk_editor,
+                             GdkDragContext *context)
+{
+	wk_editor->priv->performing_drag = TRUE;
+}
+
+static void
+webkit_editor_drag_failed_cb (EWebKitEditor *wk_editor,
+                              GdkDragContext *context,
+                              GtkDragResult result)
+{
+	wk_editor->priv->performing_drag = FALSE;
+}
+
+static void
 webkit_editor_drag_end_cb (EWebKitEditor *wk_editor,
                            GdkDragContext *context)
 {
-	webkit_editor_call_simple_extension_function (wk_editor, "DOMDragAndDropEnd");
+	wk_editor->priv->performing_drag = FALSE;
+}
+
+static void
+webkit_editor_drag_data_received_cb (GtkWidget *widget,
+                                     GdkDragContext *context,
+                                     gint x,
+                                     gint y,
+                                     GtkSelectionData *selection,
+                                     guint info,
+                                     guint time)
+{
+	EWebKitEditor *wk_editor = E_WEBKIT_EDITOR (widget);
+	gboolean is_move = FALSE;
+
+	g_signal_handler_disconnect (wk_editor, wk_editor->priv->drag_data_received_handler_id);
+	wk_editor->priv->drag_data_received_handler_id = 0;
+
+	is_move = gdk_drag_context_get_selected_action(context) == GDK_ACTION_MOVE;
+
+	/* Leave DnD inside the view on WebKit */
+	/* Leave the text on WebKit to handle it. */
+	if (wk_editor->priv->performing_drag ||
+	    info == E_DND_TARGET_TYPE_UTF8_STRING || info == E_DND_TARGET_TYPE_STRING ||
+	    info == E_DND_TARGET_TYPE_TEXT_PLAIN || info == E_DND_TARGET_TYPE_TEXT_PLAIN_UTF8) {
+		gdk_drag_status (context, gdk_drag_context_get_selected_action(context), time);
+		GTK_WIDGET_CLASS (e_webkit_editor_parent_class)->drag_drop (widget, context, x, y, time);
+		g_signal_stop_emission_by_name (widget, "drag-data-received");
+		if (!is_move)
+			webkit_editor_call_simple_extension_function (wk_editor, "DOMLastDropOperationDidCopy");
+		return;
+	}
+
+	if (info == E_DND_TARGET_TYPE_TEXT_HTML) {
+		const guchar *data;
+		gint length;
+		gint list_len, len;
+		gchar *text;
+
+		data = gtk_selection_data_get_data (selection);
+		length = gtk_selection_data_get_length (selection);
+
+		if (!data || length < 0) {
+			gtk_drag_finish (context, FALSE, is_move, time);
+			g_signal_stop_emission_by_name (widget, "drag-data-received");
+			return;
+		}
+
+		webkit_editor_move_caret_on_coordinates (E_CONTENT_EDITOR (widget), x, y, FALSE);
+
+		list_len = length;
+		do {
+			text = e_util_next_uri_from_uri_list ((guchar **) &data, &len, &list_len);
+			webkit_editor_insert_content (
+				E_CONTENT_EDITOR (wk_editor),
+				text,
+				E_CONTENT_EDITOR_INSERT_TEXT_HTML);
+			g_free (text);
+		} while (list_len);
+
+		gtk_drag_finish (context, TRUE, is_move, time);
+		g_signal_stop_emission_by_name (widget, "drag-data-received");
+		return;
+	}
+}
+
+static gboolean
+webkit_editor_drag_drop_cb (EWebKitEditor *wk_editor,
+                            GdkDragContext *context,
+                            gint x,
+                            gint y,
+                            guint time)
+{
+	wk_editor->priv->drag_data_received_handler_id = g_signal_connect (
+		wk_editor, "drag-data-received",
+		G_CALLBACK (webkit_editor_drag_data_received_cb), NULL);
+
+	webkit_editor_set_changed (wk_editor, TRUE);
+
+	return FALSE;
 }
 
 static void
 webkit_editor_web_process_crashed_cb (EWebKitEditor *wk_editor)
 {
 	g_warning (
-		"WebKitWebProcess (page id %ld) for EWebKitEditor crashed",
+		"WebKitWebProcess (page id %" G_GUINT64_FORMAT ") for EWebKitEditor crashed",
 		webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (wk_editor)));
 }
 
@@ -6050,10 +6185,22 @@ e_webkit_editor_init (EWebKitEditor *wk_
 		G_CALLBACK (webkit_editor_mouse_target_changed_cb), NULL);
 
 	g_signal_connect (
+		wk_editor, "drag-begin",
+		G_CALLBACK (webkit_editor_drag_begin_cb), NULL);
+
+	g_signal_connect (
+		wk_editor, "drag-failed",
+		G_CALLBACK (webkit_editor_drag_failed_cb), NULL);
+
+	g_signal_connect (
 		wk_editor, "drag-end",
 		G_CALLBACK (webkit_editor_drag_end_cb), NULL);
 
 	g_signal_connect (
+		wk_editor, "drag-drop",
+		G_CALLBACK (webkit_editor_drag_drop_cb), NULL);
+
+	g_signal_connect (
 		wk_editor, "web-process-crashed",
 		G_CALLBACK (webkit_editor_web_process_crashed_cb), NULL);
 
diff -up evolution-3.22.6/modules/webkit-editor/web-extension/e-composer-dom-functions.c.composer-image-insert-undo evolution-3.22.6/modules/webkit-editor/web-extension/e-composer-dom-functions.c
--- evolution-3.22.6/modules/webkit-editor/web-extension/e-composer-dom-functions.c.composer-image-insert-undo	2017-02-07 17:48:51.000000000 +0100
+++ evolution-3.22.6/modules/webkit-editor/web-extension/e-composer-dom-functions.c	2017-03-24 15:12:21.896422514 +0100
@@ -591,247 +591,3 @@ e_composer_dom_get_raw_body_content (EEd
 
 	return  webkit_dom_html_element_get_inner_text (body);
 }
-
-static void
-insert_nbsp_history_event (WebKitDOMDocument *document,
-                           EEditorUndoRedoManager *manager,
-                           gboolean delete,
-                           guint x,
-                           guint y)
-{
-	EEditorHistoryEvent *event;
-	WebKitDOMDocumentFragment *fragment;
-
-	event = g_new0 (EEditorHistoryEvent, 1);
-	event->type = HISTORY_AND;
-	e_editor_undo_redo_manager_insert_history_event (manager, event);
-
-	fragment = webkit_dom_document_create_document_fragment (document);
-	webkit_dom_node_append_child (
-		WEBKIT_DOM_NODE (fragment),
-		WEBKIT_DOM_NODE (
-			webkit_dom_document_create_text_node (document, UNICODE_NBSP)),
-		NULL);
-
-	event = g_new0 (EEditorHistoryEvent, 1);
-	event->type = HISTORY_DELETE;
-
-	if (delete)
-		g_object_set_data (G_OBJECT (fragment), "history-delete-key", GINT_TO_POINTER (1));
-
-	event->data.fragment = fragment;
-
-	event->before.start.x = x;
-	event->before.start.y = y;
-	event->before.end.x = x;
-	event->before.end.y = y;
-
-	event->after.start.x = x;
-	event->after.start.y = y;
-	event->after.end.x = x;
-	event->after.end.y = y;
-
-	e_editor_undo_redo_manager_insert_history_event (manager, event);
-}
-
-void
-e_composer_dom_save_drag_and_drop_history (EEditorPage *editor_page)
-{
-	WebKitDOMDocument *document;
-	WebKitDOMDocumentFragment *fragment;
-	WebKitDOMDOMSelection *dom_selection = NULL;
-	WebKitDOMDOMWindow *dom_window = NULL;
-	WebKitDOMRange *beginning_of_line = NULL;
-	WebKitDOMRange *range = NULL, *range_clone = NULL;
-	EEditorHistoryEvent *event;
-	EEditorUndoRedoManager *manager;
-	gboolean start_to_start, end_to_end;
-	gchar *range_text;
-	guint x, y;
-
-	g_return_if_fail (E_IS_EDITOR_PAGE (editor_page));
-
-	document = e_editor_page_get_document (editor_page);
-	manager = e_editor_page_get_undo_redo_manager (editor_page);
-
-	if (!(dom_window = webkit_dom_document_get_default_view (document)))
-		return;
-
-	if (!(dom_selection = webkit_dom_dom_window_get_selection (dom_window))) {
-		g_clear_object (&dom_window);
-		return;
-	}
-
-	g_clear_object (&dom_window);
-
-	if (webkit_dom_dom_selection_get_range_count (dom_selection) < 1) {
-		g_clear_object (&dom_selection);
-		return;
-	}
-
-	/* Obtain the dragged content. */
-	range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
-	range_clone = webkit_dom_range_clone_range (range, NULL);
-
-	/* Create the history event for the content that will
-	 * be removed by DnD. */
-	event = g_new0 (EEditorHistoryEvent, 1);
-	event->type = HISTORY_DELETE;
-
-	e_editor_dom_selection_get_coordinates (editor_page,
-		&event->before.start.x,
-		&event->before.start.y,
-		&event->before.end.x,
-		&event->before.end.y);
-
-	x = event->before.start.x;
-	y = event->before.start.y;
-
-	event->after.start.x = x;
-	event->after.start.y = y;
-	event->after.end.x = x;
-	event->after.end.y = y;
-
-	/* Save the content that will be removed. */
-	fragment = webkit_dom_range_clone_contents (range_clone, NULL);
-
-	/* Extend the cloned range to point one character after
-	 * the selection ends to later check if there is a whitespace
-	 * after it. */
-	webkit_dom_range_set_end (
-		range_clone,
-		webkit_dom_range_get_end_container (range_clone, NULL),
-		webkit_dom_range_get_end_offset (range_clone, NULL) + 1,
-		NULL);
-	range_text = webkit_dom_range_get_text (range_clone);
-
-	/* Check if the current selection starts on the beginning
-	 * of line. */
-	webkit_dom_dom_selection_modify (
-		dom_selection, "extend", "left", "lineboundary");
-	beginning_of_line = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
-	start_to_start = webkit_dom_range_compare_boundary_points (
-		beginning_of_line, 0 /* START_TO_START */, range, NULL) == 0;
-
-	/* Restore the selection to state before the check. */
-	webkit_dom_dom_selection_remove_all_ranges (dom_selection);
-	webkit_dom_dom_selection_add_range (dom_selection, range);
-	g_clear_object (&beginning_of_line);
-
-	/* Check if the current selection end on the end of the line. */
-	webkit_dom_dom_selection_modify (
-		dom_selection, "extend", "right", "lineboundary");
-	beginning_of_line = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
-	end_to_end = webkit_dom_range_compare_boundary_points (
-		beginning_of_line, 2 /* END_TO_END */, range, NULL) == 0;
-
-	/* Dragging the whole line. */
-	if (start_to_start && end_to_end) {
-		WebKitDOMNode *container, *actual_block, *tmp_block;
-
-		/* Select the whole line (to the beginning of the next
-		 * one so we can reuse the undo code while undoing this.
-		 * Because of this we need to special mark the event
-		 * with history-drag-and-drop to correct the selection
-		 * after undoing it (otherwise the beginning of the next
-		 * line will be selected as well. */
-		webkit_dom_dom_selection_modify (
-			dom_selection, "extend", "right", "character");
-		g_clear_object (&beginning_of_line);
-		beginning_of_line = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
-
-		container = webkit_dom_range_get_end_container (range, NULL);
-		actual_block = e_editor_dom_get_parent_block_node_from_child (container);
-
-		tmp_block = webkit_dom_range_get_end_container (beginning_of_line, NULL);
-		if ((tmp_block = e_editor_dom_get_parent_block_node_from_child (tmp_block))) {
-			e_editor_dom_selection_get_coordinates (editor_page,
-				&event->before.start.x,
-				&event->before.start.y,
-				&event->before.end.x,
-				&event->before.end.y);
-
-			/* Create the right content for the history event. */
-			fragment = webkit_dom_document_create_document_fragment (document);
-			/* The removed line. */
-			webkit_dom_node_append_child (
-				WEBKIT_DOM_NODE (fragment),
-				webkit_dom_node_clone_node_with_error (actual_block, TRUE, NULL),
-				NULL);
-			/* The following block, but empty. */
-			webkit_dom_node_append_child (
-				WEBKIT_DOM_NODE (fragment),
-				webkit_dom_node_clone_node_with_error (tmp_block, FALSE, NULL),
-				NULL);
-			g_object_set_data (
-				G_OBJECT (fragment),
-				"history-drag-and-drop",
-				GINT_TO_POINTER (1));
-			/* It should act as a Delete key press. */
-			g_object_set_data (
-				G_OBJECT (fragment),
-				"history-delete-key",
-				GINT_TO_POINTER (1));
-		}
-	}
-
-	event->data.fragment = fragment;
-	e_editor_undo_redo_manager_insert_history_event (manager, event);
-
-	/* Selection is ending on the end of the line, check if
-	 * there is a space before the selection start. If so, it
-	 * will be removed and we need create the history event
-	 * for it. */
-	if (end_to_end) {
-		gchar *range_text_start;
-		glong start_offset;
-
-		start_offset = webkit_dom_range_get_start_offset (range_clone, NULL);
-		webkit_dom_range_set_start (
-			range_clone,
-			webkit_dom_range_get_start_container (range_clone, NULL),
-			start_offset > 0 ? start_offset - 1 : 0,
-			NULL);
-
-		range_text_start = webkit_dom_range_get_text (range_clone);
-		if (g_str_has_prefix (range_text_start, " ") ||
-		    g_str_has_prefix (range_text_start, UNICODE_NBSP))
-			insert_nbsp_history_event (document, manager, FALSE, x, y);
-
-		g_free (range_text_start);
-	}
-
-	/* WebKit removes the space (if presented) after selection and
-	 * we need to create a new history event for it. */
-	if (g_str_has_suffix (range_text, " ") ||
-	    g_str_has_suffix (range_text, UNICODE_NBSP))
-		insert_nbsp_history_event (document, manager, TRUE, x, y);
-
-	g_free (range_text);
-
-	/* Restore the selection to original state. */
-	webkit_dom_dom_selection_remove_all_ranges (dom_selection);
-	webkit_dom_dom_selection_add_range (dom_selection, range);
-	g_clear_object (&beginning_of_line);
-
-	/* All the things above were about removing the content,
-	 * create an AND event to continue later with inserting
-	 * the dropped content. */
-	event = g_new0 (EEditorHistoryEvent, 1);
-	event->type = HISTORY_AND;
-	e_editor_undo_redo_manager_insert_history_event (manager, event);
-
-	g_clear_object (&dom_selection);
-
-	g_clear_object (&range);
-	g_clear_object (&range_clone);
-}
-
-void
-e_composer_dom_clean_after_drag_and_drop (EEditorPage *editor_page)
-{
-	g_return_if_fail (E_IS_EDITOR_PAGE (editor_page));
-
-	e_editor_dom_save_history_for_drop (editor_page);
-	e_editor_dom_check_magic_links (editor_page, FALSE);
-}
diff -up evolution-3.22.6/modules/webkit-editor/web-extension/e-composer-dom-functions.h.composer-image-insert-undo evolution-3.22.6/modules/webkit-editor/web-extension/e-composer-dom-functions.h
--- evolution-3.22.6/modules/webkit-editor/web-extension/e-composer-dom-functions.h.composer-image-insert-undo	2016-09-19 10:22:58.000000000 +0200
+++ evolution-3.22.6/modules/webkit-editor/web-extension/e-composer-dom-functions.h	2017-03-24 15:12:21.896422514 +0100
@@ -38,10 +38,6 @@ gchar *		e_composer_dom_get_raw_body_con
 						(EEditorPage *editor_page);
 gchar *		e_composer_dom_get_raw_body_content
 						(EEditorPage *editor_page);
-void		e_composer_dom_save_drag_and_drop_history
-						(EEditorPage *editor_page);
-void		e_composer_dom_clean_after_drag_and_drop
-						(EEditorPage *editor_page);
 
 G_END_DECLS
 
diff -up evolution-3.22.6/modules/webkit-editor/web-extension/e-editor-dom-functions.c.composer-image-insert-undo evolution-3.22.6/modules/webkit-editor/web-extension/e-editor-dom-functions.c
--- evolution-3.22.6/modules/webkit-editor/web-extension/e-editor-dom-functions.c.composer-image-insert-undo	2017-03-24 15:12:21.891422514 +0100
+++ evolution-3.22.6/modules/webkit-editor/web-extension/e-editor-dom-functions.c	2017-03-24 15:13:16.839420073 +0100
@@ -3408,6 +3408,7 @@ e_editor_dom_body_input_event_process (E
 		}
 
 		if (WEBKIT_DOM_IS_TEXT (node)) {
+			WebKitDOMElement *parent;
 			gchar *text;
 
 			text = webkit_dom_node_get_text_content (node);
@@ -3429,6 +3430,43 @@ e_editor_dom_body_input_event_process (E
 						e_editor_dom_check_magic_links (editor_page, FALSE);
 				}
 			}
+
+			parent = webkit_dom_node_get_parent_element (node);
+			if (element_has_class (parent, "-x-evo-resizable-wrapper") ||
+			    element_has_class (parent, "-x-evo-smiley-wrapper")) {
+				WebKitDOMDOMWindow *dom_window = NULL;
+				WebKitDOMDOMSelection *dom_selection = NULL;
+				WebKitDOMNode *prev_sibling;
+				gboolean writing_before = TRUE;
+
+				dom_window = webkit_dom_document_get_default_view (document);
+				dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+
+				prev_sibling = webkit_dom_node_get_previous_sibling (node);
+				if (prev_sibling && WEBKIT_DOM_IS_HTML_IMAGE_ELEMENT (prev_sibling))
+					writing_before = FALSE;
+
+				webkit_dom_node_insert_before (
+					webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (parent)),
+					node,
+					writing_before ?
+						WEBKIT_DOM_NODE (parent) :
+						webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (parent)),
+					NULL);
+
+				g_clear_object (&range);
+
+				range = webkit_dom_document_create_range (document);
+				webkit_dom_range_select_node_contents (range, node, NULL);
+				webkit_dom_range_collapse (range, FALSE, NULL);
+
+				webkit_dom_dom_selection_remove_all_ranges (dom_selection);
+				webkit_dom_dom_selection_add_range (dom_selection, range);
+
+				g_clear_object (&dom_window);
+				g_clear_object (&dom_selection);
+			}
+
 			g_free (text);
 		}
 	}
@@ -5751,6 +5789,94 @@ body_compositionend_event_cb (WebKitDOME
 }
 
 static void
+body_drop_event_cb (WebKitDOMElement *element,
+                    WebKitDOMUIEvent *event,
+                    EEditorPage *editor_page)
+{
+	g_return_if_fail (E_IS_EDITOR_PAGE (editor_page));
+
+	if (e_editor_page_is_pasting_content_from_itself (editor_page)) {
+		EEditorUndoRedoManager *manager;
+		EEditorHistoryEvent *and_event, *event = NULL;
+
+		/* There is a weird thing going on and I still don't know if it's
+		 * caused by WebKit or Evolution. If dragging content around the
+		 * editor sometimes the current selection is changed. The problem
+		 * is that if moving the content, then WebKit is removing the
+		 * currently selected content and at that point it could be a
+		 * different one from the dragged one. So before the drop is
+		 * performed we restore the selection to the state when the
+		 * drag was initiated. */
+		manager = e_editor_page_get_undo_redo_manager (editor_page);
+		and_event = e_editor_undo_redo_manager_get_current_history_event (manager);
+		while (and_event && and_event->type == HISTORY_AND) {
+			event = e_editor_undo_redo_manager_get_next_history_event_for (manager, and_event);
+			and_event = e_editor_undo_redo_manager_get_next_history_event_for (manager, event);
+		}
+
+		if (event)
+			e_editor_dom_selection_restore_to_history_event_state (editor_page, event->before);
+
+		e_editor_dom_save_history_for_drop (editor_page);
+	}
+}
+
+static void
+body_dragstart_event_cb (WebKitDOMElement *element,
+                         WebKitDOMUIEvent *event,
+                         EEditorPage *editor_page)
+{
+	g_return_if_fail (E_IS_EDITOR_PAGE (editor_page));
+
+	e_editor_dom_remove_input_event_listener_from_body (editor_page);
+	e_editor_page_set_pasting_content_from_itself (editor_page, TRUE);
+	e_editor_dom_save_history_for_drag (editor_page);
+}
+
+static void
+body_dragend_event_cb (WebKitDOMElement *element,
+                       WebKitDOMUIEvent *event,
+                       EEditorPage *editor_page)
+{
+	EEditorHistoryEvent *ev;
+	EEditorUndoRedoManager *manager;
+
+	g_return_if_fail (E_IS_EDITOR_PAGE (editor_page));
+
+	manager = e_editor_page_get_undo_redo_manager (editor_page);
+	if (e_editor_page_is_pasting_content_from_itself (editor_page) &&
+	   (ev = e_editor_undo_redo_manager_get_current_history_event (manager))) {
+		if (ev->type == HISTORY_INSERT_HTML &&
+		    ev->after.start.x == 0 && ev->after.start.y == 0 &&
+		    ev->after.end.x == 0 && ev->after.end.y == 0) {
+			e_editor_dom_selection_get_coordinates (editor_page,
+				&ev->after.start.x,
+				&ev->after.start.y,
+				&ev->after.end.x,
+				&ev->after.end.y);
+			ev->before.start.x = ev->after.start.x;
+			ev->before.start.y = ev->after.start.y;
+			ev->before.end.x = ev->after.start.x;
+			ev->before.end.y = ev->after.start.y;
+			e_editor_dom_force_spell_check_in_viewport (editor_page);
+		} else {
+			/* Drag and Drop was cancelled */
+			while (ev && ev->type == HISTORY_AND) {
+				e_editor_undo_redo_manager_remove_current_history_event (manager);
+				ev = e_editor_undo_redo_manager_get_current_history_event (manager);
+				/* Basically the same as in body_drop_event_cb().  See the comment there. */
+				e_editor_dom_selection_restore_to_history_event_state (editor_page, ev->before);
+				e_editor_undo_redo_manager_remove_current_history_event (manager);
+				ev = e_editor_undo_redo_manager_get_current_history_event (manager);
+			}
+		}
+	}
+
+	e_editor_page_set_pasting_content_from_itself (editor_page, FALSE);
+	e_editor_dom_register_input_event_listener_on_body (editor_page);
+}
+
+static void
 register_html_events_handlers (EEditorPage *editor_page,
                                WebKitDOMHTMLElement *body)
 {
@@ -5790,6 +5916,27 @@ register_html_events_handlers (EEditorPa
 		G_CALLBACK (body_compositionend_event_cb),
 		FALSE,
 		editor_page);
+
+	webkit_dom_event_target_add_event_listener (
+		WEBKIT_DOM_EVENT_TARGET (body),
+		"drop",
+		G_CALLBACK (body_drop_event_cb),
+		FALSE,
+		editor_page);
+
+	webkit_dom_event_target_add_event_listener (
+		WEBKIT_DOM_EVENT_TARGET (body),
+		"dragstart",
+		G_CALLBACK (body_dragstart_event_cb),
+		FALSE,
+		editor_page);
+
+	webkit_dom_event_target_add_event_listener (
+		WEBKIT_DOM_EVENT_TARGET (body),
+		"dragend",
+		G_CALLBACK (body_dragend_event_cb),
+		FALSE,
+		editor_page);
 }
 
 void
@@ -8523,11 +8670,25 @@ e_editor_dom_process_content_after_load
 
 	if (e_editor_page_get_convert_in_situ (editor_page)) {
 		e_editor_dom_convert_content (editor_page, NULL);
+		/* The BODY could be replaced during the conversion */
+		body = webkit_dom_document_get_body (document);
 		/* Make the quote marks non-selectable. */
 		e_editor_dom_disable_quote_marks_select (editor_page);
 		dom_set_links_active (document, FALSE);
 		e_editor_page_set_convert_in_situ (editor_page, FALSE);
 
+		/* The composer body could be empty in some case (loading an empty string
+		 * or empty HTML). In that case create the initial paragraph. */
+		if (!webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body))) {
+			WebKitDOMElement *paragraph;
+
+			paragraph = e_editor_dom_prepare_paragraph (editor_page, TRUE);
+			webkit_dom_element_set_id (paragraph, "-x-evo-input-start");
+			webkit_dom_node_append_child (
+				WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (paragraph), NULL);
+			e_editor_dom_selection_restore (editor_page);
+		}
+
 		goto out;
 	}
 
@@ -8933,35 +9094,6 @@ e_editor_dom_insert_html (EEditorPage *e
 		if (strstr (html_text, "id=\"-x-evo-selection-start-marker\""))
 			e_editor_dom_selection_restore (editor_page);
 
-		if (!html_mode) {
-			WebKitDOMNodeList *list = NULL;
-			gint ii, length;
-
-			list = webkit_dom_document_query_selector_all (
-				document, "span[style^=font-family]", NULL);
-			length = webkit_dom_node_list_get_length (list);
-			if (length > 0)
-				e_editor_dom_selection_save (editor_page);
-
-			for (ii = length; ii--;) {
-				WebKitDOMNode *span, *child;
-
-				span = webkit_dom_node_list_item (list, ii);
-				while ((child = webkit_dom_node_get_first_child (span)))
-					webkit_dom_node_insert_before (
-						webkit_dom_node_get_parent_node (span),
-						child,
-						span,
-						NULL);
-
-				remove_node (span);
-			}
-			g_clear_object (&list);
-
-			if (length > 0)
-				e_editor_dom_selection_restore (editor_page);
-		}
-
 		e_editor_dom_check_magic_links (editor_page, FALSE);
 		e_editor_dom_scroll_to_caret (editor_page);
 		e_editor_dom_force_spell_check_in_viewport (editor_page);
@@ -10833,6 +10965,240 @@ e_editor_dom_get_caret_position (EEditor
 	return ret_val;
 }
 
+static void
+insert_nbsp_history_event (WebKitDOMDocument *document,
+                           EEditorUndoRedoManager *manager,
+                           gboolean delete,
+                           guint x,
+                           guint y)
+{
+	EEditorHistoryEvent *event;
+	WebKitDOMDocumentFragment *fragment;
+
+	event = g_new0 (EEditorHistoryEvent, 1);
+	event->type = HISTORY_AND;
+	e_editor_undo_redo_manager_insert_history_event (manager, event);
+
+	fragment = webkit_dom_document_create_document_fragment (document);
+	webkit_dom_node_append_child (
+		WEBKIT_DOM_NODE (fragment),
+		WEBKIT_DOM_NODE (
+			webkit_dom_document_create_text_node (document, UNICODE_NBSP)),
+		NULL);
+
+	event = g_new0 (EEditorHistoryEvent, 1);
+	event->type = HISTORY_DELETE;
+
+	if (delete)
+		g_object_set_data (G_OBJECT (fragment), "history-delete-key", GINT_TO_POINTER (1));
+
+	event->data.fragment = fragment;
+
+	event->before.start.x = x;
+	event->before.start.y = y;
+	event->before.end.x = x;
+	event->before.end.y = y;
+
+	event->after.start.x = x;
+	event->after.start.y = y;
+	event->after.end.x = x;
+	event->after.end.y = y;
+
+	e_editor_undo_redo_manager_insert_history_event (manager, event);
+}
+void
+e_editor_dom_save_history_for_drag (EEditorPage *editor_page)
+{
+	WebKitDOMDocument *document;
+	WebKitDOMDocumentFragment *fragment;
+	WebKitDOMDOMSelection *dom_selection = NULL;
+	WebKitDOMDOMWindow *dom_window = NULL;
+	WebKitDOMRange *beginning_of_line = NULL;
+	WebKitDOMRange *range = NULL, *range_clone = NULL;
+	EEditorHistoryEvent *event;
+	EEditorUndoRedoManager *manager;
+	gboolean start_to_start = FALSE, end_to_end = FALSE;
+	gchar *range_text;
+	guint x, y;
+
+	g_return_if_fail (E_IS_EDITOR_PAGE (editor_page));
+
+	document = e_editor_page_get_document (editor_page);
+	manager = e_editor_page_get_undo_redo_manager (editor_page);
+
+	if (!(dom_window = webkit_dom_document_get_default_view (document)))
+		return;
+
+	if (!(dom_selection = webkit_dom_dom_window_get_selection (dom_window))) {
+		g_clear_object (&dom_window);
+		return;
+	}
+
+	g_clear_object (&dom_window);
+
+	if (webkit_dom_dom_selection_get_range_count (dom_selection) < 1) {
+		g_clear_object (&dom_selection);
+		return;
+	}
+
+	/* Obtain the dragged content. */
+	range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+	range_clone = webkit_dom_range_clone_range (range, NULL);
+
+	/* Create the history event for the content that will
+	 * be removed by DnD. */
+	event = g_new0 (EEditorHistoryEvent, 1);
+	event->type = HISTORY_DELETE;
+
+	e_editor_dom_selection_get_coordinates (editor_page,
+		&event->before.start.x,
+		&event->before.start.y,
+		&event->before.end.x,
+		&event->before.end.y);
+
+	x = event->before.start.x;
+	y = event->before.start.y;
+
+	event->after.start.x = x;
+	event->after.start.y = y;
+	event->after.end.x = x;
+	event->after.end.y = y;
+
+	/* Save the content that will be removed. */
+	fragment = webkit_dom_range_clone_contents (range_clone, NULL);
+
+	/* Extend the cloned range to point one character after
+	 * the selection ends to later check if there is a whitespace
+	 * after it. */
+	webkit_dom_range_set_end (
+		range_clone,
+		webkit_dom_range_get_end_container (range_clone, NULL),
+		webkit_dom_range_get_end_offset (range_clone, NULL) + 1,
+		NULL);
+	range_text = webkit_dom_range_get_text (range_clone);
+
+	/* Check if the current selection starts on the beginning of line. */
+	webkit_dom_dom_selection_modify (
+		dom_selection, "extend", "left", "lineboundary");
+	beginning_of_line = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+	start_to_start = webkit_dom_range_compare_boundary_points (
+		beginning_of_line, WEBKIT_DOM_RANGE_START_TO_START, range, NULL) == 0;
+
+	/* Restore the selection to state before the check. */
+	webkit_dom_dom_selection_remove_all_ranges (dom_selection);
+	webkit_dom_dom_selection_add_range (dom_selection, range);
+	g_clear_object (&beginning_of_line);
+
+	/* Check if the current selection end on the end of the line. */
+	webkit_dom_dom_selection_modify (
+		dom_selection, "extend", "right", "lineboundary");
+	beginning_of_line = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+	end_to_end = webkit_dom_range_compare_boundary_points (
+		beginning_of_line, WEBKIT_DOM_RANGE_END_TO_END, range, NULL) == 0;
+
+	/* Dragging the whole line. */
+	if (start_to_start && end_to_end) {
+		WebKitDOMNode *container, *actual_block, *tmp_block;
+
+		/* Select the whole line (to the beginning of the next
+		 * one so we can reuse the undo code while undoing this.
+		 * Because of this we need to special mark the event
+		 * with history-drag-and-drop to correct the selection
+		 * after undoing it (otherwise the beginning of the next
+		 * line will be selected as well. */
+		webkit_dom_dom_selection_modify (
+			dom_selection, "extend", "right", "character");
+		g_clear_object (&beginning_of_line);
+		beginning_of_line = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+
+		container = webkit_dom_range_get_end_container (range, NULL);
+		actual_block = e_editor_dom_get_parent_block_node_from_child (container);
+
+		tmp_block = webkit_dom_range_get_end_container (beginning_of_line, NULL);
+		if ((tmp_block = e_editor_dom_get_parent_block_node_from_child (tmp_block))) {
+			e_editor_dom_selection_get_coordinates (editor_page,
+				&event->before.start.x,
+				&event->before.start.y,
+				&event->before.end.x,
+				&event->before.end.y);
+
+			/* Create the right content for the history event. */
+			fragment = webkit_dom_document_create_document_fragment (document);
+			/* The removed line. */
+			webkit_dom_node_append_child (
+				WEBKIT_DOM_NODE (fragment),
+				webkit_dom_node_clone_node_with_error (actual_block, TRUE, NULL),
+				NULL);
+			/* The following block, but empty. */
+			webkit_dom_node_append_child (
+				WEBKIT_DOM_NODE (fragment),
+				webkit_dom_node_clone_node_with_error (tmp_block, FALSE, NULL),
+				NULL);
+			g_object_set_data (
+				G_OBJECT (fragment),
+				"history-drag-and-drop",
+				GINT_TO_POINTER (1));
+		}
+	}
+	/* It should act as a Delete key press. */
+	g_object_set_data (G_OBJECT (fragment), "history-delete-key", GINT_TO_POINTER (1));
+
+	event->data.fragment = fragment;
+	e_editor_undo_redo_manager_insert_history_event (manager, event);
+
+	/* WebKit removes the space (if presented) after selection and
+	 * we need to create a new history event for it. */
+	if (g_str_has_suffix (range_text, " ") ||
+	    g_str_has_suffix (range_text, UNICODE_NBSP))
+		insert_nbsp_history_event (document, manager, TRUE, x, y);
+	else {
+		/* If there is a space before the selection WebKit will remove
+		 * it as well unless there is a space after the selection. */
+		gchar *range_text_start;
+		glong start_offset;
+
+		start_offset = webkit_dom_range_get_start_offset (range_clone, NULL);
+		webkit_dom_range_set_start (
+			range_clone,
+			webkit_dom_range_get_start_container (range_clone, NULL),
+			start_offset > 0 ? start_offset - 1 : 0,
+			NULL);
+
+		range_text_start = webkit_dom_range_get_text (range_clone);
+		if (g_str_has_prefix (range_text_start, " ") ||
+		    g_str_has_prefix (range_text_start, UNICODE_NBSP)) {
+			if (!end_to_end) {
+				webkit_dom_dom_selection_collapse_to_start (dom_selection, NULL);
+				webkit_dom_dom_selection_modify (
+					dom_selection, "move", "backward", "character");
+				e_editor_dom_selection_get_coordinates (editor_page, &x, &y, &x, &y);
+			}
+			insert_nbsp_history_event (document, manager, TRUE, x, y);
+		}
+
+		g_free (range_text_start);
+	}
+
+	g_free (range_text);
+
+	/* Restore the selection to original state. */
+	webkit_dom_dom_selection_remove_all_ranges (dom_selection);
+	webkit_dom_dom_selection_add_range (dom_selection, range);
+	g_clear_object (&beginning_of_line);
+
+	/* All the things above were about removing the content,
+	 * create an AND event to continue later with inserting
+	 * the dropped content. */
+	event = g_new0 (EEditorHistoryEvent, 1);
+	event->type = HISTORY_AND;
+	e_editor_undo_redo_manager_insert_history_event (manager, event);
+
+	g_clear_object (&dom_selection);
+
+	g_clear_object (&range);
+	g_clear_object (&range_clone);
+}
+
 void
 e_editor_dom_save_history_for_drop (EEditorPage *editor_page)
 {
@@ -10880,14 +11246,6 @@ e_editor_dom_save_history_for_drop (EEdi
 
 	range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
 
-	/* Remove the last inserted history event as this one was inserted in
-	 * body_input_event_cb and is wrong as its type is HISTORY_INPUT. */
-	/* FIXME we could probably disable the HTML input event callback while
-	 * doing DnD within the view */
-	event = e_editor_undo_redo_manager_get_current_history_event (manager);
-	if (event && event->type == HISTORY_INPUT)
-		e_editor_undo_redo_manager_remove_current_history_event (manager);
-
 	event = g_new0 (EEditorHistoryEvent, 1);
 	event->type = HISTORY_INSERT_HTML;
 
@@ -10897,68 +11255,12 @@ e_editor_dom_save_history_for_drop (EEdi
 	/* Get the HTML content of the dropped content. */
 	event->data.string.to = dom_get_node_inner_html (WEBKIT_DOM_NODE (fragment));
 
-	e_editor_dom_selection_get_coordinates (editor_page,
-		&event->before.start.x,
-		&event->before.start.y,
-		&event->before.end.x,
-		&event->before.end.y);
-
-	event->before.end.x = event->before.start.x;
-	event->before.end.y = event->before.start.y;
-
-	if (length > 0)
-		webkit_dom_dom_selection_collapse_to_start (dom_selection, NULL);
-	else
-		webkit_dom_dom_selection_collapse_to_end (dom_selection, NULL);
-
-	e_editor_dom_selection_get_coordinates (editor_page,
-		&event->after.start.x,
-		&event->after.start.y,
-		&event->after.end.x,
-		&event->after.end.y);
-
 	e_editor_undo_redo_manager_insert_history_event (manager, event);
 
-	if (!e_editor_page_get_html_mode (editor_page)) {
-		list = webkit_dom_document_query_selector_all (
-			document, "span[style^=font-family]", NULL);
-		length = webkit_dom_node_list_get_length (list);
-		if (length > 0)
-			e_editor_dom_selection_save (editor_page);
-
-		for (ii = length; ii--;) {
-			WebKitDOMNode *span, *child;
-
-			span = webkit_dom_node_list_item (list, ii);
-			while ((child = webkit_dom_node_get_first_child (span)))
-				webkit_dom_node_insert_before (
-					webkit_dom_node_get_parent_node (span),
-					child,
-					span,
-					NULL);
-
-			remove_node (span);
-		}
-		g_clear_object (&list);
-
-		if (length > 0)
-			e_editor_dom_selection_restore (editor_page);
-	}
-
-	e_editor_dom_force_spell_check_in_viewport (editor_page);
-
 	g_clear_object (&range);
 	g_clear_object (&dom_selection);
 }
 
-void
-e_editor_dom_drag_and_drop_end (EEditorPage *editor_page)
-{
-	g_return_if_fail (E_IS_EDITOR_PAGE (editor_page));
-
-	e_editor_dom_save_history_for_drop (editor_page);
-}
-
 static void
 dom_set_link_color_in_document (EEditorPage *editor_page,
                                 const gchar *color,
@@ -17086,6 +17388,28 @@ e_editor_dom_selection_set_alignment (EE
 	e_editor_page_emit_content_changed (editor_page);
 }
 
+void
+e_editor_dom_insert_replace_all_history_event (EEditorPage *editor_page,
+                                               const gchar *search_text,
+                                               const gchar *replacement)
+{
+	EEditorUndoRedoManager *manager;
+
+	g_return_if_fail (E_IS_EDITOR_PAGE (editor_page));
+
+	manager = e_editor_page_get_undo_redo_manager (editor_page);
+
+	if (!e_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+		EEditorHistoryEvent *ev = g_new0 (EEditorHistoryEvent, 1);
+		ev->type = HISTORY_REPLACE_ALL;
+
+		ev->data.string.from = g_strdup (search_text);
+		ev->data.string.to = g_strdup (replacement);
+
+		e_editor_undo_redo_manager_insert_history_event (manager, ev);
+	}
+}
+
 /*
  * e_html_editor_selection_replace:
  * @selection: an #EEditorSelection
@@ -17099,14 +17423,17 @@ e_editor_dom_selection_replace (EEditorP
 {
 	EEditorHistoryEvent *ev = NULL;
 	EEditorUndoRedoManager *manager;
+	WebKitDOMRange *range = NULL;
 
 	g_return_if_fail (E_IS_EDITOR_PAGE (editor_page));
 
 	manager = e_editor_page_get_undo_redo_manager (editor_page);
 
-	if (!e_editor_undo_redo_manager_is_operation_in_progress (manager)) {
-		WebKitDOMRange *range = NULL;
+	if (!(range = e_editor_dom_get_current_range (editor_page)) ||
+	     e_editor_dom_selection_is_collapsed (editor_page))
+		return;
 
+	if (!e_editor_undo_redo_manager_is_operation_in_progress (manager)) {
 		ev = g_new0 (EEditorHistoryEvent, 1);
 		ev->type = HISTORY_REPLACE;
 
@@ -17116,14 +17443,12 @@ e_editor_dom_selection_replace (EEditorP
 			&ev->before.end.x,
 			&ev->before.end.y);
 
-		range = e_editor_dom_get_current_range (editor_page);
-
 		ev->data.string.from = webkit_dom_range_get_text (range);
 		ev->data.string.to = g_strdup (replacement);
-
-		g_clear_object (&range);
 	}
 
+	g_clear_object (&range);
+
 	e_editor_dom_exec_command (editor_page, E_CONTENT_EDITOR_COMMAND_INSERT_TEXT, replacement);
 
 	if (ev) {
@@ -17382,3 +17707,98 @@ e_editor_dom_selection_get_coordinates (
 	*start_y += 1;
 	*end_y += 1;
 }
+
+WebKitDOMRange *
+e_editor_dom_get_range_for_point (WebKitDOMDocument *document,
+                                  EEditorSelectionPoint point)
+{
+	glong scroll_left, scroll_top;
+	WebKitDOMHTMLElement *body;
+	WebKitDOMRange *range = NULL;
+
+	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 *dom_window = NULL;
+
+		dom_window = webkit_dom_document_get_default_view (document);
+		webkit_dom_dom_window_scroll_to (dom_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);
+		g_clear_object (&dom_window);
+	}
+
+	return range;
+}
+
+void
+e_editor_dom_selection_restore_to_history_event_state (EEditorPage *editor_page,
+                                                       EEditorSelection selection_state)
+{
+	WebKitDOMDocument *document;
+	WebKitDOMDOMWindow *dom_window = NULL;
+	WebKitDOMDOMSelection *dom_selection = NULL;
+	WebKitDOMElement *element, *tmp;
+	WebKitDOMRange *range = NULL;
+	gboolean was_collapsed = FALSE;
+
+	g_return_if_fail (E_IS_EDITOR_PAGE (editor_page));
+
+	document = e_editor_page_get_document (editor_page);
+	dom_window = webkit_dom_document_get_default_view (document);
+	dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+	g_clear_object (&dom_window);
+
+	/* Restore the selection how it was before the event occured. */
+	range = e_editor_dom_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);
+	g_clear_object (&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) {
+		g_clear_object (&dom_selection);
+		return;
+	}
+
+	e_editor_dom_selection_save (editor_page);
+
+	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 = e_editor_dom_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);
+	g_clear_object (&range);
+
+	e_editor_dom_selection_save (editor_page);
+
+	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");
+
+	e_editor_dom_selection_restore (editor_page);
+
+	g_clear_object (&dom_selection);
+}
diff -up evolution-3.22.6/modules/webkit-editor/web-extension/e-editor-dom-functions.h.composer-image-insert-undo evolution-3.22.6/modules/webkit-editor/web-extension/e-editor-dom-functions.h
--- evolution-3.22.6/modules/webkit-editor/web-extension/e-editor-dom-functions.h.composer-image-insert-undo	2016-09-19 10:22:58.000000000 +0200
+++ evolution-3.22.6/modules/webkit-editor/web-extension/e-editor-dom-functions.h	2017-03-24 15:12:21.898422514 +0100
@@ -24,6 +24,7 @@
 #undef E_UTIL_INCLUDE_WITHOUT_WEBKIT
 
 #include "e-editor-page.h"
+#include "e-editor-undo-redo-manager.h"
 
 /* stephenhay from https://mathiasbynens.be/demo/url-regex */
 #define URL_PROTOCOLS "news|telnet|nntp|file|https?|s?ftp|webcal|localhost|ssh"
@@ -158,7 +159,6 @@ void		e_editor_dom_process_content_after
 						(EEditorPage *editor_page);
 guint		e_editor_dom_get_caret_offset	(EEditorPage *editor_page);
 guint		e_editor_dom_get_caret_position	(EEditorPage *editor_page);
-void		e_editor_dom_drag_and_drop_end	(EEditorPage *editor_page);
 void		e_editor_dom_set_link_color	(EEditorPage *editor_page,
 						 const gchar *color);
 void		e_editor_dom_set_visited_link_color
@@ -208,6 +208,8 @@ WebKitDOMElement *
 						 WebKitDOMElement *element);
 gint		e_editor_dom_get_citation_level	(WebKitDOMNode *node,
 						 gboolean set_plaintext_quoted);
+void		e_editor_dom_save_history_for_drag
+						(EEditorPage *editor_page);
 void		e_editor_dom_save_history_for_drop
 						(EEditorPage *editor_page);
 void		e_editor_dom_fix_file_uri_images
@@ -347,6 +349,10 @@ EContentEditorAlignment
 void		e_editor_dom_selection_set_alignment
 						(EEditorPage *editor_page,
 						 EContentEditorAlignment alignment);
+void		e_editor_dom_insert_replace_all_history_event
+						(EEditorPage *editor_page,
+						 const gchar *search_text,
+						 const gchar *replacement);
 void		e_editor_dom_selection_replace	(EEditorPage *editor_page,
 						 const gchar *replacement);
 void		e_editor_dom_replace_caret_word	(EEditorPage *editor_page,
@@ -370,7 +376,13 @@ void		e_editor_dom_selection_get_coordin
 						 guint *end_y);
 gboolean	e_editor_dom_is_selection_position_node
 						(WebKitDOMNode *node);
-
+WebKitDOMRange *
+		e_editor_dom_get_range_for_point
+						(WebKitDOMDocument *document,
+						 EEditorSelectionPoint point);
+void		e_editor_dom_selection_restore_to_history_event_state
+						(EEditorPage *editor_page,
+						 EEditorSelection selection_state);
 G_END_DECLS
 
 #endif /* E_EDITOR_DOM_FUNCTIONS_H */
diff -up evolution-3.22.6/modules/webkit-editor/web-extension/e-editor-undo-redo-manager.c.composer-image-insert-undo evolution-3.22.6/modules/webkit-editor/web-extension/e-editor-undo-redo-manager.c
--- evolution-3.22.6/modules/webkit-editor/web-extension/e-editor-undo-redo-manager.c.composer-image-insert-undo	2017-03-24 15:12:21.891422514 +0100
+++ evolution-3.22.6/modules/webkit-editor/web-extension/e-editor-undo-redo-manager.c	2017-03-24 15:12:21.899422514 +0100
@@ -113,114 +113,19 @@ editor_undo_redo_manager_ref_editor_page
 	return g_weak_ref_get (&manager->priv->editor_page);
 }
 
-static WebKitDOMRange *
-get_range_for_point (WebKitDOMDocument *document,
-                     EEditorSelectionPoint point)
-{
-	glong scroll_left, scroll_top;
-	WebKitDOMHTMLElement *body;
-	WebKitDOMRange *range = NULL;
-
-	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 *dom_window = NULL;
-
-		dom_window = webkit_dom_document_get_default_view (document);
-		webkit_dom_dom_window_scroll_to (dom_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);
-		g_clear_object (&dom_window);
-	}
-
-	return range;
-}
-
-static void
-restore_selection_to_history_event_state (EEditorPage *editor_page,
-                                          EEditorSelection selection_state)
-{
-	WebKitDOMDocument *document;
-	WebKitDOMDOMWindow *dom_window = NULL;
-	WebKitDOMDOMSelection *dom_selection = NULL;
-	WebKitDOMElement *element, *tmp;
-	WebKitDOMRange *range = NULL;
-	gboolean was_collapsed = FALSE;
-
-	g_return_if_fail (E_IS_EDITOR_PAGE (editor_page));
-
-	document = e_editor_page_get_document (editor_page);
-	dom_window = webkit_dom_document_get_default_view (document);
-	dom_selection = webkit_dom_dom_window_get_selection (dom_window);
-	g_clear_object (&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);
-	g_clear_object (&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) {
-		g_clear_object (&dom_selection);
-		return;
-	}
-
-	e_editor_dom_selection_save (editor_page);
-
-	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);
-	g_clear_object (&range);
-
-	e_editor_dom_selection_save (editor_page);
-
-	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");
-
-	e_editor_dom_selection_restore (editor_page);
-
-	g_clear_object (&dom_selection);
-}
-
 static void
 print_node_inner_html (WebKitDOMNode *node)
 {
 	gchar *inner_html;
 
 	if (!node) {
-		printf ("    none\n");
+		printf ("    content: none\n");
 		return;
 	}
 
 	inner_html = dom_get_node_inner_html (node);
 
-	printf ("    '%s'\n", inner_html);
+	printf ("    content: '%s'\n", inner_html);
 
 	g_free (inner_html);
 }
@@ -230,14 +135,22 @@ print_history_event (EEditorHistoryEvent
 {
 	if (event->type != HISTORY_START && event->type != HISTORY_AND) {
 		printf ("  %s\n", event_type_string[event->type]);
-		printf ("    before: start_x: %u ; start_y: %u ; end_x: %u ; end_y: %u ;\n",
+		printf ("    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 ("    after:  start_x: %u ; start_y: %u ; end_x: %u ; end_y: %u ;\n",
+		printf ("    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:
+			if (g_object_get_data (G_OBJECT (event->data.fragment), "history-delete-key")) {
+				printf ("    type: delete\n");
+			} else
+				printf ("    type: backspace\n");
+			if (g_object_get_data (G_OBJECT (event->data.fragment), "history-control-key"))
+				printf ("          control\n");
 		case HISTORY_INPUT:
+			if (g_object_get_data (G_OBJECT (event->data.fragment), "history-return-key"))
+				printf ("    type: return\n");
 		case HISTORY_REMOVE_LINK:
 		case HISTORY_SMILEY:
 		case HISTORY_IMAGE:
@@ -254,13 +167,13 @@ print_history_event (EEditorHistoryEvent
 		case HISTORY_UNDERLINE:
 		case HISTORY_STRIKETHROUGH:
 		case HISTORY_WRAP:
-			printf ("    from %d to %d ;\n", event->data.style.from, event->data.style.to);
+			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);
+			printf ("    pasting: '%s' \n", event->data.string.to);
 			break;
 		case HISTORY_HRULE_DIALOG:
 		case HISTORY_IMAGE_DIALOG:
@@ -275,7 +188,7 @@ print_history_event (EEditorHistoryEvent
 		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);
+			printf ("    from '%s' to '%s'\n", event->data.string.from, event->data.string.to);
 			break;
 		case HISTORY_START:
 			printf ("  HISTORY START\n");
@@ -454,7 +367,7 @@ undo_delete (EEditorPage *editor_page,
 	     g_object_get_data (G_OBJECT (event->data.fragment), "history-concatenating-blocks")) {
 		WebKitDOMNode *node, *block;
 
-		range = get_range_for_point (document, event->after.start);
+		range = e_editor_dom_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);
 
@@ -528,7 +441,7 @@ undo_delete (EEditorPage *editor_page,
 		g_clear_object (&range);
 		g_clear_object (&dom_selection);
 
-		restore_selection_to_history_event_state (editor_page, event->before);
+		e_editor_dom_selection_restore_to_history_event_state (editor_page, event->before);
 
 		e_editor_dom_force_spell_check_in_viewport (editor_page);
 
@@ -544,7 +457,7 @@ undo_delete (EEditorPage *editor_page,
 			WebKitDOMElement *element;
 			WebKitDOMNode *next_sibling;
 
-			range = get_range_for_point (document, event->before.start);
+			range = e_editor_dom_get_range_for_point (document, event->before.start);
 			webkit_dom_dom_selection_remove_all_ranges (dom_selection);
 			webkit_dom_dom_selection_add_range (dom_selection, range);
 			g_clear_object (&range);
@@ -598,7 +511,7 @@ undo_delete (EEditorPage *editor_page,
 		WebKitDOMNode *node, *current_block, *last_child;
 		WebKitDOMNode *next_block, *insert_before;
 
-		range = get_range_for_point (document, event->after.start);
+		range = e_editor_dom_get_range_for_point (document, event->after.start);
 		webkit_dom_dom_selection_remove_all_ranges (dom_selection);
 		webkit_dom_dom_selection_add_range (dom_selection, range);
 		g_clear_object (&range);
@@ -698,7 +611,7 @@ undo_delete (EEditorPage *editor_page,
 
 				dom_remove_selection_markers (document);
 
-				restore_selection_to_history_event_state (editor_page, event->before);
+				e_editor_dom_selection_restore_to_history_event_state (editor_page, event->before);
 
 				e_editor_dom_force_spell_check_in_viewport (editor_page);
 
@@ -794,9 +707,9 @@ undo_delete (EEditorPage *editor_page,
 
 		/* Create temporary node on the selection where the delete occured. */
 		if (webkit_dom_document_fragment_query_selector (event->data.fragment, ".Apple-tab-span", NULL))
-			range = get_range_for_point (document, event->before.start);
+			range = e_editor_dom_get_range_for_point (document, event->before.start);
 		else
-			range = get_range_for_point (document, event->after.start);
+			range = e_editor_dom_get_range_for_point (document, event->after.start);
 
 		/* If redoing an INPUT event that was done in the middle of the
 		 * text we need to move one character backward as the range is
@@ -940,7 +853,7 @@ undo_delete (EEditorPage *editor_page,
 		if (webkit_dom_document_fragment_query_selector (event->data.fragment, "span#-x-evo-selection-start-marker", NULL))
 			e_editor_dom_selection_restore (editor_page);
 		else
-			restore_selection_to_history_event_state (editor_page, event->before);
+			e_editor_dom_selection_restore_to_history_event_state (editor_page, event->before);
 
 		if (event->type != HISTORY_INPUT) {
 			if (e_editor_page_get_magic_smileys_enabled (editor_page))
@@ -966,7 +879,7 @@ redo_delete (EEditorPage *editor_page,
 	gint ii;
 
 	manager = e_editor_page_get_undo_redo_manager (editor_page);
-	restore_selection_to_history_event_state (editor_page, event->before);
+	e_editor_dom_selection_restore_to_history_event_state (editor_page, event->before);
 
 	delete_key = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (event->data.fragment), "history-delete-key"));
 	control_key = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (event->data.fragment), "history-control-key"));
@@ -1048,7 +961,7 @@ redo_delete (EEditorPage *editor_page,
 	e_editor_dom_body_key_up_event_process_backspace_or_delete (editor_page, delete_key);
 	e_editor_page_set_renew_history_after_coordinates (editor_page, TRUE);
 
-	restore_selection_to_history_event_state (editor_page, event->after);
+	e_editor_dom_selection_restore_to_history_event_state (editor_page, event->after);
 
 	e_editor_dom_force_spell_check_for_current_paragraph (editor_page);
 }
@@ -1091,11 +1004,11 @@ undo_redo_style_change (EEditorPage *edi
 			return;
 	}
 
-	restore_selection_to_history_event_state (editor_page, undo ? event->after : event->before);
+	e_editor_dom_selection_restore_to_history_event_state (editor_page, undo ? event->after : event->before);
 
 	func (editor_page, undo ? event->data.style.from : event->data.style.to);
 
-	restore_selection_to_history_event_state (editor_page, undo ? event->before : event->after);
+	e_editor_dom_selection_restore_to_history_event_state (editor_page, undo ? event->before : event->after);
 }
 
 static void
@@ -1105,7 +1018,7 @@ undo_redo_indent (EEditorPage *editor_pa
 {
 	gboolean was_indent = FALSE;
 
-	restore_selection_to_history_event_state (editor_page, undo ? event->after : event->before);
+	e_editor_dom_selection_restore_to_history_event_state (editor_page, undo ? event->after : event->before);
 
 	was_indent = event->data.style.from && event->data.style.to;
 
@@ -1114,7 +1027,7 @@ undo_redo_indent (EEditorPage *editor_pa
 	else
 		e_editor_dom_selection_indent (editor_page);
 
-	restore_selection_to_history_event_state (editor_page, undo ? event->before : event->after);
+	e_editor_dom_selection_restore_to_history_event_state (editor_page, undo ? event->before : event->after);
 }
 
 static void
@@ -1122,13 +1035,13 @@ undo_redo_font_color (EEditorPage *edito
                       EEditorHistoryEvent *event,
                       gboolean undo)
 {
-	restore_selection_to_history_event_state (editor_page, undo ? event->after : event->before);
+	e_editor_dom_selection_restore_to_history_event_state (editor_page, undo ? event->after : event->before);
 
 	e_editor_dom_exec_command (editor_page,
 		E_CONTENT_EDITOR_COMMAND_FORE_COLOR,
 		undo ? event->data.string.from : event->data.string.to);
 
-	restore_selection_to_history_event_state (editor_page, undo ? event->before : event->after);
+	e_editor_dom_selection_restore_to_history_event_state (editor_page, undo ? event->before : event->after);
 }
 
 static void
@@ -1136,7 +1049,7 @@ undo_redo_wrap (EEditorPage *editor_page
                 EEditorHistoryEvent *event,
                 gboolean undo)
 {
-	restore_selection_to_history_event_state (editor_page, undo ? event->after : event->before);
+	e_editor_dom_selection_restore_to_history_event_state (editor_page, undo ? event->after : event->before);
 
 	if (undo) {
 		WebKitDOMNode *node;
@@ -1154,7 +1067,7 @@ undo_redo_wrap (EEditorPage *editor_page
 	} else
 		e_editor_dom_selection_wrap (editor_page);
 
-	restore_selection_to_history_event_state (editor_page, undo ? event->before : event->after);
+	e_editor_dom_selection_restore_to_history_event_state (editor_page, undo ? event->before : event->after);
 }
 
 static void
@@ -1170,7 +1083,7 @@ undo_redo_page_dialog (EEditorPage *edit
 	document = e_editor_page_get_document (editor_page);
 	body = webkit_dom_document_get_body (document);
 
-	restore_selection_to_history_event_state (editor_page, undo ? event->after : event->before);
+	e_editor_dom_selection_restore_to_history_event_state (editor_page, undo ? event->after : event->before);
 
 	if (undo) {
 		attributes = webkit_dom_element_get_attributes (WEBKIT_DOM_ELEMENT (body));
@@ -1249,7 +1162,7 @@ undo_redo_page_dialog (EEditorPage *edit
 	g_clear_object (&attributes);
 	g_clear_object (&attributes_history);
 
-	restore_selection_to_history_event_state (editor_page, undo ? event->before : event->after);
+	e_editor_dom_selection_restore_to_history_event_state (editor_page, undo ? event->before : event->after);
 }
 
 static void
@@ -1262,7 +1175,7 @@ undo_redo_hrule_dialog (EEditorPage *edi
 
 	document = e_editor_page_get_document (editor_page);
 
-	restore_selection_to_history_event_state (editor_page, undo ? event->after : event->before);
+	e_editor_dom_selection_restore_to_history_event_state (editor_page, undo ? event->after : event->before);
 
 	e_editor_dom_selection_save (editor_page);
 	element = webkit_dom_document_get_element_by_id (
@@ -1314,7 +1227,7 @@ undo_redo_hrule_dialog (EEditorPage *edi
 
 	if (undo) {
 		dom_remove_selection_markers (document);
-		restore_selection_to_history_event_state (editor_page, event->before);
+		e_editor_dom_selection_restore_to_history_event_state (editor_page, event->before);
 	} else
 		e_editor_dom_selection_restore (editor_page);
 }
@@ -1330,7 +1243,7 @@ undo_redo_image_dialog (EEditorPage *edi
 
 	document = e_editor_page_get_document (editor_page);
 
-	restore_selection_to_history_event_state (editor_page, undo ? event->after : event->before);
+	e_editor_dom_selection_restore_to_history_event_state (editor_page, undo ? event->after : event->before);
 
 	e_editor_dom_selection_save (editor_page);
 	element = webkit_dom_document_get_element_by_id (
@@ -1364,7 +1277,7 @@ undo_redo_image_dialog (EEditorPage *edi
 		NULL);
 
 	if (undo)
-		restore_selection_to_history_event_state (editor_page, event->before);
+		e_editor_dom_selection_restore_to_history_event_state (editor_page, event->before);
 	else
 		e_editor_dom_selection_restore (editor_page);
 }
@@ -1379,7 +1292,7 @@ undo_redo_link_dialog (EEditorPage *edit
 
 	document = e_editor_page_get_document (editor_page);
 
-	restore_selection_to_history_event_state (editor_page, undo ? event->after : event->before);
+	e_editor_dom_selection_restore_to_history_event_state (editor_page, undo ? event->after : event->before);
 
 	e_editor_dom_selection_save (editor_page);
 
@@ -1425,7 +1338,7 @@ undo_redo_link_dialog (EEditorPage *edit
 	}
 
 	if (undo)
-		restore_selection_to_history_event_state (editor_page, event->before);
+		e_editor_dom_selection_restore_to_history_event_state (editor_page, event->before);
 	else
 		e_editor_dom_selection_restore (editor_page);
 }
@@ -1440,7 +1353,7 @@ undo_redo_table_dialog (EEditorPage *edi
 
 	document = e_editor_page_get_document (editor_page);
 
-	restore_selection_to_history_event_state (editor_page, undo ? event->after : event->before);
+	e_editor_dom_selection_restore_to_history_event_state (editor_page, undo ? event->after : event->before);
 
 	e_editor_dom_selection_save (editor_page);
 	element = webkit_dom_document_get_element_by_id (document, "-x-evo-selection-start-marker");
@@ -1459,7 +1372,7 @@ undo_redo_table_dialog (EEditorPage *edi
 				webkit_dom_node_clone_node_with_error (undo ? event->data.dom.from : event->data.dom.to, TRUE, NULL),
 				WEBKIT_DOM_NODE (parent),
 				NULL);
-			restore_selection_to_history_event_state (editor_page, event->before);
+			e_editor_dom_selection_restore_to_history_event_state (editor_page, event->before);
 			return;
 		} else
 			return;
@@ -1486,7 +1399,7 @@ undo_redo_table_dialog (EEditorPage *edi
 	}
 
 	if (undo)
-		restore_selection_to_history_event_state (editor_page, event->before);
+		e_editor_dom_selection_restore_to_history_event_state (editor_page, event->before);
 	else
 		e_editor_dom_selection_restore (editor_page);
 }
@@ -1505,7 +1418,7 @@ undo_redo_table_input (EEditorPage *edit
 
 	document = e_editor_page_get_document (editor_page);
 
-	restore_selection_to_history_event_state (editor_page, undo ? event->after : event->before);
+	e_editor_dom_selection_restore_to_history_event_state (editor_page, undo ? event->after : event->before);
 
 	dom_window = webkit_dom_document_get_default_view (document);
 	dom_selection = webkit_dom_dom_window_get_selection (dom_window);
@@ -1554,7 +1467,7 @@ undo_redo_paste (EEditorPage *editor_pag
 			WebKitDOMElement *tmp;
 			WebKitDOMNode *parent;
 
-			restore_selection_to_history_event_state (editor_page, event->after);
+			e_editor_dom_selection_restore_to_history_event_state (editor_page, event->after);
 
 			e_editor_dom_selection_save (editor_page);
 			tmp = webkit_dom_document_get_element_by_id (
@@ -1573,7 +1486,9 @@ undo_redo_paste (EEditorPage *editor_pag
 				NULL);
 
 			e_editor_dom_selection_restore (editor_page);
-		} else {
+		} else if (event->after.start.x == event->after.end.x &&
+		           event->after.start.y == event->after.end.y) {
+			/* Selection was collapsed after the event */
 			WebKitDOMDOMWindow *dom_window = NULL;
 			WebKitDOMDOMSelection *dom_selection = NULL;
 			WebKitDOMElement *element, *tmp;
@@ -1583,8 +1498,8 @@ undo_redo_paste (EEditorPage *editor_pag
 			dom_selection = webkit_dom_dom_window_get_selection (dom_window);
 			g_clear_object (&dom_window);
 
-			/* Restore the selection how it was before the event occured. */
-			range = get_range_for_point (document, event->before.start);
+			/* Restore the selection how it was before the event occurred. */
+			range = e_editor_dom_get_range_for_point (document, event->before.start);
 			webkit_dom_dom_selection_remove_all_ranges (dom_selection);
 			webkit_dom_dom_selection_add_range (dom_selection, range);
 			g_clear_object (&range);
@@ -1601,7 +1516,7 @@ undo_redo_paste (EEditorPage *editor_pag
 
 			webkit_dom_element_remove_attribute (element, "id");
 
-			range = get_range_for_point (document, event->after.start);
+			range = e_editor_dom_get_range_for_point (document, event->after.start);
 			webkit_dom_dom_selection_remove_all_ranges (dom_selection);
 			webkit_dom_dom_selection_add_range (dom_selection, range);
 			g_clear_object (&range);
@@ -1622,9 +1537,15 @@ undo_redo_paste (EEditorPage *editor_pag
 			e_editor_dom_exec_command (editor_page, E_CONTENT_EDITOR_COMMAND_DELETE, NULL);
 
 			e_editor_dom_force_spell_check_for_current_paragraph (editor_page);
+		} else {
+			e_editor_dom_selection_restore_to_history_event_state (editor_page, event->after);
+
+			e_editor_dom_exec_command (editor_page, E_CONTENT_EDITOR_COMMAND_DELETE, NULL);
+
+			e_editor_dom_force_spell_check_for_current_paragraph (editor_page);
 		}
 	} else {
-		restore_selection_to_history_event_state (editor_page, event->before);
+		e_editor_dom_selection_restore_to_history_event_state (editor_page, event->before);
 
 		if (event->type == HISTORY_PASTE)
 			e_editor_dom_convert_and_insert_html_into_selection (editor_page, event->data.string.to, FALSE);
@@ -1635,6 +1556,8 @@ undo_redo_paste (EEditorPage *editor_pag
 		else
 			e_editor_dom_convert_and_insert_html_into_selection (editor_page, event->data.string.to, FALSE);
 			/* e_editor_selection_insert_as_text (selection, event->data.string.to); */
+
+		e_editor_dom_selection_restore_to_history_event_state (editor_page, event->after);
 	}
 }
 
@@ -1657,7 +1580,7 @@ undo_redo_image (EEditorPage *editor_pag
 		WebKitDOMElement *element;
 		WebKitDOMNode *node;
 
-		range = get_range_for_point (document, event->before.start);
+		range = e_editor_dom_get_range_for_point (document, event->before.start);
 		webkit_dom_dom_selection_remove_all_ranges (dom_selection);
 		webkit_dom_dom_selection_add_range (dom_selection, range);
 		g_clear_object (&range);
@@ -1668,15 +1591,24 @@ undo_redo_image (EEditorPage *editor_pag
 
 		node = webkit_dom_node_get_next_sibling  (WEBKIT_DOM_NODE (element));
 
-		if (WEBKIT_DOM_IS_ELEMENT (node))
+		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);
+			else if (WEBKIT_DOM_IS_HTML_IMAGE_ELEMENT (node)) {
+				WebKitDOMNode *parent;
+
+				parent = webkit_dom_node_get_parent_node (node);
+				if (element_has_class (WEBKIT_DOM_ELEMENT (parent), "-x-evo-resizable-wrapper") ||
+				    element_has_class (WEBKIT_DOM_ELEMENT (parent), "-x-evo-smiley-wrapper"))
+					remove_node (parent);
+			}
+		}
 		e_editor_dom_selection_restore (editor_page);
 	} else {
 		WebKitDOMElement *element;
 
-		range = get_range_for_point (document, event->before.start);
+		range = e_editor_dom_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);
@@ -1709,9 +1641,10 @@ undo_redo_replace (EEditorPage *editor_p
 
 	document = e_editor_page_get_document (editor_page);
 
-	restore_selection_to_history_event_state (editor_page, undo ? event->after : event->before);
+	e_editor_dom_selection_restore_to_history_event_state (editor_page, undo ? event->after : event->before);
 
 	if (undo) {
+		gint ii = 0;
 		WebKitDOMDOMWindow *dom_window = NULL;
 		WebKitDOMDOMSelection *dom_selection = NULL;
 
@@ -1719,7 +1652,9 @@ undo_redo_replace (EEditorPage *editor_p
 		dom_selection = webkit_dom_dom_window_get_selection (dom_window);
 		g_clear_object (&dom_window);
 
-		webkit_dom_dom_selection_modify (dom_selection, "extend", "left", "word");
+		for (ii = g_utf8_strlen (event->data.string.to, -1); ii--;)
+			webkit_dom_dom_selection_modify (dom_selection, "extend", "left", "character");
+
 		g_clear_object (&dom_selection);
 	}
 
@@ -1729,7 +1664,7 @@ undo_redo_replace (EEditorPage *editor_p
 
 	e_editor_dom_force_spell_check_for_current_paragraph (editor_page);
 
-	restore_selection_to_history_event_state (editor_page, undo ? event->before : event->after);
+	e_editor_dom_selection_restore_to_history_event_state (editor_page, undo ? event->before : event->after);
 }
 
 static void
@@ -1828,7 +1763,7 @@ undo_redo_remove_link (EEditorPage *edit
 
 	document = e_editor_page_get_document (editor_page);
 
-	restore_selection_to_history_event_state (editor_page, undo ? event->after : event->before);
+	e_editor_dom_selection_restore_to_history_event_state (editor_page, undo ? event->after : event->before);
 
 	if (undo) {
 		WebKitDOMDOMWindow *dom_window = NULL;
@@ -1857,7 +1792,7 @@ undo_redo_remove_link (EEditorPage *edit
 	} else
 		e_editor_dom_selection_unlink (editor_page);
 
-	restore_selection_to_history_event_state (editor_page, undo ? event->before : event->after);
+	e_editor_dom_selection_restore_to_history_event_state (editor_page, undo ? event->before : event->after);
 }
 
 static void
@@ -1916,7 +1851,7 @@ undo_return_press_after_h_rule (EEditorP
 	     WEBKIT_DOM_IS_HTML_HR_ELEMENT (node)) {
 
 		remove_node_if_empty (WEBKIT_DOM_NODE (block));
-		restore_selection_to_history_event_state (editor_page, event->before);
+		e_editor_dom_selection_restore_to_history_event_state (editor_page, event->before);
 
 		return TRUE;
 	}
@@ -1939,7 +1874,7 @@ undo_input (EEditorUndoRedoManager *mana
 	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 (editor_page, event->after);
+	e_editor_dom_selection_restore_to_history_event_state (editor_page, event->after);
 
 	/* Undoing Return press after the HR element */
 	if (e_editor_page_get_html_mode (editor_page) &&
@@ -2053,7 +1988,7 @@ undo_redo_citation_split (EEditorPage *e
 		WebKitDOMElement *selection_start, *parent;
 		WebKitDOMNode *citation_before, *citation_after, *child, *last_child, *tmp;
 
-		restore_selection_to_history_event_state (editor_page, event->after);
+		e_editor_dom_selection_restore_to_history_event_state (editor_page, event->after);
 
 		e_editor_dom_selection_save (editor_page);
 		selection_start = webkit_dom_document_get_element_by_id (
@@ -2137,11 +2072,11 @@ undo_redo_citation_split (EEditorPage *e
  out:
 		e_editor_dom_merge_siblings_if_necessary (editor_page, NULL);
 
-		restore_selection_to_history_event_state (editor_page, event->before);
+		e_editor_dom_selection_restore_to_history_event_state (editor_page, event->before);
 
 		e_editor_dom_force_spell_check_in_viewport (editor_page);
 	} else {
-		restore_selection_to_history_event_state (editor_page, event->before);
+		e_editor_dom_selection_restore_to_history_event_state (editor_page, event->before);
 
 		if (in_situ) {
 			WebKitDOMElement *selection_start_marker;
@@ -2176,7 +2111,7 @@ undo_redo_unquote (EEditorPage *editor_p
 
 	document = e_editor_page_get_document (editor_page);
 
-	restore_selection_to_history_event_state (editor_page, undo ? event->after : event->before);
+	e_editor_dom_selection_restore_to_history_event_state (editor_page, undo ? event->after : event->before);
 
 	e_editor_dom_selection_save (editor_page);
 	element = webkit_dom_document_get_element_by_id (
@@ -2221,7 +2156,7 @@ undo_redo_unquote (EEditorPage *editor_p
 	if (undo)
 		e_editor_dom_selection_restore (editor_page);
 	else
-		restore_selection_to_history_event_state (editor_page, event->after);
+		e_editor_dom_selection_restore_to_history_event_state (editor_page, event->after);
 
 	e_editor_dom_force_spell_check_for_current_paragraph (editor_page);
 }
@@ -2366,6 +2301,21 @@ e_editor_undo_redo_manager_get_current_h
 	return NULL;
 }
 
+EEditorHistoryEvent *
+e_editor_undo_redo_manager_get_next_history_event_for (EEditorUndoRedoManager *manager,
+                                                       EEditorHistoryEvent *event)
+{
+	g_return_val_if_fail (E_IS_EDITOR_UNDO_REDO_MANAGER (manager), NULL);
+
+	if (manager->priv->history) {
+		GList *item = g_list_find (manager->priv->history, event);
+		if (item && item->next)
+			return item->next->data;
+	}
+
+	return NULL;
+}
+
 void
 e_editor_undo_redo_manager_remove_current_history_event (EEditorUndoRedoManager *manager)
 {
@@ -2458,6 +2408,85 @@ e_editor_undo_redo_manager_insert_dash_h
 	}
 
 	g_object_unref (editor_page);
+}
+
+static void
+copy_event_coordinates_to_event (EEditorHistoryEvent *source,
+                                 EEditorHistoryEvent *target)
+{
+	target->before.start.x = source->before.start.x;
+	target->before.start.y = source->before.start.y;
+	target->before.end.x = source->before.end.x;
+	target->before.end.y = source->before.end.y;
+	target->after.start.x = source->after.start.x;
+	target->after.start.y = source->after.start.y;
+	target->after.end.x = source->after.end.x;
+	target->after.end.y = source->after.end.y;
+}
+
+void
+e_editor_undo_redo_manager_last_drop_operation_did_copy (EEditorUndoRedoManager *manager)
+{
+	EEditorPage *editor_page;
+	GList *history;
+
+	g_return_if_fail (E_IS_EDITOR_UNDO_REDO_MANAGER (manager));
+
+	editor_page = editor_undo_redo_manager_ref_editor_page (manager);
+	g_return_if_fail (editor_page != NULL);
+
+	history = manager->priv->history;
+	if (history) {
+		GList *history_and, *history_delete;
+		EEditorHistoryEvent *original_insert, *item;
+		WebKitDOMDocumentFragment *fragment;
+
+		/* When a drag operation within an editor is performed, we save
+		 * the history for it. We always assume that the drop will move
+		 * the content (the default action) and not copy it, thus the
+		 * history contains one delete item and one 'and' item. If the
+		 * action is changed to copy (by holding the Control key during
+		 * drop) there is not content deleted, but we saved it to the
+		 * history. What this function does is that it changes the
+		 * history to not delete any content, but to only insert the
+		 * dropped one. */
+		original_insert = history->data;
+		if (original_insert->type != HISTORY_INSERT_HTML || !history->next) {
+			g_object_unref (editor_page);
+			return;
+		}
+
+		history_and = history->next;
+		item = history_and->data;
+		if (item->type != HISTORY_AND || !history_and->next) {
+			g_object_unref (editor_page);
+			return;
+		}
+
+		history_delete = history_and->next;
+		item = history_delete->data;
+		if (item->type != HISTORY_DELETE) {
+			g_object_unref (editor_page);
+			return;
+		}
+
+		/* Change the history type from 'Delete' to 'Insert' */
+		item->type = HISTORY_INSERT_HTML;
+		copy_event_coordinates_to_event (original_insert, item);
+
+		/* Copy the content */
+		fragment = item->data.fragment;
+		item->data.fragment = NULL;
+		item->data.string.to = dom_get_node_inner_html (WEBKIT_DOM_NODE (fragment));
+		g_clear_object (&fragment);
+
+		/* Remove the old insert event */
+		remove_history_event (manager, manager->priv->history);
+		/* And the 'AND' event */
+		remove_history_event (manager, manager->priv->history);
+	}
+
+	g_object_unref (editor_page);
 }
 
 gboolean
diff -up evolution-3.22.6/modules/webkit-editor/web-extension/e-editor-undo-redo-manager.h.composer-image-insert-undo evolution-3.22.6/modules/webkit-editor/web-extension/e-editor-undo-redo-manager.h
--- evolution-3.22.6/modules/webkit-editor/web-extension/e-editor-undo-redo-manager.h.composer-image-insert-undo	2016-09-19 10:22:58.000000000 +0200
+++ evolution-3.22.6/modules/webkit-editor/web-extension/e-editor-undo-redo-manager.h	2017-03-24 15:12:21.899422514 +0100
@@ -151,12 +151,21 @@ void		e_editor_undo_redo_manager_insert_
 EEditorHistoryEvent *
 		e_editor_undo_redo_manager_get_current_history_event
 						(EEditorUndoRedoManager *manager);
+
+EEditorHistoryEvent *
+		e_editor_undo_redo_manager_get_next_history_event_for
+						(EEditorUndoRedoManager *manager,
+						 EEditorHistoryEvent *event);
+
 void		e_editor_undo_redo_manager_remove_current_history_event
 						(EEditorUndoRedoManager *manager);
 
 void		e_editor_undo_redo_manager_insert_dash_history_event
 						(EEditorUndoRedoManager *manager);
 
+void		e_editor_undo_redo_manager_last_drop_operation_did_copy
+						(EEditorUndoRedoManager *manager);
+
 gboolean	e_editor_undo_redo_manager_can_undo
 						(EEditorUndoRedoManager *manager);
 
diff -up evolution-3.22.6/modules/webkit-editor/web-extension/e-editor-web-extension.c.composer-image-insert-undo evolution-3.22.6/modules/webkit-editor/web-extension/e-editor-web-extension.c
--- evolution-3.22.6/modules/webkit-editor/web-extension/e-editor-web-extension.c.composer-image-insert-undo	2017-03-13 11:24:55.000000000 +0100
+++ evolution-3.22.6/modules/webkit-editor/web-extension/e-editor-web-extension.c	2017-03-24 15:13:16.839420073 +0100
@@ -480,9 +480,6 @@ static const gchar *introspection_xml =
 "      <arg type='s' name='selector' direction='in'/>"
 "      <arg type='s' name='uri' direction='in'/>"
 "    </method>"
-"    <method name='DOMDragAndDropEnd'>"
-"      <arg type='t' name='page_id' direction='in'/>"
-"    </method>"
 "    <method name='DOMMoveSelectionOnPoint'>"
 "      <arg type='t' name='page_id' direction='in'/>"
 "      <arg type='i' name='x' direction='in'/>"
@@ -493,6 +490,9 @@ static const gchar *introspection_xml =
 "      <arg type='t' name='page_id' direction='in'/>"
 "      <arg type='s' name='smiley_name' direction='in'/>"
 "    </method>"
+"    <method name='DOMLastDropOperationDidCopy'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"    </method>"
 "<!-- ********************************************************* -->"
 "<!--     Functions that are used in EEditorSelection       -->"
 "<!-- ********************************************************* -->"
@@ -503,6 +503,11 @@ static const gchar *introspection_xml =
 "      <arg type='t' name='page_id' direction='in'/>"
 "      <arg type='s' name='uri' direction='in'/>"
 "    </method>"
+"    <method name='DOMInsertReplaceAllHistoryEvent'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='search_text' direction='in'/>"
+"      <arg type='s' name='replacement' direction='in'/>"
+"    </method>"
 "    <method name='DOMSelectionReplace'>"
 "      <arg type='t' name='page_id' direction='in'/>"
 "      <arg type='s' name='replacement' direction='in'/>"
@@ -581,12 +586,6 @@ static const gchar *introspection_xml =
 "      <arg type='b' name='out_check_if_signature_is_changed' direction='out'/>"
 "      <arg type='b' name='out_ignore_next_signature_change' direction='out'/>"
 "    </method>"
-"    <method name='DOMSaveDragAndDropHistory'>"
-"      <arg type='t' name='page_id' direction='in'/>"
-"    </method>"
-"    <method name='DOMCleanAfterDragAndDrop'>"
-"      <arg type='t' name='page_id' direction='in'/>"
-"    </method>"
 "    <method name='DOMGetActiveSignatureUid'>"
 "      <arg type='t' name='page_id' direction='in'/>"
 "      <arg type='s' name='uid' direction='out'/>"
@@ -1859,15 +1858,6 @@ handle_method_call (GDBusConnection *con
 		e_editor_dom_replace_image_src (editor_page, selector, uri);
 
 		g_dbus_method_invocation_return_value (invocation, NULL);
-	} else if (g_strcmp0 (method_name, "DOMDragAndDropEnd") == 0) {
-		g_variant_get (parameters, "(t)", &page_id);
-
-		editor_page = get_editor_page_or_return_dbus_error (invocation, extension, page_id);
-		if (!editor_page)
-			goto error;
-
-		e_editor_dom_drag_and_drop_end (editor_page);
-		g_dbus_method_invocation_return_value (invocation, NULL);
 	} else if (g_strcmp0 (method_name, "DOMInsertSmiley") == 0) {
 		const gchar *smiley_name;
 
@@ -1935,6 +1925,17 @@ handle_method_call (GDBusConnection *con
 		e_editor_dom_insert_image (editor_page, uri);
 
 		g_dbus_method_invocation_return_value (invocation, NULL);
+	} else if (g_strcmp0 (method_name, "DOMInsertReplaceAllHistoryEvent") == 0) {
+		const gchar *replacement, *search_text;
+
+		g_variant_get (parameters, "(t&s&s)", &page_id, &search_text, &replacement);
+
+		editor_page = get_editor_page_or_return_dbus_error (invocation, extension, page_id);
+		if (!editor_page)
+			goto error;
+
+		e_editor_dom_insert_replace_all_history_event (editor_page, search_text, replacement);
+		g_dbus_method_invocation_return_value (invocation, NULL);
 	} else if (g_strcmp0 (method_name, "DOMSelectionReplace") == 0) {
 		const gchar *replacement;
 
@@ -2155,28 +2156,6 @@ handle_method_call (GDBusConnection *con
 				ignore_next_signature_change));
 
 		g_free (new_signature_id);
-	} else if (g_strcmp0 (method_name, "DOMSaveDragAndDropHistory") == 0) {
-		g_variant_get (
-			parameters, "(t)", &page_id);
-
-		editor_page = get_editor_page_or_return_dbus_error (invocation, extension, page_id);
-		if (!editor_page)
-			goto error;
-
-		e_composer_dom_save_drag_and_drop_history (editor_page);
-
-		g_dbus_method_invocation_return_value (invocation, NULL);
-	} else if (g_strcmp0 (method_name, "DOMCleanAfterDragAndDrop") == 0) {
-		g_variant_get (
-			parameters, "(t)", &page_id);
-
-		editor_page = get_editor_page_or_return_dbus_error (invocation, extension, page_id);
-		if (!editor_page)
-			goto error;
-
-		e_composer_dom_clean_after_drag_and_drop (editor_page);
-
-		g_dbus_method_invocation_return_value (invocation, NULL);
 	} else if (g_strcmp0 (method_name, "DOMGetActiveSignatureUid") == 0) {
 		gchar *value;
 
@@ -2194,6 +2173,20 @@ handle_method_call (GDBusConnection *con
 				"(@s)",
 				g_variant_new_take_string (
 					value ? value : g_strdup (""))));
+	} else if (g_strcmp0 (method_name, "DOMLastDropOperationDidCopy") == 0) {
+		EEditorUndoRedoManager *manager;
+
+		g_variant_get (parameters, "(t)", &page_id);
+
+		editor_page = get_editor_page_or_return_dbus_error (invocation, extension, page_id);
+		if (!editor_page)
+			goto error;
+
+		manager = e_editor_page_get_undo_redo_manager (editor_page);
+		if (manager)
+			e_editor_undo_redo_manager_last_drop_operation_did_copy (manager);
+
+		g_dbus_method_invocation_return_value (invocation, NULL);
 	} else if (g_strcmp0 (method_name, "DOMGetCaretPosition") == 0) {
 		guint32 value;
 
@@ -2243,7 +2236,7 @@ handle_method_call (GDBusConnection *con
 	return;
 
  error:
-	g_warning ("Cannot obtain WebKitWebPage for '%ld'", page_id);
+	g_warning ("Cannot obtain WebKitWebPage for '%" G_GUINT64_FORMAT "'", page_id);
 }
 
 static void