xref: /vim-8.2.3635/src/search.c (revision ed37d9b3)
1 /* vi:set ts=8 sts=4 sw=4 noet:
2  *
3  * VIM - Vi IMproved	by Bram Moolenaar
4  *
5  * Do ":help uganda"  in Vim to read copying and usage conditions.
6  * Do ":help credits" in Vim to see a list of people who contributed.
7  * See README.txt for an overview of the Vim source code.
8  */
9 /*
10  * search.c: code for normal mode searching commands
11  */
12 
13 #include "vim.h"
14 
15 #ifdef FEAT_EVAL
16 static void set_vv_searchforward(void);
17 static int first_submatch(regmmatch_T *rp);
18 #endif
19 static int check_linecomment(char_u *line);
20 #ifdef FEAT_FIND_ID
21 static void show_pat_in_path(char_u *, int,
22 					 int, int, FILE *, linenr_T *, long);
23 #endif
24 static void search_stat(int dirc, pos_T *pos, int show_top_bot_msg, char_u *msgbuf, int recompute);
25 
26 /*
27  * This file contains various searching-related routines. These fall into
28  * three groups:
29  * 1. string searches (for /, ?, n, and N)
30  * 2. character searches within a single line (for f, F, t, T, etc)
31  * 3. "other" kinds of searches like the '%' command, and 'word' searches.
32  */
33 
34 /*
35  * String searches
36  *
37  * The string search functions are divided into two levels:
38  * lowest:  searchit(); uses an pos_T for starting position and found match.
39  * Highest: do_search(); uses curwin->w_cursor; calls searchit().
40  *
41  * The last search pattern is remembered for repeating the same search.
42  * This pattern is shared between the :g, :s, ? and / commands.
43  * This is in search_regcomp().
44  *
45  * The actual string matching is done using a heavily modified version of
46  * Henry Spencer's regular expression library.  See regexp.c.
47  */
48 
49 /*
50  * Two search patterns are remembered: One for the :substitute command and
51  * one for other searches.  last_idx points to the one that was used the last
52  * time.
53  */
54 static spat_T spats[2] =
55 {
56     {NULL, TRUE, FALSE, {'/', 0, 0, 0L}},	// last used search pat
57     {NULL, TRUE, FALSE, {'/', 0, 0, 0L}}	// last used substitute pat
58 };
59 
60 static int last_idx = 0;	// index in spats[] for RE_LAST
61 
62 static char_u lastc[2] = {NUL, NUL};	// last character searched for
63 static int lastcdir = FORWARD;		// last direction of character search
64 static int last_t_cmd = TRUE;		// last search t_cmd
65 static char_u	lastc_bytes[MB_MAXBYTES + 1];
66 static int	lastc_bytelen = 1;	// >1 for multi-byte char
67 
68 // copy of spats[], for keeping the search patterns while executing autocmds
69 static spat_T	    saved_spats[2];
70 # ifdef FEAT_SEARCH_EXTRA
71 static int	    saved_spats_last_idx = 0;
72 static int	    saved_spats_no_hlsearch = 0;
73 # endif
74 
75 static char_u	    *mr_pattern = NULL;	// pattern used by search_regcomp()
76 #ifdef FEAT_RIGHTLEFT
77 static int	    mr_pattern_alloced = FALSE; // mr_pattern was allocated
78 #endif
79 
80 #ifdef FEAT_FIND_ID
81 /*
82  * Type used by find_pattern_in_path() to remember which included files have
83  * been searched already.
84  */
85 typedef struct SearchedFile
86 {
87     FILE	*fp;		// File pointer
88     char_u	*name;		// Full name of file
89     linenr_T	lnum;		// Line we were up to in file
90     int		matched;	// Found a match in this file
91 } SearchedFile;
92 #endif
93 
94 /*
95  * translate search pattern for vim_regcomp()
96  *
97  * pat_save == RE_SEARCH: save pat in spats[RE_SEARCH].pat (normal search cmd)
98  * pat_save == RE_SUBST: save pat in spats[RE_SUBST].pat (:substitute command)
99  * pat_save == RE_BOTH: save pat in both patterns (:global command)
100  * pat_use  == RE_SEARCH: use previous search pattern if "pat" is NULL
101  * pat_use  == RE_SUBST: use previous substitute pattern if "pat" is NULL
102  * pat_use  == RE_LAST: use last used pattern if "pat" is NULL
103  * options & SEARCH_HIS: put search string in history
104  * options & SEARCH_KEEP: keep previous search pattern
105  *
106  * returns FAIL if failed, OK otherwise.
107  */
108     int
109 search_regcomp(
110     char_u	*pat,
111     int		pat_save,
112     int		pat_use,
113     int		options,
114     regmmatch_T	*regmatch)	// return: pattern and ignore-case flag
115 {
116     int		magic;
117     int		i;
118 
119     rc_did_emsg = FALSE;
120     magic = p_magic;
121 
122     /*
123      * If no pattern given, use a previously defined pattern.
124      */
125     if (pat == NULL || *pat == NUL)
126     {
127 	if (pat_use == RE_LAST)
128 	    i = last_idx;
129 	else
130 	    i = pat_use;
131 	if (spats[i].pat == NULL)	// pattern was never defined
132 	{
133 	    if (pat_use == RE_SUBST)
134 		emsg(_(e_nopresub));
135 	    else
136 		emsg(_(e_noprevre));
137 	    rc_did_emsg = TRUE;
138 	    return FAIL;
139 	}
140 	pat = spats[i].pat;
141 	magic = spats[i].magic;
142 	no_smartcase = spats[i].no_scs;
143     }
144     else if (options & SEARCH_HIS)	// put new pattern in history
145 	add_to_history(HIST_SEARCH, pat, TRUE, NUL);
146 
147 #ifdef FEAT_RIGHTLEFT
148     if (mr_pattern_alloced)
149     {
150 	vim_free(mr_pattern);
151 	mr_pattern_alloced = FALSE;
152     }
153 
154     if (curwin->w_p_rl && *curwin->w_p_rlc == 's')
155     {
156 	char_u *rev_pattern;
157 
158 	rev_pattern = reverse_text(pat);
159 	if (rev_pattern == NULL)
160 	    mr_pattern = pat;	    // out of memory, keep normal pattern.
161 	else
162 	{
163 	    mr_pattern = rev_pattern;
164 	    mr_pattern_alloced = TRUE;
165 	}
166     }
167     else
168 #endif
169 	mr_pattern = pat;
170 
171     /*
172      * Save the currently used pattern in the appropriate place,
173      * unless the pattern should not be remembered.
174      */
175     if (!(options & SEARCH_KEEP) && !cmdmod.keeppatterns)
176     {
177 	// search or global command
178 	if (pat_save == RE_SEARCH || pat_save == RE_BOTH)
179 	    save_re_pat(RE_SEARCH, pat, magic);
180 	// substitute or global command
181 	if (pat_save == RE_SUBST || pat_save == RE_BOTH)
182 	    save_re_pat(RE_SUBST, pat, magic);
183     }
184 
185     regmatch->rmm_ic = ignorecase(pat);
186     regmatch->rmm_maxcol = 0;
187     regmatch->regprog = vim_regcomp(pat, magic ? RE_MAGIC : 0);
188     if (regmatch->regprog == NULL)
189 	return FAIL;
190     return OK;
191 }
192 
193 /*
194  * Get search pattern used by search_regcomp().
195  */
196     char_u *
197 get_search_pat(void)
198 {
199     return mr_pattern;
200 }
201 
202 #if defined(FEAT_RIGHTLEFT) || defined(PROTO)
203 /*
204  * Reverse text into allocated memory.
205  * Returns the allocated string, NULL when out of memory.
206  */
207     char_u *
208 reverse_text(char_u *s)
209 {
210     unsigned	len;
211     unsigned	s_i, rev_i;
212     char_u	*rev;
213 
214     /*
215      * Reverse the pattern.
216      */
217     len = (unsigned)STRLEN(s);
218     rev = alloc(len + 1);
219     if (rev != NULL)
220     {
221 	rev_i = len;
222 	for (s_i = 0; s_i < len; ++s_i)
223 	{
224 	    if (has_mbyte)
225 	    {
226 		int	mb_len;
227 
228 		mb_len = (*mb_ptr2len)(s + s_i);
229 		rev_i -= mb_len;
230 		mch_memmove(rev + rev_i, s + s_i, mb_len);
231 		s_i += mb_len - 1;
232 	    }
233 	    else
234 		rev[--rev_i] = s[s_i];
235 
236 	}
237 	rev[len] = NUL;
238     }
239     return rev;
240 }
241 #endif
242 
243     void
244 save_re_pat(int idx, char_u *pat, int magic)
245 {
246     if (spats[idx].pat != pat)
247     {
248 	vim_free(spats[idx].pat);
249 	spats[idx].pat = vim_strsave(pat);
250 	spats[idx].magic = magic;
251 	spats[idx].no_scs = no_smartcase;
252 	last_idx = idx;
253 #ifdef FEAT_SEARCH_EXTRA
254 	// If 'hlsearch' set and search pat changed: need redraw.
255 	if (p_hls)
256 	    redraw_all_later(SOME_VALID);
257 	set_no_hlsearch(FALSE);
258 #endif
259     }
260 }
261 
262 /*
263  * Save the search patterns, so they can be restored later.
264  * Used before/after executing autocommands and user functions.
265  */
266 static int save_level = 0;
267 
268     void
269 save_search_patterns(void)
270 {
271     if (save_level++ == 0)
272     {
273 	saved_spats[0] = spats[0];
274 	if (spats[0].pat != NULL)
275 	    saved_spats[0].pat = vim_strsave(spats[0].pat);
276 	saved_spats[1] = spats[1];
277 	if (spats[1].pat != NULL)
278 	    saved_spats[1].pat = vim_strsave(spats[1].pat);
279 #ifdef FEAT_SEARCH_EXTRA
280 	saved_spats_last_idx = last_idx;
281 	saved_spats_no_hlsearch = no_hlsearch;
282 #endif
283     }
284 }
285 
286     void
287 restore_search_patterns(void)
288 {
289     if (--save_level == 0)
290     {
291 	vim_free(spats[0].pat);
292 	spats[0] = saved_spats[0];
293 #if defined(FEAT_EVAL)
294 	set_vv_searchforward();
295 #endif
296 	vim_free(spats[1].pat);
297 	spats[1] = saved_spats[1];
298 #ifdef FEAT_SEARCH_EXTRA
299 	last_idx = saved_spats_last_idx;
300 	set_no_hlsearch(saved_spats_no_hlsearch);
301 #endif
302     }
303 }
304 
305 #if defined(EXITFREE) || defined(PROTO)
306     void
307 free_search_patterns(void)
308 {
309     vim_free(spats[0].pat);
310     vim_free(spats[1].pat);
311 
312 # ifdef FEAT_RIGHTLEFT
313     if (mr_pattern_alloced)
314     {
315 	vim_free(mr_pattern);
316 	mr_pattern_alloced = FALSE;
317 	mr_pattern = NULL;
318     }
319 # endif
320 }
321 #endif
322 
323 #ifdef FEAT_SEARCH_EXTRA
324 // copy of spats[RE_SEARCH], for keeping the search patterns while incremental
325 // searching
326 static spat_T	    saved_last_search_spat;
327 static int	    did_save_last_search_spat = 0;
328 static int	    saved_last_idx = 0;
329 static int	    saved_no_hlsearch = 0;
330 
331 /*
332  * Save and restore the search pattern for incremental highlight search
333  * feature.
334  *
335  * It's similar to but different from save_search_patterns() and
336  * restore_search_patterns(), because the search pattern must be restored when
337  * canceling incremental searching even if it's called inside user functions.
338  */
339     void
340 save_last_search_pattern(void)
341 {
342     if (did_save_last_search_spat != 0)
343 	iemsg("did_save_last_search_spat is not zero");
344     else
345 	++did_save_last_search_spat;
346 
347     saved_last_search_spat = spats[RE_SEARCH];
348     if (spats[RE_SEARCH].pat != NULL)
349 	saved_last_search_spat.pat = vim_strsave(spats[RE_SEARCH].pat);
350     saved_last_idx = last_idx;
351     saved_no_hlsearch = no_hlsearch;
352 }
353 
354     void
355 restore_last_search_pattern(void)
356 {
357     if (did_save_last_search_spat != 1)
358     {
359 	iemsg("did_save_last_search_spat is not one");
360 	return;
361     }
362     --did_save_last_search_spat;
363 
364     vim_free(spats[RE_SEARCH].pat);
365     spats[RE_SEARCH] = saved_last_search_spat;
366     saved_last_search_spat.pat = NULL;
367 # if defined(FEAT_EVAL)
368     set_vv_searchforward();
369 # endif
370     last_idx = saved_last_idx;
371     set_no_hlsearch(saved_no_hlsearch);
372 }
373 
374     char_u *
375 last_search_pattern(void)
376 {
377     return spats[RE_SEARCH].pat;
378 }
379 #endif
380 
381 /*
382  * Return TRUE when case should be ignored for search pattern "pat".
383  * Uses the 'ignorecase' and 'smartcase' options.
384  */
385     int
386 ignorecase(char_u *pat)
387 {
388     return ignorecase_opt(pat, p_ic, p_scs);
389 }
390 
391 /*
392  * As ignorecase() put pass the "ic" and "scs" flags.
393  */
394     int
395 ignorecase_opt(char_u *pat, int ic_in, int scs)
396 {
397     int		ic = ic_in;
398 
399     if (ic && !no_smartcase && scs
400 			    && !(ctrl_x_mode_not_default() && curbuf->b_p_inf))
401 	ic = !pat_has_uppercase(pat);
402     no_smartcase = FALSE;
403 
404     return ic;
405 }
406 
407 /*
408  * Return TRUE if pattern "pat" has an uppercase character.
409  */
410     int
411 pat_has_uppercase(char_u *pat)
412 {
413     char_u *p = pat;
414 
415     while (*p != NUL)
416     {
417 	int		l;
418 
419 	if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1)
420 	{
421 	    if (enc_utf8 && utf_isupper(utf_ptr2char(p)))
422 		return TRUE;
423 	    p += l;
424 	}
425 	else if (*p == '\\')
426 	{
427 	    if (p[1] == '_' && p[2] != NUL)  // skip "\_X"
428 		p += 3;
429 	    else if (p[1] == '%' && p[2] != NUL)  // skip "\%X"
430 		p += 3;
431 	    else if (p[1] != NUL)  // skip "\X"
432 		p += 2;
433 	    else
434 		p += 1;
435 	}
436 	else if (MB_ISUPPER(*p))
437 	    return TRUE;
438 	else
439 	    ++p;
440     }
441     return FALSE;
442 }
443 
444 #if defined(FEAT_EVAL) || defined(PROTO)
445     char_u *
446 last_csearch(void)
447 {
448     return lastc_bytes;
449 }
450 
451     int
452 last_csearch_forward(void)
453 {
454     return lastcdir == FORWARD;
455 }
456 
457     int
458 last_csearch_until(void)
459 {
460     return last_t_cmd == TRUE;
461 }
462 
463     void
464 set_last_csearch(int c, char_u *s UNUSED, int len UNUSED)
465 {
466     *lastc = c;
467     lastc_bytelen = len;
468     if (len)
469 	memcpy(lastc_bytes, s, len);
470     else
471 	CLEAR_FIELD(lastc_bytes);
472 }
473 #endif
474 
475     void
476 set_csearch_direction(int cdir)
477 {
478     lastcdir = cdir;
479 }
480 
481     void
482 set_csearch_until(int t_cmd)
483 {
484     last_t_cmd = t_cmd;
485 }
486 
487     char_u *
488 last_search_pat(void)
489 {
490     return spats[last_idx].pat;
491 }
492 
493 /*
494  * Reset search direction to forward.  For "gd" and "gD" commands.
495  */
496     void
497 reset_search_dir(void)
498 {
499     spats[0].off.dir = '/';
500 #if defined(FEAT_EVAL)
501     set_vv_searchforward();
502 #endif
503 }
504 
505 #if defined(FEAT_EVAL) || defined(FEAT_VIMINFO)
506 /*
507  * Set the last search pattern.  For ":let @/ =" and viminfo.
508  * Also set the saved search pattern, so that this works in an autocommand.
509  */
510     void
511 set_last_search_pat(
512     char_u	*s,
513     int		idx,
514     int		magic,
515     int		setlast)
516 {
517     vim_free(spats[idx].pat);
518     // An empty string means that nothing should be matched.
519     if (*s == NUL)
520 	spats[idx].pat = NULL;
521     else
522 	spats[idx].pat = vim_strsave(s);
523     spats[idx].magic = magic;
524     spats[idx].no_scs = FALSE;
525     spats[idx].off.dir = '/';
526 #if defined(FEAT_EVAL)
527     set_vv_searchforward();
528 #endif
529     spats[idx].off.line = FALSE;
530     spats[idx].off.end = FALSE;
531     spats[idx].off.off = 0;
532     if (setlast)
533 	last_idx = idx;
534     if (save_level)
535     {
536 	vim_free(saved_spats[idx].pat);
537 	saved_spats[idx] = spats[0];
538 	if (spats[idx].pat == NULL)
539 	    saved_spats[idx].pat = NULL;
540 	else
541 	    saved_spats[idx].pat = vim_strsave(spats[idx].pat);
542 # ifdef FEAT_SEARCH_EXTRA
543 	saved_spats_last_idx = last_idx;
544 # endif
545     }
546 # ifdef FEAT_SEARCH_EXTRA
547     // If 'hlsearch' set and search pat changed: need redraw.
548     if (p_hls && idx == last_idx && !no_hlsearch)
549 	redraw_all_later(SOME_VALID);
550 # endif
551 }
552 #endif
553 
554 #ifdef FEAT_SEARCH_EXTRA
555 /*
556  * Get a regexp program for the last used search pattern.
557  * This is used for highlighting all matches in a window.
558  * Values returned in regmatch->regprog and regmatch->rmm_ic.
559  */
560     void
561 last_pat_prog(regmmatch_T *regmatch)
562 {
563     if (spats[last_idx].pat == NULL)
564     {
565 	regmatch->regprog = NULL;
566 	return;
567     }
568     ++emsg_off;		// So it doesn't beep if bad expr
569     (void)search_regcomp((char_u *)"", 0, last_idx, SEARCH_KEEP, regmatch);
570     --emsg_off;
571 }
572 #endif
573 
574 /*
575  * Lowest level search function.
576  * Search for 'count'th occurrence of pattern "pat" in direction "dir".
577  * Start at position "pos" and return the found position in "pos".
578  *
579  * if (options & SEARCH_MSG) == 0 don't give any messages
580  * if (options & SEARCH_MSG) == SEARCH_NFMSG don't give 'notfound' messages
581  * if (options & SEARCH_MSG) == SEARCH_MSG give all messages
582  * if (options & SEARCH_HIS) put search pattern in history
583  * if (options & SEARCH_END) return position at end of match
584  * if (options & SEARCH_START) accept match at pos itself
585  * if (options & SEARCH_KEEP) keep previous search pattern
586  * if (options & SEARCH_FOLD) match only once in a closed fold
587  * if (options & SEARCH_PEEK) check for typed char, cancel search
588  * if (options & SEARCH_COL) start at pos->col instead of zero
589  *
590  * Return FAIL (zero) for failure, non-zero for success.
591  * When FEAT_EVAL is defined, returns the index of the first matching
592  * subpattern plus one; one if there was none.
593  */
594     int
595 searchit(
596     win_T	*win,		// window to search in; can be NULL for a
597 				// buffer without a window!
598     buf_T	*buf,
599     pos_T	*pos,
600     pos_T	*end_pos,	// set to end of the match, unless NULL
601     int		dir,
602     char_u	*pat,
603     long	count,
604     int		options,
605     int		pat_use,	// which pattern to use when "pat" is empty
606     searchit_arg_T *extra_arg)	// optional extra arguments, can be NULL
607 {
608     int		found;
609     linenr_T	lnum;		// no init to shut up Apollo cc
610     colnr_T	col;
611     regmmatch_T	regmatch;
612     char_u	*ptr;
613     colnr_T	matchcol;
614     lpos_T	endpos;
615     lpos_T	matchpos;
616     int		loop;
617     pos_T	start_pos;
618     int		at_first_line;
619     int		extra_col;
620     int		start_char_len;
621     int		match_ok;
622     long	nmatched;
623     int		submatch = 0;
624     int		first_match = TRUE;
625     int		called_emsg_before = called_emsg;
626 #ifdef FEAT_SEARCH_EXTRA
627     int		break_loop = FALSE;
628 #endif
629     linenr_T	stop_lnum = 0;	// stop after this line number when != 0
630 #ifdef FEAT_RELTIME
631     proftime_T	*tm = NULL;	// timeout limit or NULL
632     int		*timed_out = NULL;  // set when timed out or NULL
633 #endif
634 
635     if (extra_arg != NULL)
636     {
637 	stop_lnum = extra_arg->sa_stop_lnum;
638 #ifdef FEAT_RELTIME
639 	tm = extra_arg->sa_tm;
640 	timed_out = &extra_arg->sa_timed_out;
641 #endif
642     }
643 
644     if (search_regcomp(pat, RE_SEARCH, pat_use,
645 		   (options & (SEARCH_HIS + SEARCH_KEEP)), &regmatch) == FAIL)
646     {
647 	if ((options & SEARCH_MSG) && !rc_did_emsg)
648 	    semsg(_("E383: Invalid search string: %s"), mr_pattern);
649 	return FAIL;
650     }
651 
652     /*
653      * find the string
654      */
655     do	// loop for count
656     {
657 	// When not accepting a match at the start position set "extra_col" to
658 	// a non-zero value.  Don't do that when starting at MAXCOL, since
659 	// MAXCOL + 1 is zero.
660 	if (pos->col == MAXCOL)
661 	    start_char_len = 0;
662 	// Watch out for the "col" being MAXCOL - 2, used in a closed fold.
663 	else if (has_mbyte
664 		    && pos->lnum >= 1 && pos->lnum <= buf->b_ml.ml_line_count
665 						    && pos->col < MAXCOL - 2)
666 	{
667 	    ptr = ml_get_buf(buf, pos->lnum, FALSE);
668 	    if ((int)STRLEN(ptr) <= pos->col)
669 		start_char_len = 1;
670 	    else
671 		start_char_len = (*mb_ptr2len)(ptr + pos->col);
672 	}
673 	else
674 	    start_char_len = 1;
675 	if (dir == FORWARD)
676 	{
677 	    if (options & SEARCH_START)
678 		extra_col = 0;
679 	    else
680 		extra_col = start_char_len;
681 	}
682 	else
683 	{
684 	    if (options & SEARCH_START)
685 		extra_col = start_char_len;
686 	    else
687 		extra_col = 0;
688 	}
689 
690 	start_pos = *pos;	// remember start pos for detecting no match
691 	found = 0;		// default: not found
692 	at_first_line = TRUE;	// default: start in first line
693 	if (pos->lnum == 0)	// correct lnum for when starting in line 0
694 	{
695 	    pos->lnum = 1;
696 	    pos->col = 0;
697 	    at_first_line = FALSE;  // not in first line now
698 	}
699 
700 	/*
701 	 * Start searching in current line, unless searching backwards and
702 	 * we're in column 0.
703 	 * If we are searching backwards, in column 0, and not including the
704 	 * current position, gain some efficiency by skipping back a line.
705 	 * Otherwise begin the search in the current line.
706 	 */
707 	if (dir == BACKWARD && start_pos.col == 0
708 					     && (options & SEARCH_START) == 0)
709 	{
710 	    lnum = pos->lnum - 1;
711 	    at_first_line = FALSE;
712 	}
713 	else
714 	    lnum = pos->lnum;
715 
716 	for (loop = 0; loop <= 1; ++loop)   // loop twice if 'wrapscan' set
717 	{
718 	    for ( ; lnum > 0 && lnum <= buf->b_ml.ml_line_count;
719 					   lnum += dir, at_first_line = FALSE)
720 	    {
721 		// Stop after checking "stop_lnum", if it's set.
722 		if (stop_lnum != 0 && (dir == FORWARD
723 				       ? lnum > stop_lnum : lnum < stop_lnum))
724 		    break;
725 #ifdef FEAT_RELTIME
726 		// Stop after passing the "tm" time limit.
727 		if (tm != NULL && profile_passed_limit(tm))
728 		    break;
729 #endif
730 
731 		/*
732 		 * Look for a match somewhere in line "lnum".
733 		 */
734 		col = at_first_line && (options & SEARCH_COL) ? pos->col
735 								 : (colnr_T)0;
736 		nmatched = vim_regexec_multi(&regmatch, win, buf,
737 					     lnum, col,
738 #ifdef FEAT_RELTIME
739 					     tm, timed_out
740 #else
741 					     NULL, NULL
742 #endif
743 						      );
744 		// Abort searching on an error (e.g., out of stack).
745 		if (called_emsg > called_emsg_before
746 #ifdef FEAT_RELTIME
747 			|| (timed_out != NULL && *timed_out)
748 #endif
749 			)
750 		    break;
751 		if (nmatched > 0)
752 		{
753 		    // match may actually be in another line when using \zs
754 		    matchpos = regmatch.startpos[0];
755 		    endpos = regmatch.endpos[0];
756 #ifdef FEAT_EVAL
757 		    submatch = first_submatch(&regmatch);
758 #endif
759 		    // "lnum" may be past end of buffer for "\n\zs".
760 		    if (lnum + matchpos.lnum > buf->b_ml.ml_line_count)
761 			ptr = (char_u *)"";
762 		    else
763 			ptr = ml_get_buf(buf, lnum + matchpos.lnum, FALSE);
764 
765 		    /*
766 		     * Forward search in the first line: match should be after
767 		     * the start position. If not, continue at the end of the
768 		     * match (this is vi compatible) or on the next char.
769 		     */
770 		    if (dir == FORWARD && at_first_line)
771 		    {
772 			match_ok = TRUE;
773 			/*
774 			 * When the match starts in a next line it's certainly
775 			 * past the start position.
776 			 * When match lands on a NUL the cursor will be put
777 			 * one back afterwards, compare with that position,
778 			 * otherwise "/$" will get stuck on end of line.
779 			 */
780 			while (matchpos.lnum == 0
781 				&& ((options & SEARCH_END) && first_match
782 				    ?  (nmatched == 1
783 					&& (int)endpos.col - 1
784 					     < (int)start_pos.col + extra_col)
785 				    : ((int)matchpos.col
786 						  - (ptr[matchpos.col] == NUL)
787 					    < (int)start_pos.col + extra_col)))
788 			{
789 			    /*
790 			     * If vi-compatible searching, continue at the end
791 			     * of the match, otherwise continue one position
792 			     * forward.
793 			     */
794 			    if (vim_strchr(p_cpo, CPO_SEARCH) != NULL)
795 			    {
796 				if (nmatched > 1)
797 				{
798 				    // end is in next line, thus no match in
799 				    // this line
800 				    match_ok = FALSE;
801 				    break;
802 				}
803 				matchcol = endpos.col;
804 				// for empty match: advance one char
805 				if (matchcol == matchpos.col
806 						      && ptr[matchcol] != NUL)
807 				{
808 				    if (has_mbyte)
809 					matchcol +=
810 					  (*mb_ptr2len)(ptr + matchcol);
811 				    else
812 					++matchcol;
813 				}
814 			    }
815 			    else
816 			    {
817 				matchcol = matchpos.col;
818 				if (ptr[matchcol] != NUL)
819 				{
820 				    if (has_mbyte)
821 					matchcol += (*mb_ptr2len)(ptr
822 								  + matchcol);
823 				    else
824 					++matchcol;
825 				}
826 			    }
827 			    if (matchcol == 0 && (options & SEARCH_START))
828 				break;
829 			    if (ptr[matchcol] == NUL
830 				    || (nmatched = vim_regexec_multi(&regmatch,
831 					      win, buf, lnum + matchpos.lnum,
832 					      matchcol,
833 #ifdef FEAT_RELTIME
834 					      tm, timed_out
835 #else
836 					      NULL, NULL
837 #endif
838 					      )) == 0)
839 			    {
840 				match_ok = FALSE;
841 				break;
842 			    }
843 			    matchpos = regmatch.startpos[0];
844 			    endpos = regmatch.endpos[0];
845 # ifdef FEAT_EVAL
846 			    submatch = first_submatch(&regmatch);
847 # endif
848 
849 			    // Need to get the line pointer again, a
850 			    // multi-line search may have made it invalid.
851 			    ptr = ml_get_buf(buf, lnum + matchpos.lnum, FALSE);
852 			}
853 			if (!match_ok)
854 			    continue;
855 		    }
856 		    if (dir == BACKWARD)
857 		    {
858 			/*
859 			 * Now, if there are multiple matches on this line,
860 			 * we have to get the last one. Or the last one before
861 			 * the cursor, if we're on that line.
862 			 * When putting the new cursor at the end, compare
863 			 * relative to the end of the match.
864 			 */
865 			match_ok = FALSE;
866 			for (;;)
867 			{
868 			    // Remember a position that is before the start
869 			    // position, we use it if it's the last match in
870 			    // the line.  Always accept a position after
871 			    // wrapping around.
872 			    if (loop
873 				|| ((options & SEARCH_END)
874 				    ? (lnum + regmatch.endpos[0].lnum
875 							      < start_pos.lnum
876 					|| (lnum + regmatch.endpos[0].lnum
877 							     == start_pos.lnum
878 					     && (int)regmatch.endpos[0].col - 1
879 							< (int)start_pos.col
880 								+ extra_col))
881 				    : (lnum + regmatch.startpos[0].lnum
882 							      < start_pos.lnum
883 					|| (lnum + regmatch.startpos[0].lnum
884 							     == start_pos.lnum
885 					     && (int)regmatch.startpos[0].col
886 						      < (int)start_pos.col
887 							      + extra_col))))
888 			    {
889 				match_ok = TRUE;
890 				matchpos = regmatch.startpos[0];
891 				endpos = regmatch.endpos[0];
892 # ifdef FEAT_EVAL
893 				submatch = first_submatch(&regmatch);
894 # endif
895 			    }
896 			    else
897 				break;
898 
899 			    /*
900 			     * We found a valid match, now check if there is
901 			     * another one after it.
902 			     * If vi-compatible searching, continue at the end
903 			     * of the match, otherwise continue one position
904 			     * forward.
905 			     */
906 			    if (vim_strchr(p_cpo, CPO_SEARCH) != NULL)
907 			    {
908 				if (nmatched > 1)
909 				    break;
910 				matchcol = endpos.col;
911 				// for empty match: advance one char
912 				if (matchcol == matchpos.col
913 						      && ptr[matchcol] != NUL)
914 				{
915 				    if (has_mbyte)
916 					matchcol +=
917 					  (*mb_ptr2len)(ptr + matchcol);
918 				    else
919 					++matchcol;
920 				}
921 			    }
922 			    else
923 			    {
924 				// Stop when the match is in a next line.
925 				if (matchpos.lnum > 0)
926 				    break;
927 				matchcol = matchpos.col;
928 				if (ptr[matchcol] != NUL)
929 				{
930 				    if (has_mbyte)
931 					matchcol +=
932 					  (*mb_ptr2len)(ptr + matchcol);
933 				    else
934 					++matchcol;
935 				}
936 			    }
937 			    if (ptr[matchcol] == NUL
938 				    || (nmatched = vim_regexec_multi(&regmatch,
939 					      win, buf, lnum + matchpos.lnum,
940 					      matchcol,
941 #ifdef FEAT_RELTIME
942 					      tm, timed_out
943 #else
944 					      NULL, NULL
945 #endif
946 					    )) == 0)
947 			    {
948 #ifdef FEAT_RELTIME
949 				// If the search timed out, we did find a match
950 				// but it might be the wrong one, so that's not
951 				// OK.
952 				if (timed_out != NULL && *timed_out)
953 				    match_ok = FALSE;
954 #endif
955 				break;
956 			    }
957 
958 			    // Need to get the line pointer again, a
959 			    // multi-line search may have made it invalid.
960 			    ptr = ml_get_buf(buf, lnum + matchpos.lnum, FALSE);
961 			}
962 
963 			/*
964 			 * If there is only a match after the cursor, skip
965 			 * this match.
966 			 */
967 			if (!match_ok)
968 			    continue;
969 		    }
970 
971 		    // With the SEARCH_END option move to the last character
972 		    // of the match.  Don't do it for an empty match, end
973 		    // should be same as start then.
974 		    if ((options & SEARCH_END) && !(options & SEARCH_NOOF)
975 			    && !(matchpos.lnum == endpos.lnum
976 				&& matchpos.col == endpos.col))
977 		    {
978 			// For a match in the first column, set the position
979 			// on the NUL in the previous line.
980 			pos->lnum = lnum + endpos.lnum;
981 			pos->col = endpos.col;
982 			if (endpos.col == 0)
983 			{
984 			    if (pos->lnum > 1)  // just in case
985 			    {
986 				--pos->lnum;
987 				pos->col = (colnr_T)STRLEN(ml_get_buf(buf,
988 							   pos->lnum, FALSE));
989 			    }
990 			}
991 			else
992 			{
993 			    --pos->col;
994 			    if (has_mbyte
995 				    && pos->lnum <= buf->b_ml.ml_line_count)
996 			    {
997 				ptr = ml_get_buf(buf, pos->lnum, FALSE);
998 				pos->col -= (*mb_head_off)(ptr, ptr + pos->col);
999 			    }
1000 			}
1001 			if (end_pos != NULL)
1002 			{
1003 			    end_pos->lnum = lnum + matchpos.lnum;
1004 			    end_pos->col = matchpos.col;
1005 			}
1006 		    }
1007 		    else
1008 		    {
1009 			pos->lnum = lnum + matchpos.lnum;
1010 			pos->col = matchpos.col;
1011 			if (end_pos != NULL)
1012 			{
1013 			    end_pos->lnum = lnum + endpos.lnum;
1014 			    end_pos->col = endpos.col;
1015 			}
1016 		    }
1017 		    pos->coladd = 0;
1018 		    if (end_pos != NULL)
1019 			end_pos->coladd = 0;
1020 		    found = 1;
1021 		    first_match = FALSE;
1022 
1023 		    // Set variables used for 'incsearch' highlighting.
1024 		    search_match_lines = endpos.lnum - matchpos.lnum;
1025 		    search_match_endcol = endpos.col;
1026 		    break;
1027 		}
1028 		line_breakcheck();	// stop if ctrl-C typed
1029 		if (got_int)
1030 		    break;
1031 
1032 #ifdef FEAT_SEARCH_EXTRA
1033 		// Cancel searching if a character was typed.  Used for
1034 		// 'incsearch'.  Don't check too often, that would slowdown
1035 		// searching too much.
1036 		if ((options & SEARCH_PEEK)
1037 			&& ((lnum - pos->lnum) & 0x3f) == 0
1038 			&& char_avail())
1039 		{
1040 		    break_loop = TRUE;
1041 		    break;
1042 		}
1043 #endif
1044 
1045 		if (loop && lnum == start_pos.lnum)
1046 		    break;	    // if second loop, stop where started
1047 	    }
1048 	    at_first_line = FALSE;
1049 
1050 	    /*
1051 	     * Stop the search if wrapscan isn't set, "stop_lnum" is
1052 	     * specified, after an interrupt, after a match and after looping
1053 	     * twice.
1054 	     */
1055 	    if (!p_ws || stop_lnum != 0 || got_int
1056 					    || called_emsg > called_emsg_before
1057 #ifdef FEAT_RELTIME
1058 				|| (timed_out != NULL && *timed_out)
1059 #endif
1060 #ifdef FEAT_SEARCH_EXTRA
1061 				|| break_loop
1062 #endif
1063 				|| found || loop)
1064 		break;
1065 
1066 	    /*
1067 	     * If 'wrapscan' is set we continue at the other end of the file.
1068 	     * If 'shortmess' does not contain 's', we give a message.
1069 	     * This message is also remembered in keep_msg for when the screen
1070 	     * is redrawn. The keep_msg is cleared whenever another message is
1071 	     * written.
1072 	     */
1073 	    if (dir == BACKWARD)    // start second loop at the other end
1074 		lnum = buf->b_ml.ml_line_count;
1075 	    else
1076 		lnum = 1;
1077 	    if (!shortmess(SHM_SEARCH) && (options & SEARCH_MSG))
1078 		give_warning((char_u *)_(dir == BACKWARD
1079 					  ? top_bot_msg : bot_top_msg), TRUE);
1080 	    if (extra_arg != NULL)
1081 		extra_arg->sa_wrapped = TRUE;
1082 	}
1083 	if (got_int || called_emsg > called_emsg_before
1084 #ifdef FEAT_RELTIME
1085 		|| (timed_out != NULL && *timed_out)
1086 #endif
1087 #ifdef FEAT_SEARCH_EXTRA
1088 		|| break_loop
1089 #endif
1090 		)
1091 	    break;
1092     }
1093     while (--count > 0 && found);   // stop after count matches or no match
1094 
1095     vim_regfree(regmatch.regprog);
1096 
1097     if (!found)		    // did not find it
1098     {
1099 	if (got_int)
1100 	    emsg(_(e_interr));
1101 	else if ((options & SEARCH_MSG) == SEARCH_MSG)
1102 	{
1103 	    if (p_ws)
1104 		semsg(_(e_patnotf2), mr_pattern);
1105 	    else if (lnum == 0)
1106 		semsg(_("E384: search hit TOP without match for: %s"),
1107 								  mr_pattern);
1108 	    else
1109 		semsg(_("E385: search hit BOTTOM without match for: %s"),
1110 								  mr_pattern);
1111 	}
1112 	return FAIL;
1113     }
1114 
1115     // A pattern like "\n\zs" may go past the last line.
1116     if (pos->lnum > buf->b_ml.ml_line_count)
1117     {
1118 	pos->lnum = buf->b_ml.ml_line_count;
1119 	pos->col = (int)STRLEN(ml_get_buf(buf, pos->lnum, FALSE));
1120 	if (pos->col > 0)
1121 	    --pos->col;
1122     }
1123 
1124     return submatch + 1;
1125 }
1126 
1127 #ifdef FEAT_EVAL
1128     void
1129 set_search_direction(int cdir)
1130 {
1131     spats[0].off.dir = cdir;
1132 }
1133 
1134     static void
1135 set_vv_searchforward(void)
1136 {
1137     set_vim_var_nr(VV_SEARCHFORWARD, (long)(spats[0].off.dir == '/'));
1138 }
1139 
1140 /*
1141  * Return the number of the first subpat that matched.
1142  * Return zero if none of them matched.
1143  */
1144     static int
1145 first_submatch(regmmatch_T *rp)
1146 {
1147     int		submatch;
1148 
1149     for (submatch = 1; ; ++submatch)
1150     {
1151 	if (rp->startpos[submatch].lnum >= 0)
1152 	    break;
1153 	if (submatch == 9)
1154 	{
1155 	    submatch = 0;
1156 	    break;
1157 	}
1158     }
1159     return submatch;
1160 }
1161 #endif
1162 
1163 /*
1164  * Highest level string search function.
1165  * Search for the 'count'th occurrence of pattern 'pat' in direction 'dirc'
1166  *		  If 'dirc' is 0: use previous dir.
1167  *    If 'pat' is NULL or empty : use previous string.
1168  *    If 'options & SEARCH_REV' : go in reverse of previous dir.
1169  *    If 'options & SEARCH_ECHO': echo the search command and handle options
1170  *    If 'options & SEARCH_MSG' : may give error message
1171  *    If 'options & SEARCH_OPT' : interpret optional flags
1172  *    If 'options & SEARCH_HIS' : put search pattern in history
1173  *    If 'options & SEARCH_NOOF': don't add offset to position
1174  *    If 'options & SEARCH_MARK': set previous context mark
1175  *    If 'options & SEARCH_KEEP': keep previous search pattern
1176  *    If 'options & SEARCH_START': accept match at curpos itself
1177  *    If 'options & SEARCH_PEEK': check for typed char, cancel search
1178  *
1179  * Careful: If spats[0].off.line == TRUE and spats[0].off.off == 0 this
1180  * makes the movement linewise without moving the match position.
1181  *
1182  * Return 0 for failure, 1 for found, 2 for found and line offset added.
1183  */
1184     int
1185 do_search(
1186     oparg_T	    *oap,	// can be NULL
1187     int		    dirc,	// '/' or '?'
1188     int		    search_delim, // the delimiter for the search, e.g. '%' in s%regex%replacement%
1189     char_u	    *pat,
1190     long	    count,
1191     int		    options,
1192     searchit_arg_T  *sia)	// optional arguments or NULL
1193 {
1194     pos_T	    pos;	// position of the last match
1195     char_u	    *searchstr;
1196     soffset_T	    old_off;
1197     int		    retval;	// Return value
1198     char_u	    *p;
1199     long	    c;
1200     char_u	    *dircp;
1201     char_u	    *strcopy = NULL;
1202     char_u	    *ps;
1203     char_u	    *msgbuf = NULL;
1204     size_t	    len;
1205     int		    has_offset = FALSE;
1206 #define SEARCH_STAT_BUF_LEN 12
1207 
1208     /*
1209      * A line offset is not remembered, this is vi compatible.
1210      */
1211     if (spats[0].off.line && vim_strchr(p_cpo, CPO_LINEOFF) != NULL)
1212     {
1213 	spats[0].off.line = FALSE;
1214 	spats[0].off.off = 0;
1215     }
1216 
1217     /*
1218      * Save the values for when (options & SEARCH_KEEP) is used.
1219      * (there is no "if ()" around this because gcc wants them initialized)
1220      */
1221     old_off = spats[0].off;
1222 
1223     pos = curwin->w_cursor;	// start searching at the cursor position
1224 
1225     /*
1226      * Find out the direction of the search.
1227      */
1228     if (dirc == 0)
1229 	dirc = spats[0].off.dir;
1230     else
1231     {
1232 	spats[0].off.dir = dirc;
1233 #if defined(FEAT_EVAL)
1234 	set_vv_searchforward();
1235 #endif
1236     }
1237     if (options & SEARCH_REV)
1238     {
1239 #ifdef MSWIN
1240 	// There is a bug in the Visual C++ 2.2 compiler which means that
1241 	// dirc always ends up being '/'
1242 	dirc = (dirc == '/')  ?  '?'  :  '/';
1243 #else
1244 	if (dirc == '/')
1245 	    dirc = '?';
1246 	else
1247 	    dirc = '/';
1248 #endif
1249     }
1250 
1251 #ifdef FEAT_FOLDING
1252     // If the cursor is in a closed fold, don't find another match in the same
1253     // fold.
1254     if (dirc == '/')
1255     {
1256 	if (hasFolding(pos.lnum, NULL, &pos.lnum))
1257 	    pos.col = MAXCOL - 2;	// avoid overflow when adding 1
1258     }
1259     else
1260     {
1261 	if (hasFolding(pos.lnum, &pos.lnum, NULL))
1262 	    pos.col = 0;
1263     }
1264 #endif
1265 
1266 #ifdef FEAT_SEARCH_EXTRA
1267     /*
1268      * Turn 'hlsearch' highlighting back on.
1269      */
1270     if (no_hlsearch && !(options & SEARCH_KEEP))
1271     {
1272 	redraw_all_later(SOME_VALID);
1273 	set_no_hlsearch(FALSE);
1274     }
1275 #endif
1276 
1277     /*
1278      * Repeat the search when pattern followed by ';', e.g. "/foo/;?bar".
1279      */
1280     for (;;)
1281     {
1282 	int		show_top_bot_msg = FALSE;
1283 
1284 	searchstr = pat;
1285 	dircp = NULL;
1286 					    // use previous pattern
1287 	if (pat == NULL || *pat == NUL || *pat == search_delim)
1288 	{
1289 	    if (spats[RE_SEARCH].pat == NULL)	    // no previous pattern
1290 	    {
1291 		searchstr = spats[RE_SUBST].pat;
1292 		if (searchstr == NULL)
1293 		{
1294 		    emsg(_(e_noprevre));
1295 		    retval = 0;
1296 		    goto end_do_search;
1297 		}
1298 	    }
1299 	    else
1300 	    {
1301 		// make search_regcomp() use spats[RE_SEARCH].pat
1302 		searchstr = (char_u *)"";
1303 	    }
1304 	}
1305 
1306 	if (pat != NULL && *pat != NUL)	// look for (new) offset
1307 	{
1308 	    /*
1309 	     * Find end of regular expression.
1310 	     * If there is a matching '/' or '?', toss it.
1311 	     */
1312 	    ps = strcopy;
1313 	    p = skip_regexp_ex(pat, search_delim, (int)p_magic, &strcopy, NULL);
1314 	    if (strcopy != ps)
1315 	    {
1316 		// made a copy of "pat" to change "\?" to "?"
1317 		searchcmdlen += (int)(STRLEN(pat) - STRLEN(strcopy));
1318 		pat = strcopy;
1319 		searchstr = strcopy;
1320 	    }
1321 	    if (*p == search_delim)
1322 	    {
1323 		dircp = p;	// remember where we put the NUL
1324 		*p++ = NUL;
1325 	    }
1326 	    spats[0].off.line = FALSE;
1327 	    spats[0].off.end = FALSE;
1328 	    spats[0].off.off = 0;
1329 	    /*
1330 	     * Check for a line offset or a character offset.
1331 	     * For get_address (echo off) we don't check for a character
1332 	     * offset, because it is meaningless and the 's' could be a
1333 	     * substitute command.
1334 	     */
1335 	    if (*p == '+' || *p == '-' || VIM_ISDIGIT(*p))
1336 		spats[0].off.line = TRUE;
1337 	    else if ((options & SEARCH_OPT) &&
1338 					(*p == 'e' || *p == 's' || *p == 'b'))
1339 	    {
1340 		if (*p == 'e')		// end
1341 		    spats[0].off.end = SEARCH_END;
1342 		++p;
1343 	    }
1344 	    if (VIM_ISDIGIT(*p) || *p == '+' || *p == '-')  // got an offset
1345 	    {
1346 					    // 'nr' or '+nr' or '-nr'
1347 		if (VIM_ISDIGIT(*p) || VIM_ISDIGIT(*(p + 1)))
1348 		    spats[0].off.off = atol((char *)p);
1349 		else if (*p == '-')	    // single '-'
1350 		    spats[0].off.off = -1;
1351 		else			    // single '+'
1352 		    spats[0].off.off = 1;
1353 		++p;
1354 		while (VIM_ISDIGIT(*p))	    // skip number
1355 		    ++p;
1356 	    }
1357 
1358 	    // compute length of search command for get_address()
1359 	    searchcmdlen += (int)(p - pat);
1360 
1361 	    pat = p;			    // put pat after search command
1362 	}
1363 
1364 	if ((options & SEARCH_ECHO) && messaging() &&
1365 		!msg_silent &&
1366 		(!cmd_silent || !shortmess(SHM_SEARCHCOUNT)))
1367 	{
1368 	    char_u	*trunc;
1369 	    char_u	off_buf[40];
1370 	    size_t	off_len = 0;
1371 
1372 	    // Compute msg_row early.
1373 	    msg_start();
1374 
1375 	    // Get the offset, so we know how long it is.
1376 	    if (!cmd_silent &&
1377 		    (spats[0].off.line || spats[0].off.end || spats[0].off.off))
1378 	    {
1379 		p = off_buf;
1380 		*p++ = dirc;
1381 		if (spats[0].off.end)
1382 		    *p++ = 'e';
1383 		else if (!spats[0].off.line)
1384 		    *p++ = 's';
1385 		if (spats[0].off.off > 0 || spats[0].off.line)
1386 		    *p++ = '+';
1387 		*p = NUL;
1388 		if (spats[0].off.off != 0 || spats[0].off.line)
1389 		    sprintf((char *)p, "%ld", spats[0].off.off);
1390 		off_len = STRLEN(off_buf);
1391 	    }
1392 
1393 	    if (*searchstr == NUL)
1394 		p = spats[0].pat;
1395 	    else
1396 		p = searchstr;
1397 
1398 	    if (!shortmess(SHM_SEARCHCOUNT) || cmd_silent)
1399 	    {
1400 		// Reserve enough space for the search pattern + offset +
1401 		// search stat.  Use all the space available, so that the
1402 		// search state is right aligned.  If there is not enough space
1403 		// msg_strtrunc() will shorten in the middle.
1404 		if (msg_scrolled != 0 && !cmd_silent)
1405 		    // Use all the columns.
1406 		    len = (int)(Rows - msg_row) * Columns - 1;
1407 		else
1408 		    // Use up to 'showcmd' column.
1409 		    len = (int)(Rows - msg_row - 1) * Columns + sc_col - 1;
1410 		if (len < STRLEN(p) + off_len + SEARCH_STAT_BUF_LEN + 3)
1411 		    len = STRLEN(p) + off_len + SEARCH_STAT_BUF_LEN + 3;
1412 	    }
1413 	    else
1414 		// Reserve enough space for the search pattern + offset.
1415 		len = STRLEN(p) + off_len + 3;
1416 
1417 	    vim_free(msgbuf);
1418 	    msgbuf = alloc(len);
1419 	    if (msgbuf != NULL)
1420 	    {
1421 		vim_memset(msgbuf, ' ', len);
1422 		msgbuf[len - 1] = NUL;
1423 		// do not fill the msgbuf buffer, if cmd_silent is set, leave it
1424 		// empty for the search_stat feature.
1425 		if (!cmd_silent)
1426 		{
1427 		    msgbuf[0] = dirc;
1428 
1429 		    if (enc_utf8 && utf_iscomposing(utf_ptr2char(p)))
1430 		    {
1431 			// Use a space to draw the composing char on.
1432 			msgbuf[1] = ' ';
1433 			mch_memmove(msgbuf + 2, p, STRLEN(p));
1434 		    }
1435 		    else
1436 			mch_memmove(msgbuf + 1, p, STRLEN(p));
1437 		    if (off_len > 0)
1438 			mch_memmove(msgbuf + STRLEN(p) + 1, off_buf, off_len);
1439 
1440 		    trunc = msg_strtrunc(msgbuf, TRUE);
1441 		    if (trunc != NULL)
1442 		    {
1443 			vim_free(msgbuf);
1444 			msgbuf = trunc;
1445 		    }
1446 
1447     #ifdef FEAT_RIGHTLEFT
1448 		    // The search pattern could be shown on the right in rightleft
1449 		    // mode, but the 'ruler' and 'showcmd' area use it too, thus
1450 		    // it would be blanked out again very soon.  Show it on the
1451 		    // left, but do reverse the text.
1452 		    if (curwin->w_p_rl && *curwin->w_p_rlc == 's')
1453 		    {
1454 			char_u *r;
1455 			size_t pat_len;
1456 
1457 			r = reverse_text(msgbuf);
1458 			if (r != NULL)
1459 			{
1460 			    vim_free(msgbuf);
1461 			    msgbuf = r;
1462 			    // move reversed text to beginning of buffer
1463 			    while (*r != NUL && *r == ' ')
1464 				r++;
1465 			    pat_len = msgbuf + STRLEN(msgbuf) - r;
1466 			    mch_memmove(msgbuf, r, pat_len);
1467 			    // overwrite old text
1468 			    if ((size_t)(r - msgbuf) >= pat_len)
1469 				vim_memset(r, ' ', pat_len);
1470 			    else
1471 				vim_memset(msgbuf + pat_len, ' ', r - msgbuf);
1472 			}
1473 		    }
1474     #endif
1475 		    msg_outtrans(msgbuf);
1476 		    msg_clr_eos();
1477 		    msg_check();
1478 
1479 		    gotocmdline(FALSE);
1480 		    out_flush();
1481 		    msg_nowait = TRUE;	    // don't wait for this message
1482 		}
1483 	    }
1484 	}
1485 
1486 	/*
1487 	 * If there is a character offset, subtract it from the current
1488 	 * position, so we don't get stuck at "?pat?e+2" or "/pat/s-2".
1489 	 * Skip this if pos.col is near MAXCOL (closed fold).
1490 	 * This is not done for a line offset, because then we would not be vi
1491 	 * compatible.
1492 	 */
1493 	if (!spats[0].off.line && spats[0].off.off && pos.col < MAXCOL - 2)
1494 	{
1495 	    if (spats[0].off.off > 0)
1496 	    {
1497 		for (c = spats[0].off.off; c; --c)
1498 		    if (decl(&pos) == -1)
1499 			break;
1500 		if (c)			// at start of buffer
1501 		{
1502 		    pos.lnum = 0;	// allow lnum == 0 here
1503 		    pos.col = MAXCOL;
1504 		}
1505 	    }
1506 	    else
1507 	    {
1508 		for (c = spats[0].off.off; c; ++c)
1509 		    if (incl(&pos) == -1)
1510 			break;
1511 		if (c)			// at end of buffer
1512 		{
1513 		    pos.lnum = curbuf->b_ml.ml_line_count + 1;
1514 		    pos.col = 0;
1515 		}
1516 	    }
1517 	}
1518 
1519 	c = searchit(curwin, curbuf, &pos, NULL,
1520 					      dirc == '/' ? FORWARD : BACKWARD,
1521 		searchstr, count, spats[0].off.end + (options &
1522 		       (SEARCH_KEEP + SEARCH_PEEK + SEARCH_HIS
1523 			+ SEARCH_MSG + SEARCH_START
1524 			+ ((pat != NULL && *pat == ';') ? 0 : SEARCH_NOOF))),
1525 		RE_LAST, sia);
1526 
1527 	if (dircp != NULL)
1528 	    *dircp = search_delim;	// restore second '/' or '?' for normal_cmd()
1529 
1530 	if (!shortmess(SHM_SEARCH)
1531 		&& ((dirc == '/' && LT_POS(pos, curwin->w_cursor))
1532 			    || (dirc == '?' && LT_POS(curwin->w_cursor, pos))))
1533 	    show_top_bot_msg = TRUE;
1534 
1535 	if (c == FAIL)
1536 	{
1537 	    retval = 0;
1538 	    goto end_do_search;
1539 	}
1540 	if (spats[0].off.end && oap != NULL)
1541 	    oap->inclusive = TRUE;  // 'e' includes last character
1542 
1543 	retval = 1;		    // pattern found
1544 
1545 	/*
1546 	 * Add character and/or line offset
1547 	 */
1548 	if (!(options & SEARCH_NOOF) || (pat != NULL && *pat == ';'))
1549 	{
1550 	    pos_T org_pos = pos;
1551 
1552 	    if (spats[0].off.line)	// Add the offset to the line number.
1553 	    {
1554 		c = pos.lnum + spats[0].off.off;
1555 		if (c < 1)
1556 		    pos.lnum = 1;
1557 		else if (c > curbuf->b_ml.ml_line_count)
1558 		    pos.lnum = curbuf->b_ml.ml_line_count;
1559 		else
1560 		    pos.lnum = c;
1561 		pos.col = 0;
1562 
1563 		retval = 2;	    // pattern found, line offset added
1564 	    }
1565 	    else if (pos.col < MAXCOL - 2)	// just in case
1566 	    {
1567 		// to the right, check for end of file
1568 		c = spats[0].off.off;
1569 		if (c > 0)
1570 		{
1571 		    while (c-- > 0)
1572 			if (incl(&pos) == -1)
1573 			    break;
1574 		}
1575 		// to the left, check for start of file
1576 		else
1577 		{
1578 		    while (c++ < 0)
1579 			if (decl(&pos) == -1)
1580 			    break;
1581 		}
1582 	    }
1583 	    if (!EQUAL_POS(pos, org_pos))
1584 		has_offset = TRUE;
1585 	}
1586 
1587 	// Show [1/15] if 'S' is not in 'shortmess'.
1588 	if ((options & SEARCH_ECHO)
1589 		&& messaging()
1590 		&& !msg_silent
1591 		&& c != FAIL
1592 		&& !shortmess(SHM_SEARCHCOUNT)
1593 		&& msgbuf != NULL)
1594 	    search_stat(dirc, &pos, show_top_bot_msg, msgbuf,
1595 						   (count != 1 || has_offset));
1596 
1597 	/*
1598 	 * The search command can be followed by a ';' to do another search.
1599 	 * For example: "/pat/;/foo/+3;?bar"
1600 	 * This is like doing another search command, except:
1601 	 * - The remembered direction '/' or '?' is from the first search.
1602 	 * - When an error happens the cursor isn't moved at all.
1603 	 * Don't do this when called by get_address() (it handles ';' itself).
1604 	 */
1605 	if (!(options & SEARCH_OPT) || pat == NULL || *pat != ';')
1606 	    break;
1607 
1608 	dirc = *++pat;
1609 	search_delim = dirc;
1610 	if (dirc != '?' && dirc != '/')
1611 	{
1612 	    retval = 0;
1613 	    emsg(_("E386: Expected '?' or '/'  after ';'"));
1614 	    goto end_do_search;
1615 	}
1616 	++pat;
1617     }
1618 
1619     if (options & SEARCH_MARK)
1620 	setpcmark();
1621     curwin->w_cursor = pos;
1622     curwin->w_set_curswant = TRUE;
1623 
1624 end_do_search:
1625     if ((options & SEARCH_KEEP) || cmdmod.keeppatterns)
1626 	spats[0].off = old_off;
1627     vim_free(strcopy);
1628     vim_free(msgbuf);
1629 
1630     return retval;
1631 }
1632 
1633 /*
1634  * search_for_exact_line(buf, pos, dir, pat)
1635  *
1636  * Search for a line starting with the given pattern (ignoring leading
1637  * white-space), starting from pos and going in direction "dir". "pos" will
1638  * contain the position of the match found.    Blank lines match only if
1639  * ADDING is set.  If p_ic is set then the pattern must be in lowercase.
1640  * Return OK for success, or FAIL if no line found.
1641  */
1642     int
1643 search_for_exact_line(
1644     buf_T	*buf,
1645     pos_T	*pos,
1646     int		dir,
1647     char_u	*pat)
1648 {
1649     linenr_T	start = 0;
1650     char_u	*ptr;
1651     char_u	*p;
1652 
1653     if (buf->b_ml.ml_line_count == 0)
1654 	return FAIL;
1655     for (;;)
1656     {
1657 	pos->lnum += dir;
1658 	if (pos->lnum < 1)
1659 	{
1660 	    if (p_ws)
1661 	    {
1662 		pos->lnum = buf->b_ml.ml_line_count;
1663 		if (!shortmess(SHM_SEARCH))
1664 		    give_warning((char_u *)_(top_bot_msg), TRUE);
1665 	    }
1666 	    else
1667 	    {
1668 		pos->lnum = 1;
1669 		break;
1670 	    }
1671 	}
1672 	else if (pos->lnum > buf->b_ml.ml_line_count)
1673 	{
1674 	    if (p_ws)
1675 	    {
1676 		pos->lnum = 1;
1677 		if (!shortmess(SHM_SEARCH))
1678 		    give_warning((char_u *)_(bot_top_msg), TRUE);
1679 	    }
1680 	    else
1681 	    {
1682 		pos->lnum = 1;
1683 		break;
1684 	    }
1685 	}
1686 	if (pos->lnum == start)
1687 	    break;
1688 	if (start == 0)
1689 	    start = pos->lnum;
1690 	ptr = ml_get_buf(buf, pos->lnum, FALSE);
1691 	p = skipwhite(ptr);
1692 	pos->col = (colnr_T) (p - ptr);
1693 
1694 	// when adding lines the matching line may be empty but it is not
1695 	// ignored because we are interested in the next line -- Acevedo
1696 	if ((compl_cont_status & CONT_ADDING)
1697 					   && !(compl_cont_status & CONT_SOL))
1698 	{
1699 	    if ((p_ic ? MB_STRICMP(p, pat) : STRCMP(p, pat)) == 0)
1700 		return OK;
1701 	}
1702 	else if (*p != NUL)	// ignore empty lines
1703 	{	// expanding lines or words
1704 	    if ((p_ic ? MB_STRNICMP(p, pat, compl_length)
1705 				   : STRNCMP(p, pat, compl_length)) == 0)
1706 		return OK;
1707 	}
1708     }
1709     return FAIL;
1710 }
1711 
1712 /*
1713  * Character Searches
1714  */
1715 
1716 /*
1717  * Search for a character in a line.  If "t_cmd" is FALSE, move to the
1718  * position of the character, otherwise move to just before the char.
1719  * Do this "cap->count1" times.
1720  * Return FAIL or OK.
1721  */
1722     int
1723 searchc(cmdarg_T *cap, int t_cmd)
1724 {
1725     int			c = cap->nchar;	// char to search for
1726     int			dir = cap->arg;	// TRUE for searching forward
1727     long		count = cap->count1;	// repeat count
1728     int			col;
1729     char_u		*p;
1730     int			len;
1731     int			stop = TRUE;
1732 
1733     if (c != NUL)	// normal search: remember args for repeat
1734     {
1735 	if (!KeyStuffed)    // don't remember when redoing
1736 	{
1737 	    *lastc = c;
1738 	    set_csearch_direction(dir);
1739 	    set_csearch_until(t_cmd);
1740 	    lastc_bytelen = (*mb_char2bytes)(c, lastc_bytes);
1741 	    if (cap->ncharC1 != 0)
1742 	    {
1743 		lastc_bytelen += (*mb_char2bytes)(cap->ncharC1,
1744 			lastc_bytes + lastc_bytelen);
1745 		if (cap->ncharC2 != 0)
1746 		    lastc_bytelen += (*mb_char2bytes)(cap->ncharC2,
1747 			    lastc_bytes + lastc_bytelen);
1748 	    }
1749 	}
1750     }
1751     else		// repeat previous search
1752     {
1753 	if (*lastc == NUL && lastc_bytelen == 1)
1754 	    return FAIL;
1755 	if (dir)	// repeat in opposite direction
1756 	    dir = -lastcdir;
1757 	else
1758 	    dir = lastcdir;
1759 	t_cmd = last_t_cmd;
1760 	c = *lastc;
1761 	// For multi-byte re-use last lastc_bytes[] and lastc_bytelen.
1762 
1763 	// Force a move of at least one char, so ";" and "," will move the
1764 	// cursor, even if the cursor is right in front of char we are looking
1765 	// at.
1766 	if (vim_strchr(p_cpo, CPO_SCOLON) == NULL && count == 1 && t_cmd)
1767 	    stop = FALSE;
1768     }
1769 
1770     if (dir == BACKWARD)
1771 	cap->oap->inclusive = FALSE;
1772     else
1773 	cap->oap->inclusive = TRUE;
1774 
1775     p = ml_get_curline();
1776     col = curwin->w_cursor.col;
1777     len = (int)STRLEN(p);
1778 
1779     while (count--)
1780     {
1781 	if (has_mbyte)
1782 	{
1783 	    for (;;)
1784 	    {
1785 		if (dir > 0)
1786 		{
1787 		    col += (*mb_ptr2len)(p + col);
1788 		    if (col >= len)
1789 			return FAIL;
1790 		}
1791 		else
1792 		{
1793 		    if (col == 0)
1794 			return FAIL;
1795 		    col -= (*mb_head_off)(p, p + col - 1) + 1;
1796 		}
1797 		if (lastc_bytelen == 1)
1798 		{
1799 		    if (p[col] == c && stop)
1800 			break;
1801 		}
1802 		else if (STRNCMP(p + col, lastc_bytes, lastc_bytelen) == 0
1803 								       && stop)
1804 		    break;
1805 		stop = TRUE;
1806 	    }
1807 	}
1808 	else
1809 	{
1810 	    for (;;)
1811 	    {
1812 		if ((col += dir) < 0 || col >= len)
1813 		    return FAIL;
1814 		if (p[col] == c && stop)
1815 		    break;
1816 		stop = TRUE;
1817 	    }
1818 	}
1819     }
1820 
1821     if (t_cmd)
1822     {
1823 	// backup to before the character (possibly double-byte)
1824 	col -= dir;
1825 	if (has_mbyte)
1826 	{
1827 	    if (dir < 0)
1828 		// Landed on the search char which is lastc_bytelen long
1829 		col += lastc_bytelen - 1;
1830 	    else
1831 		// To previous char, which may be multi-byte.
1832 		col -= (*mb_head_off)(p, p + col);
1833 	}
1834     }
1835     curwin->w_cursor.col = col;
1836 
1837     return OK;
1838 }
1839 
1840 /*
1841  * "Other" Searches
1842  */
1843 
1844 /*
1845  * findmatch - find the matching paren or brace
1846  *
1847  * Improvement over vi: Braces inside quotes are ignored.
1848  */
1849     pos_T *
1850 findmatch(oparg_T *oap, int initc)
1851 {
1852     return findmatchlimit(oap, initc, 0, 0);
1853 }
1854 
1855 /*
1856  * Return TRUE if the character before "linep[col]" equals "ch".
1857  * Return FALSE if "col" is zero.
1858  * Update "*prevcol" to the column of the previous character, unless "prevcol"
1859  * is NULL.
1860  * Handles multibyte string correctly.
1861  */
1862     static int
1863 check_prevcol(
1864     char_u	*linep,
1865     int		col,
1866     int		ch,
1867     int		*prevcol)
1868 {
1869     --col;
1870     if (col > 0 && has_mbyte)
1871 	col -= (*mb_head_off)(linep, linep + col);
1872     if (prevcol)
1873 	*prevcol = col;
1874     return (col >= 0 && linep[col] == ch) ? TRUE : FALSE;
1875 }
1876 
1877 /*
1878  * Raw string start is found at linep[startpos.col - 1].
1879  * Return TRUE if the matching end can be found between startpos and endpos.
1880  */
1881     static int
1882 find_rawstring_end(char_u *linep, pos_T *startpos, pos_T *endpos)
1883 {
1884     char_u	*p;
1885     char_u	*delim_copy;
1886     size_t	delim_len;
1887     linenr_T	lnum;
1888     int		found = FALSE;
1889 
1890     for (p = linep + startpos->col + 1; *p && *p != '('; ++p)
1891 	;
1892     delim_len = (p - linep) - startpos->col - 1;
1893     delim_copy = vim_strnsave(linep + startpos->col + 1, (int)delim_len);
1894     if (delim_copy == NULL)
1895 	return FALSE;
1896     for (lnum = startpos->lnum; lnum <= endpos->lnum; ++lnum)
1897     {
1898 	char_u *line = ml_get(lnum);
1899 
1900 	for (p = line + (lnum == startpos->lnum
1901 					    ? startpos->col + 1 : 0); *p; ++p)
1902 	{
1903 	    if (lnum == endpos->lnum && (colnr_T)(p - line) >= endpos->col)
1904 		break;
1905 	    if (*p == ')' && p[delim_len + 1] == '"'
1906 			  && STRNCMP(delim_copy, p + 1, delim_len) == 0)
1907 	    {
1908 		found = TRUE;
1909 		break;
1910 	    }
1911 	}
1912 	if (found)
1913 	    break;
1914     }
1915     vim_free(delim_copy);
1916     return found;
1917 }
1918 
1919 /*
1920  * Check matchpairs option for "*initc".
1921  * If there is a match set "*initc" to the matching character and "*findc" to
1922  * the opposite character.  Set "*backwards" to the direction.
1923  * When "switchit" is TRUE swap the direction.
1924  */
1925     static void
1926 find_mps_values(
1927     int	    *initc,
1928     int	    *findc,
1929     int	    *backwards,
1930     int	    switchit)
1931 {
1932     char_u	*ptr;
1933 
1934     ptr = curbuf->b_p_mps;
1935     while (*ptr != NUL)
1936     {
1937 	if (has_mbyte)
1938 	{
1939 	    char_u *prev;
1940 
1941 	    if (mb_ptr2char(ptr) == *initc)
1942 	    {
1943 		if (switchit)
1944 		{
1945 		    *findc = *initc;
1946 		    *initc = mb_ptr2char(ptr + mb_ptr2len(ptr) + 1);
1947 		    *backwards = TRUE;
1948 		}
1949 		else
1950 		{
1951 		    *findc = mb_ptr2char(ptr + mb_ptr2len(ptr) + 1);
1952 		    *backwards = FALSE;
1953 		}
1954 		return;
1955 	    }
1956 	    prev = ptr;
1957 	    ptr += mb_ptr2len(ptr) + 1;
1958 	    if (mb_ptr2char(ptr) == *initc)
1959 	    {
1960 		if (switchit)
1961 		{
1962 		    *findc = *initc;
1963 		    *initc = mb_ptr2char(prev);
1964 		    *backwards = FALSE;
1965 		}
1966 		else
1967 		{
1968 		    *findc = mb_ptr2char(prev);
1969 		    *backwards = TRUE;
1970 		}
1971 		return;
1972 	    }
1973 	    ptr += mb_ptr2len(ptr);
1974 	}
1975 	else
1976 	{
1977 	    if (*ptr == *initc)
1978 	    {
1979 		if (switchit)
1980 		{
1981 		    *backwards = TRUE;
1982 		    *findc = *initc;
1983 		    *initc = ptr[2];
1984 		}
1985 		else
1986 		{
1987 		    *backwards = FALSE;
1988 		    *findc = ptr[2];
1989 		}
1990 		return;
1991 	    }
1992 	    ptr += 2;
1993 	    if (*ptr == *initc)
1994 	    {
1995 		if (switchit)
1996 		{
1997 		    *backwards = FALSE;
1998 		    *findc = *initc;
1999 		    *initc = ptr[-2];
2000 		}
2001 		else
2002 		{
2003 		    *backwards = TRUE;
2004 		    *findc =  ptr[-2];
2005 		}
2006 		return;
2007 	    }
2008 	    ++ptr;
2009 	}
2010 	if (*ptr == ',')
2011 	    ++ptr;
2012     }
2013 }
2014 
2015 /*
2016  * findmatchlimit -- find the matching paren or brace, if it exists within
2017  * maxtravel lines of the cursor.  A maxtravel of 0 means search until falling
2018  * off the edge of the file.
2019  *
2020  * "initc" is the character to find a match for.  NUL means to find the
2021  * character at or after the cursor. Special values:
2022  * '*'  look for C-style comment / *
2023  * '/'  look for C-style comment / *, ignoring comment-end
2024  * '#'  look for preprocessor directives
2025  * 'R'  look for raw string start: R"delim(text)delim" (only backwards)
2026  *
2027  * flags: FM_BACKWARD	search backwards (when initc is '/', '*' or '#')
2028  *	  FM_FORWARD	search forwards (when initc is '/', '*' or '#')
2029  *	  FM_BLOCKSTOP	stop at start/end of block ({ or } in column 0)
2030  *	  FM_SKIPCOMM	skip comments (not implemented yet!)
2031  *
2032  * "oap" is only used to set oap->motion_type for a linewise motion, it can be
2033  * NULL
2034  */
2035 
2036     pos_T *
2037 findmatchlimit(
2038     oparg_T	*oap,
2039     int		initc,
2040     int		flags,
2041     int		maxtravel)
2042 {
2043     static pos_T pos;			// current search position
2044     int		findc = 0;		// matching brace
2045     int		c;
2046     int		count = 0;		// cumulative number of braces
2047     int		backwards = FALSE;	// init for gcc
2048     int		raw_string = FALSE;	// search for raw string
2049     int		inquote = FALSE;	// TRUE when inside quotes
2050     char_u	*linep;			// pointer to current line
2051     char_u	*ptr;
2052     int		do_quotes;		// check for quotes in current line
2053     int		at_start;		// do_quotes value at start position
2054     int		hash_dir = 0;		// Direction searched for # things
2055     int		comment_dir = 0;	// Direction searched for comments
2056     pos_T	match_pos;		// Where last slash-star was found
2057     int		start_in_quotes;	// start position is in quotes
2058     int		traveled = 0;		// how far we've searched so far
2059     int		ignore_cend = FALSE;    // ignore comment end
2060     int		cpo_match;		// vi compatible matching
2061     int		cpo_bsl;		// don't recognize backslashes
2062     int		match_escaped = 0;	// search for escaped match
2063     int		dir;			// Direction to search
2064     int		comment_col = MAXCOL;   // start of / / comment
2065 #ifdef FEAT_LISP
2066     int		lispcomm = FALSE;	// inside of Lisp-style comment
2067     int		lisp = curbuf->b_p_lisp; // engage Lisp-specific hacks ;)
2068 #endif
2069 
2070     pos = curwin->w_cursor;
2071     pos.coladd = 0;
2072     linep = ml_get(pos.lnum);
2073 
2074     cpo_match = (vim_strchr(p_cpo, CPO_MATCH) != NULL);
2075     cpo_bsl = (vim_strchr(p_cpo, CPO_MATCHBSL) != NULL);
2076 
2077     // Direction to search when initc is '/', '*' or '#'
2078     if (flags & FM_BACKWARD)
2079 	dir = BACKWARD;
2080     else if (flags & FM_FORWARD)
2081 	dir = FORWARD;
2082     else
2083 	dir = 0;
2084 
2085     /*
2086      * if initc given, look in the table for the matching character
2087      * '/' and '*' are special cases: look for start or end of comment.
2088      * When '/' is used, we ignore running backwards into an star-slash, for
2089      * "[*" command, we just want to find any comment.
2090      */
2091     if (initc == '/' || initc == '*' || initc == 'R')
2092     {
2093 	comment_dir = dir;
2094 	if (initc == '/')
2095 	    ignore_cend = TRUE;
2096 	backwards = (dir == FORWARD) ? FALSE : TRUE;
2097 	raw_string = (initc == 'R');
2098 	initc = NUL;
2099     }
2100     else if (initc != '#' && initc != NUL)
2101     {
2102 	find_mps_values(&initc, &findc, &backwards, TRUE);
2103 	if (findc == NUL)
2104 	    return NULL;
2105     }
2106     else
2107     {
2108 	/*
2109 	 * Either initc is '#', or no initc was given and we need to look
2110 	 * under the cursor.
2111 	 */
2112 	if (initc == '#')
2113 	{
2114 	    hash_dir = dir;
2115 	}
2116 	else
2117 	{
2118 	    /*
2119 	     * initc was not given, must look for something to match under
2120 	     * or near the cursor.
2121 	     * Only check for special things when 'cpo' doesn't have '%'.
2122 	     */
2123 	    if (!cpo_match)
2124 	    {
2125 		// Are we before or at #if, #else etc.?
2126 		ptr = skipwhite(linep);
2127 		if (*ptr == '#' && pos.col <= (colnr_T)(ptr - linep))
2128 		{
2129 		    ptr = skipwhite(ptr + 1);
2130 		    if (   STRNCMP(ptr, "if", 2) == 0
2131 			|| STRNCMP(ptr, "endif", 5) == 0
2132 			|| STRNCMP(ptr, "el", 2) == 0)
2133 			hash_dir = 1;
2134 		}
2135 
2136 		// Are we on a comment?
2137 		else if (linep[pos.col] == '/')
2138 		{
2139 		    if (linep[pos.col + 1] == '*')
2140 		    {
2141 			comment_dir = FORWARD;
2142 			backwards = FALSE;
2143 			pos.col++;
2144 		    }
2145 		    else if (pos.col > 0 && linep[pos.col - 1] == '*')
2146 		    {
2147 			comment_dir = BACKWARD;
2148 			backwards = TRUE;
2149 			pos.col--;
2150 		    }
2151 		}
2152 		else if (linep[pos.col] == '*')
2153 		{
2154 		    if (linep[pos.col + 1] == '/')
2155 		    {
2156 			comment_dir = BACKWARD;
2157 			backwards = TRUE;
2158 		    }
2159 		    else if (pos.col > 0 && linep[pos.col - 1] == '/')
2160 		    {
2161 			comment_dir = FORWARD;
2162 			backwards = FALSE;
2163 		    }
2164 		}
2165 	    }
2166 
2167 	    /*
2168 	     * If we are not on a comment or the # at the start of a line, then
2169 	     * look for brace anywhere on this line after the cursor.
2170 	     */
2171 	    if (!hash_dir && !comment_dir)
2172 	    {
2173 		/*
2174 		 * Find the brace under or after the cursor.
2175 		 * If beyond the end of the line, use the last character in
2176 		 * the line.
2177 		 */
2178 		if (linep[pos.col] == NUL && pos.col)
2179 		    --pos.col;
2180 		for (;;)
2181 		{
2182 		    initc = PTR2CHAR(linep + pos.col);
2183 		    if (initc == NUL)
2184 			break;
2185 
2186 		    find_mps_values(&initc, &findc, &backwards, FALSE);
2187 		    if (findc)
2188 			break;
2189 		    pos.col += mb_ptr2len(linep + pos.col);
2190 		}
2191 		if (!findc)
2192 		{
2193 		    // no brace in the line, maybe use "  #if" then
2194 		    if (!cpo_match && *skipwhite(linep) == '#')
2195 			hash_dir = 1;
2196 		    else
2197 			return NULL;
2198 		}
2199 		else if (!cpo_bsl)
2200 		{
2201 		    int col, bslcnt = 0;
2202 
2203 		    // Set "match_escaped" if there are an odd number of
2204 		    // backslashes.
2205 		    for (col = pos.col; check_prevcol(linep, col, '\\', &col);)
2206 			bslcnt++;
2207 		    match_escaped = (bslcnt & 1);
2208 		}
2209 	    }
2210 	}
2211 	if (hash_dir)
2212 	{
2213 	    /*
2214 	     * Look for matching #if, #else, #elif, or #endif
2215 	     */
2216 	    if (oap != NULL)
2217 		oap->motion_type = MLINE;   // Linewise for this case only
2218 	    if (initc != '#')
2219 	    {
2220 		ptr = skipwhite(skipwhite(linep) + 1);
2221 		if (STRNCMP(ptr, "if", 2) == 0 || STRNCMP(ptr, "el", 2) == 0)
2222 		    hash_dir = 1;
2223 		else if (STRNCMP(ptr, "endif", 5) == 0)
2224 		    hash_dir = -1;
2225 		else
2226 		    return NULL;
2227 	    }
2228 	    pos.col = 0;
2229 	    while (!got_int)
2230 	    {
2231 		if (hash_dir > 0)
2232 		{
2233 		    if (pos.lnum == curbuf->b_ml.ml_line_count)
2234 			break;
2235 		}
2236 		else if (pos.lnum == 1)
2237 		    break;
2238 		pos.lnum += hash_dir;
2239 		linep = ml_get(pos.lnum);
2240 		line_breakcheck();	// check for CTRL-C typed
2241 		ptr = skipwhite(linep);
2242 		if (*ptr != '#')
2243 		    continue;
2244 		pos.col = (colnr_T) (ptr - linep);
2245 		ptr = skipwhite(ptr + 1);
2246 		if (hash_dir > 0)
2247 		{
2248 		    if (STRNCMP(ptr, "if", 2) == 0)
2249 			count++;
2250 		    else if (STRNCMP(ptr, "el", 2) == 0)
2251 		    {
2252 			if (count == 0)
2253 			    return &pos;
2254 		    }
2255 		    else if (STRNCMP(ptr, "endif", 5) == 0)
2256 		    {
2257 			if (count == 0)
2258 			    return &pos;
2259 			count--;
2260 		    }
2261 		}
2262 		else
2263 		{
2264 		    if (STRNCMP(ptr, "if", 2) == 0)
2265 		    {
2266 			if (count == 0)
2267 			    return &pos;
2268 			count--;
2269 		    }
2270 		    else if (initc == '#' && STRNCMP(ptr, "el", 2) == 0)
2271 		    {
2272 			if (count == 0)
2273 			    return &pos;
2274 		    }
2275 		    else if (STRNCMP(ptr, "endif", 5) == 0)
2276 			count++;
2277 		}
2278 	    }
2279 	    return NULL;
2280 	}
2281     }
2282 
2283 #ifdef FEAT_RIGHTLEFT
2284     // This is just guessing: when 'rightleft' is set, search for a matching
2285     // paren/brace in the other direction.
2286     if (curwin->w_p_rl && vim_strchr((char_u *)"()[]{}<>", initc) != NULL)
2287 	backwards = !backwards;
2288 #endif
2289 
2290     do_quotes = -1;
2291     start_in_quotes = MAYBE;
2292     CLEAR_POS(&match_pos);
2293 
2294     // backward search: Check if this line contains a single-line comment
2295     if ((backwards && comment_dir)
2296 #ifdef FEAT_LISP
2297 	    || lisp
2298 #endif
2299 	    )
2300 	comment_col = check_linecomment(linep);
2301 #ifdef FEAT_LISP
2302     if (lisp && comment_col != MAXCOL && pos.col > (colnr_T)comment_col)
2303 	lispcomm = TRUE;    // find match inside this comment
2304 #endif
2305     while (!got_int)
2306     {
2307 	/*
2308 	 * Go to the next position, forward or backward. We could use
2309 	 * inc() and dec() here, but that is much slower
2310 	 */
2311 	if (backwards)
2312 	{
2313 #ifdef FEAT_LISP
2314 	    // char to match is inside of comment, don't search outside
2315 	    if (lispcomm && pos.col < (colnr_T)comment_col)
2316 		break;
2317 #endif
2318 	    if (pos.col == 0)		// at start of line, go to prev. one
2319 	    {
2320 		if (pos.lnum == 1)	// start of file
2321 		    break;
2322 		--pos.lnum;
2323 
2324 		if (maxtravel > 0 && ++traveled > maxtravel)
2325 		    break;
2326 
2327 		linep = ml_get(pos.lnum);
2328 		pos.col = (colnr_T)STRLEN(linep); // pos.col on trailing NUL
2329 		do_quotes = -1;
2330 		line_breakcheck();
2331 
2332 		// Check if this line contains a single-line comment
2333 		if (comment_dir
2334 #ifdef FEAT_LISP
2335 			|| lisp
2336 #endif
2337 			)
2338 		    comment_col = check_linecomment(linep);
2339 #ifdef FEAT_LISP
2340 		// skip comment
2341 		if (lisp && comment_col != MAXCOL)
2342 		    pos.col = comment_col;
2343 #endif
2344 	    }
2345 	    else
2346 	    {
2347 		--pos.col;
2348 		if (has_mbyte)
2349 		    pos.col -= (*mb_head_off)(linep, linep + pos.col);
2350 	    }
2351 	}
2352 	else				// forward search
2353 	{
2354 	    if (linep[pos.col] == NUL
2355 		    // at end of line, go to next one
2356 #ifdef FEAT_LISP
2357 		    // don't search for match in comment
2358 		    || (lisp && comment_col != MAXCOL
2359 					   && pos.col == (colnr_T)comment_col)
2360 #endif
2361 		    )
2362 	    {
2363 		if (pos.lnum == curbuf->b_ml.ml_line_count  // end of file
2364 #ifdef FEAT_LISP
2365 			// line is exhausted and comment with it,
2366 			// don't search for match in code
2367 			 || lispcomm
2368 #endif
2369 			 )
2370 		    break;
2371 		++pos.lnum;
2372 
2373 		if (maxtravel && traveled++ > maxtravel)
2374 		    break;
2375 
2376 		linep = ml_get(pos.lnum);
2377 		pos.col = 0;
2378 		do_quotes = -1;
2379 		line_breakcheck();
2380 #ifdef FEAT_LISP
2381 		if (lisp)   // find comment pos in new line
2382 		    comment_col = check_linecomment(linep);
2383 #endif
2384 	    }
2385 	    else
2386 	    {
2387 		if (has_mbyte)
2388 		    pos.col += (*mb_ptr2len)(linep + pos.col);
2389 		else
2390 		    ++pos.col;
2391 	    }
2392 	}
2393 
2394 	/*
2395 	 * If FM_BLOCKSTOP given, stop at a '{' or '}' in column 0.
2396 	 */
2397 	if (pos.col == 0 && (flags & FM_BLOCKSTOP) &&
2398 					 (linep[0] == '{' || linep[0] == '}'))
2399 	{
2400 	    if (linep[0] == findc && count == 0)	// match!
2401 		return &pos;
2402 	    break;					// out of scope
2403 	}
2404 
2405 	if (comment_dir)
2406 	{
2407 	    // Note: comments do not nest, and we ignore quotes in them
2408 	    // TODO: ignore comment brackets inside strings
2409 	    if (comment_dir == FORWARD)
2410 	    {
2411 		if (linep[pos.col] == '*' && linep[pos.col + 1] == '/')
2412 		{
2413 		    pos.col++;
2414 		    return &pos;
2415 		}
2416 	    }
2417 	    else    // Searching backwards
2418 	    {
2419 		/*
2420 		 * A comment may contain / * or / /, it may also start or end
2421 		 * with / * /.	Ignore a / * after / / and after *.
2422 		 */
2423 		if (pos.col == 0)
2424 		    continue;
2425 		else if (raw_string)
2426 		{
2427 		    if (linep[pos.col - 1] == 'R'
2428 			&& linep[pos.col] == '"'
2429 			&& vim_strchr(linep + pos.col + 1, '(') != NULL)
2430 		    {
2431 			// Possible start of raw string. Now that we have the
2432 			// delimiter we can check if it ends before where we
2433 			// started searching, or before the previously found
2434 			// raw string start.
2435 			if (!find_rawstring_end(linep, &pos,
2436 				  count > 0 ? &match_pos : &curwin->w_cursor))
2437 			{
2438 			    count++;
2439 			    match_pos = pos;
2440 			    match_pos.col--;
2441 			}
2442 			linep = ml_get(pos.lnum); // may have been released
2443 		    }
2444 		}
2445 		else if (  linep[pos.col - 1] == '/'
2446 			&& linep[pos.col] == '*'
2447 			&& (pos.col == 1 || linep[pos.col - 2] != '*')
2448 			&& (int)pos.col < comment_col)
2449 		{
2450 		    count++;
2451 		    match_pos = pos;
2452 		    match_pos.col--;
2453 		}
2454 		else if (linep[pos.col - 1] == '*' && linep[pos.col] == '/')
2455 		{
2456 		    if (count > 0)
2457 			pos = match_pos;
2458 		    else if (pos.col > 1 && linep[pos.col - 2] == '/'
2459 					       && (int)pos.col <= comment_col)
2460 			pos.col -= 2;
2461 		    else if (ignore_cend)
2462 			continue;
2463 		    else
2464 			return NULL;
2465 		    return &pos;
2466 		}
2467 	    }
2468 	    continue;
2469 	}
2470 
2471 	/*
2472 	 * If smart matching ('cpoptions' does not contain '%'), braces inside
2473 	 * of quotes are ignored, but only if there is an even number of
2474 	 * quotes in the line.
2475 	 */
2476 	if (cpo_match)
2477 	    do_quotes = 0;
2478 	else if (do_quotes == -1)
2479 	{
2480 	    /*
2481 	     * Count the number of quotes in the line, skipping \" and '"'.
2482 	     * Watch out for "\\".
2483 	     */
2484 	    at_start = do_quotes;
2485 	    for (ptr = linep; *ptr; ++ptr)
2486 	    {
2487 		if (ptr == linep + pos.col + backwards)
2488 		    at_start = (do_quotes & 1);
2489 		if (*ptr == '"'
2490 			&& (ptr == linep || ptr[-1] != '\'' || ptr[1] != '\''))
2491 		    ++do_quotes;
2492 		if (*ptr == '\\' && ptr[1] != NUL)
2493 		    ++ptr;
2494 	    }
2495 	    do_quotes &= 1;	    // result is 1 with even number of quotes
2496 
2497 	    /*
2498 	     * If we find an uneven count, check current line and previous
2499 	     * one for a '\' at the end.
2500 	     */
2501 	    if (!do_quotes)
2502 	    {
2503 		inquote = FALSE;
2504 		if (ptr[-1] == '\\')
2505 		{
2506 		    do_quotes = 1;
2507 		    if (start_in_quotes == MAYBE)
2508 		    {
2509 			// Do we need to use at_start here?
2510 			inquote = TRUE;
2511 			start_in_quotes = TRUE;
2512 		    }
2513 		    else if (backwards)
2514 			inquote = TRUE;
2515 		}
2516 		if (pos.lnum > 1)
2517 		{
2518 		    ptr = ml_get(pos.lnum - 1);
2519 		    if (*ptr && *(ptr + STRLEN(ptr) - 1) == '\\')
2520 		    {
2521 			do_quotes = 1;
2522 			if (start_in_quotes == MAYBE)
2523 			{
2524 			    inquote = at_start;
2525 			    if (inquote)
2526 				start_in_quotes = TRUE;
2527 			}
2528 			else if (!backwards)
2529 			    inquote = TRUE;
2530 		    }
2531 
2532 		    // ml_get() only keeps one line, need to get linep again
2533 		    linep = ml_get(pos.lnum);
2534 		}
2535 	    }
2536 	}
2537 	if (start_in_quotes == MAYBE)
2538 	    start_in_quotes = FALSE;
2539 
2540 	/*
2541 	 * If 'smartmatch' is set:
2542 	 *   Things inside quotes are ignored by setting 'inquote'.  If we
2543 	 *   find a quote without a preceding '\' invert 'inquote'.  At the
2544 	 *   end of a line not ending in '\' we reset 'inquote'.
2545 	 *
2546 	 *   In lines with an uneven number of quotes (without preceding '\')
2547 	 *   we do not know which part to ignore. Therefore we only set
2548 	 *   inquote if the number of quotes in a line is even, unless this
2549 	 *   line or the previous one ends in a '\'.  Complicated, isn't it?
2550 	 */
2551 	c = PTR2CHAR(linep + pos.col);
2552 	switch (c)
2553 	{
2554 	case NUL:
2555 	    // at end of line without trailing backslash, reset inquote
2556 	    if (pos.col == 0 || linep[pos.col - 1] != '\\')
2557 	    {
2558 		inquote = FALSE;
2559 		start_in_quotes = FALSE;
2560 	    }
2561 	    break;
2562 
2563 	case '"':
2564 	    // a quote that is preceded with an odd number of backslashes is
2565 	    // ignored
2566 	    if (do_quotes)
2567 	    {
2568 		int col;
2569 
2570 		for (col = pos.col - 1; col >= 0; --col)
2571 		    if (linep[col] != '\\')
2572 			break;
2573 		if ((((int)pos.col - 1 - col) & 1) == 0)
2574 		{
2575 		    inquote = !inquote;
2576 		    start_in_quotes = FALSE;
2577 		}
2578 	    }
2579 	    break;
2580 
2581 	/*
2582 	 * If smart matching ('cpoptions' does not contain '%'):
2583 	 *   Skip things in single quotes: 'x' or '\x'.  Be careful for single
2584 	 *   single quotes, eg jon's.  Things like '\233' or '\x3f' are not
2585 	 *   skipped, there is never a brace in them.
2586 	 *   Ignore this when finding matches for `'.
2587 	 */
2588 	case '\'':
2589 	    if (!cpo_match && initc != '\'' && findc != '\'')
2590 	    {
2591 		if (backwards)
2592 		{
2593 		    if (pos.col > 1)
2594 		    {
2595 			if (linep[pos.col - 2] == '\'')
2596 			{
2597 			    pos.col -= 2;
2598 			    break;
2599 			}
2600 			else if (linep[pos.col - 2] == '\\' &&
2601 				    pos.col > 2 && linep[pos.col - 3] == '\'')
2602 			{
2603 			    pos.col -= 3;
2604 			    break;
2605 			}
2606 		    }
2607 		}
2608 		else if (linep[pos.col + 1])	// forward search
2609 		{
2610 		    if (linep[pos.col + 1] == '\\' &&
2611 			    linep[pos.col + 2] && linep[pos.col + 3] == '\'')
2612 		    {
2613 			pos.col += 3;
2614 			break;
2615 		    }
2616 		    else if (linep[pos.col + 2] == '\'')
2617 		    {
2618 			pos.col += 2;
2619 			break;
2620 		    }
2621 		}
2622 	    }
2623 	    // FALLTHROUGH
2624 
2625 	default:
2626 #ifdef FEAT_LISP
2627 	    /*
2628 	     * For Lisp skip over backslashed (), {} and [].
2629 	     * (actually, we skip #\( et al)
2630 	     */
2631 	    if (curbuf->b_p_lisp
2632 		    && vim_strchr((char_u *)"(){}[]", c) != NULL
2633 		    && pos.col > 1
2634 		    && check_prevcol(linep, pos.col, '\\', NULL)
2635 		    && check_prevcol(linep, pos.col - 1, '#', NULL))
2636 		break;
2637 #endif
2638 
2639 	    // Check for match outside of quotes, and inside of
2640 	    // quotes when the start is also inside of quotes.
2641 	    if ((!inquote || start_in_quotes == TRUE)
2642 		    && (c == initc || c == findc))
2643 	    {
2644 		int	col, bslcnt = 0;
2645 
2646 		if (!cpo_bsl)
2647 		{
2648 		    for (col = pos.col; check_prevcol(linep, col, '\\', &col);)
2649 			bslcnt++;
2650 		}
2651 		// Only accept a match when 'M' is in 'cpo' or when escaping
2652 		// is what we expect.
2653 		if (cpo_bsl || (bslcnt & 1) == match_escaped)
2654 		{
2655 		    if (c == initc)
2656 			count++;
2657 		    else
2658 		    {
2659 			if (count == 0)
2660 			    return &pos;
2661 			count--;
2662 		    }
2663 		}
2664 	    }
2665 	}
2666     }
2667 
2668     if (comment_dir == BACKWARD && count > 0)
2669     {
2670 	pos = match_pos;
2671 	return &pos;
2672     }
2673     return (pos_T *)NULL;	// never found it
2674 }
2675 
2676 /*
2677  * Check if line[] contains a / / comment.
2678  * Return MAXCOL if not, otherwise return the column.
2679  * TODO: skip strings.
2680  */
2681     static int
2682 check_linecomment(char_u *line)
2683 {
2684     char_u  *p;
2685 
2686     p = line;
2687 #ifdef FEAT_LISP
2688     // skip Lispish one-line comments
2689     if (curbuf->b_p_lisp)
2690     {
2691 	if (vim_strchr(p, ';') != NULL) // there may be comments
2692 	{
2693 	    int in_str = FALSE;	// inside of string
2694 
2695 	    p = line;		// scan from start
2696 	    while ((p = vim_strpbrk(p, (char_u *)"\";")) != NULL)
2697 	    {
2698 		if (*p == '"')
2699 		{
2700 		    if (in_str)
2701 		    {
2702 			if (*(p - 1) != '\\') // skip escaped quote
2703 			    in_str = FALSE;
2704 		    }
2705 		    else if (p == line || ((p - line) >= 2
2706 				      // skip #\" form
2707 				      && *(p - 1) != '\\' && *(p - 2) != '#'))
2708 			in_str = TRUE;
2709 		}
2710 		else if (!in_str && ((p - line) < 2
2711 				    || (*(p - 1) != '\\' && *(p - 2) != '#')))
2712 		    break;	// found!
2713 		++p;
2714 	    }
2715 	}
2716 	else
2717 	    p = NULL;
2718     }
2719     else
2720 #endif
2721     while ((p = vim_strchr(p, '/')) != NULL)
2722     {
2723 	// accept a double /, unless it's preceded with * and followed by *,
2724 	// because * / / * is an end and start of a C comment
2725 	if (p[1] == '/' && (p == line || p[-1] != '*' || p[2] != '*'))
2726 	    break;
2727 	++p;
2728     }
2729 
2730     if (p == NULL)
2731 	return MAXCOL;
2732     return (int)(p - line);
2733 }
2734 
2735 /*
2736  * Move cursor briefly to character matching the one under the cursor.
2737  * Used for Insert mode and "r" command.
2738  * Show the match only if it is visible on the screen.
2739  * If there isn't a match, then beep.
2740  */
2741     void
2742 showmatch(
2743     int		c)	    // char to show match for
2744 {
2745     pos_T	*lpos, save_cursor;
2746     pos_T	mpos;
2747     colnr_T	vcol;
2748     long	save_so;
2749     long	save_siso;
2750 #ifdef CURSOR_SHAPE
2751     int		save_state;
2752 #endif
2753     colnr_T	save_dollar_vcol;
2754     char_u	*p;
2755     long        *so = curwin->w_p_so >= 0 ? &curwin->w_p_so : &p_so;
2756     long        *siso = curwin->w_p_siso >= 0 ? &curwin->w_p_siso : &p_siso;
2757 
2758     /*
2759      * Only show match for chars in the 'matchpairs' option.
2760      */
2761     // 'matchpairs' is "x:y,x:y"
2762     for (p = curbuf->b_p_mps; *p != NUL; ++p)
2763     {
2764 #ifdef FEAT_RIGHTLEFT
2765 	if (PTR2CHAR(p) == c && (curwin->w_p_rl ^ p_ri))
2766 	    break;
2767 #endif
2768 	p += mb_ptr2len(p) + 1;
2769 	if (PTR2CHAR(p) == c
2770 #ifdef FEAT_RIGHTLEFT
2771 		&& !(curwin->w_p_rl ^ p_ri)
2772 #endif
2773 	   )
2774 	    break;
2775 	p += mb_ptr2len(p);
2776 	if (*p == NUL)
2777 	    return;
2778     }
2779 
2780     if ((lpos = findmatch(NULL, NUL)) == NULL)	    // no match, so beep
2781 	vim_beep(BO_MATCH);
2782     else if (lpos->lnum >= curwin->w_topline && lpos->lnum < curwin->w_botline)
2783     {
2784 	if (!curwin->w_p_wrap)
2785 	    getvcol(curwin, lpos, NULL, &vcol, NULL);
2786 	if (curwin->w_p_wrap || (vcol >= curwin->w_leftcol
2787 			       && vcol < curwin->w_leftcol + curwin->w_width))
2788 	{
2789 	    mpos = *lpos;    // save the pos, update_screen() may change it
2790 	    save_cursor = curwin->w_cursor;
2791 	    save_so = *so;
2792 	    save_siso = *siso;
2793 	    // Handle "$" in 'cpo': If the ')' is typed on top of the "$",
2794 	    // stop displaying the "$".
2795 	    if (dollar_vcol >= 0 && dollar_vcol == curwin->w_virtcol)
2796 		dollar_vcol = -1;
2797 	    ++curwin->w_virtcol;	// do display ')' just before "$"
2798 	    update_screen(VALID);	// show the new char first
2799 
2800 	    save_dollar_vcol = dollar_vcol;
2801 #ifdef CURSOR_SHAPE
2802 	    save_state = State;
2803 	    State = SHOWMATCH;
2804 	    ui_cursor_shape();		// may show different cursor shape
2805 #endif
2806 	    curwin->w_cursor = mpos;	// move to matching char
2807 	    *so = 0;			// don't use 'scrolloff' here
2808 	    *siso = 0;			// don't use 'sidescrolloff' here
2809 	    showruler(FALSE);
2810 	    setcursor();
2811 	    cursor_on();		// make sure that the cursor is shown
2812 	    out_flush_cursor(TRUE, FALSE);
2813 
2814 	    // Restore dollar_vcol(), because setcursor() may call curs_rows()
2815 	    // which resets it if the matching position is in a previous line
2816 	    // and has a higher column number.
2817 	    dollar_vcol = save_dollar_vcol;
2818 
2819 	    /*
2820 	     * brief pause, unless 'm' is present in 'cpo' and a character is
2821 	     * available.
2822 	     */
2823 	    if (vim_strchr(p_cpo, CPO_SHOWMATCH) != NULL)
2824 		ui_delay(p_mat * 100L + 8, TRUE);
2825 	    else if (!char_avail())
2826 		ui_delay(p_mat * 100L + 9, FALSE);
2827 	    curwin->w_cursor = save_cursor;	// restore cursor position
2828 	    *so = save_so;
2829 	    *siso = save_siso;
2830 #ifdef CURSOR_SHAPE
2831 	    State = save_state;
2832 	    ui_cursor_shape();		// may show different cursor shape
2833 #endif
2834 	}
2835     }
2836 }
2837 
2838 /*
2839  * Check if the pattern is zero-width.
2840  * If move is TRUE, check from the beginning of the buffer, else from position
2841  * "cur".
2842  * "direction" is FORWARD or BACKWARD.
2843  * Returns TRUE, FALSE or -1 for failure.
2844  */
2845     static int
2846 is_zero_width(char_u *pattern, int move, pos_T *cur, int direction)
2847 {
2848     regmmatch_T	regmatch;
2849     int		nmatched = 0;
2850     int		result = -1;
2851     pos_T	pos;
2852     int		called_emsg_before = called_emsg;
2853     int		flag = 0;
2854 
2855     if (pattern == NULL)
2856 	pattern = spats[last_idx].pat;
2857 
2858     if (search_regcomp(pattern, RE_SEARCH, RE_SEARCH,
2859 					      SEARCH_KEEP, &regmatch) == FAIL)
2860 	return -1;
2861 
2862     // init startcol correctly
2863     regmatch.startpos[0].col = -1;
2864     // move to match
2865     if (move)
2866     {
2867 	CLEAR_POS(&pos);
2868     }
2869     else
2870     {
2871 	pos = *cur;
2872 	// accept a match at the cursor position
2873 	flag = SEARCH_START;
2874     }
2875 
2876     if (searchit(curwin, curbuf, &pos, NULL, direction, pattern, 1,
2877 				  SEARCH_KEEP + flag, RE_SEARCH, NULL) != FAIL)
2878     {
2879 	// Zero-width pattern should match somewhere, then we can check if
2880 	// start and end are in the same position.
2881 	do
2882 	{
2883 	    regmatch.startpos[0].col++;
2884 	    nmatched = vim_regexec_multi(&regmatch, curwin, curbuf,
2885 			       pos.lnum, regmatch.startpos[0].col, NULL, NULL);
2886 	    if (nmatched != 0)
2887 		break;
2888 	} while (direction == FORWARD ? regmatch.startpos[0].col < pos.col
2889 				      : regmatch.startpos[0].col > pos.col);
2890 
2891 	if (called_emsg == called_emsg_before)
2892 	{
2893 	    result = (nmatched != 0
2894 		&& regmatch.startpos[0].lnum == regmatch.endpos[0].lnum
2895 		&& regmatch.startpos[0].col == regmatch.endpos[0].col);
2896 	}
2897     }
2898 
2899     vim_regfree(regmatch.regprog);
2900     return result;
2901 }
2902 
2903 
2904 /*
2905  * Find next search match under cursor, cursor at end.
2906  * Used while an operator is pending, and in Visual mode.
2907  */
2908     int
2909 current_search(
2910     long	count,
2911     int		forward)	// TRUE for forward, FALSE for backward
2912 {
2913     pos_T	start_pos;	// start position of the pattern match
2914     pos_T	end_pos;	// end position of the pattern match
2915     pos_T	orig_pos;	// position of the cursor at beginning
2916     pos_T	pos;		// position after the pattern
2917     int		i;
2918     int		dir;
2919     int		result;		// result of various function calls
2920     char_u	old_p_ws = p_ws;
2921     int		flags = 0;
2922     pos_T	save_VIsual = VIsual;
2923     int		zero_width;
2924 
2925     // Correct cursor when 'selection' is exclusive
2926     if (VIsual_active && *p_sel == 'e' && LT_POS(VIsual, curwin->w_cursor))
2927 	dec_cursor();
2928 
2929     orig_pos = pos = curwin->w_cursor;
2930     if (VIsual_active)
2931     {
2932 	if (forward)
2933 	    incl(&pos);
2934 	else
2935 	    decl(&pos);
2936     }
2937 
2938     // Is the pattern is zero-width?, this time, don't care about the direction
2939     zero_width = is_zero_width(spats[last_idx].pat, TRUE, &curwin->w_cursor,
2940 								      FORWARD);
2941     if (zero_width == -1)
2942 	return FAIL;  // pattern not found
2943 
2944     /*
2945      * The trick is to first search backwards and then search forward again,
2946      * so that a match at the current cursor position will be correctly
2947      * captured.
2948      */
2949     for (i = 0; i < 2; i++)
2950     {
2951 	if (forward)
2952 	    dir = i;
2953 	else
2954 	    dir = !i;
2955 
2956 	flags = 0;
2957 	if (!dir && !zero_width)
2958 	    flags = SEARCH_END;
2959 	end_pos = pos;
2960 
2961 	// wrapping should not occur in the first round
2962 	if (i == 0)
2963 	    p_ws = FALSE;
2964 
2965 	result = searchit(curwin, curbuf, &pos, &end_pos,
2966 		(dir ? FORWARD : BACKWARD),
2967 		spats[last_idx].pat, (long) (i ? count : 1),
2968 		SEARCH_KEEP | flags, RE_SEARCH, NULL);
2969 
2970 	p_ws = old_p_ws;
2971 
2972 	// First search may fail, but then start searching from the
2973 	// beginning of the file (cursor might be on the search match)
2974 	// except when Visual mode is active, so that extending the visual
2975 	// selection works.
2976 	if (i == 1 && !result) // not found, abort
2977 	{
2978 	    curwin->w_cursor = orig_pos;
2979 	    if (VIsual_active)
2980 		VIsual = save_VIsual;
2981 	    return FAIL;
2982 	}
2983 	else if (i == 0 && !result)
2984 	{
2985 	    if (forward)
2986 	    {
2987 		// try again from start of buffer
2988 		CLEAR_POS(&pos);
2989 	    }
2990 	    else
2991 	    {
2992 		// try again from end of buffer
2993 		// searching backwards, so set pos to last line and col
2994 		pos.lnum = curwin->w_buffer->b_ml.ml_line_count;
2995 		pos.col  = (colnr_T)STRLEN(
2996 				ml_get(curwin->w_buffer->b_ml.ml_line_count));
2997 	    }
2998 	}
2999     }
3000 
3001     start_pos = pos;
3002 
3003     if (!VIsual_active)
3004 	VIsual = start_pos;
3005 
3006     // put cursor on last character of match
3007     curwin->w_cursor = end_pos;
3008     if (LT_POS(VIsual, end_pos) && forward)
3009 	dec_cursor();
3010     else if (VIsual_active && LT_POS(curwin->w_cursor, VIsual))
3011 	curwin->w_cursor = pos;   // put the cursor on the start of the match
3012     VIsual_active = TRUE;
3013     VIsual_mode = 'v';
3014 
3015     if (*p_sel == 'e')
3016     {
3017 	// Correction for exclusive selection depends on the direction.
3018 	if (forward && LTOREQ_POS(VIsual, curwin->w_cursor))
3019 	    inc_cursor();
3020 	else if (!forward && LTOREQ_POS(curwin->w_cursor, VIsual))
3021 	    inc(&VIsual);
3022     }
3023 
3024 #ifdef FEAT_FOLDING
3025     if (fdo_flags & FDO_SEARCH && KeyTyped)
3026 	foldOpenCursor();
3027 #endif
3028 
3029     may_start_select('c');
3030     setmouse();
3031 #ifdef FEAT_CLIPBOARD
3032     // Make sure the clipboard gets updated.  Needed because start and
3033     // end are still the same, and the selection needs to be owned
3034     clip_star.vmode = NUL;
3035 #endif
3036     redraw_curbuf_later(INVERTED);
3037     showmode();
3038 
3039     return OK;
3040 }
3041 
3042 #if defined(FEAT_LISP) || defined(FEAT_CINDENT) || defined(FEAT_TEXTOBJ) \
3043 	|| defined(PROTO)
3044 /*
3045  * return TRUE if line 'lnum' is empty or has white chars only.
3046  */
3047     int
3048 linewhite(linenr_T lnum)
3049 {
3050     char_u  *p;
3051 
3052     p = skipwhite(ml_get(lnum));
3053     return (*p == NUL);
3054 }
3055 #endif
3056 
3057 /*
3058  * Add the search count "[3/19]" to "msgbuf".
3059  * When "recompute" is TRUE always recompute the numbers.
3060  */
3061     static void
3062 search_stat(
3063     int	    dirc,
3064     pos_T   *pos,
3065     int	    show_top_bot_msg,
3066     char_u  *msgbuf,
3067     int	    recompute)
3068 {
3069     int		    save_ws = p_ws;
3070     int		    wraparound = FALSE;
3071     pos_T	    p = (*pos);
3072     static  pos_T   lastpos = {0, 0, 0};
3073     static int	    cur = 0;
3074     static int	    cnt = 0;
3075     static int	    chgtick = 0;
3076     static char_u   *lastpat = NULL;
3077     static buf_T    *lbuf = NULL;
3078 #ifdef FEAT_RELTIME
3079     proftime_T  start;
3080 #endif
3081 #define OUT_OF_TIME 999
3082 
3083     wraparound = ((dirc == '?' && LT_POS(lastpos, p))
3084 	       || (dirc == '/' && LT_POS(p, lastpos)));
3085 
3086     // If anything relevant changed the count has to be recomputed.
3087     // MB_STRNICMP ignores case, but we should not ignore case.
3088     // Unfortunately, there is no MB_STRNICMP function.
3089     if (!(chgtick == CHANGEDTICK(curbuf)
3090 	&& MB_STRNICMP(lastpat, spats[last_idx].pat, STRLEN(lastpat)) == 0
3091 	&& STRLEN(lastpat) == STRLEN(spats[last_idx].pat)
3092 	&& EQUAL_POS(lastpos, curwin->w_cursor)
3093 	&& lbuf == curbuf) || wraparound || cur < 0 || cur > 99 || recompute)
3094     {
3095 	cur = 0;
3096 	cnt = 0;
3097 	CLEAR_POS(&lastpos);
3098 	lbuf = curbuf;
3099     }
3100 
3101     if (EQUAL_POS(lastpos, curwin->w_cursor) && !wraparound
3102 					&& (dirc == '/' ? cur < cnt : cur > 0))
3103 	cur += dirc == '/' ? 1 : -1;
3104     else
3105     {
3106 	p_ws = FALSE;
3107 #ifdef FEAT_RELTIME
3108 	profile_setlimit(20L, &start);
3109 #endif
3110 	while (!got_int && searchit(curwin, curbuf, &lastpos, NULL,
3111 			 FORWARD, NULL, 1, SEARCH_KEEP, RE_LAST, NULL) != FAIL)
3112 	{
3113 #ifdef FEAT_RELTIME
3114 	    // Stop after passing the time limit.
3115 	    if (profile_passed_limit(&start))
3116 	    {
3117 		cnt = OUT_OF_TIME;
3118 		cur = OUT_OF_TIME;
3119 		break;
3120 	    }
3121 #endif
3122 	    cnt++;
3123 	    if (LTOREQ_POS(lastpos, p))
3124 		cur++;
3125 	    fast_breakcheck();
3126 	    if (cnt > 99)
3127 		break;
3128 	}
3129 	if (got_int)
3130 	    cur = -1; // abort
3131     }
3132     if (cur > 0)
3133     {
3134 	char	t[SEARCH_STAT_BUF_LEN] = "";
3135 	size_t	len;
3136 
3137 #ifdef FEAT_RIGHTLEFT
3138 	if (curwin->w_p_rl && *curwin->w_p_rlc == 's')
3139 	{
3140 	    if (cur == OUT_OF_TIME)
3141 		vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[?/??]");
3142 	    else if (cnt > 99 && cur > 99)
3143 		vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[>99/>99]");
3144 	    else if (cnt > 99)
3145 		vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[>99/%d]", cur);
3146 	    else
3147 		vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[%d/%d]", cnt, cur);
3148 	}
3149 	else
3150 #endif
3151 	{
3152 	    if (cur == OUT_OF_TIME)
3153 		vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[?/??]");
3154 	    else if (cnt > 99 && cur > 99)
3155 		vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[>99/>99]");
3156 	    else if (cnt > 99)
3157 		vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[%d/>99]", cur);
3158 	    else
3159 		vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[%d/%d]", cur, cnt);
3160 	}
3161 
3162 	len = STRLEN(t);
3163 	if (show_top_bot_msg && len + 2 < SEARCH_STAT_BUF_LEN)
3164 	{
3165 	    mch_memmove(t + 2, t, len);
3166 	    t[0] = 'W';
3167 	    t[1] = ' ';
3168 	    len += 2;
3169 	}
3170 
3171 	mch_memmove(msgbuf + STRLEN(msgbuf) - len, t, len);
3172 	if (dirc == '?' && cur == 100)
3173 	    cur = -1;
3174 
3175 	vim_free(lastpat);
3176 	lastpat = vim_strsave(spats[last_idx].pat);
3177 	chgtick = CHANGEDTICK(curbuf);
3178 	lbuf    = curbuf;
3179 	lastpos = p;
3180 
3181 	// keep the message even after redraw, but don't put in history
3182 	msg_hist_off = TRUE;
3183 	give_warning(msgbuf, FALSE);
3184 	msg_hist_off = FALSE;
3185     }
3186     p_ws = save_ws;
3187 }
3188 
3189 #if defined(FEAT_FIND_ID) || defined(PROTO)
3190 /*
3191  * Find identifiers or defines in included files.
3192  * If p_ic && (compl_cont_status & CONT_SOL) then ptr must be in lowercase.
3193  */
3194     void
3195 find_pattern_in_path(
3196     char_u	*ptr,		// pointer to search pattern
3197     int		dir UNUSED,	// direction of expansion
3198     int		len,		// length of search pattern
3199     int		whole,		// match whole words only
3200     int		skip_comments,	// don't match inside comments
3201     int		type,		// Type of search; are we looking for a type?
3202 				// a macro?
3203     long	count,
3204     int		action,		// What to do when we find it
3205     linenr_T	start_lnum,	// first line to start searching
3206     linenr_T	end_lnum)	// last line for searching
3207 {
3208     SearchedFile *files;		// Stack of included files
3209     SearchedFile *bigger;		// When we need more space
3210     int		max_path_depth = 50;
3211     long	match_count = 1;
3212 
3213     char_u	*pat;
3214     char_u	*new_fname;
3215     char_u	*curr_fname = curbuf->b_fname;
3216     char_u	*prev_fname = NULL;
3217     linenr_T	lnum;
3218     int		depth;
3219     int		depth_displayed;	// For type==CHECK_PATH
3220     int		old_files;
3221     int		already_searched;
3222     char_u	*file_line;
3223     char_u	*line;
3224     char_u	*p;
3225     char_u	save_char;
3226     int		define_matched;
3227     regmatch_T	regmatch;
3228     regmatch_T	incl_regmatch;
3229     regmatch_T	def_regmatch;
3230     int		matched = FALSE;
3231     int		did_show = FALSE;
3232     int		found = FALSE;
3233     int		i;
3234     char_u	*already = NULL;
3235     char_u	*startp = NULL;
3236     char_u	*inc_opt = NULL;
3237 #if defined(FEAT_QUICKFIX)
3238     win_T	*curwin_save = NULL;
3239 #endif
3240 
3241     regmatch.regprog = NULL;
3242     incl_regmatch.regprog = NULL;
3243     def_regmatch.regprog = NULL;
3244 
3245     file_line = alloc(LSIZE);
3246     if (file_line == NULL)
3247 	return;
3248 
3249     if (type != CHECK_PATH && type != FIND_DEFINE
3250 	// when CONT_SOL is set compare "ptr" with the beginning of the line
3251 	// is faster than quote_meta/regcomp/regexec "ptr" -- Acevedo
3252 	    && !(compl_cont_status & CONT_SOL))
3253     {
3254 	pat = alloc(len + 5);
3255 	if (pat == NULL)
3256 	    goto fpip_end;
3257 	sprintf((char *)pat, whole ? "\\<%.*s\\>" : "%.*s", len, ptr);
3258 	// ignore case according to p_ic, p_scs and pat
3259 	regmatch.rm_ic = ignorecase(pat);
3260 	regmatch.regprog = vim_regcomp(pat, p_magic ? RE_MAGIC : 0);
3261 	vim_free(pat);
3262 	if (regmatch.regprog == NULL)
3263 	    goto fpip_end;
3264     }
3265     inc_opt = (*curbuf->b_p_inc == NUL) ? p_inc : curbuf->b_p_inc;
3266     if (*inc_opt != NUL)
3267     {
3268 	incl_regmatch.regprog = vim_regcomp(inc_opt, p_magic ? RE_MAGIC : 0);
3269 	if (incl_regmatch.regprog == NULL)
3270 	    goto fpip_end;
3271 	incl_regmatch.rm_ic = FALSE;	// don't ignore case in incl. pat.
3272     }
3273     if (type == FIND_DEFINE && (*curbuf->b_p_def != NUL || *p_def != NUL))
3274     {
3275 	def_regmatch.regprog = vim_regcomp(*curbuf->b_p_def == NUL
3276 			   ? p_def : curbuf->b_p_def, p_magic ? RE_MAGIC : 0);
3277 	if (def_regmatch.regprog == NULL)
3278 	    goto fpip_end;
3279 	def_regmatch.rm_ic = FALSE;	// don't ignore case in define pat.
3280     }
3281     files = lalloc_clear(max_path_depth * sizeof(SearchedFile), TRUE);
3282     if (files == NULL)
3283 	goto fpip_end;
3284     old_files = max_path_depth;
3285     depth = depth_displayed = -1;
3286 
3287     lnum = start_lnum;
3288     if (end_lnum > curbuf->b_ml.ml_line_count)
3289 	end_lnum = curbuf->b_ml.ml_line_count;
3290     if (lnum > end_lnum)		// do at least one line
3291 	lnum = end_lnum;
3292     line = ml_get(lnum);
3293 
3294     for (;;)
3295     {
3296 	if (incl_regmatch.regprog != NULL
3297 		&& vim_regexec(&incl_regmatch, line, (colnr_T)0))
3298 	{
3299 	    char_u *p_fname = (curr_fname == curbuf->b_fname)
3300 					      ? curbuf->b_ffname : curr_fname;
3301 
3302 	    if (inc_opt != NULL && strstr((char *)inc_opt, "\\zs") != NULL)
3303 		// Use text from '\zs' to '\ze' (or end) of 'include'.
3304 		new_fname = find_file_name_in_path(incl_regmatch.startp[0],
3305 		       (int)(incl_regmatch.endp[0] - incl_regmatch.startp[0]),
3306 				 FNAME_EXP|FNAME_INCL|FNAME_REL, 1L, p_fname);
3307 	    else
3308 		// Use text after match with 'include'.
3309 		new_fname = file_name_in_line(incl_regmatch.endp[0], 0,
3310 			     FNAME_EXP|FNAME_INCL|FNAME_REL, 1L, p_fname, NULL);
3311 	    already_searched = FALSE;
3312 	    if (new_fname != NULL)
3313 	    {
3314 		// Check whether we have already searched in this file
3315 		for (i = 0;; i++)
3316 		{
3317 		    if (i == depth + 1)
3318 			i = old_files;
3319 		    if (i == max_path_depth)
3320 			break;
3321 		    if (fullpathcmp(new_fname, files[i].name, TRUE, TRUE)
3322 								    & FPC_SAME)
3323 		    {
3324 			if (type != CHECK_PATH &&
3325 				action == ACTION_SHOW_ALL && files[i].matched)
3326 			{
3327 			    msg_putchar('\n');	    // cursor below last one
3328 			    if (!got_int)	    // don't display if 'q'
3329 						    // typed at "--more--"
3330 						    // message
3331 			    {
3332 				msg_home_replace_hl(new_fname);
3333 				msg_puts(_(" (includes previously listed match)"));
3334 				prev_fname = NULL;
3335 			    }
3336 			}
3337 			VIM_CLEAR(new_fname);
3338 			already_searched = TRUE;
3339 			break;
3340 		    }
3341 		}
3342 	    }
3343 
3344 	    if (type == CHECK_PATH && (action == ACTION_SHOW_ALL
3345 				 || (new_fname == NULL && !already_searched)))
3346 	    {
3347 		if (did_show)
3348 		    msg_putchar('\n');	    // cursor below last one
3349 		else
3350 		{
3351 		    gotocmdline(TRUE);	    // cursor at status line
3352 		    msg_puts_title(_("--- Included files "));
3353 		    if (action != ACTION_SHOW_ALL)
3354 			msg_puts_title(_("not found "));
3355 		    msg_puts_title(_("in path ---\n"));
3356 		}
3357 		did_show = TRUE;
3358 		while (depth_displayed < depth && !got_int)
3359 		{
3360 		    ++depth_displayed;
3361 		    for (i = 0; i < depth_displayed; i++)
3362 			msg_puts("  ");
3363 		    msg_home_replace(files[depth_displayed].name);
3364 		    msg_puts(" -->\n");
3365 		}
3366 		if (!got_int)		    // don't display if 'q' typed
3367 					    // for "--more--" message
3368 		{
3369 		    for (i = 0; i <= depth_displayed; i++)
3370 			msg_puts("  ");
3371 		    if (new_fname != NULL)
3372 		    {
3373 			// using "new_fname" is more reliable, e.g., when
3374 			// 'includeexpr' is set.
3375 			msg_outtrans_attr(new_fname, HL_ATTR(HLF_D));
3376 		    }
3377 		    else
3378 		    {
3379 			/*
3380 			 * Isolate the file name.
3381 			 * Include the surrounding "" or <> if present.
3382 			 */
3383 			if (inc_opt != NULL
3384 				   && strstr((char *)inc_opt, "\\zs") != NULL)
3385 			{
3386 			    // pattern contains \zs, use the match
3387 			    p = incl_regmatch.startp[0];
3388 			    i = (int)(incl_regmatch.endp[0]
3389 						   - incl_regmatch.startp[0]);
3390 			}
3391 			else
3392 			{
3393 			    // find the file name after the end of the match
3394 			    for (p = incl_regmatch.endp[0];
3395 						  *p && !vim_isfilec(*p); p++)
3396 				;
3397 			    for (i = 0; vim_isfilec(p[i]); i++)
3398 				;
3399 			}
3400 
3401 			if (i == 0)
3402 			{
3403 			    // Nothing found, use the rest of the line.
3404 			    p = incl_regmatch.endp[0];
3405 			    i = (int)STRLEN(p);
3406 			}
3407 			// Avoid checking before the start of the line, can
3408 			// happen if \zs appears in the regexp.
3409 			else if (p > line)
3410 			{
3411 			    if (p[-1] == '"' || p[-1] == '<')
3412 			    {
3413 				--p;
3414 				++i;
3415 			    }
3416 			    if (p[i] == '"' || p[i] == '>')
3417 				++i;
3418 			}
3419 			save_char = p[i];
3420 			p[i] = NUL;
3421 			msg_outtrans_attr(p, HL_ATTR(HLF_D));
3422 			p[i] = save_char;
3423 		    }
3424 
3425 		    if (new_fname == NULL && action == ACTION_SHOW_ALL)
3426 		    {
3427 			if (already_searched)
3428 			    msg_puts(_("  (Already listed)"));
3429 			else
3430 			    msg_puts(_("  NOT FOUND"));
3431 		    }
3432 		}
3433 		out_flush();	    // output each line directly
3434 	    }
3435 
3436 	    if (new_fname != NULL)
3437 	    {
3438 		// Push the new file onto the file stack
3439 		if (depth + 1 == old_files)
3440 		{
3441 		    bigger = ALLOC_MULT(SearchedFile, max_path_depth * 2);
3442 		    if (bigger != NULL)
3443 		    {
3444 			for (i = 0; i <= depth; i++)
3445 			    bigger[i] = files[i];
3446 			for (i = depth + 1; i < old_files + max_path_depth; i++)
3447 			{
3448 			    bigger[i].fp = NULL;
3449 			    bigger[i].name = NULL;
3450 			    bigger[i].lnum = 0;
3451 			    bigger[i].matched = FALSE;
3452 			}
3453 			for (i = old_files; i < max_path_depth; i++)
3454 			    bigger[i + max_path_depth] = files[i];
3455 			old_files += max_path_depth;
3456 			max_path_depth *= 2;
3457 			vim_free(files);
3458 			files = bigger;
3459 		    }
3460 		}
3461 		if ((files[depth + 1].fp = mch_fopen((char *)new_fname, "r"))
3462 								    == NULL)
3463 		    vim_free(new_fname);
3464 		else
3465 		{
3466 		    if (++depth == old_files)
3467 		    {
3468 			/*
3469 			 * lalloc() for 'bigger' must have failed above.  We
3470 			 * will forget one of our already visited files now.
3471 			 */
3472 			vim_free(files[old_files].name);
3473 			++old_files;
3474 		    }
3475 		    files[depth].name = curr_fname = new_fname;
3476 		    files[depth].lnum = 0;
3477 		    files[depth].matched = FALSE;
3478 		    if (action == ACTION_EXPAND)
3479 		    {
3480 			msg_hist_off = TRUE;	// reset in msg_trunc_attr()
3481 			vim_snprintf((char*)IObuff, IOSIZE,
3482 				_("Scanning included file: %s"),
3483 				(char *)new_fname);
3484 			msg_trunc_attr((char *)IObuff, TRUE, HL_ATTR(HLF_R));
3485 		    }
3486 		    else if (p_verbose >= 5)
3487 		    {
3488 			verbose_enter();
3489 			smsg(_("Searching included file %s"),
3490 							   (char *)new_fname);
3491 			verbose_leave();
3492 		    }
3493 
3494 		}
3495 	    }
3496 	}
3497 	else
3498 	{
3499 	    /*
3500 	     * Check if the line is a define (type == FIND_DEFINE)
3501 	     */
3502 	    p = line;
3503 search_line:
3504 	    define_matched = FALSE;
3505 	    if (def_regmatch.regprog != NULL
3506 			      && vim_regexec(&def_regmatch, line, (colnr_T)0))
3507 	    {
3508 		/*
3509 		 * Pattern must be first identifier after 'define', so skip
3510 		 * to that position before checking for match of pattern.  Also
3511 		 * don't let it match beyond the end of this identifier.
3512 		 */
3513 		p = def_regmatch.endp[0];
3514 		while (*p && !vim_iswordc(*p))
3515 		    p++;
3516 		define_matched = TRUE;
3517 	    }
3518 
3519 	    /*
3520 	     * Look for a match.  Don't do this if we are looking for a
3521 	     * define and this line didn't match define_prog above.
3522 	     */
3523 	    if (def_regmatch.regprog == NULL || define_matched)
3524 	    {
3525 		if (define_matched || (compl_cont_status & CONT_SOL))
3526 		{
3527 		    // compare the first "len" chars from "ptr"
3528 		    startp = skipwhite(p);
3529 		    if (p_ic)
3530 			matched = !MB_STRNICMP(startp, ptr, len);
3531 		    else
3532 			matched = !STRNCMP(startp, ptr, len);
3533 		    if (matched && define_matched && whole
3534 						  && vim_iswordc(startp[len]))
3535 			matched = FALSE;
3536 		}
3537 		else if (regmatch.regprog != NULL
3538 			 && vim_regexec(&regmatch, line, (colnr_T)(p - line)))
3539 		{
3540 		    matched = TRUE;
3541 		    startp = regmatch.startp[0];
3542 		    /*
3543 		     * Check if the line is not a comment line (unless we are
3544 		     * looking for a define).  A line starting with "# define"
3545 		     * is not considered to be a comment line.
3546 		     */
3547 		    if (!define_matched && skip_comments)
3548 		    {
3549 			if ((*line != '#' ||
3550 				STRNCMP(skipwhite(line + 1), "define", 6) != 0)
3551 				&& get_leader_len(line, NULL, FALSE, TRUE))
3552 			    matched = FALSE;
3553 
3554 			/*
3555 			 * Also check for a "/ *" or "/ /" before the match.
3556 			 * Skips lines like "int backwards;  / * normal index
3557 			 * * /" when looking for "normal".
3558 			 * Note: Doesn't skip "/ *" in comments.
3559 			 */
3560 			p = skipwhite(line);
3561 			if (matched
3562 				|| (p[0] == '/' && p[1] == '*') || p[0] == '*')
3563 			    for (p = line; *p && p < startp; ++p)
3564 			    {
3565 				if (matched
3566 					&& p[0] == '/'
3567 					&& (p[1] == '*' || p[1] == '/'))
3568 				{
3569 				    matched = FALSE;
3570 				    // After "//" all text is comment
3571 				    if (p[1] == '/')
3572 					break;
3573 				    ++p;
3574 				}
3575 				else if (!matched && p[0] == '*' && p[1] == '/')
3576 				{
3577 				    // Can find match after "* /".
3578 				    matched = TRUE;
3579 				    ++p;
3580 				}
3581 			    }
3582 		    }
3583 		}
3584 	    }
3585 	}
3586 	if (matched)
3587 	{
3588 	    if (action == ACTION_EXPAND)
3589 	    {
3590 		int	cont_s_ipos = FALSE;
3591 		int	add_r;
3592 		char_u	*aux;
3593 
3594 		if (depth == -1 && lnum == curwin->w_cursor.lnum)
3595 		    break;
3596 		found = TRUE;
3597 		aux = p = startp;
3598 		if (compl_cont_status & CONT_ADDING)
3599 		{
3600 		    p += compl_length;
3601 		    if (vim_iswordp(p))
3602 			goto exit_matched;
3603 		    p = find_word_start(p);
3604 		}
3605 		p = find_word_end(p);
3606 		i = (int)(p - aux);
3607 
3608 		if ((compl_cont_status & CONT_ADDING) && i == compl_length)
3609 		{
3610 		    // IOSIZE > compl_length, so the STRNCPY works
3611 		    STRNCPY(IObuff, aux, i);
3612 
3613 		    // Get the next line: when "depth" < 0  from the current
3614 		    // buffer, otherwise from the included file.  Jump to
3615 		    // exit_matched when past the last line.
3616 		    if (depth < 0)
3617 		    {
3618 			if (lnum >= end_lnum)
3619 			    goto exit_matched;
3620 			line = ml_get(++lnum);
3621 		    }
3622 		    else if (vim_fgets(line = file_line,
3623 						      LSIZE, files[depth].fp))
3624 			goto exit_matched;
3625 
3626 		    // we read a line, set "already" to check this "line" later
3627 		    // if depth >= 0 we'll increase files[depth].lnum far
3628 		    // bellow  -- Acevedo
3629 		    already = aux = p = skipwhite(line);
3630 		    p = find_word_start(p);
3631 		    p = find_word_end(p);
3632 		    if (p > aux)
3633 		    {
3634 			if (*aux != ')' && IObuff[i-1] != TAB)
3635 			{
3636 			    if (IObuff[i-1] != ' ')
3637 				IObuff[i++] = ' ';
3638 			    // IObuf =~ "\(\k\|\i\).* ", thus i >= 2
3639 			    if (p_js
3640 				&& (IObuff[i-2] == '.'
3641 				    || (vim_strchr(p_cpo, CPO_JOINSP) == NULL
3642 					&& (IObuff[i-2] == '?'
3643 					    || IObuff[i-2] == '!'))))
3644 				IObuff[i++] = ' ';
3645 			}
3646 			// copy as much as possible of the new word
3647 			if (p - aux >= IOSIZE - i)
3648 			    p = aux + IOSIZE - i - 1;
3649 			STRNCPY(IObuff + i, aux, p - aux);
3650 			i += (int)(p - aux);
3651 			cont_s_ipos = TRUE;
3652 		    }
3653 		    IObuff[i] = NUL;
3654 		    aux = IObuff;
3655 
3656 		    if (i == compl_length)
3657 			goto exit_matched;
3658 		}
3659 
3660 		add_r = ins_compl_add_infercase(aux, i, p_ic,
3661 			curr_fname == curbuf->b_fname ? NULL : curr_fname,
3662 			dir, cont_s_ipos);
3663 		if (add_r == OK)
3664 		    // if dir was BACKWARD then honor it just once
3665 		    dir = FORWARD;
3666 		else if (add_r == FAIL)
3667 		    break;
3668 	    }
3669 	    else if (action == ACTION_SHOW_ALL)
3670 	    {
3671 		found = TRUE;
3672 		if (!did_show)
3673 		    gotocmdline(TRUE);		// cursor at status line
3674 		if (curr_fname != prev_fname)
3675 		{
3676 		    if (did_show)
3677 			msg_putchar('\n');	// cursor below last one
3678 		    if (!got_int)		// don't display if 'q' typed
3679 						// at "--more--" message
3680 			msg_home_replace_hl(curr_fname);
3681 		    prev_fname = curr_fname;
3682 		}
3683 		did_show = TRUE;
3684 		if (!got_int)
3685 		    show_pat_in_path(line, type, TRUE, action,
3686 			    (depth == -1) ? NULL : files[depth].fp,
3687 			    (depth == -1) ? &lnum : &files[depth].lnum,
3688 			    match_count++);
3689 
3690 		// Set matched flag for this file and all the ones that
3691 		// include it
3692 		for (i = 0; i <= depth; ++i)
3693 		    files[i].matched = TRUE;
3694 	    }
3695 	    else if (--count <= 0)
3696 	    {
3697 		found = TRUE;
3698 		if (depth == -1 && lnum == curwin->w_cursor.lnum
3699 #if defined(FEAT_QUICKFIX)
3700 						      && g_do_tagpreview == 0
3701 #endif
3702 						      )
3703 		    emsg(_("E387: Match is on current line"));
3704 		else if (action == ACTION_SHOW)
3705 		{
3706 		    show_pat_in_path(line, type, did_show, action,
3707 			(depth == -1) ? NULL : files[depth].fp,
3708 			(depth == -1) ? &lnum : &files[depth].lnum, 1L);
3709 		    did_show = TRUE;
3710 		}
3711 		else
3712 		{
3713 #ifdef FEAT_GUI
3714 		    need_mouse_correct = TRUE;
3715 #endif
3716 #if defined(FEAT_QUICKFIX)
3717 		    // ":psearch" uses the preview window
3718 		    if (g_do_tagpreview != 0)
3719 		    {
3720 			curwin_save = curwin;
3721 			prepare_tagpreview(TRUE, TRUE, FALSE);
3722 		    }
3723 #endif
3724 		    if (action == ACTION_SPLIT)
3725 		    {
3726 			if (win_split(0, 0) == FAIL)
3727 			    break;
3728 			RESET_BINDING(curwin);
3729 		    }
3730 		    if (depth == -1)
3731 		    {
3732 			// match in current file
3733 #if defined(FEAT_QUICKFIX)
3734 			if (g_do_tagpreview != 0)
3735 			{
3736 			    if (!GETFILE_SUCCESS(getfile(
3737 					   curwin_save->w_buffer->b_fnum, NULL,
3738 						     NULL, TRUE, lnum, FALSE)))
3739 				break;	// failed to jump to file
3740 			}
3741 			else
3742 #endif
3743 			    setpcmark();
3744 			curwin->w_cursor.lnum = lnum;
3745 			check_cursor();
3746 		    }
3747 		    else
3748 		    {
3749 			if (!GETFILE_SUCCESS(getfile(
3750 					0, files[depth].name, NULL, TRUE,
3751 						    files[depth].lnum, FALSE)))
3752 			    break;	// failed to jump to file
3753 			// autocommands may have changed the lnum, we don't
3754 			// want that here
3755 			curwin->w_cursor.lnum = files[depth].lnum;
3756 		    }
3757 		}
3758 		if (action != ACTION_SHOW)
3759 		{
3760 		    curwin->w_cursor.col = (colnr_T)(startp - line);
3761 		    curwin->w_set_curswant = TRUE;
3762 		}
3763 
3764 #if defined(FEAT_QUICKFIX)
3765 		if (g_do_tagpreview != 0
3766 			   && curwin != curwin_save && win_valid(curwin_save))
3767 		{
3768 		    // Return cursor to where we were
3769 		    validate_cursor();
3770 		    redraw_later(VALID);
3771 		    win_enter(curwin_save, TRUE);
3772 		}
3773 # ifdef FEAT_PROP_POPUP
3774 		else if (WIN_IS_POPUP(curwin))
3775 		    // can't keep focus in popup window
3776 		    win_enter(firstwin, TRUE);
3777 # endif
3778 #endif
3779 		break;
3780 	    }
3781 exit_matched:
3782 	    matched = FALSE;
3783 	    // look for other matches in the rest of the line if we
3784 	    // are not at the end of it already
3785 	    if (def_regmatch.regprog == NULL
3786 		    && action == ACTION_EXPAND
3787 		    && !(compl_cont_status & CONT_SOL)
3788 		    && *startp != NUL
3789 		    && *(p = startp + mb_ptr2len(startp)) != NUL)
3790 		goto search_line;
3791 	}
3792 	line_breakcheck();
3793 	if (action == ACTION_EXPAND)
3794 	    ins_compl_check_keys(30, FALSE);
3795 	if (got_int || ins_compl_interrupted())
3796 	    break;
3797 
3798 	/*
3799 	 * Read the next line.  When reading an included file and encountering
3800 	 * end-of-file, close the file and continue in the file that included
3801 	 * it.
3802 	 */
3803 	while (depth >= 0 && !already
3804 		&& vim_fgets(line = file_line, LSIZE, files[depth].fp))
3805 	{
3806 	    fclose(files[depth].fp);
3807 	    --old_files;
3808 	    files[old_files].name = files[depth].name;
3809 	    files[old_files].matched = files[depth].matched;
3810 	    --depth;
3811 	    curr_fname = (depth == -1) ? curbuf->b_fname
3812 				       : files[depth].name;
3813 	    if (depth < depth_displayed)
3814 		depth_displayed = depth;
3815 	}
3816 	if (depth >= 0)		// we could read the line
3817 	{
3818 	    files[depth].lnum++;
3819 	    // Remove any CR and LF from the line.
3820 	    i = (int)STRLEN(line);
3821 	    if (i > 0 && line[i - 1] == '\n')
3822 		line[--i] = NUL;
3823 	    if (i > 0 && line[i - 1] == '\r')
3824 		line[--i] = NUL;
3825 	}
3826 	else if (!already)
3827 	{
3828 	    if (++lnum > end_lnum)
3829 		break;
3830 	    line = ml_get(lnum);
3831 	}
3832 	already = NULL;
3833     }
3834     // End of big for (;;) loop.
3835 
3836     // Close any files that are still open.
3837     for (i = 0; i <= depth; i++)
3838     {
3839 	fclose(files[i].fp);
3840 	vim_free(files[i].name);
3841     }
3842     for (i = old_files; i < max_path_depth; i++)
3843 	vim_free(files[i].name);
3844     vim_free(files);
3845 
3846     if (type == CHECK_PATH)
3847     {
3848 	if (!did_show)
3849 	{
3850 	    if (action != ACTION_SHOW_ALL)
3851 		msg(_("All included files were found"));
3852 	    else
3853 		msg(_("No included files"));
3854 	}
3855     }
3856     else if (!found && action != ACTION_EXPAND)
3857     {
3858 	if (got_int || ins_compl_interrupted())
3859 	    emsg(_(e_interr));
3860 	else if (type == FIND_DEFINE)
3861 	    emsg(_("E388: Couldn't find definition"));
3862 	else
3863 	    emsg(_("E389: Couldn't find pattern"));
3864     }
3865     if (action == ACTION_SHOW || action == ACTION_SHOW_ALL)
3866 	msg_end();
3867 
3868 fpip_end:
3869     vim_free(file_line);
3870     vim_regfree(regmatch.regprog);
3871     vim_regfree(incl_regmatch.regprog);
3872     vim_regfree(def_regmatch.regprog);
3873 }
3874 
3875     static void
3876 show_pat_in_path(
3877     char_u  *line,
3878     int	    type,
3879     int	    did_show,
3880     int	    action,
3881     FILE    *fp,
3882     linenr_T *lnum,
3883     long    count)
3884 {
3885     char_u  *p;
3886 
3887     if (did_show)
3888 	msg_putchar('\n');	// cursor below last one
3889     else if (!msg_silent)
3890 	gotocmdline(TRUE);	// cursor at status line
3891     if (got_int)		// 'q' typed at "--more--" message
3892 	return;
3893     for (;;)
3894     {
3895 	p = line + STRLEN(line) - 1;
3896 	if (fp != NULL)
3897 	{
3898 	    // We used fgets(), so get rid of newline at end
3899 	    if (p >= line && *p == '\n')
3900 		--p;
3901 	    if (p >= line && *p == '\r')
3902 		--p;
3903 	    *(p + 1) = NUL;
3904 	}
3905 	if (action == ACTION_SHOW_ALL)
3906 	{
3907 	    sprintf((char *)IObuff, "%3ld: ", count);	// show match nr
3908 	    msg_puts((char *)IObuff);
3909 	    sprintf((char *)IObuff, "%4ld", *lnum);	// show line nr
3910 						// Highlight line numbers
3911 	    msg_puts_attr((char *)IObuff, HL_ATTR(HLF_N));
3912 	    msg_puts(" ");
3913 	}
3914 	msg_prt_line(line, FALSE);
3915 	out_flush();			// show one line at a time
3916 
3917 	// Definition continues until line that doesn't end with '\'
3918 	if (got_int || type != FIND_DEFINE || p < line || *p != '\\')
3919 	    break;
3920 
3921 	if (fp != NULL)
3922 	{
3923 	    if (vim_fgets(line, LSIZE, fp)) // end of file
3924 		break;
3925 	    ++*lnum;
3926 	}
3927 	else
3928 	{
3929 	    if (++*lnum > curbuf->b_ml.ml_line_count)
3930 		break;
3931 	    line = ml_get(*lnum);
3932 	}
3933 	msg_putchar('\n');
3934     }
3935 }
3936 #endif
3937 
3938 #ifdef FEAT_VIMINFO
3939 /*
3940  * Return the last used search pattern at "idx".
3941  */
3942     spat_T *
3943 get_spat(int idx)
3944 {
3945     return &spats[idx];
3946 }
3947 
3948 /*
3949  * Return the last used search pattern index.
3950  */
3951     int
3952 get_spat_last_idx(void)
3953 {
3954     return last_idx;
3955 }
3956 #endif
3957