Home | History | Annotate | Line # | Download | only in dist
      1  1.4  simonb /*	$NetBSD: input.c,v 1.4 2023/10/06 05:49:49 simonb Exp $	*/
      2  1.1    tron 
      3  1.1    tron /*
      4  1.4  simonb  * Copyright (C) 1984-2023  Mark Nudelman
      5  1.1    tron  *
      6  1.1    tron  * You may distribute under the terms of either the GNU General Public
      7  1.1    tron  * License or the Less License, as specified in the README file.
      8  1.1    tron  *
      9  1.3    tron  * For more information, see the README file.
     10  1.1    tron  */
     11  1.1    tron 
     12  1.1    tron /*
     13  1.1    tron  * High level routines dealing with getting lines of input
     14  1.1    tron  * from the file being viewed.
     15  1.1    tron  *
     16  1.1    tron  * When we speak of "lines" here, we mean PRINTABLE lines;
     17  1.1    tron  * lines processed with respect to the screen width.
     18  1.1    tron  * We use the term "raw line" to refer to lines simply
     19  1.1    tron  * delimited by newlines; not processed with respect to screen width.
     20  1.1    tron  */
     21  1.1    tron 
     22  1.1    tron #include "less.h"
     23  1.1    tron 
     24  1.1    tron extern int squeeze;
     25  1.1    tron extern int hshift;
     26  1.1    tron extern int quit_if_one_screen;
     27  1.1    tron extern int sigs;
     28  1.1    tron extern int ignore_eoi;
     29  1.1    tron extern int status_col;
     30  1.4  simonb extern int wordwrap;
     31  1.1    tron extern POSITION start_attnpos;
     32  1.1    tron extern POSITION end_attnpos;
     33  1.1    tron #if HILITE_SEARCH
     34  1.1    tron extern int hilite_search;
     35  1.1    tron extern int size_linebuf;
     36  1.4  simonb extern int show_attn;
     37  1.1    tron #endif
     38  1.1    tron 
     39  1.1    tron /*
     40  1.4  simonb  * Set the status column.
     41  1.4  simonb  *  base  Position of first char in line.
     42  1.4  simonb  *  disp  First visible char.
     43  1.4  simonb  *        Different than base_pos if line is shifted.
     44  1.4  simonb  *  edisp Last visible char.
     45  1.4  simonb  *  eol   End of line. Normally the newline.
     46  1.4  simonb  *        Different than edisp if line is chopped.
     47  1.4  simonb  */
     48  1.4  simonb static void init_status_col(POSITION base_pos, POSITION disp_pos, POSITION edisp_pos, POSITION eol_pos)
     49  1.4  simonb {
     50  1.4  simonb 	int hl_before = (chop_line() && disp_pos != NULL_POSITION) ?
     51  1.4  simonb 	    is_hilited_attr(base_pos, disp_pos, TRUE, NULL) : 0;
     52  1.4  simonb 	int hl_after = (chop_line()) ?
     53  1.4  simonb 	    is_hilited_attr(edisp_pos, eol_pos, TRUE, NULL) : 0;
     54  1.4  simonb 	int attr;
     55  1.4  simonb 	char ch;
     56  1.4  simonb 
     57  1.4  simonb 	if (hl_before && hl_after)
     58  1.4  simonb 	{
     59  1.4  simonb 		attr = hl_after;
     60  1.4  simonb 		ch = '=';
     61  1.4  simonb 	} else if (hl_before)
     62  1.4  simonb 	{
     63  1.4  simonb 		attr = hl_before;
     64  1.4  simonb 		ch = '<';
     65  1.4  simonb 	} else if (hl_after)
     66  1.4  simonb 	{
     67  1.4  simonb 		attr = hl_after;
     68  1.4  simonb 		ch = '>';
     69  1.4  simonb 	} else
     70  1.4  simonb 	{
     71  1.4  simonb 		attr = is_hilited_attr(base_pos, eol_pos, TRUE, NULL);
     72  1.4  simonb 		ch = '*';
     73  1.4  simonb 	}
     74  1.4  simonb 	if (attr)
     75  1.4  simonb 		set_status_col(ch, attr);
     76  1.4  simonb }
     77  1.4  simonb 
     78  1.4  simonb /*
     79  1.1    tron  * Get the next line.
     80  1.1    tron  * A "current" position is passed and a "new" position is returned.
     81  1.1    tron  * The current position is the position of the first character of
     82  1.1    tron  * a line.  The new position is the position of the first character
     83  1.1    tron  * of the NEXT line.  The line obtained is the line starting at curr_pos.
     84  1.1    tron  */
     85  1.4  simonb public POSITION forw_line_seg(POSITION curr_pos, int skipeol, int rscroll, int nochop)
     86  1.1    tron {
     87  1.1    tron 	POSITION base_pos;
     88  1.1    tron 	POSITION new_pos;
     89  1.4  simonb 	POSITION edisp_pos;
     90  1.4  simonb 	int c;
     91  1.1    tron 	int blankline;
     92  1.1    tron 	int endline;
     93  1.4  simonb 	int chopped;
     94  1.1    tron 	int backchars;
     95  1.4  simonb 	POSITION wrap_pos;
     96  1.4  simonb 	int skipped_leading;
     97  1.1    tron 
     98  1.1    tron get_forw_line:
     99  1.1    tron 	if (curr_pos == NULL_POSITION)
    100  1.1    tron 	{
    101  1.1    tron 		null_line();
    102  1.1    tron 		return (NULL_POSITION);
    103  1.1    tron 	}
    104  1.1    tron #if HILITE_SEARCH
    105  1.1    tron 	if (hilite_search == OPT_ONPLUS || is_filtering() || status_col)
    106  1.4  simonb 	{
    107  1.1    tron 		/*
    108  1.1    tron 		 * If we are ignoring EOI (command F), only prepare
    109  1.1    tron 		 * one line ahead, to avoid getting stuck waiting for
    110  1.1    tron 		 * slow data without displaying the data we already have.
    111  1.1    tron 		 * If we're not ignoring EOI, we *could* do the same, but
    112  1.1    tron 		 * for efficiency we prepare several lines ahead at once.
    113  1.1    tron 		 */
    114  1.1    tron 		prep_hilite(curr_pos, curr_pos + 3*size_linebuf,
    115  1.1    tron 				ignore_eoi ? 1 : -1);
    116  1.4  simonb 		curr_pos = next_unfiltered(curr_pos);
    117  1.4  simonb 	}
    118  1.1    tron #endif
    119  1.1    tron 	if (ch_seek(curr_pos))
    120  1.1    tron 	{
    121  1.1    tron 		null_line();
    122  1.1    tron 		return (NULL_POSITION);
    123  1.1    tron 	}
    124  1.1    tron 
    125  1.1    tron 	/*
    126  1.1    tron 	 * Step back to the beginning of the line.
    127  1.1    tron 	 */
    128  1.1    tron 	base_pos = curr_pos;
    129  1.1    tron 	for (;;)
    130  1.1    tron 	{
    131  1.1    tron 		if (ABORT_SIGS())
    132  1.1    tron 		{
    133  1.1    tron 			null_line();
    134  1.1    tron 			return (NULL_POSITION);
    135  1.1    tron 		}
    136  1.1    tron 		c = ch_back_get();
    137  1.1    tron 		if (c == EOI)
    138  1.1    tron 			break;
    139  1.1    tron 		if (c == '\n')
    140  1.1    tron 		{
    141  1.1    tron 			(void) ch_forw_get();
    142  1.1    tron 			break;
    143  1.1    tron 		}
    144  1.1    tron 		--base_pos;
    145  1.1    tron 	}
    146  1.1    tron 
    147  1.1    tron 	/*
    148  1.1    tron 	 * Read forward again to the position we should start at.
    149  1.1    tron 	 */
    150  1.4  simonb 	prewind();
    151  1.4  simonb 	plinestart(base_pos);
    152  1.1    tron 	(void) ch_seek(base_pos);
    153  1.1    tron 	new_pos = base_pos;
    154  1.1    tron 	while (new_pos < curr_pos)
    155  1.1    tron 	{
    156  1.1    tron 		if (ABORT_SIGS())
    157  1.1    tron 		{
    158  1.1    tron 			null_line();
    159  1.1    tron 			return (NULL_POSITION);
    160  1.1    tron 		}
    161  1.1    tron 		c = ch_forw_get();
    162  1.1    tron 		backchars = pappend(c, new_pos);
    163  1.1    tron 		new_pos++;
    164  1.1    tron 		if (backchars > 0)
    165  1.1    tron 		{
    166  1.1    tron 			pshift_all();
    167  1.4  simonb 			if (wordwrap && (c == ' ' || c == '\t'))
    168  1.4  simonb 			{
    169  1.4  simonb 				do
    170  1.4  simonb 				{
    171  1.4  simonb 					new_pos++;
    172  1.4  simonb 					c = ch_forw_get();
    173  1.4  simonb 				} while (c == ' ' || c == '\t');
    174  1.4  simonb 				backchars = 1;
    175  1.4  simonb 			}
    176  1.1    tron 			new_pos -= backchars;
    177  1.1    tron 			while (--backchars >= 0)
    178  1.1    tron 				(void) ch_back_get();
    179  1.1    tron 		}
    180  1.1    tron 	}
    181  1.1    tron 	(void) pflushmbc();
    182  1.1    tron 	pshift_all();
    183  1.1    tron 
    184  1.1    tron 	/*
    185  1.1    tron 	 * Read the first character to display.
    186  1.1    tron 	 */
    187  1.1    tron 	c = ch_forw_get();
    188  1.1    tron 	if (c == EOI)
    189  1.1    tron 	{
    190  1.1    tron 		null_line();
    191  1.1    tron 		return (NULL_POSITION);
    192  1.1    tron 	}
    193  1.1    tron 	blankline = (c == '\n' || c == '\r');
    194  1.4  simonb 	wrap_pos = NULL_POSITION;
    195  1.4  simonb 	skipped_leading = FALSE;
    196  1.1    tron 
    197  1.1    tron 	/*
    198  1.1    tron 	 * Read each character in the line and append to the line buffer.
    199  1.1    tron 	 */
    200  1.4  simonb 	chopped = FALSE;
    201  1.1    tron 	for (;;)
    202  1.1    tron 	{
    203  1.1    tron 		if (ABORT_SIGS())
    204  1.1    tron 		{
    205  1.1    tron 			null_line();
    206  1.1    tron 			return (NULL_POSITION);
    207  1.1    tron 		}
    208  1.1    tron 		if (c == '\n' || c == EOI)
    209  1.1    tron 		{
    210  1.1    tron 			/*
    211  1.1    tron 			 * End of the line.
    212  1.1    tron 			 */
    213  1.1    tron 			backchars = pflushmbc();
    214  1.1    tron 			new_pos = ch_tell();
    215  1.4  simonb 			if (backchars > 0 && (nochop || !chop_line()) && hshift == 0)
    216  1.1    tron 			{
    217  1.1    tron 				new_pos -= backchars + 1;
    218  1.1    tron 				endline = FALSE;
    219  1.1    tron 			} else
    220  1.1    tron 				endline = TRUE;
    221  1.4  simonb 			edisp_pos = new_pos;
    222  1.1    tron 			break;
    223  1.1    tron 		}
    224  1.1    tron 		if (c != '\r')
    225  1.1    tron 			blankline = 0;
    226  1.1    tron 
    227  1.1    tron 		/*
    228  1.1    tron 		 * Append the char to the line and get the next char.
    229  1.1    tron 		 */
    230  1.1    tron 		backchars = pappend(c, ch_tell()-1);
    231  1.1    tron 		if (backchars > 0)
    232  1.1    tron 		{
    233  1.1    tron 			/*
    234  1.1    tron 			 * The char won't fit in the line; the line
    235  1.1    tron 			 * is too long to print in the screen width.
    236  1.1    tron 			 * End the line here.
    237  1.1    tron 			 */
    238  1.4  simonb 			if (skipeol)
    239  1.1    tron 			{
    240  1.4  simonb 				/* Read to end of line. */
    241  1.4  simonb 				edisp_pos = ch_tell();
    242  1.1    tron 				do
    243  1.1    tron 				{
    244  1.1    tron 					if (ABORT_SIGS())
    245  1.1    tron 					{
    246  1.1    tron 						null_line();
    247  1.1    tron 						return (NULL_POSITION);
    248  1.1    tron 					}
    249  1.1    tron 					c = ch_forw_get();
    250  1.1    tron 				} while (c != '\n' && c != EOI);
    251  1.1    tron 				new_pos = ch_tell();
    252  1.1    tron 				endline = TRUE;
    253  1.1    tron 				quit_if_one_screen = FALSE;
    254  1.4  simonb 				chopped = TRUE;
    255  1.1    tron 			} else
    256  1.1    tron 			{
    257  1.4  simonb 				if (!wordwrap)
    258  1.4  simonb 					new_pos = ch_tell() - backchars;
    259  1.4  simonb 				else
    260  1.4  simonb 				{
    261  1.4  simonb 					/*
    262  1.4  simonb 					 * We're word-wrapping, so go back to the last space.
    263  1.4  simonb 					 * However, if it's the space itself that couldn't fit,
    264  1.4  simonb 					 * simply ignore it and any subsequent spaces.
    265  1.4  simonb 					 */
    266  1.4  simonb 					if (c == ' ' || c == '\t')
    267  1.4  simonb 					{
    268  1.4  simonb 						do
    269  1.4  simonb 						{
    270  1.4  simonb 							new_pos = ch_tell();
    271  1.4  simonb 							c = ch_forw_get();
    272  1.4  simonb 						} while (c == ' ' || c == '\t');
    273  1.4  simonb 						if (c == '\r')
    274  1.4  simonb 							c = ch_forw_get();
    275  1.4  simonb 						if (c == '\n')
    276  1.4  simonb 							new_pos = ch_tell();
    277  1.4  simonb 					} else if (wrap_pos == NULL_POSITION)
    278  1.4  simonb 						new_pos = ch_tell() - backchars;
    279  1.4  simonb 					else
    280  1.4  simonb 					{
    281  1.4  simonb 						new_pos = wrap_pos;
    282  1.4  simonb 						loadc();
    283  1.4  simonb 					}
    284  1.4  simonb 				}
    285  1.1    tron 				endline = FALSE;
    286  1.1    tron 			}
    287  1.1    tron 			break;
    288  1.1    tron 		}
    289  1.4  simonb 		if (wordwrap)
    290  1.4  simonb 		{
    291  1.4  simonb 			if (c == ' ' || c == '\t')
    292  1.4  simonb 			{
    293  1.4  simonb 				if (skipped_leading)
    294  1.4  simonb 				{
    295  1.4  simonb 					wrap_pos = ch_tell();
    296  1.4  simonb 					savec();
    297  1.4  simonb 				}
    298  1.4  simonb 			} else
    299  1.4  simonb 				skipped_leading = TRUE;
    300  1.4  simonb 		}
    301  1.1    tron 		c = ch_forw_get();
    302  1.1    tron 	}
    303  1.1    tron 
    304  1.4  simonb #if HILITE_SEARCH
    305  1.4  simonb 	if (blankline && show_attn)
    306  1.4  simonb 	{
    307  1.4  simonb 		/* Add spurious space to carry possible attn hilite. */
    308  1.4  simonb 		pappend(' ', ch_tell()-1);
    309  1.4  simonb 	}
    310  1.4  simonb #endif
    311  1.4  simonb 	pdone(endline, rscroll && chopped, 1);
    312  1.1    tron 
    313  1.1    tron #if HILITE_SEARCH
    314  1.1    tron 	if (is_filtered(base_pos))
    315  1.1    tron 	{
    316  1.1    tron 		/*
    317  1.1    tron 		 * We don't want to display this line.
    318  1.1    tron 		 * Get the next line.
    319  1.1    tron 		 */
    320  1.1    tron 		curr_pos = new_pos;
    321  1.1    tron 		goto get_forw_line;
    322  1.1    tron 	}
    323  1.4  simonb 	if (status_col)
    324  1.4  simonb 		init_status_col(base_pos, line_position(), edisp_pos, new_pos);
    325  1.1    tron #endif
    326  1.1    tron 
    327  1.1    tron 	if (squeeze && blankline)
    328  1.1    tron 	{
    329  1.1    tron 		/*
    330  1.1    tron 		 * This line is blank.
    331  1.1    tron 		 * Skip down to the last contiguous blank line
    332  1.1    tron 		 * and pretend it is the one which we are returning.
    333  1.1    tron 		 */
    334  1.1    tron 		while ((c = ch_forw_get()) == '\n' || c == '\r')
    335  1.1    tron 			if (ABORT_SIGS())
    336  1.1    tron 			{
    337  1.1    tron 				null_line();
    338  1.1    tron 				return (NULL_POSITION);
    339  1.1    tron 			}
    340  1.1    tron 		if (c != EOI)
    341  1.1    tron 			(void) ch_back_get();
    342  1.1    tron 		new_pos = ch_tell();
    343  1.1    tron 	}
    344  1.1    tron 
    345  1.1    tron 	return (new_pos);
    346  1.1    tron }
    347  1.1    tron 
    348  1.4  simonb public POSITION forw_line(POSITION curr_pos)
    349  1.4  simonb {
    350  1.4  simonb 
    351  1.4  simonb 	return forw_line_seg(curr_pos, (chop_line() || hshift > 0), TRUE, FALSE);
    352  1.4  simonb }
    353  1.4  simonb 
    354  1.1    tron /*
    355  1.1    tron  * Get the previous line.
    356  1.1    tron  * A "current" position is passed and a "new" position is returned.
    357  1.1    tron  * The current position is the position of the first character of
    358  1.1    tron  * a line.  The new position is the position of the first character
    359  1.1    tron  * of the PREVIOUS line.  The line obtained is the one starting at new_pos.
    360  1.1    tron  */
    361  1.4  simonb public POSITION back_line(POSITION curr_pos)
    362  1.1    tron {
    363  1.4  simonb 	POSITION base_pos;
    364  1.4  simonb 	POSITION new_pos;
    365  1.4  simonb 	POSITION edisp_pos;
    366  1.4  simonb 	POSITION begin_new_pos;
    367  1.1    tron 	int c;
    368  1.1    tron 	int endline;
    369  1.4  simonb 	int chopped;
    370  1.1    tron 	int backchars;
    371  1.4  simonb 	POSITION wrap_pos;
    372  1.4  simonb 	int skipped_leading;
    373  1.1    tron 
    374  1.1    tron get_back_line:
    375  1.1    tron 	if (curr_pos == NULL_POSITION || curr_pos <= ch_zero())
    376  1.1    tron 	{
    377  1.1    tron 		null_line();
    378  1.1    tron 		return (NULL_POSITION);
    379  1.1    tron 	}
    380  1.1    tron #if HILITE_SEARCH
    381  1.1    tron 	if (hilite_search == OPT_ONPLUS || is_filtering() || status_col)
    382  1.1    tron 		prep_hilite((curr_pos < 3*size_linebuf) ?
    383  1.1    tron 				0 : curr_pos - 3*size_linebuf, curr_pos, -1);
    384  1.1    tron #endif
    385  1.1    tron 	if (ch_seek(curr_pos-1))
    386  1.1    tron 	{
    387  1.1    tron 		null_line();
    388  1.1    tron 		return (NULL_POSITION);
    389  1.1    tron 	}
    390  1.1    tron 
    391  1.1    tron 	if (squeeze)
    392  1.1    tron 	{
    393  1.1    tron 		/*
    394  1.1    tron 		 * Find out if the "current" line was blank.
    395  1.1    tron 		 */
    396  1.1    tron 		(void) ch_forw_get();    /* Skip the newline */
    397  1.1    tron 		c = ch_forw_get();       /* First char of "current" line */
    398  1.1    tron 		(void) ch_back_get();    /* Restore our position */
    399  1.1    tron 		(void) ch_back_get();
    400  1.1    tron 
    401  1.1    tron 		if (c == '\n' || c == '\r')
    402  1.1    tron 		{
    403  1.1    tron 			/*
    404  1.1    tron 			 * The "current" line was blank.
    405  1.1    tron 			 * Skip over any preceding blank lines,
    406  1.1    tron 			 * since we skipped them in forw_line().
    407  1.1    tron 			 */
    408  1.1    tron 			while ((c = ch_back_get()) == '\n' || c == '\r')
    409  1.1    tron 				if (ABORT_SIGS())
    410  1.1    tron 				{
    411  1.1    tron 					null_line();
    412  1.1    tron 					return (NULL_POSITION);
    413  1.1    tron 				}
    414  1.1    tron 			if (c == EOI)
    415  1.1    tron 			{
    416  1.1    tron 				null_line();
    417  1.1    tron 				return (NULL_POSITION);
    418  1.1    tron 			}
    419  1.1    tron 			(void) ch_forw_get();
    420  1.1    tron 		}
    421  1.1    tron 	}
    422  1.1    tron 
    423  1.1    tron 	/*
    424  1.1    tron 	 * Scan backwards until we hit the beginning of the line.
    425  1.1    tron 	 */
    426  1.1    tron 	for (;;)
    427  1.1    tron 	{
    428  1.1    tron 		if (ABORT_SIGS())
    429  1.1    tron 		{
    430  1.1    tron 			null_line();
    431  1.1    tron 			return (NULL_POSITION);
    432  1.1    tron 		}
    433  1.1    tron 		c = ch_back_get();
    434  1.1    tron 		if (c == '\n')
    435  1.1    tron 		{
    436  1.1    tron 			/*
    437  1.1    tron 			 * This is the newline ending the previous line.
    438  1.1    tron 			 * We have hit the beginning of the line.
    439  1.1    tron 			 */
    440  1.1    tron 			base_pos = ch_tell() + 1;
    441  1.1    tron 			break;
    442  1.1    tron 		}
    443  1.1    tron 		if (c == EOI)
    444  1.1    tron 		{
    445  1.1    tron 			/*
    446  1.1    tron 			 * We have hit the beginning of the file.
    447  1.1    tron 			 * This must be the first line in the file.
    448  1.1    tron 			 * This must, of course, be the beginning of the line.
    449  1.1    tron 			 */
    450  1.1    tron 			base_pos = ch_tell();
    451  1.1    tron 			break;
    452  1.1    tron 		}
    453  1.1    tron 	}
    454  1.1    tron 
    455  1.1    tron 	/*
    456  1.1    tron 	 * Now scan forwards from the beginning of this line.
    457  1.1    tron 	 * We keep discarding "printable lines" (based on screen width)
    458  1.1    tron 	 * until we reach the curr_pos.
    459  1.1    tron 	 *
    460  1.1    tron 	 * {{ This algorithm is pretty inefficient if the lines
    461  1.1    tron 	 *    are much longer than the screen width,
    462  1.1    tron 	 *    but I don't know of any better way. }}
    463  1.1    tron 	 */
    464  1.1    tron 	new_pos = base_pos;
    465  1.1    tron 	if (ch_seek(new_pos))
    466  1.1    tron 	{
    467  1.1    tron 		null_line();
    468  1.1    tron 		return (NULL_POSITION);
    469  1.1    tron 	}
    470  1.1    tron 	endline = FALSE;
    471  1.1    tron 	prewind();
    472  1.4  simonb 	plinestart(new_pos);
    473  1.1    tron     loop:
    474  1.4  simonb 	wrap_pos = NULL_POSITION;
    475  1.4  simonb 	skipped_leading = FALSE;
    476  1.1    tron 	begin_new_pos = new_pos;
    477  1.1    tron 	(void) ch_seek(new_pos);
    478  1.4  simonb 	chopped = FALSE;
    479  1.1    tron 
    480  1.4  simonb 	for (;;)
    481  1.1    tron 	{
    482  1.1    tron 		c = ch_forw_get();
    483  1.1    tron 		if (c == EOI || ABORT_SIGS())
    484  1.1    tron 		{
    485  1.1    tron 			null_line();
    486  1.1    tron 			return (NULL_POSITION);
    487  1.1    tron 		}
    488  1.1    tron 		new_pos++;
    489  1.1    tron 		if (c == '\n')
    490  1.1    tron 		{
    491  1.1    tron 			backchars = pflushmbc();
    492  1.4  simonb 			if (backchars > 0 && !chop_line() && hshift == 0)
    493  1.1    tron 			{
    494  1.1    tron 				backchars++;
    495  1.1    tron 				goto shift;
    496  1.1    tron 			}
    497  1.1    tron 			endline = TRUE;
    498  1.4  simonb 			edisp_pos = new_pos;
    499  1.1    tron 			break;
    500  1.1    tron 		}
    501  1.1    tron 		backchars = pappend(c, ch_tell()-1);
    502  1.1    tron 		if (backchars > 0)
    503  1.1    tron 		{
    504  1.1    tron 			/*
    505  1.1    tron 			 * Got a full printable line, but we haven't
    506  1.1    tron 			 * reached our curr_pos yet.  Discard the line
    507  1.1    tron 			 * and start a new one.
    508  1.1    tron 			 */
    509  1.4  simonb 			if (chop_line() || hshift > 0)
    510  1.1    tron 			{
    511  1.1    tron 				endline = TRUE;
    512  1.4  simonb 				chopped = TRUE;
    513  1.1    tron 				quit_if_one_screen = FALSE;
    514  1.4  simonb 				edisp_pos = new_pos;
    515  1.1    tron 				break;
    516  1.1    tron 			}
    517  1.1    tron 		shift:
    518  1.4  simonb 			if (!wordwrap)
    519  1.4  simonb 			{
    520  1.4  simonb 				pshift_all();
    521  1.4  simonb 				new_pos -= backchars;
    522  1.4  simonb 			} else
    523  1.1    tron 			{
    524  1.4  simonb 				if (c == ' ' || c == '\t')
    525  1.4  simonb 				{
    526  1.4  simonb 					for (;;)
    527  1.4  simonb 					{
    528  1.4  simonb 						c = ch_forw_get();
    529  1.4  simonb 						if (c == ' ' || c == '\t')
    530  1.4  simonb 							new_pos++;
    531  1.4  simonb 						else
    532  1.4  simonb 						{
    533  1.4  simonb 							if (c == '\r')
    534  1.4  simonb 							{
    535  1.4  simonb 								c = ch_forw_get();
    536  1.4  simonb 								if (c == '\n')
    537  1.4  simonb 									new_pos++;
    538  1.4  simonb 							}
    539  1.4  simonb 							if (c == '\n')
    540  1.4  simonb 								new_pos++;
    541  1.4  simonb 							break;
    542  1.4  simonb 						}
    543  1.4  simonb 					}
    544  1.4  simonb 					if (new_pos >= curr_pos)
    545  1.4  simonb 						break;
    546  1.4  simonb 					pshift_all();
    547  1.4  simonb 				} else
    548  1.4  simonb 				{
    549  1.4  simonb 					pshift_all();
    550  1.4  simonb 					if (wrap_pos == NULL_POSITION)
    551  1.4  simonb 						new_pos -= backchars;
    552  1.4  simonb 					else
    553  1.4  simonb 						new_pos = wrap_pos;
    554  1.4  simonb 				}
    555  1.1    tron 			}
    556  1.1    tron 			goto loop;
    557  1.1    tron 		}
    558  1.4  simonb 		if (wordwrap)
    559  1.4  simonb 		{
    560  1.4  simonb 			if (c == ' ' || c == '\t')
    561  1.4  simonb 			{
    562  1.4  simonb 				if (skipped_leading)
    563  1.4  simonb 					wrap_pos = new_pos;
    564  1.4  simonb 			} else
    565  1.4  simonb 				skipped_leading = TRUE;
    566  1.4  simonb 		}
    567  1.4  simonb 		if (new_pos >= curr_pos)
    568  1.4  simonb 		{
    569  1.4  simonb 			edisp_pos = new_pos;
    570  1.4  simonb 			break;
    571  1.4  simonb 		}
    572  1.4  simonb 	}
    573  1.1    tron 
    574  1.4  simonb 	pdone(endline, chopped, 0);
    575  1.1    tron 
    576  1.1    tron #if HILITE_SEARCH
    577  1.1    tron 	if (is_filtered(base_pos))
    578  1.1    tron 	{
    579  1.1    tron 		/*
    580  1.1    tron 		 * We don't want to display this line.
    581  1.1    tron 		 * Get the previous line.
    582  1.1    tron 		 */
    583  1.1    tron 		curr_pos = begin_new_pos;
    584  1.1    tron 		goto get_back_line;
    585  1.1    tron 	}
    586  1.4  simonb 	if (status_col)
    587  1.4  simonb 		init_status_col(base_pos, line_position(), edisp_pos, new_pos);
    588  1.1    tron #endif
    589  1.1    tron 
    590  1.1    tron 	return (begin_new_pos);
    591  1.1    tron }
    592  1.1    tron 
    593  1.1    tron /*
    594  1.1    tron  * Set attnpos.
    595  1.1    tron  */
    596  1.4  simonb public void set_attnpos(POSITION pos)
    597  1.1    tron {
    598  1.1    tron 	int c;
    599  1.1    tron 
    600  1.1    tron 	if (pos != NULL_POSITION)
    601  1.1    tron 	{
    602  1.1    tron 		if (ch_seek(pos))
    603  1.1    tron 			return;
    604  1.1    tron 		for (;;)
    605  1.1    tron 		{
    606  1.1    tron 			c = ch_forw_get();
    607  1.1    tron 			if (c == EOI)
    608  1.1    tron 				break;
    609  1.4  simonb 			if (c == '\n' || c == '\r')
    610  1.4  simonb 			{
    611  1.4  simonb 				(void) ch_back_get();
    612  1.4  simonb 				break;
    613  1.4  simonb 			}
    614  1.1    tron 			pos++;
    615  1.1    tron 		}
    616  1.4  simonb 		end_attnpos = pos;
    617  1.4  simonb 		for (;;)
    618  1.4  simonb 		{
    619  1.4  simonb 			c = ch_back_get();
    620  1.4  simonb 			if (c == EOI || c == '\n' || c == '\r')
    621  1.4  simonb 				break;
    622  1.4  simonb 			pos--;
    623  1.4  simonb 		}
    624  1.1    tron 	}
    625  1.1    tron 	start_attnpos = pos;
    626  1.1    tron }
    627