xref: /netbsd-src/external/bsd/less/dist/input.c (revision 838f5788460f0f133b15d706e644d692a9d4d6ec)
1*838f5788Ssimonb /*	$NetBSD: input.c,v 1.4 2023/10/06 05:49:49 simonb Exp $	*/
220006a0bStron 
320006a0bStron /*
4*838f5788Ssimonb  * Copyright (C) 1984-2023  Mark Nudelman
520006a0bStron  *
620006a0bStron  * You may distribute under the terms of either the GNU General Public
720006a0bStron  * License or the Less License, as specified in the README file.
820006a0bStron  *
9ec18bca0Stron  * For more information, see the README file.
1020006a0bStron  */
1120006a0bStron 
1220006a0bStron /*
1320006a0bStron  * High level routines dealing with getting lines of input
1420006a0bStron  * from the file being viewed.
1520006a0bStron  *
1620006a0bStron  * When we speak of "lines" here, we mean PRINTABLE lines;
1720006a0bStron  * lines processed with respect to the screen width.
1820006a0bStron  * We use the term "raw line" to refer to lines simply
1920006a0bStron  * delimited by newlines; not processed with respect to screen width.
2020006a0bStron  */
2120006a0bStron 
2220006a0bStron #include "less.h"
2320006a0bStron 
2420006a0bStron extern int squeeze;
2520006a0bStron extern int hshift;
2620006a0bStron extern int quit_if_one_screen;
2720006a0bStron extern int sigs;
2820006a0bStron extern int ignore_eoi;
2920006a0bStron extern int status_col;
30*838f5788Ssimonb extern int wordwrap;
3120006a0bStron extern POSITION start_attnpos;
3220006a0bStron extern POSITION end_attnpos;
3320006a0bStron #if HILITE_SEARCH
3420006a0bStron extern int hilite_search;
3520006a0bStron extern int size_linebuf;
36*838f5788Ssimonb extern int show_attn;
3720006a0bStron #endif
3820006a0bStron 
3920006a0bStron /*
40*838f5788Ssimonb  * Set the status column.
41*838f5788Ssimonb  *  base  Position of first char in line.
42*838f5788Ssimonb  *  disp  First visible char.
43*838f5788Ssimonb  *        Different than base_pos if line is shifted.
44*838f5788Ssimonb  *  edisp Last visible char.
45*838f5788Ssimonb  *  eol   End of line. Normally the newline.
46*838f5788Ssimonb  *        Different than edisp if line is chopped.
47*838f5788Ssimonb  */
init_status_col(POSITION base_pos,POSITION disp_pos,POSITION edisp_pos,POSITION eol_pos)48*838f5788Ssimonb static void init_status_col(POSITION base_pos, POSITION disp_pos, POSITION edisp_pos, POSITION eol_pos)
49*838f5788Ssimonb {
50*838f5788Ssimonb 	int hl_before = (chop_line() && disp_pos != NULL_POSITION) ?
51*838f5788Ssimonb 	    is_hilited_attr(base_pos, disp_pos, TRUE, NULL) : 0;
52*838f5788Ssimonb 	int hl_after = (chop_line()) ?
53*838f5788Ssimonb 	    is_hilited_attr(edisp_pos, eol_pos, TRUE, NULL) : 0;
54*838f5788Ssimonb 	int attr;
55*838f5788Ssimonb 	char ch;
56*838f5788Ssimonb 
57*838f5788Ssimonb 	if (hl_before && hl_after)
58*838f5788Ssimonb 	{
59*838f5788Ssimonb 		attr = hl_after;
60*838f5788Ssimonb 		ch = '=';
61*838f5788Ssimonb 	} else if (hl_before)
62*838f5788Ssimonb 	{
63*838f5788Ssimonb 		attr = hl_before;
64*838f5788Ssimonb 		ch = '<';
65*838f5788Ssimonb 	} else if (hl_after)
66*838f5788Ssimonb 	{
67*838f5788Ssimonb 		attr = hl_after;
68*838f5788Ssimonb 		ch = '>';
69*838f5788Ssimonb 	} else
70*838f5788Ssimonb 	{
71*838f5788Ssimonb 		attr = is_hilited_attr(base_pos, eol_pos, TRUE, NULL);
72*838f5788Ssimonb 		ch = '*';
73*838f5788Ssimonb 	}
74*838f5788Ssimonb 	if (attr)
75*838f5788Ssimonb 		set_status_col(ch, attr);
76*838f5788Ssimonb }
77*838f5788Ssimonb 
78*838f5788Ssimonb /*
7920006a0bStron  * Get the next line.
8020006a0bStron  * A "current" position is passed and a "new" position is returned.
8120006a0bStron  * The current position is the position of the first character of
8220006a0bStron  * a line.  The new position is the position of the first character
8320006a0bStron  * of the NEXT line.  The line obtained is the line starting at curr_pos.
8420006a0bStron  */
forw_line_seg(POSITION curr_pos,int skipeol,int rscroll,int nochop)85*838f5788Ssimonb public POSITION forw_line_seg(POSITION curr_pos, int skipeol, int rscroll, int nochop)
8620006a0bStron {
8720006a0bStron 	POSITION base_pos;
8820006a0bStron 	POSITION new_pos;
89*838f5788Ssimonb 	POSITION edisp_pos;
90*838f5788Ssimonb 	int c;
9120006a0bStron 	int blankline;
9220006a0bStron 	int endline;
93*838f5788Ssimonb 	int chopped;
9420006a0bStron 	int backchars;
95*838f5788Ssimonb 	POSITION wrap_pos;
96*838f5788Ssimonb 	int skipped_leading;
9720006a0bStron 
9820006a0bStron get_forw_line:
9920006a0bStron 	if (curr_pos == NULL_POSITION)
10020006a0bStron 	{
10120006a0bStron 		null_line();
10220006a0bStron 		return (NULL_POSITION);
10320006a0bStron 	}
10420006a0bStron #if HILITE_SEARCH
10520006a0bStron 	if (hilite_search == OPT_ONPLUS || is_filtering() || status_col)
106*838f5788Ssimonb 	{
10720006a0bStron 		/*
10820006a0bStron 		 * If we are ignoring EOI (command F), only prepare
10920006a0bStron 		 * one line ahead, to avoid getting stuck waiting for
11020006a0bStron 		 * slow data without displaying the data we already have.
11120006a0bStron 		 * If we're not ignoring EOI, we *could* do the same, but
11220006a0bStron 		 * for efficiency we prepare several lines ahead at once.
11320006a0bStron 		 */
11420006a0bStron 		prep_hilite(curr_pos, curr_pos + 3*size_linebuf,
11520006a0bStron 				ignore_eoi ? 1 : -1);
116*838f5788Ssimonb 		curr_pos = next_unfiltered(curr_pos);
117*838f5788Ssimonb 	}
11820006a0bStron #endif
11920006a0bStron 	if (ch_seek(curr_pos))
12020006a0bStron 	{
12120006a0bStron 		null_line();
12220006a0bStron 		return (NULL_POSITION);
12320006a0bStron 	}
12420006a0bStron 
12520006a0bStron 	/*
12620006a0bStron 	 * Step back to the beginning of the line.
12720006a0bStron 	 */
12820006a0bStron 	base_pos = curr_pos;
12920006a0bStron 	for (;;)
13020006a0bStron 	{
13120006a0bStron 		if (ABORT_SIGS())
13220006a0bStron 		{
13320006a0bStron 			null_line();
13420006a0bStron 			return (NULL_POSITION);
13520006a0bStron 		}
13620006a0bStron 		c = ch_back_get();
13720006a0bStron 		if (c == EOI)
13820006a0bStron 			break;
13920006a0bStron 		if (c == '\n')
14020006a0bStron 		{
14120006a0bStron 			(void) ch_forw_get();
14220006a0bStron 			break;
14320006a0bStron 		}
14420006a0bStron 		--base_pos;
14520006a0bStron 	}
14620006a0bStron 
14720006a0bStron 	/*
14820006a0bStron 	 * Read forward again to the position we should start at.
14920006a0bStron 	 */
15020006a0bStron 	prewind();
151*838f5788Ssimonb 	plinestart(base_pos);
15220006a0bStron 	(void) ch_seek(base_pos);
15320006a0bStron 	new_pos = base_pos;
15420006a0bStron 	while (new_pos < curr_pos)
15520006a0bStron 	{
15620006a0bStron 		if (ABORT_SIGS())
15720006a0bStron 		{
15820006a0bStron 			null_line();
15920006a0bStron 			return (NULL_POSITION);
16020006a0bStron 		}
16120006a0bStron 		c = ch_forw_get();
16220006a0bStron 		backchars = pappend(c, new_pos);
16320006a0bStron 		new_pos++;
16420006a0bStron 		if (backchars > 0)
16520006a0bStron 		{
16620006a0bStron 			pshift_all();
167*838f5788Ssimonb 			if (wordwrap && (c == ' ' || c == '\t'))
168*838f5788Ssimonb 			{
169*838f5788Ssimonb 				do
170*838f5788Ssimonb 				{
171*838f5788Ssimonb 					new_pos++;
172*838f5788Ssimonb 					c = ch_forw_get();
173*838f5788Ssimonb 				} while (c == ' ' || c == '\t');
174*838f5788Ssimonb 				backchars = 1;
175*838f5788Ssimonb 			}
17620006a0bStron 			new_pos -= backchars;
17720006a0bStron 			while (--backchars >= 0)
17820006a0bStron 				(void) ch_back_get();
17920006a0bStron 		}
18020006a0bStron 	}
18120006a0bStron 	(void) pflushmbc();
18220006a0bStron 	pshift_all();
18320006a0bStron 
18420006a0bStron 	/*
18520006a0bStron 	 * Read the first character to display.
18620006a0bStron 	 */
18720006a0bStron 	c = ch_forw_get();
18820006a0bStron 	if (c == EOI)
18920006a0bStron 	{
19020006a0bStron 		null_line();
19120006a0bStron 		return (NULL_POSITION);
19220006a0bStron 	}
19320006a0bStron 	blankline = (c == '\n' || c == '\r');
194*838f5788Ssimonb 	wrap_pos = NULL_POSITION;
195*838f5788Ssimonb 	skipped_leading = FALSE;
19620006a0bStron 
19720006a0bStron 	/*
19820006a0bStron 	 * Read each character in the line and append to the line buffer.
19920006a0bStron 	 */
200*838f5788Ssimonb 	chopped = FALSE;
20120006a0bStron 	for (;;)
20220006a0bStron 	{
20320006a0bStron 		if (ABORT_SIGS())
20420006a0bStron 		{
20520006a0bStron 			null_line();
20620006a0bStron 			return (NULL_POSITION);
20720006a0bStron 		}
20820006a0bStron 		if (c == '\n' || c == EOI)
20920006a0bStron 		{
21020006a0bStron 			/*
21120006a0bStron 			 * End of the line.
21220006a0bStron 			 */
21320006a0bStron 			backchars = pflushmbc();
21420006a0bStron 			new_pos = ch_tell();
215*838f5788Ssimonb 			if (backchars > 0 && (nochop || !chop_line()) && hshift == 0)
21620006a0bStron 			{
21720006a0bStron 				new_pos -= backchars + 1;
21820006a0bStron 				endline = FALSE;
21920006a0bStron 			} else
22020006a0bStron 				endline = TRUE;
221*838f5788Ssimonb 			edisp_pos = new_pos;
22220006a0bStron 			break;
22320006a0bStron 		}
22420006a0bStron 		if (c != '\r')
22520006a0bStron 			blankline = 0;
22620006a0bStron 
22720006a0bStron 		/*
22820006a0bStron 		 * Append the char to the line and get the next char.
22920006a0bStron 		 */
23020006a0bStron 		backchars = pappend(c, ch_tell()-1);
23120006a0bStron 		if (backchars > 0)
23220006a0bStron 		{
23320006a0bStron 			/*
23420006a0bStron 			 * The char won't fit in the line; the line
23520006a0bStron 			 * is too long to print in the screen width.
23620006a0bStron 			 * End the line here.
23720006a0bStron 			 */
238*838f5788Ssimonb 			if (skipeol)
23920006a0bStron 			{
240*838f5788Ssimonb 				/* Read to end of line. */
241*838f5788Ssimonb 				edisp_pos = ch_tell();
24220006a0bStron 				do
24320006a0bStron 				{
24420006a0bStron 					if (ABORT_SIGS())
24520006a0bStron 					{
24620006a0bStron 						null_line();
24720006a0bStron 						return (NULL_POSITION);
24820006a0bStron 					}
24920006a0bStron 					c = ch_forw_get();
25020006a0bStron 				} while (c != '\n' && c != EOI);
25120006a0bStron 				new_pos = ch_tell();
25220006a0bStron 				endline = TRUE;
25320006a0bStron 				quit_if_one_screen = FALSE;
254*838f5788Ssimonb 				chopped = TRUE;
25520006a0bStron 			} else
25620006a0bStron 			{
257*838f5788Ssimonb 				if (!wordwrap)
25820006a0bStron 					new_pos = ch_tell() - backchars;
259*838f5788Ssimonb 				else
260*838f5788Ssimonb 				{
261*838f5788Ssimonb 					/*
262*838f5788Ssimonb 					 * We're word-wrapping, so go back to the last space.
263*838f5788Ssimonb 					 * However, if it's the space itself that couldn't fit,
264*838f5788Ssimonb 					 * simply ignore it and any subsequent spaces.
265*838f5788Ssimonb 					 */
266*838f5788Ssimonb 					if (c == ' ' || c == '\t')
267*838f5788Ssimonb 					{
268*838f5788Ssimonb 						do
269*838f5788Ssimonb 						{
270*838f5788Ssimonb 							new_pos = ch_tell();
271*838f5788Ssimonb 							c = ch_forw_get();
272*838f5788Ssimonb 						} while (c == ' ' || c == '\t');
273*838f5788Ssimonb 						if (c == '\r')
274*838f5788Ssimonb 							c = ch_forw_get();
275*838f5788Ssimonb 						if (c == '\n')
276*838f5788Ssimonb 							new_pos = ch_tell();
277*838f5788Ssimonb 					} else if (wrap_pos == NULL_POSITION)
278*838f5788Ssimonb 						new_pos = ch_tell() - backchars;
279*838f5788Ssimonb 					else
280*838f5788Ssimonb 					{
281*838f5788Ssimonb 						new_pos = wrap_pos;
282*838f5788Ssimonb 						loadc();
283*838f5788Ssimonb 					}
284*838f5788Ssimonb 				}
28520006a0bStron 				endline = FALSE;
28620006a0bStron 			}
28720006a0bStron 			break;
28820006a0bStron 		}
289*838f5788Ssimonb 		if (wordwrap)
290*838f5788Ssimonb 		{
291*838f5788Ssimonb 			if (c == ' ' || c == '\t')
292*838f5788Ssimonb 			{
293*838f5788Ssimonb 				if (skipped_leading)
294*838f5788Ssimonb 				{
295*838f5788Ssimonb 					wrap_pos = ch_tell();
296*838f5788Ssimonb 					savec();
297*838f5788Ssimonb 				}
298*838f5788Ssimonb 			} else
299*838f5788Ssimonb 				skipped_leading = TRUE;
300*838f5788Ssimonb 		}
30120006a0bStron 		c = ch_forw_get();
30220006a0bStron 	}
30320006a0bStron 
304*838f5788Ssimonb #if HILITE_SEARCH
305*838f5788Ssimonb 	if (blankline && show_attn)
306*838f5788Ssimonb 	{
307*838f5788Ssimonb 		/* Add spurious space to carry possible attn hilite. */
308*838f5788Ssimonb 		pappend(' ', ch_tell()-1);
309*838f5788Ssimonb 	}
310*838f5788Ssimonb #endif
311*838f5788Ssimonb 	pdone(endline, rscroll && chopped, 1);
31220006a0bStron 
31320006a0bStron #if HILITE_SEARCH
31420006a0bStron 	if (is_filtered(base_pos))
31520006a0bStron 	{
31620006a0bStron 		/*
31720006a0bStron 		 * We don't want to display this line.
31820006a0bStron 		 * Get the next line.
31920006a0bStron 		 */
32020006a0bStron 		curr_pos = new_pos;
32120006a0bStron 		goto get_forw_line;
32220006a0bStron 	}
323*838f5788Ssimonb 	if (status_col)
324*838f5788Ssimonb 		init_status_col(base_pos, line_position(), edisp_pos, new_pos);
32520006a0bStron #endif
32620006a0bStron 
32720006a0bStron 	if (squeeze && blankline)
32820006a0bStron 	{
32920006a0bStron 		/*
33020006a0bStron 		 * This line is blank.
33120006a0bStron 		 * Skip down to the last contiguous blank line
33220006a0bStron 		 * and pretend it is the one which we are returning.
33320006a0bStron 		 */
33420006a0bStron 		while ((c = ch_forw_get()) == '\n' || c == '\r')
33520006a0bStron 			if (ABORT_SIGS())
33620006a0bStron 			{
33720006a0bStron 				null_line();
33820006a0bStron 				return (NULL_POSITION);
33920006a0bStron 			}
34020006a0bStron 		if (c != EOI)
34120006a0bStron 			(void) ch_back_get();
34220006a0bStron 		new_pos = ch_tell();
34320006a0bStron 	}
34420006a0bStron 
34520006a0bStron 	return (new_pos);
34620006a0bStron }
34720006a0bStron 
forw_line(POSITION curr_pos)348*838f5788Ssimonb public POSITION forw_line(POSITION curr_pos)
349*838f5788Ssimonb {
350*838f5788Ssimonb 
351*838f5788Ssimonb 	return forw_line_seg(curr_pos, (chop_line() || hshift > 0), TRUE, FALSE);
352*838f5788Ssimonb }
353*838f5788Ssimonb 
35420006a0bStron /*
35520006a0bStron  * Get the previous line.
35620006a0bStron  * A "current" position is passed and a "new" position is returned.
35720006a0bStron  * The current position is the position of the first character of
35820006a0bStron  * a line.  The new position is the position of the first character
35920006a0bStron  * of the PREVIOUS line.  The line obtained is the one starting at new_pos.
36020006a0bStron  */
back_line(POSITION curr_pos)361*838f5788Ssimonb public POSITION back_line(POSITION curr_pos)
36220006a0bStron {
363*838f5788Ssimonb 	POSITION base_pos;
364*838f5788Ssimonb 	POSITION new_pos;
365*838f5788Ssimonb 	POSITION edisp_pos;
366*838f5788Ssimonb 	POSITION begin_new_pos;
36720006a0bStron 	int c;
36820006a0bStron 	int endline;
369*838f5788Ssimonb 	int chopped;
37020006a0bStron 	int backchars;
371*838f5788Ssimonb 	POSITION wrap_pos;
372*838f5788Ssimonb 	int skipped_leading;
37320006a0bStron 
37420006a0bStron get_back_line:
37520006a0bStron 	if (curr_pos == NULL_POSITION || curr_pos <= ch_zero())
37620006a0bStron 	{
37720006a0bStron 		null_line();
37820006a0bStron 		return (NULL_POSITION);
37920006a0bStron 	}
38020006a0bStron #if HILITE_SEARCH
38120006a0bStron 	if (hilite_search == OPT_ONPLUS || is_filtering() || status_col)
38220006a0bStron 		prep_hilite((curr_pos < 3*size_linebuf) ?
38320006a0bStron 				0 : curr_pos - 3*size_linebuf, curr_pos, -1);
38420006a0bStron #endif
38520006a0bStron 	if (ch_seek(curr_pos-1))
38620006a0bStron 	{
38720006a0bStron 		null_line();
38820006a0bStron 		return (NULL_POSITION);
38920006a0bStron 	}
39020006a0bStron 
39120006a0bStron 	if (squeeze)
39220006a0bStron 	{
39320006a0bStron 		/*
39420006a0bStron 		 * Find out if the "current" line was blank.
39520006a0bStron 		 */
39620006a0bStron 		(void) ch_forw_get();    /* Skip the newline */
39720006a0bStron 		c = ch_forw_get();       /* First char of "current" line */
39820006a0bStron 		(void) ch_back_get();    /* Restore our position */
39920006a0bStron 		(void) ch_back_get();
40020006a0bStron 
40120006a0bStron 		if (c == '\n' || c == '\r')
40220006a0bStron 		{
40320006a0bStron 			/*
40420006a0bStron 			 * The "current" line was blank.
40520006a0bStron 			 * Skip over any preceding blank lines,
40620006a0bStron 			 * since we skipped them in forw_line().
40720006a0bStron 			 */
40820006a0bStron 			while ((c = ch_back_get()) == '\n' || c == '\r')
40920006a0bStron 				if (ABORT_SIGS())
41020006a0bStron 				{
41120006a0bStron 					null_line();
41220006a0bStron 					return (NULL_POSITION);
41320006a0bStron 				}
41420006a0bStron 			if (c == EOI)
41520006a0bStron 			{
41620006a0bStron 				null_line();
41720006a0bStron 				return (NULL_POSITION);
41820006a0bStron 			}
41920006a0bStron 			(void) ch_forw_get();
42020006a0bStron 		}
42120006a0bStron 	}
42220006a0bStron 
42320006a0bStron 	/*
42420006a0bStron 	 * Scan backwards until we hit the beginning of the line.
42520006a0bStron 	 */
42620006a0bStron 	for (;;)
42720006a0bStron 	{
42820006a0bStron 		if (ABORT_SIGS())
42920006a0bStron 		{
43020006a0bStron 			null_line();
43120006a0bStron 			return (NULL_POSITION);
43220006a0bStron 		}
43320006a0bStron 		c = ch_back_get();
43420006a0bStron 		if (c == '\n')
43520006a0bStron 		{
43620006a0bStron 			/*
43720006a0bStron 			 * This is the newline ending the previous line.
43820006a0bStron 			 * We have hit the beginning of the line.
43920006a0bStron 			 */
44020006a0bStron 			base_pos = ch_tell() + 1;
44120006a0bStron 			break;
44220006a0bStron 		}
44320006a0bStron 		if (c == EOI)
44420006a0bStron 		{
44520006a0bStron 			/*
44620006a0bStron 			 * We have hit the beginning of the file.
44720006a0bStron 			 * This must be the first line in the file.
44820006a0bStron 			 * This must, of course, be the beginning of the line.
44920006a0bStron 			 */
45020006a0bStron 			base_pos = ch_tell();
45120006a0bStron 			break;
45220006a0bStron 		}
45320006a0bStron 	}
45420006a0bStron 
45520006a0bStron 	/*
45620006a0bStron 	 * Now scan forwards from the beginning of this line.
45720006a0bStron 	 * We keep discarding "printable lines" (based on screen width)
45820006a0bStron 	 * until we reach the curr_pos.
45920006a0bStron 	 *
46020006a0bStron 	 * {{ This algorithm is pretty inefficient if the lines
46120006a0bStron 	 *    are much longer than the screen width,
46220006a0bStron 	 *    but I don't know of any better way. }}
46320006a0bStron 	 */
46420006a0bStron 	new_pos = base_pos;
46520006a0bStron 	if (ch_seek(new_pos))
46620006a0bStron 	{
46720006a0bStron 		null_line();
46820006a0bStron 		return (NULL_POSITION);
46920006a0bStron 	}
47020006a0bStron 	endline = FALSE;
47120006a0bStron 	prewind();
472*838f5788Ssimonb 	plinestart(new_pos);
47320006a0bStron     loop:
474*838f5788Ssimonb 	wrap_pos = NULL_POSITION;
475*838f5788Ssimonb 	skipped_leading = FALSE;
47620006a0bStron 	begin_new_pos = new_pos;
47720006a0bStron 	(void) ch_seek(new_pos);
478*838f5788Ssimonb 	chopped = FALSE;
47920006a0bStron 
480*838f5788Ssimonb 	for (;;)
48120006a0bStron 	{
48220006a0bStron 		c = ch_forw_get();
48320006a0bStron 		if (c == EOI || ABORT_SIGS())
48420006a0bStron 		{
48520006a0bStron 			null_line();
48620006a0bStron 			return (NULL_POSITION);
48720006a0bStron 		}
48820006a0bStron 		new_pos++;
48920006a0bStron 		if (c == '\n')
49020006a0bStron 		{
49120006a0bStron 			backchars = pflushmbc();
492*838f5788Ssimonb 			if (backchars > 0 && !chop_line() && hshift == 0)
49320006a0bStron 			{
49420006a0bStron 				backchars++;
49520006a0bStron 				goto shift;
49620006a0bStron 			}
49720006a0bStron 			endline = TRUE;
498*838f5788Ssimonb 			edisp_pos = new_pos;
49920006a0bStron 			break;
50020006a0bStron 		}
50120006a0bStron 		backchars = pappend(c, ch_tell()-1);
50220006a0bStron 		if (backchars > 0)
50320006a0bStron 		{
50420006a0bStron 			/*
50520006a0bStron 			 * Got a full printable line, but we haven't
50620006a0bStron 			 * reached our curr_pos yet.  Discard the line
50720006a0bStron 			 * and start a new one.
50820006a0bStron 			 */
509*838f5788Ssimonb 			if (chop_line() || hshift > 0)
51020006a0bStron 			{
51120006a0bStron 				endline = TRUE;
512*838f5788Ssimonb 				chopped = TRUE;
51320006a0bStron 				quit_if_one_screen = FALSE;
514*838f5788Ssimonb 				edisp_pos = new_pos;
51520006a0bStron 				break;
51620006a0bStron 			}
51720006a0bStron 		shift:
518*838f5788Ssimonb 			if (!wordwrap)
51920006a0bStron 			{
520*838f5788Ssimonb 				pshift_all();
521*838f5788Ssimonb 				new_pos -= backchars;
522*838f5788Ssimonb 			} else
523*838f5788Ssimonb 			{
524*838f5788Ssimonb 				if (c == ' ' || c == '\t')
525*838f5788Ssimonb 				{
526*838f5788Ssimonb 					for (;;)
527*838f5788Ssimonb 					{
528*838f5788Ssimonb 						c = ch_forw_get();
529*838f5788Ssimonb 						if (c == ' ' || c == '\t')
530*838f5788Ssimonb 							new_pos++;
531*838f5788Ssimonb 						else
532*838f5788Ssimonb 						{
533*838f5788Ssimonb 							if (c == '\r')
534*838f5788Ssimonb 							{
535*838f5788Ssimonb 								c = ch_forw_get();
536*838f5788Ssimonb 								if (c == '\n')
537*838f5788Ssimonb 									new_pos++;
538*838f5788Ssimonb 							}
539*838f5788Ssimonb 							if (c == '\n')
540*838f5788Ssimonb 								new_pos++;
541*838f5788Ssimonb 							break;
542*838f5788Ssimonb 						}
543*838f5788Ssimonb 					}
544*838f5788Ssimonb 					if (new_pos >= curr_pos)
545*838f5788Ssimonb 						break;
546*838f5788Ssimonb 					pshift_all();
547*838f5788Ssimonb 				} else
548*838f5788Ssimonb 				{
549*838f5788Ssimonb 					pshift_all();
550*838f5788Ssimonb 					if (wrap_pos == NULL_POSITION)
551*838f5788Ssimonb 						new_pos -= backchars;
552*838f5788Ssimonb 					else
553*838f5788Ssimonb 						new_pos = wrap_pos;
554*838f5788Ssimonb 				}
55520006a0bStron 			}
55620006a0bStron 			goto loop;
55720006a0bStron 		}
558*838f5788Ssimonb 		if (wordwrap)
559*838f5788Ssimonb 		{
560*838f5788Ssimonb 			if (c == ' ' || c == '\t')
561*838f5788Ssimonb 			{
562*838f5788Ssimonb 				if (skipped_leading)
563*838f5788Ssimonb 					wrap_pos = new_pos;
564*838f5788Ssimonb 			} else
565*838f5788Ssimonb 				skipped_leading = TRUE;
566*838f5788Ssimonb 		}
567*838f5788Ssimonb 		if (new_pos >= curr_pos)
568*838f5788Ssimonb 		{
569*838f5788Ssimonb 			edisp_pos = new_pos;
570*838f5788Ssimonb 			break;
571*838f5788Ssimonb 		}
572*838f5788Ssimonb 	}
57320006a0bStron 
574*838f5788Ssimonb 	pdone(endline, chopped, 0);
57520006a0bStron 
57620006a0bStron #if HILITE_SEARCH
57720006a0bStron 	if (is_filtered(base_pos))
57820006a0bStron 	{
57920006a0bStron 		/*
58020006a0bStron 		 * We don't want to display this line.
58120006a0bStron 		 * Get the previous line.
58220006a0bStron 		 */
58320006a0bStron 		curr_pos = begin_new_pos;
58420006a0bStron 		goto get_back_line;
58520006a0bStron 	}
586*838f5788Ssimonb 	if (status_col)
587*838f5788Ssimonb 		init_status_col(base_pos, line_position(), edisp_pos, new_pos);
58820006a0bStron #endif
58920006a0bStron 
59020006a0bStron 	return (begin_new_pos);
59120006a0bStron }
59220006a0bStron 
59320006a0bStron /*
59420006a0bStron  * Set attnpos.
59520006a0bStron  */
set_attnpos(POSITION pos)596*838f5788Ssimonb public void set_attnpos(POSITION pos)
59720006a0bStron {
59820006a0bStron 	int c;
59920006a0bStron 
60020006a0bStron 	if (pos != NULL_POSITION)
60120006a0bStron 	{
60220006a0bStron 		if (ch_seek(pos))
60320006a0bStron 			return;
60420006a0bStron 		for (;;)
60520006a0bStron 		{
60620006a0bStron 			c = ch_forw_get();
60720006a0bStron 			if (c == EOI)
60820006a0bStron 				break;
609*838f5788Ssimonb 			if (c == '\n' || c == '\r')
610*838f5788Ssimonb 			{
611*838f5788Ssimonb 				(void) ch_back_get();
612*838f5788Ssimonb 				break;
613*838f5788Ssimonb 			}
61420006a0bStron 			pos++;
61520006a0bStron 		}
616*838f5788Ssimonb 		end_attnpos = pos;
617*838f5788Ssimonb 		for (;;)
618*838f5788Ssimonb 		{
619*838f5788Ssimonb 			c = ch_back_get();
620*838f5788Ssimonb 			if (c == EOI || c == '\n' || c == '\r')
621*838f5788Ssimonb 				break;
622*838f5788Ssimonb 			pos--;
623*838f5788Ssimonb 		}
62420006a0bStron 	}
62520006a0bStron 	start_attnpos = pos;
62620006a0bStron }
627