home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d149 / less.lha / Less / Src / input.c < prev    next >
C/C++ Source or Header  |  1987-06-15  |  4KB  |  192 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 char *line;
  15.  
  16. /*
  17.  * Get the next line.
  18.  * A "current" position is passed and a "new" position is returned.
  19.  * The current position is the position of the first character of
  20.  * a line.  The new position is the position of the first character
  21.  * of the NEXT line.  The line obtained is the line starting at curr_pos.
  22.  */
  23.     public POSITION
  24. forw_line(curr_pos)
  25.     POSITION curr_pos;
  26. {
  27.     POSITION new_pos;
  28.     register int c;
  29.  
  30.     if (curr_pos == NULL_POSITION || ch_seek(curr_pos))
  31.         return (NULL_POSITION);
  32.  
  33.     c = ch_forw_get();
  34.     if (c == EOF)
  35.         return (NULL_POSITION);
  36.  
  37.     prewind();
  38.     for (;;)
  39.     {
  40.         if (c == '\n' || c == EOF)
  41.         {
  42.             /*
  43.              * End of the line.
  44.              */
  45.             new_pos = ch_tell();
  46.             break;
  47.         }
  48.  
  49.         /*
  50.          * Append the char to the line and get the next char.
  51.          */
  52.         if (pappend(c))
  53.         {
  54.             /*
  55.              * The char won't fit in the line; the line
  56.              * is too long to print in the screen width.
  57.              * End the line here.
  58.              */
  59.             new_pos = ch_tell() - 1;
  60.             break;
  61.         }
  62.         c = ch_forw_get();
  63.     }
  64.     (void) pappend('\0');
  65.  
  66.     if (squeeze && *line == '\0')
  67.     {
  68.         /*
  69.          * This line is blank.
  70.          * Skip down to the last contiguous blank line
  71.          * and pretend it is the one which we are returning.
  72.          */
  73.         while ((c = ch_forw_get()) == '\n')
  74.             ;
  75.         if (c != EOF)
  76.             (void) ch_back_get();
  77.         new_pos = ch_tell();
  78.     }
  79.  
  80.     return (new_pos);
  81. }
  82.  
  83. /*
  84.  * Get the previous line.
  85.  * A "current" position is passed and a "new" position is returned.
  86.  * The current position is the position of the first character of
  87.  * a line.  The new position is the position of the first character
  88.  * of the PREVIOUS line.  The line obtained is the one starting at new_pos.
  89.  */
  90.     public POSITION
  91. back_line(curr_pos)
  92.     POSITION curr_pos;
  93. {
  94.     POSITION new_pos, begin_new_pos;
  95.     int c;
  96.  
  97.     if (curr_pos == NULL_POSITION || curr_pos <= (POSITION)0 ||
  98.         ch_seek(curr_pos-1))
  99.         return (NULL_POSITION);
  100.  
  101.     if (squeeze)
  102.     {
  103.         /*
  104.          * Find out if the "current" line was blank.
  105.          */
  106.         (void) ch_forw_get();    /* Skip the newline */
  107.         c = ch_forw_get();    /* First char of "current" line */
  108.         (void) ch_back_get();    /* Restore our position */
  109.         (void) ch_back_get();
  110.  
  111.         if (c == '\n')
  112.         {
  113.             /*
  114.              * The "current" line was blank.
  115.              * Skip over any preceeding blank lines,
  116.              * since we skipped them in forw_line().
  117.              */
  118.             while ((c = ch_back_get()) == '\n')
  119.                 ;
  120.             if (c == EOF)
  121.                 return (NULL_POSITION);
  122.             (void) ch_forw_get();
  123.         }
  124.     }
  125.  
  126.     /*
  127.      * Scan backwards until we hit the beginning of the line.
  128.      */
  129.     for (;;)
  130.     {
  131.         c = ch_back_get();
  132.         if (c == '\n')
  133.         {
  134.             /*
  135.              * This is the newline ending the previous line.
  136.              * We have hit the beginning of the line.
  137.              */
  138.             new_pos = ch_tell() + 1;
  139.             break;
  140.         }
  141.         if (c == EOF)
  142.         {
  143.             /*
  144.              * We have hit the beginning of the file.
  145.              * This must be the first line in the file.
  146.              * This must, of course, be the beginning of the line.
  147.              */
  148.             new_pos = ch_tell();
  149.             break;
  150.         }
  151.     }
  152.  
  153.     /*
  154.      * Now scan forwards from the beginning of this line.
  155.      * We keep discarding "printable lines" (based on screen width)
  156.      * until we reach the curr_pos.
  157.      *
  158.      * {{ This algorithm is pretty inefficient if the lines
  159.      *    are much longer than the screen width, 
  160.      *    but I don't know of any better way. }}
  161.      */
  162.     if (ch_seek(new_pos))
  163.         return (NULL_POSITION);
  164.     loop:
  165.     begin_new_pos = new_pos;
  166.     prewind();
  167.  
  168.     do
  169.     {
  170.         c = ch_forw_get();
  171.         new_pos++;
  172.         if (c == '\n')
  173.             break;
  174.         if (pappend(c))
  175.         {
  176.             /*
  177.              * Got a full printable line, but we haven't
  178.              * reached our curr_pos yet.  Discard the line
  179.              * and start a new one.
  180.              */
  181.             (void) pappend('\0');
  182.             (void) ch_back_get();
  183.             new_pos--;
  184.             goto loop;
  185.         }
  186.     } while (new_pos < curr_pos);
  187.  
  188.     (void) pappend('\0');
  189.  
  190.     return (begin_new_pos);
  191. }
  192.