Annotation of src/usr.bin/less/jump.c, Revision 1.1.1.4
1.1 etheisen 1: /*
1.1.1.4 ! shadchin 2: * Copyright (C) 1984-2012 Mark Nudelman
1.1 etheisen 3: *
1.1.1.2 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.1.1.4 ! shadchin 7: * For more information, see the README file.
1.1 etheisen 8: */
9:
10:
11: /*
12: * Routines which jump to a new location in the file.
13: */
14:
15: #include "less.h"
16: #include "position.h"
17:
18: extern int jump_sline;
19: extern int squished;
20: extern int screen_trashed;
21: extern int sc_width, sc_height;
1.1.1.2 millert 22: extern int show_attn;
1.1.1.3 shadchin 23: extern int top_scroll;
1.1 etheisen 24:
25: /*
26: * Jump to the end of the file.
27: */
28: public void
29: jump_forw()
30: {
31: POSITION pos;
1.1.1.3 shadchin 32: POSITION end_pos;
1.1 etheisen 33:
34: if (ch_end_seek())
35: {
36: error("Cannot seek to end of file", NULL_PARG);
37: return;
38: }
1.1.1.3 shadchin 39: /*
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.1.1.3 shadchin 50: pos_clear();
51: end_pos = ch_tell();
52: pos = back_line(end_pos);
1.1 etheisen 53: if (pos == NULL_POSITION)
54: jump_loc((POSITION)0, sc_height-1);
55: else
1.1.1.3 shadchin 56: {
1.1 etheisen 57: jump_loc(pos, sc_height-1);
1.1.1.3 shadchin 58: if (position(sc_height-1) != end_pos)
59: repaint();
60: }
1.1 etheisen 61: }
62:
63: /*
64: * Jump to line n in the file.
65: */
66: public void
1.1.1.2 millert 67: jump_back(linenum)
68: LINENUM linenum;
1.1 etheisen 69: {
70: POSITION pos;
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.1.1.2 millert 79: pos = find_pos(linenum);
1.1 etheisen 80: if (pos != NULL_POSITION && ch_seek(pos) == 0)
81: {
1.1.1.2 millert 82: if (show_attn)
83: set_attnpos(pos);
1.1 etheisen 84: jump_loc(pos, jump_sline);
1.1.1.2 millert 85: } else if (linenum <= 1 && ch_beg_seek() == 0)
1.1 etheisen 86: {
87: jump_loc(ch_tell(), jump_sline);
88: error("Cannot seek to beginning of file", NULL_PARG);
89: } else
90: {
1.1.1.2 millert 91: parg.p_linenum = linenum;
92: error("Cannot seek to line number %n", &parg);
1.1 etheisen 93: }
94: }
95:
96: /*
97: * Repaint the screen.
98: */
99: public void
100: repaint()
101: {
102: struct scrpos scrpos;
103: /*
104: * Start at the line currently at the top of the screen
105: * and redisplay the screen.
106: */
107: get_scrpos(&scrpos);
108: pos_clear();
109: jump_loc(scrpos.pos, scrpos.ln);
110: }
111:
112: /*
113: * Jump to a specified percentage into the file.
114: */
115: public void
1.1.1.3 shadchin 116: jump_percent(percent, fraction)
1.1 etheisen 117: int percent;
1.1.1.3 shadchin 118: long fraction;
1.1 etheisen 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: }
1.1.1.3 shadchin 136: pos = percent_pos(len, percent, fraction);
1.1 etheisen 137: if (pos >= len)
138: pos = len-1;
139:
140: jump_line_loc(pos, jump_sline);
141: }
142:
143: /*
144: * Jump to a specified position in the file.
145: * Like jump_loc, but the position need not be
146: * the first character in a line.
147: */
148: public void
149: jump_line_loc(pos, sline)
150: POSITION pos;
151: int sline;
152: {
153: int c;
154:
155: if (ch_seek(pos) == 0)
156: {
157: /*
158: * Back up to the beginning of the line.
159: */
160: while ((c = ch_back_get()) != '\n' && c != EOI)
161: ;
162: if (c == '\n')
163: (void) ch_forw_get();
164: pos = ch_tell();
165: }
1.1.1.2 millert 166: if (show_attn)
167: set_attnpos(pos);
1.1 etheisen 168: jump_loc(pos, sline);
169: }
170:
171: /*
172: * Jump to a specified position in the file.
173: * The position must be the first character in a line.
174: * Place the target line on a specified line on the screen.
175: */
176: public void
177: jump_loc(pos, sline)
178: POSITION pos;
179: int sline;
180: {
181: register int nline;
182: POSITION tpos;
183: POSITION bpos;
184:
185: /*
186: * Normalize sline.
187: */
188: sline = adjsline(sline);
189:
190: if ((nline = onscreen(pos)) >= 0)
191: {
192: /*
193: * The line is currently displayed.
194: * Just scroll there.
195: */
196: nline -= sline;
197: if (nline > 0)
198: forw(nline, position(BOTTOM_PLUS_ONE), 1, 0, 0);
199: else
200: back(-nline, position(TOP), 1, 0);
1.1.1.3 shadchin 201: #if HILITE_SEARCH
1.1.1.2 millert 202: if (show_attn)
203: repaint_hilite(1);
1.1.1.3 shadchin 204: #endif
1.1 etheisen 205: return;
206: }
207:
208: /*
209: * Line is not on screen.
210: * Seek to the desired location.
211: */
212: if (ch_seek(pos))
213: {
214: error("Cannot seek to that file position", NULL_PARG);
215: return;
216: }
217:
218: /*
219: * See if the desired line is before or after
220: * the currently displayed screen.
221: */
222: tpos = position(TOP);
223: bpos = position(BOTTOM_PLUS_ONE);
224: if (tpos == NULL_POSITION || pos >= tpos)
225: {
226: /*
227: * The desired line is after the current screen.
228: * Move back in the file far enough so that we can
229: * call forw() and put the desired line at the
230: * sline-th line on the screen.
231: */
232: for (nline = 0; nline < sline; nline++)
233: {
234: if (bpos != NULL_POSITION && pos <= bpos)
235: {
236: /*
237: * Surprise! The desired line is
238: * close enough to the current screen
239: * that we can just scroll there after all.
240: */
241: forw(sc_height-sline+nline-1, bpos, 1, 0, 0);
1.1.1.3 shadchin 242: #if HILITE_SEARCH
1.1.1.2 millert 243: if (show_attn)
244: repaint_hilite(1);
1.1.1.3 shadchin 245: #endif
1.1 etheisen 246: return;
247: }
248: pos = back_line(pos);
249: if (pos == NULL_POSITION)
250: {
251: /*
252: * Oops. Ran into the beginning of the file.
253: * Exit the loop here and rely on forw()
254: * below to draw the required number of
255: * blank lines at the top of the screen.
256: */
257: break;
258: }
259: }
260: lastmark();
261: squished = 0;
262: screen_trashed = 0;
263: forw(sc_height-1, pos, 1, 0, sline-nline);
264: } else
265: {
266: /*
267: * The desired line is before the current screen.
268: * Move forward in the file far enough so that we
269: * can call back() and put the desired line at the
270: * sline-th line on the screen.
271: */
272: for (nline = sline; nline < sc_height - 1; nline++)
273: {
274: pos = forw_line(pos);
275: if (pos == NULL_POSITION)
276: {
277: /*
278: * Ran into end of file.
279: * This shouldn't normally happen,
280: * but may if there is some kind of read error.
281: */
282: break;
283: }
284: if (pos >= tpos)
285: {
286: /*
287: * Surprise! The desired line is
288: * close enough to the current screen
289: * that we can just scroll there after all.
290: */
291: back(nline+1, tpos, 1, 0);
1.1.1.3 shadchin 292: #if HILITE_SEARCH
1.1.1.2 millert 293: if (show_attn)
294: repaint_hilite(1);
1.1.1.3 shadchin 295: #endif
1.1 etheisen 296: return;
297: }
298: }
299: lastmark();
1.1.1.3 shadchin 300: if (!top_scroll)
301: clear();
302: else
303: home();
1.1 etheisen 304: screen_trashed = 0;
305: add_back_pos(pos);
306: back(sc_height-1, pos, 1, 0);
307: }
308: }