To: [email protected]
Subject: Patch 6.1b.005
Fcc: outbox
From: Bram Moolenaar <[email protected]>
MIME-Version: 1.0
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
------------

Patch 6.1b.005
Problem:    Using a search pattern that causes an out-of-stack error while
           'hlsearch' is set keeps giving the hit-Enter prompt.
           A search pattern that takes a long time delays typing when
           'incsearch' is set.
Solution:   Stop 'hlsearch' highlighting when the regexp causes an error.
           Stop searching for 'incsearch' when a character is typed.
Files:      src/globals.h, src/message.c, src/screen.c, src/search.c,
           src/vim.h


*** ../vim61b.004/src/globals.h Sat Mar  9 16:17:30 2002
--- src/globals.h       Tue Mar 12 20:54:52 2002
***************
*** 144,150 ****
 EXTERN int    emsg_skip INIT(= 0);        /* don't display errors for
                                              expression that is skipped */
 #endif
! EXTERN int    did_emsg;                   /* set by emsg() for DoOneCmd() */
 EXTERN int    emsg_on_display INIT(= FALSE);  /* there is an error message */
 EXTERN int    rc_did_emsg INIT(= FALSE);  /* vim_regcomp() called emsg() */

--- 144,152 ----
 EXTERN int    emsg_skip INIT(= 0);        /* don't display errors for
                                              expression that is skipped */
 #endif
! EXTERN int    did_emsg;                   /* set by emsg() when the message
!                                              is displayed */
! EXTERN int    called_emsg;                /* always set by emsg() */
 EXTERN int    emsg_on_display INIT(= FALSE);  /* there is an error message */
 EXTERN int    rc_did_emsg INIT(= FALSE);  /* vim_regcomp() called emsg() */

*** ../vim61b.004/src/message.c Sat Mar  9 16:17:30 2002
--- src/message.c       Tue Mar 12 21:06:09 2002
***************
*** 390,395 ****
--- 390,397 ----
     int               other_sourcing_name;
     char      *p;

+     called_emsg = TRUE;
+
     /*
      * If "emsg_off" is set: no error messages at the moment.
      * If 'debug' is set: do error message anyway, but without side effects.
*** ../vim61b.004/src/screen.c  Mon Mar  4 21:27:41 2002
--- src/screen.c        Tue Mar 12 20:59:15 2002
***************
*** 3006,3012 ****
               shl = &search_hl;
               for (;;)
               {
!                   for (;;)
                   {
                       if (shl->startp != NULL
                               && ptr >= shl->startp
--- 3006,3012 ----
               shl = &search_hl;
               for (;;)
               {
!                   while (shl->rm.regprog != NULL)
                   {
                       if (shl->startp != NULL
                               && ptr >= shl->startp
***************
*** 5295,5301 ****
 # endif
           }
           n = 0;
!           while (shl->first_lnum < lnum)
           {
               next_search_hl(wp, shl, shl->first_lnum, (colnr_T)n);
               if (shl->lnum != 0)
--- 5295,5301 ----
 # endif
           }
           n = 0;
!           while (shl->first_lnum < lnum && shl->rm.regprog != NULL)
           {
               next_search_hl(wp, shl, shl->first_lnum, (colnr_T)n);
               if (shl->lnum != 0)
***************
*** 5355,5360 ****
--- 5355,5361 ----
      * Repeat searching for a match until one is found that includes "mincol"
      * or none is found in this line.
      */
+     called_emsg = FALSE;
     for (;;)
     {
       /* Three situations:
***************
*** 5381,5386 ****
--- 5382,5395 ----

       shl->lnum = lnum;
       nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, matchcol);
+       if (called_emsg)
+       {
+           /* Error while handling regexp: stop using this regexp. */
+           vim_free(shl->rm.regprog);
+           shl->rm.regprog = NULL;
+           no_hlsearch = TRUE;
+           break;
+       }
       if (nmatched == 0)
       {
           shl->lnum = 0;              /* no match found */
*** ../vim61b.004/src/search.c  Sun Feb 17 15:32:34 2002
--- src/search.c        Tue Mar 12 22:25:57 2002
***************
*** 409,414 ****
--- 409,415 ----
  * if (options & SEARCH_START) accept match at pos itself
  * if (options & SEARCH_KEEP) keep previous search pattern
  * if (options & SEARCH_FOLD) match only once in a closed fold
+  * if (options & SEARCH_PEEK) check for typed char, cancel search
  *
  * Return FAIL (zero) for failure, non-zero for success.
  * When FEAT_EVAL is defined, returns the index of the first matching
***************
*** 441,446 ****
--- 442,452 ----
     long      nmatched;
     int               submatch = 0;
     linenr_T  first_lnum;
+ #ifdef FEAT_SEARCH_EXTRA
+     int               break_loop = FALSE;
+ #else
+ # define break_loop FALSE
+ #endif

     if (search_regcomp(str, RE_SEARCH, pat_use,
                  (options & (SEARCH_HIS + SEARCH_KEEP)), &regmatch) == FAIL)
***************
*** 465,470 ****
--- 471,477 ----
 /*
  * find the string
  */
+     called_emsg = FALSE;
     do        /* loop for count */
     {
       start_pos = *pos;       /* remember start pos for detecting no match */
***************
*** 500,505 ****
--- 507,515 ----
               first_lnum = lnum;
               nmatched = vim_regexec_multi(&regmatch, win, buf,
                                                           lnum, (colnr_T)0);
+               /* Abort searching on an error (e.g., out of stack). */
+               if (called_emsg)
+                   break;
               if (nmatched > 0)
               {
                   /* match may actually be in another line when using \zs */
***************
*** 708,713 ****
--- 718,736 ----
               if (got_int)
                   break;

+ #ifdef FEAT_SEARCH_EXTRA
+               /* Cancel searching if a character was typed.  Used for
+                * 'incsearch'.  Don't check too often, that would slowdown
+                * searching too much. */
+               if ((options & SEARCH_PEEK)
+                       && ((lnum - pos->lnum) & 0x3f) == 0
+                       && char_avail())
+               {
+                   break_loop = TRUE;
+                   break;
+               }
+ #endif
+
               if (loop && lnum == start_pos.lnum)
                   break;          /* if second loop, stop where started */
           }
***************
*** 717,723 ****
            * stop the search if wrapscan isn't set, after an interrupt and
            * after a match
            */
!           if (!p_ws || got_int || found)
               break;

           /*
--- 740,746 ----
            * stop the search if wrapscan isn't set, after an interrupt and
            * after a match
            */
!           if (!p_ws || got_int || called_emsg || break_loop || found)
               break;

           /*
***************
*** 740,746 ****
                   give_warning((char_u *)_(bot_top_msg), TRUE);
           }
       }
!       if (got_int)
           break;
     }
     while (--count > 0 && found);   /* stop after count matches or no match */
--- 763,769 ----
                   give_warning((char_u *)_(bot_top_msg), TRUE);
           }
       }
!       if (got_int || called_emsg || break_loop)
           break;
     }
     while (--count > 0 && found);   /* stop after count matches or no match */
***************
*** 804,809 ****
--- 827,833 ----
  *    If 'options & SEARCH_MARK': set previous context mark
  *    If 'options & SEARCH_KEEP': keep previous search pattern
  *    If 'options & SEARCH_START': accept match at curpos itself
+  *    If 'options & SEARCH_PEEK': check for typed char, cancel search
  *
  * Careful: If spats[0].off.line == TRUE and spats[0].off.off == 0 this
  * makes the movement linewise without moving the match position.
***************
*** 1046,1053 ****

       c = searchit(curwin, curbuf, &pos, dirc == '/' ? FORWARD : BACKWARD,
               searchstr, count, spats[0].off.end + (options &
!                      (SEARCH_KEEP + SEARCH_HIS + SEARCH_MSG + SEARCH_START +
!                          ((str != NULL && *str == ';') ? 0 : SEARCH_NOOF))),
               RE_LAST);
       if (dircp != NULL)
           *dircp = dirc;      /* restore second '/' or '?' for normal_cmd() */
--- 1070,1078 ----

       c = searchit(curwin, curbuf, &pos, dirc == '/' ? FORWARD : BACKWARD,
               searchstr, count, spats[0].off.end + (options &
!                      (SEARCH_KEEP + SEARCH_PEEK + SEARCH_HIS
!                       + SEARCH_MSG + SEARCH_START
!                       + ((str != NULL && *str == ';') ? 0 : SEARCH_NOOF))),
               RE_LAST);
       if (dircp != NULL)
           *dircp = dirc;      /* restore second '/' or '?' for normal_cmd() */
*** ../vim61b.004/src/vim.h     Sat Mar  9 16:17:41 2002
--- src/vim.h   Tue Mar 12 21:23:45 2002
***************
*** 680,685 ****
--- 680,686 ----
 #define SEARCH_START 0x100  /* start search without col offset */
 #define SEARCH_MARK  0x200  /* set previous context mark */
 #define SEARCH_KEEP  0x400  /* keep previous search pattern */
+ #define SEARCH_PEEK  0x800  /* peek for typed char, cancel search */

 /* Values for find_ident_under_cursor() */
 #define FIND_IDENT    1       /* find identifier (word) */
*** ../vim61b.004/src/version.c Tue Mar 12 18:04:58 2002
--- src/version.c       Tue Mar 12 22:17:44 2002
***************
*** 608,609 ****
--- 608,611 ----
 {   /* Add new patch number below this line */
+ /**/
+     5,
 /**/

--
Ten bugs in the hand is better than one as yet undetected.

///  Bram Moolenaar -- [email protected] -- http://www.moolenaar.net  \\\
///   Creator of Vim -- http://vim.sf.net -- ftp://ftp.vim.org/pub/vim   \\\
\\\           Project leader for A-A-P -- http://www.a-a-p.org           ///
\\\  Help me helping AIDS orphans in Uganda - http://iccf-holland.org  ///