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