patch 8.2.4787: prop_find() does not find the right property v8.2.4787
authorLemonBoy <thatlemon@gmail.com>
Mon, 18 Apr 2022 20:54:02 +0000 (21:54 +0100)
committerBram Moolenaar <Bram@vim.org>
Mon, 18 Apr 2022 20:54:02 +0000 (21:54 +0100)
Problem:    prop_find() does not find the right property.
Solution:   Fix the scan order. (closes #10220)

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

index 530a25662ac2ac2fee0fccffb3d762ec23425163..3dd676efc0de008f3fa5b202ad282e1243e970f1 100644 (file)
@@ -1847,4 +1847,28 @@ func Test_prop_list()
   call v9.CheckLegacyAndVim9Success(lines)
 endfunc
 
+func Test_prop_find_prev_on_same_line()
+  new
+
+  call setline(1, 'the quikc bronw fox jumsp over the layz dog')
+  call prop_type_add('misspell', #{highlight: 'ErrorMsg'})
+  for col in [8, 14, 24, 38]
+    call prop_add(1, col, #{type: 'misspell', length: 2})
+  endfor
+
+  call cursor(1,18)
+  let expected = [
+    \ #{lnum: 1, id: 0, col: 14, end: 1, type: 'misspell', type_bufnr: 0, length: 2, start: 1},
+    \ #{lnum: 1, id: 0, col: 24, end: 1, type: 'misspell', type_bufnr: 0, length: 2, start: 1}
+    \ ]
+
+  let result = prop_find(#{type: 'misspell'}, 'b')
+  call assert_equal(expected[0], result)
+  let result = prop_find(#{type: 'misspell'}, 'f')
+  call assert_equal(expected[1], result)
+
+  call prop_type_delete('misspell')
+  bwipe!
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
index f5cf6b851ca639629bbd932fbe045cb114fe1c68..5ec983fcbbacc1dad3aeeff0381bec10df8a0923 100644 (file)
@@ -713,14 +713,14 @@ f_prop_find(typval_T *argvars, typval_T *rettv)
     dictitem_T  *di;
     int                lnum_start;
     int                start_pos_has_prop = 0;
-    int                seen_end = 0;
+    int                seen_end = FALSE;
     int                id = 0;
     int                id_found = FALSE;
     int                type_id = -1;
-    int                skipstart = 0;
+    int                skipstart = FALSE;
     int                lnum = -1;
     int                col = -1;
-    int                dir = 1;    // 1 = forward, -1 = backward
+    int                dir = FORWARD;    // FORWARD == 1, BACKWARD == -1
     int                both;
 
     if (in_vim9script()
@@ -745,7 +745,7 @@ f_prop_find(typval_T *argvars, typval_T *rettv)
        char_u      *dir_s = tv_get_string(&argvars[1]);
 
        if (*dir_s == 'b')
-           dir = -1;
+           dir = BACKWARD;
        else if (*dir_s != 'f')
        {
            emsg(_(e_invalid_argument));
@@ -819,17 +819,19 @@ f_prop_find(typval_T *argvars, typval_T *rettv)
        int         prop_start;
        int         prop_end;
 
-       for (i = 0; i < count; ++i)
+       for (i = dir == BACKWARD ? count - 1 : 0; i >= 0 && i < count; i += dir)
        {
            mch_memmove(&prop, text + textlen + i * sizeof(textprop_T),
-                           sizeof(textprop_T));
+                                                          sizeof(textprop_T));
 
+           // For the very first line try to find the first property before or
+           // after `col`, depending on the search direction.
            if (lnum == lnum_start)
            {
-               if (dir < 0)
+               if (dir == BACKWARD)
                {
-                   if (col < prop.tp_col)
-                       break;
+                   if (prop.tp_col > col)
+                       continue;
                }
                else if (prop.tp_col + prop.tp_len - (prop.tp_len != 0) < col)
                    continue;
@@ -845,9 +847,13 @@ f_prop_find(typval_T *argvars, typval_T *rettv)
                                                         - (prop.tp_len != 0)))
                    start_pos_has_prop = 1;
 
+               // The property was not continued from last line, it starts on
+               // this line.
                prop_start = !(prop.tp_flags & TP_FLAG_CONT_PREV);
+               // The property does not continue on the next line, it ends on
+               // this line.
                prop_end = !(prop.tp_flags & TP_FLAG_CONT_NEXT);
-               if (!prop_start && prop_end && dir > 0)
+               if (!prop_start && prop_end && dir == FORWARD)
                    seen_end = 1;
 
                // Skip lines without the start flag.
@@ -856,7 +862,7 @@ f_prop_find(typval_T *argvars, typval_T *rettv)
                    // Always search backwards for start when search started
                    // on a prop and we're not skipping.
                    if (start_pos_has_prop && !skipstart)
-                       dir = -1;
+                       dir = BACKWARD;
                    continue;
                }
 
@@ -887,8 +893,6 @@ f_prop_find(typval_T *argvars, typval_T *rettv)
                break;
            lnum--;
        }
-       // Adjust col to indicate that we're continuing from prev/next line.
-       col = dir < 0 ? buf->b_ml.ml_line_len : 1;
     }
 }
 
index 9d3a9b5514b272bb480b2e8dfee084449ca72c9f..c221c28ad8a4a6365263f7497c147a0fa96d0cf6 100644 (file)
@@ -746,6 +746,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    4787,
 /**/
     4786,
 /**/