# HG changeset patch # User Christian Brabandt # Date 1476795604 -7200 # Node ID d0b74b18e4b57ed0dfe43d1575856deb614aff7e # Parent 76376eb4cbe5f275508014e95e13e9bc8fed4f5f commit https://github.com/vim/vim/commit/025e3e0bafbc85cc4e365145af711edf99d0a90d Author: Bram Moolenaar 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. diff --git a/src/diff.c b/src/diff.c --- 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) diff --git a/src/move.c b/src/move.c --- 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 --- 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 --- 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 --- 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,