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