[BACK]Return to input.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / less

Annotation of src/usr.bin/less/input.c, Revision 1.2

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