0
|
1 /*
|
|
2 * High level routines dealing with getting lines of input
|
|
3 * from the file being viewed.
|
|
4 *
|
|
5 * When we speak of "lines" here, we mean PRINTABLE lines;
|
|
6 * lines processed with respect to the screen width.
|
|
7 * We use the term "raw line" to refer to lines simply
|
|
8 * delimited by newlines; not processed with respect to screen width.
|
|
9 */
|
|
10
|
|
11 #include "less.h"
|
|
12
|
|
13 extern int squeeze;
|
|
14 extern int chopline;
|
|
15 extern int sigs;
|
|
16
|
|
17 /*
|
|
18 * Get the next line.
|
|
19 * A "current" position is passed and a "new" position is returned.
|
|
20 * The current position is the position of the first character of
|
|
21 * a line. The new position is the position of the first character
|
|
22 * of the NEXT line. The line obtained is the line starting at curr_pos.
|
|
23 */
|
|
24 public POSITION
|
|
25 forw_line(curr_pos)
|
|
26 POSITION curr_pos;
|
|
27 {
|
|
28 POSITION new_pos;
|
|
29 register int c;
|
|
30 int blankline;
|
|
31 int endline;
|
|
32
|
|
33 if (curr_pos == NULL_POSITION || ch_seek(curr_pos))
|
|
34 {
|
|
35 null_line();
|
|
36 return (NULL_POSITION);
|
|
37 }
|
|
38
|
|
39 prewind();
|
|
40 plinenum(curr_pos);
|
|
41 (void) ch_seek(curr_pos);
|
|
42
|
|
43 c = ch_forw_get();
|
|
44 if (c == EOI)
|
|
45 {
|
|
46 null_line();
|
|
47 return (NULL_POSITION);
|
|
48 }
|
|
49 blankline = (c == '\n' || c == '\r');
|
|
50
|
|
51 for (;;)
|
|
52 {
|
|
53 if (sigs)
|
|
54 {
|
|
55 null_line();
|
|
56 return (NULL_POSITION);
|
|
57 }
|
|
58 if (c == '\n' || c == EOI)
|
|
59 {
|
|
60 /*
|
|
61 * End of the line.
|
|
62 */
|
|
63 new_pos = ch_tell();
|
|
64 endline = 1;
|
|
65 break;
|
|
66 }
|
|
67
|
|
68 /*
|
|
69 * Append the char to the line and get the next char.
|
|
70 */
|
|
71 if (pappend(c))
|
|
72 {
|
|
73 /*
|
|
74 * The char won't fit in the line; the line
|
|
75 * is too long to print in the screen width.
|
|
76 * End the line here.
|
|
77 */
|
|
78 if (chopline)
|
|
79 {
|
|
80 do
|
|
81 {
|
|
82 c = ch_forw_get();
|
|
83 } while (c != '\n' && c != EOI);
|
|
84 new_pos = ch_tell();
|
|
85 endline = 1;
|
|
86 } else
|
|
87 {
|
|
88 new_pos = ch_tell() - 1;
|
|
89 endline = 0;
|
|
90 }
|
|
91 break;
|
|
92 }
|
|
93 c = ch_forw_get();
|
|
94 }
|
|
95 pdone(endline);
|
|
96
|
|
97 if (squeeze && blankline)
|
|
98 {
|
|
99 /*
|
|
100 * This line is blank.
|
|
101 * Skip down to the last contiguous blank line
|
|
102 * and pretend it is the one which we are returning.
|
|
103 */
|
|
104 while ((c = ch_forw_get()) == '\n' || c == '\r')
|
|
105 if (sigs)
|
|
106 {
|
|
107 null_line();
|
|
108 return (NULL_POSITION);
|
|
109 }
|
|
110 if (c != EOI)
|
|
111 (void) ch_back_get();
|
|
112 new_pos = ch_tell();
|
|
113 }
|
|
114
|
|
115 return (new_pos);
|
|
116 }
|
|
117
|
|
118 /*
|
|
119 * Get the previous line.
|
|
120 * A "current" position is passed and a "new" position is returned.
|
|
121 * The current position is the position of the first character of
|
|
122 * a line. The new position is the position of the first character
|
|
123 * of the PREVIOUS line. The line obtained is the one starting at new_pos.
|
|
124 */
|
|
125 public POSITION
|
|
126 back_line(curr_pos)
|
|
127 POSITION curr_pos;
|
|
128 {
|
|
129 POSITION new_pos, begin_new_pos;
|
|
130 int c;
|
|
131 int endline;
|
|
132
|
|
133 if (curr_pos == NULL_POSITION || curr_pos <= ch_zero() ||
|
|
134 ch_seek(curr_pos-1))
|
|
135 {
|
|
136 null_line();
|
|
137 return (NULL_POSITION);
|
|
138 }
|
|
139
|
|
140 if (squeeze)
|
|
141 {
|
|
142 /*
|
|
143 * Find out if the "current" line was blank.
|
|
144 */
|
|
145 (void) ch_forw_get(); /* Skip the newline */
|
|
146 c = ch_forw_get(); /* First char of "current" line */
|
|
147 (void) ch_back_get(); /* Restore our position */
|
|
148 (void) ch_back_get();
|
|
149
|
|
150 if (c == '\n')
|
|
151 {
|
|
152 /*
|
|
153 * The "current" line was blank.
|
|
154 * Skip over any preceding blank lines,
|
|
155 * since we skipped them in forw_line().
|
|
156 */
|
|
157 while ((c = ch_back_get()) == '\n' || c == '\r')
|
|
158 if (sigs)
|
|
159 {
|
|
160 null_line();
|
|
161 return (NULL_POSITION);
|
|
162 }
|
|
163 if (c == EOI)
|
|
164 {
|
|
165 null_line();
|
|
166 return (NULL_POSITION);
|
|
167 }
|
|
168 (void) ch_forw_get();
|
|
169 }
|
|
170 }
|
|
171
|
|
172 /*
|
|
173 * Scan backwards until we hit the beginning of the line.
|
|
174 */
|
|
175 for (;;)
|
|
176 {
|
|
177 if (sigs)
|
|
178 {
|
|
179 null_line();
|
|
180 return (NULL_POSITION);
|
|
181 }
|
|
182 c = ch_back_get();
|
|
183 if (c == '\n')
|
|
184 {
|
|
185 /*
|
|
186 * This is the newline ending the previous line.
|
|
187 * We have hit the beginning of the line.
|
|
188 */
|
|
189 new_pos = ch_tell() + 1;
|
|
190 break;
|
|
191 }
|
|
192 if (c == EOI)
|
|
193 {
|
|
194 /*
|
|
195 * We have hit the beginning of the file.
|
|
196 * This must be the first line in the file.
|
|
197 * This must, of course, be the beginning of the line.
|
|
198 */
|
|
199 new_pos = ch_tell();
|
|
200 break;
|
|
201 }
|
|
202 }
|
|
203
|
|
204 /*
|
|
205 * Now scan forwards from the beginning of this line.
|
|
206 * We keep discarding "printable lines" (based on screen width)
|
|
207 * until we reach the curr_pos.
|
|
208 *
|
|
209 * {{ This algorithm is pretty inefficient if the lines
|
|
210 * are much longer than the screen width,
|
|
211 * but I don't know of any better way. }}
|
|
212 */
|
|
213 if (ch_seek(new_pos))
|
|
214 {
|
|
215 null_line();
|
|
216 return (NULL_POSITION);
|
|
217 }
|
|
218 endline = 0;
|
|
219 loop:
|
|
220 begin_new_pos = new_pos;
|
|
221 prewind();
|
|
222 plinenum(new_pos);
|
|
223 (void) ch_seek(new_pos);
|
|
224
|
|
225 do
|
|
226 {
|
|
227 c = ch_forw_get();
|
|
228 if (c == EOI || sigs)
|
|
229 {
|
|
230 null_line();
|
|
231 return (NULL_POSITION);
|
|
232 }
|
|
233 new_pos++;
|
|
234 if (c == '\n')
|
|
235 {
|
|
236 endline = 1;
|
|
237 break;
|
|
238 }
|
|
239 if (pappend(c))
|
|
240 {
|
|
241 /*
|
|
242 * Got a full printable line, but we haven't
|
|
243 * reached our curr_pos yet. Discard the line
|
|
244 * and start a new one.
|
|
245 */
|
|
246 if (chopline)
|
|
247 {
|
|
248 endline = 1;
|
|
249 break;
|
|
250 }
|
|
251 pdone(0);
|
|
252 (void) ch_back_get();
|
|
253 new_pos--;
|
|
254 goto loop;
|
|
255 }
|
|
256 } while (new_pos < curr_pos);
|
|
257
|
|
258 pdone(endline);
|
|
259
|
|
260 return (begin_new_pos);
|
|
261 }
|