home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / CMDS / less_332.lzh / less_332 / forwback.c < prev    next >
Text File  |  1998-03-03  |  9KB  |  414 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.             pos_clear();
  150.             add_forw_pos(pos);
  151.             force = 1;
  152.             if (top_scroll == OPT_ONPLUS || first_time)
  153.                 clear();
  154.             home();
  155.         } else
  156.         {
  157.             clear_bot();
  158.             /*
  159.              * Remove the top n lines and scroll the rest
  160.              * upward, leaving cursor at first new blank line.
  161.              */
  162.             remove_top(n);
  163.         }
  164.  
  165.         if (pos != position(BOTTOM_PLUS_ONE) || empty_screen())
  166.         {
  167.             /*
  168.              * This is not contiguous with what is
  169.              * currently displayed.  Clear the screen image 
  170.              * (position table) and start a new screen.
  171.              */
  172.             pos_clear();
  173.             add_forw_pos(pos);
  174.             force = 1;
  175.             if (top_scroll)
  176.             {
  177.                 if (top_scroll == OPT_ONPLUS)
  178.                     clear();
  179.                 home();
  180.             } else if (!first_time)
  181.             {
  182.                 putstr("...skipping...\n");
  183.             }
  184.         }
  185.     }
  186.  
  187.     while (--n >= 0)
  188.     {
  189.         /*
  190.          * Read the next line of input.
  191.          */
  192.         if (nblank > 0)
  193.         {
  194.             /*
  195.              * Still drawing blanks; don't get a line 
  196.              * from the file yet.
  197.              * If this is the last blank line, get ready to
  198.              * read a line starting at ch_zero() next time.
  199.              */
  200.             if (--nblank == 0)
  201.                 pos = ch_zero();
  202.         } else
  203.         {
  204.             /* 
  205.              * Get the next line from the file.
  206.              */
  207.             pos = forw_line(pos);
  208.             if (pos == NULL_POSITION)
  209.             {
  210.                 /*
  211.                  * End of file: stop here unless the top line 
  212.                  * is still empty, or "force" is true.
  213.                  * Even if force is true, stop when the last
  214.                  * line in the file reaches the top of screen.
  215.                  */
  216.                 eof = 1;
  217.                 if (!force && position(TOP) != NULL_POSITION)
  218.                     break;
  219.                 if (!empty_lines(0, 0) && 
  220.                     !empty_lines(1, 1) &&
  221.                      empty_lines(2, sc_height-1))
  222.                     break;
  223.             }
  224.         }
  225.         /*
  226.          * Add the position of the next line to the position table.
  227.          * Display the current line on the screen.
  228.          */
  229.         add_forw_pos(pos);
  230.         nlines++;
  231.         if (do_repaint)
  232.             continue;
  233.         /*
  234.          * If this is the first screen displayed and
  235.          * we hit an early EOF (i.e. before the requested
  236.          * number of lines), we "squish" the display down
  237.          * at the bottom of the screen.
  238.          * But don't do this if a + option or a -t option
  239.          * was given.  These options can cause us to
  240.          * start the display after the beginning of the file,
  241.          * and it is not appropriate to squish in that case.
  242.          */
  243.         if (first_time && pos == NULL_POSITION && !top_scroll && 
  244. #if TAGS
  245.             tagoption == NULL &&
  246. #endif
  247.             !plusoption)
  248.         {
  249.             squished = 1;
  250.             continue;
  251.         }
  252.         if (top_scroll == OPT_ON)
  253.             clear_eol();
  254.         put_line();
  255.     }
  256.  
  257.     if (ignore_eoi)
  258.         hit_eof = 0;
  259.     else if (eof && !ABORT_SIGS())
  260.         hit_eof++;
  261.     else
  262.         eof_check();
  263.     if (nlines == 0)
  264.         eof_bell();
  265.     else if (do_repaint)
  266.         repaint();
  267.     first_time = 0;
  268.     (void) currline(BOTTOM);
  269. }
  270.  
  271. /*
  272.  * Display n lines, scrolling backward.
  273.  */
  274.     public void
  275. back(n, pos, force, only_last)
  276.     register int n;
  277.     POSITION pos;
  278.     int force;
  279.     int only_last;
  280. {
  281.     int nlines = 0;
  282.     int do_repaint;
  283.  
  284.     squish_check();
  285.     do_repaint = (n > get_back_scroll() || (only_last && n > sc_height-1));
  286.     hit_eof = 0;
  287.     while (--n >= 0)
  288.     {
  289.         /*
  290.          * Get the previous line of input.
  291.          */
  292.         pos = back_line(pos);
  293.         if (pos == NULL_POSITION)
  294.         {
  295.             /*
  296.              * Beginning of file: stop here unless "force" is true.
  297.              */
  298.             if (!force)
  299.                 break;
  300.         }
  301.         /*
  302.          * Add the position of the previous line to the position table.
  303.          * Display the line on the screen.
  304.          */
  305.         add_back_pos(pos);
  306.         nlines++;
  307.         if (!do_repaint)
  308.         {
  309.             home();
  310.             add_line();
  311.             put_line();
  312.         }
  313.     }
  314.  
  315.     eof_check();
  316.     if (nlines == 0)
  317.         eof_bell();
  318.     else if (do_repaint)
  319.         repaint();
  320.     (void) currline(BOTTOM);
  321. }
  322.  
  323. /*
  324.  * Display n more lines, forward.
  325.  * Start just after the line currently displayed at the bottom of the screen.
  326.  */
  327.     public void
  328. forward(n, force, only_last)
  329.     int n;
  330.     int force;
  331.     int only_last;
  332. {
  333.     POSITION pos;
  334.  
  335.     if (quit_at_eof && hit_eof && !(ch_getflags() & CH_HELPFILE))
  336.     {
  337.         /*
  338.          * If the -e flag is set and we're trying to go
  339.          * forward from end-of-file, go on to the next file.
  340.          */
  341.         if (edit_next(1))
  342.             quit(QUIT_OK);
  343.         return;
  344.     }
  345.  
  346.     pos = position(BOTTOM_PLUS_ONE);
  347.     if (pos == NULL_POSITION && (!force || empty_lines(2, sc_height-1)))
  348.     {
  349.         if (ignore_eoi)
  350.         {
  351.             /*
  352.              * ignore_eoi is to support A_F_FOREVER.
  353.              * Back up until there is a line at the bottom
  354.              * of the screen.
  355.              */
  356.             if (empty_screen())
  357.                 pos = ch_zero();
  358.             else
  359.             {
  360.                 do
  361.                 {
  362.                     back(1, position(TOP), 1, 0);
  363.                     pos = position(BOTTOM_PLUS_ONE);
  364.                 } while (pos == NULL_POSITION);
  365.             }
  366.         } else
  367.         {
  368.             eof_bell();
  369.             hit_eof++;
  370.             return;
  371.         }
  372.     }
  373.     forw(n, pos, force, only_last, 0);
  374. }
  375.  
  376. /*
  377.  * Display n more lines, backward.
  378.  * Start just before the line currently displayed at the top of the screen.
  379.  */
  380.     public void
  381. backward(n, force, only_last)
  382.     int n;
  383.     int force;
  384.     int only_last;
  385. {
  386.     POSITION pos;
  387.  
  388.     pos = position(TOP);
  389.     if (pos == NULL_POSITION && (!force || position(BOTTOM) == 0))
  390.     {
  391.         eof_bell();
  392.         return;   
  393.     }
  394.     back(n, pos, force, only_last);
  395. }
  396.  
  397. /*
  398.  * Get the backwards scroll limit.
  399.  * Must call this function instead of just using the value of
  400.  * back_scroll, because the default case depends on sc_height and
  401.  * top_scroll, as well as back_scroll.
  402.  */
  403.     public int
  404. get_back_scroll()
  405. {
  406.     if (no_back_scroll)
  407.         return (0);
  408.     if (back_scroll >= 0)
  409.         return (back_scroll);
  410.     if (top_scroll)
  411.         return (sc_height - 2);
  412.     return (10000); /* infinity */
  413. }
  414.