diff options
-rw-r--r-- | src/nvim/cursor.c | 4 | ||||
-rw-r--r-- | src/nvim/edit.c | 4 | ||||
-rw-r--r-- | src/nvim/ex_cmds.c | 6 | ||||
-rw-r--r-- | src/nvim/move.c | 40 | ||||
-rw-r--r-- | src/nvim/normal.c | 8 | ||||
-rw-r--r-- | src/nvim/ops.c | 2 | ||||
-rw-r--r-- | src/nvim/plines.c | 13 |
7 files changed, 52 insertions, 25 deletions
diff --git a/src/nvim/cursor.c b/src/nvim/cursor.c index 6d90b32545..cdadc89e31 100644 --- a/src/nvim/cursor.c +++ b/src/nvim/cursor.c @@ -115,7 +115,7 @@ static int coladvance2(pos_T *pos, bool addspaces, bool finetune, colnr_T wcol_a col = wcol; 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--; } @@ -129,7 +129,7 @@ static int coladvance2(pos_T *pos, bool addspaces, bool finetune, colnr_T wcol_a && curwin->w_width_inner != 0 && wcol >= (colnr_T)width && width > 0) { - csize = linetabsize(line); + csize = linetabsize_str(line); if (csize > 0) { csize--; } diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 18434ad69f..2078fc4251 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -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; if (!did_ai) { @@ -2251,7 +2251,7 @@ int stop_arrow(void) // right, except when nothing was inserted yet. 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) { arrow_used = false; diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index f276e8ae24..2c31f742c3 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -346,10 +346,8 @@ static int linelen(int *has_tab) last > first && ascii_iswhite(last[-1]); last--) {} char save = *last; *last = NUL; - // Get line length. - len = linetabsize(line); - // Check for embedded TAB. - if (has_tab != NULL) { + len = linetabsize_str(line); // Get line length. + if (has_tab != NULL) { // Check for embedded TAB. *has_tab = vim_strchr(first, TAB) != NULL; } *last = save; diff --git a/src/nvim/move.c b/src/nvim/move.c index a5383202a3..c080cf6691 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -1238,7 +1238,7 @@ bool scrolldown(long line_count, int byfold) } 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; // 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)) { int width1 = curwin->w_width - curwin_col_off(); int width2 = width1 + curwin_col_off2(); - int size = 0; + unsigned size = 0; linenr_T prev_topline = curwin->w_topline; if (do_sms) { - size = (int)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" @@ -1300,7 +1299,7 @@ bool scrollup(long line_count, int byfold) // the end of the line, then advance to the next line. int add = curwin->w_skipcol > 0 ? width2 : width1; curwin->w_skipcol += add; - if (curwin->w_skipcol >= size) { + if ((unsigned)curwin->w_skipcol >= size) { if (lnum == curbuf->b_ml.ml_line_count) { // at the last screen line, can't scroll further 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_skipcol = 0; if (todo > 1 && do_sms) { - size = (int)win_linetabsize(curwin, curwin->w_topline, - ml_get(curwin->w_topline), (colnr_T)MAXCOL); + size = linetabsize(curwin, curwin->w_topline); } } } @@ -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) { 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(curwin); 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 // '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) { colnr_T col = curwin->w_virtcol; @@ -1402,11 +1405,20 @@ void 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(curwin); long scrolloff_cols = so == 0 ? 0 : width1 + (so - 1) * width2; bool 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(curwin, UPD_NOT_VALID); + } + return; + } + while (curwin->w_skipcol > 0 && curwin->w_virtcol < curwin->w_skipcol + 3 + scrolloff_cols) { // scroll a screen line down @@ -2071,6 +2083,16 @@ void 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(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 // the top and the bottom until: // - the desired context lines are found diff --git a/src/nvim/normal.c b/src/nvim/normal.c index d4759aeaba..9792f5950e 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -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. 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 atend = false; 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; break; } - linelen = linetabsize(get_cursor_line_ptr()); + linelen = linetabsize_str(get_cursor_line_ptr()); if (linelen > width1) { int w = (((linelen - width1 - 1) / width2) + 1) * width2; 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) { 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': oap->motion_type = kMTCharWise; oap->inclusive = false; - i = linetabsize(get_cursor_line_ptr()); + i = linetabsize_str(get_cursor_line_ptr()); if (cap->count0 > 0 && cap->count0 <= 100) { coladvance((colnr_T)(i * cap->count0 / 100)); } else { diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 89fe9b464d..d8380303a3 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -5503,7 +5503,7 @@ void cursor_pos_info(dict_T *dict) validate_virtcol(); 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)); + col_print(buf2, sizeof(buf2), (int)strlen(p), linetabsize_str(p)); if (char_count_cursor == byte_count_cursor && char_count == byte_count) { diff --git a/src/nvim/plines.c b/src/nvim/plines.c index b2a4ac710d..3c8ee7d66d 100644 --- a/src/nvim/plines.c +++ b/src/nvim/plines.c @@ -243,12 +243,12 @@ int win_chartabsize(win_T *wp, char *p, colnr_T col) /// @param s /// /// @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); } -/// Like linetabsize(), but "s" starts at column "startcol". +/// Like linetabsize_str(), but "s" starts at column "startcol". /// /// @param startcol /// @param s @@ -265,7 +265,7 @@ int linetabsize_col(int startcol, char *s) 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 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 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. /// /// "line" is the start of the line, "ptr" is the first relevant character. |