]> granicus.if.org Git - vim/commitdiff
patch 8.1.0994: relative cursor position is not calculated correctly v8.1.0994
authorBram Moolenaar <Bram@vim.org>
Mon, 4 Mar 2019 12:18:30 +0000 (13:18 +0100)
committerBram Moolenaar <Bram@vim.org>
Mon, 4 Mar 2019 12:18:30 +0000 (13:18 +0100)
Problem:    Relative cursor position is not calculated correctly.
Solution:   Always set topline, also when window is one line only.
            (Robert Webb) Add more info to getwininfo() for testing.

runtime/doc/eval.txt
src/evalfunc.c
src/testdir/test_window_cmd.vim
src/version.c
src/window.c

index 33b3fe24318101c08314a3e775760ccfa82ff043..f03c1fd307eac7606736513088cef1cad95514da 100644 (file)
@@ -5228,6 +5228,7 @@ getwininfo([{winid}])                                     *getwininfo()*
                tab pages is returned.
 
                Each List item is a Dictionary with the following entries:
+                       botline         last displayed buffer line
                        bufnr           number of buffer in the window
                        height          window height (excluding winbar)
                        loclist         1 if showing a location list
@@ -5237,6 +5238,7 @@ getwininfo([{winid}])                                     *getwininfo()*
                        terminal        1 if a terminal window
                                        {only with the +terminal feature}
                        tabnr           tab page number
+                       topline         first displayed buffer line 
                        variables       a reference to the dictionary with
                                        window-local variables
                        width           window width
index 0d996c512c69af95f0159a470718a63250a7328c..7cecab0658364b226b436b941a141e28ddfe6073 100644 (file)
@@ -5762,6 +5762,8 @@ get_win_info(win_T *wp, short tpnr, short winnr)
     dict_add_number(dict, "winid", wp->w_id);
     dict_add_number(dict, "height", wp->w_height);
     dict_add_number(dict, "winrow", wp->w_winrow + 1);
+    dict_add_number(dict, "topline", wp->w_topline);
+    dict_add_number(dict, "botline", wp->w_botline - 1);
 #ifdef FEAT_MENU
     dict_add_number(dict, "winbar", wp->w_winbar_height);
 #endif
index 587ae23da8265c399c77ac88786f10dfb01e6ae0..5189e681fc6045aa2d5645ba77e78d32271ee9ca 100644 (file)
@@ -615,4 +615,132 @@ func Test_window_prevwin()
   delfunc Fun_RenewFile
 endfunc
 
+func Test_relative_cursor_position_in_one_line_window()
+  new
+  only
+  call setline(1, range(1, 10000))
+  normal 50%
+  let lnum = getcurpos()[1]
+  split
+  split
+  " make third window take as many lines as possible, other windows will
+  " become one line
+  3wincmd w
+  for i in range(1, &lines - 6)
+    wincmd +
+    redraw!
+  endfor
+
+  " first and second window should show cursor line
+  let wininfo = getwininfo()
+  call assert_equal(lnum, wininfo[0].topline)
+  call assert_equal(lnum, wininfo[1].topline)
+
+  only!
+  bwipe!
+endfunc
+
+func Test_relative_cursor_position_after_move_and_resize()
+  let so_save = &so
+  set so=0
+  enew
+  call setline(1, range(1, 10000))
+  normal 50%
+  split
+  1wincmd w
+  " Move cursor to first line in window
+  normal H
+  redraw!
+  " Reduce window height to two lines
+  let height = winheight(0)
+  while winheight(0) > 2
+    wincmd -
+    redraw!
+  endwhile
+  " move cursor to second/last line in window
+  normal j
+  " restore previous height
+  while winheight(0) < height
+    wincmd +
+    redraw!
+  endwhile
+  " make window two lines again
+  while winheight(0) > 2
+    wincmd -
+    redraw!
+  endwhile
+
+  " cursor should be at bottom line
+  let info = getwininfo(win_getid())[0]
+  call assert_equal(info.topline + 1, getcurpos()[1])
+
+  only!
+  bwipe!
+  let &so = so_save
+endfunc
+
+func Test_relative_cursor_position_after_resize()
+  let so_save = &so
+  set so=0
+  enew
+  call setline(1, range(1, 10000))
+  normal 50%
+  split
+  1wincmd w
+  let winid1 = win_getid()
+  let info = getwininfo(winid1)[0]
+  " Move cursor to second line in window
+  exe "normal " . (info.topline + 1) . "G"
+  redraw!
+  let lnum = getcurpos()[1]
+
+  " Make the window only two lines high, cursor should end up in top line
+  2wincmd w
+  exe (info.height - 2) . "wincmd +"
+  redraw!
+  let info = getwininfo(winid1)[0]
+  call assert_equal(lnum, info.topline)
+
+  only!
+  bwipe!
+  let &so = so_save
+endfunc
+
+func Test_relative_cursor_second_line_after_resize()
+  let so_save = &so
+  set so=0
+  enew
+  call setline(1, range(1, 10000))
+  normal 50%
+  split
+  1wincmd w
+  let winid1 = win_getid()
+  let info = getwininfo(winid1)[0]
+
+  " Make the window only two lines high
+  2wincmd _
+
+  " Move cursor to second line in window
+  normal H
+  normal j
+
+  " Make window size bigger, then back to 2 lines
+  for i in range(1, 10)
+    wincmd +
+    redraw!
+  endfor
+  for i in range(1, 10)
+    wincmd -
+    redraw!
+  endfor
+
+  " cursor should end up in bottom line
+  let info = getwininfo(winid1)[0]
+  call assert_equal(info.topline + 1, getcurpos()[1])
+
+  only!
+  bwipe!
+  let &so = so_save
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
index 8722a832c7f4a3d451316e5823242eb159dbb4f9..6279847e89c7cdc68a13523666abbf6b3f08a4f9 100644 (file)
@@ -779,6 +779,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    994,
 /**/
     993,
 /**/
index 074c731ea8a3f63d11882d19cd1ec2a2831f46d7..98d608517422a03ee4310c9f9fb3fe7304bbc346 100644 (file)
@@ -5719,8 +5719,11 @@ win_drag_vsep_line(win_T *dragwin, int offset)
 set_fraction(win_T *wp)
 {
     if (wp->w_height > 1)
+       // When cursor is in the first line the percentage is computed as if
+       // it's halfway that line.  Thus with two lines it is 25%, with three
+       // lines 17%, etc.  Similarly for the last line: 75%, 83%, etc.
        wp->w_fraction = ((long)wp->w_wrow * FRACTION_MULT
-                                   + wp->w_height / 2) / (long)wp->w_height;
+                                    + FRACTION_MULT / 2) / (long)wp->w_height;
 }
 
 /*
@@ -5770,8 +5773,8 @@ scroll_to_fraction(win_T *wp, int prev_height)
     int                sline, line_size;
     int                height = wp->w_height;
 
-    /* Don't change w_topline when height is zero.  Don't set w_topline when
-     * 'scrollbind' is set and this isn't the current window. */
+    // Don't change w_topline when height is zero.  Don't set w_topline when
+    // 'scrollbind' is set and this isn't the current window.
     if (height > 0 && (!wp->w_p_scb || wp == curwin))
     {
        /*
@@ -5781,8 +5784,8 @@ scroll_to_fraction(win_T *wp, int prev_height)
        lnum = wp->w_cursor.lnum;
        if (lnum < 1)           /* can happen when starting up */
            lnum = 1;
-       wp->w_wrow = ((long)wp->w_fraction * (long)height - 1L
-                                        + FRACTION_MULT / 2) / FRACTION_MULT;
+       wp->w_wrow = ((long)wp->w_fraction * (long)height - 1L)
+                                                              / FRACTION_MULT;
        line_size = plines_win_col(wp, lnum, (long)(wp->w_cursor.col)) - 1;
        sline = wp->w_wrow - line_size;
 
@@ -5818,7 +5821,6 @@ scroll_to_fraction(win_T *wp, int prev_height)
                    --wp->w_wrow;
                }
            }
-           set_topline(wp, lnum);
        }
        else if (sline > 0)
        {
@@ -5859,13 +5861,12 @@ scroll_to_fraction(win_T *wp, int prev_height)
            }
            else if (sline > 0)
            {
-               /* First line of file reached, use that as topline. */
+               // First line of file reached, use that as topline.
                lnum = 1;
                wp->w_wrow -= sline;
            }
-
-           set_topline(wp, lnum);
        }
+       set_topline(wp, lnum);
     }
 
     if (wp == curwin)