Annotation of src/usr.bin/less/jump.c, Revision 1.1.1.1
1.1 etheisen 1: /*
2: * Copyright (c) 1984,1985,1989,1994,1995 Mark Nudelman
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice in the documentation and/or other materials provided with
12: * the distribution.
13: *
14: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
15: * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
18: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
20: * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
21: * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
23: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24: * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25: */
26:
27:
28: /*
29: * Routines which jump to a new location in the file.
30: */
31:
32: #include "less.h"
33: #include "position.h"
34:
35: extern int hit_eof;
36: extern int jump_sline;
37: extern int squished;
38: extern int screen_trashed;
39: extern int sc_width, sc_height;
40:
41: /*
42: * Jump to the end of the file.
43: */
44: public void
45: jump_forw()
46: {
47: POSITION pos;
48:
49: if (ch_end_seek())
50: {
51: error("Cannot seek to end of file", NULL_PARG);
52: return;
53: }
54: /*
55: * Position the last line in the file at the last screen line.
56: * Go back one line from the end of the file
57: * to get to the beginning of the last line.
58: */
59: pos = back_line(ch_tell());
60: if (pos == NULL_POSITION)
61: jump_loc((POSITION)0, sc_height-1);
62: else
63: jump_loc(pos, sc_height-1);
64: }
65:
66: /*
67: * Jump to line n in the file.
68: */
69: public void
70: jump_back(n)
71: int n;
72: {
73: POSITION pos;
74: PARG parg;
75:
76: /*
77: * Find the position of the specified line.
78: * If we can seek there, just jump to it.
79: * If we can't seek, but we're trying to go to line number 1,
80: * use ch_beg_seek() to get as close as we can.
81: */
82: pos = find_pos(n);
83: if (pos != NULL_POSITION && ch_seek(pos) == 0)
84: {
85: jump_loc(pos, jump_sline);
86: } else if (n <= 1 && ch_beg_seek() == 0)
87: {
88: jump_loc(ch_tell(), jump_sline);
89: error("Cannot seek to beginning of file", NULL_PARG);
90: } else
91: {
92: parg.p_int = n;
93: error("Cannot seek to line number %d", &parg);
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
117: jump_percent(percent)
118: int percent;
119: {
120: POSITION pos, len;
121:
122: /*
123: * Determine the position in the file
124: * (the specified percentage of the file's length).
125: */
126: if ((len = ch_length()) == NULL_POSITION)
127: {
128: ierror("Determining length of file", NULL_PARG);
129: ch_end_seek();
130: }
131: if ((len = ch_length()) == NULL_POSITION)
132: {
133: error("Don't know length of file", NULL_PARG);
134: return;
135: }
136: /*
137: * {{ This calculation may overflow! }}
138: */
139: pos = (percent * len) / 100;
140: if (pos >= len)
141: pos = len-1;
142:
143: jump_line_loc(pos, jump_sline);
144: }
145:
146: /*
147: * Jump to a specified position in the file.
148: * Like jump_loc, but the position need not be
149: * the first character in a line.
150: */
151: public void
152: jump_line_loc(pos, sline)
153: POSITION pos;
154: int sline;
155: {
156: int c;
157:
158: if (ch_seek(pos) == 0)
159: {
160: /*
161: * Back up to the beginning of the line.
162: */
163: while ((c = ch_back_get()) != '\n' && c != EOI)
164: ;
165: if (c == '\n')
166: (void) ch_forw_get();
167: pos = ch_tell();
168: }
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: {
182: register int nline;
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);
202: return;
203: }
204:
205: /*
206: * Line is not on screen.
207: * Seek to the desired location.
208: */
209: if (ch_seek(pos))
210: {
211: error("Cannot seek to that file position", NULL_PARG);
212: return;
213: }
214:
215: /*
216: * See if the desired line is before or after
217: * the currently displayed screen.
218: */
219: tpos = position(TOP);
220: bpos = position(BOTTOM_PLUS_ONE);
221: if (tpos == NULL_POSITION || pos >= tpos)
222: {
223: /*
224: * The desired line is after the current screen.
225: * Move back in the file far enough so that we can
226: * call forw() and put the desired line at the
227: * sline-th line on the screen.
228: */
229: for (nline = 0; nline < sline; nline++)
230: {
231: if (bpos != NULL_POSITION && pos <= bpos)
232: {
233: /*
234: * Surprise! The desired line is
235: * close enough to the current screen
236: * that we can just scroll there after all.
237: */
238: forw(sc_height-sline+nline-1, bpos, 1, 0, 0);
239: return;
240: }
241: pos = back_line(pos);
242: if (pos == NULL_POSITION)
243: {
244: /*
245: * Oops. Ran into the beginning of the file.
246: * Exit the loop here and rely on forw()
247: * below to draw the required number of
248: * blank lines at the top of the screen.
249: */
250: break;
251: }
252: }
253: lastmark();
254: hit_eof = 0;
255: squished = 0;
256: screen_trashed = 0;
257: forw(sc_height-1, pos, 1, 0, sline-nline);
258: } else
259: {
260: /*
261: * The desired line is before the current screen.
262: * Move forward in the file far enough so that we
263: * can call back() and put the desired line at the
264: * sline-th line on the screen.
265: */
266: for (nline = sline; nline < sc_height - 1; nline++)
267: {
268: pos = forw_line(pos);
269: if (pos == NULL_POSITION)
270: {
271: /*
272: * Ran into end of file.
273: * This shouldn't normally happen,
274: * but may if there is some kind of read error.
275: */
276: break;
277: }
278: if (pos >= tpos)
279: {
280: /*
281: * Surprise! The desired line is
282: * close enough to the current screen
283: * that we can just scroll there after all.
284: */
285: back(nline+1, tpos, 1, 0);
286: return;
287: }
288: }
289: lastmark();
290: clear();
291: screen_trashed = 0;
292: add_back_pos(pos);
293: back(sc_height-1, pos, 1, 0);
294: }
295: }