 84d9c625bf
			
		
	
	
		84d9c625bf
		
	
	
	
	
		
			
			- Fix for possible unset uid/gid in toproto
 - Fix for default mtree style
 - Update libelf
 - Importing libexecinfo
 - Resynchronize GCC, mpc, gmp, mpfr
 - build.sh: Replace params with show-params.
     This has been done as the make target has been renamed in the same
     way, while a new target named params has been added. This new
     target generates a file containing all the parameters, instead of
     printing it on the console.
 - Update test48 with new etc/services (Fix by Ben Gras <ben@minix3.org)
     get getservbyport() out of the inner loop
Change-Id: Ie6ad5226fa2621ff9f0dee8782ea48f9443d2091
		
	
			
		
			
				
	
	
		
			460 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			460 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*	$NetBSD: input.c,v 1.3 2013/09/04 19:44:21 tron Exp $	*/
 | |
| 
 | |
| /*
 | |
|  * Copyright (C) 1984-2012  Mark Nudelman
 | |
|  *
 | |
|  * You may distribute under the terms of either the GNU General Public
 | |
|  * License or the Less License, as specified in the README file.
 | |
|  *
 | |
|  * For more information, see the README file.
 | |
|  */
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * High level routines dealing with getting lines of input 
 | |
|  * from the file being viewed.
 | |
|  *
 | |
|  * When we speak of "lines" here, we mean PRINTABLE lines;
 | |
|  * lines processed with respect to the screen width.
 | |
|  * We use the term "raw line" to refer to lines simply
 | |
|  * delimited by newlines; not processed with respect to screen width.
 | |
|  */
 | |
| 
 | |
| #include "less.h"
 | |
| 
 | |
| extern int squeeze;
 | |
| extern int chopline;
 | |
| extern int hshift;
 | |
| extern int quit_if_one_screen;
 | |
| extern int sigs;
 | |
| extern int ignore_eoi;
 | |
| extern int status_col;
 | |
| extern POSITION start_attnpos;
 | |
| extern POSITION end_attnpos;
 | |
| #if HILITE_SEARCH
 | |
| extern int hilite_search;
 | |
| extern int size_linebuf;
 | |
| #endif
 | |
| 
 | |
| /*
 | |
|  * Get the next line.
 | |
|  * A "current" position is passed and a "new" position is returned.
 | |
|  * The current position is the position of the first character of
 | |
|  * a line.  The new position is the position of the first character
 | |
|  * of the NEXT line.  The line obtained is the line starting at curr_pos.
 | |
|  */
 | |
| 	public POSITION
 | |
| forw_line(curr_pos)
 | |
| 	POSITION curr_pos;
 | |
| {
 | |
| 	POSITION base_pos;
 | |
| 	POSITION new_pos;
 | |
| 	register int c;
 | |
| 	int blankline;
 | |
| 	int endline;
 | |
| 	int backchars;
 | |
| 
 | |
| get_forw_line:
 | |
| 	if (curr_pos == NULL_POSITION)
 | |
| 	{
 | |
| 		null_line();
 | |
| 		return (NULL_POSITION);
 | |
| 	}
 | |
| #if HILITE_SEARCH
 | |
| 	if (hilite_search == OPT_ONPLUS || is_filtering() || status_col)
 | |
| 		/*
 | |
| 		 * If we are ignoring EOI (command F), only prepare
 | |
| 		 * one line ahead, to avoid getting stuck waiting for
 | |
| 		 * slow data without displaying the data we already have.
 | |
| 		 * If we're not ignoring EOI, we *could* do the same, but
 | |
| 		 * for efficiency we prepare several lines ahead at once.
 | |
| 		 */
 | |
| 		prep_hilite(curr_pos, curr_pos + 3*size_linebuf, 
 | |
| 				ignore_eoi ? 1 : -1);
 | |
| #endif
 | |
| 	if (ch_seek(curr_pos))
 | |
| 	{
 | |
| 		null_line();
 | |
| 		return (NULL_POSITION);
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	 * Step back to the beginning of the line.
 | |
| 	 */
 | |
| 	base_pos = curr_pos;
 | |
| 	for (;;)
 | |
| 	{
 | |
| 		if (ABORT_SIGS())
 | |
| 		{
 | |
| 			null_line();
 | |
| 			return (NULL_POSITION);
 | |
| 		}
 | |
| 		c = ch_back_get();
 | |
| 		if (c == EOI)
 | |
| 			break;
 | |
| 		if (c == '\n')
 | |
| 		{
 | |
| 			(void) ch_forw_get();
 | |
| 			break;
 | |
| 		}
 | |
| 		--base_pos;
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	 * Read forward again to the position we should start at.
 | |
| 	 */
 | |
|  	prewind();
 | |
| 	plinenum(base_pos);
 | |
| 	(void) ch_seek(base_pos);
 | |
| 	new_pos = base_pos;
 | |
| 	while (new_pos < curr_pos)
 | |
| 	{
 | |
| 		if (ABORT_SIGS())
 | |
| 		{
 | |
| 			null_line();
 | |
| 			return (NULL_POSITION);
 | |
| 		}
 | |
| 		c = ch_forw_get();
 | |
| 		backchars = pappend(c, new_pos);
 | |
| 		new_pos++;
 | |
| 		if (backchars > 0)
 | |
| 		{
 | |
| 			pshift_all();
 | |
| 			new_pos -= backchars;
 | |
| 			while (--backchars >= 0)
 | |
| 				(void) ch_back_get();
 | |
| 		}
 | |
| 	}
 | |
| 	(void) pflushmbc();
 | |
| 	pshift_all();
 | |
| 
 | |
| 	/*
 | |
| 	 * Read the first character to display.
 | |
| 	 */
 | |
| 	c = ch_forw_get();
 | |
| 	if (c == EOI)
 | |
| 	{
 | |
| 		null_line();
 | |
| 		return (NULL_POSITION);
 | |
| 	}
 | |
| 	blankline = (c == '\n' || c == '\r');
 | |
| 
 | |
| 	/*
 | |
| 	 * Read each character in the line and append to the line buffer.
 | |
| 	 */
 | |
| 	for (;;)
 | |
| 	{
 | |
| 		if (ABORT_SIGS())
 | |
| 		{
 | |
| 			null_line();
 | |
| 			return (NULL_POSITION);
 | |
| 		}
 | |
| 		if (c == '\n' || c == EOI)
 | |
| 		{
 | |
| 			/*
 | |
| 			 * End of the line.
 | |
| 			 */
 | |
| 			backchars = pflushmbc();
 | |
| 			new_pos = ch_tell();
 | |
| 			if (backchars > 0 && !chopline && hshift == 0)
 | |
| 			{
 | |
| 				new_pos -= backchars + 1;
 | |
| 				endline = FALSE;
 | |
| 			} else
 | |
| 				endline = TRUE;
 | |
| 			break;
 | |
| 		}
 | |
| 		if (c != '\r')
 | |
| 			blankline = 0;
 | |
| 
 | |
| 		/*
 | |
| 		 * Append the char to the line and get the next char.
 | |
| 		 */
 | |
| 		backchars = pappend(c, ch_tell()-1);
 | |
| 		if (backchars > 0)
 | |
| 		{
 | |
| 			/*
 | |
| 			 * The char won't fit in the line; the line
 | |
| 			 * is too long to print in the screen width.
 | |
| 			 * End the line here.
 | |
| 			 */
 | |
| 			if (chopline || hshift > 0)
 | |
| 			{
 | |
| 				do
 | |
| 				{
 | |
| 					if (ABORT_SIGS())
 | |
| 					{
 | |
| 						null_line();
 | |
| 						return (NULL_POSITION);
 | |
| 					}
 | |
| 					c = ch_forw_get();
 | |
| 				} while (c != '\n' && c != EOI);
 | |
| 				new_pos = ch_tell();
 | |
| 				endline = TRUE;
 | |
| 				quit_if_one_screen = FALSE;
 | |
| 			} else
 | |
| 			{
 | |
| 				new_pos = ch_tell() - backchars;
 | |
| 				endline = FALSE;
 | |
| 			}
 | |
| 			break;
 | |
| 		}
 | |
| 		c = ch_forw_get();
 | |
| 	}
 | |
| 
 | |
| 	pdone(endline, 1);
 | |
| 
 | |
| #if HILITE_SEARCH
 | |
| 	if (is_filtered(base_pos))
 | |
| 	{
 | |
| 		/*
 | |
| 		 * We don't want to display this line.
 | |
| 		 * Get the next line.
 | |
| 		 */
 | |
| 		curr_pos = new_pos;
 | |
| 		goto get_forw_line;
 | |
| 	}
 | |
| 
 | |
| 	if (status_col && is_hilited(base_pos, ch_tell()-1, 1, NULL))
 | |
| 		set_status_col('*');
 | |
| #endif
 | |
| 
 | |
| 	if (squeeze && blankline)
 | |
| 	{
 | |
| 		/*
 | |
| 		 * This line is blank.
 | |
| 		 * Skip down to the last contiguous blank line
 | |
| 		 * and pretend it is the one which we are returning.
 | |
| 		 */
 | |
| 		while ((c = ch_forw_get()) == '\n' || c == '\r')
 | |
| 			if (ABORT_SIGS())
 | |
| 			{
 | |
| 				null_line();
 | |
| 				return (NULL_POSITION);
 | |
| 			}
 | |
| 		if (c != EOI)
 | |
| 			(void) ch_back_get();
 | |
| 		new_pos = ch_tell();
 | |
| 	}
 | |
| 
 | |
| 	return (new_pos);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Get the previous line.
 | |
|  * A "current" position is passed and a "new" position is returned.
 | |
|  * The current position is the position of the first character of
 | |
|  * a line.  The new position is the position of the first character
 | |
|  * of the PREVIOUS line.  The line obtained is the one starting at new_pos.
 | |
|  */
 | |
| 	public POSITION
 | |
| back_line(curr_pos)
 | |
| 	POSITION curr_pos;
 | |
| {
 | |
| 	POSITION new_pos, begin_new_pos, base_pos;
 | |
| 	int c;
 | |
| 	int endline;
 | |
| 	int backchars;
 | |
| 
 | |
| get_back_line:
 | |
| 	if (curr_pos == NULL_POSITION || curr_pos <= ch_zero())
 | |
| 	{
 | |
| 		null_line();
 | |
| 		return (NULL_POSITION);
 | |
| 	}
 | |
| #if HILITE_SEARCH
 | |
| 	if (hilite_search == OPT_ONPLUS || is_filtering() || status_col)
 | |
| 		prep_hilite((curr_pos < 3*size_linebuf) ? 
 | |
| 				0 : curr_pos - 3*size_linebuf, curr_pos, -1);
 | |
| #endif
 | |
| 	if (ch_seek(curr_pos-1))
 | |
| 	{
 | |
| 		null_line();
 | |
| 		return (NULL_POSITION);
 | |
| 	}
 | |
| 
 | |
| 	if (squeeze)
 | |
| 	{
 | |
| 		/*
 | |
| 		 * Find out if the "current" line was blank.
 | |
| 		 */
 | |
| 		(void) ch_forw_get();    /* Skip the newline */
 | |
| 		c = ch_forw_get();       /* First char of "current" line */
 | |
| 		(void) ch_back_get();    /* Restore our position */
 | |
| 		(void) ch_back_get();
 | |
| 
 | |
| 		if (c == '\n' || c == '\r')
 | |
| 		{
 | |
| 			/*
 | |
| 			 * The "current" line was blank.
 | |
| 			 * Skip over any preceding blank lines,
 | |
| 			 * since we skipped them in forw_line().
 | |
| 			 */
 | |
| 			while ((c = ch_back_get()) == '\n' || c == '\r')
 | |
| 				if (ABORT_SIGS())
 | |
| 				{
 | |
| 					null_line();
 | |
| 					return (NULL_POSITION);
 | |
| 				}
 | |
| 			if (c == EOI)
 | |
| 			{
 | |
| 				null_line();
 | |
| 				return (NULL_POSITION);
 | |
| 			}
 | |
| 			(void) ch_forw_get();
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	 * Scan backwards until we hit the beginning of the line.
 | |
| 	 */
 | |
| 	for (;;)
 | |
| 	{
 | |
| 		if (ABORT_SIGS())
 | |
| 		{
 | |
| 			null_line();
 | |
| 			return (NULL_POSITION);
 | |
| 		}
 | |
| 		c = ch_back_get();
 | |
| 		if (c == '\n')
 | |
| 		{
 | |
| 			/*
 | |
| 			 * This is the newline ending the previous line.
 | |
| 			 * We have hit the beginning of the line.
 | |
| 			 */
 | |
| 			base_pos = ch_tell() + 1;
 | |
| 			break;
 | |
| 		}
 | |
| 		if (c == EOI)
 | |
| 		{
 | |
| 			/*
 | |
| 			 * We have hit the beginning of the file.
 | |
| 			 * This must be the first line in the file.
 | |
| 			 * This must, of course, be the beginning of the line.
 | |
| 			 */
 | |
| 			base_pos = ch_tell();
 | |
| 			break;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	 * Now scan forwards from the beginning of this line.
 | |
| 	 * We keep discarding "printable lines" (based on screen width)
 | |
| 	 * until we reach the curr_pos.
 | |
| 	 *
 | |
| 	 * {{ This algorithm is pretty inefficient if the lines
 | |
| 	 *    are much longer than the screen width, 
 | |
| 	 *    but I don't know of any better way. }}
 | |
| 	 */
 | |
| 	new_pos = base_pos;
 | |
| 	if (ch_seek(new_pos))
 | |
| 	{
 | |
| 		null_line();
 | |
| 		return (NULL_POSITION);
 | |
| 	}
 | |
| 	endline = FALSE;
 | |
| 	prewind();
 | |
| 	plinenum(new_pos);
 | |
|     loop:
 | |
| 	begin_new_pos = new_pos;
 | |
| 	(void) ch_seek(new_pos);
 | |
| 
 | |
| 	do
 | |
| 	{
 | |
| 		c = ch_forw_get();
 | |
| 		if (c == EOI || ABORT_SIGS())
 | |
| 		{
 | |
| 			null_line();
 | |
| 			return (NULL_POSITION);
 | |
| 		}
 | |
| 		new_pos++;
 | |
| 		if (c == '\n')
 | |
| 		{
 | |
| 			backchars = pflushmbc();
 | |
| 			if (backchars > 0 && !chopline && hshift == 0)
 | |
| 			{
 | |
| 				backchars++;
 | |
| 				goto shift;
 | |
| 			}
 | |
| 			endline = TRUE;
 | |
| 			break;
 | |
| 		}
 | |
| 		backchars = pappend(c, ch_tell()-1);
 | |
| 		if (backchars > 0)
 | |
| 		{
 | |
| 			/*
 | |
| 			 * Got a full printable line, but we haven't
 | |
| 			 * reached our curr_pos yet.  Discard the line
 | |
| 			 * and start a new one.
 | |
| 			 */
 | |
| 			if (chopline || hshift > 0)
 | |
| 			{
 | |
| 				endline = TRUE;
 | |
| 				quit_if_one_screen = FALSE;
 | |
| 				break;
 | |
| 			}
 | |
| 		shift:
 | |
| 			pshift_all();
 | |
| 			while (backchars-- > 0)
 | |
| 			{
 | |
| 				(void) ch_back_get();
 | |
| 				new_pos--;
 | |
| 			}
 | |
| 			goto loop;
 | |
| 		}
 | |
| 	} while (new_pos < curr_pos);
 | |
| 
 | |
| 	pdone(endline, 0);
 | |
| 
 | |
| #if HILITE_SEARCH
 | |
| 	if (is_filtered(base_pos))
 | |
| 	{
 | |
| 		/*
 | |
| 		 * We don't want to display this line.
 | |
| 		 * Get the previous line.
 | |
| 		 */
 | |
| 		curr_pos = begin_new_pos;
 | |
| 		goto get_back_line;
 | |
| 	}
 | |
| 
 | |
| 	if (status_col && curr_pos > 0 && is_hilited(base_pos, curr_pos-1, 1, NULL))
 | |
| 		set_status_col('*');
 | |
| #endif
 | |
| 
 | |
| 	return (begin_new_pos);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Set attnpos.
 | |
|  */
 | |
| 	public void
 | |
| set_attnpos(pos)
 | |
| 	POSITION pos;
 | |
| {
 | |
| 	int c;
 | |
| 
 | |
| 	if (pos != NULL_POSITION)
 | |
| 	{
 | |
| 		if (ch_seek(pos))
 | |
| 			return;
 | |
| 		for (;;)
 | |
| 		{
 | |
| 			c = ch_forw_get();
 | |
| 			if (c == EOI)
 | |
| 				return;
 | |
| 			if (c != '\n' && c != '\r')
 | |
| 				break;
 | |
| 			pos++;
 | |
| 		}
 | |
| 	}
 | |
| 	start_attnpos = pos;
 | |
| 	for (;;)
 | |
| 	{
 | |
| 		c = ch_forw_get();
 | |
| 		pos++;
 | |
| 		if (c == EOI || c == '\n' || c == '\r')
 | |
| 			break;
 | |
| 	}
 | |
| 	end_attnpos = pos;
 | |
| }
 |