home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / less3292.zip / input.c < prev    next >
C/C++ Source or Header  |  1996-04-26  |  7KB  |  320 lines

  1. /*
  2.  * Copyright (c) 1984,1985,1989,1994,1995,1996  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. extern int ignore_eoi;
  44. #if HILITE_SEARCH
  45. extern int hilite_search;
  46. extern int size_linebuf;
  47. #endif
  48.  
  49. /*
  50.  * Get the next line.
  51.  * A "current" position is passed and a "new" position is returned.
  52.  * The current position is the position of the first character of
  53.  * a line.  The new position is the position of the first character
  54.  * of the NEXT line.  The line obtained is the line starting at curr_pos.
  55.  */
  56.     public POSITION
  57. forw_line(curr_pos)
  58.     POSITION curr_pos;
  59. {
  60.     POSITION new_pos;
  61.     register int c;
  62.     int blankline;
  63.     int endline;
  64.  
  65.     if (curr_pos == NULL_POSITION)
  66.     {
  67.         null_line();
  68.         return (NULL_POSITION);
  69.     }
  70. #if HILITE_SEARCH
  71.     if (hilite_search == OPT_ONPLUS)
  72.         /*
  73.          * If we are ignoring EOI (command F), only prepare
  74.          * one line ahead, to avoid getting stuck waiting for
  75.          * slow data without displaying the data we already have.
  76.          * If we're not ignoring EOI, we *could* do the same, but
  77.          * for efficiency we prepare several lines ahead at once.
  78.          */
  79.         prep_hilite(curr_pos, curr_pos + 3*size_linebuf, 
  80.                 ignore_eoi ? 1 : -1);
  81. #endif
  82.     if (ch_seek(curr_pos))
  83.     {
  84.         null_line();
  85.         return (NULL_POSITION);
  86.     }
  87.  
  88.     prewind();
  89.     plinenum(curr_pos);
  90.     (void) ch_seek(curr_pos);
  91.  
  92.     c = ch_forw_get();
  93.     if (c == EOI)
  94.     {
  95.         null_line();
  96.         return (NULL_POSITION);
  97.     }
  98.     blankline = (c == '\n' || c == '\r');
  99.  
  100.     for (;;)
  101.     {
  102.         if (ABORT_SIGS())
  103.         {
  104.             null_line();
  105.             return (NULL_POSITION);
  106.         }
  107.         if (c == '\n' || c == EOI)
  108.         {
  109.             /*
  110.              * End of the line.
  111.              */
  112.             new_pos = ch_tell();
  113.             endline = 1;
  114.             break;
  115.         }
  116.  
  117.         /*
  118.          * Append the char to the line and get the next char.
  119.          */
  120.         if (pappend(c, ch_tell()-1))
  121.         {
  122.             /*
  123.              * The char won't fit in the line; the line
  124.              * is too long to print in the screen width.
  125.              * End the line here.
  126.              */
  127.             if (chopline)
  128.             {
  129.                 do
  130.                 {
  131.                     c = ch_forw_get();
  132.                 } while (c != '\n' && c != EOI);
  133.                 new_pos = ch_tell();
  134.                 endline = 1;
  135.             } else
  136.             {
  137.                 new_pos = ch_tell() - 1;
  138.                 endline = 0;
  139.             }
  140.             break;
  141.         }
  142.         c = ch_forw_get();
  143.     }
  144.     pdone(endline);
  145.  
  146.     if (squeeze && blankline)
  147.     {
  148.         /*
  149.          * This line is blank.
  150.          * Skip down to the last contiguous blank line
  151.          * and pretend it is the one which we are returning.
  152.          */
  153.         while ((c = ch_forw_get()) == '\n' || c == '\r')
  154.             if (ABORT_SIGS())
  155.             {
  156.                 null_line();
  157.                 return (NULL_POSITION);
  158.             }
  159.         if (c != EOI)
  160.             (void) ch_back_get();
  161.         new_pos = ch_tell();
  162.     }
  163.  
  164.     return (new_pos);
  165. }
  166.  
  167. /*
  168.  * Get the previous line.
  169.  * A "current" position is passed and a "new" position is returned.
  170.  * The current position is the position of the first character of
  171.  * a line.  The new position is the position of the first character
  172.  * of the PREVIOUS line.  The line obtained is the one starting at new_pos.
  173.  */
  174.     public POSITION
  175. back_line(curr_pos)
  176.     POSITION curr_pos;
  177. {
  178.     POSITION new_pos, begin_new_pos;
  179.     int c;
  180.     int endline;
  181.  
  182.     if (curr_pos == NULL_POSITION || curr_pos <= ch_zero())
  183.     {
  184.         null_line();
  185.         return (NULL_POSITION);
  186.     }
  187. #if HILITE_SEARCH
  188.     if (hilite_search == OPT_ONPLUS)
  189.         prep_hilite((curr_pos < 3*size_linebuf) ? 
  190.                 0 : curr_pos - 3*size_linebuf, curr_pos, -1);
  191. #endif
  192.     if (ch_seek(curr_pos-1))
  193.     {
  194.         null_line();
  195.         return (NULL_POSITION);
  196.     }
  197.  
  198.     if (squeeze)
  199.     {
  200.         /*
  201.          * Find out if the "current" line was blank.
  202.          */
  203.         (void) ch_forw_get();    /* Skip the newline */
  204.         c = ch_forw_get();    /* First char of "current" line */
  205.         (void) ch_back_get();    /* Restore our position */
  206.         (void) ch_back_get();
  207.  
  208.         if (c == '\n' || c == '\r')
  209.         {
  210.             /*
  211.              * The "current" line was blank.
  212.              * Skip over any preceding blank lines,
  213.              * since we skipped them in forw_line().
  214.              */
  215.             while ((c = ch_back_get()) == '\n' || c == '\r')
  216.                 if (ABORT_SIGS())
  217.                 {
  218.                     null_line();
  219.                     return (NULL_POSITION);
  220.                 }
  221.             if (c == EOI)
  222.             {
  223.                 null_line();
  224.                 return (NULL_POSITION);
  225.             }
  226.             (void) ch_forw_get();
  227.         }
  228.     }
  229.  
  230.     /*
  231.      * Scan backwards until we hit the beginning of the line.
  232.      */
  233.     for (;;)
  234.     {
  235.         if (ABORT_SIGS())
  236.         {
  237.             null_line();
  238.             return (NULL_POSITION);
  239.         }
  240.         c = ch_back_get();
  241.         if (c == '\n')
  242.         {
  243.             /*
  244.              * This is the newline ending the previous line.
  245.              * We have hit the beginning of the line.
  246.              */
  247.             new_pos = ch_tell() + 1;
  248.             break;
  249.         }
  250.         if (c == EOI)
  251.         {
  252.             /*
  253.              * We have hit the beginning of the file.
  254.              * This must be the first line in the file.
  255.              * This must, of course, be the beginning of the line.
  256.              */
  257.             new_pos = ch_tell();
  258.             break;
  259.         }
  260.     }
  261.  
  262.     /*
  263.      * Now scan forwards from the beginning of this line.
  264.      * We keep discarding "printable lines" (based on screen width)
  265.      * until we reach the curr_pos.
  266.      *
  267.      * {{ This algorithm is pretty inefficient if the lines
  268.      *    are much longer than the screen width, 
  269.      *    but I don't know of any better way. }}
  270.      */
  271.     if (ch_seek(new_pos))
  272.     {
  273.         null_line();
  274.         return (NULL_POSITION);
  275.     }
  276.     endline = 0;
  277.     loop:
  278.     begin_new_pos = new_pos;
  279.     prewind();
  280.     plinenum(new_pos);
  281.     (void) ch_seek(new_pos);
  282.  
  283.     do
  284.     {
  285.         c = ch_forw_get();
  286.         if (c == EOI || ABORT_SIGS())
  287.         {
  288.             null_line();
  289.             return (NULL_POSITION);
  290.         }
  291.         new_pos++;
  292.         if (c == '\n')
  293.         {
  294.             endline = 1;
  295.             break;
  296.         }
  297.         if (pappend(c, ch_tell()-1))
  298.         {
  299.             /*
  300.              * Got a full printable line, but we haven't
  301.              * reached our curr_pos yet.  Discard the line
  302.              * and start a new one.
  303.              */
  304.             if (chopline)
  305.             {
  306.                 endline = 1;
  307.                 break;
  308.             }
  309.             pdone(0);
  310.             (void) ch_back_get();
  311.             new_pos--;
  312.             goto loop;
  313.         }
  314.     } while (new_pos < curr_pos);
  315.  
  316.     pdone(endline);
  317.  
  318.     return (begin_new_pos);
  319. }
  320.