Patch 8.0.1441
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)
Files:      src/undo.c, src/testdir/test_undo.vim


*** ../vim-8.0.1440/src/undo.c  2017-12-09 19:51:44.633128944 +0100
--- src/undo.c  2018-01-30 22:40:05.496107324 +0100
***************
*** 2272,2278 ****
      long          closest_start;
      long          closest_seq = 0;
      long          val;
!     u_header_T            *uhp;
      u_header_T            *last;
      int                   mark;
      int                   nomark;
--- 2272,2278 ----
      long          closest_start;
      long          closest_seq = 0;
      long          val;
!     u_header_T            *uhp = NULL;
      u_header_T            *last;
      int                   mark;
      int                   nomark;
***************
*** 2295,2308 ****
       * 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;
        closest = -1;
      }
      else
--- 2295,2301 ----
       * Init "closest" to a value we can't reach. */
      if (absolute)
      {
!       target = step;
        closest = -1;
      }
      else
***************
*** 2369,2374 ****
--- 2362,2371 ----
      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,2501 ****
            above = TRUE;       /* stop above the header */
      }
  
      /* If we found it: Follow the path to go to where we want to be. */
!     if (uhp != NULL)
      {
        /*
         * First go up the tree as much as needed.
--- 2491,2499 ----
            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 || target == 0)
      {
        /*
         * First go up the tree as much as needed.
***************
*** 2510,2596 ****
                uhp = curbuf->b_u_newhead;
            else
                uhp = uhp->uh_next.ptr;
!           if (uhp == NULL || 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 */
        }
  
!       /*
!        * 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;
  
!           /* 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;
  
!           /* 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->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;
  
!           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;
!           }
  
!           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;
  
!           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;
            }
        }
      }
--- 2508,2600 ----
                uhp = curbuf->b_u_newhead;
            else
                uhp = uhp->uh_next.ptr;
!           if (uhp == NULL || (target > 0 && uhp->uh_walk != mark)
                                         || (uhp->uh_seq == target && !above))
                break;
            curbuf->b_u_curhead = uhp;
            u_undoredo(TRUE);
!           if (target > 0)
!               uhp->uh_walk = nomark;  /* don't go back down here */
        }
  
!       /* When back to origin, redo is not needed. */
!       if (target > 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;
  
!               /* 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;
  
!               /* 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->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;
  
!               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;
!               }
  
!               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;
  
!               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;
!               }
            }
        }
      }
*** ../vim-8.0.1440/src/testdir/test_undo.vim   2018-01-27 21:01:30.242242117 
+0100
--- src/testdir/test_undo.vim   2018-01-30 22:38:26.840843392 +0100
***************
*** 359,361 ****
--- 359,405 ----
    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
*** ../vim-8.0.1440/src/version.c       2018-01-30 22:31:13.755952680 +0100
--- src/version.c       2018-01-30 22:45:47.125513788 +0100
***************
*** 773,774 ****
--- 773,776 ----
  {   /* Add new patch number below this line */
+ /**/
+     1441,
  /**/

-- 
ARTHUR: Right! Knights! Forward!
   ARTHUR leads a charge toward the castle.  Various shots of them battling on,
   despite being hit by a variety of farm animals.
                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui