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

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