2 * Copyright (C) 1984-2021 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.
11 * High level routines dealing with getting lines of input
12 * from the file being viewed.
14 * When we speak of "lines" here, we mean PRINTABLE lines;
15 * lines processed with respect to the screen width.
16 * We use the term "raw line" to refer to lines simply
17 * delimited by newlines; not processed with respect to screen width.
25 extern int quit_if_one_screen;
27 extern int ignore_eoi;
28 extern int status_col;
29 extern POSITION start_attnpos;
30 extern POSITION end_attnpos;
32 extern int hilite_search;
33 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.
45 forw_line_seg(curr_pos, get_segpos)
58 if (curr_pos == NULL_POSITION)
61 return (NULL_POSITION);
64 if (hilite_search == OPT_ONPLUS || is_filtering() || status_col)
67 * If we are ignoring EOI (command F), only prepare
68 * one line ahead, to avoid getting stuck waiting for
69 * slow data without displaying the data we already have.
70 * If we're not ignoring EOI, we *could* do the same, but
71 * for efficiency we prepare several lines ahead at once.
73 prep_hilite(curr_pos, curr_pos + 3*size_linebuf,
75 curr_pos = next_unfiltered(curr_pos);
78 if (ch_seek(curr_pos))
81 return (NULL_POSITION);
85 * Step back to the beginning of the line.
93 return (NULL_POSITION);
100 (void) ch_forw_get();
107 * Read forward again to the position we should start at.
110 plinestart(base_pos);
111 (void) ch_seek(base_pos);
113 while (new_pos < curr_pos)
118 return (NULL_POSITION);
121 backchars = pappend(c, new_pos);
126 new_pos -= backchars;
127 while (--backchars >= 0)
128 (void) ch_back_get();
135 * Read the first character to display.
141 return (NULL_POSITION);
143 blankline = (c == '\n' || c == '\r');
146 * Read each character in the line and append to the line buffer.
154 return (NULL_POSITION);
156 if (c == '\n' || c == EOI)
161 backchars = pflushmbc();
163 if (backchars > 0 && !chopline && hshift == 0)
165 new_pos -= backchars + 1;
175 * Append the char to the line and get the next char.
177 backchars = pappend(c, ch_tell()-1);
181 * The char won't fit in the line; the line
182 * is too long to print in the screen width.
185 if ((chopline || hshift > 0) && !get_segpos)
187 /* Read to end of line. */
193 return (NULL_POSITION);
196 } while (c != '\n' && c != EOI);
199 quit_if_one_screen = FALSE;
203 new_pos = ch_tell() - backchars;
212 if (blankline && show_attn)
214 /* Add spurious space to carry possible attn hilite. */
215 pappend(' ', ch_tell()-1);
218 pdone(endline, chopped, 1);
221 if (is_filtered(base_pos))
224 * We don't want to display this line.
233 int attr = is_hilited_attr(base_pos, ch_tell()-1, 1, NULL);
235 set_status_col('*', attr);
239 if (squeeze && blankline)
242 * This line is blank.
243 * Skip down to the last contiguous blank line
244 * and pretend it is the one which we are returning.
246 while ((c = ch_forw_get()) == '\n' || c == '\r')
250 return (NULL_POSITION);
253 (void) ch_back_get();
264 return forw_line_seg(curr_pos, FALSE);
268 * Get the previous line.
269 * A "current" position is passed and a "new" position is returned.
270 * The current position is the position of the first character of
271 * a line. The new position is the position of the first character
272 * of the PREVIOUS line. The line obtained is the one starting at new_pos.
278 POSITION new_pos, begin_new_pos, base_pos;
285 if (curr_pos == NULL_POSITION || curr_pos <= ch_zero())
288 return (NULL_POSITION);
291 if (hilite_search == OPT_ONPLUS || is_filtering() || status_col)
292 prep_hilite((curr_pos < 3*size_linebuf) ?
293 0 : curr_pos - 3*size_linebuf, curr_pos, -1);
295 if (ch_seek(curr_pos-1))
298 return (NULL_POSITION);
304 * Find out if the "current" line was blank.
306 (void) ch_forw_get(); /* Skip the newline */
307 c = ch_forw_get(); /* First char of "current" line */
308 (void) ch_back_get(); /* Restore our position */
309 (void) ch_back_get();
311 if (c == '\n' || c == '\r')
314 * The "current" line was blank.
315 * Skip over any preceding blank lines,
316 * since we skipped them in forw_line().
318 while ((c = ch_back_get()) == '\n' || c == '\r')
322 return (NULL_POSITION);
327 return (NULL_POSITION);
329 (void) ch_forw_get();
334 * Scan backwards until we hit the beginning of the line.
341 return (NULL_POSITION);
347 * This is the newline ending the previous line.
348 * We have hit the beginning of the line.
350 base_pos = ch_tell() + 1;
356 * We have hit the beginning of the file.
357 * This must be the first line in the file.
358 * This must, of course, be the beginning of the line.
360 base_pos = ch_tell();
366 * Now scan forwards from the beginning of this line.
367 * We keep discarding "printable lines" (based on screen width)
368 * until we reach the curr_pos.
370 * {{ This algorithm is pretty inefficient if the lines
371 * are much longer than the screen width,
372 * but I don't know of any better way. }}
375 if (ch_seek(new_pos))
378 return (NULL_POSITION);
384 begin_new_pos = new_pos;
385 (void) ch_seek(new_pos);
391 if (c == EOI || ABORT_SIGS())
394 return (NULL_POSITION);
399 backchars = pflushmbc();
400 if (backchars > 0 && !chopline && hshift == 0)
408 backchars = pappend(c, ch_tell()-1);
412 * Got a full printable line, but we haven't
413 * reached our curr_pos yet. Discard the line
414 * and start a new one.
416 if (chopline || hshift > 0)
420 quit_if_one_screen = FALSE;
425 while (backchars-- > 0)
427 (void) ch_back_get();
432 } while (new_pos < curr_pos);
434 pdone(endline, chopped, 0);
437 if (is_filtered(base_pos))
440 * We don't want to display this line.
441 * Get the previous line.
443 curr_pos = begin_new_pos;
447 if (status_col && curr_pos > 0)
449 int attr = is_hilited_attr(base_pos, curr_pos-1, 1, NULL);
451 set_status_col('*', attr);
455 return (begin_new_pos);
467 if (pos != NULL_POSITION)
476 if (c == '\n' || c == '\r')
478 (void) ch_back_get();
487 if (c == EOI || c == '\n' || c == '\r')