/* vi:set ts=8 sts=4 sw=4: * * VIM - Vi IMproved by Bram Moolenaar * * Do ":help uganda" in Vim to read copying and usage conditions. * Do ":help credits" in Vim to see a list of people who contributed. * See README.txt for an overview of the Vim source code. *//* * search.c: code for normal mode searching commands */ #include "vim.h" static void save_re_pat __ARGS((int idx, char_u *pat, int magic));#ifdef FEAT_EVALstatic int first_submatch __ARGS((regmmatch_T *rp));#endifstatic int check_prevcol __ARGS((char_u *linep, int col, int ch, int *prevcol));static int inmacro __ARGS((char_u *, char_u *));static int check_linecomment __ARGS((char_u *line));static int cls __ARGS((void));static int skip_chars __ARGS((int, int));#ifdef FEAT_TEXTOBJstatic void back_in_line __ARGS((void));static void find_first_blank __ARGS((pos_T *));static void findsent_forward __ARGS((long count, int at_start_sent));#endif#ifdef FEAT_FIND_IDstatic void show_pat_in_path __ARGS((char_u *, int, int, int, FILE *, linenr_T *, long));#endif#ifdef FEAT_VIMINFOstatic void wvsp_one __ARGS((FILE *fp, int idx, char *s, int sc));#endif /* * This file contains various searching-related routines. These fall into * three groups: * 1. string searches (for /, ?, n, and N) * 2. character searches within a single line (for f, F, t, T, etc) * 3. "other" kinds of searches like the '%' command, and 'word' searches. */ /* * String searches * * The string search functions are divided into two levels: * lowest: searchit(); uses an pos_T for starting position and found match. * Highest: do_search(); uses curwin->w_cursor; calls searchit(). * * The last search pattern is remembered for repeating the same search. * This pattern is shared between the :g, :s, ? and / commands. * This is in search_regcomp(). * * The actual string matching is done using a heavily modified version of * Henry Spencer's regular expression library. See regexp.c. */ /* The offset for a search command is store in a soff struct *//* Note: only spats[0].off is really used */struct soffset{ int dir; /* search direction */ int line; /* search has line offset */ int end; /* search set cursor at end */ long off; /* line or char offset */}; /* A search pattern and its attributes are stored in a spat struct */struct spat{ char_u *pat; /* the pattern (in allocated memory) or NULL */ int magic; /* magicness of the pattern */ int no_scs; /* no smarcase for this pattern */ struct soffset off;}; /* * Two search patterns are remembered: One for the :substitute command and * one for other searches. last_idx points to the one that was used the last * time. */static struct spat spats[2] ={ {NULL, TRUE, FALSE, {'/', 0, 0, 0L}}, /* last used search pat */ {NULL, TRUE, FALSE, {'/', 0, 0, 0L}} /* last used substitute pat */}; static int last_idx = 0; /* index in spats[] for RE_LAST */ #if defined(FEAT_AUTOCMD) || defined(FEAT_EVAL) || defined(PROTO)/* copy of spats[], for keeping the search patterns while executing autocmds */static struct spat saved_spats[2];static int saved_last_idx = 0;# ifdef FEAT_SEARCH_EXTRAstatic int saved_no_hlsearch = 0;# endif#endif static char_u *mr_pattern = NULL; /* pattern used by search_regcomp() */#ifdef FEAT_RIGHTLEFTstatic int mr_pattern_alloced = FALSE; /* mr_pattern was allocated */static char_u *reverse_text __ARGS((char_u *s));#endif #ifdef FEAT_FIND_ID/* * Type used by find_pattern_in_path() to remember which included files have * been searched already. */typedef struct SearchedFile{ FILE *fp; /* File pointer */ char_u *name; /* Full name of file */ linenr_T lnum; /* Line we were up to in file */ int matched; /* Found a match in this file */} SearchedFile;#endif /* * translate search pattern for vim_regcomp() * * pat_save == RE_SEARCH: save pat in spats[RE_SEARCH].pat (normal search cmd) * pat_save == RE_SUBST: save pat in spats[RE_SUBST].pat (:substitute command) * pat_save == RE_BOTH: save pat in both patterns (:global command) * pat_use == RE_SEARCH: use previous search pattern if "pat" is NULL * pat_use == RE_SUBST: use previous substitute pattern if "pat" is NULL * pat_use == RE_LAST: use last used pattern if "pat" is NULL * options & SEARCH_HIS: put search string in history * options & SEARCH_KEEP: keep previous search pattern * * returns FAIL if failed, OK otherwise. */ intsearch_regcomp(pat, pat_save, pat_use, options, regmatch) char_u *pat; int pat_save; int pat_use; int options; regmmatch_T *regmatch; /* return: pattern and ignore-case flag */{ int magic; int i; rc_did_emsg = FALSE; magic = p_magic; /* * If no pattern given, use a previously defined pattern. */ if (pat == NULL || *pat == NUL) { if (pat_use == RE_LAST) i = last_idx; else i = pat_use; if (spats[i].pat == NULL) /* pattern was never defined */ { if (pat_use == RE_SUBST) EMSG(_(e_nopresub)); else EMSG(_(e_noprevre)); rc_did_emsg = TRUE; return FAIL; } pat = spats[i].pat; magic = spats[i].magic; no_smartcase = spats[i].no_scs; }#ifdef FEAT_CMDHIST else if (options & SEARCH_HIS) /* put new pattern in history */ add_to_history(HIST_SEARCH, pat, TRUE, NUL);#endif #ifdef FEAT_RIGHTLEFT if (mr_pattern_alloced) { vim_free(mr_pattern); mr_pattern_alloced = FALSE; } if (curwin->w_p_rl && *curwin->w_p_rlc == 's') { char_u *rev_pattern; rev_pattern = reverse_text(pat); if (rev_pattern == NULL) mr_pattern = pat; /* out of memory, keep normal pattern. */ else { mr_pattern = rev_pattern; mr_pattern_alloced = TRUE; } } else#endif mr_pattern = pat; /* * Save the currently used pattern in the appropriate place, * unless the pattern should not be remembered. */ if (!(options & SEARCH_KEEP)) { /* search or global command */ if (pat_save == RE_SEARCH || pat_save == RE_BOTH) save_re_pat(RE_SEARCH, pat, magic); /* substitute or global command */ if (pat_save == RE_SUBST || pat_save == RE_BOTH) save_re_pat(RE_SUBST, pat, magic); } regmatch->rmm_ic = ignorecase(pat); regmatch->rmm_maxcol = 0; regmatch->regprog = vim_regcomp(pat, magic ? RE_MAGIC : 0); if (regmatch->regprog == NULL) return FAIL; return OK;} /* * Get search pattern used by search_regcomp(). */ char_u *get_search_pat(){ return mr_pattern;} #ifdef FEAT_RIGHTLEFT/* * Reverse text into allocated memory. * Returns the allocated string, NULL when out of memory. */ static char_u *reverse_text(s) char_u *s;{ unsigned len; unsigned s_i, rev_i; char_u *rev; /* * Reverse the pattern. */ len = (unsigned)STRLEN(s); rev = alloc(len + 1); if (rev != NULL) { rev_i = len; for (s_i = 0; s_i < len; ++s_i) {# ifdef FEAT_MBYTE if (has_mbyte) { int mb_len; mb_len = (*mb_ptr2len)(s + s_i); rev_i -= mb_len; mch_memmove(rev + rev_i, s + s_i, mb_len); s_i += mb_len - 1; } else# endif rev[--rev_i] = s[s_i]; } rev[len] = NUL; } return rev;}#endif static voidsave_re_pat(idx, pat, magic) int idx; char_u *pat; int magic;{ if (spats[idx].pat != pat) { vim_free(spats[idx].pat); spats[idx].pat = vim_strsave(pat); spats[idx].magic = magic; spats[idx].no_scs = no_smartcase; last_idx = idx;#ifdef FEAT_SEARCH_EXTRA /* If 'hlsearch' set and search pat changed: need redraw. */ if (p_hls) redraw_all_later(SOME_VALID); no_hlsearch = FALSE;#endif }} #if defined(FEAT_AUTOCMD) || defined(FEAT_EVAL) || defined(PROTO)/* * Save the search patterns, so they can be restored later. * Used before/after executing autocommands and user functions. */static int save_level = 0; voidsave_search_patterns(){ if (save_level++ == 0) { saved_spats[0] = spats[0]; if (spats[0].pat != NULL) saved_spats[0].pat = vim_strsave(spats[0].pat); saved_spats[1] = spats[1]; if (spats[1].pat != NULL) saved_spats[1].pat = vim_strsave(spats[1].pat); saved_last_idx = last_idx;# ifdef FEAT_SEARCH_EXTRA saved_no_hlsearch = no_hlsearch;# endif }} voidrestore_search_patterns(){ if (--save_level == 0) { vim_free(spats[0].pat); spats[0] = saved_spats[0]; vim_free(spats[1].pat); spats[1] = saved_spats[1]; last_idx = saved_last_idx;# ifdef FEAT_SEARCH_EXTRA no_hlsearch = saved_no_hlsearch;# endif }}#endif #if defined(EXITFREE) || defined(PROTO) voidfree_search_patterns(){ vim_free(spats[0].pat); vim_free(spats[1].pat);}#endif /* * Return TRUE when case should be ignored for search pattern "pat". * Uses the 'ignorecase' and 'smartcase' options. */ intignorecase(pat) char_u *pat;{ char_u *p; int ic; ic = p_ic; if (ic && !no_smartcase && p_scs#ifdef FEAT_INS_EXPAND && !(ctrl_x_mode && curbuf->b_p_inf)#endif ) { /* don't ignore case if pattern has uppercase */ for (p = pat; *p; ) {#ifdef FEAT_MBYTE int l; if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) { if (enc_utf8 && utf_isupper(utf_ptr2char(p))) { ic = FALSE; break; } p += l; } else#endif if (*p == '\\' && p[1] != NUL) /* skip "\S" et al. */ p += 2; else if (isupper(*p)) { ic = FALSE; break; } else ++p; } } no_smartcase = FALSE; return ic;} char_u *last_search_pat(){ return spats[last_idx].pat;} /* * Reset search direction to forward. For "gd" and "gD" commands. */ voidreset_search_dir(){ spats[0].off.dir = '/';} #if defined(FEAT_EVAL) || defined(FEAT_VIMINFO)/* * Set the last search pattern. For ":let @/ =" and viminfo. * Also set the saved search pattern, so that this works in an autocommand. */ voidset_last_search_pat(s, idx, magic, setlast) char_u *s; int idx; int magic; int setlast;{ vim_free(spats[idx].pat); /* An empty string means that nothing should be matched. */ if (*s == NUL) spats[idx].pat = NULL; else spats[idx].pat = vim_strsave(s); spats[idx].magic = magic; spats[idx].no_scs = FALSE; spats[idx].off.dir = '/'; spats[idx].off.line = FALSE; spats[idx].off.end = FALSE; spats[idx].off.off = 0; if (setlast) last_idx = idx; if (save_level) { vim_free(saved_spats[idx].pat); saved_spats[idx] = spats[0]; if (spats[idx].pat == NULL) saved_spats[idx].pat = NULL; else saved_spats[idx].pat = vim_strsave(spats[idx].pat); saved_last_idx = last_idx; }# ifdef FEAT_SEARCH_EXTRA /* If 'hlsearch' set and search pat changed: need redraw. */ if (p_hls && idx == last_idx && !no_hlsearch) redraw_all_later(SOME_VALID);# endif}#endif #ifdef FEAT_SEARCH_EXTRA/* * Get a regexp program for the last used search pattern. * This is used for highlighting all matches in a window. * Values returned in regmatch->regprog and regmatch->rmm_ic. */ voidlast_pat_prog(regmatch) regmmatch_T *regmatch;{ if (spats[last_idx].pat == NULL) { regmatch->regprog = NULL; return; } ++emsg_off; /* So it doesn't beep if bad expr */ (void)search_regcomp((char_u *)"", 0, last_idx, SEARCH_KEEP, regmatch); --emsg_off;}#endif /* * lowest level search function. * Search for 'count'th occurrence of pattern 'pat' in direction 'dir'. * Start at position 'pos' and return the found position in 'pos'. * * if (options & SEARCH_MSG) == 0 don't give any messages * if (options & SEARCH_MSG) == SEARCH_NFMSG don't give 'notfound' messages * if (options & SEARCH_MSG) == SEARCH_MSG give all messages * if (options & SEARCH_HIS) put search pattern in history * if (options & SEARCH_END) return position at end of match * if (options & SEARCH_START) accept match at pos itself * if (options & SEARCH_KEEP) keep previous search pattern * if (options & SEARCH_FOLD) match only once in a closed fold * if (options & SEARCH_PEEK) check for typed char, cancel search * * Return FAIL (zero) for failure, non-zero for success. * When FEAT_EVAL is defined, returns the index of the first matching * subpattern plus one; one if there was none. */ intsearchit(win, buf, pos, dir, pat, count, options, pat_use, stop_lnum) win_T *win; /* window to search in; can be NULL for aLines 1–500 of 5296. Load more
/* vi:set ts=8 sts=4 sw=4: * * VIM - Vi IMproved by Bram Moolenaar * * Do ":help uganda" in Vim to read copying and usage conditions. * Do ":help credits" in Vim to see a list of people who contributed. * See README.txt for an overview of the Vim source code. */ /* * search.c: code for normal mode searching commands */ #include "vim.h" static void save_re_pat __ARGS((int idx, char_u *pat, int magic)); #ifdef FEAT_EVAL static int first_submatch __ARGS((regmmatch_T *rp)); #endif static int check_prevcol __ARGS((char_u *linep, int col, int ch, int *prevcol)); static int inmacro __ARGS((char_u *, char_u *)); static int check_linecomment __ARGS((char_u *line)); static int cls __ARGS((void)); static int skip_chars __ARGS((int, int)); #ifdef FEAT_TEXTOBJ static void back_in_line __ARGS((void)); static void find_first_blank __ARGS((pos_T *)); static void findsent_forward __ARGS((long count, int at_start_sent)); #endif #ifdef FEAT_FIND_ID static void show_pat_in_path __ARGS((char_u *, int, int, int, FILE *, linenr_T *, long)); #endif #ifdef FEAT_VIMINFO static void wvsp_one __ARGS((FILE *fp, int idx, char *s, int sc)); #endif /* * This file contains various searching-related routines. These fall into * three groups: * 1. string searches (for /, ?, n, and N) * 2. character searches within a single line (for f, F, t, T, etc) * 3. "other" kinds of searches like the '%' command, and 'word' searches. */ /* * String searches * * The string search functions are divided into two levels: * lowest: searchit(); uses an pos_T for starting position and found match. * Highest: do_search(); uses curwin->w_cursor; calls searchit(). * * The last search pattern is remembered for repeating the same search. * This pattern is shared between the :g, :s, ? and / commands. * This is in search_regcomp(). * * The actual string matching is done using a heavily modified version of * Henry Spencer's regular expression library. See regexp.c. */ /* The offset for a search command is store in a soff struct */ /* Note: only spats[0].off is really used */ struct soffset { int dir; /* search direction */ int line; /* search has line offset */ int end; /* search set cursor at end */ long off; /* line or char offset */ }; /* A search pattern and its attributes are stored in a spat struct */ struct spat { char_u *pat; /* the pattern (in allocated memory) or NULL */ int magic; /* magicness of the pattern */ int no_scs; /* no smarcase for this pattern */ struct soffset off; }; /* * Two search patterns are remembered: One for the :substitute command and * one for other searches. last_idx points to the one that was used the last * time. */ static struct spat spats[2] = { {NULL, TRUE, FALSE, {'/', 0, 0, 0L}}, /* last used search pat */ {NULL, TRUE, FALSE, {'/', 0, 0, 0L}} /* last used substitute pat */ }; static int last_idx = 0; /* index in spats[] for RE_LAST */ #if defined(FEAT_AUTOCMD) || defined(FEAT_EVAL) || defined(PROTO) /* copy of spats[], for keeping the search patterns while executing autocmds */ static struct spat saved_spats[2]; static int saved_last_idx = 0; # ifdef FEAT_SEARCH_EXTRA static int saved_no_hlsearch = 0; # endif #endif static char_u *mr_pattern = NULL; /* pattern used by search_regcomp() */ #ifdef FEAT_RIGHTLEFT static int mr_pattern_alloced = FALSE; /* mr_pattern was allocated */ static char_u *reverse_text __ARGS((char_u *s)); #endif #ifdef FEAT_FIND_ID /* * Type used by find_pattern_in_path() to remember which included files have * been searched already. */ typedef struct SearchedFile { FILE *fp; /* File pointer */ char_u *name; /* Full name of file */ linenr_T lnum; /* Line we were up to in file */ int matched; /* Found a match in this file */ } SearchedFile; #endif /* * translate search pattern for vim_regcomp() * * pat_save == RE_SEARCH: save pat in spats[RE_SEARCH].pat (normal search cmd) * pat_save == RE_SUBST: save pat in spats[RE_SUBST].pat (:substitute command) * pat_save == RE_BOTH: save pat in both patterns (:global command) * pat_use == RE_SEARCH: use previous search pattern if "pat" is NULL * pat_use == RE_SUBST: use previous substitute pattern if "pat" is NULL * pat_use == RE_LAST: use last used pattern if "pat" is NULL * options & SEARCH_HIS: put search string in history * options & SEARCH_KEEP: keep previous search pattern * * returns FAIL if failed, OK otherwise. */ int search_regcomp(pat, pat_save, pat_use, options, regmatch) char_u *pat; int pat_save; int pat_use; int options; regmmatch_T *regmatch; /* return: pattern and ignore-case flag */ { int magic; int i; rc_did_emsg = FALSE; magic = p_magic; /* * If no pattern given, use a previously defined pattern. */ if (pat == NULL || *pat == NUL) { if (pat_use == RE_LAST) i = last_idx; else i = pat_use; if (spats[i].pat == NULL) /* pattern was never defined */ { if (pat_use == RE_SUBST) EMSG(_(e_nopresub)); else EMSG(_(e_noprevre)); rc_did_emsg = TRUE; return FAIL; } pat = spats[i].pat; magic = spats[i].magic; no_smartcase = spats[i].no_scs; } #ifdef FEAT_CMDHIST else if (options & SEARCH_HIS) /* put new pattern in history */ add_to_history(HIST_SEARCH, pat, TRUE, NUL); #endif #ifdef FEAT_RIGHTLEFT if (mr_pattern_alloced) { vim_free(mr_pattern); mr_pattern_alloced = FALSE; } if (curwin->w_p_rl && *curwin->w_p_rlc == 's') { char_u *rev_pattern; rev_pattern = reverse_text(pat); if (rev_pattern == NULL) mr_pattern = pat; /* out of memory, keep normal pattern. */ else { mr_pattern = rev_pattern; mr_pattern_alloced = TRUE; } } else #endif mr_pattern = pat; /* * Save the currently used pattern in the appropriate place, * unless the pattern should not be remembered. */ if (!(options & SEARCH_KEEP)) { /* search or global command */ if (pat_save == RE_SEARCH || pat_save == RE_BOTH) save_re_pat(RE_SEARCH, pat, magic); /* substitute or global command */ if (pat_save == RE_SUBST || pat_save == RE_BOTH) save_re_pat(RE_SUBST, pat, magic); } regmatch->rmm_ic = ignorecase(pat); regmatch->rmm_maxcol = 0; regmatch->regprog = vim_regcomp(pat, magic ? RE_MAGIC : 0); if (regmatch->regprog == NULL) return FAIL; return OK; } /* * Get search pattern used by search_regcomp(). */ char_u * get_search_pat() { return mr_pattern; } #ifdef FEAT_RIGHTLEFT /* * Reverse text into allocated memory. * Returns the allocated string, NULL when out of memory. */ static char_u * reverse_text(s) char_u *s; { unsigned len; unsigned s_i, rev_i; char_u *rev; /* * Reverse the pattern. */ len = (unsigned)STRLEN(s); rev = alloc(len + 1); if (rev != NULL) { rev_i = len; for (s_i = 0; s_i < len; ++s_i) { # ifdef FEAT_MBYTE if (has_mbyte) { int mb_len; mb_len = (*mb_ptr2len)(s + s_i); rev_i -= mb_len; mch_memmove(rev + rev_i, s + s_i, mb_len); s_i += mb_len - 1; } else # endif rev[--rev_i] = s[s_i]; } rev[len] = NUL; } return rev; } #endif static void save_re_pat(idx, pat, magic) int idx; char_u *pat; int magic; { if (spats[idx].pat != pat) { vim_free(spats[idx].pat); spats[idx].pat = vim_strsave(pat); spats[idx].magic = magic; spats[idx].no_scs = no_smartcase; last_idx = idx; #ifdef FEAT_SEARCH_EXTRA /* If 'hlsearch' set and search pat changed: need redraw. */ if (p_hls) redraw_all_later(SOME_VALID); no_hlsearch = FALSE; #endif } } #if defined(FEAT_AUTOCMD) || defined(FEAT_EVAL) || defined(PROTO) /* * Save the search patterns, so they can be restored later. * Used before/after executing autocommands and user functions. */ static int save_level = 0; void save_search_patterns() { if (save_level++ == 0) { saved_spats[0] = spats[0]; if (spats[0].pat != NULL) saved_spats[0].pat = vim_strsave(spats[0].pat); saved_spats[1] = spats[1]; if (spats[1].pat != NULL) saved_spats[1].pat = vim_strsave(spats[1].pat); saved_last_idx = last_idx; # ifdef FEAT_SEARCH_EXTRA saved_no_hlsearch = no_hlsearch; # endif } } void restore_search_patterns() { if (--save_level == 0) { vim_free(spats[0].pat); spats[0] = saved_spats[0]; vim_free(spats[1].pat); spats[1] = saved_spats[1]; last_idx = saved_last_idx; # ifdef FEAT_SEARCH_EXTRA no_hlsearch = saved_no_hlsearch; # endif } } #endif #if defined(EXITFREE) || defined(PROTO) void free_search_patterns() { vim_free(spats[0].pat); vim_free(spats[1].pat); } #endif /* * Return TRUE when case should be ignored for search pattern "pat". * Uses the 'ignorecase' and 'smartcase' options. */ int ignorecase(pat) char_u *pat; { char_u *p; int ic; ic = p_ic; if (ic && !no_smartcase && p_scs #ifdef FEAT_INS_EXPAND && !(ctrl_x_mode && curbuf->b_p_inf) #endif ) { /* don't ignore case if pattern has uppercase */ for (p = pat; *p; ) { #ifdef FEAT_MBYTE int l; if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) { if (enc_utf8 && utf_isupper(utf_ptr2char(p))) { ic = FALSE; break; } p += l; } else #endif if (*p == '\\' && p[1] != NUL) /* skip "\S" et al. */ p += 2; else if (isupper(*p)) { ic = FALSE; break; } else ++p; } } no_smartcase = FALSE; return ic; } char_u * last_search_pat() { return spats[last_idx].pat; } /* * Reset search direction to forward. For "gd" and "gD" commands. */ void reset_search_dir() { spats[0].off.dir = '/'; } #if defined(FEAT_EVAL) || defined(FEAT_VIMINFO) /* * Set the last search pattern. For ":let @/ =" and viminfo. * Also set the saved search pattern, so that this works in an autocommand. */ void set_last_search_pat(s, idx, magic, setlast) char_u *s; int idx; int magic; int setlast; { vim_free(spats[idx].pat); /* An empty string means that nothing should be matched. */ if (*s == NUL) spats[idx].pat = NULL; else spats[idx].pat = vim_strsave(s); spats[idx].magic = magic; spats[idx].no_scs = FALSE; spats[idx].off.dir = '/'; spats[idx].off.line = FALSE; spats[idx].off.end = FALSE; spats[idx].off.off = 0; if (setlast) last_idx = idx; if (save_level) { vim_free(saved_spats[idx].pat); saved_spats[idx] = spats[0]; if (spats[idx].pat == NULL) saved_spats[idx].pat = NULL; else saved_spats[idx].pat = vim_strsave(spats[idx].pat); saved_last_idx = last_idx; } # ifdef FEAT_SEARCH_EXTRA /* If 'hlsearch' set and search pat changed: need redraw. */ if (p_hls && idx == last_idx && !no_hlsearch) redraw_all_later(SOME_VALID); # endif } #endif #ifdef FEAT_SEARCH_EXTRA /* * Get a regexp program for the last used search pattern. * This is used for highlighting all matches in a window. * Values returned in regmatch->regprog and regmatch->rmm_ic. */ void last_pat_prog(regmatch) regmmatch_T *regmatch; { if (spats[last_idx].pat == NULL) { regmatch->regprog = NULL; return; } ++emsg_off; /* So it doesn't beep if bad expr */ (void)search_regcomp((char_u *)"", 0, last_idx, SEARCH_KEEP, regmatch); --emsg_off; } #endif /* * lowest level search function. * Search for 'count'th occurrence of pattern 'pat' in direction 'dir'. * Start at position 'pos' and return the found position in 'pos'. * * if (options & SEARCH_MSG) == 0 don't give any messages * if (options & SEARCH_MSG) == SEARCH_NFMSG don't give 'notfound' messages * if (options & SEARCH_MSG) == SEARCH_MSG give all messages * if (options & SEARCH_HIS) put search pattern in history * if (options & SEARCH_END) return position at end of match * if (options & SEARCH_START) accept match at pos itself * if (options & SEARCH_KEEP) keep previous search pattern * if (options & SEARCH_FOLD) match only once in a closed fold * if (options & SEARCH_PEEK) check for typed char, cancel search * * Return FAIL (zero) for failure, non-zero for success. * When FEAT_EVAL is defined, returns the index of the first matching * subpattern plus one; one if there was none. */ int searchit(win, buf, pos, dir, pat, count, options, pat_use, stop_lnum) win_T *win; /* window to search in; can be NULL for a