]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.0.1729: screenpos() wrong when w_skipcol and cpoptions+=n v9.0.1729
authorzeertzjq <zeertzjq@outlook.com>
Thu, 17 Aug 2023 20:58:53 +0000 (22:58 +0200)
committerChristian Brabandt <cb@256bit.org>
Thu, 17 Aug 2023 20:58:53 +0000 (22:58 +0200)
Problem:    screenpos() wrong result with w_skipcol and cpoptions+=n
Solution:   Use adjust_plines_for_skipcol() instead of subtracting
            w_skipcol.

closes: #12625

Signed-off-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: zeertzjq <zeertzjq@outlook.com>
src/drawscreen.c
src/misc1.c
src/move.c
src/popupwin.c
src/proto/misc1.pro
src/testdir/test_cursor_func.vim
src/version.c

index 86fec150264d223fc3557e5c1e4df1e667918869..90e1984e9f51de6f923a554667c7fd6dc5f1a653 100644 (file)
@@ -1792,7 +1792,8 @@ win_update(win_T *wp)
                j = wp->w_lines[0].wl_lnum - wp->w_topline;
            if (j < wp->w_height - 2)           // not too far off
            {
-               i = plines_m_win(wp, wp->w_topline, wp->w_lines[0].wl_lnum - 1);
+               i = plines_m_win(wp, wp->w_topline, wp->w_lines[0].wl_lnum - 1,
+                                                                        TRUE);
 #ifdef FEAT_DIFF
                // insert extra lines for previously invisible filler lines
                if (wp->w_lines[0].wl_lnum != wp->w_topline)
index 4ef5e14e2bbfbb109b12825886e7472dddf4b459..72083504a37aee97fe7099fb4e4e8fc2939fd871 100644 (file)
@@ -342,12 +342,13 @@ plines(linenr_T lnum)
 plines_win(
     win_T      *wp,
     linenr_T   lnum,
-    int                winheight)      // when TRUE limit to window height
+    int                limit_winheight)        // when TRUE limit to window height
 {
 #if defined(FEAT_DIFF) || defined(PROTO)
     // Check for filler lines above this buffer line.  When folded the result
     // is one line anyway.
-    return plines_win_nofill(wp, lnum, winheight) + diff_check_fill(wp, lnum);
+    return plines_win_nofill(wp, lnum, limit_winheight)
+                                                  + diff_check_fill(wp, lnum);
 }
 
 /*
@@ -364,7 +365,7 @@ plines_nofill(linenr_T lnum)
 plines_win_nofill(
     win_T      *wp,
     linenr_T   lnum,
-    int                winheight)      // when TRUE limit to window height
+    int                limit_winheight)        // when TRUE limit to window height
 {
 #endif
     int                lines;
@@ -389,7 +390,7 @@ plines_win_nofill(
     else
        lines = plines_win_nofold(wp, lnum);
 
-    if (winheight > 0 && lines > wp->w_height)
+    if (limit_winheight && lines > wp->w_height)
        return wp->w_height;
     return lines;
 }
@@ -497,7 +498,7 @@ plines_win_col(win_T *wp, linenr_T lnum, long column)
 }
 
     int
-plines_m_win(win_T *wp, linenr_T first, linenr_T last)
+plines_m_win(win_T *wp, linenr_T first, linenr_T last, int limit_winheight)
 {
     int                count = 0;
 
@@ -519,10 +520,11 @@ plines_m_win(win_T *wp, linenr_T first, linenr_T last)
        {
 #ifdef FEAT_DIFF
            if (first == wp->w_topline)
-               count += plines_win_nofill(wp, first, TRUE) + wp->w_topfill;
+               count += plines_win_nofill(wp, first, limit_winheight)
+                                                              + wp->w_topfill;
            else
 #endif
-               count += plines_win(wp, first, TRUE);
+               count += plines_win(wp, first, limit_winheight);
            ++first;
        }
     }
index 94dc7dc630f5361e37d581e2b00e716183e5ef53..96692ba7d75e67271e92f7e9acaf874752ac4be0 100644 (file)
@@ -1356,7 +1356,10 @@ curs_columns(
            // don't skip more than necessary
            if (n > p_lines - curwin->w_height + 1)
                n = p_lines - curwin->w_height + 1;
-           curwin->w_skipcol = n * width2;
+           if (n > 0)
+               curwin->w_skipcol = width1 + (n - 1) * width2;
+           else
+               curwin->w_skipcol = 0;
        }
        else if (extra == 1)
        {
@@ -1443,7 +1446,6 @@ textpos2screenpos(
 {
     colnr_T    scol = 0, ccol = 0, ecol = 0;
     int                row = 0;
-    int                rowoff = 0;
     colnr_T    coloff = 0;
 
     if (pos->lnum >= wp->w_topline && pos->lnum <= wp->w_botline)
@@ -1456,7 +1458,10 @@ textpos2screenpos(
 
        is_folded = hasFoldingWin(wp, lnum, &lnum, NULL, TRUE, NULL);
 #endif
-       row = plines_m_win(wp, wp->w_topline, lnum - 1) + 1;
+       row = plines_m_win(wp, wp->w_topline, lnum - 1, FALSE) + 1;
+       // "row" should be the screen line where line "lnum" begins, which can
+       // be negative if "lnum" is "w_topline" and "w_skipcol" is non-zero.
+       row = adjust_plines_for_skipcol(wp, row);
 
 #ifdef FEAT_DIFF
        // Add filler lines above this buffer line.
@@ -1481,32 +1486,30 @@ textpos2screenpos(
            col += off;
            width = wp->w_width - off + win_col_off2(wp);
 
-           if (lnum == wp->w_topline)
-               col -= wp->w_skipcol;
-
            // 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);
+               int rowoff = ((col - wp->w_width) / width + 1);
                col -= rowoff * width;
+               row += rowoff;
            }
            col -= wp->w_leftcol;
            if (col >= wp->w_width)
                col = -1;
-           if (col >= 0 && row + rowoff <= wp->w_height)
+           if (col >= 0 && row > 0 && row <= 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;
+               // character is out of the window
+               row = scol = ccol = ecol = 0;
        }
     }
-    *rowp = row + rowoff;
+    *rowp = row;
     *scolp = scol + coloff;
     *ccolp = ccol + coloff;
     *ecolp = ecol + coloff;
index 4f72d072030d1a18feb106e32cf839ce3b1d5819..92195a20001e7383331fa598860dcb62fb62a77c 100644 (file)
@@ -654,7 +654,7 @@ popup_show_curline(win_T *wp)
            wp->w_topline = wp->w_buffer->b_ml.ml_line_count;
        while (wp->w_topline < wp->w_cursor.lnum
                && wp->w_topline < wp->w_buffer->b_ml.ml_line_count
-               && plines_m_win(wp, wp->w_topline, wp->w_cursor.lnum)
+               && plines_m_win(wp, wp->w_topline, wp->w_cursor.lnum, TRUE)
                                                                > wp->w_height)
            ++wp->w_topline;
     }
index 5884821ac3eab10f17e7391ef030c71d15f3e050..b87b7ea747576b78d624b9f65f510748e381fc60 100644 (file)
@@ -2,12 +2,12 @@
 int get_leader_len(char_u *line, char_u **flags, int backward, int include_space);
 int get_last_leader_offset(char_u *line, char_u **flags);
 int plines(linenr_T lnum);
-int plines_win(win_T *wp, linenr_T lnum, int winheight);
+int plines_win(win_T *wp, linenr_T lnum, int limit_winheight);
 int plines_nofill(linenr_T lnum);
-int plines_win_nofill(win_T *wp, linenr_T lnum, int winheight);
+int plines_win_nofill(win_T *wp, linenr_T lnum, int limit_winheight);
 int plines_win_nofold(win_T *wp, linenr_T lnum);
 int plines_win_col(win_T *wp, linenr_T lnum, long column);
-int plines_m_win(win_T *wp, linenr_T first, linenr_T last);
+int plines_m_win(win_T *wp, linenr_T first, linenr_T last, int limit_winheight);
 int gchar_pos(pos_T *pos);
 int gchar_cursor(void);
 void pchar_cursor(int c);
index b0444d5e677417c92b0b7564cfb74deddfe96ab0..4fc59288c0fe564201d23d4ae6280e9348cb7cc6 100644 (file)
@@ -130,38 +130,71 @@ func Test_screenpos()
        \ winid->screenpos(line('$'), 22))
 
   1split
-  normal G$
-  redraw
-  " w_skipcol should be subtracted
-  call assert_equal({'row': winrow + 0,
-       \ 'col': wincol + 20 - 1,
-       \ 'curscol': wincol + 20 - 1,
-       \ 'endcol': wincol + 20 - 1},
-       \ screenpos(win_getid(), line('.'), col('.')))
 
   " w_leftcol should be subtracted
   setlocal nowrap
-  normal 050zl$
+  normal G050zl$
+  redraw
   call assert_equal({'row': winrow + 0,
        \ 'col': wincol + 10 - 1,
        \ 'curscol': wincol + 10 - 1,
        \ 'endcol': wincol + 10 - 1},
        \ screenpos(win_getid(), line('.'), col('.')))
 
-  " w_skipcol should only matter for the topline
-" FIXME: This fails because pline_m_win() does not take w_skipcol into
-" account.  If it does, then other tests fail.
-"  wincmd +
-"  setlocal wrap smoothscroll
-"  call setline(line('$') + 1, 'last line')
-"  exe "normal \<C-E>G$"
-"  redraw
-"  call assert_equal({'row': winrow + 1,
-"      \ 'col': wincol + 9 - 1,
-"      \ 'curscol': wincol + 9 - 1,
-"      \ 'endcol': wincol + 9 - 1},
-"      \ screenpos(win_getid(), line('.'), col('.')))
-  close
+  " w_skipcol should be taken into account
+  setlocal wrap
+  normal $
+  redraw
+  call assert_equal({'row': winrow + 0,
+       \ 'col': wincol + 20 - 1,
+       \ 'curscol': wincol + 20 - 1,
+       \ 'endcol': wincol + 20 - 1},
+       \ screenpos(win_getid(), line('.'), col('.')))
+  call assert_equal({'row': 0, 'col': 0, 'curscol': 0, 'endcol': 0},
+       \ screenpos(win_getid(), line('.'), col('.') - 20))
+  setlocal number
+  redraw
+  call assert_equal({'row': winrow + 0,
+       \ 'col': wincol + 16 - 1,
+       \ 'curscol': wincol + 16 - 1,
+       \ 'endcol': wincol + 16 - 1},
+       \ screenpos(win_getid(), line('.'), col('.')))
+  call assert_equal({'row': 0, 'col': 0, 'curscol': 0, 'endcol': 0},
+       \ screenpos(win_getid(), line('.'), col('.') - 16))
+  set cpoptions+=n
+  redraw
+  call assert_equal({'row': winrow + 0,
+       \ 'col': wincol + 4 - 1,
+       \ 'curscol': wincol + 4 - 1,
+       \ 'endcol': wincol + 4 - 1},
+       \ screenpos(win_getid(), line('.'), col('.')))
+  call assert_equal({'row': 0, 'col': 0, 'curscol': 0, 'endcol': 0},
+       \ screenpos(win_getid(), line('.'), col('.') - 4))
+
+  wincmd +
+  call setline(line('$') + 1, 'last line')
+  setlocal smoothscroll
+  normal G$
+  redraw
+  call assert_equal({'row': winrow + 1,
+       \ 'col': wincol + 4 + 9 - 1,
+       \ 'curscol': wincol + 4 + 9 - 1,
+       \ 'endcol': wincol + 4 + 9 - 1},
+       \ screenpos(win_getid(), line('.'), col('.')))
+  set cpoptions-=n
+  redraw
+  call assert_equal({'row': winrow + 1,
+       \ 'col': wincol + 4 + 9 - 1,
+       \ 'curscol': wincol + 4 + 9 - 1,
+       \ 'endcol': wincol + 4 + 9 - 1},
+       \ screenpos(win_getid(), line('.'), col('.')))
+  setlocal nonumber
+  redraw
+  call assert_equal({'row': winrow + 1,
+       \ 'col': wincol + 9 - 1,
+       \ 'curscol': wincol + 9 - 1,
+       \ 'endcol': wincol + 9 - 1},
+       \ screenpos(win_getid(), line('.'), col('.')))
 
   close
   call assert_equal({}, screenpos(999, 1, 1))
index aa4a089bf1c1adf50c9f6c97c2b07bd68722c446..64fcfca0ca4a9d3707b0473bc8b73dd7f2180835 100644 (file)
@@ -695,6 +695,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1729,
 /**/
     1728,
 /**/