mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge pull request #15336 from bfredl/plines
refactor(plines): move "plines" (size of printed lines) family of function to own file
This commit is contained in:
commit
7d2233fad0
@ -2301,7 +2301,7 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ParserLine plines[] = {
|
ParserLine parser_lines[] = {
|
||||||
{
|
{
|
||||||
.data = expr.data,
|
.data = expr.data,
|
||||||
.size = expr.size,
|
.size = expr.size,
|
||||||
@ -2309,7 +2309,7 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight,
|
|||||||
},
|
},
|
||||||
{ NULL, 0, false },
|
{ NULL, 0, false },
|
||||||
};
|
};
|
||||||
ParserLine *plines_p = plines;
|
ParserLine *plines_p = parser_lines;
|
||||||
ParserHighlight colors;
|
ParserHighlight colors;
|
||||||
kvi_init(colors);
|
kvi_init(colors);
|
||||||
ParserHighlight *const colors_p = (highlight ? &colors : NULL);
|
ParserHighlight *const colors_p = (highlight ? &colors : NULL);
|
||||||
@ -2335,7 +2335,7 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight,
|
|||||||
ret.items[ret.size++] = (KeyValuePair) {
|
ret.items[ret.size++] = (KeyValuePair) {
|
||||||
.key = STATIC_CSTR_TO_STRING("len"),
|
.key = STATIC_CSTR_TO_STRING("len"),
|
||||||
.value = INTEGER_OBJ((Integer)(pstate.pos.line == 1
|
.value = INTEGER_OBJ((Integer)(pstate.pos.line == 1
|
||||||
? plines[0].size
|
? parser_lines[0].size
|
||||||
: pstate.pos.col)),
|
: pstate.pos.col)),
|
||||||
};
|
};
|
||||||
if (east.err.msg != NULL) {
|
if (east.err.msg != NULL) {
|
||||||
|
@ -1298,7 +1298,7 @@ struct window_S {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* w_cline_height is the number of physical lines taken by the buffer line
|
* w_cline_height is the number of physical lines taken by the buffer line
|
||||||
* that the cursor is on. We use this to avoid extra calls to plines().
|
* that the cursor is on. We use this to avoid extra calls to plines_win().
|
||||||
*/
|
*/
|
||||||
int w_cline_height; // current size of cursor line
|
int w_cline_height; // current size of cursor line
|
||||||
bool w_cline_folded; // cursor line is folded
|
bool w_cline_folded; // cursor line is folded
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "nvim/misc1.h"
|
#include "nvim/misc1.h"
|
||||||
#include "nvim/move.h"
|
#include "nvim/move.h"
|
||||||
#include "nvim/option.h"
|
#include "nvim/option.h"
|
||||||
|
#include "nvim/plines.h"
|
||||||
#include "nvim/screen.h"
|
#include "nvim/screen.h"
|
||||||
#include "nvim/search.h"
|
#include "nvim/search.h"
|
||||||
#include "nvim/state.h"
|
#include "nvim/state.h"
|
||||||
@ -593,9 +594,9 @@ void ins_char_bytes(char_u *buf, size_t charlen)
|
|||||||
// cells. May result in adding spaces to fill a gap.
|
// cells. May result in adding spaces to fill a gap.
|
||||||
colnr_T vcol;
|
colnr_T vcol;
|
||||||
getvcol(curwin, &curwin->w_cursor, NULL, &vcol, NULL);
|
getvcol(curwin, &curwin->w_cursor, NULL, &vcol, NULL);
|
||||||
colnr_T new_vcol = vcol + chartabsize(buf, vcol);
|
colnr_T new_vcol = vcol + win_chartabsize(curwin, buf, vcol);
|
||||||
while (oldp[col + oldlen] != NUL && vcol < new_vcol) {
|
while (oldp[col + oldlen] != NUL && vcol < new_vcol) {
|
||||||
vcol += chartabsize(oldp + col + oldlen, vcol);
|
vcol += win_chartabsize(curwin, oldp + col + oldlen, vcol);
|
||||||
// Don't need to remove a TAB that takes us to the right
|
// Don't need to remove a TAB that takes us to the right
|
||||||
// position.
|
// position.
|
||||||
if (vcol > new_vcol && oldp[col + oldlen] == TAB) {
|
if (vcol > new_vcol && oldp[col + oldlen] == TAB) {
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "nvim/move.h"
|
#include "nvim/move.h"
|
||||||
#include "nvim/option.h"
|
#include "nvim/option.h"
|
||||||
#include "nvim/os_unix.h"
|
#include "nvim/os_unix.h"
|
||||||
|
#include "nvim/plines.h"
|
||||||
#include "nvim/state.h"
|
#include "nvim/state.h"
|
||||||
#include "nvim/strings.h"
|
#include "nvim/strings.h"
|
||||||
#include "nvim/path.h"
|
#include "nvim/path.h"
|
||||||
@ -733,80 +734,6 @@ int vim_strnsize(char_u *s, int len)
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the number of characters 'c' will take on the screen, taking
|
|
||||||
/// into account the size of a tab.
|
|
||||||
/// Use a define to make it fast, this is used very often!!!
|
|
||||||
/// Also see getvcol() below.
|
|
||||||
///
|
|
||||||
/// @param p
|
|
||||||
/// @param col
|
|
||||||
///
|
|
||||||
/// @return Number of characters.
|
|
||||||
#define RET_WIN_BUF_CHARTABSIZE(wp, buf, p, col) \
|
|
||||||
if (*(p) == TAB && (!(wp)->w_p_list || wp->w_p_lcs_chars.tab1)) { \
|
|
||||||
return tabstop_padding(col, (buf)->b_p_ts, (buf)->b_p_vts_array); \
|
|
||||||
} else { \
|
|
||||||
return ptr2cells(p); \
|
|
||||||
}
|
|
||||||
|
|
||||||
int chartabsize(char_u *p, colnr_T col)
|
|
||||||
{
|
|
||||||
RET_WIN_BUF_CHARTABSIZE(curwin, curbuf, p, col)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int win_chartabsize(win_T *wp, char_u *p, colnr_T col)
|
|
||||||
{
|
|
||||||
RET_WIN_BUF_CHARTABSIZE(wp, wp->w_buffer, p, col)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the number of characters the string 's' will take on the screen,
|
|
||||||
/// taking into account the size of a tab.
|
|
||||||
///
|
|
||||||
/// @param s
|
|
||||||
///
|
|
||||||
/// @return Number of characters the string will take on the screen.
|
|
||||||
int linetabsize(char_u *s)
|
|
||||||
{
|
|
||||||
return linetabsize_col(0, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Like linetabsize(), but starting at column "startcol".
|
|
||||||
///
|
|
||||||
/// @param startcol
|
|
||||||
/// @param s
|
|
||||||
///
|
|
||||||
/// @return Number of characters the string will take on the screen.
|
|
||||||
int linetabsize_col(int startcol, char_u *s)
|
|
||||||
{
|
|
||||||
colnr_T col = startcol;
|
|
||||||
char_u *line = s; /* pointer to start of line, for breakindent */
|
|
||||||
|
|
||||||
while (*s != NUL) {
|
|
||||||
col += lbr_chartabsize_adv(line, &s, col);
|
|
||||||
}
|
|
||||||
return (int)col;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Like linetabsize(), but for a given window instead of the current one.
|
|
||||||
///
|
|
||||||
/// @param wp
|
|
||||||
/// @param line
|
|
||||||
/// @param len
|
|
||||||
///
|
|
||||||
/// @return Number of characters the string will take on the screen.
|
|
||||||
unsigned int win_linetabsize(win_T *wp, char_u *line, colnr_T len)
|
|
||||||
{
|
|
||||||
colnr_T col = 0;
|
|
||||||
|
|
||||||
for (char_u *s = line;
|
|
||||||
*s != NUL && (len == MAXCOL || s < line + len);
|
|
||||||
MB_PTR_ADV(s)) {
|
|
||||||
col += win_lbr_chartabsize(wp, line, s, col, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (unsigned int)col;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check that "c" is a normal identifier character:
|
/// Check that "c" is a normal identifier character:
|
||||||
/// Letters and characters from the 'isident' option.
|
/// Letters and characters from the 'isident' option.
|
||||||
///
|
///
|
||||||
@ -936,229 +863,6 @@ bool vim_isprintc_strict(int c)
|
|||||||
return c > 0 && (g_chartab[c] & CT_PRINT_CHAR);
|
return c > 0 && (g_chartab[c] & CT_PRINT_CHAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// like chartabsize(), but also check for line breaks on the screen
|
|
||||||
///
|
|
||||||
/// @param line
|
|
||||||
/// @param s
|
|
||||||
/// @param col
|
|
||||||
///
|
|
||||||
/// @return The number of characters taken up on the screen.
|
|
||||||
int lbr_chartabsize(char_u *line, unsigned char *s, colnr_T col)
|
|
||||||
{
|
|
||||||
if (!curwin->w_p_lbr && (*p_sbr == NUL) && !curwin->w_p_bri) {
|
|
||||||
if (curwin->w_p_wrap) {
|
|
||||||
return win_nolbr_chartabsize(curwin, s, col, NULL);
|
|
||||||
}
|
|
||||||
RET_WIN_BUF_CHARTABSIZE(curwin, curbuf, s, col)
|
|
||||||
}
|
|
||||||
return win_lbr_chartabsize(curwin, line == NULL ? s: line, s, col, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Call lbr_chartabsize() and advance the pointer.
|
|
||||||
///
|
|
||||||
/// @param line
|
|
||||||
/// @param s
|
|
||||||
/// @param col
|
|
||||||
///
|
|
||||||
/// @return The number of characters take up on the screen.
|
|
||||||
int lbr_chartabsize_adv(char_u *line, char_u **s, colnr_T col)
|
|
||||||
{
|
|
||||||
int retval;
|
|
||||||
|
|
||||||
retval = lbr_chartabsize(line, *s, col);
|
|
||||||
MB_PTR_ADV(*s);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This function is used very often, keep it fast!!!!
|
|
||||||
///
|
|
||||||
/// If "headp" not NULL, set *headp to the size of what we for 'showbreak'
|
|
||||||
/// string at start of line. Warning: *headp is only set if it's a non-zero
|
|
||||||
/// value, init to 0 before calling.
|
|
||||||
///
|
|
||||||
/// @param wp
|
|
||||||
/// @param line
|
|
||||||
/// @param s
|
|
||||||
/// @param col
|
|
||||||
/// @param headp
|
|
||||||
///
|
|
||||||
/// @return The number of characters taken up on the screen.
|
|
||||||
int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *headp)
|
|
||||||
{
|
|
||||||
colnr_T col2;
|
|
||||||
colnr_T col_adj = 0; /* col + screen size of tab */
|
|
||||||
colnr_T colmax;
|
|
||||||
int added;
|
|
||||||
int mb_added = 0;
|
|
||||||
int numberextra;
|
|
||||||
char_u *ps;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
// No 'linebreak', 'showbreak' and 'breakindent': return quickly.
|
|
||||||
if (!wp->w_p_lbr && !wp->w_p_bri && (*p_sbr == NUL)) {
|
|
||||||
if (wp->w_p_wrap) {
|
|
||||||
return win_nolbr_chartabsize(wp, s, col, headp);
|
|
||||||
}
|
|
||||||
RET_WIN_BUF_CHARTABSIZE(wp, wp->w_buffer, s, col)
|
|
||||||
}
|
|
||||||
|
|
||||||
// First get normal size, without 'linebreak'
|
|
||||||
int size = win_chartabsize(wp, s, col);
|
|
||||||
int c = *s;
|
|
||||||
if (*s == TAB) {
|
|
||||||
col_adj = size - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If 'linebreak' set check at a blank before a non-blank if the line
|
|
||||||
// needs a break here
|
|
||||||
if (wp->w_p_lbr
|
|
||||||
&& vim_isbreak(c)
|
|
||||||
&& !vim_isbreak((int)s[1])
|
|
||||||
&& wp->w_p_wrap
|
|
||||||
&& (wp->w_width_inner != 0)) {
|
|
||||||
// Count all characters from first non-blank after a blank up to next
|
|
||||||
// non-blank after a blank.
|
|
||||||
numberextra = win_col_off(wp);
|
|
||||||
col2 = col;
|
|
||||||
colmax = (colnr_T)(wp->w_width_inner - numberextra - col_adj);
|
|
||||||
|
|
||||||
if (col >= colmax) {
|
|
||||||
colmax += col_adj;
|
|
||||||
n = colmax + win_col_off2(wp);
|
|
||||||
|
|
||||||
if (n > 0) {
|
|
||||||
colmax += (((col - colmax) / n) + 1) * n - col_adj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
ps = s;
|
|
||||||
MB_PTR_ADV(s);
|
|
||||||
c = *s;
|
|
||||||
|
|
||||||
if (!(c != NUL
|
|
||||||
&& (vim_isbreak(c) || col2 == col || !vim_isbreak((int)(*ps))))) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
col2 += win_chartabsize(wp, s, col2);
|
|
||||||
|
|
||||||
if (col2 >= colmax) { /* doesn't fit */
|
|
||||||
size = colmax - col + col_adj;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ((size == 2)
|
|
||||||
&& (MB_BYTE2LEN(*s) > 1)
|
|
||||||
&& wp->w_p_wrap
|
|
||||||
&& in_win_border(wp, col)) {
|
|
||||||
// Count the ">" in the last column.
|
|
||||||
++size;
|
|
||||||
mb_added = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// May have to add something for 'breakindent' and/or 'showbreak'
|
|
||||||
// string at start of line.
|
|
||||||
// Set *headp to the size of what we add.
|
|
||||||
added = 0;
|
|
||||||
|
|
||||||
if ((*p_sbr != NUL || wp->w_p_bri) && wp->w_p_wrap && (col != 0)) {
|
|
||||||
colnr_T sbrlen = 0;
|
|
||||||
int numberwidth = win_col_off(wp);
|
|
||||||
|
|
||||||
numberextra = numberwidth;
|
|
||||||
col += numberextra + mb_added;
|
|
||||||
|
|
||||||
if (col >= (colnr_T)wp->w_width_inner) {
|
|
||||||
col -= wp->w_width_inner;
|
|
||||||
numberextra = wp->w_width_inner - (numberextra - win_col_off2(wp));
|
|
||||||
if (col >= numberextra && numberextra > 0) {
|
|
||||||
col %= numberextra;
|
|
||||||
}
|
|
||||||
if (*p_sbr != NUL) {
|
|
||||||
sbrlen = (colnr_T)MB_CHARLEN(p_sbr);
|
|
||||||
if (col >= sbrlen) {
|
|
||||||
col -= sbrlen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (col >= numberextra && numberextra > 0) {
|
|
||||||
col %= numberextra;
|
|
||||||
} else if (col > 0 && numberextra > 0) {
|
|
||||||
col += numberwidth - win_col_off2(wp);
|
|
||||||
}
|
|
||||||
|
|
||||||
numberwidth -= win_col_off2(wp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (col == 0 || (col + size + sbrlen > (colnr_T)wp->w_width_inner)) {
|
|
||||||
if (*p_sbr != NUL) {
|
|
||||||
if (size + sbrlen + numberwidth > (colnr_T)wp->w_width_inner) {
|
|
||||||
// Calculate effective window width.
|
|
||||||
int width = (colnr_T)wp->w_width_inner - sbrlen - numberwidth;
|
|
||||||
int prev_width = col ? ((colnr_T)wp->w_width_inner - (sbrlen + col))
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
if (width <= 0) {
|
|
||||||
width = 1;
|
|
||||||
}
|
|
||||||
added += ((size - prev_width) / width) * vim_strsize(p_sbr);
|
|
||||||
if ((size - prev_width) % width) {
|
|
||||||
// Wrapped, add another length of 'sbr'.
|
|
||||||
added += vim_strsize(p_sbr);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
added += vim_strsize(p_sbr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wp->w_p_bri)
|
|
||||||
added += get_breakindent_win(wp, line);
|
|
||||||
|
|
||||||
size += added;
|
|
||||||
if (col != 0) {
|
|
||||||
added = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headp != NULL) {
|
|
||||||
*headp = added + mb_added;
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Like win_lbr_chartabsize(), except that we know 'linebreak' is off and
|
|
||||||
/// 'wrap' is on. This means we need to check for a double-byte character that
|
|
||||||
/// doesn't fit at the end of the screen line.
|
|
||||||
///
|
|
||||||
/// @param wp
|
|
||||||
/// @param s
|
|
||||||
/// @param col
|
|
||||||
/// @param headp
|
|
||||||
///
|
|
||||||
/// @return The number of characters take up on the screen.
|
|
||||||
static int win_nolbr_chartabsize(win_T *wp, char_u *s, colnr_T col, int *headp)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
|
|
||||||
if ((*s == TAB) && (!wp->w_p_list || wp->w_p_lcs_chars.tab1)) {
|
|
||||||
return tabstop_padding(col,
|
|
||||||
wp->w_buffer->b_p_ts,
|
|
||||||
wp->w_buffer->b_p_vts_array);
|
|
||||||
}
|
|
||||||
n = ptr2cells(s);
|
|
||||||
|
|
||||||
// Add one cell for a double-width character in the last column of the
|
|
||||||
// window, displayed with a ">".
|
|
||||||
if ((n == 2) && (MB_BYTE2LEN(*s) > 1) && in_win_border(wp, col)) {
|
|
||||||
if (headp != NULL) {
|
|
||||||
*headp = 1;
|
|
||||||
}
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check that virtual column "vcol" is in the rightmost column of window "wp".
|
/// Check that virtual column "vcol" is in the rightmost column of window "wp".
|
||||||
///
|
///
|
||||||
/// @param wp window
|
/// @param wp window
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "nvim/memory.h"
|
#include "nvim/memory.h"
|
||||||
#include "nvim/misc1.h"
|
#include "nvim/misc1.h"
|
||||||
#include "nvim/move.h"
|
#include "nvim/move.h"
|
||||||
|
#include "nvim/plines.h"
|
||||||
#include "nvim/screen.h"
|
#include "nvim/screen.h"
|
||||||
#include "nvim/extmark.h"
|
#include "nvim/extmark.h"
|
||||||
#include "nvim/state.h"
|
#include "nvim/state.h"
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#include "nvim/option.h"
|
#include "nvim/option.h"
|
||||||
#include "nvim/path.h"
|
#include "nvim/path.h"
|
||||||
#include "nvim/popupmnu.h"
|
#include "nvim/popupmnu.h"
|
||||||
|
#include "nvim/plines.h"
|
||||||
#include "nvim/quickfix.h"
|
#include "nvim/quickfix.h"
|
||||||
#include "nvim/regexp.h"
|
#include "nvim/regexp.h"
|
||||||
#include "nvim/screen.h"
|
#include "nvim/screen.h"
|
||||||
@ -7187,7 +7188,7 @@ static void replace_do_bs(int limit_col)
|
|||||||
// Get the number of screen cells used by the character we are
|
// Get the number of screen cells used by the character we are
|
||||||
// going to delete.
|
// going to delete.
|
||||||
getvcol(curwin, &curwin->w_cursor, NULL, &start_vcol, NULL);
|
getvcol(curwin, &curwin->w_cursor, NULL, &start_vcol, NULL);
|
||||||
orig_vcols = chartabsize(get_cursor_pos_ptr(), start_vcol);
|
orig_vcols = win_chartabsize(curwin, get_cursor_pos_ptr(), start_vcol);
|
||||||
}
|
}
|
||||||
(void)del_char_after_col(limit_col);
|
(void)del_char_after_col(limit_col);
|
||||||
if (l_State & VREPLACE_FLAG) {
|
if (l_State & VREPLACE_FLAG) {
|
||||||
@ -7201,8 +7202,8 @@ static void replace_do_bs(int limit_col)
|
|||||||
p = get_cursor_pos_ptr();
|
p = get_cursor_pos_ptr();
|
||||||
ins_len = (int)STRLEN(p) - orig_len;
|
ins_len = (int)STRLEN(p) - orig_len;
|
||||||
vcol = start_vcol;
|
vcol = start_vcol;
|
||||||
for (i = 0; i < ins_len; ++i) {
|
for (i = 0; i < ins_len; i++) {
|
||||||
vcol += chartabsize(p + i, vcol);
|
vcol += win_chartabsize(curwin, p + i, vcol);
|
||||||
i += (*mb_ptr2len)(p) - 1;
|
i += (*mb_ptr2len)(p) - 1;
|
||||||
}
|
}
|
||||||
vcol -= start_vcol;
|
vcol -= start_vcol;
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
#include "nvim/os/input.h"
|
#include "nvim/os/input.h"
|
||||||
#include "nvim/os/shell.h"
|
#include "nvim/os/shell.h"
|
||||||
#include "nvim/path.h"
|
#include "nvim/path.h"
|
||||||
|
#include "nvim/plines.h"
|
||||||
#include "nvim/popupmnu.h"
|
#include "nvim/popupmnu.h"
|
||||||
#include "nvim/quickfix.h"
|
#include "nvim/quickfix.h"
|
||||||
#include "nvim/regexp.h"
|
#include "nvim/regexp.h"
|
||||||
@ -1055,8 +1056,10 @@ static void f_col(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
if (virtual_active() && fp == &curwin->w_cursor) {
|
if (virtual_active() && fp == &curwin->w_cursor) {
|
||||||
char_u *p = get_cursor_pos_ptr();
|
char_u *p = get_cursor_pos_ptr();
|
||||||
|
|
||||||
if (curwin->w_cursor.coladd >= (colnr_T)chartabsize(p,
|
if (curwin->w_cursor.coladd
|
||||||
curwin->w_virtcol - curwin->w_cursor.coladd)) {
|
>= (colnr_T)win_chartabsize(curwin, p,
|
||||||
|
(curwin->w_virtcol
|
||||||
|
- curwin->w_cursor.coladd))) {
|
||||||
int l;
|
int l;
|
||||||
|
|
||||||
if (*p != NUL && p[(l = (*mb_ptr2len)(p))] == NUL)
|
if (*p != NUL && p[(l = (*mb_ptr2len)(p))] == NUL)
|
||||||
|
@ -55,6 +55,7 @@
|
|||||||
#include "nvim/option.h"
|
#include "nvim/option.h"
|
||||||
#include "nvim/os_unix.h"
|
#include "nvim/os_unix.h"
|
||||||
#include "nvim/path.h"
|
#include "nvim/path.h"
|
||||||
|
#include "nvim/plines.h"
|
||||||
#include "nvim/quickfix.h"
|
#include "nvim/quickfix.h"
|
||||||
#include "nvim/regexp.h"
|
#include "nvim/regexp.h"
|
||||||
#include "nvim/screen.h"
|
#include "nvim/screen.h"
|
||||||
@ -828,7 +829,7 @@ void ex_retab(exarg_T *eap)
|
|||||||
}
|
}
|
||||||
if (ptr[col] == NUL)
|
if (ptr[col] == NUL)
|
||||||
break;
|
break;
|
||||||
vcol += chartabsize(ptr + col, (colnr_T)vcol);
|
vcol += win_chartabsize(curwin, ptr + col, (colnr_T)vcol);
|
||||||
col += utfc_ptr2len(ptr + col);
|
col += utfc_ptr2len(ptr + col);
|
||||||
}
|
}
|
||||||
if (new_line == NULL) /* out of memory */
|
if (new_line == NULL) /* out of memory */
|
||||||
|
@ -2593,7 +2593,7 @@ static void color_expr_cmdline(const CmdlineInfo *const colored_ccline,
|
|||||||
ColoredCmdline *const ret_ccline_colors)
|
ColoredCmdline *const ret_ccline_colors)
|
||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
ParserLine plines[] = {
|
ParserLine parser_lines[] = {
|
||||||
{
|
{
|
||||||
.data = (const char *)colored_ccline->cmdbuff,
|
.data = (const char *)colored_ccline->cmdbuff,
|
||||||
.size = STRLEN(colored_ccline->cmdbuff),
|
.size = STRLEN(colored_ccline->cmdbuff),
|
||||||
@ -2601,7 +2601,7 @@ static void color_expr_cmdline(const CmdlineInfo *const colored_ccline,
|
|||||||
},
|
},
|
||||||
{ NULL, 0, false },
|
{ NULL, 0, false },
|
||||||
};
|
};
|
||||||
ParserLine *plines_p = plines;
|
ParserLine *plines_p = parser_lines;
|
||||||
ParserHighlight colors;
|
ParserHighlight colors;
|
||||||
kvi_init(colors);
|
kvi_init(colors);
|
||||||
ParserState pstate;
|
ParserState pstate;
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "nvim/memory.h"
|
#include "nvim/memory.h"
|
||||||
#include "nvim/message.h"
|
#include "nvim/message.h"
|
||||||
#include "nvim/misc1.h"
|
#include "nvim/misc1.h"
|
||||||
|
#include "nvim/plines.h"
|
||||||
#include "nvim/garray.h"
|
#include "nvim/garray.h"
|
||||||
#include "nvim/move.h"
|
#include "nvim/move.h"
|
||||||
#include "nvim/option.h"
|
#include "nvim/option.h"
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "nvim/memory.h"
|
#include "nvim/memory.h"
|
||||||
#include "nvim/message.h"
|
#include "nvim/message.h"
|
||||||
#include "nvim/misc1.h"
|
#include "nvim/misc1.h"
|
||||||
|
#include "nvim/plines.h"
|
||||||
#include "nvim/keymap.h"
|
#include "nvim/keymap.h"
|
||||||
#include "nvim/garray.h"
|
#include "nvim/garray.h"
|
||||||
#include "nvim/move.h"
|
#include "nvim/move.h"
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "nvim/misc1.h"
|
#include "nvim/misc1.h"
|
||||||
#include "nvim/move.h"
|
#include "nvim/move.h"
|
||||||
#include "nvim/option.h"
|
#include "nvim/option.h"
|
||||||
|
#include "nvim/plines.h"
|
||||||
#include "nvim/regexp.h"
|
#include "nvim/regexp.h"
|
||||||
#include "nvim/screen.h"
|
#include "nvim/screen.h"
|
||||||
#include "nvim/search.h"
|
#include "nvim/search.h"
|
||||||
|
172
src/nvim/misc1.c
172
src/nvim/misc1.c
@ -349,178 +349,6 @@ int get_last_leader_offset(char_u *line, char_u **flags)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Return the number of window lines occupied by buffer line "lnum".
|
|
||||||
*/
|
|
||||||
int plines(const linenr_T lnum)
|
|
||||||
{
|
|
||||||
return plines_win(curwin, lnum, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
int plines_win(
|
|
||||||
win_T *const wp,
|
|
||||||
const linenr_T lnum,
|
|
||||||
const bool winheight // when true limit to window height
|
|
||||||
)
|
|
||||||
{
|
|
||||||
/* Check for filler lines above this buffer line. When folded the result
|
|
||||||
* is one line anyway. */
|
|
||||||
return plines_win_nofill(wp, lnum, winheight) + diff_check_fill(wp, lnum);
|
|
||||||
}
|
|
||||||
|
|
||||||
int plines_nofill(const linenr_T lnum)
|
|
||||||
{
|
|
||||||
return plines_win_nofill(curwin, lnum, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
int plines_win_nofill(
|
|
||||||
win_T *const wp,
|
|
||||||
const linenr_T lnum,
|
|
||||||
const bool winheight // when true limit to window height
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (!wp->w_p_wrap) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wp->w_width_inner == 0) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A folded lines is handled just like an empty line.
|
|
||||||
if (lineFolded(wp, lnum)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int lines = plines_win_nofold(wp, lnum);
|
|
||||||
if (winheight && lines > wp->w_height_inner) {
|
|
||||||
return wp->w_height_inner;
|
|
||||||
}
|
|
||||||
return lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return number of window lines physical line "lnum" will occupy in window
|
|
||||||
* "wp". Does not care about folding, 'wrap' or 'diff'.
|
|
||||||
*/
|
|
||||||
int plines_win_nofold(win_T *wp, linenr_T lnum)
|
|
||||||
{
|
|
||||||
char_u *s;
|
|
||||||
unsigned int col;
|
|
||||||
int width;
|
|
||||||
|
|
||||||
s = ml_get_buf(wp->w_buffer, lnum, FALSE);
|
|
||||||
if (*s == NUL) /* empty line */
|
|
||||||
return 1;
|
|
||||||
col = win_linetabsize(wp, s, MAXCOL);
|
|
||||||
|
|
||||||
// If list mode is on, then the '$' at the end of the line may take up one
|
|
||||||
// extra column.
|
|
||||||
if (wp->w_p_list && wp->w_p_lcs_chars.eol != NUL) {
|
|
||||||
col += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Add column offset for 'number', 'relativenumber' and 'foldcolumn'.
|
|
||||||
*/
|
|
||||||
width = wp->w_width_inner - win_col_off(wp);
|
|
||||||
if (width <= 0 || col > 32000) {
|
|
||||||
return 32000; // bigger than the number of screen columns
|
|
||||||
}
|
|
||||||
if (col <= (unsigned int)width) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
col -= (unsigned int)width;
|
|
||||||
width += win_col_off2(wp);
|
|
||||||
assert(col <= INT_MAX && (int)col < INT_MAX - (width -1));
|
|
||||||
return ((int)col + (width - 1)) / width + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Like plines_win(), but only reports the number of physical screen lines
|
|
||||||
* used from the start of the line to the given column number.
|
|
||||||
*/
|
|
||||||
int plines_win_col(win_T *wp, linenr_T lnum, long column)
|
|
||||||
{
|
|
||||||
// Check for filler lines above this buffer line. When folded the result
|
|
||||||
// is one line anyway.
|
|
||||||
int lines = diff_check_fill(wp, lnum);
|
|
||||||
|
|
||||||
if (!wp->w_p_wrap)
|
|
||||||
return lines + 1;
|
|
||||||
|
|
||||||
if (wp->w_width_inner == 0) {
|
|
||||||
return lines + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char_u *line = ml_get_buf(wp->w_buffer, lnum, false);
|
|
||||||
char_u *s = line;
|
|
||||||
|
|
||||||
colnr_T col = 0;
|
|
||||||
while (*s != NUL && --column >= 0) {
|
|
||||||
col += win_lbr_chartabsize(wp, line, s, col, NULL);
|
|
||||||
MB_PTR_ADV(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If *s is a TAB, and the TAB is not displayed as ^I, and we're not in
|
|
||||||
// INSERT mode, then col must be adjusted so that it represents the last
|
|
||||||
// screen position of the TAB. This only fixes an error when the TAB wraps
|
|
||||||
// from one screen line to the next (when 'columns' is not a multiple of
|
|
||||||
// 'ts') -- webb.
|
|
||||||
if (*s == TAB && (State & NORMAL)
|
|
||||||
&& (!wp->w_p_list || wp->w_p_lcs_chars.tab1)) {
|
|
||||||
col += win_lbr_chartabsize(wp, line, s, col, NULL) - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add column offset for 'number', 'relativenumber', 'foldcolumn', etc.
|
|
||||||
int width = wp->w_width_inner - win_col_off(wp);
|
|
||||||
if (width <= 0) {
|
|
||||||
return 9999;
|
|
||||||
}
|
|
||||||
|
|
||||||
lines += 1;
|
|
||||||
if (col > width)
|
|
||||||
lines += (col - width) / (width + win_col_off2(wp)) + 1;
|
|
||||||
return lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the number of screen lines lnum takes up. This takes care of
|
|
||||||
/// both folds and topfill, and limits to the current window height.
|
|
||||||
///
|
|
||||||
/// @param[in] wp window line is in
|
|
||||||
/// @param[in] lnum line number
|
|
||||||
/// @param[out] nextp if not NULL, the line after a fold
|
|
||||||
/// @param[out] foldedp if not NULL, whether lnum is on a fold
|
|
||||||
/// @param[in] cache whether to use the window's cache for folds
|
|
||||||
///
|
|
||||||
/// @return the total number of screen lines
|
|
||||||
int plines_win_full(win_T *wp, linenr_T lnum, linenr_T *const nextp,
|
|
||||||
bool *const foldedp, const bool cache)
|
|
||||||
{
|
|
||||||
bool folded = hasFoldingWin(wp, lnum, NULL, nextp, cache, NULL);
|
|
||||||
if (foldedp) {
|
|
||||||
*foldedp = folded;
|
|
||||||
}
|
|
||||||
if (folded) {
|
|
||||||
return 1;
|
|
||||||
} else if (lnum == wp->w_topline) {
|
|
||||||
return plines_win_nofill(wp, lnum, true) + wp->w_topfill;
|
|
||||||
}
|
|
||||||
return plines_win(wp, lnum, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
int plines_m_win(win_T *wp, linenr_T first, linenr_T last)
|
|
||||||
{
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
while (first <= last) {
|
|
||||||
linenr_T next = first;
|
|
||||||
count += plines_win_full(wp, first, &next, NULL, false);
|
|
||||||
first = next + 1;
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
int gchar_pos(pos_T *pos)
|
int gchar_pos(pos_T *pos)
|
||||||
FUNC_ATTR_NONNULL_ARG(1)
|
FUNC_ATTR_NONNULL_ARG(1)
|
||||||
{
|
{
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "nvim/diff.h"
|
#include "nvim/diff.h"
|
||||||
#include "nvim/move.h"
|
#include "nvim/move.h"
|
||||||
#include "nvim/misc1.h"
|
#include "nvim/misc1.h"
|
||||||
|
#include "nvim/plines.h"
|
||||||
#include "nvim/cursor.h"
|
#include "nvim/cursor.h"
|
||||||
#include "nvim/buffer_defs.h"
|
#include "nvim/buffer_defs.h"
|
||||||
#include "nvim/memline.h"
|
#include "nvim/memline.h"
|
||||||
@ -236,12 +237,14 @@ retnomove:
|
|||||||
if (row < 0) {
|
if (row < 0) {
|
||||||
count = 0;
|
count = 0;
|
||||||
for (first = true; curwin->w_topline > 1; ) {
|
for (first = true; curwin->w_topline > 1; ) {
|
||||||
if (curwin->w_topfill < diff_check(curwin, curwin->w_topline))
|
if (curwin->w_topfill < diff_check(curwin, curwin->w_topline)) {
|
||||||
++count;
|
count++;
|
||||||
else
|
} else {
|
||||||
count += plines(curwin->w_topline - 1);
|
count += plines_win(curwin, curwin->w_topline - 1, true);
|
||||||
if (!first && count > -row)
|
}
|
||||||
|
if (!first && count > -row) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
first = false;
|
first = false;
|
||||||
(void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
|
(void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
|
||||||
if (curwin->w_topfill < diff_check(curwin, curwin->w_topline)) {
|
if (curwin->w_topfill < diff_check(curwin, curwin->w_topline)) {
|
||||||
@ -262,7 +265,7 @@ retnomove:
|
|||||||
if (curwin->w_topfill > 0) {
|
if (curwin->w_topfill > 0) {
|
||||||
++count;
|
++count;
|
||||||
} else {
|
} else {
|
||||||
count += plines(curwin->w_topline);
|
count += plines_win(curwin, curwin->w_topline, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!first && count > row - curwin->w_height_inner + 1) {
|
if (!first && count > row - curwin->w_height_inner + 1) {
|
||||||
@ -522,7 +525,7 @@ static colnr_T scroll_line_len(linenr_T lnum)
|
|||||||
char_u *line = ml_get(lnum);
|
char_u *line = ml_get(lnum);
|
||||||
if (*line != NUL) {
|
if (*line != NUL) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int numchar = chartabsize(line, col);
|
int numchar = win_chartabsize(curwin, line, col);
|
||||||
MB_PTR_ADV(line);
|
MB_PTR_ADV(line);
|
||||||
if (*line == NUL) { // don't count the last character
|
if (*line == NUL) { // don't count the last character
|
||||||
break;
|
break;
|
||||||
@ -618,10 +621,10 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
|
|||||||
// scanned *up to* `col`, nudging it left or right when concealed characters
|
// scanned *up to* `col`, nudging it left or right when concealed characters
|
||||||
// are encountered.
|
// are encountered.
|
||||||
//
|
//
|
||||||
// chartabsize() is used to keep track of the virtual column position relative
|
// win_chartabsize() is used to keep track of the virtual column position
|
||||||
// to the line's bytes. For example: if col == 9 and the line starts with a
|
// relative to the line's bytes. For example: if col == 9 and the line
|
||||||
// tab that's 8 columns wide, we would want the cursor to be highlighting the
|
// starts with a tab that's 8 columns wide, we would want the cursor to be
|
||||||
// second byte, not the ninth.
|
// highlighting the second byte, not the ninth.
|
||||||
|
|
||||||
linenr_T lnum = wp->w_cursor.lnum;
|
linenr_T lnum = wp->w_cursor.lnum;
|
||||||
char_u *line = ml_get(lnum);
|
char_u *line = ml_get(lnum);
|
||||||
@ -645,7 +648,7 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
|
|||||||
// checked for concealed characters.
|
// checked for concealed characters.
|
||||||
vcol = 0;
|
vcol = 0;
|
||||||
while (vcol < offset && *ptr != NUL) {
|
while (vcol < offset && *ptr != NUL) {
|
||||||
vcol += chartabsize(ptr, vcol);
|
vcol += win_chartabsize(curwin, ptr, vcol);
|
||||||
ptr += utfc_ptr2len(ptr);
|
ptr += utfc_ptr2len(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -656,7 +659,7 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
|
|||||||
vcol = offset;
|
vcol = offset;
|
||||||
ptr_end = ptr_row_offset;
|
ptr_end = ptr_row_offset;
|
||||||
while (vcol < col && *ptr_end != NUL) {
|
while (vcol < col && *ptr_end != NUL) {
|
||||||
vcol += chartabsize(ptr_end, vcol);
|
vcol += win_chartabsize(curwin, ptr_end, vcol);
|
||||||
ptr_end += utfc_ptr2len(ptr_end);
|
ptr_end += utfc_ptr2len(ptr_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -671,7 +674,7 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
|
|||||||
#define decr() nudge--; ptr_end -= utfc_ptr2len(ptr_end)
|
#define decr() nudge--; ptr_end -= utfc_ptr2len(ptr_end)
|
||||||
|
|
||||||
while (ptr < ptr_end && *ptr != NUL) {
|
while (ptr < ptr_end && *ptr != NUL) {
|
||||||
cwidth = chartabsize(ptr, vcol);
|
cwidth = win_chartabsize(curwin, ptr, vcol);
|
||||||
vcol += cwidth;
|
vcol += cwidth;
|
||||||
if (cwidth > 1 && *ptr == '\t' && nudge > 0) {
|
if (cwidth > 1 && *ptr == '\t' && nudge > 0) {
|
||||||
// A tab will "absorb" any previous adjustments.
|
// A tab will "absorb" any previous adjustments.
|
||||||
|
117
src/nvim/move.c
117
src/nvim/move.c
@ -27,6 +27,7 @@
|
|||||||
#include "nvim/mbyte.h"
|
#include "nvim/mbyte.h"
|
||||||
#include "nvim/memline.h"
|
#include "nvim/memline.h"
|
||||||
#include "nvim/misc1.h"
|
#include "nvim/misc1.h"
|
||||||
|
#include "nvim/plines.h"
|
||||||
#include "nvim/option.h"
|
#include "nvim/option.h"
|
||||||
#include "nvim/popupmnu.h"
|
#include "nvim/popupmnu.h"
|
||||||
#include "nvim/screen.h"
|
#include "nvim/screen.h"
|
||||||
@ -1055,8 +1056,9 @@ bool scrolldown(long line_count, int byfold)
|
|||||||
line_count -= curwin->w_topline - first - 1;
|
line_count -= curwin->w_topline - first - 1;
|
||||||
curwin->w_botline -= curwin->w_topline - first;
|
curwin->w_botline -= curwin->w_topline - first;
|
||||||
curwin->w_topline = first;
|
curwin->w_topline = first;
|
||||||
} else
|
} else {
|
||||||
done += plines_nofill(curwin->w_topline);
|
done += plines_win_nofill(curwin, curwin->w_topline, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
--curwin->w_botline; /* approximate w_botline */
|
--curwin->w_botline; /* approximate w_botline */
|
||||||
invalidate_botline();
|
invalidate_botline();
|
||||||
@ -1090,8 +1092,9 @@ bool scrolldown(long line_count, int byfold)
|
|||||||
curwin->w_cursor.lnum = 1;
|
curwin->w_cursor.lnum = 1;
|
||||||
else
|
else
|
||||||
curwin->w_cursor.lnum = first - 1;
|
curwin->w_cursor.lnum = first - 1;
|
||||||
} else
|
} else {
|
||||||
wrow -= plines(curwin->w_cursor.lnum--);
|
wrow -= plines_win(curwin, curwin->w_cursor.lnum--, true);
|
||||||
|
}
|
||||||
curwin->w_valid &=
|
curwin->w_valid &=
|
||||||
~(VALID_WROW|VALID_WCOL|VALID_CHEIGHT|VALID_CROW|VALID_VIRTCOL);
|
~(VALID_WROW|VALID_WCOL|VALID_CHEIGHT|VALID_CROW|VALID_VIRTCOL);
|
||||||
moved = true;
|
moved = true;
|
||||||
@ -1194,7 +1197,7 @@ check_topfill (
|
|||||||
*/
|
*/
|
||||||
static void max_topfill(void)
|
static void max_topfill(void)
|
||||||
{
|
{
|
||||||
int n = plines_nofill(curwin->w_topline);
|
int n = plines_win_nofill(curwin, curwin->w_topline, true);
|
||||||
if (n >= curwin->w_height_inner) {
|
if (n >= curwin->w_height_inner) {
|
||||||
curwin->w_topfill = 0;
|
curwin->w_topfill = 0;
|
||||||
} else {
|
} else {
|
||||||
@ -1221,19 +1224,16 @@ void scrolldown_clamp(void)
|
|||||||
|
|
||||||
validate_cursor(); /* w_wrow needs to be valid */
|
validate_cursor(); /* w_wrow needs to be valid */
|
||||||
|
|
||||||
/*
|
// Compute the row number of the last row of the cursor line
|
||||||
* Compute the row number of the last row of the cursor line
|
// and make sure it doesn't go off the screen. Make sure the cursor
|
||||||
* and make sure it doesn't go off the screen. Make sure the cursor
|
// doesn't go past 'scrolloff' lines from the screen end.
|
||||||
* doesn't go past 'scrolloff' lines from the screen end.
|
|
||||||
*/
|
|
||||||
int end_row = curwin->w_wrow;
|
int end_row = curwin->w_wrow;
|
||||||
if (can_fill)
|
if (can_fill) {
|
||||||
++end_row;
|
end_row++;
|
||||||
else
|
} else {
|
||||||
end_row += plines_nofill(curwin->w_topline - 1);
|
end_row += plines_win_nofill(curwin, curwin->w_topline - 1, true);
|
||||||
if (curwin->w_p_wrap
|
}
|
||||||
&& curwin->w_width_inner != 0
|
if (curwin->w_p_wrap && curwin->w_width_inner != 0) {
|
||||||
) {
|
|
||||||
validate_cheight();
|
validate_cheight();
|
||||||
validate_virtcol();
|
validate_virtcol();
|
||||||
end_row += curwin->w_cline_height - 1 -
|
end_row += curwin->w_cline_height - 1 -
|
||||||
@ -1266,16 +1266,13 @@ void scrollup_clamp(void)
|
|||||||
|
|
||||||
validate_cursor(); /* w_wrow needs to be valid */
|
validate_cursor(); /* w_wrow needs to be valid */
|
||||||
|
|
||||||
/*
|
// Compute the row number of the first row of the cursor line
|
||||||
* Compute the row number of the first row of the cursor line
|
// and make sure it doesn't go off the screen. Make sure the cursor
|
||||||
* and make sure it doesn't go off the screen. Make sure the cursor
|
// doesn't go before 'scrolloff' lines from the screen start.
|
||||||
* doesn't go before 'scrolloff' lines from the screen start.
|
int start_row = (curwin->w_wrow
|
||||||
*/
|
- plines_win_nofill(curwin, curwin->w_topline, true)
|
||||||
int start_row = curwin->w_wrow - plines_nofill(curwin->w_topline)
|
- curwin->w_topfill);
|
||||||
- curwin->w_topfill;
|
if (curwin->w_p_wrap && curwin->w_width_inner != 0) {
|
||||||
if (curwin->w_p_wrap
|
|
||||||
&& curwin->w_width_inner != 0
|
|
||||||
) {
|
|
||||||
validate_virtcol();
|
validate_virtcol();
|
||||||
start_row -= curwin->w_virtcol / curwin->w_width_inner;
|
start_row -= curwin->w_virtcol / curwin->w_width_inner;
|
||||||
}
|
}
|
||||||
@ -1422,14 +1419,15 @@ void scroll_cursor_top(int min_scroll, int always)
|
|||||||
while (top > 0) {
|
while (top > 0) {
|
||||||
int i = hasFolding(top, &top, NULL)
|
int i = hasFolding(top, &top, NULL)
|
||||||
? 1 // count one logical line for a sequence of folded lines
|
? 1 // count one logical line for a sequence of folded lines
|
||||||
: plines_nofill(top);
|
: plines_win_nofill(curwin, top, true);
|
||||||
used += i;
|
used += i;
|
||||||
if (extra + i <= off && bot < curbuf->b_ml.ml_line_count) {
|
if (extra + i <= off && bot < curbuf->b_ml.ml_line_count) {
|
||||||
if (hasFolding(bot, NULL, &bot))
|
if (hasFolding(bot, NULL, &bot)) {
|
||||||
/* count one logical line for a sequence of folded lines */
|
// count one logical line for a sequence of folded lines
|
||||||
++used;
|
used++;
|
||||||
else
|
} else {
|
||||||
used += plines(bot);
|
used += plines_win(curwin, bot, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (used > curwin->w_height_inner) {
|
if (used > curwin->w_height_inner) {
|
||||||
break;
|
break;
|
||||||
@ -1555,12 +1553,12 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
|
|||||||
validate_botline(curwin);
|
validate_botline(curwin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The lines of the cursor line itself are always used. */
|
// The lines of the cursor line itself are always used.
|
||||||
used = plines_nofill(cln);
|
used = plines_win_nofill(curwin, cln, true);
|
||||||
|
|
||||||
/* If the cursor is below botline, we will at least scroll by the height
|
// If the cursor is below botline, we will at least scroll by the height
|
||||||
* of the cursor line. Correct for empty lines, which are really part of
|
// of the cursor line. Correct for empty lines, which are really part of
|
||||||
* botline. */
|
// botline.
|
||||||
if (cln >= curwin->w_botline) {
|
if (cln >= curwin->w_botline) {
|
||||||
scrolled = used;
|
scrolled = used;
|
||||||
if (cln == curwin->w_botline)
|
if (cln == curwin->w_botline)
|
||||||
@ -1704,7 +1702,7 @@ void scroll_cursor_halfway(int atend)
|
|||||||
|
|
||||||
loff.lnum = boff.lnum = curwin->w_cursor.lnum;
|
loff.lnum = boff.lnum = curwin->w_cursor.lnum;
|
||||||
(void)hasFolding(loff.lnum, &loff.lnum, &boff.lnum);
|
(void)hasFolding(loff.lnum, &loff.lnum, &boff.lnum);
|
||||||
int used = plines_nofill(loff.lnum);
|
int used = plines_win_nofill(curwin, loff.lnum, true);
|
||||||
loff.fill = 0;
|
loff.fill = 0;
|
||||||
boff.fill = 0;
|
boff.fill = 0;
|
||||||
linenr_T topline = loff.lnum;
|
linenr_T topline = loff.lnum;
|
||||||
@ -1809,17 +1807,19 @@ void cursor_correct(void)
|
|||||||
int below = curwin->w_filler_rows; /* screen lines below botline */
|
int below = curwin->w_filler_rows; /* screen lines below botline */
|
||||||
while ((above < above_wanted || below < below_wanted) && topline < botline) {
|
while ((above < above_wanted || below < below_wanted) && topline < botline) {
|
||||||
if (below < below_wanted && (below <= above || above >= above_wanted)) {
|
if (below < below_wanted && (below <= above || above >= above_wanted)) {
|
||||||
if (hasFolding(botline, &botline, NULL))
|
if (hasFolding(botline, &botline, NULL)) {
|
||||||
++below;
|
below++;
|
||||||
else
|
} else {
|
||||||
below += plines(botline);
|
below += plines_win(curwin, botline, true);
|
||||||
--botline;
|
}
|
||||||
|
botline--;
|
||||||
}
|
}
|
||||||
if (above < above_wanted && (above < below || below >= below_wanted)) {
|
if (above < above_wanted && (above < below || below >= below_wanted)) {
|
||||||
if (hasFolding(topline, NULL, &topline))
|
if (hasFolding(topline, NULL, &topline)) {
|
||||||
++above;
|
above++;
|
||||||
else
|
} else {
|
||||||
above += plines_nofill(topline);
|
above += plines_win_nofill(curwin, topline, true);
|
||||||
|
}
|
||||||
|
|
||||||
/* Count filler lines below this line as context. */
|
/* Count filler lines below this line as context. */
|
||||||
if (topline < botline)
|
if (topline < botline)
|
||||||
@ -2047,10 +2047,11 @@ static void get_scroll_overlap(lineoff_T *lp, int dir)
|
|||||||
{
|
{
|
||||||
int min_height = curwin->w_height_inner - 2;
|
int min_height = curwin->w_height_inner - 2;
|
||||||
|
|
||||||
if (lp->fill > 0)
|
if (lp->fill > 0) {
|
||||||
lp->height = 1;
|
lp->height = 1;
|
||||||
else
|
} else {
|
||||||
lp->height = plines_nofill(lp->lnum);
|
lp->height = plines_win_nofill(curwin, lp->lnum, true);
|
||||||
|
}
|
||||||
int h1 = lp->height;
|
int h1 = lp->height;
|
||||||
if (h1 > min_height)
|
if (h1 > min_height)
|
||||||
return; /* no overlap */
|
return; /* no overlap */
|
||||||
@ -2120,7 +2121,7 @@ void halfpage(bool flag, linenr_T Prenum)
|
|||||||
n--;
|
n--;
|
||||||
curwin->w_topfill--;
|
curwin->w_topfill--;
|
||||||
} else {
|
} else {
|
||||||
i = plines_nofill(curwin->w_topline);
|
i = plines_win_nofill(curwin, curwin->w_topline, true);
|
||||||
n -= i;
|
n -= i;
|
||||||
if (n < 0 && scrolled > 0)
|
if (n < 0 && scrolled > 0)
|
||||||
break;
|
break;
|
||||||
@ -2146,12 +2147,12 @@ void halfpage(bool flag, linenr_T Prenum)
|
|||||||
else {
|
else {
|
||||||
room += i;
|
room += i;
|
||||||
do {
|
do {
|
||||||
i = plines(curwin->w_botline);
|
i = plines_win(curwin, curwin->w_botline, true);
|
||||||
if (i > room)
|
if (i > room) {
|
||||||
break;
|
break;
|
||||||
(void)hasFolding(curwin->w_botline, NULL,
|
}
|
||||||
&curwin->w_botline);
|
(void)hasFolding(curwin->w_botline, NULL, &curwin->w_botline);
|
||||||
++curwin->w_botline;
|
curwin->w_botline++;
|
||||||
room -= i;
|
room -= i;
|
||||||
} while (curwin->w_botline <= curbuf->b_ml.ml_line_count);
|
} while (curwin->w_botline <= curbuf->b_ml.ml_line_count);
|
||||||
}
|
}
|
||||||
@ -2180,7 +2181,7 @@ void halfpage(bool flag, linenr_T Prenum)
|
|||||||
n--;
|
n--;
|
||||||
curwin->w_topfill++;
|
curwin->w_topfill++;
|
||||||
} else {
|
} else {
|
||||||
i = plines_nofill(curwin->w_topline - 1);
|
i = plines_win_nofill(curwin, curwin->w_topline - 1, true);
|
||||||
n -= i;
|
n -= i;
|
||||||
if (n < 0 && scrolled > 0)
|
if (n < 0 && scrolled > 0)
|
||||||
break;
|
break;
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
#include "nvim/mouse.h"
|
#include "nvim/mouse.h"
|
||||||
#include "nvim/ops.h"
|
#include "nvim/ops.h"
|
||||||
#include "nvim/option.h"
|
#include "nvim/option.h"
|
||||||
|
#include "nvim/plines.h"
|
||||||
#include "nvim/quickfix.h"
|
#include "nvim/quickfix.h"
|
||||||
#include "nvim/screen.h"
|
#include "nvim/screen.h"
|
||||||
#include "nvim/search.h"
|
#include "nvim/search.h"
|
||||||
@ -5122,11 +5123,13 @@ static void nv_scroll(cmdarg_T *cap)
|
|||||||
--n;
|
--n;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
used += plines(curwin->w_topline + n);
|
used += plines_win(curwin, curwin->w_topline + n, true);
|
||||||
if (used >= half)
|
if (used >= half) {
|
||||||
break;
|
break;
|
||||||
if (hasFolding(curwin->w_topline + n, NULL, &lnum))
|
}
|
||||||
|
if (hasFolding(curwin->w_topline + n, NULL, &lnum)) {
|
||||||
n = lnum - curwin->w_topline;
|
n = lnum - curwin->w_topline;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (n > 0 && used > curwin->w_height_inner) {
|
if (n > 0 && used > curwin->w_height_inner) {
|
||||||
n--;
|
n--;
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#include "nvim/normal.h"
|
#include "nvim/normal.h"
|
||||||
#include "nvim/option.h"
|
#include "nvim/option.h"
|
||||||
#include "nvim/path.h"
|
#include "nvim/path.h"
|
||||||
|
#include "nvim/plines.h"
|
||||||
#include "nvim/screen.h"
|
#include "nvim/screen.h"
|
||||||
#include "nvim/search.h"
|
#include "nvim/search.h"
|
||||||
#include "nvim/state.h"
|
#include "nvim/state.h"
|
||||||
|
481
src/nvim/plines.c
Normal file
481
src/nvim/plines.c
Normal file
@ -0,0 +1,481 @@
|
|||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check
|
||||||
|
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
// plines.c: calculate the vertical and horizontal size of text in a window
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "nvim/vim.h"
|
||||||
|
#include "nvim/ascii.h"
|
||||||
|
#include "nvim/plines.h"
|
||||||
|
#include "nvim/charset.h"
|
||||||
|
#include "nvim/cursor.h"
|
||||||
|
#include "nvim/diff.h"
|
||||||
|
#include "nvim/func_attr.h"
|
||||||
|
#include "nvim/fold.h"
|
||||||
|
#include "nvim/indent.h"
|
||||||
|
#include "nvim/main.h"
|
||||||
|
#include "nvim/mbyte.h"
|
||||||
|
#include "nvim/memline.h"
|
||||||
|
#include "nvim/memory.h"
|
||||||
|
#include "nvim/move.h"
|
||||||
|
#include "nvim/option.h"
|
||||||
|
#include "nvim/screen.h"
|
||||||
|
#include "nvim/strings.h"
|
||||||
|
#include "nvim/window.h"
|
||||||
|
#include "nvim/buffer.h"
|
||||||
|
|
||||||
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
|
# include "plines.c.generated.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Functions calculating vertical size of text when displayed inside a window.
|
||||||
|
/// Calls horizontal size functions defined below.
|
||||||
|
|
||||||
|
/// @param winheight when true limit to window height
|
||||||
|
int plines_win(win_T *wp, linenr_T lnum, bool winheight)
|
||||||
|
{
|
||||||
|
// Check for filler lines above this buffer line. When folded the result
|
||||||
|
// is one line anyway.
|
||||||
|
return plines_win_nofill(wp, lnum, winheight) + diff_check_fill(wp, lnum);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @param winheight when true limit to window height
|
||||||
|
int plines_win_nofill(win_T *wp, linenr_T lnum, bool winheight)
|
||||||
|
{
|
||||||
|
if (!wp->w_p_wrap) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wp->w_width_inner == 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A folded lines is handled just like an empty line.
|
||||||
|
if (lineFolded(wp, lnum)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int lines = plines_win_nofold(wp, lnum);
|
||||||
|
if (winheight && lines > wp->w_height_inner) {
|
||||||
|
return wp->w_height_inner;
|
||||||
|
}
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @Return number of window lines physical line "lnum" will occupy in window
|
||||||
|
/// "wp". Does not care about folding, 'wrap' or 'diff'.
|
||||||
|
int plines_win_nofold(win_T *wp, linenr_T lnum)
|
||||||
|
{
|
||||||
|
char_u *s;
|
||||||
|
unsigned int col;
|
||||||
|
int width;
|
||||||
|
|
||||||
|
s = ml_get_buf(wp->w_buffer, lnum, false);
|
||||||
|
if (*s == NUL) { // empty line
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
col = win_linetabsize(wp, s, MAXCOL);
|
||||||
|
|
||||||
|
// If list mode is on, then the '$' at the end of the line may take up one
|
||||||
|
// extra column.
|
||||||
|
if (wp->w_p_list && wp->w_p_lcs_chars.eol != NUL) {
|
||||||
|
col += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add column offset for 'number', 'relativenumber' and 'foldcolumn'.
|
||||||
|
width = wp->w_width_inner - win_col_off(wp);
|
||||||
|
if (width <= 0 || col > 32000) {
|
||||||
|
return 32000; // bigger than the number of screen columns
|
||||||
|
}
|
||||||
|
if (col <= (unsigned int)width) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
col -= (unsigned int)width;
|
||||||
|
width += win_col_off2(wp);
|
||||||
|
assert(col <= INT_MAX && (int)col < INT_MAX - (width -1));
|
||||||
|
return ((int)col + (width - 1)) / width + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Like plines_win(), but only reports the number of physical screen lines
|
||||||
|
/// used from the start of the line to the given column number.
|
||||||
|
int plines_win_col(win_T *wp, linenr_T lnum, long column)
|
||||||
|
{
|
||||||
|
// Check for filler lines above this buffer line. When folded the result
|
||||||
|
// is one line anyway.
|
||||||
|
int lines = diff_check_fill(wp, lnum);
|
||||||
|
|
||||||
|
if (!wp->w_p_wrap) {
|
||||||
|
return lines + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wp->w_width_inner == 0) {
|
||||||
|
return lines + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char_u *line = ml_get_buf(wp->w_buffer, lnum, false);
|
||||||
|
char_u *s = line;
|
||||||
|
|
||||||
|
colnr_T col = 0;
|
||||||
|
while (*s != NUL && --column >= 0) {
|
||||||
|
col += win_lbr_chartabsize(wp, line, s, col, NULL);
|
||||||
|
MB_PTR_ADV(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If *s is a TAB, and the TAB is not displayed as ^I, and we're not in
|
||||||
|
// INSERT mode, then col must be adjusted so that it represents the last
|
||||||
|
// screen position of the TAB. This only fixes an error when the TAB wraps
|
||||||
|
// from one screen line to the next (when 'columns' is not a multiple of
|
||||||
|
// 'ts') -- webb.
|
||||||
|
if (*s == TAB && (State & NORMAL)
|
||||||
|
&& (!wp->w_p_list || wp->w_p_lcs_chars.tab1)) {
|
||||||
|
col += win_lbr_chartabsize(wp, line, s, col, NULL) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add column offset for 'number', 'relativenumber', 'foldcolumn', etc.
|
||||||
|
int width = wp->w_width_inner - win_col_off(wp);
|
||||||
|
if (width <= 0) {
|
||||||
|
return 9999;
|
||||||
|
}
|
||||||
|
|
||||||
|
lines += 1;
|
||||||
|
if (col > width) {
|
||||||
|
lines += (col - width) / (width + win_col_off2(wp)) + 1;
|
||||||
|
}
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the number of screen lines lnum takes up. This takes care of
|
||||||
|
/// both folds and topfill, and limits to the current window height.
|
||||||
|
///
|
||||||
|
/// @param[in] wp window line is in
|
||||||
|
/// @param[in] lnum line number
|
||||||
|
/// @param[out] nextp if not NULL, the line after a fold
|
||||||
|
/// @param[out] foldedp if not NULL, whether lnum is on a fold
|
||||||
|
/// @param[in] cache whether to use the window's cache for folds
|
||||||
|
///
|
||||||
|
/// @return the total number of screen lines
|
||||||
|
int plines_win_full(win_T *wp, linenr_T lnum, linenr_T *const nextp,
|
||||||
|
bool *const foldedp, const bool cache)
|
||||||
|
{
|
||||||
|
bool folded = hasFoldingWin(wp, lnum, NULL, nextp, cache, NULL);
|
||||||
|
if (foldedp) {
|
||||||
|
*foldedp = folded;
|
||||||
|
}
|
||||||
|
if (folded) {
|
||||||
|
return 1;
|
||||||
|
} else if (lnum == wp->w_topline) {
|
||||||
|
return plines_win_nofill(wp, lnum, true) + wp->w_topfill;
|
||||||
|
}
|
||||||
|
return plines_win(wp, lnum, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
int plines_m_win(win_T *wp, linenr_T first, linenr_T last)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
while (first <= last) {
|
||||||
|
linenr_T next = first;
|
||||||
|
count += plines_win_full(wp, first, &next, NULL, false);
|
||||||
|
first = next + 1;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Functions calculating horizontal size of text, when displayed in a window.
|
||||||
|
|
||||||
|
/// Return the number of characters 'c' will take on the screen, taking
|
||||||
|
/// into account the size of a tab.
|
||||||
|
/// Also see getvcol()
|
||||||
|
///
|
||||||
|
/// @param p
|
||||||
|
/// @param col
|
||||||
|
///
|
||||||
|
/// @return Number of characters.
|
||||||
|
int win_chartabsize(win_T *wp, char_u *p, colnr_T col)
|
||||||
|
{
|
||||||
|
buf_T *buf = wp->w_buffer;
|
||||||
|
if (*p == TAB && (!wp->w_p_list || wp->w_p_lcs_chars.tab1)) {
|
||||||
|
return tabstop_padding(col, buf->b_p_ts, buf->b_p_vts_array);
|
||||||
|
} else {
|
||||||
|
return ptr2cells(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the number of characters the string 's' will take on the screen,
|
||||||
|
/// taking into account the size of a tab.
|
||||||
|
///
|
||||||
|
/// @param s
|
||||||
|
///
|
||||||
|
/// @return Number of characters the string will take on the screen.
|
||||||
|
int linetabsize(char_u *s)
|
||||||
|
{
|
||||||
|
return linetabsize_col(0, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Like linetabsize(), but starting at column "startcol".
|
||||||
|
///
|
||||||
|
/// @param startcol
|
||||||
|
/// @param s
|
||||||
|
///
|
||||||
|
/// @return Number of characters the string will take on the screen.
|
||||||
|
int linetabsize_col(int startcol, char_u *s)
|
||||||
|
{
|
||||||
|
colnr_T col = startcol;
|
||||||
|
char_u *line = s; // pointer to start of line, for breakindent
|
||||||
|
|
||||||
|
while (*s != NUL) {
|
||||||
|
col += lbr_chartabsize_adv(line, &s, col);
|
||||||
|
}
|
||||||
|
return (int)col;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Like linetabsize(), but for a given window instead of the current one.
|
||||||
|
///
|
||||||
|
/// @param wp
|
||||||
|
/// @param line
|
||||||
|
/// @param len
|
||||||
|
///
|
||||||
|
/// @return Number of characters the string will take on the screen.
|
||||||
|
unsigned int win_linetabsize(win_T *wp, char_u *line, colnr_T len)
|
||||||
|
{
|
||||||
|
colnr_T col = 0;
|
||||||
|
|
||||||
|
for (char_u *s = line;
|
||||||
|
*s != NUL && (len == MAXCOL || s < line + len);
|
||||||
|
MB_PTR_ADV(s)) {
|
||||||
|
col += win_lbr_chartabsize(wp, line, s, col, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (unsigned int)col;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// like win_chartabsize(), but also check for line breaks on the screen
|
||||||
|
///
|
||||||
|
/// @param line
|
||||||
|
/// @param s
|
||||||
|
/// @param col
|
||||||
|
///
|
||||||
|
/// @return The number of characters taken up on the screen.
|
||||||
|
int lbr_chartabsize(char_u *line, unsigned char *s, colnr_T col)
|
||||||
|
{
|
||||||
|
if (!curwin->w_p_lbr && (*p_sbr == NUL) && !curwin->w_p_bri) {
|
||||||
|
if (curwin->w_p_wrap) {
|
||||||
|
return win_nolbr_chartabsize(curwin, s, col, NULL);
|
||||||
|
}
|
||||||
|
return win_chartabsize(curwin, s, col);
|
||||||
|
}
|
||||||
|
return win_lbr_chartabsize(curwin, line == NULL ? s: line, s, col, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Call lbr_chartabsize() and advance the pointer.
|
||||||
|
///
|
||||||
|
/// @param line
|
||||||
|
/// @param s
|
||||||
|
/// @param col
|
||||||
|
///
|
||||||
|
/// @return The number of characters take up on the screen.
|
||||||
|
int lbr_chartabsize_adv(char_u *line, char_u **s, colnr_T col)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = lbr_chartabsize(line, *s, col);
|
||||||
|
MB_PTR_ADV(*s);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This function is used very often, keep it fast!!!!
|
||||||
|
///
|
||||||
|
/// If "headp" not NULL, set *headp to the size of what we for 'showbreak'
|
||||||
|
/// string at start of line. Warning: *headp is only set if it's a non-zero
|
||||||
|
/// value, init to 0 before calling.
|
||||||
|
///
|
||||||
|
/// @param wp
|
||||||
|
/// @param line
|
||||||
|
/// @param s
|
||||||
|
/// @param col
|
||||||
|
/// @param headp
|
||||||
|
///
|
||||||
|
/// @return The number of characters taken up on the screen.
|
||||||
|
int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s,
|
||||||
|
colnr_T col, int *headp)
|
||||||
|
{
|
||||||
|
colnr_T col2;
|
||||||
|
colnr_T col_adj = 0; // col + screen size of tab
|
||||||
|
colnr_T colmax;
|
||||||
|
int added;
|
||||||
|
int mb_added = 0;
|
||||||
|
int numberextra;
|
||||||
|
char_u *ps;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
// No 'linebreak', 'showbreak' and 'breakindent': return quickly.
|
||||||
|
if (!wp->w_p_lbr && !wp->w_p_bri && (*p_sbr == NUL)) {
|
||||||
|
if (wp->w_p_wrap) {
|
||||||
|
return win_nolbr_chartabsize(wp, s, col, headp);
|
||||||
|
}
|
||||||
|
return win_chartabsize(wp, s, col);
|
||||||
|
}
|
||||||
|
|
||||||
|
// First get normal size, without 'linebreak'
|
||||||
|
int size = win_chartabsize(wp, s, col);
|
||||||
|
int c = *s;
|
||||||
|
if (*s == TAB) {
|
||||||
|
col_adj = size - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If 'linebreak' set check at a blank before a non-blank if the line
|
||||||
|
// needs a break here
|
||||||
|
if (wp->w_p_lbr
|
||||||
|
&& vim_isbreak(c)
|
||||||
|
&& !vim_isbreak((int)s[1])
|
||||||
|
&& wp->w_p_wrap
|
||||||
|
&& (wp->w_width_inner != 0)) {
|
||||||
|
// Count all characters from first non-blank after a blank up to next
|
||||||
|
// non-blank after a blank.
|
||||||
|
numberextra = win_col_off(wp);
|
||||||
|
col2 = col;
|
||||||
|
colmax = (colnr_T)(wp->w_width_inner - numberextra - col_adj);
|
||||||
|
|
||||||
|
if (col >= colmax) {
|
||||||
|
colmax += col_adj;
|
||||||
|
n = colmax + win_col_off2(wp);
|
||||||
|
|
||||||
|
if (n > 0) {
|
||||||
|
colmax += (((col - colmax) / n) + 1) * n - col_adj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
ps = s;
|
||||||
|
MB_PTR_ADV(s);
|
||||||
|
c = *s;
|
||||||
|
|
||||||
|
if (!(c != NUL
|
||||||
|
&& (vim_isbreak(c) || col2 == col || !vim_isbreak((int)(*ps))))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
col2 += win_chartabsize(wp, s, col2);
|
||||||
|
|
||||||
|
if (col2 >= colmax) { // doesn't fit
|
||||||
|
size = colmax - col + col_adj;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ((size == 2)
|
||||||
|
&& (MB_BYTE2LEN(*s) > 1)
|
||||||
|
&& wp->w_p_wrap
|
||||||
|
&& in_win_border(wp, col)) {
|
||||||
|
// Count the ">" in the last column.
|
||||||
|
size++;
|
||||||
|
mb_added = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// May have to add something for 'breakindent' and/or 'showbreak'
|
||||||
|
// string at start of line.
|
||||||
|
// Set *headp to the size of what we add.
|
||||||
|
added = 0;
|
||||||
|
|
||||||
|
if ((*p_sbr != NUL || wp->w_p_bri) && wp->w_p_wrap && (col != 0)) {
|
||||||
|
colnr_T sbrlen = 0;
|
||||||
|
int numberwidth = win_col_off(wp);
|
||||||
|
|
||||||
|
numberextra = numberwidth;
|
||||||
|
col += numberextra + mb_added;
|
||||||
|
|
||||||
|
if (col >= (colnr_T)wp->w_width_inner) {
|
||||||
|
col -= wp->w_width_inner;
|
||||||
|
numberextra = wp->w_width_inner - (numberextra - win_col_off2(wp));
|
||||||
|
if (col >= numberextra && numberextra > 0) {
|
||||||
|
col %= numberextra;
|
||||||
|
}
|
||||||
|
if (*p_sbr != NUL) {
|
||||||
|
sbrlen = (colnr_T)MB_CHARLEN(p_sbr);
|
||||||
|
if (col >= sbrlen) {
|
||||||
|
col -= sbrlen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (col >= numberextra && numberextra > 0) {
|
||||||
|
col %= numberextra;
|
||||||
|
} else if (col > 0 && numberextra > 0) {
|
||||||
|
col += numberwidth - win_col_off2(wp);
|
||||||
|
}
|
||||||
|
|
||||||
|
numberwidth -= win_col_off2(wp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (col == 0 || (col + size + sbrlen > (colnr_T)wp->w_width_inner)) {
|
||||||
|
if (*p_sbr != NUL) {
|
||||||
|
if (size + sbrlen + numberwidth > (colnr_T)wp->w_width_inner) {
|
||||||
|
// Calculate effective window width.
|
||||||
|
int width = (colnr_T)wp->w_width_inner - sbrlen - numberwidth;
|
||||||
|
int prev_width = col ? ((colnr_T)wp->w_width_inner - (sbrlen + col))
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
if (width <= 0) {
|
||||||
|
width = 1;
|
||||||
|
}
|
||||||
|
added += ((size - prev_width) / width) * vim_strsize(p_sbr);
|
||||||
|
if ((size - prev_width) % width) {
|
||||||
|
// Wrapped, add another length of 'sbr'.
|
||||||
|
added += vim_strsize(p_sbr);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
added += vim_strsize(p_sbr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wp->w_p_bri) {
|
||||||
|
added += get_breakindent_win(wp, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
size += added;
|
||||||
|
if (col != 0) {
|
||||||
|
added = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headp != NULL) {
|
||||||
|
*headp = added + mb_added;
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Like win_lbr_chartabsize(), except that we know 'linebreak' is off and
|
||||||
|
/// 'wrap' is on. This means we need to check for a double-byte character that
|
||||||
|
/// doesn't fit at the end of the screen line.
|
||||||
|
///
|
||||||
|
/// @param wp
|
||||||
|
/// @param s
|
||||||
|
/// @param col
|
||||||
|
/// @param headp
|
||||||
|
///
|
||||||
|
/// @return The number of characters take up on the screen.
|
||||||
|
static int win_nolbr_chartabsize(win_T *wp, char_u *s, colnr_T col, int *headp)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if ((*s == TAB) && (!wp->w_p_list || wp->w_p_lcs_chars.tab1)) {
|
||||||
|
return tabstop_padding(col,
|
||||||
|
wp->w_buffer->b_p_ts,
|
||||||
|
wp->w_buffer->b_p_vts_array);
|
||||||
|
}
|
||||||
|
n = ptr2cells(s);
|
||||||
|
|
||||||
|
// Add one cell for a double-width character in the last column of the
|
||||||
|
// window, displayed with a ">".
|
||||||
|
if ((n == 2) && (MB_BYTE2LEN(*s) > 1) && in_win_border(wp, col)) {
|
||||||
|
if (headp != NULL) {
|
||||||
|
*headp = 1;
|
||||||
|
}
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
9
src/nvim/plines.h
Normal file
9
src/nvim/plines.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#ifndef NVIM_PLINES_H
|
||||||
|
#define NVIM_PLINES_H
|
||||||
|
|
||||||
|
#include "nvim/vim.h"
|
||||||
|
|
||||||
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
|
# include "plines.h.generated.h"
|
||||||
|
#endif
|
||||||
|
#endif // NVIM_PLINES_H
|
@ -63,6 +63,7 @@
|
|||||||
#include "nvim/memory.h"
|
#include "nvim/memory.h"
|
||||||
#include "nvim/message.h"
|
#include "nvim/message.h"
|
||||||
#include "nvim/misc1.h"
|
#include "nvim/misc1.h"
|
||||||
|
#include "nvim/plines.h"
|
||||||
#include "nvim/garray.h"
|
#include "nvim/garray.h"
|
||||||
#include "nvim/strings.h"
|
#include "nvim/strings.h"
|
||||||
|
|
||||||
|
@ -101,6 +101,7 @@
|
|||||||
#include "nvim/option.h"
|
#include "nvim/option.h"
|
||||||
#include "nvim/os_unix.h"
|
#include "nvim/os_unix.h"
|
||||||
#include "nvim/path.h"
|
#include "nvim/path.h"
|
||||||
|
#include "nvim/plines.h"
|
||||||
#include "nvim/popupmnu.h"
|
#include "nvim/popupmnu.h"
|
||||||
#include "nvim/quickfix.h"
|
#include "nvim/quickfix.h"
|
||||||
#include "nvim/regexp.h"
|
#include "nvim/regexp.h"
|
||||||
@ -1694,7 +1695,7 @@ static void win_update(win_T *wp, Providers *providers)
|
|||||||
/*
|
/*
|
||||||
* There is a trick with w_botline. If we invalidate it on each
|
* There is a trick with w_botline. If we invalidate it on each
|
||||||
* change that might modify it, this will cause a lot of expensive
|
* change that might modify it, this will cause a lot of expensive
|
||||||
* calls to plines() in update_topline() each time. Therefore the
|
* calls to plines_win() in update_topline() each time. Therefore the
|
||||||
* value of w_botline is often approximated, and this value is used to
|
* value of w_botline is often approximated, and this value is used to
|
||||||
* compute the value of w_topline. If the value of w_botline was
|
* compute the value of w_topline. If the value of w_botline was
|
||||||
* wrong, check that the value of w_topline is correct (cursor is on
|
* wrong, check that the value of w_topline is correct (cursor is on
|
||||||
@ -4119,7 +4120,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Update w_cline_height and w_cline_folded if the cursor line was
|
* Update w_cline_height and w_cline_folded if the cursor line was
|
||||||
* updated (saves a call to plines() later).
|
* updated (saves a call to plines_win() later).
|
||||||
*/
|
*/
|
||||||
if (wp == curwin && lnum == curwin->w_cursor.lnum) {
|
if (wp == curwin && lnum == curwin->w_cursor.lnum) {
|
||||||
curwin->w_cline_row = startrow;
|
curwin->w_cline_row = startrow;
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "nvim/memory.h"
|
#include "nvim/memory.h"
|
||||||
#include "nvim/message.h"
|
#include "nvim/message.h"
|
||||||
#include "nvim/misc1.h"
|
#include "nvim/misc1.h"
|
||||||
|
#include "nvim/plines.h"
|
||||||
#include "nvim/file_search.h"
|
#include "nvim/file_search.h"
|
||||||
#include "nvim/garray.h"
|
#include "nvim/garray.h"
|
||||||
#include "nvim/move.h"
|
#include "nvim/move.h"
|
||||||
|
Loading…
Reference in New Issue
Block a user