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