changeset 10295:d0b74b18e4b5 v8.0.0044

commit https://github.com/vim/vim/commit/025e3e0bafbc85cc4e365145af711edf99d0a90d Author: Bram Moolenaar <Bram@vim.org> Date: Tue Oct 18 14:50:18 2016 +0200 patch 8.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.
author Christian Brabandt <cb@256bit.org>
date Tue, 18 Oct 2016 15:00:04 +0200
parents 76376eb4cbe5
children 5197102a03f8
files src/diff.c src/move.c src/proto/diff.pro src/testdir/test_diffmode.vim src/version.c
diffstat 5 files changed, 54 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- 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;
+    return lnum1 - baseline;
+}
+
+/*
+ * 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 (lnum2 > buf2->b_ml.ml_line_count)
-	lnum2 = buf2->b_ml.ml_line_count;
-
-    return lnum2;
+    if (lnum > curbuf->b_ml.ml_line_count)
+	return curbuf->b_ml.ml_line_count;
+    return lnum;
 }
 
 #if defined(FEAT_FOLDING) || defined(PROTO)
--- 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;
--- 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 : */
--- 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
--- 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,