home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / more / input.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-03  |  6.1 KB  |  242 lines

  1. /*
  2.  * Copyright (c) 1988 Mark Nudleman
  3.  * Copyright (c) 1988 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. All advertising materials mentioning features or use of this software
  15.  *    must display the following acknowledgement:
  16.  *    This product includes software developed by the University of
  17.  *    California, Berkeley and its contributors.
  18.  * 4. Neither the name of the University nor the names of its contributors
  19.  *    may be used to endorse or promote products derived from this software
  20.  *    without specific prior written permission.
  21.  *
  22.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32.  * SUCH DAMAGE.
  33.  */
  34.  
  35. #ifndef lint
  36. static char sccsid[] = "@(#)input.c    5.4 (Berkeley) 6/1/90";
  37. #endif /* not lint */
  38.  
  39. /*
  40.  * High level routines dealing with getting lines of input 
  41.  * from the file being viewed.
  42.  *
  43.  * When we speak of "lines" here, we mean PRINTABLE lines;
  44.  * lines processed with respect to the screen width.
  45.  * We use the term "raw line" to refer to lines simply
  46.  * delimited by newlines; not processed with respect to screen width.
  47.  */
  48.  
  49. #include <sys/types.h>
  50. #include <less.h>
  51.  
  52. extern int squeeze;
  53. extern int sigs;
  54. extern char *line;
  55.  
  56. off_t ch_tell();
  57.  
  58. /*
  59.  * Get the next line.
  60.  * A "current" position is passed and a "new" position is returned.
  61.  * The current position is the position of the first character of
  62.  * a line.  The new position is the position of the first character
  63.  * of the NEXT line.  The line obtained is the line starting at curr_pos.
  64.  */
  65. off_t
  66. forw_line(curr_pos)
  67.     off_t curr_pos;
  68. {
  69.     off_t new_pos;
  70.     register int c;
  71.  
  72.     if (curr_pos == NULL_POSITION || ch_seek(curr_pos))
  73.         return (NULL_POSITION);
  74.  
  75.     c = ch_forw_get();
  76.     if (c == EOI)
  77.         return (NULL_POSITION);
  78.  
  79.     prewind();
  80.     for (;;)
  81.     {
  82.         if (sigs)
  83.             return (NULL_POSITION);
  84.         if (c == '\n' || c == EOI)
  85.         {
  86.             /*
  87.              * End of the line.
  88.              */
  89.             new_pos = ch_tell();
  90.             break;
  91.         }
  92.  
  93.         /*
  94.          * Append the char to the line and get the next char.
  95.          */
  96.         if (pappend(c))
  97.         {
  98.             /*
  99.              * The char won't fit in the line; the line
  100.              * is too long to print in the screen width.
  101.              * End the line here.
  102.              */
  103.             new_pos = ch_tell() - 1;
  104.             break;
  105.         }
  106.         c = ch_forw_get();
  107.     }
  108.     (void) pappend('\0');
  109.  
  110.     if (squeeze && *line == '\0')
  111.     {
  112.         /*
  113.          * This line is blank.
  114.          * Skip down to the last contiguous blank line
  115.          * and pretend it is the one which we are returning.
  116.          */
  117.         while ((c = ch_forw_get()) == '\n')
  118.             if (sigs)
  119.                 return (NULL_POSITION);
  120.         if (c != EOI)
  121.             (void) ch_back_get();
  122.         new_pos = ch_tell();
  123.     }
  124.  
  125.     return (new_pos);
  126. }
  127.  
  128. /*
  129.  * Get the previous line.
  130.  * A "current" position is passed and a "new" position is returned.
  131.  * The current position is the position of the first character of
  132.  * a line.  The new position is the position of the first character
  133.  * of the PREVIOUS line.  The line obtained is the one starting at new_pos.
  134.  */
  135. off_t
  136. back_line(curr_pos)
  137.     off_t curr_pos;
  138. {
  139.     off_t new_pos, begin_new_pos;
  140.     int c;
  141.  
  142.     if (curr_pos == NULL_POSITION || curr_pos <= (off_t)0 ||
  143.         ch_seek(curr_pos-1))
  144.         return (NULL_POSITION);
  145.  
  146.     if (squeeze)
  147.     {
  148.         /*
  149.          * Find out if the "current" line was blank.
  150.          */
  151.         (void) ch_forw_get();    /* Skip the newline */
  152.         c = ch_forw_get();    /* First char of "current" line */
  153.         (void) ch_back_get();    /* Restore our position */
  154.         (void) ch_back_get();
  155.  
  156.         if (c == '\n')
  157.         {
  158.             /*
  159.              * The "current" line was blank.
  160.              * Skip over any preceeding blank lines,
  161.              * since we skipped them in forw_line().
  162.              */
  163.             while ((c = ch_back_get()) == '\n')
  164.                 if (sigs)
  165.                     return (NULL_POSITION);
  166.             if (c == EOI)
  167.                 return (NULL_POSITION);
  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.             return (NULL_POSITION);
  179.         c = ch_back_get();
  180.         if (c == '\n')
  181.         {
  182.             /*
  183.              * This is the newline ending the previous line.
  184.              * We have hit the beginning of the line.
  185.              */
  186.             new_pos = ch_tell() + 1;
  187.             break;
  188.         }
  189.         if (c == EOI)
  190.         {
  191.             /*
  192.              * We have hit the beginning of the file.
  193.              * This must be the first line in the file.
  194.              * This must, of course, be the beginning of the line.
  195.              */
  196.             new_pos = ch_tell();
  197.             break;
  198.         }
  199.     }
  200.  
  201.     /*
  202.      * Now scan forwards from the beginning of this line.
  203.      * We keep discarding "printable lines" (based on screen width)
  204.      * until we reach the curr_pos.
  205.      *
  206.      * {{ This algorithm is pretty inefficient if the lines
  207.      *    are much longer than the screen width, 
  208.      *    but I don't know of any better way. }}
  209.      */
  210.     if (ch_seek(new_pos))
  211.         return (NULL_POSITION);
  212.     loop:
  213.     begin_new_pos = new_pos;
  214.     prewind();
  215.  
  216.     do
  217.     {
  218.         c = ch_forw_get();
  219.         if (c == EOI || sigs)
  220.             return (NULL_POSITION);
  221.         new_pos++;
  222.         if (c == '\n')
  223.             break;
  224.         if (pappend(c))
  225.         {
  226.             /*
  227.              * Got a full printable line, but we haven't
  228.              * reached our curr_pos yet.  Discard the line
  229.              * and start a new one.
  230.              */
  231.             (void) pappend('\0');
  232.             (void) ch_back_get();
  233.             new_pos--;
  234.             goto loop;
  235.         }
  236.     } while (new_pos < curr_pos);
  237.  
  238.     (void) pappend('\0');
  239.  
  240.     return (begin_new_pos);
  241. }
  242.