forked from aniani/vim
patch 8.2.0324: text property not updated correctly when inserting/deleting
Problem: Text property not updated correctly when inserting/deleting. Solution: Use the right column when deleting. Make zero-width text properties respect start_incl and end_incl. (Axel Forsman, closes #5696, closes #5679)
This commit is contained in:
@@ -1301,7 +1301,7 @@ del_bytes(
|
||||
#endif
|
||||
|
||||
// mark the buffer as changed and prepare for displaying
|
||||
inserted_bytes(lnum, curwin->w_cursor.col, -count);
|
||||
inserted_bytes(lnum, col, -count);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
@@ -326,3 +326,16 @@ func Test_listener_cleared_newbuf()
|
||||
bwipe!
|
||||
delfunc Listener
|
||||
endfunc
|
||||
|
||||
func Test_col_after_deletion_moved_cur()
|
||||
func Listener(bufnr, start, end, added, changes)
|
||||
call assert_equal([#{lnum: 1, end: 2, added: 0, col: 2}], a:changes)
|
||||
endfunc
|
||||
new
|
||||
call setline(1, ['foo'])
|
||||
let lid = listener_add('Listener')
|
||||
call feedkeys("lD", 'xt')
|
||||
call listener_flush()
|
||||
bwipe!
|
||||
delfunc Listener
|
||||
endfunc
|
||||
|
@@ -6,8 +6,6 @@ CheckFeature textprop
|
||||
|
||||
source screendump.vim
|
||||
|
||||
" test length zero
|
||||
|
||||
func Test_proptype_global()
|
||||
call prop_type_add('comment', {'highlight': 'Directory', 'priority': 123, 'start_incl': 1, 'end_incl': 1})
|
||||
let proptypes = prop_type_list()
|
||||
@@ -233,13 +231,20 @@ func Test_prop_add()
|
||||
|
||||
" Prop without length or end column is zero length
|
||||
call prop_clear(1)
|
||||
call prop_add(1, 5, {'type': 'two'})
|
||||
let expected = [{'col': 5, 'length': 0, 'type': 'two', 'id': 0, 'start': 1, 'end': 1}]
|
||||
call prop_type_add('included', {'start_incl': 1, 'end_incl': 1})
|
||||
call prop_add(1, 5, #{type: 'included'})
|
||||
let expected = [#{col: 5, length: 0, type: 'included', id: 0, start: 1, end: 1}]
|
||||
call assert_equal(expected, prop_list(1))
|
||||
|
||||
" Inserting text makes the prop bigger.
|
||||
exe "normal 5|ixx\<Esc>"
|
||||
let expected = [#{col: 5, length: 2, type: 'included', id: 0, start: 1, end: 1}]
|
||||
call assert_equal(expected, prop_list(1))
|
||||
|
||||
call assert_fails("call prop_add(1, 5, {'type': 'two', 'bufnr': 234343})", 'E158:')
|
||||
|
||||
call DeletePropTypes()
|
||||
call prop_type_delete('included')
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
|
@@ -1232,7 +1232,6 @@ adjust_prop_columns(
|
||||
{
|
||||
int proplen;
|
||||
char_u *props;
|
||||
textprop_T tmp_prop;
|
||||
proptype_T *pt;
|
||||
int dirty = FALSE;
|
||||
int ri, wi;
|
||||
@@ -1249,62 +1248,80 @@ adjust_prop_columns(
|
||||
wi = 0; // write index
|
||||
for (ri = 0; ri < proplen; ++ri)
|
||||
{
|
||||
int start_incl;
|
||||
textprop_T prop;
|
||||
int start_incl, end_incl;
|
||||
int can_drop;
|
||||
|
||||
mch_memmove(&tmp_prop, props + ri * sizeof(textprop_T),
|
||||
sizeof(textprop_T));
|
||||
pt = text_prop_type_by_id(curbuf, tmp_prop.tp_type);
|
||||
start_incl = (flags & APC_SUBSTITUTE) ||
|
||||
(pt != NULL && (pt->pt_flags & PT_FLAG_INS_START_INCL));
|
||||
mch_memmove(&prop, props + ri * sizeof(textprop_T), sizeof(textprop_T));
|
||||
pt = text_prop_type_by_id(curbuf, prop.tp_type);
|
||||
start_incl = (pt != NULL && (pt->pt_flags & PT_FLAG_INS_START_INCL))
|
||||
|| (flags & APC_SUBSTITUTE);
|
||||
end_incl = (pt != NULL && (pt->pt_flags & PT_FLAG_INS_END_INCL));
|
||||
// Do not drop zero-width props if they later can increase in size
|
||||
can_drop = !(start_incl || end_incl);
|
||||
|
||||
if (bytes_added > 0
|
||||
&& (tmp_prop.tp_col >= col + (start_incl ? 2 : 1)))
|
||||
if (bytes_added > 0)
|
||||
{
|
||||
tmp_prop.tp_col += bytes_added;
|
||||
// Save for undo if requested and not done yet.
|
||||
if ((flags & APC_SAVE_FOR_UNDO) && !dirty)
|
||||
u_savesub(lnum);
|
||||
dirty = TRUE;
|
||||
if (col + 1 <= prop.tp_col
|
||||
- (start_incl || (prop.tp_len == 0 && end_incl)))
|
||||
{
|
||||
// Change is entirely before the text property: Only shift
|
||||
prop.tp_col += bytes_added;
|
||||
// Save for undo if requested and not done yet.
|
||||
if ((flags & APC_SAVE_FOR_UNDO) && !dirty)
|
||||
u_savesub(lnum);
|
||||
dirty = TRUE;
|
||||
}
|
||||
else if (col + 1 < prop.tp_col + prop.tp_len + end_incl)
|
||||
{
|
||||
// Insertion was inside text property
|
||||
prop.tp_len += bytes_added;
|
||||
// Save for undo if requested and not done yet.
|
||||
if ((flags & APC_SAVE_FOR_UNDO) && !dirty)
|
||||
u_savesub(lnum);
|
||||
dirty = TRUE;
|
||||
}
|
||||
}
|
||||
else if (bytes_added <= 0 && (tmp_prop.tp_col > col + 1))
|
||||
else if (prop.tp_col > col + 1)
|
||||
{
|
||||
int len_changed = FALSE;
|
||||
|
||||
if (tmp_prop.tp_col + bytes_added < col + 1)
|
||||
if (prop.tp_col + bytes_added < col + 1)
|
||||
{
|
||||
tmp_prop.tp_len += (tmp_prop.tp_col - 1 - col) + bytes_added;
|
||||
tmp_prop.tp_col = col + 1;
|
||||
prop.tp_len += (prop.tp_col - 1 - col) + bytes_added;
|
||||
prop.tp_col = col + 1;
|
||||
len_changed = TRUE;
|
||||
}
|
||||
else
|
||||
tmp_prop.tp_col += bytes_added;
|
||||
prop.tp_col += bytes_added;
|
||||
// Save for undo if requested and not done yet.
|
||||
if ((flags & APC_SAVE_FOR_UNDO) && !dirty)
|
||||
u_savesub(lnum);
|
||||
dirty = TRUE;
|
||||
if (len_changed && tmp_prop.tp_len <= 0)
|
||||
continue; // drop this text property
|
||||
if (len_changed && prop.tp_len <= 0)
|
||||
{
|
||||
prop.tp_len = 0;
|
||||
if (can_drop)
|
||||
continue; // drop this text property
|
||||
}
|
||||
}
|
||||
else if (tmp_prop.tp_len > 0
|
||||
&& tmp_prop.tp_col + tmp_prop.tp_len > col
|
||||
+ ((pt != NULL && (pt->pt_flags & PT_FLAG_INS_END_INCL))
|
||||
? 0 : 1))
|
||||
else if (prop.tp_len > 0 && prop.tp_col + prop.tp_len > col)
|
||||
{
|
||||
int after = col - bytes_added
|
||||
- (tmp_prop.tp_col - 1 + tmp_prop.tp_len);
|
||||
int after = col - bytes_added - (prop.tp_col - 1 + prop.tp_len);
|
||||
|
||||
if (after > 0)
|
||||
tmp_prop.tp_len += bytes_added + after;
|
||||
prop.tp_len += bytes_added + after;
|
||||
else
|
||||
tmp_prop.tp_len += bytes_added;
|
||||
prop.tp_len += bytes_added;
|
||||
// Save for undo if requested and not done yet.
|
||||
if ((flags & APC_SAVE_FOR_UNDO) && !dirty)
|
||||
u_savesub(lnum);
|
||||
dirty = TRUE;
|
||||
if (tmp_prop.tp_len <= 0)
|
||||
if (prop.tp_len <= 0 && can_drop)
|
||||
continue; // drop this text property
|
||||
}
|
||||
mch_memmove(props + wi * sizeof(textprop_T), &tmp_prop,
|
||||
sizeof(textprop_T));
|
||||
|
||||
mch_memmove(props + wi * sizeof(textprop_T), &prop, sizeof(textprop_T));
|
||||
++wi;
|
||||
}
|
||||
if (dirty)
|
||||
|
@@ -738,6 +738,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
324,
|
||||
/**/
|
||||
323,
|
||||
/**/
|
||||
|
Reference in New Issue
Block a user