--- gtksourceundomanager.c	2008-01-22 13:32:55.000000000 -0500
+++ gtksourceundomanager.c	2008-04-22 00:43:05.000000000 -0400
@@ -50,10 +51,12 @@
 typedef struct _GtkSourceUndoAction  			GtkSourceUndoAction;
 typedef struct _GtkSourceUndoInsertAction		GtkSourceUndoInsertAction;
 typedef struct _GtkSourceUndoDeleteAction		GtkSourceUndoDeleteAction;
+typedef struct _GtkSourceUndoInsertAnchorAction GtkSourceUndoInsertAnchorAction;
 
 typedef enum {
 	GTK_SOURCE_UNDO_ACTION_INSERT,
-	GTK_SOURCE_UNDO_ACTION_DELETE
+	GTK_SOURCE_UNDO_ACTION_DELETE,
+	GTK_SOURCE_UNDO_ACTION_INSERT_ANCHOR,
 } GtkSourceUndoActionType;
 
 /*
@@ -77,6 +80,12 @@ struct _GtkSourceUndoDeleteAction
 	gboolean forward;
 };
 
+struct _GtkSourceUndoInsertAnchorAction
+{
+	gint pos;
+	GtkTextChildAnchor *anchor;
+};
+
 struct _GtkSourceUndoAction
 {
 	GtkSourceUndoActionType action_type;
@@ -84,6 +93,7 @@ struct _GtkSourceUndoAction
 	union {
 		GtkSourceUndoInsertAction  insert;
 		GtkSourceUndoDeleteAction  delete;
+		GtkSourceUndoInsertAnchorAction insert_anchor;
 	} action;
 
 	gint order_in_group;
@@ -150,6 +160,11 @@ static void gtk_source_undo_manager_inse
 		                             		 	 const 	gchar 			*text,
 							 	 gint 				 length,
 							 	 GtkSourceUndoManager 		*um);
+static void gtk_source_undo_manager_insert_anchor_handler (GtkTextBuffer *buffer,
+			                   GtkTextIter            *pos,
+			                   GtkTextChildAnchor     *anchor,
+			                   GtkSourceUndoManager   *um);
+
 static void gtk_source_undo_manager_delete_range_handler 	(GtkTextBuffer 			*buffer,
 							 	 GtkTextIter 			*start,
                         		      		 	 GtkTextIter 			*end,
@@ -254,6 +268,10 @@ gtk_source_undo_manager_finalize (GObjec
 			  um);
 
 	g_signal_handlers_disconnect_by_func (G_OBJECT (um->priv->document),
+			  G_CALLBACK (gtk_source_undo_manager_insert_anchor_handler),
+			  um);
+
+	g_signal_handlers_disconnect_by_func (G_OBJECT (um->priv->document),
 			  G_CALLBACK (gtk_source_undo_manager_begin_user_action_handler),
 			  um);
 
@@ -274,6 +292,10 @@ gtk_source_undo_manager_new (GtkTextBuff
 			  G_CALLBACK (gtk_source_undo_manager_insert_text_handler),
 			  um);
 
+	g_signal_connect (G_OBJECT (buffer), "insert_child_anchor",
+			  G_CALLBACK (gtk_source_undo_manager_insert_anchor_handler),
+			  um);
+
 	g_signal_connect (G_OBJECT (buffer), "delete_range",
 			  G_CALLBACK (gtk_source_undo_manager_delete_range_handler),
 			  um);
@@ -380,6 +402,15 @@ insert_text (GtkTextBuffer *buffer, gint
 }
 
 static void
+insert_anchor (GtkTextBuffer *buffer, gint pos, GtkTextChildAnchor *anchor)
+{
+	GtkTextIter iter;
+
+	gtk_text_buffer_get_iter_at_offset (buffer, &iter, pos);
+	gtk_text_buffer_insert_child_anchor (buffer, &iter, anchor);
+}
+
+static void 
 delete_text (GtkTextBuffer *buffer, gint start, gint end)
 {
 	GtkTextIter start_iter;
@@ -505,6 +536,13 @@ gtk_source_undo_manager_undo (GtkSourceU
 				cursor_pos = undo_action->action.insert.pos;
 				break;
 
+			case GTK_SOURCE_UNDO_ACTION_INSERT_ANCHOR:
+				delete_text (
+					um->priv->document,
+					undo_action->action.insert_anchor.pos,
+					undo_action->action.insert_anchor.pos + 1);
+				undo_action->action.insert_anchor.anchor->segment = NULL; /* XXX: This may be a bug in GTK+ */
+				break;
 			default:
 				/* Unknown action type. */
 				g_return_if_reached ();
@@ -597,6 +635,15 @@ gtk_source_undo_manager_redo (GtkSourceU
 
 				break;
 
+			case GTK_SOURCE_UNDO_ACTION_INSERT_ANCHOR:
+				cursor_pos = undo_action->action.insert_anchor.pos;
+
+				insert_anchor (
+					um->priv->document,
+					undo_action->action.insert_anchor.pos,
+					undo_action->action.insert_anchor.anchor);
+				break;
+
 			default:
 				/* Unknown action type */
 				++um->priv->next_redo;
@@ -645,6 +692,8 @@ gtk_source_undo_action_free (GtkSourceUn
 		g_free (action->action.insert.text);
 	else if (action->action_type == GTK_SOURCE_UNDO_ACTION_DELETE)
 		g_free (action->action.delete.text);
+	else if (action->action_type == GTK_SOURCE_UNDO_ACTION_INSERT_ANCHOR)
+		g_object_unref(action->action.insert_anchor.anchor);
 	else
 		g_return_if_reached ();
 
@@ -713,6 +760,27 @@ gtk_source_undo_manager_insert_text_hand
 	gtk_source_undo_manager_add_action (um, &undo_action);
 }
 
+static void gtk_source_undo_manager_insert_anchor_handler (GtkTextBuffer *buffer,
+			                   GtkTextIter            *pos,
+			                   GtkTextChildAnchor     *anchor,
+			                   GtkSourceUndoManager   *um)
+{
+	GtkSourceUndoAction undo_action;
+
+	if (um->priv->running_not_undoable_actions > 0)
+		return;
+
+	undo_action.action_type = GTK_SOURCE_UNDO_ACTION_INSERT_ANCHOR;
+
+	undo_action.action.insert_anchor.pos    = gtk_text_iter_get_offset (pos);
+	undo_action.action.insert_anchor.anchor = g_object_ref (anchor);
+
+	undo_action.mergeable = FALSE;
+	undo_action.modified = FALSE;
+
+	gtk_source_undo_manager_add_action (um, &undo_action);
+}
+
 static void
 gtk_source_undo_manager_delete_range_handler (GtkTextBuffer 		*buffer,
 					      GtkTextIter 		*start,
@@ -790,9 +858,13 @@ gtk_source_undo_manager_add_action (GtkS
 		*action = *undo_action;
 
 		if (action->action_type == GTK_SOURCE_UNDO_ACTION_INSERT)
-			action->action.insert.text = g_strdup (undo_action->action.insert.text);
+			action->action.insert.text = g_strndup (undo_action->action.insert.text, undo_action->action.insert.length);
 		else if (action->action_type == GTK_SOURCE_UNDO_ACTION_DELETE)
-			action->action.delete.text = g_strdup (undo_action->action.delete.text);
+			action->action.delete.text = g_strdup (undo_action->action.delete.text); 
+		else if (action->action_type == GTK_SOURCE_UNDO_ACTION_INSERT_ANCHOR)
+		{
+			/* Nothing needs to be done */
+		}
 		else
 		{
 			g_free (action);
@@ -1009,10 +1080,14 @@ gtk_source_undo_manager_merge_action (Gt
 		last_action->action.insert.chars += undo_action->action.insert.chars;
 
 	}
+	else if (undo_action->action_type == GTK_SOURCE_UNDO_ACTION_INSERT_ANCHOR)
+	{
+		/* Nothing needs to be done */
+	}
 	else
 		/* Unknown action inside undo merge encountered */
 		g_return_val_if_reached (TRUE);
-
+		
 	return TRUE;
 }
 
