changeset 28526:171f9def0398 v8.2.4787

patch 8.2.4787: prop_find() does not find the right property Commit: https://github.com/vim/vim/commit/9bd3ce22e36b5760a5e22e7d34d1bd6a3411258e Author: LemonBoy <thatlemon@gmail.com> Date: Mon Apr 18 21:54:02 2022 +0100 patch 8.2.4787: prop_find() does not find the right property Problem: prop_find() does not find the right property. Solution: Fix the scan order. (closes https://github.com/vim/vim/issues/10220)
author Bram Moolenaar <Bram@vim.org>
date Mon, 18 Apr 2022 23:00:03 +0200
parents ea09c444fb6b
children 1386340aaedc
files src/testdir/test_textprop.vim src/textprop.c src/version.c
diffstat 3 files changed, 43 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/src/testdir/test_textprop.vim
+++ b/src/testdir/test_textprop.vim
@@ -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
--- a/src/textprop.c
+++ b/src/textprop.c
@@ -713,14 +713,14 @@ f_prop_find(typval_T *argvars, typval_T 
     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 
 	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 
 	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 
 							 - (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 
 		    // 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 
 		break;
 	    lnum--;
 	}
-	// Adjust col to indicate that we're continuing from prev/next line.
-	col = dir < 0 ? buf->b_ml.ml_line_len : 1;
     }
 }
 
--- a/src/version.c
+++ b/src/version.c
@@ -747,6 +747,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    4787,
+/**/
     4786,
 /**/
     4785,