summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2018-01-30 22:46:06 +0100
committerBram Moolenaar <Bram@vim.org>2018-01-30 22:46:06 +0100
commitce46d934af35d0f774be7f996001db03cf0b894a (patch)
tree1145362d6a0ddfe22acf17aac1f34fcc2c3eda1f
parentb50773c6df0bc2c9c2ab1afecc78083abc606de0 (diff)
patch 8.0.1441: using ":undo 0" leaves undo in wrong statev8.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)
-rw-r--r--src/testdir/test_undo.vim44
-rw-r--r--src/undo.c148
-rw-r--r--src/version.c2
3 files changed, 122 insertions, 72 deletions
diff --git a/src/testdir/test_undo.vim b/src/testdir/test_undo.vim
index b7235867b9..cc3cceb1ae 100644
--- 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
index 69d4fc6030..d2ac457cfa 100644
--- 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);
+ /*
+ * 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;
+ }
}
}
}
diff --git a/src/version.c b/src/version.c
index 282f662a9d..1cee1481fc 100644
--- 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,