[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.6

1.1       etheisen    1: /*
1.5       shadchin    2:  * Copyright (C) 1984-2011  Mark Nudelman
1.1       etheisen    3:  *
1.4       millert     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.
1.1       etheisen    6:  *
1.4       millert     7:  * For more information about less, or for information on how to
                      8:  * contact the author, see the README file.
1.1       etheisen    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;
1.4       millert    26: extern int hshift;
                     27: extern int quit_if_one_screen;
1.6     ! millert    28: extern volatile sig_atomic_t sigs;
1.4       millert    29: extern int ignore_eoi;
1.5       shadchin   30: extern int status_col;
1.4       millert    31: extern POSITION start_attnpos;
                     32: extern POSITION end_attnpos;
1.1       etheisen   33: #if HILITE_SEARCH
                     34: extern int hilite_search;
                     35: extern int size_linebuf;
                     36: #endif
                     37:
                     38: /*
                     39:  * Get the next line.
                     40:  * A "current" position is passed and a "new" position is returned.
                     41:  * The current position is the position of the first character of
                     42:  * a line.  The new position is the position of the first character
                     43:  * of the NEXT line.  The line obtained is the line starting at curr_pos.
                     44:  */
                     45:        public POSITION
                     46: forw_line(curr_pos)
                     47:        POSITION curr_pos;
                     48: {
1.5       shadchin   49:        POSITION base_pos;
1.1       etheisen   50:        POSITION new_pos;
1.4       millert    51:        register int c;
1.1       etheisen   52:        int blankline;
                     53:        int endline;
1.5       shadchin   54:        int backchars;
1.1       etheisen   55:
1.5       shadchin   56: get_forw_line:
1.1       etheisen   57:        if (curr_pos == NULL_POSITION)
                     58:        {
                     59:                null_line();
                     60:                return (NULL_POSITION);
                     61:        }
                     62: #if HILITE_SEARCH
1.5       shadchin   63:        if (hilite_search == OPT_ONPLUS || is_filtering() || status_col)
1.4       millert    64:                /*
                     65:                 * If we are ignoring EOI (command F), only prepare
                     66:                 * one line ahead, to avoid getting stuck waiting for
                     67:                 * slow data without displaying the data we already have.
                     68:                 * If we're not ignoring EOI, we *could* do the same, but
                     69:                 * for efficiency we prepare several lines ahead at once.
                     70:                 */
                     71:                prep_hilite(curr_pos, curr_pos + 3*size_linebuf,
                     72:                                ignore_eoi ? 1 : -1);
1.1       etheisen   73: #endif
                     74:        if (ch_seek(curr_pos))
                     75:        {
                     76:                null_line();
                     77:                return (NULL_POSITION);
                     78:        }
                     79:
1.5       shadchin   80:        /*
                     81:         * Step back to the beginning of the line.
                     82:         */
                     83:        base_pos = curr_pos;
                     84:        for (;;)
                     85:        {
                     86:                if (ABORT_SIGS())
                     87:                {
                     88:                        null_line();
                     89:                        return (NULL_POSITION);
                     90:                }
                     91:                c = ch_back_get();
                     92:                if (c == EOI)
                     93:                        break;
                     94:                if (c == '\n')
                     95:                {
                     96:                        (void) ch_forw_get();
                     97:                        break;
                     98:                }
                     99:                --base_pos;
                    100:        }
                    101:
                    102:        /*
                    103:         * Read forward again to the position we should start at.
                    104:         */
                    105:        prewind();
                    106:        plinenum(base_pos);
                    107:        (void) ch_seek(base_pos);
                    108:        new_pos = base_pos;
                    109:        while (new_pos < curr_pos)
                    110:        {
                    111:                if (ABORT_SIGS())
                    112:                {
                    113:                        null_line();
                    114:                        return (NULL_POSITION);
                    115:                }
                    116:                c = ch_forw_get();
                    117:                backchars = pappend(c, new_pos);
                    118:                new_pos++;
                    119:                if (backchars > 0)
                    120:                {
                    121:                        pshift_all();
                    122:                        new_pos -= backchars;
                    123:                        while (--backchars >= 0)
                    124:                                (void) ch_back_get();
                    125:                }
                    126:        }
                    127:        (void) pflushmbc();
                    128:        pshift_all();
1.1       etheisen  129:
1.5       shadchin  130:        /*
                    131:         * Read the first character to display.
                    132:         */
1.1       etheisen  133:        c = ch_forw_get();
                    134:        if (c == EOI)
                    135:        {
                    136:                null_line();
                    137:                return (NULL_POSITION);
                    138:        }
                    139:        blankline = (c == '\n' || c == '\r');
                    140:
1.5       shadchin  141:        /*
                    142:         * Read each character in the line and append to the line buffer.
                    143:         */
1.1       etheisen  144:        for (;;)
                    145:        {
                    146:                if (ABORT_SIGS())
                    147:                {
                    148:                        null_line();
                    149:                        return (NULL_POSITION);
                    150:                }
                    151:                if (c == '\n' || c == EOI)
                    152:                {
                    153:                        /*
                    154:                         * End of the line.
                    155:                         */
1.5       shadchin  156:                        backchars = pflushmbc();
1.1       etheisen  157:                        new_pos = ch_tell();
1.5       shadchin  158:                        if (backchars > 0 && !chopline && hshift == 0)
                    159:                        {
                    160:                                new_pos -= backchars + 1;
                    161:                                endline = FALSE;
                    162:                        } else
                    163:                                endline = TRUE;
1.1       etheisen  164:                        break;
                    165:                }
1.5       shadchin  166:                if (c != '\r')
                    167:                        blankline = 0;
1.1       etheisen  168:
                    169:                /*
                    170:                 * Append the char to the line and get the next char.
                    171:                 */
1.5       shadchin  172:                backchars = pappend(c, ch_tell()-1);
                    173:                if (backchars > 0)
1.1       etheisen  174:                {
                    175:                        /*
                    176:                         * The char won't fit in the line; the line
                    177:                         * is too long to print in the screen width.
                    178:                         * End the line here.
                    179:                         */
1.4       millert   180:                        if (chopline || hshift > 0)
1.1       etheisen  181:                        {
                    182:                                do
                    183:                                {
1.5       shadchin  184:                                        if (ABORT_SIGS())
                    185:                                        {
                    186:                                                null_line();
                    187:                                                return (NULL_POSITION);
                    188:                                        }
1.1       etheisen  189:                                        c = ch_forw_get();
                    190:                                } while (c != '\n' && c != EOI);
                    191:                                new_pos = ch_tell();
1.4       millert   192:                                endline = TRUE;
                    193:                                quit_if_one_screen = FALSE;
1.1       etheisen  194:                        } else
                    195:                        {
1.5       shadchin  196:                                new_pos = ch_tell() - backchars;
1.4       millert   197:                                endline = FALSE;
1.1       etheisen  198:                        }
                    199:                        break;
                    200:                }
                    201:                c = ch_forw_get();
                    202:        }
1.5       shadchin  203:
                    204:        pdone(endline, 1);
                    205:
                    206: #if HILITE_SEARCH
                    207:        if (is_filtered(base_pos))
                    208:        {
                    209:                /*
                    210:                 * We don't want to display this line.
                    211:                 * Get the next line.
                    212:                 */
                    213:                curr_pos = new_pos;
                    214:                goto get_forw_line;
                    215:        }
                    216:
                    217:        if (status_col && is_hilited(base_pos, ch_tell()-1, 1, NULL))
                    218:                set_status_col('*');
                    219: #endif
1.1       etheisen  220:
                    221:        if (squeeze && blankline)
                    222:        {
                    223:                /*
                    224:                 * This line is blank.
                    225:                 * Skip down to the last contiguous blank line
                    226:                 * and pretend it is the one which we are returning.
                    227:                 */
                    228:                while ((c = ch_forw_get()) == '\n' || c == '\r')
                    229:                        if (ABORT_SIGS())
                    230:                        {
                    231:                                null_line();
                    232:                                return (NULL_POSITION);
                    233:                        }
                    234:                if (c != EOI)
                    235:                        (void) ch_back_get();
                    236:                new_pos = ch_tell();
                    237:        }
                    238:
                    239:        return (new_pos);
                    240: }
                    241:
                    242: /*
                    243:  * Get the previous line.
                    244:  * A "current" position is passed and a "new" position is returned.
                    245:  * The current position is the position of the first character of
                    246:  * a line.  The new position is the position of the first character
                    247:  * of the PREVIOUS line.  The line obtained is the one starting at new_pos.
                    248:  */
                    249:        public POSITION
                    250: back_line(curr_pos)
                    251:        POSITION curr_pos;
                    252: {
1.5       shadchin  253:        POSITION new_pos, begin_new_pos, base_pos;
1.1       etheisen  254:        int c;
                    255:        int endline;
1.5       shadchin  256:        int backchars;
1.1       etheisen  257:
1.5       shadchin  258: get_back_line:
1.1       etheisen  259:        if (curr_pos == NULL_POSITION || curr_pos <= ch_zero())
                    260:        {
                    261:                null_line();
                    262:                return (NULL_POSITION);
                    263:        }
                    264: #if HILITE_SEARCH
1.5       shadchin  265:        if (hilite_search == OPT_ONPLUS || is_filtering() || status_col)
1.1       etheisen  266:                prep_hilite((curr_pos < 3*size_linebuf) ?
1.4       millert   267:                                0 : curr_pos - 3*size_linebuf, curr_pos, -1);
1.1       etheisen  268: #endif
                    269:        if (ch_seek(curr_pos-1))
                    270:        {
                    271:                null_line();
                    272:                return (NULL_POSITION);
                    273:        }
                    274:
                    275:        if (squeeze)
                    276:        {
                    277:                /*
                    278:                 * Find out if the "current" line was blank.
                    279:                 */
1.5       shadchin  280:                (void) ch_forw_get();    /* Skip the newline */
                    281:                c = ch_forw_get();       /* First char of "current" line */
                    282:                (void) ch_back_get();    /* Restore our position */
1.1       etheisen  283:                (void) ch_back_get();
                    284:
                    285:                if (c == '\n' || c == '\r')
                    286:                {
                    287:                        /*
                    288:                         * The "current" line was blank.
                    289:                         * Skip over any preceding blank lines,
                    290:                         * since we skipped them in forw_line().
                    291:                         */
                    292:                        while ((c = ch_back_get()) == '\n' || c == '\r')
                    293:                                if (ABORT_SIGS())
                    294:                                {
                    295:                                        null_line();
                    296:                                        return (NULL_POSITION);
                    297:                                }
                    298:                        if (c == EOI)
                    299:                        {
                    300:                                null_line();
                    301:                                return (NULL_POSITION);
                    302:                        }
                    303:                        (void) ch_forw_get();
                    304:                }
                    305:        }
                    306:
                    307:        /*
                    308:         * Scan backwards until we hit the beginning of the line.
                    309:         */
                    310:        for (;;)
                    311:        {
                    312:                if (ABORT_SIGS())
                    313:                {
                    314:                        null_line();
                    315:                        return (NULL_POSITION);
                    316:                }
                    317:                c = ch_back_get();
                    318:                if (c == '\n')
                    319:                {
                    320:                        /*
                    321:                         * This is the newline ending the previous line.
                    322:                         * We have hit the beginning of the line.
                    323:                         */
1.5       shadchin  324:                        base_pos = ch_tell() + 1;
1.1       etheisen  325:                        break;
                    326:                }
                    327:                if (c == EOI)
                    328:                {
                    329:                        /*
                    330:                         * We have hit the beginning of the file.
                    331:                         * This must be the first line in the file.
                    332:                         * This must, of course, be the beginning of the line.
                    333:                         */
1.5       shadchin  334:                        base_pos = ch_tell();
1.1       etheisen  335:                        break;
                    336:                }
                    337:        }
                    338:
                    339:        /*
                    340:         * Now scan forwards from the beginning of this line.
                    341:         * We keep discarding "printable lines" (based on screen width)
                    342:         * until we reach the curr_pos.
                    343:         *
                    344:         * {{ This algorithm is pretty inefficient if the lines
                    345:         *    are much longer than the screen width,
                    346:         *    but I don't know of any better way. }}
                    347:         */
1.5       shadchin  348:        new_pos = base_pos;
1.1       etheisen  349:        if (ch_seek(new_pos))
                    350:        {
                    351:                null_line();
                    352:                return (NULL_POSITION);
                    353:        }
1.4       millert   354:        endline = FALSE;
1.5       shadchin  355:        prewind();
                    356:        plinenum(new_pos);
1.1       etheisen  357:     loop:
                    358:        begin_new_pos = new_pos;
                    359:        (void) ch_seek(new_pos);
                    360:
                    361:        do
                    362:        {
                    363:                c = ch_forw_get();
                    364:                if (c == EOI || ABORT_SIGS())
                    365:                {
                    366:                        null_line();
                    367:                        return (NULL_POSITION);
                    368:                }
                    369:                new_pos++;
                    370:                if (c == '\n')
                    371:                {
1.5       shadchin  372:                        backchars = pflushmbc();
                    373:                        if (backchars > 0 && !chopline && hshift == 0)
                    374:                        {
                    375:                                backchars++;
                    376:                                goto shift;
                    377:                        }
1.4       millert   378:                        endline = TRUE;
1.1       etheisen  379:                        break;
                    380:                }
1.5       shadchin  381:                backchars = pappend(c, ch_tell()-1);
                    382:                if (backchars > 0)
1.1       etheisen  383:                {
                    384:                        /*
                    385:                         * Got a full printable line, but we haven't
                    386:                         * reached our curr_pos yet.  Discard the line
                    387:                         * and start a new one.
                    388:                         */
1.4       millert   389:                        if (chopline || hshift > 0)
1.1       etheisen  390:                        {
1.4       millert   391:                                endline = TRUE;
                    392:                                quit_if_one_screen = FALSE;
1.1       etheisen  393:                                break;
                    394:                        }
1.5       shadchin  395:                shift:
                    396:                        pshift_all();
                    397:                        while (backchars-- > 0)
                    398:                        {
                    399:                                (void) ch_back_get();
                    400:                                new_pos--;
                    401:                        }
1.1       etheisen  402:                        goto loop;
                    403:                }
                    404:        } while (new_pos < curr_pos);
                    405:
1.5       shadchin  406:        pdone(endline, 0);
                    407:
                    408: #if HILITE_SEARCH
                    409:        if (is_filtered(base_pos))
                    410:        {
                    411:                /*
                    412:                 * We don't want to display this line.
                    413:                 * Get the previous line.
                    414:                 */
                    415:                curr_pos = begin_new_pos;
                    416:                goto get_back_line;
                    417:        }
                    418:
                    419:        if (status_col && is_hilited(base_pos, ch_tell()-1, 1, NULL))
                    420:                set_status_col('*');
                    421: #endif
1.1       etheisen  422:
                    423:        return (begin_new_pos);
1.4       millert   424: }
                    425:
                    426: /*
                    427:  * Set attnpos.
                    428:  */
                    429:        public void
                    430: set_attnpos(pos)
                    431:        POSITION pos;
                    432: {
                    433:        int c;
                    434:
                    435:        if (pos != NULL_POSITION)
                    436:        {
                    437:                if (ch_seek(pos))
                    438:                        return;
                    439:                for (;;)
                    440:                {
                    441:                        c = ch_forw_get();
                    442:                        if (c == EOI)
                    443:                                return;
                    444:                        if (c != '\n' && c != '\r')
                    445:                                break;
                    446:                        pos++;
                    447:                }
                    448:        }
                    449:        start_attnpos = pos;
                    450:        for (;;)
                    451:        {
                    452:                c = ch_forw_get();
                    453:                pos++;
                    454:                if (c == EOI || c == '\n' || c == '\r')
                    455:                        break;
                    456:        }
                    457:        end_attnpos = pos;
1.1       etheisen  458: }