mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge pull request #19975 from bfredl/chartabsize
refactor(plines): use a struct for chartabsize state
This commit is contained in:
commit
f05cc672e3
@ -653,9 +653,9 @@ void ins_char_bytes(char_u *buf, size_t charlen)
|
||||
// cells. May result in adding spaces to fill a gap.
|
||||
colnr_T vcol;
|
||||
getvcol(curwin, &curwin->w_cursor, NULL, &vcol, NULL);
|
||||
colnr_T new_vcol = vcol + win_chartabsize(curwin, buf, vcol);
|
||||
colnr_T new_vcol = vcol + win_chartabsize(curwin, (char *)buf, vcol);
|
||||
while (oldp[col + oldlen] != NUL && vcol < new_vcol) {
|
||||
vcol += win_chartabsize(curwin, oldp + col + oldlen, vcol);
|
||||
vcol += win_chartabsize(curwin, (char *)oldp + col + oldlen, vcol);
|
||||
// Don't need to remove a TAB that takes us to the right
|
||||
// position.
|
||||
if (vcol > new_vcol && oldp[col + oldlen] == TAB) {
|
||||
|
@ -930,14 +930,18 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *en
|
||||
posptr -= utf_head_off(line, posptr);
|
||||
}
|
||||
|
||||
chartabsize_T cts;
|
||||
init_chartabsize_arg(&cts, wp, pos->lnum, 0, line, line);
|
||||
|
||||
// This function is used very often, do some speed optimizations.
|
||||
// When 'list', 'linebreak', 'showbreak' and 'breakindent' are not set
|
||||
// use a simple loop.
|
||||
// and there are no virtual text use a simple loop.
|
||||
// Also use this when 'list' is set but tabs take their normal size.
|
||||
if ((!wp->w_p_list || (wp->w_p_lcs_chars.tab1 != NUL))
|
||||
&& !wp->w_p_lbr
|
||||
&& *get_showbreak_value(wp) == NUL
|
||||
&& !wp->w_p_bri) {
|
||||
&& !wp->w_p_bri
|
||||
&& !cts.cts_has_virt_text) {
|
||||
for (;;) {
|
||||
head = 0;
|
||||
int c = *ptr;
|
||||
@ -984,25 +988,29 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *en
|
||||
} else {
|
||||
for (;;) {
|
||||
// A tab gets expanded, depending on the current column
|
||||
// Other things also take up space.
|
||||
head = 0;
|
||||
incr = win_lbr_chartabsize(wp, line, ptr, vcol, &head);
|
||||
incr = win_lbr_chartabsize(&cts, &head);
|
||||
|
||||
// make sure we don't go past the end of the line
|
||||
if (*ptr == NUL) {
|
||||
if (*cts.cts_ptr == NUL) {
|
||||
// NUL at end of line only takes one column
|
||||
incr = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((posptr != NULL) && (ptr >= posptr)) {
|
||||
if ((posptr != NULL) && ((char_u *)cts.cts_ptr >= posptr)) {
|
||||
// character at pos->col
|
||||
break;
|
||||
}
|
||||
|
||||
vcol += incr;
|
||||
MB_PTR_ADV(ptr);
|
||||
cts.cts_vcol += incr;
|
||||
MB_PTR_ADV(cts.cts_ptr);
|
||||
}
|
||||
vcol = cts.cts_vcol;
|
||||
ptr = (char_u *)cts.cts_ptr;
|
||||
}
|
||||
clear_chartabsize_arg(&cts);
|
||||
|
||||
if (start != NULL) {
|
||||
*start = vcol + head;
|
||||
@ -1013,6 +1021,8 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *en
|
||||
}
|
||||
|
||||
if (cursor != NULL) {
|
||||
// cursor is after inserted text
|
||||
vcol += cts.cts_cur_text_width;
|
||||
if ((*ptr == TAB)
|
||||
&& (State & MODE_NORMAL)
|
||||
&& !wp->w_p_list
|
||||
|
@ -137,14 +137,18 @@ static int coladvance2(pos_T *pos, bool addspaces, bool finetune, colnr_T wcol_a
|
||||
}
|
||||
}
|
||||
|
||||
char_u *ptr = line;
|
||||
while (col <= wcol && *ptr != NUL) {
|
||||
chartabsize_T cts;
|
||||
init_chartabsize_arg(&cts, curwin, pos->lnum, 0, line, line);
|
||||
while (cts.cts_vcol <= wcol && *cts.cts_ptr != NUL) {
|
||||
// Count a tab for what it's worth (if list mode not on)
|
||||
csize = win_lbr_chartabsize(curwin, line, ptr, col, &head);
|
||||
MB_PTR_ADV(ptr);
|
||||
col += csize;
|
||||
csize = win_lbr_chartabsize(&cts, &head);
|
||||
MB_PTR_ADV(cts.cts_ptr);
|
||||
cts.cts_vcol += csize;
|
||||
}
|
||||
idx = (int)(ptr - line);
|
||||
col = cts.cts_vcol;
|
||||
idx = (int)(cts.cts_ptr - (char *)line);
|
||||
clear_chartabsize_arg(&cts);
|
||||
|
||||
// Handle all the special cases. The virtual_active() check
|
||||
// is needed to ensure that a virtual position off the end of
|
||||
// a line has the correct indexing. The one_more comparison
|
||||
|
@ -940,12 +940,19 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|
||||
}
|
||||
if (v > 0 && !number_only) {
|
||||
char_u *prev_ptr = ptr;
|
||||
while (vcol < v && *ptr != NUL) {
|
||||
c = win_lbr_chartabsize(wp, line, ptr, (colnr_T)vcol, NULL);
|
||||
vcol += c;
|
||||
prev_ptr = ptr;
|
||||
MB_PTR_ADV(ptr);
|
||||
chartabsize_T cts;
|
||||
int charsize;
|
||||
|
||||
init_chartabsize_arg(&cts, wp, lnum, (colnr_T)vcol, line, ptr);
|
||||
while (cts.cts_vcol < v && *cts.cts_ptr != NUL) {
|
||||
charsize = win_lbr_chartabsize(&cts, NULL);
|
||||
cts.cts_vcol += charsize;
|
||||
prev_ptr = (char_u *)cts.cts_ptr;
|
||||
MB_PTR_ADV(cts.cts_ptr);
|
||||
}
|
||||
vcol = cts.cts_vcol;
|
||||
ptr = (char_u *)cts.cts_ptr;
|
||||
clear_chartabsize_arg(&cts);
|
||||
|
||||
// When:
|
||||
// - 'cuc' is set, or
|
||||
@ -963,11 +970,11 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|
||||
// Handle a character that's not completely on the screen: Put ptr at
|
||||
// that character but skip the first few screen characters.
|
||||
if (vcol > v) {
|
||||
vcol -= c;
|
||||
vcol -= charsize;
|
||||
ptr = prev_ptr;
|
||||
// If the character fits on the screen, don't need to skip it.
|
||||
// Except for a TAB.
|
||||
if (utf_ptr2cells((char *)ptr) >= c || *ptr == TAB) {
|
||||
if (utf_ptr2cells((char *)ptr) >= charsize || *ptr == TAB) {
|
||||
n_skip = (int)(v - vcol);
|
||||
}
|
||||
}
|
||||
@ -1798,8 +1805,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|
||||
&& !vim_isbreak((int)(*ptr))) {
|
||||
int mb_off = utf_head_off(line, ptr - 1);
|
||||
char_u *p = ptr - (mb_off + 1);
|
||||
// TODO(neovim): is passing p for start of the line OK?
|
||||
n_extra = win_lbr_chartabsize(wp, line, p, (colnr_T)vcol, NULL) - 1;
|
||||
chartabsize_T cts;
|
||||
|
||||
init_chartabsize_arg(&cts, wp, lnum, (colnr_T)vcol, line, p);
|
||||
n_extra = win_lbr_chartabsize(&cts, NULL) - 1;
|
||||
|
||||
// We have just drawn the showbreak value, no need to add
|
||||
// space for it again.
|
||||
@ -1825,6 +1834,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|
||||
c = ' ';
|
||||
}
|
||||
}
|
||||
clear_chartabsize_arg(&cts);
|
||||
}
|
||||
|
||||
in_multispace = c == ' ' && ((ptr > line + 1 && ptr[-2] == ' ') || *ptr == ' ');
|
||||
|
@ -1665,28 +1665,28 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang
|
||||
} else if (!(State & MODE_INSERT)) {
|
||||
new_cursor_col = curwin->w_cursor.col;
|
||||
} else {
|
||||
/*
|
||||
* Compute the screen column where the cursor should be.
|
||||
*/
|
||||
// Compute the screen column where the cursor should be.
|
||||
vcol = get_indent() - vcol;
|
||||
curwin->w_virtcol = (colnr_T)((vcol < 0) ? 0 : vcol);
|
||||
|
||||
/*
|
||||
* Advance the cursor until we reach the right screen column.
|
||||
*/
|
||||
vcol = last_vcol = 0;
|
||||
new_cursor_col = -1;
|
||||
// Advance the cursor until we reach the right screen column.
|
||||
last_vcol = 0;
|
||||
ptr = get_cursor_line_ptr();
|
||||
while (vcol <= (int)curwin->w_virtcol) {
|
||||
last_vcol = vcol;
|
||||
if (new_cursor_col >= 0) {
|
||||
new_cursor_col += utfc_ptr2len((char *)ptr + new_cursor_col);
|
||||
} else {
|
||||
new_cursor_col++;
|
||||
chartabsize_T cts;
|
||||
init_chartabsize_arg(&cts, curwin, 0, 0, ptr, ptr);
|
||||
while (cts.cts_vcol <= (int)curwin->w_virtcol) {
|
||||
last_vcol = cts.cts_vcol;
|
||||
if (cts.cts_vcol > 0) {
|
||||
MB_PTR_ADV(cts.cts_ptr);
|
||||
}
|
||||
vcol += lbr_chartabsize(ptr, ptr + new_cursor_col, (colnr_T)vcol);
|
||||
if (*cts.cts_ptr == NUL) {
|
||||
break;
|
||||
}
|
||||
cts.cts_vcol += lbr_chartabsize(&cts);
|
||||
}
|
||||
vcol = last_vcol;
|
||||
new_cursor_col = (int)(cts.cts_ptr - cts.cts_line);
|
||||
clear_chartabsize_arg(&cts);
|
||||
|
||||
/*
|
||||
* May need to insert spaces to be able to position the cursor on
|
||||
@ -2991,7 +2991,7 @@ static void replace_do_bs(int limit_col)
|
||||
// Get the number of screen cells used by the character we are
|
||||
// going to delete.
|
||||
getvcol(curwin, &curwin->w_cursor, NULL, &start_vcol, NULL);
|
||||
orig_vcols = win_chartabsize(curwin, get_cursor_pos_ptr(), start_vcol);
|
||||
orig_vcols = win_chartabsize(curwin, (char *)get_cursor_pos_ptr(), start_vcol);
|
||||
}
|
||||
(void)del_char_after_col(limit_col);
|
||||
if (l_State & VREPLACE_FLAG) {
|
||||
@ -3006,7 +3006,7 @@ static void replace_do_bs(int limit_col)
|
||||
ins_len = (int)STRLEN(p) - orig_len;
|
||||
vcol = start_vcol;
|
||||
for (i = 0; i < ins_len; i++) {
|
||||
vcol += win_chartabsize(curwin, p + i, vcol);
|
||||
vcol += win_chartabsize(curwin, (char *)p + i, vcol);
|
||||
i += utfc_ptr2len((char *)p) - 1;
|
||||
}
|
||||
vcol -= start_vcol;
|
||||
@ -4644,11 +4644,15 @@ static bool ins_tab(void)
|
||||
getvcol(curwin, &fpos, &vcol, NULL, NULL);
|
||||
getvcol(curwin, cursor, &want_vcol, NULL, NULL);
|
||||
|
||||
char_u *tab = (char_u *)"\t";
|
||||
chartabsize_T cts;
|
||||
init_chartabsize_arg(&cts, curwin, 0, vcol, tab, tab);
|
||||
|
||||
// Use as many TABs as possible. Beware of 'breakindent', 'showbreak'
|
||||
// and 'linebreak' adding extra virtual columns.
|
||||
while (ascii_iswhite(*ptr)) {
|
||||
i = lbr_chartabsize(NULL, (char_u *)"\t", vcol);
|
||||
if (vcol + i > want_vcol) {
|
||||
i = lbr_chartabsize(&cts);
|
||||
if (cts.cts_vcol + i > want_vcol) {
|
||||
break;
|
||||
}
|
||||
if (*ptr != TAB) {
|
||||
@ -4663,19 +4667,24 @@ static bool ins_tab(void)
|
||||
}
|
||||
fpos.col++;
|
||||
ptr++;
|
||||
vcol += i;
|
||||
cts.cts_vcol += i;
|
||||
}
|
||||
vcol = cts.cts_vcol;
|
||||
clear_chartabsize_arg(&cts);
|
||||
|
||||
if (change_col >= 0) {
|
||||
int repl_off = 0;
|
||||
char_u *line = ptr;
|
||||
|
||||
// Skip over the spaces we need.
|
||||
while (vcol < want_vcol && *ptr == ' ') {
|
||||
vcol += lbr_chartabsize(line, ptr, vcol);
|
||||
ptr++;
|
||||
init_chartabsize_arg(&cts, curwin, 0, vcol, ptr, ptr);
|
||||
while (cts.cts_vcol < want_vcol && *cts.cts_ptr == ' ') {
|
||||
cts.cts_vcol += lbr_chartabsize(&cts);
|
||||
cts.cts_ptr++;
|
||||
repl_off++;
|
||||
}
|
||||
ptr = (char_u *)cts.cts_ptr;
|
||||
vcol = cts.cts_vcol;
|
||||
clear_chartabsize_arg(&cts);
|
||||
|
||||
if (vcol > want_vcol) {
|
||||
// Must have a char with 'showbreak' just before it.
|
||||
ptr--;
|
||||
@ -4855,7 +4864,6 @@ static int ins_digraph(void)
|
||||
int ins_copychar(linenr_T lnum)
|
||||
{
|
||||
int c;
|
||||
int temp;
|
||||
char_u *ptr, *prev_ptr;
|
||||
char_u *line;
|
||||
|
||||
@ -4865,17 +4873,23 @@ int ins_copychar(linenr_T lnum)
|
||||
}
|
||||
|
||||
// try to advance to the cursor column
|
||||
temp = 0;
|
||||
line = ptr = ml_get(lnum);
|
||||
prev_ptr = ptr;
|
||||
line = ml_get(lnum);
|
||||
prev_ptr = line;
|
||||
validate_virtcol();
|
||||
while ((colnr_T)temp < curwin->w_virtcol && *ptr != NUL) {
|
||||
prev_ptr = ptr;
|
||||
temp += lbr_chartabsize_adv(line, &ptr, (colnr_T)temp);
|
||||
|
||||
chartabsize_T cts;
|
||||
init_chartabsize_arg(&cts, curwin, lnum, 0, line, line);
|
||||
while (cts.cts_vcol < curwin->w_virtcol && *cts.cts_ptr != NUL) {
|
||||
prev_ptr = (char_u *)cts.cts_ptr;
|
||||
cts.cts_vcol += lbr_chartabsize_adv(&cts);
|
||||
}
|
||||
if ((colnr_T)temp > curwin->w_virtcol) {
|
||||
|
||||
if (cts.cts_vcol > curwin->w_virtcol) {
|
||||
ptr = prev_ptr;
|
||||
} else {
|
||||
ptr = (char_u *)cts.cts_ptr;
|
||||
}
|
||||
clear_chartabsize_arg(&cts);
|
||||
|
||||
c = utf_ptr2char((char *)ptr);
|
||||
if (c == NUL) {
|
||||
|
@ -849,11 +849,11 @@ static void get_col(typval_T *argvars, typval_T *rettv, bool charcol)
|
||||
// col(".") when the cursor is on the NUL at the end of the line
|
||||
// because of "coladd" can be seen as an extra column.
|
||||
if (virtual_active() && fp == &curwin->w_cursor) {
|
||||
char_u *p = get_cursor_pos_ptr();
|
||||
char *p = (char *)get_cursor_pos_ptr();
|
||||
if (curwin->w_cursor.coladd >=
|
||||
(colnr_T)win_chartabsize(curwin, p, curwin->w_virtcol - curwin->w_cursor.coladd)) {
|
||||
int l;
|
||||
if (*p != NUL && p[(l = utfc_ptr2len((char *)p))] == NUL) {
|
||||
if (*p != NUL && p[(l = utfc_ptr2len(p))] == NUL) {
|
||||
col += l;
|
||||
}
|
||||
}
|
||||
@ -8537,7 +8537,7 @@ static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv, EvalFuncData f
|
||||
col = (int)tv_get_number(&argvars[1]);
|
||||
}
|
||||
|
||||
rettv->vval.v_number = (varnumber_T)(linetabsize_col(col, (char_u *)s) - col);
|
||||
rettv->vval.v_number = (varnumber_T)(linetabsize_col(col, (char *)s) - col);
|
||||
}
|
||||
|
||||
/// "strwidth()" function
|
||||
|
@ -841,7 +841,7 @@ void ex_retab(exarg_T *eap)
|
||||
if (ptr[col] == NUL) {
|
||||
break;
|
||||
}
|
||||
vcol += win_chartabsize(curwin, (char_u *)ptr + col, (colnr_T)vcol);
|
||||
vcol += win_chartabsize(curwin, ptr + col, (colnr_T)vcol);
|
||||
if (vcol >= MAXCOL) {
|
||||
emsg(_(e_resulting_text_too_long));
|
||||
break;
|
||||
|
@ -2547,7 +2547,7 @@ static int vgetorpeek(bool advance)
|
||||
&& (State & MODE_INSERT)
|
||||
&& (p_timeout || (keylen == KEYLEN_PART_KEY && p_ttimeout))
|
||||
&& (c = inchar(typebuf.tb_buf + typebuf.tb_off + typebuf.tb_len, 3, 25L)) == 0) {
|
||||
colnr_T col = 0, vcol;
|
||||
colnr_T col = 0;
|
||||
char_u *ptr;
|
||||
|
||||
if (mode_displayed) {
|
||||
@ -2565,15 +2565,20 @@ static int vgetorpeek(bool advance)
|
||||
// We are expecting to truncate the trailing
|
||||
// white-space, so find the last non-white
|
||||
// character -- webb
|
||||
col = vcol = curwin->w_wcol = 0;
|
||||
curwin->w_wcol = 0;
|
||||
ptr = get_cursor_line_ptr();
|
||||
while (col < curwin->w_cursor.col) {
|
||||
if (!ascii_iswhite(ptr[col])) {
|
||||
curwin->w_wcol = vcol;
|
||||
chartabsize_T cts;
|
||||
init_chartabsize_arg(&cts, curwin,
|
||||
curwin->w_cursor.lnum, 0, ptr, ptr);
|
||||
while ((char_u *)cts.cts_ptr < ptr + curwin->w_cursor.col) {
|
||||
if (!ascii_iswhite(*cts.cts_ptr)) {
|
||||
curwin->w_wcol = cts.cts_vcol;
|
||||
}
|
||||
vcol += lbr_chartabsize(ptr, ptr + col, vcol);
|
||||
col += utfc_ptr2len((char *)ptr + col);
|
||||
cts.cts_vcol += lbr_chartabsize(&cts);
|
||||
cts.cts_ptr += utfc_ptr2len(cts.cts_ptr);
|
||||
}
|
||||
clear_chartabsize_arg(&cts);
|
||||
|
||||
curwin->w_wrow = curwin->w_cline_row
|
||||
+ curwin->w_wcol / curwin->w_width_inner;
|
||||
curwin->w_wcol %= curwin->w_width_inner;
|
||||
|
@ -1034,13 +1034,15 @@ int get_lisp_indent(void)
|
||||
amount = 2;
|
||||
} else {
|
||||
char_u *line = that;
|
||||
|
||||
amount = 0;
|
||||
|
||||
while (*that && col) {
|
||||
amount += lbr_chartabsize_adv(line, &that, (colnr_T)amount);
|
||||
chartabsize_T cts;
|
||||
init_chartabsize_arg(&cts, curwin, pos->lnum, 0, line, line);
|
||||
while (*cts.cts_ptr != NUL && col > 0) {
|
||||
cts.cts_vcol += lbr_chartabsize_adv(&cts);
|
||||
col--;
|
||||
}
|
||||
amount = cts.cts_vcol;
|
||||
that = (char_u *)cts.cts_ptr;
|
||||
clear_chartabsize_arg(&cts);
|
||||
|
||||
// Some keywords require "body" indenting rules (the
|
||||
// non-standard-lisp ones are Scheme special forms):
|
||||
@ -1056,10 +1058,15 @@ int get_lisp_indent(void)
|
||||
}
|
||||
firsttry = amount;
|
||||
|
||||
while (ascii_iswhite(*that)) {
|
||||
amount += lbr_chartabsize(line, that, (colnr_T)amount);
|
||||
that++;
|
||||
init_chartabsize_arg(&cts, curwin, (colnr_T)(that - line),
|
||||
amount, line, that);
|
||||
while (ascii_iswhite(*cts.cts_ptr)) {
|
||||
cts.cts_vcol += lbr_chartabsize(&cts);
|
||||
cts.cts_ptr++;
|
||||
}
|
||||
that = (char_u *)cts.cts_ptr;
|
||||
amount = cts.cts_vcol;
|
||||
clear_chartabsize_arg(&cts);
|
||||
|
||||
if (*that && (*that != ';')) {
|
||||
// Not a comment line.
|
||||
@ -1072,33 +1079,38 @@ int get_lisp_indent(void)
|
||||
parencount = 0;
|
||||
quotecount = 0;
|
||||
|
||||
init_chartabsize_arg(&cts, curwin,
|
||||
(colnr_T)(that - line), amount, line, that);
|
||||
if (vi_lisp || ((*that != '"') && (*that != '\'')
|
||||
&& (*that != '#') && ((*that < '0') || (*that > '9')))) {
|
||||
while (*that
|
||||
&& (!ascii_iswhite(*that) || quotecount || parencount)
|
||||
&& (!((*that == '(' || *that == '[')
|
||||
while (*cts.cts_ptr
|
||||
&& (!ascii_iswhite(*cts.cts_ptr) || quotecount || parencount)
|
||||
&& (!((*cts.cts_ptr == '(' || *cts.cts_ptr == '[')
|
||||
&& !quotecount && !parencount && vi_lisp))) {
|
||||
if (*that == '"') {
|
||||
if (*cts.cts_ptr == '"') {
|
||||
quotecount = !quotecount;
|
||||
}
|
||||
if (((*that == '(') || (*that == '[')) && !quotecount) {
|
||||
if (((*cts.cts_ptr == '(') || (*cts.cts_ptr == '[')) && !quotecount) {
|
||||
parencount++;
|
||||
}
|
||||
if (((*that == ')') || (*that == ']')) && !quotecount) {
|
||||
if (((*cts.cts_ptr == ')') || (*cts.cts_ptr == ']')) && !quotecount) {
|
||||
parencount--;
|
||||
}
|
||||
if ((*that == '\\') && (*(that + 1) != NUL)) {
|
||||
amount += lbr_chartabsize_adv(line, &that, (colnr_T)amount);
|
||||
if ((*cts.cts_ptr == '\\') && (*(cts.cts_ptr + 1) != NUL)) {
|
||||
cts.cts_vcol += lbr_chartabsize_adv(&cts);
|
||||
}
|
||||
|
||||
amount += lbr_chartabsize_adv(line, &that, (colnr_T)amount);
|
||||
cts.cts_vcol += lbr_chartabsize_adv(&cts);
|
||||
}
|
||||
}
|
||||
|
||||
while (ascii_iswhite(*that)) {
|
||||
amount += lbr_chartabsize(line, that, (colnr_T)amount);
|
||||
that++;
|
||||
while (ascii_iswhite(*cts.cts_ptr)) {
|
||||
cts.cts_vcol += lbr_chartabsize(&cts);
|
||||
cts.cts_ptr++;
|
||||
}
|
||||
that = (char_u *)cts.cts_ptr;
|
||||
amount = cts.cts_vcol;
|
||||
clear_chartabsize_arg(&cts);
|
||||
|
||||
if (!*that || (*that == ';')) {
|
||||
amount = firsttry;
|
||||
|
@ -631,14 +631,16 @@ colnr_T vcol2col(win_T *const wp, const linenr_T lnum, const colnr_T vcol)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
// try to advance to the specified column
|
||||
char_u *ptr = ml_get_buf(wp->w_buffer, lnum, false);
|
||||
char_u *const line = ptr;
|
||||
colnr_T count = 0;
|
||||
while (count < vcol && *ptr != NUL) {
|
||||
count += win_lbr_chartabsize(wp, line, ptr, count, NULL);
|
||||
MB_PTR_ADV(ptr);
|
||||
char_u *line = ml_get_buf(wp->w_buffer, lnum, false);
|
||||
chartabsize_T cts;
|
||||
init_chartabsize_arg(&cts, wp, lnum, 0, line, line);
|
||||
while (cts.cts_vcol < vcol && *cts.cts_ptr != NUL) {
|
||||
cts.cts_vcol += win_lbr_chartabsize(&cts, NULL);
|
||||
MB_PTR_ADV(cts.cts_ptr);
|
||||
}
|
||||
return (colnr_T)(ptr - line);
|
||||
clear_chartabsize_arg(&cts);
|
||||
|
||||
return (colnr_T)((char_u *)cts.cts_ptr - line);
|
||||
}
|
||||
|
||||
/// Set UI mouse depending on current mode and 'mouse'.
|
||||
@ -667,7 +669,7 @@ static colnr_T scroll_line_len(linenr_T lnum)
|
||||
char_u *line = ml_get(lnum);
|
||||
if (*line != NUL) {
|
||||
for (;;) {
|
||||
int numchar = win_chartabsize(curwin, line, col);
|
||||
int numchar = win_chartabsize(curwin, (char *)line, col);
|
||||
MB_PTR_ADV(line);
|
||||
if (*line == NUL) { // don't count the last character
|
||||
break;
|
||||
@ -790,7 +792,7 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
|
||||
// checked for concealed characters.
|
||||
vcol = 0;
|
||||
while (vcol < offset && *ptr != NUL) {
|
||||
vcol += win_chartabsize(curwin, ptr, vcol);
|
||||
vcol += win_chartabsize(curwin, (char *)ptr, vcol);
|
||||
ptr += utfc_ptr2len((char *)ptr);
|
||||
}
|
||||
|
||||
@ -801,7 +803,7 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
|
||||
vcol = offset;
|
||||
ptr_end = ptr_row_offset;
|
||||
while (vcol < col && *ptr_end != NUL) {
|
||||
vcol += win_chartabsize(curwin, ptr_end, vcol);
|
||||
vcol += win_chartabsize(curwin, (char *)ptr_end, vcol);
|
||||
ptr_end += utfc_ptr2len((char *)ptr_end);
|
||||
}
|
||||
|
||||
@ -816,7 +818,7 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
|
||||
#define DECR() nudge--; ptr_end -= utfc_ptr2len((char *)ptr_end)
|
||||
|
||||
while (ptr < ptr_end && *ptr != NUL) {
|
||||
cwidth = win_chartabsize(curwin, ptr, vcol);
|
||||
cwidth = win_chartabsize(curwin, (char *)ptr, vcol);
|
||||
vcol += cwidth;
|
||||
if (cwidth > 1 && *ptr == '\t' && nudge > 0) {
|
||||
// A tab will "absorb" any previous adjustments.
|
||||
|
101
src/nvim/ops.c
101
src/nvim/ops.c
@ -378,12 +378,20 @@ static void shift_block(oparg_T *oap, int amount)
|
||||
bd.startspaces = 0;
|
||||
}
|
||||
}
|
||||
for (; ascii_iswhite(*bd.textstart);) {
|
||||
// TODO(fmoralesc): is passing bd.textstart for start of the line OK?
|
||||
incr = lbr_chartabsize_adv(bd.textstart, &bd.textstart, bd.start_vcol);
|
||||
|
||||
// TODO(vim): is passing bd.textstart for start of the line OK?
|
||||
chartabsize_T cts;
|
||||
init_chartabsize_arg(&cts, curwin, curwin->w_cursor.lnum,
|
||||
bd.start_vcol, bd.textstart, bd.textstart);
|
||||
while (ascii_iswhite(*cts.cts_ptr)) {
|
||||
incr = lbr_chartabsize_adv(&cts);
|
||||
total += incr;
|
||||
bd.start_vcol += incr;
|
||||
cts.cts_vcol += incr;
|
||||
}
|
||||
bd.textstart = (char_u *)cts.cts_ptr;
|
||||
bd.start_vcol = cts.cts_vcol;
|
||||
clear_chartabsize_arg(&cts);
|
||||
|
||||
// OK, now total=all the VWS reqd, and textstart points at the 1st
|
||||
// non-ws char in the block.
|
||||
if (!curbuf->b_p_et) {
|
||||
@ -438,10 +446,16 @@ static void shift_block(oparg_T *oap, int amount)
|
||||
// The character's column is in "bd.start_vcol".
|
||||
colnr_T non_white_col = bd.start_vcol;
|
||||
|
||||
while (ascii_iswhite(*non_white)) {
|
||||
incr = lbr_chartabsize_adv(bd.textstart, &non_white, non_white_col);
|
||||
non_white_col += incr;
|
||||
chartabsize_T cts;
|
||||
init_chartabsize_arg(&cts, curwin, curwin->w_cursor.lnum,
|
||||
non_white_col, bd.textstart, non_white);
|
||||
while (ascii_iswhite(*cts.cts_ptr)) {
|
||||
incr = lbr_chartabsize_adv(&cts);
|
||||
cts.cts_vcol += incr;
|
||||
}
|
||||
non_white_col = cts.cts_vcol;
|
||||
non_white = (char_u *)cts.cts_ptr;
|
||||
clear_chartabsize_arg(&cts);
|
||||
|
||||
const colnr_T block_space_width = non_white_col - oap->start_vcol;
|
||||
// We will shift by "total" or "block_space_width", whichever is less.
|
||||
@ -462,17 +476,19 @@ static void shift_block(oparg_T *oap, int amount)
|
||||
if (bd.startspaces) {
|
||||
verbatim_copy_width -= bd.start_char_vcols;
|
||||
}
|
||||
while (verbatim_copy_width < destination_col) {
|
||||
char_u *line = verbatim_copy_end;
|
||||
|
||||
// TODO: is passing verbatim_copy_end for start of the line OK?
|
||||
incr = lbr_chartabsize(line, verbatim_copy_end, verbatim_copy_width);
|
||||
if (verbatim_copy_width + incr > destination_col) {
|
||||
init_chartabsize_arg(&cts, curwin, 0, verbatim_copy_width,
|
||||
bd.textstart, verbatim_copy_end);
|
||||
while (cts.cts_vcol < destination_col) {
|
||||
incr = lbr_chartabsize(&cts);
|
||||
if (cts.cts_vcol + incr > destination_col) {
|
||||
break;
|
||||
}
|
||||
verbatim_copy_width += incr;
|
||||
MB_PTR_ADV(verbatim_copy_end);
|
||||
cts.cts_vcol += incr;
|
||||
MB_PTR_ADV(cts.cts_ptr);
|
||||
}
|
||||
verbatim_copy_width = cts.cts_vcol;
|
||||
verbatim_copy_end = (char_u *)cts.cts_ptr;
|
||||
clear_chartabsize_arg(&cts);
|
||||
|
||||
// If "destination_col" is different from the width of the initial
|
||||
// part of the line that will be copied, it means we encountered a tab
|
||||
@ -1550,6 +1566,7 @@ int op_delete(oparg_T *oap)
|
||||
// Put deleted text into register 1 and shift number registers if the
|
||||
// delete contains a line break, or when using a specific operator (Vi
|
||||
// compatible)
|
||||
|
||||
if (oap->motion_type == kMTLineWise || oap->line_count > 1 || oap->use_reg_one) {
|
||||
shift_delete_registers(is_append_register(oap->regname));
|
||||
reg = &y_regs[1];
|
||||
@ -3280,12 +3297,19 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
|
||||
// get the old line and advance to the position to insert at
|
||||
oldp = get_cursor_line_ptr();
|
||||
oldlen = STRLEN(oldp);
|
||||
for (ptr = oldp; vcol < col && *ptr;) {
|
||||
chartabsize_T cts;
|
||||
init_chartabsize_arg(&cts, curwin, curwin->w_cursor.lnum, 0,
|
||||
oldp, oldp);
|
||||
|
||||
while (cts.cts_vcol < col && *cts.cts_ptr != NUL) {
|
||||
// Count a tab for what it's worth (if list mode not on)
|
||||
incr = lbr_chartabsize_adv(oldp, &ptr, vcol);
|
||||
vcol += incr;
|
||||
incr = lbr_chartabsize_adv(&cts);
|
||||
cts.cts_vcol += incr;
|
||||
}
|
||||
vcol = cts.cts_vcol;
|
||||
ptr = (char_u *)cts.cts_ptr;
|
||||
bd.textcol = (colnr_T)(ptr - oldp);
|
||||
clear_chartabsize_arg(&cts);
|
||||
|
||||
shortline = (vcol < col) || (vcol == col && !*ptr);
|
||||
|
||||
@ -3312,9 +3336,14 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
|
||||
// calculate number of spaces required to fill right side of
|
||||
// block
|
||||
spaces = y_width + 1;
|
||||
init_chartabsize_arg(&cts, curwin, 0, 0,
|
||||
(char_u *)y_array[i], (char_u *)y_array[i]);
|
||||
for (int j = 0; j < yanklen; j++) {
|
||||
spaces -= lbr_chartabsize(NULL, (char_u *)(&y_array[i][j]), 0);
|
||||
spaces -= lbr_chartabsize(&cts);
|
||||
cts.cts_ptr++;
|
||||
cts.cts_vcol = 0;
|
||||
}
|
||||
clear_chartabsize_arg(&cts);
|
||||
if (spaces < 0) {
|
||||
spaces = 0;
|
||||
}
|
||||
@ -4227,22 +4256,28 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, bool
|
||||
bdp->start_char_vcols = 0;
|
||||
|
||||
line = ml_get(lnum);
|
||||
pstart = line;
|
||||
prev_pstart = line;
|
||||
while (bdp->start_vcol < oap->start_vcol && *pstart) {
|
||||
|
||||
chartabsize_T cts;
|
||||
init_chartabsize_arg(&cts, curwin, lnum, bdp->start_vcol, line, line);
|
||||
while (cts.cts_vcol < oap->start_vcol && *cts.cts_ptr != NUL) {
|
||||
// Count a tab for what it's worth (if list mode not on)
|
||||
incr = lbr_chartabsize(line, pstart, bdp->start_vcol);
|
||||
bdp->start_vcol += incr;
|
||||
if (ascii_iswhite(*pstart)) {
|
||||
incr = lbr_chartabsize(&cts);
|
||||
cts.cts_vcol += incr;
|
||||
if (ascii_iswhite(*cts.cts_ptr)) {
|
||||
bdp->pre_whitesp += incr;
|
||||
bdp->pre_whitesp_c++;
|
||||
} else {
|
||||
bdp->pre_whitesp = 0;
|
||||
bdp->pre_whitesp_c = 0;
|
||||
}
|
||||
prev_pstart = pstart;
|
||||
MB_PTR_ADV(pstart);
|
||||
prev_pstart = (char_u *)cts.cts_ptr;
|
||||
MB_PTR_ADV(cts.cts_ptr);
|
||||
}
|
||||
bdp->start_vcol = cts.cts_vcol;
|
||||
pstart = (char_u *)cts.cts_ptr;
|
||||
clear_chartabsize_arg(&cts);
|
||||
|
||||
bdp->start_char_vcols = incr;
|
||||
if (bdp->start_vcol < oap->start_vcol) { // line too short
|
||||
bdp->end_vcol = bdp->start_vcol;
|
||||
@ -4278,13 +4313,19 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, bool
|
||||
}
|
||||
}
|
||||
} else {
|
||||
init_chartabsize_arg(&cts, curwin, lnum, bdp->end_vcol,
|
||||
line, pend);
|
||||
prev_pend = pend;
|
||||
while (bdp->end_vcol <= oap->end_vcol && *pend != NUL) {
|
||||
while (cts.cts_vcol <= oap->end_vcol && *cts.cts_ptr != NUL) {
|
||||
// Count a tab for what it's worth (if list mode not on)
|
||||
prev_pend = pend;
|
||||
incr = lbr_chartabsize_adv(line, &pend, bdp->end_vcol);
|
||||
bdp->end_vcol += incr;
|
||||
prev_pend = (char_u *)cts.cts_ptr;
|
||||
incr = lbr_chartabsize_adv(&cts);
|
||||
cts.cts_vcol += incr;
|
||||
}
|
||||
bdp->end_vcol = cts.cts_vcol;
|
||||
pend = (char_u *)cts.cts_ptr;
|
||||
clear_chartabsize_arg(&cts);
|
||||
|
||||
if (bdp->end_vcol <= oap->end_vcol
|
||||
&& (!is_del
|
||||
|| oap->op_type == OP_APPEND
|
||||
|
@ -98,15 +98,15 @@ int plines_win_nofill(win_T *wp, linenr_T lnum, bool winheight)
|
||||
/// "wp". Does not care about folding, 'wrap' or 'diff'.
|
||||
int plines_win_nofold(win_T *wp, linenr_T lnum)
|
||||
{
|
||||
char_u *s;
|
||||
char *s;
|
||||
unsigned int col;
|
||||
int width;
|
||||
|
||||
s = ml_get_buf(wp->w_buffer, lnum, false);
|
||||
s = (char *)ml_get_buf(wp->w_buffer, lnum, false);
|
||||
if (*s == NUL) { // empty line
|
||||
return 1;
|
||||
}
|
||||
col = win_linetabsize(wp, s, MAXCOL);
|
||||
col = win_linetabsize(wp, lnum, (char_u *)s, MAXCOL);
|
||||
|
||||
// If list mode is on, then the '$' at the end of the line may take up one
|
||||
// extra column.
|
||||
@ -145,23 +145,27 @@ int plines_win_col(win_T *wp, linenr_T lnum, long column)
|
||||
}
|
||||
|
||||
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);
|
||||
chartabsize_T cts;
|
||||
|
||||
init_chartabsize_arg(&cts, wp, lnum, 0, line, line);
|
||||
while (*cts.cts_ptr != NUL && --column >= 0) {
|
||||
cts.cts_vcol += win_lbr_chartabsize(&cts, NULL);
|
||||
MB_PTR_ADV(cts.cts_ptr);
|
||||
}
|
||||
|
||||
// If *s is a TAB, and the TAB is not displayed as ^I, and we're not in
|
||||
// MODE_INSERT state, then col must be adjusted so that it represents the
|
||||
// If *cts.cts_ptr is a TAB, and the TAB is not displayed as ^I, and we're not
|
||||
// in MODE_INSERT state, 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 & MODE_NORMAL)
|
||||
col = cts.cts_vcol;
|
||||
if (*cts.cts_ptr == TAB && (State & MODE_NORMAL)
|
||||
&& (!wp->w_p_list || wp->w_p_lcs_chars.tab1)) {
|
||||
col += win_lbr_chartabsize(wp, line, s, col, NULL) - 1;
|
||||
col += win_lbr_chartabsize(&cts, NULL) - 1;
|
||||
}
|
||||
clear_chartabsize_arg(&cts);
|
||||
|
||||
// Add column offset for 'number', 'relativenumber', 'foldcolumn', etc.
|
||||
int width = wp->w_width_inner - win_col_off(wp);
|
||||
@ -223,7 +227,7 @@ int plines_m_win(win_T *wp, linenr_T first, linenr_T last)
|
||||
/// @param col
|
||||
///
|
||||
/// @return Number of characters.
|
||||
int win_chartabsize(win_T *wp, char_u *p, colnr_T col)
|
||||
int win_chartabsize(win_T *wp, char *p, colnr_T col)
|
||||
{
|
||||
buf_T *buf = wp->w_buffer;
|
||||
if (*p == TAB && (!wp->w_p_list || wp->w_p_lcs_chars.tab1)) {
|
||||
@ -241,24 +245,24 @@ int win_chartabsize(win_T *wp, char_u *p, colnr_T col)
|
||||
/// @return Number of characters the string will take on the screen.
|
||||
int linetabsize(char_u *s)
|
||||
{
|
||||
return linetabsize_col(0, s);
|
||||
return linetabsize_col(0, (char *)s);
|
||||
}
|
||||
|
||||
/// Like linetabsize(), but starting at column "startcol".
|
||||
/// Like linetabsize(), but "s" starts 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)
|
||||
int linetabsize_col(int startcol, char *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);
|
||||
chartabsize_T cts;
|
||||
init_chartabsize_arg(&cts, curwin, 0, startcol, (char_u *)s, (char_u *)s);
|
||||
while (*cts.cts_ptr != NUL) {
|
||||
cts.cts_vcol += lbr_chartabsize_adv(&cts);
|
||||
}
|
||||
return (int)col;
|
||||
clear_chartabsize_arg(&cts);
|
||||
return (int)cts.cts_vcol;
|
||||
}
|
||||
|
||||
/// Like linetabsize(), but for a given window instead of the current one.
|
||||
@ -268,19 +272,39 @@ int linetabsize_col(int startcol, char_u *s)
|
||||
/// @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)
|
||||
unsigned int win_linetabsize(win_T *wp, linenr_T lnum, 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);
|
||||
chartabsize_T cts;
|
||||
init_chartabsize_arg(&cts, wp, lnum, 0, line, line);
|
||||
for (; *cts.cts_ptr != NUL && (len == MAXCOL || cts.cts_ptr < (char *)line + len);
|
||||
MB_PTR_ADV(cts.cts_ptr)) {
|
||||
cts.cts_vcol += win_lbr_chartabsize(&cts, NULL);
|
||||
}
|
||||
|
||||
return (unsigned int)col;
|
||||
clear_chartabsize_arg(&cts);
|
||||
return (unsigned int)cts.cts_vcol;
|
||||
}
|
||||
|
||||
/// Prepare the structure passed to chartabsize functions.
|
||||
///
|
||||
/// "line" is the start of the line, "ptr" is the first relevant character.
|
||||
/// When "lnum" is zero do not use text properties that insert text.
|
||||
void init_chartabsize_arg(chartabsize_T *cts, win_T *wp, linenr_T lnum, colnr_T col, char_u *line,
|
||||
char_u *ptr)
|
||||
{
|
||||
cts->cts_win = wp;
|
||||
cts->cts_lnum = lnum;
|
||||
cts->cts_vcol = col;
|
||||
cts->cts_line = (char *)line;
|
||||
cts->cts_ptr = (char *)ptr;
|
||||
cts->cts_cur_text_width = 0;
|
||||
// TODO(bfredl): actually lookup inline virtual text here
|
||||
cts->cts_has_virt_text = false;
|
||||
}
|
||||
|
||||
/// Free any allocated item in "cts".
|
||||
void clear_chartabsize_arg(chartabsize_T *cts)
|
||||
{}
|
||||
|
||||
/// like win_chartabsize(), but also check for line breaks on the screen
|
||||
///
|
||||
/// @param line
|
||||
@ -288,16 +312,16 @@ unsigned int win_linetabsize(win_T *wp, char_u *line, colnr_T len)
|
||||
/// @param col
|
||||
///
|
||||
/// @return The number of characters taken up on the screen.
|
||||
int lbr_chartabsize(char_u *line, unsigned char *s, colnr_T col)
|
||||
int lbr_chartabsize(chartabsize_T *cts)
|
||||
{
|
||||
if (!curwin->w_p_lbr && *get_showbreak_value(curwin) == NUL
|
||||
&& !curwin->w_p_bri) {
|
||||
&& !curwin->w_p_bri && !cts->cts_has_virt_text) {
|
||||
if (curwin->w_p_wrap) {
|
||||
return win_nolbr_chartabsize(curwin, s, col, NULL);
|
||||
return win_nolbr_chartabsize(cts, NULL);
|
||||
}
|
||||
return win_chartabsize(curwin, s, col);
|
||||
return win_chartabsize(curwin, cts->cts_ptr, cts->cts_vcol);
|
||||
}
|
||||
return win_lbr_chartabsize(curwin, line == NULL ? s: line, s, col, NULL);
|
||||
return win_lbr_chartabsize(cts, NULL);
|
||||
}
|
||||
|
||||
/// Call lbr_chartabsize() and advance the pointer.
|
||||
@ -307,12 +331,12 @@ int lbr_chartabsize(char_u *line, unsigned char *s, colnr_T col)
|
||||
/// @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 lbr_chartabsize_adv(chartabsize_T *cts)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = lbr_chartabsize(line, *s, col);
|
||||
MB_PTR_ADV(*s);
|
||||
retval = lbr_chartabsize(cts);
|
||||
MB_PTR_ADV(cts->cts_ptr);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -322,17 +346,19 @@ int lbr_chartabsize_adv(char_u *line, char_u **s, colnr_T col)
|
||||
/// 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 cts
|
||||
/// @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)
|
||||
int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
|
||||
{
|
||||
win_T *wp = cts->cts_win;
|
||||
char *line = cts->cts_line; // start of the line
|
||||
char_u *s = (char_u *)cts->cts_ptr;
|
||||
colnr_T vcol = cts->cts_vcol;
|
||||
|
||||
colnr_T col2;
|
||||
colnr_T col_adj = 0; // col + screen size of tab
|
||||
colnr_T col_adj = 0; // vcol + screen size of tab
|
||||
colnr_T colmax;
|
||||
int added;
|
||||
int mb_added = 0;
|
||||
@ -340,16 +366,23 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he
|
||||
char_u *ps;
|
||||
int n;
|
||||
|
||||
cts->cts_cur_text_width = 0;
|
||||
|
||||
// No 'linebreak', 'showbreak' and 'breakindent': return quickly.
|
||||
if (!wp->w_p_lbr && !wp->w_p_bri && *get_showbreak_value(wp) == NUL) {
|
||||
if (!wp->w_p_lbr && !wp->w_p_bri && *get_showbreak_value(wp) == NUL
|
||||
&& !cts->cts_has_virt_text) {
|
||||
if (wp->w_p_wrap) {
|
||||
return win_nolbr_chartabsize(wp, s, col, headp);
|
||||
return win_nolbr_chartabsize(cts, headp);
|
||||
}
|
||||
return win_chartabsize(wp, s, col);
|
||||
return win_chartabsize(wp, (char *)s, vcol);
|
||||
}
|
||||
|
||||
// First get normal size, without 'linebreak' or virtual text
|
||||
int size = win_chartabsize(wp, (char *)s, vcol);
|
||||
if (cts->cts_has_virt_text) {
|
||||
// TODO(bfredl): inline virtual text
|
||||
}
|
||||
|
||||
// First get normal size, without 'linebreak'
|
||||
int size = win_chartabsize(wp, s, col);
|
||||
int c = *s;
|
||||
if (*s == TAB) {
|
||||
col_adj = size - 1;
|
||||
@ -365,15 +398,15 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he
|
||||
// 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;
|
||||
col2 = vcol;
|
||||
colmax = (colnr_T)(wp->w_width_inner - numberextra - col_adj);
|
||||
|
||||
if (col >= colmax) {
|
||||
if (vcol >= colmax) {
|
||||
colmax += col_adj;
|
||||
n = colmax + win_col_off2(wp);
|
||||
|
||||
if (n > 0) {
|
||||
colmax += (((col - colmax) / n) + 1) * n - col_adj;
|
||||
colmax += (((vcol - colmax) / n) + 1) * n - col_adj;
|
||||
}
|
||||
}
|
||||
|
||||
@ -383,21 +416,21 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he
|
||||
c = *s;
|
||||
|
||||
if (!(c != NUL
|
||||
&& (vim_isbreak(c) || col2 == col || !vim_isbreak((int)(*ps))))) {
|
||||
&& (vim_isbreak(c) || col2 == vcol || !vim_isbreak((int)(*ps))))) {
|
||||
break;
|
||||
}
|
||||
|
||||
col2 += win_chartabsize(wp, s, col2);
|
||||
col2 += win_chartabsize(wp, (char *)s, col2);
|
||||
|
||||
if (col2 >= colmax) { // doesn't fit
|
||||
size = colmax - col + col_adj;
|
||||
size = colmax - vcol + col_adj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if ((size == 2)
|
||||
&& (MB_BYTE2LEN(*s) > 1)
|
||||
&& wp->w_p_wrap
|
||||
&& in_win_border(wp, col)) {
|
||||
&& in_win_border(wp, vcol)) {
|
||||
// Count the ">" in the last column.
|
||||
size++;
|
||||
mb_added = 1;
|
||||
@ -409,40 +442,40 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he
|
||||
added = 0;
|
||||
|
||||
char *const sbr = (char *)get_showbreak_value(wp);
|
||||
if ((*sbr != NUL || wp->w_p_bri) && wp->w_p_wrap && col != 0) {
|
||||
if ((*sbr != NUL || wp->w_p_bri) && wp->w_p_wrap && vcol != 0) {
|
||||
colnr_T sbrlen = 0;
|
||||
int numberwidth = win_col_off(wp);
|
||||
|
||||
numberextra = numberwidth;
|
||||
col += numberextra + mb_added;
|
||||
vcol += numberextra + mb_added;
|
||||
|
||||
if (col >= (colnr_T)wp->w_width_inner) {
|
||||
col -= wp->w_width_inner;
|
||||
if (vcol >= (colnr_T)wp->w_width_inner) {
|
||||
vcol -= wp->w_width_inner;
|
||||
numberextra = wp->w_width_inner - (numberextra - win_col_off2(wp));
|
||||
if (col >= numberextra && numberextra > 0) {
|
||||
col %= numberextra;
|
||||
if (vcol >= numberextra && numberextra > 0) {
|
||||
vcol %= numberextra;
|
||||
}
|
||||
if (*sbr != NUL) {
|
||||
sbrlen = (colnr_T)mb_charlen((char_u *)sbr);
|
||||
if (col >= sbrlen) {
|
||||
col -= sbrlen;
|
||||
if (vcol >= sbrlen) {
|
||||
vcol -= sbrlen;
|
||||
}
|
||||
}
|
||||
if (col >= numberextra && numberextra > 0) {
|
||||
col %= numberextra;
|
||||
} else if (col > 0 && numberextra > 0) {
|
||||
col += numberwidth - win_col_off2(wp);
|
||||
if (vcol >= numberextra && numberextra > 0) {
|
||||
vcol %= numberextra;
|
||||
} else if (vcol > 0 && numberextra > 0) {
|
||||
vcol += numberwidth - win_col_off2(wp);
|
||||
}
|
||||
|
||||
numberwidth -= win_col_off2(wp);
|
||||
}
|
||||
|
||||
if (col == 0 || (col + size + sbrlen > (colnr_T)wp->w_width_inner)) {
|
||||
if (vcol == 0 || (vcol + size + sbrlen > (colnr_T)wp->w_width_inner)) {
|
||||
if (*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))
|
||||
int prev_width = vcol ? ((colnr_T)wp->w_width_inner - (sbrlen + vcol))
|
||||
: 0;
|
||||
|
||||
if (width <= 0) {
|
||||
@ -459,11 +492,11 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he
|
||||
}
|
||||
|
||||
if (wp->w_p_bri) {
|
||||
added += get_breakindent_win(wp, line);
|
||||
added += get_breakindent_win(wp, (char_u *)line);
|
||||
}
|
||||
|
||||
size += added;
|
||||
if (col != 0) {
|
||||
if (vcol != 0) {
|
||||
added = 0;
|
||||
}
|
||||
}
|
||||
@ -485,8 +518,11 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he
|
||||
/// @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)
|
||||
static int win_nolbr_chartabsize(chartabsize_T *cts, int *headp)
|
||||
{
|
||||
win_T *wp = cts->cts_win;
|
||||
char *s = cts->cts_ptr;
|
||||
colnr_T col = cts->cts_vcol;
|
||||
int n;
|
||||
|
||||
if ((*s == TAB) && (!wp->w_p_list || wp->w_p_lcs_chars.tab1)) {
|
||||
@ -498,7 +534,7 @@ static int win_nolbr_chartabsize(win_T *wp, char_u *s, colnr_T col, int *headp)
|
||||
|
||||
// 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 ((n == 2) && (MB_BYTE2LEN((uint8_t)(*s)) > 1) && in_win_border(wp, col)) {
|
||||
if (headp != NULL) {
|
||||
*headp = 1;
|
||||
}
|
||||
|
@ -3,6 +3,20 @@
|
||||
|
||||
#include "nvim/vim.h"
|
||||
|
||||
// Argument for lbr_chartabsize().
|
||||
typedef struct {
|
||||
win_T *cts_win;
|
||||
linenr_T cts_lnum; // zero when not using text properties
|
||||
char *cts_line; // start of the line
|
||||
char *cts_ptr; // current position in line
|
||||
|
||||
bool cts_has_virt_text; // true if if a property inserts text
|
||||
int cts_cur_text_width; // width of current inserted text
|
||||
// TODO(bfredl): iterator in to the marktree for scanning virt text
|
||||
|
||||
int cts_vcol; // virtual column at current position
|
||||
} chartabsize_T;
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "plines.h.generated.h"
|
||||
#endif
|
||||
|
@ -1165,7 +1165,7 @@ static bool reg_match_visual(void)
|
||||
rex.line = reg_getline(rex.lnum);
|
||||
rex.input = rex.line + col;
|
||||
|
||||
unsigned int cols_u = win_linetabsize(wp, rex.line, col);
|
||||
unsigned int cols_u = win_linetabsize(wp, rex.reg_firstlnum + rex.lnum, rex.line, col);
|
||||
assert(cols_u <= MAXCOL);
|
||||
colnr_T cols = (colnr_T)cols_u;
|
||||
if (cols < start || cols > end - (*p_sel == 'e')) {
|
||||
|
@ -3764,6 +3764,7 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
|
||||
case RE_VCOL:
|
||||
if (!re_num_cmp(win_linetabsize(rex.reg_win == NULL
|
||||
? curwin : rex.reg_win,
|
||||
rex.reg_firstlnum + rex.lnum,
|
||||
rex.line,
|
||||
(colnr_T)(rex.input - rex.line)) + 1,
|
||||
scan)) {
|
||||
|
@ -6910,7 +6910,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
|
||||
result = col > t->state->val * ts;
|
||||
}
|
||||
if (!result) {
|
||||
uintmax_t lts = win_linetabsize(wp, rex.line, col);
|
||||
uintmax_t lts = win_linetabsize(wp, rex.reg_firstlnum + rex.lnum, rex.line, col);
|
||||
assert(t->state->val >= 0);
|
||||
result = nfa_re_num_cmp((uintmax_t)t->state->val, op, lts + 1);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user