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: }