changeset 19097:bcbc9fe665b5 v8.2.0109

patch 8.2.0109: corrupted text properties when expanding spaces Commit: https://github.com/vim/vim/commit/ac15fd8c6761763c8feedef1a2fbd8309f0a823c Author: Bram Moolenaar <Bram@vim.org> Date: Thu Jan 9 21:35:48 2020 +0100 patch 8.2.0109: corrupted text properties when expanding spaces Problem: Corrupted text properties when expanding spaces. Solution: Reallocate the line. (Nobuhiro Takasaki, closes https://github.com/vim/vim/issues/5457)
author Bram Moolenaar <Bram@vim.org>
date Thu, 09 Jan 2020 21:45:03 +0100
parents af8bd2f486b6
children 254834ce268e
files src/edit.c src/testdir/test_textprop.vim src/version.c
diffstat 3 files changed, 86 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/src/edit.c
+++ b/src/edit.c
@@ -5604,9 +5604,25 @@ ins_tab(void)
 #ifdef FEAT_PROP_POPUP
 		if (!(State & VREPLACE_FLAG))
 		{
-		    mch_memmove(ptr, ptr + i, curbuf->b_ml.ml_line_len - i
-					   - (ptr - curbuf->b_ml.ml_line_ptr));
+		    char_u  *newp;
+		    int	    col;
+
+		    newp = alloc(curbuf->b_ml.ml_line_len - i);
+		    if (newp == NULL)
+			return FALSE;
+
+		    col = ptr - curbuf->b_ml.ml_line_ptr;
+		    if (col > 0)
+			mch_memmove(newp, ptr - col, col);
+		    mch_memmove(newp + col, ptr + i,
+					   curbuf->b_ml.ml_line_len - col - i);
+
+		    if (curbuf->b_ml.ml_flags & ML_LINE_DIRTY)
+			vim_free(curbuf->b_ml.ml_line_ptr);
+		    curbuf->b_ml.ml_line_ptr = newp;
 		    curbuf->b_ml.ml_line_len -= i;
+		    curbuf->b_ml.ml_flags =
+			   (curbuf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY;
 		}
 		else
 #endif
--- a/src/testdir/test_textprop.vim
+++ b/src/testdir/test_textprop.vim
@@ -926,19 +926,32 @@ func Test_proptype_substitute2()
   bwipe!
 endfunc
 
+func SaveOptions()
+  let d = #{tabstop: &tabstop,
+	  \ softtabstop: &softtabstop,
+	  \ shiftwidth: &shiftwidth,
+	  \ expandtab: &expandtab,
+	  \ foldmethod: '"' .. &foldmethod .. '"',
+	  \ }
+  return d
+endfunc
+
+func RestoreOptions(dict)
+  for name in keys(a:dict)
+    exe 'let &' .. name .. ' = ' .. a:dict[name]
+  endfor
+endfunc
+
 func Test_textprop_noexpandtab()
-  %bwipe!
   new
-  let save_ts = &tabstop
+  let save_dict = SaveOptions()
+
   set tabstop=8
-  let save_sts = &softtabstop
   set softtabstop=4
-  let save_sw = &shiftwidth
   set shiftwidth=4
-  let save_et = &expandtab
   set noexpandtab
-  let save_fdm = &foldmethod
   set foldmethod=marker
+
   call feedkeys("\<esc>\<esc>0Ca\<cr>\<esc>\<up>", "tx")
   call prop_type_add('test', {'highlight': 'ErrorMsg'})
   call prop_add(1, 1, {'end_col': 2, 'type': 'test'})
@@ -955,9 +968,51 @@ func Test_textprop_noexpandtab()
   catch /^Vim\%((\a\+)\)\=:E964/
   endtry
   call prop_remove({'type': 'test'})
-  let &foldmethod = save_fdm
-  let &expandtab = save_et
-  let &shiftwidth = save_sw
-  let &softtabstop = save_sts
-  let &tabstop = save_ts
+  call prop_type_delete('test')
+
+  call RestoreOptions(save_dict)
+  bwipe!
 endfunc
+
+func Test_textprop_noexpandtab_redraw()
+  new
+  let save_dict = SaveOptions()
+
+  set tabstop=8
+  set softtabstop=4
+  set shiftwidth=4
+  set noexpandtab
+  set foldmethod=marker
+
+  call feedkeys("\<esc>\<esc>0Ca\<cr>\<space>\<esc>\<up>", "tx")
+  call prop_type_add('test', {'highlight': 'ErrorMsg'})
+  call prop_add(1, 1, {'end_col': 2, 'type': 'test'})
+  call feedkeys("0i\<tab>", "tx")
+  " Internally broken at the next line
+  call feedkeys("A\<left>\<tab>", "tx")
+  redraw
+  " Index calculation failed internally on next line
+  call prop_add(1, 1, {'end_col': 2, 'type': 'test'})
+  call prop_remove({'type': 'test', 'all': v:true})
+  call prop_type_delete('test')
+  call prop_type_delete('test')
+
+  call RestoreOptions(save_dict)
+  bwipe!
+endfunc
+
+func Test_textprop_ins_str()
+  new
+  call setline(1, 'just some text')
+  call prop_type_add('test', {'highlight': 'ErrorMsg'})
+  call prop_add(1, 1, {'end_col': 2, 'type': 'test'})
+  call assert_equal([{'id': 0, 'col': 1, 'end': 1, 'type': 'test', 'length': 1, 'start': 1}], prop_list(1))
+
+  call feedkeys("foi\<F8>\<Esc>", "tx")
+  call assert_equal('just s<F8>ome text', getline(1))
+  call assert_equal([{'id': 0, 'col': 1, 'end': 1, 'type': 'test', 'length': 1, 'start': 1}], prop_list(1))
+
+  bwipe!
+  call prop_remove({'type': 'test'})
+  call prop_type_delete('test')
+endfunc
--- a/src/version.c
+++ b/src/version.c
@@ -743,6 +743,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    109,
+/**/
     108,
 /**/
     107,