# HG changeset patch # User Sadrul Habib Chowdhury # Date 1208705716 0 # Node ID 27c9c55499f8d5eba268705654c6eb63404a4da3 # Parent 269bba623a6265054aa4d044563a1c86e96ecece Smiley insertions can be undone with this fix. References #5577. But redo doesn't work yet. diff -r 269bba623a62 -r 27c9c55499f8 pidgin/gtkimhtml.c --- 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) diff -r 269bba623a62 -r 27c9c55499f8 pidgin/gtksourceundomanager.c --- 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);