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