Annotation of src/usr.bin/less/forwback.c, Revision 1.10
1.1 etheisen 1: /*
1.9 shadchin 2: * Copyright (C) 1984-2012 Mark Nudelman
1.1 etheisen 3: *
1.5 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.9 shadchin 7: * For more information, see the README file.
1.1 etheisen 8: */
1.10 ! nicm 9: /*
! 10: * Modified for use with illumos.
! 11: * Copyright 2014 Garrett D'Amore <garrett@damore.org>
! 12: */
1.1 etheisen 13:
14: /*
15: * Primitives for displaying the file on the screen,
16: * scrolling either forward or backward.
17: */
18:
19: #include "less.h"
20: #include "position.h"
21:
1.10 ! nicm 22: int screen_trashed;
! 23: int squished;
! 24: int no_back_scroll = 0;
! 25: int forw_prompt;
1.1 etheisen 26:
1.8 millert 27: extern volatile sig_atomic_t sigs;
1.1 etheisen 28: extern int top_scroll;
29: extern int quiet;
30: extern int sc_width, sc_height;
31: extern int plusoption;
32: extern int forw_scroll;
33: extern int back_scroll;
34: extern int ignore_eoi;
1.5 millert 35: extern int clear_bg;
36: extern int final_attr;
1.7 shadchin 37: extern int oldbot;
1.1 etheisen 38: extern char *tagoption;
39:
40: /*
41: * Sound the bell to indicate user is trying to move past end of file.
42: */
1.10 ! nicm 43: static void
! 44: eof_bell(void)
1.1 etheisen 45: {
46: if (quiet == NOT_QUIET)
1.10 ! nicm 47: ring_bell();
1.1 etheisen 48: else
49: vbell();
50: }
51:
52: /*
1.7 shadchin 53: * Check to see if the end of file is currently displayed.
1.1 etheisen 54: */
1.10 ! nicm 55: int
! 56: eof_displayed(void)
1.1 etheisen 57: {
1.10 ! nicm 58: off_t pos;
1.1 etheisen 59:
60: if (ignore_eoi)
1.7 shadchin 61: return (0);
62:
1.10 ! nicm 63: if (ch_length() == -1)
1.7 shadchin 64: /*
65: * If the file length is not known,
66: * we can't possibly be displaying EOF.
67: */
68: return (0);
69:
1.1 etheisen 70: /*
71: * If the bottom line is empty, we are at EOF.
72: * If the bottom line ends at the file length,
73: * we must be just at EOF.
74: */
75: pos = position(BOTTOM_PLUS_ONE);
1.10 ! nicm 76: return (pos == -1 || pos == ch_length());
1.7 shadchin 77: }
78:
79: /*
80: * Check to see if the entire file is currently displayed.
81: */
1.10 ! nicm 82: int
! 83: entire_file_displayed(void)
1.7 shadchin 84: {
1.10 ! nicm 85: off_t pos;
1.7 shadchin 86:
87: /* Make sure last line of file is displayed. */
88: if (!eof_displayed())
89: return (0);
90:
91: /* Make sure first line of file is displayed. */
92: pos = position(0);
1.10 ! nicm 93: return (pos == -1 || pos == 0);
1.1 etheisen 94: }
95:
96: /*
97: * If the screen is "squished", repaint it.
98: * "Squished" means the first displayed line is not at the top
99: * of the screen; this can happen when we display a short file
100: * for the first time.
101: */
1.10 ! nicm 102: void
! 103: squish_check(void)
1.1 etheisen 104: {
105: if (!squished)
106: return;
107: squished = 0;
108: repaint();
109: }
110:
111: /*
1.10 ! nicm 112: * Display n lines, scrolling forward,
1.1 etheisen 113: * starting at position pos in the input file.
114: * "force" means display the n lines even if we hit end of file.
115: * "only_last" means display only the last screenful if n > screen size.
116: * "nblank" is the number of blank lines to draw before the first
1.10 ! nicm 117: * real line. If nblank > 0, the pos must be -1.
1.1 etheisen 118: * The first real line after the blanks will start at ch_zero().
119: */
1.10 ! nicm 120: void
! 121: forw(int n, off_t pos, int force, int only_last, int nblank)
1.1 etheisen 122: {
123: int nlines = 0;
124: int do_repaint;
125: static int first_time = 1;
126:
127: squish_check();
128:
129: /*
1.10 ! nicm 130: * do_repaint tells us not to display anything till the end,
1.1 etheisen 131: * then just repaint the entire screen.
1.10 ! nicm 132: * We repaint if we are supposed to display only the last
1.1 etheisen 133: * screenful and the request is for more than a screenful.
134: * Also if the request exceeds the forward scroll limit
135: * (but not if the request is for exactly a screenful, since
136: * repainting itself involves scrolling forward a screenful).
137: */
1.10 ! nicm 138: do_repaint = (only_last && n > sc_height-1) ||
! 139: (forw_scroll >= 0 && n > forw_scroll && n != sc_height-1);
1.1 etheisen 140:
1.10 ! nicm 141: if (!do_repaint) {
! 142: if (top_scroll && n >= sc_height - 1 && pos != ch_length()) {
1.1 etheisen 143: /*
144: * Start a new screen.
145: * {{ This is not really desirable if we happen
146: * to hit eof in the middle of this screen,
147: * but we don't yet know if that will happen. }}
148: */
1.5 millert 149: pos_clear();
150: add_forw_pos(pos);
151: force = 1;
1.10 ! nicm 152: do_clear();
1.1 etheisen 153: home();
154: }
155:
1.10 ! nicm 156: if (pos != position(BOTTOM_PLUS_ONE) || empty_screen()) {
1.1 etheisen 157: /*
158: * This is not contiguous with what is
1.10 ! nicm 159: * currently displayed. Clear the screen image
1.1 etheisen 160: * (position table) and start a new screen.
161: */
162: pos_clear();
163: add_forw_pos(pos);
164: force = 1;
1.10 ! nicm 165: if (top_scroll) {
! 166: do_clear();
1.1 etheisen 167: home();
1.10 ! nicm 168: } else if (!first_time) {
1.1 etheisen 169: putstr("...skipping...\n");
170: }
171: }
172: }
173:
1.10 ! nicm 174: while (--n >= 0) {
1.1 etheisen 175: /*
176: * Read the next line of input.
177: */
1.10 ! nicm 178: if (nblank > 0) {
1.1 etheisen 179: /*
1.10 ! nicm 180: * Still drawing blanks; don't get a line
1.1 etheisen 181: * from the file yet.
182: * If this is the last blank line, get ready to
183: * read a line starting at ch_zero() next time.
184: */
185: if (--nblank == 0)
186: pos = ch_zero();
1.10 ! nicm 187: } else {
! 188: /*
1.1 etheisen 189: * Get the next line from the file.
190: */
191: pos = forw_line(pos);
1.10 ! nicm 192: if (pos == -1) {
1.1 etheisen 193: /*
1.10 ! nicm 194: * End of file: stop here unless the top line
1.1 etheisen 195: * is still empty, or "force" is true.
1.5 millert 196: * Even if force is true, stop when the last
197: * line in the file reaches the top of screen.
1.1 etheisen 198: */
1.10 ! nicm 199: if (!force && position(TOP) != -1)
1.1 etheisen 200: break;
1.10 ! nicm 201: if (!empty_lines(0, 0) &&
1.5 millert 202: !empty_lines(1, 1) &&
1.10 ! nicm 203: empty_lines(2, sc_height-1))
1.5 millert 204: break;
1.1 etheisen 205: }
206: }
207: /*
208: * Add the position of the next line to the position table.
209: * Display the current line on the screen.
210: */
211: add_forw_pos(pos);
212: nlines++;
213: if (do_repaint)
214: continue;
215: /*
216: * If this is the first screen displayed and
217: * we hit an early EOF (i.e. before the requested
218: * number of lines), we "squish" the display down
219: * at the bottom of the screen.
220: * But don't do this if a + option or a -t option
221: * was given. These options can cause us to
222: * start the display after the beginning of the file,
223: * and it is not appropriate to squish in that case.
224: */
1.10 ! nicm 225: if (first_time && pos == -1 && !top_scroll &&
! 226: tagoption == NULL && !plusoption) {
1.1 etheisen 227: squished = 1;
228: continue;
229: }
230: put_line();
1.7 shadchin 231: forw_prompt = 1;
1.1 etheisen 232: }
233:
234: if (nlines == 0)
235: eof_bell();
236: else if (do_repaint)
237: repaint();
238: first_time = 0;
239: (void) currline(BOTTOM);
240: }
241:
242: /*
243: * Display n lines, scrolling backward.
244: */
1.10 ! nicm 245: void
! 246: back(int n, off_t pos, int force, int only_last)
1.1 etheisen 247: {
248: int nlines = 0;
249: int do_repaint;
250:
251: squish_check();
252: do_repaint = (n > get_back_scroll() || (only_last && n > sc_height-1));
1.10 ! nicm 253: while (--n >= 0) {
1.1 etheisen 254: /*
255: * Get the previous line of input.
256: */
257: pos = back_line(pos);
1.10 ! nicm 258: if (pos == -1) {
1.1 etheisen 259: /*
260: * Beginning of file: stop here unless "force" is true.
261: */
262: if (!force)
263: break;
264: }
265: /*
266: * Add the position of the previous line to the position table.
267: * Display the line on the screen.
268: */
269: add_back_pos(pos);
270: nlines++;
1.10 ! nicm 271: if (!do_repaint) {
1.1 etheisen 272: home();
273: add_line();
274: put_line();
275: }
276: }
277:
278: if (nlines == 0)
279: eof_bell();
280: else if (do_repaint)
281: repaint();
1.7 shadchin 282: else if (!oldbot)
283: lower_left();
1.1 etheisen 284: (void) currline(BOTTOM);
285: }
286:
287: /*
288: * Display n more lines, forward.
289: * Start just after the line currently displayed at the bottom of the screen.
290: */
1.10 ! nicm 291: void
! 292: forward(int n, int force, int only_last)
1.1 etheisen 293: {
1.10 ! nicm 294: off_t pos;
1.1 etheisen 295:
1.10 ! nicm 296: if (get_quit_at_eof() && eof_displayed() &&
! 297: !(ch_getflags() & CH_HELPFILE)) {
1.1 etheisen 298: /*
299: * If the -e flag is set and we're trying to go
300: * forward from end-of-file, go on to the next file.
301: */
302: if (edit_next(1))
303: quit(QUIT_OK);
304: return;
305: }
306:
307: pos = position(BOTTOM_PLUS_ONE);
1.10 ! nicm 308: if (pos == -1 && (!force || empty_lines(2, sc_height-1))) {
! 309: if (ignore_eoi) {
1.1 etheisen 310: /*
311: * ignore_eoi is to support A_F_FOREVER.
312: * Back up until there is a line at the bottom
313: * of the screen.
314: */
1.10 ! nicm 315: if (empty_screen()) {
1.1 etheisen 316: pos = ch_zero();
1.10 ! nicm 317: } else {
! 318: do {
1.1 etheisen 319: back(1, position(TOP), 1, 0);
320: pos = position(BOTTOM_PLUS_ONE);
1.10 ! nicm 321: } while (pos == -1);
1.1 etheisen 322: }
1.10 ! nicm 323: } else {
1.1 etheisen 324: eof_bell();
325: return;
326: }
327: }
328: forw(n, pos, force, only_last, 0);
329: }
330:
331: /*
332: * Display n more lines, backward.
333: * Start just before the line currently displayed at the top of the screen.
334: */
1.10 ! nicm 335: void
! 336: backward(int n, int force, int only_last)
1.1 etheisen 337: {
1.10 ! nicm 338: off_t pos;
1.1 etheisen 339:
340: pos = position(TOP);
1.10 ! nicm 341: if (pos == -1 && (!force || position(BOTTOM) == 0)) {
1.1 etheisen 342: eof_bell();
1.10 ! nicm 343: return;
1.1 etheisen 344: }
345: back(n, pos, force, only_last);
346: }
347:
348: /*
349: * Get the backwards scroll limit.
350: * Must call this function instead of just using the value of
351: * back_scroll, because the default case depends on sc_height and
352: * top_scroll, as well as back_scroll.
353: */
1.10 ! nicm 354: int
! 355: get_back_scroll(void)
1.1 etheisen 356: {
1.5 millert 357: if (no_back_scroll)
358: return (0);
1.1 etheisen 359: if (back_scroll >= 0)
360: return (back_scroll);
361: if (top_scroll)
362: return (sc_height - 2);
363: return (10000); /* infinity */
364: }