home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 6 File / 06-File.zip / less373.zip / forwback.c < prev    next >
C/C++ Source or Header  |  2002-01-14  |  9KB  |  413 lines

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