patch 8.2.5014: byte offsets are wrong when using text properties

Problem:    Byte offsets are wrong when using text properties.
Solution:   Make sure text properties do not affect the byte counts.
            (Paul Ollis, closes #10474)
diff --git a/src/testdir/test_textprop.vim b/src/testdir/test_textprop.vim
index c29c10b..1345045 100644
--- a/src/testdir/test_textprop.vim
+++ b/src/testdir/test_textprop.vim
@@ -2094,4 +2094,97 @@
   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