]> granicus.if.org Git - vim/commitdiff
patch 8.0.1441: using ":undo 0" leaves undo in wrong state v8.0.1441
authorBram Moolenaar <Bram@vim.org>
Tue, 30 Jan 2018 21:46:06 +0000 (22:46 +0100)
committerBram Moolenaar <Bram@vim.org>
Tue, 30 Jan 2018 21:46:06 +0000 (22:46 +0100)
Problem:    Using ":undo 0" leaves undo in wrong state.
Solution:   Instead of searching for state 1 and go above, just use the start.
            (Ozaki Kiichi, closes #2595)

src/testdir/test_undo.vim
src/undo.c
src/version.c

index b7235867b9030e88227ab42ced4f5fd10c8bafff..cc3cceb1ae95257e0b5d48686194f2eb06ad9288 100644 (file)
@@ -359,3 +359,47 @@ func Test_undo_append()
   norm o
   quit
 endfunc
+
+func Test_undo_0()
+  new
+  set ul=100
+  normal i1
+  undo
+  normal i2
+  undo
+  normal i3
+
+  undo 0
+  let d = undotree()
+  call assert_equal('', getline(1))
+  call assert_equal(0, d.seq_cur)
+
+  redo
+  let d = undotree()
+  call assert_equal('3', getline(1))
+  call assert_equal(3, d.seq_cur)
+
+  undo 2
+  undo 0
+  let d = undotree()
+  call assert_equal('', getline(1))
+  call assert_equal(0, d.seq_cur)
+
+  redo
+  let d = undotree()
+  call assert_equal('2', getline(1))
+  call assert_equal(2, d.seq_cur)
+
+  undo 1
+  undo 0
+  let d = undotree()
+  call assert_equal('', getline(1))
+  call assert_equal(0, d.seq_cur)
+
+  redo
+  let d = undotree()
+  call assert_equal('1', getline(1))
+  call assert_equal(1, d.seq_cur)
+
+  bwipe!
+endfunc
index 69d4fc603004f77c31213499a189a8f194c2d96e..d2ac457cfabde566b800f01f35ba796f459fed7c 100644 (file)
@@ -2272,7 +2272,7 @@ undo_time(
     long           closest_start;
     long           closest_seq = 0;
     long           val;
-    u_header_T     *uhp;
+    u_header_T     *uhp = NULL;
     u_header_T     *last;
     int                    mark;
     int                    nomark;
@@ -2295,14 +2295,7 @@ undo_time(
      * Init "closest" to a value we can't reach. */
     if (absolute)
     {
-       if (step == 0)
-       {
-           /* target 0 does not exist, got to 1 and above it. */
-           target = 1;
-           above = TRUE;
-       }
-       else
-           target = step;
+       target = step;
        closest = -1;
     }
     else
@@ -2369,6 +2362,10 @@ undo_time(
     closest_start = closest;
     closest_seq = curbuf->b_u_seq_cur;
 
+    /* When "target" is 0; Back to origin. */
+    if (target == 0)
+       goto found;
+
     /*
      * May do this twice:
      * 1. Search for "target", update "closest" to the best match found.
@@ -2494,8 +2491,9 @@ undo_time(
            above = TRUE;       /* stop above the header */
     }
 
+found:
     /* If we found it: Follow the path to go to where we want to be. */
-    if (uhp != NULL)
+    if (uhp != NULL || target == 0)
     {
        /*
         * First go up the tree as much as needed.
@@ -2510,87 +2508,93 @@ undo_time(
                uhp = curbuf->b_u_newhead;
            else
                uhp = uhp->uh_next.ptr;
-           if (uhp == NULL || uhp->uh_walk != mark
+           if (uhp == NULL || (target > 0 && uhp->uh_walk != mark)
                                         || (uhp->uh_seq == target && !above))
                break;
            curbuf->b_u_curhead = uhp;
            u_undoredo(TRUE);
-           uhp->uh_walk = nomark;      /* don't go back down here */
+           if (target > 0)
+               uhp->uh_walk = nomark;  /* don't go back down here */
        }
 
-       /*
-        * And now go down the tree (redo), branching off where needed.
-        */
-       while (!got_int)
+       /* When back to origin, redo is not needed. */
+       if (target > 0)
        {
-           /* Do the change warning now, for the same reason as above. */
-           change_warning(0);
+           /*
+            * And now go down the tree (redo), branching off where needed.
+            */
+           while (!got_int)
+           {
+               /* Do the change warning now, for the same reason as above. */
+               change_warning(0);
 
-           uhp = curbuf->b_u_curhead;
-           if (uhp == NULL)
-               break;
+               uhp = curbuf->b_u_curhead;
+               if (uhp == NULL)
+                   break;
 
-           /* Go back to the first branch with a mark. */
-           while (uhp->uh_alt_prev.ptr != NULL
+               /* Go back to the first branch with a mark. */
+               while (uhp->uh_alt_prev.ptr != NULL
                                     && uhp->uh_alt_prev.ptr->uh_walk == mark)
-               uhp = uhp->uh_alt_prev.ptr;
+                   uhp = uhp->uh_alt_prev.ptr;
 
-           /* Find the last branch with a mark, that's the one. */
-           last = uhp;
-           while (last->uh_alt_next.ptr != NULL
+               /* Find the last branch with a mark, that's the one. */
+               last = uhp;
+               while (last->uh_alt_next.ptr != NULL
                                    && last->uh_alt_next.ptr->uh_walk == mark)
-               last = last->uh_alt_next.ptr;
-           if (last != uhp)
-           {
-               /* Make the used branch the first entry in the list of
-                * alternatives to make "u" and CTRL-R take this branch. */
-               while (uhp->uh_alt_prev.ptr != NULL)
-                   uhp = uhp->uh_alt_prev.ptr;
-               if (last->uh_alt_next.ptr != NULL)
-                   last->uh_alt_next.ptr->uh_alt_prev.ptr =
+                   last = last->uh_alt_next.ptr;
+               if (last != uhp)
+               {
+                   /* Make the used branch the first entry in the list of
+                    * alternatives to make "u" and CTRL-R take this branch. */
+                   while (uhp->uh_alt_prev.ptr != NULL)
+                       uhp = uhp->uh_alt_prev.ptr;
+                   if (last->uh_alt_next.ptr != NULL)
+                       last->uh_alt_next.ptr->uh_alt_prev.ptr =
                                                        last->uh_alt_prev.ptr;
-               last->uh_alt_prev.ptr->uh_alt_next.ptr = last->uh_alt_next.ptr;
-               last->uh_alt_prev.ptr = NULL;
-               last->uh_alt_next.ptr = uhp;
-               uhp->uh_alt_prev.ptr = last;
-
-               if (curbuf->b_u_oldhead == uhp)
-                   curbuf->b_u_oldhead = last;
-               uhp = last;
-               if (uhp->uh_next.ptr != NULL)
-                   uhp->uh_next.ptr->uh_prev.ptr = uhp;
-           }
-           curbuf->b_u_curhead = uhp;
+                   last->uh_alt_prev.ptr->uh_alt_next.ptr =
+                                                       last->uh_alt_next.ptr;
+                   last->uh_alt_prev.ptr = NULL;
+                   last->uh_alt_next.ptr = uhp;
+                   uhp->uh_alt_prev.ptr = last;
+
+                   if (curbuf->b_u_oldhead == uhp)
+                       curbuf->b_u_oldhead = last;
+                   uhp = last;
+                   if (uhp->uh_next.ptr != NULL)
+                       uhp->uh_next.ptr->uh_prev.ptr = uhp;
+               }
+               curbuf->b_u_curhead = uhp;
 
-           if (uhp->uh_walk != mark)
-               break;      /* must have reached the target */
+               if (uhp->uh_walk != mark)
+                   break;          /* must have reached the target */
 
-           /* Stop when going backwards in time and didn't find the exact
-            * header we were looking for. */
-           if (uhp->uh_seq == target && above)
-           {
-               curbuf->b_u_seq_cur = target - 1;
-               break;
-           }
+               /* Stop when going backwards in time and didn't find the exact
+                * header we were looking for. */
+               if (uhp->uh_seq == target && above)
+               {
+                   curbuf->b_u_seq_cur = target - 1;
+                   break;
+               }
 
-           u_undoredo(FALSE);
+               u_undoredo(FALSE);
 
-           /* Advance "curhead" to below the header we last used.  If it
-            * becomes NULL then we need to set "newhead" to this leaf. */
-           if (uhp->uh_prev.ptr == NULL)
-               curbuf->b_u_newhead = uhp;
-           curbuf->b_u_curhead = uhp->uh_prev.ptr;
-           did_undo = FALSE;
+               /* Advance "curhead" to below the header we last used.  If it
+                * becomes NULL then we need to set "newhead" to this leaf. */
+               if (uhp->uh_prev.ptr == NULL)
+                   curbuf->b_u_newhead = uhp;
+               curbuf->b_u_curhead = uhp->uh_prev.ptr;
+               did_undo = FALSE;
 
-           if (uhp->uh_seq == target)  /* found it! */
-               break;
+               if (uhp->uh_seq == target)      /* found it! */
+                   break;
 
-           uhp = uhp->uh_prev.ptr;
-           if (uhp == NULL || uhp->uh_walk != mark)
-           {
-               /* Need to redo more but can't find it... */
-               internal_error("undo_time()");
-               break;
+               uhp = uhp->uh_prev.ptr;
+               if (uhp == NULL || uhp->uh_walk != mark)
+               {
+                   /* Need to redo more but can't find it... */
+                   internal_error("undo_time()");
+                   break;
+               }
            }
        }
     }
index 282f662a9db1e111291ed5ac81b0653d910ad88f..1cee1481fcedc457f93b14042fbdeae3abc9cf46 100644 (file)
@@ -771,6 +771,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1441,
 /**/
     1440,
 /**/