home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / less2912.zip / forwback.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-17  |  8.8 KB  |  402 lines

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