home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / LESS177.ZIP / src / forwback.c < prev    next >
C/C++ Source or Header  |  1992-07-18  |  8KB  |  373 lines

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