changeset 19110:e40814841406 v8.2.0115

patch 8.2.0115: byte2line() does not work correctly with text properties Commit: https://github.com/vim/vim/commit/9df53b62de86f544b41bef5e964b7fc8ae5231e3 Author: Bram Moolenaar <Bram@vim.org> Date: Mon Jan 13 20:40:51 2020 +0100 patch 8.2.0115: byte2line() does not work correctly with text properties Problem: Byte2line() does not work correctly with text properties. (Billie Cleek) Solution: Take the bytes of the text properties into account. (closes #5334)
author Bram Moolenaar <Bram@vim.org>
date Mon, 13 Jan 2020 20:45:03 +0100
parents a25bb65cb6d8
children ca362df0be20
files src/memline.c src/testdir/test_textprop.vim src/version.c
diffstat 3 files changed, 50 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/memline.c
+++ b/src/memline.c
@@ -5738,7 +5738,7 @@ ml_find_line_or_offset(buf_T *buf, linen
 	count = (long)(buf->b_ml.ml_locked_high) -
 		(long)(buf->b_ml.ml_locked_low) + 1;
 	start_idx = idx = curline - buf->b_ml.ml_locked_low;
-	if (idx == 0)// first line in block, text at the end
+	if (idx == 0)  // first line in block, text at the end
 	    text_end = dp->db_txt_end;
 	else
 	    text_end = ((dp->db_index[idx - 1]) & DB_INDEX_MASK);
@@ -5752,13 +5752,38 @@ ml_find_line_or_offset(buf_T *buf, linen
 	}
 	else
 	{
+#ifdef FEAT_PROP_POPUP
+	    long textprop_total = 0;
+	    long textprop_size = 0;
+	    char_u *l1, *l2;
+#endif
+
 	    extra = 0;
-	    while (offset >= size
-		       + text_end - (int)((dp->db_index[idx]) & DB_INDEX_MASK)
-								      + ffdos)
+	    for (;;)
 	    {
+#ifdef FEAT_PROP_POPUP
+		if (buf->b_has_textprop)
+		{
+		    // compensate for the extra bytes taken by textprops
+		    l1 = (char_u *)dp + ((dp->db_index[idx]) & DB_INDEX_MASK);
+		    l2 = (char_u *)dp + (idx == 0 ? dp->db_txt_end
+				  : ((dp->db_index[idx - 1]) & DB_INDEX_MASK));
+		    textprop_size = (l2 - l1) - (STRLEN(l1) + 1);
+		}
+#endif
+		if (!(offset >= size
+			+ text_end - (int)((dp->db_index[idx]) & DB_INDEX_MASK)
+#ifdef FEAT_PROP_POPUP
+			- textprop_total - textprop_size
+#endif
+			+ ffdos))
+		    break;
+
 		if (ffdos)
 		    size++;
+#ifdef FEAT_PROP_POPUP
+		textprop_total += textprop_size;
+#endif
 		if (idx == count - 1)
 		{
 		    extra = 1;
@@ -5776,7 +5801,8 @@ ml_find_line_or_offset(buf_T *buf, linen
 	    // lengths.
 	    len = 0;
 	    for (i = start_idx; i <= idx; ++i)
-		len += (int)STRLEN((char_u *)dp + ((dp->db_index[i]) & DB_INDEX_MASK)) + 1;
+		len += (int)STRLEN((char_u *)dp
+				    + ((dp->db_index[i]) & DB_INDEX_MASK)) + 1;
 	}
 	else
 #endif
--- a/src/testdir/test_textprop.vim
+++ b/src/testdir/test_textprop.vim
@@ -664,7 +664,7 @@ func Test_prop_multiline()
   call prop_type_delete('comment')
 endfunc
 
-func Test_prop_byteoff()
+func Test_prop_line2byte()
   call prop_type_add('comment', {'highlight': 'Directory'})
   new
   call setline(1, ['line1', 'second line', ''])
@@ -677,6 +677,22 @@ func Test_prop_byteoff()
   call prop_type_delete('comment')
 endfunc
 
+func Test_prop_byte2line()
+  new
+  set ff=unix
+  call setline(1, ['one one', 'two two', 'three three', 'four four', 'five'])
+  call assert_equal(4, byte2line(line2byte(4)))
+  call assert_equal(5, byte2line(line2byte(5)))
+
+  call prop_type_add('prop', {'highlight': 'Directory'})
+  call prop_add(3, 1, {'length': 5, 'type': 'prop'})
+  call assert_equal(4, byte2line(line2byte(4)))
+  call assert_equal(5, byte2line(line2byte(5)))
+
+  bwipe!
+  call prop_type_delete('prop')
+endfunc
+
 func Test_prop_undo()
   new
   call prop_type_add('comment', {'highlight': 'Directory'})
--- 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 */
 /**/
+    115,
+/**/
     114,
 /**/
     113,