To: vim_dev@googlegroups.com Subject: Patch 8.0.0044 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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. Files: src/move.c, src/diff.c, src/proto/diff.pro, src/testdir/test_diffmode.vim *** ../vim-8.0.0043/src/move.c 2016-09-04 14:29:37.000000000 +0200 --- src/move.c 2016-10-18 14:28:15.793415019 +0200 *************** *** 2824,2834 **** { # ifdef FEAT_DIFF if (curwin->w_p_diff) ! curwin->w_cursor.lnum ! = diff_get_corresponding_line(old_curbuf, ! line, ! curbuf, ! curwin->w_cursor.lnum); else # endif curwin->w_cursor.lnum = line; --- 2824,2831 ---- { # ifdef FEAT_DIFF if (curwin->w_p_diff) ! curwin->w_cursor.lnum = ! diff_get_corresponding_line(old_curbuf, line); else # endif curwin->w_cursor.lnum = line; *** ../vim-8.0.0043/src/diff.c 2016-08-29 22:42:20.000000000 +0200 --- src/diff.c 2016-10-18 14:48:59.700247046 +0200 *************** *** 1100,1109 **** 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); } /* Now that lines are folded scroll to show the cursor at the same * relative position. */ --- 1100,1106 ---- 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); } /* Now that lines are folded scroll to show the cursor at the same * relative position. */ *************** *** 2524,2544 **** return OK; } ! linenr_T ! diff_get_corresponding_line( buf_T *buf1, ! linenr_T lnum1, ! buf_T *buf2, ! linenr_T lnum3) { int idx1; int idx2; diff_T *dp; int baseline = 0; - linenr_T lnum2; idx1 = diff_buf_idx(buf1); ! idx2 = diff_buf_idx(buf2); if (idx1 == DB_COUNT || idx2 == DB_COUNT || curtab->tp_first_diff == NULL) return lnum1; --- 2521,2542 ---- return OK; } ! /* ! * 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) { int idx1; int idx2; diff_T *dp; int baseline = 0; idx1 = diff_buf_idx(buf1); ! idx2 = diff_buf_idx(curbuf); if (idx1 == DB_COUNT || idx2 == DB_COUNT || curtab->tp_first_diff == NULL) return lnum1; *************** *** 2551,2565 **** 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) { /* Inside the diffblock */ baseline = lnum1 - dp->df_lnum[idx1]; --- 2549,2556 ---- for (dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next) { if (dp->df_lnum[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,2577 **** 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)) /* * Special case: if the cursor is just after a zero-count * block (i.e. all filler) and the target cursor is already --- 2559,2569 ---- return dp->df_lnum[idx2] + baseline; } ! 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,2596 **** * unmoved. This makes repeated CTRL-W W operations work * as expected. */ ! return lnum3; 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 lnum2; } #if defined(FEAT_FOLDING) || defined(PROTO) --- 2571,2598 ---- * unmoved. This makes repeated CTRL-W W operations work * as expected. */ ! 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 */ ! 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 (lnum > curbuf->b_ml.ml_line_count) ! return curbuf->b_ml.ml_line_count; ! return lnum; } #if defined(FEAT_FOLDING) || defined(PROTO) *** ../vim-8.0.0043/src/proto/diff.pro 2016-09-12 13:03:59.000000000 +0200 --- src/proto/diff.pro 2016-10-18 14:30:25.208461191 +0200 *************** *** 22,27 **** 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_lnum_win(linenr_T lnum, win_T *wp); /* vim: set ft=c : */ --- 22,27 ---- 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); linenr_T diff_lnum_win(linenr_T lnum, win_T *wp); /* vim: set ft=c : */ *** ../vim-8.0.0043/src/testdir/test_diffmode.vim 2016-08-27 22:20:56.000000000 +0200 --- src/testdir/test_diffmode.vim 2016-10-18 14:48:01.108678884 +0200 *************** *** 218,220 **** --- 218,237 ---- 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 *** ../vim-8.0.0043/src/version.c 2016-10-18 13:06:33.377547323 +0200 --- src/version.c 2016-10-18 14:28:23.337359418 +0200 *************** *** 766,767 **** --- 766,769 ---- { /* Add new patch number below this line */ + /**/ + 44, /**/ -- Zen Microsystems: we're the om in .commmmmmmmm /// 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 ///