comparison miscellany/less-177/input.c @ 0:bce86c4163a3

Initial revision
author kono
date Mon, 18 Apr 2005 23:46:02 +0900
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:bce86c4163a3
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 }