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

Annotation of src/usr.bin/less/jump.c, Revision 1.7

1.1       etheisen    1: /*
1.6       shadchin    2:  * Copyright (C) 1984-2012  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.6       shadchin    7:  * For more information, see the README file.
1.1       etheisen    8:  */
1.7     ! nicm        9: /*
        !            10:  * Modified for use with illumos.
        !            11:  * Copyright 2014 Garrett D'Amore <garrett@damore.org>
        !            12:  */
1.1       etheisen   13:
                     14: /*
                     15:  * Routines which jump to a new location in the file.
                     16:  */
                     17:
                     18: #include "less.h"
                     19: #include "position.h"
                     20:
                     21: extern int jump_sline;
                     22: extern int squished;
                     23: extern int screen_trashed;
                     24: extern int sc_width, sc_height;
1.4       millert    25: extern int show_attn;
1.5       shadchin   26: extern int top_scroll;
1.1       etheisen   27:
                     28: /*
                     29:  * Jump to the end of the file.
                     30:  */
1.7     ! nicm       31: void
        !            32: jump_forw(void)
1.1       etheisen   33: {
1.7     ! nicm       34:        off_t pos;
        !            35:        off_t end_pos;
1.1       etheisen   36:
1.7     ! nicm       37:        if (ch_end_seek()) {
1.1       etheisen   38:                error("Cannot seek to end of file", NULL_PARG);
                     39:                return;
                     40:        }
1.7     ! nicm       41:        /*
1.5       shadchin   42:         * Note; lastmark will be called later by jump_loc, but it fails
                     43:         * because the position table has been cleared by pos_clear below.
                     44:         * So call it here before calling pos_clear.
                     45:         */
                     46:        lastmark();
1.1       etheisen   47:        /*
                     48:         * Position the last line in the file at the last screen line.
                     49:         * Go back one line from the end of the file
                     50:         * to get to the beginning of the last line.
                     51:         */
1.5       shadchin   52:        pos_clear();
                     53:        end_pos = ch_tell();
                     54:        pos = back_line(end_pos);
1.7     ! nicm       55:        if (pos == -1) {
        !            56:                jump_loc(0, sc_height-1);
        !            57:        } else {
1.1       etheisen   58:                jump_loc(pos, sc_height-1);
1.5       shadchin   59:                if (position(sc_height-1) != end_pos)
                     60:                        repaint();
                     61:        }
1.1       etheisen   62: }
                     63:
                     64: /*
                     65:  * Jump to line n in the file.
                     66:  */
1.7     ! nicm       67: void
        !            68: jump_back(LINENUM linenum)
1.1       etheisen   69: {
1.7     ! nicm       70:        off_t pos;
1.1       etheisen   71:        PARG parg;
                     72:
                     73:        /*
                     74:         * Find the position of the specified line.
                     75:         * If we can seek there, just jump to it.
                     76:         * If we can't seek, but we're trying to go to line number 1,
                     77:         * use ch_beg_seek() to get as close as we can.
                     78:         */
1.4       millert    79:        pos = find_pos(linenum);
1.7     ! nicm       80:        if (pos != -1 && ch_seek(pos) == 0) {
1.4       millert    81:                if (show_attn)
                     82:                        set_attnpos(pos);
1.1       etheisen   83:                jump_loc(pos, jump_sline);
1.7     ! nicm       84:        } else if (linenum <= 1 && ch_beg_seek() == 0) {
1.1       etheisen   85:                jump_loc(ch_tell(), jump_sline);
                     86:                error("Cannot seek to beginning of file", NULL_PARG);
1.7     ! nicm       87:        } else {
1.4       millert    88:                parg.p_linenum = linenum;
                     89:                error("Cannot seek to line number %n", &parg);
1.1       etheisen   90:        }
                     91: }
                     92:
                     93: /*
                     94:  * Repaint the screen.
                     95:  */
1.7     ! nicm       96: void
        !            97: repaint(void)
1.1       etheisen   98: {
                     99:        struct scrpos scrpos;
                    100:        /*
                    101:         * Start at the line currently at the top of the screen
                    102:         * and redisplay the screen.
                    103:         */
                    104:        get_scrpos(&scrpos);
                    105:        pos_clear();
                    106:        jump_loc(scrpos.pos, scrpos.ln);
                    107: }
                    108:
                    109: /*
                    110:  * Jump to a specified percentage into the file.
                    111:  */
1.7     ! nicm      112: void
        !           113: jump_percent(int percent, long fraction)
1.1       etheisen  114: {
1.7     ! nicm      115:        off_t pos, len;
1.1       etheisen  116:
                    117:        /*
                    118:         * Determine the position in the file
                    119:         * (the specified percentage of the file's length).
                    120:         */
1.7     ! nicm      121:        if ((len = ch_length()) == -1) {
1.1       etheisen  122:                ierror("Determining length of file", NULL_PARG);
                    123:                ch_end_seek();
                    124:        }
1.7     ! nicm      125:        if ((len = ch_length()) == -1) {
1.1       etheisen  126:                error("Don't know length of file", NULL_PARG);
                    127:                return;
                    128:        }
1.5       shadchin  129:        pos = percent_pos(len, percent, fraction);
1.1       etheisen  130:        if (pos >= len)
                    131:                pos = len-1;
                    132:
                    133:        jump_line_loc(pos, jump_sline);
                    134: }
                    135:
                    136: /*
                    137:  * Jump to a specified position in the file.
1.7     ! nicm      138:  * Like jump_loc, but the position need not be
1.1       etheisen  139:  * the first character in a line.
                    140:  */
1.7     ! nicm      141: void
        !           142: jump_line_loc(off_t pos, int sline)
1.1       etheisen  143: {
                    144:        int c;
                    145:
1.7     ! nicm      146:        if (ch_seek(pos) == 0) {
1.1       etheisen  147:                /*
                    148:                 * Back up to the beginning of the line.
                    149:                 */
                    150:                while ((c = ch_back_get()) != '\n' && c != EOI)
                    151:                        ;
                    152:                if (c == '\n')
                    153:                        (void) ch_forw_get();
                    154:                pos = ch_tell();
                    155:        }
1.4       millert   156:        if (show_attn)
                    157:                set_attnpos(pos);
1.1       etheisen  158:        jump_loc(pos, sline);
                    159: }
                    160:
                    161: /*
                    162:  * Jump to a specified position in the file.
                    163:  * The position must be the first character in a line.
                    164:  * Place the target line on a specified line on the screen.
                    165:  */
1.7     ! nicm      166: void
        !           167: jump_loc(off_t pos, int sline)
1.1       etheisen  168: {
1.7     ! nicm      169:        int nline;
        !           170:        off_t tpos;
        !           171:        off_t bpos;
1.1       etheisen  172:
                    173:        /*
                    174:         * Normalize sline.
                    175:         */
                    176:        sline = adjsline(sline);
                    177:
1.7     ! nicm      178:        if ((nline = onscreen(pos)) >= 0) {
1.1       etheisen  179:                /*
1.7     ! nicm      180:                 * The line is currently displayed.
1.1       etheisen  181:                 * Just scroll there.
                    182:                 */
                    183:                nline -= sline;
                    184:                if (nline > 0)
                    185:                        forw(nline, position(BOTTOM_PLUS_ONE), 1, 0, 0);
                    186:                else
                    187:                        back(-nline, position(TOP), 1, 0);
1.4       millert   188:                if (show_attn)
                    189:                        repaint_hilite(1);
1.1       etheisen  190:                return;
                    191:        }
                    192:
                    193:        /*
                    194:         * Line is not on screen.
                    195:         * Seek to the desired location.
                    196:         */
1.7     ! nicm      197:        if (ch_seek(pos)) {
1.1       etheisen  198:                error("Cannot seek to that file position", NULL_PARG);
                    199:                return;
                    200:        }
                    201:
                    202:        /*
1.7     ! nicm      203:         * See if the desired line is before or after
1.1       etheisen  204:         * the currently displayed screen.
                    205:         */
                    206:        tpos = position(TOP);
                    207:        bpos = position(BOTTOM_PLUS_ONE);
1.7     ! nicm      208:        if (tpos == -1 || pos >= tpos) {
1.1       etheisen  209:                /*
                    210:                 * The desired line is after the current screen.
                    211:                 * Move back in the file far enough so that we can
1.7     ! nicm      212:                 * call forw() and put the desired line at the
1.1       etheisen  213:                 * sline-th line on the screen.
                    214:                 */
1.7     ! nicm      215:                for (nline = 0;  nline < sline;  nline++) {
        !           216:                        if (bpos != -1 && pos <= bpos) {
1.1       etheisen  217:                                /*
                    218:                                 * Surprise!  The desired line is
                    219:                                 * close enough to the current screen
                    220:                                 * that we can just scroll there after all.
                    221:                                 */
                    222:                                forw(sc_height-sline+nline-1, bpos, 1, 0, 0);
1.4       millert   223:                                if (show_attn)
                    224:                                        repaint_hilite(1);
1.1       etheisen  225:                                return;
                    226:                        }
                    227:                        pos = back_line(pos);
1.7     ! nicm      228:                        if (pos == -1) {
1.1       etheisen  229:                                /*
                    230:                                 * Oops.  Ran into the beginning of the file.
                    231:                                 * Exit the loop here and rely on forw()
                    232:                                 * below to draw the required number of
                    233:                                 * blank lines at the top of the screen.
                    234:                                 */
                    235:                                break;
                    236:                        }
                    237:                }
                    238:                lastmark();
                    239:                squished = 0;
                    240:                screen_trashed = 0;
                    241:                forw(sc_height-1, pos, 1, 0, sline-nline);
1.7     ! nicm      242:        } else {
1.1       etheisen  243:                /*
                    244:                 * The desired line is before the current screen.
                    245:                 * Move forward in the file far enough so that we
1.7     ! nicm      246:                 * can call back() and put the desired line at the
1.1       etheisen  247:                 * sline-th line on the screen.
                    248:                 */
1.7     ! nicm      249:                for (nline = sline;  nline < sc_height - 1;  nline++) {
1.1       etheisen  250:                        pos = forw_line(pos);
1.7     ! nicm      251:                        if (pos == -1) {
1.1       etheisen  252:                                /*
                    253:                                 * Ran into end of file.
1.7     ! nicm      254:                                 * This shouldn't normally happen,
1.1       etheisen  255:                                 * but may if there is some kind of read error.
                    256:                                 */
                    257:                                break;
                    258:                        }
1.7     ! nicm      259:                        if (pos >= tpos) {
        !           260:                                /*
1.1       etheisen  261:                                 * Surprise!  The desired line is
                    262:                                 * close enough to the current screen
                    263:                                 * that we can just scroll there after all.
                    264:                                 */
1.7     ! nicm      265:                                back(nline + 1, tpos, 1, 0);
1.4       millert   266:                                if (show_attn)
                    267:                                        repaint_hilite(1);
1.1       etheisen  268:                                return;
                    269:                        }
                    270:                }
                    271:                lastmark();
1.5       shadchin  272:                if (!top_scroll)
1.7     ! nicm      273:                        do_clear();
1.5       shadchin  274:                else
                    275:                        home();
1.1       etheisen  276:                screen_trashed = 0;
                    277:                add_back_pos(pos);
                    278:                back(sc_height-1, pos, 1, 0);
                    279:        }
                    280: }