11133e27eSPeter Avalos /*
2*320d7c8aSAaron LI * Copyright (C) 1984-2023 Mark Nudelman
31133e27eSPeter Avalos *
41133e27eSPeter Avalos * You may distribute under the terms of either the GNU General Public
51133e27eSPeter Avalos * License or the Less License, as specified in the README file.
61133e27eSPeter Avalos *
7e639dc31SJohn Marino * For more information, see the README file.
81133e27eSPeter Avalos */
91133e27eSPeter Avalos
101133e27eSPeter Avalos /*
111133e27eSPeter Avalos * High level routines dealing with getting lines of input
121133e27eSPeter Avalos * from the file being viewed.
131133e27eSPeter Avalos *
141133e27eSPeter Avalos * When we speak of "lines" here, we mean PRINTABLE lines;
151133e27eSPeter Avalos * lines processed with respect to the screen width.
161133e27eSPeter Avalos * We use the term "raw line" to refer to lines simply
171133e27eSPeter Avalos * delimited by newlines; not processed with respect to screen width.
181133e27eSPeter Avalos */
191133e27eSPeter Avalos
201133e27eSPeter Avalos #include "less.h"
211133e27eSPeter Avalos
221133e27eSPeter Avalos extern int squeeze;
231133e27eSPeter Avalos extern int hshift;
241133e27eSPeter Avalos extern int quit_if_one_screen;
251133e27eSPeter Avalos extern int sigs;
261133e27eSPeter Avalos extern int ignore_eoi;
271133e27eSPeter Avalos extern int status_col;
28*320d7c8aSAaron LI extern int wordwrap;
291133e27eSPeter Avalos extern POSITION start_attnpos;
301133e27eSPeter Avalos extern POSITION end_attnpos;
311133e27eSPeter Avalos #if HILITE_SEARCH
321133e27eSPeter Avalos extern int hilite_search;
331133e27eSPeter Avalos extern int size_linebuf;
340c7ad07eSAntonio Huete Jimenez extern int show_attn;
351133e27eSPeter Avalos #endif
361133e27eSPeter Avalos
371133e27eSPeter Avalos /*
38*320d7c8aSAaron LI * Set the status column.
39*320d7c8aSAaron LI * base Position of first char in line.
40*320d7c8aSAaron LI * disp First visible char.
41*320d7c8aSAaron LI * Different than base_pos if line is shifted.
42*320d7c8aSAaron LI * edisp Last visible char.
43*320d7c8aSAaron LI * eol End of line. Normally the newline.
44*320d7c8aSAaron LI * Different than edisp if line is chopped.
45*320d7c8aSAaron LI */
init_status_col(POSITION base_pos,POSITION disp_pos,POSITION edisp_pos,POSITION eol_pos)46*320d7c8aSAaron LI static void init_status_col(POSITION base_pos, POSITION disp_pos, POSITION edisp_pos, POSITION eol_pos)
47*320d7c8aSAaron LI {
48*320d7c8aSAaron LI int hl_before = (chop_line() && disp_pos != NULL_POSITION) ?
49*320d7c8aSAaron LI is_hilited_attr(base_pos, disp_pos, TRUE, NULL) : 0;
50*320d7c8aSAaron LI int hl_after = (chop_line()) ?
51*320d7c8aSAaron LI is_hilited_attr(edisp_pos, eol_pos, TRUE, NULL) : 0;
52*320d7c8aSAaron LI int attr;
53*320d7c8aSAaron LI char ch;
54*320d7c8aSAaron LI
55*320d7c8aSAaron LI if (hl_before && hl_after)
56*320d7c8aSAaron LI {
57*320d7c8aSAaron LI attr = hl_after;
58*320d7c8aSAaron LI ch = '=';
59*320d7c8aSAaron LI } else if (hl_before)
60*320d7c8aSAaron LI {
61*320d7c8aSAaron LI attr = hl_before;
62*320d7c8aSAaron LI ch = '<';
63*320d7c8aSAaron LI } else if (hl_after)
64*320d7c8aSAaron LI {
65*320d7c8aSAaron LI attr = hl_after;
66*320d7c8aSAaron LI ch = '>';
67*320d7c8aSAaron LI } else
68*320d7c8aSAaron LI {
69*320d7c8aSAaron LI attr = is_hilited_attr(base_pos, eol_pos, TRUE, NULL);
70*320d7c8aSAaron LI ch = '*';
71*320d7c8aSAaron LI }
72*320d7c8aSAaron LI if (attr)
73*320d7c8aSAaron LI set_status_col(ch, attr);
74*320d7c8aSAaron LI }
75*320d7c8aSAaron LI
76*320d7c8aSAaron LI /*
771133e27eSPeter Avalos * Get the next line.
781133e27eSPeter Avalos * A "current" position is passed and a "new" position is returned.
791133e27eSPeter Avalos * The current position is the position of the first character of
801133e27eSPeter Avalos * a line. The new position is the position of the first character
811133e27eSPeter Avalos * of the NEXT line. The line obtained is the line starting at curr_pos.
821133e27eSPeter Avalos */
forw_line_seg(POSITION curr_pos,int skipeol,int rscroll,int nochop)83*320d7c8aSAaron LI public POSITION forw_line_seg(POSITION curr_pos, int skipeol, int rscroll, int nochop)
841133e27eSPeter Avalos {
851133e27eSPeter Avalos POSITION base_pos;
861133e27eSPeter Avalos POSITION new_pos;
87*320d7c8aSAaron LI POSITION edisp_pos;
8802d62a0fSDaniel Fojt int c;
891133e27eSPeter Avalos int blankline;
901133e27eSPeter Avalos int endline;
9102d62a0fSDaniel Fojt int chopped;
921133e27eSPeter Avalos int backchars;
93*320d7c8aSAaron LI POSITION wrap_pos;
94*320d7c8aSAaron LI int skipped_leading;
951133e27eSPeter Avalos
968be36e5bSPeter Avalos get_forw_line:
971133e27eSPeter Avalos if (curr_pos == NULL_POSITION)
981133e27eSPeter Avalos {
991133e27eSPeter Avalos null_line();
1001133e27eSPeter Avalos return (NULL_POSITION);
1011133e27eSPeter Avalos }
1021133e27eSPeter Avalos #if HILITE_SEARCH
1038be36e5bSPeter Avalos if (hilite_search == OPT_ONPLUS || is_filtering() || status_col)
104fa0be7c5SJohn Marino {
1051133e27eSPeter Avalos /*
1061133e27eSPeter Avalos * If we are ignoring EOI (command F), only prepare
1071133e27eSPeter Avalos * one line ahead, to avoid getting stuck waiting for
1081133e27eSPeter Avalos * slow data without displaying the data we already have.
1091133e27eSPeter Avalos * If we're not ignoring EOI, we *could* do the same, but
1101133e27eSPeter Avalos * for efficiency we prepare several lines ahead at once.
1111133e27eSPeter Avalos */
1121133e27eSPeter Avalos prep_hilite(curr_pos, curr_pos + 3*size_linebuf,
1131133e27eSPeter Avalos ignore_eoi ? 1 : -1);
114fa0be7c5SJohn Marino curr_pos = next_unfiltered(curr_pos);
115fa0be7c5SJohn Marino }
1161133e27eSPeter Avalos #endif
1171133e27eSPeter Avalos if (ch_seek(curr_pos))
1181133e27eSPeter Avalos {
1191133e27eSPeter Avalos null_line();
1201133e27eSPeter Avalos return (NULL_POSITION);
1211133e27eSPeter Avalos }
1221133e27eSPeter Avalos
1238be36e5bSPeter Avalos /*
1248be36e5bSPeter Avalos * Step back to the beginning of the line.
1258be36e5bSPeter Avalos */
1261133e27eSPeter Avalos base_pos = curr_pos;
1271133e27eSPeter Avalos for (;;)
1281133e27eSPeter Avalos {
1291133e27eSPeter Avalos if (ABORT_SIGS())
1301133e27eSPeter Avalos {
1311133e27eSPeter Avalos null_line();
1321133e27eSPeter Avalos return (NULL_POSITION);
1331133e27eSPeter Avalos }
1341133e27eSPeter Avalos c = ch_back_get();
1351133e27eSPeter Avalos if (c == EOI)
1361133e27eSPeter Avalos break;
1371133e27eSPeter Avalos if (c == '\n')
1381133e27eSPeter Avalos {
1391133e27eSPeter Avalos (void) ch_forw_get();
1401133e27eSPeter Avalos break;
1411133e27eSPeter Avalos }
1421133e27eSPeter Avalos --base_pos;
1431133e27eSPeter Avalos }
1441133e27eSPeter Avalos
1458be36e5bSPeter Avalos /*
1468be36e5bSPeter Avalos * Read forward again to the position we should start at.
1478be36e5bSPeter Avalos */
1481133e27eSPeter Avalos prewind();
1490c7ad07eSAntonio Huete Jimenez plinestart(base_pos);
1501133e27eSPeter Avalos (void) ch_seek(base_pos);
1518be36e5bSPeter Avalos new_pos = base_pos;
1528be36e5bSPeter Avalos while (new_pos < curr_pos)
1531133e27eSPeter Avalos {
1541133e27eSPeter Avalos if (ABORT_SIGS())
1551133e27eSPeter Avalos {
1561133e27eSPeter Avalos null_line();
1571133e27eSPeter Avalos return (NULL_POSITION);
1581133e27eSPeter Avalos }
1591133e27eSPeter Avalos c = ch_forw_get();
1608be36e5bSPeter Avalos backchars = pappend(c, new_pos);
1618be36e5bSPeter Avalos new_pos++;
1621133e27eSPeter Avalos if (backchars > 0)
1631133e27eSPeter Avalos {
1641133e27eSPeter Avalos pshift_all();
165*320d7c8aSAaron LI if (wordwrap && (c == ' ' || c == '\t'))
166*320d7c8aSAaron LI {
167*320d7c8aSAaron LI do
168*320d7c8aSAaron LI {
169*320d7c8aSAaron LI new_pos++;
170*320d7c8aSAaron LI c = ch_forw_get();
171*320d7c8aSAaron LI } while (c == ' ' || c == '\t');
172*320d7c8aSAaron LI backchars = 1;
173*320d7c8aSAaron LI }
1748be36e5bSPeter Avalos new_pos -= backchars;
1751133e27eSPeter Avalos while (--backchars >= 0)
1761133e27eSPeter Avalos (void) ch_back_get();
1771133e27eSPeter Avalos }
1781133e27eSPeter Avalos }
1791133e27eSPeter Avalos (void) pflushmbc();
1801133e27eSPeter Avalos pshift_all();
1811133e27eSPeter Avalos
1828be36e5bSPeter Avalos /*
1838be36e5bSPeter Avalos * Read the first character to display.
1848be36e5bSPeter Avalos */
1851133e27eSPeter Avalos c = ch_forw_get();
1861133e27eSPeter Avalos if (c == EOI)
1871133e27eSPeter Avalos {
1881133e27eSPeter Avalos null_line();
1891133e27eSPeter Avalos return (NULL_POSITION);
1901133e27eSPeter Avalos }
1911133e27eSPeter Avalos blankline = (c == '\n' || c == '\r');
192*320d7c8aSAaron LI wrap_pos = NULL_POSITION;
193*320d7c8aSAaron LI skipped_leading = FALSE;
1941133e27eSPeter Avalos
1958be36e5bSPeter Avalos /*
1968be36e5bSPeter Avalos * Read each character in the line and append to the line buffer.
1978be36e5bSPeter Avalos */
19802d62a0fSDaniel Fojt chopped = FALSE;
1991133e27eSPeter Avalos for (;;)
2001133e27eSPeter Avalos {
2011133e27eSPeter Avalos if (ABORT_SIGS())
2021133e27eSPeter Avalos {
2031133e27eSPeter Avalos null_line();
2041133e27eSPeter Avalos return (NULL_POSITION);
2051133e27eSPeter Avalos }
2061133e27eSPeter Avalos if (c == '\n' || c == EOI)
2071133e27eSPeter Avalos {
2081133e27eSPeter Avalos /*
2091133e27eSPeter Avalos * End of the line.
2101133e27eSPeter Avalos */
2111133e27eSPeter Avalos backchars = pflushmbc();
2121133e27eSPeter Avalos new_pos = ch_tell();
2130c7ad07eSAntonio Huete Jimenez if (backchars > 0 && (nochop || !chop_line()) && hshift == 0)
2141133e27eSPeter Avalos {
2151133e27eSPeter Avalos new_pos -= backchars + 1;
2161133e27eSPeter Avalos endline = FALSE;
2171133e27eSPeter Avalos } else
2181133e27eSPeter Avalos endline = TRUE;
219*320d7c8aSAaron LI edisp_pos = new_pos;
2201133e27eSPeter Avalos break;
2211133e27eSPeter Avalos }
2221133e27eSPeter Avalos if (c != '\r')
2231133e27eSPeter Avalos blankline = 0;
2241133e27eSPeter Avalos
2251133e27eSPeter Avalos /*
2261133e27eSPeter Avalos * Append the char to the line and get the next char.
2271133e27eSPeter Avalos */
2281133e27eSPeter Avalos backchars = pappend(c, ch_tell()-1);
2291133e27eSPeter Avalos if (backchars > 0)
2301133e27eSPeter Avalos {
2311133e27eSPeter Avalos /*
2321133e27eSPeter Avalos * The char won't fit in the line; the line
2331133e27eSPeter Avalos * is too long to print in the screen width.
2341133e27eSPeter Avalos * End the line here.
2351133e27eSPeter Avalos */
2360c7ad07eSAntonio Huete Jimenez if (skipeol)
2371133e27eSPeter Avalos {
2380c7ad07eSAntonio Huete Jimenez /* Read to end of line. */
239*320d7c8aSAaron LI edisp_pos = ch_tell();
2401133e27eSPeter Avalos do
2411133e27eSPeter Avalos {
24225ce721eSPeter Avalos if (ABORT_SIGS())
24325ce721eSPeter Avalos {
24425ce721eSPeter Avalos null_line();
24525ce721eSPeter Avalos return (NULL_POSITION);
24625ce721eSPeter Avalos }
2471133e27eSPeter Avalos c = ch_forw_get();
2481133e27eSPeter Avalos } while (c != '\n' && c != EOI);
2491133e27eSPeter Avalos new_pos = ch_tell();
2501133e27eSPeter Avalos endline = TRUE;
2511133e27eSPeter Avalos quit_if_one_screen = FALSE;
25202d62a0fSDaniel Fojt chopped = TRUE;
2531133e27eSPeter Avalos } else
2541133e27eSPeter Avalos {
255*320d7c8aSAaron LI if (!wordwrap)
2561133e27eSPeter Avalos new_pos = ch_tell() - backchars;
257*320d7c8aSAaron LI else
258*320d7c8aSAaron LI {
259*320d7c8aSAaron LI /*
260*320d7c8aSAaron LI * We're word-wrapping, so go back to the last space.
261*320d7c8aSAaron LI * However, if it's the space itself that couldn't fit,
262*320d7c8aSAaron LI * simply ignore it and any subsequent spaces.
263*320d7c8aSAaron LI */
264*320d7c8aSAaron LI if (c == ' ' || c == '\t')
265*320d7c8aSAaron LI {
266*320d7c8aSAaron LI do
267*320d7c8aSAaron LI {
268*320d7c8aSAaron LI new_pos = ch_tell();
269*320d7c8aSAaron LI c = ch_forw_get();
270*320d7c8aSAaron LI } while (c == ' ' || c == '\t');
271*320d7c8aSAaron LI if (c == '\r')
272*320d7c8aSAaron LI c = ch_forw_get();
273*320d7c8aSAaron LI if (c == '\n')
274*320d7c8aSAaron LI new_pos = ch_tell();
275*320d7c8aSAaron LI } else if (wrap_pos == NULL_POSITION)
276*320d7c8aSAaron LI new_pos = ch_tell() - backchars;
277*320d7c8aSAaron LI else
278*320d7c8aSAaron LI {
279*320d7c8aSAaron LI new_pos = wrap_pos;
280*320d7c8aSAaron LI loadc();
281*320d7c8aSAaron LI }
282*320d7c8aSAaron LI }
2831133e27eSPeter Avalos endline = FALSE;
2841133e27eSPeter Avalos }
2851133e27eSPeter Avalos break;
2861133e27eSPeter Avalos }
287*320d7c8aSAaron LI if (wordwrap)
288*320d7c8aSAaron LI {
289*320d7c8aSAaron LI if (c == ' ' || c == '\t')
290*320d7c8aSAaron LI {
291*320d7c8aSAaron LI if (skipped_leading)
292*320d7c8aSAaron LI {
293*320d7c8aSAaron LI wrap_pos = ch_tell();
294*320d7c8aSAaron LI savec();
295*320d7c8aSAaron LI }
296*320d7c8aSAaron LI } else
297*320d7c8aSAaron LI skipped_leading = TRUE;
298*320d7c8aSAaron LI }
2991133e27eSPeter Avalos c = ch_forw_get();
3001133e27eSPeter Avalos }
3018be36e5bSPeter Avalos
3020c7ad07eSAntonio Huete Jimenez #if HILITE_SEARCH
3030c7ad07eSAntonio Huete Jimenez if (blankline && show_attn)
3040c7ad07eSAntonio Huete Jimenez {
3050c7ad07eSAntonio Huete Jimenez /* Add spurious space to carry possible attn hilite. */
3060c7ad07eSAntonio Huete Jimenez pappend(' ', ch_tell()-1);
3070c7ad07eSAntonio Huete Jimenez }
3080c7ad07eSAntonio Huete Jimenez #endif
3090c7ad07eSAntonio Huete Jimenez pdone(endline, rscroll && chopped, 1);
3108be36e5bSPeter Avalos
3118be36e5bSPeter Avalos #if HILITE_SEARCH
3128be36e5bSPeter Avalos if (is_filtered(base_pos))
3138be36e5bSPeter Avalos {
3148be36e5bSPeter Avalos /*
3158be36e5bSPeter Avalos * We don't want to display this line.
3168be36e5bSPeter Avalos * Get the next line.
3178be36e5bSPeter Avalos */
3188be36e5bSPeter Avalos curr_pos = new_pos;
3198be36e5bSPeter Avalos goto get_forw_line;
3208be36e5bSPeter Avalos }
3210c7ad07eSAntonio Huete Jimenez if (status_col)
322*320d7c8aSAaron LI init_status_col(base_pos, line_position(), edisp_pos, new_pos);
3238be36e5bSPeter Avalos #endif
3241133e27eSPeter Avalos
3251133e27eSPeter Avalos if (squeeze && blankline)
3261133e27eSPeter Avalos {
3271133e27eSPeter Avalos /*
3281133e27eSPeter Avalos * This line is blank.
3291133e27eSPeter Avalos * Skip down to the last contiguous blank line
3301133e27eSPeter Avalos * and pretend it is the one which we are returning.
3311133e27eSPeter Avalos */
3321133e27eSPeter Avalos while ((c = ch_forw_get()) == '\n' || c == '\r')
3331133e27eSPeter Avalos if (ABORT_SIGS())
3341133e27eSPeter Avalos {
3351133e27eSPeter Avalos null_line();
3361133e27eSPeter Avalos return (NULL_POSITION);
3371133e27eSPeter Avalos }
3381133e27eSPeter Avalos if (c != EOI)
3391133e27eSPeter Avalos (void) ch_back_get();
3401133e27eSPeter Avalos new_pos = ch_tell();
3411133e27eSPeter Avalos }
3421133e27eSPeter Avalos
3431133e27eSPeter Avalos return (new_pos);
3441133e27eSPeter Avalos }
3451133e27eSPeter Avalos
forw_line(POSITION curr_pos)346*320d7c8aSAaron LI public POSITION forw_line(POSITION curr_pos)
3470c7ad07eSAntonio Huete Jimenez {
3480c7ad07eSAntonio Huete Jimenez
3490c7ad07eSAntonio Huete Jimenez return forw_line_seg(curr_pos, (chop_line() || hshift > 0), TRUE, FALSE);
3500c7ad07eSAntonio Huete Jimenez }
3510c7ad07eSAntonio Huete Jimenez
3521133e27eSPeter Avalos /*
3531133e27eSPeter Avalos * Get the previous line.
3541133e27eSPeter Avalos * A "current" position is passed and a "new" position is returned.
3551133e27eSPeter Avalos * The current position is the position of the first character of
3561133e27eSPeter Avalos * a line. The new position is the position of the first character
3571133e27eSPeter Avalos * of the PREVIOUS line. The line obtained is the one starting at new_pos.
3581133e27eSPeter Avalos */
back_line(POSITION curr_pos)359*320d7c8aSAaron LI public POSITION back_line(POSITION curr_pos)
3601133e27eSPeter Avalos {
361*320d7c8aSAaron LI POSITION base_pos;
362*320d7c8aSAaron LI POSITION new_pos;
363*320d7c8aSAaron LI POSITION edisp_pos;
364*320d7c8aSAaron LI POSITION begin_new_pos;
3651133e27eSPeter Avalos int c;
3661133e27eSPeter Avalos int endline;
36702d62a0fSDaniel Fojt int chopped;
3681133e27eSPeter Avalos int backchars;
369*320d7c8aSAaron LI POSITION wrap_pos;
370*320d7c8aSAaron LI int skipped_leading;
3711133e27eSPeter Avalos
3728be36e5bSPeter Avalos get_back_line:
3731133e27eSPeter Avalos if (curr_pos == NULL_POSITION || curr_pos <= ch_zero())
3741133e27eSPeter Avalos {
3751133e27eSPeter Avalos null_line();
3761133e27eSPeter Avalos return (NULL_POSITION);
3771133e27eSPeter Avalos }
3781133e27eSPeter Avalos #if HILITE_SEARCH
3798be36e5bSPeter Avalos if (hilite_search == OPT_ONPLUS || is_filtering() || status_col)
3801133e27eSPeter Avalos prep_hilite((curr_pos < 3*size_linebuf) ?
3811133e27eSPeter Avalos 0 : curr_pos - 3*size_linebuf, curr_pos, -1);
3821133e27eSPeter Avalos #endif
3831133e27eSPeter Avalos if (ch_seek(curr_pos-1))
3841133e27eSPeter Avalos {
3851133e27eSPeter Avalos null_line();
3861133e27eSPeter Avalos return (NULL_POSITION);
3871133e27eSPeter Avalos }
3881133e27eSPeter Avalos
3891133e27eSPeter Avalos if (squeeze)
3901133e27eSPeter Avalos {
3911133e27eSPeter Avalos /*
3921133e27eSPeter Avalos * Find out if the "current" line was blank.
3931133e27eSPeter Avalos */
3941133e27eSPeter Avalos (void) ch_forw_get(); /* Skip the newline */
3951133e27eSPeter Avalos c = ch_forw_get(); /* First char of "current" line */
3961133e27eSPeter Avalos (void) ch_back_get(); /* Restore our position */
3971133e27eSPeter Avalos (void) ch_back_get();
3981133e27eSPeter Avalos
3991133e27eSPeter Avalos if (c == '\n' || c == '\r')
4001133e27eSPeter Avalos {
4011133e27eSPeter Avalos /*
4021133e27eSPeter Avalos * The "current" line was blank.
4031133e27eSPeter Avalos * Skip over any preceding blank lines,
4041133e27eSPeter Avalos * since we skipped them in forw_line().
4051133e27eSPeter Avalos */
4061133e27eSPeter Avalos while ((c = ch_back_get()) == '\n' || c == '\r')
4071133e27eSPeter Avalos if (ABORT_SIGS())
4081133e27eSPeter Avalos {
4091133e27eSPeter Avalos null_line();
4101133e27eSPeter Avalos return (NULL_POSITION);
4111133e27eSPeter Avalos }
4121133e27eSPeter Avalos if (c == EOI)
4131133e27eSPeter Avalos {
4141133e27eSPeter Avalos null_line();
4151133e27eSPeter Avalos return (NULL_POSITION);
4161133e27eSPeter Avalos }
4171133e27eSPeter Avalos (void) ch_forw_get();
4181133e27eSPeter Avalos }
4191133e27eSPeter Avalos }
4201133e27eSPeter Avalos
4211133e27eSPeter Avalos /*
4221133e27eSPeter Avalos * Scan backwards until we hit the beginning of the line.
4231133e27eSPeter Avalos */
4241133e27eSPeter Avalos for (;;)
4251133e27eSPeter Avalos {
4261133e27eSPeter Avalos if (ABORT_SIGS())
4271133e27eSPeter Avalos {
4281133e27eSPeter Avalos null_line();
4291133e27eSPeter Avalos return (NULL_POSITION);
4301133e27eSPeter Avalos }
4311133e27eSPeter Avalos c = ch_back_get();
4321133e27eSPeter Avalos if (c == '\n')
4331133e27eSPeter Avalos {
4341133e27eSPeter Avalos /*
4351133e27eSPeter Avalos * This is the newline ending the previous line.
4361133e27eSPeter Avalos * We have hit the beginning of the line.
4371133e27eSPeter Avalos */
4388be36e5bSPeter Avalos base_pos = ch_tell() + 1;
4391133e27eSPeter Avalos break;
4401133e27eSPeter Avalos }
4411133e27eSPeter Avalos if (c == EOI)
4421133e27eSPeter Avalos {
4431133e27eSPeter Avalos /*
4441133e27eSPeter Avalos * We have hit the beginning of the file.
4451133e27eSPeter Avalos * This must be the first line in the file.
4461133e27eSPeter Avalos * This must, of course, be the beginning of the line.
4471133e27eSPeter Avalos */
4488be36e5bSPeter Avalos base_pos = ch_tell();
4491133e27eSPeter Avalos break;
4501133e27eSPeter Avalos }
4511133e27eSPeter Avalos }
4521133e27eSPeter Avalos
4531133e27eSPeter Avalos /*
4541133e27eSPeter Avalos * Now scan forwards from the beginning of this line.
4551133e27eSPeter Avalos * We keep discarding "printable lines" (based on screen width)
4561133e27eSPeter Avalos * until we reach the curr_pos.
4571133e27eSPeter Avalos *
4581133e27eSPeter Avalos * {{ This algorithm is pretty inefficient if the lines
4591133e27eSPeter Avalos * are much longer than the screen width,
4601133e27eSPeter Avalos * but I don't know of any better way. }}
4611133e27eSPeter Avalos */
4628be36e5bSPeter Avalos new_pos = base_pos;
4631133e27eSPeter Avalos if (ch_seek(new_pos))
4641133e27eSPeter Avalos {
4651133e27eSPeter Avalos null_line();
4661133e27eSPeter Avalos return (NULL_POSITION);
4671133e27eSPeter Avalos }
4681133e27eSPeter Avalos endline = FALSE;
4691133e27eSPeter Avalos prewind();
4700c7ad07eSAntonio Huete Jimenez plinestart(new_pos);
4711133e27eSPeter Avalos loop:
472*320d7c8aSAaron LI wrap_pos = NULL_POSITION;
473*320d7c8aSAaron LI skipped_leading = FALSE;
4741133e27eSPeter Avalos begin_new_pos = new_pos;
4751133e27eSPeter Avalos (void) ch_seek(new_pos);
47602d62a0fSDaniel Fojt chopped = FALSE;
4771133e27eSPeter Avalos
478*320d7c8aSAaron LI for (;;)
4791133e27eSPeter Avalos {
4801133e27eSPeter Avalos c = ch_forw_get();
4811133e27eSPeter Avalos if (c == EOI || ABORT_SIGS())
4821133e27eSPeter Avalos {
4831133e27eSPeter Avalos null_line();
4841133e27eSPeter Avalos return (NULL_POSITION);
4851133e27eSPeter Avalos }
4861133e27eSPeter Avalos new_pos++;
4871133e27eSPeter Avalos if (c == '\n')
4881133e27eSPeter Avalos {
4891133e27eSPeter Avalos backchars = pflushmbc();
4900c7ad07eSAntonio Huete Jimenez if (backchars > 0 && !chop_line() && hshift == 0)
4911133e27eSPeter Avalos {
4921133e27eSPeter Avalos backchars++;
4931133e27eSPeter Avalos goto shift;
4941133e27eSPeter Avalos }
4951133e27eSPeter Avalos endline = TRUE;
496*320d7c8aSAaron LI edisp_pos = new_pos;
4971133e27eSPeter Avalos break;
4981133e27eSPeter Avalos }
4991133e27eSPeter Avalos backchars = pappend(c, ch_tell()-1);
5001133e27eSPeter Avalos if (backchars > 0)
5011133e27eSPeter Avalos {
5021133e27eSPeter Avalos /*
5031133e27eSPeter Avalos * Got a full printable line, but we haven't
5041133e27eSPeter Avalos * reached our curr_pos yet. Discard the line
5051133e27eSPeter Avalos * and start a new one.
5061133e27eSPeter Avalos */
5070c7ad07eSAntonio Huete Jimenez if (chop_line() || hshift > 0)
5081133e27eSPeter Avalos {
5091133e27eSPeter Avalos endline = TRUE;
51002d62a0fSDaniel Fojt chopped = TRUE;
5111133e27eSPeter Avalos quit_if_one_screen = FALSE;
512*320d7c8aSAaron LI edisp_pos = new_pos;
5131133e27eSPeter Avalos break;
5141133e27eSPeter Avalos }
5151133e27eSPeter Avalos shift:
516*320d7c8aSAaron LI if (!wordwrap)
5171133e27eSPeter Avalos {
518*320d7c8aSAaron LI pshift_all();
519*320d7c8aSAaron LI new_pos -= backchars;
520*320d7c8aSAaron LI } else
521*320d7c8aSAaron LI {
522*320d7c8aSAaron LI if (c == ' ' || c == '\t')
523*320d7c8aSAaron LI {
524*320d7c8aSAaron LI for (;;)
525*320d7c8aSAaron LI {
526*320d7c8aSAaron LI c = ch_forw_get();
527*320d7c8aSAaron LI if (c == ' ' || c == '\t')
528*320d7c8aSAaron LI new_pos++;
529*320d7c8aSAaron LI else
530*320d7c8aSAaron LI {
531*320d7c8aSAaron LI if (c == '\r')
532*320d7c8aSAaron LI {
533*320d7c8aSAaron LI c = ch_forw_get();
534*320d7c8aSAaron LI if (c == '\n')
535*320d7c8aSAaron LI new_pos++;
536*320d7c8aSAaron LI }
537*320d7c8aSAaron LI if (c == '\n')
538*320d7c8aSAaron LI new_pos++;
539*320d7c8aSAaron LI break;
540*320d7c8aSAaron LI }
541*320d7c8aSAaron LI }
542*320d7c8aSAaron LI if (new_pos >= curr_pos)
543*320d7c8aSAaron LI break;
544*320d7c8aSAaron LI pshift_all();
545*320d7c8aSAaron LI } else
546*320d7c8aSAaron LI {
547*320d7c8aSAaron LI pshift_all();
548*320d7c8aSAaron LI if (wrap_pos == NULL_POSITION)
549*320d7c8aSAaron LI new_pos -= backchars;
550*320d7c8aSAaron LI else
551*320d7c8aSAaron LI new_pos = wrap_pos;
552*320d7c8aSAaron LI }
5531133e27eSPeter Avalos }
5541133e27eSPeter Avalos goto loop;
5551133e27eSPeter Avalos }
556*320d7c8aSAaron LI if (wordwrap)
557*320d7c8aSAaron LI {
558*320d7c8aSAaron LI if (c == ' ' || c == '\t')
559*320d7c8aSAaron LI {
560*320d7c8aSAaron LI if (skipped_leading)
561*320d7c8aSAaron LI wrap_pos = new_pos;
562*320d7c8aSAaron LI } else
563*320d7c8aSAaron LI skipped_leading = TRUE;
564*320d7c8aSAaron LI }
565*320d7c8aSAaron LI if (new_pos >= curr_pos)
566*320d7c8aSAaron LI {
567*320d7c8aSAaron LI edisp_pos = new_pos;
568*320d7c8aSAaron LI break;
569*320d7c8aSAaron LI }
570*320d7c8aSAaron LI }
5711133e27eSPeter Avalos
57202d62a0fSDaniel Fojt pdone(endline, chopped, 0);
5738be36e5bSPeter Avalos
5748be36e5bSPeter Avalos #if HILITE_SEARCH
5758be36e5bSPeter Avalos if (is_filtered(base_pos))
5768be36e5bSPeter Avalos {
5778be36e5bSPeter Avalos /*
5788be36e5bSPeter Avalos * We don't want to display this line.
5798be36e5bSPeter Avalos * Get the previous line.
5808be36e5bSPeter Avalos */
5818be36e5bSPeter Avalos curr_pos = begin_new_pos;
5828be36e5bSPeter Avalos goto get_back_line;
5838be36e5bSPeter Avalos }
584*320d7c8aSAaron LI if (status_col)
585*320d7c8aSAaron LI init_status_col(base_pos, line_position(), edisp_pos, new_pos);
5868be36e5bSPeter Avalos #endif
5871133e27eSPeter Avalos
5881133e27eSPeter Avalos return (begin_new_pos);
5891133e27eSPeter Avalos }
5901133e27eSPeter Avalos
5911133e27eSPeter Avalos /*
5921133e27eSPeter Avalos * Set attnpos.
5931133e27eSPeter Avalos */
set_attnpos(POSITION pos)594*320d7c8aSAaron LI public void set_attnpos(POSITION pos)
5951133e27eSPeter Avalos {
5961133e27eSPeter Avalos int c;
5971133e27eSPeter Avalos
5981133e27eSPeter Avalos if (pos != NULL_POSITION)
5991133e27eSPeter Avalos {
6001133e27eSPeter Avalos if (ch_seek(pos))
6011133e27eSPeter Avalos return;
6021133e27eSPeter Avalos for (;;)
6031133e27eSPeter Avalos {
6041133e27eSPeter Avalos c = ch_forw_get();
6051133e27eSPeter Avalos if (c == EOI)
6061133e27eSPeter Avalos break;
607fa0be7c5SJohn Marino if (c == '\n' || c == '\r')
608fa0be7c5SJohn Marino {
609fa0be7c5SJohn Marino (void) ch_back_get();
610fa0be7c5SJohn Marino break;
611fa0be7c5SJohn Marino }
6121133e27eSPeter Avalos pos++;
6131133e27eSPeter Avalos }
614fa0be7c5SJohn Marino end_attnpos = pos;
615fa0be7c5SJohn Marino for (;;)
616fa0be7c5SJohn Marino {
617fa0be7c5SJohn Marino c = ch_back_get();
618fa0be7c5SJohn Marino if (c == EOI || c == '\n' || c == '\r')
619fa0be7c5SJohn Marino break;
620fa0be7c5SJohn Marino pos--;
621fa0be7c5SJohn Marino }
6221133e27eSPeter Avalos }
6231133e27eSPeter Avalos start_attnpos = pos;
6241133e27eSPeter Avalos }
625