To: vim_dev@googlegroups.com Subject: Patch 8.0.1441 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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 -- Bram@Moolenaar.net -- 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 ///