aboutsummaryrefslogtreecommitdiff
path: root/input.c
diff options
context:
space:
mode:
authorXin LI <delphij@FreeBSD.org>2023-05-01 08:22:19 +0000
committerXin LI <delphij@FreeBSD.org>2023-05-01 08:22:19 +0000
commit159d764c16684166cab1428d7aebd0c0f3666cd3 (patch)
tree4964e28a9d48c96e0f735eeb60fa830e51649fc1 /input.c
parent2b6624fffa5fac26d860898ddb335f852cfeb6b5 (diff)
downloadsrc-159d764c16684166cab1428d7aebd0c0f3666cd3.tar.gz
src-159d764c16684166cab1428d7aebd0c0f3666cd3.zip
Vendor import of less v632.vendor/less/v632
Diffstat (limited to 'input.c')
-rw-r--r--input.c203
1 files changed, 166 insertions, 37 deletions
diff --git a/input.c b/input.c
index ffd2f13e3f3f..0e021e1d05e1 100644
--- a/input.c
+++ b/input.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1984-2022 Mark Nudelman
+ * Copyright (C) 1984-2023 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -25,6 +25,7 @@ extern int quit_if_one_screen;
extern int sigs;
extern int ignore_eoi;
extern int status_col;
+extern int wordwrap;
extern POSITION start_attnpos;
extern POSITION end_attnpos;
#if HILITE_SEARCH
@@ -34,26 +35,63 @@ extern int show_attn;
#endif
/*
+ * Set the status column.
+ * base Position of first char in line.
+ * disp First visible char.
+ * Different than base_pos if line is shifted.
+ * edisp Last visible char.
+ * eol End of line. Normally the newline.
+ * Different than edisp if line is chopped.
+ */
+static void init_status_col(POSITION base_pos, POSITION disp_pos, POSITION edisp_pos, POSITION eol_pos)
+{
+ int hl_before = (chop_line() && disp_pos != NULL_POSITION) ?
+ is_hilited_attr(base_pos, disp_pos, TRUE, NULL) : 0;
+ int hl_after = (chop_line()) ?
+ is_hilited_attr(edisp_pos, eol_pos, TRUE, NULL) : 0;
+ int attr;
+ char ch;
+
+ if (hl_before && hl_after)
+ {
+ attr = hl_after;
+ ch = '=';
+ } else if (hl_before)
+ {
+ attr = hl_before;
+ ch = '<';
+ } else if (hl_after)
+ {
+ attr = hl_after;
+ ch = '>';
+ } else
+ {
+ attr = is_hilited_attr(base_pos, eol_pos, TRUE, NULL);
+ ch = '*';
+ }
+ if (attr)
+ set_status_col(ch, attr);
+}
+
+/*
* Get the next line.
* A "current" position is passed and a "new" position is returned.
* The current position is the position of the first character of
* a line. The new position is the position of the first character
* of the NEXT line. The line obtained is the line starting at curr_pos.
*/
- public POSITION
-forw_line_seg(curr_pos, skipeol, rscroll, nochop)
- POSITION curr_pos;
- int skipeol;
- int rscroll;
- int nochop;
+public POSITION forw_line_seg(POSITION curr_pos, int skipeol, int rscroll, int nochop)
{
POSITION base_pos;
POSITION new_pos;
+ POSITION edisp_pos;
int c;
int blankline;
int endline;
int chopped;
int backchars;
+ POSITION wrap_pos;
+ int skipped_leading;
get_forw_line:
if (curr_pos == NULL_POSITION)
@@ -124,6 +162,15 @@ get_forw_line:
if (backchars > 0)
{
pshift_all();
+ if (wordwrap && (c == ' ' || c == '\t'))
+ {
+ do
+ {
+ new_pos++;
+ c = ch_forw_get();
+ } while (c == ' ' || c == '\t');
+ backchars = 1;
+ }
new_pos -= backchars;
while (--backchars >= 0)
(void) ch_back_get();
@@ -142,6 +189,8 @@ get_forw_line:
return (NULL_POSITION);
}
blankline = (c == '\n' || c == '\r');
+ wrap_pos = NULL_POSITION;
+ skipped_leading = FALSE;
/*
* Read each character in the line and append to the line buffer.
@@ -167,6 +216,7 @@ get_forw_line:
endline = FALSE;
} else
endline = TRUE;
+ edisp_pos = new_pos;
break;
}
if (c != '\r')
@@ -186,6 +236,7 @@ get_forw_line:
if (skipeol)
{
/* Read to end of line. */
+ edisp_pos = ch_tell();
do
{
if (ABORT_SIGS())
@@ -201,11 +252,50 @@ get_forw_line:
chopped = TRUE;
} else
{
- new_pos = ch_tell() - backchars;
+ if (!wordwrap)
+ new_pos = ch_tell() - backchars;
+ else
+ {
+ /*
+ * We're word-wrapping, so go back to the last space.
+ * However, if it's the space itself that couldn't fit,
+ * simply ignore it and any subsequent spaces.
+ */
+ if (c == ' ' || c == '\t')
+ {
+ do
+ {
+ new_pos = ch_tell();
+ c = ch_forw_get();
+ } while (c == ' ' || c == '\t');
+ if (c == '\r')
+ c = ch_forw_get();
+ if (c == '\n')
+ new_pos = ch_tell();
+ } else if (wrap_pos == NULL_POSITION)
+ new_pos = ch_tell() - backchars;
+ else
+ {
+ new_pos = wrap_pos;
+ loadc();
+ }
+ }
endline = FALSE;
}
break;
}
+ if (wordwrap)
+ {
+ if (c == ' ' || c == '\t')
+ {
+ if (skipped_leading)
+ {
+ wrap_pos = ch_tell();
+ savec();
+ }
+ } else
+ skipped_leading = TRUE;
+ }
c = ch_forw_get();
}
@@ -228,13 +318,8 @@ get_forw_line:
curr_pos = new_pos;
goto get_forw_line;
}
-
if (status_col)
- {
- int attr = is_hilited_attr(base_pos, ch_tell()-1, 1, NULL);
- if (attr)
- set_status_col('*', attr);
- }
+ init_status_col(base_pos, line_position(), edisp_pos, new_pos);
#endif
if (squeeze && blankline)
@@ -258,9 +343,7 @@ get_forw_line:
return (new_pos);
}
- public POSITION
-forw_line(curr_pos)
- POSITION curr_pos;
+public POSITION forw_line(POSITION curr_pos)
{
return forw_line_seg(curr_pos, (chop_line() || hshift > 0), TRUE, FALSE);
@@ -273,15 +356,18 @@ forw_line(curr_pos)
* a line. The new position is the position of the first character
* of the PREVIOUS line. The line obtained is the one starting at new_pos.
*/
- public POSITION
-back_line(curr_pos)
- POSITION curr_pos;
+public POSITION back_line(POSITION curr_pos)
{
- POSITION new_pos, begin_new_pos, base_pos;
+ POSITION base_pos;
+ POSITION new_pos;
+ POSITION edisp_pos;
+ POSITION begin_new_pos;
int c;
int endline;
int chopped;
int backchars;
+ POSITION wrap_pos;
+ int skipped_leading;
get_back_line:
if (curr_pos == NULL_POSITION || curr_pos <= ch_zero())
@@ -383,11 +469,13 @@ get_back_line:
prewind();
plinestart(new_pos);
loop:
+ wrap_pos = NULL_POSITION;
+ skipped_leading = FALSE;
begin_new_pos = new_pos;
(void) ch_seek(new_pos);
chopped = FALSE;
- do
+ for (;;)
{
c = ch_forw_get();
if (c == EOI || ABORT_SIGS())
@@ -405,6 +493,7 @@ get_back_line:
goto shift;
}
endline = TRUE;
+ edisp_pos = new_pos;
break;
}
backchars = pappend(c, ch_tell()-1);
@@ -420,18 +509,65 @@ get_back_line:
endline = TRUE;
chopped = TRUE;
quit_if_one_screen = FALSE;
+ edisp_pos = new_pos;
break;
}
shift:
- pshift_all();
- while (backchars-- > 0)
+ if (!wordwrap)
{
- (void) ch_back_get();
- new_pos--;
+ pshift_all();
+ new_pos -= backchars;
+ } else
+ {
+ if (c == ' ' || c == '\t')
+ {
+ for (;;)
+ {
+ c = ch_forw_get();
+ if (c == ' ' || c == '\t')
+ new_pos++;
+ else
+ {
+ if (c == '\r')
+ {
+ c = ch_forw_get();
+ if (c == '\n')
+ new_pos++;
+ }
+ if (c == '\n')
+ new_pos++;
+ break;
+ }
+ }
+ if (new_pos >= curr_pos)
+ break;
+ pshift_all();
+ } else
+ {
+ pshift_all();
+ if (wrap_pos == NULL_POSITION)
+ new_pos -= backchars;
+ else
+ new_pos = wrap_pos;
+ }
}
goto loop;
}
- } while (new_pos < curr_pos);
+ if (wordwrap)
+ {
+ if (c == ' ' || c == '\t')
+ {
+ if (skipped_leading)
+ wrap_pos = new_pos;
+ } else
+ skipped_leading = TRUE;
+ }
+ if (new_pos >= curr_pos)
+ {
+ edisp_pos = new_pos;
+ break;
+ }
+ }
pdone(endline, chopped, 0);
@@ -445,13 +581,8 @@ get_back_line:
curr_pos = begin_new_pos;
goto get_back_line;
}
-
- if (status_col && curr_pos > 0)
- {
- int attr = is_hilited_attr(base_pos, curr_pos-1, 1, NULL);
- if (attr)
- set_status_col('*', attr);
- }
+ if (status_col)
+ init_status_col(base_pos, line_position(), edisp_pos, new_pos);
#endif
return (begin_new_pos);
@@ -460,9 +591,7 @@ get_back_line:
/*
* Set attnpos.
*/
- public void
-set_attnpos(pos)
- POSITION pos;
+public void set_attnpos(POSITION pos)
{
int c;