less: upgrade to v590.

MFC after:	2 weeks
This commit is contained in:
Xin LI 2021-07-17 22:20:44 -07:00
commit 30a1828c51
31 changed files with 1183 additions and 763 deletions

View file

@ -3,8 +3,7 @@
======================================================================
For the latest news about less, see the "less" Web page:
https://greenwoodsoftware.com/less
For the latest news about less, see https://greenwoodsoftware.com/less
You can also download the latest version of less from there.
Report bugs, suggestions or comments at
@ -12,7 +11,32 @@
======================================================================
Major changes between "less" versions 563 and 581.2
Major changes between "less" versions 581 and 590
* Make less able to read lesskey source files (deprecating lesskey).
* If XDG_CONFIG_HOME is set, find lesskey source file
in $XDG_CONFIG_HOME/lesskey rather than $HOME/.lesskey.
* If XDG_DATA_HOME is set, find and store history file
in $XDG_DATA_HOME/lesshst rather than $HOME/.lesshst.
* Add the --lesskey-src option.
* Add the --file-size option.
* With -F, if screen is resized to make file fit on one screen, don't exit.
* Fix bug which could leave terminal in mouse-reporting mode
after exiting less.
* Fix bug which caused failure to respond to window resize.
* Fix backslash bug searching in tag file.
======================================================================
Major changes between "less" versions 563 and 581
* Change ESC-u command to toggle, not disable, highlighting per man page.

View file

@ -7,9 +7,7 @@
**************************************************************************
**************************************************************************
Less, version 581.2
This is the distribution of less, version 581.2, released 28 Apr 2021.
This is the source code distribution of "less".
This program is part of the GNU project (http://www.gnu.org).
This program is free software. You may redistribute it and/or
@ -27,6 +25,11 @@
=========================================================================
You should build from a clone of a git repository
ONLY IF you are doing development on the less source itself.
If you are merely using less as a tool, you should download a release
from http://greenwoodsoftware.com and NOT from github.
The formatted manual page is in less.man.
The manual page nroff source is in less.nro.
Major changes made since the last posted version are in NEWS.

View file

@ -860,7 +860,7 @@ ch_init(f, flags)
* Allocate and initialize a new filestate.
*/
thisfile = (struct filestate *)
calloc(1, sizeof(struct filestate));
ecalloc(1, sizeof(struct filestate));
thisfile->buflist.next = thisfile->buflist.prev = END_OF_CHAIN;
thisfile->nbufs = 0;
thisfile->flags = flags;

View file

@ -1401,11 +1401,12 @@ mlist_size(ml)
* Get the name of the history file.
*/
static char *
histfile_name(VOID_PARAM)
histfile_name(must_exist)
int must_exist;
{
char *home;
char *xdg;
char *name;
int len;
/* See if filename is explicitly specified by $LESSHISTFILE. */
name = lgetenv("LESSHISTFILE");
@ -1421,19 +1422,25 @@ histfile_name(VOID_PARAM)
if (strcmp(LESSHISTFILE, "") == 0 || strcmp(LESSHISTFILE, "-") == 0)
return (NULL);
/* Otherwise, file is in $HOME. */
/* Try in $XDG_DATA_HOME first, then in $HOME. */
xdg = lgetenv("XDG_DATA_HOME");
home = lgetenv("HOME");
if (isnullenv(home))
{
#if OS2
if (isnullenv(home))
home = lgetenv("INIT");
if (isnullenv(home))
#endif
return (NULL);
name = NULL;
if (!must_exist)
{
/* If we're writing the file and the file already exists, use it. */
name = dirfile(xdg, &LESSHISTFILE[1], 1);
if (name == NULL)
name = dirfile(home, LESSHISTFILE, 1);
}
len = (int) (strlen(home) + strlen(LESSHISTFILE) + 2);
name = (char *) ecalloc(len, sizeof(char));
SNPRINTF2(name, len, "%s/%s", home, LESSHISTFILE);
if (name == NULL)
name = dirfile(xdg, &LESSHISTFILE[1], must_exist);
if (name == NULL)
name = dirfile(home, LESSHISTFILE, must_exist);
return (name);
}
@ -1454,7 +1461,7 @@ read_cmdhist2(action, uparam, skip_search, skip_shell)
char *p;
int *skip = NULL;
filename = histfile_name();
filename = histfile_name(1);
if (filename == NULL)
return;
f = fopen(filename, "r");
@ -1700,7 +1707,7 @@ save_cmdhist(VOID_PARAM)
if (!histfile_modified())
return;
histname = histfile_name();
histname = histfile_name(0);
if (histname == NULL)
return;
tempname = make_tempname(histname);

View file

@ -797,6 +797,7 @@ prompt(VOID_PARAM)
entire_file_displayed() && !(ch_getflags() & CH_HELPFILE) &&
next_ifile(curr_ifile) == NULL_IFILE)
quit(QUIT_OK);
quit_if_one_screen = FALSE; /* only get one chance at this */
#if MSDOS_COMPILER==WIN32C
/*

View file

@ -339,21 +339,41 @@ init_cmds(VOID_PARAM)
add_fcmd_table((char*)cmdtable, sizeof(cmdtable));
add_ecmd_table((char*)edittable, sizeof(edittable));
#if USERFILE
/*
* For backwards compatibility,
* try to add tables in the OLD system lesskey file.
*/
#ifdef BINDIR
add_hometable(NULL, BINDIR "/.sysless", 1);
#ifdef BINDIR /* For backwards compatibility */
/* Try to add tables in the OLD system lesskey file. */
add_hometable(lesskey, NULL, BINDIR "/.sysless", 1);
#endif
/*
* Try to add the tables in the system lesskey file.
* Try to load lesskey source file or binary file.
* If the source file succeeds, don't load binary file.
* The binary file is likely to have been generated from
* a (possibly out of date) copy of the src file,
* so loading it is at best redundant.
*/
add_hometable("LESSKEY_SYSTEM", LESSKEYFILE_SYS, 1);
/*
* Try to add the tables in the standard lesskey file "$HOME/.less".
* Try to add tables in system lesskey src file.
*/
add_hometable("LESSKEY", LESSKEYFILE, 0);
#if HAVE_LESSKEYSRC
if (add_hometable(lesskey_src, "LESSKEYIN_SYSTEM", LESSKEYINFILE_SYS, 1) != 0)
#endif
{
/*
* Try to add the tables in the system lesskey binary file.
*/
add_hometable(lesskey, "LESSKEY_SYSTEM", LESSKEYFILE_SYS, 1);
}
/*
* Try to add tables in the lesskey src file "$HOME/.lesskey".
*/
#if HAVE_LESSKEYSRC
if (add_hometable(lesskey_src, "LESSKEYIN", DEF_LESSKEYINFILE, 0) != 0)
#endif
{
/*
* Try to add the tables in the standard lesskey binary file "$HOME/.less".
*/
add_hometable(lesskey, "LESSKEY", LESSKEYFILE, 0);
}
#endif
}
@ -877,32 +897,63 @@ lesskey(filename, sysvar)
return (new_lesskey(buf, (int)len, sysvar));
}
#if HAVE_LESSKEYSRC
public int
lesskey_src(filename, sysvar)
char *filename;
int sysvar;
{
static struct lesskey_tables tables;
int r = parse_lesskey(filename, &tables);
if (r != 0)
return (r);
add_fcmd_table(tables.cmdtable.buf.data, tables.cmdtable.buf.end);
add_ecmd_table(tables.edittable.buf.data, tables.edittable.buf.end);
add_var_table(sysvar ? &list_sysvar_tables : &list_var_tables,
tables.vartable.buf.data, tables.vartable.buf.end);
return (0);
}
void
lesskey_parse_error(s)
char *s;
{
PARG parg;
parg.p_string = s;
error("%s", &parg);
}
#endif /* HAVE_LESSKEYSRC */
/*
* Add the standard lesskey file "$HOME/.less"
* Add a lesskey file.
*/
public void
add_hometable(envname, def_filename, sysvar)
public int
add_hometable(call_lesskey, envname, def_filename, sysvar)
int (*call_lesskey)(char *, int);
char *envname;
char *def_filename;
int sysvar;
{
char *filename;
PARG parg;
int r;
if (envname != NULL && (filename = lgetenv(envname)) != NULL)
filename = save(filename);
else if (sysvar)
else if (sysvar) /* def_filename is full path */
filename = save(def_filename);
else
filename = homefile(def_filename);
if (filename == NULL)
return;
if (lesskey(filename, sysvar) < 0)
else /* def_filename is just basename */
{
parg.p_string = filename;
error("Cannot use lesskey file \"%s\"", &parg);
char *xdg = lgetenv("XDG_CONFIG_HOME");
if (!isnullenv(xdg))
filename = dirfile(xdg, def_filename+1, 1);
if (filename == NULL)
filename = homefile(def_filename);
}
if (filename == NULL)
return -1;
r = (*call_lesskey)(filename, sysvar);
free(filename);
return (r);
}
#endif

View file

@ -26,6 +26,7 @@ extern int force_open;
extern int is_tty;
extern int sigs;
extern int hshift;
extern int want_filesize;
extern IFILE curr_ifile;
extern IFILE old_ifile;
extern struct scrpos initial_scrpos;
@ -487,7 +488,8 @@ edit_ifile(ifile)
cmd_addhist(ml_examine, qfilename, 1);
free(qfilename);
}
if (want_filesize)
scan_eof();
}
free(filename);
return (0);

View file

@ -216,10 +216,11 @@ shell_quote(s)
* Return a pathname that points to a specified file in a specified directory.
* Return NULL if the file does not exist in the directory.
*/
static char *
dirfile(dirname, filename)
public char *
dirfile(dirname, filename, must_exist)
char *dirname;
char *filename;
int must_exist;
{
char *pathname;
int len;
@ -235,17 +236,20 @@ dirfile(dirname, filename)
if (pathname == NULL)
return (NULL);
SNPRINTF3(pathname, len, "%s%s%s", dirname, PATHNAME_SEP, filename);
/*
* Make sure the file exists.
*/
f = open(pathname, OPEN_READ);
if (f < 0)
if (must_exist)
{
free(pathname);
pathname = NULL;
} else
{
close(f);
/*
* Make sure the file exists.
*/
f = open(pathname, OPEN_READ);
if (f < 0)
{
free(pathname);
pathname = NULL;
} else
{
close(f);
}
}
return (pathname);
}
@ -259,25 +263,19 @@ homefile(filename)
{
char *pathname;
/*
* Try $HOME/filename.
*/
pathname = dirfile(lgetenv("HOME"), filename);
/* Try $HOME/filename. */
pathname = dirfile(lgetenv("HOME"), filename, 1);
if (pathname != NULL)
return (pathname);
#if OS2
/*
* Try $INIT/filename.
*/
pathname = dirfile(lgetenv("INIT"), filename);
/* Try $INIT/filename. */
pathname = dirfile(lgetenv("INIT"), filename, 1);
if (pathname != NULL)
return (pathname);
#endif
#if MSDOS_COMPILER || OS2
/*
* Look for the file anywhere on search path.
*/
pathname = (char *) calloc(_MAX_PATH, sizeof(char));
/* Look for the file anywhere on search path. */
pathname = (char *) ecalloc(_MAX_PATH, sizeof(char));
#if MSDOS_COMPILER==DJGPPC
{
char *res = searchpath(filename);
@ -517,6 +515,7 @@ seek_filesize(f)
return ((POSITION) spos);
}
#if HAVE_POPEN
/*
* Read a string from a file.
* Return a pointer to the string in memory.
@ -560,10 +559,6 @@ readfd(fd)
return (buf);
}
#if HAVE_POPEN
/*
* Execute a shell command.
* Return a pointer to a pipe connected to the shell command's standard output.
@ -812,6 +807,7 @@ lrealpath(path)
return (save(path));
}
#if HAVE_POPEN
/*
* Return number of %s escapes in a string.
* Return a large number if there are any other % escapes besides %s.
@ -837,6 +833,7 @@ num_pct_s(lessopen)
}
return (num);
}
#endif
/*
* See if we should open a "replacement file"
@ -953,10 +950,13 @@ open_altfile(filename, pf, pfd)
cmd = readfd(fd);
pclose(fd);
if (*cmd == '\0')
{
/*
* Pipe is empty. This means there is no alt file.
*/
free(cmd);
return (NULL);
}
return (cmd);
#endif /* HAVE_POPEN */
}
@ -1122,4 +1122,3 @@ last_component(name)
}
return (name);
}

View file

@ -106,7 +106,8 @@ public int ecmd_decode LESSPARAMS ((char *cmd, char **sp));
public char * lgetenv LESSPARAMS ((char *var));
public int isnullenv LESSPARAMS ((char* s));
public int lesskey LESSPARAMS ((char *filename, int sysvar));
public void add_hometable LESSPARAMS ((char *envname, char *def_filename, int sysvar));
public int lesskey_src LESSPARAMS ((char *filename, int sysvar));
public int add_hometable LESSPARAMS ((int (*call_lesskey)(char *, int), char *envname, char *def_filename, int sysvar));
public int editchar LESSPARAMS ((int c, int flags));
public void init_textlist LESSPARAMS ((struct textlist *tlist, char *str));
public char * forw_textlist LESSPARAMS ((struct textlist *tlist, char *prev));
@ -129,6 +130,7 @@ public void use_logfile LESSPARAMS ((char *filename));
public char * shell_unquote LESSPARAMS ((char *str));
public char * get_meta_escape LESSPARAMS ((VOID_PARAM));
public char * shell_quote LESSPARAMS ((char *s));
public char * dirfile LESSPARAMS ((char *dirname, char *filename, int must_exist));
public char * homefile LESSPARAMS ((char *filename));
public char * fexpand LESSPARAMS ((char *s));
public char * fcomplete LESSPARAMS ((char *s));
@ -213,6 +215,7 @@ public void add_lnum LESSPARAMS ((LINENUM linenum, POSITION pos));
public LINENUM find_linenum LESSPARAMS ((POSITION pos));
public POSITION find_pos LESSPARAMS ((LINENUM linenum));
public LINENUM currline LESSPARAMS ((int where));
public void scan_eof LESSPARAMS ((VOID_PARAM));
public void lsystem LESSPARAMS ((char *cmd, char *donemsg));
public int pipe_mark LESSPARAMS ((int c, char *cmd));
public int pipe_data LESSPARAMS ((char *cmd, POSITION spos, POSITION epos));
@ -235,6 +238,7 @@ public void calc_jump_sline LESSPARAMS ((VOID_PARAM));
public void opt_shift LESSPARAMS ((int type, char *s));
public void calc_shift_count LESSPARAMS ((VOID_PARAM));
public void opt_k LESSPARAMS ((int type, char *s));
public void opt_ks LESSPARAMS ((int type, char *s));
public void opt_t LESSPARAMS ((int type, char *s));
public void opt__T LESSPARAMS ((int type, char *s));
public void opt_p LESSPARAMS ((int type, char *s));
@ -251,6 +255,7 @@ public void opt_mousecap LESSPARAMS ((int type, char *s));
public void opt_wheel_lines LESSPARAMS ((int type, char *s));
public void opt_linenum_width LESSPARAMS ((int type, char *s));
public void opt_status_col_width LESSPARAMS ((int type, char *s));
public void opt_filesize LESSPARAMS ((int type, char *s));
public void opt_ttyin_name LESSPARAMS ((int type, char *s));
public void opt_rstat LESSPARAMS ((int type, char *s));
public int get_swindow LESSPARAMS ((VOID_PARAM));
@ -280,6 +285,7 @@ public void put_line LESSPARAMS ((VOID_PARAM));
public void flush LESSPARAMS ((VOID_PARAM));
public void set_output LESSPARAMS ((int fd));
public int putchr LESSPARAMS ((int c));
public void clear_bot_if_needed LESSPARAMS ((VOID_PARAM));
public void putstr LESSPARAMS ((constant char *s));
public int less_printf LESSPARAMS ((char *fmt, PARG *parg));
public void get_return LESSPARAMS ((VOID_PARAM));
@ -342,3 +348,7 @@ public void close_getchr LESSPARAMS ((VOID_PARAM));
public int default_wheel_lines LESSPARAMS ((VOID_PARAM));
public void rstat LESSPARAMS ((char st));
public int getchr LESSPARAMS ((VOID_PARAM));
public void xbuf_init LESSPARAMS ((struct xbuffer *xbuf));
public void xbuf_deinit LESSPARAMS ((struct xbuffer *xbuf));
public void xbuf_reset LESSPARAMS ((struct xbuffer *xbuf));
public void xbuf_add LESSPARAMS ((struct xbuffer *xbuf, char ch));

View file

@ -1,4 +1,4 @@
/* This file was generated by mkhelp.pl from less.hlp at 14:59 on 2021/4/28 */
/* This file was generated by mkhelp.pl from less.hlp at 17:45 on 2021/6/3 */
#include "less.h"
constant char helpdata[] = {
'\n',
@ -208,6 +208,8 @@ constant char helpdata[] = {
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','o','n','\'','t',' ','d','i','s','p','l','a','y',' ','t','i','l','d','e','s',' ','a','f','t','e','r',' ','e','n','d',' ','o','f',' ','f','i','l','e','.','\n',
' ',' ','-','#',' ','[','_','\b','N',']',' ',' ','.','.','.','.',' ',' ','-','-','s','h','i','f','t','=','[','_','\b','N',']','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','t',' ','h','o','r','i','z','o','n','t','a','l',' ','s','c','r','o','l','l',' ','a','m','o','u','n','t',' ','(','0',' ','=',' ','o','n','e',' ','h','a','l','f',' ','s','c','r','e','e','n',' ','w','i','d','t','h',')','.','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','f','i','l','e','-','s','i','z','e','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','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',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','i','n','c','s','e','a','r','c','h','\n',

View file

@ -571,6 +571,7 @@ struct loption;
struct hilite_tree;
struct ansi_state;
#include "pattern.h"
#include "xbuf.h"
#include "funcs.h"
/* Functions not included in funcs.h */

View file

@ -205,6 +205,8 @@
Don't display tildes after end of file.
-# [_N] .... --shift=[_N]
Set horizontal scroll amount (0 = one half screen width).
--file-size
Automatically determine the size of the input file.
--follow-name
The F command changes files if the input file is renamed.
--incsearch

View file

@ -1,5 +1,5 @@
'\" t
.TH LESS 1 "Version 581.2: 28 Apr 2021"
.TH LESS 1 "Version 590: 03 Jun 2021"
.SH NAME
less \- opposite of more
.SH SYNOPSIS
@ -759,13 +759,38 @@ Causes
.I less
to open and interpret the named file as a
.IR lesskey (1)
file.
binary file.
Multiple \-k options may be specified.
If the LESSKEY or LESSKEY_SYSTEM environment variable is set, or
if a lesskey file is found in a standard place (see KEY BINDINGS),
it is also used as a
.I lesskey
file.
.IP "\-\-lesskey-src=\fIfilename\fP"
Causes
.I less
to open and interpret the named file as a
.IR lesskey (1)
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.
Prior to version 582, the
.I lesskey
program needed to be run to convert a
.I "lesskey source"
file to a
.I "lesskey binary"
file for
.I less
to use.
Newer versions of
.I less
read the
.I "lesskey source"
file directly and ignore the binary file if the source file exists.
.IP "\-K or \-\-quit-on-intr"
Causes
.I less
@ -1054,6 +1079,12 @@ If the number is specified as a fraction, the actual number of
scroll positions is recalculated if the terminal window is resized,
so that the actual scroll remains at the specified fraction
of the screen width.
.IP "\-\-file-size"
If \-\-file-size is specified,
.I less
will determine the size of the file
immediately after opening the file.
Normally this is not done, because it can be slow if the input file is large.
.IP "\-\-follow-name"
Normally, if the input file is renamed while an F command is executing,
.I less
@ -1222,57 +1253,61 @@ Delete the entire command line and return to the main prompt.
.SH "KEY BINDINGS"
You may define your own
.I less
commands by using the program
.IR lesskey (1)
to create a lesskey file.
commands by creating a lesskey source file.
This file specifies a set of command keys and an action
associated with each key.
You may also use
.I lesskey
to change the line-editing keys (see LINE EDITING),
You may also change the line-editing keys (see LINE EDITING),
and to set environment variables.
If the environment variable LESSKEY is set,
If the environment variable LESSKEYIN is set,
.I less
uses that as the name of the lesskey file.
uses that as the name of the lesskey source file.
Otherwise,
.I less
looks in a standard place for the lesskey file:
looks in a standard place for the lesskey source file:
On Unix systems,
.I less
looks for a lesskey file called "$HOME/.less".
looks for a lesskey file called "$XDG_CONFIG_HOME/lesskey" or "$HOME/.lesskey".
On MS-DOS and Windows systems,
.I less
looks for a lesskey file called "$HOME/_less", and if it is not found there,
then looks for a lesskey file called "_less" in any directory specified
looks for a lesskey file called "$HOME/_lesskey", and if it is not found there,
then looks for a lesskey file called "_lesskey" in any directory specified
in the PATH environment variable.
On OS/2 systems,
.I less
looks for a lesskey file called "$HOME/less.ini", and if it is not found,
then looks for a lesskey file called "less.ini" in any directory specified
looks for a lesskey file called "$HOME/lesskey.ini", and if it is not found,
then looks for a lesskey file called "lesskey.ini" in any directory specified
in the INIT environment variable, and if it not found there,
then looks for a lesskey file called "less.ini" in any directory specified
then looks for a lesskey file called "lesskey.ini" in any directory specified
in the PATH environment variable.
See the
.I lesskey
manual page for more details.
.P
A system-wide lesskey file may also be set up to provide key bindings.
.PP
A system-wide lesskey source file may also be set up to provide key bindings.
If a key is defined in both a local lesskey file and in the
system-wide file, key bindings in the local file take precedence over
those in the system-wide file.
If the environment variable LESSKEY_SYSTEM is set,
If the environment variable LESSKEYIN_SYSTEM is set,
.I less
uses that as the name of the system-wide lesskey file.
Otherwise,
.I less
looks in a standard place for the system-wide lesskey file:
On Unix systems, the system-wide lesskey file is /usr/local/etc/sysless.
On Unix systems, the system-wide lesskey file is /usr/local/etc/syslesskey.
(However, if
.I less
was built with a different sysconf directory than /usr/local/etc,
that directory is where the sysless file is found.)
On MS-DOS and Windows systems, the system-wide lesskey file is c:\e_sysless.
On OS/2 systems, the system-wide lesskey file is c:\esysless.ini.
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
.I less
(before v582) used lesskey files with a binary format, produced by the
.I lesskey
program. It is no longer necessary to use the
.I lesskey
program.
.
.SH "INPUT PREPROCESSOR"
You may define an "input preprocessor" for
@ -1890,20 +1925,29 @@ Name of the history file used to remember search commands and
shell commands between invocations of
.IR less .
If set to "\-" or "/dev/null", a history file is not used.
The default is "$HOME/.lesshst" on Unix systems, "$HOME/_lesshst" on
DOS and Windows systems, or "$HOME/lesshst.ini" or "$INIT/lesshst.ini"
The default is "$XDG_DATA_HOME/lesshst" or "$HOME/.lesshst" on Unix systems,
"$HOME/_lesshst" on DOS and Windows systems,
or "$HOME/lesshst.ini" or "$INIT/lesshst.ini"
on OS/2 systems.
.IP LESSHISTSIZE
The maximum number of commands to save in the history file.
The default is 100.
.IP LESSKEYIN
Name of the default
.I "lesskey source"
file.
.IP LESSKEY
Name of the default
.IR lesskey (1)
.I "lesskey binary"
file. (Not used if "$LESSKEYIN" exists.)
.IP LESSKEYIN_SYSTEM
Name of the default system-wide
.I "lesskey source"
file.
.IP LESSKEY_SYSTEM
Name of the default system-wide
.IR lesskey (1)
file.
.I "lesskey binary"
file. (Not used if "$LESSKEYIN_SYSTEM" exists.)
.IP LESSMETACHARS
List of characters which are considered "metacharacters" by the shell.
.IP LESSMETAESCAPE
@ -1981,4 +2025,4 @@ Report bugs at https://github.com/gwsw/less/issues.
.br
For more information, see the less homepage at
.br
https://greenwoodsoftware.com/less.
https://greenwoodsoftware.com/less

View file

@ -1,4 +1,4 @@
.TH LESSECHO 1 "Version 581.2: 28 Apr 2021"
.TH LESSECHO 1 "Version 590: 03 Jun 2021"
.SH NAME
lessecho \- expand metacharacters
.SH SYNOPSIS

View file

@ -80,121 +80,12 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
#include "less.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "lesskey.h"
#include "cmd.h"
struct cmdname
{
char *cn_name;
int cn_action;
};
struct cmdname cmdnames[] =
{
{ "back-bracket", A_B_BRACKET },
{ "back-line", A_B_LINE },
{ "back-line-force", A_BF_LINE },
{ "back-screen", A_B_SCREEN },
{ "back-scroll", A_B_SCROLL },
{ "back-search", A_B_SEARCH },
{ "back-window", A_B_WINDOW },
{ "clear-mark", A_CLRMARK },
{ "debug", A_DEBUG },
{ "digit", A_DIGIT },
{ "display-flag", A_DISP_OPTION },
{ "display-option", A_DISP_OPTION },
{ "end", A_GOEND },
{ "end-scroll", A_RRSHIFT },
{ "examine", A_EXAMINE },
{ "filter", A_FILTER },
{ "first-cmd", A_FIRSTCMD },
{ "firstcmd", A_FIRSTCMD },
{ "flush-repaint", A_FREPAINT },
{ "forw-bracket", A_F_BRACKET },
{ "forw-forever", A_F_FOREVER },
{ "forw-until-hilite", A_F_UNTIL_HILITE },
{ "forw-line", A_F_LINE },
{ "forw-line-force", A_FF_LINE },
{ "forw-screen", A_F_SCREEN },
{ "forw-screen-force", A_FF_SCREEN },
{ "forw-scroll", A_F_SCROLL },
{ "forw-search", A_F_SEARCH },
{ "forw-window", A_F_WINDOW },
{ "goto-end", A_GOEND },
{ "goto-end-buffered", A_GOEND_BUF },
{ "goto-line", A_GOLINE },
{ "goto-mark", A_GOMARK },
{ "help", A_HELP },
{ "index-file", A_INDEX_FILE },
{ "invalid", A_UINVALID },
{ "left-scroll", A_LSHIFT },
{ "next-file", A_NEXT_FILE },
{ "next-tag", A_NEXT_TAG },
{ "noaction", A_NOACTION },
{ "no-scroll", A_LLSHIFT },
{ "percent", A_PERCENT },
{ "pipe", A_PIPE },
{ "prev-file", A_PREV_FILE },
{ "prev-tag", A_PREV_TAG },
{ "quit", A_QUIT },
{ "remove-file", A_REMOVE_FILE },
{ "repaint", A_REPAINT },
{ "repaint-flush", A_FREPAINT },
{ "repeat-search", A_AGAIN_SEARCH },
{ "repeat-search-all", A_T_AGAIN_SEARCH },
{ "reverse-search", A_REVERSE_SEARCH },
{ "reverse-search-all", A_T_REVERSE_SEARCH },
{ "right-scroll", A_RSHIFT },
{ "set-mark", A_SETMARK },
{ "set-mark-bottom", A_SETMARKBOT },
{ "shell", A_SHELL },
{ "status", A_STAT },
{ "toggle-flag", A_OPT_TOGGLE },
{ "toggle-option", A_OPT_TOGGLE },
{ "undo-hilite", A_UNDO_SEARCH },
{ "clear-search", A_CLR_SEARCH },
{ "version", A_VERSION },
{ "visual", A_VISUAL },
{ NULL, 0 }
};
struct cmdname editnames[] =
{
{ "back-complete", EC_B_COMPLETE },
{ "backspace", EC_BACKSPACE },
{ "delete", EC_DELETE },
{ "down", EC_DOWN },
{ "end", EC_END },
{ "expand", EC_EXPAND },
{ "forw-complete", EC_F_COMPLETE },
{ "home", EC_HOME },
{ "insert", EC_INSERT },
{ "invalid", EC_UINVALID },
{ "kill-line", EC_LINEKILL },
{ "abort", EC_ABORT },
{ "left", EC_LEFT },
{ "literal", EC_LITERAL },
{ "right", EC_RIGHT },
{ "up", EC_UP },
{ "word-backspace", EC_W_BACKSPACE },
{ "word-delete", EC_W_DELETE },
{ "word-left", EC_W_LEFT },
{ "word-right", EC_W_RIGHT },
{ NULL, 0 }
};
struct table
{
struct cmdname *names;
char *pbuffer;
char buffer[MAX_USERCMD];
};
struct table cmdtable;
struct table edittable;
struct table vartable;
struct table *currtable = &cmdtable;
#include "defines.h"
char fileheader[] = {
C0_LESSKEY_MAGIC,
@ -215,26 +106,44 @@ char endsection[1] = { END_SECTION };
char *infile = NULL;
char *outfile = NULL ;
int linenum;
int errors;
extern char version[];
void
usage(VOID_PARAM)
static void
usage(void)
{
fprintf(stderr, "usage: lesskey [-o output] [input]\n");
exit(1);
}
char *
void
lesskey_parse_error(s)
char *s;
{
fprintf(stderr, "%s\n", s);
}
void *
ecalloc(count, size)
int count;
unsigned int size;
{
void *p;
p = calloc(count, size);
if (p != NULL)
return (p);
fprintf(stderr, "lesskey: cannot allocate %d bytes of memory\n", count*size);
exit(1);
}
static char *
mkpathname(dirname, filename)
char *dirname;
char *filename;
{
char *pathname;
pathname = calloc(strlen(dirname) + strlen(filename) + 2, sizeof(char));
pathname = ecalloc(strlen(dirname) + strlen(filename) + 2, sizeof(char));
strcpy(pathname, dirname);
strcat(pathname, PATHNAME_SEP);
strcat(pathname, filename);
@ -268,7 +177,7 @@ homefile(filename)
/*
* Parse command line arguments.
*/
void
static void
parse_args(argc, argv)
int argc;
char **argv;
@ -336,247 +245,12 @@ parse_args(argc, argv)
*/
if (argc > 0)
infile = *argv;
else
infile = homefile(DEF_LESSKEYINFILE);
}
/*
* Initialize data structures.
*/
void
init_tables(VOID_PARAM)
{
cmdtable.names = cmdnames;
cmdtable.pbuffer = cmdtable.buffer;
edittable.names = editnames;
edittable.pbuffer = edittable.buffer;
vartable.names = NULL;
vartable.pbuffer = vartable.buffer;
}
/*
* Parse one character of a string.
*/
char *
tstr(pp, xlate)
char **pp;
int xlate;
{
char *p;
char ch;
int i;
static char buf[10];
static char tstr_control_k[] =
{ SK_SPECIAL_KEY, SK_CONTROL_K, 6, 1, 1, 1, '\0' };
p = *pp;
switch (*p)
{
case '\\':
++p;
switch (*p)
{
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
/*
* Parse an octal number.
*/
ch = 0;
i = 0;
do
ch = 8*ch + (*p - '0');
while (*++p >= '0' && *p <= '7' && ++i < 3);
*pp = p;
if (xlate && ch == CONTROL('K'))
return tstr_control_k;
buf[0] = ch;
buf[1] = '\0';
return (buf);
case 'b':
*pp = p+1;
return ("\b");
case 'e':
*pp = p+1;
buf[0] = ESC;
buf[1] = '\0';
return (buf);
case 'n':
*pp = p+1;
return ("\n");
case 'r':
*pp = p+1;
return ("\r");
case 't':
*pp = p+1;
return ("\t");
case 'k':
if (xlate)
{
switch (*++p)
{
case 'u': ch = SK_UP_ARROW; break;
case 'd': ch = SK_DOWN_ARROW; break;
case 'r': ch = SK_RIGHT_ARROW; break;
case 'l': ch = SK_LEFT_ARROW; break;
case 'U': ch = SK_PAGE_UP; break;
case 'D': ch = SK_PAGE_DOWN; break;
case 'h': ch = SK_HOME; break;
case 'e': ch = SK_END; break;
case 'x': ch = SK_DELETE; break;
default:
error("illegal char after \\k", NULL_PARG);
*pp = p+1;
return ("");
}
*pp = p+1;
buf[0] = SK_SPECIAL_KEY;
buf[1] = ch;
buf[2] = 6;
buf[3] = 1;
buf[4] = 1;
buf[5] = 1;
buf[6] = '\0';
return (buf);
}
/* FALLTHRU */
default:
/*
* Backslash followed by any other char
* just means that char.
*/
*pp = p+1;
buf[0] = *p;
buf[1] = '\0';
if (xlate && buf[0] == CONTROL('K'))
return tstr_control_k;
return (buf);
}
case '^':
/*
* Caret means CONTROL.
*/
*pp = p+2;
buf[0] = CONTROL(p[1]);
buf[1] = '\0';
if (xlate && buf[0] == CONTROL('K'))
return tstr_control_k;
return (buf);
}
*pp = p+1;
buf[0] = *p;
buf[1] = '\0';
if (xlate && buf[0] == CONTROL('K'))
return tstr_control_k;
return (buf);
}
/*
* Skip leading spaces in a string.
*/
public char *
skipsp(s)
char *s;
{
while (*s == ' ' || *s == '\t')
s++;
return (s);
}
/*
* Skip non-space characters in a string.
*/
public char *
skipnsp(s)
char *s;
{
while (*s != '\0' && *s != ' ' && *s != '\t')
s++;
return (s);
}
/*
* Clean up an input line:
* strip off the trailing newline & any trailing # comment.
*/
char *
clean_line(s)
char *s;
{
int i;
s = skipsp(s);
for (i = 0; s[i] != '\n' && s[i] != '\r' && s[i] != '\0'; i++)
if (s[i] == '#' && (i == 0 || s[i-1] != '\\'))
break;
s[i] = '\0';
return (s);
}
/*
* Add a byte to the output command table.
*/
void
add_cmd_char(c)
int c;
{
if (currtable->pbuffer >= currtable->buffer + MAX_USERCMD)
{
error("too many commands", NULL_PARG);
exit(1);
}
*(currtable->pbuffer)++ = c;
}
/*
* Add a string to the output command table.
*/
void
add_cmd_str(s)
char *s;
{
for ( ; *s != '\0'; s++)
add_cmd_char(*s);
}
/*
* See if we have a special "control" line.
*/
int
control_line(s)
char *s;
{
#define PREFIX(str,pat) (strncmp(str,pat,strlen(pat)) == 0)
if (PREFIX(s, "#line-edit"))
{
currtable = &edittable;
return (1);
}
if (PREFIX(s, "#command"))
{
currtable = &cmdtable;
return (1);
}
if (PREFIX(s, "#env"))
{
currtable = &vartable;
return (1);
}
if (PREFIX(s, "#stop"))
{
add_cmd_char('\0');
add_cmd_char(A_END_LIST);
return (1);
}
return (0);
}
/*
* Output some bytes.
*/
void
static void
fputbytes(fd, buf, len)
FILE *fd;
char *buf;
@ -592,7 +266,7 @@ fputbytes(fd, buf, len)
/*
* Output an integer, in special KRADIX form.
*/
void
static void
fputint(fd, val)
FILE *fd;
unsigned int val;
@ -601,7 +275,7 @@ fputint(fd, val)
if (val >= KRADIX*KRADIX)
{
fprintf(stderr, "error: integer too big (%d > %d)\n",
fprintf(stderr, "error: cannot write %d, max %d\n",
val, KRADIX*KRADIX);
exit(1);
}
@ -611,174 +285,14 @@ fputint(fd, val)
fwrite(&c, sizeof(char), 1, fd);
}
/*
* Find an action, given the name of the action.
*/
int
findaction(actname)
char *actname;
{
int i;
for (i = 0; currtable->names[i].cn_name != NULL; i++)
if (strcmp(currtable->names[i].cn_name, actname) == 0)
return (currtable->names[i].cn_action);
error("unknown action", NULL_PARG);
return (A_INVALID);
}
void
error(s, parg)
char *s;
PARG *parg;
{
fprintf(stderr, "line %d: %s\n", linenum, s);
errors++;
(void) parg;
}
void
parse_cmdline(p)
char *p;
{
int cmdlen;
char *actname;
int action;
char *s;
char c;
/*
* Parse the command string and store it in the current table.
*/
cmdlen = 0;
do
{
s = tstr(&p, 1);
cmdlen += (int) strlen(s);
if (cmdlen > MAX_CMDLEN)
error("command too long", NULL_PARG);
else
add_cmd_str(s);
} while (*p != ' ' && *p != '\t' && *p != '\0');
/*
* Terminate the command string with a null byte.
*/
add_cmd_char('\0');
/*
* Skip white space between the command string
* and the action name.
* Terminate the action name with a null byte.
*/
p = skipsp(p);
if (*p == '\0')
{
error("missing action", NULL_PARG);
return;
}
actname = p;
p = skipnsp(p);
c = *p;
*p = '\0';
/*
* Parse the action name and store it in the current table.
*/
action = findaction(actname);
/*
* See if an extra string follows the action name.
*/
*p = c;
p = skipsp(p);
if (*p == '\0')
{
add_cmd_char(action);
} else
{
/*
* OR the special value A_EXTRA into the action byte.
* Put the extra string after the action byte.
*/
add_cmd_char(action | A_EXTRA);
while (*p != '\0')
add_cmd_str(tstr(&p, 0));
add_cmd_char('\0');
}
}
void
parse_varline(p)
char *p;
{
char *s;
do
{
s = tstr(&p, 0);
add_cmd_str(s);
} while (*p != ' ' && *p != '\t' && *p != '=' && *p != '\0');
/*
* Terminate the variable name with a null byte.
*/
add_cmd_char('\0');
p = skipsp(p);
if (*p++ != '=')
{
error("missing =", NULL_PARG);
return;
}
add_cmd_char(EV_OK|A_EXTRA);
p = skipsp(p);
while (*p != '\0')
{
s = tstr(&p, 0);
add_cmd_str(s);
}
add_cmd_char('\0');
}
/*
* Parse a line from the lesskey file.
*/
void
parse_line(line)
char *line;
{
char *p;
/*
* See if it is a control line.
*/
if (control_line(line))
return;
/*
* Skip leading white space.
* Replace the final newline with a null byte.
* Ignore blank lines and comments.
*/
p = clean_line(line);
if (*p == '\0')
return;
if (currtable == &vartable)
parse_varline(p);
else
parse_cmdline(p);
}
int
main(argc, argv)
int argc;
char *argv[];
{
FILE *desc;
struct lesskey_tables tables;
FILE *out;
char line[1024];
int errors;
#ifdef WIN32
if (getenv("HOME") == NULL)
@ -791,7 +305,7 @@ main(argc, argv)
char *path = getenv("HOMEPATH");
if (drive != NULL && path != NULL)
{
char *env = (char *) calloc(strlen(drive) +
char *env = (char *) ecalloc(strlen(drive) +
strlen(path) + 6, sizeof(char));
strcpy(env, "HOME=");
strcat(env, drive);
@ -805,44 +319,19 @@ main(argc, argv)
* Process command line arguments.
*/
parse_args(argc, argv);
init_tables();
/*
* Open the input file.
*/
if (strcmp(infile, "-") == 0)
desc = stdin;
else if ((desc = fopen(infile, "r")) == NULL)
errors = parse_lesskey(infile, &tables);
if (errors)
{
#if HAVE_PERROR
perror(infile);
#else
fprintf(stderr, "Cannot open %s\n", infile);
#endif
usage();
fprintf(stderr, "%d errors; no output produced\n", errors);
return (1);
}
/*
* Read and parse the input file, one line at a time.
*/
errors = 0;
linenum = 0;
while (fgets(line, sizeof(line), desc) != NULL)
{
++linenum;
parse_line(line);
}
fprintf(stderr, "NOTE: lesskey is deprecated.\n It is no longer necessary to run lesskey,\n when using less version 582 and later.\n");
/*
* Write the output file.
* If no output file was specified, use "$HOME/.less"
*/
if (errors > 0)
{
fprintf(stderr, "%d errors; no output produced\n", errors);
exit(1);
}
if (outfile == NULL)
outfile = getenv("LESSKEY");
if (outfile == NULL)
@ -854,7 +343,7 @@ main(argc, argv)
#else
fprintf(stderr, "Cannot open %s\n", outfile);
#endif
exit(1);
return (1);
}
/* File header */
@ -862,17 +351,17 @@ main(argc, argv)
/* Command key section */
fputbytes(out, cmdsection, sizeof(cmdsection));
fputint(out, cmdtable.pbuffer - cmdtable.buffer);
fputbytes(out, (char *)cmdtable.buffer, cmdtable.pbuffer-cmdtable.buffer);
fputint(out, tables.cmdtable.buf.end);
fputbytes(out, (char *)tables.cmdtable.buf.data, tables.cmdtable.buf.end);
/* Edit key section */
fputbytes(out, editsection, sizeof(editsection));
fputint(out, edittable.pbuffer - edittable.buffer);
fputbytes(out, (char *)edittable.buffer, edittable.pbuffer-edittable.buffer);
fputint(out, tables.edittable.buf.end);
fputbytes(out, (char *)tables.edittable.buf.data, tables.edittable.buf.end);
/* Environment variable section */
fputbytes(out, varsection, sizeof(varsection));
fputint(out, vartable.pbuffer - vartable.buffer);
fputbytes(out, (char *)vartable.buffer, vartable.pbuffer-vartable.buffer);
fputint(out, tables.vartable.buf.end);
fputbytes(out, (char *)tables.vartable.buf.data, tables.vartable.buf.end);
/* File trailer */
fputbytes(out, endsection, sizeof(endsection));

View file

@ -7,6 +7,7 @@
* For more information, see the README file.
*/
#include "xbuf.h"
/*
* Format of a lesskey file:
@ -37,3 +38,26 @@
/* */
#define KRADIX 64
struct lesskey_cmdname
{
char *cn_name;
int cn_action;
};
struct lesskey_table
{
struct lesskey_cmdname *names;
struct xbuffer buf;
int is_var;
};
struct lesskey_tables
{
struct lesskey_table *currtable;
struct lesskey_table cmdtable;
struct lesskey_table edittable;
struct lesskey_table vartable;
};
extern int parse_lesskey(char *infile, struct lesskey_tables *tables);

View file

@ -1,8 +1,8 @@
'\" t
.TH LESSKEY 1 "Version 581.2: 28 Apr 2021"
.TH LESSKEY 1 "Version 590: 03 Jun 2021"
.SH NAME
lesskey \- specify key bindings for less
.SH SYNOPSIS
.SH "SYNOPSIS (deprecated)"
.B "lesskey [\-o output] [\-\-] [input]"
.br
.B "lesskey [\-\-output=output] [\-\-] [input]"
@ -10,38 +10,27 @@ lesskey \- specify key bindings for less
.B "lesskey \-V"
.br
.B "lesskey \-\-version"
.SH DESCRIPTION
.I Lesskey
is used to specify a set of key bindings to be used by
.IR less .
The input file is a text file which describes the key bindings.
If the input file is "\-", standard input is read.
If no input file is specified, a standard filename is used
as the name of the input file, which depends on the system being used:
On Unix systems, "$HOME/.lesskey" is used;
on MS-DOS systems, "$HOME/_lesskey" is used;
and on OS/2 systems "$HOME/lesskey.ini" is used,
or "$INIT/lesskey.ini" if $HOME is undefined.
The output file is a binary file which is used by
.IR less .
If no output file is specified,
and the environment variable LESSKEY is set,
the value of LESSKEY is used as the name of the output file.
Otherwise, a standard filename is used as the name of the output file,
which depends on the system being used:
On Unix and OS-9 systems, "$HOME/.less" is used;
on MS-DOS systems, "$HOME/_less" is used;
and on OS/2 systems, "$HOME/less.ini" is used,
or "$INIT/less.ini" if $HOME is undefined.
If the output file already exists,
.SH SCOPE
This document describes the format of the
.I lesskey
will overwrite it.
.PP
The \-V or \-\-version option causes
source file, which is used by
.I less
version 582 and later.
In previous versions of
.IR less ,
a separate program called
.I lesskey
to print its version number and immediately exit.
If \-V or \-\-version is present, other options and arguments are ignored.
was used to compile the
.I lesskey
source file into a format understood by
.IR less .
This compilation step is no longer required and the
.I lesskey
program is therefore deprecated although the file format remains supported by
.I less
itself.
.PP
.SH FILE FORMAT
The input file consists of one or more
.I sections.
Each section starts with a line that identifies the type of section.

View file

@ -0,0 +1,580 @@
/*
* Copyright (C) 1984-2021 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.
*
* For more information, see the README file.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "lesskey.h"
#include "cmd.h"
#include "xbuf.h"
#include "defines.h"
#define CONTROL(c) ((c)&037)
#define ESC CONTROL('[')
extern void lesskey_parse_error(char *msg);
extern char *homefile(char *filename);
extern void *ecalloc(int count, unsigned int size);
static int linenum;
static int errors;
static char *lesskey_file;
static struct lesskey_cmdname cmdnames[] =
{
{ "back-bracket", A_B_BRACKET },
{ "back-line", A_B_LINE },
{ "back-line-force", A_BF_LINE },
{ "back-screen", A_B_SCREEN },
{ "back-scroll", A_B_SCROLL },
{ "back-search", A_B_SEARCH },
{ "back-window", A_B_WINDOW },
{ "clear-mark", A_CLRMARK },
{ "debug", A_DEBUG },
{ "digit", A_DIGIT },
{ "display-flag", A_DISP_OPTION },
{ "display-option", A_DISP_OPTION },
{ "end", A_GOEND },
{ "end-scroll", A_RRSHIFT },
{ "examine", A_EXAMINE },
{ "filter", A_FILTER },
{ "first-cmd", A_FIRSTCMD },
{ "firstcmd", A_FIRSTCMD },
{ "flush-repaint", A_FREPAINT },
{ "forw-bracket", A_F_BRACKET },
{ "forw-forever", A_F_FOREVER },
{ "forw-until-hilite", A_F_UNTIL_HILITE },
{ "forw-line", A_F_LINE },
{ "forw-line-force", A_FF_LINE },
{ "forw-screen", A_F_SCREEN },
{ "forw-screen-force", A_FF_SCREEN },
{ "forw-scroll", A_F_SCROLL },
{ "forw-search", A_F_SEARCH },
{ "forw-window", A_F_WINDOW },
{ "goto-end", A_GOEND },
{ "goto-end-buffered", A_GOEND_BUF },
{ "goto-line", A_GOLINE },
{ "goto-mark", A_GOMARK },
{ "help", A_HELP },
{ "index-file", A_INDEX_FILE },
{ "invalid", A_UINVALID },
{ "left-scroll", A_LSHIFT },
{ "next-file", A_NEXT_FILE },
{ "next-tag", A_NEXT_TAG },
{ "noaction", A_NOACTION },
{ "no-scroll", A_LLSHIFT },
{ "percent", A_PERCENT },
{ "pipe", A_PIPE },
{ "prev-file", A_PREV_FILE },
{ "prev-tag", A_PREV_TAG },
{ "quit", A_QUIT },
{ "remove-file", A_REMOVE_FILE },
{ "repaint", A_REPAINT },
{ "repaint-flush", A_FREPAINT },
{ "repeat-search", A_AGAIN_SEARCH },
{ "repeat-search-all", A_T_AGAIN_SEARCH },
{ "reverse-search", A_REVERSE_SEARCH },
{ "reverse-search-all", A_T_REVERSE_SEARCH },
{ "right-scroll", A_RSHIFT },
{ "set-mark", A_SETMARK },
{ "set-mark-bottom", A_SETMARKBOT },
{ "shell", A_SHELL },
{ "status", A_STAT },
{ "toggle-flag", A_OPT_TOGGLE },
{ "toggle-option", A_OPT_TOGGLE },
{ "undo-hilite", A_UNDO_SEARCH },
{ "clear-search", A_CLR_SEARCH },
{ "version", A_VERSION },
{ "visual", A_VISUAL },
{ NULL, 0 }
};
static struct lesskey_cmdname editnames[] =
{
{ "back-complete", EC_B_COMPLETE },
{ "backspace", EC_BACKSPACE },
{ "delete", EC_DELETE },
{ "down", EC_DOWN },
{ "end", EC_END },
{ "expand", EC_EXPAND },
{ "forw-complete", EC_F_COMPLETE },
{ "home", EC_HOME },
{ "insert", EC_INSERT },
{ "invalid", EC_UINVALID },
{ "kill-line", EC_LINEKILL },
{ "abort", EC_ABORT },
{ "left", EC_LEFT },
{ "literal", EC_LITERAL },
{ "right", EC_RIGHT },
{ "up", EC_UP },
{ "word-backspace", EC_W_BACKSPACE },
{ "word-delete", EC_W_DELETE },
{ "word-left", EC_W_LEFT },
{ "word-right", EC_W_RIGHT },
{ NULL, 0 }
};
/*
* Print a parse error message.
*/
static void
parse_error(s1, s2)
char *s1;
char *s2;
{
char buf[1024];
++errors;
snprintf(buf, sizeof(buf), "%s: line %d: %s%s", lesskey_file, linenum, s1, s2);
lesskey_parse_error(buf);
}
/*
* Initialize lesskey_tables.
*/
static void
init_tables(tables)
struct lesskey_tables *tables;
{
tables->currtable = &tables->cmdtable;
tables->cmdtable.names = cmdnames;
tables->cmdtable.is_var = 0;
xbuf_init(&tables->cmdtable.buf);
tables->edittable.names = editnames;
tables->edittable.is_var = 0;
xbuf_init(&tables->edittable.buf);
tables->vartable.names = NULL;
tables->vartable.is_var = 1;
xbuf_init(&tables->vartable.buf);
}
/*
* Parse one character of a string.
*/
static char *
tstr(pp, xlate)
char **pp;
int xlate;
{
char *p;
char ch;
int i;
static char buf[10];
static char tstr_control_k[] =
{ SK_SPECIAL_KEY, SK_CONTROL_K, 6, 1, 1, 1, '\0' };
p = *pp;
switch (*p)
{
case '\\':
++p;
switch (*p)
{
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
/*
* Parse an octal number.
*/
ch = 0;
i = 0;
do
ch = 8*ch + (*p - '0');
while (*++p >= '0' && *p <= '7' && ++i < 3);
*pp = p;
if (xlate && ch == CONTROL('K'))
return tstr_control_k;
buf[0] = ch;
buf[1] = '\0';
return (buf);
case 'b':
*pp = p+1;
return ("\b");
case 'e':
*pp = p+1;
buf[0] = ESC;
buf[1] = '\0';
return (buf);
case 'n':
*pp = p+1;
return ("\n");
case 'r':
*pp = p+1;
return ("\r");
case 't':
*pp = p+1;
return ("\t");
case 'k':
if (xlate)
{
switch (*++p)
{
case 'u': ch = SK_UP_ARROW; break;
case 'd': ch = SK_DOWN_ARROW; break;
case 'r': ch = SK_RIGHT_ARROW; break;
case 'l': ch = SK_LEFT_ARROW; break;
case 'U': ch = SK_PAGE_UP; break;
case 'D': ch = SK_PAGE_DOWN; break;
case 'h': ch = SK_HOME; break;
case 'e': ch = SK_END; break;
case 'x': ch = SK_DELETE; break;
default: { char buf[2]; buf[0] = *p; buf[1] = '\0';
parse_error("illegal escape sequence \\k", buf);
*pp = p+1;
return (""); }
}
*pp = p+1;
buf[0] = SK_SPECIAL_KEY;
buf[1] = ch;
buf[2] = 6;
buf[3] = 1;
buf[4] = 1;
buf[5] = 1;
buf[6] = '\0';
return (buf);
}
/* FALLTHRU */
default:
/*
* Backslash followed by any other char
* just means that char.
*/
*pp = p+1;
buf[0] = *p;
buf[1] = '\0';
if (xlate && buf[0] == CONTROL('K'))
return tstr_control_k;
return (buf);
}
case '^':
/*
* Caret means CONTROL.
*/
*pp = p+2;
buf[0] = CONTROL(p[1]);
buf[1] = '\0';
if (xlate && buf[0] == CONTROL('K'))
return tstr_control_k;
return (buf);
}
*pp = p+1;
buf[0] = *p;
buf[1] = '\0';
if (xlate && buf[0] == CONTROL('K'))
return tstr_control_k;
return (buf);
}
static int
issp(ch)
char ch;
{
return (ch == ' ' || ch == '\t');
}
/*
* Skip leading spaces in a string.
*/
static char *
skipsp(s)
char *s;
{
while (issp(*s))
s++;
return (s);
}
/*
* Skip non-space characters in a string.
*/
static char *
skipnsp(s)
char *s;
{
while (*s != '\0' && !issp(*s))
s++;
return (s);
}
/*
* Clean up an input line:
* strip off the trailing newline & any trailing # comment.
*/
static char *
clean_line(s)
char *s;
{
int i;
s = skipsp(s);
for (i = 0; s[i] != '\0' && s[i] != '\n' && s[i] != '\r'; i++)
if (s[i] == '#' && (i == 0 || s[i-1] != '\\'))
break;
s[i] = '\0';
return (s);
}
/*
* Add a byte to the output command table.
*/
static void
add_cmd_char(c, tables)
int c;
struct lesskey_tables *tables;
{
xbuf_add(&tables->currtable->buf, c);
}
/*
* Add a string to the output command table.
*/
static void
add_cmd_str(s, tables)
char *s;
struct lesskey_tables *tables;
{
for ( ; *s != '\0'; s++)
add_cmd_char(*s, tables);
}
/*
* See if we have a special "control" line.
*/
static int
control_line(s, tables)
char *s;
struct lesskey_tables *tables;
{
#define PREFIX(str,pat) (strncmp(str,pat,strlen(pat)) == 0)
if (PREFIX(s, "#line-edit"))
{
tables->currtable = &tables->edittable;
return (1);
}
if (PREFIX(s, "#command"))
{
tables->currtable = &tables->cmdtable;
return (1);
}
if (PREFIX(s, "#env"))
{
tables->currtable = &tables->vartable;
return (1);
}
if (PREFIX(s, "#stop"))
{
add_cmd_char('\0', tables);
add_cmd_char(A_END_LIST, tables);
return (1);
}
return (0);
}
/*
* Find an action, given the name of the action.
*/
static int
findaction(actname, tables)
char *actname;
struct lesskey_tables *tables;
{
int i;
for (i = 0; tables->currtable->names[i].cn_name != NULL; i++)
if (strcmp(tables->currtable->names[i].cn_name, actname) == 0)
return (tables->currtable->names[i].cn_action);
parse_error("unknown action: ", actname);
return (A_INVALID);
}
/*
* Parse a line describing one key binding, of the form
* KEY ACTION [EXTRA]
* where KEY is the user key sequence, ACTION is the
* resulting less action, and EXTRA is an "extra" user
* key sequence injected after the action.
*/
static void
parse_cmdline(p, tables)
char *p;
struct lesskey_tables *tables;
{
char *actname;
int action;
char *s;
char c;
/*
* Parse the command string and store it in the current table.
*/
do
{
s = tstr(&p, 1);
add_cmd_str(s, tables);
} while (*p != '\0' && !issp(*p));
/*
* Terminate the command string with a null byte.
*/
add_cmd_char('\0', tables);
/*
* Skip white space between the command string
* and the action name.
* Terminate the action name with a null byte.
*/
p = skipsp(p);
if (*p == '\0')
{
parse_error("missing action", "");
return;
}
actname = p;
p = skipnsp(p);
c = *p;
*p = '\0';
/*
* Parse the action name and store it in the current table.
*/
action = findaction(actname, tables);
/*
* See if an extra string follows the action name.
*/
*p = c;
p = skipsp(p);
if (*p == '\0')
{
add_cmd_char(action, tables);
} else
{
/*
* OR the special value A_EXTRA into the action byte.
* Put the extra string after the action byte.
*/
add_cmd_char(action | A_EXTRA, tables);
while (*p != '\0')
add_cmd_str(tstr(&p, 0), tables);
add_cmd_char('\0', tables);
}
}
/*
* Parse a variable definition line, of the form
* NAME = VALUE
*/
static void
parse_varline(line, tables)
char *line;
struct lesskey_tables *tables;
{
char *s;
char *p = line;
do
{
s = tstr(&p, 0);
add_cmd_str(s, tables);
} while (*p != '\0' && !issp(*p) && *p != '=');
/*
* Terminate the variable name with a null byte.
*/
add_cmd_char('\0', tables);
p = skipsp(p);
if (*p++ != '=')
{
parse_error("missing = in: ", line);
return;
}
add_cmd_char(EV_OK|A_EXTRA, tables);
p = skipsp(p);
while (*p != '\0')
{
s = tstr(&p, 0);
add_cmd_str(s, tables);
}
add_cmd_char('\0', tables);
}
/*
* Parse a line from the lesskey file.
*/
static void
parse_line(line, tables)
char *line;
struct lesskey_tables *tables;
{
char *p;
/*
* See if it is a control line.
*/
if (control_line(line, tables))
return;
/*
* Skip leading white space.
* Replace the final newline with a null byte.
* Ignore blank lines and comments.
*/
p = clean_line(line);
if (*p == '\0')
return;
if (tables->currtable->is_var)
parse_varline(p, tables);
else
parse_cmdline(p, tables);
}
/*
* Parse a lesskey source file and store result in tables.
*/
int
parse_lesskey(infile, tables)
char *infile;
struct lesskey_tables *tables;
{
FILE *desc;
char line[1024];
if (infile == NULL)
infile = homefile(DEF_LESSKEYINFILE);
lesskey_file = infile;
init_tables(tables);
errors = 0;
linenum = 0;
/*
* Open the input file.
*/
if (strcmp(infile, "-") == 0)
desc = stdin;
else if ((desc = fopen(infile, "r")) == NULL)
{
/* parse_error("cannot open lesskey file ", infile); */
return (-1);
}
/*
* Read and parse the input file, one line at a time.
*/
while (fgets(line, sizeof(line), desc) != NULL)
{
++linenum;
parse_line(line, tables);
}
return (errors);
}

View file

@ -33,11 +33,8 @@ static struct {
int pfx_end; /* Number of chars in pfx */
} linebuf;
static struct {
char *buf;
int size;
int end;
} shifted_ansi;
struct xbuffer shifted_ansi;
struct xbuffer last_ansi;
public int size_linebuf = 0; /* Size of line buffer (and attr buffer) */
static struct ansi_state *line_ansi = NULL;
@ -58,6 +55,7 @@ static LWCHAR pendc;
static POSITION pendpos;
static char *end_ansi_chars;
static char *mid_ansi_chars;
static int in_hilite;
static int attr_swidth LESSPARAMS ((int a));
static int attr_ewidth LESSPARAMS ((int a));
@ -131,8 +129,8 @@ init_line(VOID_PARAM)
linebuf.buf = (char *) ecalloc(LINEBUF_SIZE, sizeof(char));
linebuf.attr = (int *) ecalloc(LINEBUF_SIZE, sizeof(int));
size_linebuf = LINEBUF_SIZE;
shifted_ansi.buf = NULL;
shifted_ansi.size = 0;
xbuf_init(&shifted_ansi);
xbuf_init(&last_ansi);
}
/*
@ -222,7 +220,9 @@ prewind(VOID_PARAM)
mbc_buf_len = 0;
is_null_line = 0;
pendc = '\0';
shifted_ansi.end = 0;
in_hilite = 0;
xbuf_reset(&shifted_ansi);
xbuf_reset(&last_ansi);
}
/*
@ -354,26 +354,6 @@ line_pfx_width(VOID_PARAM)
return width;
}
/*
* Add char to the shifted_ansi buffer.
*/
static void
add_ansi(ch)
char ch;
{
if (shifted_ansi.end == shifted_ansi.size)
{
/* Expand shifted_ansi buffer. */
int size = (shifted_ansi.size == 0) ? 8 : shifted_ansi.size * 2;
char *buf = (char *) ecalloc(size, sizeof(char));
memcpy(buf, shifted_ansi.buf, shifted_ansi.size);
if (shifted_ansi.buf != NULL) free(shifted_ansi.buf);
shifted_ansi.buf = buf;
shifted_ansi.size = size;
}
shifted_ansi.buf[shifted_ansi.end++] = ch;
}
/*
* Shift line left so that the last char is just to the left
* of the first visible column.
@ -384,7 +364,7 @@ pshift_all(VOID_PARAM)
int i;
for (i = linebuf.print; i < linebuf.end; i++)
if (linebuf.attr[i] == AT_ANSI)
add_ansi(linebuf.buf[i]);
xbuf_add(&shifted_ansi, linebuf.buf[i]);
linebuf.end = linebuf.print;
end_column = linebuf.pfx_end;
}
@ -676,6 +656,7 @@ store_char(ch, a, rep, pos)
#if HILITE_SEARCH
{
int matches;
int resend_last = 0;
int hl_attr = is_hilited_attr(pos, pos+1, 0, &matches);
if (hl_attr)
{
@ -689,6 +670,23 @@ store_char(ch, a, rep, pos)
highest_hilite = pos;
a |= hl_attr;
}
in_hilite = 1;
} else
{
if (in_hilite)
{
/*
* This is the first non-hilited char after a hilite.
* Resend the last ANSI seq to restore color.
*/
resend_last = 1;
}
in_hilite = 0;
}
if (resend_last)
{
for (i = 0; i < last_ansi.end; i++)
STORE_CHAR(last_ansi.data[i], AT_ANSI, NULL, pos);
}
}
#endif
@ -731,8 +729,8 @@ store_char(ch, a, rep, pos)
{
/* Copy shifted ANSI sequences to beginning of line. */
for (i = 0; i < shifted_ansi.end; i++)
add_linebuf(shifted_ansi.buf[i], AT_ANSI, 0);
shifted_ansi.end = 0;
add_linebuf(shifted_ansi.data[i], AT_ANSI, 0);
xbuf_reset(&shifted_ansi);
}
/* Add the char to the buf, even if we will left-shift it next. */
inc_end_column(w);
@ -743,12 +741,16 @@ store_char(ch, a, rep, pos)
{
/* We haven't left-shifted enough yet. */
if (a == AT_ANSI)
add_ansi(ch); /* Save ANSI attributes */
xbuf_add(&shifted_ansi, ch); /* Save ANSI attributes */
if (linebuf.end > linebuf.print)
{
/* Shift left enough to put last byte of this char at print-1. */
memcpy(&linebuf.buf[0], &linebuf.buf[replen], linebuf.print);
memcpy(&linebuf.attr[0], &linebuf.attr[replen], linebuf.print);
int i;
for (i = 0; i < linebuf.print; i++)
{
linebuf.buf[i] = linebuf.buf[i+replen];
linebuf.attr[i] = linebuf.attr[i+replen];
}
linebuf.end -= replen;
cshift += w;
/*
@ -954,16 +956,18 @@ store_ansi(ch, rep, pos)
switch (ansi_step(line_ansi, ch))
{
case ANSI_MID:
STORE_CHAR(ch, AT_ANSI, rep, pos);
if (!in_hilite)
STORE_CHAR(ch, AT_ANSI, rep, pos);
break;
case ANSI_END:
STORE_CHAR(ch, AT_ANSI, rep, pos);
if (!in_hilite)
STORE_CHAR(ch, AT_ANSI, rep, pos);
ansi_done(line_ansi);
line_ansi = NULL;
break;
case ANSI_ERR: {
/* Remove whole unrecognized sequence. */
char *start = (cshift < hshift) ? shifted_ansi.buf : linebuf.buf;
char *start = (cshift < hshift) ? shifted_ansi.data : linebuf.buf;
int *end = (cshift < hshift) ? &shifted_ansi.end : &linebuf.end;
char *p = start + *end;
LWCHAR bch;
@ -1006,10 +1010,17 @@ do_append(ch, rep, pos)
int a = AT_NORMAL;
if (ctldisp == OPT_ONPLUS && line_ansi == NULL)
{
line_ansi = ansi_start(ch);
if (line_ansi != NULL)
xbuf_reset(&last_ansi);
}
if (line_ansi != NULL)
{
xbuf_add(&last_ansi, ch);
return store_ansi(ch, rep, pos);
}
if (ch == '\b')
return store_bs(ch, rep, pos);

View file

@ -469,3 +469,26 @@ currline(where)
linenum--;
return (linenum);
}
/*
* Scan entire file, counting line numbers.
*/
public void
scan_eof(VOID_PARAM)
{
POSITION pos = 0;
LINENUM linenum = 0;
if (ch_seek(0))
return;
ierror("Determining length of file", NULL_PARG);
while (pos != NULL_POSITION)
{
/* For efficiency, only add one every 256 line numbers. */
if ((linenum++ % 256) == 0)
add_lnum(linenum, pos);
pos = forw_raw_line(pos, (char **)NULL, (int *)NULL);
if (ABORT_SIGS())
break;
}
}

View file

@ -58,6 +58,7 @@ extern int less_is_more;
extern int linenum_width;
extern int status_col_width;
extern int use_color;
extern int want_filesize;
#if LOGFILE
extern char *namelogfile;
extern int force_logfile;
@ -163,7 +164,7 @@ opt_j(type, s)
char *s;
{
PARG parg;
char buf[16];
char buf[24];
int len;
int err;
@ -199,7 +200,7 @@ opt_j(type, s)
} else
{
sprintf(buf, ".%06ld", jump_sline_fraction);
SNPRINTF1(buf, sizeof(buf), ".%06ld", jump_sline_fraction);
len = (int) strlen(buf);
while (len > 2 && buf[len-1] == '0')
len--;
@ -228,7 +229,7 @@ opt_shift(type, s)
char *s;
{
PARG parg;
char buf[16];
char buf[24];
int len;
int err;
@ -264,7 +265,7 @@ opt_shift(type, s)
} else
{
sprintf(buf, ".%06ld", shift_count_fraction);
SNPRINTF1(buf, sizeof(buf), ".%06ld", shift_count_fraction);
len = (int) strlen(buf);
while (len > 2 && buf[len-1] == '0')
len--;
@ -275,6 +276,7 @@ opt_shift(type, s)
break;
}
}
public void
calc_shift_count(VOID_PARAM)
{
@ -302,7 +304,28 @@ opt_k(type, s)
break;
}
}
#endif
#if HAVE_LESSKEYSRC
public void
opt_ks(type, s)
int type;
char *s;
{
PARG parg;
switch (type)
{
case INIT:
if (lesskey_src(s, 0))
{
parg.p_string = s;
error("Cannot use lesskey source file \"%s\"", &parg);
}
break;
}
}
#endif /* HAVE_LESSKEYSRC */
#endif /* USERFILE */
#if TAGS
/*
@ -518,9 +541,8 @@ opt__V(type, s)
putstr(pattern_lib_name());
putstr(" regular expressions)\n");
{
char constant *copyright = "Copyright (C) 1984-2021 Mark Nudelman\n\n";
if (copyright[0] == '@')
copyright = "Copyright (C) 1984 Mark Nudelman\n\n";
char constant *copyright =
"Copyright (C) 1984-2021 Mark Nudelman\n\n";
putstr(copyright);
}
if (version[strlen(version)-1] == 'x')
@ -590,7 +612,7 @@ color_from_namechar(namechar)
{
switch (namechar)
{
case 'A': return AT_COLOR_ATTN;
case 'W': case 'A': return AT_COLOR_ATTN;
case 'B': return AT_COLOR_BIN;
case 'C': return AT_COLOR_CTRL;
case 'E': return AT_COLOR_ERROR;
@ -940,6 +962,27 @@ opt_status_col_width(type, s)
}
}
/*
* Handler for the --file-size option.
*/
/*ARGSUSED*/
public void
opt_filesize(type, s)
int type;
char *s;
{
switch (type)
{
case INIT:
case TOGGLE:
if (want_filesize && curr_ifile != NULL && ch_length() == NULL_POSITION)
scan_eof();
break;
case QUERY:
break;
}
}
#if LESSTEST
/*
* Handler for the --tty option.

View file

@ -63,6 +63,7 @@ public int linenum_width; /* Width of line numbers */
public int status_col_width; /* Width of status column */
public int incr_search; /* Incremental search */
public int use_color; /* Use UI color */
public int want_filesize; /* */
#if HILITE_SEARCH
public int hilite_search; /* Highlight matched search patterns? */
#endif
@ -90,6 +91,9 @@ static struct optname j_optname = { "jump-target", NULL };
static struct optname J__optname = { "status-column", NULL };
#if USERFILE
static struct optname k_optname = { "lesskey-file", NULL };
#if HAVE_LESSKEYSRC
static struct optname ks_optname = { "lesskey-src", NULL };
#endif /* HAVE_LESSKEYSRC */
#endif
static struct optname K__optname = { "quit-on-intr", NULL };
static struct optname L__optname = { "no-lessopen", NULL };
@ -134,6 +138,7 @@ static struct optname linenum_width_optname = { "line-num-width", NULL };
static struct optname status_col_width_optname = { "status-col-width", NULL };
static struct optname incr_search_optname = { "incsearch", NULL };
static struct optname use_color_optname = { "use-color", NULL };
static struct optname want_filesize_optname = { "file-size", NULL };
#if LESSTEST
static struct optname ttyin_name_optname = { "tty", NULL };
static struct optname rstat_optname = { "rstat", NULL };
@ -274,6 +279,12 @@ static struct loption option[] =
STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_k,
{ NULL, NULL, NULL }
},
#if HAVE_LESSKEYSRC
{ OLETTER_NONE, &ks_optname,
STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_ks,
{ NULL, NULL, NULL }
},
#endif /* HAVE_LESSKEYSRC */
#endif
{ 'K', &K__optname,
BOOL, OPT_OFF, &quit_on_intr, NULL,
@ -337,8 +348,8 @@ static struct loption option[] =
TRIPLE|REPAINT, OPT_OFF, &ctldisp, NULL,
{
"Display control characters as ^X",
"Display control characters directly",
"Display control characters directly, processing ANSI sequences"
"Display control characters directly (not recommended)",
"Display ANSI sequences directly, other control characters as ^X"
}
},
{ 's', &s_optname,
@ -543,6 +554,14 @@ static struct loption option[] =
NULL
}
},
{ OLETTER_NONE, &want_filesize_optname,
BOOL|REPAINT, OPT_OFF, &want_filesize, opt_filesize,
{
"Don't get size of each file",
"Get size of each file",
NULL
}
},
#if LESSTEST
{ OLETTER_NONE, &ttyin_name_optname,
STRING|NO_TOGGLE, 0, NULL, opt_ttyin_name,

View file

@ -431,11 +431,7 @@ putchr(c)
ubuf_len = 0;
}
#endif
if (need_clr)
{
need_clr = 0;
clear_bot();
}
clear_bot_if_needed();
#if MSDOS_COMPILER
if (c == '\n' && is_tty)
{
@ -459,6 +455,15 @@ putchr(c)
return (c);
}
public void
clear_bot_if_needed(VOID_PARAM)
{
if (!need_clr)
return;
need_clr = 0;
clear_bot();
}
/*
* Output a string.
*/

View file

@ -843,10 +843,10 @@ scrsize(VOID_PARAM)
#endif
#endif
if ((s = lgetenv("LINES")) != NULL)
sc_height = atoi(s);
else if (sys_height > 0)
if (sys_height > 0)
sc_height = sys_height;
else if ((s = lgetenv("LINES")) != NULL)
sc_height = atoi(s);
#if !MSDOS_COMPILER
else if ((n = ltgetnum("li")) > 0)
sc_height = n;
@ -854,10 +854,10 @@ scrsize(VOID_PARAM)
if (sc_height <= 0)
sc_height = DEF_SC_HEIGHT;
if ((s = lgetenv("COLUMNS")) != NULL)
sc_width = atoi(s);
else if (sys_width > 0)
if (sys_width > 0)
sc_width = sys_width;
else if ((s = lgetenv("COLUMNS")) != NULL)
sc_width = atoi(s);
#if !MSDOS_COMPILER
else if ((n = ltgetnum("co")) > 0)
sc_width = n;
@ -1707,6 +1707,7 @@ deinit_mouse(VOID_PARAM)
public void
init(VOID_PARAM)
{
clear_bot_if_needed();
#if !MSDOS_COMPILER
if (!(quit_if_one_screen && one_screen))
{
@ -2526,7 +2527,7 @@ tput_fmt(fmt, color, f_putc)
int color;
int (*f_putc)(int);
{
char buf[16];
char buf[32];
if (color == attrcolor)
return;
SNPRINTF1(buf, sizeof(buf), fmt, color);

View file

@ -272,6 +272,7 @@ findctag(tag)
char *tag;
{
char *p;
char *q;
FILE *f;
int taglen;
LINENUM taglinenum;
@ -352,17 +353,24 @@ findctag(tag)
search_char = *p++;
if (*p == '^')
p++;
tagpattern = p;
tagpattern = q = p;
while (*p != search_char && *p != '\0')
{
if (*p == '\\')
p++;
p++;
if (q != p)
{
*q++ = *p++;
} else
{
q++;
p++;
}
}
tagendline = (p[-1] == '$');
tagendline = (q[-1] == '$');
if (tagendline)
p--;
*p = '\0';
q--;
*q = '\0';
}
tp = maketagent(tag, tagfile, taglinenum, tagpattern, tagendline);
TAG_INS(tp);

View file

@ -919,7 +919,18 @@ v578 2/9/21 Doc
v579 2/14/21 Fix double-width char bugs and non-match search crash.
v580 3/2/21 Some color fixes; fix compiler warnings; some lesstest support.
v581 4/6/21 Ignore SIGTSTP in secure mode; don't print "skipping" when filtering.
v581.2 4/28/21 Fix failure to deinit mouse.
v582 4/21/21 Less now reads lesskey source file rather than binary;
fix bug in finding tags with backslashes.
v583 4/21/21 Use XDG_CONFIG_HOME and XDG_DATA_HOME to find files.
v584 4/30/21 Add --file-size option.
v585 5/2/21 Allow color desc W per man page.
v586 5/7/21 Doc changes.
v587 5/27/21 Fix --with-secure; fix --file-size message on Windows;
fix colored search hilite in colored text; don't exit
if -F and screen is resized; fix memcpy usage.
v588 5/27/21 Fix release.
v589 5/29/21 Copyright & build changes.
v590 6/3/21 Fix non-autoconf Makefiles.
*/
char version[] = "581.2";
char version[] = "590";

52
contrib/less/xbuf.c Normal file
View file

@ -0,0 +1,52 @@
#include "less.h"
#include "xbuf.h"
/*
* Initialize an expandable text buffer.
*/
public void
xbuf_init(xbuf)
struct xbuffer *xbuf;
{
xbuf->data = NULL;
xbuf->size = xbuf->end = 0;
}
public void
xbuf_deinit(xbuf)
struct xbuffer *xbuf;
{
if (xbuf->data != NULL)
free(xbuf->data);
xbuf_init(xbuf);
}
public void
xbuf_reset(xbuf)
struct xbuffer *xbuf;
{
xbuf->end = 0;
}
/*
* Add a char to an expandable text buffer.
*/
public void
xbuf_add(xbuf, ch)
struct xbuffer *xbuf;
char ch;
{
if (xbuf->end >= xbuf->size)
{
char *data;
xbuf->size = (xbuf->size == 0) ? 16 : xbuf->size * 2;
data = (char *) ecalloc(xbuf->size, sizeof(char));
if (xbuf->data != NULL)
{
memcpy(data, xbuf->data, xbuf->end);
free(xbuf->data);
}
xbuf->data = data;
}
xbuf->data[xbuf->end++] = ch;
}

15
contrib/less/xbuf.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef XBUF_H_
#define XBUF_H_
struct xbuffer
{
char *data;
int end;
int size;
};
void xbuf_init(struct xbuffer *xbuf);
void xbuf_reset(struct xbuffer *xbuf);
void xbuf_add(struct xbuffer *xbuf, char ch);
#endif

View file

@ -5,7 +5,7 @@ SRCS= main.c screen.c brac.c ch.c charset.c cmdbuf.c command.c cvt.c \
decode.c edit.c filename.c forwback.c help.c ifile.c input.c \
jump.c line.c linenum.c lsystem.c mark.c optfunc.c option.c \
opttbl.c os.c output.c pattern.c position.c prompt.c search.c \
signal.c tags.c ttyin.c version.c
signal.c tags.c ttyin.c version.c xbuf.c
SCRIPTS=lesspipe.sh zless.sh
SCRIPTSNAME_lesspipe.sh=lesspipe.sh
LIBADD= ncursesw

View file

@ -81,7 +81,7 @@
* PIPEC is 1 if you wish to have the "|" command
* which allows the user to pipe data into a shell command.
*/
#define PIPEC (!SECURE)
#define PIPEC (!SECURE && HAVE_POPEN)
/*
* LOGFILE is 1 if you wish to allow the -o option (to create log files).
@ -113,6 +113,7 @@
#define LESSKEYFILE ".less"
#define LESSKEYFILE_SYS "/etc/lesskey"
#define DEF_LESSKEYINFILE ".lesskey"
#define LESSKEYINFILE_SYS "/etc/syslesskey"
#define LESSHISTFILE ".lesshst"
@ -185,6 +186,9 @@
/* Define to 1 if you have the strstr() function. */
#define HAVE_STRSTR 1
/* Define to 1 to support reading lesskey source files (not just binary). */
#define HAVE_LESSKEYSRC 1
/*
* Sizes of various buffers.
*/

View file

@ -1,7 +1,7 @@
# $FreeBSD$
PROG= lesskey
SRCS= lesskey.c version.c
SRCS= lesskey.c lesskey_parse.c version.c xbuf.c
CLEANFILES= lesskey.1
.include "${SRCTOP}/usr.bin/less/Makefile.common"