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 -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20220513205719.BE4301C075E%40moolenaar.net.

Raspunde prin e-mail lui