MFV: less v678.

MFC after:	2 weeks
This commit is contained in:
Xin LI committed 2025-05-19 20:44:02 -07:00
commit 252d6dde57
61 files changed
+1906 -1002

No files matched your search

+1 -1
View File
@@ -2,7 +2,7 @@
------------
Less
Copyright (C) 1984-2024 Mark Nudelman
Copyright (C) 1984-2025 Mark Nudelman
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
+73
View File
@@ -9,6 +9,79 @@
Report bugs, suggestions or comments at
https://github.com/gwsw/less/issues.
======================================================================
Major changes between "less" versions 668 and 678
* Treat -r in LESS environment variable as -R.
* Add ESC-j and ESC-k commands (github #560).
* Add --no-paste option (github #523).
* Add --no-edit-warn option (github #513).
* Add --form-feed option (github #496).
* Add ESC-b command (github #615).
* Make TAB complete option name in -- command (github #531).
* Update the file size on an attempt to go past end of file.
* Make -R able to pass through any OSC escape sequences,
not just OSC 8 (github #504).
* Setting LESS_IS_MORE=0 now disables "more" compatibility even
if invoked via a file link named "more" (github #500).
* Pass through escape sequences in prompts even if -R is not set.
* Add LESS_SHELL_LINES to support shell prompts which use more than
one line (github #514).
* Add LESSANSIOSCALLOW to define OSC types which may be passed through.
* Add LESSANSIOSCCHARS to define non-standard OSC intro chars.
* Add LESS_SIGUSR1 to define user signal handler (github #582).
* Add mouse and mouse6 commands to lesskey (github #569).
* Improve behavior of ^O^N and ^O^P commands.
* Leave stty tabs setting unchanged (github #620).
* Fix unexpected behavior when entering a partial command followed by
a valid command (github #543).
* Fix bug when coloring prompt string with SGR sequences (github #516).
* Fix bug when searching for text near an invalid UTF-8 sequence (github #542).
* Fix display bug when file contains ESC followed by NUL (github #550).
* Fix bug when using +:n +:p +:x or +:d on the command line (github #552).
* Fix bug with --no-number-headers when header is not at start of file
(github #566).
* Fix bug where lesstest fails if window is resized (github #570).
* Fix bug using "configure --with-secure=no" (github #584).
* Fix bug using multibyte command chars (github #595).
* Fix auto_wrap setting on Windows (github #497).
* Fix two bugs using ^S search modifier (github #605).
* Fix bug searching for UTF-8 strings with the PCRE2 library (github #610).
* Fix bug highlighting OSC 8 links when opening a new file.
* Fix bug when & filtering is active (github #618).
======================================================================
Major changes between "less" versions 661 and 668
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
+46 -9
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -149,10 +149,7 @@ static int ch_get(void)
struct buf *bp;
struct bufnode *bn;
ssize_t n;
lbool read_again;
int h;
POSITION pos;
POSITION len;
if (thisfile == NULL)
return (EOI);
@@ -224,12 +221,28 @@ static int ch_get(void)
for (;;)
{
pos = ch_position(ch_block, bp->datasize);
lbool read_again;
POSITION len;
POSITION pos = ch_position(ch_block, bp->datasize);
lbool read_pipe_at_eof = FALSE;
if ((len = ch_length()) != NULL_POSITION && pos >= len)
{
/*
* At end of file.
* Apparently at end of file.
* Double-check the file size in case it has changed.
*/
return (EOI);
ch_resize();
if ((len = ch_length()) != NULL_POSITION && pos >= len)
{
if (ch_flags & (CH_CANSEEK|CH_HELPFILE))
return (EOI);
/* ch_length doesn't work for pipes, so just try to
* read from the pipe to see if more data has appeared.
* This can happen only in limited situations, such as
* a fifo that the writer has closed and reopened. */
read_pipe_at_eof = TRUE;
}
}
if (pos != ch_fpos)
{
@@ -271,7 +284,8 @@ static int ch_get(void)
read_again = FALSE;
if (n == READ_INTR)
{
ch_fsize = pos;
if (ch_flags & CH_CANSEEK)
ch_fsize = pos;
return (EOI);
}
if (n == READ_AGAIN)
@@ -304,6 +318,8 @@ static int ch_get(void)
ch_fpos += n;
bp->datasize += (size_t) n;
if (read_pipe_at_eof)
ch_set_eof(); /* update length of pipe */
if (n == 0)
{
@@ -331,6 +347,9 @@ static int ch_get(void)
}
if (sigs)
return (EOI);
if (read_pipe_at_eof)
/* No new data; we are still at EOF on the pipe. */
return (EOI);
}
found:
@@ -400,6 +419,8 @@ public void end_logfile(void)
logfile = -1;
free(namelogfile);
namelogfile = NULL;
putstr("\n");
flush();
}
/*
@@ -412,6 +433,7 @@ public void sync_logfile(void)
struct buf *bp;
struct bufnode *bn;
lbool warned = FALSE;
int h;
BLOCKNUM block;
BLOCKNUM nblocks;
@@ -421,7 +443,8 @@ public void sync_logfile(void)
for (block = 0; block < nblocks; block++)
{
lbool wrote = FALSE;
FOR_BUFS(bn)
h = BUFHASH(block);
FOR_BUFS_IN_CHAIN(h, bn)
{
bp = bufnode_buf(bn);
if (bp->block == block)
@@ -599,6 +622,20 @@ public POSITION ch_length(void)
return (ch_fsize);
}
/*
* Update the file size, in case it has changed.
*/
public void ch_resize(void)
{
POSITION fsize;
if (!(ch_flags & CH_CANSEEK))
return;
fsize = filesize(ch_file);
if (fsize != NULL_POSITION)
ch_fsize = fsize;
}
/*
* Return the current position in the file.
*/
+25 -11
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -756,24 +756,38 @@ public LWCHAR step_charc(constant char **pp, signed int dir, constant char *limi
ch = (LWCHAR) (unsigned char) ((p > limit) ? *--p : 0);
} else if (dir > 0)
{
len = utf_len(*p);
if (p + len > limit)
{
if (p >= limit)
ch = 0;
p = (char *) limit;
} else
else
{
ch = get_wchar(p);
p += len;
len = utf_len(*p);
if (p + len > limit || !is_utf8_well_formed(p, len))
{
ch = (LWCHAR) (unsigned char) *p++;
} else
{
ch = get_wchar(p);
p += len;
}
}
} else
{
while (p > limit && IS_UTF8_TRAIL(p[-1]))
p--;
if (p > limit)
ch = get_wchar(--p);
else
if (p <= limit)
ch = 0;
else
{
len = utf_len(*--p);
if (p + len != *pp || !is_utf8_well_formed(p, len))
{
p = *pp - 1;
ch = (LWCHAR) (unsigned char) *p;
} else
{
ch = get_wchar(p);
}
}
}
*pp = p;
return ch;
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
+8 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -31,6 +31,7 @@
#define A_HELP 19
#define A_NEXT_FILE 20
#define A_PERCENT 21
#define A_BF_SCREEN 22
#define A_PREV_FILE 23
#define A_QUIT 24
#define A_REPAINT 25
@@ -68,6 +69,8 @@
#define A_GOEND_BUF 57
#define A_LLSHIFT 58
#define A_RRSHIFT 59
#define A_F_NEWLINE 60
#define A_B_NEWLINE 61
#define A_CLRMARK 62
#define A_SETMARKBOT 63
#define A_X11MOUSE_IN 64
@@ -81,6 +84,8 @@
#define A_OSC8_B_SEARCH 72
#define A_OSC8_OPEN 73
#define A_OSC8_JUMP 74
#define A_START_PASTE 75 /* must not overlap EC_* */
#define A_END_PASTE 76 /* must not overlap EC_* */
/* These values must not conflict with any A_* or EC_* value. */
#define A_INVALID 100
@@ -117,6 +122,8 @@
#define EC_ABORT 20
#define EC_X11MOUSE 21
#define EC_X116MOUSE 22
#define EC_START_PASTE A_START_PASTE
#define EC_END_PASTE A_END_PASTE
#define EC_UINVALID 102
+138 -51
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -24,6 +24,8 @@ extern int sc_width;
extern int utf_mode;
extern int no_hist_dups;
extern int marks_modified;
extern int no_paste;
public lbool pasting = FALSE;
static char cmdbuf[CMDBUF_SIZE]; /* Buffer for holding a multi-char command */
static int cmd_col; /* Current column of the cursor */
@@ -34,7 +36,6 @@ static lbool literal; /* Next input char should not be interpreted */
static size_t updown_match; /* Prefix length in up/down movement */
static lbool have_updown_match = FALSE;
#if TAB_COMPLETE_FILENAME
static int cmd_complete(int action);
/*
* These variables are statics used by cmd_complete.
@@ -45,7 +46,6 @@ static char *tk_original;
static constant char *tk_ipoint;
static constant char *tk_trial = NULL;
static struct textlist tk_tlist;
#endif
static int cmd_left();
static int cmd_right();
@@ -182,6 +182,16 @@ public int len_cmdbuf(void)
return (len);
}
/*
* Is the command buffer empty?
* It is considered nonempty if there is any text in it,
* or if a multibyte command is being entered but not yet complete.
*/
public lbool cmdbuf_empty(void)
{
return cp == cmdbuf && cmd_mbc_buf_len == 0;
}
/*
* Common part of cmd_step_right() and cmd_step_left().
* {{ Returning pwidth and bswidth separately is a historical artifact
@@ -304,6 +314,16 @@ public void cmd_repaint(constant char *old_cp)
cmd_left();
}
/*
* Repaint the entire line, without moving the cursor.
*/
static void cmd_repaint_curr(void)
{
char *save_cp = cp;
cmd_home();
cmd_repaint(save_cp);
}
/*
* Shift the cmdbuf display left a half-screen.
*/
@@ -804,17 +824,13 @@ public void cmd_accept(void)
* CC_OK Line edit function done.
* CC_QUIT The char requests the current command to be aborted.
*/
static int cmd_edit(char c)
static int cmd_edit(char c, lbool stay_in_completion)
{
int action;
int flags;
#if TAB_COMPLETE_FILENAME
#define not_in_completion() in_completion = 0
#else
#define not_in_completion(void)
#endif
#define not_in_completion() do { if (!stay_in_completion) in_completion = FALSE; } while(0)
/*
* See if the char is indeed a line-editing command.
*/
@@ -826,21 +842,35 @@ static int cmd_edit(char c)
*/
flags |= ECF_NOHISTORY;
#endif
/*
* Don't accept completion cmds in contexts
* such as search pattern, digits, etc.
*/
if ((curr_mlist == NULL && (curr_cmdflags & CF_OPTION))
#if TAB_COMPLETE_FILENAME
if (curr_mlist == ml_search || curr_mlist == NULL)
/*
* Don't accept file-completion cmds in contexts
* such as search pattern, digits, long option name, etc.
*/
flags |= ECF_NOCOMPLETE;
|| curr_mlist == ml_examine || curr_mlist == ml_shell
#endif
)
; /* allow completion */
else
flags |= ECF_NOCOMPLETE;
action = editchar(c, flags);
if (is_ignoring_input(action))
return (CC_OK);
switch (action)
{
case A_NOACTION:
return (CC_OK);
case EC_START_PASTE:
if (no_paste)
pasting = TRUE;
return (CC_OK);
case EC_END_PASTE:
stop_ignoring_input();
return (CC_OK);
case EC_RIGHT:
not_in_completion();
return (cmd_right());
@@ -903,19 +933,16 @@ static int cmd_edit(char c)
not_in_completion();
return (cmd_updown(action));
#endif
#if TAB_COMPLETE_FILENAME
case EC_F_COMPLETE:
case EC_B_COMPLETE:
case EC_EXPAND:
return (cmd_complete(action));
#endif
default:
not_in_completion();
return (CC_PASS);
}
}
#if TAB_COMPLETE_FILENAME
/*
* Insert a string into the command buffer, at the current position.
*/
@@ -936,6 +963,18 @@ static int cmd_istr(constant char *str)
return (CC_OK);
}
/*
* Set tk_original to word.
*/
static void set_tk_original(constant char *word)
{
if (tk_original != NULL)
free(tk_original);
tk_original = (char *) ecalloc(ptr_diff(cp,word)+1, sizeof(char));
strncpy(tk_original, word, ptr_diff(cp,word));
}
#if TAB_COMPLETE_FILENAME
/*
* Find the beginning and end of the "current" word.
* This is the word which the cursor (cp) is inside or at the end of.
@@ -1024,23 +1063,15 @@ static char * delimit_word(void)
}
/*
* Set things up to enter completion mode.
* Set things up to enter file completion mode.
* Expand the word under the cursor into a list of filenames
* which start with that word, and set tk_text to that list.
*/
static void init_compl(void)
static void init_file_compl(void)
{
char *word;
char c;
/*
* Get rid of any previous tk_text.
*/
if (tk_text != NULL)
{
free(tk_text);
tk_text = NULL;
}
/*
* Find the original (uncompleted) word in the command buffer.
*/
@@ -1052,13 +1083,7 @@ static void init_compl(void)
* where the original (uncompleted) word now sits.
*/
tk_ipoint = word;
/*
* Save the original (uncompleted) word
*/
if (tk_original != NULL)
free(tk_original);
tk_original = (char *) ecalloc(ptr_diff(cp,word)+1, sizeof(char));
strncpy(tk_original, word, ptr_diff(cp,word));
set_tk_original(word);
/*
* Get the expanded filename.
* This may result in a single filename, or
@@ -1086,6 +1111,17 @@ static void init_compl(void)
}
*cp = c;
}
#endif /* TAB_COMPLETE_FILENAME */
/*
* Set things up to enter option completion mode.
*/
static void init_opt_compl(void)
{
tk_ipoint = cmdbuf;
set_tk_original(cmdbuf);
tk_text = findopts_name(cmdbuf);
}
/*
* Return the next word in the current completion list.
@@ -1120,7 +1156,19 @@ static int cmd_complete(int action)
* use the first word in the expansion
* (or the entire expansion if we're doing EC_EXPAND).
*/
init_compl();
if (tk_text != NULL)
{
free(tk_text);
tk_text = NULL;
}
if (curr_cmdflags & CF_OPTION)
init_opt_compl();
else
#if TAB_COMPLETE_FILENAME
init_file_compl();
#else
quit(QUIT_ERROR); /* cannot happen */
#endif /* TAB_COMPLETE_FILENAME */
if (tk_text == NULL)
{
bell();
@@ -1195,25 +1243,20 @@ fail:
return (CC_OK);
}
#endif /* TAB_COMPLETE_FILENAME */
/*
* Process a single character of a multi-character command, such as
* a number, or the pattern of a search command.
* Build a UTF-8 char in cmd_mbc_buf.
* Returns:
* CC_OK The char was accepted.
* CC_QUIT The char requests the command to be aborted.
* CC_ERROR The char could not be accepted due to an error.
* CC_OK Char has been stored but we don't have a complete UTF-8 sequence yet.
* CC_ERROR This is an invalid UTF-8 sequence.
* CC_PASS There is a complete UTF-8 sequence in cmd_mbc_buf.
* The length of the complete sequence is returned in *plen.
*/
public int cmd_char(char c)
static int cmd_uchar(char c, size_t *plen)
{
int action;
size_t len;
if (!utf_mode)
{
cmd_mbc_buf[0] = c;
len = 1;
*plen = 1;
} else
{
/* Perform strict validation in all possible cases. */
@@ -1262,9 +1305,26 @@ public int cmd_char(char c)
goto retry;
}
len = (size_t) cmd_mbc_buf_len; /*{{type-issue}}*/
*plen = (size_t) cmd_mbc_buf_len; /*{{type-issue}}*/
cmd_mbc_buf_len = 0;
}
return (CC_PASS);
}
/*
* Process a single character of a multi-character command, such as
* a number, or the pattern of a search command.
* Returns:
* CC_OK The char was accepted.
* CC_QUIT The char requests the command to be aborted.
* CC_ERROR The char could not be accepted due to an error.
*/
static int cmd_char2(char c, lbool stay_in_completion)
{
size_t len;
int action = cmd_uchar(c, &len);
if (action != CC_PASS)
return (action);
if (literal)
{
@@ -1280,7 +1340,7 @@ public int cmd_char(char c)
*/
if (in_mca() && len == 1)
{
action = cmd_edit(c);
action = cmd_edit(c, stay_in_completion);
switch (action)
{
case CC_OK:
@@ -1297,6 +1357,30 @@ public int cmd_char(char c)
return (cmd_ichar(cmd_mbc_buf, len));
}
public int cmd_char(char c)
{
return cmd_char2(c, FALSE);
}
/*
* Copy an ASCII string to the command buffer.
*/
public int cmd_setstring(constant char *s, lbool uc)
{
while (*s != '\0')
{
int action;
char c = *s++;
if (uc && ASCII_IS_LOWER(c))
c = ASCII_TO_UPPER(c);
action = cmd_char2(c, TRUE);
if (action != CC_OK)
return (action);
}
cmd_repaint_curr();
return (CC_OK);
}
/*
* Return the number currently in the command buffer.
*/
@@ -1464,6 +1548,7 @@ static void read_cmdhist2(void (*action)(void*,struct mlist*,constant char*), vo
#else
ml = NULL;
skip = NULL;
(void) skip_shell;
#endif
} else if (strcmp(line, HISTFILE_MARK_SECTION) == 0)
{
@@ -1674,6 +1759,8 @@ public void save_cmdhist(void)
skip_search = mlist_size(&mlist_search) - histsize;
#if SHELL_ESCAPE || PIPEC
skip_shell = mlist_size(&mlist_shell) - histsize;
#else
skip_shell = 0; /* not actually used */
#endif
fprintf(fout, "%s\n", HISTFILE_FIRST_LINE);
ctx.fout = fout;
+150 -56
View File
@@ -1,6 +1,5 @@
/* $FreeBSD$ */
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -30,7 +29,7 @@ extern int sc_height;
extern char *kent;
extern int swindow;
extern int jump_sline;
extern int quitting;
extern lbool quitting;
extern int wscroll;
extern int top_scroll;
extern int ignore_eoi;
@@ -39,6 +38,7 @@ extern int bs_mode;
extern int proc_backspace;
extern int show_attn;
extern int less_is_more;
extern int chopline;
extern POSITION highest_hilite;
extern char *every_first_cmd;
extern char version[];
@@ -49,6 +49,10 @@ extern void *ml_examine;
extern int wheel_lines;
extern int def_search_type;
extern lbool search_wrapped;
extern int no_paste;
extern lbool pasting;
extern int no_edit_warn;
extern POSITION soft_eof;
#if SHELL_ESCAPE || PIPEC
extern void *ml_shell;
#endif
@@ -76,7 +80,7 @@ static int last_search_type; /* Type of last executed search */
static LINENUM number; /* The number typed by the user */
static long fraction; /* The fractional part of the number */
static struct loption *curropt;
static int opt_lower;
static lbool opt_lower;
static int optflag;
static lbool optgetname;
static POSITION bottompos;
@@ -85,6 +89,10 @@ static int save_bs_mode;
static int save_proc_backspace;
static int screen_trashed_value = 0;
static lbool literal_char = FALSE;
static lbool ignoring_input = FALSE;
#if HAVE_TIME
static time_type ignoring_input_time;
#endif
#if PIPEC
static char pipec;
#endif
@@ -104,7 +112,7 @@ static void multi_search(constant char *pattern, int n, int silent);
* This looks nicer if the command takes a long time before
* updating the screen.
*/
static void cmd_exec(void)
public void cmd_exec(void)
{
clear_attn();
clear_bot();
@@ -230,7 +238,7 @@ static void mca_opt_toggle(void)
break;
}
forw_prompt = 0;
set_mlist(NULL, 0);
set_mlist(NULL, CF_OPTION);
}
/*
@@ -239,7 +247,6 @@ static void mca_opt_toggle(void)
static void exec_mca(void)
{
constant char *cbuf;
char *p;
cmd_exec();
cbuf = get_cmdbuf();
@@ -256,6 +263,7 @@ static void exec_mca(void)
case A_FILTER:
search_type ^= SRCH_NO_MATCH;
set_filter_pattern(cbuf, search_type);
soft_eof = NULL_POSITION;
break;
#endif
case A_FIRSTCMD:
@@ -282,7 +290,8 @@ static void exec_mca(void)
match_brac(cbuf[1], cbuf[0], 0, (int) number);
break;
#if EXAMINE
case A_EXAMINE:
case A_EXAMINE: {
char *p;
if (!secure_allow(SF_EXAMINE))
break;
p = save(cbuf);
@@ -292,7 +301,7 @@ static void exec_mca(void)
/* If tag structure is loaded then clean it up. */
cleantags();
#endif
break;
break; }
#endif
#if SHELL_ESCAPE
case A_SHELL: {
@@ -415,16 +424,18 @@ static int mca_opt_nonfirst_char(char c)
constant char *p;
constant char *oname;
lbool ambig;
struct loption *was_curropt;
if (curropt != NULL)
{
/*
* Already have a match for the name.
* Don't accept anything but erase/kill.
*/
/* Already have a match for the name. */
if (is_erase_char(c))
return (MCA_DONE);
return (MCA_MORE);
/* {{ Checking for TAB here is ugly.
* Also doesn't extend well -- can't do BACKTAB this way
* because it's a multichar sequence. }} */
if (c != '\t')
return (MCA_MORE);
}
/*
* Add char to cmd buffer and try to match
@@ -433,26 +444,23 @@ static int mca_opt_nonfirst_char(char c)
if (cmd_char(c) == CC_QUIT)
return (MCA_DONE);
p = get_cmdbuf();
if (p == NULL)
if (p == NULL || p[0] == '\0')
return (MCA_MORE);
opt_lower = ASCII_IS_LOWER(p[0]);
was_curropt = curropt;
curropt = findopt_name(&p, &oname, &ambig);
if (curropt != NULL)
{
/*
* Got a match.
* Remember the option and
* display the full option name.
*/
cmd_reset();
mca_opt_toggle();
for (p = oname; *p != '\0'; p++)
if (was_curropt == NULL)
{
c = *p;
if (!opt_lower && ASCII_IS_LOWER(c))
c = ASCII_TO_UPPER(c);
if (cmd_char(c) != CC_OK)
return (MCA_DONE);
/*
* Got a match.
* Remember the option and
* display the full option name.
*/
cmd_reset();
mca_opt_toggle();
cmd_setstring(oname, !opt_lower);
}
} else if (!ambig)
{
@@ -473,7 +481,7 @@ static int mca_opt_char(char c)
* or one char of a long option name,
* or one char of the option parameter.
*/
if (curropt == NULL && len_cmdbuf() == 0)
if (curropt == NULL && cmdbuf_empty())
{
int ret = mca_opt_first_char(c);
if (ret != NO_MCA)
@@ -524,7 +532,7 @@ static int mca_opt_char(char c)
/*
* Display a prompt appropriate for the option parameter.
*/
start_mca(A_OPT_TOGGLE, opt_prompt(curropt), NULL, 0);
start_mca(A_OPT_TOGGLE, opt_prompt(curropt), NULL, CF_OPTION);
return (MCA_MORE);
}
@@ -553,7 +561,7 @@ static int mca_search_char(char c)
* * Toggle the PAST_EOF flag
* @ Toggle the FIRST_FILE flag
*/
if (len_cmdbuf() > 0 || literal_char)
if (!cmdbuf_empty() || literal_char)
{
literal_char = FALSE;
return (NO_MCA);
@@ -694,9 +702,13 @@ static int mca_char(char c)
*/
if (is_newline_char(c))
{
/*
* Execute the command.
*/
if (pasting && no_paste)
{
/* Ignore pasted input after (and including) the first newline */
start_ignoring_input();
return (MCA_MORE);
}
/* Execute the command. */
exec_mca();
return (MCA_DONE);
}
@@ -865,7 +877,7 @@ static void prompt(void)
* If we've hit EOF on the last file and the -E flag is set, quit.
*/
if (get_quit_at_eof() == OPT_ONPLUS &&
eof_displayed() && !(ch_getflags() & CH_HELPFILE) &&
eof_displayed(FALSE) && !(ch_getflags() & CH_HELPFILE) &&
next_ifile(curr_ifile) == NULL_IFILE)
quit(QUIT_OK);
@@ -947,7 +959,7 @@ static void prompt(void)
p = a;
#endif
load_line(p);
put_line();
put_line(FALSE);
}
clear_eol();
}
@@ -1021,14 +1033,14 @@ public void getcc_clear(void)
static char getccu(void)
{
int c = 0;
while (c == 0 && !ABORT_SIGS())
while (c == 0 && sigs == 0)
{
if (ungot == NULL)
{
/* Normal case: no ungotten chars.
* Get char from the user. */
c = getchr();
if (c < 0) return ('\0');
if (c < 0) c = '\0';
} else
{
/* Ungotten chars available:
@@ -1276,7 +1288,7 @@ static int forw_loop(int until_hilite)
break;
}
make_display();
forward(1, 0, 0);
forward(1, FALSE, FALSE, FALSE);
}
ignore_eoi = 0;
ch_set_eof();
@@ -1291,6 +1303,46 @@ static int forw_loop(int until_hilite)
return (A_NOACTION);
}
/*
* Ignore subsequent (pasted) input chars.
*/
public void start_ignoring_input()
{
ignoring_input = TRUE;
#if HAVE_TIME
ignoring_input_time = get_time();
#endif
}
/*
* Stop ignoring input chars.
*/
public void stop_ignoring_input()
{
ignoring_input = FALSE;
pasting = FALSE;
}
/*
* Are we ignoring input chars?
*/
public lbool is_ignoring_input(int action)
{
if (!ignoring_input)
return FALSE;
if (action == A_END_PASTE)
stop_ignoring_input();
#if HAVE_TIME
if (get_time() >= ignoring_input_time + MAX_PASTE_IGNORE_SEC)
stop_ignoring_input();
#endif
/*
* Don't ignore prefix chars so we can parse a full command
* (which might be A_END_PASTE).
*/
return (action != A_PREFIX);
}
/*
* Main command processor.
* Accept and execute commands until a quit command.
@@ -1308,7 +1360,9 @@ public void commands(void)
PARG parg;
IFILE old_ifile;
IFILE new_ifile;
#if TAGS
constant char *tagfile;
#endif
search_type = SRCH_FORW;
wscroll = (sc_height + 1) / 2;
@@ -1398,11 +1452,14 @@ public void commands(void)
* If the user backspaces past the start
* of the line, abort the command.
*/
if (cmd_char(c) == CC_QUIT || len_cmdbuf() == 0)
if (cmd_char(c) == CC_QUIT || cmdbuf_empty())
continue;
cbuf = get_cmdbuf();
if (cbuf == NULL)
continue;
{
c = getcc();
goto again;
}
action = fcmd_decode(cbuf, &extra);
} else
{
@@ -1432,8 +1489,16 @@ public void commands(void)
if (action != A_PREFIX)
cmd_reset();
if (is_ignoring_input(action))
continue;
switch (action)
{
case A_START_PASTE:
if (no_paste)
start_ignoring_input();
break;
case A_DIGIT:
/*
* First digit of a number.
@@ -1457,7 +1522,7 @@ public void commands(void)
cmd_exec();
if (show_attn)
set_attnpos(bottompos);
forward((int) number, 0, 1);
forward((int) number, FALSE, TRUE, FALSE);
break;
case A_B_WINDOW:
@@ -1474,10 +1539,12 @@ public void commands(void)
if (number <= 0)
number = get_swindow();
cmd_exec();
backward((int) number, 0, 1);
backward((int) number, FALSE, TRUE, FALSE);
break;
case A_F_LINE:
case A_F_NEWLINE:
/*
* Forward N (default 1) line.
*/
@@ -1486,17 +1553,18 @@ public void commands(void)
cmd_exec();
if (show_attn == OPT_ONPLUS && number > 1)
set_attnpos(bottompos);
forward((int) number, 0, 0);
forward((int) number, FALSE, FALSE, action == A_F_NEWLINE && !chopline);
break;
case A_B_LINE:
case A_B_NEWLINE:
/*
* Backward N (default 1) line.
*/
if (number <= 0)
number = 1;
cmd_exec();
backward((int) number, 0, 0);
backward((int) number, FALSE, FALSE, action == A_B_NEWLINE && !chopline);
break;
case A_F_MOUSE:
@@ -1504,7 +1572,7 @@ public void commands(void)
* Forward wheel_lines lines.
*/
cmd_exec();
forward(wheel_lines, 0, 0);
forward(wheel_lines, FALSE, FALSE, FALSE);
break;
case A_B_MOUSE:
@@ -1512,7 +1580,7 @@ public void commands(void)
* Backward wheel_lines lines.
*/
cmd_exec();
backward(wheel_lines, 0, 0);
backward(wheel_lines, FALSE, FALSE, FALSE);
break;
case A_FF_LINE:
@@ -1524,7 +1592,7 @@ public void commands(void)
cmd_exec();
if (show_attn == OPT_ONPLUS && number > 1)
set_attnpos(bottompos);
forward((int) number, 1, 0);
forward((int) number, TRUE, FALSE, FALSE);
break;
case A_BF_LINE:
@@ -1534,7 +1602,7 @@ public void commands(void)
if (number <= 0)
number = 1;
cmd_exec();
backward((int) number, 1, 0);
backward((int) number, TRUE, FALSE, FALSE);
break;
case A_FF_SCREEN:
@@ -1546,13 +1614,25 @@ public void commands(void)
cmd_exec();
if (show_attn == OPT_ONPLUS)
set_attnpos(bottompos);
forward((int) number, 1, 0);
forward((int) number, TRUE, FALSE, FALSE);
break;
case A_BF_SCREEN:
/*
* Force backward one screen.
*/
if (number <= 0)
number = get_swindow();
cmd_exec();
backward((int) number, TRUE, FALSE, FALSE);
break;
case A_F_FOREVER:
/*
* Forward forever, ignoring EOF.
*/
if (get_altfilename(curr_ifile) != NULL)
error("Warning: command may not work correctly when file is viewed via LESSOPEN", NULL_PARG);
if (show_attn)
set_attnpos(bottompos);
newaction = forw_loop(0);
@@ -1572,7 +1652,7 @@ public void commands(void)
cmd_exec();
if (show_attn == OPT_ONPLUS)
set_attnpos(bottompos);
forward(wscroll, 0, 0);
forward(wscroll, FALSE, FALSE, FALSE);
break;
case A_B_SCROLL:
@@ -1583,7 +1663,7 @@ public void commands(void)
if (number > 0)
wscroll = (int) number;
cmd_exec();
backward(wscroll, 0, 0);
backward(wscroll, FALSE, FALSE, FALSE);
break;
case A_FREPAINT:
@@ -1890,10 +1970,9 @@ public void commands(void)
error("Cannot edit standard input", NULL_PARG);
break;
}
if (get_altfilename(curr_ifile) != NULL)
if (!no_edit_warn && get_altfilename(curr_ifile) != NULL)
{
error("WARNING: This file was viewed via LESSOPEN",
NULL_PARG);
error("WARNING: This file was viewed via LESSOPEN", NULL_PARG);
}
start_mca(A_SHELL, "!", ml_shell, 0);
/*
@@ -1924,9 +2003,10 @@ public void commands(void)
#endif
if (number <= 0)
number = 1;
cmd_exec();
if (edit_next((int) number))
{
if (get_quit_at_eof() && eof_displayed() &&
if (get_quit_at_eof() && eof_displayed(FALSE) &&
!(ch_getflags() & CH_HELPFILE))
quit(QUIT_OK);
parg.p_string = (number > 1) ? "(N-th) " : "";
@@ -1947,6 +2027,7 @@ public void commands(void)
#endif
if (number <= 0)
number = 1;
cmd_exec();
if (edit_prev((int) number))
{
parg.p_string = (number > 1) ? "(N-th) " : "";
@@ -2010,6 +2091,7 @@ public void commands(void)
*/
if (number <= 0)
number = 1;
cmd_exec();
if (edit_index((int) number))
error("No such file", NULL_PARG);
break;
@@ -2022,6 +2104,7 @@ public void commands(void)
break;
old_ifile = curr_ifile;
new_ifile = getoff_ifile(curr_ifile);
cmd_exec();
if (new_ifile == NULL_IFILE)
{
bell();
@@ -2091,7 +2174,18 @@ public void commands(void)
* Set a mark.
*/
if (ch_getflags() & CH_HELPFILE)
{
if (ungot != NULL)
{
/*
* Probably from a lesskey file, in which case there
* is probably an ungotten letter from the "extra" string.
* Eat it so it is not interpreted as a command.
*/
(void) getcc();
}
break;
}
start_mca(A_SETMARK, "set mark: ", NULL, 0);
c = getcc();
if (is_erase_char(c) || is_newline_char(c))
+15 -4
View File
@@ -1,4 +1,4 @@
/* Generated by "./mkutable -f2 Mn Me -- unicode/UnicodeData.txt" on Sun Sep 17 17:56:27 PDT 2023 */
/* Generated by "./mkutable -f2 Mn Me -- unicode/UnicodeData.txt" on Oct 1 18:10:07 GMT 2024 */
{ 0x0300, 0x036f }, /* Mn */
{ 0x0483, 0x0487 }, /* Mn */
{ 0x0488, 0x0489 }, /* Me */
@@ -24,7 +24,7 @@
{ 0x0825, 0x0827 }, /* Mn */
{ 0x0829, 0x082d }, /* Mn */
{ 0x0859, 0x085b }, /* Mn */
{ 0x0898, 0x089f }, /* Mn */
{ 0x0897, 0x089f }, /* Mn */
{ 0x08ca, 0x08e1 }, /* Mn */
{ 0x08e3, 0x0902 }, /* Mn */
{ 0x093a, 0x093a }, /* Mn */
@@ -229,8 +229,9 @@
{ 0x10a3f, 0x10a3f }, /* Mn */
{ 0x10ae5, 0x10ae6 }, /* Mn */
{ 0x10d24, 0x10d27 }, /* Mn */
{ 0x10d69, 0x10d6d }, /* Mn */
{ 0x10eab, 0x10eac }, /* Mn */
{ 0x10efd, 0x10eff }, /* Mn */
{ 0x10efc, 0x10eff }, /* Mn */
{ 0x10f46, 0x10f50 }, /* Mn */
{ 0x10f82, 0x10f85 }, /* Mn */
{ 0x11001, 0x11001 }, /* Mn */
@@ -261,6 +262,11 @@
{ 0x11340, 0x11340 }, /* Mn */
{ 0x11366, 0x1136c }, /* Mn */
{ 0x11370, 0x11374 }, /* Mn */
{ 0x113bb, 0x113c0 }, /* Mn */
{ 0x113ce, 0x113ce }, /* Mn */
{ 0x113d0, 0x113d0 }, /* Mn */
{ 0x113d2, 0x113d2 }, /* Mn */
{ 0x113e1, 0x113e2 }, /* Mn */
{ 0x11438, 0x1143f }, /* Mn */
{ 0x11442, 0x11444 }, /* Mn */
{ 0x11446, 0x11446 }, /* Mn */
@@ -280,7 +286,8 @@
{ 0x116ad, 0x116ad }, /* Mn */
{ 0x116b0, 0x116b5 }, /* Mn */
{ 0x116b7, 0x116b7 }, /* Mn */
{ 0x1171d, 0x1171f }, /* Mn */
{ 0x1171d, 0x1171d }, /* Mn */
{ 0x1171f, 0x1171f }, /* Mn */
{ 0x11722, 0x11725 }, /* Mn */
{ 0x11727, 0x1172b }, /* Mn */
{ 0x1182f, 0x11837 }, /* Mn */
@@ -319,8 +326,11 @@
{ 0x11f36, 0x11f3a }, /* Mn */
{ 0x11f40, 0x11f40 }, /* Mn */
{ 0x11f42, 0x11f42 }, /* Mn */
{ 0x11f5a, 0x11f5a }, /* Mn */
{ 0x13440, 0x13440 }, /* Mn */
{ 0x13447, 0x13455 }, /* Mn */
{ 0x1611e, 0x16129 }, /* Mn */
{ 0x1612d, 0x1612f }, /* Mn */
{ 0x16af0, 0x16af4 }, /* Mn */
{ 0x16b30, 0x16b36 }, /* Mn */
{ 0x16f4f, 0x16f4f }, /* Mn */
@@ -350,6 +360,7 @@
{ 0x1e2ae, 0x1e2ae }, /* Mn */
{ 0x1e2ec, 0x1e2ef }, /* Mn */
{ 0x1e4ec, 0x1e4ef }, /* Mn */
{ 0x1e5ee, 0x1e5ef }, /* Mn */
{ 0x1e8d0, 0x1e8d6 }, /* Mn */
{ 0x1e944, 0x1e94a }, /* Mn */
{ 0xe0100, 0xe01ef }, /* Mn */
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
+182 -137
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -37,6 +37,8 @@ extern int erase_char, erase2_char, kill_char;
extern int mousecap;
extern int sc_height;
static constant lbool allow_drag = TRUE;
#if USERFILE
/* "content" is lesskey source, never binary. */
static void add_content_table(int (*call_lesskey)(constant char *, lbool), constant char *envname, lbool sysvar);
@@ -86,6 +88,9 @@ static unsigned char cmdtable[] =
'z',0, A_F_WINDOW,
'w',0, A_B_WINDOW,
ESC,' ',0, A_FF_SCREEN,
ESC,'b',0, A_BF_SCREEN,
ESC,'j',0, A_F_NEWLINE,
ESC,'k',0, A_B_NEWLINE,
'F',0, A_F_FOREVER,
ESC,'F',0, A_F_UNTIL_HILITE,
'R',0, A_FREPAINT,
@@ -178,6 +183,8 @@ static unsigned char cmdtable[] =
'!',0, A_SHELL,
'#',0, A_PSHELL,
'+',0, A_FIRSTCMD,
ESC,'[','2','0','0','~',0, A_START_PASTE,
ESC,'[','2','0','1','~',0, A_END_PASTE,
'H',0, A_HELP,
'h',0, A_HELP,
@@ -229,6 +236,8 @@ static unsigned char edittable[] =
CONTROL('G'),0, EC_ABORT, /* CTRL-G */
ESC,'[','M',0, EC_X11MOUSE, /* X11 mouse report */
ESC,'[','<',0, EC_X116MOUSE, /* X11 1006 mouse report */
ESC,'[','2','0','0','~',0, A_START_PASTE, /* open paste bracket */
ESC,'[','2','0','1','~',0, A_END_PASTE, /* close paste bracket */
};
static unsigned char dflt_vartable[] =
@@ -514,22 +523,42 @@ static int mouse_wheel_up(void)
/*
* Return action for the left mouse button trigger.
*/
static int mouse_button_left(int x, int y)
static int mouse_button_left(int x, int y, lbool down, lbool drag)
{
/*
* {{ It would be better to return an action and then do this
* in commands() but it's nontrivial to pass y to it. }}
*/
#if OSC8_LINK
if (osc8_click(y, x))
return (A_NOACTION);
#else
(void) x;
#endif /* OSC8_LINK */
if (y < sc_height-1)
static int last_drag_y = -1;
static int last_click_y = -1;
if (down && !drag)
{
setmark('#', y);
screen_trashed();
last_drag_y = last_click_y = y;
}
if (allow_drag && drag && last_drag_y >= 0)
{
/* Drag text up/down */
if (y > last_drag_y)
{
cmd_exec();
backward(y - last_drag_y, FALSE, FALSE, FALSE);
last_drag_y = y;
} else if (y < last_drag_y)
{
cmd_exec();
forward(last_drag_y - y, FALSE, FALSE, FALSE);
last_drag_y = y;
}
} else if (!down)
{
#if OSC8_LINK
if (osc8_click(y, x))
return (A_NOACTION);
#else
(void) x;
#endif /* OSC8_LINK */
if (y < sc_height-1 && y == last_click_y)
{
setmark('#', y);
screen_trashed();
}
}
return (A_NOACTION);
}
@@ -537,14 +566,14 @@ static int mouse_button_left(int x, int y)
/*
* Return action for the right mouse button trigger.
*/
static int mouse_button_right(int x, int y)
static int mouse_button_right(int x, int y, lbool down, lbool drag)
{
(void) x;
(void) x; (void) drag;
/*
* {{ unlike mouse_button_left, we could return an action,
* but keep it near mouse_button_left for readability. }}
*/
if (y < sc_height-1)
if (!down && y < sc_height-1)
{
gomark('#');
screen_trashed();
@@ -575,49 +604,61 @@ static int getcc_int(char *pterm)
}
}
static int x11mouse_button(int btn, int x, int y, lbool down, lbool drag)
{
switch (btn) {
case X11MOUSE_BUTTON1:
return mouse_button_left(x, y, down, drag);
/* is BUTTON2 the rightmost with 2-buttons mouse? */
case X11MOUSE_BUTTON2:
case X11MOUSE_BUTTON3:
return mouse_button_right(x, y, down, drag);
}
return (A_NOACTION);
}
/*
* Read suffix of mouse input and return the action to take.
* The prefix ("\e[M") has already been read.
*/
static int x11mouse_action(int skip)
static int x11mouse_action(lbool skip)
{
static int prev_b = X11MOUSE_BUTTON_REL;
int x, y;
int b = getcc() - X11MOUSE_OFFSET;
int x = getcc() - X11MOUSE_OFFSET-1;
int y = getcc() - X11MOUSE_OFFSET-1;
lbool drag = ((b & X11MOUSE_DRAG) != 0);
b &= ~X11MOUSE_DRAG;
x = getcc() - X11MOUSE_OFFSET-1;
y = getcc() - X11MOUSE_OFFSET-1;
if (skip)
return (A_NOACTION);
switch (b) {
default:
prev_b = b;
return (A_NOACTION);
case X11MOUSE_WHEEL_DOWN:
return mouse_wheel_down();
case X11MOUSE_WHEEL_UP:
return mouse_wheel_up();
case X11MOUSE_BUTTON_REL:
/* to trigger on button-up, we check the last button-down */
switch (prev_b) {
case X11MOUSE_BUTTON1:
return mouse_button_left(x, y);
/* is BUTTON2 the rightmost with 2-buttons mouse? */
case X11MOUSE_BUTTON2:
case X11MOUSE_BUTTON3:
return mouse_button_right(x, y);
}
return (A_NOACTION);
case X11MOUSE_BUTTON1:
case X11MOUSE_BUTTON2:
case X11MOUSE_BUTTON3:
prev_b = b;
return x11mouse_button(b, x, y, TRUE, drag);
case X11MOUSE_BUTTON_REL: /* button up */
return x11mouse_button(prev_b, x, y, FALSE, drag);
}
return (A_NOACTION);
}
/*
* Read suffix of mouse input and return the action to take.
* The prefix ("\e[<") has already been read.
*/
static int x116mouse_action(int skip)
static int x116mouse_action(lbool skip)
{
char ch;
int x, y;
int b = getcc_int(&ch);
lbool drag = ((b & X11MOUSE_DRAG) != 0);
b &= ~X11MOUSE_DRAG;
if (b < 0 || ch != ';') return (A_NOACTION);
x = getcc_int(&ch) - 1;
if (x < 0 || ch != ';') return (A_NOACTION);
@@ -631,106 +672,94 @@ static int x116mouse_action(int skip)
case X11MOUSE_WHEEL_UP:
return mouse_wheel_up();
case X11MOUSE_BUTTON1:
if (ch != 'm') return (A_NOACTION);
return mouse_button_left(x, y);
default:
if (ch != 'm') return (A_NOACTION);
/* any other button release */
return mouse_button_right(x, y);
case X11MOUSE_BUTTON2:
case X11MOUSE_BUTTON3: {
lbool down = (ch == 'M');
lbool up = (ch == 'm');
if (up || down)
return x11mouse_button(b, x, y, down, drag);
break; }
}
return (A_NOACTION);
}
/*
* Return the largest N such that the first N chars of goal
* are equal to the last N chars of str.
*/
static size_t cmd_match(constant char *goal, constant char *str)
{
size_t slen = strlen(str);
size_t len;
for (len = slen; len > 0; len--)
if (strncmp(str + slen - len, goal, len) == 0)
break;
return len;
}
/*
* Return pointer to next command table entry.
* Also return the action and the extra string from the entry.
*/
static constant unsigned char * cmd_next_entry(constant unsigned char *entry, mutable int *action, mutable constant unsigned char **extra, mutable size_t *cmdlen)
{
int a;
constant unsigned char *oentry = entry;
while (*entry != '\0') /* skip cmd */
++entry;
if (cmdlen != NULL)
*cmdlen = ptr_diff(entry, oentry);
do
a = *++entry; /* get action */
while (a == A_SKIP);
++entry; /* skip action */
if (extra != NULL)
*extra = (a & A_EXTRA) ? entry : NULL;
if (a & A_EXTRA)
{
while (*entry++ != '\0') /* skip extra string */
continue;
a &= ~A_EXTRA;
}
if (action != NULL)
*action = a;
return entry;
}
/*
* Search a single command table for the command string in cmd.
*/
static int cmd_search(constant char *cmd, constant char *table, constant char *endtable, constant char **sp)
static int cmd_search(constant char *cmd, constant unsigned char *table, constant unsigned char *endtable, constant unsigned char **extra, size_t *mlen)
{
constant char *p;
constant char *q;
int a = A_INVALID;
*sp = NULL;
for (p = table, q = cmd; p < endtable; p++, q++)
int action = A_INVALID;
size_t match_len = 0;
if (extra != NULL)
*extra = NULL;
while (table < endtable)
{
if (*p == *q)
int taction;
const unsigned char *textra;
size_t cmdlen;
size_t match = cmd_match((constant char *) table, cmd);
table = cmd_next_entry(table, &taction, &textra, &cmdlen);
if (taction == A_END_LIST)
return (-action);
if (match >= match_len)
{
/*
* Current characters match.
* If we're at the end of the string, we've found it.
* Return the action code, which is the character
* after the null at the end of the string
* in the command table.
*/
if (*p == '\0')
if (match == cmdlen) /* (last chars of) cmd matches this table entry */
{
a = *++p & 0377;
while (a == A_SKIP)
a = *++p & 0377;
if (a == A_END_LIST)
{
/*
* We get here only if the original
* cmd string passed in was empty ("").
* I don't think that can happen,
* but just in case ...
*/
return (A_UINVALID);
}
/*
* Check for an "extra" string.
*/
if (a & A_EXTRA)
{
*sp = ++p;
while (*p != '\0')
++p;
a &= ~A_EXTRA;
}
if (a == A_X11MOUSE_IN)
a = x11mouse_action(0);
else if (a == A_X116MOUSE_IN)
a = x116mouse_action(0);
q = cmd-1;
}
} else if (*q == '\0')
{
/*
* Hit the end of the user's command,
* but not the end of the string in the command table.
* The user's command is incomplete.
*/
if (a == A_INVALID)
a = A_PREFIX;
q = cmd-1;
} else
{
/*
* Not a match.
* Skip ahead to the next command in the
* command table, and reset the pointer
* to the beginning of the user's command.
*/
if (*p == '\0' && p[1] == A_END_LIST)
action = taction;
*extra = textra;
} else if (match > 0) /* cmd is a prefix of this table entry */
{
/*
* A_END_LIST is a special marker that tells
* us to abort the cmd search.
* Negative action means accept this action
* without searching any more cmd tables.
*/
return -a;
action = A_PREFIX;
}
while (*p++ != '\0')
continue;
while (*p == A_SKIP)
p++;
if (*p & A_EXTRA)
while (*++p != '\0')
continue;
q = cmd-1;
match_len = match;
}
}
return (a);
if (mlen != NULL)
*mlen = match_len;
return (action);
}
/*
@@ -741,6 +770,7 @@ static int cmd_decode(struct tablelist *tlist, constant char *cmd, constant char
{
struct tablelist *t;
int action = A_INVALID;
size_t match_len = 0;
/*
* Search for the cmd thru all the command tables.
@@ -749,18 +779,30 @@ static int cmd_decode(struct tablelist *tlist, constant char *cmd, constant char
*sp = NULL;
for (t = tlist; t != NULL; t = t->t_next)
{
constant char *tsp;
int taction = cmd_search(cmd, (char *) t->t_start, (char *) t->t_end, &tsp);
if (taction == A_UINVALID)
taction = A_INVALID;
if (taction != A_INVALID)
constant unsigned char *tsp;
size_t mlen;
int taction = cmd_search(cmd, t->t_start, t->t_end, &tsp, &mlen);
if (mlen >= match_len)
{
*sp = tsp;
if (taction < 0)
return (-taction);
action = taction;
match_len = mlen;
if (taction == A_UINVALID)
taction = A_INVALID;
if (taction != A_INVALID)
{
*sp = (constant char *) tsp;
if (taction < 0)
{
action = -taction;
break;
}
action = taction;
}
}
}
if (action == A_X11MOUSE_IN)
action = x11mouse_action(FALSE);
else if (action == A_X116MOUSE_IN)
action = x116mouse_action(FALSE);
return (action);
}
@@ -780,6 +822,7 @@ public int ecmd_decode(constant char *cmd, constant char **sp)
return (cmd_decode(list_ecmd_tables, cmd, sp));
}
/*
* Get the value of an environment variable.
* Looks first in the lesskey file, then in the real environment.
@@ -1003,10 +1046,12 @@ public int lesskey(constant char *filename, lbool sysvar)
#if HAVE_LESSKEYSRC
static int lesskey_text(constant char *filename, lbool sysvar, lbool content)
{
int r;
static struct lesskey_tables tables;
if (!secure_allow(SF_LESSKEY))
return (1);
int r = content ? parse_lesskey_content(filename, &tables) : parse_lesskey(filename, &tables);
r = content ? parse_lesskey_content(filename, &tables) : parse_lesskey(filename, &tables);
if (r != 0)
return (r);
add_fcmd_table(tables.cmdtable.buf.data, tables.cmdtable.buf.end);
@@ -1080,8 +1125,10 @@ static int add_hometable(int (*call_lesskey)(constant char *, lbool), constant c
*/
static void add_content_table(int (*call_lesskey)(constant char *, lbool), constant char *envname, lbool sysvar)
{
constant char *content;
(void) call_lesskey; /* not used */
constant char *content = lgetenv(envname);
content = lgetenv(envname);
if (isnullenv(content))
return;
lesskey_content(content, sysvar);
@@ -1130,9 +1177,9 @@ public int editchar(char c, int flags)
} while (action == A_PREFIX && nch < MAX_CMDLEN);
if (action == EC_X11MOUSE)
return (x11mouse_action(1));
return (x11mouse_action(TRUE));
if (action == EC_X116MOUSE)
return (x116mouse_action(1));
return (x116mouse_action(TRUE));
if (flags & ECF_NORIGHTLEFT)
{
@@ -1160,7 +1207,6 @@ public int editchar(char c, int flags)
}
}
#endif
#if TAB_COMPLETE_FILENAME
if (flags & ECF_NOCOMPLETE)
{
/*
@@ -1176,7 +1222,6 @@ public int editchar(char c, int flags)
break;
}
}
#endif
if ((flags & ECF_PEEK) || action == A_INVALID)
{
/*
+5 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -36,6 +36,7 @@ extern IFILE curr_ifile;
extern IFILE old_ifile;
extern struct scrpos initial_scrpos;
extern void *ml_examine;
extern POSITION soft_eof;
#if SPACES_IN_FILENAMES
extern char openquote;
extern char closequote;
@@ -531,7 +532,7 @@ public int edit_ifile(IFILE ifile)
error("%s", &parg);
free(p);
return edit_error(filename, alt_filename, altpipe, ifile);
} else if ((f = open(open_filename, OPEN_READ)) < 0)
} else if ((f = iopen(open_filename, OPEN_READ)) < 0)
{
/*
* Got an error trying to open it.
@@ -604,6 +605,7 @@ public int edit_ifile(IFILE ifile)
* Get the saved position for the file.
*/
curr_ifile = ifile;
soft_eof = NULL_POSITION;
set_altfilename(curr_ifile, alt_filename);
set_altpipe(curr_ifile, altpipe);
set_open(curr_ifile); /* File has been opened */
@@ -656,6 +658,7 @@ public int edit_ifile(IFILE ifile)
#if HILITE_SEARCH
clr_hilite();
#endif
undo_osc8();
hshift = 0;
if (strcmp(filename, FAKE_HELPFILE) && strcmp(filename, FAKE_EMPTYFILE))
{
+3 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -28,7 +28,7 @@ static size_t skipsl(constant char *buf, size_t len, size_t e)
lbool esc = FALSE;
while (e < len && buf[e] != '\0' && (esc || (buf[e] != '/' && buf[e] != '}')))
{
esc = (!esc && buf[e] == '\\');
esc = (!esc && buf[e] == '\\' && buf[e+1] != '\0');
++e;
}
return e;
@@ -150,7 +150,7 @@ static size_t add_evar(struct xbuffer *xbuf, mutable char *buf, size_t len, size
size_t r;
for (r = 0; repl[r] != '\0'; r++)
{
if (repl[r] == '\\') ++r;
if (repl[r] == '\\' && repl[r+1] != '\0') ++r;
xbuf_add_char(xbuf, repl[r]);
}
}
+3 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -288,7 +288,7 @@ public char * homefile(constant char *filename)
if (pathname != NULL)
return (pathname);
#endif
#if MSDOS_COMPILER || OS2
#if (MSDOS_COMPILER && MSDOS_COMPILER!=WIN32C) || OS2
/* Look for the file anywhere on search path. */
pathname = (char *) ecalloc(_MAX_PATH, sizeof(char));
#if MSDOS_COMPILER==DJGPPC
@@ -496,7 +496,7 @@ public int bin_file(int f, ssize_t *n)
struct ansi_state *pansi;
if (ctldisp == OPT_ONPLUS && (pansi = ansi_start(c)) != NULL)
{
skip_ansi(pansi, &p, edata);
skip_ansi(pansi, c, &p, edata);
ansi_done(pansi);
} else if (binary_char(c))
bin_count++;
+1 -1
View File
@@ -1,4 +1,4 @@
/* Generated by "./mkutable -f2 Cf -- unicode/UnicodeData.txt" on Sun Sep 17 17:56:27 PDT 2023 */
/* Generated by "./mkutable -f2 Cf -- unicode/UnicodeData.txt" on Oct 1 18:10:07 GMT 2024 */
{ 0x00ad, 0x00ad }, /* Cf */
{ 0x0600, 0x0605 }, /* Cf */
{ 0x061c, 0x061c }, /* Cf */
+78 -85
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -21,8 +21,11 @@ extern int less_is_more;
public lbool squished;
public int no_back_scroll = 0;
public int forw_prompt;
public int first_time = 1;
public lbool no_eof_bell = FALSE;
public lbool first_time = TRUE; /* We're printing the first screen of output */
public int shell_lines = 1;
/* soft_eof is set as end-of-file when a read attempt returns EOF. This can
* differ from actual EOF (ch_length()) if & filtering is in effect. */
public POSITION soft_eof = NULL_POSITION;
extern int sigs;
extern int top_scroll;
@@ -37,9 +40,10 @@ extern int ignore_eoi;
extern int header_lines;
extern int header_cols;
extern int full_screen;
extern int stop_on_form_feed;
extern POSITION header_start_pos;
extern lbool getting_one_screen;
#if HILITE_SEARCH
extern size_t size_linebuf;
extern int hilite_search;
extern int status_col;
#endif
@@ -52,14 +56,14 @@ extern char *tagoption;
*/
public void eof_bell(void)
{
if (no_eof_bell)
return;
#if HAVE_TIME
static time_type last_eof_bell = 0;
time_type now = get_time();
if (now == last_eof_bell) /* max once per second */
return;
last_eof_bell = now;
{
static time_type last_eof_bell = 0;
time_type now = get_time();
if (now == last_eof_bell) /* max once per second */
return;
last_eof_bell = now;
}
#endif
if (quiet == NOT_QUIET)
bell();
@@ -70,7 +74,7 @@ public void eof_bell(void)
/*
* Check to see if the end of file is currently displayed.
*/
public lbool eof_displayed(void)
public lbool eof_displayed(lbool offset)
{
POSITION pos;
@@ -89,8 +93,8 @@ public lbool eof_displayed(void)
* If the bottom line ends at the file length,
* we must be just at EOF.
*/
pos = position(BOTTOM_PLUS_ONE);
return (pos == NULL_POSITION || pos == ch_length());
pos = position(offset ? BOTTOM_OFFSET : BOTTOM_PLUS_ONE);
return (pos == NULL_POSITION || pos == ch_length() || pos == soft_eof);
}
/*
@@ -101,7 +105,7 @@ public lbool entire_file_displayed(void)
POSITION pos;
/* Make sure last line of file is displayed. */
if (!eof_displayed())
if (!eof_displayed(TRUE))
return (FALSE);
/* Make sure first line of file is displayed. */
@@ -136,7 +140,7 @@ static POSITION forw_line_pfx(POSITION pos, int pfx, int skipeol)
sc_width = pfx + line_pfx_width();
auto_wrap = 0;
hshift = 0;
pos = forw_line_seg(pos, skipeol, FALSE, FALSE);
pos = forw_line_seg(pos, skipeol, FALSE, FALSE, NULL, NULL);
sc_width = save_sc_width;
auto_wrap = save_auto_wrap;
hshift = save_hshift;
@@ -171,10 +175,10 @@ public int overlay_header(void)
home();
for (ln = 0; ln < header_lines; ++ln)
{
pos = forw_line(pos);
pos = forw_line(pos, NULL, NULL);
set_attr_header(ln);
clear_eol();
put_line();
put_line(FALSE);
}
moved = TRUE;
}
@@ -194,7 +198,7 @@ public int overlay_header(void)
/* Need skipeol for all header lines except the last one. */
pos = forw_line_pfx(pos, header_cols, ln+1 < header_lines);
set_attr_header(ln);
put_line();
put_line(FALSE);
}
}
moved = TRUE;
@@ -212,11 +216,14 @@ public int overlay_header(void)
* "nblank" is the number of blank lines to draw before the first
* real line. If nblank > 0, the pos must be NULL_POSITION.
* The first real line after the blanks will start at ch_zero().
* "to_newline" means count file lines rather than screen lines.
*/
public void forw(int n, POSITION pos, lbool force, lbool only_last, int nblank)
public void forw(int n, POSITION pos, lbool force, lbool only_last, lbool to_newline, int nblank)
{
int nlines = 0;
lbool do_repaint;
lbool newline;
lbool first_line = TRUE;
if (pos != NULL_POSITION)
pos = after_header_pos(pos);
@@ -233,14 +240,6 @@ public void forw(int n, POSITION pos, lbool force, lbool only_last, int nblank)
*/
do_repaint = (only_last && n > sc_height-1) ||
(forw_scroll >= 0 && n > forw_scroll && n != sc_height-1);
#if HILITE_SEARCH
if (pos != NULL_POSITION && (hilite_search == OPT_ONPLUS || is_filtering() || status_col)) {
prep_hilite(pos, pos + (POSITION) (4*size_linebuf), ignore_eoi ? 1 : -1);
pos = next_unfiltered(pos);
}
#endif
if (!do_repaint)
{
if (top_scroll && n >= sc_height - 1 && pos != ch_length())
@@ -252,7 +251,6 @@ public void forw(int n, POSITION pos, lbool force, lbool only_last, int nblank)
* but we don't yet know if that will happen. }}
*/
pos_clear();
add_forw_pos(pos);
force = TRUE;
if (less_is_more == 0) {
clear();
@@ -268,7 +266,6 @@ public void forw(int n, POSITION pos, lbool force, lbool only_last, int nblank)
* (position table) and start a new screen.
*/
pos_clear();
add_forw_pos(pos);
force = TRUE;
if (top_scroll)
{
@@ -283,6 +280,7 @@ public void forw(int n, POSITION pos, lbool force, lbool only_last, int nblank)
while (--n >= 0)
{
POSITION linepos = NULL_POSITION;
/*
* Read the next line of input.
*/
@@ -301,10 +299,10 @@ public void forw(int n, POSITION pos, lbool force, lbool only_last, int nblank)
/*
* Get the next line from the file.
*/
pos = forw_line(pos);
#if HILITE_SEARCH
pos = next_unfiltered(pos);
#endif
POSITION opos = pos;
pos = forw_line(pos, &linepos, &newline);
if (to_newline && !newline)
++n;
if (pos == NULL_POSITION)
{
/*
@@ -313,19 +311,23 @@ public void forw(int n, POSITION pos, lbool force, lbool only_last, int nblank)
* Even if force is true, stop when the last
* line in the file reaches the top of screen.
*/
if (!force && position(TOP) != NULL_POSITION)
break;
if (!empty_lines(0, 0) &&
!empty_lines(1, 1) &&
empty_lines(2, sc_height-1))
soft_eof = opos;
linepos = opos;
if (ABORT_SIGS() ||
(!force && position(TOP) != NULL_POSITION) ||
(!empty_lines(0, 0) && !empty_lines(1, 1) && empty_lines(2, sc_height-1)))
{
pos = opos;
break;
}
}
}
/*
* Add the position of the next line to the position table.
* Display the current line on the screen.
*/
add_forw_pos(pos);
add_forw_pos(linepos, first_line);
first_line = FALSE;
nlines++;
if (do_repaint)
continue;
@@ -350,30 +352,13 @@ public void forw(int n, POSITION pos, lbool force, lbool only_last, int nblank)
squished = TRUE;
continue;
}
put_line();
#if 0
/* {{
* Can't call clear_eol here. The cursor might be at end of line
* on an ignaw terminal, so clear_eol would clear the last char
* of the current line instead of all of the next line.
* If we really need to do this on clear_bg terminals, we need
* to find a better way.
* }}
*/
if (clear_bg && apply_at_specials(final_attr) != AT_NORMAL)
{
/*
* Writing the last character on the last line
* of the display may have scrolled the screen.
* If we were in standout mode, clear_bg terminals
* will fill the new line with the standout color.
* Now we're in normal mode again, so clear the line.
*/
clear_eol();
}
#endif
put_line(TRUE);
if (stop_on_form_feed && !do_repaint && line_is_ff() && position(TOP) != NULL_POSITION)
break;
forw_prompt = 1;
}
if (!first_line)
add_forw_pos(pos, FALSE);
if (nlines == 0 && !ignore_eoi)
eof_bell();
else if (do_repaint)
@@ -383,34 +368,30 @@ public void forw(int n, POSITION pos, lbool force, lbool only_last, int nblank)
overlay_header();
/* lower_left(); {{ considered harmful? }} */
}
first_time = 0;
first_time = FALSE;
(void) currline(BOTTOM);
}
/*
* Display n lines, scrolling backward.
*/
public void back(int n, POSITION pos, lbool force, lbool only_last)
public void back(int n, POSITION pos, lbool force, lbool only_last, lbool to_newline)
{
int nlines = 0;
lbool do_repaint;
lbool newline;
squish_check();
do_repaint = (n > get_back_scroll() || (only_last && n > sc_height-1) || header_lines > 0);
#if HILITE_SEARCH
if (pos != NULL_POSITION && (hilite_search == OPT_ONPLUS || is_filtering() || status_col)) {
prep_hilite((pos < (POSITION) (3*size_linebuf)) ? 0 : pos - (POSITION) (3*size_linebuf), pos, -1);
}
#endif
while (--n >= 0)
{
/*
* Get the previous line of input.
*/
#if HILITE_SEARCH
pos = prev_unfiltered(pos);
#endif
pos = back_line(pos);
pos = back_line(pos, &newline);
if (to_newline && !newline)
++n;
if (pos == NULL_POSITION)
{
/*
@@ -436,7 +417,9 @@ public void back(int n, POSITION pos, lbool force, lbool only_last)
{
home();
add_line();
put_line();
put_line(FALSE);
if (stop_on_form_feed && line_is_ff())
break;
}
}
if (nlines == 0)
@@ -455,11 +438,11 @@ public void back(int n, POSITION pos, lbool force, lbool only_last)
* Display n more lines, forward.
* Start just after the line currently displayed at the bottom of the screen.
*/
public void forward(int n, lbool force, lbool only_last)
public void forward(int n, lbool force, lbool only_last, lbool to_newline)
{
POSITION pos;
if (get_quit_at_eof() && eof_displayed() && !(ch_getflags() & CH_HELPFILE))
if (get_quit_at_eof() && eof_displayed(FALSE) && !(ch_getflags() & CH_HELPFILE))
{
/*
* If the -e flag is set and we're trying to go
@@ -486,7 +469,7 @@ public void forward(int n, lbool force, lbool only_last)
{
do
{
back(1, position(TOP), 1, 0);
back(1, position(TOP), TRUE, FALSE, FALSE);
pos = position(BOTTOM_PLUS_ONE);
} while (pos == NULL_POSITION && !ABORT_SIGS());
}
@@ -496,14 +479,14 @@ public void forward(int n, lbool force, lbool only_last)
return;
}
}
forw(n, pos, force, only_last, 0);
forw(n, pos, force, only_last, to_newline, 0);
}
/*
* Display n more lines, backward.
* Start just before the line currently displayed at the top of the screen.
*/
public void backward(int n, lbool force, lbool only_last)
public void backward(int n, lbool force, lbool only_last, lbool to_newline)
{
POSITION pos;
@@ -513,7 +496,7 @@ public void backward(int n, lbool force, lbool only_last)
eof_bell();
return;
}
back(n, pos, force, only_last);
back(n, pos, force, only_last, to_newline);
}
/*
@@ -536,15 +519,25 @@ public int get_back_scroll(void)
/*
* Will the entire file fit on one screen?
*/
public int get_one_screen(void)
public lbool get_one_screen(void)
{
int nlines;
POSITION pos = ch_zero();
lbool ret = FALSE;
for (nlines = 0; nlines < sc_height; nlines++)
/* Disable polling until we know whether we will exit early due to -F. */
getting_one_screen = TRUE;
for (nlines = 0; nlines + shell_lines <= sc_height; nlines++)
{
pos = forw_line(pos);
if (pos == NULL_POSITION) break;
pos = forw_line(pos, NULL, NULL);
if (ABORT_SIGS())
break;
if (pos == NULL_POSITION)
{
ret = TRUE;
break;
}
}
return (nlines < sc_height);
getting_one_screen = FALSE;
return ret;
}
+33 -18
View File
@@ -31,6 +31,8 @@ public void bell(void);
public void clear(void);
public void clear_eol(void);
public void clear_bot(void);
public void init_bracketed_paste(void);
public void deinit_bracketed_paste(void);
public COLOR_TYPE parse_color(constant char *str, mutable int *p_fg, mutable int *p_bg, mutable CHAR_ATTR *p_cattr);
public void at_enter(int attr);
public void at_exit(void);
@@ -39,6 +41,7 @@ public lbool is_at_equiv(int attr1, int attr2);
public int apply_at_specials(int attr);
public void putbs(void);
public void WIN32ungetch(int ch);
public lbool win32_kbhit2(lbool no_queued);
public lbool win32_kbhit(void);
public char WIN32getch(void);
public void win32_getch_clear(void);
@@ -53,6 +56,7 @@ public int ch_end_seek(void);
public int ch_end_buffer_seek(void);
public int ch_beg_seek(void);
public POSITION ch_length(void);
public void ch_resize(void);
public POSITION ch_tell(void);
public int ch_forw_get(void);
public int ch_back_get(void);
@@ -84,6 +88,7 @@ public void cmd_reset(void);
public void clear_cmd(void);
public void cmd_putstr(constant char *s);
public int len_cmdbuf(void);
public lbool cmdbuf_empty(void);
public void cmd_repaint(constant char *old_cp);
public void set_mlist(void *mlist, int cmdflags);
public ssize_t save_updown_match(void);
@@ -91,11 +96,13 @@ public void restore_updown_match(ssize_t udm);
public void cmd_addhist(struct mlist *mlist, constant char *cmd, lbool modified);
public void cmd_accept(void);
public int cmd_char(char c);
public int cmd_setstring(constant char *s, lbool uc);
public LINENUM cmd_int(mutable long *frac);
public constant char * get_cmdbuf(void);
public constant char * cmd_lastpattern(void);
public void init_cmdhist(void);
public void save_cmdhist(void);
public void cmd_exec(void);
public int in_mca(void);
public int norm_search_type(int st);
public void screen_trashed_num(int trashed);
@@ -109,6 +116,9 @@ public void ungetcc_back(char c);
public void ungetcc_end_command(void);
public void ungetsc(constant char *s);
public char peekcc(void);
public void start_ignoring_input();
public void stop_ignoring_input();
public lbool is_ignoring_input(int action);
public void commands(void);
public size_t cvt_length(size_t len, int ops);
public int * cvt_alloc_chpos(size_t len);
@@ -171,16 +181,16 @@ public lbool curr_ifile_changed(void);
public constant char * shell_coption(void);
public constant char * last_component(constant char *name);
public void eof_bell(void);
public lbool eof_displayed(void);
public lbool eof_displayed(lbool offset);
public lbool entire_file_displayed(void);
public void squish_check(void);
public int overlay_header(void);
public void forw(int n, POSITION pos, lbool force, lbool only_last, int nblank);
public void back(int n, POSITION pos, lbool force, lbool only_last);
public void forward(int n, lbool force, lbool only_last);
public void backward(int n, lbool force, lbool only_last);
public void forw(int n, POSITION pos, lbool force, lbool only_last, lbool to_newline, int nblank);
public void back(int n, POSITION pos, lbool force, lbool only_last, lbool to_newline);
public void forward(int n, lbool force, lbool only_last, lbool to_newline);
public void backward(int n, lbool force, lbool only_last, lbool to_newline);
public int get_back_scroll(void);
public int get_one_screen(void);
public lbool get_one_screen(void);
public void del_ifile(IFILE h);
public IFILE next_ifile(IFILE h);
public IFILE prev_ifile(IFILE h);
@@ -203,9 +213,9 @@ public void *get_altpipe(IFILE ifile);
public void set_altfilename(IFILE ifile, char *altfilename);
public char * get_altfilename(IFILE ifile);
public void if_dump(void);
public POSITION forw_line_seg(POSITION curr_pos, lbool skipeol, lbool rscroll, lbool nochop);
public POSITION forw_line(POSITION curr_pos);
public POSITION back_line(POSITION curr_pos);
public POSITION forw_line_seg(POSITION curr_pos, lbool skipeol, lbool rscroll, lbool nochop, POSITION *p_linepos, lbool *p_newline);
public POSITION forw_line(POSITION curr_pos, POSITION *p_linepos, lbool *p_newline);
public POSITION back_line(POSITION curr_pos, lbool *p_newline);
public void set_attnpos(POSITION pos);
public void jump_forw(void);
public void jump_forw_buffered(void);
@@ -227,20 +237,22 @@ public void savec(void);
public void loadc(void);
public lbool is_ansi_end(LWCHAR ch);
public lbool is_ansi_middle(LWCHAR ch);
public void skip_ansi(struct ansi_state *pansi, constant char **pp, constant char *limit);
public void skip_ansi(struct ansi_state *pansi, LWCHAR ch, constant char **pp, constant char *limit);
public struct ansi_state * ansi_start(LWCHAR ch);
public ansi_state ansi_step(struct ansi_state *pansi, LWCHAR ch);
public osc8_state ansi_osc8_state(struct ansi_state *pansi);
public void ansi_done(struct ansi_state *pansi);
public int pappend_b(char c, POSITION pos, lbool before_pendc);
public int pappend(char c, POSITION pos);
public lbool line_is_ff(void);
public int pflushmbc(void);
public void pdone(int endline, int chopped, int forw);
public void pdone(lbool endline, lbool chopped, lbool forw);
public int col_from_pos(POSITION linepos, POSITION spos, POSITION saved_pos, int saved_col);
public POSITION pos_from_col(POSITION linepos, int col, POSITION saved_pos, int saved_col);
public void set_attr_line(int a);
public void set_status_col(char c, int attr);
public int gline(size_t i, int *ap);
public lbool should_clear_after_line(void);
public void null_line(void);
public POSITION forw_raw_line_len(POSITION curr_pos, size_t read_len, constant char **linep, size_t *line_lenp);
public POSITION forw_raw_line(POSITION curr_pos, constant char **linep, size_t *line_lenp);
@@ -309,12 +321,13 @@ public void opt_search_type(int type, constant char *s);
public void opt_nosearch_headers(int type, constant char *s);
public void opt_nosearch_header_lines(int type, constant char *s);
public void opt_nosearch_header_cols(int type, constant char *s);
public void opt_no_paste(int type, constant char *s);
public void opt_ttyin_name(int type, constant char *s);
public int chop_line(void);
public int get_swindow(void);
public constant char * propt(char c);
public void scan_option(constant char *s);
public void toggle_option(struct loption *o, int lower, constant char *s, int how_toggle);
public void scan_option(constant char *s, lbool is_env);
public void toggle_option(struct loption *o, lbool lower, constant char *s, int how_toggle);
public int opt_has_param(struct loption *o);
public constant char * opt_prompt(struct loption *o);
public constant char * opt_toggle_disallowed(int c);
@@ -328,10 +341,12 @@ public int get_quit_at_eof(void);
public void init_option(void);
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 int supports_ctrl_x(void);
public ssize_t iread(int fd, unsigned char *buf, size_t len);
public void intread(void);
public int iopen(constant char *filename, int flags);
public void intio(void);
public time_type get_time(void);
public char * errno_message(constant char *filename);
public constant char * signal_message(int sig);
@@ -340,7 +355,7 @@ public int percentage(POSITION num, POSITION den);
public POSITION percent_pos(POSITION pos, int percent, long fraction);
public int os9_signal(int type, RETSIGTYPE (*handler)());
public void sleep_ms(int ms);
public void put_line(void);
public void put_line(lbool forw_scroll);
public void flush(void);
public void set_output(int fd);
public int putchr(int ch);
@@ -356,10 +371,10 @@ public int compile_pattern(constant char *pattern, int search_type, int show_err
public void uncompile_pattern(PATTERN_TYPE *pattern);
public int valid_pattern(char *pattern);
public lbool is_null_pattern(PATTERN_TYPE pattern);
public int match_pattern(PATTERN_TYPE pattern, constant char *tpattern, constant char *line, size_t line_len, constant char **sp, constant char **ep, int nsp, int notbol, int search_type);
public lbool match_pattern(PATTERN_TYPE pattern, constant char *tpattern, constant char *line, size_t line_len, size_t line_off, constant char **sp, constant char **ep, int nsp, int notbol, int search_type);
public constant char * pattern_lib_name(void);
public POSITION position(int sindex);
public void add_forw_pos(POSITION pos);
public void add_forw_pos(POSITION pos, lbool no_scroll);
public void add_back_pos(POSITION pos);
public void pos_clear(void);
public void pos_init(void);
@@ -379,13 +394,13 @@ public int get_cvt_ops(int search_type);
public void repaint_hilite(lbool on);
public void clear_attn(void);
public void undo_search(lbool clear);
public void undo_osc8(void);
public void clr_hlist(struct hilite_tree *anchor);
public void clr_hilite(void);
public void clr_filter(void);
public void set_header(POSITION pos);
public lbool is_filtered(POSITION pos);
public POSITION next_unfiltered(POSITION pos);
public POSITION prev_unfiltered(POSITION pos);
public int is_hilited_attr(POSITION pos, POSITION epos, int nohide, int *p_matches);
public void chg_hilite(void);
public void osc8_search(int search_type, constant char *param, int matches);
+11 -1
View File
@@ -1,4 +1,4 @@
/* This file was generated by mkhelp.pl from less.hlp at 22:29 on 2024/10/6 */
/* This file was generated by mkhelp.pl from less.hlp at 20:41 on 2025/5/1 */
#include "less.h"
constant char helpdata[] = {
'\n',
@@ -16,11 +16,14 @@ constant char helpdata[] = {
'\n',
' ',' ','e',' ',' ','^','E',' ',' ','j',' ',' ','^','N',' ',' ','C','R',' ',' ','*',' ',' ','F','o','r','w','a','r','d',' ',' ','o','n','e',' ','l','i','n','e',' ',' ',' ','(','o','r',' ','_','\b','N',' ','l','i','n','e','s',')','.','\n',
' ',' ','y',' ',' ','^','Y',' ',' ','k',' ',' ','^','K',' ',' ','^','P',' ',' ','*',' ',' ','B','a','c','k','w','a','r','d',' ','o','n','e',' ','l','i','n','e',' ',' ',' ','(','o','r',' ','_','\b','N',' ','l','i','n','e','s',')','.','\n',
' ',' ','E','S','C','-','j',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','F','o','r','w','a','r','d',' ',' ','o','n','e',' ','f','i','l','e',' ','l','i','n','e',' ','(','o','r',' ','_','\b','N',' ','f','i','l','e',' ','l','i','n','e','s',')','.','\n',
' ',' ','E','S','C','-','k',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','B','a','c','k','w','a','r','d',' ','o','n','e',' ','f','i','l','e',' ','l','i','n','e',' ','(','o','r',' ','_','\b','N',' ','f','i','l','e',' ','l','i','n','e','s',')','.','\n',
' ',' ','f',' ',' ','^','F',' ',' ','^','V',' ',' ','S','P','A','C','E',' ',' ','*',' ',' ','F','o','r','w','a','r','d',' ',' ','o','n','e',' ','w','i','n','d','o','w',' ','(','o','r',' ','_','\b','N',' ','l','i','n','e','s',')','.','\n',
' ',' ','b',' ',' ','^','B',' ',' ','E','S','C','-','v',' ',' ',' ',' ',' ',' ','*',' ',' ','B','a','c','k','w','a','r','d',' ','o','n','e',' ','w','i','n','d','o','w',' ','(','o','r',' ','_','\b','N',' ','l','i','n','e','s',')','.','\n',
' ',' ','z',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','F','o','r','w','a','r','d',' ',' ','o','n','e',' ','w','i','n','d','o','w',' ','(','a','n','d',' ','s','e','t',' ','w','i','n','d','o','w',' ','t','o',' ','_','\b','N',')','.','\n',
' ',' ','w',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','B','a','c','k','w','a','r','d',' ','o','n','e',' ','w','i','n','d','o','w',' ','(','a','n','d',' ','s','e','t',' ','w','i','n','d','o','w',' ','t','o',' ','_','\b','N',')','.','\n',
' ',' ','E','S','C','-','S','P','A','C','E',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','F','o','r','w','a','r','d',' ',' ','o','n','e',' ','w','i','n','d','o','w',',',' ','b','u','t',' ','d','o','n','\'','t',' ','s','t','o','p',' ','a','t',' ','e','n','d','-','o','f','-','f','i','l','e','.','\n',
' ',' ','E','S','C','-','b',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','B','a','c','k','w','a','r','d',' ','o','n','e',' ','w','i','n','d','o','w',',',' ','b','u','t',' ','d','o','n','\'','t',' ','s','t','o','p',' ','a','t',' ','b','e','g','i','n','n','i','n','g','-','o','f','-','f','i','l','e','.','\n',
' ',' ','d',' ',' ','^','D',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','F','o','r','w','a','r','d',' ',' ','o','n','e',' ','h','a','l','f','-','w','i','n','d','o','w',' ','(','a','n','d',' ','s','e','t',' ','h','a','l','f','-','w','i','n','d','o','w',' ','t','o',' ','_','\b','N',')','.','\n',
' ',' ','u',' ',' ','^','U',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','B','a','c','k','w','a','r','d',' ','o','n','e',' ','h','a','l','f','-','w','i','n','d','o','w',' ','(','a','n','d',' ','s','e','t',' ','h','a','l','f','-','w','i','n','d','o','w',' ','t','o',' ','_','\b','N',')','.','\n',
' ',' ','E','S','C','-',')',' ',' ','R','i','g','h','t','A','r','r','o','w',' ','*',' ',' ','R','i','g','h','t',' ','o','n','e',' ','h','a','l','f',' ','s','c','r','e','e','n',' ','w','i','d','t','h',' ','(','o','r',' ','_','\b','N',' ','p','o','s','i','t','i','o','n','s',')','.','\n',
@@ -51,6 +54,7 @@ constant char helpdata[] = {
' ',' ','E','S','C','-','U',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','C','l','e','a','r',' ','s','e','a','r','c','h',' ','h','i','g','h','l','i','g','h','t','i','n','g','.','\n',
' ',' ','&','_','\b','p','_','\b','a','_','\b','t','_','\b','t','_','\b','e','_','\b','r','_','\b','n',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','D','i','s','p','l','a','y',' ','o','n','l','y',' ','m','a','t','c','h','i','n','g',' ','l','i','n','e','s','.','\n',
' ',' ',' ',' ',' ',' ',' ',' ','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\n',
'\t','\t','S','e','a','r','c','h',' ','i','s',' ','c','a','s','e','-','s','e','n','s','i','t','i','v','e',' ','u','n','l','e','s','s',' ','c','h','a','n','g','e','d',' ','w','i','t','h',' ','-','i',' ','o','r',' ','-','I','.','\n',
' ',' ',' ',' ',' ',' ',' ',' ','A',' ','s','e','a','r','c','h',' ','p','a','t','t','e','r','n',' ','m','a','y',' ','b','e','g','i','n',' ','w','i','t','h',' ','o','n','e',' ','o','r',' ','m','o','r','e',' ','o','f',':','\n',
' ',' ',' ',' ',' ',' ',' ',' ','^','N',' ','o','r',' ','!',' ',' ','S','e','a','r','c','h',' ','f','o','r',' ','N','O','N','-','m','a','t','c','h','i','n','g',' ','l','i','n','e','s','.','\n',
' ',' ',' ',' ',' ',' ',' ',' ','^','E',' ','o','r',' ','*',' ',' ','S','e','a','r','c','h',' ','m','u','l','t','i','p','l','e',' ','f','i','l','e','s',' ','(','p','a','s','s',' ','t','h','r','u',' ','E','N','D',' ','O','F',' ','F','I','L','E',')','.','\n',
@@ -224,6 +228,8 @@ constant char helpdata[] = {
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','A','u','t','o','m','a','t','i','c','a','l','l','y',' ','d','e','t','e','r','m','i','n','e',' ','t','h','e',' ','s','i','z','e',' ','o','f',' ','t','h','e',' ','i','n','p','u','t',' ','f','i','l','e','.','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','f','o','l','l','o','w','-','n','a','m','e','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','T','h','e',' ','F',' ','c','o','m','m','a','n','d',' ','c','h','a','n','g','e','s',' ','f','i','l','e','s',' ','i','f',' ','t','h','e',' ','i','n','p','u','t',' ','f','i','l','e',' ','i','s',' ','r','e','n','a','m','e','d','.','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','f','o','r','m','-','f','e','e','d','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','t','o','p',' ','s','c','r','o','l','l','i','n','g',' ','w','h','e','n',' ','a',' ','f','o','r','m',' ','f','e','e','d',' ','c','h','a','r','a','c','t','e','r',' ','i','s',' ','r','e','a','c','h','e','d','.','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','h','e','a','d','e','r','=','[','_','\b','L','[',',','_','\b','C','[',',','_','\b','N',']',']',']','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','U','s','e',' ','_','\b','L',' ','l','i','n','e','s',' ','(','s','t','a','r','t','i','n','g',' ','a','t',' ','l','i','n','e',' ','_','\b','N',')',' ','a','n','d',' ','_','\b','C',' ','c','o','l','u','m','n','s',' ','a','s',' ','h','e','a','d','e','r','s','.','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','i','n','c','s','e','a','r','c','h','\n',
@@ -242,12 +248,16 @@ constant char helpdata[] = {
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','R','e','a','d',' ','_','\b','N',' ','l','i','n','e','s',' ','f','r','o','m',' ','t','h','e',' ','i','n','p','u','t',' ','f','i','l','e',' ','a','n','d',' ','l','o','o','k',' ','f','o','r',' ','v','i','m',' ','m','o','d','e','l','i','n','e','s','.','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','m','o','u','s','e','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','E','n','a','b','l','e',' ','m','o','u','s','e',' ','i','n','p','u','t','.','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','n','o','-','e','d','i','t','-','w','a','r','n','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','o','n','\'','t',' ','w','a','r','n',' ','w','h','e','n',' ','u','s','i','n','g',' ','v',' ','c','o','m','m','a','n','d',' ','o','n',' ','a',' ','f','i','l','e',' ','o','p','e','n','e','d',' ','v','i','a',' ','L','E','S','S','O','P','E','N','.','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','n','o','-','k','e','y','p','a','d','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','o','n','\'','t',' ','s','e','n','d',' ','t','e','r','m','c','a','p',' ','k','e','y','p','a','d',' ','i','n','i','t','/','d','e','i','n','i','t',' ','s','t','r','i','n','g','s','.','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','n','o','-','h','i','s','t','d','u','p','s','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','R','e','m','o','v','e',' ','d','u','p','l','i','c','a','t','e','s',' ','f','r','o','m',' ','c','o','m','m','a','n','d',' ','h','i','s','t','o','r','y','.','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','n','o','-','n','u','m','b','e','r','-','h','e','a','d','e','r','s','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','o','n','\'','t',' ','g','i','v','e',' ','l','i','n','e',' ','n','u','m','b','e','r','s',' ','t','o',' ','h','e','a','d','e','r',' ','l','i','n','e','s','.','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','n','o','-','p','a','s','t','e','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','I','g','n','o','r','e',' ','p','a','s','t','e','d',' ','i','n','p','u','t','.','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','n','o','-','s','e','a','r','c','h','-','h','e','a','d','e','r','-','l','i','n','e','s','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','a','r','c','h','e','s',' ','d','o',' ','n','o','t',' ','i','n','c','l','u','d','e',' ','h','e','a','d','e','r',' ','l','i','n','e','s','.','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','n','o','-','s','e','a','r','c','h','-','h','e','a','d','e','r','-','c','o','l','u','m','n','s','\n',
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
+27 -21
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -29,7 +29,6 @@ extern POSITION start_attnpos;
extern POSITION end_attnpos;
#if HILITE_SEARCH
extern int hilite_search;
extern size_t size_linebuf;
extern int show_attn;
#endif
@@ -68,9 +67,9 @@ static void init_status_col(POSITION base_pos, POSITION disp_pos, POSITION edisp
attr = is_hilited_attr(disp_pos, edisp_pos, TRUE, NULL);
ch = '*';
} else
{
attr = 0;
}
{
attr = 0;
}
if (attr)
set_status_col(ch, attr);
}
@@ -82,7 +81,7 @@ static void init_status_col(POSITION base_pos, POSITION disp_pos, POSITION edisp
* a line. The new position is the position of the first character
* of the NEXT line. The line obtained is the line starting at curr_pos.
*/
public POSITION forw_line_seg(POSITION curr_pos, lbool skipeol, lbool rscroll, lbool nochop)
public POSITION forw_line_seg(POSITION curr_pos, lbool skipeol, lbool rscroll, lbool nochop, POSITION *p_linepos, lbool *p_newline)
{
POSITION base_pos;
POSITION new_pos;
@@ -95,6 +94,9 @@ public POSITION forw_line_seg(POSITION curr_pos, lbool skipeol, lbool rscroll, l
POSITION wrap_pos;
lbool skipped_leading;
if (p_linepos != NULL)
*p_linepos = NULL_POSITION;
get_forw_line:
if (curr_pos == NULL_POSITION)
{
@@ -111,8 +113,7 @@ get_forw_line:
* If we're not ignoring EOI, we *could* do the same, but
* for efficiency we prepare several lines ahead at once.
*/
prep_hilite(curr_pos, curr_pos + (POSITION) (3*size_linebuf), ignore_eoi ? 1 : -1);
curr_pos = next_unfiltered(curr_pos);
prep_hilite(curr_pos, NULL_POSITION, 1);
}
#endif
if (ch_seek(curr_pos))
@@ -295,7 +296,7 @@ get_forw_line:
pappend_b(' ', ch_tell()-1, TRUE);
}
#endif
pdone(endline, rscroll && chopped, 1);
pdone(endline, rscroll && chopped, TRUE);
#if HILITE_SEARCH
if (is_filtered(base_pos))
@@ -324,14 +325,16 @@ get_forw_line:
(void) ch_back_get();
new_pos = ch_tell();
}
if (p_linepos != NULL)
*p_linepos = curr_pos;
if (p_newline != NULL)
*p_newline = endline;
return (new_pos);
}
public POSITION forw_line(POSITION curr_pos)
public POSITION forw_line(POSITION curr_pos, POSITION *p_linepos, lbool *p_newline)
{
return forw_line_seg(curr_pos, (chop_line() || hshift > 0), TRUE, FALSE);
return forw_line_seg(curr_pos, (chop_line() || hshift > 0), TRUE, FALSE, p_linepos, p_newline);
}
/*
@@ -341,7 +344,7 @@ public POSITION forw_line(POSITION curr_pos)
* a line. The new position is the position of the first character
* of the PREVIOUS line. The line obtained is the one starting at new_pos.
*/
public POSITION back_line(POSITION curr_pos)
public POSITION back_line(POSITION curr_pos, lbool *p_newline)
{
POSITION base_pos;
POSITION new_pos;
@@ -360,11 +363,6 @@ get_back_line:
null_line();
return (NULL_POSITION);
}
#if HILITE_SEARCH
if (hilite_search == OPT_ONPLUS || is_filtering() || status_col)
prep_hilite((curr_pos < (POSITION) (3*size_linebuf)) ? 0 :
curr_pos - (POSITION) (3*size_linebuf), curr_pos, -1);
#endif
if (ch_seek(curr_pos-1))
{
null_line();
@@ -427,6 +425,11 @@ get_back_line:
}
}
#if HILITE_SEARCH
if (hilite_search == OPT_ONPLUS || is_filtering() || status_col)
prep_hilite(base_pos, NULL_POSITION, 1);
#endif
/*
* Now scan forwards from the beginning of this line.
* We keep discarding "printable lines" (based on screen width)
@@ -445,6 +448,8 @@ get_back_line:
endline = FALSE;
prewind();
plinestart(new_pos);
if (p_newline != NULL)
*p_newline = TRUE;
loop:
wrap_pos = NULL_POSITION;
skipped_leading = FALSE;
@@ -489,6 +494,8 @@ get_back_line:
edisp_pos = new_pos;
break;
}
if (p_newline != NULL)
*p_newline = FALSE;
shift:
if (!wordwrap)
{
@@ -550,7 +557,7 @@ get_back_line:
}
}
pdone(endline, chopped, 0);
pdone(endline, chopped, FALSE);
#if HILITE_SEARCH
if (is_filtered(base_pos))
@@ -565,7 +572,6 @@ get_back_line:
if (status_col)
init_status_col(base_pos, line_position(), edisp_pos, new_pos);
#endif
return (begin_new_pos);
}
+13 -14
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -53,7 +53,7 @@ public void jump_forw(void)
* to get to the beginning of the last line.
*/
pos_clear();
pos = back_line(end_pos);
pos = back_line(end_pos, NULL);
if (pos == NULL_POSITION)
jump_loc(ch_zero(), sc_height-1);
else
@@ -232,6 +232,7 @@ public void jump_loc(POSITION pos, int sline)
* Normalize sline.
*/
pos = after_header_pos(pos);
pos = next_unfiltered(pos);
sindex = sindex_from_sline(sline);
if ((nline = onscreen(pos)) >= 0)
@@ -242,9 +243,9 @@ public void jump_loc(POSITION pos, int sline)
*/
nline -= sindex;
if (nline > 0)
forw(nline, position(BOTTOM_PLUS_ONE), 1, 0, 0);
forw(nline, position(BOTTOM_PLUS_ONE), TRUE, FALSE, FALSE, 0);
else
back(-nline, position(TOP), 1, 0);
back(-nline, position(TOP), TRUE, FALSE, FALSE);
#if HILITE_SEARCH
if (show_attn)
repaint_hilite(TRUE);
@@ -285,14 +286,14 @@ public void jump_loc(POSITION pos, int sline)
* close enough to the current screen
* that we can just scroll there after all.
*/
forw(sc_height-sindex+nline-1, bpos, 1, 0, 0);
forw(sc_height-sindex+nline-1, bpos, TRUE, FALSE, FALSE, 0);
#if HILITE_SEARCH
if (show_attn)
repaint_hilite(TRUE);
#endif
return;
}
pos = back_line(pos);
pos = back_line(pos, NULL);
if (pos == NULL_POSITION)
{
/*
@@ -307,7 +308,7 @@ public void jump_loc(POSITION pos, int sline)
lastmark();
squished = FALSE;
screen_trashed_num(0);
forw(sc_height-1, pos, 1, 0, sindex-nline);
forw(sc_height-1, pos, TRUE, FALSE, FALSE, sindex-nline);
} else
{
/*
@@ -318,7 +319,8 @@ public void jump_loc(POSITION pos, int sline)
*/
for (nline = sindex; nline < sc_height - 1; nline++)
{
pos = forw_line(pos);
POSITION linepos;
pos = forw_line(pos, &linepos, NULL);
if (pos == NULL_POSITION)
{
/*
@@ -328,17 +330,14 @@ public void jump_loc(POSITION pos, int sline)
*/
break;
}
#if HILITE_SEARCH
pos = next_unfiltered(pos);
#endif
if (pos >= tpos)
if (linepos >= tpos)
{
/*
* Surprise! The desired line is
* close enough to the current screen
* that we can just scroll there after all.
*/
back(nline+1, tpos, 1, 0);
back(nline, tpos, TRUE, FALSE, FALSE);
#if HILITE_SEARCH
if (show_attn)
repaint_hilite(TRUE);
@@ -353,6 +352,6 @@ public void jump_loc(POSITION pos, int sline)
home();
screen_trashed_num(0);
add_back_pos(pos);
back(sc_height-1, pos, 1, 0);
back(sc_height-1, pos, TRUE, FALSE, FALSE);
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
+22 -19
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -7,8 +7,6 @@
* For more information, see the README file.
*/
#define NEWBOT 1
/*
* Standard include file for "less".
*/
@@ -169,7 +167,7 @@ void free();
#define IS_DIGIT(c) ((c) >= '0' && (c) <= '9')
#endif
#define IS_CSI_START(c) (((LWCHAR)(c)) == ESC || (((LWCHAR)(c)) == CSI))
#define IS_CSI_START(c) (control_char(c) && (((LWCHAR)(c)) == ESC || (((LWCHAR)(c)) == CSI)))
#define OPT_OFF 0
#define OPT_ON 1
@@ -290,15 +288,6 @@ typedef off_t LINENUM;
#endif
#endif
/*
* Does the shell treat "?" as a metacharacter?
*/
#if MSDOS_COMPILER || OS2 || _OSK
#define SHELL_META_QUEST 0
#else
#define SHELL_META_QUEST 1
#endif
#define SPACES_IN_FILENAMES 1
/*
@@ -364,6 +353,14 @@ typedef short POLL_EVENTS;
#define NUM_FRAC_DENOM 1000000
#define NUM_LOG_FRAC_DENOM 6
/*
* Max expected reasonable duration of a paste.
* Increasing this value avoids accidentally reenabling unwanted paste input
* in the middle of a very long paste but risks apparently frozen UI if the
* end bracket is missing.
*/
#define MAX_PASTE_IGNORE_SEC 5
/* How quiet should we be? */
#define NOT_QUIET 0 /* Ring bell at eof and for errors */
#define LITTLE_QUIET 1 /* Ring bell only for errors */
@@ -404,12 +401,16 @@ typedef short POLL_EVENTS;
(((t) & ~SRCH_BACK) | SRCH_FORW))
/* Parsing position in an OSC8 link: "\e]8;PARAMS;URI\e\\" (final "\e\\" may be "\7") */
typedef enum osc8_state {
OSC_START, /* Waiting for initial \e */
OSC_INTRO, /* Waiting for intro char, usually ']' */
OSC_TYPENUM, /* Reading OS command type */
OSC_STRING, /* Reading OS command string */
OSC_END_CSI, /* Waiting for backslash after the final ESC. */
OSC_END, /* At end */
OSC8_PARAMS, /* In the OSC8 parameters */
OSC8_URI, /* In the OSC8 URI */
OSC8_NOT, /* This is not an OSC8 link */
OSC8_PREFIX, /* In the "\e]8;" */
OSC8_PARAMS, /* In the parameters */
OSC8_URI, /* In the URI */
OSC8_ST_ESC, /* After the final \e */
OSC8_END, /* At end */
} osc8_state;
/* */
@@ -422,7 +423,8 @@ typedef enum osc8_state {
#define CC_ERROR 2 /* Char could not be accepted due to error */
#define CC_PASS 3 /* Char was rejected (internal) */
#define CF_QUIT_ON_ERASE 0001 /* Abort cmd if its entirely erased */
#define CF_QUIT_ON_ERASE (1<<0) /* Abort cmd if its entirely erased */
#define CF_OPTION (1<<1) /* A_OPT_TOGGLE */
/* Special char bit-flags used to tell put_line() to do something special */
#define AT_NORMAL (0)
@@ -625,6 +627,7 @@ typedef enum {
#define X11MOUSE_BUTTON2 1 /* Middle button press */
#define X11MOUSE_BUTTON3 2 /* Right button press */
#define X11MOUSE_BUTTON_REL 3 /* Button release */
#define X11MOUSE_DRAG 0x20 /* Drag with button down */
#define X11MOUSE_WHEEL_UP 0x40 /* Wheel scroll up */
#define X11MOUSE_WHEEL_DOWN 0x41 /* Wheel scroll down */
#define X11MOUSE_OFFSET 0x20 /* Added to button & pos bytes to create a char */
+10
View File
@@ -13,11 +13,14 @@
e ^E j ^N CR * Forward one line (or _N lines).
y ^Y k ^K ^P * Backward one line (or _N lines).
ESC-j * Forward one file line (or _N file lines).
ESC-k * Backward one file line (or _N file lines).
f ^F ^V SPACE * Forward one window (or _N lines).
b ^B ESC-v * Backward one window (or _N lines).
z * Forward one window (and set window to _N).
w * Backward one window (and set window to _N).
ESC-SPACE * Forward one window, but don't stop at end-of-file.
ESC-b * Backward one window, but don't stop at beginning-of-file.
d ^D * Forward one half-window (and set half-window to _N).
u ^U * Backward one half-window (and set half-window to _N).
ESC-) RightArrow * Right one half screen width (or _N positions).
@@ -48,6 +51,7 @@
ESC-U Clear search highlighting.
&_p_a_t_t_e_r_n * Display only matching lines.
---------------------------------------------------
Search is case-sensitive unless changed with -i or -I.
A search pattern may begin with one or more of:
^N or ! Search for NON-matching lines.
^E or * Search multiple files (pass thru END OF FILE).
@@ -221,6 +225,8 @@
Automatically determine the size of the input file.
--follow-name
The F command changes files if the input file is renamed.
--form-feed
Stop scrolling when a form feed character is reached.
--header=[_L[,_C[,_N]]]
Use _L lines (starting at line _N) and _C columns as headers.
--incsearch
@@ -239,12 +245,16 @@
Read _N lines from the input file and look for vim modelines.
--mouse
Enable mouse input.
--no-edit-warn
Don't warn when using v command on a file opened via LESSOPEN.
--no-keypad
Don't send termcap keypad init/deinit strings.
--no-histdups
Remove duplicates from command history.
--no-number-headers
Don't give line numbers to header lines.
--no-paste
Ignore pasted input.
--no-search-header-lines
Searches do not include header lines.
--no-search-header-columns
+144 -68
View File
@@ -1,5 +1,5 @@
'\" t
.TH LESS 1 "Version 668: 06 Oct 2024"
.TH LESS 1 "Version 678: 01 May 2025"
.SH NAME
less \- display the contents of a file in a terminal
.SH SYNOPSIS
@@ -38,7 +38,7 @@ so it can run on a variety of terminals.
There is even limited support for hardcopy terminals.
(On a hardcopy terminal, lines which should be printed at the top
of the screen are prefixed with a caret.)
.PP
.SH COMMANDS
Commands are based on both
.B more
and
@@ -46,8 +46,7 @@ and
Commands may be preceded by a decimal number,
called N in the descriptions below.
The number is used by some commands, as indicated.
.
.SH COMMANDS
.PP
In the following descriptions, \(haX means control-X.
ESC stands for the ESCAPE key; for example ESC-v means the
two character sequence "ESCAPE", then "v".
@@ -60,9 +59,6 @@ If N is more than the screen size, only the final screenful is displayed.
Warning: some systems use \(haV as a special literalization character.
.IP "z"
Like SPACE, but if N is specified, it becomes the new window size.
.IP "ESC-SPACE"
Like SPACE, but scrolls a full screenful, even if it reaches
end-of-file in the process.
.IP "ENTER or RETURN or \(haN or e or \(haE or j or \(haJ"
Scroll forward N lines, default 1.
The entire N lines are displayed, even if N is more than the screen size.
@@ -87,6 +83,17 @@ subsequent d and u commands.
Like j, but continues to scroll beyond the end of the file.
.IP "K or Y"
Like k, but continues to scroll beyond the beginning of the file.
.IP "ESC-SPACE"
Like SPACE, but scrolls a full screenful,
even if it reaches the end of the file.
.IP "ESC-b"
Like b, but scrolls a full screenful,
even if it reaches the beginning of the file.
.IP "ESC-j"
Scroll forward N file lines, default 1.
A file line is a complete line in the file, terminated by a newline.
.IP "ESC-k"
Scroll backwards N file lines, default 1.
.IP "ESC-) or RIGHTARROW"
Scroll horizontally right N characters, default half the screen width
(see the \-# option).
@@ -239,6 +246,9 @@ that is, do a simple textual comparison.
Followed by a digit N between 1 and 5.
Only text which has a non-empty match for the N-th parenthesized SUB-PATTERN
will be considered to match the pattern.
For example, searching for "(abc)|(def)" modified with \(haS1
would search for instances of "abc", but would highlight
instances of both "abc" and "def".
(Supported only if
.B less
is built with one of the regular expression libraries
@@ -285,6 +295,8 @@ WRAP around the current file.
That is, if the search reaches the beginning of the current file
without finding a match, the search continues from the last line of the
current file up to the line where it started.
.IP "\(haL"
As in forward searches.
.RE
.IP "ESC-/pattern"
Same as "/*".
@@ -298,6 +310,8 @@ If the previous search was modified by \(haE, the search continues
in the next (or previous) file if not satisfied in the current file.
If the previous search was modified by \(haR, the search is done
without using regular expressions.
If the previous search was modified by \(haW, the search wraps at
the end (or beginning) of the file.
There is no effect if the previous search was modified by \(haF or \(haK.
.IP N
Repeat previous search, but in the reverse direction.
@@ -404,7 +418,9 @@ the current setting is printed and nothing is changed.
.IP \-\-
Like the \- command, but takes a long option name (see OPTIONS below)
rather than a single option letter.
You must press ENTER or RETURN after typing the option name.
Press ENTER or RETURN after typing the option name to change it.
You can enter just the beginning of an option name,
then press TAB to find all option names which begin with that string.
A \(haP immediately after the second dash suppresses printing of a
message describing the new setting, as in the \- command.
.IP \-+
@@ -465,7 +481,7 @@ A percent sign (%) in the command is replaced by the name of the
current file.
A pound sign (#) is replaced by the name of the previously examined file.
"!!" repeats the last shell command.
"!" with no shell command simply invokes a shell.
"!" with no shell command invokes an interactive shell.
If a \(haP (CONTROL-P) is entered immediately after the !,
no "done" message is printed after the shell command is executed.
On Unix systems, the shell is taken from the environment variable SHELL,
@@ -582,8 +598,8 @@ either a dash followed by a single letter,
or two dashes followed by a long option name.
A long option name may be abbreviated as long as
the abbreviation is unambiguous.
For example, \-\-quit-at-eof may be abbreviated \-\-quit, but not
\-\-qui, since both \-\-quit-at-eof and \-\-quiet begin with \-\-qui.
For example, \-\-mouse may be abbreviated \-\-mou, but not
\-\-mo, since both \-\-mouse and \-\-modelines begin with \-\-mo.
Some long option names are in uppercase, such as \-\-QUIT-AT-EOF, as
distinct from \-\-quit-at-eof.
Such option names need only have their first letter capitalized;
@@ -784,9 +800,8 @@ 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
.nh
https://en.wikipedia.org/wiki/ANSI_escape_code#SGR).
.hy
.UR https://en.wikipedia.org/wiki/ANSI_escape_code#SGR
.UE ).
If either integer is a "-" or is omitted,
the corresponding color is set to that of normal text.
.PP
@@ -820,9 +835,8 @@ CHAR_INFO.Attributes
.hy
value, between 0 and 15 inclusive
(see
.nh
https://learn.microsoft.com/en-us/windows/console/char-info-str).
.hy
.UR https://learn.microsoft.com/en-us/windows/console/char-info-str
.UE ).
To avoid confusion, it is recommended that the equivalent letters rather than numbers
be used after a lowercase color selector on MS-DOS/Windows.
@@ -867,6 +881,7 @@ Causes
.B less
to automatically exit
if the entire file can be displayed on the first screen.
Also see the description of the LESS_SHELL_LINES environment variable below.
.IP "\-g or \-\-hilite-search"
Normally,
.B less
@@ -913,8 +928,6 @@ is recalculated if the terminal window is resized.
If the \-\-header option is used and the target line specified by \-j
would be obscured by the header, the target line is moved to the first
line after the header.
While the \-\-header option is active, the \-S option is ignored,
and lines longer than the screen width are truncated.
.RS
.PP
If any form of the \-j option is used,
@@ -947,7 +960,7 @@ and there are matches beyond both sides of the screen.
There are matches in the visible part of the line
but none to the right or left of it.
.IP "a-z, A-Z"
The line has been marked with the corresponding letter via the m command.
The line has been marked with the corresponding letter via the m or M command.
.RE
.IP "\-k\fIfilename\fP or \-\-lesskey-file=\fIfilename\fP"
Causes
@@ -970,26 +983,25 @@ to open and interpret the named file as a
source file.
If the LESSKEYIN or LESSKEYIN_SYSTEM environment variable is set, or
if a lesskey source file is found in a standard place (see KEY BINDINGS),
it is also used as a
.I "lesskey source"
file.
it is also used as a lesskey source file.
Prior to version 582, the
.B lesskey
program needed to be run to convert a
.I "lesskey source"
file to a
.I "lesskey binary"
program needed to be run to convert a lesskey
.I source
file to a lesskey
.I binary
file for
.B less
to use.
Newer versions of
.B less
read the
.I "lesskey source"
read the lesskey source
file directly and ignore the binary file if the source file exists.
Note the warning under "\-\-lesskey-content" below.
.IP "\-\-lesskey-content=\fItext\fP"
Causes less to interpret the specified text as the contents of a
Causes
.B less
to interpret the specified text as the contents of a
.BR lesskey (1)
source file.
In the text,
@@ -1043,7 +1055,6 @@ Suppresses line numbers.
The default (to use line numbers) may cause
.B less
to run more slowly in some cases, especially with a very large input file.
Suppressing line numbers with the \-n option will avoid this problem.
Using line numbers means: the line number will be displayed in the verbose
prompt and in the = command,
and the v command will pass the current line number to the editor
@@ -1124,32 +1135,38 @@ each type of control character).
Thus, various display problems may result,
such as long lines being split in the wrong place.
.sp
USE OF THE \-r OPTION IS NOT RECOMMENDED.
USE OF THE \-r OPTION IS DANGEROUS AND IS NOT RECOMMENDED.
.br
The \-r option can be set on the command line or via the \- command,
but to avoid unintentional use, it cannot be set in a LESS environment variable.
If \-r appears in a LESS environment variable, it is treated as if it were \-R.
.IP "\-R or \-\-RAW-CONTROL-CHARS"
Like \-r, but only ANSI "color" escape sequences and OSC 8 hyperlink
Like \-r, but only a limited set of escape
sequences are output in "raw" form.
Unlike \-r, the screen appearance is maintained correctly,
provided that there are no escape sequences in the file
other than these types of escape sequences.
Color escape sequences are only supported when the color
is changed within one line, not across lines.
In other words, the beginning of each line is assumed to be
normal (non-colored), regardless of any escape sequences in previous lines.
For the purpose of keeping track of screen appearance,
these escape sequences are assumed to not move the cursor.
Unlike \-r, the screen appearance is maintained correctly.
The sequences which are output raw are:
.sp
OSC 8 hyperlinks are sequences of the form:
1. ANSI SGR ("color") sequences
.sp
ESC ] 8 ; \&...\& \\7
2. OSC 8 hyperlinks
.sp
The terminating sequence may be either a BEL character (\\7)
or the two-character sequence "ESC \\".
3. Other OSC sequences, if the OSC type number is listed in
the LESSANSIOSCALLOW environment variable
.sp
4. OSC sequences starting with a non-standard introductory character
(that is, something other than "]"), if the character is listed in
the LESSANSIOSCCHARS environment variable followed by an asterisk
.sp
ANSI color escape sequences are sequences of the form:
.sp
ESC [ \&...\& m
.sp
where the "...\&" is zero or more color specification characters.
Color escape sequences are only supported when the color
is changed within one line, not across lines.
In other words, the beginning of each line is assumed to be
normal (non-colored), regardless of any escape sequences in previous lines.
.sp
You can make
.B less
think that characters other than "m" can end ANSI color escape sequences
@@ -1160,10 +1177,18 @@ And you can make
think that characters other than the standard ones may appear between
the ESC and the m by setting the environment variable LESSANSIMIDCHARS
to the list of characters which can appear.
.sp
OSC sequences are of the form:
.sp
ESC ] N ; \&...\& \\7
.sp
where the OSC type number N is a decimal integer.
The terminating sequence may be either a BEL character (\\7)
as above, or the two-character sequence "ESC \\".
.IP "\-s or \-\-squeeze-blank-lines"
Causes consecutive blank lines to be squeezed into a single blank line.
This is useful when viewing
.B nroff
.BR nroff (1)
output.
.IP "\-S or \-\-chop-long-lines"
Causes lines longer than the screen width to be
@@ -1173,6 +1198,8 @@ the screen width is not displayed until you press RIGHT-ARROW.
The default is to wrap long lines; that is, display the remainder
on the next line.
See also the \-\-wordwrap option.
While the \-\-header option is active, the \-S option is ignored,
and lines longer than the screen width are truncated.
.IP "\-t\fItag\fP or \-\-tag=\fItag\fP"
The \-t option, followed immediately by a TAG,
will edit the file containing that tag.
@@ -1186,9 +1213,8 @@ the name of a command compatible with
.BR global (1),
and that command is executed to find the tag.
(See
.nh
http://www.gnu.org/software/global/global.html).
.hy
.UR http://www.gnu.org/software/global/global.html
.UE ).
The \-t option may also be specified from within
.B less
(using the \- command) as a way of examining a new file.
@@ -1328,6 +1354,10 @@ If the reopen succeeds and the file is a different file from the original
with the same name as the original (now renamed) file),
.B less
will display the contents of that new file.
.IP "\-\-form-feed"
When scrolling forward or backward in the file,
stop if a line beginning with a form feed character (\(haL) is reached.
This can be useful when viewing a file which uses form feeds between pages.
.IP "\-\-header=\fIL\fP,\fIC\fP,\fIN\fP"
.RS
Sets the number of header lines and columns displayed on the screen.
@@ -1353,6 +1383,10 @@ When header lines are displayed, any file contents before the header line cannot
When \fIC\fP is nonzero, the first \fIC\fP characters displayed at the
beginning of each line are replaced with the first \fIC\fP characters of the line,
even if the rest of the line is scrolled horizontally.
.PP
While the \-\-header option is active,
lines longer than the screen width are truncated,
and the \-S option is ignored.
.RE
.IP "\-\-incsearch"
Subsequent search commands will be "incremental"; that is,
@@ -1418,6 +1452,7 @@ scrolling the mouse wheel down moves forward in the file,
scrolling the mouse wheel up moves backwards in the file,
left-click sets the "#" mark to the line where the mouse is clicked,
and right-click (or any other) returns to the "#" mark position.
Holding down the left button and dragging also moves in the file.
If a left-click is performed with the mouse cursor on an OSC 8 hyperlink,
the hyperlink is selected as if by the \(haO\(haN command.
If a left-click is performed with the mouse cursor on an OSC 8 hyperlink
@@ -1430,6 +1465,10 @@ and on the Windows version of
.IP "\-\-MOUSE"
Like \-\-mouse, except the direction scrolled
on mouse wheel movement is reversed.
.IP "\-\-no-edit-warn"
Don't print a warning message when using the v command
on a file which was opened using a LESSOPEN preprocessor
(see the INPUT PREPROCESSOR section below).
.IP "\-\-no-keypad"
Disables sending the keypad initialization and deinitialization strings
to the terminal.
@@ -1444,6 +1483,14 @@ Normally, a string may appear multiple times.
.IP "\-\-no-number-headers"
Header lines (defined via the \-\-header option) are not assigned line numbers.
Line number 1 is assigned to the first line after any header lines.
.IP "\-\-no-paste"
If the terminal supports xterm-compatible "bracketed paste",
any text pasted into
.B less
is ignored, except that one line of text may be pasted into the command line
at the bottom of the screen (search strings, file names, etc).
That is, the first newline of text pasted into the command line
and any text that follows it is ignored.
.IP "\-\-no-search-header-lines"
Searches do not include header lines, but still include header columns.
.IP "\-\-no-search-header-columns"
@@ -1479,7 +1526,7 @@ If set, tabs are handled as if the \-U option were not set.
That is, tabs are expanded to spaces.
This option overrides the \-U option, so that display of
tabs can be controlled separate from that of backspaces and carriage returns.
If not set, tab display is controlled by the \-U options.
If not set, tab display is controlled by the \-U option.
.IP "\-\-PROC-TAB"
If set, tabs are handled as if the \-U option were set;
that is tabs are treated as control characters.
@@ -1536,9 +1583,8 @@ 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
.nh
https://www.ecma-international.org/publications-and-standards/standards/ecma-48).
.hy
.UR https://www.ecma-international.org/publications-and-standards/standards/ecma-48
.UE ).
.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.
@@ -1576,7 +1622,7 @@ certain keys can be used to manipulate the command line.
Most commands have an alternate form in [ brackets ] which can be used if
a key does not exist on a particular keyboard.
(Note that the forms beginning with ESC do not work
in some MS-DOS and Windows systems because ESC is the line erase character.)
on some MS-DOS and Windows systems because ESC is the line erase character.)
Any of these special keys may be entered literally by preceding
it with the "literal" character, either \(haV or \(haA.
A backslash itself may also be entered literally by entering two backslashes.
@@ -1630,7 +1676,7 @@ If it matches more than one filename, all matches are entered into
the command line (if they fit).
.IP "\(haU (Unix and OS/2) or ESC (MS-DOS and Windows)"
Delete the entire command line,
or cancel the command if the command line is empty.
or cancel the command if the cursor is at the beginning of the command line.
If you have changed your line-kill character in Unix to something
other than \(haU, that character is used instead of \(haU.
.IP "\(haG"
@@ -1689,7 +1735,7 @@ that directory is where the sysless file is found.)
On MS-DOS and Windows systems, the system-wide lesskey file is c:\e_syslesskey.
On OS/2 systems, the system-wide lesskey file is c:\esyslesskey.ini.
.PP
Previous versions of
Older versions of
.B less
(before v582) used lesskey files with a binary format, produced by the
.B lesskey
@@ -1702,7 +1748,7 @@ You may define an "input preprocessor" for
.BR less .
Before
.B less
opens a file, it first gives your input preprocessor a chance to modify the
opens a file, it first gives the input preprocessor a chance to modify the
way the contents of the file are displayed.
An input preprocessor is simply an executable program (or shell script),
which writes the contents of the file to a different file,
@@ -2263,7 +2309,7 @@ the shell and pshell commands (! and #)
.IP "stop"
stopping
.B less
via a SIGSTOP signal
via a SIGTSTP signal
.IP "tags"
use of tags files (-t)
.PP
@@ -2287,7 +2333,8 @@ In that case, the LESSSECURE and LESSSECURE_ALLOW variables are ignored.
.
.SH "COMPATIBILITY WITH MORE"
If the environment variable LESS_IS_MORE is set to 1,
or if the program is invoked via a file link named "more",
or if the program is invoked via a file link named "more"
and the environment variable LESS_IS_MORE is not set to 0,
.B less
behaves (mostly) in conformance with the POSIX
.BR more (1)
@@ -2357,7 +2404,22 @@ Characters which may end an ANSI color escape sequence
.IP LESSANSIMIDCHARS
Characters which may appear between the ESC character and the
end character in an ANSI color escape sequence
(default "0123456789:;[?!"\(aq#%()*+\ ".
(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.
.IP LESSANSIOSCCHARS
Characters which may follow an ESC character to mark the start
of an "OS Command" sequence.
All characters that follow this character up to a
String Terminator (ESC-backslash or BEL)
are considered to be part of the OSC sequence
(default "]").
If a character in LESSANSIOSCCHARS is followed by an asterisk,
sequences that begin with that character in the file contents
are passed through to the terminal;
otherwise only sequences that appear in a prompt string are passed through.
.IP LESSBINFMT
Format for displaying non-printable, non-control characters.
.IP LESSCHARDEF
@@ -2469,6 +2531,22 @@ sets an OSC 8 handler for opening OSC 8 links containing a URI with that scheme.
.IP LESS_OSC8_ANY
Sets an OSC 8 handler for opening OSC 8 links for which there is
no specific LESS_OSC8_xxx handler set for the "xxx" scheme.
.IP LESS_SHELL_LINES
When the \-F option is set,
.B less
exits automatically if the number of screen lines used to display the file
is less than or equal to the screen height minus the value of
the LESS_SHELL_LINES variable.
Thus, if you use a shell prompt which occupies more than one screen line,
this variable can be set to the number of lines used by your prompt,
to ensure that the entire file can be seen when \-F is used.
If not set, LESS_SHELL_LINES is assumed to be 1.
.IP LESS_SIGUSR1
If set to a string of one or more
.B less
command characters, those commands will be executed when
.B less
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.
@@ -2515,7 +2593,7 @@ Possible location of the history file; see the description of the LESSHISTFILE e
.BR lessecho (1)
.
.SH COPYRIGHT
Copyright (C) 1984-2024 Mark Nudelman
Copyright (C) 1984-2025 Mark Nudelman
.PP
less is part of the GNU project and is free software.
You can redistribute it and/or modify it
@@ -2541,12 +2619,10 @@ See the GNU General Public License for more details.
Mark Nudelman
.br
Report bugs at
.nh
https://github.com/gwsw/less/issues.
.hy
.UR https://github.com/gwsw/less/issues
.UE .
.br
For more information, see the less homepage at
.br
.nh
https://greenwoodsoftware.com/less.
.hy
.UR https://greenwoodsoftware.com/less
.UE .
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
+4 -2
View File
@@ -1,4 +1,4 @@
.TH LESSECHO 1 "Version 668: 06 Oct 2024"
.TH LESSECHO 1 "Version 678: 01 May 2025"
.SH NAME
lessecho \- expand metacharacters
.SH SYNOPSIS
@@ -53,4 +53,6 @@ The default is that only arguments containing metacharacters are quoted.
This manual page was written by Thomas Schoepf <[email protected]>,
for the Debian GNU/Linux system (but may be used by others).
.PP
Report bugs at https://github.com/gwsw/less/issues.
Report bugs at
.UR https://github.com/gwsw/less/issues
.UE .
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
+17 -6
View File
@@ -1,5 +1,5 @@
'\" t
.TH LESSKEY 1 "Version 668: 06 Oct 2024"
.TH LESSKEY 1 "Version 678: 01 May 2025"
.SH NAME
lesskey \- customize key bindings for less
.SH "SYNOPSIS (deprecated)"
@@ -48,7 +48,8 @@ Customizes line-editing key bindings.
.IP #env
Defines environment variables.
.PP
Blank lines and lines which start with a hash mark (#) are ignored,
Blank lines are ignored.
Any text that follows an unescaped hash mark (#) in a line is ignored,
except as noted below.
.
.SH "COMMAND SECTION"
@@ -60,12 +61,13 @@ If the command section is the first section in the file,
this line may be omitted.
The command section consists of lines of the form:
.sp
\fIstring\fP <whitespace> \fIaction\fP [extra-string] <newline>
\fIstring\fP <whitespace> \fIaction\fP <whitespace> [extra-string] <newline>
.sp
Whitespace is any sequence of one or more spaces and/or tabs.
The \fIstring\fP is the command key(s) which invoke the action.
The \fIstring\fP may be a single command key, or a sequence of up to 15 keys.
The \fIaction\fP is the name of the less action, from the list below.
The \fIaction\fP is the name of the less action,
from the lists in the EXAMPLE sections below.
The characters in the \fIstring\fP may appear literally, or be
prefixed by a caret to indicate a control key.
A backslash followed by one to three octal digits may be used to
@@ -152,6 +154,8 @@ y back-line
J forw-line-force
K back-line-force
Y back-line-force
\eej forw-newline
\eek back-newline
d forw-scroll
^D forw-scroll
u back-scroll
@@ -168,6 +172,7 @@ b back-screen
z forw-window
w back-window
\ee\e40 forw-screen-force
\eeb back-screen-force
F forw-forever
\eeF forw-until-hilite
R repaint-flush
@@ -244,6 +249,8 @@ v visual
! shell
# pshell
+ firstcmd
\ee[M mouse
\ee[< mouse6
H help
h help
V version
@@ -339,6 +346,8 @@ l l.
\eku up
\eej down
^G abort
\ee[M mouse
\ee[< mouse6
.TE
.RE
.sp
@@ -452,7 +461,7 @@ which start with a NUL character (0).
This NUL character should be represented as \e340 in a lesskey file.
.
.SH COPYRIGHT
Copyright (C) 1984-2024 Mark Nudelman
Copyright (C) 1984-2025 Mark Nudelman
.PP
less is part of the GNU project and is free software.
You can redistribute it and/or modify it
@@ -477,4 +486,6 @@ See the GNU General Public License for more details.
.
Mark Nudelman
.br
Report bugs at https://github.com/gwsw/less/issues.
Report bugs at
.UR https://github.com/gwsw/less/issues
.UE .
+8 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -34,7 +34,9 @@ static constant struct lesskey_cmdname cmdnames[] =
{ "back-bracket", A_B_BRACKET },
{ "back-line", A_B_LINE },
{ "back-line-force", A_BF_LINE },
{ "back-newline", A_B_NEWLINE },
{ "back-screen", A_B_SCREEN },
{ "back-screen-force", A_BF_SCREEN },
{ "back-scroll", A_B_SCROLL },
{ "back-search", A_B_SEARCH },
{ "back-window", A_B_WINDOW },
@@ -55,6 +57,7 @@ static constant struct lesskey_cmdname cmdnames[] =
{ "forw-forever", A_F_FOREVER },
{ "forw-line", A_F_LINE },
{ "forw-line-force", A_FF_LINE },
{ "forw-newline", A_F_NEWLINE },
{ "forw-screen", A_F_SCREEN },
{ "forw-screen-force", A_FF_SCREEN },
{ "forw-scroll", A_F_SCROLL },
@@ -69,6 +72,8 @@ static constant struct lesskey_cmdname cmdnames[] =
{ "index-file", A_INDEX_FILE },
{ "invalid", A_UINVALID },
{ "left-scroll", A_LSHIFT },
{ "mouse", A_X11MOUSE_IN },
{ "mouse6", A_X116MOUSE_IN },
{ "next-file", A_NEXT_FILE },
{ "next-tag", A_NEXT_TAG },
{ "no-scroll", A_LLSHIFT },
@@ -118,6 +123,8 @@ static constant struct lesskey_cmdname editnames[] =
{ "abort", EC_ABORT },
{ "left", EC_LEFT },
{ "literal", EC_LITERAL },
{ "mouse", EC_X11MOUSE },
{ "mouse6", EC_X116MOUSE },
{ "right", EC_RIGHT },
{ "up", EC_UP },
{ "word-backspace", EC_W_BACKSPACE },
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
+215 -64
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -50,10 +50,11 @@ static struct xbuffer last_ansi;
static struct xbuffer last_ansis[NUM_LAST_ANSIS];
static int curr_last_ansi;
public size_t size_linebuf = 0; /* Size of line buffer (and attr buffer) */
static size_t size_linebuf = 0; /* Size of line buffer (and attr buffer) */
static struct ansi_state *line_ansi = NULL;
static lbool ansi_in_line;
static int hlink_in_line;
static int ff_starts_line;
static lbool hlink_in_line;
static int line_mark_attr;
static int cshift; /* Current left-shift of output line buffer */
public int hshift; /* Desired left-shift of output line buffer */
@@ -73,7 +74,11 @@ static LWCHAR pendc;
static POSITION pendpos;
static constant char *end_ansi_chars;
static constant char *mid_ansi_chars;
static int in_hilite;
static constant char *osc_ansi_chars;
static int osc_ansi_allow_count;
static long *osc_ansi_allow;
static lbool in_hilite;
static lbool clear_after_line;
static int attr_swidth(int a);
static int attr_ewidth(int a);
@@ -137,8 +142,9 @@ static struct color_map color_map[] = {
/* State while processing an ANSI escape sequence */
struct ansi_state {
int oindex; /* Index into OSC8 prefix */
osc8_state ostate; /* State while processing OSC8 sequence */
unsigned int otype; /* OSC type number */
unsigned int escs_in_seq;
};
/*
@@ -147,6 +153,7 @@ struct ansi_state {
public void init_line(void)
{
int ax;
constant char *s;
end_ansi_chars = lgetenv("LESSANSIENDCHARS");
if (isnullenv(end_ansi_chars))
@@ -156,6 +163,32 @@ public void init_line(void)
if (isnullenv(mid_ansi_chars))
mid_ansi_chars = "0123456789:;[?!\"'#%()*+ ";
osc_ansi_chars = lgetenv("LESSANSIOSCCHARS");
if (isnullenv(osc_ansi_chars))
osc_ansi_chars = "";
osc_ansi_allow_count = 0;
s = lgetenv("LESSANSIOSCALLOW");
if (!isnullenv(s))
{
struct xbuffer xbuf;
xbuf_init(&xbuf);
for (;;)
{
long num;
s = skipspc(s);
if (*s == '\0')
break;
num = lstrtoulc(s, &s, 10);
s = skipspc(s);
if (*s == ',')
++s;
xbuf_add_data(&xbuf, (constant void *) &num, sizeof(num));
++osc_ansi_allow_count;
}
osc_ansi_allow = (long *) xbuf.data;
}
linebuf.buf = (char *) ecalloc(LINEBUF_SIZE, sizeof(char));
linebuf.attr = (int *) ecalloc(LINEBUF_SIZE, sizeof(int));
size_linebuf = LINEBUF_SIZE;
@@ -245,9 +278,11 @@ public void prewind(void)
mbc_buf_len = 0;
is_null_line = FALSE;
pendc = '\0';
in_hilite = 0;
in_hilite = FALSE;
ansi_in_line = FALSE;
hlink_in_line = 0;
ff_starts_line = -1;
hlink_in_line = FALSE;
clear_after_line = FALSE;
line_mark_attr = 0;
line_pos = NULL_POSITION;
xbuf_reset(&shifted_ansi);
@@ -568,7 +603,7 @@ public lbool is_ansi_end(LWCHAR ch)
{
if (!is_ascii_char(ch))
return (FALSE);
return (strchr(end_ansi_chars, (char) ch) != NULL);
return (ch != 0 && strchr(end_ansi_chars, (char) ch) != NULL);
}
/*
@@ -580,19 +615,19 @@ public lbool is_ansi_middle(LWCHAR ch)
return (FALSE);
if (is_ansi_end(ch))
return (FALSE);
return (strchr(mid_ansi_chars, (char) ch) != NULL);
return (ch != 0 && strchr(mid_ansi_chars, (char) ch) != NULL);
}
/*
* Skip past an ANSI escape sequence.
* pp is initially positioned just after the CSI_START char.
*/
public void skip_ansi(struct ansi_state *pansi, constant char **pp, constant char *limit)
public void skip_ansi(struct ansi_state *pansi, LWCHAR ch, constant char **pp, constant char *limit)
{
LWCHAR c;
ansi_step(pansi, ch);
do {
c = step_charc(pp, +1, limit);
} while (*pp < limit && ansi_step(pansi, c) == ANSI_MID);
ch = step_charc(pp, +1, limit);
} while (*pp < limit && ansi_step(pansi, ch) == ANSI_MID);
/* Note that we discard final char, for which is_ansi_end is true. */
}
@@ -607,56 +642,121 @@ public struct ansi_state * ansi_start(LWCHAR ch)
if (!IS_CSI_START(ch))
return NULL;
pansi = ecalloc(1, sizeof(struct ansi_state));
pansi->oindex = 0;
pansi->ostate = OSC8_PREFIX;
pansi->ostate = OSC_START;
pansi->otype = 0;
pansi->escs_in_seq = 0;
return pansi;
}
/*
* Is a character a valid intro char for an OSC sequence?
* An intro char is the one immediately after the ESC, usually ']'.
*/
static lbool valid_osc_intro(char ch, lbool content)
{
constant char *p = strchr(osc_ansi_chars, ch);
if (p == NULL)
return FALSE;
return (!content || p[1] == '*');
}
/*
* Is a given number a valid OSC type?
*/
static lbool valid_osc_type(int otype, lbool content)
{
int i;
if (!content)
return TRUE;
if (otype == 8)
return TRUE;
for (i = 0; i < osc_ansi_allow_count; i++)
if (osc_ansi_allow[i] == otype)
return TRUE;
return FALSE;
}
/*
* Helper function for ansi_step.
*/
static ansi_state osc_return(struct ansi_state *pansi, osc8_state ostate, ansi_state astate)
{
pansi->ostate = ostate;
return astate;
}
/*
* Determine whether the next char in an ANSI escape sequence
* ends the sequence.
*/
public ansi_state ansi_step(struct ansi_state *pansi, LWCHAR ch)
static ansi_state ansi_step2(struct ansi_state *pansi, LWCHAR ch, lbool content)
{
static constant char osc8_prefix[] = ESCS "]8;";
/*
* Pass thru OS commands. Assume OSC commands do not move the cursor.
* A "typed" OSC starts with ESC ] <integer> <semicolon>, followed by an
* arbitrary string, and ends with a String Terminator (ESC-backslash or BEL).
* An untyped OSC starts with ESC ] or ESC x where x is in osc_ansi_chars,
* and ends with ST.
* The only typed OSC we actually parse is OSC 8.
*/
switch (pansi->ostate)
{
case OSC8_PREFIX:
if (ch != (LWCHAR) osc8_prefix[pansi->oindex] &&
!(pansi->oindex == 0 && IS_CSI_START(ch)))
case OSC_START:
if (IS_CSI_START(ch))
return osc_return(pansi, OSC_INTRO, ANSI_MID);
break;
case OSC_INTRO:
if (ch == ']')
return osc_return(pansi, OSC_TYPENUM, ANSI_MID);
if (is_ascii_char(ch) && valid_osc_intro((char) ch, content))
return osc_return(pansi, OSC_STRING, ANSI_MID);
if (IS_CSI_START(ch))
return osc_return(pansi, OSC_INTRO, ANSI_MID);
/* ESC not followed by bracket; restart. */
pansi->ostate = OSC_START;
break;
case OSC_TYPENUM:
if (ch >= '0' && ch <= '9')
{
pansi->ostate = OSC8_NOT; /* not an OSC8 sequence */
break;
if (ckd_mul(&pansi->otype, pansi->otype, 10) ||
ckd_add(&pansi->otype, pansi->otype, ch - '0'))
return osc_return(pansi, OSC_STRING, ANSI_MID);
return osc_return(pansi, OSC_TYPENUM, ANSI_MID);
}
pansi->oindex++;
if (osc8_prefix[pansi->oindex] == '\0') /* end of prefix */
pansi->ostate = OSC8_PARAMS;
return ANSI_MID;
if (ch == ';')
return osc_return(pansi, (pansi->otype == 8) ? OSC8_PARAMS : OSC_STRING, ANSI_MID);
/* OSC is untyped */
if (IS_CSI_START(ch))
return osc_return(pansi, OSC_END_CSI, ANSI_MID);
if (ch == '\7')
return osc_return(pansi, OSC_END, ANSI_END);
return osc_return(pansi, OSC_STRING, ANSI_MID);
case OSC8_PARAMS:
if (ch == ';')
pansi->ostate = OSC8_URI;
return ANSI_MID;
return osc_return(pansi, OSC8_URI, ANSI_MID);
/* FALLTHRU */
case OSC8_URI:
/* URI ends with \7 or ESC-backslash. */
case OSC_STRING:
/* Look for ST. */
if (ch == '\7')
return osc_return(pansi, OSC_END, valid_osc_type(pansi->otype, content) ? ANSI_END : ANSI_ERR);
if (IS_CSI_START(ch))
{
pansi->ostate = OSC8_END;
return ANSI_END;
pansi->escs_in_seq++;
return osc_return(pansi, OSC_END_CSI, ANSI_MID);
}
if (ch == ESC)
pansi->ostate = OSC8_ST_ESC;
/* Stay in same ostate */
return ANSI_MID;
case OSC8_ST_ESC:
if (ch != '\\')
{
return ANSI_ERR;
}
pansi->ostate = OSC8_END;
return ANSI_END;
case OSC8_END:
case OSC_END_CSI:
/* Got ESC of ST, expect backslash next. */
if (ch == '\\')
return osc_return(pansi, OSC_END, valid_osc_type(pansi->otype, content) ? ANSI_END : ANSI_ERR);
/* ESC not followed by backslash. */
return osc_return(pansi, OSC_STRING, ANSI_MID);
case OSC_END:
return ANSI_END;
case OSC8_NOT:
/* cannot happen */
break;
}
/* Check for SGR sequences */
@@ -667,6 +767,11 @@ public ansi_state ansi_step(struct ansi_state *pansi, LWCHAR ch)
return ANSI_ERR;
}
public ansi_state ansi_step(struct ansi_state *pansi, LWCHAR ch)
{
return ansi_step2(pansi, ch, TRUE);
}
/*
* Return the current OSC8 parsing state.
*/
@@ -686,11 +791,11 @@ public void ansi_done(struct ansi_state *pansi)
/*
* Will w characters in attribute a fit on the screen?
*/
static int fits_on_screen(int w, int a)
static lbool fits_on_screen(int w, int a)
{
if (ctldisp == OPT_ON)
/* We're not counting, so say that everything fits. */
return 1;
return TRUE;
return (end_column - cshift + w + attr_ewidth(a) <= sc_width);
}
@@ -720,11 +825,7 @@ static int store_char(LWCHAR ch, int a, constant char *rep, POSITION pos)
int resend_last = 0;
int hl_attr = 0;
if (pos == NULL_POSITION)
{
/* Color the prompt unless it has ansi sequences in it. */
hl_attr = ansi_in_line ? 0 : AT_STANDOUT|AT_COLOR_PROMPT;
} else if (a != AT_ANSI)
if (pos != NULL_POSITION && a != AT_ANSI)
{
hl_attr = is_hilited_attr(pos, pos+1, 0, &matches);
if (hl_attr == 0 && status_line)
@@ -739,7 +840,7 @@ static int store_char(LWCHAR ch, int a, constant char *rep, POSITION pos)
a |= hl_attr;
if (highest_hilite != NULL_POSITION && pos != NULL_POSITION && pos > highest_hilite)
highest_hilite = pos;
in_hilite = 1;
in_hilite = TRUE;
} else
{
if (in_hilite)
@@ -750,7 +851,7 @@ static int store_char(LWCHAR ch, int a, constant char *rep, POSITION pos)
*/
resend_last = 1;
}
in_hilite = 0;
in_hilite = FALSE;
}
if (resend_last)
{
@@ -1005,9 +1106,16 @@ public int pappend_b(char c, POSITION pos, lbool before_pendc)
public int pappend(char c, POSITION pos)
{
if (ff_starts_line < 0)
ff_starts_line = (c == CONTROL('L'));
return pappend_b(c, pos, FALSE);
}
public lbool line_is_ff(void)
{
return (ff_starts_line == 1);
}
static int store_control_char(LWCHAR ch, constant char *rep, POSITION pos)
{
if (ctldisp == OPT_ON)
@@ -1024,12 +1132,15 @@ static int store_control_char(LWCHAR ch, constant char *rep, POSITION pos)
static int store_ansi(LWCHAR ch, constant char *rep, POSITION pos)
{
switch (ansi_step(line_ansi, ch))
switch (ansi_step2(line_ansi, ch, pos != NULL_POSITION))
{
case ANSI_MID:
STORE_CHAR(ch, AT_ANSI, rep, pos);
if (ansi_osc8_state(line_ansi) == OSC8_PARAMS)
hlink_in_line = 1;
switch (ansi_osc8_state(line_ansi))
{
case OSC_TYPENUM: case OSC_STRING: hlink_in_line = TRUE; break;
default: break;
}
xbuf_add_char(&last_ansi, (char) ch);
break;
case ANSI_END:
@@ -1050,7 +1161,7 @@ static int store_ansi(LWCHAR ch, constant char *rep, POSITION pos)
LWCHAR bch;
do {
bch = step_charc(&p, -1, start);
} while (p > start && !IS_CSI_START(bch));
} while (p > start && (!IS_CSI_START(bch) || line_ansi->escs_in_seq-- > 0));
*end = ptr_diff(p, start);
}
xbuf_reset(&last_ansi);
@@ -1083,7 +1194,7 @@ static int do_append(LWCHAR ch, constant char *rep, POSITION pos)
int a = AT_NORMAL;
int in_overstrike = overstrike;
if (ctldisp == OPT_ONPLUS && line_ansi == NULL)
if ((ctldisp == OPT_ONPLUS || pos == NULL_POSITION) && line_ansi == NULL)
{
line_ansi = ansi_start(ch);
if (line_ansi != NULL)
@@ -1200,6 +1311,22 @@ public int pflushmbc(void)
*/
static void add_attr_normal(void)
{
if (line_ansi != NULL)
{
switch (line_ansi->ostate)
{
case OSC_TYPENUM:
case OSC8_PARAMS:
case OSC8_URI:
case OSC_STRING:
addstr_linebuf("\033\\", AT_ANSI, 0);
break;
default:
break;
}
ansi_done(line_ansi);
line_ansi = NULL;
}
if (ctldisp != OPT_ONPLUS || !is_ansi_end('m'))
return;
addstr_linebuf("\033[m", AT_ANSI, 0);
@@ -1210,7 +1337,7 @@ static void add_attr_normal(void)
/*
* Terminate the line in the line buffer.
*/
public void pdone(int endline, int chopped, int forw)
public void pdone(lbool endline, lbool chopped, lbool forw)
{
(void) pflushmbc();
@@ -1302,6 +1429,14 @@ public void pdone(int endline, int chopped, int forw)
add_linebuf(' ', AT_NORMAL, 1);
add_linebuf('\b', AT_NORMAL, -1);
}
/*
* If a terminal moves the cursor to the next line immediately after
* writing into the last char of a line, the following line may get
* colored with the last char's background color before the color
* reset sequence is sent. Clear the line to reset the background color.
*/
if (auto_wrap && !ignaw && end_column >= sc_width + cshift)
clear_after_line = TRUE;
set_linebuf(linebuf.end, '\0', AT_NORMAL);
}
@@ -1354,28 +1489,28 @@ static void col_vs_pos(POSITION linepos, mutable struct col_pos *cp, POSITION sa
} else if (ch == '\b')
{
if (proc_backspace == OPT_ONPLUS || (bs_mode == BS_CONTROL && proc_backspace == OPT_OFF))
cw = strlen(prchar(ch));
cw = (int) strlen(prchar(ch));
else
cw = (utf_mode && is_wide_char(prev_ch)) ? -2 : -1;
} else if (ch == '\t')
{
if (proc_tab == OPT_ONPLUS || (bs_mode == BS_CONTROL && proc_tab == OPT_OFF))
cw = strlen(prchar(ch));
cw = (int) strlen(prchar(ch));
else
cw = tab_spaces(col);
} else if ((!utf_mode || is_ascii_char(ch)) && control_char(ch))
{
cw = strlen(prchar(ch));
cw = (int) strlen(prchar(ch));
} else if (utf8_len < MAX_UTF_CHAR_LEN)
{
utf8_buf[utf8_len++] = ch;
if (is_utf8_well_formed(utf8_buf, utf8_len))
{
LWCHAR wch = get_wchar(utf8_buf);
utf8_len = 0;
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))
cw = strlen(prutfchar(wch));
cw = (int) strlen(prutfchar(wch));
else
cw = pwidth(wch, attr, prev_ch, attr);
prev_ch = wch;
@@ -1471,6 +1606,14 @@ public int gline(size_t i, int *ap)
return (linebuf.buf[i] & 0xFF);
}
/*
* Should we clear to end of line after printing this line?
*/
public lbool should_clear_after_line(void)
{
return clear_after_line;
}
/*
* Indicate that there is no current line.
*/
@@ -1623,7 +1766,7 @@ public int skip_columns(int cols, constant char **linep, size_t *line_lenp)
struct ansi_state *pansi = ansi_start(ch);
if (pansi != NULL)
{
skip_ansi(pansi, &line, eline);
skip_ansi(pansi, ch, &line, eline);
ansi_done(pansi);
pch = 0;
} else
@@ -1676,6 +1819,14 @@ public void load_line(constant char *str)
hshift += 1;
}
set_linebuf(linebuf.end, '\0', AT_NORMAL);
/* Color the prompt unless it has ansi sequences in it. */
if (!ansi_in_line)
{
size_t i;
for (i = linebuf.print; i < linebuf.end; i++)
set_linebuf(i, linebuf.buf[i], AT_STANDOUT|AT_COLOR_PROMPT);
}
hshift = save_hshift;
}
@@ -1696,7 +1847,7 @@ public int rrshift(void)
break;
for (; sline < sc_height && pos != NULL_POSITION; sline++)
{
pos = forw_line(pos);
pos = forw_line(pos, NULL, NULL);
if (end_column > longest)
longest = end_column;
}
+15 -9
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -55,13 +55,11 @@ struct linenum_info
* when we have a new one to insert and the table is full.
*/
#define NPOOL 200 /* Size of line number pool */
#define LONGTIME (2) /* In seconds */
static struct linenum_info anchor; /* Anchor of the list */
static struct linenum_info *freelist; /* Anchor of the unused entries */
static struct linenum_info pool[NPOOL]; /* The pool itself */
static struct linenum_info pool[LINENUM_POOL]; /* The pool itself */
static struct linenum_info *spare; /* We always keep one spare entry */
public lbool scanning_eof = FALSE;
@@ -70,6 +68,7 @@ extern int sigs;
extern int sc_height;
extern int header_lines;
extern int nonum_headers;
extern POSITION header_start_pos;
/*
* Initialize the line number structures.
@@ -82,12 +81,12 @@ public void clr_linenum(void)
* Put all the entries on the free list.
* Leave one for the "spare".
*/
for (p = pool; p < &pool[NPOOL-2]; p++)
for (p = pool; p < &pool[LINENUM_POOL-2]; p++)
p->next = p+1;
pool[NPOOL-2].next = NULL;
pool[LINENUM_POOL-2].next = NULL;
freelist = pool;
spare = &pool[NPOOL-1];
spare = &pool[LINENUM_POOL-1];
/*
* Initialize the anchor.
@@ -511,7 +510,14 @@ public void scan_eof(void)
*/
public LINENUM vlinenum(LINENUM linenum)
{
if (nonum_headers)
linenum = (linenum < header_lines) ? 0 : linenum - header_lines;
if (nonum_headers && header_lines > 0)
{
LINENUM header_start_line = find_linenum(header_start_pos);
if (header_start_line != 0)
{
LINENUM header_end_line = header_start_line + header_lines; /* first line after header */
linenum = (linenum < header_end_line) ? 0 : linenum - header_end_line + 1;
}
}
return linenum;
}
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
+21 -12
View File
@@ -1,6 +1,5 @@
/* $FreeBSD$ */
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -38,7 +37,7 @@ public POSITION start_attnpos = NULL_POSITION;
public POSITION end_attnpos = NULL_POSITION;
public int wscroll;
public constant char *progname;
public int quitting;
public lbool quitting = FALSE;
public int dohelp;
public char * init_header = NULL;
static int secure_allow_features;
@@ -60,20 +59,24 @@ extern char * tagoption;
extern int jump_sline;
#endif
#if HAVE_TIME
public time_type less_start_time;
#endif
#ifdef WIN32
static wchar_t consoleTitle[256];
#endif
public int one_screen;
extern int less_is_more;
extern int missing_cap;
extern lbool missing_cap;
extern int know_dumb;
extern int quit_if_one_screen;
extern int no_init;
extern int errmsgs;
extern int redraw_on_quit;
extern int term_init_done;
extern int first_time;
extern lbool first_time;
#if MSDOS_COMPILER==WIN32C && (defined(MINGW) || defined(_MSC_VER))
/* malloc'ed 0-terminated utf8 of 0-terminated wide ws, or null on errors */
@@ -153,6 +156,7 @@ cleanup:
}
#endif
#if !SECURE
static int security_feature_error(constant char *type, size_t len, constant char *name)
{
PARG parg;
@@ -201,6 +205,7 @@ static int security_feature(constant char *name, size_t len)
return security_feature_error("invalid", len, name);
return features[match].sf_value;
}
#endif /* !SECURE */
/*
* Set the secure_allow_features bitmask, which controls
@@ -298,9 +303,10 @@ int main(int argc, constant char *argv[])
* If the name of the executable program is "more",
* act like LESS_IS_MORE is set.
*/
if (strcmp(last_component(progname), "more") == 0) {
if (strcmp(last_component(progname), "more") == 0 &&
isnullenv(lgetenv("LESS_IS_MORE"))) {
less_is_more = 1;
scan_option("-fG");
scan_option("-fG", FALSE);
}
init_prompt();
@@ -308,7 +314,7 @@ int main(int argc, constant char *argv[])
init_unsupport();
s = lgetenv(less_is_more ? "MORE" : "LESS");
if (s != NULL)
scan_option(s);
scan_option(s, TRUE);
#define isoptstring(s) less_is_more ? (((s)[0] == '-') && (s)[1] != '\0') : \
(((s)[0] == '-' || (s)[0] == '+') && (s)[1] != '\0')
@@ -318,7 +324,7 @@ int main(int argc, constant char *argv[])
argc--;
if (strcmp(s, "--") == 0)
break;
scan_option(s);
scan_option(s, FALSE);
}
#undef isoptstring
@@ -340,7 +346,7 @@ int main(int argc, constant char *argv[])
#if EDITOR
editor = lgetenv("VISUAL");
if (editor == NULL || *editor == '\0')
if (isnullenv(editor))
{
editor = lgetenv("EDITOR");
if (isnullenv(editor))
@@ -413,6 +419,9 @@ int main(int argc, constant char *argv[])
open_getchr();
raw_mode(1);
init_signals(1);
#if HAVE_TIME
less_start_time = get_time();
#endif
/*
* Select the first file to examine.
@@ -587,7 +596,7 @@ public void quit(int status)
status = save_status;
else
save_status = status;
quitting = 1;
quitting = TRUE;
check_altpipe_error();
if (interactive())
clear_bot();
@@ -600,7 +609,7 @@ public void quit(int status)
* alternate screen, which now (since deinit) cannot be seen.
* redraw_on_quit tells us to redraw it on the main screen.
*/
first_time = 1; /* Don't print "skipping" or tildes */
first_time = TRUE; /* Don't print "skipping" or tildes */
repaint();
flush();
}
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
+4 -3
View File
@@ -52,9 +52,10 @@ sub main {
}
}
my $date = `date`;
chomp $date;
print "/* Generated by \"$0 $args\" on $date */\n";
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" );
printf "/* Generated by \"%s %s\" on %s %2d %2d:%02d:%02d GMT %d */\n",
$0, $args, $month[$mon], $mday, $hour, $min, $sec, $year+1900;
my $last_code = 0;
my $start_range = 0;
+22 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -66,6 +66,7 @@ extern int chopline;
extern int tabstops[];
extern int ntabstops;
extern int tabdefault;
extern int no_paste;
extern char intr_char;
extern int nosearch_header_lines;
extern int nosearch_header_cols;
@@ -528,7 +529,7 @@ public void opt__V(int type, constant char *s)
putstr(" regular expressions)\n");
{
char constant *copyright =
"Copyright (C) 1984-2024 Mark Nudelman\n\n";
"Copyright (C) 1984-2025 Mark Nudelman\n\n";
putstr(copyright);
}
if (version[strlen(version)-1] == 'x')
@@ -1164,7 +1165,8 @@ static void do_nosearch_headers(int type, int no_header_lines, int no_header_col
case TOGGLE:
nosearch_header_lines = no_header_lines;
nosearch_header_cols = no_header_cols;
break;
if (type != TOGGLE) break;
/*FALLTHRU*/
case QUERY:
if (nosearch_header_lines && nosearch_header_cols)
error("Search does not include header lines or columns", NULL_PARG);
@@ -1195,6 +1197,23 @@ public void opt_nosearch_header_cols(int type, constant char *s)
do_nosearch_headers(type, 0, 1);
}
/*ARGSUSED*/
public void opt_no_paste(int type, constant char *s)
{
switch (type)
{
case TOGGLE:
if (no_paste)
init_bracketed_paste();
else
deinit_bracketed_paste();
break;
case INIT:
case QUERY:
break;
}
}
#if LESSTEST
/*
* Handler for the --tty option.
+42 -38
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -24,12 +24,13 @@ static struct loption *pendopt;
public lbool plusoption = FALSE;
static constant char *optstring(constant char *s, char **p_str, constant char *printopt, constant char *validchars);
static int flip_triple(int val, int lc);
static int flip_triple(int val, lbool lc);
extern int less_is_more;
extern int quit_at_eof;
extern char *every_first_cmd;
extern int opt_use_backslash;
extern int ctldisp;
/*
* Return a printable description of an option.
@@ -60,7 +61,7 @@ public constant char * propt(char c)
* Scan an argument (either from the command line or from the
* LESS environment variable) and process it.
*/
public void scan_option(constant char *s)
public void scan_option(constant char *s, lbool is_env)
{
struct loption *o;
char optc;
@@ -68,7 +69,7 @@ public void scan_option(constant char *s)
constant char *printopt;
char *str;
lbool set_default;
int lc;
lbool lc;
lbool ambig;
PARG parg;
@@ -84,14 +85,14 @@ public void scan_option(constant char *s)
*/
if (pendopt != NULL)
{
if (!(pendopt->otype & UNSUPPORTED))
if (!(pendopt->otype & O_UNSUPPORTED))
{
switch (pendopt->otype & OTYPE)
{
case STRING:
case O_STRING:
(*pendopt->ofunc)(INIT, s);
break;
case NUMBER:
case O_NUMBER:
printopt = opt_desc(pendopt);
*(pendopt->ovar) = getnumc(&s, printopt, NULL);
break;
@@ -203,8 +204,8 @@ public void scan_option(constant char *s)
* The option name is followed by "=value".
*/
if (o != NULL &&
(o->otype & OTYPE) != STRING &&
(o->otype & OTYPE) != NUMBER)
(o->otype & OTYPE) != O_STRING &&
(o->otype & OTYPE) != O_NUMBER)
{
parg.p_string = printopt;
error("The %s option should not be followed by =",
@@ -236,8 +237,8 @@ public void scan_option(constant char *s)
str = NULL;
switch (o->otype & OTYPE)
{
case BOOL:
if (o->otype & UNSUPPORTED)
case O_BOOL:
if (o->otype & O_UNSUPPORTED)
break;
if (o->ovar != NULL)
{
@@ -247,18 +248,21 @@ public void scan_option(constant char *s)
*(o->ovar) = ! o->odefault;
}
break;
case TRIPLE:
if (o->otype & UNSUPPORTED)
case O_TRIPLE:
if (o->otype & O_UNSUPPORTED)
break;
if (o->ovar != NULL)
{
if (set_default)
*(o->ovar) = o->odefault;
else if (is_env && o->ovar == &ctldisp)
/* If -r appears in an env var, treat it as -R. */
*(o->ovar) = OPT_ONPLUS;
else
*(o->ovar) = flip_triple(o->odefault, lc);
}
break;
case STRING:
case O_STRING:
if (*s == '\0')
{
/*
@@ -280,13 +284,13 @@ public void scan_option(constant char *s)
if (s == NULL)
return;
break;
case NUMBER:
case O_NUMBER:
if (*s == '\0')
{
pendopt = o;
return;
}
if (o->otype & UNSUPPORTED)
if (o->otype & O_UNSUPPORTED)
break;
*(o->ovar) = getnumc(&s, printopt, NULL);
break;
@@ -294,7 +298,7 @@ public void scan_option(constant char *s)
/*
* If the option has a handling function, call it.
*/
if (o->ofunc != NULL && !(o->otype & UNSUPPORTED))
if (o->ofunc != NULL && !(o->otype & O_UNSUPPORTED))
(*o->ofunc)(INIT, str);
if (str != NULL)
free(str);
@@ -310,7 +314,7 @@ public void scan_option(constant char *s)
* OPT_UNSET set to the default value
* OPT_SET set to the inverse of the default value
*/
public void toggle_option(struct loption *o, int lower, constant char *s, int how_toggle)
public void toggle_option(struct loption *o, lbool lower, constant char *s, int how_toggle)
{
int num;
int no_prompt;
@@ -326,14 +330,14 @@ public void toggle_option(struct loption *o, int lower, constant char *s, int ho
return;
}
if (how_toggle == OPT_TOGGLE && (o->otype & NO_TOGGLE))
if (how_toggle == OPT_TOGGLE && (o->otype & O_NO_TOGGLE))
{
parg.p_string = opt_desc(o);
error("Cannot change the %s option", &parg);
return;
}
if (how_toggle == OPT_NO_TOGGLE && (o->otype & NO_QUERY))
if (how_toggle == OPT_NO_TOGGLE && (o->otype & O_NO_QUERY))
{
parg.p_string = opt_desc(o);
error("Cannot query the %s option", &parg);
@@ -348,15 +352,15 @@ public void toggle_option(struct loption *o, int lower, constant char *s, int ho
*/
switch (o->otype & OTYPE)
{
case STRING:
case NUMBER:
case O_STRING:
case O_NUMBER:
if (how_toggle == OPT_TOGGLE && *s == '\0')
how_toggle = OPT_NO_TOGGLE;
break;
}
#if HILITE_SEARCH
if (how_toggle != OPT_NO_TOGGLE && (o->otype & HL_REPAINT))
if (how_toggle != OPT_NO_TOGGLE && (o->otype & O_HL_REPAINT))
repaint_hilite(FALSE);
#endif
@@ -367,7 +371,7 @@ public void toggle_option(struct loption *o, int lower, constant char *s, int ho
{
switch (o->otype & OTYPE)
{
case BOOL:
case O_BOOL:
/*
* Boolean.
*/
@@ -387,7 +391,7 @@ public void toggle_option(struct loption *o, int lower, constant char *s, int ho
}
}
break;
case TRIPLE:
case O_TRIPLE:
/*
* Triple:
* If user gave the lower case letter, then switch
@@ -411,7 +415,7 @@ public void toggle_option(struct loption *o, int lower, constant char *s, int ho
}
}
break;
case STRING:
case O_STRING:
/*
* String: don't do anything here.
* The handling function will do everything.
@@ -420,12 +424,12 @@ public void toggle_option(struct loption *o, int lower, constant char *s, int ho
{
case OPT_SET:
case OPT_UNSET:
error("Cannot use \"-+\" or \"--\" for a string option",
error("Cannot use \"-+\" or \"-!\" for a string option",
NULL_PARG);
return;
}
break;
case NUMBER:
case O_NUMBER:
/*
* Number: set the variable to the given number.
*/
@@ -456,7 +460,7 @@ public void toggle_option(struct loption *o, int lower, constant char *s, int ho
(*o->ofunc)((how_toggle==OPT_NO_TOGGLE) ? QUERY : TOGGLE, s);
#if HILITE_SEARCH
if (how_toggle != OPT_NO_TOGGLE && (o->otype & HL_REPAINT))
if (how_toggle != OPT_NO_TOGGLE && (o->otype & O_HL_REPAINT))
chg_hilite();
#endif
@@ -467,15 +471,15 @@ public void toggle_option(struct loption *o, int lower, constant char *s, int ho
*/
switch (o->otype & OTYPE)
{
case BOOL:
case TRIPLE:
case O_BOOL:
case O_TRIPLE:
/*
* Print the odesc message.
*/
if (o->ovar != NULL)
error(o->odesc[*(o->ovar)], NULL_PARG);
break;
case NUMBER:
case O_NUMBER:
/*
* The message is in odesc[1] and has a %d for
* the value of the variable.
@@ -483,7 +487,7 @@ public void toggle_option(struct loption *o, int lower, constant char *s, int ho
parg.p_int = *(o->ovar);
error(o->odesc[1], &parg);
break;
case STRING:
case O_STRING:
/*
* Message was already printed by the handling function.
*/
@@ -491,14 +495,14 @@ public void toggle_option(struct loption *o, int lower, constant char *s, int ho
}
}
if (how_toggle != OPT_NO_TOGGLE && (o->otype & REPAINT))
if (how_toggle != OPT_NO_TOGGLE && (o->otype & O_REPAINT))
screen_trashed();
}
/*
* "Toggle" a triple-valued option.
*/
static int flip_triple(int val, int lc)
static int flip_triple(int val, lbool lc)
{
if (lc)
return ((val == OPT_ON) ? OPT_OFF : OPT_ON);
@@ -513,7 +517,7 @@ public int opt_has_param(struct loption *o)
{
if (o == NULL)
return (0);
if (o->otype & (BOOL|TRIPLE|NOVAR|NO_TOGGLE))
if (o->otype & (O_BOOL|O_TRIPLE|O_NOVAR|O_NO_TOGGLE))
return (0);
return (1);
}
@@ -524,7 +528,7 @@ public int opt_has_param(struct loption *o)
*/
public constant char * opt_prompt(struct loption *o)
{
if (o == NULL || (o->otype & (STRING|NUMBER)) == 0)
if (o == NULL || (o->otype & (O_STRING|O_NUMBER)) == 0)
return ("?");
return (o->odesc[0]);
}
@@ -766,7 +770,7 @@ public void init_unsupport(void)
if (opt != NULL) ++s;
}
if (opt != NULL)
opt->otype |= UNSUPPORTED;
opt->otype |= O_UNSUPPORTED;
}
}
+13 -13
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -13,19 +13,19 @@
/*
* Types of options.
*/
#define BOOL 01 /* Boolean option: 0 or 1 */
#define TRIPLE 02 /* Triple-valued option: 0, 1 or 2 */
#define NUMBER 04 /* Numeric option */
#define STRING 010 /* String-valued option */
#define NOVAR 020 /* No associated variable */
#define REPAINT 040 /* Repaint screen after toggling option */
#define NO_TOGGLE 0100 /* Option cannot be toggled with "-" cmd */
#define HL_REPAINT 0200 /* Repaint hilites after toggling option */
#define NO_QUERY 0400 /* Option cannot be queried with "_" cmd */
#define INIT_HANDLER 01000 /* Call option handler function at startup */
#define UNSUPPORTED 02000 /* Option is unsupported via LESS_UNSUPPORT */
#define O_BOOL 01 /* Boolean option: 0 or 1 */
#define O_TRIPLE 02 /* Triple-valued option: 0, 1 or 2 */
#define O_NUMBER 04 /* Numeric option */
#define O_STRING 010 /* String-valued option */
#define O_NOVAR 020 /* No associated variable */
#define O_REPAINT 040 /* Repaint screen after toggling option */
#define O_NO_TOGGLE 0100 /* Option cannot be toggled with "-" cmd */
#define O_HL_REPAINT 0200 /* Repaint hilites after toggling option */
#define O_NO_QUERY 0400 /* Option cannot be queried with "_" cmd */
#define O_INIT_HANDLER 01000 /* Call option handler function at startup */
#define O_UNSUPPORTED 02000 /* Option is unsupported via LESS_UNSUPPORT */
#define OTYPE (BOOL|TRIPLE|NUMBER|STRING|NOVAR)
#define OTYPE (O_BOOL|O_TRIPLE|O_NUMBER|O_STRING|O_NOVAR)
#define OLETTER_NONE '\1' /* Invalid option letter */
+150 -81
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -81,6 +81,9 @@ public int proc_backspace; /* Special handling of backspace */
public int proc_tab; /* Special handling of tab */
public int proc_return; /* Special handling of carriage return */
public int match_shift; /* Extra horizontal shift on search match */
public int no_paste; /* Don't accept pasted input */
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 */
#if HILITE_SEARCH
@@ -161,6 +164,10 @@ static struct optname use_color_optname = { "use-color", NULL };
static struct optname want_filesize_optname = { "file-size", NULL };
static struct optname status_line_optname = { "status-line", NULL };
static struct optname header_optname = { "header", NULL };
static struct optname no_paste_optname = { "no-paste", NULL };
static struct optname form_feed_optname = { "form-feed", NULL };
static struct optname no_edit_warn_optname2 = { "no-warn-edit", NULL };
static struct optname no_edit_warn_optname = { "no-edit-warn", &no_edit_warn_optname2 };
static struct optname nonum_headers_optname = { "no-number-headers", NULL };
static struct optname nosearch_headers_optname = { "no-search-headers", NULL };
static struct optname nosearch_header_lines_optname = { "no-search-header-lines", NULL };
@@ -197,7 +204,7 @@ static struct optname ttyin_name_optname = { "tty", NULL };
static struct loption option[] =
{
{ 'a', &a_optname,
TRIPLE, OPT_ONPLUS, &how_search, NULL,
O_TRIPLE, OPT_ONPLUS, &how_search, NULL,
{
"Search includes displayed screen",
"Search skips displayed screen",
@@ -206,7 +213,7 @@ static struct loption option[] =
},
{ 'b', &b_optname,
NUMBER|INIT_HANDLER, 64, &bufspace, opt_b,
O_NUMBER|O_INIT_HANDLER, 64, &bufspace, opt_b,
{
"Max buffer space per file (K): ",
"Max buffer space per file: %dK",
@@ -214,7 +221,7 @@ static struct loption option[] =
}
},
{ 'B', &B__optname,
BOOL, OPT_ON, &autobuf, NULL,
O_BOOL, OPT_ON, &autobuf, NULL,
{
"Don't automatically allocate buffers",
"Automatically allocate buffers when needed",
@@ -222,7 +229,7 @@ static struct loption option[] =
}
},
{ 'c', &c_optname,
TRIPLE, OPT_OFF, &top_scroll, NULL,
O_TRIPLE, OPT_OFF, &top_scroll, NULL,
{
"Repaint by scrolling from bottom of screen",
"Repaint by painting from top of screen",
@@ -230,7 +237,7 @@ static struct loption option[] =
}
},
{ 'd', &d_optname,
BOOL|NO_TOGGLE, OPT_OFF, &know_dumb, NULL,
O_BOOL|O_NO_TOGGLE, OPT_OFF, &know_dumb, NULL,
{
"Assume intelligent terminal",
"Assume dumb terminal",
@@ -238,11 +245,11 @@ static struct loption option[] =
}
},
{ 'D', &D__optname,
STRING|REPAINT|NO_QUERY, 0, NULL, opt_D,
O_STRING|O_REPAINT|O_NO_QUERY, 0, NULL, opt_D,
{ "color desc: ", "s", NULL }
},
{ 'e', &e_optname,
TRIPLE, OPT_OFF, &quit_at_eof, NULL,
O_TRIPLE, OPT_OFF, &quit_at_eof, NULL,
{
"Don't quit at end-of-file",
"Quit at end-of-file",
@@ -250,7 +257,7 @@ static struct loption option[] =
}
},
{ 'f', &f_optname,
BOOL, OPT_OFF, &force_open, NULL,
O_BOOL, OPT_OFF, &force_open, NULL,
{
"Open only regular files",
"Open even non-regular files",
@@ -258,7 +265,7 @@ static struct loption option[] =
}
},
{ 'F', &F__optname,
BOOL, OPT_OFF, &quit_if_one_screen, NULL,
O_BOOL, OPT_OFF, &quit_if_one_screen, NULL,
{
"Don't quit if end-of-file on first screen",
"Quit if end-of-file on first screen",
@@ -267,7 +274,7 @@ static struct loption option[] =
},
#if HILITE_SEARCH
{ 'g', &g_optname,
TRIPLE|HL_REPAINT, OPT_ONPLUS, &hilite_search, NULL,
O_TRIPLE|O_HL_REPAINT, OPT_ONPLUS, &hilite_search, NULL,
{
"Don't highlight search matches",
"Highlight matches for previous search only",
@@ -276,7 +283,7 @@ static struct loption option[] =
},
#endif
{ 'h', &h_optname,
NUMBER, -1, &back_scroll, NULL,
O_NUMBER, -1, &back_scroll, NULL,
{
"Backwards scroll limit: ",
"Backwards scroll limit is %d lines",
@@ -284,7 +291,7 @@ static struct loption option[] =
}
},
{ 'i', &i_optname,
TRIPLE|HL_REPAINT, OPT_OFF, &caseless, opt_i,
O_TRIPLE|O_HL_REPAINT, OPT_OFF, &caseless, opt_i,
{
"Case is significant in searches",
"Ignore case in searches",
@@ -292,7 +299,7 @@ static struct loption option[] =
}
},
{ 'j', &j_optname,
STRING, 0, NULL, opt_j,
O_STRING, 0, NULL, opt_j,
{
"Target line: ",
"-.d",
@@ -300,7 +307,7 @@ static struct loption option[] =
}
},
{ 'J', &J__optname,
BOOL|REPAINT, OPT_OFF, &status_col, NULL,
O_BOOL|O_REPAINT, OPT_OFF, &status_col, NULL,
{
"Don't display a status column",
"Display a status column",
@@ -309,22 +316,22 @@ static struct loption option[] =
},
#if USERFILE
{ 'k', &k_optname,
STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_k,
O_STRING|O_NO_TOGGLE|O_NO_QUERY, 0, NULL, opt_k,
{ NULL, NULL, NULL }
},
#if HAVE_LESSKEYSRC
{ OLETTER_NONE, &kc_optname,
STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_kc,
O_STRING|O_NO_TOGGLE|O_NO_QUERY, 0, NULL, opt_kc,
{ NULL, NULL, NULL }
},
{ OLETTER_NONE, &ks_optname,
STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_ks,
O_STRING|O_NO_TOGGLE|O_NO_QUERY, 0, NULL, opt_ks,
{ NULL, NULL, NULL }
},
#endif /* HAVE_LESSKEYSRC */
#endif
{ 'K', &K__optname,
BOOL, OPT_OFF, &quit_on_intr, NULL,
O_BOOL, OPT_OFF, &quit_on_intr, NULL,
{
"Interrupt (ctrl-C) returns to prompt",
"Interrupt (ctrl-C) exits less",
@@ -332,7 +339,7 @@ static struct loption option[] =
}
},
{ 'L', &L__optname,
BOOL, OPT_ON, &use_lessopen, NULL,
O_BOOL, OPT_ON, &use_lessopen, NULL,
{
"Don't use the LESSOPEN filter",
"Use the LESSOPEN filter",
@@ -340,7 +347,7 @@ static struct loption option[] =
}
},
{ 'm', &m_optname,
TRIPLE, OPT_OFF, &pr_type, NULL,
O_TRIPLE, OPT_OFF, &pr_type, NULL,
{
"Short prompt",
"Medium prompt",
@@ -348,7 +355,7 @@ static struct loption option[] =
}
},
{ 'n', &n_optname,
TRIPLE|REPAINT, OPT_ON, &linenums, NULL,
O_TRIPLE|O_REPAINT, OPT_ON, &linenums, NULL,
{
"Don't use line numbers",
"Use line numbers",
@@ -357,24 +364,24 @@ static struct loption option[] =
},
#if LOGFILE
{ 'o', &o_optname,
STRING, 0, NULL, opt_o,
O_STRING, 0, NULL, opt_o,
{ "log file: ", NULL, NULL }
},
{ 'O', &O__optname,
STRING, 0, NULL, opt__O,
O_STRING, 0, NULL, opt__O,
{ "Log file: ", NULL, NULL }
},
#endif
{ 'p', &p_optname,
STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_p,
O_STRING|O_NO_TOGGLE|O_NO_QUERY, 0, NULL, opt_p,
{ NULL, NULL, NULL }
},
{ 'P', &P__optname,
STRING, 0, NULL, opt__P,
O_STRING, 0, NULL, opt__P,
{ "prompt: ", NULL, NULL }
},
{ 'q', &q_optname,
TRIPLE, OPT_OFF, &quiet, NULL,
O_TRIPLE, OPT_OFF, &quiet, NULL,
{
"Ring the bell for errors AND at eof/bof",
"Ring the bell for errors but not at eof/bof",
@@ -382,7 +389,7 @@ static struct loption option[] =
}
},
{ 'r', &r_optname,
TRIPLE|REPAINT, OPT_OFF, &ctldisp, NULL,
O_TRIPLE|O_REPAINT, OPT_OFF, &ctldisp, NULL,
{
"Display control characters as ^X",
"Display control characters directly (not recommended)",
@@ -390,7 +397,7 @@ static struct loption option[] =
}
},
{ 's', &s_optname,
BOOL|REPAINT, OPT_OFF, &squeeze, NULL,
O_BOOL|O_REPAINT, OPT_OFF, &squeeze, NULL,
{
"Display all blank lines",
"Squeeze multiple blank lines",
@@ -398,7 +405,7 @@ static struct loption option[] =
}
},
{ 'S', &S__optname,
BOOL|REPAINT, OPT_OFF, &chopline, opt__S,
O_BOOL|O_REPAINT, OPT_OFF, &chopline, opt__S,
{
"Fold long lines",
"Chop long lines",
@@ -407,16 +414,16 @@ static struct loption option[] =
},
#if TAGS
{ 't', &t_optname,
STRING|NO_QUERY, 0, NULL, opt_t,
O_STRING|O_NO_QUERY, 0, NULL, opt_t,
{ "tag: ", NULL, NULL }
},
{ 'T', &T__optname,
STRING, 0, NULL, opt__T,
O_STRING, 0, NULL, opt__T,
{ "tags file: ", NULL, NULL }
},
#endif
{ 'u', &u_optname,
TRIPLE|REPAINT|HL_REPAINT, OPT_OFF, &bs_mode, NULL,
O_TRIPLE|O_REPAINT|O_HL_REPAINT, OPT_OFF, &bs_mode, NULL,
{
"Display underlined text in underline mode",
"Backspaces cause overstrike",
@@ -424,11 +431,11 @@ static struct loption option[] =
}
},
{ 'V', &V__optname,
NOVAR, 0, NULL, opt__V,
O_NOVAR, 0, NULL, opt__V,
{ NULL, NULL, NULL }
},
{ 'w', &w_optname,
TRIPLE|REPAINT, OPT_OFF, &show_attn, NULL,
O_TRIPLE|O_REPAINT, OPT_OFF, &show_attn, NULL,
{
"Don't highlight first unread line",
"Highlight first unread line after forward-screen",
@@ -436,7 +443,7 @@ static struct loption option[] =
}
},
{ 'x', &x_optname,
STRING|REPAINT, 0, NULL, opt_x,
O_STRING|O_REPAINT, 0, NULL, opt_x,
{
"Tab stops: ",
"d,",
@@ -444,7 +451,7 @@ static struct loption option[] =
}
},
{ 'X', &X__optname,
BOOL|NO_TOGGLE, OPT_OFF, &no_init, NULL,
O_BOOL|O_NO_TOGGLE, OPT_OFF, &no_init, NULL,
{
"Send init/deinit strings to terminal",
"Don't use init/deinit strings",
@@ -452,7 +459,7 @@ static struct loption option[] =
}
},
{ 'y', &y_optname,
NUMBER, -1, &forw_scroll, NULL,
O_NUMBER, -1, &forw_scroll, NULL,
{
"Forward scroll limit: ",
"Forward scroll limit is %d lines",
@@ -460,7 +467,7 @@ static struct loption option[] =
}
},
{ 'z', &z_optname,
NUMBER, -1, &swindow, NULL,
O_NUMBER, -1, &swindow, NULL,
{
"Scroll window size: ",
"Scroll window size is %d lines",
@@ -468,11 +475,11 @@ static struct loption option[] =
}
},
{ '"', &quote_optname,
STRING, 0, NULL, opt_quote,
O_STRING, 0, NULL, opt_quote,
{ "quotes: ", "s", NULL }
},
{ '~', &tilde_optname,
BOOL|REPAINT, OPT_ON, &twiddle, NULL,
O_BOOL|O_REPAINT, OPT_ON, &twiddle, NULL,
{
"Don't show tildes after end of file",
"Show tildes after end of file",
@@ -480,11 +487,11 @@ static struct loption option[] =
}
},
{ '?', &query_optname,
NOVAR, 0, NULL, opt_query,
O_NOVAR, 0, NULL, opt_query,
{ NULL, NULL, NULL }
},
{ '#', &pound_optname,
STRING, 0, NULL, opt_shift,
O_STRING, 0, NULL, opt_shift,
{
"Horizontal shift: ",
".d",
@@ -492,7 +499,7 @@ static struct loption option[] =
}
},
{ OLETTER_NONE, &keypad_optname,
BOOL|NO_TOGGLE, OPT_OFF, &no_keypad, NULL,
O_BOOL|O_NO_TOGGLE, OPT_OFF, &no_keypad, NULL,
{
"Use keypad mode",
"Don't use keypad mode",
@@ -500,7 +507,7 @@ static struct loption option[] =
}
},
{ OLETTER_NONE, &oldbot_optname,
BOOL, OPT_OFF, &oldbot, NULL,
O_BOOL, OPT_OFF, &oldbot, NULL,
{
"Use new bottom of screen behavior",
"Use old bottom of screen behavior",
@@ -508,7 +515,7 @@ static struct loption option[] =
}
},
{ OLETTER_NONE, &follow_optname,
BOOL, FOLLOW_DESC, &follow_mode, NULL,
O_BOOL, FOLLOW_DESC, &follow_mode, NULL,
{
"F command follows file descriptor",
"F command follows file name",
@@ -516,7 +523,7 @@ static struct loption option[] =
}
},
{ OLETTER_NONE, &use_backslash_optname,
BOOL, OPT_OFF, &opt_use_backslash, NULL,
O_BOOL, OPT_OFF, &opt_use_backslash, NULL,
{
"Use backslash escaping in command line parameters",
"Don't use backslash escaping in command line parameters",
@@ -524,11 +531,11 @@ static struct loption option[] =
}
},
{ OLETTER_NONE, &rscroll_optname,
STRING|REPAINT|INIT_HANDLER, 0, NULL, opt_rscroll,
O_STRING|O_REPAINT|O_INIT_HANDLER, 0, NULL, opt_rscroll,
{ "rscroll character: ", "s", NULL }
},
{ OLETTER_NONE, &nohistdups_optname,
BOOL, OPT_OFF, &no_hist_dups, NULL,
O_BOOL, OPT_OFF, &no_hist_dups, NULL,
{
"Allow duplicates in history list",
"Remove duplicates from history list",
@@ -536,7 +543,7 @@ static struct loption option[] =
}
},
{ OLETTER_NONE, &mousecap_optname,
TRIPLE, OPT_OFF, &mousecap, opt_mousecap,
O_TRIPLE, OPT_OFF, &mousecap, opt_mousecap,
{
"Ignore mouse input",
"Use the mouse for scrolling",
@@ -544,7 +551,7 @@ static struct loption option[] =
}
},
{ OLETTER_NONE, &wheel_lines_optname,
NUMBER|INIT_HANDLER, 0, &wheel_lines, opt_wheel_lines,
O_NUMBER|O_INIT_HANDLER, 0, &wheel_lines, opt_wheel_lines,
{
"Lines to scroll on mouse wheel: ",
"Scroll %d line(s) on mouse wheel",
@@ -552,7 +559,7 @@ static struct loption option[] =
}
},
{ OLETTER_NONE, &perma_marks_optname,
BOOL, OPT_OFF, &perma_marks, NULL,
O_BOOL, OPT_OFF, &perma_marks, NULL,
{
"Don't save marks in history file",
"Save marks in history file",
@@ -560,7 +567,7 @@ static struct loption option[] =
}
},
{ OLETTER_NONE, &linenum_width_optname,
NUMBER|REPAINT, MIN_LINENUM_WIDTH, &linenum_width, opt_linenum_width,
O_NUMBER|O_REPAINT, MIN_LINENUM_WIDTH, &linenum_width, opt_linenum_width,
{
"Line number width: ",
"Line number width is %d chars",
@@ -568,7 +575,7 @@ static struct loption option[] =
}
},
{ OLETTER_NONE, &status_col_width_optname,
NUMBER|REPAINT, 2, &status_col_width, opt_status_col_width,
O_NUMBER|O_REPAINT, 2, &status_col_width, opt_status_col_width,
{
"Status column width: ",
"Status column width is %d chars",
@@ -576,7 +583,7 @@ static struct loption option[] =
}
},
{ OLETTER_NONE, &incr_search_optname,
BOOL, OPT_OFF, &incr_search, NULL,
O_BOOL, OPT_OFF, &incr_search, NULL,
{
"Incremental search is off",
"Incremental search is on",
@@ -584,7 +591,7 @@ static struct loption option[] =
}
},
{ OLETTER_NONE, &use_color_optname,
BOOL|REPAINT, OPT_OFF, &use_color, NULL,
O_BOOL|O_REPAINT, OPT_OFF, &use_color, NULL,
{
"Don't use color",
"Use color",
@@ -592,7 +599,7 @@ static struct loption option[] =
}
},
{ OLETTER_NONE, &want_filesize_optname,
BOOL|REPAINT, OPT_OFF, &want_filesize, opt_filesize,
O_BOOL|O_REPAINT, OPT_OFF, &want_filesize, opt_filesize,
{
"Don't get size of each file",
"Get size of each file",
@@ -600,7 +607,7 @@ static struct loption option[] =
}
},
{ OLETTER_NONE, &status_line_optname,
BOOL|REPAINT, OPT_OFF, &status_line, NULL,
O_BOOL|O_REPAINT, OPT_OFF, &status_line, NULL,
{
"Don't color each line with its status column color",
"Color each line with its status column color",
@@ -608,11 +615,35 @@ static struct loption option[] =
}
},
{ OLETTER_NONE, &header_optname,
STRING|REPAINT, 0, NULL, opt_header,
O_STRING|O_REPAINT, 0, NULL, opt_header,
{ "Header lines: ", "d,", NULL }
},
{ OLETTER_NONE, &no_paste_optname,
O_BOOL, OPT_OFF, &no_paste, opt_no_paste,
{
"Accept pasted input",
"Ignore pasted input",
NULL
}
},
{ OLETTER_NONE, &form_feed_optname,
O_BOOL, OPT_OFF, &stop_on_form_feed, NULL,
{
"Don't stop on form feed",
"Stop on form feed",
NULL
}
},
{ OLETTER_NONE, &no_edit_warn_optname,
O_BOOL, OPT_OFF, &no_edit_warn, NULL,
{
"Warn when editing a file opened via LESSOPEN",
"Don't warn when editing a file opened via LESSOPEN",
NULL
}
},
{ OLETTER_NONE, &nonum_headers_optname,
BOOL|REPAINT, 0, &nonum_headers, NULL,
O_BOOL|O_REPAINT, 0, &nonum_headers, NULL,
{
"Number header lines",
"Don't number header lines",
@@ -620,25 +651,25 @@ static struct loption option[] =
}
},
{ OLETTER_NONE, &nosearch_headers_optname,
BOOL|HL_REPAINT, 0, NULL, opt_nosearch_headers,
O_BOOL|O_HL_REPAINT, 0, NULL, opt_nosearch_headers,
{
NULL, NULL, NULL
}
},
{ OLETTER_NONE, &nosearch_header_lines_optname,
BOOL|HL_REPAINT, 0, NULL, opt_nosearch_header_lines,
O_BOOL|O_HL_REPAINT, 0, NULL, opt_nosearch_header_lines,
{
NULL, NULL, NULL
}
},
{ OLETTER_NONE, &nosearch_header_cols_optname,
BOOL|HL_REPAINT, 0, NULL, opt_nosearch_header_cols,
O_BOOL|O_HL_REPAINT, 0, NULL, opt_nosearch_header_cols,
{
NULL, NULL, NULL
}
},
{ OLETTER_NONE, &redraw_on_quit_optname,
BOOL, OPT_OFF, &redraw_on_quit, NULL,
O_BOOL, OPT_OFF, &redraw_on_quit, NULL,
{
"Don't redraw screen when quitting",
"Redraw last screen when quitting",
@@ -646,11 +677,11 @@ static struct loption option[] =
}
},
{ OLETTER_NONE, &search_type_optname,
STRING, 0, NULL, opt_search_type,
O_STRING, 0, NULL, opt_search_type,
{ "Search options: ", "s", NULL }
},
{ OLETTER_NONE, &exit_F_on_close_optname,
BOOL, OPT_OFF, &exit_F_on_close, NULL,
O_BOOL, OPT_OFF, &exit_F_on_close, NULL,
{
"Don't exit F command when input closes",
"Exit F command when input closes",
@@ -658,7 +689,7 @@ static struct loption option[] =
}
},
{ OLETTER_NONE, &no_vbell_optname,
BOOL, OPT_OFF, &no_vbell, NULL,
O_BOOL, OPT_OFF, &no_vbell, NULL,
{
"Display visual bell",
"Don't display visual bell",
@@ -666,7 +697,7 @@ static struct loption option[] =
}
},
{ OLETTER_NONE, &modelines_optname,
NUMBER, 0, &modelines, NULL,
O_NUMBER, 0, &modelines, NULL,
{
"Lines to read looking for modelines: ",
"Read %d lines looking for modelines",
@@ -674,11 +705,11 @@ static struct loption option[] =
}
},
{ OLETTER_NONE, &intr_optname,
STRING, 0, NULL, opt_intr,
O_STRING, 0, NULL, opt_intr,
{ "interrupt character: ", "s", NULL }
},
{ OLETTER_NONE, &wordwrap_optname,
BOOL|REPAINT, OPT_OFF, &wordwrap, NULL,
O_BOOL|O_REPAINT, OPT_OFF, &wordwrap, NULL,
{
"Wrap lines at any character",
"Wrap lines at spaces",
@@ -686,7 +717,7 @@ static struct loption option[] =
}
},
{ OLETTER_NONE, &show_preproc_error_optname,
BOOL, OPT_OFF, &show_preproc_error, NULL,
O_BOOL, OPT_OFF, &show_preproc_error, NULL,
{
"Don't show error message if preprocessor fails",
"Show error message if preprocessor fails",
@@ -694,7 +725,7 @@ static struct loption option[] =
}
},
{ OLETTER_NONE, &proc_backspace_optname,
TRIPLE|REPAINT|HL_REPAINT, OPT_OFF, &proc_backspace, NULL,
O_TRIPLE|O_REPAINT|O_HL_REPAINT, OPT_OFF, &proc_backspace, NULL,
{
"Backspace handling is specified by the -U option",
"Display underline text in underline mode",
@@ -702,7 +733,7 @@ static struct loption option[] =
}
},
{ OLETTER_NONE, &proc_tab_optname,
TRIPLE|REPAINT|HL_REPAINT, OPT_OFF, &proc_tab, NULL,
O_TRIPLE|O_REPAINT|O_HL_REPAINT, OPT_OFF, &proc_tab, NULL,
{
"Tab handling is specified by the -U option",
"Expand tabs to spaces",
@@ -710,7 +741,7 @@ static struct loption option[] =
}
},
{ OLETTER_NONE, &proc_return_optname,
TRIPLE|REPAINT|HL_REPAINT, OPT_OFF, &proc_return, NULL,
O_TRIPLE|O_REPAINT|O_HL_REPAINT, OPT_OFF, &proc_return, NULL,
{
"Carriage return handling is specified by the -U option",
"Delete carriage return before newline",
@@ -718,7 +749,7 @@ static struct loption option[] =
}
},
{ OLETTER_NONE, &match_shift_optname,
STRING|INIT_HANDLER, 0, NULL, opt_match_shift,
O_STRING|O_INIT_HANDLER, 0, NULL, opt_match_shift,
{
"Search match shift: ",
".d",
@@ -727,7 +758,7 @@ static struct loption option[] =
},
#if LESSTEST
{ OLETTER_NONE, &ttyin_name_optname,
STRING|NO_TOGGLE, 0, NULL, opt_ttyin_name,
O_STRING|O_NO_TOGGLE, 0, NULL, opt_ttyin_name,
{
NULL,
NULL,
@@ -735,7 +766,7 @@ static struct loption option[] =
}
},
#endif /*LESSTEST*/
{ '\0', NULL, NOVAR, 0, NULL, NULL, { NULL, NULL, NULL } }
{ '\0', NULL, O_NOVAR, 0, NULL, NULL, { NULL, NULL, NULL } }
};
@@ -748,7 +779,7 @@ public void init_option(void)
constant char *p;
p = lgetenv("LESS_IS_MORE");
if (!isnullenv(p))
if (!isnullenv(p) && !(p[0] == '0' && p[1] == '\0'))
less_is_more = 1;
for (o = option; o->oletter != '\0'; o++)
@@ -758,7 +789,7 @@ public void init_option(void)
*/
if (o->ovar != NULL)
*(o->ovar) = o->odefault;
if (o->otype & INIT_HANDLER)
if (o->otype & O_INIT_HANDLER)
(*(o->ofunc))(INIT, (char *) NULL);
}
}
@@ -774,7 +805,7 @@ public struct loption * findopt(int c)
{
if (o->oletter == c)
return (o);
if ((o->otype & TRIPLE) && ASCII_TO_UPPER(o->oletter) == c)
if ((o->otype & O_TRIPLE) && ASCII_TO_UPPER(o->oletter) == c)
return (o);
}
return (NULL);
@@ -857,7 +888,7 @@ public struct loption * findopt_name(constant char **p_optname, constant char **
ambig = FALSE;
exact = (len == strlen(oname->oname));
}
if (!(o->otype & TRIPLE))
if (!(o->otype & O_TRIPLE))
break;
}
}
@@ -876,3 +907,41 @@ public struct loption * findopt_name(constant char **p_optname, constant char **
*p_oname = maxoname == NULL ? NULL : maxoname->oname;
return (maxo);
}
/*
* Find all toggleable options whose names begin with a specified string.
* Return them in a space-separated string.
*/
public char * findopts_name(constant char *pfx)
{
constant struct loption *o;
constant struct optname *oname;
struct xbuffer xbuf;
int uppercase;
xbuf_init(&xbuf);
for (o = option; o->oletter != '\0'; o++)
{
if (o->otype & O_NO_TOGGLE)
continue;
for (oname = o->onames; oname != NULL; oname = oname->onext)
{
for (uppercase = 0; uppercase <= 1; uppercase++)
{
size_t len = sprefix(pfx, oname->oname, uppercase);
if (len >= strlen(pfx))
{
constant char *np;
for (np = oname->oname; *np != '\0'; np++)
xbuf_add_char(&xbuf, uppercase && ASCII_IS_LOWER(*np) ? ASCII_TO_UPPER(*np) : *np);
xbuf_add_char(&xbuf, ' ');
}
if (!(o->otype & O_TRIPLE))
break;
}
}
}
xbuf_pop(&xbuf); /* remove final space */
xbuf_add_char(&xbuf, '\0');
return (char *) xbuf.data;
}
+87 -30
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -32,6 +32,9 @@
#if HAVE_ERRNO_H
#include <errno.h>
#endif
#if MUST_DEFINE_ERRNO
extern int errno;
#endif
#if HAVE_VALUES_H
#include <values.h>
#endif
@@ -58,21 +61,35 @@ static lbool any_data = FALSE;
* On other systems, setjmp() doesn't affect the signal mask and so
* _setjmp() does not exist; we just use setjmp().
*/
#if HAVE__SETJMP && HAVE_SIGSETMASK
#define SET_JUMP _setjmp
#define LONG_JUMP _longjmp
#if HAVE_SIGSETJMP
#define SET_JUMP(label) sigsetjmp(label, 1)
#define LONG_JUMP(label, val) siglongjmp(label, val)
#define JUMP_BUF sigjmp_buf
#else
#define SET_JUMP setjmp
#define LONG_JUMP longjmp
#if HAVE__SETJMP && HAVE_SIGSETMASK
#define SET_JUMP(label) _setjmp(label)
#define LONG_JUMP(label, val) _longjmp(label, val)
#define JUMP_BUF jmp_buf
#else
#define SET_JUMP(label) setjmp(label)
#define LONG_JUMP(label, val) longjmp(label, val)
#define JUMP_BUF jmp_buf
#endif
#endif
public int reading;
static lbool reading;
static lbool opening;
public lbool waiting_for_data;
public int consecutive_nulls = 0;
public lbool getting_one_screen = FALSE;
/* Milliseconds to wait for data before displaying "waiting for data" message. */
static int waiting_for_data_delay = 4000;
static jmp_buf read_label;
/* Max milliseconds expected to "normally" read and display a screen of text. */
public int screenfill_ms = 3000;
static JUMP_BUF read_label;
static JUMP_BUF open_label;
extern int sigs;
extern int ignore_eoi;
@@ -81,6 +98,11 @@ extern int follow_mode;
extern int scanning_eof;
extern char intr_char;
extern int is_tty;
extern int quit_if_one_screen;
extern int one_screen;
#if HAVE_TIME
extern time_type less_start_time;
#endif
#if !MSDOS_COMPILER
extern int tty;
#endif
@@ -91,6 +113,10 @@ public void init_poll(void)
int idelay = (delay == NULL) ? 0 : atoi(delay);
if (idelay > 0)
waiting_for_data_delay = idelay;
delay = lgetenv("LESS_SCREENFILL_TIME");
idelay = (delay == NULL) ? 0 : atoi(delay);
if (idelay > 0)
screenfill_ms = idelay;
#if USE_POLL
#if defined(__APPLE__)
/* In old versions of MacOS, poll() does not work with /dev/tty. */
@@ -111,7 +137,11 @@ public void init_poll(void)
static int check_poll(int fd, int tty)
{
struct pollfd poller[2] = { { fd, POLLIN, 0 }, { tty, POLLIN, 0 } };
int timeout = (waiting_for_data && !(scanning_eof && follow_mode == FOLLOW_NAME)) ? -1 : waiting_for_data_delay;
int timeout = (waiting_for_data && !(scanning_eof && follow_mode == FOLLOW_NAME)) ? -1 : (ignore_eoi && !waiting_for_data) ? 0 : waiting_for_data_delay;
#if HAVE_TIME
if (getting_one_screen && get_time() < less_start_time + screenfill_ms/1000)
return (0);
#endif
if (!any_data)
{
/*
@@ -133,6 +163,7 @@ 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 (ignore_eoi && exit_F_on_close && (poller[0].revents & (POLLHUP|POLLIN)) == POLLHUP)
@@ -161,7 +192,7 @@ public int supports_ctrl_x(void)
/*
* Like read() system call, but is deliberately interruptible.
* A call to intread() from a signal handler will interrupt
* A call to intio() from a signal handler will interrupt
* any pending iread().
*/
public ssize_t iread(int fd, unsigned char *buf, size_t len)
@@ -188,7 +219,7 @@ start:
if (!reading && SET_JUMP(read_label))
{
/*
* We jumped here from intread.
* We jumped here from intio.
*/
reading = FALSE;
#if HAVE_SIGPROCMASK
@@ -238,7 +269,7 @@ start:
}
#endif
#if USE_POLL
if (is_tty && fd != tty && use_poll)
if (is_tty && fd != tty && use_poll && !(quit_if_one_screen && one_screen))
{
int ret = check_poll(fd, tty);
if (ret != 0)
@@ -251,24 +282,22 @@ start:
}
#else
#if MSDOS_COMPILER==WIN32C
if (win32_kbhit())
if (win32_kbhit2(TRUE))
{
int c;
c = WIN32getch();
if (c == intr_char)
{
sigs |= S_INTERRUPT;
reading = FALSE;
return (READ_INTR);
}
WIN32ungetch(c);
sigs |= S_INTERRUPT;
reading = FALSE;
if (c != CONTROL('C') && c != intr_char)
WIN32ungetch((char) c);
return (READ_INTR);
}
#endif
#endif
n = read(fd, buf, len);
reading = FALSE;
#if 1
#if 0
/*
* This is a kludge to workaround a problem on some systems
* where terminating a remote tty connection causes read() to
@@ -292,9 +321,6 @@ start:
/*
* Certain values of errno indicate we should just retry the read.
*/
#if MUST_DEFINE_ERRNO
extern int errno;
#endif
#ifdef EINTR
if (errno == EINTR)
goto start;
@@ -314,11 +340,45 @@ start:
}
/*
* Interrupt a pending iread().
* Like open() system call, but is interruptible.
*/
public void intread(void)
public int iopen(constant char *filename, int flags)
{
LONG_JUMP(read_label, 1);
int r;
while (!opening && SET_JUMP(open_label))
{
opening = FALSE;
if (sigs & S_INTERRUPT)
{
sigs = 0;
#if HAVE_SETTABLE_ERRNO
#ifdef EINTR
errno = EINTR;
#endif
#endif
return -1;
}
psignals(); /* Handle S_STOP or S_WINCH */
}
opening = TRUE;
r = open(filename, flags);
opening = FALSE;
return r;
}
/*
* Interrupt a pending iopen() or iread().
*/
public void intio(void)
{
if (opening)
{
LONG_JUMP(open_label, 1);
}
if (reading)
{
LONG_JUMP(read_label, 1);
}
}
/*
@@ -363,9 +423,6 @@ public char * errno_message(constant char *filename)
char *m;
size_t len;
#if HAVE_ERRNO
#if MUST_DEFINE_ERRNO
extern int errno;
#endif
p = strerror(errno);
#else
p = "cannot open";
+10 -9
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -49,7 +49,7 @@ extern int vt_enabled;
/*
* Display the line which is in the line buffer.
*/
public void put_line(void)
public void put_line(lbool forw_scroll)
{
int c;
size_t i;
@@ -75,8 +75,10 @@ public void put_line(void)
else
putchr(c);
}
at_exit();
if (forw_scroll && should_clear_after_line())
clear_eol();
}
/*
@@ -243,18 +245,17 @@ static void set_win_colors(t_sgr *sgr)
}
/* like is_ansi_end, but doesn't assume c != 0 (returns 0 for c == 0) */
static int is_ansi_end_0(char c)
static lbool is_ansi_end_0(char c)
{
return c && is_ansi_end((unsigned char)c);
return c != '\0' && is_ansi_end((unsigned char)c);
}
static void win_flush(void)
{
if (ctldisp != OPT_ONPLUS
#if MSDOS_COMPILER==WIN32C
|| (vt_enabled && sgr_mode)
#if MSDOS_COMPILER != WIN32C
static constant int vt_enabled = 0;
#endif
)
if (ctldisp != OPT_ONPLUS || (vt_enabled && sgr_mode))
WIN32textout(obuf, ptr_diff(ob, obuf));
else
{
+36 -16
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -81,6 +81,7 @@ static int compile_pattern2(constant char *pattern, int search_type, PATTERN_TYP
PCRE2_SIZE erroffset;
PARG parg;
pcre2_code *comp = pcre2_compile((PCRE2_SPTR)pattern, strlen(pattern),
((utf_mode) ? PCRE2_UTF | PCRE2_NO_UTF_CHECK : 0) |
(is_caseless ? PCRE2_CASELESS : 0),
&errcode, &erroffset, NULL);
if (comp == NULL)
@@ -295,7 +296,7 @@ static int match(constant char *pattern, size_t pattern_len, constant char *buf,
* Set sp[i] and ep[i] to the start and end of the i-th matched subpattern.
* Subpatterns are defined by parentheses in the regex language.
*/
static int match_pattern1(PATTERN_TYPE pattern, constant char *tpattern, constant char *line, size_t aline_len, constant char **sp, constant char **ep, int nsp, int notbol, int search_type)
static lbool match_pattern1(PATTERN_TYPE pattern, constant char *tpattern, constant char *line, size_t aline_len, size_t line_off, constant char **sp, constant char **ep, int nsp, int notbol, int search_type)
{
int matched;
int line_len = (int) aline_len; /*{{type-issue}}*/
@@ -304,7 +305,7 @@ static int match_pattern1(PATTERN_TYPE pattern, constant char *tpattern, constan
search_type |= SRCH_NO_REGEX;
#endif
if (search_type & SRCH_NO_REGEX)
matched = match(tpattern, strlen(tpattern), line, line_len, &sp, &ep, nsp);
matched = match(tpattern, strlen(tpattern), line + line_off, line_len - line_off, &sp, &ep, nsp);
else
{
#if HAVE_GNU_REGEX
@@ -312,7 +313,7 @@ static int match_pattern1(PATTERN_TYPE pattern, constant char *tpattern, constan
struct re_registers search_regs;
pattern->not_bol = notbol;
pattern->regs_allocated = REGS_UNALLOCATED;
matched = re_search(pattern, line, line_len, 0, line_len, &search_regs) >= 0;
matched = re_search(pattern, line, line_len, line_off, line_len - line_off, &search_regs) >= 0;
if (matched)
{
*sp++ = line + search_regs.start[0];
@@ -327,8 +328,10 @@ static int match_pattern1(PATTERN_TYPE pattern, constant char *tpattern, constan
int flags = (notbol) ? REG_NOTBOL : 0;
#ifdef REG_STARTEND
flags |= REG_STARTEND;
rm[0].rm_so = 0;
rm[0].rm_so = line_off;
rm[0].rm_eo = line_len;
#else
line += line_off;
#endif
matched = !regexec(pattern, line, RM_COUNT, rm, flags);
if (matched)
@@ -367,7 +370,7 @@ static int match_pattern1(PATTERN_TYPE pattern, constant char *tpattern, constan
int i;
int ecount;
int mcount = pcre_exec(pattern, NULL, line, line_len,
0, flags, ovector, OVECTOR_COUNT);
line_off, flags, ovector, OVECTOR_COUNT);
matched = (mcount > 0);
ecount = nsp-1;
if (ecount > mcount) ecount = mcount;
@@ -390,7 +393,7 @@ static int match_pattern1(PATTERN_TYPE pattern, constant char *tpattern, constan
int flags = (notbol) ? PCRE2_NOTBOL : 0;
pcre2_match_data *md = pcre2_match_data_create(nsp-1, NULL);
int mcount = pcre2_match(pattern, (PCRE2_SPTR)line, line_len,
0, flags, md, NULL);
line_off, flags, md, NULL);
matched = (mcount > 0);
if (matched)
{
@@ -415,21 +418,21 @@ static int match_pattern1(PATTERN_TYPE pattern, constant char *tpattern, constan
}
#endif
#if HAVE_RE_COMP
matched = (re_exec(line) == 1);
matched = (re_exec(line + line_off) == 1);
/*
* re_exec doesn't seem to provide a way to get the matched string.
*/
#endif
#if HAVE_REGCMP
matched = ((*ep++ = regex(pattern, line)) != NULL);
matched = ((*ep++ = regex(pattern, line + line_off)) != NULL);
if (matched)
*sp++ = __loc1;
#endif
#if HAVE_V8_REGCOMP
#if HAVE_REGEXEC2
matched = regexec2(pattern, line, notbol);
matched = regexec2(pattern, line + line_off, notbol);
#else
matched = regexec(pattern, line);
matched = regexec(pattern, line + line_off);
#endif
if (matched)
{
@@ -441,19 +444,36 @@ static int match_pattern1(PATTERN_TYPE pattern, constant char *tpattern, constan
*sp = *ep = NULL;
matched = (!(search_type & SRCH_NO_MATCH) && matched) ||
((search_type & SRCH_NO_MATCH) && !matched);
return (matched);
return (matched != 0);
}
public int match_pattern(PATTERN_TYPE pattern, constant char *tpattern, constant char *line, size_t line_len, constant char **sp, constant char **ep, int nsp, int notbol, int search_type)
/*
* Return TRUE if the match satisfies all SUBSEARCH conditions.
*/
static lbool subsearch_ok(constant char **sp, constant char **ep, int search_type)
{
int matched = match_pattern1(pattern, tpattern, line, line_len, sp, ep, nsp, notbol, search_type);
int i;
for (i = 1; i <= NUM_SEARCH_COLORS; i++)
{
if ((search_type & SRCH_SUBSEARCH(i)) && ep[i] == sp[i])
matched = 0;
return FALSE;
}
return TRUE;
}
public lbool match_pattern(PATTERN_TYPE pattern, constant char *tpattern, constant char *line, size_t line_len, size_t line_off, constant char **sp, constant char **ep, int nsp, int notbol, int search_type)
{
for (;;)
{
size_t mlen;
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;
line += mlen;
line_len -= mlen;
notbol = 1;
}
return matched;
}
/*
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
+11 -4
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -26,6 +26,7 @@ static int table_size = 0;
extern int sc_width, sc_height;
extern int hshift;
extern int shell_lines;
/*
* Return the starting file position of a line displayed on the screen.
@@ -46,6 +47,9 @@ public POSITION position(int sindex)
case BOTTOM_PLUS_ONE:
sindex = sc_height - 1;
break;
case BOTTOM_OFFSET:
sindex = sc_height - shell_lines;
break;
case MIDDLE:
sindex = (sc_height - 1) / 2;
break;
@@ -56,15 +60,18 @@ public POSITION position(int sindex)
/*
* Add a new file position to the bottom of the position table.
*/
public void add_forw_pos(POSITION pos)
public void add_forw_pos(POSITION pos, lbool no_scroll)
{
int i;
/*
* Scroll the position table up.
*/
for (i = 1; i < sc_height; i++)
table[i-1] = table[i];
if (!no_scroll)
{
for (i = 1; i < sc_height; i++)
table[i-1] = table[i];
}
table[sc_height - 1] = pos;
}
+2 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -16,3 +16,4 @@
#define BOTTOM (-1)
#define BOTTOM_PLUS_ONE (-2)
#define MIDDLE (-3)
#define BOTTOM_OFFSET (-4)
+5 -6
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -203,7 +203,7 @@ static lbool cond(char c, int where)
case 'c':
return (hshift != 0);
case 'e': /* At end of file? */
return (eof_displayed());
return (eof_displayed(FALSE));
case 'f': /* Filename known? */
case 'g':
return (strcmp(get_filename(curr_ifile), "-") != 0);
@@ -257,7 +257,6 @@ static void protochar(char c, int where)
{
POSITION pos;
POSITION len;
int n;
LINENUM linenum;
LINENUM last_linenum;
IFILE h;
@@ -341,15 +340,15 @@ static void protochar(char c, int where)
else
ap_linenum(vlinenum(linenum-1));
break;
case 'm': /* Number of files */
case 'm': { /* Number of files */
#if TAGS
n = ntags();
int n = ntags();
if (n)
ap_int(n);
else
#endif
ap_int(nifile());
break;
break; }
case 'o': /* path (URI without protocol) of selected OSC8 link */
#if OSC8_LINK
if (osc8_path != NULL)
+81 -39
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -145,7 +145,7 @@ static HANDLE con_out_ours = INVALID_HANDLE_VALUE; /* our own */
HANDLE con_out = INVALID_HANDLE_VALUE; /* current console */
extern int utf_mode;
extern int quitting;
extern lbool quitting;
static void win32_init_term();
static void win32_deinit_term();
@@ -219,6 +219,8 @@ static constant char
*sc_e_keypad, /* End keypad mode */
*sc_s_mousecap, /* Start mouse capture mode */
*sc_e_mousecap, /* End mouse capture mode */
*sc_s_bracketed_paste, /* Start bracketed paste mode */
*sc_e_bracketed_paste, /* End bracketed paste mode */
*sc_init, /* Startup terminal initialization */
*sc_deinit; /* Exit terminal de-initialization */
@@ -240,9 +242,9 @@ public int so_s_width, so_e_width; /* Printing width of standout seq */
public int bl_s_width, bl_e_width; /* Printing width of blink seq */
public int above_mem, below_mem; /* Memory retained above/below screen */
public int can_goto_line; /* Can move cursor to any line */
public int clear_bg; /* Clear fills with background color */
public int missing_cap = 0; /* Some capability is missing */
public constant char *kent = NULL; /* Keypad ENTER sequence */
public int clear_bg; /* Clear fills with background color */
public lbool missing_cap = FALSE; /* Some capability is missing */
public constant char *kent = NULL; /* Keypad ENTER sequence */
public lbool term_init_done = FALSE;
public lbool full_screen = TRUE;
@@ -251,6 +253,7 @@ static int termcap_debug = -1;
static int no_alt_screen; /* sc_init does not switch to alt screen */
extern int binattr;
extern int one_screen;
extern int shell_lines;
#if !MSDOS_COMPILER
static constant char *cheaper(constant char *t1, constant char *t2, constant char *def);
@@ -283,6 +286,7 @@ extern int oldbot;
extern int mousecap;
extern int is_tty;
extern int use_color;
extern int no_paste;
#if HILITE_SEARCH
extern int hilite_search;
#endif
@@ -324,17 +328,6 @@ static void set_termio_flags(
);
s->c_oflag |= (0
#ifdef OXTABS
| OXTABS
#else
#ifdef TAB3
| TAB3
#else
#ifdef XTABS
| XTABS
#endif
#endif
#endif
#ifdef OPOST
| OPOST
#endif
@@ -624,7 +617,7 @@ public void raw_mode(int on)
* Set the modes to the way we want them.
*/
s.sg_flags |= CBREAK;
s.sg_flags &= ~(ECHO|XTABS);
s.sg_flags &= ~(ECHO);
} else
{
/*
@@ -1325,10 +1318,17 @@ public void get_term(void)
sc_s_mousecap = ltgetstr("MOUSE_START", &sp);
if (sc_s_mousecap == NULL)
sc_s_mousecap = ESCS "[?1000h" ESCS "[?1006h";
sc_s_mousecap = ESCS "[?1000h" ESCS "[?1002h" ESCS "[?1006h";
sc_e_mousecap = ltgetstr("MOUSE_END", &sp);
if (sc_e_mousecap == NULL)
sc_e_mousecap = ESCS "[?1006l" ESCS "[?1000l";
sc_e_mousecap = ESCS "[?1006l" ESCS "[?1002l" ESCS "[?1000l";
sc_s_bracketed_paste = ltgetstr("BRACKETED_PASTE_START", &sp);
if (sc_s_bracketed_paste == NULL)
sc_s_bracketed_paste = ESCS"[?2004h";
sc_e_bracketed_paste = ltgetstr("BRACKETED_PASTE_END", &sp);
if (sc_e_bracketed_paste == NULL)
sc_e_bracketed_paste = ESCS"[?2004l";
sc_init = ltgetstr("ti", &sp);
if (sc_init == NULL)
@@ -1341,21 +1341,21 @@ public void get_term(void)
sc_eol_clear = ltgetstr("ce", &sp);
if (sc_eol_clear == NULL || *sc_eol_clear == '\0')
{
missing_cap = 1;
missing_cap = TRUE;
sc_eol_clear = "";
}
sc_eos_clear = ltgetstr("cd", &sp);
if (below_mem && (sc_eos_clear == NULL || *sc_eos_clear == '\0'))
{
missing_cap = 1;
missing_cap = TRUE;
sc_eos_clear = "";
}
sc_clear = ltgetstr("cl", &sp);
if (sc_clear == NULL || *sc_clear == '\0')
{
missing_cap = 1;
missing_cap = TRUE;
sc_clear = "\n\n";
}
@@ -1441,12 +1441,9 @@ public void get_term(void)
t2 = ltgetstr("sr", &sp);
if (t2 == NULL)
t2 = "";
#if OS2
if (*t1 == '\0' && *t2 == '\0')
sc_addline = "";
else
#endif
if (above_mem)
else if (above_mem)
sc_addline = t1;
else
sc_addline = cheaper(t1, t2, "");
@@ -1459,6 +1456,12 @@ public void get_term(void)
}
}
#endif /* MSDOS_COMPILER */
{
const char *env = lgetenv("LESS_SHELL_LINES");
shell_lines = isnullenv(env) ? 1 : atoi(env);
if (shell_lines >= sc_height)
shell_lines = sc_height - 1;
}
}
#if !MSDOS_COMPILER
@@ -1494,7 +1497,7 @@ static constant char * cheaper(constant char *t1, constant char *t2, constant ch
{
if (*t1 == '\0' && *t2 == '\0')
{
missing_cap = 1;
missing_cap = TRUE;
return (def);
}
if (*t1 == '\0')
@@ -1590,17 +1593,17 @@ static void initcolor(void)
*/
static void win32_init_vt_term(void)
{
DWORD console_output_mode;
if (vt_enabled == 0 || (vt_enabled == 1 && con_out == con_out_ours))
return;
return; // already initialized
console_output_mode = init_console_output_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING;
vt_enabled = SetConsoleMode(con_out, console_output_mode);
/* don't care about the initial mode, and win VT hard-enables am+xn */
vt_enabled = SetConsoleMode(con_out, ENABLE_PROCESSED_OUTPUT |
ENABLE_VIRTUAL_TERMINAL_PROCESSING |
ENABLE_WRAP_AT_EOL_OUTPUT);
if (vt_enabled)
{
auto_wrap = 0;
ignaw = 1;
auto_wrap = 1;
ignaw = 1;
}
}
@@ -1635,6 +1638,12 @@ static void win32_init_term(void)
(LPSECURITY_ATTRIBUTES) NULL,
CONSOLE_TEXTMODE_BUFFER,
(LPVOID) NULL);
// we don't care about the initial state. we need processed
// output without anything else (no wrap at EOL, no VT,
// no disabled auto-return).
if (SetConsoleMode(con_out_ours, ENABLE_PROCESSED_OUTPUT))
auto_wrap = 0;
}
size.X = scr.srWindow.Right - scr.srWindow.Left + 1;
@@ -1772,6 +1781,8 @@ public void init(void)
ltputs(sc_s_keypad, sc_height, putchr);
if (mousecap)
init_mouse();
if (no_paste)
init_bracketed_paste();
}
init_done = 1;
if (top_scroll)
@@ -1821,6 +1832,8 @@ public void deinit(void)
{
if (mousecap)
deinit_mouse();
if (no_paste)
deinit_bracketed_paste();
if (!no_keypad)
ltputs(sc_e_keypad, sc_height, putchr);
if (!no_init)
@@ -2444,6 +2457,25 @@ public void clear_bot(void)
}
}
/*
* Enable or disable bracketed paste mode.
* When enabled, the terminal sends an "open bracket" sequence
* before pasted content and "close bracket" after it.
*/
public void init_bracketed_paste(void)
{
#if !MSDOS_COMPILER
ltputs(sc_s_bracketed_paste, 1, putchr);
#endif
}
public void deinit_bracketed_paste(void)
{
#if !MSDOS_COMPILER
ltputs(sc_e_bracketed_paste, 1, putchr);
#endif
}
/*
* Color string may be "x[y]" where x and y are 4-bit color chars,
* or "N[.M]" where N and M are decimal integers>
@@ -2953,8 +2985,7 @@ static lbool win32_mouse_event(XINPUT_RECORD *xip)
{
char b;
if (!mousecap || xip->ir.EventType != MOUSE_EVENT ||
xip->ir.Event.MouseEvent.dwEventFlags == MOUSE_MOVED)
if (!mousecap || xip->ir.EventType != MOUSE_EVENT)
return (FALSE);
/* Generate an X11 mouse sequence from the mouse event. */
@@ -2976,6 +3007,12 @@ static lbool win32_mouse_event(XINPUT_RECORD *xip)
case MOUSE_WHEELED:
b = X11MOUSE_OFFSET + (((int)xip->ir.Event.MouseEvent.dwButtonState < 0) ? X11MOUSE_WHEEL_DOWN : X11MOUSE_WHEEL_UP);
break;
case MOUSE_MOVED:
if (xip->ir.Event.MouseEvent.dwButtonState != 1)
return (FALSE);
/* Drag with left button down. */
b = X11MOUSE_OFFSET + X11MOUSE_DRAG;
break;
default:
return (FALSE);
}
@@ -3123,11 +3160,11 @@ static lbool win32_key_event(XINPUT_RECORD *xip)
/*
* Determine whether an input character is waiting to be read.
*/
public lbool win32_kbhit(void)
public lbool win32_kbhit2(lbool no_queued)
{
XINPUT_RECORD xip;
if (win32_queued_char())
if (!no_queued && win32_queued_char())
return (TRUE);
for (;;)
@@ -3152,6 +3189,11 @@ public lbool win32_kbhit(void)
return (TRUE);
}
public lbool win32_kbhit(void)
{
return win32_kbhit2(FALSE);
}
/*
* Read a character from the keyboard.
*/
@@ -3201,7 +3243,7 @@ public void WIN32textout(constant char *text, size_t len)
len = MultiByteToWideChar(CP_UTF8, 0, text, len, wtext, countof(wtext));
WriteConsoleW(con_out, wtext, len, &written, NULL);
} else
WriteConsole(con_out, text, len, &written, NULL);
WriteConsole(con_out, text, (DWORD) len, &written, NULL);
#else
char buf[2048];
if (len >= sizeof(buf))
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
+71 -113
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -44,10 +44,8 @@ extern int header_cols;
extern LWCHAR rscroll_char;
#if HILITE_SEARCH
extern int hilite_search;
extern size_t size_linebuf;
extern lbool squished;
extern int can_goto_line;
extern lbool no_eof_bell;
static lbool hide_hilite;
static POSITION prep_startpos;
static POSITION prep_endpos;
@@ -245,7 +243,7 @@ public int get_cvt_ops(int search_type)
/*
* Is there a previous (remembered) search pattern?
*/
static int prev_pattern(struct pattern_info *info)
static lbool prev_pattern(struct pattern_info *info)
{
#if !NO_REGEX
if ((info->search_type & SRCH_NO_REGEX) == 0)
@@ -289,10 +287,10 @@ public void repaint_hilite(lbool on)
pos = position(sindex);
if (pos == NULL_POSITION)
continue;
(void) forw_line(pos);
(void) forw_line(pos, NULL, NULL);
goto_line(sindex);
clear_eol();
put_line();
put_line(FALSE);
}
overlay_header();
lower_left();
@@ -336,10 +334,10 @@ public void clear_attn(void)
if (pos <= old_end_attnpos &&
(epos == NULL_POSITION || epos > old_start_attnpos))
{
(void) forw_line(pos);
(void) forw_line(pos, NULL, NULL);
goto_line(sindex);
clear_eol();
put_line();
put_line(FALSE);
moved = 1;
}
}
@@ -356,9 +354,7 @@ public void clear_attn(void)
public void undo_search(lbool clear)
{
clear_pattern(&search_info);
#if OSC8_LINK
osc8_linepos = NULL_POSITION;
#endif
undo_osc8();
#if HILITE_SEARCH
if (clear)
{
@@ -376,6 +372,15 @@ public void undo_search(lbool clear)
#endif
}
/*
*/
public void undo_osc8(void)
{
#if OSC8_LINK
osc8_linepos = NULL_POSITION;
#endif
}
#if HILITE_SEARCH
/*
* Clear the hilite list.
@@ -537,7 +542,7 @@ public void set_header(POSITION pos)
/*
* Is a position within the header lines?
*/
static int pos_in_header(POSITION pos)
static lbool pos_in_header(POSITION pos)
{
return (header_start_pos != NULL_POSITION &&
pos >= header_start_pos && pos < header_end_pos);
@@ -550,11 +555,10 @@ public lbool is_filtered(POSITION pos)
{
struct hilite_node *n;
if (ch_getflags() & CH_HELPFILE)
if (!is_filtering())
return (FALSE);
if (pos_in_header(pos))
return (FALSE);
n = hlist_find(&filter_anchor, pos);
return (n != NULL && pos >= n->r.hl_startpos);
}
@@ -565,45 +569,19 @@ public lbool is_filtered(POSITION pos)
*/
public POSITION next_unfiltered(POSITION pos)
{
struct hilite_node *n;
if (ch_getflags() & CH_HELPFILE)
if (!is_filtering())
return (pos);
if (pos_in_header(pos))
return (pos);
n = hlist_find(&filter_anchor, pos);
while (n != NULL && pos >= n->r.hl_startpos)
flush();
while (pos != NULL_POSITION)
{
pos = n->r.hl_endpos;
n = n->next;
}
return (pos);
}
/*
* If pos is hidden, return the previous position which isn't or 0 if
* we're filtered right to the beginning, otherwise just return pos.
*/
public POSITION prev_unfiltered(POSITION pos)
{
struct hilite_node *n;
if (ch_getflags() & CH_HELPFILE)
return (pos);
if (pos_in_header(pos))
return (pos);
n = hlist_find(&filter_anchor, pos);
while (n != NULL && pos >= n->r.hl_startpos)
{
pos = n->r.hl_startpos;
if (pos == 0)
prep_hilite(pos, NULL_POSITION, 1);
if (!is_filtered(pos))
break;
pos--;
n = n->prev;
pos = forw_raw_line(pos, NULL, NULL);
}
return (pos);
return pos;
}
/*
@@ -661,7 +639,7 @@ public int is_hilited_attr(POSITION pos, POSITION epos, int nohide, int *p_match
#if OSC8_LINK
if (osc8_linepos != NULL_POSITION &&
pos <= osc8_text_end && (epos == NULL_POSITION || epos > osc8_text_start))
pos < osc8_text_end && (epos == NULL_POSITION || epos > osc8_text_start))
return (AT_HILITE|AT_COLOR_SEARCH);
#endif
@@ -1017,8 +995,7 @@ static void create_hilites(POSITION linepos, constant char *line, constant char
*/
static void hilite_line(POSITION linepos, constant char *line, size_t line_len, int *chpos, constant char **sp, constant char **ep, int nsp)
{
constant char *searchp;
constant char *line_end = line + line_len;
size_t line_off = 0;
/*
* sp[0] and ep[0] delimit the first match in the line.
@@ -1032,7 +1009,6 @@ static void hilite_line(POSITION linepos, constant char *line, size_t line_len,
* sp[i] and ep[i] for i>0 delimit subpattern matches.
* Color each of them with its unique color.
*/
searchp = line;
do {
constant char *lep = sp[0];
int i;
@@ -1059,14 +1035,14 @@ static void hilite_line(POSITION linepos, constant char *line, size_t line_len,
* move to the first char after the string we matched.
* If we matched zero, just move to the next char.
*/
if (ep[0] > searchp)
searchp = ep[0];
else if (searchp != line_end)
searchp++;
if (ep[0] > &line[line_off])
line_off = ptr_diff(ep[0], line);
else if (line_off != line_len)
line_off++;
else /* end of line */
break;
} while (match_pattern(info_compiled(&search_info), search_info.text,
searchp, ptr_diff(line_end, searchp), sp, ep, nsp, 1, search_info.search_type));
line, line_len, line_off, sp, ep, nsp, 1, search_info.search_type));
}
#endif
@@ -1200,14 +1176,14 @@ static POSITION search_pos(int search_type)
* If so, add an entry to the filter list.
*/
#if HILITE_SEARCH
static int matches_filters(POSITION pos, char *cline, size_t line_len, int *chpos, POSITION linepos, constant char **sp, constant char **ep, int nsp)
static lbool matches_filters(POSITION pos, char *cline, size_t line_len, int *chpos, POSITION linepos, constant char **sp, constant char **ep, int nsp)
{
struct pattern_info *filter;
for (filter = filter_infos; filter != NULL; filter = filter->next)
{
int line_filter = match_pattern(info_compiled(filter), filter->text,
cline, line_len, sp, ep, nsp, 0, filter->search_type);
lbool line_filter = match_pattern(info_compiled(filter), filter->text,
cline, line_len, 0, sp, ep, nsp, 0, filter->search_type);
if (line_filter)
{
struct hilite hl;
@@ -1216,10 +1192,10 @@ static int matches_filters(POSITION pos, char *cline, size_t line_len, int *chpo
add_hilite(&filter_anchor, &hl);
free(cline);
free(chpos);
return (1);
return (TRUE);
}
}
return (0);
return (FALSE);
}
#endif
@@ -1231,9 +1207,10 @@ static POSITION get_lastlinepos(POSITION pos, POSITION tpos, int sheight)
{
int nlines;
flush();
for (nlines = 0;; nlines++)
{
POSITION npos = forw_line(pos);
POSITION npos = forw_line(pos, NULL, NULL);
if (npos > tpos)
{
if (nlines < sheight)
@@ -1264,12 +1241,14 @@ struct osc8_parse_info {
static lbool osc8_parse(constant char *line, constant char *line_end, struct osc8_parse_info *pop)
{
constant char *oline;
pop->osc8_start = pop->osc8_end = pop->uri_start = pop->uri_end = pop->params_start = pop->params_end = NULL;
LWCHAR ch;
struct ansi_state *pansi;
pop->osc8_start = pop->osc8_end = pop->uri_start = pop->uri_end = pop->params_start = pop->params_end = NULL;
oline = line;
LWCHAR ch = step_charc(&line, +1, line_end);
ch = step_charc(&line, +1, line_end);
/* oline points to character ch, line points to the one after it. */
struct ansi_state *pansi = ansi_start(ch);
pansi = ansi_start(ch);
if (pansi == NULL)
return FALSE;
pop->osc8_start = oline; /* start at the ESC */
@@ -1292,12 +1271,14 @@ static lbool osc8_parse(constant char *line, constant char *line_end, struct osc
pop->uri_start = line;
}
break;
case OSC8_ST_ESC:
case OSC_END_CSI:
if (pop->uri_end == NULL)
pop->uri_end = oline;
break;
case OSC8_END:
case OSC_END:
ansi_done(pansi);
if (pop->params_start == NULL || pop->uri_start == NULL)
return FALSE;
pop->osc8_end = line;
if (pop->uri_end == NULL) /* happens when ST is "\7" */
pop->uri_end = oline;
@@ -1503,7 +1484,7 @@ static int search_range(POSITION pos, POSITION endpos, int search_type, int matc
#define NSP (NUM_SEARCH_COLORS+2)
constant char *sp[NSP];
constant char *ep[NSP];
int line_match;
lbool line_match;
int cvt_ops;
size_t cvt_len;
int *chpos;
@@ -1524,6 +1505,7 @@ static int search_range(POSITION pos, POSITION endpos, int search_type, int matc
/* When the search wraps around, end at starting position. */
if ((search_type & SRCH_WRAP) && endpos == NULL_POSITION)
endpos = pos;
flush();
for (;;)
{
/*
@@ -1677,7 +1659,7 @@ static int search_range(POSITION pos, POSITION endpos, int search_type, int matc
if (prev_pattern(&search_info))
{
line_match = match_pattern(info_compiled(&search_info), search_info.text,
cline, line_len, sp, ep, NSP, 0, search_type);
cline, line_len, 0, sp, ep, NSP, 0, search_type);
if (line_match)
{
/*
@@ -1761,8 +1743,9 @@ public void osc8_search(int search_type, constant char *param, int matches)
{
POSITION pos;
int match;
int curr_sindex = -1;
if (osc8_linepos != NULL_POSITION)
if (osc8_linepos != NULL_POSITION && (curr_sindex = onscreen(osc8_linepos)) >= 0)
{
/* Continue search in same line as current match. */
constant char *line;
@@ -1772,9 +1755,6 @@ public void osc8_search(int search_type, constant char *param, int matches)
{
if (osc8_search_line(search_type, osc8_linepos, line, line_len, param, NULL_POSITION, &matches) != OSC8_NO_MATCH)
{
no_eof_bell = TRUE;
jump_loc(osc8_linepos, jump_sline);
no_eof_bell = FALSE;
osc8_shift_visible();
#if HILITE_SEARCH
repaint_hilite(TRUE);
@@ -1784,7 +1764,14 @@ public void osc8_search(int search_type, constant char *param, int matches)
}
search_type |= SRCH_AFTER_TARGET;
}
pos = search_pos(search_type);
/*
* If the current OSC 8 link is on screen, start searching after it.
* Otherwise, start searching at the -j line like a normal search.
*/
if (curr_sindex >= 0)
pos = osc8_linepos;
else
pos = search_pos(search_type);
if (pos == NULL_POSITION)
{
error("Nothing to search", NULL_PARG);
@@ -1798,7 +1785,9 @@ public void osc8_search(int search_type, constant char *param, int matches)
error("OSC 8 link not found", NULL_PARG);
return;
}
jump_loc(pos, jump_sline);
/* If new link is on screen, just highlight it without scrolling. */
if (onscreen(pos) < 0)
jump_loc(pos, jump_sline);
#if HILITE_SEARCH
repaint_hilite(TRUE);
#endif
@@ -1843,7 +1832,7 @@ public lbool osc8_click(int sindex, int col)
/*
* Return the length of the scheme prefix in a URI.
*/
static int scheme_length(constant char *uri, size_t uri_len)
static size_t scheme_length(constant char *uri, size_t uri_len)
{
size_t plen;
for (plen = 0; plen < uri_len; plen++)
@@ -1930,13 +1919,13 @@ public void osc8_open(void)
#if HAVE_POPEN
if (bad_uri(op.uri_start, uri_len))
{
error("Cannot open link containing dangerous characters", NULL_PARG);
error("Cannot open link containing quote characters", NULL_PARG);
return;
}
SNPRINTF3(env_name, sizeof(env_name), "%s%.*s", env_name_pfx, (int) scheme_len, op.uri_start);
handler = lgetenv(env_name);
if (isnullenv(handler) || strcmp(handler, "-") == 0)
handler = lgetenv("LESS_OSC8_ANY");
handler = lgetenv("LESS_OSC8_ANY");
if (isnullenv(handler))
{
PARG parg;
@@ -2212,12 +2201,6 @@ public void prep_hilite(POSITION spos, POSITION epos, int maxlines)
int result;
int i;
/*
* Search beyond where we're asked to search, so the prep region covers
* more than we need. Do one big search instead of a bunch of small ones.
*/
POSITION SEARCH_MORE = (POSITION) (3*size_linebuf);
if (!prev_pattern(&search_info) && !is_filtering())
return;
@@ -2239,6 +2222,8 @@ public void prep_hilite(POSITION spos, POSITION epos, int maxlines)
for (i = 0; i < maxlines; i++)
max_epos = forw_raw_line(max_epos, NULL, NULL);
}
if (epos == NULL_POSITION || (max_epos != NULL_POSITION && epos > max_epos))
epos = max_epos;
/*
* Find two ranges:
@@ -2256,28 +2241,13 @@ public void prep_hilite(POSITION spos, POSITION epos, int maxlines)
*/
clr_hilite();
clr_filter();
if (epos != NULL_POSITION)
epos += SEARCH_MORE;
nprep_startpos = spos;
} else
{
/*
* New range partially or completely overlaps old prep region.
*/
if (epos == NULL_POSITION)
{
/*
* New range goes to end of file.
*/
;
} else if (epos > prep_endpos)
{
/*
* New range ends after old prep region.
* Extend prep region to end at end of new range.
*/
epos += SEARCH_MORE;
} else /* (epos <= prep_endpos) */
if (epos != NULL_POSITION && epos <= prep_endpos)
{
/*
* New range ends within old prep region.
@@ -2285,7 +2255,6 @@ public void prep_hilite(POSITION spos, POSITION epos, int maxlines)
*/
epos = prep_startpos;
}
if (spos < prep_startpos)
{
/*
@@ -2293,10 +2262,6 @@ public void prep_hilite(POSITION spos, POSITION epos, int maxlines)
* Extend old prep region backwards to start at
* start of new range.
*/
if (spos < SEARCH_MORE)
spos = 0;
else
spos -= SEARCH_MORE;
nprep_startpos = spos;
} else /* (spos >= prep_startpos) */
{
@@ -2308,17 +2273,10 @@ public void prep_hilite(POSITION spos, POSITION epos, int maxlines)
}
}
if (epos != NULL_POSITION && max_epos != NULL_POSITION &&
epos > max_epos)
/*
* Don't go past the max position we're allowed.
*/
epos = max_epos;
if (epos == NULL_POSITION || epos > spos)
{
int search_type = SRCH_FORW | SRCH_FIND_ALL;
search_type |= (search_info.search_type & (SRCH_NO_REGEX|SRCH_SUBSEARCH_ALL));
search_type |= (search_info.search_type & SRCH_NO_REGEX);
for (;;)
{
result = search_range(spos, epos, search_type, 0, maxlines, (POSITION*)NULL, &new_epos, (POSITION*)NULL);
+42 -13
View File
@@ -1,5 +1,6 @@
#include <errno.h>
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -16,7 +17,7 @@
* At some convenient time, the mainline code checks to see if any
* signals need processing by calling psignal().
* If we happen to be reading from a file [in iread()] at the time
* the signal is received, we call intread to interrupt the iread.
* the signal is received, we call intio to interrupt the iread.
*/
#include "less.h"
@@ -30,7 +31,6 @@ public int sigs;
extern int sc_width, sc_height;
extern int linenums;
extern int wscroll;
extern int reading;
extern int quit_on_intr;
extern long jump_sline_fraction;
@@ -64,8 +64,7 @@ static RETSIGTYPE u_interrupt(int type)
#if HILITE_SEARCH
set_filter_pattern(NULL, 0);
#endif
if (reading)
intread(); /* May longjmp */
intio();
}
#endif
@@ -79,8 +78,7 @@ static RETSIGTYPE stop(int type)
(void) type;
LSIGNAL(SIGTSTP, stop);
sigs |= S_STOP;
if (reading)
intread();
intio();
}
#endif
@@ -102,9 +100,17 @@ public RETSIGTYPE winch(int type)
{
(void) type;
LSIGNAL(SIG_LESSWINDOW, winch);
#if LESSTEST
/*
* Ignore window changes during lesstest.
* Changes in the real window are unrelated to the simulated
* screen used by lesstest.
*/
if (is_lesstest())
return;
#endif
sigs |= S_WINCH;
if (reading)
intread();
intio();
}
#endif
@@ -139,6 +145,27 @@ static RETSIGTYPE terminate(int type)
quit(15);
}
/*
* Handle a SIGUSR signal.
*/
#ifdef SIGUSR1
static void sigusr(constant char *var)
{
constant char *cmd = lgetenv(var);
if (isnullenv(cmd))
return;
ungetsc(cmd);
intio();
}
static RETSIGTYPE sigusr1(int type)
{
(void) type;
LSIGNAL(SIGUSR1, sigusr1);
sigusr("LESS_SIGUSR1");
}
#endif
/*
* Set up the signal handlers.
*/
@@ -168,6 +195,9 @@ public void init_signals(int on)
#endif
#ifdef SIGTERM
(void) LSIGNAL(SIGTERM, terminate);
#endif
#ifdef SIGUSR1
(void) LSIGNAL(SIGUSR1, sigusr1);
#endif
} else
{
@@ -193,6 +223,9 @@ public void init_signals(int on)
#endif
#ifdef SIGTERM
(void) LSIGNAL(SIGTERM, SIG_DFL);
#endif
#ifdef SIGUSR1
(void) LSIGNAL(SIGUSR1, SIG_DFL);
#endif
}
}
@@ -262,9 +295,5 @@ public void psignals(void)
{
if (quit_on_intr)
quit(QUIT_INTERRUPT);
getcc_clear();
#if MSDOS_COMPILER==WIN32C
win32_getch_clear();
#endif
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
+7 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -69,7 +69,11 @@ public int open_tty(void)
int fd = -1;
#if LESSTEST
if (is_lesstest())
{
fd = open_tty_device(ttyin_name);
if (fd < 0)
fd = 0; /* assume lesstest uses stdin */
}
#endif /*LESSTEST*/
#if HAVE_TTYNAME
if (fd < 0)
@@ -193,8 +197,10 @@ public int getchr(void)
* In raw read, we don't see ^C so look here for it.
*/
#if MSDOS_COMPILER==WIN32C
#if 0
if (ABORT_SIGS())
return (READ_INTR);
#endif
c = WIN32getch();
#else
c = getch();
+1 -1
View File
@@ -1,4 +1,4 @@
/* Generated by "./mkutable -f2 Cc Cs Co Zl Zp -- unicode/UnicodeData.txt" on Sun Sep 17 17:56:27 PDT 2023 */
/* Generated by "./mkutable -f2 Cc Cs Co Zl Zp -- unicode/UnicodeData.txt" on Oct 1 18:10:07 GMT 2024 */
{ 0x0000, 0x0007 }, /* Cc */
{ 0x000b, 0x000b }, /* Cc */
{ 0x000e, 0x001f }, /* Cc */
+17 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 1984-2024 Mark Nudelman
* Copyright (C) 1984-2025 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
@@ -1032,6 +1032,21 @@ v665 9/4/24 Fix ^Z bug.
v666 9/21/24 Fix missing first byte from LESSOPEN if >0x7f.
v667 9/26/24 Fix uninitialized variable in edit_ifile.
v668 10/6/24 Fix UTF-8 chars in prompt.
v669 11/6/24 Add --no-paste; add --no-edit-warn; add TAB for -- command;
add LESSANSIOSCALLOW and LESSANSIOSCCCHARS; fix bug searching
near invalid UTF-8 sequence; add LESS_SHELL_LINES; fix bug
with --no-number-headers; add mouse cmds to lesskey;
add form-feed; add --no-poll; add LESS_SIGUSR1;
fix "configure --with-secure=no".
v670 11/16/24 Fix SIGWINCH handling; add iopen.
v671 12/6/24 Fix multibyte command chars; fix Windows auto_wrap.
v672 1/20/25 Don't poll with -F on short file; remove --no-poll.
v673 3/13/25 Treat -r in LESS var as -R; add ESC-j and ESC-k.
v674 3/24/25 Improve behavior of ^O^N and ^O^P commands.
v675 4/3/25 Add ESC-b.
v676 4/16/25 Fix two OSC 8 display bugs.
v677 4/27/25 Fix & filtering bug.
v678 5/1/25 Don't change stty tab setting.
*/
char version[] = "668";
char version[] = "678";
+12 -10
View File
@@ -1,4 +1,4 @@
/* Generated by "./mkutable -f1 W F -- unicode/EastAsianWidth.txt" on Sun Sep 17 17:56:27 PDT 2023 */
/* Generated by "./mkutable -f1 W F -- unicode/EastAsianWidth.txt" on Sep 23 19:46:51 GMT 2024 */
{ 0x1100, 0x115f }, /* W */
{ 0x231a, 0x231b }, /* W */
{ 0x2329, 0x232a }, /* W */
@@ -7,8 +7,10 @@
{ 0x23f3, 0x23f3 }, /* W */
{ 0x25fd, 0x25fe }, /* W */
{ 0x2614, 0x2615 }, /* W */
{ 0x2630, 0x2637 }, /* W */
{ 0x2648, 0x2653 }, /* W */
{ 0x267f, 0x267f }, /* W */
{ 0x268a, 0x268f }, /* W */
{ 0x2693, 0x2693 }, /* W */
{ 0x26a1, 0x26a1 }, /* W */
{ 0x26aa, 0x26ab }, /* W */
@@ -44,11 +46,10 @@
{ 0x3099, 0x30ff }, /* W */
{ 0x3105, 0x312f }, /* W */
{ 0x3131, 0x318e }, /* W */
{ 0x3190, 0x31e3 }, /* W */
{ 0x3190, 0x31e5 }, /* W */
{ 0x31ef, 0x321e }, /* W */
{ 0x3220, 0x3247 }, /* W */
{ 0x3250, 0x4dbf }, /* W */
{ 0x4e00, 0xa48c }, /* W */
{ 0x3250, 0xa48c }, /* W */
{ 0xa490, 0xa4c6 }, /* W */
{ 0xa960, 0xa97c }, /* W */
{ 0xac00, 0xd7a3 }, /* W */
@@ -63,7 +64,7 @@
{ 0x16ff0, 0x16ff1 }, /* W */
{ 0x17000, 0x187f7 }, /* W */
{ 0x18800, 0x18cd5 }, /* W */
{ 0x18d00, 0x18d08 }, /* W */
{ 0x18cff, 0x18d08 }, /* W */
{ 0x1aff0, 0x1aff3 }, /* W */
{ 0x1aff5, 0x1affb }, /* W */
{ 0x1affd, 0x1affe }, /* W */
@@ -73,6 +74,8 @@
{ 0x1b155, 0x1b155 }, /* W */
{ 0x1b164, 0x1b167 }, /* W */
{ 0x1b170, 0x1b2fb }, /* W */
{ 0x1d300, 0x1d356 }, /* W */
{ 0x1d360, 0x1d376 }, /* W */
{ 0x1f004, 0x1f004 }, /* W */
{ 0x1f0cf, 0x1f0cf }, /* W */
{ 0x1f18e, 0x1f18e }, /* W */
@@ -113,11 +116,10 @@
{ 0x1f93c, 0x1f945 }, /* W */
{ 0x1f947, 0x1f9ff }, /* W */
{ 0x1fa70, 0x1fa7c }, /* W */
{ 0x1fa80, 0x1fa88 }, /* W */
{ 0x1fa90, 0x1fabd }, /* W */
{ 0x1fabf, 0x1fac5 }, /* W */
{ 0x1face, 0x1fadb }, /* W */
{ 0x1fae0, 0x1fae8 }, /* W */
{ 0x1fa80, 0x1fa89 }, /* W */
{ 0x1fa8f, 0x1fac6 }, /* W */
{ 0x1face, 0x1fadc }, /* W */
{ 0x1fadf, 0x1fae9 }, /* W */
{ 0x1faf0, 0x1faf8 }, /* W */
{ 0x20000, 0x2fffd }, /* W */
{ 0x30000, 0x3fffd }, /* W */
+10 -5
View File
@@ -208,6 +208,7 @@
#define TERMSBUF_SIZE 1024 /* Buffer to hold termcap strings */
#define TAGLINE_SIZE 512 /* Max size of line in tags file */
#define TABSTOP_MAX 32 /* Max number of custom tab stops */
#define LINENUM_POOL 200 /* Size of line number pool */
#else /* more reasonable sizes for modern machines */
#define CMDBUF_SIZE 2048 /* Buffer for multichar commands */
#define UNGOT_SIZE 200 /* Max chars to unget() */
@@ -218,6 +219,7 @@
#define TERMSBUF_SIZE 1024 /* Buffer to hold termcap strings */
#define TAGLINE_SIZE 1024 /* Max size of line in tags file */
#define TABSTOP_MAX 128 /* Max number of custom tab stops */
#define LINENUM_POOL 1024 /* Size of line number pool */
#endif
/* Define as the return type of signal handlers (int or void). */
@@ -262,9 +264,6 @@
/* Define to 1 if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
/* Define to 1 if you have the <linux/magic.h> header file. */
/* #undef HAVE_LINUX_MAGIC_H */
/* Define HAVE_LOCALE if you have locale.h and setlocale. */
#define HAVE_LOCALE 1
@@ -307,12 +306,18 @@
/* BSD re_comp() */
/* #undef HAVE_RE_COMP */
/* Define HAVE_SETTABLE_ERRNO if the errno variable can be assigned to. */
#define HAVE_SETTABLE_ERRNO 1
/* Define HAVE_SIGEMPTYSET if you have the sigemptyset macro. */
#define HAVE_SIGEMPTYSET 1
/* Define to 1 if you have the 'sigprocmask' function. */
#define HAVE_SIGPROCMASK 1
/* Define HAVE_SIGSETJMP if you have sigsetjmp and siglongjmp. */
#define HAVE_SIGSETJMP 1
/* Define to 1 if you have the 'sigsetmask' function. */
#define HAVE_SIGSETMASK 1
@@ -421,8 +426,8 @@
/* Define to 1 if you have the '_setjmp' function. */
#define HAVE__SETJMP 1
/* Define MUST_DEFINE_ERRNO if you have errno but it is not define in errno.h.
*/
/* Define MUST_DEFINE_ERRNO if you have errno but it is not defined in
errno.h. */
/* #undef MUST_DEFINE_ERRNO */
/* Define MUST_DEFINE_OSPEED if you have ospeed but it is not defined in