textview: improve undo grouping when overwriting
authorChristian Hergert <chergert@redhat.com>
Thu, 23 Sep 2021 02:41:06 +0000 (19:41 -0700)
committerChristian Hergert <chergert@redhat.com>
Fri, 24 Sep 2021 23:37:59 +0000 (16:37 -0700)
We want to group in more than one undo group when removing a selection
and replacing it with a new character or characters, unless we're
replacing a single character. In that case, the natural thing is to treat
it as an atomic change.

gtk/gtktextview.c

index e37d44c722200f107465f6218f8b831dadcce58d..381124acebeeba299e9a477be9f06eb0120771df 100644 (file)
@@ -8401,17 +8401,32 @@ gtk_text_view_commit_text (GtkTextView   *text_view,
 {
   GtkTextViewPrivate *priv;
   gboolean had_selection;
+  GtkTextIter begin, end;
+  guint length;
 
   priv = text_view->priv;
 
   gtk_text_view_obscure_mouse_cursor (text_view);
   gtk_text_buffer_begin_user_action (get_buffer (text_view));
 
-  had_selection = gtk_text_buffer_get_selection_bounds (get_buffer (text_view),
-                                                        NULL, NULL);
-  
-  gtk_text_buffer_delete_selection (get_buffer (text_view), TRUE,
-                                    priv->editable);
+  had_selection = gtk_text_buffer_get_selection_bounds (get_buffer (text_view), &begin, &end);
+  gtk_text_iter_order (&begin, &end);
+  length = gtk_text_iter_get_offset (&end) - gtk_text_iter_get_offset (&begin);
+
+  if (gtk_text_buffer_delete_selection (get_buffer (text_view), TRUE, priv->editable))
+    {
+      /* If something was deleted, create a second group for the insert. This
+       * ensures that there are two undo operations. One for the deletion, and
+       * one for the insertion of new text. However, if there is only a single
+       * character overwritten, that isn't very useful, just keep the single
+       * undo group.
+       */
+      if (length > 1)
+        {
+          gtk_text_buffer_end_user_action (get_buffer (text_view));
+          gtk_text_buffer_begin_user_action (get_buffer (text_view));
+        }
+    }
 
   if (!strcmp (str, "\n"))
     {