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 |
|
|
* Routines dealing with the "position" table. |
14 |
|
|
* This is a table which tells the position (in the input file) of the |
15 |
|
|
* first char on each currently displayed line. |
16 |
|
|
* |
17 |
|
|
* {{ The position table is scrolled by moving all the entries. |
18 |
|
|
* Would be better to have a circular table |
19 |
|
|
* and just change a couple of pointers. }} |
20 |
|
|
*/ |
21 |
|
|
|
22 |
|
|
#include "less.h" |
23 |
|
|
#include "position.h" |
24 |
|
|
|
25 |
|
|
static off_t *table = NULL; /* The position table */ |
26 |
|
|
static int table_size; |
27 |
|
|
|
28 |
|
|
extern int sc_width, sc_height; |
29 |
|
|
|
30 |
|
|
/* |
31 |
|
|
* Return the starting file position of a line displayed on the screen. |
32 |
|
|
* The line may be specified as a line number relative to the top |
33 |
|
|
* of the screen, but is usually one of these special cases: |
34 |
|
|
* the top (first) line on the screen |
35 |
|
|
* the second line on the screen |
36 |
|
|
* the bottom line on the screen |
37 |
|
|
* the line after the bottom line on the screen |
38 |
|
|
*/ |
39 |
|
|
off_t |
40 |
|
|
position(int where) |
41 |
|
|
{ |
42 |
✓✓✗✓
|
14368 |
switch (where) { |
43 |
|
|
case BOTTOM: |
44 |
|
984 |
where = sc_height - 2; |
45 |
|
984 |
break; |
46 |
|
|
case BOTTOM_PLUS_ONE: |
47 |
|
3534 |
where = sc_height - 1; |
48 |
|
3534 |
break; |
49 |
|
|
case MIDDLE: |
50 |
|
|
where = (sc_height - 1) / 2; |
51 |
|
|
} |
52 |
|
4925 |
return (table[where]); |
53 |
|
|
} |
54 |
|
|
|
55 |
|
|
/* |
56 |
|
|
* Add a new file position to the bottom of the position table. |
57 |
|
|
*/ |
58 |
|
|
void |
59 |
|
|
add_forw_pos(off_t pos) |
60 |
|
|
{ |
61 |
|
|
int i; |
62 |
|
|
|
63 |
|
|
/* |
64 |
|
|
* Scroll the position table up. |
65 |
|
|
*/ |
66 |
✓✓ |
1724934 |
for (i = 1; i < sc_height; i++) |
67 |
|
823839 |
table[i-1] = table[i]; |
68 |
|
25752 |
table[sc_height - 1] = pos; |
69 |
|
25752 |
} |
70 |
|
|
|
71 |
|
|
/* |
72 |
|
|
* Add a new file position to the top of the position table. |
73 |
|
|
*/ |
74 |
|
|
void |
75 |
|
|
add_back_pos(off_t pos) |
76 |
|
|
{ |
77 |
|
|
int i; |
78 |
|
|
|
79 |
|
|
/* |
80 |
|
|
* Scroll the position table down. |
81 |
|
|
*/ |
82 |
✓✓ |
162408 |
for (i = sc_height - 1; i > 0; i--) |
83 |
|
77568 |
table[i] = table[i-1]; |
84 |
|
2424 |
table[0] = pos; |
85 |
|
2424 |
} |
86 |
|
|
|
87 |
|
|
/* |
88 |
|
|
* Initialize the position table, done whenever we clear the screen. |
89 |
|
|
*/ |
90 |
|
|
void |
91 |
|
|
pos_clear(void) |
92 |
|
|
{ |
93 |
|
|
int i; |
94 |
|
|
|
95 |
✓✓ |
65202 |
for (i = 0; i < sc_height; i++) |
96 |
|
31182 |
table[i] = -1; |
97 |
|
946 |
} |
98 |
|
|
|
99 |
|
|
/* |
100 |
|
|
* Allocate or reallocate the position table. |
101 |
|
|
*/ |
102 |
|
|
void |
103 |
|
|
pos_init(void) |
104 |
|
|
{ |
105 |
|
78 |
struct scrpos scrpos; |
106 |
|
|
|
107 |
✗✓ |
39 |
if (sc_height <= table_size) |
108 |
|
|
return; |
109 |
|
|
/* |
110 |
|
|
* If we already have a table, remember the first line in it |
111 |
|
|
* before we free it, so we can copy that line to the new table. |
112 |
|
|
*/ |
113 |
✗✓ |
39 |
if (table != NULL) { |
114 |
|
|
get_scrpos(&scrpos); |
115 |
|
|
free(table); |
116 |
|
|
} else { |
117 |
|
39 |
scrpos.pos = -1; |
118 |
|
|
} |
119 |
|
39 |
table = ecalloc(sc_height, sizeof (off_t)); |
120 |
|
39 |
table_size = sc_height; |
121 |
|
39 |
pos_clear(); |
122 |
✗✓ |
39 |
if (scrpos.pos != -1) |
123 |
|
|
table[scrpos.ln-1] = scrpos.pos; |
124 |
|
78 |
} |
125 |
|
|
|
126 |
|
|
/* |
127 |
|
|
* See if the byte at a specified position is currently on the screen. |
128 |
|
|
* Check the position table to see if the position falls within its range. |
129 |
|
|
* Return the position table entry if found, -1 if not. |
130 |
|
|
*/ |
131 |
|
|
int |
132 |
|
|
onscreen(off_t pos) |
133 |
|
|
{ |
134 |
|
|
int i; |
135 |
|
|
|
136 |
✓✓ |
274 |
if (pos < table[0]) |
137 |
|
2 |
return (-1); |
138 |
✓✓ |
8352 |
for (i = 1; i < sc_height; i++) |
139 |
✓✓ |
4050 |
if (pos < table[i]) |
140 |
|
9 |
return (i-1); |
141 |
|
126 |
return (-1); |
142 |
|
137 |
} |
143 |
|
|
|
144 |
|
|
/* |
145 |
|
|
* See if the entire screen is empty. |
146 |
|
|
*/ |
147 |
|
|
int |
148 |
|
|
empty_screen(void) |
149 |
|
|
{ |
150 |
|
3554 |
return (empty_lines(0, sc_height-1)); |
151 |
|
|
} |
152 |
|
|
|
153 |
|
|
int |
154 |
|
|
empty_lines(int s, int e) |
155 |
|
|
{ |
156 |
|
|
int i; |
157 |
|
|
|
158 |
✓✓ |
56420 |
for (i = s; i <= e; i++) |
159 |
✓✓✓✓
|
28780 |
if (table[i] != -1 && table[i] != 0) |
160 |
|
1705 |
return (0); |
161 |
|
241 |
return (1); |
162 |
|
1946 |
} |
163 |
|
|
|
164 |
|
|
/* |
165 |
|
|
* Get the current screen position. |
166 |
|
|
* The screen position consists of both a file position and |
167 |
|
|
* a screen line number where the file position is placed on the screen. |
168 |
|
|
* Normally the screen line number is 0, but if we are positioned |
169 |
|
|
* such that the top few lines are empty, we may have to set |
170 |
|
|
* the screen line to a number > 0. |
171 |
|
|
*/ |
172 |
|
|
void |
173 |
|
|
get_scrpos(struct scrpos *scrpos) |
174 |
|
|
{ |
175 |
|
|
int i; |
176 |
|
|
|
177 |
|
|
/* |
178 |
|
|
* Find the first line on the screen which has something on it, |
179 |
|
|
* and return the screen line number and the file position. |
180 |
|
|
*/ |
181 |
✓✓ |
8763 |
for (i = 0; i < sc_height; i++) |
182 |
✓✓ |
4118 |
if (table[i] != -1) { |
183 |
|
167 |
scrpos->ln = i+1; |
184 |
|
167 |
scrpos->pos = table[i]; |
185 |
|
167 |
return; |
186 |
|
|
} |
187 |
|
|
/* |
188 |
|
|
* The screen is empty. |
189 |
|
|
*/ |
190 |
|
120 |
scrpos->pos = -1; |
191 |
|
407 |
} |
192 |
|
|
|
193 |
|
|
/* |
194 |
|
|
* Adjust a screen line number to be a simple positive integer |
195 |
|
|
* in the range { 0 .. sc_height-2 }. |
196 |
|
|
* (The bottom line, sc_height-1, is reserved for prompts, etc.) |
197 |
|
|
* The given "sline" may be in the range { 1 .. sc_height-1 } |
198 |
|
|
* to refer to lines relative to the top of the screen (starting from 1), |
199 |
|
|
* or it may be in { -1 .. -(sc_height-1) } to refer to lines |
200 |
|
|
* relative to the bottom of the screen. |
201 |
|
|
*/ |
202 |
|
|
int |
203 |
|
|
adjsline(int sline) |
204 |
|
|
{ |
205 |
|
|
/* |
206 |
|
|
* Negative screen line number means |
207 |
|
|
* relative to the bottom of the screen. |
208 |
|
|
*/ |
209 |
✗✓ |
296 |
if (sline < 0) |
210 |
|
|
sline += sc_height; |
211 |
|
|
/* |
212 |
|
|
* Can't be less than 1 or greater than sc_height-1. |
213 |
|
|
*/ |
214 |
✓✓ |
148 |
if (sline <= 0) |
215 |
|
28 |
sline = 1; |
216 |
✗✓ |
148 |
if (sline >= sc_height) |
217 |
|
|
sline = sc_height - 1; |
218 |
|
|
/* |
219 |
|
|
* Return zero-based line number, not one-based. |
220 |
|
|
*/ |
221 |
|
148 |
return (sline-1); |
222 |
|
|
} |