]> granicus.if.org Git - vim/commitdiff
patch 8.2.2429: :goto does not work correctly with text properties v8.2.2429
authorBram Moolenaar <Bram@vim.org>
Sat, 30 Jan 2021 16:16:28 +0000 (17:16 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 30 Jan 2021 16:16:28 +0000 (17:16 +0100)
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)

src/memline.c
src/testdir/test_textprop.vim
src/version.c

index 4137a66ad88dcbaca0917c811376dabc1e3b3839..c5303bb837a0310983b802ba445ce484309d2a03 100644 (file)
@@ -5701,6 +5701,10 @@ ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp)
 
     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, linenr_T lnum, long *offp)
        }
        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, linenr_T lnum, long *offp)
            }
        }
 #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, linenr_T lnum, long *offp)
            // 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, linenr_T lnum, long *offp)
                *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
index a4033fa48b3be4765fe5b94a14bfa6dc6ee9eaf4..245533567f3478a4b57a995855fcb855417fdba8 100644 (file)
@@ -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'})
index f7e267f030ad4d208af6eaa5c6efdbc2865d95da..52fa66399748c80513cd8f233520f4a0bd9334d0 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2429,
 /**/
     2428,
 /**/