# HG changeset patch # User Bram Moolenaar # Date 1644932703 -3600 # Node ID d3ed8b1a7bde89f85def32c3cab56864bc2f6f0a # Parent 8c46546e1e2f5deb91f608941a016b659211918a patch 8.2.4389: screenpos() does not handle a position in a closed fold Commit: https://github.com/vim/vim/commit/4556a2e8681c5c98fb4c7ca0a016924a69b4452a Author: Bram Moolenaar Date: Tue Feb 15 13:40:17 2022 +0000 patch 8.2.4389: screenpos() does not handle a position in a closed fold Problem: screenpos() does not handle a position in a closed fold. Solution: Check if the position is inside a closed fold. (closes https://github.com/vim/vim/issues/9778) diff --git a/src/move.c b/src/move.c --- a/src/move.c +++ b/src/move.c @@ -1236,39 +1236,54 @@ textpos2screenpos( if (pos->lnum >= wp->w_topline && pos->lnum <= wp->w_botline) { - colnr_T off; - colnr_T col; - int width; - - row = plines_m_win(wp, wp->w_topline, pos->lnum - 1) + 1; - getvcol(wp, pos, &scol, &ccol, &ecol); - - // similar to what is done in validate_cursor_col() - col = scol; - off = win_col_off(wp); - col += off; - width = wp->w_width - off + win_col_off2(wp); + colnr_T off; + colnr_T col; + int width; + linenr_T lnum = pos->lnum; +#ifdef FEAT_FOLDING + int is_folded; - // long line wrapping, adjust row - if (wp->w_p_wrap - && col >= (colnr_T)wp->w_width - && width > 0) + is_folded = hasFoldingWin(wp, lnum, &lnum, NULL, TRUE, NULL); +#endif + row = plines_m_win(wp, wp->w_topline, lnum - 1) + 1; +#ifdef FEAT_FOLDING + if (is_folded) { - // use same formula as what is used in curs_columns() - rowoff = ((col - wp->w_width) / width + 1); - col -= rowoff * width; - } - col -= wp->w_leftcol; - if (col >= wp->w_width) - col = -1; - if (col >= 0 && row + rowoff <= wp->w_height) - { - coloff = col - scol + wp->w_wincol + 1; row += W_WINROW(wp); + coloff = wp->w_wincol + 1; } else - // character is left, right or below of the window - row = rowoff = scol = ccol = ecol = 0; +#endif + { + getvcol(wp, pos, &scol, &ccol, &ecol); + + // similar to what is done in validate_cursor_col() + col = scol; + off = win_col_off(wp); + col += off; + width = wp->w_width - off + win_col_off2(wp); + + // long line wrapping, adjust row + if (wp->w_p_wrap + && col >= (colnr_T)wp->w_width + && width > 0) + { + // use same formula as what is used in curs_columns() + rowoff = ((col - wp->w_width) / width + 1); + col -= rowoff * width; + } + col -= wp->w_leftcol; + if (col >= wp->w_width) + col = -1; + if (col >= 0 && row + rowoff <= wp->w_height) + { + coloff = col - scol + wp->w_wincol + 1; + row += W_WINROW(wp); + } + else + // character is left, right or below of the window + row = rowoff = scol = ccol = ecol = 0; + } } *rowp = row + rowoff; *scolp = scol + coloff; diff --git a/src/testdir/test_cursor_func.vim b/src/testdir/test_cursor_func.vim --- a/src/testdir/test_cursor_func.vim +++ b/src/testdir/test_cursor_func.vim @@ -1,5 +1,7 @@ " Tests for cursor() and other functions that get/set the cursor position +source check.vim + func Test_wrong_arguments() call assert_fails('call cursor(1. 3)', 'E474:') call assert_fails('call cursor(test_null_list())', 'E474:') @@ -133,12 +135,27 @@ func Test_screenpos() bwipe! set display& - call assert_equal({'col': 1, 'row': 1, 'endcol': 1, 'curscol': 1}, screenpos(win_getid(), 1, 1)) + call assert_equal(#{col: 1, row: 1, endcol: 1, curscol: 1}, screenpos(win_getid(), 1, 1)) nmenu WinBar.TEST : - call assert_equal({'col': 1, 'row': 2, 'endcol': 1, 'curscol': 1}, screenpos(win_getid(), 1, 1)) + call assert_equal(#{col: 1, row: 2, endcol: 1, curscol: 1}, screenpos(win_getid(), 1, 1)) nunmenu WinBar.TEST endfunc +func Test_screenpos_fold() + CheckFeature folding + + enew! + call setline(1, range(10)) + 3,5fold + redraw + call assert_equal(2, screenpos(1, 2, 1).row) + call assert_equal(#{col: 1, row: 3, endcol: 1, curscol: 1}, screenpos(1, 3, 1)) + call assert_equal(3, screenpos(1, 4, 1).row) + call assert_equal(3, screenpos(1, 5, 1).row) + call assert_equal(4, screenpos(1, 6, 1).row) + bwipe! +endfunc + func Test_screenpos_number() rightbelow new rightbelow 73vsplit diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 4389, +/**/ 4388, /**/ 4387,