home *** CD-ROM | disk | FTP | other *** search
/ The Pier Shareware 6 / The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso / 036 / less232.zip / FORWBACK.C < prev    next >
C/C++ Source or Header  |  1994-09-02  |  9KB  |  399 lines

  1. /*
  2.  * Copyright (c) 1984,1985,1989,1994  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.  
  40. extern int sigs;
  41. extern int top_scroll;
  42. extern int quiet;
  43. extern int sc_width, sc_height;
  44. extern int quit_at_eof;
  45. extern int plusoption;
  46. extern int forw_scroll;
  47. extern int back_scroll;
  48. extern int need_clr;
  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 == 2 || 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 == 2)
  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.                  */
  207.                 eof = 1;
  208.                 if (!force && position(TOP) != NULL_POSITION)
  209.                     break;
  210.             }
  211.         }
  212.         /*
  213.          * Add the position of the next line to the position table.
  214.          * Display the current line on the screen.
  215.          */
  216.         add_forw_pos(pos);
  217.         nlines++;
  218.         if (do_repaint)
  219.             continue;
  220.         /*
  221.          * If this is the first screen displayed and
  222.          * we hit an early EOF (i.e. before the requested
  223.          * number of lines), we "squish" the display down
  224.          * at the bottom of the screen.
  225.          * But don't do this if a + option or a -t option
  226.          * was given.  These options can cause us to
  227.          * start the display after the beginning of the file,
  228.          * and it is not appropriate to squish in that case.
  229.          */
  230.         if (first_time && pos == NULL_POSITION && !top_scroll && 
  231. #if TAGS
  232.             tagoption == NULL &&
  233. #endif
  234.             !plusoption)
  235.         {
  236.             squished = 1;
  237.             continue;
  238.         }
  239.         if (top_scroll == 1)
  240.             clear_eol();
  241.         put_line();
  242.     }
  243.  
  244.     if (ignore_eoi)
  245.         hit_eof = 0;
  246.     else if (eof && !ABORT_SIGS())
  247.         hit_eof++;
  248.     else
  249.         eof_check();
  250.     if (nlines == 0)
  251.         eof_bell();
  252.     else if (do_repaint)
  253.         repaint();
  254.     first_time = 0;
  255.     (void) currline(BOTTOM);
  256. }
  257.  
  258. /*
  259.  * Display n lines, scrolling backward.
  260.  */
  261.     public void
  262. back(n, pos, force, only_last)
  263.     register int n;
  264.     POSITION pos;
  265.     int force;
  266.     int only_last;
  267. {
  268.     int nlines = 0;
  269.     int do_repaint;
  270.  
  271.     squish_check();
  272.     do_repaint = (n > get_back_scroll() || (only_last && n > sc_height-1));
  273.     hit_eof = 0;
  274.     while (--n >= 0)
  275.     {
  276.         /*
  277.          * Get the previous line of input.
  278.          */
  279.         pos = back_line(pos);
  280.         if (pos == NULL_POSITION)
  281.         {
  282.             /*
  283.              * Beginning of file: stop here unless "force" is true.
  284.              */
  285.             if (!force)
  286.                 break;
  287.         }
  288.         /*
  289.          * Add the position of the previous line to the position table.
  290.          * Display the line on the screen.
  291.          */
  292.         add_back_pos(pos);
  293.         nlines++;
  294.         if (!do_repaint)
  295.         {
  296.             home();
  297.             add_line();
  298.             put_line();
  299.         }
  300.     }
  301.  
  302.     eof_check();
  303.     if (nlines == 0)
  304.         eof_bell();
  305.     else if (do_repaint)
  306.         repaint();
  307.     (void) currline(BOTTOM);
  308. }
  309.  
  310. /*
  311.  * Display n more lines, forward.
  312.  * Start just after the line currently displayed at the bottom of the screen.
  313.  */
  314.     public void
  315. forward(n, force, only_last)
  316.     int n;
  317.     int force;
  318.     int only_last;
  319. {
  320.     POSITION pos;
  321.  
  322.     if (quit_at_eof && hit_eof)
  323.     {
  324.         /*
  325.          * If the -e flag is set and we're trying to go
  326.          * forward from end-of-file, go on to the next file.
  327.          */
  328.         if (edit_next(1))
  329.             quit(0);
  330.         return;
  331.     }
  332.  
  333.     pos = position(BOTTOM_PLUS_ONE);
  334.     if (pos == NULL_POSITION && (!force || empty_lines(2, sc_height-1)))
  335.     {
  336.         if (ignore_eoi)
  337.         {
  338.             /*
  339.              * ignore_eoi is to support A_F_FOREVER.
  340.              * Back up until there is a line at the bottom
  341.              * of the screen.
  342.              */
  343.             if (empty_screen())
  344.                 pos = ch_zero();
  345.             else
  346.             {
  347.                 do
  348.                 {
  349.                     back(1, position(TOP), 1, 0);
  350.                     pos = position(BOTTOM_PLUS_ONE);
  351.                 } while (pos == NULL_POSITION);
  352.             }
  353.         } else
  354.         {
  355.             eof_bell();
  356.             hit_eof++;
  357.             return;
  358.         }
  359.     }
  360.     forw(n, pos, force, only_last, 0);
  361. }
  362.  
  363. /*
  364.  * Display n more lines, backward.
  365.  * Start just before the line currently displayed at the top of the screen.
  366.  */
  367.     public void
  368. backward(n, force, only_last)
  369.     int n;
  370.     int force;
  371.     int only_last;
  372. {
  373.     POSITION pos;
  374.  
  375.     pos = position(TOP);
  376.     if (pos == NULL_POSITION && (!force || position(BOTTOM) == 0))
  377.     {
  378.         eof_bell();
  379.         return;   
  380.     }
  381.     back(n, pos, force, only_last);
  382. }
  383.  
  384. /*
  385.  * Get the backwards scroll limit.
  386.  * Must call this function instead of just using the value of
  387.  * back_scroll, because the default case depends on sc_height and
  388.  * top_scroll, as well as back_scroll.
  389.  */
  390.     public int
  391. get_back_scroll()
  392. {
  393.     if (back_scroll >= 0)
  394.         return (back_scroll);
  395.     if (top_scroll)
  396.         return (sc_height - 2);
  397.     return (10000); /* infinity */
  398. }
  399.