Patch 8.2.4950
Problem: Text properties position wrong after shifting text.
Solution: Adjust the text properties when shifting a block of text.
(closes #10418)
Files: src/ops.c, src/testdir/test_textprop.vim
*** ../vim-8.2.4949/src/ops.c 2022-05-09 20:09:19.290641428 +0100
--- src/ops.c 2022-05-13 21:55:46.377099505 +0100
***************
*** 286,293 ****
struct block_def bd;
int incr;
colnr_T ws_vcol;
! int i = 0, j = 0;
! int len;
#ifdef FEAT_RIGHTLEFT
int old_p_ri = p_ri;
--- 286,294 ----
struct block_def bd;
int incr;
colnr_T ws_vcol;
! int added;
! unsigned new_line_len; // the length of the line after the
! // block shift
#ifdef FEAT_RIGHTLEFT
int old_p_ri = p_ri;
***************
*** 308,313 ****
--- 309,316 ----
if (!left)
{
+ int tabs = 0, spaces = 0;
+
/*
* 1. Get start vcol
* 2. Total ws vcols
***************
*** 343,371 ****
#ifdef FEAT_VARTABS
if (!curbuf->b_p_et)
tabstop_fromto(ws_vcol, ws_vcol + total,
! ts_val, curbuf->b_p_vts_array, &i, &j);
else
! j = total;
#else
if (!curbuf->b_p_et)
! i = ((ws_vcol % ts_val) + total) / ts_val; // number of tabs
! if (i)
! j = ((ws_vcol % ts_val) + total) % ts_val; // number of spp
else
! j = total;
#endif
// if we're splitting a TAB, allow for it
bd.textcol -= bd.pre_whitesp_c - (bd.startspaces != 0);
! len = (int)STRLEN(bd.textstart) + 1;
! newp = alloc(bd.textcol + i + j + len);
if (newp == NULL)
return;
- vim_memset(newp, NUL, (size_t)(bd.textcol + i + j + len));
mch_memmove(newp, oldp, (size_t)bd.textcol);
! vim_memset(newp + bd.textcol, TAB, (size_t)i);
! vim_memset(newp + bd.textcol + i, ' ', (size_t)j);
! // the end
! mch_memmove(newp + bd.textcol + i + j, bd.textstart, (size_t)len);
}
else // left
{
--- 346,374 ----
#ifdef FEAT_VARTABS
if (!curbuf->b_p_et)
tabstop_fromto(ws_vcol, ws_vcol + total,
! ts_val, curbuf->b_p_vts_array, &tabs, &spaces);
else
! spaces = total;
#else
if (!curbuf->b_p_et)
! tabs = ((ws_vcol % ts_val) + total) / ts_val; // number of tabs
! if (tabs > 0)
! spaces = ((ws_vcol % ts_val) + total) % ts_val; // number of spp
else
! spaces = total;
#endif
// if we're splitting a TAB, allow for it
bd.textcol -= bd.pre_whitesp_c - (bd.startspaces != 0);
!
! new_line_len = bd.textcol + tabs + spaces + (int)STRLEN(bd.textstart);
! newp = alloc(new_line_len + 1);
if (newp == NULL)
return;
mch_memmove(newp, oldp, (size_t)bd.textcol);
! vim_memset(newp + bd.textcol, TAB, (size_t)tabs);
! vim_memset(newp + bd.textcol + tabs, ' ', (size_t)spaces);
! // Note that STRMOVE() copies the trailing NUL.
! STRMOVE(newp + bd.textcol + tabs + spaces, bd.textstart);
}
else // left
{
***************
*** 376,383 ****
colnr_T verbatim_copy_width;// the (displayed) width of this part
// of line
unsigned fill; // nr of spaces that replace a TAB
- unsigned new_line_len; // the length of the line after the
- // block shift
size_t block_space_width;
size_t shift_amount;
char_u *non_white = bd.textstart;
--- 379,384 ----
***************
*** 448,465 ****
// - the rest of the line, pointed to by non_white.
new_line_len = (unsigned)(verbatim_copy_end - oldp)
+ fill
! + (unsigned)STRLEN(non_white) + 1;
! newp = alloc(new_line_len);
if (newp == NULL)
return;
mch_memmove(newp, oldp, (size_t)(verbatim_copy_end - oldp));
vim_memset(newp + (verbatim_copy_end - oldp), ' ', (size_t)fill);
STRMOVE(newp + (verbatim_copy_end - oldp) + fill, non_white);
}
// replace the line
ml_replace(curwin->w_cursor.lnum, newp, FALSE);
! changed_bytes(curwin->w_cursor.lnum, bd.textcol);
State = oldstate;
curwin->w_cursor.col = oldcol;
#ifdef FEAT_RIGHTLEFT
--- 449,468 ----
// - the rest of the line, pointed to by non_white.
new_line_len = (unsigned)(verbatim_copy_end - oldp)
+ fill
! + (unsigned)STRLEN(non_white);
! newp = alloc(new_line_len + 1);
if (newp == NULL)
return;
mch_memmove(newp, oldp, (size_t)(verbatim_copy_end - oldp));
vim_memset(newp + (verbatim_copy_end - oldp), ' ', (size_t)fill);
+ // Note that STRMOVE() copies the trailing NUL.
STRMOVE(newp + (verbatim_copy_end - oldp) + fill, non_white);
}
// replace the line
+ added = new_line_len - (int)STRLEN(oldp);
ml_replace(curwin->w_cursor.lnum, newp, FALSE);
! inserted_bytes(curwin->w_cursor.lnum, bd.textcol, added);
State = oldstate;
curwin->w_cursor.col = oldcol;
#ifdef FEAT_RIGHTLEFT
*** ../vim-8.2.4949/src/testdir/test_textprop.vim 2022-05-13 12:41:39.469488941 +0100
--- src/testdir/test_textprop.vim 2022-05-13 21:48:25.837324296 +0100
***************
*** 1933,1937 ****
--- 1933,1961 ----
bwipe!
endfunc
+ func Test_prop_shift_block()
+ new
+ call AddPropTypes()
+
+ call setline(1, ['some highlighted text']->repeat(2))
+ call prop_add(1, 10, #{type: 'one', length: 11})
+ call prop_add(2, 10, #{type: 'two', length: 11})
+
+ call cursor(1, 1)
+ call feedkeys("5l\<c-v>>", 'nxt')
+ call cursor(2, 1)
+ call feedkeys("5l\<c-v><", 'nxt')
+
+ let expected = [
+ \ {'lnum': 1, 'id': 0, 'col': 8, 'type_bufnr': 0, 'end': 1, 'type': 'one',
+ \ 'length': 11, 'start' : 1},
+ \ {'lnum': 2, 'id': 0, 'col': 6, 'type_bufnr': 0, 'end': 1, 'type': 'two',
+ \ 'length': 11, 'start' : 1}
+ \ ]
+ call assert_equal(expected, prop_list(1, #{end_lnum: 2}))
+
+ call DeletePropTypes()
+ bwipe!
+ endfunc
" vim: shiftwidth=2 sts=2 expandtab
*** ../vim-8.2.4949/src/version.c 2022-05-13 16:23:33.797284090 +0100
--- src/version.c 2022-05-13 21:49:48.961281878 +0100
***************
*** 748,749 ****
--- 748,751 ----
{ /* Add new patch number below this line */
+ /**/
+ 4950,
/**/
--
What is the difference between a professional and an amateur?
The ark was built by an amateur; professionals gave us the Titanic.
/// Bram Moolenaar -- Br...@Moolenaar.net --
http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features --
http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims --
http://ICCF-Holland.org ///