git: 054ae5e7b465 - stable/14 - MFV: less v685.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 13 Nov 2025 04:50:20 UTC
The branch stable/14 has been updated by delphij:
URL: https://cgit.FreeBSD.org/src/commit/?id=054ae5e7b465a32079a5ec8a9b943150b8da3212
commit 054ae5e7b465a32079a5ec8a9b943150b8da3212
Author: Xin LI <delphij@FreeBSD.org>
AuthorDate: 2025-11-10 08:55:06 +0000
Commit: Xin LI <delphij@FreeBSD.org>
CommitDate: 2025-11-13 04:49:52 +0000
MFV: less v685.
(cherry picked from commit d5cb458b4b58b0f0b3c058a32439f232fd5455ca)
---
contrib/less/NEWS | 39 ++++++++++++++++
contrib/less/ch.c | 4 --
contrib/less/charset.c | 48 +++++++++++++++++---
contrib/less/command.c | 40 +++++++++++++++++
contrib/less/compose.uni | 4 +-
contrib/less/decode.c | 11 +++--
contrib/less/edit.c | 10 +++--
contrib/less/fmt.uni | 6 +--
contrib/less/forwback.c | 2 +-
contrib/less/funcs.h | 12 ++++-
contrib/less/help.c | 2 +-
contrib/less/input.c | 72 +++++++++++++++++-------------
contrib/less/less.h | 5 ++-
contrib/less/less.nro | 110 ++++++++++++++++++++++++++++++++++++----------
contrib/less/lessecho.nro | 6 +--
contrib/less/lesskey.nro | 18 +++++---
contrib/less/lglob.h | 2 +-
contrib/less/line.c | 106 +++++++++++++++++++++++++++++++++++++++-----
contrib/less/lsystem.c | 2 +-
contrib/less/main.c | 41 ++++++++++++-----
contrib/less/mkutable | 21 ++++++++-
contrib/less/omit.uni | 7 +++
contrib/less/optfunc.c | 18 ++++++++
contrib/less/opttbl.c | 6 +++
contrib/less/os.c | 51 ++++++++++++++++++---
contrib/less/pattern.c | 7 ++-
contrib/less/screen.c | 30 +++++++++++++
contrib/less/search.c | 12 +++--
contrib/less/ubin.uni | 2 +-
contrib/less/version.c | 14 +++++-
contrib/less/wide.uni | 8 ++--
contrib/less/xbuf.c | 2 +-
usr.bin/less/defines.h | 18 ++++++--
33 files changed, 596 insertions(+), 140 deletions(-)
diff --git a/contrib/less/NEWS b/contrib/less/NEWS
index cdc8196a5f16..442fe21e406a 100644
--- a/contrib/less/NEWS
+++ b/contrib/less/NEWS
@@ -9,6 +9,45 @@
Report bugs, suggestions or comments at
https://github.com/gwsw/less/issues.
+======================================================================
+
+ 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
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},
@@ -856,6 +867,17 @@ static lbool is_in_table(LWCHAR ch, struct wchar_range_table *table)
return FALSE;
}
+/*
+ * 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.
*** 938 LINES SKIPPED ***