fix(column): corrupted screen with minwid sign item in 'statuscolumn'

This commit is contained in:
Luuk van Baal
2023-05-30 12:40:01 +02:00
parent b8a2220f5e
commit 2016ff6f37
2 changed files with 38 additions and 16 deletions

View File

@@ -1031,6 +1031,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
int evaldepth = 0; int evaldepth = 0;
int curitem = 0; int curitem = 0;
int foldsignitem = -1;
bool prevchar_isflag = true; bool prevchar_isflag = true;
bool prevchar_isitem = false; bool prevchar_isitem = false;
@@ -1655,6 +1656,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
if (width == 0) { if (width == 0) {
break; break;
} }
foldsignitem = curitem;
char *p = NULL; char *p = NULL;
if (fold) { if (fold) {
@@ -1664,34 +1666,24 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
p[n] = NUL; p[n] = NUL;
} }
*buf_tmp = NUL; size_t buflen = 0;
varnumber_T virtnum = get_vim_var_nr(VV_VIRTNUM); varnumber_T virtnum = get_vim_var_nr(VV_VIRTNUM);
for (int i = 0; i <= width; i++) { for (int i = 0; i < width; i++) {
if (i == width) { if (!fold) {
if (*buf_tmp == NUL) {
break;
}
stl_items[curitem].minwid = 0;
} else if (!fold) {
SignTextAttrs *sattr = virtnum ? NULL : sign_get_attr(i, stcp->sattrs, wp->w_scwidth); SignTextAttrs *sattr = virtnum ? NULL : sign_get_attr(i, stcp->sattrs, wp->w_scwidth);
p = sattr && sattr->text ? sattr->text : " "; p = sattr && sattr->text ? sattr->text : " ";
stl_items[curitem].minwid = -(sattr ? stcp->sign_cul_id ? stcp->sign_cul_id stl_items[curitem].minwid = -(sattr ? stcp->sign_cul_id ? stcp->sign_cul_id
: sattr->hl_id : (stcp->use_cul ? HLF_CLS : HLF_SC) + 1); : sattr->hl_id : (stcp->use_cul ? HLF_CLS : HLF_SC) + 1);
} }
size_t buflen = strlen(buf_tmp);
stl_items[curitem].type = Highlight; stl_items[curitem].type = Highlight;
stl_items[curitem].start = out_p + buflen; stl_items[curitem].start = out_p + buflen;
xstrlcpy(buf_tmp + buflen, p, TMPLEN - buflen);
buflen += strlen(p);
curitem++; curitem++;
if (i == width) { }
str = buf_tmp; str = buf_tmp;
break; break;
} }
int rc = snprintf(buf_tmp + buflen, sizeof(buf_tmp) - buflen, "%s", p);
(void)rc; // Avoid unused warning on release build
assert(rc > 0);
}
break;
}
case STL_FILETYPE: case STL_FILETYPE:
// Copy the filetype if it is not null and the formatted string will fit // Copy the filetype if it is not null and the formatted string will fit
@@ -1832,6 +1824,13 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
} }
} }
minwid = 0; minwid = 0;
// For a 'statuscolumn' sign or fold item, shift the added items
if (foldsignitem >= 0) {
ptrdiff_t offset = out_p - stl_items[foldsignitem].start;
for (int i = foldsignitem; i < curitem; i++) {
stl_items[i].start += offset;
}
}
} else { } else {
// Note: The negative value denotes a left aligned item. // Note: The negative value denotes a left aligned item.
// Here we switch the minimum width back to a positive value. // Here we switch the minimum width back to a positive value.
@@ -1851,6 +1850,14 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
} }
// } // }
// For a 'statuscolumn' sign or fold item, add an item to reset the highlight group
if (foldsignitem >= 0) {
foldsignitem = -1;
stl_items[curitem].type = Highlight;
stl_items[curitem].start = out_p;
stl_items[curitem].minwid = 0;
}
// For left-aligned items, fill any remaining space with the fillchar // For left-aligned items, fill any remaining space with the fillchar
for (; l < minwid && out_p < out_end_p; l++) { for (; l < minwid && out_p < out_end_p; l++) {
MB_CHAR2BYTES(fillchar, out_p); MB_CHAR2BYTES(fillchar, out_p);

View File

@@ -424,6 +424,21 @@ describe('statuscolumn', function()
]]) ]])
end) end)
it('does not corrupt the screen with minwid sign item', function()
screen:try_resize(screen._width, 3)
screen:set_default_attr_ids({
[0] = {foreground = Screen.colors.Brown},
[1] = {foreground = Screen.colors.Blue4, background = Screen.colors.Gray},
})
command([[set stc=%6s\ %l]])
exec_lua('vim.api.nvim_buf_set_extmark(0, ns, 7, 0, {sign_text = "𒀀"})')
screen:expect([[
{0: 𒀀 8}^aaaaa |
{0: }{1: }{0: 9}aaaaa |
|
]])
end)
for _, model in ipairs(mousemodels) do for _, model in ipairs(mousemodels) do
it("works with 'statuscolumn' clicks with mousemodel=" .. model, function() it("works with 'statuscolumn' clicks with mousemodel=" .. model, function()
command('set mousemodel=' .. model) command('set mousemodel=' .. model)