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