# HG changeset patch # User vimboss # Date 1200754798 0 # Node ID cc4fe241baa3596ae9cd27ce65ad25077bfb2e71 # Parent cd6175cc27d9c8b4d4f4dadc7c38f6c490f3fa62 updated for version 7.1-236 diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -3618,6 +3618,7 @@ A jump table for the options with a shor When you get bored looking at the highlighted matches, you can turn it off with |:nohlsearch|. As soon as you use a search command, the highlighting comes back. + 'redrawtime' specifies the maximum time spend on finding matches. When the search pattern can match an end-of-line, Vim will try to highlight all of the matched text. However, this depends on where the search starts. This will be the first line in the window or the first @@ -3851,6 +3852,10 @@ A jump table for the options with a shor original position when no match is found and when pressing . You still need to finish the search command with to move the cursor to the match. + When compiled with the |+reltime| feature Vim only searches for about + half a second. With a complicated pattern and/or a lot of text the + match may not be found. This is to avoid that Vim hangs while you + are typing the pattern. The highlighting can be set with the 'i' flag in 'highlight'. See also: 'hlsearch'. CTRL-L can be used to add one character from after the current match @@ -5185,6 +5190,18 @@ A jump table for the options with a shor {not in Vi:} When using the ":view" command the 'readonly' option is set for the newly edited buffer. + *'redrawtime'* *'rdt'* +'redrawtime' 'rdt' number (default 2000) + global + {not in Vi} + {only available when compiled with the |+reltime| + feature} + The time in milliseconds for redrawing the display. This applies to + searching for patterns for 'hlsearch' and |:match| highlighting. + When redrawing takes more than this many milliseconds no further + matches will be highlighted. This is used to avoid that Vim hangs + when using a very complicated pattern. + *'remap'* *'noremap'* 'remap' boolean (default on) global diff --git a/src/ex_cmds.c b/src/ex_cmds.c --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -4446,7 +4446,8 @@ do_sub(eap) #endif ); ++lnum) { - nmatch = vim_regexec_multi(®match, curwin, curbuf, lnum, (colnr_T)0); + nmatch = vim_regexec_multi(®match, curwin, curbuf, lnum, + (colnr_T)0, NULL); if (nmatch) { colnr_T copycol; @@ -4957,7 +4958,8 @@ skip: || (do_ask && !re_lookbehind(regmatch.regprog)) || nmatch_tl > 0 || (nmatch = vim_regexec_multi(®match, curwin, - curbuf, sub_firstlnum, matchcol)) == 0 + curbuf, sub_firstlnum, + matchcol, NULL)) == 0 || regmatch.startpos[0].lnum > 0) { if (new_start != NULL) @@ -5022,7 +5024,7 @@ skip: } if (nmatch == -1 && !lastone) nmatch = vim_regexec_multi(®match, curwin, curbuf, - sub_firstlnum, matchcol); + sub_firstlnum, matchcol, NULL); /* * 5. break if there isn't another match in this line @@ -5252,7 +5254,8 @@ ex_global(eap) for (lnum = eap->line1; lnum <= eap->line2 && !got_int; ++lnum) { /* a match on this line? */ - match = vim_regexec_multi(®match, curwin, curbuf, lnum, (colnr_T)0); + match = vim_regexec_multi(®match, curwin, curbuf, lnum, + (colnr_T)0, NULL); if ((type == 'g' && match) || (type == 'v' && !match)) { ml_setmarked(lnum); diff --git a/src/ex_docmd.c b/src/ex_docmd.c --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -3931,7 +3931,8 @@ get_address(ptr, skip, to_other_file) curwin->w_cursor.col = 0; searchcmdlen = 0; if (!do_search(NULL, c, cmd, 1L, - SEARCH_HIS + SEARCH_MSG + SEARCH_START)) + SEARCH_HIS + SEARCH_MSG + SEARCH_START, + NULL)) { curwin->w_cursor = pos; cmd = NULL; diff --git a/src/ex_getln.c b/src/ex_getln.c --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -1709,6 +1709,9 @@ cmdline_changed: if (p_is && !cmd_silent && (firstc == '/' || firstc == '?')) { pos_T end_pos; +#ifdef FEAT_RELTIME + proftime_T tm; +#endif /* if there is a character waiting, search and redraw later */ if (char_avail()) @@ -1727,8 +1730,18 @@ cmdline_changed: cursor_off(); /* so the user knows we're busy */ out_flush(); ++emsg_off; /* So it doesn't beep if bad expr */ +#ifdef FEAT_RELTIME + /* Set the time limit to half a second. */ + profile_setlimit(500L, &tm); +#endif i = do_search(NULL, firstc, ccline.cmdbuff, count, - SEARCH_KEEP + SEARCH_OPT + SEARCH_NOOF + SEARCH_PEEK); + SEARCH_KEEP + SEARCH_OPT + SEARCH_NOOF + SEARCH_PEEK, +#ifdef FEAT_RELTIME + &tm +#else + NULL +#endif + ); --emsg_off; /* if interrupted while searching, behave like it failed */ if (got_int) diff --git a/src/gui.c b/src/gui.c --- a/src/gui.c +++ b/src/gui.c @@ -5052,7 +5052,7 @@ gui_do_findrepl(flags, find_text, repl_t /* Search for the next match. */ i = msg_scroll; do_search(NULL, down ? '/' : '?', ga.ga_data, 1L, - SEARCH_MSG + SEARCH_MARK); + SEARCH_MSG + SEARCH_MARK, NULL); msg_scroll = i; /* don't let an error message set msg_scroll */ } diff --git a/src/misc1.c b/src/misc1.c --- a/src/misc1.c +++ b/src/misc1.c @@ -437,7 +437,8 @@ get_number_indent(lnum) { regmatch.rmm_ic = FALSE; regmatch.rmm_maxcol = 0; - if (vim_regexec_multi(®match, curwin, curbuf, lnum, (colnr_T)0)) + if (vim_regexec_multi(®match, curwin, curbuf, lnum, + (colnr_T)0, NULL)) { pos.lnum = regmatch.endpos[0].lnum + lnum; pos.col = regmatch.endpos[0].col; diff --git a/src/normal.c b/src/normal.c --- a/src/normal.c +++ b/src/normal.c @@ -6093,7 +6093,7 @@ normal_search(cap, dir, pat, opt) curwin->w_set_curswant = TRUE; i = do_search(cap->oap, dir, pat, cap->count1, - opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG); + opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG, NULL); if (i == 0) clearop(cap->oap); else diff --git a/src/option.c b/src/option.c --- a/src/option.c +++ b/src/option.c @@ -1991,6 +1991,13 @@ static struct vimoption {"redraw", NULL, P_BOOL|P_VI_DEF, (char_u *)NULL, PV_NONE, {(char_u *)FALSE, (char_u *)0L}}, + {"redrawtime", "rdt", P_NUM|P_VI_DEF, +#ifdef FEAT_RELTIME + (char_u *)&p_rdt, PV_NONE, +#else + (char_u *)NULL, PV_NONE, +#endif + {(char_u *)2000L, (char_u *)0L}}, {"remap", NULL, P_BOOL|P_VI_DEF, (char_u *)&p_remap, PV_NONE, {(char_u *)TRUE, (char_u *)0L}}, diff --git a/src/option.h b/src/option.h --- a/src/option.h +++ b/src/option.h @@ -633,6 +633,9 @@ EXTERN char_u *p_path; /* 'path' */ #ifdef FEAT_SEARCHPATH EXTERN char_u *p_cdpath; /* 'cdpath' */ #endif +#ifdef FEAT_RELTIME +EXTERN long p_rdt; /* 'redrawtime' */ +#endif EXTERN int p_remap; /* 'remap' */ EXTERN long p_report; /* 'report' */ #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX) diff --git a/src/proto/regexp.pro b/src/proto/regexp.pro --- a/src/proto/regexp.pro +++ b/src/proto/regexp.pro @@ -1,13 +1,13 @@ /* regexp.c */ -void free_regexp_stuff __ARGS((void)); int re_multiline __ARGS((regprog_T *prog)); int re_lookbehind __ARGS((regprog_T *prog)); char_u *skip_regexp __ARGS((char_u *startp, int dirc, int magic, char_u **newp)); regprog_T *vim_regcomp __ARGS((char_u *expr, int re_flags)); int vim_regcomp_had_eol __ARGS((void)); +void free_regexp_stuff __ARGS((void)); int vim_regexec __ARGS((regmatch_T *rmp, char_u *line, colnr_T col)); int vim_regexec_nl __ARGS((regmatch_T *rmp, char_u *line, colnr_T col)); -long vim_regexec_multi __ARGS((regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum, colnr_T col)); +long vim_regexec_multi __ARGS((regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum, colnr_T col, proftime_T *tm)); reg_extmatch_T *ref_extmatch __ARGS((reg_extmatch_T *em)); void unref_extmatch __ARGS((reg_extmatch_T *em)); char_u *regtilde __ARGS((char_u *source, int magic)); diff --git a/src/proto/search.pro b/src/proto/search.pro --- a/src/proto/search.pro +++ b/src/proto/search.pro @@ -11,7 +11,7 @@ void reset_search_dir __ARGS((void)); void set_last_search_pat __ARGS((char_u *s, int idx, int magic, int setlast)); void last_pat_prog __ARGS((regmmatch_T *regmatch)); int searchit __ARGS((win_T *win, buf_T *buf, pos_T *pos, int dir, char_u *pat, long count, int options, int pat_use, linenr_T stop_lnum, proftime_T *tm)); -int do_search __ARGS((oparg_T *oap, int dirc, char_u *pat, long count, int options)); +int do_search __ARGS((oparg_T *oap, int dirc, char_u *pat, long count, int options, proftime_T *tm)); int search_for_exact_line __ARGS((buf_T *buf, pos_T *pos, int dir, char_u *pat)); int searchc __ARGS((cmdarg_T *cap, int t_cmd)); pos_T *findmatch __ARGS((oparg_T *oap, int initc)); diff --git a/src/quickfix.c b/src/quickfix.c --- a/src/quickfix.c +++ b/src/quickfix.c @@ -1803,7 +1803,8 @@ qf_jump(qi, dir, errornr, forceit) /* Move the cursor to the first line in the buffer */ save_cursor = curwin->w_cursor; curwin->w_cursor.lnum = 0; - if (!do_search(NULL, '/', qf_ptr->qf_pattern, (long)1, SEARCH_KEEP)) + if (!do_search(NULL, '/', qf_ptr->qf_pattern, (long)1, + SEARCH_KEEP, NULL)) curwin->w_cursor = save_cursor; } @@ -3159,7 +3160,7 @@ ex_vimgrep(eap) { col = 0; while (vim_regexec_multi(®match, curwin, buf, lnum, - col) > 0) + col, NULL) > 0) { ; if (qf_add_entry(qi, &prevp, diff --git a/src/regexp.c b/src/regexp.c --- a/src/regexp.c +++ b/src/regexp.c @@ -3040,7 +3040,7 @@ typedef struct } save_se_T; static char_u *reg_getline __ARGS((linenr_T lnum)); -static long vim_regexec_both __ARGS((char_u *line, colnr_T col)); +static long vim_regexec_both __ARGS((char_u *line, colnr_T col, proftime_T *tm)); static long regtry __ARGS((regprog_T *prog, colnr_T col)); static void cleanup_subexpr __ARGS((void)); #ifdef FEAT_SYN_HL @@ -3284,7 +3284,7 @@ vim_regexec(rmp, line, col) ireg_icombine = FALSE; #endif ireg_maxcol = 0; - return (vim_regexec_both(line, col) != 0); + return (vim_regexec_both(line, col, NULL) != 0); } #if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) \ @@ -3308,7 +3308,7 @@ vim_regexec_nl(rmp, line, col) ireg_icombine = FALSE; #endif ireg_maxcol = 0; - return (vim_regexec_both(line, col) != 0); + return (vim_regexec_both(line, col, NULL) != 0); } #endif @@ -3321,12 +3321,13 @@ vim_regexec_nl(rmp, line, col) * match otherwise. */ long -vim_regexec_multi(rmp, win, buf, lnum, col) +vim_regexec_multi(rmp, win, buf, lnum, col, tm) regmmatch_T *rmp; win_T *win; /* window in which to search or NULL */ buf_T *buf; /* buffer in which to search */ linenr_T lnum; /* nr of line to start looking for match */ colnr_T col; /* column to start looking for match */ + proftime_T *tm; /* timeout limit or NULL */ { long r; buf_T *save_curbuf = curbuf; @@ -3346,7 +3347,7 @@ vim_regexec_multi(rmp, win, buf, lnum, c /* Need to switch to buffer "buf" to make vim_iswordc() work. */ curbuf = buf; - r = vim_regexec_both(NULL, col); + r = vim_regexec_both(NULL, col, tm); curbuf = save_curbuf; return r; @@ -3356,10 +3357,12 @@ vim_regexec_multi(rmp, win, buf, lnum, c * Match a regexp against a string ("line" points to the string) or multiple * lines ("line" is NULL, use reg_getline()). */ +/*ARGSUSED*/ static long -vim_regexec_both(line, col) +vim_regexec_both(line, col, tm) char_u *line; colnr_T col; /* column to start looking for match */ + proftime_T *tm; /* timeout limit or NULL */ { regprog_T *prog; char_u *s; @@ -3502,6 +3505,9 @@ vim_regexec_both(line, col) } else { +#ifdef FEAT_RELTIME + int tm_count = 0; +#endif /* Messy cases: unanchored match. */ while (!got_int) { @@ -3550,6 +3556,15 @@ vim_regexec_both(line, col) else #endif ++col; +#ifdef FEAT_RELTIME + /* Check for timeout once in a twenty times to avoid overhead. */ + if (tm != NULL && ++tm_count == 20) + { + tm_count = 0; + if (profile_passed_limit(tm)) + break; + } +#endif } } diff --git a/src/screen.c b/src/screen.c --- a/src/screen.c +++ b/src/screen.c @@ -848,11 +848,16 @@ win_update(wp) cur->hl.buf = buf; cur->hl.lnum = 0; cur->hl.first_lnum = 0; +# ifdef FEAT_RELTIME + /* Set the time limit to 'redrawtime'. */ + profile_setlimit(p_rdt, &(cur->hl.tm)); +# endif cur = cur->next; } search_hl.buf = buf; search_hl.lnum = 0; search_hl.first_lnum = 0; + /* time limit is set at the toplevel, for all windows */ #endif #ifdef FEAT_LINEBREAK @@ -6462,6 +6467,10 @@ start_search_hl() { last_pat_prog(&search_hl.rm); search_hl.attr = hl_attr(HLF_L); +# ifdef FEAT_RELTIME + /* Set the time limit to 'redrawtime'. */ + profile_setlimit(p_rdt, &search_hl.tm); +# endif } } @@ -6587,6 +6596,14 @@ next_search_hl(win, shl, lnum, mincol) called_emsg = FALSE; for (;;) { +#ifdef FEAT_RELTIME + /* Stop searching after passing the time limit. */ + if (profile_passed_limit(&(shl->tm))) + { + shl->lnum = 0; /* no match found in time */ + break; + } +#endif /* Three situations: * 1. No useful previous match: search from start of line. * 2. Not Vi compatible or empty match: continue at next character. @@ -6620,7 +6637,13 @@ next_search_hl(win, shl, lnum, mincol) matchcol = shl->rm.endpos[0].col; shl->lnum = lnum; - nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, matchcol); + nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, matchcol, +#ifdef FEAT_RELTIME + &(shl->tm) +#else + NULL +#endif + ); if (called_emsg) { /* Error while handling regexp: stop using this regexp. */ diff --git a/src/search.c b/src/search.c --- a/src/search.c +++ b/src/search.c @@ -606,7 +606,13 @@ searchit(win, buf, pos, dir, pat, count, * Look for a match somewhere in line "lnum". */ nmatched = vim_regexec_multi(®match, win, buf, - lnum, (colnr_T)0); + lnum, (colnr_T)0, +#ifdef FEAT_RELTIME + tm +#else + NULL +#endif + ); /* Abort searching on an error (e.g., out of stack). */ if (called_emsg) break; @@ -615,9 +621,9 @@ searchit(win, buf, pos, dir, pat, count, /* match may actually be in another line when using \zs */ matchpos = regmatch.startpos[0]; endpos = regmatch.endpos[0]; -# ifdef FEAT_EVAL +#ifdef FEAT_EVAL submatch = first_submatch(®match); -# endif +#endif /* Line me be past end of buffer for "\n\zs". */ if (lnum + matchpos.lnum > buf->b_ml.ml_line_count) ptr = (char_u *)""; @@ -693,7 +699,13 @@ searchit(win, buf, pos, dir, pat, count, if (ptr[matchcol] == NUL || (nmatched = vim_regexec_multi(®match, win, buf, lnum + matchpos.lnum, - matchcol)) == 0) + matchcol, +#ifdef FEAT_RELTIME + tm +#else + NULL +#endif + )) == 0) { match_ok = FALSE; break; @@ -799,7 +811,13 @@ searchit(win, buf, pos, dir, pat, count, if (ptr[matchcol] == NUL || (nmatched = vim_regexec_multi(®match, win, buf, lnum + matchpos.lnum, - matchcol)) == 0) + matchcol, +#ifdef FEAT_RELTIME + tm +#else + NULL +#endif + )) == 0) break; /* Need to get the line pointer again, a @@ -977,12 +995,13 @@ first_submatch(rp) * return 0 for failure, 1 for found, 2 for found and line offset added */ int -do_search(oap, dirc, pat, count, options) +do_search(oap, dirc, pat, count, options, tm) oparg_T *oap; /* can be NULL */ int dirc; /* '/' or '?' */ char_u *pat; long count; int options; + proftime_T *tm; /* timeout limit or NULL */ { pos_T pos; /* position of the last match */ char_u *searchstr; @@ -1256,7 +1275,7 @@ do_search(oap, dirc, pat, count, options (SEARCH_KEEP + SEARCH_PEEK + SEARCH_HIS + SEARCH_MSG + SEARCH_START + ((pat != NULL && *pat == ';') ? 0 : SEARCH_NOOF))), - RE_LAST, (linenr_T)0, NULL); + RE_LAST, (linenr_T)0, tm); if (dircp != NULL) *dircp = dirc; /* restore second '/' or '?' for normal_cmd() */ diff --git a/src/spell.c b/src/spell.c --- a/src/spell.c +++ b/src/spell.c @@ -10343,7 +10343,7 @@ ex_spellrepall(eap) curwin->w_cursor.lnum = 0; while (!got_int) { - if (do_search(NULL, '/', frompat, 1L, SEARCH_KEEP) == 0 + if (do_search(NULL, '/', frompat, 1L, SEARCH_KEEP, NULL) == 0 || u_save_cursor() == FAIL) break; diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -1717,6 +1717,9 @@ typedef struct linenr_T first_lnum; /* first lnum to search for multi-line pat */ colnr_T startcol; /* in win_line() points to char where HL starts */ colnr_T endcol; /* in win_line() points to char where HL ends */ +#ifdef FEAT_RELTIME + proftime_T tm; /* for a time limit */ +#endif } match_T; /* diff --git a/src/syntax.c b/src/syntax.c --- a/src/syntax.c +++ b/src/syntax.c @@ -3097,7 +3097,7 @@ syn_regexec(rmp, lnum, col) colnr_T col; { rmp->rmm_maxcol = syn_buf->b_p_smc; - if (vim_regexec_multi(rmp, syn_win, syn_buf, lnum, col) > 0) + if (vim_regexec_multi(rmp, syn_win, syn_buf, lnum, col, NULL) > 0) { rmp->startpos[0].lnum += lnum; rmp->endpos[0].lnum += lnum; diff --git a/src/tag.c b/src/tag.c --- a/src/tag.c +++ b/src/tag.c @@ -3191,7 +3191,8 @@ jumpto_tag(lbuf, forceit, keep_help) #endif save_lnum = curwin->w_cursor.lnum; curwin->w_cursor.lnum = 0; /* start search before first line */ - if (do_search(NULL, pbuf[0], pbuf + 1, (long)1, search_options)) + if (do_search(NULL, pbuf[0], pbuf + 1, (long)1, + search_options, NULL)) retval = OK; else { @@ -3203,7 +3204,7 @@ jumpto_tag(lbuf, forceit, keep_help) */ p_ic = TRUE; if (!do_search(NULL, pbuf[0], pbuf + 1, (long)1, - search_options)) + search_options, NULL)) { /* * Failed to find pattern, take a guess: "^func (" @@ -3213,13 +3214,14 @@ jumpto_tag(lbuf, forceit, keep_help) cc = *tagp.tagname_end; *tagp.tagname_end = NUL; sprintf((char *)pbuf, "^%s\\s\\*(", tagp.tagname); - if (!do_search(NULL, '/', pbuf, (long)1, search_options)) + if (!do_search(NULL, '/', pbuf, (long)1, + search_options, NULL)) { /* Guess again: "^char * \