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

1.3     ! niklas      1: /*     $OpenBSD$       */
        !             2:
1.1       etheisen    3: /*
                      4:  * Copyright (c) 1984,1985,1989,1994,1995  Mark Nudelman
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice in the documentation and/or other materials provided with
                     14:  *    the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
                     17:  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     18:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     19:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
                     20:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     21:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
                     22:  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
                     23:  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
                     24:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
                     25:  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
                     26:  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     27:  */
                     28:
                     29:
                     30: /*
                     31:  * Primitives for displaying the file on the screen,
                     32:  * scrolling either forward or backward.
                     33:  */
                     34:
                     35: #include "less.h"
                     36: #include "position.h"
                     37:
                     38: public int hit_eof;    /* Keeps track of how many times we hit end of file */
                     39: public int screen_trashed;
                     40: public int squished;
                     41:
                     42: extern int sigs;
                     43: extern int top_scroll;
                     44: extern int quiet;
                     45: extern int sc_width, sc_height;
                     46: extern int quit_at_eof;
1.2       etheisen   47: extern int less_mode;
1.1       etheisen   48: extern int plusoption;
                     49: extern int forw_scroll;
                     50: extern int back_scroll;
                     51: extern int need_clr;
                     52: extern int ignore_eoi;
                     53: #if TAGS
                     54: extern char *tagoption;
                     55: #endif
                     56:
                     57: /*
                     58:  * Sound the bell to indicate user is trying to move past end of file.
                     59:  */
                     60:        static void
                     61: eof_bell()
                     62: {
                     63:        if (quiet == NOT_QUIET)
                     64:                bell();
                     65:        else
                     66:                vbell();
                     67: }
                     68:
                     69: /*
                     70:  * Check to see if the end of file is currently "displayed".
                     71:  */
                     72:        static void
                     73: eof_check()
                     74: {
                     75:        POSITION pos;
                     76:
                     77:        if (ignore_eoi)
                     78:                return;
                     79:        if (ABORT_SIGS())
                     80:                return;
                     81:        /*
                     82:         * If the bottom line is empty, we are at EOF.
                     83:         * If the bottom line ends at the file length,
                     84:         * we must be just at EOF.
                     85:         */
                     86:        pos = position(BOTTOM_PLUS_ONE);
                     87:        if (pos == NULL_POSITION || pos == ch_length())
                     88:                hit_eof++;
                     89: }
                     90:
                     91: /*
                     92:  * If the screen is "squished", repaint it.
                     93:  * "Squished" means the first displayed line is not at the top
                     94:  * of the screen; this can happen when we display a short file
                     95:  * for the first time.
                     96:  */
                     97:        static void
                     98: squish_check()
                     99: {
                    100:        if (!squished)
                    101:                return;
                    102:        squished = 0;
                    103:        repaint();
                    104: }
                    105:
                    106: /*
                    107:  * Display n lines, scrolling forward,
                    108:  * starting at position pos in the input file.
                    109:  * "force" means display the n lines even if we hit end of file.
                    110:  * "only_last" means display only the last screenful if n > screen size.
                    111:  * "nblank" is the number of blank lines to draw before the first
                    112:  *   real line.  If nblank > 0, the pos must be NULL_POSITION.
                    113:  *   The first real line after the blanks will start at ch_zero().
                    114:  */
                    115:        public void
                    116: forw(n, pos, force, only_last, nblank)
                    117:        register int n;
                    118:        POSITION pos;
                    119:        int force;
                    120:        int only_last;
                    121:        int nblank;
                    122: {
                    123:        int eof = 0;
                    124:        int nlines = 0;
                    125:        int do_repaint;
                    126:        static int first_time = 1;
                    127:
                    128:        squish_check();
                    129:
                    130:        /*
                    131:         * do_repaint tells us not to display anything till the end,
                    132:         * then just repaint the entire screen.
                    133:         * We repaint if we are supposed to display only the last
                    134:         * screenful and the request is for more than a screenful.
                    135:         * Also if the request exceeds the forward scroll limit
                    136:         * (but not if the request is for exactly a screenful, since
                    137:         * repainting itself involves scrolling forward a screenful).
                    138:         */
                    139:        do_repaint = (only_last && n > sc_height-1) ||
                    140:                (forw_scroll >= 0 && n > forw_scroll && n != sc_height-1);
                    141:
                    142:        if (!do_repaint)
                    143:        {
                    144:                if (top_scroll && n >= sc_height - 1 && pos != ch_length())
                    145:                {
                    146:                        /*
                    147:                         * Start a new screen.
                    148:                         * {{ This is not really desirable if we happen
                    149:                         *    to hit eof in the middle of this screen,
                    150:                         *    but we don't yet know if that will happen. }}
                    151:                         */
                    152:                        if (top_scroll == OPT_ONPLUS || first_time)
                    153:                                clear();
                    154:                        home();
                    155:                        force = 1;
                    156:                } else
                    157:                {
                    158:                        clear_bot();
                    159:                }
                    160:
                    161:                if (pos != position(BOTTOM_PLUS_ONE) || empty_screen())
                    162:                {
                    163:                        /*
                    164:                         * This is not contiguous with what is
                    165:                         * currently displayed.  Clear the screen image
                    166:                         * (position table) and start a new screen.
                    167:                         */
                    168:                        pos_clear();
                    169:                        add_forw_pos(pos);
                    170:                        force = 1;
                    171:                        if (top_scroll)
                    172:                        {
                    173:                                if (top_scroll == OPT_ONPLUS)
                    174:                                        clear();
                    175:                                home();
                    176:                        } else if (!first_time)
                    177:                        {
                    178:                                putstr("...skipping...\n");
                    179:                        }
                    180:                }
                    181:        }
                    182:
                    183:        while (--n >= 0)
                    184:        {
                    185:                /*
                    186:                 * Read the next line of input.
                    187:                 */
                    188:                if (nblank > 0)
                    189:                {
                    190:                        /*
                    191:                         * Still drawing blanks; don't get a line
                    192:                         * from the file yet.
                    193:                         * If this is the last blank line, get ready to
                    194:                         * read a line starting at ch_zero() next time.
                    195:                         */
                    196:                        if (--nblank == 0)
                    197:                                pos = ch_zero();
                    198:                } else
                    199:                {
                    200:                        /*
                    201:                         * Get the next line from the file.
                    202:                         */
                    203:                        pos = forw_line(pos);
                    204:                        if (pos == NULL_POSITION)
                    205:                        {
                    206:                                /*
                    207:                                 * End of file: stop here unless the top line
                    208:                                 * is still empty, or "force" is true.
                    209:                                 */
                    210:                                eof = 1;
                    211:                                if (!force && position(TOP) != NULL_POSITION)
                    212:                                        break;
                    213:                        }
                    214:                }
                    215:                /*
                    216:                 * Add the position of the next line to the position table.
                    217:                 * Display the current line on the screen.
                    218:                 */
                    219:                add_forw_pos(pos);
                    220:                nlines++;
                    221:                if (do_repaint)
                    222:                        continue;
                    223:                /*
                    224:                 * If this is the first screen displayed and
                    225:                 * we hit an early EOF (i.e. before the requested
                    226:                 * number of lines), we "squish" the display down
                    227:                 * at the bottom of the screen.
                    228:                 * But don't do this if a + option or a -t option
                    229:                 * was given.  These options can cause us to
                    230:                 * start the display after the beginning of the file,
                    231:                 * and it is not appropriate to squish in that case.
                    232:                 */
                    233:                if (first_time && pos == NULL_POSITION && !top_scroll &&
                    234: #if TAGS
                    235:                    tagoption == NULL &&
                    236: #endif
                    237:                    !plusoption)
                    238:                {
                    239:                        squished = 1;
                    240:                        continue;
                    241:                }
                    242:                if (top_scroll == 1)
                    243:                        clear_eol();
                    244:                put_line();
                    245:        }
                    246:
                    247:        if (ignore_eoi)
                    248:                hit_eof = 0;
                    249:        else if (eof && !ABORT_SIGS())
                    250:                hit_eof++;
                    251:        else
                    252:                eof_check();
                    253:        if (nlines == 0)
                    254:                eof_bell();
                    255:        else if (do_repaint)
                    256:                repaint();
                    257:        first_time = 0;
                    258:        (void) currline(BOTTOM);
                    259: }
                    260:
                    261: /*
                    262:  * Display n lines, scrolling backward.
                    263:  */
                    264:        public void
                    265: back(n, pos, force, only_last)
                    266:        register int n;
                    267:        POSITION pos;
                    268:        int force;
                    269:        int only_last;
                    270: {
                    271:        int nlines = 0;
                    272:        int do_repaint;
                    273:
                    274:        squish_check();
                    275:        do_repaint = (n > get_back_scroll() || (only_last && n > sc_height-1));
                    276:        hit_eof = 0;
                    277:        while (--n >= 0)
                    278:        {
                    279:                /*
                    280:                 * Get the previous line of input.
                    281:                 */
                    282:                pos = back_line(pos);
                    283:                if (pos == NULL_POSITION)
                    284:                {
                    285:                        /*
                    286:                         * Beginning of file: stop here unless "force" is true.
                    287:                         */
                    288:                        if (!force)
                    289:                                break;
                    290:                }
                    291:                /*
                    292:                 * Add the position of the previous line to the position table.
                    293:                 * Display the line on the screen.
                    294:                 */
                    295:                add_back_pos(pos);
                    296:                nlines++;
                    297:                if (!do_repaint)
                    298:                {
                    299:                        home();
                    300:                        add_line();
                    301:                        put_line();
                    302:                }
                    303:        }
                    304:
                    305:        eof_check();
                    306:        if (nlines == 0)
                    307:                eof_bell();
                    308:        else if (do_repaint)
                    309:                repaint();
                    310:        (void) currline(BOTTOM);
                    311: }
                    312:
                    313: /*
                    314:  * Display n more lines, forward.
                    315:  * Start just after the line currently displayed at the bottom of the screen.
                    316:  */
                    317:        public void
                    318: forward(n, force, only_last)
                    319:        int n;
                    320:        int force;
                    321:        int only_last;
                    322: {
                    323:        POSITION pos;
                    324:
                    325:        if (quit_at_eof && hit_eof)
                    326:        {
                    327:                /*
                    328:                 * If the -e flag is set and we're trying to go
                    329:                 * forward from end-of-file, go on to the next file.
                    330:                 */
                    331:                if (edit_next(1))
                    332:                        quit(QUIT_OK);
                    333:                return;
                    334:        }
                    335:
                    336:        pos = position(BOTTOM_PLUS_ONE);
                    337:        if (pos == NULL_POSITION && (!force || empty_lines(2, sc_height-1)))
                    338:        {
                    339:                if (ignore_eoi)
                    340:                {
                    341:                        /*
                    342:                         * ignore_eoi is to support A_F_FOREVER.
                    343:                         * Back up until there is a line at the bottom
                    344:                         * of the screen.
                    345:                         */
                    346:                        if (empty_screen())
                    347:                                pos = ch_zero();
                    348:                        else
                    349:                        {
                    350:                                do
                    351:                                {
                    352:                                        back(1, position(TOP), 1, 0);
                    353:                                        pos = position(BOTTOM_PLUS_ONE);
                    354:                                } while (pos == NULL_POSITION);
                    355:                        }
1.2       etheisen  356:                } else {
1.1       etheisen  357:                        eof_bell();
                    358:                        hit_eof++;
                    359:                        return;
                    360:                }
                    361:        }
                    362:        forw(n, pos, force, only_last, 0);
                    363: }
                    364:
                    365: /*
                    366:  * Display n more lines, backward.
                    367:  * Start just before the line currently displayed at the top of the screen.
                    368:  */
                    369:        public void
                    370: backward(n, force, only_last)
                    371:        int n;
                    372:        int force;
                    373:        int only_last;
                    374: {
                    375:        POSITION pos;
                    376:
                    377:        pos = position(TOP);
                    378:        if (pos == NULL_POSITION && (!force || position(BOTTOM) == 0))
                    379:        {
                    380:                eof_bell();
                    381:                return;
                    382:        }
                    383:        back(n, pos, force, only_last);
                    384: }
                    385:
                    386: /*
                    387:  * Get the backwards scroll limit.
                    388:  * Must call this function instead of just using the value of
                    389:  * back_scroll, because the default case depends on sc_height and
                    390:  * top_scroll, as well as back_scroll.
                    391:  */
                    392:        public int
                    393: get_back_scroll()
                    394: {
                    395:        if (back_scroll >= 0)
                    396:                return (back_scroll);
                    397:        if (top_scroll)
                    398:                return (sc_height - 2);
                    399:        return (10000); /* infinity */
                    400: }