pidgin: a060cc83: Smiley insertions can be undone with thi...

sadrul at pidgin.im sadrul at pidgin.im
Sun Apr 20 11:40:50 EDT 2008


-----------------------------------------------------------------
Revision: a060cc8315a6500f42289837501a738d109ce642
Ancestor: 35556576c8b9b3c77f9674eb5de05f1a325e2851
Author: sadrul at pidgin.im
Date: 2008-04-20T15:35:16
Branch: im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/a060cc8315a6500f42289837501a738d109ce642

Modified files:
        pidgin/gtkimhtml.c pidgin/gtksourceundomanager.c

ChangeLog: 

Smiley insertions can be undone with this fix. References #5577. But redo
doesn't work yet.

-------------- next part --------------
============================================================
--- pidgin/gtkimhtml.c	68bfbe6c83a614dbd6f0c70f846849571c7dae1b
+++ pidgin/gtkimhtml.c	1917ef0ea282673f5f17685055709d13ea7195f1
@@ -1201,16 +1201,20 @@ static void
 }
 
 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 @@ void gtk_imhtml_insert_html_at_iter(GtkI
 	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 @@ void gtk_imhtml_insert_html_at_iter(GtkI
 	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)
============================================================
--- pidgin/gtksourceundomanager.c	d884207163126f125bd060de5b2e00d133a44d95
+++ pidgin/gtksourceundomanager.c	69772385ac890e4914040019da83eedc6f4835d8
@@ -41,10 +41,12 @@ typedef struct _GtkSourceUndoDeleteActio
 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 @@ struct _GtkSourceUndoDeleteAction
 	gboolean forward;
 };
 
+struct _GtkSourceUndoInsertAnchorAction
+{
+	gint pos;
+	GtkTextChildAnchor *anchor;
+};
+
 struct _GtkSourceUndoAction
 {
 	GtkSourceUndoActionType action_type;
@@ -75,6 +83,7 @@ struct _GtkSourceUndoAction
 	union {
 		GtkSourceUndoInsertAction  insert;
 		GtkSourceUndoDeleteAction  delete;
+		GtkSourceUndoInsertAnchorAction insert_anchor;
 	} action;
 
 	gint order_in_group;
@@ -139,6 +148,10 @@ 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,
@@ -275,6 +288,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);
 
@@ -297,6 +314,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);
@@ -403,6 +424,15 @@ static void 
 }
 
 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 @@ gtk_source_undo_manager_undo (GtkSourceU
 					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 @@ gtk_source_undo_manager_redo (GtkSourceU
 
 				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 @@ 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 ();
 
@@ -695,6 +745,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,
@@ -775,6 +846,10 @@ gtk_source_undo_manager_add_action (GtkS
 			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 @@ 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);


More information about the Commits mailing list