search('multi-byte char', 'bce') does not match at cursor position.

Steps to reproduce:

  $ vim -u NONE
  :set encoding=utf-8
  :call setline(1, "\uff21")
  :echo search("\uff21", "bceW")  " no wrap scan
  0

Expected:

  1

I think that the attached patch fixes this problem.  Please check it.


For search("\uff21", "bce"), Vim checks if matched position is before the
start
position with this expression:

  regmatch.endpos[0].col - 1 + extra_col <= start_pos.col
  (extra_col = SEARCH_START ? 0 : 1)

  normal boundary
  |     SEARCH_START boundary
<-|   <-|
  |0|1|2|3|
  |  A  |
   ^   ^ ^
   |   | regmatch.endpos[0].col
   |   | LHS: regmatch.endpos[0].col - 1 + extra_col(1)
   |   LHS: regmatch.endpos[0].col - 1 + extra_col(0)   (LHS<=RHS => false)
   RHS: start_pos.col

This patch change it to:

  regmatch.endpos[0].col - 1 < start_pos.col + extra_col
  (extra_col = SEARCH_START ? len(A) : 0)

  normal boundary
  |     SEARCH_START boundary
<-|   <-|
  |0|1|2|3|
  |  A  |
   ^   ^ ^
   |   | regmatch.endpos[0].col
   |   | RHS: start_pos.col + extra_col(len(A))  (LHS<RHS => true)
   |   LHS: regmatch.endpos[0].col - 1
   start_pos.col
   RHS: start_pos.col + extra_col(0)


-- 
Yukihiro Nakadaira - [email protected]

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.
diff -r bfc3682510d6 src/search.c
--- a/src/search.c      Sat Jul 04 15:05:14 2015 +0200
+++ b/src/search.c      Thu Jul 09 21:28:34 2015 +0900
@@ -548,6 +548,7 @@
     pos_T      start_pos;
     int                at_first_line;
     int                extra_col;
+    int                start_char_len;
     int                match_ok;
     long       nmatched;
     int                submatch = 0;
@@ -574,23 +575,37 @@
        /* When not accepting a match at the start position set "extra_col" to
         * a non-zero value.  Don't do that when starting at MAXCOL, since
         * MAXCOL + 1 is zero. */
-       if ((options & SEARCH_START) || pos->col == MAXCOL)
-           extra_col = 0;
+       if (pos->col == MAXCOL)
+           start_char_len = 0;
 #ifdef FEAT_MBYTE
        /* Watch out for the "col" being MAXCOL - 2, used in a closed fold. */
-       else if (dir != BACKWARD && has_mbyte
-                    && pos->lnum >= 1 && pos->lnum <= buf->b_ml.ml_line_count
-                                                    && pos->col < MAXCOL - 2)
+       else if (has_mbyte
+                   && pos->lnum >= 1 && pos->lnum <= buf->b_ml.ml_line_count
+                                                   && pos->col < MAXCOL - 2)
        {
            ptr = ml_get_buf(buf, pos->lnum, FALSE) + pos->col;
            if (*ptr == NUL)
-               extra_col = 1;
+               start_char_len = 1;
            else
-               extra_col = (*mb_ptr2len)(ptr);
+               start_char_len = (*mb_ptr2len)(ptr);
        }
 #endif
        else
-           extra_col = 1;
+           start_char_len = 1;
+       if (dir == FORWARD)
+       {
+           if (options & SEARCH_START)
+               extra_col = 0;
+           else
+               extra_col = start_char_len;
+       }
+       else
+       {
+           if (options & SEARCH_START)
+               extra_col = start_char_len;
+           else
+               extra_col = 0;
+       }
 
        start_pos = *pos;       /* remember start pos for detecting no match */
        found = 0;              /* default: not found */
@@ -779,15 +794,15 @@
                                        || (lnum + regmatch.endpos[0].lnum
                                                             == start_pos.lnum
                                             && (int)regmatch.endpos[0].col - 1
-                                                                  + extra_col
-                                                       <= (int)start_pos.col))
+                                                       < (int)start_pos.col
+                                                               + extra_col))
                                    : (lnum + regmatch.startpos[0].lnum
                                                              < start_pos.lnum
                                        || (lnum + regmatch.startpos[0].lnum
                                                             == start_pos.lnum
                                             && (int)regmatch.startpos[0].col
-                                                                  + extra_col
-                                                     <= (int)start_pos.col))))
+                                                     < (int)start_pos.col
+                                                             + extra_col))))
                            {
                                match_ok = TRUE;
                                matchpos = regmatch.startpos[0];
diff -r bfc3682510d6 src/testdir/test_search_bce_multibyte.in
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/src/testdir/test_search_bce_multibyte.in  Thu Jul 09 21:28:34 2015 +0900
@@ -0,0 +1,15 @@
+Test for search('multi-byte char', 'bce')
+
+STARTTEST
+:source small.vim
+:source mbyte.vim
+:set encoding=utf-8
+:/^Test bce:/+1
+:$put =search('A', 'bce', line('.'))
+:1;/^Results:/,$wq! test.out
+ENDTEST
+
+Results:
+
+Test bce:
+A
diff -r bfc3682510d6 src/testdir/test_search_bce_multibyte.ok
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/src/testdir/test_search_bce_multibyte.ok  Thu Jul 09 21:28:34 2015 +0900
@@ -0,0 +1,5 @@
+Results:
+
+Test bce:
+A
+15

Raspunde prin e-mail lui