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

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