home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / LESS177.ZIP / src / input.c < prev    next >
C/C++ Source or Header  |  1992-07-18  |  5KB  |  262 lines

  1. /*
  2.  * High level routines dealing with getting lines of input 
  3.  * from the file being viewed.
  4.  *
  5.  * When we speak of "lines" here, we mean PRINTABLE lines;
  6.  * lines processed with respect to the screen width.
  7.  * We use the term "raw line" to refer to lines simply
  8.  * delimited by newlines; not processed with respect to screen width.
  9.  */
  10.  
  11. #include "less.h"
  12.  
  13. extern int squeeze;
  14. extern int chopline;
  15. extern int sigs;
  16.  
  17. /*
  18.  * Get the next line.
  19.  * A "current" position is passed and a "new" position is returned.
  20.  * The current position is the position of the first character of
  21.  * a line.  The new position is the position of the first character
  22.  * of the NEXT line.  The line obtained is the line starting at curr_pos.
  23.  */
  24.     public POSITION
  25. forw_line(curr_pos)
  26.     POSITION curr_pos;
  27. {
  28.     POSITION new_pos;
  29.     register int c;
  30.     int blankline;
  31.     int endline;
  32.  
  33.     if (curr_pos == NULL_POSITION || ch_seek(curr_pos))
  34.     {
  35.         null_line();
  36.         return (NULL_POSITION);
  37.     }
  38.  
  39.     prewind();
  40.     plinenum(curr_pos);
  41.     (void) ch_seek(curr_pos);
  42.  
  43.     c = ch_forw_get();
  44.     if (c == EOI)
  45.     {
  46.         null_line();
  47.         return (NULL_POSITION);
  48.     }
  49.     blankline = (c == '\n' || c == '\r');
  50.  
  51.     for (;;)
  52.     {
  53.         if (sigs)
  54.         {
  55.             null_line();
  56.             return (NULL_POSITION);
  57.         }
  58.         if (c == '\n' || c == EOI)
  59.         {
  60.             /*
  61.              * End of the line.
  62.              */
  63.             new_pos = ch_tell();
  64.             endline = 1;
  65.             break;
  66.         }
  67.  
  68.         /*
  69.          * Append the char to the line and get the next char.
  70.          */
  71.         if (pappend(c))
  72.         {
  73.             /*
  74.              * The char won't fit in the line; the line
  75.              * is too long to print in the screen width.
  76.              * End the line here.
  77.              */
  78.             if (chopline)
  79.             {
  80.                 do
  81.                 {
  82.                     c = ch_forw_get();
  83.                 } while (c != '\n' && c != EOI);
  84.                 new_pos = ch_tell();
  85.                 endline = 1;
  86.             } else
  87.             {
  88.                 new_pos = ch_tell() - 1;
  89.                 endline = 0;
  90.             }
  91.             break;
  92.         }
  93.         c = ch_forw_get();
  94.     }
  95.     pdone(endline);
  96.  
  97.     if (squeeze && blankline)
  98.     {
  99.         /*
  100.          * This line is blank.
  101.          * Skip down to the last contiguous blank line
  102.          * and pretend it is the one which we are returning.
  103.          */
  104.         while ((c = ch_forw_get()) == '\n' || c == '\r')
  105.             if (sigs)
  106.             {
  107.                 null_line();
  108.                 return (NULL_POSITION);
  109.             }
  110.         if (c != EOI)
  111.             (void) ch_back_get();
  112.         new_pos = ch_tell();
  113.     }
  114.  
  115.     return (new_pos);
  116. }
  117.  
  118. /*
  119.  * Get the previous line.
  120.  * A "current" position is passed and a "new" position is returned.
  121.  * The current position is the position of the first character of
  122.  * a line.  The new position is the position of the first character
  123.  * of the PREVIOUS line.  The line obtained is the one starting at new_pos.
  124.  */
  125.     public POSITION
  126. back_line(curr_pos)
  127.     POSITION curr_pos;
  128. {
  129.     POSITION new_pos, begin_new_pos;
  130.     int c;
  131.     int endline;
  132.  
  133.     if (curr_pos == NULL_POSITION || curr_pos <= ch_zero() ||
  134.         ch_seek(curr_pos-1))
  135.     {
  136.         null_line();
  137.         return (NULL_POSITION);
  138.     }
  139.  
  140.     if (squeeze)
  141.     {
  142.         /*
  143.          * Find out if the "current" line was blank.
  144.          */
  145.         (void) ch_forw_get();    /* Skip the newline */
  146.         c = ch_forw_get();    /* First char of "current" line */
  147.         (void) ch_back_get();    /* Restore our position */
  148.         (void) ch_back_get();
  149.  
  150.         if (c == '\n')
  151.         {
  152.             /*
  153.              * The "current" line was blank.
  154.              * Skip over any preceding blank lines,
  155.              * since we skipped them in forw_line().
  156.              */
  157.             while ((c = ch_back_get()) == '\n' || c == '\r')
  158.                 if (sigs)
  159.                 {
  160.                     null_line();
  161.                     return (NULL_POSITION);
  162.                 }
  163.             if (c == EOI)
  164.             {
  165.                 null_line();
  166.                 return (NULL_POSITION);
  167.             }
  168.             (void) ch_forw_get();
  169.         }
  170.     }
  171.  
  172.     /*
  173.      * Scan backwards until we hit the beginning of the line.
  174.      */
  175.     for (;;)
  176.     {
  177.         if (sigs)
  178.         {
  179.             null_line();
  180.             return (NULL_POSITION);
  181.         }
  182.         c = ch_back_get();
  183.         if (c == '\n')
  184.         {
  185.             /*
  186.              * This is the newline ending the previous line.
  187.              * We have hit the beginning of the line.
  188.              */
  189.             new_pos = ch_tell() + 1;
  190.             break;
  191.         }
  192.         if (c == EOI)
  193.         {
  194.             /*
  195.              * We have hit the beginning of the file.
  196.              * This must be the first line in the file.
  197.              * This must, of course, be the beginning of the line.
  198.              */
  199.             new_pos = ch_tell();
  200.             break;
  201.         }
  202.     }
  203.  
  204.     /*
  205.      * Now scan forwards from the beginning of this line.
  206.      * We keep discarding "printable lines" (based on screen width)
  207.      * until we reach the curr_pos.
  208.      *
  209.      * {{ This algorithm is pretty inefficient if the lines
  210.      *    are much longer than the screen width, 
  211.      *    but I don't know of any better way. }}
  212.      */
  213.     if (ch_seek(new_pos))
  214.     {
  215.         null_line();
  216.         return (NULL_POSITION);
  217.     }
  218.     endline = 0;
  219.     loop:
  220.     begin_new_pos = new_pos;
  221.     prewind();
  222.     plinenum(new_pos);
  223.     (void) ch_seek(new_pos);
  224.  
  225.     do
  226.     {
  227.         c = ch_forw_get();
  228.         if (c == EOI || sigs)
  229.         {
  230.             null_line();
  231.             return (NULL_POSITION);
  232.         }
  233.         new_pos++;
  234.         if (c == '\n')
  235.         {
  236.             endline = 1;
  237.             break;
  238.         }
  239.         if (pappend(c))
  240.         {
  241.             /*
  242.              * Got a full printable line, but we haven't
  243.              * reached our curr_pos yet.  Discard the line
  244.              * and start a new one.
  245.              */
  246.             if (chopline)
  247.             {
  248.                 endline = 1;
  249.                 break;
  250.             }
  251.             pdone(0);
  252.             (void) ch_back_get();
  253.             new_pos--;
  254.             goto loop;
  255.         }
  256.     } while (new_pos < curr_pos);
  257.  
  258.     pdone(endline);
  259.  
  260.     return (begin_new_pos);
  261. }
  262.