home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 6 File / 06-File.zip / less373.zip / input.c < prev    next >
C/C++ Source or Header  |  2002-01-14  |  7KB  |  344 lines

  1. /*
  2.  * Copyright (C) 1984-2000  Mark Nudelman
  3.  *
  4.  * You may distribute under the terms of either the GNU General Public
  5.  * License or the Less License, as specified in the README file.
  6.  *
  7.  * For more information about less, or for information on how to 
  8.  * contact the author, see the README file.
  9.  */
  10.  
  11.  
  12. /*
  13.  * High level routines dealing with getting lines of input 
  14.  * from the file being viewed.
  15.  *
  16.  * When we speak of "lines" here, we mean PRINTABLE lines;
  17.  * lines processed with respect to the screen width.
  18.  * We use the term "raw line" to refer to lines simply
  19.  * delimited by newlines; not processed with respect to screen width.
  20.  */
  21.  
  22. #include "less.h"
  23.  
  24. extern int squeeze;
  25. extern int chopline;
  26. extern int hshift;
  27. extern int quit_if_one_screen;
  28. extern int sigs;
  29. extern int ignore_eoi;
  30. extern POSITION start_attnpos;
  31. extern POSITION end_attnpos;
  32. #if HILITE_SEARCH
  33. extern int hilite_search;
  34. extern int size_linebuf;
  35. #endif
  36.  
  37. /*
  38.  * Get the next line.
  39.  * A "current" position is passed and a "new" position is returned.
  40.  * The current position is the position of the first character of
  41.  * a line.  The new position is the position of the first character
  42.  * of the NEXT line.  The line obtained is the line starting at curr_pos.
  43.  */
  44.     public POSITION
  45. forw_line(curr_pos)
  46.     POSITION curr_pos;
  47. {
  48.     POSITION new_pos;
  49.     register int c;
  50.     int blankline;
  51.     int endline;
  52.  
  53.     if (curr_pos == NULL_POSITION)
  54.     {
  55.         null_line();
  56.         return (NULL_POSITION);
  57.     }
  58. #if HILITE_SEARCH
  59.     if (hilite_search == OPT_ONPLUS)
  60.         /*
  61.          * If we are ignoring EOI (command F), only prepare
  62.          * one line ahead, to avoid getting stuck waiting for
  63.          * slow data without displaying the data we already have.
  64.          * If we're not ignoring EOI, we *could* do the same, but
  65.          * for efficiency we prepare several lines ahead at once.
  66.          */
  67.         prep_hilite(curr_pos, curr_pos + 3*size_linebuf, 
  68.                 ignore_eoi ? 1 : -1);
  69. #endif
  70.     if (ch_seek(curr_pos))
  71.     {
  72.         null_line();
  73.         return (NULL_POSITION);
  74.     }
  75.  
  76.     prewind();
  77.     plinenum(curr_pos);
  78.     (void) ch_seek(curr_pos);
  79.  
  80.     c = ch_forw_get();
  81.     if (c == EOI)
  82.     {
  83.         null_line();
  84.         return (NULL_POSITION);
  85.     }
  86.     blankline = (c == '\n' || c == '\r');
  87.  
  88.     for (;;)
  89.     {
  90.         if (ABORT_SIGS())
  91.         {
  92.             null_line();
  93.             return (NULL_POSITION);
  94.         }
  95.         if (c == '\n' || c == EOI)
  96.         {
  97.             /*
  98.              * End of the line.
  99.              */
  100.             new_pos = ch_tell();
  101.             endline = TRUE;
  102.             break;
  103.         }
  104.  
  105.         /*
  106.          * Append the char to the line and get the next char.
  107.          */
  108.         if (pappend(c, ch_tell()-1))
  109.         {
  110.             /*
  111.              * The char won't fit in the line; the line
  112.              * is too long to print in the screen width.
  113.              * End the line here.
  114.              */
  115.             if (chopline || hshift > 0)
  116.             {
  117.                 do
  118.                 {
  119.                     c = ch_forw_get();
  120.                 } while (c != '\n' && c != EOI);
  121.                 new_pos = ch_tell();
  122.                 endline = TRUE;
  123.                 quit_if_one_screen = FALSE;
  124.             } else
  125.             {
  126.                 new_pos = ch_tell() - 1;
  127.                 endline = FALSE;
  128.             }
  129.             break;
  130.         }
  131.         c = ch_forw_get();
  132.     }
  133.     pdone(endline);
  134.  
  135.     if (squeeze && blankline)
  136.     {
  137.         /*
  138.          * This line is blank.
  139.          * Skip down to the last contiguous blank line
  140.          * and pretend it is the one which we are returning.
  141.          */
  142.         while ((c = ch_forw_get()) == '\n' || c == '\r')
  143.             if (ABORT_SIGS())
  144.             {
  145.                 null_line();
  146.                 return (NULL_POSITION);
  147.             }
  148.         if (c != EOI)
  149.             (void) ch_back_get();
  150.         new_pos = ch_tell();
  151.     }
  152.  
  153.     return (new_pos);
  154. }
  155.  
  156. /*
  157.  * Get the previous line.
  158.  * A "current" position is passed and a "new" position is returned.
  159.  * The current position is the position of the first character of
  160.  * a line.  The new position is the position of the first character
  161.  * of the PREVIOUS line.  The line obtained is the one starting at new_pos.
  162.  */
  163.     public POSITION
  164. back_line(curr_pos)
  165.     POSITION curr_pos;
  166. {
  167.     POSITION new_pos, begin_new_pos;
  168.     int c;
  169.     int endline;
  170.  
  171.     if (curr_pos == NULL_POSITION || curr_pos <= ch_zero())
  172.     {
  173.         null_line();
  174.         return (NULL_POSITION);
  175.     }
  176. #if HILITE_SEARCH
  177.     if (hilite_search == OPT_ONPLUS)
  178.         prep_hilite((curr_pos < 3*size_linebuf) ? 
  179.                 0 : curr_pos - 3*size_linebuf, curr_pos, -1);
  180. #endif
  181.     if (ch_seek(curr_pos-1))
  182.     {
  183.         null_line();
  184.         return (NULL_POSITION);
  185.     }
  186.  
  187.     if (squeeze)
  188.     {
  189.         /*
  190.          * Find out if the "current" line was blank.
  191.          */
  192.         (void) ch_forw_get();    /* Skip the newline */
  193.         c = ch_forw_get();    /* First char of "current" line */
  194.         (void) ch_back_get();    /* Restore our position */
  195.         (void) ch_back_get();
  196.  
  197.         if (c == '\n' || c == '\r')
  198.         {
  199.             /*
  200.              * The "current" line was blank.
  201.              * Skip over any preceding blank lines,
  202.              * since we skipped them in forw_line().
  203.              */
  204.             while ((c = ch_back_get()) == '\n' || c == '\r')
  205.                 if (ABORT_SIGS())
  206.                 {
  207.                     null_line();
  208.                     return (NULL_POSITION);
  209.                 }
  210.             if (c == EOI)
  211.             {
  212.                 null_line();
  213.                 return (NULL_POSITION);
  214.             }
  215.             (void) ch_forw_get();
  216.         }
  217.     }
  218.  
  219.     /*
  220.      * Scan backwards until we hit the beginning of the line.
  221.      */
  222.     for (;;)
  223.     {
  224.         if (ABORT_SIGS())
  225.         {
  226.             null_line();
  227.             return (NULL_POSITION);
  228.         }
  229.         c = ch_back_get();
  230.         if (c == '\n')
  231.         {
  232.             /*
  233.              * This is the newline ending the previous line.
  234.              * We have hit the beginning of the line.
  235.              */
  236.             new_pos = ch_tell() + 1;
  237.             break;
  238.         }
  239.         if (c == EOI)
  240.         {
  241.             /*
  242.              * We have hit the beginning of the file.
  243.              * This must be the first line in the file.
  244.              * This must, of course, be the beginning of the line.
  245.              */
  246.             new_pos = ch_tell();
  247.             break;
  248.         }
  249.     }
  250.  
  251.     /*
  252.      * Now scan forwards from the beginning of this line.
  253.      * We keep discarding "printable lines" (based on screen width)
  254.      * until we reach the curr_pos.
  255.      *
  256.      * {{ This algorithm is pretty inefficient if the lines
  257.      *    are much longer than the screen width, 
  258.      *    but I don't know of any better way. }}
  259.      */
  260.     if (ch_seek(new_pos))
  261.     {
  262.         null_line();
  263.         return (NULL_POSITION);
  264.     }
  265.     endline = FALSE;
  266.     loop:
  267.     begin_new_pos = new_pos;
  268.     prewind();
  269.     plinenum(new_pos);
  270.     (void) ch_seek(new_pos);
  271.  
  272.     do
  273.     {
  274.         c = ch_forw_get();
  275.         if (c == EOI || ABORT_SIGS())
  276.         {
  277.             null_line();
  278.             return (NULL_POSITION);
  279.         }
  280.         new_pos++;
  281.         if (c == '\n')
  282.         {
  283.             endline = TRUE;
  284.             break;
  285.         }
  286.         if (pappend(c, ch_tell()-1))
  287.         {
  288.             /*
  289.              * Got a full printable line, but we haven't
  290.              * reached our curr_pos yet.  Discard the line
  291.              * and start a new one.
  292.              */
  293.             if (chopline || hshift > 0)
  294.             {
  295.                 endline = TRUE;
  296.                 quit_if_one_screen = FALSE;
  297.                 break;
  298.             }
  299.             pdone(0);
  300.             (void) ch_back_get();
  301.             new_pos--;
  302.             goto loop;
  303.         }
  304.     } while (new_pos < curr_pos);
  305.  
  306.     pdone(endline);
  307.  
  308.     return (begin_new_pos);
  309. }
  310.  
  311. /*
  312.  * Set attnpos.
  313.  */
  314.     public void
  315. set_attnpos(pos)
  316.     POSITION pos;
  317. {
  318.     int c;
  319.  
  320.     if (pos != NULL_POSITION)
  321.     {
  322.         if (ch_seek(pos))
  323.             return;
  324.         for (;;)
  325.         {
  326.             c = ch_forw_get();
  327.             if (c == EOI)
  328.                 return;
  329.             if (c != '\n' && c != '\r')
  330.                 break;
  331.             pos++;
  332.         }
  333.     }
  334.     start_attnpos = pos;
  335.     for (;;)
  336.     {
  337.         c = ch_forw_get();
  338.         pos++;
  339.         if (c == EOI || c == '\n' || c == '\r')
  340.             break;
  341.     }
  342.     end_attnpos = pos;
  343. }
  344.