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

Annotation of src/usr.bin/less/forwback.c, Revision 1.10

1.1       etheisen    1: /*
1.9       shadchin    2:  * Copyright (C) 1984-2012  Mark Nudelman
1.1       etheisen    3:  *
1.5       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.9       shadchin    7:  * For more information, see the README file.
1.1       etheisen    8:  */
1.10    ! nicm        9: /*
        !            10:  * Modified for use with illumos.
        !            11:  * Copyright 2014 Garrett D'Amore <garrett@damore.org>
        !            12:  */
1.1       etheisen   13:
                     14: /*
                     15:  * Primitives for displaying the file on the screen,
                     16:  * scrolling either forward or backward.
                     17:  */
                     18:
                     19: #include "less.h"
                     20: #include "position.h"
                     21:
1.10    ! nicm       22: int screen_trashed;
        !            23: int squished;
        !            24: int no_back_scroll = 0;
        !            25: int forw_prompt;
1.1       etheisen   26:
1.8       millert    27: extern volatile sig_atomic_t sigs;
1.1       etheisen   28: extern int top_scroll;
                     29: extern int quiet;
                     30: extern int sc_width, sc_height;
                     31: extern int plusoption;
                     32: extern int forw_scroll;
                     33: extern int back_scroll;
                     34: extern int ignore_eoi;
1.5       millert    35: extern int clear_bg;
                     36: extern int final_attr;
1.7       shadchin   37: extern int oldbot;
1.1       etheisen   38: extern char *tagoption;
                     39:
                     40: /*
                     41:  * Sound the bell to indicate user is trying to move past end of file.
                     42:  */
1.10    ! nicm       43: static void
        !            44: eof_bell(void)
1.1       etheisen   45: {
                     46:        if (quiet == NOT_QUIET)
1.10    ! nicm       47:                ring_bell();
1.1       etheisen   48:        else
                     49:                vbell();
                     50: }
                     51:
                     52: /*
1.7       shadchin   53:  * Check to see if the end of file is currently displayed.
1.1       etheisen   54:  */
1.10    ! nicm       55: int
        !            56: eof_displayed(void)
1.1       etheisen   57: {
1.10    ! nicm       58:        off_t pos;
1.1       etheisen   59:
                     60:        if (ignore_eoi)
1.7       shadchin   61:                return (0);
                     62:
1.10    ! nicm       63:        if (ch_length() == -1)
1.7       shadchin   64:                /*
                     65:                 * If the file length is not known,
                     66:                 * we can't possibly be displaying EOF.
                     67:                 */
                     68:                return (0);
                     69:
1.1       etheisen   70:        /*
                     71:         * If the bottom line is empty, we are at EOF.
                     72:         * If the bottom line ends at the file length,
                     73:         * we must be just at EOF.
                     74:         */
                     75:        pos = position(BOTTOM_PLUS_ONE);
1.10    ! nicm       76:        return (pos == -1 || pos == ch_length());
1.7       shadchin   77: }
                     78:
                     79: /*
                     80:  * Check to see if the entire file is currently displayed.
                     81:  */
1.10    ! nicm       82: int
        !            83: entire_file_displayed(void)
1.7       shadchin   84: {
1.10    ! nicm       85:        off_t pos;
1.7       shadchin   86:
                     87:        /* Make sure last line of file is displayed. */
                     88:        if (!eof_displayed())
                     89:                return (0);
                     90:
                     91:        /* Make sure first line of file is displayed. */
                     92:        pos = position(0);
1.10    ! nicm       93:        return (pos == -1 || pos == 0);
1.1       etheisen   94: }
                     95:
                     96: /*
                     97:  * If the screen is "squished", repaint it.
                     98:  * "Squished" means the first displayed line is not at the top
                     99:  * of the screen; this can happen when we display a short file
                    100:  * for the first time.
                    101:  */
1.10    ! nicm      102: void
        !           103: squish_check(void)
1.1       etheisen  104: {
                    105:        if (!squished)
                    106:                return;
                    107:        squished = 0;
                    108:        repaint();
                    109: }
                    110:
                    111: /*
1.10    ! nicm      112:  * Display n lines, scrolling forward,
1.1       etheisen  113:  * starting at position pos in the input file.
                    114:  * "force" means display the n lines even if we hit end of file.
                    115:  * "only_last" means display only the last screenful if n > screen size.
                    116:  * "nblank" is the number of blank lines to draw before the first
1.10    ! nicm      117:  *   real line.  If nblank > 0, the pos must be -1.
1.1       etheisen  118:  *   The first real line after the blanks will start at ch_zero().
                    119:  */
1.10    ! nicm      120: void
        !           121: forw(int n, off_t pos, int force, int only_last, int nblank)
1.1       etheisen  122: {
                    123:        int nlines = 0;
                    124:        int do_repaint;
                    125:        static int first_time = 1;
                    126:
                    127:        squish_check();
                    128:
                    129:        /*
1.10    ! nicm      130:         * do_repaint tells us not to display anything till the end,
1.1       etheisen  131:         * then just repaint the entire screen.
1.10    ! nicm      132:         * We repaint if we are supposed to display only the last
1.1       etheisen  133:         * screenful and the request is for more than a screenful.
                    134:         * Also if the request exceeds the forward scroll limit
                    135:         * (but not if the request is for exactly a screenful, since
                    136:         * repainting itself involves scrolling forward a screenful).
                    137:         */
1.10    ! nicm      138:        do_repaint = (only_last && n > sc_height-1) ||
        !           139:            (forw_scroll >= 0 && n > forw_scroll && n != sc_height-1);
1.1       etheisen  140:
1.10    ! nicm      141:        if (!do_repaint) {
        !           142:                if (top_scroll && n >= sc_height - 1 && pos != ch_length()) {
1.1       etheisen  143:                        /*
                    144:                         * Start a new screen.
                    145:                         * {{ This is not really desirable if we happen
                    146:                         *    to hit eof in the middle of this screen,
                    147:                         *    but we don't yet know if that will happen. }}
                    148:                         */
1.5       millert   149:                        pos_clear();
                    150:                        add_forw_pos(pos);
                    151:                        force = 1;
1.10    ! nicm      152:                        do_clear();
1.1       etheisen  153:                        home();
                    154:                }
                    155:
1.10    ! nicm      156:                if (pos != position(BOTTOM_PLUS_ONE) || empty_screen()) {
1.1       etheisen  157:                        /*
                    158:                         * This is not contiguous with what is
1.10    ! nicm      159:                         * currently displayed.  Clear the screen image
1.1       etheisen  160:                         * (position table) and start a new screen.
                    161:                         */
                    162:                        pos_clear();
                    163:                        add_forw_pos(pos);
                    164:                        force = 1;
1.10    ! nicm      165:                        if (top_scroll) {
        !           166:                                do_clear();
1.1       etheisen  167:                                home();
1.10    ! nicm      168:                        } else if (!first_time) {
1.1       etheisen  169:                                putstr("...skipping...\n");
                    170:                        }
                    171:                }
                    172:        }
                    173:
1.10    ! nicm      174:        while (--n >= 0) {
1.1       etheisen  175:                /*
                    176:                 * Read the next line of input.
                    177:                 */
1.10    ! nicm      178:                if (nblank > 0) {
1.1       etheisen  179:                        /*
1.10    ! nicm      180:                         * Still drawing blanks; don't get a line
1.1       etheisen  181:                         * from the file yet.
                    182:                         * If this is the last blank line, get ready to
                    183:                         * read a line starting at ch_zero() next time.
                    184:                         */
                    185:                        if (--nblank == 0)
                    186:                                pos = ch_zero();
1.10    ! nicm      187:                } else {
        !           188:                        /*
1.1       etheisen  189:                         * Get the next line from the file.
                    190:                         */
                    191:                        pos = forw_line(pos);
1.10    ! nicm      192:                        if (pos == -1) {
1.1       etheisen  193:                                /*
1.10    ! nicm      194:                                 * End of file: stop here unless the top line
1.1       etheisen  195:                                 * is still empty, or "force" is true.
1.5       millert   196:                                 * Even if force is true, stop when the last
                    197:                                 * line in the file reaches the top of screen.
1.1       etheisen  198:                                 */
1.10    ! nicm      199:                                if (!force && position(TOP) != -1)
1.1       etheisen  200:                                        break;
1.10    ! nicm      201:                                if (!empty_lines(0, 0) &&
1.5       millert   202:                                    !empty_lines(1, 1) &&
1.10    ! nicm      203:                                    empty_lines(2, sc_height-1))
1.5       millert   204:                                        break;
1.1       etheisen  205:                        }
                    206:                }
                    207:                /*
                    208:                 * Add the position of the next line to the position table.
                    209:                 * Display the current line on the screen.
                    210:                 */
                    211:                add_forw_pos(pos);
                    212:                nlines++;
                    213:                if (do_repaint)
                    214:                        continue;
                    215:                /*
                    216:                 * If this is the first screen displayed and
                    217:                 * we hit an early EOF (i.e. before the requested
                    218:                 * number of lines), we "squish" the display down
                    219:                 * at the bottom of the screen.
                    220:                 * But don't do this if a + option or a -t option
                    221:                 * was given.  These options can cause us to
                    222:                 * start the display after the beginning of the file,
                    223:                 * and it is not appropriate to squish in that case.
                    224:                 */
1.10    ! nicm      225:                if (first_time && pos == -1 && !top_scroll &&
        !           226:                    tagoption == NULL && !plusoption) {
1.1       etheisen  227:                        squished = 1;
                    228:                        continue;
                    229:                }
                    230:                put_line();
1.7       shadchin  231:                forw_prompt = 1;
1.1       etheisen  232:        }
                    233:
                    234:        if (nlines == 0)
                    235:                eof_bell();
                    236:        else if (do_repaint)
                    237:                repaint();
                    238:        first_time = 0;
                    239:        (void) currline(BOTTOM);
                    240: }
                    241:
                    242: /*
                    243:  * Display n lines, scrolling backward.
                    244:  */
1.10    ! nicm      245: void
        !           246: back(int n, off_t pos, int force, int only_last)
1.1       etheisen  247: {
                    248:        int nlines = 0;
                    249:        int do_repaint;
                    250:
                    251:        squish_check();
                    252:        do_repaint = (n > get_back_scroll() || (only_last && n > sc_height-1));
1.10    ! nicm      253:        while (--n >= 0) {
1.1       etheisen  254:                /*
                    255:                 * Get the previous line of input.
                    256:                 */
                    257:                pos = back_line(pos);
1.10    ! nicm      258:                if (pos == -1) {
1.1       etheisen  259:                        /*
                    260:                         * Beginning of file: stop here unless "force" is true.
                    261:                         */
                    262:                        if (!force)
                    263:                                break;
                    264:                }
                    265:                /*
                    266:                 * Add the position of the previous line to the position table.
                    267:                 * Display the line on the screen.
                    268:                 */
                    269:                add_back_pos(pos);
                    270:                nlines++;
1.10    ! nicm      271:                if (!do_repaint) {
1.1       etheisen  272:                        home();
                    273:                        add_line();
                    274:                        put_line();
                    275:                }
                    276:        }
                    277:
                    278:        if (nlines == 0)
                    279:                eof_bell();
                    280:        else if (do_repaint)
                    281:                repaint();
1.7       shadchin  282:        else if (!oldbot)
                    283:                lower_left();
1.1       etheisen  284:        (void) currline(BOTTOM);
                    285: }
                    286:
                    287: /*
                    288:  * Display n more lines, forward.
                    289:  * Start just after the line currently displayed at the bottom of the screen.
                    290:  */
1.10    ! nicm      291: void
        !           292: forward(int n, int force, int only_last)
1.1       etheisen  293: {
1.10    ! nicm      294:        off_t pos;
1.1       etheisen  295:
1.10    ! nicm      296:        if (get_quit_at_eof() && eof_displayed() &&
        !           297:            !(ch_getflags() & CH_HELPFILE)) {
1.1       etheisen  298:                /*
                    299:                 * If the -e flag is set and we're trying to go
                    300:                 * forward from end-of-file, go on to the next file.
                    301:                 */
                    302:                if (edit_next(1))
                    303:                        quit(QUIT_OK);
                    304:                return;
                    305:        }
                    306:
                    307:        pos = position(BOTTOM_PLUS_ONE);
1.10    ! nicm      308:        if (pos == -1 && (!force || empty_lines(2, sc_height-1))) {
        !           309:                if (ignore_eoi) {
1.1       etheisen  310:                        /*
                    311:                         * ignore_eoi is to support A_F_FOREVER.
                    312:                         * Back up until there is a line at the bottom
                    313:                         * of the screen.
                    314:                         */
1.10    ! nicm      315:                        if (empty_screen()) {
1.1       etheisen  316:                                pos = ch_zero();
1.10    ! nicm      317:                        } else {
        !           318:                                do {
1.1       etheisen  319:                                        back(1, position(TOP), 1, 0);
                    320:                                        pos = position(BOTTOM_PLUS_ONE);
1.10    ! nicm      321:                                } while (pos == -1);
1.1       etheisen  322:                        }
1.10    ! nicm      323:                } else {
1.1       etheisen  324:                        eof_bell();
                    325:                        return;
                    326:                }
                    327:        }
                    328:        forw(n, pos, force, only_last, 0);
                    329: }
                    330:
                    331: /*
                    332:  * Display n more lines, backward.
                    333:  * Start just before the line currently displayed at the top of the screen.
                    334:  */
1.10    ! nicm      335: void
        !           336: backward(int n, int force, int only_last)
1.1       etheisen  337: {
1.10    ! nicm      338:        off_t pos;
1.1       etheisen  339:
                    340:        pos = position(TOP);
1.10    ! nicm      341:        if (pos == -1 && (!force || position(BOTTOM) == 0)) {
1.1       etheisen  342:                eof_bell();
1.10    ! nicm      343:                return;
1.1       etheisen  344:        }
                    345:        back(n, pos, force, only_last);
                    346: }
                    347:
                    348: /*
                    349:  * Get the backwards scroll limit.
                    350:  * Must call this function instead of just using the value of
                    351:  * back_scroll, because the default case depends on sc_height and
                    352:  * top_scroll, as well as back_scroll.
                    353:  */
1.10    ! nicm      354: int
        !           355: get_back_scroll(void)
1.1       etheisen  356: {
1.5       millert   357:        if (no_back_scroll)
                    358:                return (0);
1.1       etheisen  359:        if (back_scroll >= 0)
                    360:                return (back_scroll);
                    361:        if (top_scroll)
                    362:                return (sc_height - 2);
                    363:        return (10000); /* infinity */
                    364: }