[evolution/webkit-composer: 74/111] Fix ESpellEntry crash



commit 5854b7ab0e5f4b1202f479adfe4a34bf1f3dfc74
Author: Dan VrÃtil <dvratil redhat com>
Date:   Wed Aug 29 15:43:02 2012 +0200

    Fix ESpellEntry crash

 composer/e-composer-private.c       |   17 ++-
 e-util/e-editor-widget.c            |   23 ++--
 e-util/e-editor-window.c            |    4 +-
 e-util/e-spell-dictionary.c         |    3 +
 e-util/e-spell-entry.c              |   67 ++++-----
 modules/mail/e-mail-shell-backend.c |    2 +-
 widgets/editor/selection-style.c    |  288 +++++++++++++++++++++++++++++++++++
 7 files changed, 347 insertions(+), 57 deletions(-)
---
diff --git a/composer/e-composer-private.c b/composer/e-composer-private.c
index 0ab151d..5f9371e 100644
--- a/composer/e-composer-private.c
+++ b/composer/e-composer-private.c
@@ -131,13 +131,18 @@ composer_update_gallery_visibility (EMsgComposer *composer)
 
 static void
 composer_spell_languages_changed (EMsgComposer *composer,
-                                  GList *languages)
+				  GParamSpec *pspec,
+				  EEditorWidget *editor_widget)
 {
+	GList *languages;
 	EComposerHeader *header;
 	EComposerHeaderTable *table = e_msg_composer_get_header_table (composer);
 
+	languages = e_editor_widget_get_spell_languages (editor_widget);
 	header = e_composer_header_table_get_header (table, E_COMPOSER_HEADER_SUBJECT);
 	e_composer_spell_header_set_languages (E_COMPOSER_SPELL_HEADER (header), languages);
+
+	g_list_free (languages);
 }
 
 void
@@ -288,17 +293,15 @@ e_composer_private_constructed (EMsgComposer *composer)
 	priv->header_table = g_object_ref (widget);
 	gtk_widget_show (widget);
 
-	header = e_composer_header_table_get_header (
-		E_COMPOSER_HEADER_TABLE (widget),
+	header = e_composer_header_table_get_header (E_COMPOSER_HEADER_TABLE (widget),
 		E_COMPOSER_HEADER_SUBJECT);
 	g_object_bind_property (
 		shell_settings, "composer-inline-spelling",
 		header->input_widget, "checking-enabled",
 		G_BINDING_SYNC_CREATE);
 
-	g_signal_connect (
-		G_OBJECT (composer), "spell-languages-changed",
-		G_CALLBACK (composer_spell_languages_changed), NULL);
+	g_signal_connect_swapped (editor_widget, "notify::spell-languages",
+		G_CALLBACK (composer_spell_languages_changed), composer);
 
 	/* Construct the attachment paned. */
 
@@ -1018,7 +1021,7 @@ composer_load_signature_cb (EMailSignatureComboBox *combo_box,
 		"<!--+GtkHTML:<DATA class=\"ClueFlow\" "
 		"    key=\"signature\" value=\"1\">-->"
 		"<!--+GtkHTML:<DATA class=\"ClueFlow\" "
-		"    key=\"signature_name\" value=\"uid:%s\">-->",
+		"    key=\"signature_name\" value=\"uid:%s\"-->",
 		(encoded_uid != NULL) ? encoded_uid : "");
 
 	g_string_append (
diff --git a/e-util/e-editor-widget.c b/e-util/e-editor-widget.c
index 23f8143..83f43a3 100644
--- a/e-util/e-editor-widget.c
+++ b/e-util/e-editor-widget.c
@@ -806,6 +806,15 @@ e_editor_widget_class_init (EEditorWidgetClass *klass)
 			FALSE,
 			G_PARAM_READABLE));
 
+	g_object_class_install_property (
+		object_class,
+		PROP_SPELL_LANGUAGES,
+		g_param_spec_pointer (
+			"spell-languages",
+			"Active spell checking languages",
+			NULL,
+			G_PARAM_READWRITE));
+
 	signals[POPUP_EVENT] = g_signal_new (
 		"popup-event",
 		G_TYPE_FROM_CLASS (klass),
@@ -1064,20 +1073,12 @@ void
 e_editor_widget_set_spell_languages (EEditorWidget *widget,
 				     GList *spell_languages)
 {
-	GList *iter;
-
 	g_return_if_fail (E_IS_EDITOR_WIDGET (widget));
 	g_return_if_fail (spell_languages);
 
-	g_list_free_full (widget->priv->spelling_langs, g_free);
-
-	widget->priv->spelling_langs = NULL;
-	for (iter = spell_languages; iter; iter = g_list_next (iter)) {
-		widget->priv->spelling_langs =
-			g_list_append (
-				widget->priv->spelling_langs,
-		  		g_strdup (iter->data));
-	}
+	g_list_free_full (widget->priv->spelling_langs, g_object_unref);
+	widget->priv->spelling_langs = g_list_copy (spell_languages);
+	g_list_foreach (widget->priv->spelling_langs, (GFunc) g_object_ref, NULL);
 
 	g_object_notify (G_OBJECT (widget), "spell-languages");
 }
diff --git a/e-util/e-editor-window.c b/e-util/e-editor-window.c
index fd55563..30a4286 100644
--- a/e-util/e-editor-window.c
+++ b/e-util/e-editor-window.c
@@ -147,8 +147,10 @@ e_editor_window_pack_above (EEditorWindow *window,
 	g_return_if_fail (E_IS_EDITOR_WINDOW (window));
 	g_return_if_fail (GTK_IS_WIDGET (child));
 
-	gtk_grid_insert_row (window->priv->main_layout, window->priv->editor_row);
+	gtk_grid_insert_row (
+		window->priv->main_layout, window->priv->editor_row);
 	window->priv->editor_row++;
+
 	gtk_grid_attach_next_to (
 		window->priv->main_layout, child,
 		GTK_WIDGET (window->priv->editor),
diff --git a/e-util/e-spell-dictionary.c b/e-util/e-spell-dictionary.c
index e5ed02a..002a5ac 100644
--- a/e-util/e-spell-dictionary.c
+++ b/e-util/e-spell-dictionary.c
@@ -647,5 +647,8 @@ gint
 e_spell_dictionary_compare (ESpellDictionary *dict1,
 			    ESpellDictionary *dict2)
 {
+	g_return_val_if_fail (E_IS_SPELL_DICTIONARY (dict1), 0);
+	g_return_val_if_fail (E_IS_SPELL_DICTIONARY (dict2), 0);
+
 	return strcmp (dict1->priv->collate_key, dict2->priv->collate_key);
 }
diff --git a/e-util/e-spell-entry.c b/e-util/e-spell-entry.c
index 2330fc1..ab870c3 100644
--- a/e-util/e-spell-entry.c
+++ b/e-util/e-spell-entry.c
@@ -42,7 +42,7 @@ struct _ESpellEntryPrivate
 	GSettings *settings;
 	gboolean custom_checkers;
 	gboolean checking_enabled;
-	GSList *dictionaries;
+	GList *dictionaries;
 	gchar **words;
 	gint *word_starts;
 	gint *word_ends;
@@ -74,12 +74,12 @@ word_misspelled (ESpellEntry *entry,
 	g_strlcpy (word, text + start, end - start + 1);
 
 	if (g_unichar_isalpha (*word)) {
-		GSList *li;
+		GList *li;
 		gssize wlen = strlen (word);
 
-		for (li = entry->priv->dictionaries; li; li = g_slist_next (li)) {
-			EnchantDict *dict = li->data;
-			if (enchant_dict_check (dict, word, wlen)) {
+		for (li = entry->priv->dictionaries; li; li = g_list_next (li)) {
+			ESpellDictionary *dict = li->data;
+			if (e_spell_dictionary_check (dict, word, wlen)) {
 				result = FALSE;
 				break;
 			}
@@ -253,14 +253,14 @@ add_to_dictionary (GtkWidget *menuitem,
 {
 	gchar *word;
 	gint start, end;
-	EnchantDict *dict;
+	ESpellDictionary *dict;
 
 	get_word_extents_from_position (entry, &start, &end, entry->priv->mark_character);
 	word = gtk_editable_get_chars (GTK_EDITABLE (entry), start, end);
 
 	dict = g_object_get_data (G_OBJECT (menuitem), "spell-entry-checker");
 	if (dict) {
-		enchant_dict_add_to_personal (dict, word, -1);
+		e_spell_dictionary_learn_word (dict, word, -1);
 	}
 
 	g_free (word);
@@ -281,14 +281,14 @@ ignore_all (GtkWidget *menuitem,
 {
 	gchar *word;
 	gint start, end;
-	GSList *li;
+	GList *li;
 
 	get_word_extents_from_position (entry, &start, &end, entry->priv->mark_character);
 	word = gtk_editable_get_chars (GTK_EDITABLE (entry), start, end);
 
-	for (li = entry->priv->dictionaries; li; li = g_slist_next (li)) {
-		EnchantDict *dict = li->data;
-		enchant_dict_add_to_session (dict, word, -1);
+	for (li = entry->priv->dictionaries; li; li = g_list_next (li)) {
+		ESpellDictionary *dict = li->data;
+		e_spell_dictionary_ignore_word (dict, word, -1);
 	}
 
 	g_free (word);
@@ -310,7 +310,7 @@ replace_word (GtkWidget *menuitem,
 	const gchar *newword;
 	gint start, end;
 	gint cursor;
-	EnchantDict *dict;
+	ESpellDictionary *dict;
 
 	get_word_extents_from_position (entry, &start, &end, entry->priv->mark_character);
 	oldword = gtk_editable_get_chars (GTK_EDITABLE (entry), start, end);
@@ -332,7 +332,7 @@ replace_word (GtkWidget *menuitem,
 	dict = g_object_get_data (G_OBJECT (menuitem), "spell-entry-checker");
 
 	if (dict) {
-		enchant_dict_store_replacement (dict, oldword, -1, newword, -1);
+		e_spell_dictionary_store_correction (dict, oldword, -1, newword, -1);
 	}
 
 	g_free (oldword);
@@ -415,11 +415,11 @@ build_spelling_menu (ESpellEntry *entry,
 		dict = entry->priv->dictionaries->data;
 		build_suggestion_menu (entry, topmenu, dict, word);
 	} else {
-		GSList *li;
+		GList *li;
 		GtkWidget *menu;
 		const gchar *lang_name;
 
-		for (li = entry->priv->dictionaries; li; li = g_slist_next (li)) {
+		for (li = entry->priv->dictionaries; li; li = g_list_next (li)) {
 			dict = li->data;
 
 			lang_name = e_spell_dictionary_get_name (dict);
@@ -453,14 +453,14 @@ build_spelling_menu (ESpellEntry *entry,
 		g_object_set_data (G_OBJECT (mi), "spell-entry-checker", dict);
 		g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (add_to_dictionary), entry);
 	} else {
-		GSList *li;
+		GList *li;
 		GtkWidget *menu, *submi;
 		const gchar *lang_name;
 
 		menu = gtk_menu_new ();
 		gtk_menu_item_set_submenu (GTK_MENU_ITEM (mi), menu);
 
-		for (li = entry->priv->dictionaries; li; li = g_slist_next (li)) {
+		for (li = entry->priv->dictionaries; li; li = g_list_next (li)) {
 			dict = li->data;
 
 			lang_name = e_spell_dictionary_get_name (dict);
@@ -571,7 +571,7 @@ spell_entry_changed (GtkEditable *editable)
 static void
 spell_entry_notify_scroll_offset (ESpellEntry *spell_entry)
 {
-	g_return_if_fail (spell_entry != NULL);
+	g_return_if_fail (E_IS_SPELL_ENTRY (spell_entry));
 
 	g_object_get (G_OBJECT (spell_entry), "scroll-offset", &spell_entry->priv->entry_scroll_offset, NULL);
 }
@@ -764,7 +764,7 @@ e_spell_entry_finalize (GObject *object)
 	g_clear_object (&entry->priv->spell_checker);
 
 	if (entry->priv->dictionaries) {
-		g_slist_free_full (entry->priv->dictionaries, g_object_unref);
+		g_list_free_full (entry->priv->dictionaries, g_object_unref);
 		entry->priv->dictionaries = NULL;
 	}
 
@@ -819,36 +819,29 @@ e_spell_entry_new (void)
 
 void
 e_spell_entry_set_languages (ESpellEntry *spell_entry,
-                             GList *languages)
+                             GList *dictionaries)
 {
-	GList *iter;
-
-	g_return_if_fail (spell_entry != NULL);
+	g_return_if_fail (E_IS_SPELL_ENTRY (spell_entry));
 
 	spell_entry->priv->custom_checkers = TRUE;
 
-	if (spell_entry->priv->dictionaries)
-		g_slist_free_full (spell_entry->priv->dictionaries, g_object_unref);
-	spell_entry->priv->dictionaries = NULL;
-
-	for (iter = languages; iter; iter = g_list_next (iter)) {
-		ESpellDictionary *dict = iter->data;
-
-		if (dict)
-			spell_entry->priv->dictionaries =
-				g_slist_prepend (spell_entry->priv->dictionaries, dict);
+	if (spell_entry->priv->dictionaries) {
+		g_list_free_full (spell_entry->priv->dictionaries, g_object_unref);
 	}
+	spell_entry->priv->dictionaries = NULL;
 
-	spell_entry->priv->dictionaries = g_slist_reverse (spell_entry->priv->dictionaries);
+	spell_entry->priv->dictionaries = g_list_copy (dictionaries);
+	g_list_foreach (spell_entry->priv->dictionaries, (GFunc) g_object_ref, NULL);
 
-	if (gtk_widget_get_realized (GTK_WIDGET (spell_entry)))
+	if (gtk_widget_get_realized (GTK_WIDGET (spell_entry))) {
 		spell_entry_recheck_all (spell_entry);
+	}
 }
 
 gboolean
 e_spell_entry_get_checking_enabled (ESpellEntry *spell_entry)
 {
-	g_return_val_if_fail (spell_entry != NULL, FALSE);
+	g_return_val_if_fail (E_IS_SPELL_ENTRY (spell_entry), FALSE);
 
 	return spell_entry->priv->checking_enabled;
 }
@@ -857,7 +850,7 @@ void
 e_spell_entry_set_checking_enabled (ESpellEntry *spell_entry,
                                     gboolean enable_checking)
 {
-	g_return_if_fail (spell_entry != NULL);
+	g_return_if_fail (E_IS_SPELL_ENTRY (spell_entry));
 
 	if ((enable_checking ? 1 : 0) == (spell_entry->priv->checking_enabled ? 1 : 0))
 		return;
diff --git a/modules/mail/e-mail-shell-backend.c b/modules/mail/e-mail-shell-backend.c
index 2f7cee6..9a745a6 100644
--- a/modules/mail/e-mail-shell-backend.c
+++ b/modules/mail/e-mail-shell-backend.c
@@ -383,7 +383,7 @@ mail_shell_backend_window_added_cb (GtkApplication *application,
 						editor_widget));
 
 		e_editor_widget_set_spell_languages (editor_widget, spell_languages);
-		g_list_free (spell_languages);
+		g_list_free_full (spell_languages, g_object_unref);
 
 		shell_settings = e_shell_get_shell_settings (shell);
 
diff --git a/widgets/editor/selection-style.c b/widgets/editor/selection-style.c
new file mode 100644
index 0000000..d75f1f0
--- /dev/null
+++ b/widgets/editor/selection-style.c
@@ -0,0 +1,288 @@
+
+
+/*
+ * DO NOT replace type casting of WebKit types by GLib macros unless
+ * you know what you are doing (I do).
+ *
+ * Probably due to bugs in WebKitGtk+ DOM bindings these macros will
+ * produce runtime warnings, but the objects and class hierarchy ARE VALID.
+ *
+ * This mostly affects only WebKitDOMText, which is subclass
+ * of WebKitDOMNode, but the text nodes are rarely created as instances of
+ * WebKitDOMText. To make sure that you really can cast WebKitDOMNode to
+ * WebKitDOMText, check whether webkit_dom_node_get_node_type() == 3
+ * (3 is "text" node type). WebKitDOMNode is just a thin wrapper around
+ * WebKit's internal WebCore objects. Using get_node_type() is evaluated
+ * against properties of these internal object.
+ */
+
+
+
+static void
+normalize (WebKitDOMNode *node)
+{
+	WebKitDOMNodeList *children;
+	gulong ii;
+
+	/* Standard normalization */
+	webkit_dom_node_normalize (node);
+
+	children = webkit_dom_node_get_child_nodes (node);
+
+	ii = 0;
+	while (ii < webkit_dom_node_list_get_length (children)) {
+		WebKitDOMNode *child, *sibling;
+		gchar *tag_name, *sibling_tag_name;
+
+		child = webkit_dom_node_list_item (children, ii);
+
+		/* We are interested only in nodes representing HTML
+		 * elements */
+		if (webkit_dom_node_get_node_type (child) != 1) {
+			ii++;
+			continue;
+		}
+
+		sibling = webkit_dom_node_get_next_sibling (child);
+
+		/* If sibling node is not an element, then skip the current
+		 * element and the sibling node as well */
+		if (webkit_dom_node_get_node_type (sibling) != 1) {
+			ii += 2;
+			continue;
+		}
+
+		/* Recursively normalize the child element */
+		normalize (child);
+
+		tag_name = webkit_dom_element_get_tag_name (
+				WEBKIT_DOM_ELEMENT (child));
+		sibling_tag_name = webkit_dom_element_get_tag_name (
+				WEBKIT_DOM_ELEMENT (sibling));
+
+		if (g_strcmp0 (tag_name, sibling_tag_name) == 0) {
+			gchar *str1, *str2, *inner_html;
+
+			str1 = webkit_dom_html_element_get_inner_html (
+				WEBKIT_DOM_HTML_ELEMENT (child));
+			str2 = webkit_dom_html_element_get_inner_html (
+				WEBKIT_DOM_HTML_ELEMENT (sibling));
+			inner_html = g_strconcat (str1, str2, NULL);
+			webkit_dom_html_element_set_inner_html (
+				WEBKIT_DOM_HTML_ELEMENT (child), inner_html, NULL);
+
+			g_free (str1);
+			g_free (str2);
+			g_free (inner_html);
+
+			webkit_dom_node_remove_child (
+				webkit_dom_node_get_parent_node (sibling),
+				sibling, NULL);
+		}
+
+		ii++;
+	}
+}
+
+static void
+remove_format (EEditorSelection *selection,
+	       const gchar *format_tag)
+{
+	WebKitDOMDocument *document;
+	WebKitDOMRange *range;
+	WebKitDOMNode *start_node, *end_node;
+	WebKitDOMElement *common_ancestor;
+
+	document = webkit_web_view_get_dom_document (selection->priv->webview);
+	range = editor_selection_get_current_range (selection);
+
+	start_node = webkit_dom_range_get_start_container (range, NULL);
+	end_node = webkit_dom_range_get_end_container (range, NULL);
+
+	common_ancestor = webkit_dom_node_get_parent_element (
+				webkit_dom_node_get_parent_node (
+					webkit_dom_range_get_common_ancestor_container (
+						range, NULL)));
+
+	/* Cool! The selection is all within one node */
+	if (start_node == end_node) {
+		WebKitDOMElement *element;
+		WebKitDOMNode *node = start_node;
+		WebKitDOMNodeList *children;
+		gchar *wrapper_tag_name;
+
+		if (webkit_dom_node_get_node_type (start_node) != 3) {
+			/* XXX Is it possible for selection to start somewhere
+			 * else then in a text node? If yes, what should we
+			 * do about it? */
+			return;
+		}
+
+		/* Split <b>|blabla SELECTED TEXT bla|</b> to
+		 * <b>|blabla |SELECTED TEXT| bla|</b> (| indicates node) */
+		node = (WebKitDOMNode *) webkit_dom_text_split_text (
+				(WebKitDOMText *) (node),
+			webkit_dom_range_get_start_offset (range, NULL), NULL);
+		webkit_dom_text_split_text  (
+				(WebKitDOMText *) node,
+				webkit_dom_range_get_end_offset (range, NULL),
+				NULL);
+
+		element = webkit_dom_node_get_parent_element (node);
+		children = webkit_dom_node_get_child_nodes (WEBKIT_DOM_NODE (element));
+		wrapper_tag_name = webkit_dom_element_get_tag_name (element);
+
+		while (webkit_dom_node_list_get_length (children) > 0) {
+			WebKitDOMNode *child;
+
+			child = webkit_dom_node_list_item (children, 0);
+
+			if (child != node) {
+				WebKitDOMElement *wrapper;
+				wrapper = webkit_dom_document_create_element (
+					document, wrapper_tag_name, NULL);
+
+				webkit_dom_node_append_child (
+					WEBKIT_DOM_NODE (wrapper), child, NULL);
+
+				child = WEBKIT_DOM_NODE (wrapper);
+			}
+
+			webkit_dom_node_insert_before (
+				webkit_dom_node_get_parent_node (
+					WEBKIT_DOM_NODE (element)),
+				child, WEBKIT_DOM_NODE (element), NULL);
+		}
+
+		/* Remove the now empty container */
+		/*
+		webkit_dom_node_remove_child (
+			webkit_dom_node_get_parent_node (
+				WEBKIT_DOM_NODE (element)),
+			WEBKIT_DOM_NODE (element), NULL);
+		*/
+
+		g_free (wrapper_tag_name);
+	}
+
+	normalize (WEBKIT_DOM_NODE (common_ancestor));
+}
+
+static void
+apply_format (EEditorSelection *editor_selection,
+	      const gchar *format_tag)
+{
+	WebKitDOMDocument *document;
+	WebKitDOMRange *range;
+	WebKitDOMNode *selection, *node;
+	WebKitDOMNode *new_parent;
+	gint format_tag_len = strlen (format_tag);
+	gboolean prev_sibling_match, next_sibling_match;
+
+	prev_sibling_match = FALSE;
+	next_sibling_match = FALSE;
+
+	document = webkit_web_view_get_dom_document (editor_selection->priv->webview);
+	range = editor_selection_get_current_range (editor_selection);
+
+	if (webkit_dom_range_get_start_offset (range, NULL) != 0) {
+		node = webkit_dom_range_get_start_container (range, NULL);
+		selection = (WebKitDOMNode*) webkit_dom_text_split_text (
+			(WebKitDOMText *) node,
+			webkit_dom_range_get_start_offset (range, NULL), NULL);
+	} else {
+		selection = webkit_dom_range_get_start_container (range, NULL);
+	}
+
+	webkit_dom_text_split_text ((WebKitDOMText *) selection,
+			webkit_dom_range_get_end_offset (range, NULL), NULL);
+
+	/* The split above might have produced an empty text node
+	 * (for example splitting "TEXT" on offset 4 will produce
+	 * "TEXT" and "" nodes), so remove it */
+	node = webkit_dom_node_get_next_sibling (selection);
+	if (webkit_dom_node_get_node_type (node) == 3) {
+		gchar *content;
+
+		content = webkit_dom_node_get_text_content (node);
+		if (!content || (strlen (content) == 0)) {
+			webkit_dom_node_remove_child (
+				webkit_dom_node_get_parent_node (node),
+				node, NULL);
+		}
+
+		g_free (content);
+	}
+
+	/* Check whether previous sibling is an element and whether it is <format_tag> */
+	node = webkit_dom_node_get_previous_sibling (selection);
+	if (node && (webkit_dom_node_get_node_type (node) == 1)) {
+		gchar *tag_name;
+
+		tag_name = webkit_dom_element_get_tag_name (
+				(WebKitDOMElement *) node);
+		prev_sibling_match = ((format_tag_len == strlen (tag_name)) &&
+				      (g_ascii_strncasecmp (
+						format_tag, tag_name,
+						format_tag_len) == 0));
+		g_free (tag_name);
+	}
+
+	/* Check whether next sibling is an element and whether it is <format_tag> */
+	node = webkit_dom_node_get_next_sibling (selection);
+	if (node && (webkit_dom_node_get_node_type (node) == 1)) {
+		gchar *tag_name;
+
+		tag_name = webkit_dom_element_get_tag_name (
+				(WebKitDOMElement *) node);
+		next_sibling_match = ((format_tag_len == strlen (tag_name)) &&
+				      (g_ascii_strncasecmp (
+					      	format_tag, tag_name,
+						format_tag_len) == 0));
+		g_free (tag_name);
+	}
+
+	/* Merge selection and next sibling to the orevious sibling */
+	if (prev_sibling_match && next_sibling_match) {
+		WebKitDOMNode *next_sibling, *child;
+
+		new_parent = webkit_dom_node_get_previous_sibling (selection);
+		next_sibling = webkit_dom_node_get_next_sibling (selection);
+
+		/* Append selection to the new parent */
+		webkit_dom_node_append_child (new_parent, selection, NULL);
+
+		/* Append all children of next sibling to the new parent */
+		while ((child = webkit_dom_node_get_first_child (next_sibling)) != NULL) {
+			webkit_dom_node_append_child (new_parent, child, NULL);
+		}
+		webkit_dom_node_remove_child (
+			webkit_dom_node_get_parent_node (next_sibling),
+			next_sibling, NULL);
+
+	/* Merge selection to the previous sibling */
+	} else if (prev_sibling_match && !next_sibling_match) {
+		new_parent = webkit_dom_node_get_previous_sibling (selection);
+		webkit_dom_node_append_child (new_parent, selection, NULL);
+
+	/* Merge selection to the next sibling */
+	} else if (!prev_sibling_match && next_sibling_match) {
+		new_parent = webkit_dom_node_get_next_sibling (selection);
+		webkit_dom_node_insert_before (
+			new_parent, selection,
+			webkit_dom_node_get_first_child (new_parent), NULL);
+
+	/* Just wrap the selection to <tag_name> */
+	} else {
+		new_parent = (WebKitDOMNode *)
+				webkit_dom_document_create_element (
+					document, format_tag, NULL);
+		webkit_dom_range_surround_contents (range, new_parent, NULL);
+	}
+
+	webkit_dom_node_normalize (
+		(WebKitDOMNode *) webkit_dom_node_get_parent_element (new_parent));
+}
+
+
+ 



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