changeset 22674:27c9c55499f8

Smiley insertions can be undone with this fix. References #5577. But redo doesn't work yet.
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Sun, 20 Apr 2008 15:35:16 +0000
parents 269bba623a62
children f35a57b8f4ce
files pidgin/gtkimhtml.c pidgin/gtksourceundomanager.c
diffstat 2 files changed, 90 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/pidgin/gtkimhtml.c	Sat Apr 19 14:18:06 2008 +0000
+++ b/pidgin/gtkimhtml.c	Sun Apr 20 15:35:16 2008 +0000
@@ -1201,16 +1201,20 @@
 }
 
 static void
-gtk_imhtml_undo(GtkIMHtml *imhtml) {
+gtk_imhtml_undo(GtkIMHtml *imhtml)
+{
 	g_return_if_fail(GTK_IS_IMHTML(imhtml));
-	if (imhtml->editable)
+	if (imhtml->editable &&
+			gtk_source_undo_manager_can_undo(imhtml->undo_manager))
 		gtk_source_undo_manager_undo(imhtml->undo_manager);
 }
 
 static void
-gtk_imhtml_redo(GtkIMHtml *imhtml) {
+gtk_imhtml_redo(GtkIMHtml *imhtml)
+{
 	g_return_if_fail(GTK_IS_IMHTML(imhtml));
-	if (imhtml->editable)
+	if (imhtml->editable &&
+			gtk_source_undo_manager_can_redo(imhtml->undo_manager))
 		gtk_source_undo_manager_redo(imhtml->undo_manager);
 
 }
@@ -2425,6 +2429,7 @@
 	ws = g_malloc(len + 1);
 	ws[0] = 0;
 
+	gtk_text_buffer_begin_user_action(imhtml->text_buffer);
 	while (pos < len) {
 		if (*c == '<' && gtk_imhtml_is_tag (c + 1, &tag, &tlen, &type)) {
 			c++;
@@ -3153,6 +3158,7 @@
 	g_signal_emit(object, signals[UPDATE_FORMAT], 0);
 	g_object_unref(object);
 
+	gtk_text_buffer_end_user_action(imhtml->text_buffer);
 }
 
 void gtk_imhtml_remove_smileys(GtkIMHtml *imhtml)
--- a/pidgin/gtksourceundomanager.c	Sat Apr 19 14:18:06 2008 +0000
+++ b/pidgin/gtksourceundomanager.c	Sun Apr 20 15:35:16 2008 +0000
@@ -41,10 +41,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;
 
 /* 
@@ -68,6 +70,12 @@
 	gboolean forward;
 };
 
+struct _GtkSourceUndoInsertAnchorAction
+{
+	gint pos;
+	GtkTextChildAnchor *anchor;
+};
+
 struct _GtkSourceUndoAction
 {
 	GtkSourceUndoActionType action_type;
@@ -75,6 +83,7 @@
 	union {
 		GtkSourceUndoInsertAction  insert;
 		GtkSourceUndoDeleteAction  delete;
+		GtkSourceUndoInsertAnchorAction insert_anchor;
 	} action;
 
 	gint order_in_group;
@@ -139,6 +148,10 @@
 		                             		 	 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,
@@ -275,6 +288,10 @@
 			  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);
 
@@ -297,6 +314,10 @@
 			  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);
@@ -403,6 +424,15 @@
 }
 
 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;
@@ -497,6 +527,13 @@
 					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 ();
@@ -588,6 +625,17 @@
 
 				break;
 
+			case GTK_SOURCE_UNDO_ACTION_INSERT_ANCHOR:
+				set_cursor (
+					um->priv->document,
+					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;
@@ -633,6 +681,8 @@
 		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 ();
 
@@ -695,6 +745,27 @@
 	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,
@@ -775,6 +846,10 @@
 			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); 
+		else if (action->action_type == GTK_SOURCE_UNDO_ACTION_INSERT_ANCHOR)
+		{
+			/* Nothing needs to be done */
+		}
 		else
 		{
 			g_free (action);
@@ -998,6 +1073,10 @@
 		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);