3 * Copyright (C) 1984-2008 Mark Nudelman
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Less License, as specified in the README file.
8 * For more information about less, or for information on how to
9 * contact the author, see the README file.
14 * Routines to search a file for a pattern.
21 #define MINPOS(a,b) (((a) < (b)) ? (a) : (b))
22 #define MAXPOS(a,b) (((a) > (b)) ? (a) : (b))
24 #if HAVE_POSIX_REGCOMP
27 #define REGCOMP_FLAG (less_is_more ? 0 : REG_EXTENDED)
29 #define REGCOMP_FLAG 0
51 extern int how_search;
55 extern int jump_sline;
57 extern int less_is_more;
59 extern int status_col;
60 extern void * constant ml_search;
61 extern POSITION start_attnpos;
62 extern POSITION end_attnpos;
64 extern int screen_trashed;
66 extern int hilite_search;
67 extern int size_linebuf;
69 extern int can_goto_line;
70 static int hide_hilite;
72 static POSITION prep_startpos;
73 static POSITION prep_endpos;
77 struct hilite *hl_next;
81 static struct hilite hilite_anchor = { NULL, NULL_POSITION, NULL_POSITION };
82 static struct hilite filter_anchor = { NULL, NULL_POSITION, NULL_POSITION };
83 #define hl_first hl_next
87 * These are the static variables that represent the "remembered"
90 #if HAVE_POSIX_REGCOMP
91 #define DEFINE_PATTERN(name) static regex_t *name = NULL
94 #define DEFINE_PATTERN(name) pcre *name = NULL;
97 #define DEFINE_PATTERN(name) int name = 0;
100 #define DEFINE_PATTERN(name) static char *name = NULL;
103 #define DEFINE_PATTERN(name) static struct regexp *name = NULL;
106 DEFINE_PATTERN(search_pattern);
107 DEFINE_PATTERN(filter_pattern);
109 static int is_caseless;
110 static int is_ucase_pattern;
111 static int last_search_type;
112 static int last_filter_type;
113 static char *last_pattern = NULL;
115 #define CVT_TO_LC 01 /* Convert upper-case to lower-case */
116 #define CVT_BS 02 /* Do backspace processing */
117 #define CVT_CRLF 04 /* Remove CR after LF */
118 #define CVT_ANSI 010 /* Remove ANSI escape sequences */
121 * Get the length of a buffer needed to convert a string.
130 * Just copying a string in UTF-8 mode can cause it to grow
132 * Six output bytes for one input byte is the worst case
133 * (and unfortunately is far more than is needed in any
134 * non-pathological situation, so this is very wasteful).
141 * Convert text. Perform the transformations specified by ops.
144 cvt_text(odst, osrc, lenp, ops)
152 register char *src_end;
156 src_end = osrc + *lenp;
158 src_end = osrc + strlen(osrc);
160 for (src = osrc, dst = odst; src < src_end; )
162 ch = step_char(&src, +1, src_end);
163 if ((ops & CVT_TO_LC) && IS_UPPER(ch))
165 /* Convert uppercase to lowercase. */
166 put_wchar(&dst, TO_LOWER(ch));
167 } else if ((ops & CVT_BS) && ch == '\b' && dst > odst)
169 /* Delete backspace and preceding char. */
172 } while (dst > odst &&
173 !IS_ASCII_OCTET(*dst) && !IS_UTF8_LEAD(*dst));
174 } else if ((ops & CVT_ANSI) && IS_CSI_START(ch))
176 /* Skip to end of ANSI escape sequence. */
177 src++; /* skip the CSI start char */
178 while (src < src_end)
179 if (!is_ansi_middle(*src++))
185 if ((ops & CVT_CRLF) && dst > odst && dst[-1] == '\r')
193 * Determine which conversions to perform.
199 if (is_caseless || bs_mode == BS_SPECIAL)
203 if (bs_mode == BS_SPECIAL)
205 if (bs_mode != BS_CONTROL)
207 } else if (bs_mode != BS_CONTROL)
211 if (ctldisp == OPT_ONPLUS)
217 * Are there any uppercase letters in this string?
223 char *str_end = str + strlen(str);
226 while (str < str_end)
228 ch = step_char(&str, +1, str_end);
236 * Is there a previous (remembered) search pattern?
241 if (last_search_type & SRCH_NO_REGEX)
242 return (last_pattern != NULL);
243 #if HAVE_POSIX_REGCOMP
244 return (search_pattern != NULL);
247 return (search_pattern != NULL);
250 return (search_pattern != 0);
253 return (search_pattern != NULL);
256 return (search_pattern != NULL);
259 return (search_pattern != NULL);
265 * Repaint the hilites currently displayed on the screen.
266 * Repaint each line which contains highlighted text.
267 * If on==0, force all hilites off.
276 int save_hide_hilite;
281 save_hide_hilite = hide_hilite;
292 hide_hilite = save_hide_hilite;
296 for (slinenum = TOP; slinenum < TOP + sc_height-1; slinenum++)
298 pos = position(slinenum);
299 if (pos == NULL_POSITION)
301 epos = position(slinenum+1);
304 * If any character in the line is highlighted,
307 * {{ This doesn't work -- if line is drawn with highlights
308 * which should be erased (e.g. toggle -i with status column),
309 * we must redraw the line even if it has no highlights.
310 * For now, just repaint every line. }}
312 if (is_hilited(pos, epos, 1, NULL))
315 (void) forw_line(pos);
322 hide_hilite = save_hide_hilite;
326 * Clear the attn hilite.
332 POSITION old_start_attnpos;
333 POSITION old_end_attnpos;
338 if (start_attnpos == NULL_POSITION)
340 old_start_attnpos = start_attnpos;
341 old_end_attnpos = end_attnpos;
342 start_attnpos = end_attnpos = NULL_POSITION;
352 for (slinenum = TOP; slinenum < TOP + sc_height-1; slinenum++)
354 pos = position(slinenum);
355 if (pos == NULL_POSITION)
357 epos = position(slinenum+1);
358 if (pos < old_end_attnpos &&
359 (epos == NULL_POSITION || epos > old_start_attnpos))
361 (void) forw_line(pos);
373 * Hide search string highlighting.
380 error("No previous regular expression", NULL_PARG);
384 hide_hilite = !hide_hilite;
390 * Compile a search pattern, for future use by match_pattern.
393 compile_pattern2(pattern, search_type, comp_pattern)
398 if ((search_type & SRCH_NO_REGEX) == 0)
400 #if HAVE_POSIX_REGCOMP
401 regex_t *comp = (regex_t *) ecalloc(1, sizeof(regex_t));
402 regex_t **pcomp = (regex_t **) comp_pattern;
403 if (regcomp(comp, pattern, REGCOMP_FLAG))
406 error("Invalid pattern", NULL_PARG);
415 pcre **pcomp = (pcre **) comp_pattern;
416 const char *errstring;
419 comp = pcre_compile(pattern, 0,
420 &errstring, &erroffset, NULL);
423 parg.p_string = (char *) errstring;
431 int *pcomp = (int *) comp_pattern;
432 if ((parg.p_string = re_comp(pattern)) != NULL)
441 char **pcomp = (char **) comp_pattern;
442 if ((comp = regcmp(pattern, 0)) == NULL)
444 error("Invalid pattern", NULL_PARG);
453 struct regexp **pcomp = (struct regexp **) comp_pattern;
454 if ((comp = regcomp(pattern)) == NULL)
457 * regcomp has already printed an error message
468 if (comp_pattern == (void **) &search_pattern)
470 if (last_pattern != NULL)
472 last_pattern = (char *) calloc(1, strlen(pattern)+1);
473 if (last_pattern != NULL)
474 strcpy(last_pattern, pattern);
475 last_search_type = search_type;
478 last_filter_type = search_type;
484 * Like compile_pattern2, but convert the pattern to lowercase if necessary.
487 compile_pattern(pattern, search_type, comp_pattern)
495 if (caseless != OPT_ONPLUS)
496 cvt_pattern = pattern;
499 cvt_pattern = (char*) ecalloc(1, cvt_length(strlen(pattern), CVT_TO_LC));
500 cvt_text(cvt_pattern, pattern, (int *)NULL, CVT_TO_LC);
502 result = compile_pattern2(cvt_pattern, search_type, comp_pattern);
503 if (cvt_pattern != pattern)
509 * Forget that we have a compiled pattern.
512 uncompile_pattern(pattern)
515 #if HAVE_POSIX_REGCOMP
516 regex_t **pcomp = (regex_t **) pattern;
522 pcre **pcomp = (pcre **) pattern;
528 int *pcomp = (int *) pattern;
532 char **pcomp = (char **) pattern;
538 struct regexp **pcomp = (struct regexp **) pattern;
546 uncompile_search_pattern()
548 uncompile_pattern(&search_pattern);
553 uncompile_filter_pattern()
555 uncompile_pattern(&filter_pattern);
559 * Is a compiled pattern null?
562 is_null_pattern(pattern)
565 #if HAVE_POSIX_REGCOMP
566 return (pattern == NULL);
569 return (pattern == NULL);
572 return (pattern == 0);
575 return (pattern == NULL);
578 return (pattern == NULL);
583 * Perform a pattern match with the previously compiled pattern.
584 * Set sp and ep to the start and end of the matched string.
587 match_pattern(pattern, line, line_len, sp, ep, notbol, search_type)
597 #if HAVE_POSIX_REGCOMP
598 regex_t *spattern = (regex_t *) pattern;
601 pcre *spattern = (pcre *) pattern;
604 int spattern = (int) pattern;
607 char *spattern = (char *) pattern;
610 struct regexp *spattern = (struct regexp *) pattern;
613 if (search_type & SRCH_NO_REGEX)
614 return (match(last_pattern, strlen(last_pattern), line, line_len, sp, ep));
616 #if HAVE_POSIX_REGCOMP
619 int flags = (notbol) ? REG_NOTBOL : 0;
620 matched = !regexec(spattern, line, 1, &rm, flags);
624 *sp = line + rm.rm_so;
625 *ep = line + rm.rm_eo;
635 int flags = (notbol) ? PCRE_NOTBOL : 0;
637 matched = pcre_exec(spattern, NULL, line, line_len,
638 0, flags, ovector, 3) >= 0;
641 *sp = line + ovector[0];
642 *ep = line + ovector[1];
647 matched = (re_exec(line) == 1);
649 * re_exec doesn't seem to provide a way to get the matched string.
654 *ep = regex(spattern, line);
655 matched = (*ep != NULL);
661 matched = regexec2(spattern, line, notbol);
663 matched = regexec(spattern, line);
667 *sp = spattern->startp[0];
668 *ep = spattern->endp[0];
672 matched = match(last_pattern, strlen(last_pattern), line, line_len, sp, ep);
674 matched = (!(search_type & SRCH_NO_MATCH) && matched) ||
675 ((search_type & SRCH_NO_MATCH) && !matched);
681 * Clear the hilite list.
685 struct hilite *anchor;
688 struct hilite *nexthl;
690 for (hl = anchor->hl_first; hl != NULL; hl = nexthl)
692 nexthl = hl->hl_next;
695 anchor->hl_first = NULL;
696 prep_startpos = prep_endpos = NULL_POSITION;
702 clr_hlist(&hilite_anchor);
708 clr_hlist(&filter_anchor);
712 * Should any characters in a specified range be highlighted?
715 is_hilited_range(pos, epos)
722 * Look at each highlight and see if any part of it falls in the range.
724 for (hl = hilite_anchor.hl_first; hl != NULL; hl = hl->hl_next)
726 if (hl->hl_endpos > pos &&
727 (epos == NULL_POSITION || epos > hl->hl_startpos))
734 * Is a line "filtered" -- that is, should it be hidden?
742 if (ch_getflags() & CH_HELPFILE)
746 * Look at each filter and see if the start position
747 * equals the start position of the line.
749 for (hl = filter_anchor.hl_first; hl != NULL; hl = hl->hl_next)
751 if (hl->hl_startpos == pos)
758 * Should any characters in a specified range be highlighted?
759 * If nohide is nonzero, don't consider hide_hilite.
762 is_hilited(pos, epos, nohide, p_matches)
770 if (p_matches != NULL)
774 start_attnpos != NULL_POSITION &&
776 (epos == NULL_POSITION || epos > start_attnpos))
778 * The attn line overlaps this range.
782 match = is_hilited_range(pos, epos);
786 if (p_matches != NULL)
788 * Report matches, even if we're hiding highlights.
792 if (hilite_search == 0)
794 * Not doing highlighting.
798 if (!nohide && hide_hilite)
800 * Highlighting is hidden.
808 * Add a new hilite to a hilite list.
811 add_hilite(anchor, hl)
812 struct hilite *anchor;
818 * Hilites are sorted in the list; find where new one belongs.
819 * Insert new one after ihl.
821 for (ihl = anchor; ihl->hl_next != NULL; ihl = ihl->hl_next)
823 if (ihl->hl_next->hl_startpos > hl->hl_startpos)
828 * Truncate hilite so it doesn't overlap any existing ones
829 * above and below it.
832 hl->hl_startpos = MAXPOS(hl->hl_startpos, ihl->hl_endpos);
833 if (ihl->hl_next != NULL)
834 hl->hl_endpos = MINPOS(hl->hl_endpos, ihl->hl_next->hl_startpos);
835 if (hl->hl_startpos >= hl->hl_endpos)
838 * Hilite was truncated out of existence.
843 hl->hl_next = ihl->hl_next;
848 * Adjust hl_startpos & hl_endpos to account for processing by cvt_text.
851 adj_hilite(anchor, linepos, cvt_ops)
852 struct hilite *anchor;
870 * The line was already scanned and hilites were added (in hilite_line).
871 * But it was assumed that each char position in the line
872 * correponds to one char position in the file.
873 * This may not be true if cvt_text modified the line.
874 * Get the raw line again. Look at each character.
876 (void) forw_raw_line(linepos, &line, &line_len);
877 line_end = line + line_len;
878 opos = npos = linepos;
879 hl = anchor->hl_first;
882 hl_opos = hl_npos = hl->hl_startpos;
885 while (hl != NULL && line < line_end)
888 * See if we need to adjust the current hl_startpos or
889 * hl_endpos. After adjusting startpos[i], move to endpos[i].
890 * After adjusting endpos[i], move to startpos[i+1].
891 * The hilite list must be sorted thus:
892 * startpos[0] < endpos[0] <= startpos[1] < endpos[1] <= etc.
895 ch = step_char(&line, +1, line_end);
896 ncwidth = line - oline;
899 /* Figure out how this char was processed by cvt_text. */
900 if ((cvt_ops & CVT_BS) && ch == '\b')
902 /* Skip the backspace and the following char. */
904 ch = step_char(&line, +1, line_end);
905 ncwidth = line - oline;
907 } else if ((cvt_ops & CVT_TO_LC) && IS_UPPER(ch))
909 /* Converted uppercase to lower.
910 * Note that this may have changed the number of bytes
911 * that the character occupies. */
914 put_wchar(&dst, TO_LOWER(ch));
916 } else if ((cvt_ops & CVT_ANSI) && IS_CSI_START(ch))
918 /* Skip to end of ANSI escape sequence. */
919 line++; /* skip the CSI start char */
921 while (line < line_end)
924 if (!is_ansi_middle(*line++))
929 /* Ordinary unprocessed character. */
933 if (opos == hl_opos) {
934 /* Adjust highlight position. */
940 * We've moved past the highlight position; store the
941 * adjusted highlight position and move to the next highlight.
945 hl->hl_startpos = hl_npos;
946 hl_opos = hl->hl_endpos;
950 hl->hl_endpos = hl_npos;
953 hl_opos = hl->hl_startpos;
962 * Make a hilite for each string in a physical line which matches
963 * the current pattern.
964 * sp,ep delimit the first match already found.
967 hilite_line(linepos, line, line_len, sp, ep, cvt_ops)
976 char *line_end = line + line_len;
978 struct hilite hilites;
980 if (sp == NULL || ep == NULL)
983 * sp and ep delimit the first match in the line.
984 * Mark the corresponding file positions, then
985 * look for further matches and mark them.
986 * {{ This technique, of calling match_pattern on subsequent
987 * substrings of the line, may mark more than is correct
988 * if the pattern starts with "^". This bug is fixed
989 * for those regex functions that accept a notbol parameter
990 * (currently POSIX, PCRE and V8-with-regexec2). }}
994 * Put the hilites into a temporary list until they're adjusted.
996 hilites.hl_first = NULL;
1001 * Assume that each char position in the "line"
1002 * buffer corresponds to one char position in the file.
1003 * This is not quite true; we need to adjust later.
1005 hl = (struct hilite *) ecalloc(1, sizeof(struct hilite));
1006 hl->hl_startpos = linepos + (sp-line);
1007 hl->hl_endpos = linepos + (ep-line);
1008 add_hilite(&hilites, hl);
1011 * If we matched more than zero characters,
1012 * move to the first char after the string we matched.
1013 * If we matched zero, just move to the next char.
1017 else if (searchp != line_end)
1019 else /* end of line */
1021 } while (match_pattern(search_pattern, searchp, line_end - searchp, &sp, &ep, 1, last_search_type));
1024 * If there were backspaces in the original line, they
1025 * were removed, and hl_startpos/hl_endpos are not correct.
1026 * {{ This is very ugly. }}
1028 adj_hilite(&hilites, linepos, cvt_ops);
1031 * Now put the hilites into the real list.
1033 while ((hl = hilites.hl_next) != NULL)
1035 hilites.hl_next = hl->hl_next;
1036 add_hilite(&hilite_anchor, hl);
1042 * Change the caseless-ness of searches.
1043 * Updates the internal search state to reflect a change in the -i flag.
1048 if (!is_ucase_pattern)
1050 * Pattern did not have uppercase.
1051 * Just set the search caselessness to the global caselessness.
1053 is_caseless = caseless;
1056 * Pattern did have uppercase.
1057 * Discard the pattern; we can't change search caselessness now.
1059 uncompile_search_pattern();
1064 * Find matching text which is currently on screen and highlight it.
1069 struct scrpos scrpos;
1071 get_scrpos(&scrpos);
1072 if (scrpos.pos == NULL_POSITION)
1074 prep_hilite(scrpos.pos, position(BOTTOM_PLUS_ONE), -1);
1079 * Change highlighting parameters.
1085 * Erase any highlights currently on screen.
1090 if (hilite_search == OPT_ONPLUS)
1092 * Display highlights.
1099 * Figure out where to start a search.
1102 search_pos(search_type)
1111 * Start at the beginning (or end) of the file.
1112 * The empty_screen() case is mainly for
1113 * command line initiated searches;
1114 * for example, "+/xyz" on the command line.
1115 * Also for multi-file (SRCH_PAST_EOF) searches.
1117 if (search_type & SRCH_FORW)
1123 if (pos == NULL_POSITION)
1125 (void) ch_end_seek();
1134 * Search does not include current screen.
1136 if (search_type & SRCH_FORW)
1137 linenum = BOTTOM_PLUS_ONE;
1140 pos = position(linenum);
1144 * Search includes current screen.
1145 * It starts at the jump target (if searching backwards),
1146 * or at the jump target plus one (if forwards).
1148 linenum = adjsline(jump_sline);
1149 pos = position(linenum);
1150 if (search_type & SRCH_FORW)
1152 pos = forw_raw_line(pos, (char **)NULL, (int *)NULL);
1153 while (pos == NULL_POSITION)
1155 if (++linenum >= sc_height)
1157 pos = position(linenum);
1161 while (pos == NULL_POSITION)
1165 pos = position(linenum);
1173 * Search a subset of the file, specified by start/end position.
1176 search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos)
1192 POSITION linepos, oldpos;
1194 linenum = find_linenum(pos);
1199 * Get lines until we find a matching one or until
1200 * we hit end-of-file (or beginning-of-file if we're
1201 * going backwards), or until we hit the end position.
1206 * A signal aborts the search.
1211 if ((endpos != NULL_POSITION && pos >= endpos) || maxlines == 0)
1214 * Reached end position without a match.
1216 if (pendpos != NULL)
1223 if (search_type & SRCH_FORW)
1226 * Read the next line, and save the
1227 * starting position of that line in linepos.
1230 pos = forw_raw_line(pos, &line, &line_len);
1236 * Read the previous line and save the
1237 * starting position of that line in linepos.
1239 pos = back_raw_line(pos, &line, &line_len);
1245 if (pos == NULL_POSITION)
1248 * Reached EOF/BOF without a match.
1250 if (pendpos != NULL)
1256 * If we're using line numbers, we might as well
1257 * remember the information we have now (the position
1258 * and line number of the current line).
1259 * Don't do it for every line because it slows down
1260 * the search. Remember the line number only if
1261 * we're "far" from the last place we remembered it.
1263 if (linenums && abs((int)(pos - oldpos)) > 1024)
1264 add_lnum(linenum, pos);
1267 if (is_filtered(linepos))
1271 * If it's a caseless search, convert the line to lowercase.
1272 * If we're doing backspace processing, delete backspaces.
1274 cvt_ops = get_cvt_ops();
1275 cline = calloc(1, cvt_length(line_len, cvt_ops));
1276 cvt_text(cline, line, &line_len, cvt_ops);
1280 * Check to see if the line matches the filter pattern.
1281 * If so, add an entry to the filter list.
1283 if ((search_type & SRCH_FIND_ALL) &&
1284 !is_null_pattern(filter_pattern))
1286 int line_filter = match_pattern(filter_pattern,
1287 cline, line_len, &sp, &ep, 0, last_filter_type);
1290 struct hilite *hl = (struct hilite *)
1291 ecalloc(1, sizeof(struct hilite));
1292 hl->hl_startpos = linepos;
1293 hl->hl_endpos = pos;
1294 add_hilite(&filter_anchor, hl);
1300 * Test the next line to see if we have a match.
1301 * We are successful if we either want a match and got one,
1302 * or if we want a non-match and got one.
1304 if (!is_null_pattern(search_pattern))
1306 line_match = match_pattern(search_pattern,
1307 cline, line_len, &sp, &ep, 0, search_type);
1313 if (search_type & SRCH_FIND_ALL)
1317 * We are supposed to find all matches in the range.
1318 * Just add the matches in this line to the
1319 * hilite list and keep searching.
1321 hilite_line(linepos, cline, line_len, sp, ep, cvt_ops);
1323 } else if (--matches <= 0)
1326 * Found the one match we're looking for.
1330 if (hilite_search == OPT_ON)
1333 * Clear the hilite list and add only
1334 * the matches in this one line.
1337 hilite_line(linepos, cline, line_len, sp, ep, cvt_ops);
1341 if (plinepos != NULL)
1342 *plinepos = linepos;
1352 * search for a pattern in history. If found, compile that pattern.
1355 hist_pattern(search_type)
1361 set_mlist(ml_search, 0);
1362 pattern = cmd_lastpattern();
1363 if (pattern == NULL)
1366 if (compile_pattern(pattern, search_type, &search_pattern) < 0)
1369 is_ucase_pattern = is_ucase(pattern);
1370 if (is_ucase_pattern && caseless != OPT_ONPLUS)
1373 is_caseless = caseless;
1376 if (hilite_search == OPT_ONPLUS && !hide_hilite)
1381 #else /* CMD_HISTORY */
1383 #endif /* CMD_HISTORY */
1387 * Search for the n-th occurrence of a specified pattern,
1388 * either forward or backward.
1389 * Return the number of matches not yet found in this file
1390 * (that is, n minus the number of matches found).
1391 * Return -1 if the search should be aborted.
1392 * Caller may continue the search in another file
1393 * if less than n matches are found in this file.
1396 search(search_type, pattern, n)
1403 if (pattern == NULL || *pattern == '\0')
1406 * A null pattern means use the previously compiled pattern.
1408 if (!prev_pattern() && !hist_pattern(search_type))
1410 error("No previous regular expression", NULL_PARG);
1413 if ((search_type & SRCH_NO_REGEX) !=
1414 (last_search_type & SRCH_NO_REGEX))
1416 error("Please re-enter search pattern", NULL_PARG);
1420 if (hilite_search == OPT_ON)
1423 * Erase the highlights currently on screen.
1424 * If the search fails, we'll redisplay them later.
1428 if (hilite_search == OPT_ONPLUS && hide_hilite)
1431 * Highlight any matches currently on screen,
1432 * before we actually start the search.
1442 * Compile the pattern.
1444 if (compile_pattern(pattern, search_type, &search_pattern) < 0)
1447 * Ignore case if -I is set OR
1448 * -i is set AND the pattern is all lowercase.
1450 is_ucase_pattern = is_ucase(pattern);
1451 if (is_ucase_pattern && caseless != OPT_ONPLUS)
1454 is_caseless = caseless;
1459 * Erase the highlights currently on screen.
1460 * Also permanently delete them from the hilite list.
1466 if (hilite_search == OPT_ONPLUS)
1469 * Highlight any matches currently on screen,
1470 * before we actually start the search.
1478 * Figure out where to start the search.
1480 pos = search_pos(search_type);
1481 if (pos == NULL_POSITION)
1484 * Can't find anyplace to start searching from.
1486 if (search_type & SRCH_PAST_EOF)
1488 /* repaint(); -- why was this here? */
1489 error("Nothing to search", NULL_PARG);
1493 n = search_range(pos, NULL_POSITION, search_type, n, -1,
1494 &pos, (POSITION*)NULL);
1498 * Search was unsuccessful.
1501 if (hilite_search == OPT_ON && n > 0)
1503 * Redisplay old hilites.
1510 if (!(search_type & SRCH_NO_MOVE))
1513 * Go to the matching line.
1515 jump_loc(pos, jump_sline);
1519 if (hilite_search == OPT_ON)
1521 * Display new hilites in the matching line.
1531 * Prepare hilites in a given range of the file.
1533 * The pair (prep_startpos,prep_endpos) delimits a contiguous region
1534 * of the file that has been "prepared"; that is, scanned for matches for
1535 * the current search pattern, and hilites have been created for such matches.
1536 * If prep_startpos == NULL_POSITION, the prep region is empty.
1537 * If prep_endpos == NULL_POSITION, the prep region extends to EOF.
1538 * prep_hilite asks that the range (spos,epos) be covered by the prep region.
1541 prep_hilite(spos, epos, maxlines)
1546 POSITION nprep_startpos = prep_startpos;
1547 POSITION nprep_endpos = prep_endpos;
1553 * Search beyond where we're asked to search, so the prep region covers
1554 * more than we need. Do one big search instead of a bunch of small ones.
1556 #define SEARCH_MORE (3*size_linebuf)
1558 if (!prev_pattern() && !is_filtering())
1562 * If we're limited to a max number of lines, figure out the
1563 * file position we should stop at.
1566 max_epos = NULL_POSITION;
1570 for (i = 0; i < maxlines; i++)
1571 max_epos = forw_raw_line(max_epos, (char **)NULL, (int *)NULL);
1576 * The range that we need to search (spos,epos); and the range that
1577 * the "prep" region will then cover (nprep_startpos,nprep_endpos).
1580 if (prep_startpos == NULL_POSITION ||
1581 (epos != NULL_POSITION && epos < prep_startpos) ||
1585 * New range is not contiguous with old prep region.
1586 * Discard the old prep region and start a new one.
1590 if (epos != NULL_POSITION)
1591 epos += SEARCH_MORE;
1592 nprep_startpos = spos;
1596 * New range partially or completely overlaps old prep region.
1598 if (epos == NULL_POSITION)
1601 * New range goes to end of file.
1604 } else if (epos > prep_endpos)
1607 * New range ends after old prep region.
1608 * Extend prep region to end at end of new range.
1610 epos += SEARCH_MORE;
1611 } else /* (epos <= prep_endpos) */
1614 * New range ends within old prep region.
1615 * Truncate search to end at start of old prep region.
1617 epos = prep_startpos;
1620 if (spos < prep_startpos)
1623 * New range starts before old prep region.
1624 * Extend old prep region backwards to start at
1625 * start of new range.
1627 if (spos < SEARCH_MORE)
1630 spos -= SEARCH_MORE;
1631 nprep_startpos = spos;
1632 } else /* (spos >= prep_startpos) */
1635 * New range starts within or after old prep region.
1636 * Trim search to start at end of old prep region.
1642 if (epos != NULL_POSITION && max_epos != NULL_POSITION &&
1645 * Don't go past the max position we're allowed.
1649 if (epos == NULL_POSITION || epos > spos)
1651 result = search_range(spos, epos, SRCH_FORW|SRCH_FIND_ALL, 0,
1652 maxlines, (POSITION*)NULL, &new_epos);
1655 if (prep_endpos == NULL_POSITION || new_epos > prep_endpos)
1656 nprep_endpos = new_epos;
1658 prep_startpos = nprep_startpos;
1659 prep_endpos = nprep_endpos;
1663 * Set the pattern to be used for line filtering.
1666 set_filter_pattern(pattern, search_type)
1671 if (pattern == NULL || *pattern == '\0')
1672 uncompile_filter_pattern();
1674 compile_pattern(pattern, search_type, &filter_pattern);
1679 * Is there a line filter in effect?
1684 if (ch_getflags() & CH_HELPFILE)
1686 return !is_null_pattern(filter_pattern);
1691 * Simple pattern matching function.
1692 * It supports no metacharacters like *, etc.
1695 match(pattern, pattern_len, buf, buf_len, pfound, pend)
1700 char **pfound, **pend;
1702 register char *pp, *lp;
1703 register char *pattern_end = pattern + pattern_len;
1704 register char *buf_end = buf + buf_len;
1706 for ( ; buf < buf_end; buf++)
1708 for (pp = pattern, lp = buf; *pp == *lp; pp++, lp++)
1709 if (pp == pattern_end || lp == buf_end)
1711 if (pp == pattern_end)
1725 * This function is called by the V8 regcomp to report
1726 * errors in regular expressions.