mirror of
https://github.com/vim/vim.git
synced 2025-07-04 23:07:33 -04:00
patch 9.0.0067: cannot show virtual text
Problem: Cannot show virtual text. Solution: Initial changes for virtual text support, using text properties.
This commit is contained in:
parent
b529cfbd04
commit
7f9969c559
@ -137,7 +137,11 @@ prop_add({lnum}, {col}, {props})
|
|||||||
bufnr buffer to add the property to; when omitted
|
bufnr buffer to add the property to; when omitted
|
||||||
the current buffer is used
|
the current buffer is used
|
||||||
id user defined ID for the property; must be a
|
id user defined ID for the property; must be a
|
||||||
number; when omitted zero is used
|
number, should be positive; when using "text"
|
||||||
|
then "id" must not be present and will be set
|
||||||
|
automatically to a negative number; otherwise
|
||||||
|
zero is used
|
||||||
|
text text to be displayed at {col}
|
||||||
type name of the text property type
|
type name of the text property type
|
||||||
All fields except "type" are optional.
|
All fields except "type" are optional.
|
||||||
|
|
||||||
@ -157,6 +161,17 @@ prop_add({lnum}, {col}, {props})
|
|||||||
"type" will first be looked up in the buffer the property is
|
"type" will first be looked up in the buffer the property is
|
||||||
added to. When not found, the global property types are used.
|
added to. When not found, the global property types are used.
|
||||||
If not found an error is given.
|
If not found an error is given.
|
||||||
|
*virtual-text*
|
||||||
|
When "text" is used this text will be displayed at the start
|
||||||
|
location of the text property. The text of the buffer line
|
||||||
|
will be shifted to make room. This is called "virtual text".
|
||||||
|
The text will be displayed but it is not part of the actual
|
||||||
|
buffer line, the cursor cannot be placed on it. A mouse click
|
||||||
|
in the text will move the cursor to the first character after
|
||||||
|
the text.
|
||||||
|
A negative "id" will be chosen and is returned. Once a
|
||||||
|
property with "text" has been added for a buffer then using a
|
||||||
|
negative "id" for any other property will give an error.
|
||||||
|
|
||||||
Can also be used as a |method|: >
|
Can also be used as a |method|: >
|
||||||
GetLnum()->prop_add(col, props)
|
GetLnum()->prop_add(col, props)
|
||||||
@ -181,6 +196,9 @@ prop_add_list({props}, [[{lnum}, {col}, {end-lnum}, {end-col}], ...])
|
|||||||
two items {end-lnum} and {end-col} specify the position just
|
two items {end-lnum} and {end-col} specify the position just
|
||||||
after the text.
|
after the text.
|
||||||
|
|
||||||
|
It is not possible to add a text property with a "text" field
|
||||||
|
here.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
call prop_add_list(#{type: 'MyProp', id: 2},
|
call prop_add_list(#{type: 'MyProp', id: 2},
|
||||||
\ [[1, 4, 1, 7],
|
\ [[1, 4, 1, 7],
|
||||||
|
@ -47,7 +47,7 @@ find_word_under_cursor(
|
|||||||
{
|
{
|
||||||
// Not past end of the file.
|
// Not past end of the file.
|
||||||
lbuf = ml_get_buf(wp->w_buffer, lnum, FALSE);
|
lbuf = ml_get_buf(wp->w_buffer, lnum, FALSE);
|
||||||
if (col <= win_linetabsize(wp, lbuf, (colnr_T)MAXCOL))
|
if (col <= win_linetabsize(wp, lnum, lbuf, (colnr_T)MAXCOL))
|
||||||
{
|
{
|
||||||
// Not past end of line.
|
// Not past end of line.
|
||||||
if (getword)
|
if (getword)
|
||||||
|
301
src/charset.c
301
src/charset.c
@ -12,8 +12,8 @@
|
|||||||
#if defined(HAVE_WCHAR_H)
|
#if defined(HAVE_WCHAR_H)
|
||||||
# include <wchar.h> // for towupper() and towlower()
|
# include <wchar.h> // for towupper() and towlower()
|
||||||
#endif
|
#endif
|
||||||
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);
|
||||||
static unsigned nr2hex(unsigned c);
|
static unsigned nr2hex(unsigned c);
|
||||||
|
|
||||||
static int chartab_initialized = FALSE;
|
static int chartab_initialized = FALSE;
|
||||||
@ -737,8 +737,9 @@ win_chartabsize(win_T *wp, char_u *p, colnr_T col)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the number of characters the string 's' will take on the screen,
|
* Return the number of characters the string "s" will take on the screen,
|
||||||
* taking into account the size of a tab.
|
* taking into account the size of a tab.
|
||||||
|
* Does not handle text properties, since "s" is not a buffer line.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
linetabsize(char_u *s)
|
linetabsize(char_u *s)
|
||||||
@ -747,32 +748,34 @@ linetabsize(char_u *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Like linetabsize(), but starting at column "startcol".
|
* Like linetabsize(), but "s" starts at column "startcol".
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
linetabsize_col(int startcol, char_u *s)
|
linetabsize_col(int startcol, char_u *s)
|
||||||
{
|
{
|
||||||
colnr_T col = startcol;
|
chartabsize_T cts;
|
||||||
char_u *line = s; // pointer to start of line, for breakindent
|
|
||||||
|
|
||||||
while (*s != NUL)
|
init_chartabsize_arg(&cts, curwin, 0, startcol, s, s);
|
||||||
col += lbr_chartabsize_adv(line, &s, col);
|
while (*cts.cts_ptr != NUL)
|
||||||
return (int)col;
|
cts.cts_vcol += lbr_chartabsize_adv(&cts);
|
||||||
|
clear_chartabsize_arg(&cts);
|
||||||
|
return (int)cts.cts_vcol;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Like linetabsize(), but for a given window instead of the current one.
|
* Like linetabsize(), but for a given window instead of the current one.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
win_linetabsize(win_T *wp, char_u *line, colnr_T len)
|
win_linetabsize(win_T *wp, linenr_T lnum, char_u *line, colnr_T len)
|
||||||
{
|
{
|
||||||
colnr_T col = 0;
|
chartabsize_T cts;
|
||||||
char_u *s;
|
|
||||||
|
|
||||||
for (s = line; *s != NUL && (len == MAXCOL || s < line + len);
|
init_chartabsize_arg(&cts, wp, lnum, 0, line, line);
|
||||||
MB_PTR_ADV(s))
|
for ( ; *cts.cts_ptr != NUL && (len == MAXCOL || cts.cts_ptr < line + len);
|
||||||
col += win_lbr_chartabsize(wp, line, s, col, NULL);
|
MB_PTR_ADV(cts.cts_ptr))
|
||||||
return (int)col;
|
cts.cts_vcol += win_lbr_chartabsize(&cts, NULL);
|
||||||
|
clear_chartabsize_arg(&cts);
|
||||||
|
return (int)cts.cts_vcol;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -893,25 +896,101 @@ vim_isprintc_strict(int c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* like chartabsize(), but also check for line breaks on the screen
|
* 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 = line;
|
||||||
|
cts->cts_ptr = ptr;
|
||||||
|
#ifdef FEAT_PROP_POPUP
|
||||||
|
cts->cts_text_prop_count = 0;
|
||||||
|
cts->cts_has_prop_with_text = FALSE;
|
||||||
|
cts->cts_cur_text_width = 0;
|
||||||
|
if (lnum > 0)
|
||||||
|
{
|
||||||
|
char_u *prop_start;
|
||||||
|
|
||||||
|
cts->cts_text_prop_count = get_text_props(wp->w_buffer, lnum,
|
||||||
|
&prop_start, FALSE);
|
||||||
|
if (cts->cts_text_prop_count > 0)
|
||||||
|
{
|
||||||
|
// Make a copy of the properties, so that they are properly
|
||||||
|
// aligned.
|
||||||
|
cts->cts_text_props = ALLOC_MULT(textprop_T,
|
||||||
|
cts->cts_text_prop_count);
|
||||||
|
if (cts->cts_text_props == NULL)
|
||||||
|
cts->cts_text_prop_count = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
mch_memmove(cts->cts_text_props, prop_start,
|
||||||
|
cts->cts_text_prop_count * sizeof(textprop_T));
|
||||||
|
for (i = 0; i < cts->cts_text_prop_count; ++i)
|
||||||
|
if (cts->cts_text_props[i].tp_id < 0)
|
||||||
|
{
|
||||||
|
cts->cts_has_prop_with_text = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!cts->cts_has_prop_with_text)
|
||||||
|
{
|
||||||
|
// won't use the text properties, free them
|
||||||
|
vim_free(cts->cts_text_props);
|
||||||
|
cts->cts_text_prop_count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free any allocated item in "cts".
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clear_chartabsize_arg(chartabsize_T *cts)
|
||||||
|
{
|
||||||
|
if (cts->cts_text_prop_count > 0)
|
||||||
|
vim_free(cts->cts_text_props);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Like chartabsize(), but also check for line breaks on the screen and text
|
||||||
|
* properties that insert text.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
lbr_chartabsize(
|
lbr_chartabsize(chartabsize_T *cts)
|
||||||
char_u *line UNUSED, // start of the line
|
|
||||||
unsigned char *s,
|
|
||||||
colnr_T col)
|
|
||||||
{
|
{
|
||||||
|
#if defined(FEAT_LINEBREAK) || defined(FEAT_PROP_POPUP)
|
||||||
|
if (1
|
||||||
# ifdef FEAT_LINEBREAK
|
# ifdef FEAT_LINEBREAK
|
||||||
if (!curwin->w_p_lbr && *get_showbreak_value(curwin) == NUL
|
&& !curwin->w_p_lbr && *get_showbreak_value(curwin) == NUL
|
||||||
&& !curwin->w_p_bri)
|
&& !curwin->w_p_bri
|
||||||
|
# endif
|
||||||
|
# ifdef FEAT_PROP_POPUP
|
||||||
|
&& !cts->cts_has_prop_with_text
|
||||||
|
#endif
|
||||||
|
)
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
if (curwin->w_p_wrap)
|
if (curwin->w_p_wrap)
|
||||||
return win_nolbr_chartabsize(curwin, s, col, NULL);
|
return win_nolbr_chartabsize(cts, NULL);
|
||||||
RET_WIN_BUF_CHARTABSIZE(curwin, curbuf, s, col)
|
RET_WIN_BUF_CHARTABSIZE(curwin, curbuf, cts->cts_ptr, cts->cts_vcol)
|
||||||
#ifdef FEAT_LINEBREAK
|
#if defined(FEAT_LINEBREAK) || defined(FEAT_PROP_POPUP)
|
||||||
}
|
}
|
||||||
return win_lbr_chartabsize(curwin, line == NULL ? s : line, s, col, NULL);
|
return win_lbr_chartabsize(cts, NULL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -919,19 +998,19 @@ lbr_chartabsize(
|
|||||||
* Call lbr_chartabsize() and advance the pointer.
|
* Call lbr_chartabsize() and advance the pointer.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
lbr_chartabsize_adv(
|
lbr_chartabsize_adv(chartabsize_T *cts)
|
||||||
char_u *line, // start of the line
|
|
||||||
char_u **s,
|
|
||||||
colnr_T col)
|
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
retval = lbr_chartabsize(line, *s, col);
|
retval = lbr_chartabsize(cts);
|
||||||
MB_PTR_ADV(*s);
|
MB_PTR_ADV(cts->cts_ptr);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* Return the screen size of the character indicated by "cts".
|
||||||
|
* "cts->cts_cur_text_width" is set to the extra size for a text property that
|
||||||
|
* inserts text.
|
||||||
* This function is used very often, keep it fast!!!!
|
* This function is used very often, keep it fast!!!!
|
||||||
*
|
*
|
||||||
* If "headp" not NULL, set *headp to the size of what we for 'showbreak'
|
* If "headp" not NULL, set *headp to the size of what we for 'showbreak'
|
||||||
@ -940,17 +1019,18 @@ lbr_chartabsize_adv(
|
|||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
win_lbr_chartabsize(
|
win_lbr_chartabsize(
|
||||||
win_T *wp,
|
chartabsize_T *cts,
|
||||||
char_u *line UNUSED, // start of the line
|
|
||||||
char_u *s,
|
|
||||||
colnr_T col,
|
|
||||||
int *headp UNUSED)
|
int *headp UNUSED)
|
||||||
{
|
{
|
||||||
|
win_T *wp = cts->cts_win;
|
||||||
|
char_u *line = cts->cts_line; // start of the line
|
||||||
|
char_u *s = cts->cts_ptr;
|
||||||
|
colnr_T vcol = cts->cts_vcol;
|
||||||
#ifdef FEAT_LINEBREAK
|
#ifdef FEAT_LINEBREAK
|
||||||
int c;
|
int c;
|
||||||
int size;
|
int size;
|
||||||
colnr_T col2;
|
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;
|
colnr_T colmax;
|
||||||
int added;
|
int added;
|
||||||
int mb_added = 0;
|
int mb_added = 0;
|
||||||
@ -959,23 +1039,66 @@ win_lbr_chartabsize(
|
|||||||
int tab_corr = (*s == TAB);
|
int tab_corr = (*s == TAB);
|
||||||
int n;
|
int n;
|
||||||
char_u *sbr;
|
char_u *sbr;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(FEAT_PROP_POPUP)
|
||||||
|
cts->cts_cur_text_width = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(FEAT_LINEBREAK) || defined(FEAT_PROP_POPUP)
|
||||||
/*
|
/*
|
||||||
* No 'linebreak', 'showbreak' and 'breakindent': return quickly.
|
* No 'linebreak', 'showbreak', 'breakindent' and text properties that
|
||||||
|
* insert text: return quickly.
|
||||||
*/
|
*/
|
||||||
if (!wp->w_p_lbr && !wp->w_p_bri && *get_showbreak_value(wp) == NUL)
|
if (1
|
||||||
|
# ifdef FEAT_LINEBREAK
|
||||||
|
&& !wp->w_p_lbr && !wp->w_p_bri && *get_showbreak_value(wp) == NUL
|
||||||
|
# endif
|
||||||
|
# ifdef FEAT_PROP_POPUP
|
||||||
|
&& !cts->cts_has_prop_with_text
|
||||||
|
# endif
|
||||||
|
)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (wp->w_p_wrap)
|
if (wp->w_p_wrap)
|
||||||
return win_nolbr_chartabsize(wp, s, col, headp);
|
return win_nolbr_chartabsize(cts, headp);
|
||||||
RET_WIN_BUF_CHARTABSIZE(wp, wp->w_buffer, s, col)
|
RET_WIN_BUF_CHARTABSIZE(wp, wp->w_buffer, s, vcol)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FEAT_LINEBREAK
|
#if defined(FEAT_LINEBREAK) || defined(FEAT_PROP_POPUP)
|
||||||
/*
|
/*
|
||||||
* First get normal size, without 'linebreak'
|
* First get the normal size, without 'linebreak' or text properties
|
||||||
*/
|
*/
|
||||||
size = win_chartabsize(wp, s, col);
|
size = win_chartabsize(wp, s, vcol);
|
||||||
|
|
||||||
|
# ifdef FEAT_PROP_POPUP
|
||||||
|
if (cts->cts_has_prop_with_text)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int col = (int)(s - line);
|
||||||
|
|
||||||
|
for (i = 0; i < cts->cts_text_prop_count; ++i)
|
||||||
|
{
|
||||||
|
textprop_T *tp = cts->cts_text_props + i;
|
||||||
|
|
||||||
|
if (tp->tp_id < 0
|
||||||
|
&& tp->tp_col - 1 >= col && tp->tp_col - 1 < col + size
|
||||||
|
&& -tp->tp_id <= wp->w_buffer->b_textprop_text.ga_len)
|
||||||
|
{
|
||||||
|
char_u *p = ((char_u **)wp->w_buffer->b_textprop_text.ga_data)[
|
||||||
|
-tp->tp_id - 1];
|
||||||
|
// TODO: count screen cells
|
||||||
|
cts->cts_cur_text_width = STRLEN(p);
|
||||||
|
size += cts->cts_cur_text_width;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (tp->tp_col - 1 > col)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifdef FEAT_LINEBREAK
|
||||||
c = *s;
|
c = *s;
|
||||||
if (tab_corr)
|
if (tab_corr)
|
||||||
col_adj = size - 1;
|
col_adj = size - 1;
|
||||||
@ -995,14 +1118,14 @@ win_lbr_chartabsize(
|
|||||||
* non-blank after a blank.
|
* non-blank after a blank.
|
||||||
*/
|
*/
|
||||||
numberextra = win_col_off(wp);
|
numberextra = win_col_off(wp);
|
||||||
col2 = col;
|
col2 = vcol;
|
||||||
colmax = (colnr_T)(wp->w_width - numberextra - col_adj);
|
colmax = (colnr_T)(wp->w_width - numberextra - col_adj);
|
||||||
if (col >= colmax)
|
if (vcol >= colmax)
|
||||||
{
|
{
|
||||||
colmax += col_adj;
|
colmax += col_adj;
|
||||||
n = colmax + win_col_off2(wp);
|
n = colmax + win_col_off2(wp);
|
||||||
if (n > 0)
|
if (n > 0)
|
||||||
colmax += (((col - colmax) / n) + 1) * n - col_adj;
|
colmax += (((vcol - colmax) / n) + 1) * n - col_adj;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
@ -1013,19 +1136,19 @@ win_lbr_chartabsize(
|
|||||||
if (!(c != NUL
|
if (!(c != NUL
|
||||||
&& (VIM_ISBREAK(c)
|
&& (VIM_ISBREAK(c)
|
||||||
|| (!VIM_ISBREAK(c)
|
|| (!VIM_ISBREAK(c)
|
||||||
&& (col2 == col || !VIM_ISBREAK((int)*ps))))))
|
&& (col2 == vcol || !VIM_ISBREAK((int)*ps))))))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
col2 += win_chartabsize(wp, s, col2);
|
col2 += win_chartabsize(wp, s, col2);
|
||||||
if (col2 >= colmax) // doesn't fit
|
if (col2 >= colmax) // doesn't fit
|
||||||
{
|
{
|
||||||
size = colmax - col + col_adj;
|
size = colmax - vcol + col_adj;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (has_mbyte && size == 2 && MB_BYTE2LEN(*s) > 1
|
else if (has_mbyte && size == 2 && MB_BYTE2LEN(*s) > 1
|
||||||
&& wp->w_p_wrap && in_win_border(wp, col))
|
&& wp->w_p_wrap && in_win_border(wp, vcol))
|
||||||
{
|
{
|
||||||
++size; // Count the ">" in the last column.
|
++size; // Count the ">" in the last column.
|
||||||
mb_added = 1;
|
mb_added = 1;
|
||||||
@ -1039,33 +1162,33 @@ win_lbr_chartabsize(
|
|||||||
*/
|
*/
|
||||||
added = 0;
|
added = 0;
|
||||||
sbr = c == NUL ? empty_option : get_showbreak_value(wp);
|
sbr = c == NUL ? empty_option : 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;
|
colnr_T sbrlen = 0;
|
||||||
int numberwidth = win_col_off(wp);
|
int numberwidth = win_col_off(wp);
|
||||||
|
|
||||||
numberextra = numberwidth;
|
numberextra = numberwidth;
|
||||||
col += numberextra + mb_added;
|
vcol += numberextra + mb_added;
|
||||||
if (col >= (colnr_T)wp->w_width)
|
if (vcol >= (colnr_T)wp->w_width)
|
||||||
{
|
{
|
||||||
col -= wp->w_width;
|
vcol -= wp->w_width;
|
||||||
numberextra = wp->w_width - (numberextra - win_col_off2(wp));
|
numberextra = wp->w_width - (numberextra - win_col_off2(wp));
|
||||||
if (col >= numberextra && numberextra > 0)
|
if (vcol >= numberextra && numberextra > 0)
|
||||||
col %= numberextra;
|
vcol %= numberextra;
|
||||||
if (*sbr != NUL)
|
if (*sbr != NUL)
|
||||||
{
|
{
|
||||||
sbrlen = (colnr_T)MB_CHARLEN(sbr);
|
sbrlen = (colnr_T)MB_CHARLEN(sbr);
|
||||||
if (col >= sbrlen)
|
if (vcol >= sbrlen)
|
||||||
col -= sbrlen;
|
vcol -= sbrlen;
|
||||||
}
|
}
|
||||||
if (col >= numberextra && numberextra > 0)
|
if (vcol >= numberextra && numberextra > 0)
|
||||||
col = col % numberextra;
|
vcol = vcol % numberextra;
|
||||||
else if (col > 0 && numberextra > 0)
|
else if (vcol > 0 && numberextra > 0)
|
||||||
col += numberwidth - win_col_off2(wp);
|
vcol += numberwidth - win_col_off2(wp);
|
||||||
|
|
||||||
numberwidth -= win_col_off2(wp);
|
numberwidth -= win_col_off2(wp);
|
||||||
}
|
}
|
||||||
if (col == 0 || col + size + sbrlen > (colnr_T)wp->w_width)
|
if (vcol == 0 || vcol + size + sbrlen > (colnr_T)wp->w_width)
|
||||||
{
|
{
|
||||||
added = 0;
|
added = 0;
|
||||||
if (*sbr != NUL)
|
if (*sbr != NUL)
|
||||||
@ -1074,8 +1197,8 @@ win_lbr_chartabsize(
|
|||||||
{
|
{
|
||||||
// calculate effective window width
|
// calculate effective window width
|
||||||
int width = (colnr_T)wp->w_width - sbrlen - numberwidth;
|
int width = (colnr_T)wp->w_width - sbrlen - numberwidth;
|
||||||
int prev_width = col
|
int prev_width = vcol
|
||||||
? ((colnr_T)wp->w_width - (sbrlen + col)) : 0;
|
? ((colnr_T)wp->w_width - (sbrlen + vcol)) : 0;
|
||||||
|
|
||||||
if (width <= 0)
|
if (width <= 0)
|
||||||
width = (colnr_T)1;
|
width = (colnr_T)1;
|
||||||
@ -1091,7 +1214,7 @@ win_lbr_chartabsize(
|
|||||||
added += get_breakindent_win(wp, line);
|
added += get_breakindent_win(wp, line);
|
||||||
|
|
||||||
size += added;
|
size += added;
|
||||||
if (col != 0)
|
if (vcol != 0)
|
||||||
added = 0;
|
added = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1099,20 +1222,24 @@ win_lbr_chartabsize(
|
|||||||
*headp = added + mb_added;
|
*headp = added + mb_added;
|
||||||
return size;
|
return size;
|
||||||
# endif
|
# endif
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Like win_lbr_chartabsize(), except that we know 'linebreak' is off and
|
* Like win_lbr_chartabsize(), except that we know 'linebreak' is off, 'wrap'
|
||||||
* 'wrap' is on. This means we need to check for a double-byte character that
|
* is on and there are no properties that insert text. This means we need to
|
||||||
* doesn't fit at the end of the screen line.
|
* check for a double-byte character that doesn't fit at the end of the screen
|
||||||
|
* line.
|
||||||
|
* Only uses "cts_win", "cts_ptr" and "cts_vcol" from "cts".
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
win_nolbr_chartabsize(
|
win_nolbr_chartabsize(
|
||||||
win_T *wp,
|
chartabsize_T *cts,
|
||||||
char_u *s,
|
|
||||||
colnr_T col,
|
|
||||||
int *headp)
|
int *headp)
|
||||||
{
|
{
|
||||||
|
win_T *wp = cts->cts_win;
|
||||||
|
char_u *s = cts->cts_ptr;
|
||||||
|
colnr_T col = cts->cts_vcol;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
if (*s == TAB && (!wp->w_p_list || wp->w_lcs_chars.tab1))
|
if (*s == TAB && (!wp->w_p_list || wp->w_lcs_chars.tab1))
|
||||||
@ -1187,6 +1314,7 @@ getvcol(
|
|||||||
#endif
|
#endif
|
||||||
int ts = wp->w_buffer->b_p_ts;
|
int ts = wp->w_buffer->b_p_ts;
|
||||||
int c;
|
int c;
|
||||||
|
chartabsize_T cts;
|
||||||
|
|
||||||
vcol = 0;
|
vcol = 0;
|
||||||
line = ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE);
|
line = ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE);
|
||||||
@ -1209,15 +1337,20 @@ getvcol(
|
|||||||
posptr -= (*mb_head_off)(line, posptr);
|
posptr -= (*mb_head_off)(line, posptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init_chartabsize_arg(&cts, wp, pos->lnum, 0, line, line);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function is used very often, do some speed optimizations.
|
* This function is used very often, do some speed optimizations.
|
||||||
* When 'list', 'linebreak', 'showbreak' and 'breakindent' are not set
|
* When 'list', 'linebreak', 'showbreak' and 'breakindent' are not set
|
||||||
* use a simple loop.
|
* and there are no text properties with "text" use a simple loop.
|
||||||
* Also use this when 'list' is set but tabs take their normal size.
|
* Also use this when 'list' is set but tabs take their normal size.
|
||||||
*/
|
*/
|
||||||
if ((!wp->w_p_list || wp->w_lcs_chars.tab1 != NUL)
|
if ((!wp->w_p_list || wp->w_lcs_chars.tab1 != NUL)
|
||||||
#ifdef FEAT_LINEBREAK
|
#ifdef FEAT_LINEBREAK
|
||||||
&& !wp->w_p_lbr && *get_showbreak_value(wp) == NUL && !wp->w_p_bri
|
&& !wp->w_p_lbr && *get_showbreak_value(wp) == NUL && !wp->w_p_bri
|
||||||
|
#endif
|
||||||
|
#ifdef FEAT_PROP_POPUP
|
||||||
|
&& !cts.cts_has_prop_with_text
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -1274,29 +1407,39 @@ getvcol(
|
|||||||
{
|
{
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
// A tab gets expanded, depending on the current column
|
// A tab gets expanded, depending on the current column.
|
||||||
|
// Other things also take up space.
|
||||||
head = 0;
|
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
|
// make sure we don't go past the end of the line
|
||||||
if (*ptr == NUL)
|
if (*cts.cts_ptr == NUL)
|
||||||
{
|
{
|
||||||
incr = 1; // NUL at end of line only takes one column
|
incr = 1; // NUL at end of line only takes one column
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (posptr != NULL && ptr >= posptr) // character at pos->col
|
if (posptr != NULL && cts.cts_ptr >= posptr)
|
||||||
|
// character at pos->col
|
||||||
break;
|
break;
|
||||||
|
|
||||||
vcol += incr;
|
cts.cts_vcol += incr;
|
||||||
MB_PTR_ADV(ptr);
|
MB_PTR_ADV(cts.cts_ptr);
|
||||||
}
|
}
|
||||||
|
vcol = cts.cts_vcol;
|
||||||
|
ptr = cts.cts_ptr;
|
||||||
}
|
}
|
||||||
|
clear_chartabsize_arg(&cts);
|
||||||
|
|
||||||
if (start != NULL)
|
if (start != NULL)
|
||||||
*start = vcol + head;
|
*start = vcol + head;
|
||||||
if (end != NULL)
|
if (end != NULL)
|
||||||
*end = vcol + incr - 1;
|
*end = vcol + incr - 1;
|
||||||
if (cursor != NULL)
|
if (cursor != NULL)
|
||||||
{
|
{
|
||||||
|
#ifdef FEAT_PROP_POPUP
|
||||||
|
// cursor is after inserted text
|
||||||
|
vcol += cts.cts_cur_text_width;
|
||||||
|
#endif
|
||||||
if (*ptr == TAB
|
if (*ptr == TAB
|
||||||
&& (State & MODE_NORMAL)
|
&& (State & MODE_NORMAL)
|
||||||
&& !wp->w_p_list
|
&& !wp->w_p_list
|
||||||
|
@ -326,6 +326,7 @@ win_line(
|
|||||||
int text_props_active = 0;
|
int text_props_active = 0;
|
||||||
proptype_T *text_prop_type = NULL;
|
proptype_T *text_prop_type = NULL;
|
||||||
int text_prop_attr = 0;
|
int text_prop_attr = 0;
|
||||||
|
int text_prop_id = 0; // active property ID
|
||||||
int text_prop_combine = FALSE;
|
int text_prop_combine = FALSE;
|
||||||
#endif
|
#endif
|
||||||
#ifdef FEAT_SPELL
|
#ifdef FEAT_SPELL
|
||||||
@ -817,14 +818,20 @@ win_line(
|
|||||||
if (v > 0 && !number_only)
|
if (v > 0 && !number_only)
|
||||||
{
|
{
|
||||||
char_u *prev_ptr = ptr;
|
char_u *prev_ptr = ptr;
|
||||||
|
chartabsize_T cts;
|
||||||
|
int charsize;
|
||||||
|
|
||||||
while (vcol < v && *ptr != NUL)
|
init_chartabsize_arg(&cts, wp, lnum, vcol, line, ptr);
|
||||||
|
while (cts.cts_vcol < v && *cts.cts_ptr != NUL)
|
||||||
{
|
{
|
||||||
c = win_lbr_chartabsize(wp, line, ptr, (colnr_T)vcol, NULL);
|
charsize = win_lbr_chartabsize(&cts, NULL);
|
||||||
vcol += c;
|
cts.cts_vcol += charsize;
|
||||||
prev_ptr = ptr;
|
prev_ptr = cts.cts_ptr;
|
||||||
MB_PTR_ADV(ptr);
|
MB_PTR_ADV(cts.cts_ptr);
|
||||||
}
|
}
|
||||||
|
vcol = cts.cts_vcol;
|
||||||
|
ptr = cts.cts_ptr;
|
||||||
|
clear_chartabsize_arg(&cts);
|
||||||
|
|
||||||
// When:
|
// When:
|
||||||
// - 'cuc' is set, or
|
// - 'cuc' is set, or
|
||||||
@ -844,11 +851,11 @@ win_line(
|
|||||||
// that character but skip the first few screen characters.
|
// that character but skip the first few screen characters.
|
||||||
if (vcol > v)
|
if (vcol > v)
|
||||||
{
|
{
|
||||||
vcol -= c;
|
vcol -= charsize;
|
||||||
ptr = prev_ptr;
|
ptr = prev_ptr;
|
||||||
// If the character fits on the screen, don't need to skip it.
|
// If the character fits on the screen, don't need to skip it.
|
||||||
// Except for a TAB.
|
// Except for a TAB.
|
||||||
if (( (*mb_ptr2cells)(ptr) >= c || *ptr == TAB) && col == 0)
|
if (( (*mb_ptr2cells)(ptr) >= charsize || *ptr == TAB) && col == 0)
|
||||||
n_skip = v - vcol;
|
n_skip = v - vcol;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1476,8 +1483,12 @@ win_line(
|
|||||||
text_prop_attr = 0;
|
text_prop_attr = 0;
|
||||||
text_prop_combine = FALSE;
|
text_prop_combine = FALSE;
|
||||||
text_prop_type = NULL;
|
text_prop_type = NULL;
|
||||||
|
text_prop_id = 0;
|
||||||
if (text_props_active > 0)
|
if (text_props_active > 0)
|
||||||
{
|
{
|
||||||
|
int used_tpi;
|
||||||
|
int used_attr = 0;
|
||||||
|
|
||||||
// Sort the properties on priority and/or starting last.
|
// Sort the properties on priority and/or starting last.
|
||||||
// Then combine the attributes, highest priority last.
|
// Then combine the attributes, highest priority last.
|
||||||
current_text_props = text_props;
|
current_text_props = text_props;
|
||||||
@ -1491,16 +1502,44 @@ win_line(
|
|||||||
proptype_T *pt = text_prop_type_by_id(
|
proptype_T *pt = text_prop_type_by_id(
|
||||||
wp->w_buffer, text_props[tpi].tp_type);
|
wp->w_buffer, text_props[tpi].tp_type);
|
||||||
|
|
||||||
if (pt != NULL && pt->pt_hl_id > 0)
|
if (pt != NULL && pt->pt_hl_id > 0
|
||||||
|
&& text_props[tpi].tp_id != -MAXCOL)
|
||||||
{
|
{
|
||||||
int pt_attr = syn_id2attr(pt->pt_hl_id);
|
used_attr = syn_id2attr(pt->pt_hl_id);
|
||||||
|
|
||||||
text_prop_type = pt;
|
text_prop_type = pt;
|
||||||
text_prop_attr =
|
text_prop_attr =
|
||||||
hl_combine_attr(text_prop_attr, pt_attr);
|
hl_combine_attr(text_prop_attr, used_attr);
|
||||||
text_prop_combine = pt->pt_flags & PT_FLAG_COMBINE;
|
text_prop_combine = pt->pt_flags & PT_FLAG_COMBINE;
|
||||||
|
text_prop_id = text_props[tpi].tp_id;
|
||||||
|
used_tpi = tpi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (n_extra == 0 && text_prop_id < 0
|
||||||
|
&& -text_prop_id
|
||||||
|
<= wp->w_buffer->b_textprop_text.ga_len)
|
||||||
|
{
|
||||||
|
char_u *p = ((char_u **)wp->w_buffer
|
||||||
|
->b_textprop_text.ga_data)[
|
||||||
|
-text_prop_id - 1];
|
||||||
|
if (p != NULL)
|
||||||
|
{
|
||||||
|
p_extra = p;
|
||||||
|
n_extra = STRLEN(p);
|
||||||
|
extra_attr = used_attr;
|
||||||
|
n_attr = n_extra;
|
||||||
|
text_prop_attr = 0;
|
||||||
|
|
||||||
|
// If the cursor is on or after this position,
|
||||||
|
// move it forward.
|
||||||
|
if (wp == curwin
|
||||||
|
&& lnum == curwin->w_cursor.lnum
|
||||||
|
&& curwin->w_cursor.col >= vcol)
|
||||||
|
curwin->w_cursor.col += n_extra;
|
||||||
|
}
|
||||||
|
// reset the ID in the copy to avoid it being used
|
||||||
|
// again
|
||||||
|
text_props[used_tpi].tp_id = -MAXCOL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -2025,10 +2064,10 @@ win_line(
|
|||||||
int mb_off = has_mbyte ? (*mb_head_off)(line, ptr - 1)
|
int mb_off = has_mbyte ? (*mb_head_off)(line, ptr - 1)
|
||||||
: 0;
|
: 0;
|
||||||
char_u *p = ptr - (mb_off + 1);
|
char_u *p = ptr - (mb_off + 1);
|
||||||
|
chartabsize_T cts;
|
||||||
|
|
||||||
// TODO: is passing p for start of the line OK?
|
init_chartabsize_arg(&cts, wp, lnum, vcol, line, p);
|
||||||
n_extra = win_lbr_chartabsize(wp, line, p, (colnr_T)vcol,
|
n_extra = win_lbr_chartabsize(&cts, NULL) - 1;
|
||||||
NULL) - 1;
|
|
||||||
|
|
||||||
// We have just drawn the showbreak value, no need to add
|
// We have just drawn the showbreak value, no need to add
|
||||||
// space for it again.
|
// space for it again.
|
||||||
@ -2069,6 +2108,7 @@ win_line(
|
|||||||
if (!wp->w_p_list)
|
if (!wp->w_p_list)
|
||||||
c = ' ';
|
c = ' ';
|
||||||
}
|
}
|
||||||
|
clear_chartabsize_arg(&cts);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
43
src/edit.c
43
src/edit.c
@ -4905,6 +4905,8 @@ ins_tab(void)
|
|||||||
colnr_T want_vcol, vcol;
|
colnr_T want_vcol, vcol;
|
||||||
int change_col = -1;
|
int change_col = -1;
|
||||||
int save_list = curwin->w_p_list;
|
int save_list = curwin->w_p_list;
|
||||||
|
char_u *tab = (char_u *)"\t";
|
||||||
|
chartabsize_T cts;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the current line. For MODE_VREPLACE state, don't make real
|
* Get the current line. For MODE_VREPLACE state, don't make real
|
||||||
@ -4950,12 +4952,14 @@ ins_tab(void)
|
|||||||
getvcol(curwin, &fpos, &vcol, NULL, NULL);
|
getvcol(curwin, &fpos, &vcol, NULL, NULL);
|
||||||
getvcol(curwin, cursor, &want_vcol, NULL, NULL);
|
getvcol(curwin, cursor, &want_vcol, NULL, NULL);
|
||||||
|
|
||||||
|
init_chartabsize_arg(&cts, curwin, 0, vcol, tab, tab);
|
||||||
|
|
||||||
// Use as many TABs as possible. Beware of 'breakindent', 'showbreak'
|
// Use as many TABs as possible. Beware of 'breakindent', 'showbreak'
|
||||||
// and 'linebreak' adding extra virtual columns.
|
// and 'linebreak' adding extra virtual columns.
|
||||||
while (VIM_ISWHITE(*ptr))
|
while (VIM_ISWHITE(*ptr))
|
||||||
{
|
{
|
||||||
i = lbr_chartabsize(NULL, (char_u *)"\t", vcol);
|
i = lbr_chartabsize(&cts);
|
||||||
if (vcol + i > want_vcol)
|
if (cts.cts_vcol + i > want_vcol)
|
||||||
break;
|
break;
|
||||||
if (*ptr != TAB)
|
if (*ptr != TAB)
|
||||||
{
|
{
|
||||||
@ -4970,21 +4974,27 @@ ins_tab(void)
|
|||||||
}
|
}
|
||||||
++fpos.col;
|
++fpos.col;
|
||||||
++ptr;
|
++ptr;
|
||||||
vcol += i;
|
cts.cts_vcol += i;
|
||||||
}
|
}
|
||||||
|
vcol = cts.cts_vcol;
|
||||||
|
clear_chartabsize_arg(&cts);
|
||||||
|
|
||||||
if (change_col >= 0)
|
if (change_col >= 0)
|
||||||
{
|
{
|
||||||
int repl_off = 0;
|
int repl_off = 0;
|
||||||
char_u *line = ptr;
|
|
||||||
|
|
||||||
// Skip over the spaces we need.
|
// Skip over the spaces we need.
|
||||||
while (vcol < want_vcol && *ptr == ' ')
|
init_chartabsize_arg(&cts, curwin, 0, vcol, ptr, ptr);
|
||||||
|
while (cts.cts_vcol < want_vcol && *cts.cts_ptr == ' ')
|
||||||
{
|
{
|
||||||
vcol += lbr_chartabsize(line, ptr, vcol);
|
cts.cts_vcol += lbr_chartabsize(&cts);
|
||||||
++ptr;
|
++cts.cts_ptr;
|
||||||
++repl_off;
|
++repl_off;
|
||||||
}
|
}
|
||||||
|
ptr = cts.cts_ptr;
|
||||||
|
vcol = cts.cts_vcol;
|
||||||
|
clear_chartabsize_arg(&cts);
|
||||||
|
|
||||||
if (vcol > want_vcol)
|
if (vcol > want_vcol)
|
||||||
{
|
{
|
||||||
// Must have a char with 'showbreak' just before it.
|
// Must have a char with 'showbreak' just before it.
|
||||||
@ -5221,9 +5231,9 @@ ins_digraph(void)
|
|||||||
ins_copychar(linenr_T lnum)
|
ins_copychar(linenr_T lnum)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
int temp;
|
|
||||||
char_u *ptr, *prev_ptr;
|
char_u *ptr, *prev_ptr;
|
||||||
char_u *line;
|
char_u *line;
|
||||||
|
chartabsize_T cts;
|
||||||
|
|
||||||
if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)
|
if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)
|
||||||
{
|
{
|
||||||
@ -5233,16 +5243,19 @@ ins_copychar(linenr_T lnum)
|
|||||||
|
|
||||||
// try to advance to the cursor column
|
// try to advance to the cursor column
|
||||||
validate_virtcol();
|
validate_virtcol();
|
||||||
temp = 0;
|
line = ml_get(lnum);
|
||||||
line = ptr = ml_get(lnum);
|
prev_ptr = line;
|
||||||
prev_ptr = ptr;
|
init_chartabsize_arg(&cts, curwin, lnum, 0, line, line);
|
||||||
while ((colnr_T)temp < curwin->w_virtcol && *ptr != NUL)
|
while (cts.cts_vcol < curwin->w_virtcol && *cts.cts_ptr != NUL)
|
||||||
{
|
{
|
||||||
prev_ptr = ptr;
|
prev_ptr = cts.cts_ptr;
|
||||||
temp += lbr_chartabsize_adv(line, &ptr, (colnr_T)temp);
|
cts.cts_vcol += lbr_chartabsize_adv(&cts);
|
||||||
}
|
}
|
||||||
if ((colnr_T)temp > curwin->w_virtcol)
|
if (cts.cts_vcol > curwin->w_virtcol)
|
||||||
ptr = prev_ptr;
|
ptr = prev_ptr;
|
||||||
|
else
|
||||||
|
ptr = cts.cts_ptr;
|
||||||
|
clear_chartabsize_arg(&cts);
|
||||||
|
|
||||||
c = (*mb_ptr2char)(ptr);
|
c = (*mb_ptr2char)(ptr);
|
||||||
if (c == NUL)
|
if (c == NUL)
|
||||||
|
@ -3310,3 +3310,7 @@ EXTERN char e_invalid_argument_nr[]
|
|||||||
EXTERN char e_cmdline_window_already_open[]
|
EXTERN char e_cmdline_window_already_open[]
|
||||||
INIT(= N_("E1292: Command-line window is already open"));
|
INIT(= N_("E1292: Command-line window is already open"));
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef FEAT_PROP_POPUP
|
||||||
|
EXTERN char e_cannot_use_negative_id_after_adding_textprop_with_text[]
|
||||||
|
INIT(= N_("E1291: Cannot use a negative id after adding a textprop with text"));
|
||||||
|
#endif
|
||||||
|
@ -2218,7 +2218,7 @@ static funcentry_T global_functions[] =
|
|||||||
{"prompt_setprompt", 2, 2, FEARG_1, arg2_buffer_string,
|
{"prompt_setprompt", 2, 2, FEARG_1, arg2_buffer_string,
|
||||||
ret_void, JOB_FUNC(f_prompt_setprompt)},
|
ret_void, JOB_FUNC(f_prompt_setprompt)},
|
||||||
{"prop_add", 3, 3, FEARG_1, arg3_number_number_dict,
|
{"prop_add", 3, 3, FEARG_1, arg3_number_number_dict,
|
||||||
ret_void, PROP_FUNC(f_prop_add)},
|
ret_number, PROP_FUNC(f_prop_add)},
|
||||||
{"prop_add_list", 2, 2, FEARG_1, arg2_dict_any_list_any,
|
{"prop_add_list", 2, 2, FEARG_1, arg2_dict_any_list_any,
|
||||||
ret_void, PROP_FUNC(f_prop_add_list)},
|
ret_void, PROP_FUNC(f_prop_add_list)},
|
||||||
{"prop_clear", 1, 3, FEARG_1, arg3_number_number_dict,
|
{"prop_clear", 1, 3, FEARG_1, arg3_number_number_dict,
|
||||||
|
@ -3210,7 +3210,7 @@ vgetorpeek(int advance)
|
|||||||
&& (c = inchar(typebuf.tb_buf + typebuf.tb_off
|
&& (c = inchar(typebuf.tb_buf + typebuf.tb_off
|
||||||
+ typebuf.tb_len, 3, 25L)) == 0)
|
+ typebuf.tb_len, 3, 25L)) == 0)
|
||||||
{
|
{
|
||||||
colnr_T col = 0, vcol;
|
colnr_T col = 0;
|
||||||
char_u *ptr;
|
char_u *ptr;
|
||||||
|
|
||||||
if (mode_displayed)
|
if (mode_displayed)
|
||||||
@ -3242,24 +3242,30 @@ vgetorpeek(int advance)
|
|||||||
{
|
{
|
||||||
if (did_ai)
|
if (did_ai)
|
||||||
{
|
{
|
||||||
|
chartabsize_T cts;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We are expecting to truncate the trailing
|
* We are expecting to truncate the trailing
|
||||||
* white-space, so find the last non-white
|
* white-space, so find the last non-white
|
||||||
* character -- webb
|
* character -- webb
|
||||||
*/
|
*/
|
||||||
col = vcol = curwin->w_wcol = 0;
|
curwin->w_wcol = 0;
|
||||||
ptr = ml_get_curline();
|
ptr = ml_get_curline();
|
||||||
while (col < curwin->w_cursor.col)
|
init_chartabsize_arg(&cts, curwin,
|
||||||
|
curwin->w_cursor.lnum, 0, ptr, ptr);
|
||||||
|
while (cts.cts_ptr < ptr + curwin->w_cursor.col)
|
||||||
{
|
{
|
||||||
if (!VIM_ISWHITE(ptr[col]))
|
if (!VIM_ISWHITE(*cts.cts_ptr))
|
||||||
curwin->w_wcol = vcol;
|
curwin->w_wcol = cts.cts_vcol;
|
||||||
vcol += lbr_chartabsize(ptr, ptr + col,
|
cts.cts_vcol += lbr_chartabsize(&cts);
|
||||||
vcol);
|
|
||||||
if (has_mbyte)
|
if (has_mbyte)
|
||||||
col += (*mb_ptr2len)(ptr + col);
|
cts.cts_ptr +=
|
||||||
|
(*mb_ptr2len)(cts.cts_ptr);
|
||||||
else
|
else
|
||||||
++col;
|
++cts.cts_ptr;
|
||||||
}
|
}
|
||||||
|
clear_chartabsize_arg(&cts);
|
||||||
|
|
||||||
curwin->w_wrow = curwin->w_cline_row
|
curwin->w_wrow = curwin->w_cline_row
|
||||||
+ curwin->w_wcol / curwin->w_width;
|
+ curwin->w_wcol / curwin->w_width;
|
||||||
curwin->w_wcol %= curwin->w_width;
|
curwin->w_wcol %= curwin->w_width;
|
||||||
|
78
src/indent.c
78
src/indent.c
@ -1350,26 +1350,28 @@ change_indent(
|
|||||||
new_cursor_col = curwin->w_cursor.col;
|
new_cursor_col = curwin->w_cursor.col;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
chartabsize_T cts;
|
||||||
|
|
||||||
// Compute the screen column where the cursor should be.
|
// Compute the screen column where the cursor should be.
|
||||||
vcol = get_indent() - vcol;
|
vcol = get_indent() - vcol;
|
||||||
curwin->w_virtcol = (colnr_T)((vcol < 0) ? 0 : vcol);
|
curwin->w_virtcol = (colnr_T)((vcol < 0) ? 0 : vcol);
|
||||||
|
|
||||||
// Advance the cursor until we reach the right screen column.
|
// Advance the cursor until we reach the right screen column.
|
||||||
vcol = last_vcol = 0;
|
last_vcol = 0;
|
||||||
new_cursor_col = -1;
|
|
||||||
ptr = ml_get_curline();
|
ptr = ml_get_curline();
|
||||||
while (vcol <= (int)curwin->w_virtcol)
|
init_chartabsize_arg(&cts, curwin, 0, 0, ptr, ptr);
|
||||||
|
while (cts.cts_vcol <= (int)curwin->w_virtcol)
|
||||||
{
|
{
|
||||||
last_vcol = vcol;
|
last_vcol = cts.cts_vcol;
|
||||||
if (has_mbyte && new_cursor_col >= 0)
|
if (cts.cts_vcol > 0)
|
||||||
new_cursor_col += (*mb_ptr2len)(ptr + new_cursor_col);
|
MB_PTR_ADV(cts.cts_ptr);
|
||||||
else
|
if (*cts.cts_ptr == NUL)
|
||||||
++new_cursor_col;
|
|
||||||
if (ptr[new_cursor_col] == NUL)
|
|
||||||
break;
|
break;
|
||||||
vcol += lbr_chartabsize(ptr, ptr + new_cursor_col, (colnr_T)vcol);
|
cts.cts_vcol += lbr_chartabsize(&cts);
|
||||||
}
|
}
|
||||||
vcol = last_vcol;
|
vcol = last_vcol;
|
||||||
|
new_cursor_col = cts.cts_ptr - cts.cts_line;
|
||||||
|
clear_chartabsize_arg(&cts);
|
||||||
|
|
||||||
// May need to insert spaces to be able to position the cursor on
|
// May need to insert spaces to be able to position the cursor on
|
||||||
// the right screen column.
|
// the right screen column.
|
||||||
@ -2065,13 +2067,17 @@ get_lisp_indent(void)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
char_u *line = that;
|
char_u *line = that;
|
||||||
|
chartabsize_T cts;
|
||||||
|
|
||||||
amount = 0;
|
init_chartabsize_arg(&cts, curwin, pos->lnum, 0, line, line);
|
||||||
while (*that && col)
|
while (*cts.cts_ptr != NUL && col > 0)
|
||||||
{
|
{
|
||||||
amount += lbr_chartabsize_adv(line, &that, (colnr_T)amount);
|
cts.cts_vcol += lbr_chartabsize_adv(&cts);
|
||||||
col--;
|
col--;
|
||||||
}
|
}
|
||||||
|
amount = cts.cts_vcol;
|
||||||
|
that = cts.cts_ptr;
|
||||||
|
clear_chartabsize_arg(&cts);
|
||||||
|
|
||||||
// Some keywords require "body" indenting rules (the
|
// Some keywords require "body" indenting rules (the
|
||||||
// non-standard-lisp ones are Scheme special forms):
|
// non-standard-lisp ones are Scheme special forms):
|
||||||
@ -2091,11 +2097,16 @@ get_lisp_indent(void)
|
|||||||
}
|
}
|
||||||
firsttry = amount;
|
firsttry = amount;
|
||||||
|
|
||||||
while (VIM_ISWHITE(*that))
|
init_chartabsize_arg(&cts, curwin, (colnr_T)(that - line),
|
||||||
|
amount, line, that);
|
||||||
|
while (VIM_ISWHITE(*cts.cts_ptr))
|
||||||
{
|
{
|
||||||
amount += lbr_chartabsize(line, that, (colnr_T)amount);
|
cts.cts_vcol += lbr_chartabsize(&cts);
|
||||||
++that;
|
++cts.cts_ptr;
|
||||||
}
|
}
|
||||||
|
that = cts.cts_ptr;
|
||||||
|
amount = cts.cts_vcol;
|
||||||
|
clear_chartabsize_arg(&cts);
|
||||||
|
|
||||||
if (*that && *that != ';') // not a comment line
|
if (*that && *that != ';') // not a comment line
|
||||||
{
|
{
|
||||||
@ -2107,42 +2118,47 @@ get_lisp_indent(void)
|
|||||||
parencount = 0;
|
parencount = 0;
|
||||||
quotecount = 0;
|
quotecount = 0;
|
||||||
|
|
||||||
|
init_chartabsize_arg(&cts, curwin,
|
||||||
|
(colnr_T)(that - line), amount, line, that);
|
||||||
if (vi_lisp
|
if (vi_lisp
|
||||||
|| (*that != '"'
|
|| (*that != '"'
|
||||||
&& *that != '\''
|
&& *that != '\''
|
||||||
&& *that != '#'
|
&& *that != '#'
|
||||||
&& (*that < '0' || *that > '9')))
|
&& (*that < '0' || *that > '9')))
|
||||||
{
|
{
|
||||||
while (*that
|
while (*cts.cts_ptr
|
||||||
&& (!VIM_ISWHITE(*that)
|
&& (!VIM_ISWHITE(*cts.cts_ptr)
|
||||||
|| quotecount
|
|| quotecount
|
||||||
|| parencount)
|
|| parencount)
|
||||||
&& (!((*that == '(' || *that == '[')
|
&& (!((*cts.cts_ptr == '('
|
||||||
|
|| *cts.cts_ptr == '[')
|
||||||
&& !quotecount
|
&& !quotecount
|
||||||
&& !parencount
|
&& !parencount
|
||||||
&& vi_lisp)))
|
&& vi_lisp)))
|
||||||
{
|
{
|
||||||
if (*that == '"')
|
if (*cts.cts_ptr == '"')
|
||||||
quotecount = !quotecount;
|
quotecount = !quotecount;
|
||||||
if ((*that == '(' || *that == '[')
|
if ((*cts.cts_ptr == '(' || *cts.cts_ptr == '[')
|
||||||
&& !quotecount)
|
&& !quotecount)
|
||||||
++parencount;
|
++parencount;
|
||||||
if ((*that == ')' || *that == ']')
|
if ((*cts.cts_ptr == ')' || *cts.cts_ptr == ']')
|
||||||
&& !quotecount)
|
&& !quotecount)
|
||||||
--parencount;
|
--parencount;
|
||||||
if (*that == '\\' && *(that+1) != NUL)
|
if (*cts.cts_ptr == '\\'
|
||||||
amount += lbr_chartabsize_adv(
|
&& *(cts.cts_ptr+1) != NUL)
|
||||||
line, &that, (colnr_T)amount);
|
cts.cts_vcol += lbr_chartabsize_adv(&cts);
|
||||||
amount += lbr_chartabsize_adv(
|
cts.cts_vcol += lbr_chartabsize_adv(&cts);
|
||||||
line, &that, (colnr_T)amount);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (VIM_ISWHITE(*that))
|
while (VIM_ISWHITE(*cts.cts_ptr))
|
||||||
{
|
{
|
||||||
amount += lbr_chartabsize(
|
cts.cts_vcol += lbr_chartabsize(&cts);
|
||||||
line, that, (colnr_T)amount);
|
++cts.cts_ptr;
|
||||||
that++;
|
|
||||||
}
|
}
|
||||||
|
that = cts.cts_ptr;
|
||||||
|
amount = cts.cts_vcol;
|
||||||
|
clear_chartabsize_arg(&cts);
|
||||||
|
|
||||||
if (!*that || *that == ';')
|
if (!*that || *that == ';')
|
||||||
amount = firsttry;
|
amount = firsttry;
|
||||||
}
|
}
|
||||||
|
30
src/misc1.c
30
src/misc1.c
@ -397,7 +397,7 @@ plines_win_nofold(win_T *wp, linenr_T lnum)
|
|||||||
s = ml_get_buf(wp->w_buffer, lnum, FALSE);
|
s = ml_get_buf(wp->w_buffer, lnum, FALSE);
|
||||||
if (*s == NUL) // empty line
|
if (*s == NUL) // empty line
|
||||||
return 1;
|
return 1;
|
||||||
col = win_linetabsize(wp, s, (colnr_T)MAXCOL);
|
col = win_linetabsize(wp, lnum, s, (colnr_T)MAXCOL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If list mode is on, then the '$' at the end of the line may take up one
|
* If list mode is on, then the '$' at the end of the line may take up one
|
||||||
@ -427,10 +427,10 @@ plines_win_nofold(win_T *wp, linenr_T lnum)
|
|||||||
plines_win_col(win_T *wp, linenr_T lnum, long column)
|
plines_win_col(win_T *wp, linenr_T lnum, long column)
|
||||||
{
|
{
|
||||||
long col;
|
long col;
|
||||||
char_u *s;
|
|
||||||
int lines = 0;
|
int lines = 0;
|
||||||
int width;
|
int width;
|
||||||
char_u *line;
|
char_u *line;
|
||||||
|
chartabsize_T cts;
|
||||||
|
|
||||||
#ifdef FEAT_DIFF
|
#ifdef FEAT_DIFF
|
||||||
// Check for filler lines above this buffer line. When folded the result
|
// Check for filler lines above this buffer line. When folded the result
|
||||||
@ -444,25 +444,27 @@ plines_win_col(win_T *wp, linenr_T lnum, long column)
|
|||||||
if (wp->w_width == 0)
|
if (wp->w_width == 0)
|
||||||
return lines + 1;
|
return lines + 1;
|
||||||
|
|
||||||
line = s = ml_get_buf(wp->w_buffer, lnum, FALSE);
|
line = ml_get_buf(wp->w_buffer, lnum, FALSE);
|
||||||
|
|
||||||
col = 0;
|
init_chartabsize_arg(&cts, wp, lnum, 0, line, line);
|
||||||
while (*s != NUL && --column >= 0)
|
while (*cts.cts_ptr != NUL && --column >= 0)
|
||||||
{
|
{
|
||||||
col += win_lbr_chartabsize(wp, line, s, (colnr_T)col, NULL);
|
cts.cts_vcol += win_lbr_chartabsize(&cts, NULL);
|
||||||
MB_PTR_ADV(s);
|
MB_PTR_ADV(cts.cts_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If *s is a TAB, and the TAB is not displayed as ^I, and we're not in
|
* If *cts.cts_ptr is a TAB, and the TAB is not displayed as ^I, and we're
|
||||||
* MODE_INSERT state, then col must be adjusted so that it represents the
|
* not in MODE_INSERT state, then col must be adjusted so that it
|
||||||
* last screen position of the TAB. This only fixes an error when the TAB
|
* represents the last screen position of the TAB. This only fixes an
|
||||||
* wraps from one screen line to the next (when 'columns' is not a multiple
|
* error when the TAB wraps from one screen line to the next (when
|
||||||
* of 'ts') -- webb.
|
* '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_lcs_chars.tab1))
|
&& (!wp->w_p_list || wp->w_lcs_chars.tab1))
|
||||||
col += win_lbr_chartabsize(wp, line, s, (colnr_T)col, NULL) - 1;
|
col += win_lbr_chartabsize(&cts, NULL) - 1;
|
||||||
|
clear_chartabsize_arg(&cts);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add column offset for 'number', 'relativenumber', 'foldcolumn', etc.
|
* Add column offset for 'number', 'relativenumber', 'foldcolumn', etc.
|
||||||
|
19
src/misc2.c
19
src/misc2.c
@ -128,7 +128,6 @@ coladvance2(
|
|||||||
{
|
{
|
||||||
colnr_T wcol = wcol_arg;
|
colnr_T wcol = wcol_arg;
|
||||||
int idx;
|
int idx;
|
||||||
char_u *ptr;
|
|
||||||
char_u *line;
|
char_u *line;
|
||||||
colnr_T col = 0;
|
colnr_T col = 0;
|
||||||
int csize = 0;
|
int csize = 0;
|
||||||
@ -158,6 +157,7 @@ coladvance2(
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
int width = curwin->w_width - win_col_off(curwin);
|
int width = curwin->w_width - win_col_off(curwin);
|
||||||
|
chartabsize_T cts;
|
||||||
|
|
||||||
if (finetune
|
if (finetune
|
||||||
&& curwin->w_p_wrap
|
&& curwin->w_p_wrap
|
||||||
@ -180,19 +180,22 @@ coladvance2(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr = line;
|
init_chartabsize_arg(&cts, curwin, pos->lnum, 0, line, line);
|
||||||
while (col <= wcol && *ptr != NUL)
|
while (cts.cts_vcol <= wcol && *cts.cts_ptr != NUL)
|
||||||
{
|
{
|
||||||
// Count a tab for what it's worth (if list mode not on)
|
// Count a tab for what it's worth (if list mode not on)
|
||||||
#ifdef FEAT_LINEBREAK
|
#ifdef FEAT_LINEBREAK
|
||||||
csize = win_lbr_chartabsize(curwin, line, ptr, col, &head);
|
csize = win_lbr_chartabsize(&cts, &head);
|
||||||
MB_PTR_ADV(ptr);
|
MB_PTR_ADV(cts.cts_ptr);
|
||||||
#else
|
#else
|
||||||
csize = lbr_chartabsize_adv(line, &ptr, col);
|
csize = lbr_chartabsize_adv(&cts);
|
||||||
#endif
|
#endif
|
||||||
col += csize;
|
cts.cts_vcol += csize;
|
||||||
}
|
}
|
||||||
idx = (int)(ptr - line);
|
col = cts.cts_vcol;
|
||||||
|
idx = (int)(cts.cts_ptr - line);
|
||||||
|
clear_chartabsize_arg(&cts);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle all the special cases. The virtual_active() check
|
* Handle all the special cases. The virtual_active() check
|
||||||
* is needed to ensure that a virtual position off the end of
|
* is needed to ensure that a virtual position off the end of
|
||||||
|
18
src/mouse.c
18
src/mouse.c
@ -3101,18 +3101,20 @@ mouse_find_win(int *rowp, int *colp, mouse_find_T popup UNUSED)
|
|||||||
int
|
int
|
||||||
vcol2col(win_T *wp, linenr_T lnum, int vcol)
|
vcol2col(win_T *wp, linenr_T lnum, int vcol)
|
||||||
{
|
{
|
||||||
// try to advance to the specified column
|
|
||||||
int count = 0;
|
|
||||||
char_u *ptr;
|
|
||||||
char_u *line;
|
char_u *line;
|
||||||
|
chartabsize_T cts;
|
||||||
|
|
||||||
line = ptr = ml_get_buf(wp->w_buffer, lnum, FALSE);
|
// try to advance to the specified column
|
||||||
while (count < vcol && *ptr != NUL)
|
line = ml_get_buf(wp->w_buffer, lnum, FALSE);
|
||||||
|
init_chartabsize_arg(&cts, wp, lnum, 0, line, line);
|
||||||
|
while (cts.cts_vcol < vcol && *cts.cts_ptr != NUL)
|
||||||
{
|
{
|
||||||
count += win_lbr_chartabsize(wp, line, ptr, count, NULL);
|
cts.cts_vcol += win_lbr_chartabsize(&cts, NULL);
|
||||||
MB_PTR_ADV(ptr);
|
MB_PTR_ADV(cts.cts_ptr);
|
||||||
}
|
}
|
||||||
return (int)(ptr - line);
|
clear_chartabsize_arg(&cts);
|
||||||
|
|
||||||
|
return (int)(cts.cts_ptr - line);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
84
src/ops.c
84
src/ops.c
@ -308,6 +308,7 @@ shift_block(oparg_T *oap, int amount)
|
|||||||
if (!left)
|
if (!left)
|
||||||
{
|
{
|
||||||
int tabs = 0, spaces = 0;
|
int tabs = 0, spaces = 0;
|
||||||
|
chartabsize_T cts;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 1. Get start vcol
|
* 1. Get start vcol
|
||||||
@ -332,13 +333,20 @@ shift_block(oparg_T *oap, int amount)
|
|||||||
else
|
else
|
||||||
++bd.textstart;
|
++bd.textstart;
|
||||||
}
|
}
|
||||||
for ( ; VIM_ISWHITE(*bd.textstart); )
|
|
||||||
{
|
|
||||||
// TODO: is passing bd.textstart for start of the line OK?
|
// TODO: is passing bd.textstart for start of the line OK?
|
||||||
incr = lbr_chartabsize_adv(bd.textstart, &bd.textstart, bd.start_vcol);
|
init_chartabsize_arg(&cts, curwin, curwin->w_cursor.lnum,
|
||||||
|
bd.start_vcol, bd.textstart, bd.textstart);
|
||||||
|
for ( ; VIM_ISWHITE(*cts.cts_ptr); )
|
||||||
|
{
|
||||||
|
incr = lbr_chartabsize_adv(&cts);
|
||||||
total += incr;
|
total += incr;
|
||||||
bd.start_vcol += incr;
|
cts.cts_vcol += incr;
|
||||||
}
|
}
|
||||||
|
bd.textstart = 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
|
// OK, now total=all the VWS reqd, and textstart points at the 1st
|
||||||
// non-ws char in the block.
|
// non-ws char in the block.
|
||||||
#ifdef FEAT_VARTABS
|
#ifdef FEAT_VARTABS
|
||||||
@ -381,6 +389,7 @@ shift_block(oparg_T *oap, int amount)
|
|||||||
size_t shift_amount;
|
size_t shift_amount;
|
||||||
char_u *non_white = bd.textstart;
|
char_u *non_white = bd.textstart;
|
||||||
colnr_T non_white_col;
|
colnr_T non_white_col;
|
||||||
|
chartabsize_T cts;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Firstly, let's find the first non-whitespace character that is
|
* Firstly, let's find the first non-whitespace character that is
|
||||||
@ -399,11 +408,16 @@ shift_block(oparg_T *oap, int amount)
|
|||||||
// The character's column is in "bd.start_vcol".
|
// The character's column is in "bd.start_vcol".
|
||||||
non_white_col = bd.start_vcol;
|
non_white_col = bd.start_vcol;
|
||||||
|
|
||||||
while (VIM_ISWHITE(*non_white))
|
init_chartabsize_arg(&cts, curwin, curwin->w_cursor.lnum,
|
||||||
|
non_white_col, bd.textstart, non_white);
|
||||||
|
while (VIM_ISWHITE(*cts.cts_ptr))
|
||||||
{
|
{
|
||||||
incr = lbr_chartabsize_adv(bd.textstart, &non_white, non_white_col);
|
incr = lbr_chartabsize_adv(&cts);
|
||||||
non_white_col += incr;
|
cts.cts_vcol += incr;
|
||||||
}
|
}
|
||||||
|
non_white_col = cts.cts_vcol;
|
||||||
|
non_white = cts.cts_ptr;
|
||||||
|
clear_chartabsize_arg(&cts);
|
||||||
|
|
||||||
block_space_width = non_white_col - oap->start_vcol;
|
block_space_width = non_white_col - oap->start_vcol;
|
||||||
// We will shift by "total" or "block_space_width", whichever is less.
|
// We will shift by "total" or "block_space_width", whichever is less.
|
||||||
@ -423,18 +437,19 @@ shift_block(oparg_T *oap, int amount)
|
|||||||
// column number.
|
// column number.
|
||||||
if (bd.startspaces)
|
if (bd.startspaces)
|
||||||
verbatim_copy_width -= bd.start_char_vcols;
|
verbatim_copy_width -= bd.start_char_vcols;
|
||||||
while (verbatim_copy_width < destination_col)
|
init_chartabsize_arg(&cts, curwin, 0, verbatim_copy_width,
|
||||||
|
bd.textstart, verbatim_copy_end);
|
||||||
|
while (cts.cts_vcol < destination_col)
|
||||||
{
|
{
|
||||||
char_u *line = verbatim_copy_end;
|
incr = lbr_chartabsize(&cts);
|
||||||
|
if (cts.cts_vcol + incr > destination_col)
|
||||||
// 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)
|
|
||||||
break;
|
break;
|
||||||
verbatim_copy_width += incr;
|
cts.cts_vcol += incr;
|
||||||
MB_PTR_ADV(verbatim_copy_end);
|
MB_PTR_ADV(cts.cts_ptr);
|
||||||
}
|
}
|
||||||
|
verbatim_copy_width = cts.cts_vcol;
|
||||||
|
verbatim_copy_end = cts.cts_ptr;
|
||||||
|
clear_chartabsize_arg(&cts);
|
||||||
|
|
||||||
// If "destination_col" is different from the width of the initial
|
// 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
|
// part of the line that will be copied, it means we encountered a tab
|
||||||
@ -703,8 +718,6 @@ op_delete(oparg_T *oap)
|
|||||||
* Put deleted text into register 1 and shift number registers if the
|
* Put deleted text into register 1 and shift number registers if the
|
||||||
* delete contains a line break, or when using a specific operator (Vi
|
* delete contains a line break, or when using a specific operator (Vi
|
||||||
* compatible)
|
* compatible)
|
||||||
* Use the register name from before adjust_clip_reg() may have
|
|
||||||
* changed it.
|
|
||||||
*/
|
*/
|
||||||
if (oap->motion_type == MLINE || oap->line_count > 1
|
if (oap->motion_type == MLINE || oap->line_count > 1
|
||||||
|| oap->use_reg_one)
|
|| oap->use_reg_one)
|
||||||
@ -2213,6 +2226,7 @@ block_prep(
|
|||||||
char_u *line;
|
char_u *line;
|
||||||
char_u *prev_pstart;
|
char_u *prev_pstart;
|
||||||
char_u *prev_pend;
|
char_u *prev_pend;
|
||||||
|
chartabsize_T cts;
|
||||||
#ifdef FEAT_LINEBREAK
|
#ifdef FEAT_LINEBREAK
|
||||||
int lbr_saved = curwin->w_p_lbr;
|
int lbr_saved = curwin->w_p_lbr;
|
||||||
|
|
||||||
@ -2232,14 +2246,14 @@ block_prep(
|
|||||||
bdp->start_char_vcols = 0;
|
bdp->start_char_vcols = 0;
|
||||||
|
|
||||||
line = ml_get(lnum);
|
line = ml_get(lnum);
|
||||||
pstart = line;
|
|
||||||
prev_pstart = line;
|
prev_pstart = line;
|
||||||
while (bdp->start_vcol < oap->start_vcol && *pstart)
|
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)
|
// Count a tab for what it's worth (if list mode not on)
|
||||||
incr = lbr_chartabsize(line, pstart, bdp->start_vcol);
|
incr = lbr_chartabsize(&cts);
|
||||||
bdp->start_vcol += incr;
|
cts.cts_vcol += incr;
|
||||||
if (VIM_ISWHITE(*pstart))
|
if (VIM_ISWHITE(*cts.cts_ptr))
|
||||||
{
|
{
|
||||||
bdp->pre_whitesp += incr;
|
bdp->pre_whitesp += incr;
|
||||||
bdp->pre_whitesp_c++;
|
bdp->pre_whitesp_c++;
|
||||||
@ -2249,9 +2263,13 @@ block_prep(
|
|||||||
bdp->pre_whitesp = 0;
|
bdp->pre_whitesp = 0;
|
||||||
bdp->pre_whitesp_c = 0;
|
bdp->pre_whitesp_c = 0;
|
||||||
}
|
}
|
||||||
prev_pstart = pstart;
|
prev_pstart = cts.cts_ptr;
|
||||||
MB_PTR_ADV(pstart);
|
MB_PTR_ADV(cts.cts_ptr);
|
||||||
}
|
}
|
||||||
|
bdp->start_vcol = cts.cts_vcol;
|
||||||
|
pstart = cts.cts_ptr;
|
||||||
|
clear_chartabsize_arg(&cts);
|
||||||
|
|
||||||
bdp->start_char_vcols = incr;
|
bdp->start_char_vcols = incr;
|
||||||
if (bdp->start_vcol < oap->start_vcol) // line too short
|
if (bdp->start_vcol < oap->start_vcol) // line too short
|
||||||
{
|
{
|
||||||
@ -2295,14 +2313,20 @@ block_prep(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
init_chartabsize_arg(&cts, curwin, lnum, bdp->end_vcol,
|
||||||
|
line, pend);
|
||||||
prev_pend = 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)
|
// count a tab for what it's worth (if list mode not on)
|
||||||
prev_pend = pend;
|
prev_pend = cts.cts_ptr;
|
||||||
incr = lbr_chartabsize_adv(line, &pend, bdp->end_vcol);
|
incr = lbr_chartabsize_adv(&cts);
|
||||||
bdp->end_vcol += incr;
|
cts.cts_vcol += incr;
|
||||||
}
|
}
|
||||||
|
bdp->end_vcol = cts.cts_vcol;
|
||||||
|
pend = cts.cts_ptr;
|
||||||
|
clear_chartabsize_arg(&cts);
|
||||||
|
|
||||||
if (bdp->end_vcol <= oap->end_vcol
|
if (bdp->end_vcol <= oap->end_vcol
|
||||||
&& (!is_del
|
&& (!is_del
|
||||||
|| oap->op_type == OP_APPEND
|
|| oap->op_type == OP_APPEND
|
||||||
|
@ -1371,7 +1371,7 @@ popup_adjust_position(win_T *wp)
|
|||||||
// "margin_width" is added to "len" where it matters.
|
// "margin_width" is added to "len" where it matters.
|
||||||
if (wp->w_width < maxwidth)
|
if (wp->w_width < maxwidth)
|
||||||
wp->w_width = maxwidth;
|
wp->w_width = maxwidth;
|
||||||
len = win_linetabsize(wp, ml_get_buf(wp->w_buffer, lnum, FALSE),
|
len = win_linetabsize(wp, lnum, ml_get_buf(wp->w_buffer, lnum, FALSE),
|
||||||
(colnr_T)MAXCOL);
|
(colnr_T)MAXCOL);
|
||||||
wp->w_width = w_width;
|
wp->w_width = w_width;
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ int vim_strnsize(char_u *s, int len);
|
|||||||
int chartabsize(char_u *p, colnr_T col);
|
int chartabsize(char_u *p, colnr_T col);
|
||||||
int linetabsize(char_u *s);
|
int linetabsize(char_u *s);
|
||||||
int linetabsize_col(int startcol, char_u *s);
|
int linetabsize_col(int startcol, char_u *s);
|
||||||
int win_linetabsize(win_T *wp, char_u *line, colnr_T len);
|
int win_linetabsize(win_T *wp, linenr_T lnum, char_u *line, colnr_T len);
|
||||||
int vim_isIDc(int c);
|
int vim_isIDc(int c);
|
||||||
int vim_isNormalIDc(int c);
|
int vim_isNormalIDc(int c);
|
||||||
int vim_iswordc(int c);
|
int vim_iswordc(int c);
|
||||||
@ -28,9 +28,11 @@ int vim_isfilec(int c);
|
|||||||
int vim_isfilec_or_wc(int c);
|
int vim_isfilec_or_wc(int c);
|
||||||
int vim_isprintc(int c);
|
int vim_isprintc(int c);
|
||||||
int vim_isprintc_strict(int c);
|
int vim_isprintc_strict(int c);
|
||||||
int lbr_chartabsize(char_u *line, unsigned char *s, colnr_T col);
|
void init_chartabsize_arg(chartabsize_T *cts, win_T *wp, linenr_T lnum, colnr_T col, char_u *line, char_u *ptr);
|
||||||
int lbr_chartabsize_adv(char_u *line, char_u **s, colnr_T col);
|
void clear_chartabsize_arg(chartabsize_T *cts);
|
||||||
int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *headp);
|
int lbr_chartabsize(chartabsize_T *cts);
|
||||||
|
int lbr_chartabsize_adv(chartabsize_T *cts);
|
||||||
|
int win_lbr_chartabsize(chartabsize_T *cts, int *headp);
|
||||||
void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end);
|
void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end);
|
||||||
colnr_T getvcol_nolist(pos_T *posp);
|
colnr_T getvcol_nolist(pos_T *posp);
|
||||||
void getvvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end);
|
void getvvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
int find_prop_type_id(char_u *name, buf_T *buf);
|
int find_prop_type_id(char_u *name, buf_T *buf);
|
||||||
void f_prop_add(typval_T *argvars, typval_T *rettv);
|
void f_prop_add(typval_T *argvars, typval_T *rettv);
|
||||||
void f_prop_add_list(typval_T *argvars, typval_T *rettv);
|
void f_prop_add_list(typval_T *argvars, typval_T *rettv);
|
||||||
void prop_add_common(linenr_T start_lnum, colnr_T start_col, dict_T *dict, buf_T *default_buf, typval_T *dict_arg);
|
int prop_add_common(linenr_T start_lnum, colnr_T start_col, dict_T *dict, buf_T *default_buf, typval_T *dict_arg);
|
||||||
int get_text_props(buf_T *buf, linenr_T lnum, char_u **props, int will_change);
|
int get_text_props(buf_T *buf, linenr_T lnum, char_u **props, int will_change);
|
||||||
int count_props(linenr_T lnum, int only_starting);
|
int count_props(linenr_T lnum, int only_starting);
|
||||||
int find_visible_prop(win_T *wp, int type_id, int id, textprop_T *prop, linenr_T *found_lnum);
|
int find_visible_prop(win_T *wp, int type_id, int id, textprop_T *prop, linenr_T *found_lnum);
|
||||||
|
@ -1303,7 +1303,7 @@ reg_match_visual(void)
|
|||||||
rex.line = reg_getline(rex.lnum);
|
rex.line = reg_getline(rex.lnum);
|
||||||
rex.input = rex.line + col;
|
rex.input = rex.line + col;
|
||||||
|
|
||||||
cols = win_linetabsize(wp, rex.line, col);
|
cols = win_linetabsize(wp, rex.reg_firstlnum + rex.lnum, rex.line, col);
|
||||||
if (cols < start || cols > end - (*p_sel == 'e'))
|
if (cols < start || cols > end - (*p_sel == 'e'))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -3441,7 +3441,9 @@ regmatch(
|
|||||||
case RE_VCOL:
|
case RE_VCOL:
|
||||||
if (!re_num_cmp((long_u)win_linetabsize(
|
if (!re_num_cmp((long_u)win_linetabsize(
|
||||||
rex.reg_win == NULL ? curwin : rex.reg_win,
|
rex.reg_win == NULL ? curwin : rex.reg_win,
|
||||||
rex.line, (colnr_T)(rex.input - rex.line)) + 1, scan))
|
rex.reg_firstlnum + rex.lnum,
|
||||||
|
rex.line,
|
||||||
|
(colnr_T)(rex.input - rex.line)) + 1, scan))
|
||||||
status = RA_NOMATCH;
|
status = RA_NOMATCH;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -6775,7 +6775,9 @@ nfa_regmatch(
|
|||||||
}
|
}
|
||||||
if (!result)
|
if (!result)
|
||||||
result = nfa_re_num_cmp(t->state->val, op,
|
result = nfa_re_num_cmp(t->state->val, op,
|
||||||
(long_u)win_linetabsize(wp, rex.line, col) + 1);
|
(long_u)win_linetabsize(wp,
|
||||||
|
rex.reg_firstlnum + rex.lnum,
|
||||||
|
rex.line, col) + 1);
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
add_here = TRUE;
|
add_here = TRUE;
|
||||||
|
@ -1822,6 +1822,7 @@ do_put(
|
|||||||
{
|
{
|
||||||
int spaces = 0;
|
int spaces = 0;
|
||||||
char shortline;
|
char shortline;
|
||||||
|
chartabsize_T cts;
|
||||||
|
|
||||||
bd.startspaces = 0;
|
bd.startspaces = 0;
|
||||||
bd.endspaces = 0;
|
bd.endspaces = 0;
|
||||||
@ -1839,13 +1840,19 @@ do_put(
|
|||||||
// get the old line and advance to the position to insert at
|
// get the old line and advance to the position to insert at
|
||||||
oldp = ml_get_curline();
|
oldp = ml_get_curline();
|
||||||
oldlen = (int)STRLEN(oldp);
|
oldlen = (int)STRLEN(oldp);
|
||||||
for (ptr = oldp; vcol < col && *ptr; )
|
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)
|
// Count a tab for what it's worth (if list mode not on)
|
||||||
incr = lbr_chartabsize_adv(oldp, &ptr, vcol);
|
incr = lbr_chartabsize_adv(&cts);
|
||||||
vcol += incr;
|
cts.cts_vcol += incr;
|
||||||
}
|
}
|
||||||
|
vcol = cts.cts_vcol;
|
||||||
|
ptr = cts.cts_ptr;
|
||||||
bd.textcol = (colnr_T)(ptr - oldp);
|
bd.textcol = (colnr_T)(ptr - oldp);
|
||||||
|
clear_chartabsize_arg(&cts);
|
||||||
|
|
||||||
shortline = (vcol < col) || (vcol == col && !*ptr) ;
|
shortline = (vcol < col) || (vcol == col && !*ptr) ;
|
||||||
|
|
||||||
@ -1876,8 +1883,15 @@ do_put(
|
|||||||
// calculate number of spaces required to fill right side of
|
// calculate number of spaces required to fill right side of
|
||||||
// block
|
// block
|
||||||
spaces = y_width + 1;
|
spaces = y_width + 1;
|
||||||
|
init_chartabsize_arg(&cts, curwin, 0, 0,
|
||||||
|
y_array[i], y_array[i]);
|
||||||
for (j = 0; j < yanklen; j++)
|
for (j = 0; j < yanklen; j++)
|
||||||
spaces -= lbr_chartabsize(NULL, &y_array[i][j], 0);
|
{
|
||||||
|
spaces -= lbr_chartabsize(&cts);
|
||||||
|
++cts.cts_ptr;
|
||||||
|
cts.cts_vcol = 0;
|
||||||
|
}
|
||||||
|
clear_chartabsize_arg(&cts);
|
||||||
if (spaces < 0)
|
if (spaces < 0)
|
||||||
spaces = 0;
|
spaces = 0;
|
||||||
}
|
}
|
||||||
|
@ -806,8 +806,9 @@ typedef struct textprop_S
|
|||||||
int tp_flags; // TP_FLAG_ values
|
int tp_flags; // TP_FLAG_ values
|
||||||
} textprop_T;
|
} textprop_T;
|
||||||
|
|
||||||
#define TP_FLAG_CONT_NEXT 1 // property continues in next line
|
#define TP_FLAG_CONT_NEXT 0x1 // property continues in next line
|
||||||
#define TP_FLAG_CONT_PREV 2 // property was continued from prev line
|
#define TP_FLAG_CONT_PREV 0x2 // property was continued from prev line
|
||||||
|
#define TP_VIRTUAL 0x4 // virtual text, uses tp_id
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Structure defining a property type.
|
* Structure defining a property type.
|
||||||
@ -3074,6 +3075,7 @@ struct file_buffer
|
|||||||
#ifdef FEAT_PROP_POPUP
|
#ifdef FEAT_PROP_POPUP
|
||||||
int b_has_textprop; // TRUE when text props were added
|
int b_has_textprop; // TRUE when text props were added
|
||||||
hashtab_T *b_proptypes; // text property types local to buffer
|
hashtab_T *b_proptypes; // text property types local to buffer
|
||||||
|
garray_T b_textprop_text; // stores text for props, index by (-id - 1)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(FEAT_BEVAL) && defined(FEAT_EVAL)
|
#if defined(FEAT_BEVAL) && defined(FEAT_EVAL)
|
||||||
@ -4560,3 +4562,18 @@ typedef struct {
|
|||||||
char_u *str;
|
char_u *str;
|
||||||
int score;
|
int score;
|
||||||
} fuzmatch_str_T;
|
} fuzmatch_str_T;
|
||||||
|
|
||||||
|
// Argument for lbr_chartabsize().
|
||||||
|
typedef struct {
|
||||||
|
win_T *cts_win;
|
||||||
|
linenr_T cts_lnum; // zero when not using text properties
|
||||||
|
char_u *cts_line; // start of the line
|
||||||
|
char_u *cts_ptr; // current position in line
|
||||||
|
#ifdef FEAT_PROP_POPUP
|
||||||
|
int cts_text_prop_count; // number of text props
|
||||||
|
textprop_T *cts_text_props; // text props (allocated) or NULL
|
||||||
|
char cts_has_prop_with_text; // TRUE if if a property inserts text
|
||||||
|
int cts_cur_text_width; // width of current inserted text
|
||||||
|
#endif
|
||||||
|
int cts_vcol; // virtual column at current position
|
||||||
|
} chartabsize_T;
|
||||||
|
6
src/testdir/dumps/Test_prop_inserts_text.dump
Normal file
6
src/testdir/dumps/Test_prop_inserts_text.dump
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|i+0&#ffffff0|n|s|e|r|t| |s|o|m|e| |t|e|x|t| |S+0#ffffff16#e000002|O|M|E| |h+0#0000000#ffffff0|e|r|e| |a|n|d| |o|t|h|e|r| |t|e|x|t| |O+0&#ffff4012|T|H|E|R| |t+0&#ffffff0|h|e|r|e| |a|n|d| |s|o
|
||||||
|
|m|e| |m|o|r|e| |t|e|x|t| |a|f|t|e|r| |M+0fd7ff255|O|R|E| |w+0&#ffffff0|r|a|p@1|i|n|g> @27
|
||||||
|
|~+0#4040ff13&| @58
|
||||||
|
|~| @58
|
||||||
|
|~| @58
|
||||||
|
| +0#0000000&@41|1|,|7@1|-|9|3| @6|A|l@1|
|
@ -2187,4 +2187,27 @@ func Test_props_do_not_affect_byte_offsets_editline()
|
|||||||
bwipe!
|
bwipe!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_prop_inserts_text()
|
||||||
|
CheckRunVimInTerminal
|
||||||
|
|
||||||
|
" Just a basic check for now
|
||||||
|
let lines =<< trim END
|
||||||
|
call setline(1, 'insert some text here and other text there and some more text after wrapping')
|
||||||
|
call prop_type_add('someprop', #{highlight: 'ErrorMsg'})
|
||||||
|
call prop_type_add('otherprop', #{highlight: 'Search'})
|
||||||
|
call prop_type_add('moreprop', #{highlight: 'DiffAdd'})
|
||||||
|
call prop_add(1, 18, #{type: 'someprop', text: 'SOME '})
|
||||||
|
call prop_add(1, 38, #{type: 'otherprop', text: 'OTHER '})
|
||||||
|
call prop_add(1, 69, #{type: 'moreprop', text: 'MORE '})
|
||||||
|
redraw
|
||||||
|
normal $
|
||||||
|
END
|
||||||
|
call writefile(lines, 'XscriptPropsWithText')
|
||||||
|
let buf = RunVimInTerminal('-S XscriptPropsWithText', #{rows: 6, cols: 60})
|
||||||
|
call VerifyScreenDump(buf, 'Test_prop_inserts_text', {})
|
||||||
|
|
||||||
|
call StopVimInTerminal(buf)
|
||||||
|
call delete('XscriptPropsWithText')
|
||||||
|
endfunc
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
100
src/textprop.c
100
src/textprop.c
@ -150,7 +150,7 @@ get_bufnr_from_arg(typval_T *arg, buf_T **buf)
|
|||||||
* prop_add({lnum}, {col}, {props})
|
* prop_add({lnum}, {col}, {props})
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
f_prop_add(typval_T *argvars, typval_T *rettv UNUSED)
|
f_prop_add(typval_T *argvars, typval_T *rettv)
|
||||||
{
|
{
|
||||||
linenr_T start_lnum;
|
linenr_T start_lnum;
|
||||||
colnr_T start_col;
|
colnr_T start_col;
|
||||||
@ -174,20 +174,22 @@ f_prop_add(typval_T *argvars, typval_T *rettv UNUSED)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
prop_add_common(start_lnum, start_col, argvars[2].vval.v_dict,
|
rettv->vval.v_number = prop_add_common(start_lnum, start_col,
|
||||||
curbuf, &argvars[2]);
|
argvars[2].vval.v_dict, curbuf, &argvars[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attach a text property 'type_name' to the text starting
|
* Attach a text property 'type_name' to the text starting
|
||||||
* at [start_lnum, start_col] and ending at [end_lnum, end_col] in
|
* at [start_lnum, start_col] and ending at [end_lnum, end_col] in
|
||||||
* the buffer 'buf' and assign identifier 'id'.
|
* the buffer "buf" and assign identifier "id".
|
||||||
|
* When "text" is not NULL add it to buf->b_textprop_text[-id - 1].
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
prop_add_one(
|
prop_add_one(
|
||||||
buf_T *buf,
|
buf_T *buf,
|
||||||
char_u *type_name,
|
char_u *type_name,
|
||||||
int id,
|
int id,
|
||||||
|
char_u *text_arg,
|
||||||
linenr_T start_lnum,
|
linenr_T start_lnum,
|
||||||
linenr_T end_lnum,
|
linenr_T end_lnum,
|
||||||
colnr_T start_col,
|
colnr_T start_col,
|
||||||
@ -202,26 +204,43 @@ prop_add_one(
|
|||||||
char_u *newtext;
|
char_u *newtext;
|
||||||
int i;
|
int i;
|
||||||
textprop_T tmp_prop;
|
textprop_T tmp_prop;
|
||||||
|
char_u *text = text_arg;
|
||||||
|
int res = FAIL;
|
||||||
|
|
||||||
type = lookup_prop_type(type_name, buf);
|
type = lookup_prop_type(type_name, buf);
|
||||||
if (type == NULL)
|
if (type == NULL)
|
||||||
return FAIL;
|
goto theend;
|
||||||
|
|
||||||
if (start_lnum < 1 || start_lnum > buf->b_ml.ml_line_count)
|
if (start_lnum < 1 || start_lnum > buf->b_ml.ml_line_count)
|
||||||
{
|
{
|
||||||
semsg(_(e_invalid_line_number_nr), (long)start_lnum);
|
semsg(_(e_invalid_line_number_nr), (long)start_lnum);
|
||||||
return FAIL;
|
goto theend;
|
||||||
}
|
}
|
||||||
if (end_lnum < start_lnum || end_lnum > buf->b_ml.ml_line_count)
|
if (end_lnum < start_lnum || end_lnum > buf->b_ml.ml_line_count)
|
||||||
{
|
{
|
||||||
semsg(_(e_invalid_line_number_nr), (long)end_lnum);
|
semsg(_(e_invalid_line_number_nr), (long)end_lnum);
|
||||||
return FAIL;
|
goto theend;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf->b_ml.ml_mfp == NULL)
|
if (buf->b_ml.ml_mfp == NULL)
|
||||||
{
|
{
|
||||||
emsg(_(e_cannot_add_text_property_to_unloaded_buffer));
|
emsg(_(e_cannot_add_text_property_to_unloaded_buffer));
|
||||||
return FAIL;
|
goto theend;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (text != NULL)
|
||||||
|
{
|
||||||
|
garray_T *gap = &buf->b_textprop_text;
|
||||||
|
|
||||||
|
// double check we got the right ID
|
||||||
|
if (-id - 1 != gap->ga_len)
|
||||||
|
iemsg("text prop ID mismatch");
|
||||||
|
if (gap->ga_growsize == 0)
|
||||||
|
ga_init2(gap, sizeof(char *), 50);
|
||||||
|
if (ga_grow(gap, 1) == FAIL)
|
||||||
|
goto theend;
|
||||||
|
((char_u **)gap->ga_data)[gap->ga_len++] = text;
|
||||||
|
text = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (lnum = start_lnum; lnum <= end_lnum; ++lnum)
|
for (lnum = start_lnum; lnum <= end_lnum; ++lnum)
|
||||||
@ -240,7 +259,7 @@ prop_add_one(
|
|||||||
if (col - 1 > (colnr_T)textlen)
|
if (col - 1 > (colnr_T)textlen)
|
||||||
{
|
{
|
||||||
semsg(_(e_invalid_column_number_nr), (long)start_col);
|
semsg(_(e_invalid_column_number_nr), (long)start_col);
|
||||||
return FAIL;
|
goto theend;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lnum == end_lnum)
|
if (lnum == end_lnum)
|
||||||
@ -255,7 +274,7 @@ prop_add_one(
|
|||||||
// Allocate the new line with space for the new property.
|
// Allocate the new line with space for the new property.
|
||||||
newtext = alloc(buf->b_ml.ml_line_len + sizeof(textprop_T));
|
newtext = alloc(buf->b_ml.ml_line_len + sizeof(textprop_T));
|
||||||
if (newtext == NULL)
|
if (newtext == NULL)
|
||||||
return FAIL;
|
goto theend;
|
||||||
// Copy the text, including terminating NUL.
|
// Copy the text, including terminating NUL.
|
||||||
mch_memmove(newtext, buf->b_ml.ml_line_ptr, textlen);
|
mch_memmove(newtext, buf->b_ml.ml_line_ptr, textlen);
|
||||||
|
|
||||||
@ -295,7 +314,11 @@ prop_add_one(
|
|||||||
}
|
}
|
||||||
|
|
||||||
changed_lines_buf(buf, start_lnum, end_lnum + 1, 0);
|
changed_lines_buf(buf, start_lnum, end_lnum + 1, 0);
|
||||||
return OK;
|
res = OK;
|
||||||
|
|
||||||
|
theend:
|
||||||
|
vim_free(text);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -367,7 +390,7 @@ f_prop_add_list(typval_T *argvars, typval_T *rettv UNUSED)
|
|||||||
emsg(_(e_invalid_argument));
|
emsg(_(e_invalid_argument));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (prop_add_one(buf, type_name, id, start_lnum, end_lnum,
|
if (prop_add_one(buf, type_name, id, NULL, start_lnum, end_lnum,
|
||||||
start_col, end_col) == FAIL)
|
start_col, end_col) == FAIL)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -375,12 +398,23 @@ f_prop_add_list(typval_T *argvars, typval_T *rettv UNUSED)
|
|||||||
redraw_buf_later(buf, VALID);
|
redraw_buf_later(buf, VALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the next ID to use for a textprop with text in buffer "buf".
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
get_textprop_id(buf_T *buf)
|
||||||
|
{
|
||||||
|
// TODO: recycle deleted entries
|
||||||
|
return -(buf->b_textprop_text.ga_len + 1);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Shared between prop_add() and popup_create().
|
* Shared between prop_add() and popup_create().
|
||||||
* "dict_arg" is the function argument of a dict containing "bufnr".
|
* "dict_arg" is the function argument of a dict containing "bufnr".
|
||||||
* it is NULL for popup_create().
|
* it is NULL for popup_create().
|
||||||
|
* Returns the "id" used for "text" or zero.
|
||||||
*/
|
*/
|
||||||
void
|
int
|
||||||
prop_add_common(
|
prop_add_common(
|
||||||
linenr_T start_lnum,
|
linenr_T start_lnum,
|
||||||
colnr_T start_col,
|
colnr_T start_col,
|
||||||
@ -393,11 +427,12 @@ prop_add_common(
|
|||||||
char_u *type_name;
|
char_u *type_name;
|
||||||
buf_T *buf = default_buf;
|
buf_T *buf = default_buf;
|
||||||
int id = 0;
|
int id = 0;
|
||||||
|
char_u *text = NULL;
|
||||||
|
|
||||||
if (dict == NULL || !dict_has_key(dict, "type"))
|
if (dict == NULL || !dict_has_key(dict, "type"))
|
||||||
{
|
{
|
||||||
emsg(_(e_missing_property_type_name));
|
emsg(_(e_missing_property_type_name));
|
||||||
return;
|
goto theend;
|
||||||
}
|
}
|
||||||
type_name = dict_get_string(dict, "type", FALSE);
|
type_name = dict_get_string(dict, "type", FALSE);
|
||||||
|
|
||||||
@ -407,7 +442,7 @@ prop_add_common(
|
|||||||
if (end_lnum < start_lnum)
|
if (end_lnum < start_lnum)
|
||||||
{
|
{
|
||||||
semsg(_(e_invalid_value_for_argument_str), "end_lnum");
|
semsg(_(e_invalid_value_for_argument_str), "end_lnum");
|
||||||
return;
|
goto theend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -420,7 +455,7 @@ prop_add_common(
|
|||||||
if (length < 0 || end_lnum > start_lnum)
|
if (length < 0 || end_lnum > start_lnum)
|
||||||
{
|
{
|
||||||
semsg(_(e_invalid_value_for_argument_str), "length");
|
semsg(_(e_invalid_value_for_argument_str), "length");
|
||||||
return;
|
goto theend;
|
||||||
}
|
}
|
||||||
end_col = start_col + length;
|
end_col = start_col + length;
|
||||||
}
|
}
|
||||||
@ -430,7 +465,7 @@ prop_add_common(
|
|||||||
if (end_col <= 0)
|
if (end_col <= 0)
|
||||||
{
|
{
|
||||||
semsg(_(e_invalid_value_for_argument_str), "end_col");
|
semsg(_(e_invalid_value_for_argument_str), "end_col");
|
||||||
return;
|
goto theend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (start_lnum == end_lnum)
|
else if (start_lnum == end_lnum)
|
||||||
@ -441,17 +476,40 @@ prop_add_common(
|
|||||||
if (dict_has_key(dict, "id"))
|
if (dict_has_key(dict, "id"))
|
||||||
id = dict_get_number(dict, "id");
|
id = dict_get_number(dict, "id");
|
||||||
|
|
||||||
|
if (dict_has_key(dict, "text"))
|
||||||
|
{
|
||||||
|
text = dict_get_string(dict, "text", TRUE);
|
||||||
|
if (text == NULL)
|
||||||
|
goto theend;
|
||||||
|
// use a default length of 1 to make multiple props show up
|
||||||
|
end_col = start_col + 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (dict_arg != NULL && get_bufnr_from_arg(dict_arg, &buf) == FAIL)
|
if (dict_arg != NULL && get_bufnr_from_arg(dict_arg, &buf) == FAIL)
|
||||||
return;
|
goto theend;
|
||||||
|
|
||||||
|
if (id < 0 && buf->b_textprop_text.ga_len > 0)
|
||||||
|
{
|
||||||
|
emsg(_(e_cannot_use_negative_id_after_adding_textprop_with_text));
|
||||||
|
goto theend;
|
||||||
|
}
|
||||||
|
if (text != NULL)
|
||||||
|
id = get_textprop_id(buf);
|
||||||
|
|
||||||
// This must be done _before_ we add the property because property changes
|
// This must be done _before_ we add the property because property changes
|
||||||
// trigger buffer (memline) reorganisation, which needs this flag to be
|
// trigger buffer (memline) reorganisation, which needs this flag to be
|
||||||
// correctly set.
|
// correctly set.
|
||||||
buf->b_has_textprop = TRUE; // this is never reset
|
buf->b_has_textprop = TRUE; // this is never reset
|
||||||
|
|
||||||
prop_add_one(buf, type_name, id, start_lnum, end_lnum, start_col, end_col);
|
prop_add_one(buf, type_name, id, text,
|
||||||
|
start_lnum, end_lnum, start_col, end_col);
|
||||||
|
text = NULL;
|
||||||
|
|
||||||
redraw_buf_later(buf, VALID);
|
redraw_buf_later(buf, VALID);
|
||||||
|
|
||||||
|
theend:
|
||||||
|
vim_free(text);
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -954,8 +1012,8 @@ get_props_in_line(
|
|||||||
if ((prop_types == NULL
|
if ((prop_types == NULL
|
||||||
|| prop_type_or_id_in_list(prop_types, prop_types_len,
|
|| prop_type_or_id_in_list(prop_types, prop_types_len,
|
||||||
prop.tp_type))
|
prop.tp_type))
|
||||||
&& (prop_ids == NULL ||
|
&& (prop_ids == NULL
|
||||||
prop_type_or_id_in_list(prop_ids, prop_ids_len,
|
|| prop_type_or_id_in_list(prop_ids, prop_ids_len,
|
||||||
prop.tp_id)))
|
prop.tp_id)))
|
||||||
{
|
{
|
||||||
dict_T *d = dict_alloc();
|
dict_T *d = dict_alloc();
|
||||||
|
@ -735,6 +735,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
67,
|
||||||
/**/
|
/**/
|
||||||
66,
|
66,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user