diff options
author | Bram Moolenaar <Bram@vim.org> | 2020-02-26 22:06:00 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2020-02-26 22:06:00 +0100 |
commit | 12f20038714928bfecdeee31ed1f927324542034 (patch) | |
tree | 2a621ca1c4a57514ec42c53132f1839a452167e2 | |
parent | 7eeefd4a395fe3d7c7a2a0879467cf7ed4c29fe6 (diff) | |
download | vim-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.c | 2 | ||||
-rw-r--r-- | src/testdir/test_listener.vim | 13 | ||||
-rw-r--r-- | src/testdir/test_textprop.vim | 13 | ||||
-rw-r--r-- | src/textprop.c | 85 | ||||
-rw-r--r-- | src/version.c | 2 |
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, |