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