Patch 8.2.5014
Problem:    Byte offsets are wrong when using text properties.
Solution:   Make sure text properties do not affect the byte counts.
            (Paul Ollis, closes #10474)
Files:      src/memline.c, src/textprop.c, src/testdir/test_textprop.vim


*** ../vim-8.2.5013/src/memline.c       2022-05-16 10:04:46.674376854 +0100
--- src/memline.c       2022-05-24 21:22:09.836491617 +0100
***************
*** 4004,4009 ****
--- 4004,4011 ----
            {
  #if defined(FEAT_BYTEOFF) && defined(FEAT_PROP_POPUP)
                int old_prop_len = 0;
+               if (buf->b_has_textprop)
+                   old_prop_len = old_len - (int)STRLEN(old_line) - 1;
  #endif
                // if the length changes and there are following lines
                count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low + 1;
***************
*** 4023,4032 ****
                // adjust free space
                dp->db_free -= extra;
                dp->db_txt_start -= extra;
- #if defined(FEAT_BYTEOFF) && defined(FEAT_PROP_POPUP)
-               if (buf->b_has_textprop)
-                   old_prop_len = old_len - (int)STRLEN(new_line) - 1;
- #endif
  
                // copy new line into the data block
                mch_memmove(old_line - extra, new_line, (size_t)new_len);
--- 4025,4030 ----
*** ../vim-8.2.5013/src/textprop.c      2022-05-14 18:10:12.166454734 +0100
--- src/textprop.c      2022-05-24 21:22:09.840491616 +0100
***************
*** 344,349 ****
--- 344,353 ----
      if (get_bufnr_from_arg(&argvars[0], &buf) == FAIL)
        return;
  
+     // This must be done _before_ we start adding properties because property
+     // changes trigger buffer (memline) reorganisation, which needs this flag
+     // to be correctly set.
+     buf->b_has_textprop = TRUE;  // this is never reset
      FOR_ALL_LIST_ITEMS(argvars[1].vval.v_list, li)
      {
        if (li->li_tv.v_type != VAR_LIST || li->li_tv.vval.v_list == NULL)
***************
*** 368,374 ****
            return;
      }
  
-     buf->b_has_textprop = TRUE;  // this is never reset
      redraw_buf_later(buf, VALID);
  }
  
--- 372,377 ----
***************
*** 441,449 ****
      if (dict_arg != NULL && get_bufnr_from_arg(dict_arg, &buf) == FAIL)
        return;
  
      prop_add_one(buf, type_name, id, start_lnum, end_lnum, start_col, 
end_col);
  
-     buf->b_has_textprop = TRUE;  // this is never reset
      redraw_buf_later(buf, VALID);
  }
  
--- 444,456 ----
      if (dict_arg != NULL && get_bufnr_from_arg(dict_arg, &buf) == FAIL)
        return;
  
+     // This must be done _before_ we add the property because property changes
+     // trigger buffer (memline) reorganisation, which needs this flag to be
+     // correctly set.
+     buf->b_has_textprop = TRUE;  // this is never reset
+ 
      prop_add_one(buf, type_name, id, start_lnum, end_lnum, start_col, 
end_col);
  
      redraw_buf_later(buf, VALID);
  }
  
*** ../vim-8.2.5013/src/testdir/test_textprop.vim       2022-05-21 
11:20:38.102070988 +0100
--- src/testdir/test_textprop.vim       2022-05-24 21:22:09.836491617 +0100
***************
*** 2094,2097 ****
--- 2094,2190 ----
    bwipe!
  endfunc
  
+ func Do_test_props_do_not_affect_byte_offsets(ff, increment)
+   new
+   let lcount = 410
+ 
+   " File format affects byte-offset calculations, so make sure it is known.
+   exec 'setlocal fileformat=' . a:ff
+ 
+   " Fill the buffer with varying length lines. We need a suitably large number
+   " to force Vim code through paths wehere previous error have occurred. This
+   " is more 'art' than 'science'.
+   let text = 'a'
+   call setline(1, text)
+   let offsets = [1]
+   for idx in range(lcount)
+       call add(offsets, offsets[idx] + len(text) + a:increment)
+       if (idx % 6) == 0
+           let text = text . 'a'
+       endif
+       call append(line('$'), text)
+   endfor
+ 
+   " Set a property that spans a few lines to cause Vim's internal buffer code
+   " to perform a reasonable amount of rearrangement.
+   call prop_type_add('one', {'highlight': 'ErrorMsg'})
+   call prop_add(1, 1, {'type': 'one', 'end_lnum': 6, 'end_col': 2})
+ 
+   for idx in range(lcount)
+       let boff = line2byte(idx + 1)
+       call assert_equal(offsets[idx], boff, 'Bad byte offset at line ' . (idx 
+ 1))
+   endfor
+ 
+   call prop_type_delete('one')
+   bwipe!
+ endfunc
+ 
+ func Test_props_do_not_affect_byte_offsets()
+   call Do_test_props_do_not_affect_byte_offsets('unix', 1)
+ endfunc
+ 
+ func Test_props_do_not_affect_byte_offsets_dos()
+   call Do_test_props_do_not_affect_byte_offsets('dos', 2)
+ endfunc
+ 
+ func Test_props_do_not_affect_byte_offsets_editline()
+   new
+   let lcount = 410
+ 
+   " File format affects byte-offset calculations, so make sure it is known.
+   setlocal fileformat=unix
+ 
+   " Fill the buffer with varying length lines. We need a suitably large number
+   " to force Vim code through paths wehere previous error have occurred. This
+   " is more 'art' than 'science'.
+   let text = 'aa'
+   call setline(1, text)
+   let offsets = [1]
+   for idx in range(lcount)
+       call add(offsets, offsets[idx] + len(text) + 1)
+       if (idx % 6) == 0
+           let text = text . 'a'
+       endif
+       call append(line('$'), text)
+   endfor
+ 
+   " Set a property that just covers the first line. When this test was
+   " developed, this did not trigger a byte-offset error.
+   call prop_type_add('one', {'highlight': 'ErrorMsg'})
+   call prop_add(1, 1, {'type': 'one', 'end_lnum': 1, 'end_col': 3})
+ 
+   for idx in range(lcount)
+       let boff = line2byte(idx + 1)
+       call assert_equal(offsets[idx], boff,
+           \ 'Confounding bad byte offset at line ' . (idx + 1))
+   endfor
+ 
+   " Insert text in the middle of the first line, keeping the property
+   " unchanged.
+   :1
+   normal aHello
+   for idx in range(1, lcount)
+       let offsets[idx] = offsets[idx] + 5
+   endfor
+ 
+   for idx in range(lcount)
+       let boff = line2byte(idx + 1)
+       call assert_equal(offsets[idx], boff,
+           \ 'Bad byte offset at line ' . (idx + 1))
+   endfor
+ 
+   call prop_type_delete('one')
+   bwipe!
+ endfunc
+ 
  " vim: shiftwidth=2 sts=2 expandtab
*** ../vim-8.2.5013/src/version.c       2022-05-24 13:57:50.434117756 +0100
--- src/version.c       2022-05-24 21:24:19.784415036 +0100
***************
*** 736,737 ****
--- 736,739 ----
  {   /* Add new patch number below this line */
+ /**/
+     5014,
  /**/

-- 
GALAHAD: No. Look, I can tackle this lot single-handed!
GIRLS:   Yes, yes, let him Tackle us single-handed!
                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

 /// 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/20220524202712.933EF1C0736%40moolenaar.net.

Raspunde prin e-mail lui