diff options
author | Xin LI <delphij@FreeBSD.org> | 2023-05-01 08:22:19 +0000 |
---|---|---|
committer | Xin LI <delphij@FreeBSD.org> | 2023-05-01 08:22:19 +0000 |
commit | 159d764c16684166cab1428d7aebd0c0f3666cd3 (patch) | |
tree | 4964e28a9d48c96e0f735eeb60fa830e51649fc1 /input.c | |
parent | 2b6624fffa5fac26d860898ddb335f852cfeb6b5 (diff) | |
download | src-159d764c16684166cab1428d7aebd0c0f3666cd3.tar.gz src-159d764c16684166cab1428d7aebd0c0f3666cd3.zip |
Vendor import of less v632.vendor/less/v632
Diffstat (limited to 'input.c')
-rw-r--r-- | input.c | 203 |
1 files changed, 166 insertions, 37 deletions
@@ -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; |