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