# HG changeset patch # User Bram Moolenaar # Date 1665774903 -7200 # Node ID e3d5781c7ec6340686df728f30eed2740da2c32d # Parent 64fffffc3295fc688c9011c0f2091cdf51691827 patch 9.0.0751: 'scrolloff' does not work well with 'smoothscroll' Commit: https://github.com/vim/vim/commit/c9121f798f49fa71e814912cb186d89c164090c3 Author: Bram Moolenaar Date: Fri Oct 14 20:09:04 2022 +0100 patch 9.0.0751: 'scrolloff' does not work well with 'smoothscroll' Problem: 'scrolloff' does not work well with 'smoothscroll'. Solution: Make positioning the cursor a bit better. Rename functions. diff --git a/src/charset.c b/src/charset.c --- a/src/charset.c +++ b/src/charset.c @@ -743,13 +743,13 @@ win_chartabsize(win_T *wp, char_u *p, co * Does not handle text properties, since "s" is not a buffer line. */ int -linetabsize(char_u *s) +linetabsize_str(char_u *s) { return linetabsize_col(0, s); } /* - * Like linetabsize(), but "s" starts at column "startcol". + * Like linetabsize_str(), but "s" starts at column "startcol". */ int linetabsize_col(int startcol, char_u *s) @@ -772,7 +772,7 @@ linetabsize_col(int startcol, char_u *s) } /* - * Like linetabsize(), but for a given window instead of the current one. + * Like linetabsize_str(), but for a given window instead of the current one. */ int win_linetabsize(win_T *wp, linenr_T lnum, char_u *line, colnr_T len) @@ -785,6 +785,17 @@ win_linetabsize(win_T *wp, linenr_T lnum return (int)cts.cts_vcol; } +/* + * Return the number of cells line "lnum" of window "wp" will take on the + * screen, taking into account the size of a tab and text properties. + */ + int +linetabsize(win_T *wp, linenr_T lnum) +{ + return win_linetabsize(wp, lnum, + ml_get_buf(wp->w_buffer, lnum, FALSE), (colnr_T)MAXCOL); +} + void win_linetabsize_cts(chartabsize_T *cts, colnr_T len) { diff --git a/src/edit.c b/src/edit.c --- a/src/edit.c +++ b/src/edit.c @@ -237,7 +237,7 @@ edit( if (startln) Insstart.col = 0; } - Insstart_textlen = (colnr_T)linetabsize(ml_get_curline()); + Insstart_textlen = (colnr_T)linetabsize_str(ml_get_curline()); Insstart_blank_vcol = MAXCOL; if (!did_ai) ai_col = 0; @@ -2372,7 +2372,7 @@ stop_arrow(void) // Don't update the original insert position when moved to the // right, except when nothing was inserted yet. update_Insstart_orig = FALSE; - Insstart_textlen = (colnr_T)linetabsize(ml_get_curline()); + Insstart_textlen = (colnr_T)linetabsize_str(ml_get_curline()); if (u_save_cursor() == OK) { diff --git a/src/ex_cmds.c b/src/ex_cmds.c --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -256,7 +256,7 @@ linelen(int *has_tab) ; save = *last; *last = NUL; - len = linetabsize(line); // get line length + len = linetabsize_str(line); // get line length on screen if (has_tab != NULL) // check for embedded TAB *has_tab = (vim_strchr(first, TAB) != NULL); *last = save; diff --git a/src/misc2.c b/src/misc2.c --- a/src/misc2.c +++ b/src/misc2.c @@ -150,7 +150,7 @@ coladvance2( if ((addspaces || finetune) && !VIsual_active) { - curwin->w_curswant = linetabsize(line) + one_more; + curwin->w_curswant = linetabsize_str(line) + one_more; if (curwin->w_curswant > 0) --curwin->w_curswant; } @@ -166,7 +166,7 @@ coladvance2( && wcol >= (colnr_T)width && width > 0) { - csize = linetabsize(line); + csize = linetabsize_str(line); if (csize > 0) csize--; diff --git a/src/move.c b/src/move.c --- a/src/move.c +++ b/src/move.c @@ -1633,7 +1633,7 @@ scrolldown( if (curwin->w_cursor.lnum == curwin->w_topline && do_sms) { - long so = curwin->w_p_so >= 0 ? curwin->w_p_so : p_so; + long so = get_scrolloff_value(); int scrolloff_cols = so == 0 ? 0 : width1 + (so - 1) * width2; // make sure the cursor is in the visible text @@ -1684,8 +1684,7 @@ scrollup( linenr_T prev_topline = curwin->w_topline; if (do_sms) - size = win_linetabsize(curwin, curwin->w_topline, - ml_get(curwin->w_topline), (colnr_T)MAXCOL); + size = linetabsize(curwin, curwin->w_topline); // diff mode: first consume "topfill" // 'smoothscroll': increase "w_skipcol" until it goes over the end of @@ -1740,8 +1739,7 @@ scrollup( # endif curwin->w_skipcol = 0; if (todo > 1 && do_sms) - size = win_linetabsize(curwin, curwin->w_topline, - ml_get(curwin->w_topline), (colnr_T)MAXCOL); + size = linetabsize(curwin, curwin->w_topline); } } } @@ -1784,11 +1782,15 @@ scrollup( { int width1 = curwin->w_width - curwin_col_off(); int width2 = width1 + curwin_col_off2(); - long so = curwin->w_p_so >= 0 ? curwin->w_p_so : p_so; + long so = get_scrolloff_value(); int scrolloff_cols = so == 0 ? 0 : width1 + (so - 1) * width2; + int space_cols = (curwin->w_height - 1) * width2; // Make sure the cursor is in a visible part of the line, taking // 'scrolloff' into account, but using screen lines. + // If there are not enough screen lines put the cursor in the middle. + if (scrolloff_cols > space_cols / 2) + scrolloff_cols = space_cols / 2; validate_virtcol(); if (curwin->w_virtcol < curwin->w_skipcol + 3 + scrolloff_cols) { @@ -1823,11 +1825,22 @@ adjust_skipcol(void) int width1 = curwin->w_width - curwin_col_off(); int width2 = width1 + curwin_col_off2(); - long so = curwin->w_p_so >= 0 ? curwin->w_p_so : p_so; + long so = get_scrolloff_value(); int scrolloff_cols = so == 0 ? 0 : width1 + (so - 1) * width2; int scrolled = FALSE; validate_virtcol(); + if (curwin->w_cline_height == curwin->w_height) + { + // the line just fits in the window, don't scroll + if (curwin->w_skipcol != 0) + { + curwin->w_skipcol = 0; + redraw_later(UPD_NOT_VALID); + } + return; + } + while (curwin->w_skipcol > 0 && curwin->w_virtcol < curwin->w_skipcol + 3 + scrolloff_cols) { @@ -2691,6 +2704,19 @@ cursor_correct(void) ) return; + if (curwin->w_p_sms && !curwin->w_p_wrap) + { + // 'smoothscroll is active + if (curwin->w_cline_height == curwin->w_height) + { + // The cursor line just fits in the window, don't scroll. + curwin->w_skipcol = 0; + return; + } + // TODO: If the cursor line doesn't fit in the window then only adjust + // w_skipcol. + } + /* * Narrow down the area where the cursor can be put by taking lines from * the top and the bottom until: diff --git a/src/normal.c b/src/normal.c --- a/src/normal.c +++ b/src/normal.c @@ -2266,7 +2266,7 @@ find_decl( static int nv_screengo(oparg_T *oap, int dir, long dist) { - int linelen = linetabsize(ml_get_curline()); + int linelen = linetabsize_str(ml_get_curline()); int retval = OK; int atend = FALSE; int n; @@ -2343,7 +2343,7 @@ nv_screengo(oparg_T *oap, int dir, long } --curwin->w_cursor.lnum; - linelen = linetabsize(ml_get_curline()); + linelen = linetabsize_str(ml_get_curline()); if (linelen > width1) curwin->w_curswant += (((linelen - width1 - 1) / width2) + 1) * width2; @@ -2383,7 +2383,7 @@ nv_screengo(oparg_T *oap, int dir, long // clipped to column 0. if (curwin->w_curswant >= width1) curwin->w_curswant -= width2; - linelen = linetabsize(ml_get_curline()); + linelen = linetabsize_str(ml_get_curline()); } } } @@ -6005,7 +6005,7 @@ nv_g_cmd(cmdarg_T *cap) { oap->motion_type = MCHAR; oap->inclusive = FALSE; - i = linetabsize(ml_get_curline()); + i = linetabsize_str(ml_get_curline()); if (cap->count0 > 0 && cap->count0 <= 100) coladvance((colnr_T)(i * cap->count0 / 100)); else diff --git a/src/ops.c b/src/ops.c --- a/src/ops.c +++ b/src/ops.c @@ -3261,7 +3261,7 @@ cursor_pos_info(dict_T *dict) col_print(buf1, sizeof(buf1), (int)curwin->w_cursor.col + 1, (int)curwin->w_virtcol + 1); col_print(buf2, sizeof(buf2), (int)STRLEN(p), - linetabsize(p)); + linetabsize_str(p)); if (char_count_cursor == byte_count_cursor && char_count == byte_count) diff --git a/src/popupwin.c b/src/popupwin.c --- a/src/popupwin.c +++ b/src/popupwin.c @@ -1403,8 +1403,7 @@ popup_adjust_position(win_T *wp) // "margin_width" is added to "len" where it matters. if (wp->w_width < maxwidth) wp->w_width = maxwidth; - len = win_linetabsize(wp, lnum, ml_get_buf(wp->w_buffer, lnum, FALSE), - (colnr_T)MAXCOL); + len = linetabsize(wp, lnum); wp->w_width = w_width; if (wp->w_p_wrap) diff --git a/src/proto/charset.pro b/src/proto/charset.pro --- a/src/proto/charset.pro +++ b/src/proto/charset.pro @@ -15,9 +15,10 @@ int ptr2cells(char_u *p); int vim_strsize(char_u *s); int vim_strnsize(char_u *s, int len); int chartabsize(char_u *p, colnr_T col); -int linetabsize(char_u *s); +int linetabsize_str(char_u *s); int linetabsize_col(int startcol, char_u *s); int win_linetabsize(win_T *wp, linenr_T lnum, char_u *line, colnr_T len); +int linetabsize(win_T *wp, linenr_T lnum); void win_linetabsize_cts(chartabsize_T *cts, colnr_T len); int vim_isIDc(int c); int vim_isNormalIDc(int c); diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -696,6 +696,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 751, +/**/ 750, /**/ 749,