"SfR Fresh" - the SfR Freeware/Shareware Archive 
Member "less-424/forwback.c" of archive less-424.tar.gz:
As a special service "SfR Fresh" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting with prefixed line numbers.
Alternatively you can here view or download the uninterpreted source code file.
That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
1 /*
2 * Copyright (C) 1984-2008 Mark Nudelman
3 *
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.
6 *
7 * For more information about less, or for information on how to
8 * contact the author, see the README file.
9 */
10
11
12 /*
13 * Primitives for displaying the file on the screen,
14 * scrolling either forward or backward.
15 */
16
17 #include "less.h"
18 #include "position.h"
19
20 public int screen_trashed;
21 public int squished;
22 public int no_back_scroll = 0;
23 public int forw_prompt;
24
25 extern int sigs;
26 extern int top_scroll;
27 extern int quiet;
28 extern int sc_width, sc_height;
29 extern int plusoption;
30 extern int forw_scroll;
31 extern int back_scroll;
32 extern int ignore_eoi;
33 extern int clear_bg;
34 extern int final_attr;
35 extern int oldbot;
36 #if TAGS
37 extern char *tagoption;
38 #endif
39
40 /*
41 * Sound the bell to indicate user is trying to move past end of file.
42 */
43 static void
44 eof_bell()
45 {
46 if (quiet == NOT_QUIET)
47 bell();
48 else
49 vbell();
50 }
51
52 /*
53 * Check to see if the end of file is currently displayed.
54 */
55 public int
56 eof_displayed()
57 {
58 POSITION pos;
59
60 if (ignore_eoi)
61 return (0);
62
63 if (ch_length() == NULL_POSITION)
64 /*
65 * If the file length is not known,
66 * we can't possibly be displaying EOF.
67 */
68 return (0);
69
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);
76 return (pos == NULL_POSITION || pos == ch_length());
77 }
78
79 /*
80 * Check to see if the entire file is currently displayed.
81 */
82 public int
83 entire_file_displayed()
84 {
85 POSITION pos;
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);
93 return (pos == NULL_POSITION || pos == 0);
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 */
102 public void
103 squish_check()
104 {
105 if (!squished)
106 return;
107 squished = 0;
108 repaint();
109 }
110
111 /*
112 * Display n lines, scrolling forward,
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
117 * real line. If nblank > 0, the pos must be NULL_POSITION.
118 * The first real line after the blanks will start at ch_zero().
119 */
120 public void
121 forw(n, pos, force, only_last, nblank)
122 register int n;
123 POSITION pos;
124 int force;
125 int only_last;
126 int nblank;
127 {
128 int eof = 0;
129 int nlines = 0;
130 int do_repaint;
131 static int first_time = 1;
132
133 squish_check();
134
135 /*
136 * do_repaint tells us not to display anything till the end,
137 * then just repaint the entire screen.
138 * We repaint if we are supposed to display only the last
139 * screenful and the request is for more than a screenful.
140 * Also if the request exceeds the forward scroll limit
141 * (but not if the request is for exactly a screenful, since
142 * repainting itself involves scrolling forward a screenful).
143 */
144 do_repaint = (only_last && n > sc_height-1) ||
145 (forw_scroll >= 0 && n > forw_scroll && n != sc_height-1);
146
147 if (!do_repaint)
148 {
149 if (top_scroll && n >= sc_height - 1 && pos != ch_length())
150 {
151 /*
152 * Start a new screen.
153 * {{ This is not really desirable if we happen
154 * to hit eof in the middle of this screen,
155 * but we don't yet know if that will happen. }}
156 */
157 pos_clear();
158 add_forw_pos(pos);
159 force = 1;
160 clear();
161 home();
162 }
163
164 if (pos != position(BOTTOM_PLUS_ONE) || empty_screen())
165 {
166 /*
167 * This is not contiguous with what is
168 * currently displayed. Clear the screen image
169 * (position table) and start a new screen.
170 */
171 pos_clear();
172 add_forw_pos(pos);
173 force = 1;
174 if (top_scroll)
175 {
176 clear();
177 home();
178 } else if (!first_time)
179 {
180 putstr("...skipping...\n");
181 }
182 }
183 }
184
185 while (--n >= 0)
186 {
187 /*
188 * Read the next line of input.
189 */
190 if (nblank > 0)
191 {
192 /*
193 * Still drawing blanks; don't get a line
194 * from the file yet.
195 * If this is the last blank line, get ready to
196 * read a line starting at ch_zero() next time.
197 */
198 if (--nblank == 0)
199 pos = ch_zero();
200 } else
201 {
202 /*
203 * Get the next line from the file.
204 */
205 pos = forw_line(pos);
206 if (pos == NULL_POSITION)
207 {
208 /*
209 * End of file: stop here unless the top line
210 * is still empty, or "force" is true.
211 * Even if force is true, stop when the last
212 * line in the file reaches the top of screen.
213 */
214 eof = 1;
215 if (!force && position(TOP) != NULL_POSITION)
216 break;
217 if (!empty_lines(0, 0) &&
218 !empty_lines(1, 1) &&
219 empty_lines(2, sc_height-1))
220 break;
221 }
222 }
223 /*
224 * Add the position of the next line to the position table.
225 * Display the current line on the screen.
226 */
227 add_forw_pos(pos);
228 nlines++;
229 if (do_repaint)
230 continue;
231 /*
232 * If this is the first screen displayed and
233 * we hit an early EOF (i.e. before the requested
234 * number of lines), we "squish" the display down
235 * at the bottom of the screen.
236 * But don't do this if a + option or a -t option
237 * was given. These options can cause us to
238 * start the display after the beginning of the file,
239 * and it is not appropriate to squish in that case.
240 */
241 if (first_time && pos == NULL_POSITION && !top_scroll &&
242 #if TAGS
243 tagoption == NULL &&
244 #endif
245 !plusoption)
246 {
247 squished = 1;
248 continue;
249 }
250 put_line();
251 #if 0
252 /* {{
253 * Can't call clear_eol here. The cursor might be at end of line
254 * on an ignaw terminal, so clear_eol would clear the last char
255 * of the current line instead of all of the next line.
256 * If we really need to do this on clear_bg terminals, we need
257 * to find a better way.
258 * }}
259 */
260 if (clear_bg && apply_at_specials(final_attr) != AT_NORMAL)
261 {
262 /*
263 * Writing the last character on the last line
264 * of the display may have scrolled the screen.
265 * If we were in standout mode, clear_bg terminals
266 * will fill the new line with the standout color.
267 * Now we're in normal mode again, so clear the line.
268 */
269 clear_eol();
270 }
271 #endif
272 forw_prompt = 1;
273 }
274
275 if (nlines == 0)
276 eof_bell();
277 else if (do_repaint)
278 repaint();
279 first_time = 0;
280 (void) currline(BOTTOM);
281 }
282
283 /*
284 * Display n lines, scrolling backward.
285 */
286 public void
287 back(n, pos, force, only_last)
288 register int n;
289 POSITION pos;
290 int force;
291 int only_last;
292 {
293 int nlines = 0;
294 int do_repaint;
295
296 squish_check();
297 do_repaint = (n > get_back_scroll() || (only_last && n > sc_height-1));
298 while (--n >= 0)
299 {
300 /*
301 * Get the previous line of input.
302 */
303 pos = back_line(pos);
304 if (pos == NULL_POSITION)
305 {
306 /*
307 * Beginning of file: stop here unless "force" is true.
308 */
309 if (!force)
310 break;
311 }
312 /*
313 * Add the position of the previous line to the position table.
314 * Display the line on the screen.
315 */
316 add_back_pos(pos);
317 nlines++;
318 if (!do_repaint)
319 {
320 home();
321 add_line();
322 put_line();
323 }
324 }
325
326 if (nlines == 0)
327 eof_bell();
328 else if (do_repaint)
329 repaint();
330 else if (!oldbot)
331 lower_left();
332 (void) currline(BOTTOM);
333 }
334
335 /*
336 * Display n more lines, forward.
337 * Start just after the line currently displayed at the bottom of the screen.
338 */
339 public void
340 forward(n, force, only_last)
341 int n;
342 int force;
343 int only_last;
344 {
345 POSITION pos;
346
347 if (get_quit_at_eof() && eof_displayed() && !(ch_getflags() & CH_HELPFILE))
348 {
349 /*
350 * If the -e flag is set and we're trying to go
351 * forward from end-of-file, go on to the next file.
352 */
353 if (edit_next(1))
354 quit(QUIT_OK);
355 return;
356 }
357
358 pos = position(BOTTOM_PLUS_ONE);
359 if (pos == NULL_POSITION && (!force || empty_lines(2, sc_height-1)))
360 {
361 if (ignore_eoi)
362 {
363 /*
364 * ignore_eoi is to support A_F_FOREVER.
365 * Back up until there is a line at the bottom
366 * of the screen.
367 */
368 if (empty_screen())
369 pos = ch_zero();
370 else
371 {
372 do
373 {
374 back(1, position(TOP), 1, 0);
375 pos = position(BOTTOM_PLUS_ONE);
376 } while (pos == NULL_POSITION);
377 }
378 } else
379 {
380 eof_bell();
381 return;
382 }
383 }
384 forw(n, pos, force, only_last, 0);
385 }
386
387 /*
388 * Display n more lines, backward.
389 * Start just before the line currently displayed at the top of the screen.
390 */
391 public void
392 backward(n, force, only_last)
393 int n;
394 int force;
395 int only_last;
396 {
397 POSITION pos;
398
399 pos = position(TOP);
400 if (pos == NULL_POSITION && (!force || position(BOTTOM) == 0))
401 {
402 eof_bell();
403 return;
404 }
405 back(n, pos, force, only_last);
406 }
407
408 /*
409 * Get the backwards scroll limit.
410 * Must call this function instead of just using the value of
411 * back_scroll, because the default case depends on sc_height and
412 * top_scroll, as well as back_scroll.
413 */
414 public int
415 get_back_scroll()
416 {
417 if (no_back_scroll)
418 return (0);
419 if (back_scroll >= 0)
420 return (back_scroll);
421 if (top_scroll)
422 return (sc_height - 2);
423 return (10000); /* infinity */
424 }