home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / less-321-src.tgz / tar.out / fsf / less / forwback.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  9KB  |  405 lines

  1. /*
  2.  * Copyright (c) 1984,1985,1989,1994,1995,1996  Mark Nudelman
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice in the documentation and/or other materials provided with 
  12.  *    the distribution.
  13.  *
  14.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
  15.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  17.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
  18.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
  19.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
  20.  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
  21.  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  22.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
  23.  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 
  24.  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25.  */
  26.  
  27.  
  28. /*
  29.  * Primitives for displaying the file on the screen,
  30.  * scrolling either forward or backward.
  31.  */
  32.  
  33. #include "less.h"
  34. #include "position.h"
  35.  
  36. public int hit_eof;    /* Keeps track of how many times we hit end of file */
  37. public int screen_trashed;
  38. public int squished;
  39. public int no_back_scroll = 0;
  40.  
  41. extern int sigs;
  42. extern int top_scroll;
  43. extern int quiet;
  44. extern int sc_width, sc_height;
  45. extern int quit_at_eof;
  46. extern int plusoption;
  47. extern int forw_scroll;
  48. extern int back_scroll;
  49. extern int ignore_eoi;
  50. #if TAGS
  51. extern char *tagoption;
  52. #endif
  53.  
  54. /*
  55.  * Sound the bell to indicate user is trying to move past end of file.
  56.  */
  57.     static void
  58. eof_bell()
  59. {
  60.     if (quiet == NOT_QUIET)
  61.         bell();
  62.     else
  63.         vbell();
  64. }
  65.  
  66. /*
  67.  * Check to see if the end of file is currently "displayed".
  68.  */
  69.     static void
  70. eof_check()
  71. {
  72.     POSITION pos;
  73.  
  74.     if (ignore_eoi)
  75.         return;
  76.     if (ABORT_SIGS())
  77.         return;
  78.     /*
  79.      * If the bottom line is empty, we are at EOF.
  80.      * If the bottom line ends at the file length,
  81.      * we must be just at EOF.
  82.      */
  83.     pos = position(BOTTOM_PLUS_ONE);
  84.     if (pos == NULL_POSITION || pos == ch_length())
  85.         hit_eof++;
  86. }
  87.  
  88. /*
  89.  * If the screen is "squished", repaint it.
  90.  * "Squished" means the first displayed line is not at the top
  91.  * of the screen; this can happen when we display a short file
  92.  * for the first time.
  93.  */
  94.     static void
  95. squish_check()
  96. {
  97.     if (!squished)
  98.         return;
  99.     squished = 0;
  100.     repaint();
  101. }
  102.  
  103. /*
  104.  * Display n lines, scrolling forward, 
  105.  * starting at position pos in the input file.
  106.  * "force" means display the n lines even if we hit end of file.
  107.  * "only_last" means display only the last screenful if n > screen size.
  108.  * "nblank" is the number of blank lines to draw before the first
  109.  *   real line.  If nblank > 0, the pos must be NULL_POSITION.
  110.  *   The first real line after the blanks will start at ch_zero().
  111.  */
  112.     public void
  113. forw(n, pos, force, only_last, nblank)
  114.     register int n;
  115.     POSITION pos;
  116.     int force;
  117.     int only_last;
  118.     int nblank;
  119. {
  120.     int eof = 0;
  121.     int nlines = 0;
  122.     int do_repaint;
  123.     static int first_time = 1;
  124.  
  125.     squish_check();
  126.  
  127.     /*
  128.      * do_repaint tells us not to display anything till the end, 
  129.      * then just repaint the entire screen.
  130.      * We repaint if we are supposed to display only the last 
  131.      * screenful and the request is for more than a screenful.
  132.      * Also if the request exceeds the forward scroll limit
  133.      * (but not if the request is for exactly a screenful, since
  134.      * repainting itself involves scrolling forward a screenful).
  135.      */
  136.     do_repaint = (only_last && n > sc_height-1) || 
  137.         (forw_scroll >= 0 && n > forw_scroll && n != sc_height-1);
  138.  
  139.     if (!do_repaint)
  140.     {
  141.         if (top_scroll && n >= sc_height - 1 && pos != ch_length())
  142.         {
  143.             /*
  144.              * Start a new screen.
  145.              * {{ This is not really desirable if we happen
  146.              *    to hit eof in the middle of this screen,
  147.              *    but we don't yet know if that will happen. }}
  148.              */
  149.             if (top_scroll == OPT_ONPLUS || first_time)
  150.                 clear();
  151.             home();
  152.             force = 1;
  153.         } else
  154.         {
  155.             clear_bot();
  156.         }
  157.  
  158.         if (pos != position(BOTTOM_PLUS_ONE) || empty_screen())
  159.         {
  160.             /*
  161.              * This is not contiguous with what is
  162.              * currently displayed.  Clear the screen image 
  163.              * (position table) and start a new screen.
  164.              */
  165.             pos_clear();
  166.             add_forw_pos(pos);
  167.             force = 1;
  168.             if (top_scroll)
  169.             {
  170.                 if (top_scroll == OPT_ONPLUS)
  171.                     clear();
  172.                 home();
  173.             } else if (!first_time)
  174.             {
  175.                 putstr("...skipping...\n");
  176.             }
  177.         }
  178.     }
  179.  
  180.     while (--n >= 0)
  181.     {
  182.         /*
  183.          * Read the next line of input.
  184.          */
  185.         if (nblank > 0)
  186.         {
  187.             /*
  188.              * Still drawing blanks; don't get a line 
  189.              * from the file yet.
  190.              * If this is the last blank line, get ready to
  191.              * read a line starting at ch_zero() next time.
  192.              */
  193.             if (--nblank == 0)
  194.                 pos = ch_zero();
  195.         } else
  196.         {
  197.             /* 
  198.              * Get the next line from the file.
  199.              */
  200.             pos = forw_line(pos);
  201.             if (pos == NULL_POSITION)
  202.             {
  203.                 /*
  204.                  * End of file: stop here unless the top line 
  205.                  * is still empty, or "force" is true.
  206.                  * Even if force is true, stop when the last
  207.                  * line in the file reaches the top of screen.
  208.                  */
  209.                 eof = 1;
  210.                 if (!force && position(TOP) != NULL_POSITION)
  211.                     break;
  212.                 if (empty_lines(2, sc_height-1))
  213.                     break;
  214.             }
  215.         }
  216.         /*
  217.          * Add the position of the next line to the position table.
  218.          * Display the current line on the screen.
  219.          */
  220.         add_forw_pos(pos);
  221.         nlines++;
  222.         if (do_repaint)
  223.             continue;
  224.         /*
  225.          * If this is the first screen displayed and
  226.          * we hit an early EOF (i.e. before the requested
  227.          * number of lines), we "squish" the display down
  228.          * at the bottom of the screen.
  229.          * But don't do this if a + option or a -t option
  230.          * was given.  These options can cause us to
  231.          * start the display after the beginning of the file,
  232.          * and it is not appropriate to squish in that case.
  233.          */
  234.         if (first_time && pos == NULL_POSITION && !top_scroll && 
  235. #if TAGS
  236.             tagoption == NULL &&
  237. #endif
  238.             !plusoption)
  239.         {
  240.             squished = 1;
  241.             continue;
  242.         }
  243.         if (top_scroll == 1)
  244.             clear_eol();
  245.         put_line();
  246.     }
  247.  
  248.     if (ignore_eoi)
  249.         hit_eof = 0;
  250.     else if (eof && !ABORT_SIGS())
  251.         hit_eof++;
  252.     else
  253.         eof_check();
  254.     if (nlines == 0)
  255.         eof_bell();
  256.     else if (do_repaint)
  257.         repaint();
  258.     first_time = 0;
  259.     (void) currline(BOTTOM);
  260. }
  261.  
  262. /*
  263.  * Display n lines, scrolling backward.
  264.  */
  265.     public void
  266. back(n, pos, force, only_last)
  267.     register int n;
  268.     POSITION pos;
  269.     int force;
  270.     int only_last;
  271. {
  272.     int nlines = 0;
  273.     int do_repaint;
  274.  
  275.     squish_check();
  276.     do_repaint = (n > get_back_scroll() || (only_last && n > sc_height-1));
  277.     hit_eof = 0;
  278.     while (--n >= 0)
  279.     {
  280.         /*
  281.          * Get the previous line of input.
  282.          */
  283.         pos = back_line(pos);
  284.         if (pos == NULL_POSITION)
  285.         {
  286.             /*
  287.              * Beginning of file: stop here unless "force" is true.
  288.              */
  289.             if (!force)
  290.                 break;
  291.         }
  292.         /*
  293.          * Add the position of the previous line to the position table.
  294.          * Display the line on the screen.
  295.          */
  296.         add_back_pos(pos);
  297.         nlines++;
  298.         if (!do_repaint)
  299.         {
  300.             home();
  301.             add_line();
  302.             put_line();
  303.         }
  304.     }
  305.  
  306.     eof_check();
  307.     if (nlines == 0)
  308.         eof_bell();
  309.     else if (do_repaint)
  310.         repaint();
  311.     (void) currline(BOTTOM);
  312. }
  313.  
  314. /*
  315.  * Display n more lines, forward.
  316.  * Start just after the line currently displayed at the bottom of the screen.
  317.  */
  318.     public void
  319. forward(n, force, only_last)
  320.     int n;
  321.     int force;
  322.     int only_last;
  323. {
  324.     POSITION pos;
  325.  
  326.     if (quit_at_eof && hit_eof && !(ch_getflags() & CH_HELPFILE))
  327.     {
  328.         /*
  329.          * If the -e flag is set and we're trying to go
  330.          * forward from end-of-file, go on to the next file.
  331.          */
  332.         if (edit_next(1))
  333.             quit(QUIT_OK);
  334.         return;
  335.     }
  336.  
  337.     pos = position(BOTTOM_PLUS_ONE);
  338.     if (pos == NULL_POSITION && (!force || empty_lines(2, sc_height-1)))
  339.     {
  340.         if (ignore_eoi)
  341.         {
  342.             /*
  343.              * ignore_eoi is to support A_F_FOREVER.
  344.              * Back up until there is a line at the bottom
  345.              * of the screen.
  346.              */
  347.             if (empty_screen())
  348.                 pos = ch_zero();
  349.             else
  350.             {
  351.                 do
  352.                 {
  353.                     back(1, position(TOP), 1, 0);
  354.                     pos = position(BOTTOM_PLUS_ONE);
  355.                 } while (pos == NULL_POSITION);
  356.             }
  357.         } else
  358.         {
  359.             eof_bell();
  360.             hit_eof++;
  361.             return;
  362.         }
  363.     }
  364.     forw(n, pos, force, only_last, 0);
  365. }
  366.  
  367. /*
  368.  * Display n more lines, backward.
  369.  * Start just before the line currently displayed at the top of the screen.
  370.  */
  371.     public void
  372. backward(n, force, only_last)
  373.     int n;
  374.     int force;
  375.     int only_last;
  376. {
  377.     POSITION pos;
  378.  
  379.     pos = position(TOP);
  380.     if (pos == NULL_POSITION && (!force || position(BOTTOM) == 0))
  381.     {
  382.         eof_bell();
  383.         return;   
  384.     }
  385.     back(n, pos, force, only_last);
  386. }
  387.  
  388. /*
  389.  * Get the backwards scroll limit.
  390.  * Must call this function instead of just using the value of
  391.  * back_scroll, because the default case depends on sc_height and
  392.  * top_scroll, as well as back_scroll.
  393.  */
  394.     public int
  395. get_back_scroll()
  396. {
  397.     if (no_back_scroll)
  398.         return (0);
  399.     if (back_scroll >= 0)
  400.         return (back_scroll);
  401.     if (top_scroll)
  402.         return (sc_height - 2);
  403.     return (10000); /* infinity */
  404. }
  405.