Patch 8.2.0324

10 views
Skip to first unread message

Bram Moolenaar

unread,
Feb 26, 2020, 4:06:52 PM2/26/20
to vim...@googlegroups.com

Patch 8.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)
Files: src/change.c, src/textprop.c, src/testdir/test_listener.vim,
src/testdir/test_textprop.vim


*** ../vim-8.2.0323/src/change.c 2020-01-01 16:18:33.204997405 +0100
--- src/change.c 2020-02-26 21:30:39.696404345 +0100
***************
*** 1301,1307 ****
#endif

// mark the buffer as changed and prepare for displaying
! inserted_bytes(lnum, curwin->w_cursor.col, -count);

return OK;
}
--- 1301,1307 ----
#endif

// mark the buffer as changed and prepare for displaying
! inserted_bytes(lnum, col, -count);

return OK;
}
*** ../vim-8.2.0323/src/textprop.c 2020-01-10 19:56:42.774995632 +0100
--- src/textprop.c 2020-02-26 21:47:14.650393448 +0100
***************
*** 1232,1238 ****
{
int proplen;
char_u *props;
- textprop_T tmp_prop;
proptype_T *pt;
int dirty = FALSE;
int ri, wi;
--- 1232,1237 ----
***************
*** 1249,1310 ****
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)))
{
! 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;
}
! else if (bytes_added <= 0 && (tmp_prop.tp_col > col + 1))
{
int len_changed = FALSE;

! if (tmp_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;
len_changed = TRUE;
}
else
! 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 (len_changed && tmp_prop.tp_len <= 0)
! 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))
{
! int after = col - bytes_added
! - (tmp_prop.tp_col - 1 + tmp_prop.tp_len);
if (after > 0)
! tmp_prop.tp_len += bytes_added + after;
else
! tmp_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)
continue; // drop this text property
}
! mch_memmove(props + wi * sizeof(textprop_T), &tmp_prop,
! sizeof(textprop_T));
++wi;
}
if (dirty)
--- 1248,1327 ----
wi = 0; // write index
for (ri = 0; ri < proplen; ++ri)
{
! 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)
{
! 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 (prop.tp_col > col + 1)
{
int len_changed = FALSE;

! if (prop.tp_col + bytes_added < col + 1)
{
! prop.tp_len += (prop.tp_col - 1 - col) + bytes_added;
! prop.tp_col = col + 1;
len_changed = TRUE;
}
else
! 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 && prop.tp_len <= 0)
! {
! prop.tp_len = 0;
! if (can_drop)
! continue; // drop this text property
! }
}
! else if (prop.tp_len > 0 && prop.tp_col + prop.tp_len > col)
{
! int after = col - bytes_added - (prop.tp_col - 1 + prop.tp_len);
!
if (after > 0)
! prop.tp_len += bytes_added + after;
else
! 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 (prop.tp_len <= 0 && can_drop)
continue; // drop this text property
}
!
! mch_memmove(props + wi * sizeof(textprop_T), &prop, sizeof(textprop_T));
++wi;
}
if (dirty)
*** ../vim-8.2.0323/src/testdir/test_listener.vim 2020-01-03 20:59:55.847158293 +0100
--- src/testdir/test_listener.vim 2020-02-26 21:30:39.696404345 +0100
***************
*** 326,328 ****
--- 326,341 ----
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
*** ../vim-8.2.0323/src/testdir/test_textprop.vim 2020-01-13 20:40:47.694773941 +0100
--- src/testdir/test_textprop.vim 2020-02-26 21:43:43.762965932 +0100
***************
*** 6,13 ****

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()
--- 6,11 ----
***************
*** 233,245 ****

" 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 assert_equal(expected, prop_list(1))

call assert_fails("call prop_add(1, 5, {'type': 'two', 'bufnr': 234343})", 'E158:')

call DeletePropTypes()
bwipe!
endfunc

--- 231,250 ----

" Prop without length or end column is zero length
call prop_clear(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

*** ../vim-8.2.0323/src/version.c 2020-02-26 21:24:19.157582116 +0100
--- src/version.c 2020-02-26 21:33:38.852232085 +0100
***************
*** 740,741 ****
--- 740,743 ----
{ /* Add new patch number below this line */
+ /**/
+ 324,
/**/

--
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
Reply all
Reply to author
Forward
0 new messages