aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/move.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/move.c')
-rw-r--r--src/nvim/move.c189
1 files changed, 108 insertions, 81 deletions
diff --git a/src/nvim/move.c b/src/nvim/move.c
index 9b7755a828..3af26b910e 100644
--- a/src/nvim/move.c
+++ b/src/nvim/move.c
@@ -11,8 +11,9 @@
// The 'scrolloff' option makes this a bit complicated.
#include <assert.h>
-#include <inttypes.h>
+#include <limits.h>
#include <stdbool.h>
+#include <stddef.h>
#include "nvim/ascii.h"
#include "nvim/buffer.h"
@@ -21,21 +22,30 @@
#include "nvim/diff.h"
#include "nvim/drawscreen.h"
#include "nvim/edit.h"
-#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
+#include "nvim/eval/window.h"
#include "nvim/fold.h"
#include "nvim/getchar.h"
+#include "nvim/gettext.h"
+#include "nvim/globals.h"
#include "nvim/grid.h"
#include "nvim/highlight.h"
+#include "nvim/macros.h"
#include "nvim/mbyte.h"
-#include "nvim/memline.h"
+#include "nvim/memline_defs.h"
+#include "nvim/message.h"
#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/option.h"
#include "nvim/plines.h"
#include "nvim/popupmenu.h"
+#include "nvim/pos.h"
+#include "nvim/screen.h"
#include "nvim/search.h"
#include "nvim/strings.h"
+#include "nvim/types.h"
+#include "nvim/vim.h"
#include "nvim/window.h"
typedef struct {
@@ -150,7 +160,6 @@ void update_topline(win_T *wp)
if (!default_grid.chars || wp->w_height_inner == 0) {
wp->w_topline = wp->w_cursor.lnum;
wp->w_botline = wp->w_topline;
- wp->w_valid |= VALID_BOTLINE|VALID_BOTLINE_AP;
wp->w_viewport_invalid = true;
wp->w_scbind_pos = 1;
return;
@@ -333,15 +342,6 @@ void update_topline(win_T *wp)
*so_ptr = save_so;
}
-// Update win->w_topline to move the cursor onto the screen.
-void update_topline_win(win_T *win)
-{
- switchwin_T switchwin;
- switch_win(&switchwin, win, NULL, true);
- update_topline(curwin);
- restore_win(&switchwin, true);
-}
-
// Return the scrolljump value to use for the current window.
// When 'scrolljump' is positive use it as-is.
// When 'scrolljump' is negative use it as a percentage of the window height.
@@ -381,12 +381,19 @@ static bool check_top_offset(void)
return false;
}
+/// Update w_curswant.
+void update_curswant_force(void)
+{
+ validate_virtcol();
+ curwin->w_curswant = curwin->w_virtcol;
+ curwin->w_set_curswant = false;
+}
+
+/// Update w_curswant if w_set_curswant is set.
void update_curswant(void)
{
if (curwin->w_set_curswant) {
- validate_virtcol();
- curwin->w_curswant = curwin->w_virtcol;
- curwin->w_set_curswant = false;
+ update_curswant_force();
}
}
@@ -601,57 +608,67 @@ void validate_virtcol(void)
void validate_virtcol_win(win_T *wp)
{
check_cursor_moved(wp);
- if (!(wp->w_valid & VALID_VIRTCOL)) {
- getvvcol(wp, &wp->w_cursor, NULL, &(wp->w_virtcol), NULL);
- redraw_for_cursorcolumn(wp);
- wp->w_valid |= VALID_VIRTCOL;
+
+ if (wp->w_valid & VALID_VIRTCOL) {
+ return;
}
+
+ getvvcol(wp, &wp->w_cursor, NULL, &(wp->w_virtcol), NULL);
+ redraw_for_cursorcolumn(wp);
+ wp->w_valid |= VALID_VIRTCOL;
}
// Validate curwin->w_cline_height only.
void validate_cheight(void)
{
check_cursor_moved(curwin);
- if (!(curwin->w_valid & VALID_CHEIGHT)) {
- curwin->w_cline_height = plines_win_full(curwin, curwin->w_cursor.lnum,
- NULL, &curwin->w_cline_folded,
- true);
- curwin->w_valid |= VALID_CHEIGHT;
+
+ if (curwin->w_valid & VALID_CHEIGHT) {
+ return;
}
+
+ curwin->w_cline_height = plines_win_full(curwin, curwin->w_cursor.lnum,
+ NULL, &curwin->w_cline_folded,
+ true);
+ curwin->w_valid |= VALID_CHEIGHT;
}
// Validate w_wcol and w_virtcol only.
void validate_cursor_col(void)
{
validate_virtcol();
- if (!(curwin->w_valid & VALID_WCOL)) {
- colnr_T col = curwin->w_virtcol;
- colnr_T off = curwin_col_off();
- col += off;
- int width = curwin->w_width_inner - off + curwin_col_off2();
-
- // long line wrapping, adjust curwin->w_wrow
- if (curwin->w_p_wrap && col >= (colnr_T)curwin->w_width_inner
- && width > 0) {
- // use same formula as what is used in curs_columns()
- col -= ((col - curwin->w_width_inner) / width + 1) * width;
- }
- if (col > (int)curwin->w_leftcol) {
- col -= curwin->w_leftcol;
- } else {
- col = 0;
- }
- curwin->w_wcol = col;
- curwin->w_valid |= VALID_WCOL;
+ if (curwin->w_valid & VALID_WCOL) {
+ return;
}
+
+ colnr_T col = curwin->w_virtcol;
+ colnr_T off = curwin_col_off();
+ col += off;
+ int width = curwin->w_width_inner - off + curwin_col_off2();
+
+ // long line wrapping, adjust curwin->w_wrow
+ if (curwin->w_p_wrap && col >= (colnr_T)curwin->w_width_inner
+ && width > 0) {
+ // use same formula as what is used in curs_columns()
+ col -= ((col - curwin->w_width_inner) / width + 1) * width;
+ }
+ if (col > (int)curwin->w_leftcol) {
+ col -= curwin->w_leftcol;
+ } else {
+ col = 0;
+ }
+ curwin->w_wcol = col;
+
+ curwin->w_valid |= VALID_WCOL;
}
// Compute offset of a window, occupied by absolute or relative line number,
// fold column and sign column (these don't move when scrolling horizontally).
int win_col_off(win_T *wp)
{
- return ((wp->w_p_nu || wp->w_p_rnu) ? number_width(wp) + 1 : 0)
+ return ((wp->w_p_nu || wp->w_p_rnu || (*wp->w_p_stc != NUL)) ?
+ (number_width(wp) + (*wp->w_p_stc == NUL)) : 0)
+ (cmdwin_type == 0 || wp != curwin ? 0 : 1)
+ win_fdccol_count(wp)
+ (win_signcol_count(wp) * win_signcol_width(wp));
@@ -743,7 +760,7 @@ void curs_columns(win_T *wp, int may_scroll)
// When cursor wraps to first char of next line in Insert
// mode, the 'showbreak' string isn't shown, backup to first
// column
- char *const sbr = (char *)get_showbreak_value(wp);
+ char *const sbr = get_showbreak_value(wp);
if (*sbr && *get_cursor_pos_ptr() == NUL
&& wp->w_wcol == vim_strsize(sbr)) {
wp->w_wcol = 0;
@@ -813,8 +830,7 @@ void curs_columns(win_T *wp, int may_scroll)
if ((wp->w_wrow >= wp->w_height_inner
|| ((prev_skipcol > 0
|| wp->w_wrow + so >= wp->w_height_inner)
- && (plines =
- plines_win_nofill(wp, wp->w_cursor.lnum, false)) - 1
+ && (plines = plines_win_nofill(wp, wp->w_cursor.lnum, false)) - 1
>= wp->w_height_inner))
&& wp->w_height_inner != 0
&& wp->w_cursor.lnum == wp->w_topline
@@ -922,11 +938,16 @@ void textpos2screenpos(win_T *wp, pos_T *pos, int *rowp, int *scolp, int *ccolp,
int rowoff = 0;
colnr_T coloff = 0;
bool visible_row = false;
-
- if (pos->lnum >= wp->w_topline && pos->lnum < wp->w_botline) {
- row = plines_m_win(wp, wp->w_topline, pos->lnum - 1) + 1;
+ bool is_folded = false;
+
+ if (pos->lnum >= wp->w_topline && pos->lnum <= wp->w_botline) {
+ linenr_T lnum = pos->lnum;
+ is_folded = hasFoldingWin(wp, lnum, &lnum, NULL, true, NULL);
+ row = plines_m_win(wp, wp->w_topline, lnum - 1) + 1;
+ // Add filler lines above this buffer line.
+ row += win_get_fill(wp, lnum);
visible_row = true;
- } else if (pos->lnum < wp->w_topline) {
+ } else if (!local || pos->lnum < wp->w_topline) {
row = 0;
} else {
row = wp->w_height_inner;
@@ -935,41 +956,43 @@ void textpos2screenpos(win_T *wp, pos_T *pos, int *rowp, int *scolp, int *ccolp,
bool existing_row = (pos->lnum > 0
&& pos->lnum <= wp->w_buffer->b_ml.ml_line_count);
- if ((local && existing_row) || visible_row) {
- colnr_T off;
- colnr_T col;
- int width;
-
- getvcol(wp, pos, &scol, &ccol, &ecol);
-
- // similar to what is done in validate_cursor_col()
- col = scol;
- off = win_col_off(wp);
- col += off;
- width = wp->w_width - off + win_col_off2(wp);
-
- // 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 = visible_row ? ((col - wp->w_width) / width + 1) : 0;
- col -= rowoff * width;
- }
+ if ((local || visible_row) && existing_row) {
+ const colnr_T off = win_col_off(wp);
+ if (is_folded) {
+ row += local ? 0 : wp->w_winrow + wp->w_winrow_off;
+ coloff = (local ? 0 : wp->w_wincol + wp->w_wincol_off) + 1 + off;
+ } else {
+ getvcol(wp, pos, &scol, &ccol, &ecol);
+
+ // similar to what is done in validate_cursor_col()
+ colnr_T col = scol;
+ col += off;
+ int width = wp->w_width - off + win_col_off2(wp);
+
+ // 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 = visible_row ? ((col - wp->w_width) / width + 1) : 0;
+ col -= rowoff * width;
+ }
- col -= wp->w_leftcol;
+ col -= wp->w_leftcol;
- if (col >= 0 && col < wp->w_width) {
- coloff = col - scol + (local ? 0 : wp->w_wincol + wp->w_wincol_off) + 1;
- } else {
- scol = ccol = ecol = 0;
- // character is left or right of the window
- if (local) {
- coloff = col < 0 ? -1 : wp->w_width_inner + 1;
+ if (col >= 0 && col < wp->w_width && row + rowoff <= wp->w_height) {
+ coloff = col - scol + (local ? 0 : wp->w_wincol + wp->w_wincol_off) + 1;
+ row += local ? 0 : wp->w_winrow + wp->w_winrow_off;
} else {
- row = 0;
+ // character is left, right or below of the window
+ scol = ccol = ecol = 0;
+ if (local) {
+ coloff = col < 0 ? -1 : wp->w_width_inner + 1;
+ } else {
+ row = rowoff = 0;
+ }
}
}
}
- *rowp = (local ? 0 : wp->w_winrow + wp->w_winrow_off) + row + rowoff;
+ *rowp = row + rowoff;
*scolp = scol + coloff;
*ccolp = ccol + coloff;
*ecolp = ecol + coloff;
@@ -991,6 +1014,10 @@ void f_screenpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
.col = (colnr_T)tv_get_number(&argvars[2]) - 1,
.coladd = 0
};
+ if (pos.lnum > wp->w_buffer->b_ml.ml_line_count) {
+ semsg(_(e_invalid_line_number_nr), pos.lnum);
+ return;
+ }
int row = 0;
int scol = 0, ccol = 0, ecol = 0;
textpos2screenpos(wp, &pos, &row, &scol, &ccol, &ecol, false);