mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-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.
c9121f798f
Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
parent
223c7173ee
commit
c426f7a622
@ -115,7 +115,7 @@ static int coladvance2(pos_T *pos, bool addspaces, bool finetune, colnr_T wcol_a
|
|||||||
col = wcol;
|
col = wcol;
|
||||||
|
|
||||||
if ((addspaces || finetune) && !VIsual_active) {
|
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) {
|
if (curwin->w_curswant > 0) {
|
||||||
curwin->w_curswant--;
|
curwin->w_curswant--;
|
||||||
}
|
}
|
||||||
@ -129,7 +129,7 @@ static int coladvance2(pos_T *pos, bool addspaces, bool finetune, colnr_T wcol_a
|
|||||||
&& curwin->w_width_inner != 0
|
&& curwin->w_width_inner != 0
|
||||||
&& wcol >= (colnr_T)width
|
&& wcol >= (colnr_T)width
|
||||||
&& width > 0) {
|
&& width > 0) {
|
||||||
csize = linetabsize(line);
|
csize = linetabsize_str(line);
|
||||||
if (csize > 0) {
|
if (csize > 0) {
|
||||||
csize--;
|
csize--;
|
||||||
}
|
}
|
||||||
|
@ -193,7 +193,7 @@ static void insert_enter(InsertState *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Insstart_textlen = (colnr_T)linetabsize(get_cursor_line_ptr());
|
Insstart_textlen = linetabsize_str(get_cursor_line_ptr());
|
||||||
Insstart_blank_vcol = MAXCOL;
|
Insstart_blank_vcol = MAXCOL;
|
||||||
|
|
||||||
if (!did_ai) {
|
if (!did_ai) {
|
||||||
@ -2251,7 +2251,7 @@ int stop_arrow(void)
|
|||||||
// right, except when nothing was inserted yet.
|
// right, except when nothing was inserted yet.
|
||||||
update_Insstart_orig = false;
|
update_Insstart_orig = false;
|
||||||
}
|
}
|
||||||
Insstart_textlen = (colnr_T)linetabsize(get_cursor_line_ptr());
|
Insstart_textlen = linetabsize_str(get_cursor_line_ptr());
|
||||||
|
|
||||||
if (u_save_cursor() == OK) {
|
if (u_save_cursor() == OK) {
|
||||||
arrow_used = false;
|
arrow_used = false;
|
||||||
|
@ -346,10 +346,8 @@ static int linelen(int *has_tab)
|
|||||||
last > first && ascii_iswhite(last[-1]); last--) {}
|
last > first && ascii_iswhite(last[-1]); last--) {}
|
||||||
char save = *last;
|
char save = *last;
|
||||||
*last = NUL;
|
*last = NUL;
|
||||||
// Get line length.
|
len = linetabsize_str(line); // Get line length.
|
||||||
len = linetabsize(line);
|
if (has_tab != NULL) { // Check for embedded TAB.
|
||||||
// Check for embedded TAB.
|
|
||||||
if (has_tab != NULL) {
|
|
||||||
*has_tab = vim_strchr(first, TAB) != NULL;
|
*has_tab = vim_strchr(first, TAB) != NULL;
|
||||||
}
|
}
|
||||||
*last = save;
|
*last = save;
|
||||||
|
@ -1238,7 +1238,7 @@ bool scrolldown(long line_count, int byfold)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (curwin->w_cursor.lnum == curwin->w_topline && do_sms) {
|
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(curwin);
|
||||||
long scrolloff_cols = so == 0 ? 0 : width1 + (so - 1) * width2;
|
long scrolloff_cols = so == 0 ? 0 : width1 + (so - 1) * width2;
|
||||||
|
|
||||||
// make sure the cursor is in the visible text
|
// make sure the cursor is in the visible text
|
||||||
@ -1274,12 +1274,11 @@ bool scrollup(long line_count, int byfold)
|
|||||||
if (do_sms || (byfold && hasAnyFolding(curwin)) || win_may_fill(curwin)) {
|
if (do_sms || (byfold && hasAnyFolding(curwin)) || win_may_fill(curwin)) {
|
||||||
int width1 = curwin->w_width - curwin_col_off();
|
int width1 = curwin->w_width - curwin_col_off();
|
||||||
int width2 = width1 + curwin_col_off2();
|
int width2 = width1 + curwin_col_off2();
|
||||||
int size = 0;
|
unsigned size = 0;
|
||||||
linenr_T prev_topline = curwin->w_topline;
|
linenr_T prev_topline = curwin->w_topline;
|
||||||
|
|
||||||
if (do_sms) {
|
if (do_sms) {
|
||||||
size = (int)win_linetabsize(curwin, curwin->w_topline,
|
size = linetabsize(curwin, curwin->w_topline);
|
||||||
ml_get(curwin->w_topline), (colnr_T)MAXCOL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// diff mode: first consume "topfill"
|
// diff mode: first consume "topfill"
|
||||||
@ -1300,7 +1299,7 @@ bool scrollup(long line_count, int byfold)
|
|||||||
// the end of the line, then advance to the next line.
|
// the end of the line, then advance to the next line.
|
||||||
int add = curwin->w_skipcol > 0 ? width2 : width1;
|
int add = curwin->w_skipcol > 0 ? width2 : width1;
|
||||||
curwin->w_skipcol += add;
|
curwin->w_skipcol += add;
|
||||||
if (curwin->w_skipcol >= size) {
|
if ((unsigned)curwin->w_skipcol >= size) {
|
||||||
if (lnum == curbuf->b_ml.ml_line_count) {
|
if (lnum == curbuf->b_ml.ml_line_count) {
|
||||||
// at the last screen line, can't scroll further
|
// at the last screen line, can't scroll further
|
||||||
curwin->w_skipcol -= add;
|
curwin->w_skipcol -= add;
|
||||||
@ -1322,8 +1321,7 @@ bool scrollup(long line_count, int byfold)
|
|||||||
curwin->w_topfill = win_get_fill(curwin, lnum);
|
curwin->w_topfill = win_get_fill(curwin, lnum);
|
||||||
curwin->w_skipcol = 0;
|
curwin->w_skipcol = 0;
|
||||||
if (todo > 1 && do_sms) {
|
if (todo > 1 && do_sms) {
|
||||||
size = (int)win_linetabsize(curwin, curwin->w_topline,
|
size = linetabsize(curwin, curwin->w_topline);
|
||||||
ml_get(curwin->w_topline), (colnr_T)MAXCOL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1363,11 +1361,16 @@ bool scrollup(long line_count, int byfold)
|
|||||||
if (curwin->w_cursor.lnum == curwin->w_topline && do_sms && curwin->w_skipcol > 0) {
|
if (curwin->w_cursor.lnum == curwin->w_topline && do_sms && curwin->w_skipcol > 0) {
|
||||||
int width1 = curwin->w_width - curwin_col_off();
|
int width1 = curwin->w_width - curwin_col_off();
|
||||||
int width2 = width1 + curwin_col_off2();
|
int width2 = width1 + curwin_col_off2();
|
||||||
long so = curwin->w_p_so >= 0 ? curwin->w_p_so : p_so;
|
long so = get_scrolloff_value(curwin);
|
||||||
long scrolloff_cols = so == 0 ? 0 : width1 + (so - 1) * width2;
|
long 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
|
// Make sure the cursor is in a visible part of the line, taking
|
||||||
// 'scrolloff' into account, but using screen lines.
|
// '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();
|
validate_virtcol();
|
||||||
if (curwin->w_virtcol < curwin->w_skipcol + 3 + scrolloff_cols) {
|
if (curwin->w_virtcol < curwin->w_skipcol + 3 + scrolloff_cols) {
|
||||||
colnr_T col = curwin->w_virtcol;
|
colnr_T col = curwin->w_virtcol;
|
||||||
@ -1402,11 +1405,20 @@ void adjust_skipcol(void)
|
|||||||
|
|
||||||
int width1 = curwin->w_width - curwin_col_off();
|
int width1 = curwin->w_width - curwin_col_off();
|
||||||
int width2 = width1 + curwin_col_off2();
|
int width2 = width1 + curwin_col_off2();
|
||||||
long so = curwin->w_p_so >= 0 ? curwin->w_p_so : p_so;
|
long so = get_scrolloff_value(curwin);
|
||||||
long scrolloff_cols = so == 0 ? 0 : width1 + (so - 1) * width2;
|
long scrolloff_cols = so == 0 ? 0 : width1 + (so - 1) * width2;
|
||||||
bool scrolled = false;
|
bool scrolled = false;
|
||||||
|
|
||||||
validate_virtcol();
|
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(curwin, UPD_NOT_VALID);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
while (curwin->w_skipcol > 0
|
while (curwin->w_skipcol > 0
|
||||||
&& curwin->w_virtcol < curwin->w_skipcol + 3 + scrolloff_cols) {
|
&& curwin->w_virtcol < curwin->w_skipcol + 3 + scrolloff_cols) {
|
||||||
// scroll a screen line down
|
// scroll a screen line down
|
||||||
@ -2071,6 +2083,16 @@ void cursor_correct(void)
|
|||||||
return;
|
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(vim): 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
|
// Narrow down the area where the cursor can be put by taking lines from
|
||||||
// the top and the bottom until:
|
// the top and the bottom until:
|
||||||
// - the desired context lines are found
|
// - the desired context lines are found
|
||||||
|
@ -2432,7 +2432,7 @@ bool find_decl(char *ptr, size_t len, bool locally, bool thisblock, int flags_ar
|
|||||||
/// @return true if able to move cursor, false otherwise.
|
/// @return true if able to move cursor, false otherwise.
|
||||||
static bool nv_screengo(oparg_T *oap, int dir, long dist)
|
static bool nv_screengo(oparg_T *oap, int dir, long dist)
|
||||||
{
|
{
|
||||||
int linelen = linetabsize(get_cursor_line_ptr());
|
int linelen = linetabsize_str(get_cursor_line_ptr());
|
||||||
bool retval = true;
|
bool retval = true;
|
||||||
bool atend = false;
|
bool atend = false;
|
||||||
int col_off1; // margin offset for first screen line
|
int col_off1; // margin offset for first screen line
|
||||||
@ -2494,7 +2494,7 @@ static bool nv_screengo(oparg_T *oap, int dir, long dist)
|
|||||||
retval = false;
|
retval = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
linelen = linetabsize(get_cursor_line_ptr());
|
linelen = linetabsize_str(get_cursor_line_ptr());
|
||||||
if (linelen > width1) {
|
if (linelen > width1) {
|
||||||
int w = (((linelen - width1 - 1) / width2) + 1) * width2;
|
int w = (((linelen - width1 - 1) / width2) + 1) * width2;
|
||||||
assert(curwin->w_curswant <= INT_MAX - w);
|
assert(curwin->w_curswant <= INT_MAX - w);
|
||||||
@ -2525,7 +2525,7 @@ static bool nv_screengo(oparg_T *oap, int dir, long dist)
|
|||||||
if (curwin->w_curswant >= width1) {
|
if (curwin->w_curswant >= width1) {
|
||||||
curwin->w_curswant -= width2;
|
curwin->w_curswant -= width2;
|
||||||
}
|
}
|
||||||
linelen = linetabsize(get_cursor_line_ptr());
|
linelen = linetabsize_str(get_cursor_line_ptr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5497,7 +5497,7 @@ static void nv_g_cmd(cmdarg_T *cap)
|
|||||||
case 'M':
|
case 'M':
|
||||||
oap->motion_type = kMTCharWise;
|
oap->motion_type = kMTCharWise;
|
||||||
oap->inclusive = false;
|
oap->inclusive = false;
|
||||||
i = linetabsize(get_cursor_line_ptr());
|
i = linetabsize_str(get_cursor_line_ptr());
|
||||||
if (cap->count0 > 0 && cap->count0 <= 100) {
|
if (cap->count0 > 0 && cap->count0 <= 100) {
|
||||||
coladvance((colnr_T)(i * cap->count0 / 100));
|
coladvance((colnr_T)(i * cap->count0 / 100));
|
||||||
} else {
|
} else {
|
||||||
|
@ -5503,7 +5503,7 @@ void cursor_pos_info(dict_T *dict)
|
|||||||
validate_virtcol();
|
validate_virtcol();
|
||||||
col_print(buf1, sizeof(buf1), (int)curwin->w_cursor.col + 1,
|
col_print(buf1, sizeof(buf1), (int)curwin->w_cursor.col + 1,
|
||||||
(int)curwin->w_virtcol + 1);
|
(int)curwin->w_virtcol + 1);
|
||||||
col_print(buf2, sizeof(buf2), (int)strlen(p), linetabsize(p));
|
col_print(buf2, sizeof(buf2), (int)strlen(p), linetabsize_str(p));
|
||||||
|
|
||||||
if (char_count_cursor == byte_count_cursor
|
if (char_count_cursor == byte_count_cursor
|
||||||
&& char_count == byte_count) {
|
&& char_count == byte_count) {
|
||||||
|
@ -243,12 +243,12 @@ int win_chartabsize(win_T *wp, char *p, colnr_T col)
|
|||||||
/// @param s
|
/// @param s
|
||||||
///
|
///
|
||||||
/// @return Number of characters the string will take on the screen.
|
/// @return Number of characters the string will take on the screen.
|
||||||
int linetabsize(char *s)
|
int linetabsize_str(char *s)
|
||||||
{
|
{
|
||||||
return linetabsize_col(0, s);
|
return linetabsize_col(0, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Like linetabsize(), but "s" starts at column "startcol".
|
/// Like linetabsize_str(), but "s" starts at column "startcol".
|
||||||
///
|
///
|
||||||
/// @param startcol
|
/// @param startcol
|
||||||
/// @param s
|
/// @param s
|
||||||
@ -265,7 +265,7 @@ int linetabsize_col(int startcol, char *s)
|
|||||||
return cts.cts_vcol;
|
return cts.cts_vcol;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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.
|
||||||
///
|
///
|
||||||
/// @param wp
|
/// @param wp
|
||||||
/// @param line
|
/// @param line
|
||||||
@ -284,6 +284,13 @@ unsigned win_linetabsize(win_T *wp, linenr_T lnum, char *line, colnr_T len)
|
|||||||
return (unsigned)cts.cts_vcol;
|
return (unsigned)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.
|
||||||
|
unsigned linetabsize(win_T *wp, linenr_T lnum)
|
||||||
|
{
|
||||||
|
return win_linetabsize(wp, lnum, ml_get_buf(wp->w_buffer, lnum, false), (colnr_T)MAXCOL);
|
||||||
|
}
|
||||||
|
|
||||||
/// Prepare the structure passed to chartabsize functions.
|
/// Prepare the structure passed to chartabsize functions.
|
||||||
///
|
///
|
||||||
/// "line" is the start of the line, "ptr" is the first relevant character.
|
/// "line" is the start of the line, "ptr" is the first relevant character.
|
||||||
|
Loading…
Reference in New Issue
Block a user