11133e27eSPeter Avalos /*
2*e433da38SAaron LI * Copyright (C) 1984-2024 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 ignore_eoi;
261133e27eSPeter Avalos extern int status_col;
27320d7c8aSAaron LI extern int wordwrap;
281133e27eSPeter Avalos extern POSITION start_attnpos;
291133e27eSPeter Avalos extern POSITION end_attnpos;
301133e27eSPeter Avalos #if HILITE_SEARCH
311133e27eSPeter Avalos extern int hilite_search;
32*e433da38SAaron LI extern size_t size_linebuf;
330c7ad07eSAntonio Huete Jimenez extern int show_attn;
341133e27eSPeter Avalos #endif
351133e27eSPeter Avalos
361133e27eSPeter Avalos /*
37320d7c8aSAaron LI * Set the status column.
38320d7c8aSAaron LI * base Position of first char in line.
39320d7c8aSAaron LI * disp First visible char.
40320d7c8aSAaron LI * Different than base_pos if line is shifted.
41320d7c8aSAaron LI * edisp Last visible char.
42320d7c8aSAaron LI * eol End of line. Normally the newline.
43320d7c8aSAaron LI * Different than edisp if line is chopped.
44320d7c8aSAaron LI */
init_status_col(POSITION base_pos,POSITION disp_pos,POSITION edisp_pos,POSITION eol_pos)45320d7c8aSAaron LI static void init_status_col(POSITION base_pos, POSITION disp_pos, POSITION edisp_pos, POSITION eol_pos)
46320d7c8aSAaron LI {
47320d7c8aSAaron LI int hl_before = (chop_line() && disp_pos != NULL_POSITION) ?
48320d7c8aSAaron LI is_hilited_attr(base_pos, disp_pos, TRUE, NULL) : 0;
49*e433da38SAaron LI int hl_after = (chop_line() && edisp_pos != NULL_POSITION) ?
50320d7c8aSAaron LI is_hilited_attr(edisp_pos, eol_pos, TRUE, NULL) : 0;
51320d7c8aSAaron LI int attr;
52320d7c8aSAaron LI char ch;
53320d7c8aSAaron LI
54320d7c8aSAaron LI if (hl_before && hl_after)
55320d7c8aSAaron LI {
56320d7c8aSAaron LI attr = hl_after;
57320d7c8aSAaron LI ch = '=';
58320d7c8aSAaron LI } else if (hl_before)
59320d7c8aSAaron LI {
60320d7c8aSAaron LI attr = hl_before;
61320d7c8aSAaron LI ch = '<';
62320d7c8aSAaron LI } else if (hl_after)
63320d7c8aSAaron LI {
64320d7c8aSAaron LI attr = hl_after;
65320d7c8aSAaron LI ch = '>';
66*e433da38SAaron LI } else if (disp_pos != NULL_POSITION)
67*e433da38SAaron LI {
68*e433da38SAaron LI attr = is_hilited_attr(disp_pos, edisp_pos, TRUE, NULL);
69*e433da38SAaron LI ch = '*';
70320d7c8aSAaron LI } else
71320d7c8aSAaron LI {
72*e433da38SAaron LI attr = 0;
73320d7c8aSAaron LI }
74320d7c8aSAaron LI if (attr)
75320d7c8aSAaron LI set_status_col(ch, attr);
76320d7c8aSAaron LI }
77320d7c8aSAaron LI
78320d7c8aSAaron LI /*
791133e27eSPeter Avalos * Get the next line.
801133e27eSPeter Avalos * A "current" position is passed and a "new" position is returned.
811133e27eSPeter Avalos * The current position is the position of the first character of
821133e27eSPeter Avalos * a line. The new position is the position of the first character
831133e27eSPeter Avalos * of the NEXT line. The line obtained is the line starting at curr_pos.
841133e27eSPeter Avalos */
forw_line_seg(POSITION curr_pos,lbool skipeol,lbool rscroll,lbool nochop)85*e433da38SAaron LI public POSITION forw_line_seg(POSITION curr_pos, lbool skipeol, lbool rscroll, lbool nochop)
861133e27eSPeter Avalos {
871133e27eSPeter Avalos POSITION base_pos;
881133e27eSPeter Avalos POSITION new_pos;
89320d7c8aSAaron LI POSITION edisp_pos;
9002d62a0fSDaniel Fojt int c;
91*e433da38SAaron LI lbool blankline;
92*e433da38SAaron LI lbool endline;
93*e433da38SAaron LI lbool chopped;
941133e27eSPeter Avalos int backchars;
95320d7c8aSAaron LI POSITION wrap_pos;
96*e433da38SAaron LI lbool skipped_leading;
971133e27eSPeter Avalos
988be36e5bSPeter Avalos get_forw_line:
991133e27eSPeter Avalos if (curr_pos == NULL_POSITION)
1001133e27eSPeter Avalos {
1011133e27eSPeter Avalos null_line();
1021133e27eSPeter Avalos return (NULL_POSITION);
1031133e27eSPeter Avalos }
1041133e27eSPeter Avalos #if HILITE_SEARCH
1058be36e5bSPeter Avalos if (hilite_search == OPT_ONPLUS || is_filtering() || status_col)
106fa0be7c5SJohn Marino {
1071133e27eSPeter Avalos /*
1081133e27eSPeter Avalos * If we are ignoring EOI (command F), only prepare
1091133e27eSPeter Avalos * one line ahead, to avoid getting stuck waiting for
1101133e27eSPeter Avalos * slow data without displaying the data we already have.
1111133e27eSPeter Avalos * If we're not ignoring EOI, we *could* do the same, but
1121133e27eSPeter Avalos * for efficiency we prepare several lines ahead at once.
1131133e27eSPeter Avalos */
114*e433da38SAaron LI prep_hilite(curr_pos, curr_pos + (POSITION) (3*size_linebuf), ignore_eoi ? 1 : -1);
115fa0be7c5SJohn Marino curr_pos = next_unfiltered(curr_pos);
116fa0be7c5SJohn Marino }
1171133e27eSPeter Avalos #endif
1181133e27eSPeter Avalos if (ch_seek(curr_pos))
1191133e27eSPeter Avalos {
1201133e27eSPeter Avalos null_line();
1211133e27eSPeter Avalos return (NULL_POSITION);
1221133e27eSPeter Avalos }
1231133e27eSPeter Avalos
1248be36e5bSPeter Avalos /*
1258be36e5bSPeter Avalos * Step back to the beginning of the line.
1268be36e5bSPeter Avalos */
1271133e27eSPeter Avalos base_pos = curr_pos;
1281133e27eSPeter Avalos for (;;)
1291133e27eSPeter Avalos {
1301133e27eSPeter Avalos c = ch_back_get();
1311133e27eSPeter Avalos if (c == EOI)
1321133e27eSPeter Avalos break;
1331133e27eSPeter Avalos if (c == '\n')
1341133e27eSPeter Avalos {
1351133e27eSPeter Avalos (void) ch_forw_get();
1361133e27eSPeter Avalos break;
1371133e27eSPeter Avalos }
1381133e27eSPeter Avalos --base_pos;
1391133e27eSPeter Avalos }
1401133e27eSPeter Avalos
1418be36e5bSPeter Avalos /*
1428be36e5bSPeter Avalos * Read forward again to the position we should start at.
1438be36e5bSPeter Avalos */
1441133e27eSPeter Avalos prewind();
1450c7ad07eSAntonio Huete Jimenez plinestart(base_pos);
1461133e27eSPeter Avalos (void) ch_seek(base_pos);
1478be36e5bSPeter Avalos new_pos = base_pos;
1488be36e5bSPeter Avalos while (new_pos < curr_pos)
1491133e27eSPeter Avalos {
150*e433da38SAaron LI c = ch_forw_get();
151*e433da38SAaron LI if (c == EOI)
1521133e27eSPeter Avalos {
1531133e27eSPeter Avalos null_line();
1541133e27eSPeter Avalos return (NULL_POSITION);
1551133e27eSPeter Avalos }
156*e433da38SAaron LI backchars = pappend((char) c, new_pos);
1578be36e5bSPeter Avalos new_pos++;
1581133e27eSPeter Avalos if (backchars > 0)
1591133e27eSPeter Avalos {
1601133e27eSPeter Avalos pshift_all();
161320d7c8aSAaron LI if (wordwrap && (c == ' ' || c == '\t'))
162320d7c8aSAaron LI {
163320d7c8aSAaron LI do
164320d7c8aSAaron LI {
165320d7c8aSAaron LI new_pos++;
166*e433da38SAaron LI c = ch_forw_get(); /* {{ what if c == EOI? }} */
167320d7c8aSAaron LI } while (c == ' ' || c == '\t');
168320d7c8aSAaron LI backchars = 1;
169320d7c8aSAaron LI }
1708be36e5bSPeter Avalos new_pos -= backchars;
1711133e27eSPeter Avalos while (--backchars >= 0)
1721133e27eSPeter Avalos (void) ch_back_get();
1731133e27eSPeter Avalos }
1741133e27eSPeter Avalos }
1751133e27eSPeter Avalos (void) pflushmbc();
1761133e27eSPeter Avalos pshift_all();
1771133e27eSPeter Avalos
1788be36e5bSPeter Avalos /*
1798be36e5bSPeter Avalos * Read the first character to display.
1808be36e5bSPeter Avalos */
1811133e27eSPeter Avalos c = ch_forw_get();
1821133e27eSPeter Avalos if (c == EOI)
1831133e27eSPeter Avalos {
1841133e27eSPeter Avalos null_line();
1851133e27eSPeter Avalos return (NULL_POSITION);
1861133e27eSPeter Avalos }
1871133e27eSPeter Avalos blankline = (c == '\n' || c == '\r');
188320d7c8aSAaron LI wrap_pos = NULL_POSITION;
189320d7c8aSAaron LI skipped_leading = FALSE;
1901133e27eSPeter Avalos
1918be36e5bSPeter Avalos /*
1928be36e5bSPeter Avalos * Read each character in the line and append to the line buffer.
1938be36e5bSPeter Avalos */
19402d62a0fSDaniel Fojt chopped = FALSE;
1951133e27eSPeter Avalos for (;;)
1961133e27eSPeter Avalos {
1971133e27eSPeter Avalos if (c == '\n' || c == EOI)
1981133e27eSPeter Avalos {
1991133e27eSPeter Avalos /*
2001133e27eSPeter Avalos * End of the line.
2011133e27eSPeter Avalos */
2021133e27eSPeter Avalos backchars = pflushmbc();
2031133e27eSPeter Avalos new_pos = ch_tell();
2040c7ad07eSAntonio Huete Jimenez if (backchars > 0 && (nochop || !chop_line()) && hshift == 0)
2051133e27eSPeter Avalos {
2061133e27eSPeter Avalos new_pos -= backchars + 1;
2071133e27eSPeter Avalos endline = FALSE;
2081133e27eSPeter Avalos } else
2091133e27eSPeter Avalos endline = TRUE;
210320d7c8aSAaron LI edisp_pos = new_pos;
2111133e27eSPeter Avalos break;
2121133e27eSPeter Avalos }
2131133e27eSPeter Avalos if (c != '\r')
214*e433da38SAaron LI blankline = FALSE;
2151133e27eSPeter Avalos
2161133e27eSPeter Avalos /*
2171133e27eSPeter Avalos * Append the char to the line and get the next char.
2181133e27eSPeter Avalos */
219*e433da38SAaron LI backchars = pappend((char) c, ch_tell()-1);
2201133e27eSPeter Avalos if (backchars > 0)
2211133e27eSPeter Avalos {
2221133e27eSPeter Avalos /*
2231133e27eSPeter Avalos * The char won't fit in the line; the line
2241133e27eSPeter Avalos * is too long to print in the screen width.
2251133e27eSPeter Avalos * End the line here.
2261133e27eSPeter Avalos */
2270c7ad07eSAntonio Huete Jimenez if (skipeol)
2281133e27eSPeter Avalos {
2290c7ad07eSAntonio Huete Jimenez /* Read to end of line. */
230*e433da38SAaron LI edisp_pos = ch_tell() - backchars;
2311133e27eSPeter Avalos do
2321133e27eSPeter Avalos {
2331133e27eSPeter Avalos c = ch_forw_get();
2341133e27eSPeter Avalos } while (c != '\n' && c != EOI);
2351133e27eSPeter Avalos new_pos = ch_tell();
2361133e27eSPeter Avalos endline = TRUE;
2371133e27eSPeter Avalos quit_if_one_screen = FALSE;
23802d62a0fSDaniel Fojt chopped = TRUE;
2391133e27eSPeter Avalos } else
2401133e27eSPeter Avalos {
241320d7c8aSAaron LI if (!wordwrap)
2421133e27eSPeter Avalos new_pos = ch_tell() - backchars;
243320d7c8aSAaron LI else
244320d7c8aSAaron LI {
245320d7c8aSAaron LI /*
246320d7c8aSAaron LI * We're word-wrapping, so go back to the last space.
247320d7c8aSAaron LI * However, if it's the space itself that couldn't fit,
248320d7c8aSAaron LI * simply ignore it and any subsequent spaces.
249320d7c8aSAaron LI */
250320d7c8aSAaron LI if (c == ' ' || c == '\t')
251320d7c8aSAaron LI {
252320d7c8aSAaron LI do
253320d7c8aSAaron LI {
254320d7c8aSAaron LI new_pos = ch_tell();
255*e433da38SAaron LI c = ch_forw_get(); /* {{ what if c == EOI? }} */
256320d7c8aSAaron LI } while (c == ' ' || c == '\t');
257320d7c8aSAaron LI if (c == '\r')
258*e433da38SAaron LI c = ch_forw_get(); /* {{ what if c == EOI? }} */
259320d7c8aSAaron LI if (c == '\n')
260320d7c8aSAaron LI new_pos = ch_tell();
261320d7c8aSAaron LI } else if (wrap_pos == NULL_POSITION)
262320d7c8aSAaron LI new_pos = ch_tell() - backchars;
263320d7c8aSAaron LI else
264320d7c8aSAaron LI {
265320d7c8aSAaron LI new_pos = wrap_pos;
266320d7c8aSAaron LI loadc();
267320d7c8aSAaron LI }
268320d7c8aSAaron LI }
2691133e27eSPeter Avalos endline = FALSE;
270*e433da38SAaron LI edisp_pos = new_pos;
2711133e27eSPeter Avalos }
2721133e27eSPeter Avalos break;
2731133e27eSPeter Avalos }
274320d7c8aSAaron LI if (wordwrap)
275320d7c8aSAaron LI {
276320d7c8aSAaron LI if (c == ' ' || c == '\t')
277320d7c8aSAaron LI {
278320d7c8aSAaron LI if (skipped_leading)
279320d7c8aSAaron LI {
280320d7c8aSAaron LI wrap_pos = ch_tell();
281320d7c8aSAaron LI savec();
282320d7c8aSAaron LI }
283320d7c8aSAaron LI } else
284320d7c8aSAaron LI skipped_leading = TRUE;
285320d7c8aSAaron LI }
2861133e27eSPeter Avalos c = ch_forw_get();
2871133e27eSPeter Avalos }
2888be36e5bSPeter Avalos
2890c7ad07eSAntonio Huete Jimenez #if HILITE_SEARCH
2900c7ad07eSAntonio Huete Jimenez if (blankline && show_attn)
2910c7ad07eSAntonio Huete Jimenez {
292*e433da38SAaron LI /* Add spurious space to carry possible attn hilite.
293*e433da38SAaron LI * Use pappend_b so that if line ended with \r\n,
294*e433da38SAaron LI * we insert the space before the \r. */
295*e433da38SAaron LI pappend_b(' ', ch_tell()-1, TRUE);
2960c7ad07eSAntonio Huete Jimenez }
2970c7ad07eSAntonio Huete Jimenez #endif
2980c7ad07eSAntonio Huete Jimenez pdone(endline, rscroll && chopped, 1);
2998be36e5bSPeter Avalos
3008be36e5bSPeter Avalos #if HILITE_SEARCH
3018be36e5bSPeter Avalos if (is_filtered(base_pos))
3028be36e5bSPeter Avalos {
3038be36e5bSPeter Avalos /*
3048be36e5bSPeter Avalos * We don't want to display this line.
3058be36e5bSPeter Avalos * Get the next line.
3068be36e5bSPeter Avalos */
3078be36e5bSPeter Avalos curr_pos = new_pos;
3088be36e5bSPeter Avalos goto get_forw_line;
3098be36e5bSPeter Avalos }
3100c7ad07eSAntonio Huete Jimenez if (status_col)
311320d7c8aSAaron LI init_status_col(base_pos, line_position(), edisp_pos, new_pos);
3128be36e5bSPeter Avalos #endif
3131133e27eSPeter Avalos
3141133e27eSPeter Avalos if (squeeze && blankline)
3151133e27eSPeter Avalos {
3161133e27eSPeter Avalos /*
3171133e27eSPeter Avalos * This line is blank.
3181133e27eSPeter Avalos * Skip down to the last contiguous blank line
3191133e27eSPeter Avalos * and pretend it is the one which we are returning.
3201133e27eSPeter Avalos */
3211133e27eSPeter Avalos while ((c = ch_forw_get()) == '\n' || c == '\r')
322*e433da38SAaron LI continue;
3231133e27eSPeter Avalos if (c != EOI)
3241133e27eSPeter Avalos (void) ch_back_get();
3251133e27eSPeter Avalos new_pos = ch_tell();
3261133e27eSPeter Avalos }
3271133e27eSPeter Avalos
3281133e27eSPeter Avalos return (new_pos);
3291133e27eSPeter Avalos }
3301133e27eSPeter Avalos
forw_line(POSITION curr_pos)331320d7c8aSAaron LI public POSITION forw_line(POSITION curr_pos)
3320c7ad07eSAntonio Huete Jimenez {
3330c7ad07eSAntonio Huete Jimenez
3340c7ad07eSAntonio Huete Jimenez return forw_line_seg(curr_pos, (chop_line() || hshift > 0), TRUE, FALSE);
3350c7ad07eSAntonio Huete Jimenez }
3360c7ad07eSAntonio Huete Jimenez
3371133e27eSPeter Avalos /*
3381133e27eSPeter Avalos * Get the previous line.
3391133e27eSPeter Avalos * A "current" position is passed and a "new" position is returned.
3401133e27eSPeter Avalos * The current position is the position of the first character of
3411133e27eSPeter Avalos * a line. The new position is the position of the first character
3421133e27eSPeter Avalos * of the PREVIOUS line. The line obtained is the one starting at new_pos.
3431133e27eSPeter Avalos */
back_line(POSITION curr_pos)344320d7c8aSAaron LI public POSITION back_line(POSITION curr_pos)
3451133e27eSPeter Avalos {
346320d7c8aSAaron LI POSITION base_pos;
347320d7c8aSAaron LI POSITION new_pos;
348320d7c8aSAaron LI POSITION edisp_pos;
349320d7c8aSAaron LI POSITION begin_new_pos;
3501133e27eSPeter Avalos int c;
351*e433da38SAaron LI lbool endline;
352*e433da38SAaron LI lbool chopped;
3531133e27eSPeter Avalos int backchars;
354320d7c8aSAaron LI POSITION wrap_pos;
355*e433da38SAaron LI lbool skipped_leading;
3561133e27eSPeter Avalos
3578be36e5bSPeter Avalos get_back_line:
3581133e27eSPeter Avalos if (curr_pos == NULL_POSITION || curr_pos <= ch_zero())
3591133e27eSPeter Avalos {
3601133e27eSPeter Avalos null_line();
3611133e27eSPeter Avalos return (NULL_POSITION);
3621133e27eSPeter Avalos }
3631133e27eSPeter Avalos #if HILITE_SEARCH
3648be36e5bSPeter Avalos if (hilite_search == OPT_ONPLUS || is_filtering() || status_col)
365*e433da38SAaron LI prep_hilite((curr_pos < (POSITION) (3*size_linebuf)) ? 0 :
366*e433da38SAaron LI curr_pos - (POSITION) (3*size_linebuf), curr_pos, -1);
3671133e27eSPeter Avalos #endif
3681133e27eSPeter Avalos if (ch_seek(curr_pos-1))
3691133e27eSPeter Avalos {
3701133e27eSPeter Avalos null_line();
3711133e27eSPeter Avalos return (NULL_POSITION);
3721133e27eSPeter Avalos }
3731133e27eSPeter Avalos
3741133e27eSPeter Avalos if (squeeze)
3751133e27eSPeter Avalos {
3761133e27eSPeter Avalos /*
3771133e27eSPeter Avalos * Find out if the "current" line was blank.
3781133e27eSPeter Avalos */
3791133e27eSPeter Avalos (void) ch_forw_get(); /* Skip the newline */
3801133e27eSPeter Avalos c = ch_forw_get(); /* First char of "current" line */
381*e433da38SAaron LI /* {{ what if c == EOI? }} */
3821133e27eSPeter Avalos (void) ch_back_get(); /* Restore our position */
3831133e27eSPeter Avalos (void) ch_back_get();
3841133e27eSPeter Avalos
3851133e27eSPeter Avalos if (c == '\n' || c == '\r')
3861133e27eSPeter Avalos {
3871133e27eSPeter Avalos /*
3881133e27eSPeter Avalos * The "current" line was blank.
3891133e27eSPeter Avalos * Skip over any preceding blank lines,
3901133e27eSPeter Avalos * since we skipped them in forw_line().
3911133e27eSPeter Avalos */
3921133e27eSPeter Avalos while ((c = ch_back_get()) == '\n' || c == '\r')
393*e433da38SAaron LI continue;
3941133e27eSPeter Avalos if (c == EOI)
3951133e27eSPeter Avalos {
3961133e27eSPeter Avalos null_line();
3971133e27eSPeter Avalos return (NULL_POSITION);
3981133e27eSPeter Avalos }
3991133e27eSPeter Avalos (void) ch_forw_get();
4001133e27eSPeter Avalos }
4011133e27eSPeter Avalos }
4021133e27eSPeter Avalos
4031133e27eSPeter Avalos /*
4041133e27eSPeter Avalos * Scan backwards until we hit the beginning of the line.
4051133e27eSPeter Avalos */
4061133e27eSPeter Avalos for (;;)
4071133e27eSPeter Avalos {
4081133e27eSPeter Avalos c = ch_back_get();
4091133e27eSPeter Avalos if (c == '\n')
4101133e27eSPeter Avalos {
4111133e27eSPeter Avalos /*
4121133e27eSPeter Avalos * This is the newline ending the previous line.
4131133e27eSPeter Avalos * We have hit the beginning of the line.
4141133e27eSPeter Avalos */
4158be36e5bSPeter Avalos base_pos = ch_tell() + 1;
4161133e27eSPeter Avalos break;
4171133e27eSPeter Avalos }
4181133e27eSPeter Avalos if (c == EOI)
4191133e27eSPeter Avalos {
4201133e27eSPeter Avalos /*
4211133e27eSPeter Avalos * We have hit the beginning of the file.
4221133e27eSPeter Avalos * This must be the first line in the file.
4231133e27eSPeter Avalos * This must, of course, be the beginning of the line.
4241133e27eSPeter Avalos */
4258be36e5bSPeter Avalos base_pos = ch_tell();
4261133e27eSPeter Avalos break;
4271133e27eSPeter Avalos }
4281133e27eSPeter Avalos }
4291133e27eSPeter Avalos
4301133e27eSPeter Avalos /*
4311133e27eSPeter Avalos * Now scan forwards from the beginning of this line.
4321133e27eSPeter Avalos * We keep discarding "printable lines" (based on screen width)
4331133e27eSPeter Avalos * until we reach the curr_pos.
4341133e27eSPeter Avalos *
4351133e27eSPeter Avalos * {{ This algorithm is pretty inefficient if the lines
4361133e27eSPeter Avalos * are much longer than the screen width,
4371133e27eSPeter Avalos * but I don't know of any better way. }}
4381133e27eSPeter Avalos */
4398be36e5bSPeter Avalos new_pos = base_pos;
4401133e27eSPeter Avalos if (ch_seek(new_pos))
4411133e27eSPeter Avalos {
4421133e27eSPeter Avalos null_line();
4431133e27eSPeter Avalos return (NULL_POSITION);
4441133e27eSPeter Avalos }
4451133e27eSPeter Avalos endline = FALSE;
4461133e27eSPeter Avalos prewind();
4470c7ad07eSAntonio Huete Jimenez plinestart(new_pos);
4481133e27eSPeter Avalos loop:
449320d7c8aSAaron LI wrap_pos = NULL_POSITION;
450320d7c8aSAaron LI skipped_leading = FALSE;
4511133e27eSPeter Avalos begin_new_pos = new_pos;
4521133e27eSPeter Avalos (void) ch_seek(new_pos);
45302d62a0fSDaniel Fojt chopped = FALSE;
4541133e27eSPeter Avalos
455320d7c8aSAaron LI for (;;)
4561133e27eSPeter Avalos {
4571133e27eSPeter Avalos c = ch_forw_get();
458*e433da38SAaron LI if (c == EOI)
4591133e27eSPeter Avalos {
4601133e27eSPeter Avalos null_line();
4611133e27eSPeter Avalos return (NULL_POSITION);
4621133e27eSPeter Avalos }
4631133e27eSPeter Avalos new_pos++;
4641133e27eSPeter Avalos if (c == '\n')
4651133e27eSPeter Avalos {
4661133e27eSPeter Avalos backchars = pflushmbc();
4670c7ad07eSAntonio Huete Jimenez if (backchars > 0 && !chop_line() && hshift == 0)
4681133e27eSPeter Avalos {
4691133e27eSPeter Avalos backchars++;
4701133e27eSPeter Avalos goto shift;
4711133e27eSPeter Avalos }
4721133e27eSPeter Avalos endline = TRUE;
473320d7c8aSAaron LI edisp_pos = new_pos;
4741133e27eSPeter Avalos break;
4751133e27eSPeter Avalos }
476*e433da38SAaron LI backchars = pappend((char) c, ch_tell()-1);
4771133e27eSPeter Avalos if (backchars > 0)
4781133e27eSPeter Avalos {
4791133e27eSPeter Avalos /*
4801133e27eSPeter Avalos * Got a full printable line, but we haven't
4811133e27eSPeter Avalos * reached our curr_pos yet. Discard the line
4821133e27eSPeter Avalos * and start a new one.
4831133e27eSPeter Avalos */
4840c7ad07eSAntonio Huete Jimenez if (chop_line() || hshift > 0)
4851133e27eSPeter Avalos {
4861133e27eSPeter Avalos endline = TRUE;
48702d62a0fSDaniel Fojt chopped = TRUE;
4881133e27eSPeter Avalos quit_if_one_screen = FALSE;
489320d7c8aSAaron LI edisp_pos = new_pos;
4901133e27eSPeter Avalos break;
4911133e27eSPeter Avalos }
4921133e27eSPeter Avalos shift:
493320d7c8aSAaron LI if (!wordwrap)
4941133e27eSPeter Avalos {
495320d7c8aSAaron LI pshift_all();
496320d7c8aSAaron LI new_pos -= backchars;
497320d7c8aSAaron LI } else
498320d7c8aSAaron LI {
499320d7c8aSAaron LI if (c == ' ' || c == '\t')
500320d7c8aSAaron LI {
501320d7c8aSAaron LI for (;;)
502320d7c8aSAaron LI {
503*e433da38SAaron LI c = ch_forw_get(); /* {{ what if c == EOI? }} */
504320d7c8aSAaron LI if (c == ' ' || c == '\t')
505320d7c8aSAaron LI new_pos++;
506320d7c8aSAaron LI else
507320d7c8aSAaron LI {
508320d7c8aSAaron LI if (c == '\r')
509320d7c8aSAaron LI {
510*e433da38SAaron LI c = ch_forw_get(); /* {{ what if c == EOI? }} */
511320d7c8aSAaron LI if (c == '\n')
512320d7c8aSAaron LI new_pos++;
513320d7c8aSAaron LI }
514320d7c8aSAaron LI if (c == '\n')
515320d7c8aSAaron LI new_pos++;
516*e433da38SAaron LI edisp_pos = new_pos;
517320d7c8aSAaron LI break;
518320d7c8aSAaron LI }
519320d7c8aSAaron LI }
520320d7c8aSAaron LI if (new_pos >= curr_pos)
521*e433da38SAaron LI {
522*e433da38SAaron LI edisp_pos = new_pos;
523320d7c8aSAaron LI break;
524*e433da38SAaron LI }
525320d7c8aSAaron LI pshift_all();
526320d7c8aSAaron LI } else
527320d7c8aSAaron LI {
528320d7c8aSAaron LI pshift_all();
529320d7c8aSAaron LI if (wrap_pos == NULL_POSITION)
530320d7c8aSAaron LI new_pos -= backchars;
531320d7c8aSAaron LI else
532320d7c8aSAaron LI new_pos = wrap_pos;
533320d7c8aSAaron LI }
5341133e27eSPeter Avalos }
5351133e27eSPeter Avalos goto loop;
5361133e27eSPeter Avalos }
537320d7c8aSAaron LI if (wordwrap)
538320d7c8aSAaron LI {
539320d7c8aSAaron LI if (c == ' ' || c == '\t')
540320d7c8aSAaron LI {
541320d7c8aSAaron LI if (skipped_leading)
542320d7c8aSAaron LI wrap_pos = new_pos;
543320d7c8aSAaron LI } else
544320d7c8aSAaron LI skipped_leading = TRUE;
545320d7c8aSAaron LI }
546320d7c8aSAaron LI if (new_pos >= curr_pos)
547320d7c8aSAaron LI {
548320d7c8aSAaron LI edisp_pos = new_pos;
549320d7c8aSAaron LI break;
550320d7c8aSAaron LI }
551320d7c8aSAaron LI }
5521133e27eSPeter Avalos
55302d62a0fSDaniel Fojt pdone(endline, chopped, 0);
5548be36e5bSPeter Avalos
5558be36e5bSPeter Avalos #if HILITE_SEARCH
5568be36e5bSPeter Avalos if (is_filtered(base_pos))
5578be36e5bSPeter Avalos {
5588be36e5bSPeter Avalos /*
5598be36e5bSPeter Avalos * We don't want to display this line.
5608be36e5bSPeter Avalos * Get the previous line.
5618be36e5bSPeter Avalos */
5628be36e5bSPeter Avalos curr_pos = begin_new_pos;
5638be36e5bSPeter Avalos goto get_back_line;
5648be36e5bSPeter Avalos }
565320d7c8aSAaron LI if (status_col)
566320d7c8aSAaron LI init_status_col(base_pos, line_position(), edisp_pos, new_pos);
5678be36e5bSPeter Avalos #endif
5681133e27eSPeter Avalos
5691133e27eSPeter Avalos return (begin_new_pos);
5701133e27eSPeter Avalos }
5711133e27eSPeter Avalos
5721133e27eSPeter Avalos /*
5731133e27eSPeter Avalos * Set attnpos.
5741133e27eSPeter Avalos */
set_attnpos(POSITION pos)575320d7c8aSAaron LI public void set_attnpos(POSITION pos)
5761133e27eSPeter Avalos {
5771133e27eSPeter Avalos int c;
5781133e27eSPeter Avalos
5791133e27eSPeter Avalos if (pos != NULL_POSITION)
5801133e27eSPeter Avalos {
5811133e27eSPeter Avalos if (ch_seek(pos))
5821133e27eSPeter Avalos return;
5831133e27eSPeter Avalos for (;;)
5841133e27eSPeter Avalos {
5851133e27eSPeter Avalos c = ch_forw_get();
5861133e27eSPeter Avalos if (c == EOI)
5871133e27eSPeter Avalos break;
588fa0be7c5SJohn Marino if (c == '\n' || c == '\r')
589fa0be7c5SJohn Marino {
590fa0be7c5SJohn Marino (void) ch_back_get();
591fa0be7c5SJohn Marino break;
592fa0be7c5SJohn Marino }
5931133e27eSPeter Avalos pos++;
5941133e27eSPeter Avalos }
595fa0be7c5SJohn Marino end_attnpos = pos;
596fa0be7c5SJohn Marino for (;;)
597fa0be7c5SJohn Marino {
598fa0be7c5SJohn Marino c = ch_back_get();
599fa0be7c5SJohn Marino if (c == EOI || c == '\n' || c == '\r')
600fa0be7c5SJohn Marino break;
601fa0be7c5SJohn Marino pos--;
602fa0be7c5SJohn Marino }
6031133e27eSPeter Avalos }
6041133e27eSPeter Avalos start_attnpos = pos;
6051133e27eSPeter Avalos }
606