summaryrefslogtreecommitdiff
path: root/src/search.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2017-06-17 18:44:21 +0200
committerBram Moolenaar <Bram@vim.org>2017-06-17 18:44:21 +0200
commitfbd0b0af6800f6ff89857863d6a07ea03f09ff6c (patch)
treed970232ff584511e30efcfe2f7ea5eefb9e9f8d4 /src/search.c
parent8cf91286ca46a501d24e4b7d631b193256782c88 (diff)
downloadvim-git-fbd0b0af6800f6ff89857863d6a07ea03f09ff6c.tar.gz
patch 8.0.0643: when a pattern search is slow Vim becomes unusablev8.0.0643
Problem: When 'hlsearch' is set and matching with the last search pattern is very slow, Vim becomes unusable. Cannot quit search by pressing CTRL-C. Solution: When the search times out set a flag and don't try again. Check for timeout and CTRL-C in NFA loop that adds states.
Diffstat (limited to 'src/search.c')
-rw-r--r--src/search.c45
1 files changed, 29 insertions, 16 deletions
diff --git a/src/search.c b/src/search.c
index 947007341..ac1192725 100644
--- a/src/search.c
+++ b/src/search.c
@@ -593,7 +593,8 @@ searchit(
int options,
int pat_use, /* which pattern to use when "pat" is empty */
linenr_T stop_lnum, /* stop after this line number when != 0 */
- proftime_T *tm UNUSED) /* timeout limit or NULL */
+ proftime_T *tm UNUSED, /* timeout limit or NULL */
+ int *timed_out UNUSED) /* set when timed out or NULL */
{
int found;
linenr_T lnum; /* no init to shut up Apollo cc */
@@ -715,13 +716,17 @@ searchit(
nmatched = vim_regexec_multi(&regmatch, win, buf,
lnum, col,
#ifdef FEAT_RELTIME
- tm
+ tm, timed_out
#else
- NULL
+ NULL, NULL
#endif
);
/* Abort searching on an error (e.g., out of stack). */
- if (called_emsg)
+ if (called_emsg
+#ifdef FEAT_RELTIME
+ || (timed_out != NULL && *timed_out)
+#endif
+ )
break;
if (nmatched > 0)
{
@@ -810,9 +815,9 @@ searchit(
win, buf, lnum + matchpos.lnum,
matchcol,
#ifdef FEAT_RELTIME
- tm
+ tm, timed_out
#else
- NULL
+ NULL, NULL
#endif
)) == 0)
{
@@ -922,9 +927,9 @@ searchit(
win, buf, lnum + matchpos.lnum,
matchcol,
#ifdef FEAT_RELTIME
- tm
+ tm, timed_out
#else
- NULL
+ NULL, NULL
#endif
)) == 0)
break;
@@ -1019,10 +1024,13 @@ searchit(
* twice.
*/
if (!p_ws || stop_lnum != 0 || got_int || called_emsg
+#ifdef FEAT_RELTIME
+ || (timed_out != NULL && *timed_out)
+#endif
#ifdef FEAT_SEARCH_EXTRA
- || break_loop
+ || break_loop
#endif
- || found || loop)
+ || found || loop)
break;
/*
@@ -1041,6 +1049,9 @@ searchit(
? top_bot_msg : bot_top_msg), TRUE);
}
if (got_int || called_emsg
+#ifdef FEAT_RELTIME
+ || (timed_out != NULL && *timed_out)
+#endif
#ifdef FEAT_SEARCH_EXTRA
|| break_loop
#endif
@@ -1147,7 +1158,8 @@ do_search(
char_u *pat,
long count,
int options,
- proftime_T *tm) /* timeout limit or NULL */
+ proftime_T *tm, /* timeout limit or NULL */
+ int *timed_out) /* flag set on timeout or NULL */
{
pos_T pos; /* position of the last match */
char_u *searchstr;
@@ -1433,7 +1445,7 @@ do_search(
(SEARCH_KEEP + SEARCH_PEEK + SEARCH_HIS
+ SEARCH_MSG + SEARCH_START
+ ((pat != NULL && *pat == ';') ? 0 : SEARCH_NOOF))),
- RE_LAST, (linenr_T)0, tm);
+ RE_LAST, (linenr_T)0, tm, timed_out);
if (dircp != NULL)
*dircp = dirc; /* restore second '/' or '?' for normal_cmd() */
@@ -4672,7 +4684,7 @@ current_search(
result = searchit(curwin, curbuf, &pos, (dir ? FORWARD : BACKWARD),
spats[last_idx].pat, (long) (i ? count : 1),
- SEARCH_KEEP | flags, RE_SEARCH, 0, NULL);
+ SEARCH_KEEP | flags, RE_SEARCH, 0, NULL, NULL);
/* First search may fail, but then start searching from the
* beginning of the file (cursor might be on the search match)
@@ -4719,7 +4731,8 @@ current_search(
* already on the next match */
if (!one_char)
result = searchit(curwin, curbuf, &pos, (forward ? FORWARD : BACKWARD),
- spats[last_idx].pat, 0L, flags | SEARCH_KEEP, RE_SEARCH, 0, NULL);
+ spats[last_idx].pat, 0L, flags | SEARCH_KEEP, RE_SEARCH, 0,
+ NULL, NULL);
if (!VIsual_active)
VIsual = start_pos;
@@ -4800,7 +4813,7 @@ is_one_char(char_u *pattern, int move, pos_T *cur)
}
if (searchit(curwin, curbuf, &pos, FORWARD, pattern, 1,
- SEARCH_KEEP + flag, RE_SEARCH, 0, NULL) != FAIL)
+ SEARCH_KEEP + flag, RE_SEARCH, 0, NULL, NULL) != FAIL)
{
/* Zero-width pattern should match somewhere, then we can check if
* start and end are in the same position. */
@@ -4809,7 +4822,7 @@ is_one_char(char_u *pattern, int move, pos_T *cur)
{
regmatch.startpos[0].col++;
nmatched = vim_regexec_multi(&regmatch, curwin, curbuf,
- pos.lnum, regmatch.startpos[0].col, NULL);
+ pos.lnum, regmatch.startpos[0].col, NULL, NULL);
if (!nmatched)
break;
} while (regmatch.startpos[0].col < pos.col);