aboutsummaryrefslogtreecommitdiff
path: root/contrib/less
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/less')
-rw-r--r--contrib/less/NEWS39
-rw-r--r--contrib/less/ch.c4
-rw-r--r--contrib/less/charset.c48
-rw-r--r--contrib/less/command.c40
-rw-r--r--contrib/less/compose.uni4
-rw-r--r--contrib/less/decode.c11
-rw-r--r--contrib/less/edit.c10
-rw-r--r--contrib/less/fmt.uni6
-rw-r--r--contrib/less/forwback.c2
-rw-r--r--contrib/less/funcs.h12
-rw-r--r--contrib/less/help.c2
-rw-r--r--contrib/less/input.c72
-rw-r--r--contrib/less/less.h5
-rw-r--r--contrib/less/less.nro110
-rw-r--r--contrib/less/lessecho.nro6
-rw-r--r--contrib/less/lesskey.nro18
-rw-r--r--contrib/less/lglob.h2
-rw-r--r--contrib/less/line.c106
-rw-r--r--contrib/less/lsystem.c2
-rw-r--r--contrib/less/main.c41
-rwxr-xr-xcontrib/less/mkutable21
-rw-r--r--contrib/less/omit.uni7
-rw-r--r--contrib/less/optfunc.c18
-rw-r--r--contrib/less/opttbl.c6
-rw-r--r--contrib/less/os.c51
-rw-r--r--contrib/less/pattern.c7
-rw-r--r--contrib/less/screen.c30
-rw-r--r--contrib/less/search.c12
-rw-r--r--contrib/less/ubin.uni2
-rw-r--r--contrib/less/version.c14
-rw-r--r--contrib/less/wide.uni8
-rw-r--r--contrib/less/xbuf.c2
32 files changed, 581 insertions, 137 deletions
diff --git a/contrib/less/NEWS b/contrib/less/NEWS
index cdc8196a5f16..442fe21e406a 100644
--- a/contrib/less/NEWS
+++ b/contrib/less/NEWS
@@ -11,6 +11,45 @@
======================================================================
+ Major changes between "less" versions 679 and 685
+
+* Add --cmd option (github #624).
+
+* Add LESS_TERMCAP_SUSPEND and LESS_TERMCAP_RESUME (github #654).
+
+* Change --incsearch so that after typing each character of the pattern,
+ the search begins at the position where the search command was invoked,
+ not the current position (github #640).
+
+* Allow mixing of option arguments and filename arguments on the
+ command line unless POSIXLY_CORRECT is set (github #653).
+
+* Don't output U+00AD and U+200D, and fix some bugs handling emoji
+ modifier characters (github #637).
+
+* Fix hang if a search using ^S modifier matches empty string (github #634).
+
+* Fix bug using -g and -J (github #636).
+
+* Fix bug when pasting a search pattern while --incsearch is active
+ (github #635).
+
+* Fix bug in Windows build when autorepeating a search pattern (github #639).
+
+* Fix lesskey bug using #stop directive.
+
+* Fix lesskey bug using "invalid" action (github #643).
+
+* Fix bug causing file to appear to end prematurely if an input command
+ was received during a file read (github #649).
+
+* Fix performance issue in & filtering (github #638). Problem was introduced
+ in da2a9ecdf16beb642d0c030e35f0351c5f2e5a12 and released in less-673.
+
+* Fix some problems reported by valgrind (github #659, github #660, github #661).
+
+======================================================================
+
Major changes between "less" versions 678 and 679
* Fix bad parsing of lesskey file an env var is a prefix of another
diff --git a/contrib/less/ch.c b/contrib/less/ch.c
index 870028c73a23..fb7572e7f88a 100644
--- a/contrib/less/ch.c
+++ b/contrib/less/ch.c
@@ -283,11 +283,7 @@ static int ch_get(void)
read_again = FALSE;
if (n == READ_INTR)
- {
- if (ch_flags & CH_CANSEEK)
- ch_fsize = pos;
return (EOI);
- }
if (n == READ_AGAIN)
{
read_again = TRUE;
diff --git a/contrib/less/charset.c b/contrib/less/charset.c
index 5e5df2a4e60f..0f62739bc88d 100644
--- a/contrib/less/charset.c
+++ b/contrib/less/charset.c
@@ -128,10 +128,12 @@ static struct xbuffer user_wide_array;
static struct xbuffer user_ubin_array;
static struct xbuffer user_compose_array;
static struct xbuffer user_prt_array;
+static struct xbuffer user_omit_array;
static struct wchar_range_table user_wide_table;
static struct wchar_range_table user_ubin_table;
static struct wchar_range_table user_compose_table;
static struct wchar_range_table user_prt_table;
+static struct wchar_range_table user_omit_table;
/*
* Set a wchar_range_table to the table in an xbuffer.
@@ -179,6 +181,7 @@ static void ichardef_utf(constant char *s)
xbuf_init(&user_ubin_array);
xbuf_init(&user_compose_array);
xbuf_init(&user_prt_array);
+ xbuf_init(&user_omit_array);
if (s != NULL)
{
@@ -204,6 +207,9 @@ static void ichardef_utf(constant char *s)
case 'c':
xbuf_add_data(&user_compose_array, (unsigned char *) &range, sizeof(range));
break;
+ case 'd':
+ xbuf_add_data(&user_omit_array, (unsigned char *) &range, sizeof(range));
+ break;
case 'w':
xbuf_add_data(&user_wide_array, (unsigned char *) &range, sizeof(range));
xbuf_add_data(&user_prt_array, (unsigned char *) &range, sizeof(range));
@@ -225,6 +231,7 @@ static void ichardef_utf(constant char *s)
wchar_range_table_set(&user_ubin_table, &user_ubin_array);
wchar_range_table_set(&user_compose_table, &user_compose_array);
wchar_range_table_set(&user_prt_table, &user_prt_array);
+ wchar_range_table_set(&user_omit_table, &user_omit_array);
}
/*
@@ -554,7 +561,7 @@ public constant char * prutfchar(LWCHAR ch)
SNPRINTF1(buf, sizeof(buf), "^%c", ((char) ch) ^ 0100);
else
SNPRINTF1(buf, sizeof(buf), binfmt, (char) ch);
- } else if (is_ubin_char(ch))
+ } else if (is_ubin_char(ch) || is_omit_char(ch))
{
SNPRINTF1(buf, sizeof(buf), utfbinfmt, ch);
} else
@@ -827,6 +834,10 @@ DECLARE_RANGE_TABLE_START(fmt)
#include "fmt.uni"
DECLARE_RANGE_TABLE_END(fmt)
+DECLARE_RANGE_TABLE_START(omit)
+#include "omit.uni"
+DECLARE_RANGE_TABLE_END(omit)
+
/* comb_table is special pairs, not ranges. */
static struct wchar_range comb_table[] = {
{0x0644,0x0622}, {0x0644,0x0623}, {0x0644,0x0625}, {0x0644,0x0627},
@@ -857,6 +868,17 @@ static lbool is_in_table(LWCHAR ch, struct wchar_range_table *table)
}
/*
+ * Is a character in none of a set of specified user tables?
+ */
+static lbool not_user_defined(LWCHAR ch, struct wchar_range_table *tbl1, struct wchar_range_table *tbl2, struct wchar_range_table *tbl3)
+{
+ if (is_in_table(ch, tbl1)) return FALSE;
+ if (is_in_table(ch, tbl2)) return FALSE;
+ if (is_in_table(ch, tbl3)) return FALSE;
+ return TRUE;
+}
+
+/*
* Is a character a UTF-8 composing character?
* If a composing character follows any char, the two combine into one glyph.
*/
@@ -864,8 +886,9 @@ public lbool is_composing_char(LWCHAR ch)
{
if (is_in_table(ch, &user_prt_table)) return FALSE;
return is_in_table(ch, &user_compose_table) ||
- is_in_table(ch, &compose_table) ||
- (bs_mode != BS_CONTROL && is_in_table(ch, &fmt_table));
+ (is_in_table(ch, &compose_table) ||
+ (bs_mode != BS_CONTROL && is_in_table(ch, &fmt_table) &&
+ not_user_defined(ch, &user_prt_table, &user_ubin_table, &user_omit_table)));
}
/*
@@ -875,8 +898,9 @@ public lbool is_ubin_char(LWCHAR ch)
{
if (is_in_table(ch, &user_prt_table)) return FALSE;
return is_in_table(ch, &user_ubin_table) ||
- is_in_table(ch, &ubin_table) ||
- (bs_mode == BS_CONTROL && is_in_table(ch, &fmt_table));
+ (is_in_table(ch, &ubin_table) ||
+ (bs_mode == BS_CONTROL && is_in_table(ch, &fmt_table) &&
+ not_user_defined(ch, &user_prt_table, &user_compose_table, &user_omit_table)));
}
/*
@@ -885,7 +909,18 @@ public lbool is_ubin_char(LWCHAR ch)
public lbool is_wide_char(LWCHAR ch)
{
return is_in_table(ch, &user_wide_table) ||
- is_in_table(ch, &wide_table);
+ (is_in_table(ch, &wide_table) &&
+ not_user_defined(ch, &user_compose_table, &user_ubin_table, &user_omit_table));
+}
+
+/*
+ * Is this an omittable character?
+ */
+public lbool is_omit_char(LWCHAR ch)
+{
+ return is_in_table(ch, &user_omit_table) ||
+ (is_in_table(ch, &omit_table) &&
+ not_user_defined(ch, &user_prt_table, &user_compose_table, &user_ubin_table));
}
/*
@@ -905,4 +940,3 @@ public lbool is_combining_char(LWCHAR ch1, LWCHAR ch2)
}
return FALSE;
}
-
diff --git a/contrib/less/command.c b/contrib/less/command.c
index 3ec1f9b48358..390385547385 100644
--- a/contrib/less/command.c
+++ b/contrib/less/command.c
@@ -49,10 +49,13 @@ extern void *ml_examine;
extern int wheel_lines;
extern int def_search_type;
extern lbool search_wrapped;
+extern lbool no_poll;
extern int no_paste;
extern lbool pasting;
extern int no_edit_warn;
extern POSITION soft_eof;
+extern POSITION search_incr_start;
+extern char *first_cmd_at_prompt;
#if SHELL_ESCAPE || PIPEC
extern void *ml_shell;
#endif
@@ -90,6 +93,8 @@ static int save_proc_backspace;
static int screen_trashed_value = 0;
static lbool literal_char = FALSE;
static lbool ignoring_input = FALSE;
+static struct scrpos search_incr_pos = { NULL_POSITION, 0 };
+static int search_incr_hshift;
#if HAVE_TIME
static time_type ignoring_input_time;
#endif
@@ -209,6 +214,13 @@ static void mca_search1(void)
static void mca_search(void)
{
+ if (incr_search)
+ {
+ /* Remember where the incremental search started. */
+ get_scrpos(&search_incr_pos, TOP);
+ search_incr_start = search_pos(search_type);
+ search_incr_hshift = hshift;
+ }
mca_search1();
set_mlist(ml_search, 0);
}
@@ -747,6 +759,9 @@ static int mca_char(char c)
constant char *pattern = get_cmdbuf();
if (pattern == NULL)
return (MCA_MORE);
+ /* Defer searching if more chars of the pattern are available. */
+ if (ttyin_ready())
+ return (MCA_MORE);
/*
* Must save updown_match because mca_search
* reinits it. That breaks history scrolling.
@@ -758,11 +773,24 @@ static int mca_char(char c)
{
/* User has backspaced to an empty pattern. */
undo_search(1);
+ hshift = search_incr_hshift;
+ jump_loc(search_incr_pos.pos, search_incr_pos.ln);
} else
{
+ /*
+ * Suppress tty polling while searching.
+ * This avoids a problem where tty input
+ * can cause the search to be interrupted.
+ */
+ no_poll = TRUE;
if (search(st | SRCH_INCR, pattern, 1) != 0)
+ {
/* No match, invalid pattern, etc. */
undo_search(1);
+ hshift = search_incr_hshift;
+ jump_loc(search_incr_pos.pos, search_incr_pos.ln);
+ }
+ no_poll = FALSE;
}
/* Redraw the search prompt and search string. */
if (is_screen_trashed() || !full_screen)
@@ -795,6 +823,7 @@ static void clear_buffers(void)
#if HILITE_SEARCH
clr_hilite();
#endif
+ set_line_contig_pos(NULL_POSITION);
}
public void screen_trashed_num(int trashed)
@@ -889,6 +918,12 @@ static void prompt(void)
next_ifile(curr_ifile) == NULL_IFILE)
quit(QUIT_OK);
quit_if_one_screen = FALSE; /* only get one chance at this */
+ if (first_cmd_at_prompt != NULL)
+ {
+ ungetsc(first_cmd_at_prompt);
+ first_cmd_at_prompt = NULL;
+ return;
+ }
#if MSDOS_COMPILER==WIN32C
/*
@@ -962,6 +997,7 @@ static void prompt(void)
put_line(FALSE);
}
clear_eol();
+ resume_screen();
}
/*
@@ -2261,6 +2297,7 @@ public void commands(void)
pos_rehead();
hshift -= (int) number;
screen_trashed();
+ cmd_exec();
break;
case A_RSHIFT:
@@ -2274,6 +2311,7 @@ public void commands(void)
pos_rehead();
hshift += (int) number;
screen_trashed();
+ cmd_exec();
break;
case A_LLSHIFT:
@@ -2283,6 +2321,7 @@ public void commands(void)
pos_rehead();
hshift = 0;
screen_trashed();
+ cmd_exec();
break;
case A_RRSHIFT:
@@ -2292,6 +2331,7 @@ public void commands(void)
pos_rehead();
hshift = rrshift();
screen_trashed();
+ cmd_exec();
break;
case A_PREFIX:
diff --git a/contrib/less/compose.uni b/contrib/less/compose.uni
index 0875a8dceec1..6b4458efc4b4 100644
--- a/contrib/less/compose.uni
+++ b/contrib/less/compose.uni
@@ -1,4 +1,4 @@
-/* Generated by "./mkutable -f2 Mn Me -- unicode/UnicodeData.txt" on Oct 1 18:10:07 GMT 2024 */
+/* Generated by "./mkutable -f2 Mn Me -- unicode/UnicodeData.txt" on Aug 11 0:27:25 GMT 2025 */
{ 0x0300, 0x036f }, /* Mn */
{ 0x0483, 0x0487 }, /* Mn */
{ 0x0488, 0x0489 }, /* Me */
@@ -217,7 +217,6 @@
{ 0xd7b0, 0xd7c6 }, /* Mn */
{ 0xd7cb, 0xd7fb }, /* Mn */
{ 0xfb1e, 0xfb1e }, /* Mn */
- { 0xfe00, 0xfe0f }, /* Mn */
{ 0xfe20, 0xfe2f }, /* Mn */
{ 0x101fd, 0x101fd }, /* Mn */
{ 0x102e0, 0x102e0 }, /* Mn */
@@ -363,4 +362,3 @@
{ 0x1e5ee, 0x1e5ef }, /* Mn */
{ 0x1e8d0, 0x1e8d6 }, /* Mn */
{ 0x1e944, 0x1e94a }, /* Mn */
- { 0xe0100, 0xe01ef }, /* Mn */
diff --git a/contrib/less/decode.c b/contrib/less/decode.c
index 8e451d1810c9..1d80d126c207 100644
--- a/contrib/less/decode.c
+++ b/contrib/less/decode.c
@@ -483,12 +483,12 @@ public void add_ecmd_table(unsigned char *buf, size_t len)
/*
* Add an environment variable table.
*/
-static void add_var_table(struct tablelist **tlist, unsigned char *buf, size_t len)
+static void add_var_table(struct tablelist **tlist, mutable unsigned char *buf, size_t len)
{
struct xbuffer xbuf;
xbuf_init(&xbuf);
- expand_evars((char*)buf, len, &xbuf); /*{{unsigned-issue}}*/
+ expand_evars((mutable char*)buf, len, &xbuf); /*{{unsigned-issue}}*/
/* {{ We leak the table in buf. expand_evars scribbled in it so it's useless anyway. }} */
if (add_cmd_table(tlist, xbuf.data, xbuf.end) < 0)
error("Warning: environment variables from lesskey file unavailable", NULL_PARG);
@@ -749,7 +749,8 @@ static int cmd_search(constant char *cmd, constant unsigned char *table, constan
if (match == cmdlen) /* (last chars of) cmd matches this table entry */
{
action = taction;
- *extra = textra;
+ if (extra != NULL)
+ *extra = textra;
} else if (match > 0 && action == A_INVALID) /* cmd is a prefix of this table entry */
{
action = A_PREFIX;
@@ -780,13 +781,11 @@ static int cmd_decode(struct tablelist *tlist, constant char *cmd, constant char
for (t = tlist; t != NULL; t = t->t_next)
{
constant unsigned char *tsp;
- size_t mlen;
+ size_t mlen = match_len;
int taction = cmd_search(cmd, t->t_start, t->t_end, &tsp, &mlen);
if (mlen >= match_len)
{
match_len = mlen;
- if (taction == A_UINVALID)
- taction = A_INVALID;
if (taction != A_INVALID)
{
*sp = (constant char *) tsp;
diff --git a/contrib/less/edit.c b/contrib/less/edit.c
index 0254584bf211..1816e6f9f9bc 100644
--- a/contrib/less/edit.c
+++ b/contrib/less/edit.c
@@ -113,9 +113,7 @@ public constant char * forw_textlist(struct textlist *tlist, constant char *prev
s = tlist->string;
else
s = prev + strlen(prev);
- if (s >= tlist->endstring)
- return (NULL);
- while (*s == '\0')
+ while (s < tlist->endstring && *s == '\0')
s++;
if (s >= tlist->endstring)
return (NULL);
@@ -306,7 +304,11 @@ static void close_pipe(FILE *pipefd)
if (WIFSIGNALED(status))
{
int sig = WTERMSIG(status);
- if (sig != SIGPIPE || ch_length() != NULL_POSITION)
+ if (
+#ifdef SIGPIPE
+ sig != SIGPIPE ||
+#endif
+ ch_length() != NULL_POSITION)
{
parg.p_string = signal_message(sig);
error("Input preprocessor terminated: %s", &parg);
diff --git a/contrib/less/fmt.uni b/contrib/less/fmt.uni
index 91cfc3e91e61..c861e1908360 100644
--- a/contrib/less/fmt.uni
+++ b/contrib/less/fmt.uni
@@ -1,5 +1,4 @@
-/* Generated by "./mkutable -f2 Cf -- unicode/UnicodeData.txt" on Oct 1 18:10:07 GMT 2024 */
- { 0x00ad, 0x00ad }, /* Cf */
+/* Generated by "./mkutable -f2 Cf -- unicode/UnicodeData.txt" on Jul 27 19:38:50 GMT 2025 */
{ 0x0600, 0x0605 }, /* Cf */
{ 0x061c, 0x061c }, /* Cf */
{ 0x06dd, 0x06dd }, /* Cf */
@@ -7,7 +6,8 @@
{ 0x0890, 0x0891 }, /* Cf */
{ 0x08e2, 0x08e2 }, /* Cf */
{ 0x180e, 0x180e }, /* Cf */
- { 0x200b, 0x200f }, /* Cf */
+ { 0x200b, 0x200c }, /* Cf */
+ { 0x200e, 0x200f }, /* Cf */
{ 0x202a, 0x202e }, /* Cf */
{ 0x2060, 0x2064 }, /* Cf */
{ 0x2066, 0x206f }, /* Cf */
diff --git a/contrib/less/forwback.c b/contrib/less/forwback.c
index 300e669f9371..e77c0d4ce198 100644
--- a/contrib/less/forwback.c
+++ b/contrib/less/forwback.c
@@ -359,7 +359,7 @@ public void forw(int n, POSITION pos, lbool force, lbool only_last, lbool to_new
}
if (!first_line)
add_forw_pos(pos, FALSE);
- if (nlines == 0 && !ignore_eoi)
+ if (nlines == 0 && !ignore_eoi && !ABORT_SIGS())
eof_bell();
else if (do_repaint)
repaint();
diff --git a/contrib/less/funcs.h b/contrib/less/funcs.h
index b001a5c31902..11605acc8b3b 100644
--- a/contrib/less/funcs.h
+++ b/contrib/less/funcs.h
@@ -14,6 +14,8 @@ public void init_win_colors(void);
public void get_term(void);
public void init_mouse(void);
public void deinit_mouse(void);
+public void suspend_screen(void);
+public void resume_screen(void);
public void init(void);
public void deinit(void);
public int interactive(void);
@@ -83,6 +85,7 @@ public LWCHAR step_char(char **pp, signed int dir, constant char *limit);
public lbool is_composing_char(LWCHAR ch);
public lbool is_ubin_char(LWCHAR ch);
public lbool is_wide_char(LWCHAR ch);
+public lbool is_omit_char(LWCHAR ch);
public lbool is_combining_char(LWCHAR ch1, LWCHAR ch2);
public void cmd_reset(void);
public void clear_cmd(void);
@@ -228,7 +231,9 @@ public void jump_loc(POSITION pos, int sline);
public void init_line(void);
public lbool is_ascii_char(LWCHAR ch);
public POSITION line_position(void);
-public void prewind(void);
+public lbool is_line_contig_pos(POSITION pos);
+public void set_line_contig_pos(POSITION pos);
+public void prewind(lbool contig);
public void plinestart(POSITION pos);
public int line_pfx_width(void);
public void pshift_all(void);
@@ -314,6 +319,7 @@ public void opt_wheel_lines(int type, constant char *s);
public void opt_linenum_width(int type, constant char *s);
public void opt_status_col_width(int type, constant char *s);
public void opt_filesize(int type, constant char *s);
+public void opt_first_cmd_at_prompt(int type, constant char *s);
public void opt_intr(int type, constant char *s);
public int next_cnum(constant char **sp, constant char *printopt, constant char *errmsg, lbool *errp);
public void opt_header(int type, constant char *s);
@@ -343,6 +349,7 @@ public struct loption * findopt(int c);
public struct loption * findopt_name(constant char **p_optname, constant char **p_oname, lbool *p_ambig);
public char * findopts_name(constant char *pfx);
public void init_poll(void);
+public lbool ttyin_ready(void);
public int supports_ctrl_x(void);
public ssize_t iread(int fd, unsigned char *buf, size_t len);
public int iopen(constant char *filename, int flags);
@@ -403,6 +410,7 @@ public lbool is_filtered(POSITION pos);
public POSITION next_unfiltered(POSITION pos);
public int is_hilited_attr(POSITION pos, POSITION epos, int nohide, int *p_matches);
public void chg_hilite(void);
+public POSITION search_pos(int search_type);
public void osc8_search(int search_type, constant char *param, int matches);
public lbool osc8_click(int sindex, int col);
public void osc8_open(void);
@@ -439,7 +447,7 @@ public void xbuf_add_byte(struct xbuffer *xbuf, unsigned char b);
public void xbuf_add_char(struct xbuffer *xbuf, char c);
public void xbuf_add_data(struct xbuffer *xbuf, constant unsigned char *data, size_t len);
public int xbuf_pop(struct xbuffer *buf);
-public void xbuf_set(struct xbuffer *dst, struct xbuffer *src);
+public void xbuf_set(struct xbuffer *dst, constant struct xbuffer *src);
public constant char * xbuf_char_data(constant struct xbuffer *xbuf);
public lbool help_ckd_add(void *r, uintmax a, uintmax b, int rsize, int rsigned);
public lbool help_ckd_mul(void *r, uintmax a, uintmax b, int rsize, int rsigned);
diff --git a/contrib/less/help.c b/contrib/less/help.c
index 5d8ba9a1b0fe..ed9465ad9560 100644
--- a/contrib/less/help.c
+++ b/contrib/less/help.c
@@ -1,4 +1,4 @@
-/* This file was generated by mkhelp.pl from less.hlp at 19:46 on 2025/5/28 */
+/* This file was generated by mkhelp.pl from less.hlp at 18:02 on 2025/10/4 */
#include "less.h"
constant char helpdata[] = {
'\n',
diff --git a/contrib/less/input.c b/contrib/less/input.c
index c2f7a28c2c58..dda039b21a27 100644
--- a/contrib/less/input.c
+++ b/contrib/less/input.c
@@ -96,6 +96,8 @@ public POSITION forw_line_seg(POSITION curr_pos, lbool skipeol, lbool rscroll, l
if (p_linepos != NULL)
*p_linepos = NULL_POSITION;
+ if (p_newline != NULL)
+ *p_newline = TRUE;
get_forw_line:
if (curr_pos == NULL_POSITION)
@@ -104,7 +106,7 @@ get_forw_line:
return (NULL_POSITION);
}
#if HILITE_SEARCH
- if (hilite_search == OPT_ONPLUS || is_filtering() || status_col)
+ if (hilite_search == OPT_ONPLUS || is_filtering() || (status_col && hilite_search != OPT_ON))
{
/*
* If we are ignoring EOI (command F), only prepare
@@ -142,39 +144,48 @@ get_forw_line:
/*
* Read forward again to the position we should start at.
*/
- prewind();
- plinestart(base_pos);
- (void) ch_seek(base_pos);
- new_pos = base_pos;
- while (new_pos < curr_pos)
+ if (is_line_contig_pos(curr_pos))
{
- c = ch_forw_get();
- if (c == EOI)
- {
- null_line();
- return (NULL_POSITION);
- }
- backchars = pappend((char) c, new_pos);
- new_pos++;
- if (backchars > 0)
+ prewind(TRUE);
+ plinestart(base_pos);
+ ch_seek(curr_pos);
+ new_pos = curr_pos;
+ } else
+ {
+ prewind(FALSE);
+ plinestart(base_pos);
+ ch_seek(base_pos);
+ new_pos = base_pos;
+ while (new_pos < curr_pos)
{
- pshift_all();
- if (wordwrap && (c == ' ' || c == '\t'))
+ c = ch_forw_get();
+ if (c == EOI)
{
- do
+ null_line();
+ return (NULL_POSITION);
+ }
+ backchars = pappend((char) c, new_pos);
+ new_pos++;
+ if (backchars > 0)
+ {
+ pshift_all();
+ if (wordwrap && (c == ' ' || c == '\t'))
{
- new_pos++;
- c = ch_forw_get(); /* {{ what if c == EOI? }} */
- } while (c == ' ' || c == '\t');
- backchars = 1;
+ do
+ {
+ new_pos++;
+ c = ch_forw_get(); /* {{ what if c == EOI? }} */
+ } while (c == ' ' || c == '\t');
+ backchars = 1;
+ }
+ new_pos -= backchars;
+ while (--backchars >= 0)
+ (void) ch_back_get();
}
- new_pos -= backchars;
- while (--backchars >= 0)
- (void) ch_back_get();
}
+ pshift_all();
}
(void) pflushmbc();
- pshift_all();
/*
* Read the first character to display.
@@ -329,6 +340,7 @@ get_forw_line:
*p_linepos = curr_pos;
if (p_newline != NULL)
*p_newline = endline;
+ set_line_contig_pos(endline ? NULL_POSITION : new_pos);
return (new_pos);
}
@@ -358,6 +370,8 @@ public POSITION back_line(POSITION curr_pos, lbool *p_newline)
lbool skipped_leading;
get_back_line:
+ if (p_newline != NULL)
+ *p_newline = TRUE;
if (curr_pos == NULL_POSITION || curr_pos <= ch_zero())
{
null_line();
@@ -426,7 +440,7 @@ get_back_line:
}
#if HILITE_SEARCH
- if (hilite_search == OPT_ONPLUS || is_filtering() || status_col)
+ if (hilite_search == OPT_ONPLUS || is_filtering() || (status_col && hilite_search != OPT_ON))
prep_hilite(base_pos, NULL_POSITION, 1);
#endif
@@ -446,10 +460,8 @@ get_back_line:
return (NULL_POSITION);
}
endline = FALSE;
- prewind();
+ prewind(FALSE);
plinestart(new_pos);
- if (p_newline != NULL)
- *p_newline = TRUE;
loop:
wrap_pos = NULL_POSITION;
skipped_leading = FALSE;
diff --git a/contrib/less/less.h b/contrib/less/less.h
index 7b2d2c25bfc6..a30693a35a7a 100644
--- a/contrib/less/less.h
+++ b/contrib/less/less.h
@@ -216,7 +216,7 @@ void free();
* Special types and constants.
*/
typedef unsigned long LWCHAR;
-#if defined(MINGW) || (defined(_MSC_VER) && _MSC_VER >= 1500)
+#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER >= 1500)
typedef long long less_off_t; /* __int64 */
typedef struct _stat64 less_stat_t;
#define less_fstat _fstat64
@@ -435,6 +435,7 @@ typedef enum osc8_state {
#define AT_ANSI (1 << 4) /* Content-supplied "ANSI" escape sequence */
#define AT_BINARY (1 << 5) /* LESS*BINFMT representation */
#define AT_HILITE (1 << 6) /* Internal highlights (e.g., for search) */
+#define AT_PLACEHOLDER (1 << 7) /* Placeholder for half of double-wide char */
#define AT_COLOR_SHIFT 8
#define AT_NUM_COLORS 16
@@ -554,6 +555,8 @@ typedef enum {
#define ESC CONTROL('[')
#define ESCS "\33"
#define CSI ((unsigned char)'\233')
+#define VARSEL_15 ((LWCHAR)0xFE0E) /* VARIATION SELECTOR 15 */
+#define VARSEL_16 ((LWCHAR)0xFE0F) /* VARIATION SELECTOR 16 */
#if _OSK_MWC32
#define LSIGNAL(sig,func) os9_signal(sig,func)
diff --git a/contrib/less/less.nro b/contrib/less/less.nro
index 25a9869a9c59..ae43e8851d0e 100644
--- a/contrib/less/less.nro
+++ b/contrib/less/less.nro
@@ -1,5 +1,5 @@
'\" t
-.TH LESS 1 "Version 679: 28 May 2025"
+.TH LESS 1 "Version 685: 04 Oct 2025"
.SH NAME
less \- display the contents of a file in a terminal
.SH SYNOPSIS
@@ -203,8 +203,11 @@ Followed by another single quote, returns to the position at
which the last "large" movement command was executed.
Followed by a \(ha or $, jumps to the beginning or end of the
file respectively.
-Marks are preserved when a new file is examined,
+Marks are preserved when a new file is examined within a single invocation of
+.BR less ,
so the \(aq command can be used to switch between input files.
+The \-\-save-marks option causes marks to be preserved across different invocations of
+.BR less .
.IP "\(haX\(haX"
Same as single quote.
.IP "ESC-m"
@@ -800,8 +803,9 @@ where the first integer specifies the foreground color and
the second specifies the background color.
Each integer is a value between 0 and 255 inclusive which selects
a "CSI 38;5" color value (see
-.UR https://en.wikipedia.org/wiki/ANSI_escape_code#SGR
-.UE ).
+.nh
+https://en.wikipedia.org/wiki/ANSI_escape_code#SGR).
+.hy
If either integer is a "-" or is omitted,
the corresponding color is set to that of normal text.
.PP
@@ -835,8 +839,9 @@ CHAR_INFO.Attributes
.hy
value, between 0 and 15 inclusive
(see
-.UR https://learn.microsoft.com/en-us/windows/console/char-info-str
-.UE ).
+.nh
+https://learn.microsoft.com/en-us/windows/console/char-info-str).
+.hy
To avoid confusion, it is recommended that the equivalent letters rather than numbers
be used after a lowercase color selector on MS-DOS/Windows.
@@ -1213,8 +1218,9 @@ the name of a command compatible with
.BR global (1),
and that command is executed to find the tag.
(See
-.UR http://www.gnu.org/software/global/global.html
-.UE ).
+.nh
+http://www.gnu.org/software/global/global.html).
+.hy
The \-t option may also be specified from within
.B less
(using the \- command) as a way of examining a new file.
@@ -1328,6 +1334,16 @@ of the screen, starting with a decimal point: \&.5 is half of the
screen width, \&.3 is three tenths of the screen width, and so on.
If the number is specified as a fraction, the actual number of
scroll positions is recalculated if the terminal window is resized.
+.IP "\-\-cmd=\fIcommands\fP
+The specified string is taken to be an initial command to
+.BR less .
+This is similar to specifying "+\fIcommands\fP", except that
+commands specified by \-\-cmd are not executed if
+.B less
+exits immediately due to the use of the \-E or \-F option, while
+commands specified by the \fB+\fP option are executed even if
+.B less
+exits immediately.
.IP "\-\-exit-follow-on-close"
When using the "F" command on a pipe,
.B less
@@ -1583,8 +1599,9 @@ Enables colored text in various places.
The \-D option can be used to change the colors.
Colored text works only if the terminal supports
ANSI color escape sequences (as defined in
-.UR https://www.ecma-international.org/publications-and-standards/standards/ecma-48
-.UE ).
+.nh
+https://www.ecma-international.org/publications-and-standards/standards/ecma-48).
+.hy
.IP "\-\-wheel-lines=\fIn\fP"
Set the number of lines to scroll when the mouse wheel is scrolled
and the \-\-mouse or \-\-MOUSE option is in effect.
@@ -1598,6 +1615,9 @@ The default is to wrap at any character.
A command line argument of "\-\-" marks the end of option arguments.
Any arguments following this are interpreted as filenames.
This can be useful when viewing a file whose name begins with a "\-" or "+".
+Otherwise, option arguments and filename arguments can be intermixed;
+that is, option arguments do not need to appear before filename arguments,
+unless the environment variable POSIXLY_CORRECT is set.
.IP +
If a command line option begins with \fB+\fP,
the remainder of that option is taken to be an initial command to
@@ -1613,6 +1633,7 @@ If the option starts with ++, the initial command applies to
every file being viewed, not just the first one.
The + command described previously
may also be used to set (or change) an initial command for every file.
+Also see the \-\-cmd option.
.
.SH "LINE EDITING"
When entering a command line at the bottom of the screen
@@ -1913,7 +1934,7 @@ Again, in this case the dash is not considered to be part of
the input pipe command.
.
.SH "NATIONAL CHARACTER SETS"
-There are three types of characters in the input file:
+There are five types of characters in the input file:
.IP "normal characters"
can be displayed directly to the screen.
.IP "control characters"
@@ -1922,6 +1943,12 @@ in ordinary text files (such as backspace and tab).
.IP "binary characters"
should not be displayed directly and are not expected to be found
in text files.
+.IP "composing characters"
+are not displayed separately, but modify the display of the
+preceding character. (Only when LESSCHARSET is "utf8".)
+.IP "deleted characters"
+are simply deleted from the input and not displayed.
+(Only when LESSCHARSET is "utf8".)
.PP
A "character set" is simply a description of which characters are to
be considered normal, control, and binary.
@@ -2049,7 +2076,7 @@ of how the UTF-8 file is ill-formed.
.PP
When the character set is utf-8, in rare cases it may be desirable to
override the Unicode definition of the type of certain characters.
-For example, characters in a Private Use Area are normally treated as control
+For example, characters in a Private Use Area are normally treated as binary
characters, but if you are using a custom font with printable characters
in that range, it may be desirable to tell
.B less
@@ -2076,6 +2103,8 @@ A wide (2-space) printable character.
A binary (non-printable) character.
.IP "c"
A composing (zero width) character.
+.IP "d"
+A deleted character (deleted from the input and not displayed).
.RE
.PP
For example, setting LESSUTFCHARDEF to
@@ -2085,6 +2114,18 @@ For example, setting LESSUTFCHARDEF to
.sp
.fi
would make all Private Use Area characters be treated as printable.
+.PP
+By default, emoji modifiers, components and variation selectors
+are deleted because many terminals do not display them correctly.
+If you use a terminal which does display some or all of them correctly,
+you can cause to be displayed by setting LESSUTFCHARDEF
+to treat them as composing characters.
+For example, this sets them all to composing characters:
+.nf
+.sp
+ FE00-FE0F:c,1F3FB-1F3FF:c,1F9B0-1F9B3:c,E0100-E01EF:c
+.sp
+.fi
.SH "PROMPTS"
The \-P option allows you to tailor the prompt to your preference.
The string given to the \-P option replaces the specified prompt string.
@@ -2407,8 +2448,8 @@ end character in an ANSI color escape sequence
(default "0123456789:;[?!"\(aq#%()*+\ ").
.IP LESSANSIOSCALLOW
A comma-separated list of OSC types which are output directly to the
-terminal when \-R is in effect.
-By default, only OSC 8 sequences are output directly.
+terminal when \-R is in effect
+(default "8"; that is, only OSC 8 sequences are output directly).
.IP LESSANSIOSCCHARS
Characters which may follow an ESC character to mark the start
of an "OS Command" sequence.
@@ -2480,9 +2521,7 @@ file. (Not used if "$LESSKEYIN_SYSTEM" exists.)
List of characters which are considered "metacharacters" by the shell.
.IP LESSMETAESCAPE
Prefix which less will add before each metacharacter in a
-command sent to the shell.
-If LESSMETAESCAPE is an empty string, commands containing
-metacharacters will not be passed to the shell.
+command sent to the shell (default "\\").
.IP LESSOPEN
Command line to invoke the (optional) input-preprocessor.
.IP LESSSECURE
@@ -2492,7 +2531,8 @@ See discussion under SECURITY.
Enables individual features which are normally disabled by LESSSECURE.
See discussion under SECURITY.
.IP LESSSEPARATOR
-String to be appended to a directory name in filename completion.
+String to be appended to a directory name in filename completion
+(default "\\" on MS-DOS, Windows, and OS/2; otherwise "/").
.IP LESSUTFBINFMT
Format for displaying non-printable Unicode code points.
.IP LESSUTFCHARDEF
@@ -2550,6 +2590,24 @@ receives a SIGUSR1 signal.
.IP LESS_TERMCAP_xx
Where "xx" is any two characters, overrides the definition
of the termcap "xx" capability for the terminal.
+.IP LESS_TERMCAP_BRACKETED_PASTE_START
+Overrides the standard ANSI escape sequence to enable bracketed paste.
+This is used when the \-\-no-paste option is in effect.
+.IP LESS_TERMCAP_BRACKETED_PASTE_END
+Overrides the standard ANSI escape sequence to disable bracketed paste.
+.IP LESS_TERMCAP_MOUSE_START
+Overrides the standard ANSI escape sequence to enable mouse reporting.
+This is used when the \-\-mouse option is in effect.
+.IP LESS_TERMCAP_MOUSE_END
+Overrides the standard ANSI escape sequence to disable mouse reporting.
+.IP LESS_TERMCAP_SUSPEND
+Defines an escape sequence to temporarily suspend screen updates.
+This is sent to the terminal before clearing the screen.
+This can be used to avoid screen tearing when the screen is redrawn
+on certain terminals.
+.IP LESS_TERMCAP_RESUME
+Defines an escape sequence to resume screen updates.
+This is sent to the terminal after displaying the prompt.
.IP LESS_UNSUPPORT
A space-separated list of command line options.
These options will be ignored (with no error message) if they appear
@@ -2571,6 +2629,12 @@ automatically when running in
.IP PATH
User's search path (used to find a lesskey file
on MS-DOS, Windows, and OS/2 systems).
+.IP POSIXLY_CORRECT
+If set to any value, all option arguments on the command line
+are expected to appear before any filename arguments.
+This must be set as an actual environment variable, not in a
+.B lesskey
+file.
.IP SHELL
The shell used to execute the !\& command, as well as to expand filenames.
.IP TERM
@@ -2619,10 +2683,12 @@ See the GNU General Public License for more details.
Mark Nudelman
.br
Report bugs at
-.UR https://github.com/gwsw/less/issues
-.UE .
+.nh
+https://github.com/gwsw/less/issues.
+.hy
.br
For more information, see the less homepage at
.br
-.UR https://greenwoodsoftware.com/less
-.UE .
+.nh
+https://greenwoodsoftware.com/less.
+.hy
diff --git a/contrib/less/lessecho.nro b/contrib/less/lessecho.nro
index f0cccc4de6da..71e029fe81c4 100644
--- a/contrib/less/lessecho.nro
+++ b/contrib/less/lessecho.nro
@@ -1,4 +1,4 @@
-.TH LESSECHO 1 "Version 679: 28 May 2025"
+.TH LESSECHO 1 "Version 685: 04 Oct 2025"
.SH NAME
lessecho \- expand metacharacters
.SH SYNOPSIS
@@ -53,6 +53,4 @@ The default is that only arguments containing metacharacters are quoted.
This manual page was written by Thomas Schoepf <schoepf@debian.org>,
for the Debian GNU/Linux system (but may be used by others).
.PP
-Report bugs at
-.UR https://github.com/gwsw/less/issues
-.UE .
+Report bugs at https://github.com/gwsw/less/issues.
diff --git a/contrib/less/lesskey.nro b/contrib/less/lesskey.nro
index 0a17c9deff71..b829c062cdb4 100644
--- a/contrib/less/lesskey.nro
+++ b/contrib/less/lesskey.nro
@@ -1,5 +1,5 @@
'\" t
-.TH LESSKEY 1 "Version 679: 28 May 2025"
+.TH LESSKEY 1 "Version 685: 04 Oct 2025"
.SH NAME
lesskey \- customize key bindings for less
.SH "SYNOPSIS (deprecated)"
@@ -83,8 +83,10 @@ l l l.
\er RETURN (0x0D)
\et TAB (0x09)
.TE
+.RE
.sp
\ek followed by a single character represents the char(s) produced when one of these keys is pressed:
+.RS 5m
.TS
l l.
\ekb BACKSPACE (the BACKSPACE key)
@@ -105,7 +107,7 @@ l l.
\ekX ctrl-DELETE
\ek1 F1
.TE
-
+.RE
.PP
A backslash followed by any other character indicates that character is
to be taken literally.
@@ -121,6 +123,14 @@ string is parsed, just as if it were typed in to
This feature can be used in certain cases to extend
the functionality of a command.
For example, see the "{" and ":t" commands in the example below.
+It can also be used to execute more than one command when a key is pressed.
+For example, if this line were in a lesskey file, pressing the "B" key
+would first set the "b" mark and then search for the string "next":
+.sp
+.nf
+ B set-mark b/next\en
+.fi
+.sp
The extra string has a special meaning for the "quit" action:
when
.B less
@@ -486,6 +496,4 @@ See the GNU General Public License for more details.
.
Mark Nudelman
.br
-Report bugs at
-.UR https://github.com/gwsw/less/issues
-.UE .
+Report bugs at https://github.com/gwsw/less/issues.
diff --git a/contrib/less/lglob.h b/contrib/less/lglob.h
index d54315aef39d..af261fb2cfdd 100644
--- a/contrib/less/lglob.h
+++ b/contrib/less/lglob.h
@@ -56,7 +56,7 @@
char ext[_MAX_EXT]; \
int handle;
#else
-#if MSDOS_COMPILER==WIN32C && (defined(_MSC_VER) || defined(MINGW))
+#if MSDOS_COMPILER==WIN32C && (defined(_MSC_VER) || defined(__MINGW32__))
#define GLOB_FIRST_NAME(filename,fndp,h) h = _findfirst(filename, fndp)
#define GLOB_FIRST_FAILED(handle) ((handle) == -1)
diff --git a/contrib/less/line.c b/contrib/less/line.c
index 8cc6397b804b..fc5d18abf4d2 100644
--- a/contrib/less/line.c
+++ b/contrib/less/line.c
@@ -28,6 +28,7 @@ static struct {
int *attr; /* Parallel to buf, to hold attributes */
size_t print; /* Index in buf of first printable char */
size_t end; /* Number of chars in buf */
+ size_t prev_end; /* Number of chars in buf for previous line */
char pfx[MAX_PFX_WIDTH]; /* Holds status column and line number */
int pfx_attr[MAX_PFX_WIDTH];
size_t pfx_end; /* Number of chars in pfx */
@@ -63,6 +64,7 @@ public int ntabstops = 1; /* Number of tabstops */
public int tabdefault = 8; /* Default repeated tabstops */
public POSITION highest_hilite; /* Pos of last hilite in file found so far */
static POSITION line_pos;
+static POSITION line_contig_pos = NULL_POSITION; /* One after last byte processed */
static int end_column; /* Printable length, accounting for backspaces, etc. */
static int right_curr;
@@ -255,12 +257,42 @@ public POSITION line_position(void)
}
/*
+ * Is this byte the next one after the previous byte processed?
+ */
+public lbool is_line_contig_pos(POSITION pos)
+{
+ return pos == line_contig_pos;
+}
+
+/*
+ * Set the position of the next byte to be processed.
+ */
+public void set_line_contig_pos(POSITION pos)
+{
+ line_contig_pos = pos;
+}
+
+/*
+ * Copy any ANSI sequences from line buffer to shifted_ansi.
+ */
+static void pshift(size_t end)
+{
+ size_t i;
+ for (i = linebuf.print; i < end; i++)
+ if (linebuf.attr[i] == AT_ANSI)
+ xbuf_add_char(&shifted_ansi, linebuf.buf[i]);
+}
+
+/*
* Rewind the line buffer.
*/
-public void prewind(void)
+public void prewind(lbool contig)
{
int ax;
+ xbuf_reset(&shifted_ansi);
+ if (contig && linebuf.prev_end != 0)
+ pshift(linebuf.prev_end);
linebuf.print = 6; /* big enough for longest UTF-8 sequence */
linebuf.pfx_end = 0;
for (linebuf.end = 0; linebuf.end < linebuf.print; linebuf.end++)
@@ -285,7 +317,6 @@ public void prewind(void)
clear_after_line = FALSE;
line_mark_attr = 0;
line_pos = NULL_POSITION;
- xbuf_reset(&shifted_ansi);
xbuf_reset(&last_ansi);
for (ax = 0; ax < NUM_LAST_ANSIS; ax++)
xbuf_reset(&last_ansis[ax]);
@@ -431,10 +462,7 @@ public int line_pfx_width(void)
*/
public void pshift_all(void)
{
- size_t i;
- for (i = linebuf.print; i < linebuf.end; i++)
- if (linebuf.attr[i] == AT_ANSI)
- xbuf_add_char(&shifted_ansi, linebuf.buf[i]);
+ pshift(linebuf.end);
linebuf.end = linebuf.print;
end_column = (int) linebuf.pfx_end; /*{{type-issue}}*/
line_pos = NULL_POSITION;
@@ -517,6 +545,12 @@ public int pwidth(LWCHAR ch, int a, LWCHAR prev_ch, int prev_a)
}
} else
{
+ if (ch == VARSEL_15)
+ /* If prev char was double width, make it single width. */
+ return (prev_ch != 0 && pwidth(prev_ch, a, 0, 0) == 2) ? -1 : 0;
+ if (ch == VARSEL_16)
+ /* If prev char was single width, make it double width. */
+ return (prev_ch != 0 && pwidth(prev_ch, a, 0, 0) == 1) ? +1 : 0;
if (is_composing_char(ch) || is_combining_char(prev_ch, ch))
{
/*
@@ -814,6 +848,7 @@ static int store_char(LWCHAR ch, int a, constant char *rep, POSITION pos)
size_t replen;
char cs;
int ov;
+ lbool need_shift;
ov = (a & (AT_UNDERLINE|AT_BOLD));
if (ov != AT_NORMAL)
@@ -899,14 +934,41 @@ static int store_char(LWCHAR ch, int a, constant char *rep, POSITION pos)
add_linebuf((char) shifted_ansi.data[i], AT_ANSI, 0);
xbuf_reset(&shifted_ansi);
}
+ if (linebuf.end == linebuf.print+1)
+ {
+ /* If first char is a placeholder, the one before it is double-width.
+ * VS15 changes the double-width char to single-width, so replace the
+ * placeholder with this VS15. */
+ if (ch == VARSEL_15 && (linebuf.attr[linebuf.end-1] & AT_PLACEHOLDER))
+ {
+ linebuf.end--;
+ inc_end_column(-1);
+ }
+ } else if (linebuf.end == linebuf.print)
+ {
+ /* VS16 changes the previous single-width char to double-width.
+ * Add a placeholder to represent the second half of the
+ * double-width char. */
+ if (ch == VARSEL_16)
+ {
+ char *p = &linebuf.buf[linebuf.end];
+ LWCHAR prev_ch = (linebuf.end > 0) ? step_char(&p, -1, linebuf.buf) : 0;
+ if (prev_ch != 0 && pwidth(prev_ch, a, 0, 0) == 1)
+ add_linebuf(' ', rscroll_attr|AT_PLACEHOLDER, 0);
+ }
+ }
}
/* Add the char to the buf, even if we will left-shift it next. */
+ need_shift = (cshift < hshift);
+ if (!need_shift && w <= 0 && linebuf.end <= linebuf.print+1 && is_composing_char(ch) &&
+ (linebuf.end == linebuf.print || (linebuf.end == linebuf.print+1 && (linebuf.attr[linebuf.end-1] & AT_PLACEHOLDER))))
+ need_shift = TRUE;
inc_end_column(w);
for (i = 0; i < replen; i++)
add_linebuf(*rep++, a, 0);
- if (cshift < hshift)
+ if (need_shift)
{
/* We haven't left-shifted enough yet. */
if (a == AT_ANSI)
@@ -929,7 +991,7 @@ static int store_char(LWCHAR ch, int a, constant char *rep, POSITION pos)
*/
while (cshift > hshift)
{
- add_linebuf(' ', rscroll_attr, 0);
+ add_linebuf(' ', rscroll_attr|AT_PLACEHOLDER, 0);
cshift--;
}
}
@@ -1267,6 +1329,17 @@ static int do_append(LWCHAR ch, constant char *rep, POSITION pos)
overstrike = 0;
}
+ if (is_omit_char(ch))
+ {
+ if (bs_mode == BS_CONTROL)
+ {
+ if (utf_mode)
+ STORE_STRING(prutfchar(ch), AT_BINARY, pos);
+ else
+ STORE_PRCHAR(ch, pos);
+ }
+ return (0); /* omit the character. */
+ }
if (ch == '\t')
{
/*
@@ -1340,6 +1413,7 @@ static void add_attr_normal(void)
public void pdone(lbool endline, lbool chopped, lbool forw)
{
(void) pflushmbc();
+ linebuf.prev_end = (!endline && !chopped) ? linebuf.end : 0;
if (pendc && (pendc != '\r' || !endline))
/*
@@ -1509,7 +1583,11 @@ static void col_vs_pos(POSITION linepos, mutable struct col_pos *cp, POSITION sa
LWCHAR wch = get_wchar(utf8_buf);
int attr = 0; /* {{ ignoring attribute is not correct for magic cookie terminals }} */
utf8_len = 0;
- if (utf_mode && ctldisp != OPT_ON && is_ubin_char(wch))
+ if (is_omit_char(wch))
+ {
+ if (bs_mode == BS_CONTROL)
+ cw = strlen(utf_mode ? prutfchar(wch) : prchar(wch));
+ } else if (utf_mode && ctldisp != OPT_ON && is_ubin_char(wch))
cw = (int) strlen(prutfchar(wch));
else
cw = pwidth(wch, attr, prev_ch, attr);
@@ -1638,6 +1716,7 @@ public POSITION forw_raw_line_len(POSITION curr_pos, size_t read_len, constant c
(c = ch_forw_get()) == EOI)
return (NULL_POSITION);
+ set_line_contig_pos(NULL_POSITION);
n = 0;
for (;;)
{
@@ -1693,6 +1772,7 @@ public POSITION back_raw_line(POSITION curr_pos, constant char **linep, size_t *
ch_seek(curr_pos-1))
return (NULL_POSITION);
+ set_line_contig_pos(NULL_POSITION);
n = size_linebuf;
linebuf.buf[--n] = '\0';
for (;;)
@@ -1804,11 +1884,14 @@ static int pappstr(constant char *str)
public void load_line(constant char *str)
{
int save_hshift = hshift;
-
hshift = 0;
+
+ /* We're overwriting the line buffer, so what's in it will no longer be contiguous. */
+ set_line_contig_pos(NULL_POSITION);
+
for (;;)
{
- prewind();
+ prewind(FALSE);
if (pappstr(str) == 0)
break;
/*
@@ -1819,6 +1902,7 @@ public void load_line(constant char *str)
hshift += 1;
}
set_linebuf(linebuf.end, '\0', AT_NORMAL);
+ linebuf.prev_end = 0;
/* Color the prompt unless it has ansi sequences in it. */
if (!ansi_in_line)
diff --git a/contrib/less/lsystem.c b/contrib/less/lsystem.c
index c32d5d59d4c2..a56f8238e480 100644
--- a/contrib/less/lsystem.c
+++ b/contrib/less/lsystem.c
@@ -19,7 +19,7 @@
#if MSDOS_COMPILER
#include <dos.h>
-#if MSDOS_COMPILER==WIN32C && defined(MINGW)
+#if MSDOS_COMPILER==WIN32C && defined(__MINGW32__)
#include <direct.h>
#define setdisk(n) _chdrive((n)+1)
#else
diff --git a/contrib/less/main.c b/contrib/less/main.c
index 280322e01d4b..e3a546d7084d 100644
--- a/contrib/less/main.c
+++ b/contrib/less/main.c
@@ -17,7 +17,7 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
-#if defined(MINGW) || defined(_MSC_VER)
+#if defined(__MINGW32__) || defined(_MSC_VER)
#include <locale.h>
#include <shellapi.h>
#endif
@@ -78,7 +78,7 @@ extern int redraw_on_quit;
extern int term_init_done;
extern lbool first_time;
-#if MSDOS_COMPILER==WIN32C && (defined(MINGW) || defined(_MSC_VER))
+#if MSDOS_COMPILER==WIN32C && (defined(__MINGW32__) || defined(_MSC_VER))
/* malloc'ed 0-terminated utf8 of 0-terminated wide ws, or null on errors */
static char *utf8_from_wide(constant wchar_t *ws)
{
@@ -247,8 +247,14 @@ int main(int argc, constant char *argv[])
{
IFILE ifile;
constant char *s;
+ int i;
+ struct xbuffer xfiles;
+ constant int *files;
+ size_t num_files;
+ lbool end_opts = FALSE;
+ lbool posixly_correct = FALSE;
-#if MSDOS_COMPILER==WIN32C && (defined(MINGW) || defined(_MSC_VER))
+#if MSDOS_COMPILER==WIN32C && (defined(__MINGW32__) || defined(_MSC_VER))
if (GetACP() != CP_UTF8) /* not using a UTF-8 manifest */
try_utf8_locale(&argc, &argv);
#endif
@@ -318,13 +324,20 @@ int main(int argc, constant char *argv[])
#define isoptstring(s) less_is_more ? (((s)[0] == '-') && (s)[1] != '\0') : \
(((s)[0] == '-' || (s)[0] == '+') && (s)[1] != '\0')
- while (argc > 0 && (isoptstring(*argv) || isoptpending()))
+ xbuf_init(&xfiles);
+ posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
+ for (i = 0; i < argc; i++)
{
- s = *argv++;
- argc--;
- if (strcmp(s, "--") == 0)
- break;
- scan_option(s, FALSE);
+ if (strcmp(argv[i], "--") == 0)
+ end_opts = TRUE;
+ else if (!end_opts && (isoptstring(argv[i]) || isoptpending()))
+ scan_option(argv[i], FALSE);
+ else
+ {
+ if (posixly_correct)
+ end_opts = TRUE;
+ xbuf_add_data(&xfiles, (constant unsigned char *) &i, sizeof(i));
+ }
}
#undef isoptstring
@@ -364,7 +377,9 @@ int main(int argc, constant char *argv[])
ifile = NULL_IFILE;
if (dohelp)
ifile = get_ifile(FAKE_HELPFILE, ifile);
- while (argc-- > 0)
+ files = (constant int *) xfiles.data;
+ num_files = xfiles.end / sizeof(int);
+ for (i = 0; i < num_files; i++)
{
#if (MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC)
/*
@@ -378,7 +393,7 @@ int main(int argc, constant char *argv[])
char *gfilename;
char *qfilename;
- gfilename = lglob(*argv++);
+ gfilename = lglob(argv[files[i]]);
init_textlist(&tlist, gfilename);
filename = NULL;
while ((filename = forw_textlist(&tlist, filename)) != NULL)
@@ -390,10 +405,12 @@ int main(int argc, constant char *argv[])
}
free(gfilename);
#else
- (void) get_ifile(*argv++, ifile);
+ (void) get_ifile(argv[files[i]], ifile);
ifile = prev_ifile(NULL_IFILE);
#endif
}
+ xbuf_deinit(&xfiles);
+
/*
* Set up terminal, etc.
*/
diff --git a/contrib/less/mkutable b/contrib/less/mkutable
index 21b84c3d55de..51dbab71d161 100755
--- a/contrib/less/mkutable
+++ b/contrib/less/mkutable
@@ -22,6 +22,17 @@ my %force_space = (
0x0d => 1, # carriage return
);
+# Override Unicode tables for certain modifier chars which act differently
+# on different terminals. Treat them as omittable.
+my @force_omit = (
+ [0xad, 0xad], # SOFT HYPHEN
+ [0x200d, 0x200d], # ZERO WIDTH JOINER
+ [0x1f3fb, 0x1f3ff], # EMOJI MODIFIER FITZPATRICK TYPE-[1-6]
+ [0x1f9b0, 0x1f9b3], # EMOJI COMPONENT [RED,CURLY,BALD,WHITE] HAIR
+ [0xfe00, 0xfe0f], # VARIATION SELECTOR-[1-16]
+ [0xe0100, 0xe01ef], # VARIATION SELECTOR-[17-256]
+);
+
# Hangul Jamo medial vowels and final consonants should be zero width.
my @force_compose = (
[0x1160, 0x11ff],
@@ -51,6 +62,13 @@ sub main {
$force_compose{$ch} = 1;
}
}
+ my %force_omit;
+ foreach my $comp (@force_omit) {
+ my ($lo,$hi) = @$comp;
+ for (my $ch = $lo; $ch <= $hi; ++$ch) {
+ $force_omit{$ch} = 1;
+ }
+ }
my ($sec,$min,$hour,$mday,$mon,$year) = gmtime($ENV{SOURCE_DATE_EPOCH} // time());
my @month = ( "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" );
@@ -88,7 +106,8 @@ sub main {
$type =~ s/\s//g;
for ($last_code = $lo_code; $last_code <= $hi_code; ++$last_code) {
output(\%out, $last_code,
- $force_space{$last_code} ? 'Zs' : $force_compose{$last_code} ? 'Mn' : $type);
+ $force_space{$last_code} ? 'Zs' : $force_compose{$last_code} ? 'Mn' :
+ $force_omit{$last_code} ? 'Xx' : $type);
}
}
output(\%out, $last_code);
diff --git a/contrib/less/omit.uni b/contrib/less/omit.uni
new file mode 100644
index 000000000000..9977ec403f3d
--- /dev/null
+++ b/contrib/less/omit.uni
@@ -0,0 +1,7 @@
+/* Generated by "./mkutable -f2 Xx -- unicode/UnicodeData.txt" on Aug 19 1:16:32 GMT 2025 */
+ { 0x00ad, 0x00ad }, /* Xx */
+ { 0x200d, 0x200d }, /* Xx */
+ { 0xfe00, 0xfe0f }, /* Xx */
+ { 0x1f3fb, 0x1f3ff }, /* Xx */
+ { 0x1f9b0, 0x1f9b3 }, /* Xx */
+ { 0xe0100, 0xe01ef }, /* Xx */
diff --git a/contrib/less/optfunc.c b/contrib/less/optfunc.c
index fda46b588f21..9c0117cc84ff 100644
--- a/contrib/less/optfunc.c
+++ b/contrib/less/optfunc.c
@@ -72,6 +72,7 @@ extern int nosearch_header_lines;
extern int nosearch_header_cols;
extern POSITION header_start_pos;
extern char *init_header;
+extern char *first_cmd_at_prompt;
#if LOGFILE
extern char *namelogfile;
extern lbool force_logfile;
@@ -974,6 +975,23 @@ public void opt_filesize(int type, constant char *s)
}
/*
+ * Handler for the --cmd option.
+ */
+ /*ARGSUSED*/
+public void opt_first_cmd_at_prompt(int type, constant char *s)
+{
+ switch (type)
+ {
+ case INIT:
+ case TOGGLE:
+ first_cmd_at_prompt = save(s);
+ break;
+ case QUERY:
+ break;
+ }
+}
+
+/*
* Handler for the --intr option.
*/
/*ARGSUSED*/
diff --git a/contrib/less/opttbl.c b/contrib/less/opttbl.c
index be89403d6ce9..292a8be15d1e 100644
--- a/contrib/less/opttbl.c
+++ b/contrib/less/opttbl.c
@@ -86,6 +86,7 @@ public int no_edit_warn; /* Don't warn when editing a LESSOPENed file */
public int stop_on_form_feed; /* Stop scrolling on a line starting with form feed */
public long match_shift_fraction = NUM_FRAC_DENOM/2; /* 1/2 of screen width */
public char intr_char = CONTROL('X'); /* Char to interrupt reads */
+public char *first_cmd_at_prompt = NULL; /* Command to exec before first prompt */
#if HILITE_SEARCH
public int hilite_search; /* Highlight matched search patterns? */
#endif
@@ -184,6 +185,7 @@ static struct optname proc_backspace_optname = { "proc-backspace", NULL };
static struct optname proc_tab_optname = { "proc-tab", NULL };
static struct optname proc_return_optname = { "proc-return", NULL };
static struct optname match_shift_optname = { "match-shift", NULL };
+static struct optname first_cmd_at_prompt_optname = { "cmd", NULL };
#if LESSTEST
static struct optname ttyin_name_optname = { "tty", NULL };
#endif /*LESSTEST*/
@@ -748,6 +750,10 @@ static struct loption option[] =
"Print carriage return as ^M"
}
},
+ { OLETTER_NONE, &first_cmd_at_prompt_optname,
+ O_STRING|O_NO_TOGGLE|O_NO_QUERY, 0, NULL, opt_first_cmd_at_prompt,
+ { NULL, NULL, NULL }
+ },
{ OLETTER_NONE, &match_shift_optname,
O_STRING|O_INIT_HANDLER, 0, NULL, opt_match_shift,
{
diff --git a/contrib/less/os.c b/contrib/less/os.c
index 357cbb356a16..3bac7a61a7be 100644
--- a/contrib/less/os.c
+++ b/contrib/less/os.c
@@ -43,7 +43,7 @@ extern int errno;
#include <sys/utsname.h>
#endif
-#if HAVE_POLL && !MSDOS_COMPILER
+#if HAVE_POLL && !MSDOS_COMPILER && !defined(__MVS__)
#define USE_POLL 1
static lbool use_poll = TRUE;
#else
@@ -82,6 +82,7 @@ static lbool opening;
public lbool waiting_for_data;
public int consecutive_nulls = 0;
public lbool getting_one_screen = FALSE;
+public lbool no_poll = FALSE;
/* Milliseconds to wait for data before displaying "waiting for data" message. */
static int waiting_for_data_delay = 4000;
@@ -163,7 +164,8 @@ static int check_poll(int fd, int tty)
/* Break out of "waiting for data". */
return (READ_INTR);
ungetcc_back((char) ch);
- return (READ_INTR);
+ if (!no_poll)
+ return (READ_INTR);
}
}
if (ignore_eoi && exit_F_on_close && (poller[0].revents & (POLLHUP|POLLIN)) == POLLHUP)
@@ -177,6 +179,36 @@ static int check_poll(int fd, int tty)
}
#endif /* USE_POLL */
+/*
+ * Is a character available to be read from the tty?
+ */
+public lbool ttyin_ready(void)
+{
+#if MSDOS_COMPILER==WIN32C
+ return win32_kbhit();
+#else
+#if MSDOS_COMPILER
+ return kbhit();
+#else
+#if USE_POLL
+#if LESSTEST
+ if (is_lesstest())
+ return FALSE;
+#endif /*LESSTEST*/
+ if (!use_poll)
+ return FALSE;
+ {
+ struct pollfd poller[1] = { { tty, POLLIN, 0 } };
+ poll(poller, 1, 0);
+ return ((poller[0].revents & POLLIN) != 0);
+ }
+#else
+ return FALSE;
+#endif
+#endif
+#endif
+}
+
public int supports_ctrl_x(void)
{
#if MSDOS_COMPILER==WIN32C
@@ -282,16 +314,21 @@ start:
}
#else
#if MSDOS_COMPILER==WIN32C
- if (win32_kbhit2(TRUE))
+ if (!(quit_if_one_screen && one_screen) && win32_kbhit2(TRUE))
{
int c;
+ lbool intr;
c = WIN32getch();
- sigs |= S_SWINTERRUPT;
- reading = FALSE;
- if (c != CONTROL('C') && c != intr_char)
+ intr = (c == CONTROL('C') || c == intr_char);
+ if (!intr)
WIN32ungetch((char) c);
- return (READ_INTR);
+ if (intr || !no_poll)
+ {
+ sigs |= S_SWINTERRUPT;
+ reading = FALSE;
+ return (READ_INTR);
+ }
}
#endif
#endif
diff --git a/contrib/less/pattern.c b/contrib/less/pattern.c
index f2ec7cbcb6c8..0c72b98d2cd1 100644
--- a/contrib/less/pattern.c
+++ b/contrib/less/pattern.c
@@ -469,7 +469,12 @@ public lbool match_pattern(PATTERN_TYPE pattern, constant char *tpattern, consta
lbool matched = match_pattern1(pattern, tpattern, line, line_len, line_off, sp, ep, nsp, notbol, search_type);
if (!matched || subsearch_ok(sp, ep, search_type))
return matched;
- mlen = ep[0] - line;
+ /* We have a match, but it does not satisfy all SUBSEARCH conditions.
+ * Continue searching after this match. */
+ mlen = ptr_diff(ep[0], line);
+ if (mlen == 0)
+ /* If the match is empty, we can't progress. */
+ return FALSE;
line += mlen;
line_len -= mlen;
notbol = 1;
diff --git a/contrib/less/screen.c b/contrib/less/screen.c
index 3a997b6f1a70..7b91cbb63bbe 100644
--- a/contrib/less/screen.c
+++ b/contrib/less/screen.c
@@ -221,6 +221,8 @@ static constant char
*sc_e_mousecap, /* End mouse capture mode */
*sc_s_bracketed_paste, /* Start bracketed paste mode */
*sc_e_bracketed_paste, /* End bracketed paste mode */
+ *sc_suspend, /* Suspend screen updates */
+ *sc_resume, /* Resume screen updates */
*sc_init, /* Startup terminal initialization */
*sc_deinit; /* Exit terminal de-initialization */
@@ -1330,6 +1332,13 @@ public void get_term(void)
if (sc_e_bracketed_paste == NULL)
sc_e_bracketed_paste = ESCS"[?2004l";
+ sc_suspend = ltgetstr("SUSPEND", &sp);
+ if (sc_suspend == NULL)
+ sc_suspend = "";
+ sc_resume = ltgetstr("RESUME", &sp);
+ if (sc_resume == NULL)
+ sc_resume = "";
+
sc_init = ltgetstr("ti", &sp);
if (sc_init == NULL)
sc_init = "";
@@ -1756,6 +1765,26 @@ public void deinit_mouse(void)
}
/*
+ * Suspend screen updates.
+ */
+public void suspend_screen(void)
+{
+#if !MSDOS_COMPILER
+ ltputs(sc_suspend, 1, putchr);
+#endif
+}
+
+/*
+ * Resume screen updates.
+ */
+public void resume_screen(void)
+{
+#if !MSDOS_COMPILER
+ ltputs(sc_resume, 1, putchr);
+#endif
+}
+
+/*
* Initialize terminal
*/
public void init(void)
@@ -2341,6 +2370,7 @@ public void bell(void)
public void clear(void)
{
assert_interactive();
+ suspend_screen();
#if !MSDOS_COMPILER
ltputs(sc_clear, sc_height, putchr);
#else
diff --git a/contrib/less/search.c b/contrib/less/search.c
index 78bcc7085e2d..75f7efee0535 100644
--- a/contrib/less/search.c
+++ b/contrib/less/search.c
@@ -52,6 +52,7 @@ static POSITION prep_endpos;
public POSITION header_start_pos = NULL_POSITION;
static POSITION header_end_pos;
public lbool search_wrapped = FALSE;
+public POSITION search_incr_start = NULL_POSITION;
#if OSC8_LINK
public POSITION osc8_linepos = NULL_POSITION;
public POSITION osc8_match_start = NULL_POSITION;
@@ -1083,7 +1084,7 @@ public void chg_hilite(void)
/*
* Figure out where to start a search.
*/
-static POSITION search_pos(int search_type)
+public POSITION search_pos(int search_type)
{
POSITION pos;
int sindex;
@@ -1189,6 +1190,7 @@ static lbool matches_filters(POSITION pos, char *cline, size_t line_len, int *ch
struct hilite hl;
hl.hl_startpos = linepos;
hl.hl_endpos = pos;
+ hl.hl_attr = 0;
add_hilite(&filter_anchor, &hl);
free(cline);
free(chpos);
@@ -2118,7 +2120,8 @@ public int search(int search_type, constant char *pattern, int n)
/*
* Figure out where to start the search.
*/
- pos = search_pos(search_type);
+ pos = ((search_type & SRCH_INCR) && search_incr_start != NULL_POSITION) ?
+ search_incr_start : search_pos(search_type);
opos = position(sindex_from_sline(jump_sline));
if (pos == NULL_POSITION)
{
@@ -2241,7 +2244,7 @@ public void prep_hilite(POSITION spos, POSITION epos, int maxlines)
*/
clr_hilite();
clr_filter();
- nprep_startpos = spos;
+ nprep_startpos = nprep_endpos = spos;
} else
{
/*
@@ -2282,7 +2285,7 @@ public void prep_hilite(POSITION spos, POSITION epos, int maxlines)
result = search_range(spos, epos, search_type, 0, maxlines, (POSITION*)NULL, &new_epos, (POSITION*)NULL);
if (result < 0)
return;
- if (prep_endpos == NULL_POSITION || new_epos > prep_endpos)
+ if (nprep_endpos == NULL_POSITION || new_epos > nprep_endpos)
nprep_endpos = new_epos;
/*
@@ -2300,6 +2303,7 @@ public void prep_hilite(POSITION spos, POSITION epos, int maxlines)
if (epos == NULL_POSITION)
break;
maxlines = 1;
+ nprep_endpos = epos;
continue;
}
}
diff --git a/contrib/less/ubin.uni b/contrib/less/ubin.uni
index e422427e1976..5d6f97c237ad 100644
--- a/contrib/less/ubin.uni
+++ b/contrib/less/ubin.uni
@@ -1,4 +1,4 @@
-/* Generated by "./mkutable -f2 Cc Cs Co Zl Zp -- unicode/UnicodeData.txt" on Oct 1 18:10:07 GMT 2024 */
+/* Generated by "./mkutable -f2 Cc Cs Co Zl Zp -- unicode/UnicodeData.txt" on Aug 19 1:16:32 GMT 2025 */
{ 0x0000, 0x0007 }, /* Cc */
{ 0x000b, 0x000b }, /* Cc */
{ 0x000e, 0x001f }, /* Cc */
diff --git a/contrib/less/version.c b/contrib/less/version.c
index 68a42a6272fa..a5925c335a8f 100644
--- a/contrib/less/version.c
+++ b/contrib/less/version.c
@@ -1049,6 +1049,18 @@ v677 4/27/25 Fix & filtering bug.
v678 5/1/25 Don't change stty tab setting.
v679 5/28/25 Fix lesskey parsing bug when env var is prefix of another;
fix unexpected exit when using -K.
+v680 6/25/25 Fix hang if a search using ^S modifier matches empty string.
+v681 8/2/25 Fix bug using -g with -J; fix bug when pasting input
+ with --incsearch; improve performance with long lines;
+ fix performance with & filtering; change search position when
+ using --incsearch; treat some composing chars as binary.
+v682 8/24/25 Add --cmd; fix lesskey bug using #stop; fix lesskey bug
+ using "invalid"; fix some emoji bugs.
+v683 9/4/25 Fix bug if cmd char received during file read.
+v684 9/18/25 Allow mixing of options and filenames on command line;
+ add LESS_TERMCAP_SUSPEND & LESS_TERMCAP_RESUME.
+v685 10/4/25 Make --incsearch return to same column as well as same line;
+ fix some problems reported by valgrind.
*/
-char version[] = "679";
+char version[] = "685";
diff --git a/contrib/less/wide.uni b/contrib/less/wide.uni
index 6b4688c3b1f1..7ac89653987b 100644
--- a/contrib/less/wide.uni
+++ b/contrib/less/wide.uni
@@ -1,4 +1,4 @@
-/* Generated by "./mkutable -f1 W F -- unicode/EastAsianWidth.txt" on Sep 23 19:46:51 GMT 2024 */
+/* Generated by "./mkutable -f1 W F -- unicode/EastAsianWidth.txt" on Aug 10 20:15:03 GMT 2025 */
{ 0x1100, 0x115f }, /* W */
{ 0x231a, 0x231b }, /* W */
{ 0x2329, 0x232a }, /* W */
@@ -93,7 +93,8 @@
{ 0x1f3cf, 0x1f3d3 }, /* W */
{ 0x1f3e0, 0x1f3f0 }, /* W */
{ 0x1f3f4, 0x1f3f4 }, /* W */
- { 0x1f3f8, 0x1f43e }, /* W */
+ { 0x1f3f8, 0x1f3fa }, /* W */
+ { 0x1f400, 0x1f43e }, /* W */
{ 0x1f440, 0x1f440 }, /* W */
{ 0x1f442, 0x1f4fc }, /* W */
{ 0x1f4ff, 0x1f53d }, /* W */
@@ -114,7 +115,8 @@
{ 0x1f7f0, 0x1f7f0 }, /* W */
{ 0x1f90c, 0x1f93a }, /* W */
{ 0x1f93c, 0x1f945 }, /* W */
- { 0x1f947, 0x1f9ff }, /* W */
+ { 0x1f947, 0x1f9af }, /* W */
+ { 0x1f9b4, 0x1f9ff }, /* W */
{ 0x1fa70, 0x1fa7c }, /* W */
{ 0x1fa80, 0x1fa89 }, /* W */
{ 0x1fa8f, 0x1fac6 }, /* W */
diff --git a/contrib/less/xbuf.c b/contrib/less/xbuf.c
index 443e21da907b..8c940c41c8a9 100644
--- a/contrib/less/xbuf.c
+++ b/contrib/less/xbuf.c
@@ -86,7 +86,7 @@ public int xbuf_pop(struct xbuffer *buf)
/*
* Set an xbuf to the contents of another xbuf.
*/
-public void xbuf_set(struct xbuffer *dst, struct xbuffer *src)
+public void xbuf_set(struct xbuffer *dst, constant struct xbuffer *src)
{
xbuf_reset(dst);
xbuf_add_data(dst, src->data, src->end);