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