summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-02-26 22:06:00 +0100
committerBram Moolenaar <Bram@vim.org>2020-02-26 22:06:00 +0100
commit12f20038714928bfecdeee31ed1f927324542034 (patch)
tree2a621ca1c4a57514ec42c53132f1839a452167e2
parent7eeefd4a395fe3d7c7a2a0879467cf7ed4c29fe6 (diff)
downloadvim-git-12f20038714928bfecdeee31ed1f927324542034.tar.gz
patch 8.2.0324: text property not updated correctly when inserting/deletingv8.2.0324
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)
-rw-r--r--src/change.c2
-rw-r--r--src/testdir/test_listener.vim13
-rw-r--r--src/testdir/test_textprop.vim13
-rw-r--r--src/textprop.c85
-rw-r--r--src/version.c2
5 files changed, 76 insertions, 39 deletions
diff --git a/src/change.c b/src/change.c
index e5ac97bd5..3ee719812 100644
--- a/src/change.c
+++ b/src/change.c
@@ -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;
}
diff --git a/src/testdir/test_listener.vim b/src/testdir/test_listener.vim
index a263abadd..9c9ba7fe4 100644
--- a/src/testdir/test_listener.vim
+++ b/src/testdir/test_listener.vim
@@ -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
diff --git a/src/testdir/test_textprop.vim b/src/testdir/test_textprop.vim
index 32001b362..6dbaa5350 100644
--- a/src/testdir/test_textprop.vim
+++ b/src/testdir/test_textprop.vim
@@ -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
diff --git a/src/textprop.c b/src/textprop.c
index 4ddb42e9d..3ad84a242 100644
--- a/src/textprop.c
+++ b/src/textprop.c
@@ -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;
-
- 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));
-
- if (bytes_added > 0
- && (tmp_prop.tp_col >= col + (start_incl ? 2 : 1)))
+ textprop_T prop;
+ int start_incl, end_incl;
+ int can_drop;
+
+ 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 += 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)
diff --git a/src/version.c b/src/version.c
index f95526c0a..3f6443124 100644
--- a/src/version.c
+++ b/src/version.c
@@ -739,6 +739,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 324,
+/**/
323,
/**/
322,