mirror of
https://github.com/neovim/neovim.git
synced 2024-12-19 02:34:59 -07:00
Merge pull request #27481 from bfredl/meta_revise
fix(decorations): crash with revised mark with changed decoration flags
This commit is contained in:
commit
b12d193b4a
@ -74,11 +74,15 @@ void extmark_set(buf_T *buf, uint32_t ns_id, uint32_t *idp, int row, colnr_T col
|
|||||||
if (old_mark.pos.row == row && old_mark.pos.col == col) {
|
if (old_mark.pos.row == row && old_mark.pos.col == col) {
|
||||||
// not paired: we can revise in place
|
// not paired: we can revise in place
|
||||||
if (!invalid && mt_decor_any(old_mark)) {
|
if (!invalid && mt_decor_any(old_mark)) {
|
||||||
|
// TODO(bfredl): conflict of concerns: buf_decor_remove() must process
|
||||||
|
// the buffer as if MT_FLAG_DECOR_SIGNTEXT is already removed, however
|
||||||
|
// marktree must precisely adjust the set of flags from the old set to the new
|
||||||
|
uint16_t save_flags = mt_itr_rawkey(itr).flags;
|
||||||
mt_itr_rawkey(itr).flags &= (uint16_t) ~MT_FLAG_DECOR_SIGNTEXT;
|
mt_itr_rawkey(itr).flags &= (uint16_t) ~MT_FLAG_DECOR_SIGNTEXT;
|
||||||
buf_decor_remove(buf, row, row, col, mt_decor(old_mark), true);
|
buf_decor_remove(buf, row, row, col, mt_decor(old_mark), true);
|
||||||
|
mt_itr_rawkey(itr).flags = save_flags;
|
||||||
}
|
}
|
||||||
mt_itr_rawkey(itr).flags &= (uint16_t) ~MT_FLAG_EXTERNAL_MASK;
|
marktree_revise_flags(buf->b_marktree, itr, flags);
|
||||||
mt_itr_rawkey(itr).flags |= flags;
|
|
||||||
mt_itr_rawkey(itr).decor_data = decor.data;
|
mt_itr_rawkey(itr).decor_data = decor.data;
|
||||||
goto revised;
|
goto revised;
|
||||||
}
|
}
|
||||||
|
@ -774,6 +774,35 @@ uint64_t marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
|
|||||||
return other;
|
return other;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void marktree_revise_flags(MarkTree *b, MarkTreeIter *itr, uint16_t new_flags)
|
||||||
|
{
|
||||||
|
uint32_t meta_old[4];
|
||||||
|
meta_describe_key(meta_old, rawkey(itr));
|
||||||
|
rawkey(itr).flags &= (uint16_t) ~MT_FLAG_EXTERNAL_MASK;
|
||||||
|
rawkey(itr).flags |= new_flags;
|
||||||
|
|
||||||
|
uint32_t meta_new[4];
|
||||||
|
meta_describe_key(meta_new, rawkey(itr));
|
||||||
|
|
||||||
|
if (!memcmp(meta_old, meta_new, sizeof(meta_old))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MTNode *lnode = itr->x;
|
||||||
|
while (lnode->parent) {
|
||||||
|
uint32_t *meta_p = lnode->parent->meta[lnode->p_idx];
|
||||||
|
for (int m = 0; m < kMTMetaCount; m++) {
|
||||||
|
meta_p[m] += meta_new[m] - meta_old[m];
|
||||||
|
}
|
||||||
|
|
||||||
|
lnode = lnode->parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int m = 0; m < kMTMetaCount; m++) {
|
||||||
|
b->meta_root[m] += meta_new[m] - meta_old[m];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// similar to intersect_common but modify x and y in place to retain
|
/// similar to intersect_common but modify x and y in place to retain
|
||||||
/// only the items which are NOT in common
|
/// only the items which are NOT in common
|
||||||
static void intersect_merge(Intersection *restrict m, Intersection *restrict x,
|
static void intersect_merge(Intersection *restrict m, Intersection *restrict x,
|
||||||
|
@ -2371,6 +2371,36 @@ describe('extmark decorations', function()
|
|||||||
|
|
|
|
||||||
]]}
|
]]}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('can replace marks in place with different decorations #27211', function()
|
||||||
|
local mark = api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_lines = {{{"foo", "ErrorMsg"}}}, })
|
||||||
|
screen:expect{grid=[[
|
||||||
|
^ |
|
||||||
|
{4:foo} |
|
||||||
|
{1:~ }|*12
|
||||||
|
|
|
||||||
|
]]}
|
||||||
|
|
||||||
|
api.nvim_buf_set_extmark(0, ns, 0, 0, {
|
||||||
|
id = mark,
|
||||||
|
virt_text = { { "testing", "NonText" } },
|
||||||
|
virt_text_pos = "inline",
|
||||||
|
})
|
||||||
|
screen:expect{grid=[[
|
||||||
|
{1:^testing} |
|
||||||
|
{1:~ }|*13
|
||||||
|
|
|
||||||
|
]]}
|
||||||
|
|
||||||
|
api.nvim_buf_del_extmark(0, ns, mark)
|
||||||
|
screen:expect{grid=[[
|
||||||
|
^ |
|
||||||
|
{1:~ }|*13
|
||||||
|
|
|
||||||
|
]]}
|
||||||
|
|
||||||
|
helpers.assert_alive()
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('decorations: inline virtual text', function()
|
describe('decorations: inline virtual text', function()
|
||||||
|
Loading…
Reference in New Issue
Block a user