2 * Copyright (C) 1984-2012 Mark Nudelman
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.
7 * For more information, see the README file.
12 * High level routines dealing with getting lines of input
13 * from the file being viewed.
15 * When we speak of "lines" here, we mean PRINTABLE lines;
16 * lines processed with respect to the screen width.
17 * We use the term "raw line" to refer to lines simply
18 * delimited by newlines; not processed with respect to screen width.
26 extern int quit_if_one_screen;
28 extern int ignore_eoi;
29 extern int status_col;
30 extern POSITION start_attnpos;
31 extern POSITION end_attnpos;
33 extern int hilite_search;
34 extern int size_linebuf;
39 * A "current" position is passed and a "new" position is returned.
40 * The current position is the position of the first character of
41 * a line. The new position is the position of the first character
42 * of the NEXT line. The line obtained is the line starting at curr_pos.
56 if (curr_pos == NULL_POSITION)
59 return (NULL_POSITION);
62 if (hilite_search == OPT_ONPLUS || is_filtering() || status_col)
64 * If we are ignoring EOI (command F), only prepare
65 * one line ahead, to avoid getting stuck waiting for
66 * slow data without displaying the data we already have.
67 * If we're not ignoring EOI, we *could* do the same, but
68 * for efficiency we prepare several lines ahead at once.
70 prep_hilite(curr_pos, curr_pos + 3*size_linebuf,
73 if (ch_seek(curr_pos))
76 return (NULL_POSITION);
80 * Step back to the beginning of the line.
88 return (NULL_POSITION);
102 * Read forward again to the position we should start at.
106 (void) ch_seek(base_pos);
108 while (new_pos < curr_pos)
113 return (NULL_POSITION);
116 backchars = pappend(c, new_pos);
121 new_pos -= backchars;
122 while (--backchars >= 0)
123 (void) ch_back_get();
130 * Read the first character to display.
136 return (NULL_POSITION);
138 blankline = (c == '\n' || c == '\r');
141 * Read each character in the line and append to the line buffer.
148 return (NULL_POSITION);
150 if (c == '\n' || c == EOI)
155 backchars = pflushmbc();
157 if (backchars > 0 && !chopline && hshift == 0)
159 new_pos -= backchars + 1;
169 * Append the char to the line and get the next char.
171 backchars = pappend(c, ch_tell()-1);
175 * The char won't fit in the line; the line
176 * is too long to print in the screen width.
179 if (chopline || hshift > 0)
186 return (NULL_POSITION);
189 } while (c != '\n' && c != EOI);
192 quit_if_one_screen = FALSE;
195 new_pos = ch_tell() - backchars;
206 if (is_filtered(base_pos))
209 * We don't want to display this line.
216 if (status_col && is_hilited(base_pos, ch_tell()-1, 1, NULL))
220 if (squeeze && blankline)
223 * This line is blank.
224 * Skip down to the last contiguous blank line
225 * and pretend it is the one which we are returning.
227 while ((c = ch_forw_get()) == '\n' || c == '\r')
231 return (NULL_POSITION);
234 (void) ch_back_get();
242 * Get the previous line.
243 * A "current" position is passed and a "new" position is returned.
244 * The current position is the position of the first character of
245 * a line. The new position is the position of the first character
246 * of the PREVIOUS line. The line obtained is the one starting at new_pos.
252 POSITION new_pos, begin_new_pos, base_pos;
258 if (curr_pos == NULL_POSITION || curr_pos <= ch_zero())
261 return (NULL_POSITION);
264 if (hilite_search == OPT_ONPLUS || is_filtering() || status_col)
265 prep_hilite((curr_pos < 3*size_linebuf) ?
266 0 : curr_pos - 3*size_linebuf, curr_pos, -1);
268 if (ch_seek(curr_pos-1))
271 return (NULL_POSITION);
277 * Find out if the "current" line was blank.
279 (void) ch_forw_get(); /* Skip the newline */
280 c = ch_forw_get(); /* First char of "current" line */
281 (void) ch_back_get(); /* Restore our position */
282 (void) ch_back_get();
284 if (c == '\n' || c == '\r')
287 * The "current" line was blank.
288 * Skip over any preceding blank lines,
289 * since we skipped them in forw_line().
291 while ((c = ch_back_get()) == '\n' || c == '\r')
295 return (NULL_POSITION);
300 return (NULL_POSITION);
302 (void) ch_forw_get();
307 * Scan backwards until we hit the beginning of the line.
314 return (NULL_POSITION);
320 * This is the newline ending the previous line.
321 * We have hit the beginning of the line.
323 base_pos = ch_tell() + 1;
329 * We have hit the beginning of the file.
330 * This must be the first line in the file.
331 * This must, of course, be the beginning of the line.
333 base_pos = ch_tell();
339 * Now scan forwards from the beginning of this line.
340 * We keep discarding "printable lines" (based on screen width)
341 * until we reach the curr_pos.
343 * {{ This algorithm is pretty inefficient if the lines
344 * are much longer than the screen width,
345 * but I don't know of any better way. }}
348 if (ch_seek(new_pos))
351 return (NULL_POSITION);
357 begin_new_pos = new_pos;
358 (void) ch_seek(new_pos);
363 if (c == EOI || ABORT_SIGS())
366 return (NULL_POSITION);
371 backchars = pflushmbc();
372 if (backchars > 0 && !chopline && hshift == 0)
380 backchars = pappend(c, ch_tell()-1);
384 * Got a full printable line, but we haven't
385 * reached our curr_pos yet. Discard the line
386 * and start a new one.
388 if (chopline || hshift > 0)
391 quit_if_one_screen = FALSE;
396 while (backchars-- > 0)
398 (void) ch_back_get();
403 } while (new_pos < curr_pos);
408 if (is_filtered(base_pos))
411 * We don't want to display this line.
412 * Get the previous line.
414 curr_pos = begin_new_pos;
418 if (status_col && curr_pos > 0 && is_hilited(base_pos, curr_pos-1, 1, NULL))
422 return (begin_new_pos);
434 if (pos != NULL_POSITION)
443 if (c != '\n' && c != '\r')
453 if (c == EOI || c == '\n' || c == '\r')