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