1 |
|
|
/* |
2 |
|
|
* Copyright (C) 1984-2012 Mark Nudelman |
3 |
|
|
* Modified for use with illumos by Garrett D'Amore. |
4 |
|
|
* Copyright 2014 Garrett D'Amore <garrett@damore.org> |
5 |
|
|
* |
6 |
|
|
* You may distribute under the terms of either the GNU General Public |
7 |
|
|
* License or the Less License, as specified in the README file. |
8 |
|
|
* |
9 |
|
|
* For more information, see the README file. |
10 |
|
|
*/ |
11 |
|
|
|
12 |
|
|
/* |
13 |
|
|
* Routines to search a file for a pattern. |
14 |
|
|
*/ |
15 |
|
|
|
16 |
|
|
#include "charset.h" |
17 |
|
|
#include "less.h" |
18 |
|
|
#include "pattern.h" |
19 |
|
|
#include "position.h" |
20 |
|
|
|
21 |
|
|
#define MINPOS(a, b) (((a) < (b)) ? (a) : (b)) |
22 |
|
|
#define MAXPOS(a, b) (((a) > (b)) ? (a) : (b)) |
23 |
|
|
|
24 |
|
|
extern volatile sig_atomic_t sigs; |
25 |
|
|
extern int how_search; |
26 |
|
|
extern int caseless; |
27 |
|
|
extern int linenums; |
28 |
|
|
extern int sc_height; |
29 |
|
|
extern int jump_sline; |
30 |
|
|
extern int bs_mode; |
31 |
|
|
extern int ctldisp; |
32 |
|
|
extern int status_col; |
33 |
|
|
extern void *const ml_search; |
34 |
|
|
extern off_t start_attnpos; |
35 |
|
|
extern off_t end_attnpos; |
36 |
|
|
extern int utf_mode; |
37 |
|
|
extern int screen_trashed; |
38 |
|
|
extern int hilite_search; |
39 |
|
|
extern int size_linebuf; |
40 |
|
|
extern int squished; |
41 |
|
|
extern int can_goto_line; |
42 |
|
|
static int hide_hilite; |
43 |
|
|
static off_t prep_startpos; |
44 |
|
|
static off_t prep_endpos; |
45 |
|
|
static int is_caseless; |
46 |
|
|
static int is_ucase_pattern; |
47 |
|
|
|
48 |
|
|
struct hilite { |
49 |
|
|
struct hilite *hl_next; |
50 |
|
|
off_t hl_startpos; |
51 |
|
|
off_t hl_endpos; |
52 |
|
|
}; |
53 |
|
|
static struct hilite hilite_anchor = { NULL, -1, -1 }; |
54 |
|
|
static struct hilite filter_anchor = { NULL, -1, -1 }; |
55 |
|
|
#define hl_first hl_next |
56 |
|
|
|
57 |
|
|
/* |
58 |
|
|
* These are the static variables that represent the "remembered" |
59 |
|
|
* search pattern and filter pattern. |
60 |
|
|
*/ |
61 |
|
|
struct pattern_info { |
62 |
|
|
regex_t *compiled; |
63 |
|
|
char *text; |
64 |
|
|
int search_type; |
65 |
|
|
}; |
66 |
|
|
|
67 |
|
|
#define info_compiled(info) ((info)->compiled) |
68 |
|
|
|
69 |
|
|
static struct pattern_info search_info; |
70 |
|
|
static struct pattern_info filter_info; |
71 |
|
|
|
72 |
|
|
/* |
73 |
|
|
* Are there any uppercase letters in this string? |
74 |
|
|
*/ |
75 |
|
|
static int |
76 |
|
|
is_ucase(char *str) |
77 |
|
|
{ |
78 |
|
3 |
char *str_end = str + strlen(str); |
79 |
|
|
LWCHAR ch; |
80 |
|
|
|
81 |
✓✓ |
30 |
while (str < str_end) { |
82 |
|
12 |
ch = step_char(&str, +1, str_end); |
83 |
✗✓ |
12 |
if (isupper(ch)) |
84 |
|
|
return (1); |
85 |
|
|
} |
86 |
|
3 |
return (0); |
87 |
|
3 |
} |
88 |
|
|
|
89 |
|
|
/* |
90 |
|
|
* Compile and save a search pattern. |
91 |
|
|
*/ |
92 |
|
|
static int |
93 |
|
|
set_pattern(struct pattern_info *info, char *pattern, int search_type) |
94 |
|
|
{ |
95 |
✗✓ |
6 |
if (pattern == NULL) |
96 |
|
|
info->compiled = NULL; |
97 |
✗✓ |
3 |
else if (compile_pattern(pattern, search_type, &info->compiled) < 0) |
98 |
|
|
return (-1); |
99 |
|
|
/* Pattern compiled successfully; save the text too. */ |
100 |
|
3 |
free(info->text); |
101 |
|
3 |
info->text = NULL; |
102 |
✓✗ |
3 |
if (pattern != NULL) |
103 |
|
3 |
info->text = estrdup(pattern); |
104 |
|
3 |
info->search_type = search_type; |
105 |
|
|
|
106 |
|
|
/* |
107 |
|
|
* Ignore case if -I is set OR |
108 |
|
|
* -i is set AND the pattern is all lowercase. |
109 |
|
|
*/ |
110 |
|
3 |
is_ucase_pattern = is_ucase(pattern); |
111 |
|
3 |
if (is_ucase_pattern && caseless != OPT_ONPLUS) |
112 |
|
|
is_caseless = 0; |
113 |
|
|
else |
114 |
|
|
is_caseless = caseless; |
115 |
|
3 |
return (0); |
116 |
|
3 |
} |
117 |
|
|
|
118 |
|
|
/* |
119 |
|
|
* Discard a saved pattern. |
120 |
|
|
*/ |
121 |
|
|
static void |
122 |
|
|
clear_pattern(struct pattern_info *info) |
123 |
|
|
{ |
124 |
|
|
free(info->text); |
125 |
|
|
info->text = NULL; |
126 |
|
|
uncompile_pattern(&info->compiled); |
127 |
|
|
} |
128 |
|
|
|
129 |
|
|
/* |
130 |
|
|
* Initialize saved pattern to nothing. |
131 |
|
|
*/ |
132 |
|
|
static void |
133 |
|
|
init_pattern(struct pattern_info *info) |
134 |
|
|
{ |
135 |
|
32 |
info->compiled = NULL; |
136 |
|
16 |
info->text = NULL; |
137 |
|
16 |
info->search_type = 0; |
138 |
|
16 |
} |
139 |
|
|
|
140 |
|
|
/* |
141 |
|
|
* Initialize search variables. |
142 |
|
|
*/ |
143 |
|
|
void |
144 |
|
|
init_search(void) |
145 |
|
|
{ |
146 |
|
16 |
init_pattern(&search_info); |
147 |
|
8 |
init_pattern(&filter_info); |
148 |
|
8 |
} |
149 |
|
|
|
150 |
|
|
/* |
151 |
|
|
* Determine which text conversions to perform before pattern matching. |
152 |
|
|
*/ |
153 |
|
|
static int |
154 |
|
|
get_cvt_ops(void) |
155 |
|
|
{ |
156 |
|
|
int ops = 0; |
157 |
✓✗ |
19980 |
if (is_caseless || bs_mode == BS_SPECIAL) { |
158 |
✗✓ |
9990 |
if (is_caseless) |
159 |
|
|
ops |= CVT_TO_LC; |
160 |
✓✗ |
9990 |
if (bs_mode == BS_SPECIAL) |
161 |
|
9990 |
ops |= CVT_BS; |
162 |
✓✗ |
9990 |
if (bs_mode != BS_CONTROL) |
163 |
|
9990 |
ops |= CVT_CRLF; |
164 |
|
|
} else if (bs_mode != BS_CONTROL) { |
165 |
|
|
ops |= CVT_CRLF; |
166 |
|
|
} |
167 |
✗✓ |
9990 |
if (ctldisp == OPT_ONPLUS) |
168 |
|
|
ops |= CVT_ANSI; |
169 |
|
9990 |
return (ops); |
170 |
|
|
} |
171 |
|
|
|
172 |
|
|
/* |
173 |
|
|
* Is there a previous (remembered) search pattern? |
174 |
|
|
*/ |
175 |
|
|
static int |
176 |
|
|
prev_pattern(struct pattern_info *info) |
177 |
|
|
{ |
178 |
✓✗ |
29098 |
if ((info->search_type & SRCH_NO_REGEX) == 0) |
179 |
|
14549 |
return (info->compiled != NULL); |
180 |
|
|
return (info->text != NULL); |
181 |
|
14549 |
} |
182 |
|
|
|
183 |
|
|
/* |
184 |
|
|
* Repaint the hilites currently displayed on the screen. |
185 |
|
|
* Repaint each line which contains highlighted text. |
186 |
|
|
* If on==0, force all hilites off. |
187 |
|
|
*/ |
188 |
|
|
void |
189 |
|
|
repaint_hilite(int on) |
190 |
|
|
{ |
191 |
|
|
int slinenum; |
192 |
|
|
off_t pos; |
193 |
|
|
int save_hide_hilite; |
194 |
|
|
|
195 |
✗✓ |
12 |
if (squished) |
196 |
|
|
repaint(); |
197 |
|
|
|
198 |
|
6 |
save_hide_hilite = hide_hilite; |
199 |
✓✓ |
6 |
if (!on) { |
200 |
✗✓ |
3 |
if (hide_hilite) |
201 |
|
|
return; |
202 |
|
3 |
hide_hilite = 1; |
203 |
|
3 |
} |
204 |
|
|
|
205 |
✗✓ |
6 |
if (!can_goto_line) { |
206 |
|
|
repaint(); |
207 |
|
|
hide_hilite = save_hide_hilite; |
208 |
|
|
return; |
209 |
|
|
} |
210 |
|
|
|
211 |
✓✓ |
396 |
for (slinenum = TOP; slinenum < TOP + sc_height-1; slinenum++) { |
212 |
|
192 |
pos = position(slinenum); |
213 |
✓✗ |
192 |
if (pos == -1) |
214 |
|
|
continue; |
215 |
|
192 |
(void) forw_line(pos); |
216 |
|
192 |
goto_line(slinenum); |
217 |
|
192 |
put_line(); |
218 |
|
192 |
} |
219 |
|
6 |
lower_left(); |
220 |
|
6 |
hide_hilite = save_hide_hilite; |
221 |
|
12 |
} |
222 |
|
|
|
223 |
|
|
/* |
224 |
|
|
* Clear the attn hilite. |
225 |
|
|
*/ |
226 |
|
|
void |
227 |
|
|
clear_attn(void) |
228 |
|
|
{ |
229 |
|
|
int slinenum; |
230 |
|
|
off_t old_start_attnpos; |
231 |
|
|
off_t old_end_attnpos; |
232 |
|
|
off_t pos; |
233 |
|
|
off_t epos; |
234 |
|
|
int moved = 0; |
235 |
|
|
|
236 |
✓✗ |
72 |
if (start_attnpos == -1) |
237 |
|
36 |
return; |
238 |
|
|
old_start_attnpos = start_attnpos; |
239 |
|
|
old_end_attnpos = end_attnpos; |
240 |
|
|
start_attnpos = end_attnpos = -1; |
241 |
|
|
|
242 |
|
|
if (!can_goto_line) { |
243 |
|
|
repaint(); |
244 |
|
|
return; |
245 |
|
|
} |
246 |
|
|
if (squished) |
247 |
|
|
repaint(); |
248 |
|
|
|
249 |
|
|
for (slinenum = TOP; slinenum < TOP + sc_height-1; slinenum++) { |
250 |
|
|
pos = position(slinenum); |
251 |
|
|
if (pos == -1) |
252 |
|
|
continue; |
253 |
|
|
epos = position(slinenum+1); |
254 |
|
|
if (pos < old_end_attnpos && |
255 |
|
|
(epos == -1 || epos > old_start_attnpos)) { |
256 |
|
|
(void) forw_line(pos); |
257 |
|
|
goto_line(slinenum); |
258 |
|
|
put_line(); |
259 |
|
|
moved = 1; |
260 |
|
|
} |
261 |
|
|
} |
262 |
|
|
if (moved) |
263 |
|
|
lower_left(); |
264 |
|
36 |
} |
265 |
|
|
|
266 |
|
|
/* |
267 |
|
|
* Hide search string highlighting. |
268 |
|
|
*/ |
269 |
|
|
void |
270 |
|
|
undo_search(void) |
271 |
|
|
{ |
272 |
|
|
if (!prev_pattern(&search_info)) { |
273 |
|
|
error("No previous regular expression", NULL); |
274 |
|
|
return; |
275 |
|
|
} |
276 |
|
|
hide_hilite = !hide_hilite; |
277 |
|
|
repaint_hilite(1); |
278 |
|
|
} |
279 |
|
|
|
280 |
|
|
/* |
281 |
|
|
* Clear the hilite list. |
282 |
|
|
*/ |
283 |
|
|
static void |
284 |
|
|
clr_hlist(struct hilite *anchor) |
285 |
|
|
{ |
286 |
|
|
struct hilite *hl; |
287 |
|
|
struct hilite *nexthl; |
288 |
|
|
|
289 |
✓✓ |
117 |
for (hl = anchor->hl_first; hl != NULL; hl = nexthl) { |
290 |
|
24 |
nexthl = hl->hl_next; |
291 |
|
24 |
free(hl); |
292 |
|
|
} |
293 |
|
23 |
anchor->hl_first = NULL; |
294 |
|
23 |
prep_startpos = prep_endpos = -1; |
295 |
|
23 |
} |
296 |
|
|
|
297 |
|
|
void |
298 |
|
|
clr_hilite(void) |
299 |
|
|
{ |
300 |
|
34 |
clr_hlist(&hilite_anchor); |
301 |
|
17 |
} |
302 |
|
|
|
303 |
|
|
static void |
304 |
|
|
clr_filter(void) |
305 |
|
|
{ |
306 |
|
12 |
clr_hlist(&filter_anchor); |
307 |
|
6 |
} |
308 |
|
|
|
309 |
|
|
/* |
310 |
|
|
* Should any characters in a specified range be highlighted? |
311 |
|
|
*/ |
312 |
|
|
static int |
313 |
|
|
is_hilited_range(off_t pos, off_t epos) |
314 |
|
|
{ |
315 |
|
|
struct hilite *hl; |
316 |
|
|
|
317 |
|
|
/* |
318 |
|
|
* Look at each highlight and see if any part of it falls in the range. |
319 |
|
|
*/ |
320 |
✓✓ |
343641 |
for (hl = hilite_anchor.hl_first; hl != NULL; hl = hl->hl_next) { |
321 |
✓✓✓✓
|
180280 |
if (hl->hl_endpos > pos && |
322 |
✓✗ |
132512 |
(epos == -1 || epos > hl->hl_startpos)) |
323 |
|
156 |
return (1); |
324 |
|
|
} |
325 |
|
38479 |
return (0); |
326 |
|
38635 |
} |
327 |
|
|
|
328 |
|
|
/* |
329 |
|
|
* Is a line "filtered" -- that is, should it be hidden? |
330 |
|
|
*/ |
331 |
|
|
int |
332 |
|
|
is_filtered(off_t pos) |
333 |
|
|
{ |
334 |
|
|
struct hilite *hl; |
335 |
|
|
|
336 |
✗✓ |
22300 |
if (ch_getflags() & CH_HELPFILE) |
337 |
|
|
return (0); |
338 |
|
|
|
339 |
|
|
/* |
340 |
|
|
* Look at each filter and see if the start position |
341 |
|
|
* equals the start position of the line. |
342 |
|
|
*/ |
343 |
✗✓ |
22300 |
for (hl = filter_anchor.hl_first; hl != NULL; hl = hl->hl_next) { |
344 |
|
|
if (hl->hl_startpos == pos) |
345 |
|
|
return (1); |
346 |
|
|
} |
347 |
|
11150 |
return (0); |
348 |
|
11150 |
} |
349 |
|
|
|
350 |
|
|
/* |
351 |
|
|
* Should any characters in a specified range be highlighted? |
352 |
|
|
* If nohide is nonzero, don't consider hide_hilite. |
353 |
|
|
*/ |
354 |
|
|
int |
355 |
|
|
is_hilited(off_t pos, off_t epos, int nohide, int *p_matches) |
356 |
|
|
{ |
357 |
|
|
int match; |
358 |
|
|
|
359 |
✓✗ |
77270 |
if (p_matches != NULL) |
360 |
|
38635 |
*p_matches = 0; |
361 |
|
|
|
362 |
✗✓✗✗
|
77270 |
if (!status_col && |
363 |
|
38635 |
start_attnpos != -1 && |
364 |
|
|
pos < end_attnpos && |
365 |
|
|
(epos == -1 || epos > start_attnpos)) |
366 |
|
|
/* |
367 |
|
|
* The attn line overlaps this range. |
368 |
|
|
*/ |
369 |
|
|
return (1); |
370 |
|
|
|
371 |
|
38635 |
match = is_hilited_range(pos, epos); |
372 |
✓✓ |
38635 |
if (!match) |
373 |
|
38479 |
return (0); |
374 |
|
|
|
375 |
✓✗ |
156 |
if (p_matches != NULL) |
376 |
|
|
/* |
377 |
|
|
* Report matches, even if we're hiding highlights. |
378 |
|
|
*/ |
379 |
|
156 |
*p_matches = 1; |
380 |
|
|
|
381 |
✗✓ |
156 |
if (hilite_search == 0) |
382 |
|
|
/* |
383 |
|
|
* Not doing highlighting. |
384 |
|
|
*/ |
385 |
|
|
return (0); |
386 |
|
|
|
387 |
✓✓ |
156 |
if (!nohide && hide_hilite) |
388 |
|
|
/* |
389 |
|
|
* Highlighting is hidden. |
390 |
|
|
*/ |
391 |
|
60 |
return (0); |
392 |
|
|
|
393 |
|
96 |
return (1); |
394 |
|
38635 |
} |
395 |
|
|
|
396 |
|
|
/* |
397 |
|
|
* Add a new hilite to a hilite list. |
398 |
|
|
*/ |
399 |
|
|
static void |
400 |
|
|
add_hilite(struct hilite *anchor, struct hilite *hl) |
401 |
|
|
{ |
402 |
|
|
struct hilite *ihl; |
403 |
|
|
|
404 |
|
|
/* |
405 |
|
|
* Hilites are sorted in the list; find where new one belongs. |
406 |
|
|
* Insert new one after ihl. |
407 |
|
|
*/ |
408 |
✓✓ |
1248 |
for (ihl = anchor; ihl->hl_next != NULL; ihl = ihl->hl_next) |
409 |
|
|
{ |
410 |
✓✗ |
552 |
if (ihl->hl_next->hl_startpos > hl->hl_startpos) |
411 |
|
|
break; |
412 |
|
|
} |
413 |
|
|
|
414 |
|
|
/* |
415 |
|
|
* Truncate hilite so it doesn't overlap any existing ones |
416 |
|
|
* above and below it. |
417 |
|
|
*/ |
418 |
✓✓ |
48 |
if (ihl != anchor) |
419 |
|
46 |
hl->hl_startpos = MAXPOS(hl->hl_startpos, ihl->hl_endpos); |
420 |
✗✓ |
48 |
if (ihl->hl_next != NULL) |
421 |
|
|
hl->hl_endpos = MINPOS(hl->hl_endpos, |
422 |
|
|
ihl->hl_next->hl_startpos); |
423 |
✗✓ |
48 |
if (hl->hl_startpos >= hl->hl_endpos) { |
424 |
|
|
/* |
425 |
|
|
* Hilite was truncated out of existence. |
426 |
|
|
*/ |
427 |
|
|
free(hl); |
428 |
|
|
return; |
429 |
|
|
} |
430 |
|
48 |
hl->hl_next = ihl->hl_next; |
431 |
|
48 |
ihl->hl_next = hl; |
432 |
|
96 |
} |
433 |
|
|
|
434 |
|
|
/* |
435 |
|
|
* Hilight every character in a range of displayed characters. |
436 |
|
|
*/ |
437 |
|
|
static void |
438 |
|
|
create_hilites(off_t linepos, int start_index, int end_index, int *chpos) |
439 |
|
|
{ |
440 |
|
|
struct hilite *hl; |
441 |
|
|
int i; |
442 |
|
|
|
443 |
|
|
/* Start the first hilite. */ |
444 |
|
96 |
hl = ecalloc(1, sizeof (struct hilite)); |
445 |
|
48 |
hl->hl_startpos = linepos + chpos[start_index]; |
446 |
|
|
|
447 |
|
|
/* |
448 |
|
|
* Step through the displayed chars. |
449 |
|
|
* If the source position (before cvt) of the char is one more |
450 |
|
|
* than the source pos of the previous char (the usual case), |
451 |
|
|
* just increase the size of the current hilite by one. |
452 |
|
|
* Otherwise (there are backspaces or something involved), |
453 |
|
|
* finish the current hilite and start a new one. |
454 |
|
|
*/ |
455 |
✓✓ |
480 |
for (i = start_index+1; i <= end_index; i++) { |
456 |
✓✗✓✓
|
384 |
if (chpos[i] != chpos[i-1] + 1 || i == end_index) { |
457 |
|
48 |
hl->hl_endpos = linepos + chpos[i-1] + 1; |
458 |
|
48 |
add_hilite(&hilite_anchor, hl); |
459 |
|
|
/* Start new hilite unless this is the last char. */ |
460 |
✗✓ |
48 |
if (i < end_index) { |
461 |
|
|
hl = ecalloc(1, sizeof (struct hilite)); |
462 |
|
|
hl->hl_startpos = linepos + chpos[i]; |
463 |
|
|
} |
464 |
|
|
} |
465 |
|
|
} |
466 |
|
48 |
} |
467 |
|
|
|
468 |
|
|
/* |
469 |
|
|
* Make a hilite for each string in a physical line which matches |
470 |
|
|
* the current pattern. |
471 |
|
|
* sp,ep delimit the first match already found. |
472 |
|
|
*/ |
473 |
|
|
static void |
474 |
|
|
hilite_line(off_t linepos, char *line, int line_len, int *chpos, |
475 |
|
|
char *sp, char *ep) |
476 |
|
|
{ |
477 |
|
|
char *searchp; |
478 |
|
48 |
char *line_end = line + line_len; |
479 |
|
|
|
480 |
|
|
/* |
481 |
|
|
* sp and ep delimit the first match in the line. |
482 |
|
|
* Mark the corresponding file positions, then |
483 |
|
|
* look for further matches and mark them. |
484 |
|
|
* {{ This technique, of calling match_pattern on subsequent |
485 |
|
|
* substrings of the line, may mark more than is correct |
486 |
|
|
* if the pattern starts with "^". This bug is fixed |
487 |
|
|
* for those regex functions that accept a notbol parameter |
488 |
|
|
* (currently POSIX, PCRE and V8-with-regexec2). }} |
489 |
|
|
*/ |
490 |
|
|
searchp = line; |
491 |
|
48 |
do { |
492 |
✗✓ |
48 |
if (sp == NULL || ep == NULL) |
493 |
|
|
return; |
494 |
|
|
|
495 |
|
96 |
create_hilites(linepos, (intptr_t)sp - (intptr_t)line, |
496 |
|
48 |
(intptr_t)ep - (intptr_t)line, chpos); |
497 |
|
|
/* |
498 |
|
|
* If we matched more than zero characters, |
499 |
|
|
* move to the first char after the string we matched. |
500 |
|
|
* If we matched zero, just move to the next char. |
501 |
|
|
*/ |
502 |
✓✗ |
48 |
if (ep > searchp) |
503 |
|
48 |
searchp = ep; |
504 |
|
|
else if (searchp != line_end) |
505 |
|
|
searchp++; |
506 |
|
|
else /* end of line */ |
507 |
|
|
break; |
508 |
✗✓ |
96 |
} while (match_pattern(info_compiled(&search_info), search_info.text, |
509 |
|
48 |
searchp, (intptr_t)line_end - (intptr_t)searchp, &sp, &ep, 1, |
510 |
|
48 |
search_info.search_type)); |
511 |
|
96 |
} |
512 |
|
|
|
513 |
|
|
/* |
514 |
|
|
* Change the caseless-ness of searches. |
515 |
|
|
* Updates the internal search state to reflect a change in the -i flag. |
516 |
|
|
*/ |
517 |
|
|
void |
518 |
|
|
chg_caseless(void) |
519 |
|
|
{ |
520 |
|
|
if (!is_ucase_pattern) |
521 |
|
|
/* |
522 |
|
|
* Pattern did not have uppercase. |
523 |
|
|
* Just set the search caselessness to the global caselessness. |
524 |
|
|
*/ |
525 |
|
|
is_caseless = caseless; |
526 |
|
|
else |
527 |
|
|
/* |
528 |
|
|
* Pattern did have uppercase. |
529 |
|
|
* Discard the pattern; we can't change search caselessness now. |
530 |
|
|
*/ |
531 |
|
|
clear_pattern(&search_info); |
532 |
|
|
} |
533 |
|
|
|
534 |
|
|
/* |
535 |
|
|
* Find matching text which is currently on screen and highlight it. |
536 |
|
|
*/ |
537 |
|
|
static void |
538 |
|
|
hilite_screen(void) |
539 |
|
|
{ |
540 |
|
6 |
struct scrpos scrpos; |
541 |
|
|
|
542 |
|
3 |
get_scrpos(&scrpos); |
543 |
✗✓ |
3 |
if (scrpos.pos == -1) |
544 |
|
|
return; |
545 |
|
3 |
prep_hilite(scrpos.pos, position(BOTTOM_PLUS_ONE), -1); |
546 |
|
3 |
repaint_hilite(1); |
547 |
|
6 |
} |
548 |
|
|
|
549 |
|
|
/* |
550 |
|
|
* Change highlighting parameters. |
551 |
|
|
*/ |
552 |
|
|
void |
553 |
|
|
chg_hilite(void) |
554 |
|
|
{ |
555 |
|
|
/* |
556 |
|
|
* Erase any highlights currently on screen. |
557 |
|
|
*/ |
558 |
|
|
clr_hilite(); |
559 |
|
|
hide_hilite = 0; |
560 |
|
|
|
561 |
|
|
if (hilite_search == OPT_ONPLUS) |
562 |
|
|
/* |
563 |
|
|
* Display highlights. |
564 |
|
|
*/ |
565 |
|
|
hilite_screen(); |
566 |
|
|
} |
567 |
|
|
|
568 |
|
|
/* |
569 |
|
|
* Figure out where to start a search. |
570 |
|
|
*/ |
571 |
|
|
static off_t |
572 |
|
|
search_pos(int search_type) |
573 |
|
|
{ |
574 |
|
|
off_t pos; |
575 |
|
|
int linenum; |
576 |
|
|
|
577 |
✗✓ |
6 |
if (empty_screen()) { |
578 |
|
|
/* |
579 |
|
|
* Start at the beginning (or end) of the file. |
580 |
|
|
* The empty_screen() case is mainly for |
581 |
|
|
* command line initiated searches; |
582 |
|
|
* for example, "+/xyz" on the command line. |
583 |
|
|
* Also for multi-file (SRCH_PAST_EOF) searches. |
584 |
|
|
*/ |
585 |
|
|
if (search_type & SRCH_FORW) { |
586 |
|
|
pos = ch_zero(); |
587 |
|
|
} else { |
588 |
|
|
pos = ch_length(); |
589 |
|
|
if (pos == -1) { |
590 |
|
|
(void) ch_end_seek(); |
591 |
|
|
pos = ch_length(); |
592 |
|
|
} |
593 |
|
|
} |
594 |
|
|
linenum = 0; |
595 |
|
|
} else { |
596 |
|
|
int add_one = 0; |
597 |
|
|
|
598 |
✗✓ |
3 |
if (how_search == OPT_ON) { |
599 |
|
|
/* |
600 |
|
|
* Search does not include current screen. |
601 |
|
|
*/ |
602 |
|
|
if (search_type & SRCH_FORW) |
603 |
|
|
linenum = BOTTOM_PLUS_ONE; |
604 |
|
|
else |
605 |
|
|
linenum = TOP; |
606 |
✓✗✓✗
|
6 |
} else if (how_search == OPT_ONPLUS && |
607 |
|
3 |
!(search_type & SRCH_AFTER_TARGET)) { |
608 |
|
|
/* |
609 |
|
|
* Search includes all of displayed screen. |
610 |
|
|
*/ |
611 |
✓✗ |
3 |
if (search_type & SRCH_FORW) |
612 |
|
3 |
linenum = TOP; |
613 |
|
|
else |
614 |
|
|
linenum = BOTTOM_PLUS_ONE; |
615 |
|
|
} else { |
616 |
|
|
/* |
617 |
|
|
* Search includes the part of current screen beyond |
618 |
|
|
* the jump target. |
619 |
|
|
* It starts at the jump target (if searching |
620 |
|
|
* backwards), or at the jump target plus one |
621 |
|
|
* (if forwards). |
622 |
|
|
*/ |
623 |
|
|
linenum = jump_sline; |
624 |
|
|
if (search_type & SRCH_FORW) |
625 |
|
|
add_one = 1; |
626 |
|
|
} |
627 |
|
3 |
linenum = adjsline(linenum); |
628 |
|
3 |
pos = position(linenum); |
629 |
✗✓ |
3 |
if (add_one) |
630 |
|
|
pos = forw_raw_line(pos, NULL, NULL); |
631 |
|
|
} |
632 |
|
|
|
633 |
|
|
/* |
634 |
|
|
* If the line is empty, look around for a plausible starting place. |
635 |
|
|
*/ |
636 |
✓✗ |
3 |
if (search_type & SRCH_FORW) { |
637 |
✗✓ |
6 |
while (pos == -1) { |
638 |
|
|
if (++linenum >= sc_height) |
639 |
|
|
break; |
640 |
|
|
pos = position(linenum); |
641 |
|
|
} |
642 |
|
|
} else { |
643 |
|
|
while (pos == -1) { |
644 |
|
|
if (--linenum < 0) |
645 |
|
|
break; |
646 |
|
|
pos = position(linenum); |
647 |
|
|
} |
648 |
|
|
} |
649 |
|
3 |
return (pos); |
650 |
|
|
} |
651 |
|
|
|
652 |
|
|
/* |
653 |
|
|
* Search a subset of the file, specified by start/end position. |
654 |
|
|
*/ |
655 |
|
|
static int |
656 |
|
|
search_range(off_t pos, off_t endpos, int search_type, int matches, |
657 |
|
|
int maxlines, off_t *plinepos, off_t *pendpos) |
658 |
|
|
{ |
659 |
|
594 |
char *line; |
660 |
|
|
char *cline; |
661 |
|
297 |
int line_len; |
662 |
|
|
off_t linenum; |
663 |
|
297 |
char *sp, *ep; |
664 |
|
|
int line_match; |
665 |
|
|
int cvt_ops; |
666 |
|
|
int cvt_len; |
667 |
|
|
int *chpos; |
668 |
|
|
off_t linepos, oldpos; |
669 |
|
|
|
670 |
|
297 |
linenum = find_linenum(pos); |
671 |
|
|
oldpos = pos; |
672 |
|
10286 |
for (;;) { |
673 |
|
|
/* |
674 |
|
|
* Get lines until we find a matching one or until |
675 |
|
|
* we hit end-of-file (or beginning-of-file if we're |
676 |
|
|
* going backwards), or until we hit the end position. |
677 |
|
|
*/ |
678 |
✗✓ |
10286 |
if (ABORT_SIGS()) { |
679 |
|
|
/* |
680 |
|
|
* A signal aborts the search. |
681 |
|
|
*/ |
682 |
|
|
return (-1); |
683 |
|
|
} |
684 |
|
|
|
685 |
✓✓✓✓ ✗✓ |
23962 |
if ((endpos != -1 && pos >= endpos) || |
686 |
|
10286 |
maxlines == 0) { |
687 |
|
|
/* |
688 |
|
|
* Reached end position without a match. |
689 |
|
|
*/ |
690 |
✓✗ |
6 |
if (pendpos != NULL) |
691 |
|
6 |
*pendpos = pos; |
692 |
|
6 |
return (matches); |
693 |
|
|
} |
694 |
✗✓ |
10280 |
if (maxlines > 0) |
695 |
|
|
maxlines--; |
696 |
|
|
|
697 |
✓✗ |
10280 |
if (search_type & SRCH_FORW) { |
698 |
|
|
/* |
699 |
|
|
* Read the next line, and save the |
700 |
|
|
* starting position of that line in linepos. |
701 |
|
|
*/ |
702 |
|
|
linepos = pos; |
703 |
|
10280 |
pos = forw_raw_line(pos, &line, &line_len); |
704 |
✓✗ |
10280 |
if (linenum != 0) |
705 |
|
10280 |
linenum++; |
706 |
|
|
} else { |
707 |
|
|
/* |
708 |
|
|
* Read the previous line and save the |
709 |
|
|
* starting position of that line in linepos. |
710 |
|
|
*/ |
711 |
|
|
pos = back_raw_line(pos, &line, &line_len); |
712 |
|
|
linepos = pos; |
713 |
|
|
if (linenum != 0) |
714 |
|
|
linenum--; |
715 |
|
|
} |
716 |
|
|
|
717 |
✓✓ |
10280 |
if (pos == -1) { |
718 |
|
|
/* |
719 |
|
|
* Reached EOF/BOF without a match. |
720 |
|
|
*/ |
721 |
✓✓ |
290 |
if (pendpos != NULL) |
722 |
|
288 |
*pendpos = oldpos; |
723 |
|
290 |
return (matches); |
724 |
|
|
} |
725 |
|
|
|
726 |
|
|
/* |
727 |
|
|
* If we're using line numbers, we might as well |
728 |
|
|
* remember the information we have now (the position |
729 |
|
|
* and line number of the current line). |
730 |
|
|
* Don't do it for every line because it slows down |
731 |
|
|
* the search. Remember the line number only if |
732 |
|
|
* we're "far" from the last place we remembered it. |
733 |
|
|
*/ |
734 |
✓✗✓✓
|
19980 |
if (linenums && abs((int)(pos - oldpos)) > 2048) |
735 |
|
3 |
add_lnum(linenum, pos); |
736 |
|
|
oldpos = pos; |
737 |
|
|
|
738 |
✗✓ |
9990 |
if (is_filtered(linepos)) |
739 |
|
|
continue; |
740 |
|
|
|
741 |
|
|
/* |
742 |
|
|
* If it's a caseless search, convert the line to lowercase. |
743 |
|
|
* If we're doing backspace processing, delete backspaces. |
744 |
|
|
*/ |
745 |
|
9990 |
cvt_ops = get_cvt_ops(); |
746 |
|
9990 |
cvt_len = cvt_length(line_len); |
747 |
|
9990 |
cline = ecalloc(1, cvt_len); |
748 |
|
9990 |
chpos = cvt_alloc_chpos(cvt_len); |
749 |
|
9990 |
cvt_text(cline, line, chpos, &line_len, cvt_ops); |
750 |
|
|
|
751 |
|
|
/* |
752 |
|
|
* Check to see if the line matches the filter pattern. |
753 |
|
|
* If so, add an entry to the filter list. |
754 |
|
|
*/ |
755 |
✓✓✗✓
|
13086 |
if ((search_type & SRCH_FIND_ALL) && |
756 |
|
3096 |
prev_pattern(&filter_info)) { |
757 |
|
|
int line_filter = |
758 |
|
|
match_pattern(info_compiled(&filter_info), |
759 |
|
|
filter_info.text, cline, line_len, &sp, &ep, 0, |
760 |
|
|
filter_info.search_type); |
761 |
|
|
if (line_filter) { |
762 |
|
|
struct hilite *hl = |
763 |
|
|
ecalloc(1, sizeof (struct hilite)); |
764 |
|
|
hl->hl_startpos = linepos; |
765 |
|
|
hl->hl_endpos = pos; |
766 |
|
|
add_hilite(&filter_anchor, hl); |
767 |
|
|
} |
768 |
|
|
} |
769 |
|
|
|
770 |
|
|
/* |
771 |
|
|
* Test the next line to see if we have a match. |
772 |
|
|
* We are successful if we either want a match and got one, |
773 |
|
|
* or if we want a non-match and got one. |
774 |
|
|
*/ |
775 |
✓✗ |
9990 |
if (prev_pattern(&search_info)) { |
776 |
|
19980 |
line_match = match_pattern(info_compiled(&search_info), |
777 |
|
9990 |
search_info.text, cline, line_len, &sp, &ep, 0, |
778 |
|
|
search_type); |
779 |
✓✓ |
9990 |
if (line_match) { |
780 |
|
|
/* |
781 |
|
|
* Got a match. |
782 |
|
|
*/ |
783 |
✓✓ |
49 |
if (search_type & SRCH_FIND_ALL) { |
784 |
|
|
/* |
785 |
|
|
* We are supposed to find all matches |
786 |
|
|
* in the range. |
787 |
|
|
* Just add the matches in this line |
788 |
|
|
* to the hilite list and keep |
789 |
|
|
* searching. |
790 |
|
|
*/ |
791 |
|
96 |
hilite_line(linepos, cline, line_len, |
792 |
|
48 |
chpos, sp, ep); |
793 |
✓✗ |
49 |
} else if (--matches <= 0) { |
794 |
|
|
/* |
795 |
|
|
* Found the one match we're looking |
796 |
|
|
* for. Return it. |
797 |
|
|
*/ |
798 |
✗✓ |
1 |
if (hilite_search == OPT_ON) { |
799 |
|
|
/* |
800 |
|
|
* Clear the hilite list and |
801 |
|
|
* add only |
802 |
|
|
* the matches in this one line. |
803 |
|
|
*/ |
804 |
|
|
clr_hilite(); |
805 |
|
|
hilite_line(linepos, cline, |
806 |
|
|
line_len, chpos, sp, ep); |
807 |
|
|
} |
808 |
|
1 |
free(cline); |
809 |
|
1 |
free(chpos); |
810 |
✓✗ |
1 |
if (plinepos != NULL) |
811 |
|
1 |
*plinepos = linepos; |
812 |
|
1 |
return (0); |
813 |
|
|
} |
814 |
|
|
} |
815 |
|
|
} |
816 |
|
9989 |
free(cline); |
817 |
|
9989 |
free(chpos); |
818 |
|
|
} |
819 |
|
297 |
} |
820 |
|
|
|
821 |
|
|
/* |
822 |
|
|
* search for a pattern in history. If found, compile that pattern. |
823 |
|
|
*/ |
824 |
|
|
static int |
825 |
|
|
hist_pattern(int search_type) |
826 |
|
|
{ |
827 |
|
|
char *pattern; |
828 |
|
|
|
829 |
|
2 |
set_mlist(ml_search, 0); |
830 |
|
1 |
pattern = cmd_lastpattern(); |
831 |
✓✗ |
1 |
if (pattern == NULL) |
832 |
|
1 |
return (0); |
833 |
|
|
|
834 |
|
|
if (set_pattern(&search_info, pattern, search_type) < 0) |
835 |
|
|
return (0); |
836 |
|
|
|
837 |
|
|
if (hilite_search == OPT_ONPLUS && !hide_hilite) |
838 |
|
|
hilite_screen(); |
839 |
|
|
|
840 |
|
|
return (1); |
841 |
|
1 |
} |
842 |
|
|
|
843 |
|
|
/* |
844 |
|
|
* Search for the n-th occurrence of a specified pattern, |
845 |
|
|
* either forward or backward. |
846 |
|
|
* Return the number of matches not yet found in this file |
847 |
|
|
* (that is, n minus the number of matches found). |
848 |
|
|
* Return -1 if the search should be aborted. |
849 |
|
|
* Caller may continue the search in another file |
850 |
|
|
* if less than n matches are found in this file. |
851 |
|
|
*/ |
852 |
|
|
int |
853 |
|
|
search(int search_type, char *pattern, int n) |
854 |
|
|
{ |
855 |
|
8 |
off_t pos; |
856 |
|
|
|
857 |
✓✓✗✓
|
7 |
if (pattern == NULL || *pattern == '\0') { |
858 |
|
|
/* |
859 |
|
|
* A null pattern means use the previously compiled pattern. |
860 |
|
|
*/ |
861 |
|
1 |
search_type |= SRCH_AFTER_TARGET; |
862 |
✓✗✓✗
|
2 |
if (!prev_pattern(&search_info) && !hist_pattern(search_type)) { |
863 |
|
1 |
error("No previous regular expression", NULL); |
864 |
|
1 |
return (-1); |
865 |
|
|
} |
866 |
|
|
if ((search_type & SRCH_NO_REGEX) != |
867 |
|
|
(search_info.search_type & SRCH_NO_REGEX)) { |
868 |
|
|
error("Please re-enter search pattern", NULL); |
869 |
|
|
return (-1); |
870 |
|
|
} |
871 |
|
|
if (hilite_search == OPT_ON) { |
872 |
|
|
/* |
873 |
|
|
* Erase the highlights currently on screen. |
874 |
|
|
* If the search fails, we'll redisplay them later. |
875 |
|
|
*/ |
876 |
|
|
repaint_hilite(0); |
877 |
|
|
} |
878 |
|
|
if (hilite_search == OPT_ONPLUS && hide_hilite) { |
879 |
|
|
/* |
880 |
|
|
* Highlight any matches currently on screen, |
881 |
|
|
* before we actually start the search. |
882 |
|
|
*/ |
883 |
|
|
hide_hilite = 0; |
884 |
|
|
hilite_screen(); |
885 |
|
|
} |
886 |
|
|
hide_hilite = 0; |
887 |
|
|
} else { |
888 |
|
|
/* |
889 |
|
|
* Compile the pattern. |
890 |
|
|
*/ |
891 |
✗✓ |
3 |
if (set_pattern(&search_info, pattern, search_type) < 0) |
892 |
|
|
return (-1); |
893 |
✓✗ |
3 |
if (hilite_search) { |
894 |
|
|
/* |
895 |
|
|
* Erase the highlights currently on screen. |
896 |
|
|
* Also permanently delete them from the hilite list. |
897 |
|
|
*/ |
898 |
|
3 |
repaint_hilite(0); |
899 |
|
3 |
hide_hilite = 0; |
900 |
|
3 |
clr_hilite(); |
901 |
|
3 |
} |
902 |
✓✗ |
3 |
if (hilite_search == OPT_ONPLUS) { |
903 |
|
|
/* |
904 |
|
|
* Highlight any matches currently on screen, |
905 |
|
|
* before we actually start the search. |
906 |
|
|
*/ |
907 |
|
3 |
hilite_screen(); |
908 |
|
3 |
} |
909 |
|
|
} |
910 |
|
|
|
911 |
|
|
/* |
912 |
|
|
* Figure out where to start the search. |
913 |
|
|
*/ |
914 |
|
3 |
pos = search_pos(search_type); |
915 |
✗✓ |
3 |
if (pos == -1) { |
916 |
|
|
/* |
917 |
|
|
* Can't find anyplace to start searching from. |
918 |
|
|
*/ |
919 |
|
|
if (search_type & SRCH_PAST_EOF) |
920 |
|
|
return (n); |
921 |
|
|
/* repaint(); -- why was this here? */ |
922 |
|
|
error("Nothing to search", NULL); |
923 |
|
|
return (-1); |
924 |
|
|
} |
925 |
|
|
|
926 |
|
3 |
n = search_range(pos, -1, search_type, n, -1, &pos, NULL); |
927 |
✓✓ |
3 |
if (n != 0) { |
928 |
|
|
/* |
929 |
|
|
* Search was unsuccessful. |
930 |
|
|
*/ |
931 |
✗✓ |
2 |
if (hilite_search == OPT_ON && n > 0) |
932 |
|
|
/* |
933 |
|
|
* Redisplay old hilites. |
934 |
|
|
*/ |
935 |
|
|
repaint_hilite(1); |
936 |
|
2 |
return (n); |
937 |
|
|
} |
938 |
|
|
|
939 |
✓✗ |
1 |
if (!(search_type & SRCH_NO_MOVE)) { |
940 |
|
|
/* |
941 |
|
|
* Go to the matching line. |
942 |
|
|
*/ |
943 |
|
1 |
jump_loc(pos, jump_sline); |
944 |
|
1 |
} |
945 |
|
|
|
946 |
✗✓ |
1 |
if (hilite_search == OPT_ON) |
947 |
|
|
/* |
948 |
|
|
* Display new hilites in the matching line. |
949 |
|
|
*/ |
950 |
|
|
repaint_hilite(1); |
951 |
|
1 |
return (0); |
952 |
|
4 |
} |
953 |
|
|
|
954 |
|
|
|
955 |
|
|
/* |
956 |
|
|
* Prepare hilites in a given range of the file. |
957 |
|
|
* |
958 |
|
|
* The pair (prep_startpos,prep_endpos) delimits a contiguous region |
959 |
|
|
* of the file that has been "prepared"; that is, scanned for matches for |
960 |
|
|
* the current search pattern, and hilites have been created for such matches. |
961 |
|
|
* If prep_startpos == -1, the prep region is empty. |
962 |
|
|
* If prep_endpos == -1, the prep region extends to EOF. |
963 |
|
|
* prep_hilite asks that the range (spos,epos) be covered by the prep region. |
964 |
|
|
*/ |
965 |
|
|
void |
966 |
|
|
prep_hilite(off_t spos, off_t epos, int maxlines) |
967 |
|
|
{ |
968 |
|
2330 |
off_t nprep_startpos = prep_startpos; |
969 |
|
1165 |
off_t nprep_endpos = prep_endpos; |
970 |
|
1165 |
off_t new_epos; |
971 |
|
|
off_t max_epos; |
972 |
|
|
int result; |
973 |
|
|
int i; |
974 |
|
|
|
975 |
|
|
/* |
976 |
|
|
* Search beyond where we're asked to search, so the prep region covers |
977 |
|
|
* more than we need. Do one big search instead of a bunch of small ones. |
978 |
|
|
*/ |
979 |
|
|
#define SEARCH_MORE (3*size_linebuf) |
980 |
|
|
|
981 |
✓✓✓✗
|
1421 |
if (!prev_pattern(&search_info) && !is_filtering()) |
982 |
|
256 |
return; |
983 |
|
|
|
984 |
|
|
/* |
985 |
|
|
* If we're limited to a max number of lines, figure out the |
986 |
|
|
* file position we should stop at. |
987 |
|
|
*/ |
988 |
✓✗ |
909 |
if (maxlines < 0) { |
989 |
|
|
max_epos = -1; |
990 |
|
909 |
} else { |
991 |
|
|
max_epos = spos; |
992 |
|
|
for (i = 0; i < maxlines; i++) |
993 |
|
|
max_epos = forw_raw_line(max_epos, NULL, NULL); |
994 |
|
|
} |
995 |
|
|
|
996 |
|
|
/* |
997 |
|
|
* Find two ranges: |
998 |
|
|
* The range that we need to search (spos,epos); and the range that |
999 |
|
|
* the "prep" region will then cover (nprep_startpos,nprep_endpos). |
1000 |
|
|
*/ |
1001 |
|
|
|
1002 |
✓✓✗✓
|
1812 |
if (prep_startpos == -1 || |
1003 |
✓✗✓✗
|
1806 |
(epos != -1 && epos < prep_startpos) || |
1004 |
|
903 |
spos > prep_endpos) { |
1005 |
|
|
/* |
1006 |
|
|
* New range is not contiguous with old prep region. |
1007 |
|
|
* Discard the old prep region and start a new one. |
1008 |
|
|
*/ |
1009 |
|
6 |
clr_hilite(); |
1010 |
|
6 |
clr_filter(); |
1011 |
✓✗ |
6 |
if (epos != -1) |
1012 |
|
6 |
epos += SEARCH_MORE; |
1013 |
|
|
nprep_startpos = spos; |
1014 |
|
6 |
} else { |
1015 |
|
|
/* |
1016 |
|
|
* New range partially or completely overlaps old prep region. |
1017 |
|
|
*/ |
1018 |
✓✗ |
903 |
if (epos != -1) { |
1019 |
✓✓ |
903 |
if (epos > prep_endpos) { |
1020 |
|
|
/* |
1021 |
|
|
* New range ends after old prep region. |
1022 |
|
|
* Extend prep region to end at end of new |
1023 |
|
|
* range. |
1024 |
|
|
*/ |
1025 |
|
288 |
epos += SEARCH_MORE; |
1026 |
|
|
|
1027 |
|
288 |
} else { |
1028 |
|
|
/* |
1029 |
|
|
* New range ends within old prep region. |
1030 |
|
|
* Truncate search to end at start of old prep |
1031 |
|
|
* region. |
1032 |
|
|
*/ |
1033 |
|
615 |
epos = prep_startpos; |
1034 |
|
|
} |
1035 |
|
|
} |
1036 |
|
|
|
1037 |
✗✓ |
903 |
if (spos < prep_startpos) { |
1038 |
|
|
/* |
1039 |
|
|
* New range starts before old prep region. |
1040 |
|
|
* Extend old prep region backwards to start at |
1041 |
|
|
* start of new range. |
1042 |
|
|
*/ |
1043 |
|
|
if (spos < SEARCH_MORE) |
1044 |
|
|
spos = 0; |
1045 |
|
|
else |
1046 |
|
|
spos -= SEARCH_MORE; |
1047 |
|
|
nprep_startpos = spos; |
1048 |
|
|
} else { /* (spos >= prep_startpos) */ |
1049 |
|
|
/* |
1050 |
|
|
* New range starts within or after old prep region. |
1051 |
|
|
* Trim search to start at end of old prep region. |
1052 |
|
|
*/ |
1053 |
|
903 |
spos = prep_endpos; |
1054 |
|
|
} |
1055 |
|
|
} |
1056 |
|
|
|
1057 |
✗✓✗✗
|
909 |
if (epos != -1 && max_epos != -1 && |
1058 |
|
|
epos > max_epos) |
1059 |
|
|
/* |
1060 |
|
|
* Don't go past the max position we're allowed. |
1061 |
|
|
*/ |
1062 |
|
|
epos = max_epos; |
1063 |
|
|
|
1064 |
✓✗✓✓
|
1818 |
if (epos == -1 || epos > spos) { |
1065 |
|
|
int search_type = SRCH_FORW | SRCH_FIND_ALL; |
1066 |
|
294 |
search_type |= (search_info.search_type & SRCH_NO_REGEX); |
1067 |
|
294 |
result = search_range(spos, epos, search_type, 0, |
1068 |
|
|
maxlines, NULL, &new_epos); |
1069 |
✗✓ |
294 |
if (result < 0) |
1070 |
|
|
return; |
1071 |
✓✓✓✓
|
582 |
if (prep_endpos == -1 || new_epos > prep_endpos) |
1072 |
|
9 |
nprep_endpos = new_epos; |
1073 |
✓✗ |
294 |
} |
1074 |
|
909 |
prep_startpos = nprep_startpos; |
1075 |
|
909 |
prep_endpos = nprep_endpos; |
1076 |
|
2074 |
} |
1077 |
|
|
|
1078 |
|
|
/* |
1079 |
|
|
* Set the pattern to be used for line filtering. |
1080 |
|
|
*/ |
1081 |
|
|
void |
1082 |
|
|
set_filter_pattern(char *pattern, int search_type) |
1083 |
|
|
{ |
1084 |
|
|
clr_filter(); |
1085 |
|
|
if (pattern == NULL || *pattern == '\0') |
1086 |
|
|
clear_pattern(&filter_info); |
1087 |
|
|
else |
1088 |
|
|
(void) set_pattern(&filter_info, pattern, search_type); |
1089 |
|
|
screen_trashed = 1; |
1090 |
|
|
} |
1091 |
|
|
|
1092 |
|
|
/* |
1093 |
|
|
* Is there a line filter in effect? |
1094 |
|
|
*/ |
1095 |
|
|
int |
1096 |
|
|
is_filtering(void) |
1097 |
|
|
{ |
1098 |
✗✓ |
594 |
if (ch_getflags() & CH_HELPFILE) |
1099 |
|
|
return (0); |
1100 |
|
297 |
return (prev_pattern(&filter_info)); |
1101 |
|
297 |
} |