summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-10-18 14:50:18 +0200
committerBram Moolenaar <Bram@vim.org>2016-10-18 14:50:18 +0200
commit025e3e0bafbc85cc4e365145af711edf99d0a90d (patch)
tree0bbd3a565a44576e714d9f8c7c85fd5e6255ad9b
parent9ec7fa82a2c4f0283862ed704c2940959e6130ee (diff)
patch 8.0.0044v8.0.0044
Problem: In diff mode the cursor may end up below the last line, resulting in an ml_get error. Solution: Check the line to be valid.
-rw-r--r--src/diff.c62
-rw-r--r--src/move.c7
-rw-r--r--src/proto/diff.pro2
-rw-r--r--src/testdir/test_diffmode.vim17
-rw-r--r--src/version.c2
5 files changed, 54 insertions, 36 deletions
diff --git a/src/diff.c b/src/diff.c
index 9c12ea4e67..a4a2acb95f 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -1100,10 +1100,7 @@ ex_diffsplit(exarg_T *eap)
if (bufref_valid(&old_curbuf))
/* Move the cursor position to that of the old window. */
curwin->w_cursor.lnum = diff_get_corresponding_line(
- old_curbuf.br_buf,
- old_curwin->w_cursor.lnum,
- curbuf,
- curwin->w_cursor.lnum);
+ old_curbuf.br_buf, old_curwin->w_cursor.lnum);
}
/* Now that lines are folded scroll to show the cursor at the same
* relative position. */
@@ -2524,21 +2521,22 @@ diff_move_to(int dir, long count)
return OK;
}
- linenr_T
-diff_get_corresponding_line(
+/*
+ * Return the line number in the current window that is closest to "lnum1" in
+ * "buf1" in diff mode.
+ */
+ static linenr_T
+diff_get_corresponding_line_int(
buf_T *buf1,
- linenr_T lnum1,
- buf_T *buf2,
- linenr_T lnum3)
+ linenr_T lnum1)
{
int idx1;
int idx2;
diff_T *dp;
int baseline = 0;
- linenr_T lnum2;
idx1 = diff_buf_idx(buf1);
- idx2 = diff_buf_idx(buf2);
+ idx2 = diff_buf_idx(curbuf);
if (idx1 == DB_COUNT || idx2 == DB_COUNT || curtab->tp_first_diff == NULL)
return lnum1;
@@ -2551,15 +2549,8 @@ diff_get_corresponding_line(
for (dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next)
{
if (dp->df_lnum[idx1] > lnum1)
- {
- lnum2 = lnum1 - baseline;
- /* don't end up past the end of the file */
- if (lnum2 > buf2->b_ml.ml_line_count)
- lnum2 = buf2->b_ml.ml_line_count;
-
- return lnum2;
- }
- else if ((dp->df_lnum[idx1] + dp->df_count[idx1]) > lnum1)
+ return lnum1 - baseline;
+ if ((dp->df_lnum[idx1] + dp->df_count[idx1]) > lnum1)
{
/* Inside the diffblock */
baseline = lnum1 - dp->df_lnum[idx1];
@@ -2568,10 +2559,11 @@ diff_get_corresponding_line(
return dp->df_lnum[idx2] + baseline;
}
- else if ( (dp->df_lnum[idx1] == lnum1)
- && (dp->df_count[idx1] == 0)
- && (dp->df_lnum[idx2] <= lnum3)
- && ((dp->df_lnum[idx2] + dp->df_count[idx2]) > lnum3))
+ if ( (dp->df_lnum[idx1] == lnum1)
+ && (dp->df_count[idx1] == 0)
+ && (dp->df_lnum[idx2] <= curwin->w_cursor.lnum)
+ && ((dp->df_lnum[idx2] + dp->df_count[idx2])
+ > curwin->w_cursor.lnum))
/*
* Special case: if the cursor is just after a zero-count
* block (i.e. all filler) and the target cursor is already
@@ -2579,18 +2571,28 @@ diff_get_corresponding_line(
* unmoved. This makes repeated CTRL-W W operations work
* as expected.
*/
- return lnum3;
+ return curwin->w_cursor.lnum;
baseline = (dp->df_lnum[idx1] + dp->df_count[idx1])
- (dp->df_lnum[idx2] + dp->df_count[idx2]);
}
/* If we get here then the cursor is after the last diff */
- lnum2 = lnum1 - baseline;
- /* don't end up past the end of the file */
- if (lnum2 > buf2->b_ml.ml_line_count)
- lnum2 = buf2->b_ml.ml_line_count;
+ return lnum1 - baseline;
+}
- return lnum2;
+/*
+ * Return the line number in the current window that is closest to "lnum1" in
+ * "buf1" in diff mode. Checks the line number to be valid.
+ */
+ linenr_T
+diff_get_corresponding_line(buf_T *buf1, linenr_T lnum1)
+{
+ linenr_T lnum = diff_get_corresponding_line_int(buf1, lnum1);
+
+ /* don't end up past the end of the file */
+ if (lnum > curbuf->b_ml.ml_line_count)
+ return curbuf->b_ml.ml_line_count;
+ return lnum;
}
#if defined(FEAT_FOLDING) || defined(PROTO)
diff --git a/src/move.c b/src/move.c
index a4d5f82997..c7acdfa68b 100644
--- a/src/move.c
+++ b/src/move.c
@@ -2824,11 +2824,8 @@ do_check_cursorbind(void)
{
# ifdef FEAT_DIFF
if (curwin->w_p_diff)
- curwin->w_cursor.lnum
- = diff_get_corresponding_line(old_curbuf,
- line,
- curbuf,
- curwin->w_cursor.lnum);
+ curwin->w_cursor.lnum =
+ diff_get_corresponding_line(old_curbuf, line);
else
# endif
curwin->w_cursor.lnum = line;
diff --git a/src/proto/diff.pro b/src/proto/diff.pro
index c7a7ebe579..718640152f 100644
--- a/src/proto/diff.pro
+++ b/src/proto/diff.pro
@@ -22,6 +22,6 @@ void nv_diffgetput(int put, long count);
void ex_diffgetput(exarg_T *eap);
int diff_mode_buf(buf_T *buf);
int diff_move_to(int dir, long count);
-linenr_T diff_get_corresponding_line(buf_T *buf1, linenr_T lnum1, buf_T *buf2, linenr_T lnum3);
+linenr_T diff_get_corresponding_line(buf_T *buf1, linenr_T lnum1);
linenr_T diff_lnum_win(linenr_T lnum, win_T *wp);
/* vim: set ft=c : */
diff --git a/src/testdir/test_diffmode.vim b/src/testdir/test_diffmode.vim
index 5de394de8e..f40e06ff33 100644
--- a/src/testdir/test_diffmode.vim
+++ b/src/testdir/test_diffmode.vim
@@ -218,3 +218,20 @@ func Test_diffoff()
bwipe!
bwipe!
endfunc
+
+func Test_setting_cursor()
+ new Xtest1
+ put =range(1,90)
+ wq
+ new Xtest2
+ put =range(1,100)
+ wq
+
+ tabe Xtest2
+ $
+ diffsp Xtest1
+ tabclose
+
+ call delete('Xtest1')
+ call delete('Xtest2')
+endfunc
diff --git a/src/version.c b/src/version.c
index e910845d1c..80a837a381 100644
--- a/src/version.c
+++ b/src/version.c
@@ -765,6 +765,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 44,
+/**/
43,
/**/
42,