mirror of
https://github.com/vim/vim.git
synced 2025-08-26 20:03:41 -04:00
patch 9.0.0247: cannot add padding to virtual text without highlight
Problem: Cannot add padding to virtual text without highlight. Solution: Add the "text_padding_left" argument. (issue #10906)
This commit is contained in:
parent
adce965162
commit
f396ce83ee
@ -126,6 +126,7 @@ prop_add({lnum}, {col}, {props})
|
|||||||
If {col} is invalid an error is given. *E964*
|
If {col} is invalid an error is given. *E964*
|
||||||
|
|
||||||
{props} is a dictionary with these fields:
|
{props} is a dictionary with these fields:
|
||||||
|
type name of the text property type
|
||||||
length length of text in bytes, can only be used
|
length length of text in bytes, can only be used
|
||||||
for a property that does not continue in
|
for a property that does not continue in
|
||||||
another line; can be zero
|
another line; can be zero
|
||||||
@ -142,9 +143,10 @@ prop_add({lnum}, {col}, {props})
|
|||||||
automatically to a negative number; otherwise
|
automatically to a negative number; otherwise
|
||||||
zero is used
|
zero is used
|
||||||
text text to be displayed before {col}, or after the
|
text text to be displayed before {col}, or after the
|
||||||
line if {col} is zero
|
line if {col} is zero; prepend and/or append
|
||||||
|
spaces for padding with highlighting
|
||||||
*E1294*
|
*E1294*
|
||||||
text_align when "text" is present and {col} is zero
|
text_align when "text" is present and {col} is zero;
|
||||||
specifies where to display the text:
|
specifies where to display the text:
|
||||||
after after the end of the line
|
after after the end of the line
|
||||||
right right aligned in the window (unless
|
right right aligned in the window (unless
|
||||||
@ -152,14 +154,20 @@ prop_add({lnum}, {col}, {props})
|
|||||||
line)
|
line)
|
||||||
below in the next screen line
|
below in the next screen line
|
||||||
When omitted "after" is used. Only one
|
When omitted "after" is used. Only one
|
||||||
"right" property can fit in earch line.
|
"right" property can fit in each line, if
|
||||||
|
there are two ore more these will go in a
|
||||||
|
separate line (still right aligned).
|
||||||
|
text_padding_left *E1296*
|
||||||
|
used when "text" is present and {col} is zero;
|
||||||
|
padding between the end of the text line
|
||||||
|
(leftmost column for "below") and the virtual
|
||||||
|
text, not highlighted
|
||||||
text_wrap when "text" is present and {col} is zero,
|
text_wrap when "text" is present and {col} is zero,
|
||||||
specifies what happens if the text doesn't
|
specifies what happens if the text doesn't
|
||||||
fit:
|
fit:
|
||||||
wrap wrap the text to the next line
|
wrap wrap the text to the next line
|
||||||
truncate truncate the text to make it fit
|
truncate truncate the text to make it fit
|
||||||
When omitted "truncate" is used.
|
When omitted "truncate" is used.
|
||||||
type name of the text property type
|
|
||||||
All fields except "type" are optional.
|
All fields except "type" are optional.
|
||||||
|
|
||||||
It is an error when both "length" and "end_lnum" or "end_col"
|
It is an error when both "length" and "end_lnum" or "end_col"
|
||||||
|
@ -957,26 +957,26 @@ init_chartabsize_arg(
|
|||||||
#ifdef FEAT_PROP_POPUP
|
#ifdef FEAT_PROP_POPUP
|
||||||
if (lnum > 0)
|
if (lnum > 0)
|
||||||
{
|
{
|
||||||
char_u *prop_start;
|
char_u *prop_start;
|
||||||
|
int count;
|
||||||
|
|
||||||
cts->cts_text_prop_count = get_text_props(wp->w_buffer, lnum,
|
count = get_text_props(wp->w_buffer, lnum, &prop_start, FALSE);
|
||||||
&prop_start, FALSE);
|
cts->cts_text_prop_count = count;
|
||||||
if (cts->cts_text_prop_count > 0)
|
if (count > 0)
|
||||||
{
|
{
|
||||||
// Make a copy of the properties, so that they are properly
|
// Make a copy of the properties, so that they are properly
|
||||||
// aligned.
|
// aligned. Make it twice as long for the sorting below.
|
||||||
cts->cts_text_props = ALLOC_MULT(textprop_T,
|
cts->cts_text_props = ALLOC_MULT(textprop_T, count * 2);
|
||||||
cts->cts_text_prop_count);
|
|
||||||
if (cts->cts_text_props == NULL)
|
if (cts->cts_text_props == NULL)
|
||||||
cts->cts_text_prop_count = 0;
|
cts->cts_text_prop_count = 0;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
mch_memmove(cts->cts_text_props, prop_start,
|
mch_memmove(cts->cts_text_props + count, prop_start,
|
||||||
cts->cts_text_prop_count * sizeof(textprop_T));
|
count * sizeof(textprop_T));
|
||||||
for (i = 0; i < cts->cts_text_prop_count; ++i)
|
for (i = 0; i < count; ++i)
|
||||||
if (cts->cts_text_props[i].tp_id < 0)
|
if (cts->cts_text_props[i + count].tp_id < 0)
|
||||||
{
|
{
|
||||||
cts->cts_has_prop_with_text = TRUE;
|
cts->cts_has_prop_with_text = TRUE;
|
||||||
break;
|
break;
|
||||||
@ -987,6 +987,27 @@ init_chartabsize_arg(
|
|||||||
VIM_CLEAR(cts->cts_text_props);
|
VIM_CLEAR(cts->cts_text_props);
|
||||||
cts->cts_text_prop_count = 0;
|
cts->cts_text_prop_count = 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int *text_prop_idxs;
|
||||||
|
|
||||||
|
// Need to sort the array to get any truncation right.
|
||||||
|
// Do the sorting in the second part of the array, then
|
||||||
|
// move the sorted props to the first part of the array.
|
||||||
|
text_prop_idxs = ALLOC_MULT(int, count);
|
||||||
|
if (text_prop_idxs != NULL)
|
||||||
|
{
|
||||||
|
for (i = 0; i < count; ++i)
|
||||||
|
text_prop_idxs[i] = i + count;
|
||||||
|
sort_text_props(curbuf, cts->cts_text_props,
|
||||||
|
text_prop_idxs, count);
|
||||||
|
// Here we want the reverse order.
|
||||||
|
for (i = 0; i < count; ++i)
|
||||||
|
cts->cts_text_props[count - i - 1] =
|
||||||
|
cts->cts_text_props[text_prop_idxs[i]];
|
||||||
|
vim_free(text_prop_idxs);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1159,6 +1180,11 @@ win_lbr_chartabsize(
|
|||||||
int col = (int)(s - line);
|
int col = (int)(s - line);
|
||||||
garray_T *gap = &wp->w_buffer->b_textprop_text;
|
garray_T *gap = &wp->w_buffer->b_textprop_text;
|
||||||
|
|
||||||
|
// The "$" for 'list' mode will go between the EOL and
|
||||||
|
// the text prop, account for that.
|
||||||
|
if (wp->w_p_list && wp->w_lcs_chars.eol != NUL)
|
||||||
|
++vcol;
|
||||||
|
|
||||||
for (i = 0; i < cts->cts_text_prop_count; ++i)
|
for (i = 0; i < cts->cts_text_prop_count; ++i)
|
||||||
{
|
{
|
||||||
textprop_T *tp = cts->cts_text_props + i;
|
textprop_T *tp = cts->cts_text_props + i;
|
||||||
@ -1176,46 +1202,21 @@ win_lbr_chartabsize(
|
|||||||
|
|
||||||
if (p != NULL)
|
if (p != NULL)
|
||||||
{
|
{
|
||||||
int cells = vim_strsize(p);
|
int cells;
|
||||||
|
|
||||||
if (tp->tp_col == MAXCOL)
|
if (tp->tp_col == MAXCOL)
|
||||||
{
|
{
|
||||||
int below = (tp->tp_flags & TP_FLAG_ALIGN_BELOW);
|
int n_extra = (int)STRLEN(p);
|
||||||
int right = (tp->tp_flags & TP_FLAG_ALIGN_RIGHT);
|
|
||||||
int wrap = (tp->tp_flags & TP_FLAG_WRAP);
|
|
||||||
int len = (int)STRLEN(p);
|
|
||||||
int n_used = len;
|
|
||||||
|
|
||||||
// The "$" for 'list' mode will go between the EOL and
|
cells = text_prop_position(wp, tp,
|
||||||
// the text prop, account for that.
|
(vcol + size) % wp->w_width,
|
||||||
if (wp->w_p_list && wp->w_lcs_chars.eol != NUL)
|
&n_extra, &p, NULL, NULL);
|
||||||
++vcol;
|
|
||||||
|
|
||||||
// Keep in sync with where textprop_size_after_trunc()
|
|
||||||
// is called in win_line().
|
|
||||||
if (!wrap)
|
|
||||||
{
|
|
||||||
added = wp->w_width - (vcol + size) % wp->w_width;
|
|
||||||
cells = textprop_size_after_trunc(wp,
|
|
||||||
below, added, p, &n_used);
|
|
||||||
}
|
|
||||||
if (below)
|
|
||||||
cells += wp->w_width - (vcol + size) % wp->w_width;
|
|
||||||
else if (right)
|
|
||||||
{
|
|
||||||
len = wp->w_width - vcol % wp->w_width;
|
|
||||||
if (len > cells + size)
|
|
||||||
// add the padding for right-alignment
|
|
||||||
cells = len - size;
|
|
||||||
else if (len == 0)
|
|
||||||
// padding to right-align in the next line
|
|
||||||
cells += cells > wp->w_width ? 0
|
|
||||||
:wp->w_width - cells;
|
|
||||||
}
|
|
||||||
#ifdef FEAT_LINEBREAK
|
#ifdef FEAT_LINEBREAK
|
||||||
no_sbr = TRUE; // don't use 'showbreak' now
|
no_sbr = TRUE; // don't use 'showbreak' now
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
cells = vim_strsize(p);
|
||||||
cts->cts_cur_text_width += cells;
|
cts->cts_cur_text_width += cells;
|
||||||
cts->cts_start_incl = tp->tp_flags & TP_FLAG_START_INCL;
|
cts->cts_start_incl = tp->tp_flags & TP_FLAG_START_INCL;
|
||||||
size += cells;
|
size += cells;
|
||||||
@ -1231,6 +1232,8 @@ win_lbr_chartabsize(
|
|||||||
if (tp->tp_col != MAXCOL && tp->tp_col - 1 > col)
|
if (tp->tp_col != MAXCOL && tp->tp_col - 1 > col)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (wp->w_p_list && wp->w_lcs_chars.eol != NUL)
|
||||||
|
--vcol;
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
276
src/drawline.c
276
src/drawline.c
@ -277,74 +277,123 @@ get_sign_display_info(
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef FEAT_PROP_POPUP
|
#if defined(FEAT_PROP_POPUP) || defined(PROTO)
|
||||||
static textprop_T *current_text_props = NULL;
|
|
||||||
static buf_T *current_buf = NULL;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function passed to qsort() to sort text properties.
|
* Take care of padding, right-align and truncation of virtual text after a
|
||||||
* Return 1 if "s1" has priority over "s2", -1 if the other way around, zero if
|
* line.
|
||||||
* both have the same priority.
|
* if "n_attr" is not NULL then "n_extra" and "p_extra" are adjusted for any
|
||||||
|
* padding, right-align and truncation. Otherwise only the size is computed.
|
||||||
|
* When "n_attr" is NULL returns the number of screen cells used.
|
||||||
|
* Otherwise returns TRUE when drawing continues on the next line.
|
||||||
*/
|
*/
|
||||||
static int
|
int
|
||||||
text_prop_compare(const void *s1, const void *s2)
|
text_prop_position(
|
||||||
|
win_T *wp,
|
||||||
|
textprop_T *tp,
|
||||||
|
int vcol, // current screen column
|
||||||
|
int *n_extra, // nr of bytes for virtual text
|
||||||
|
char_u **p_extra, // virtual text
|
||||||
|
int *n_attr, // attribute cells, NULL if not used
|
||||||
|
int *n_attr_skip) // cells to skip attr, NULL if not used
|
||||||
{
|
{
|
||||||
int idx1, idx2;
|
int right = (tp->tp_flags & TP_FLAG_ALIGN_RIGHT);
|
||||||
textprop_T *tp1, *tp2;
|
int below = (tp->tp_flags & TP_FLAG_ALIGN_BELOW);
|
||||||
proptype_T *pt1, *pt2;
|
int wrap = (tp->tp_flags & TP_FLAG_WRAP);
|
||||||
colnr_T col1, col2;
|
int padding = tp->tp_col == MAXCOL && tp->tp_len > 1
|
||||||
|
? tp->tp_len - 1 : 0;
|
||||||
|
int col_with_padding = vcol + (below ? 0 : padding);
|
||||||
|
int room = wp->w_width - col_with_padding;
|
||||||
|
int added = room;
|
||||||
|
int n_used = *n_extra;
|
||||||
|
char_u *l = NULL;
|
||||||
|
int strsize = vim_strsize(*p_extra);
|
||||||
|
int cells = wrap ? strsize
|
||||||
|
: textprop_size_after_trunc(wp, below, added, *p_extra, &n_used);
|
||||||
|
|
||||||
idx1 = *(int *)s1;
|
if (wrap || right || below || padding > 0 || n_used < *n_extra)
|
||||||
idx2 = *(int *)s2;
|
|
||||||
tp1 = ¤t_text_props[idx1];
|
|
||||||
tp2 = ¤t_text_props[idx2];
|
|
||||||
col1 = tp1->tp_col;
|
|
||||||
col2 = tp2->tp_col;
|
|
||||||
if (col1 == MAXCOL && col2 == MAXCOL)
|
|
||||||
{
|
{
|
||||||
int flags1 = 0;
|
// Right-align: fill with spaces
|
||||||
int flags2 = 0;
|
if (right)
|
||||||
|
added -= cells;
|
||||||
|
if (added < 0
|
||||||
|
|| !(right || below)
|
||||||
|
|| (below
|
||||||
|
? (col_with_padding == 0 || !wp->w_p_wrap)
|
||||||
|
: (n_used < *n_extra)))
|
||||||
|
{
|
||||||
|
if (right && (wrap || room < PROP_TEXT_MIN_CELLS))
|
||||||
|
{
|
||||||
|
// right-align on next line instead of wrapping if possible
|
||||||
|
added = wp->w_width - strsize + room;
|
||||||
|
if (added < 0)
|
||||||
|
added = 0;
|
||||||
|
else
|
||||||
|
n_used = *n_extra;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
added = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// both props add text are after the line, order on 0: after (default),
|
// With 'nowrap' add one to show the "extends" character if needed (it
|
||||||
// 1: right, 2: below (comes last)
|
// doesn't show if the text just fits).
|
||||||
if (tp1->tp_flags & TP_FLAG_ALIGN_RIGHT)
|
if (!wp->w_p_wrap
|
||||||
flags1 = 1;
|
&& n_used < *n_extra
|
||||||
if (tp1->tp_flags & TP_FLAG_ALIGN_BELOW)
|
&& wp->w_lcs_chars.ext != NUL
|
||||||
flags1 = 2;
|
&& wp->w_p_list)
|
||||||
if (tp2->tp_flags & TP_FLAG_ALIGN_RIGHT)
|
++n_used;
|
||||||
flags2 = 1;
|
|
||||||
if (tp2->tp_flags & TP_FLAG_ALIGN_BELOW)
|
// add 1 for NUL, 2 for when '…' is used
|
||||||
flags2 = 2;
|
if (n_attr != NULL)
|
||||||
if (flags1 != flags2)
|
l = alloc(n_used + added + padding + 3);
|
||||||
return flags1 < flags2 ? 1 : -1;
|
if (n_attr == NULL || l != NULL)
|
||||||
|
{
|
||||||
|
int off = 0;
|
||||||
|
|
||||||
|
if (n_attr != NULL)
|
||||||
|
{
|
||||||
|
vim_memset(l, ' ', added);
|
||||||
|
off += added;
|
||||||
|
if (padding > 0)
|
||||||
|
{
|
||||||
|
vim_memset(l + off, ' ', padding);
|
||||||
|
off += padding;
|
||||||
|
}
|
||||||
|
vim_strncpy(l + off, *p_extra, n_used);
|
||||||
|
off += n_used;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
off = added + padding + n_used;
|
||||||
|
cells += added + padding;
|
||||||
|
}
|
||||||
|
if (n_attr != NULL)
|
||||||
|
{
|
||||||
|
if (n_used < *n_extra && wp->w_p_wrap)
|
||||||
|
{
|
||||||
|
char_u *lp = l + off - 1;
|
||||||
|
|
||||||
|
if (has_mbyte)
|
||||||
|
{
|
||||||
|
// change last character to '…'
|
||||||
|
lp -= (*mb_head_off)(l, lp);
|
||||||
|
STRCPY(lp, "…");
|
||||||
|
n_used = lp - l + 3 - padding;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
// change last character to '>'
|
||||||
|
*lp = '>';
|
||||||
|
}
|
||||||
|
*p_extra = l;
|
||||||
|
*n_extra = n_used + added + padding;
|
||||||
|
*n_attr = mb_charlen(*p_extra);
|
||||||
|
*n_attr_skip = added + padding;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// property that inserts text has priority over one that doesn't
|
if (n_attr == NULL)
|
||||||
if ((tp1->tp_id < 0) != (tp2->tp_id < 0))
|
return cells;
|
||||||
return tp1->tp_id < 0 ? 1 : -1;
|
return (below && col_with_padding > win_col_off(wp) && !wp->w_p_wrap);
|
||||||
|
|
||||||
// check highest priority, defined by the type
|
|
||||||
pt1 = text_prop_type_by_id(current_buf, tp1->tp_type);
|
|
||||||
pt2 = text_prop_type_by_id(current_buf, tp2->tp_type);
|
|
||||||
if (pt1 != pt2)
|
|
||||||
{
|
|
||||||
if (pt1 == NULL)
|
|
||||||
return -1;
|
|
||||||
if (pt2 == NULL)
|
|
||||||
return 1;
|
|
||||||
if (pt1->pt_priority != pt2->pt_priority)
|
|
||||||
return pt1->pt_priority > pt2->pt_priority ? 1 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// same priority, one that starts first wins
|
|
||||||
if (col1 != col2)
|
|
||||||
return col1 < col2 ? 1 : -1;
|
|
||||||
|
|
||||||
// for a property with text the id can be used as tie breaker
|
|
||||||
if (tp1->tp_id < 0)
|
|
||||||
return tp1->tp_id > tp2->tp_id ? 1 : -1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1219,6 +1268,9 @@ win_line(
|
|||||||
|
|
||||||
// Allocate an array for the indexes.
|
// Allocate an array for the indexes.
|
||||||
text_prop_idxs = ALLOC_MULT(int, text_prop_count);
|
text_prop_idxs = ALLOC_MULT(int, text_prop_count);
|
||||||
|
if (text_prop_idxs == NULL)
|
||||||
|
VIM_CLEAR(text_props);
|
||||||
|
|
||||||
area_highlighting = TRUE;
|
area_highlighting = TRUE;
|
||||||
extra_check = TRUE;
|
extra_check = TRUE;
|
||||||
}
|
}
|
||||||
@ -1609,8 +1661,9 @@ win_line(
|
|||||||
{
|
{
|
||||||
int tpi = text_prop_idxs[pi];
|
int tpi = text_prop_idxs[pi];
|
||||||
|
|
||||||
if (bcol >= text_props[tpi].tp_col - 1
|
if (text_props[tpi].tp_col != MAXCOL
|
||||||
+ text_props[tpi].tp_len)
|
&& bcol >= text_props[tpi].tp_col - 1
|
||||||
|
+ text_props[tpi].tp_len)
|
||||||
{
|
{
|
||||||
if (pi + 1 < text_props_active)
|
if (pi + 1 < text_props_active)
|
||||||
mch_memmove(text_prop_idxs + pi,
|
mch_memmove(text_prop_idxs + pi,
|
||||||
@ -1674,10 +1727,8 @@ win_line(
|
|||||||
// 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.
|
||||||
text_prop_follows = FALSE;
|
text_prop_follows = FALSE;
|
||||||
current_text_props = text_props;
|
sort_text_props(wp->w_buffer, text_props,
|
||||||
current_buf = wp->w_buffer;
|
text_prop_idxs, text_props_active);
|
||||||
qsort((void *)text_prop_idxs, (size_t)text_props_active,
|
|
||||||
sizeof(int), text_prop_compare);
|
|
||||||
|
|
||||||
for (pi = 0; pi < text_props_active; ++pi)
|
for (pi = 0; pi < text_props_active; ++pi)
|
||||||
{
|
{
|
||||||
@ -1704,23 +1755,28 @@ win_line(
|
|||||||
&& -text_prop_id
|
&& -text_prop_id
|
||||||
<= wp->w_buffer->b_textprop_text.ga_len)
|
<= wp->w_buffer->b_textprop_text.ga_len)
|
||||||
{
|
{
|
||||||
char_u *p = ((char_u **)wp->w_buffer
|
textprop_T *tp = &text_props[used_tpi];
|
||||||
|
char_u *p = ((char_u **)wp->w_buffer
|
||||||
->b_textprop_text.ga_data)[
|
->b_textprop_text.ga_data)[
|
||||||
-text_prop_id - 1];
|
-text_prop_id - 1];
|
||||||
|
|
||||||
// reset the ID in the copy to avoid it being used
|
// reset the ID in the copy to avoid it being used
|
||||||
// again
|
// again
|
||||||
text_props[used_tpi].tp_id = -MAXCOL;
|
tp->tp_id = -MAXCOL;
|
||||||
|
|
||||||
if (p != NULL)
|
if (p != NULL)
|
||||||
{
|
{
|
||||||
int right = (text_props[used_tpi].tp_flags
|
int right = (tp->tp_flags
|
||||||
& TP_FLAG_ALIGN_RIGHT);
|
& TP_FLAG_ALIGN_RIGHT);
|
||||||
int below = (text_props[used_tpi].tp_flags
|
int below = (tp->tp_flags
|
||||||
& TP_FLAG_ALIGN_BELOW);
|
& TP_FLAG_ALIGN_BELOW);
|
||||||
int wrap = (text_props[used_tpi].tp_flags
|
int wrap = (tp->tp_flags & TP_FLAG_WRAP);
|
||||||
& TP_FLAG_WRAP);
|
int padding = tp->tp_col == MAXCOL
|
||||||
|
&& tp->tp_len > 1
|
||||||
|
? tp->tp_len - 1 : 0;
|
||||||
|
|
||||||
|
// Insert virtual text before the current
|
||||||
|
// character, or add after the end of the line.
|
||||||
wlv.p_extra = p;
|
wlv.p_extra = p;
|
||||||
wlv.c_extra = NUL;
|
wlv.c_extra = NUL;
|
||||||
wlv.c_final = NUL;
|
wlv.c_final = NUL;
|
||||||
@ -1746,72 +1802,30 @@ win_line(
|
|||||||
// Keep in sync with where
|
// Keep in sync with where
|
||||||
// textprop_size_after_trunc() is called in
|
// textprop_size_after_trunc() is called in
|
||||||
// win_lbr_chartabsize().
|
// win_lbr_chartabsize().
|
||||||
if ((right || below || !wrap) && wp->w_width > 2)
|
if ((right || below || !wrap || padding > 0)
|
||||||
|
&& wp->w_width > 2)
|
||||||
{
|
{
|
||||||
int added = wp->w_width - wlv.col;
|
char_u *prev_p_extra = wlv.p_extra;
|
||||||
int n_used = wlv.n_extra;
|
int start_line;
|
||||||
char_u *l;
|
|
||||||
int strsize = wrap
|
|
||||||
? vim_strsize(wlv.p_extra)
|
|
||||||
: textprop_size_after_trunc(wp,
|
|
||||||
below, added, wlv.p_extra, &n_used);
|
|
||||||
|
|
||||||
if (wrap || right || below
|
// Take care of padding, right-align and
|
||||||
|| n_used < wlv.n_extra)
|
// truncation.
|
||||||
|
// Shared with win_lbr_chartabsize(), must do
|
||||||
|
// exactly the same.
|
||||||
|
start_line = text_prop_position(wp, tp,
|
||||||
|
wlv.col,
|
||||||
|
&wlv.n_extra, &wlv.p_extra,
|
||||||
|
&n_attr, &n_attr_skip);
|
||||||
|
if (wlv.p_extra != prev_p_extra)
|
||||||
{
|
{
|
||||||
// Right-align: fill with spaces
|
// wlv.p_extra was allocated
|
||||||
if (right)
|
vim_free(p_extra_free2);
|
||||||
added -= strsize;
|
p_extra_free2 = wlv.p_extra;
|
||||||
if (added < 0
|
|
||||||
|| (below
|
|
||||||
? wlv.col == 0 || !wp->w_p_wrap
|
|
||||||
: n_used < wlv.n_extra))
|
|
||||||
added = 0;
|
|
||||||
|
|
||||||
// With 'nowrap' add one to show the
|
|
||||||
// "extends" character if needed (it
|
|
||||||
// doesn't show it the text just fits).
|
|
||||||
if (!wp->w_p_wrap
|
|
||||||
&& n_used < wlv.n_extra
|
|
||||||
&& wp->w_lcs_chars.ext != NUL
|
|
||||||
&& wp->w_p_list)
|
|
||||||
++n_used;
|
|
||||||
|
|
||||||
// add 1 for NUL, 2 for when '…' is used
|
|
||||||
l = alloc(n_used + added + 3);
|
|
||||||
if (l != NULL)
|
|
||||||
{
|
|
||||||
vim_memset(l, ' ', added);
|
|
||||||
vim_strncpy(l + added, wlv.p_extra,
|
|
||||||
n_used);
|
|
||||||
if (n_used < wlv.n_extra
|
|
||||||
&& wp->w_p_wrap)
|
|
||||||
{
|
|
||||||
char_u *lp = l + added + n_used - 1;
|
|
||||||
|
|
||||||
if (has_mbyte)
|
|
||||||
{
|
|
||||||
// change last character to '…'
|
|
||||||
lp -= (*mb_head_off)(l, lp);
|
|
||||||
STRCPY(lp, "…");
|
|
||||||
n_used = lp - l + 3;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
// change last character to '>'
|
|
||||||
*lp = '>';
|
|
||||||
}
|
|
||||||
vim_free(p_extra_free2);
|
|
||||||
wlv.p_extra = p_extra_free2 = l;
|
|
||||||
wlv.n_extra = n_used + added;
|
|
||||||
n_attr_skip = added;
|
|
||||||
n_attr = mb_charlen(wlv.p_extra);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// When 'wrap' is off then for "below" we need
|
// When 'wrap' is off then for "below" we need
|
||||||
// to start a new line explictly.
|
// to start a new line explictly.
|
||||||
if (below && wlv.col > win_col_off(wp)
|
if (start_line)
|
||||||
&& !wp->w_p_wrap)
|
|
||||||
{
|
{
|
||||||
draw_screen_line(wp, &wlv);
|
draw_screen_line(wp, &wlv);
|
||||||
|
|
||||||
|
@ -1218,6 +1218,8 @@ EXTERN char e_pattern_not_found_str[]
|
|||||||
INIT(= N_("E486: Pattern not found: %s"));
|
INIT(= N_("E486: Pattern not found: %s"));
|
||||||
EXTERN char e_argument_must_be_positive[]
|
EXTERN char e_argument_must_be_positive[]
|
||||||
INIT(= N_("E487: Argument must be positive"));
|
INIT(= N_("E487: Argument must be positive"));
|
||||||
|
EXTERN char e_argument_must_be_positive_str[]
|
||||||
|
INIT(= N_("E487: Argument must be positive: %s"));
|
||||||
EXTERN char e_trailing_characters[]
|
EXTERN char e_trailing_characters[]
|
||||||
INIT(= N_("E488: Trailing characters"));
|
INIT(= N_("E488: Trailing characters"));
|
||||||
EXTERN char e_trailing_characters_str[]
|
EXTERN char e_trailing_characters_str[]
|
||||||
@ -3319,4 +3321,6 @@ EXTERN char e_can_only_use_text_align_when_column_is_zero[]
|
|||||||
#ifdef FEAT_PROP_POPUP
|
#ifdef FEAT_PROP_POPUP
|
||||||
EXTERN char e_cannot_specify_both_type_and_types[]
|
EXTERN char e_cannot_specify_both_type_and_types[]
|
||||||
INIT(= N_("E1295: Cannot specify both 'type' and 'types'"));
|
INIT(= N_("E1295: Cannot specify both 'type' and 'types'"));
|
||||||
|
EXTERN char e_can_only_use_left_padding_when_column_is_zero[]
|
||||||
|
INIT(= N_("E1296: Can only use left padding when column is zero"));
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
/* drawline.c */
|
/* drawline.c */
|
||||||
|
int text_prop_position(win_T *wp, textprop_T *tp, int vcol, int *n_extra, char_u **p_extra, int *n_attr, int *n_attr_skip);
|
||||||
int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int nochange, int number_only);
|
int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int nochange, int number_only);
|
||||||
/* vim: set ft=c : */
|
/* vim: set ft=c : */
|
||||||
|
@ -6,6 +6,7 @@ int prop_add_common(linenr_T start_lnum, colnr_T start_col, dict_T *dict, buf_T
|
|||||||
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 prop_count_below(buf_T *buf, linenr_T lnum);
|
int prop_count_below(buf_T *buf, linenr_T lnum);
|
||||||
int count_props(linenr_T lnum, int only_starting, int last_line);
|
int count_props(linenr_T lnum, int only_starting, int last_line);
|
||||||
|
void sort_text_props(buf_T *buf, textprop_T *props, int *idxs, int count);
|
||||||
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);
|
||||||
void add_text_props(linenr_T lnum, textprop_T *text_props, int text_prop_count);
|
void add_text_props(linenr_T lnum, textprop_T *text_props, int text_prop_count);
|
||||||
proptype_T *text_prop_type_by_id(buf_T *buf, int id);
|
proptype_T *text_prop_type_by_id(buf_T *buf, int id);
|
||||||
|
@ -800,7 +800,8 @@ typedef struct memline
|
|||||||
typedef struct textprop_S
|
typedef struct textprop_S
|
||||||
{
|
{
|
||||||
colnr_T tp_col; // start column (one based, in bytes)
|
colnr_T tp_col; // start column (one based, in bytes)
|
||||||
colnr_T tp_len; // length in bytes
|
colnr_T tp_len; // length in bytes, when tp_id is negative used
|
||||||
|
// for left padding plus one
|
||||||
int tp_id; // identifier
|
int tp_id; // identifier
|
||||||
int tp_type; // property type
|
int tp_type; // property type
|
||||||
int tp_flags; // TP_FLAG_ values
|
int tp_flags; // TP_FLAG_ values
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
|s+0&#ffffff0|o|m|e| |m|o|r|e| |t|e|x|t|s|o|m|e| |t|e|x|t| |s|o|m|e| |t|e|x|t| |s|o|m|e| |t|e|x|t| |s|o|m|e| |t|e|x|t| +0&#ffd7ff255|n|o|t|h|i|n|g| |h|e|r|e|S+0#ffffff16#e000002|o|m|e| |e|r@1|o
|
|s+0&#ffffff0|o|m|e| |m|o|r|e| |t|e|x|t|s|o|m|e| |t|e|x|t| |s|o|m|e| |t|e|x|t| |s|o|m|e| |t|e|x|t| |s|o|m|e| |t|e|x|t| +0&#ffd7ff255|n|o|t|h|i|n|g| |h|e|r|e| +0&#ffffff0@8
|
||||||
|r| +0#0000000#ffffff0@60|A+0#ffffff16#e000002|n|o|t|h|e|r| |e|r@1|o|r
|
@65|S+0#ffffff16#e000002|o|m|e| |e|r@1|o|r
|
||||||
|
| +0#0000000#ffffff0@61|A+0#ffffff16#e000002|n|o|t|h|e|r| |e|r@1|o|r
|
||||||
|l+0#0000000#ffffff0|i|n|e| |t|w>o| @66
|
|l+0#0000000#ffffff0|i|n|e| |t|w>o| @66
|
||||||
|~+0#4040ff13&| @73
|
|~+0#4040ff13&| @73
|
||||||
|~| @73
|
|~| @73
|
||||||
|~| @73
|
|~| @73
|
||||||
|~| @73
|
|
||||||
| +0#0000000&@56|2|,|8| @10|A|l@1|
|
| +0#0000000&@56|2|,|8| @10|A|l@1|
|
||||||
|
8
src/testdir/dumps/Test_prop_text_with_padding_1.dump
Normal file
8
src/testdir/dumps/Test_prop_text_with_padding_1.dump
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
>S+0&#ffffff0|o|m|e| |t|e|x|t| |t|o| |a|d@1| |v|i|r|t|u|a|l| |t|e|x|t| |t|o|.| @2|a+0&#ffd7ff255|f|t|e|r| +0&#ffffff0@5|r+0&#ffd7ff255|i|g|h|t| |a|l|i|g|n|e|d
|
||||||
|
| +0&#ffffff0@3|b+0&#ffd7ff255|e|l|o|w| |t|h|e| |l|i|n|e| +0&#ffffff0@41
|
||||||
|
|s|e|c|o|n|d| |l|i|n|e| @48
|
||||||
|
|A|n|o|t|h|e|r| |l|i|n|e| |w|i|t|h| |s|o|m|e| |t|e|x|t| |t|o| |m|a|k|e| |t|h|e| |w|r|a|p|.| @5|r+0&#ffd7ff255|i|g|h|t|m|o|s|t
|
||||||
|
|~+0#4040ff13#ffffff0| @58
|
||||||
|
|~| @58
|
||||||
|
|~| @58
|
||||||
|
| +0#0000000&@41|1|,|1| @10|A|l@1|
|
8
src/testdir/dumps/Test_prop_text_with_padding_2.dump
Normal file
8
src/testdir/dumps/Test_prop_text_with_padding_2.dump
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
|x+0&#ffffff0@9|S|o|m|e| |t|e|x|t| |t|o| |a|d@1| |v|i|r|t|u|a|l| |t|e|x|t| |t|o|.| @2|a+0&#ffd7ff255|f|t|e|r| +0&#ffffff0@4|r+0&#ffd7ff255|i|g|…
|
||||||
|
| +0&#ffffff0@3|b+0&#ffd7ff255|e|l|o|w| |t|h|e| |l|i|n|e| +0&#ffffff0@41
|
||||||
|
|s|e|c|o|n|d| |l|i|n|e| @48
|
||||||
|
>x|A|n|o|t|h|e|r| |l|i|n|e| |w|i|t|h| |s|o|m|e| |t|e|x|t| |t|o| |m|a|k|e| |t|h|e| |w|r|a|p|.| @13
|
||||||
|
@51|r+0&#ffd7ff255|i|g|h|t|m|o|s|t
|
||||||
|
|~+0#4040ff13#ffffff0| @58
|
||||||
|
|~| @58
|
||||||
|
| +0#0000000&@41|3|,|1| @10|A|l@1|
|
8
src/testdir/dumps/Test_prop_text_with_padding_3.dump
Normal file
8
src/testdir/dumps/Test_prop_text_with_padding_3.dump
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
>x+0&#ffffff0@10|S|o|m|e| |t|e|x|t| |t|o| |a|d@1| |v|i|r|t|u|a|l| |t|e|x|t| |t|o|.| @2|a+0&#ffd7ff255|f|t|e|r| +0&#ffffff0@7
|
||||||
|
@47|r+0&#ffd7ff255|i|g|h|t| |a|l|i|g|n|e|d
|
||||||
|
| +0&#ffffff0@3|b+0&#ffd7ff255|e|l|o|w| |t|h|e| |l|i|n|e| +0&#ffffff0@41
|
||||||
|
|s|e|c|o|n|d| |l|i|n|e| @48
|
||||||
|
|x|A|n|o|t|h|e|r| |l|i|n|e| |w|i|t|h| |s|o|m|e| |t|e|x|t| |t|o| |m|a|k|e| |t|h|e| |w|r|a|p|.| @13
|
||||||
|
@51|r+0&#ffd7ff255|i|g|h|t|m|o|s|t
|
||||||
|
|~+0#4040ff13#ffffff0| @58
|
||||||
|
| +0#0000000&@41|1|,|1| @10|A|l@1|
|
@ -1,8 +1,8 @@
|
|||||||
|o+0&#ffffff0|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| |s|i|x| |s|e|v|e|n| +0&#ffff4012|O|N|E| |a|n|d| |T|W|O| |a|n|d| |T|H|R|E@1| |a|n|d|
|
|o+0&#ffffff0|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| |s|i|x| |s|e|v|e|n| +0&#ffff4012|O|N|E| |a|n|d| |T|W|O| |a|n|d| |T|H|R|E@1| |a|n|d|
|
||||||
|F|O|U|R| |a|n|d| |F|I|V|E| +0&#ffffff0@46
|
|F|O|U|R| |a|n|d| |F|I|V|E| +0&#ffffff0@46
|
||||||
|o|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| |s|i|x| |s|e|v|e|n| +0&#ffff4012|o|n|e| |A|N|D| |t|w|o| |A|N|D| |t|h|r|e@1| |A|N|D|
|
|
||||||
|f|o|u|r| |A|N|D| |f|i|v|e| +0&#ffffff0@46
|
|
||||||
|o|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| |s|i|x| |s|e|v|e|n| @26
|
|o|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| |s|i|x| |s|e|v|e|n| @26
|
||||||
|
@20| +0&#ffff4012|o|n|e| |A|N|D| |t|w|o| |A|N|D| |t|h|r|e@1| |A|N|D| |f|o|u|r| |A|N|D| |f|i|v|e
|
||||||
|
|o+0&#ffffff0|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| |s|i|x| |s|e|v|e|n| @26
|
||||||
| +0&#ffff4012|o|n|e| |A|N|D| |t|w|o| |A|N|D| |t|h|r|e@1| |A|N|D| |f|o|u|r| |A|N|D| |f|i|v|e| |l|e|t|s| |w|r|a|p| |a|f|t|e|r| |s|o|m
|
| +0&#ffff4012|o|n|e| |A|N|D| |t|w|o| |A|N|D| |t|h|r|e@1| |A|N|D| |f|o|u|r| |A|N|D| |f|i|v|e| |l|e|t|s| |w|r|a|p| |a|f|t|e|r| |s|o|m
|
||||||
|e| |m|o|r|e| |t|e|x|t| +0&#ffffff0@48
|
|e| |m|o|r|e| |t|e|x|t| +0&#ffffff0@48
|
||||||
|c|u|r|s|o|r| >h|e|r|e| @48
|
|c|u|r|s|o|r| >h|e|r|e| @48
|
||||||
|
@ -3041,4 +3041,54 @@ func Test_insert_text_list_mode()
|
|||||||
call delete('XscriptPropsListMode')
|
call delete('XscriptPropsListMode')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_insert_text_with_padding()
|
||||||
|
CheckRunVimInTerminal
|
||||||
|
|
||||||
|
let lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
setline(1, ['Some text to add virtual text to.',
|
||||||
|
'second line',
|
||||||
|
'Another line with some text to make the wrap.'])
|
||||||
|
prop_type_add('theprop', {highlight: 'DiffChange'})
|
||||||
|
prop_add(1, 0, {
|
||||||
|
type: 'theprop',
|
||||||
|
text: 'after',
|
||||||
|
text_align: 'after',
|
||||||
|
text_padding_left: 3,
|
||||||
|
})
|
||||||
|
prop_add(1, 0, {
|
||||||
|
type: 'theprop',
|
||||||
|
text: 'right aligned',
|
||||||
|
text_align: 'right',
|
||||||
|
text_padding_left: 5,
|
||||||
|
})
|
||||||
|
prop_add(1, 0, {
|
||||||
|
type: 'theprop',
|
||||||
|
text: 'below the line',
|
||||||
|
text_align: 'below',
|
||||||
|
text_padding_left: 4,
|
||||||
|
})
|
||||||
|
prop_add(3, 0, {
|
||||||
|
type: 'theprop',
|
||||||
|
text: 'rightmost',
|
||||||
|
text_align: 'right',
|
||||||
|
text_padding_left: 6,
|
||||||
|
text_wrap: 'wrap',
|
||||||
|
})
|
||||||
|
END
|
||||||
|
call writefile(lines, 'XscriptPropsPadded')
|
||||||
|
let buf = RunVimInTerminal('-S XscriptPropsPadded', #{rows: 8, cols: 60})
|
||||||
|
call VerifyScreenDump(buf, 'Test_prop_text_with_padding_1', {})
|
||||||
|
|
||||||
|
call term_sendkeys(buf, "ggixxxxxxxxxx\<Esc>")
|
||||||
|
call term_sendkeys(buf, "3Gix\<Esc>")
|
||||||
|
call VerifyScreenDump(buf, 'Test_prop_text_with_padding_2', {})
|
||||||
|
|
||||||
|
call term_sendkeys(buf, "ggix\<Esc>")
|
||||||
|
call VerifyScreenDump(buf, 'Test_prop_text_with_padding_3', {})
|
||||||
|
|
||||||
|
call StopVimInTerminal(buf)
|
||||||
|
call delete('XscriptPropsPadded')
|
||||||
|
endfunc
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
110
src/textprop.c
110
src/textprop.c
@ -171,6 +171,7 @@ prop_add_one(
|
|||||||
char_u *type_name,
|
char_u *type_name,
|
||||||
int id,
|
int id,
|
||||||
char_u *text_arg,
|
char_u *text_arg,
|
||||||
|
int text_padding_left,
|
||||||
int text_flags,
|
int text_flags,
|
||||||
linenr_T start_lnum,
|
linenr_T start_lnum,
|
||||||
linenr_T end_lnum,
|
linenr_T end_lnum,
|
||||||
@ -264,7 +265,10 @@ prop_add_one(
|
|||||||
{
|
{
|
||||||
length = 1; // text is placed on one character
|
length = 1; // text is placed on one character
|
||||||
if (col == 0)
|
if (col == 0)
|
||||||
|
{
|
||||||
col = MAXCOL; // after the line
|
col = MAXCOL; // after the line
|
||||||
|
length += text_padding_left;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate the new line with space for the new property.
|
// Allocate the new line with space for the new property.
|
||||||
@ -390,7 +394,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, NULL, 0, start_lnum, end_lnum,
|
if (prop_add_one(buf, type_name, id, NULL, 0, 0, start_lnum, end_lnum,
|
||||||
start_col, end_col) == FAIL)
|
start_col, end_col) == FAIL)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -428,6 +432,7 @@ prop_add_common(
|
|||||||
buf_T *buf = default_buf;
|
buf_T *buf = default_buf;
|
||||||
int id = 0;
|
int id = 0;
|
||||||
char_u *text = NULL;
|
char_u *text = NULL;
|
||||||
|
int text_padding_left = 0;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
|
||||||
if (dict == NULL || !dict_has_key(dict, "type"))
|
if (dict == NULL || !dict_has_key(dict, "type"))
|
||||||
@ -507,9 +512,20 @@ prop_add_common(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dict_has_key(dict, "text_padding_left"))
|
||||||
|
{
|
||||||
|
text_padding_left = dict_get_number(dict, "text_padding_left");
|
||||||
|
if (text_padding_left < 0)
|
||||||
|
{
|
||||||
|
semsg(_(e_argument_must_be_positive_str), "text_padding_left");
|
||||||
|
goto theend;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (dict_has_key(dict, "text_wrap"))
|
if (dict_has_key(dict, "text_wrap"))
|
||||||
{
|
{
|
||||||
char_u *p = dict_get_string(dict, "text_wrap", FALSE);
|
char_u *p = dict_get_string(dict, "text_wrap", FALSE);
|
||||||
|
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
goto theend;
|
goto theend;
|
||||||
if (STRCMP(p, "wrap") == 0)
|
if (STRCMP(p, "wrap") == 0)
|
||||||
@ -529,6 +545,11 @@ prop_add_common(
|
|||||||
semsg(_(e_invalid_column_number_nr), (long)start_col);
|
semsg(_(e_invalid_column_number_nr), (long)start_col);
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
|
if (start_col > 0 && text_padding_left > 0)
|
||||||
|
{
|
||||||
|
emsg(_(e_can_only_use_left_padding_when_column_is_zero));
|
||||||
|
goto theend;
|
||||||
|
}
|
||||||
|
|
||||||
if (dict_arg != NULL && get_bufnr_from_arg(dict_arg, &buf) == FAIL)
|
if (dict_arg != NULL && get_bufnr_from_arg(dict_arg, &buf) == FAIL)
|
||||||
goto theend;
|
goto theend;
|
||||||
@ -546,7 +567,7 @@ prop_add_common(
|
|||||||
// 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, text, flags,
|
prop_add_one(buf, type_name, id, text, text_padding_left, flags,
|
||||||
start_lnum, end_lnum, start_col, end_col);
|
start_lnum, end_lnum, start_col, end_col);
|
||||||
text = NULL;
|
text = NULL;
|
||||||
|
|
||||||
@ -655,6 +676,91 @@ count_props(linenr_T lnum, int only_starting, int last_line)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static textprop_T *text_prop_compare_props;
|
||||||
|
static buf_T *text_prop_compare_buf;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function passed to qsort() to sort text properties.
|
||||||
|
* Return 1 if "s1" has priority over "s2", -1 if the other way around, zero if
|
||||||
|
* both have the same priority.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
text_prop_compare(const void *s1, const void *s2)
|
||||||
|
{
|
||||||
|
int idx1, idx2;
|
||||||
|
textprop_T *tp1, *tp2;
|
||||||
|
proptype_T *pt1, *pt2;
|
||||||
|
colnr_T col1, col2;
|
||||||
|
|
||||||
|
idx1 = *(int *)s1;
|
||||||
|
idx2 = *(int *)s2;
|
||||||
|
tp1 = &text_prop_compare_props[idx1];
|
||||||
|
tp2 = &text_prop_compare_props[idx2];
|
||||||
|
col1 = tp1->tp_col;
|
||||||
|
col2 = tp2->tp_col;
|
||||||
|
if (col1 == MAXCOL && col2 == MAXCOL)
|
||||||
|
{
|
||||||
|
int flags1 = 0;
|
||||||
|
int flags2 = 0;
|
||||||
|
|
||||||
|
// both props add text are after the line, order on 0: after (default),
|
||||||
|
// 1: right, 2: below (comes last)
|
||||||
|
if (tp1->tp_flags & TP_FLAG_ALIGN_RIGHT)
|
||||||
|
flags1 = 1;
|
||||||
|
if (tp1->tp_flags & TP_FLAG_ALIGN_BELOW)
|
||||||
|
flags1 = 2;
|
||||||
|
if (tp2->tp_flags & TP_FLAG_ALIGN_RIGHT)
|
||||||
|
flags2 = 1;
|
||||||
|
if (tp2->tp_flags & TP_FLAG_ALIGN_BELOW)
|
||||||
|
flags2 = 2;
|
||||||
|
if (flags1 != flags2)
|
||||||
|
return flags1 < flags2 ? 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// property that inserts text has priority over one that doesn't
|
||||||
|
if ((tp1->tp_id < 0) != (tp2->tp_id < 0))
|
||||||
|
return tp1->tp_id < 0 ? 1 : -1;
|
||||||
|
|
||||||
|
// check highest priority, defined by the type
|
||||||
|
pt1 = text_prop_type_by_id(text_prop_compare_buf, tp1->tp_type);
|
||||||
|
pt2 = text_prop_type_by_id(text_prop_compare_buf, tp2->tp_type);
|
||||||
|
if (pt1 != pt2)
|
||||||
|
{
|
||||||
|
if (pt1 == NULL)
|
||||||
|
return -1;
|
||||||
|
if (pt2 == NULL)
|
||||||
|
return 1;
|
||||||
|
if (pt1->pt_priority != pt2->pt_priority)
|
||||||
|
return pt1->pt_priority > pt2->pt_priority ? 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// same priority, one that starts first wins
|
||||||
|
if (col1 != col2)
|
||||||
|
return col1 < col2 ? 1 : -1;
|
||||||
|
|
||||||
|
// for a property with text the id can be used as tie breaker
|
||||||
|
if (tp1->tp_id < 0)
|
||||||
|
return tp1->tp_id > tp2->tp_id ? 1 : -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sort "count" text properties using an array if indexes "idxs" into the list
|
||||||
|
* of text props "props" for buffer "buf".
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
sort_text_props(
|
||||||
|
buf_T *buf,
|
||||||
|
textprop_T *props,
|
||||||
|
int *idxs,
|
||||||
|
int count)
|
||||||
|
{
|
||||||
|
text_prop_compare_buf = buf;
|
||||||
|
text_prop_compare_props = props;
|
||||||
|
qsort((void *)idxs, (size_t)count, sizeof(int), text_prop_compare);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find text property "type_id" in the visible lines of window "wp".
|
* Find text property "type_id" in the visible lines of window "wp".
|
||||||
* Match "id" when it is > 0.
|
* Match "id" when it is > 0.
|
||||||
|
@ -731,6 +731,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 */
|
||||||
|
/**/
|
||||||
|
247,
|
||||||
/**/
|
/**/
|
||||||
246,
|
246,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user