changeset 23776:9f692a75d481 v8.2.2429

patch 8.2.2429: :goto does not work correctly with text properties Commit: https://github.com/vim/vim/commit/59ff64079b4fcf0393a7413e3242a8b58c2ceadb Author: Bram Moolenaar <Bram@vim.org> Date: Sat Jan 30 17:16:28 2021 +0100 patch 8.2.2429: :goto does not work correctly with text properties Problem: :goto does not work correctly with text properties. (Sam McCall) Solution: Add a test. (Andrew Radev) Also use the text property size when computing the remaining offset. (closes #5930)
author Bram Moolenaar <Bram@vim.org>
date Sat, 30 Jan 2021 17:30:03 +0100
parents 86461330648b
children 047036413343
files src/memline.c src/testdir/test_textprop.vim src/version.c
diffstat 3 files changed, 55 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/src/memline.c
+++ b/src/memline.c
@@ -5701,6 +5701,10 @@ ml_find_line_or_offset(buf_T *buf, linen
 
     while ((lnum != 0 && curline < lnum) || (offset != 0 && size < offset))
     {
+#ifdef FEAT_PROP_POPUP
+	size_t textprop_total = 0;
+#endif
+
 	if (curline > buf->b_ml.ml_line_count
 		|| (hp = ml_find_line(buf, curline, ML_FIND)) == NULL)
 	    return -1;
@@ -5722,18 +5726,16 @@ ml_find_line_or_offset(buf_T *buf, linen
 	}
 	else
 	{
-#ifdef FEAT_PROP_POPUP
-	    size_t textprop_total = 0;
-	    size_t textprop_size = 0;
-	    char_u *l1, *l2;
-#endif
-
 	    extra = 0;
 	    for (;;)
 	    {
 #ifdef FEAT_PROP_POPUP
+		size_t textprop_size = 0;
+
 		if (buf->b_has_textprop)
 		{
+		    char_u *l1, *l2;
+
 		    // 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
@@ -5763,7 +5765,7 @@ ml_find_line_or_offset(buf_T *buf, linen
 	    }
 	}
 #ifdef FEAT_PROP_POPUP
-	if (buf->b_has_textprop)
+	if (buf->b_has_textprop && lnum != 0)
 	{
 	    int i;
 
@@ -5771,12 +5773,18 @@ 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;
+	    {
+		char_u *p = (char_u *)dp + ((dp->db_index[i]) & DB_INDEX_MASK);
+		len += (int)STRLEN(p) + 1;
+	    }
 	}
 	else
 #endif
-	    len = text_end - ((dp->db_index[idx]) & DB_INDEX_MASK);
+	    len = text_end - ((dp->db_index[idx]) & DB_INDEX_MASK)
+#ifdef FEAT_PROP_POPUP
+				- (long)textprop_total
+#endif
+				;
 	size += len;
 	if (offset != 0 && size >= offset)
 	{
@@ -5786,7 +5794,11 @@ ml_find_line_or_offset(buf_T *buf, linen
 		*offp = offset - size + len;
 	    else
 		*offp = offset - size + len
-		     - (text_end - ((dp->db_index[idx - 1]) & DB_INDEX_MASK));
+		     - (text_end - ((dp->db_index[idx - 1]) & DB_INDEX_MASK))
+#ifdef FEAT_PROP_POPUP
+		     + (long)textprop_total
+#endif
+		     ;
 	    curline += idx - start_idx + extra;
 	    if (curline > buf->b_ml.ml_line_count)
 		return -1;	// exactly one byte beyond the end
--- a/src/testdir/test_textprop.vim
+++ b/src/testdir/test_textprop.vim
@@ -771,6 +771,36 @@ func Test_prop_byte2line()
   call prop_type_delete('prop')
 endfunc
 
+func Test_prop_goto_byte()
+  new
+  call setline(1, '')
+  call setline(2, 'two three')
+  call setline(3, '')
+  call setline(4, 'four five')
+
+  call prop_type_add('testprop', {'highlight': 'Directory'})
+  call search('^two')
+  call prop_add(line('.'), col('.'), {
+        \ 'length': len('two'),
+        \ 'type':   'testprop'
+        \ })
+
+  call search('two \zsthree')
+  let expected_pos = line2byte(line('.')) + col('.') - 1
+  exe expected_pos .. 'goto'
+  let actual_pos = line2byte(line('.')) + col('.') - 1
+  eval actual_pos->assert_equal(expected_pos)
+
+  call search('four \zsfive')
+  let expected_pos = line2byte(line('.')) + col('.') - 1
+  exe expected_pos .. 'goto'
+  let actual_pos = line2byte(line('.')) + col('.') - 1
+  eval actual_pos->assert_equal(expected_pos)
+
+  call prop_type_delete('testprop')
+  bwipe!
+endfunc
+
 func Test_prop_undo()
   new
   call prop_type_add('comment', {'highlight': 'Directory'})
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    2429,
+/**/
     2428,
 /**/
     2427,