"SfR Fresh" - the SfR Freeware/Shareware Archive

Member "less-424/forwback.c" of archive less-424.tar.gz:


As a special service "SfR Fresh" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
    1 /*
    2  * Copyright (C) 1984-2008  Mark Nudelman
    3  *
    4  * You may distribute under the terms of either the GNU General Public
    5  * License or the Less License, as specified in the README file.
    6  *
    7  * For more information about less, or for information on how to
    8  * contact the author, see the README file.
    9  */
   10 
   11 
   12 /*
   13  * Primitives for displaying the file on the screen,
   14  * scrolling either forward or backward.
   15  */
   16 
   17 #include "less.h"
   18 #include "position.h"
   19 
   20 public int screen_trashed;
   21 public int squished;
   22 public int no_back_scroll = 0;
   23 public int forw_prompt;
   24 
   25 extern int sigs;
   26 extern int top_scroll;
   27 extern int quiet;
   28 extern int sc_width, sc_height;
   29 extern int plusoption;
   30 extern int forw_scroll;
   31 extern int back_scroll;
   32 extern int ignore_eoi;
   33 extern int clear_bg;
   34 extern int final_attr;
   35 extern int oldbot;
   36 #if TAGS
   37 extern char *tagoption;
   38 #endif
   39 
   40 /*
   41  * Sound the bell to indicate user is trying to move past end of file.
   42  */
   43 	static void
   44 eof_bell()
   45 {
   46 	if (quiet == NOT_QUIET)
   47 		bell();
   48 	else
   49 		vbell();
   50 }
   51 
   52 /*
   53  * Check to see if the end of file is currently displayed.
   54  */
   55 	public int
   56 eof_displayed()
   57 {
   58 	POSITION pos;
   59 
   60 	if (ignore_eoi)
   61 		return (0);
   62 
   63 	if (ch_length() == NULL_POSITION)
   64 		/*
   65 		 * If the file length is not known,
   66 		 * we can't possibly be displaying EOF.
   67 		 */
   68 		return (0);
   69 
   70 	/*
   71 	 * If the bottom line is empty, we are at EOF.
   72 	 * If the bottom line ends at the file length,
   73 	 * we must be just at EOF.
   74 	 */
   75 	pos = position(BOTTOM_PLUS_ONE);
   76 	return (pos == NULL_POSITION || pos == ch_length());
   77 }
   78 
   79 /*
   80  * Check to see if the entire file is currently displayed.
   81  */
   82 	public int
   83 entire_file_displayed()
   84 {
   85 	POSITION pos;
   86 
   87 	/* Make sure last line of file is displayed. */
   88 	if (!eof_displayed())
   89 		return (0);
   90 
   91 	/* Make sure first line of file is displayed. */
   92 	pos = position(0);
   93 	return (pos == NULL_POSITION || pos == 0);
   94 }
   95 
   96 /*
   97  * If the screen is "squished", repaint it.
   98  * "Squished" means the first displayed line is not at the top
   99  * of the screen; this can happen when we display a short file
  100  * for the first time.
  101  */
  102 	public void
  103 squish_check()
  104 {
  105 	if (!squished)
  106 		return;
  107 	squished = 0;
  108 	repaint();
  109 }
  110 
  111 /*
  112  * Display n lines, scrolling forward,
  113  * starting at position pos in the input file.
  114  * "force" means display the n lines even if we hit end of file.
  115  * "only_last" means display only the last screenful if n > screen size.
  116  * "nblank" is the number of blank lines to draw before the first
  117  *   real line.  If nblank > 0, the pos must be NULL_POSITION.
  118  *   The first real line after the blanks will start at ch_zero().
  119  */
  120 	public void
  121 forw(n, pos, force, only_last, nblank)
  122 	register int n;
  123 	POSITION pos;
  124 	int force;
  125 	int only_last;
  126 	int nblank;
  127 {
  128 	int eof = 0;
  129 	int nlines = 0;
  130 	int do_repaint;
  131 	static int first_time = 1;
  132 
  133 	squish_check();
  134 
  135 	/*
  136 	 * do_repaint tells us not to display anything till the end,
  137 	 * then just repaint the entire screen.
  138 	 * We repaint if we are supposed to display only the last
  139 	 * screenful and the request is for more than a screenful.
  140 	 * Also if the request exceeds the forward scroll limit
  141 	 * (but not if the request is for exactly a screenful, since
  142 	 * repainting itself involves scrolling forward a screenful).
  143 	 */
  144 	do_repaint = (only_last && n > sc_height-1) ||
  145 		(forw_scroll >= 0 && n > forw_scroll && n != sc_height-1);
  146 
  147 	if (!do_repaint)
  148 	{
  149 		if (top_scroll && n >= sc_height - 1 && pos != ch_length())
  150 		{
  151 			/*
  152 			 * Start a new screen.
  153 			 * {{ This is not really desirable if we happen
  154 			 *    to hit eof in the middle of this screen,
  155 			 *    but we don't yet know if that will happen. }}
  156 			 */
  157 			pos_clear();
  158 			add_forw_pos(pos);
  159 			force = 1;
  160 			clear();
  161 			home();
  162 		}
  163 
  164 		if (pos != position(BOTTOM_PLUS_ONE) || empty_screen())
  165 		{
  166 			/*
  167 			 * This is not contiguous with what is
  168 			 * currently displayed.  Clear the screen image
  169 			 * (position table) and start a new screen.
  170 			 */
  171 			pos_clear();
  172 			add_forw_pos(pos);
  173 			force = 1;
  174 			if (top_scroll)
  175 			{
  176 				clear();
  177 				home();
  178 			} else if (!first_time)
  179 			{
  180 				putstr("...skipping...\n");
  181 			}
  182 		}
  183 	}
  184 
  185 	while (--n >= 0)
  186 	{
  187 		/*
  188 		 * Read the next line of input.
  189 		 */
  190 		if (nblank > 0)
  191 		{
  192 			/*
  193 			 * Still drawing blanks; don't get a line
  194 			 * from the file yet.
  195 			 * If this is the last blank line, get ready to
  196 			 * read a line starting at ch_zero() next time.
  197 			 */
  198 			if (--nblank == 0)
  199 				pos = ch_zero();
  200 		} else
  201 		{
  202 			/*
  203 			 * Get the next line from the file.
  204 			 */
  205 			pos = forw_line(pos);
  206 			if (pos == NULL_POSITION)
  207 			{
  208 				/*
  209 				 * End of file: stop here unless the top line
  210 				 * is still empty, or "force" is true.
  211 				 * Even if force is true, stop when the last
  212 				 * line in the file reaches the top of screen.
  213 				 */
  214 				eof = 1;
  215 				if (!force && position(TOP) != NULL_POSITION)
  216 					break;
  217 				if (!empty_lines(0, 0) &&
  218 				    !empty_lines(1, 1) &&
  219 				     empty_lines(2, sc_height-1))
  220 					break;
  221 			}
  222 		}
  223 		/*
  224 		 * Add the position of the next line to the position table.
  225 		 * Display the current line on the screen.
  226 		 */
  227 		add_forw_pos(pos);
  228 		nlines++;
  229 		if (do_repaint)
  230 			continue;
  231 		/*
  232 		 * If this is the first screen displayed and
  233 		 * we hit an early EOF (i.e. before the requested
  234 		 * number of lines), we "squish" the display down
  235 		 * at the bottom of the screen.
  236 		 * But don't do this if a + option or a -t option
  237 		 * was given.  These options can cause us to
  238 		 * start the display after the beginning of the file,
  239 		 * and it is not appropriate to squish in that case.
  240 		 */
  241 		if (first_time && pos == NULL_POSITION && !top_scroll &&
  242 #if TAGS
  243 		    tagoption == NULL &&
  244 #endif
  245 		    !plusoption)
  246 		{
  247 			squished = 1;
  248 			continue;
  249 		}
  250 		put_line();
  251 #if 0
  252 		/* {{
  253 		 * Can't call clear_eol here.  The cursor might be at end of line
  254 		 * on an ignaw terminal, so clear_eol would clear the last char
  255 		 * of the current line instead of all of the next line.
  256 		 * If we really need to do this on clear_bg terminals, we need
  257 		 * to find a better way.
  258 		 * }}
  259 		 */
  260 		if (clear_bg && apply_at_specials(final_attr) != AT_NORMAL)
  261 		{
  262 			/*
  263 			 * Writing the last character on the last line
  264 			 * of the display may have scrolled the screen.
  265 			 * If we were in standout mode, clear_bg terminals
  266 			 * will fill the new line with the standout color.
  267 			 * Now we're in normal mode again, so clear the line.
  268 			 */
  269 			clear_eol();
  270 		}
  271 #endif
  272 		forw_prompt = 1;
  273 	}
  274 
  275 	if (nlines == 0)
  276 		eof_bell();
  277 	else if (do_repaint)
  278 		repaint();
  279 	first_time = 0;
  280 	(void) currline(BOTTOM);
  281 }
  282 
  283 /*
  284  * Display n lines, scrolling backward.
  285  */
  286 	public void
  287 back(n, pos, force, only_last)
  288 	register int n;
  289 	POSITION pos;
  290 	int force;
  291 	int only_last;
  292 {
  293 	int nlines = 0;
  294 	int do_repaint;
  295 
  296 	squish_check();
  297 	do_repaint = (n > get_back_scroll() || (only_last && n > sc_height-1));
  298 	while (--n >= 0)
  299 	{
  300 		/*
  301 		 * Get the previous line of input.
  302 		 */
  303 		pos = back_line(pos);
  304 		if (pos == NULL_POSITION)
  305 		{
  306 			/*
  307 			 * Beginning of file: stop here unless "force" is true.
  308 			 */
  309 			if (!force)
  310 				break;
  311 		}
  312 		/*
  313 		 * Add the position of the previous line to the position table.
  314 		 * Display the line on the screen.
  315 		 */
  316 		add_back_pos(pos);
  317 		nlines++;
  318 		if (!do_repaint)
  319 		{
  320 			home();
  321 			add_line();
  322 			put_line();
  323 		}
  324 	}
  325 
  326 	if (nlines == 0)
  327 		eof_bell();
  328 	else if (do_repaint)
  329 		repaint();
  330 	else if (!oldbot)
  331 		lower_left();
  332 	(void) currline(BOTTOM);
  333 }
  334 
  335 /*
  336  * Display n more lines, forward.
  337  * Start just after the line currently displayed at the bottom of the screen.
  338  */
  339 	public void
  340 forward(n, force, only_last)
  341 	int n;
  342 	int force;
  343 	int only_last;
  344 {
  345 	POSITION pos;
  346 
  347 	if (get_quit_at_eof() && eof_displayed() && !(ch_getflags() & CH_HELPFILE))
  348 	{
  349 		/*
  350 		 * If the -e flag is set and we're trying to go
  351 		 * forward from end-of-file, go on to the next file.
  352 		 */
  353 		if (edit_next(1))
  354 			quit(QUIT_OK);
  355 		return;
  356 	}
  357 
  358 	pos = position(BOTTOM_PLUS_ONE);
  359 	if (pos == NULL_POSITION && (!force || empty_lines(2, sc_height-1)))
  360 	{
  361 		if (ignore_eoi)
  362 		{
  363 			/*
  364 			 * ignore_eoi is to support A_F_FOREVER.
  365 			 * Back up until there is a line at the bottom
  366 			 * of the screen.
  367 			 */
  368 			if (empty_screen())
  369 				pos = ch_zero();
  370 			else
  371 			{
  372 				do
  373 				{
  374 					back(1, position(TOP), 1, 0);
  375 					pos = position(BOTTOM_PLUS_ONE);
  376 				} while (pos == NULL_POSITION);
  377 			}
  378 		} else
  379 		{
  380 			eof_bell();
  381 			return;
  382 		}
  383 	}
  384 	forw(n, pos, force, only_last, 0);
  385 }
  386 
  387 /*
  388  * Display n more lines, backward.
  389  * Start just before the line currently displayed at the top of the screen.
  390  */
  391 	public void
  392 backward(n, force, only_last)
  393 	int n;
  394 	int force;
  395 	int only_last;
  396 {
  397 	POSITION pos;
  398 
  399 	pos = position(TOP);
  400 	if (pos == NULL_POSITION && (!force || position(BOTTOM) == 0))
  401 	{
  402 		eof_bell();
  403 		return;
  404 	}
  405 	back(n, pos, force, only_last);
  406 }
  407 
  408 /*
  409  * Get the backwards scroll limit.
  410  * Must call this function instead of just using the value of
  411  * back_scroll, because the default case depends on sc_height and
  412  * top_scroll, as well as back_scroll.
  413  */
  414 	public int
  415 get_back_scroll()
  416 {
  417 	if (no_back_scroll)
  418 		return (0);
  419 	if (back_scroll >= 0)
  420 		return (back_scroll);
  421 	if (top_scroll)
  422 		return (sc_height - 2);
  423 	return (10000); /* infinity */
  424 }