1 /* $NetBSD: input.c,v 1.3 2013/09/04 19:44:21 tron Exp $ */
4 * Copyright (C) 1984-2012 Mark Nudelman
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.
9 * For more information, see the README file.
14 * High level routines dealing with getting lines of input
15 * from the file being viewed.
17 * When we speak of "lines" here, we mean PRINTABLE lines;
18 * lines processed with respect to the screen width.
19 * We use the term "raw line" to refer to lines simply
20 * delimited by newlines; not processed with respect to screen width.
28 extern int quit_if_one_screen
;
30 extern int ignore_eoi
;
31 extern int status_col
;
32 extern POSITION start_attnpos
;
33 extern POSITION end_attnpos
;
35 extern int hilite_search
;
36 extern int size_linebuf
;
41 * A "current" position is passed and a "new" position is returned.
42 * The current position is the position of the first character of
43 * a line. The new position is the position of the first character
44 * of the NEXT line. The line obtained is the line starting at curr_pos.
58 if (curr_pos
== NULL_POSITION
)
61 return (NULL_POSITION
);
64 if (hilite_search
== OPT_ONPLUS
|| is_filtering() || status_col
)
66 * If we are ignoring EOI (command F), only prepare
67 * one line ahead, to avoid getting stuck waiting for
68 * slow data without displaying the data we already have.
69 * If we're not ignoring EOI, we *could* do the same, but
70 * for efficiency we prepare several lines ahead at once.
72 prep_hilite(curr_pos
, curr_pos
+ 3*size_linebuf
,
75 if (ch_seek(curr_pos
))
78 return (NULL_POSITION
);
82 * Step back to the beginning of the line.
90 return (NULL_POSITION
);
104 * Read forward again to the position we should start at.
108 (void) ch_seek(base_pos
);
110 while (new_pos
< curr_pos
)
115 return (NULL_POSITION
);
118 backchars
= pappend(c
, new_pos
);
123 new_pos
-= backchars
;
124 while (--backchars
>= 0)
125 (void) ch_back_get();
132 * Read the first character to display.
138 return (NULL_POSITION
);
140 blankline
= (c
== '\n' || c
== '\r');
143 * Read each character in the line and append to the line buffer.
150 return (NULL_POSITION
);
152 if (c
== '\n' || c
== EOI
)
157 backchars
= pflushmbc();
159 if (backchars
> 0 && !chopline
&& hshift
== 0)
161 new_pos
-= backchars
+ 1;
171 * Append the char to the line and get the next char.
173 backchars
= pappend(c
, ch_tell()-1);
177 * The char won't fit in the line; the line
178 * is too long to print in the screen width.
181 if (chopline
|| hshift
> 0)
188 return (NULL_POSITION
);
191 } while (c
!= '\n' && c
!= EOI
);
194 quit_if_one_screen
= FALSE
;
197 new_pos
= ch_tell() - backchars
;
208 if (is_filtered(base_pos
))
211 * We don't want to display this line.
218 if (status_col
&& is_hilited(base_pos
, ch_tell()-1, 1, NULL
))
222 if (squeeze
&& blankline
)
225 * This line is blank.
226 * Skip down to the last contiguous blank line
227 * and pretend it is the one which we are returning.
229 while ((c
= ch_forw_get()) == '\n' || c
== '\r')
233 return (NULL_POSITION
);
236 (void) ch_back_get();
244 * Get the previous line.
245 * A "current" position is passed and a "new" position is returned.
246 * The current position is the position of the first character of
247 * a line. The new position is the position of the first character
248 * of the PREVIOUS line. The line obtained is the one starting at new_pos.
254 POSITION new_pos
, begin_new_pos
, base_pos
;
260 if (curr_pos
== NULL_POSITION
|| curr_pos
<= ch_zero())
263 return (NULL_POSITION
);
266 if (hilite_search
== OPT_ONPLUS
|| is_filtering() || status_col
)
267 prep_hilite((curr_pos
< 3*size_linebuf
) ?
268 0 : curr_pos
- 3*size_linebuf
, curr_pos
, -1);
270 if (ch_seek(curr_pos
-1))
273 return (NULL_POSITION
);
279 * Find out if the "current" line was blank.
281 (void) ch_forw_get(); /* Skip the newline */
282 c
= ch_forw_get(); /* First char of "current" line */
283 (void) ch_back_get(); /* Restore our position */
284 (void) ch_back_get();
286 if (c
== '\n' || c
== '\r')
289 * The "current" line was blank.
290 * Skip over any preceding blank lines,
291 * since we skipped them in forw_line().
293 while ((c
= ch_back_get()) == '\n' || c
== '\r')
297 return (NULL_POSITION
);
302 return (NULL_POSITION
);
304 (void) ch_forw_get();
309 * Scan backwards until we hit the beginning of the line.
316 return (NULL_POSITION
);
322 * This is the newline ending the previous line.
323 * We have hit the beginning of the line.
325 base_pos
= ch_tell() + 1;
331 * We have hit the beginning of the file.
332 * This must be the first line in the file.
333 * This must, of course, be the beginning of the line.
335 base_pos
= ch_tell();
341 * Now scan forwards from the beginning of this line.
342 * We keep discarding "printable lines" (based on screen width)
343 * until we reach the curr_pos.
345 * {{ This algorithm is pretty inefficient if the lines
346 * are much longer than the screen width,
347 * but I don't know of any better way. }}
350 if (ch_seek(new_pos
))
353 return (NULL_POSITION
);
359 begin_new_pos
= new_pos
;
360 (void) ch_seek(new_pos
);
365 if (c
== EOI
|| ABORT_SIGS())
368 return (NULL_POSITION
);
373 backchars
= pflushmbc();
374 if (backchars
> 0 && !chopline
&& hshift
== 0)
382 backchars
= pappend(c
, ch_tell()-1);
386 * Got a full printable line, but we haven't
387 * reached our curr_pos yet. Discard the line
388 * and start a new one.
390 if (chopline
|| hshift
> 0)
393 quit_if_one_screen
= FALSE
;
398 while (backchars
-- > 0)
400 (void) ch_back_get();
405 } while (new_pos
< curr_pos
);
410 if (is_filtered(base_pos
))
413 * We don't want to display this line.
414 * Get the previous line.
416 curr_pos
= begin_new_pos
;
420 if (status_col
&& curr_pos
> 0 && is_hilited(base_pos
, curr_pos
-1, 1, NULL
))
424 return (begin_new_pos
);
436 if (pos
!= NULL_POSITION
)
445 if (c
!= '\n' && c
!= '\r')
455 if (c
== EOI
|| c
== '\n' || c
== '\r')