home *** CD-ROM | disk | FTP | other *** search
/ The Pier Shareware 6 / The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso / 036 / less232.zip / INPUT.C < prev    next >
C/C++ Source or Header  |  1994-08-26  |  6KB  |  289 lines

  1. /*
  2.  * Copyright (c) 1984,1985,1989,1994  Mark Nudelman
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice in the documentation and/or other materials provided with 
  12.  *    the distribution.
  13.  *
  14.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
  15.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  17.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
  18.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
  19.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
  20.  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
  21.  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  22.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
  23.  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 
  24.  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25.  */
  26.  
  27.  
  28. /*
  29.  * High level routines dealing with getting lines of input 
  30.  * from the file being viewed.
  31.  *
  32.  * When we speak of "lines" here, we mean PRINTABLE lines;
  33.  * lines processed with respect to the screen width.
  34.  * We use the term "raw line" to refer to lines simply
  35.  * delimited by newlines; not processed with respect to screen width.
  36.  */
  37.  
  38. #include "less.h"
  39.  
  40. extern int squeeze;
  41. extern int chopline;
  42. extern int sigs;
  43.  
  44. /*
  45.  * Get the next line.
  46.  * A "current" position is passed and a "new" position is returned.
  47.  * The current position is the position of the first character of
  48.  * a line.  The new position is the position of the first character
  49.  * of the NEXT line.  The line obtained is the line starting at curr_pos.
  50.  */
  51.     public POSITION
  52. forw_line(curr_pos)
  53.     POSITION curr_pos;
  54. {
  55.     POSITION new_pos;
  56.     register int c;
  57.     int blankline;
  58.     int endline;
  59.  
  60.     if (curr_pos == NULL_POSITION || ch_seek(curr_pos))
  61.     {
  62.         null_line();
  63.         return (NULL_POSITION);
  64.     }
  65.  
  66.     prewind();
  67.     plinenum(curr_pos);
  68.     (void) ch_seek(curr_pos);
  69.  
  70.     c = ch_forw_get();
  71.     if (c == EOI)
  72.     {
  73.         null_line();
  74.         return (NULL_POSITION);
  75.     }
  76.     blankline = (c == '\n' || c == '\r');
  77.  
  78.     for (;;)
  79.     {
  80.         if (ABORT_SIGS())
  81.         {
  82.             null_line();
  83.             return (NULL_POSITION);
  84.         }
  85.         if (c == '\n' || c == EOI)
  86.         {
  87.             /*
  88.              * End of the line.
  89.              */
  90.             new_pos = ch_tell();
  91.             endline = 1;
  92.             break;
  93.         }
  94.  
  95.         /*
  96.          * Append the char to the line and get the next char.
  97.          */
  98.         if (pappend(c))
  99.         {
  100.             /*
  101.              * The char won't fit in the line; the line
  102.              * is too long to print in the screen width.
  103.              * End the line here.
  104.              */
  105.             if (chopline)
  106.             {
  107.                 do
  108.                 {
  109.                     c = ch_forw_get();
  110.                 } while (c != '\n' && c != EOI);
  111.                 new_pos = ch_tell();
  112.                 endline = 1;
  113.             } else
  114.             {
  115.                 new_pos = ch_tell() - 1;
  116.                 endline = 0;
  117.             }
  118.             break;
  119.         }
  120.         c = ch_forw_get();
  121.     }
  122.     pdone(endline);
  123.  
  124.     if (squeeze && blankline)
  125.     {
  126.         /*
  127.          * This line is blank.
  128.          * Skip down to the last contiguous blank line
  129.          * and pretend it is the one which we are returning.
  130.          */
  131.         while ((c = ch_forw_get()) == '\n' || c == '\r')
  132.             if (ABORT_SIGS())
  133.             {
  134.                 null_line();
  135.                 return (NULL_POSITION);
  136.             }
  137.         if (c != EOI)
  138.             (void) ch_back_get();
  139.         new_pos = ch_tell();
  140.     }
  141.  
  142.     return (new_pos);
  143. }
  144.  
  145. /*
  146.  * Get the previous line.
  147.  * A "current" position is passed and a "new" position is returned.
  148.  * The current position is the position of the first character of
  149.  * a line.  The new position is the position of the first character
  150.  * of the PREVIOUS line.  The line obtained is the one starting at new_pos.
  151.  */
  152.     public POSITION
  153. back_line(curr_pos)
  154.     POSITION curr_pos;
  155. {
  156.     POSITION new_pos, begin_new_pos;
  157.     int c;
  158.     int endline;
  159.  
  160.     if (curr_pos == NULL_POSITION || curr_pos <= ch_zero() ||
  161.         ch_seek(curr_pos-1))
  162.     {
  163.         null_line();
  164.         return (NULL_POSITION);
  165.     }
  166.  
  167.     if (squeeze)
  168.     {
  169.         /*
  170.          * Find out if the "current" line was blank.
  171.          */
  172.         (void) ch_forw_get();    /* Skip the newline */
  173.         c = ch_forw_get();    /* First char of "current" line */
  174.         (void) ch_back_get();    /* Restore our position */
  175.         (void) ch_back_get();
  176.  
  177.         if (c == '\n' || c == '\r')
  178.         {
  179.             /*
  180.              * The "current" line was blank.
  181.              * Skip over any preceding blank lines,
  182.              * since we skipped them in forw_line().
  183.              */
  184.             while ((c = ch_back_get()) == '\n' || c == '\r')
  185.                 if (ABORT_SIGS())
  186.                 {
  187.                     null_line();
  188.                     return (NULL_POSITION);
  189.                 }
  190.             if (c == EOI)
  191.             {
  192.                 null_line();
  193.                 return (NULL_POSITION);
  194.             }
  195.             (void) ch_forw_get();
  196.         }
  197.     }
  198.  
  199.     /*
  200.      * Scan backwards until we hit the beginning of the line.
  201.      */
  202.     for (;;)
  203.     {
  204.         if (ABORT_SIGS())
  205.         {
  206.             null_line();
  207.             return (NULL_POSITION);
  208.         }
  209.         c = ch_back_get();
  210.         if (c == '\n')
  211.         {
  212.             /*
  213.              * This is the newline ending the previous line.
  214.              * We have hit the beginning of the line.
  215.              */
  216.             new_pos = ch_tell() + 1;
  217.             break;
  218.         }
  219.         if (c == EOI)
  220.         {
  221.             /*
  222.              * We have hit the beginning of the file.
  223.              * This must be the first line in the file.
  224.              * This must, of course, be the beginning of the line.
  225.              */
  226.             new_pos = ch_tell();
  227.             break;
  228.         }
  229.     }
  230.  
  231.     /*
  232.      * Now scan forwards from the beginning of this line.
  233.      * We keep discarding "printable lines" (based on screen width)
  234.      * until we reach the curr_pos.
  235.      *
  236.      * {{ This algorithm is pretty inefficient if the lines
  237.      *    are much longer than the screen width, 
  238.      *    but I don't know of any better way. }}
  239.      */
  240.     if (ch_seek(new_pos))
  241.     {
  242.         null_line();
  243.         return (NULL_POSITION);
  244.     }
  245.     endline = 0;
  246.     loop:
  247.     begin_new_pos = new_pos;
  248.     prewind();
  249.     plinenum(new_pos);
  250.     (void) ch_seek(new_pos);
  251.  
  252.     do
  253.     {
  254.         c = ch_forw_get();
  255.         if (c == EOI || ABORT_SIGS())
  256.         {
  257.             null_line();
  258.             return (NULL_POSITION);
  259.         }
  260.         new_pos++;
  261.         if (c == '\n')
  262.         {
  263.             endline = 1;
  264.             break;
  265.         }
  266.         if (pappend(c))
  267.         {
  268.             /*
  269.              * Got a full printable line, but we haven't
  270.              * reached our curr_pos yet.  Discard the line
  271.              * and start a new one.
  272.              */
  273.             if (chopline)
  274.             {
  275.                 endline = 1;
  276.                 break;
  277.             }
  278.             pdone(0);
  279.             (void) ch_back_get();
  280.             new_pos--;
  281.             goto loop;
  282.         }
  283.     } while (new_pos < curr_pos);
  284.  
  285.     pdone(endline);
  286.  
  287.     return (begin_new_pos);
  288. }
  289.