# HG changeset patch # User Christian Brabandt # Date 1517349606 -3600 # Node ID c4b5ad2b35967167c59c03660e56f6dc4f93900f # Parent 31a78144e47fd8c47b9b9ec9d1dab660d65345d3 patch 8.0.1441: using ":undo 0" leaves undo in wrong state commit https://github.com/vim/vim/commit/ce46d934af35d0f774be7f996001db03cf0b894a Author: Bram Moolenaar Date: Tue Jan 30 22:46:06 2018 +0100 patch 8.0.1441: using ":undo 0" leaves undo in wrong state 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) diff --git a/src/testdir/test_undo.vim b/src/testdir/test_undo.vim --- a/src/testdir/test_undo.vim +++ b/src/testdir/test_undo.vim @@ -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 diff --git a/src/undo.c b/src/undo.c --- a/src/undo.c +++ b/src/undo.c @@ -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); - - 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 + /* + * 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 + 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 = 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; + 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; + } } } } diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -772,6 +772,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1441, +/**/ 1440, /**/ 1439,