From 1737d9dd586fd32916293643b7b06c088f8c22e7 Mon Sep 17 00:00:00 2001 From: Xin LI Date: Sun, 18 Apr 2021 18:15:19 -0700 Subject: [PATCH] Vendor import of less v581. --- INSTALL | 10 +- Makefile.aut | 18 +- Makefile.wng | 132 ++++++ Makefile.wnm | 2 +- NEWS | 50 +- README | 38 +- brac.c | 2 +- ch.c | 54 +-- charset.c | 154 +++---- charset.h | 2 +- cmd.h | 20 +- cmdbuf.c | 87 ++-- command.c | 187 +++++--- configure | 4 +- configure.ac | 4 +- cvt.c | 12 +- decode.c | 361 ++++++++------- defines.ds | 2 +- defines.h.in | 12 + defines.o2 | 2 +- defines.o9 | 2 +- defines.wn | 2 +- edit.c | 33 +- filename.c | 29 +- forwback.c | 11 +- funcs.h | 35 +- help.c | 24 +- ifile.c | 39 +- input.c | 45 +- jump.c | 2 +- less.h | 419 +++++++++-------- less.hlp | 22 +- less.man | 1238 ++++++++++++++++++++++++++++---------------------- less.nro | 204 +++++++-- lessecho.c | 14 +- lessecho.man | 6 +- lessecho.nro | 8 +- lesskey.c | 163 +++---- lesskey.h | 38 +- lesskey.man | 69 +-- lesskey.nro | 25 +- lglob.h | 110 ++--- line.c | 905 ++++++++++++++++++++---------------- linenum.c | 31 +- lsystem.c | 44 +- main.c | 84 ++-- mark.c | 26 +- mkfuncs.pl | 0 mkfuncs.py | 26 ++ mkhelp.py | 36 ++ optfunc.c | 313 +++++++++---- option.c | 25 +- option.h | 62 +-- opttbl.c | 154 +++++-- os.c | 94 +++- output.c | 612 +++++++++++++------------ pattern.c | 11 +- pattern.h | 18 +- pckeys.h | 38 +- position.c | 12 +- position.h | 12 +- prompt.c | 88 ++-- regexp.h | 14 +- screen.c | 782 ++++++++++++++++++++++--------- scrsize.c | 2 +- search.c | 359 +++++++++++---- signal.c | 11 +- tags.c | 77 ++-- ttyin.c | 51 ++- version.c | 29 +- 70 files changed, 4711 insertions(+), 2896 deletions(-) create mode 100644 Makefile.wng mode change 100644 => 100755 mkfuncs.pl create mode 100755 mkfuncs.py create mode 100755 mkhelp.py diff --git a/INSTALL b/INSTALL index c2ab230e4470..78ae93246d88 100644 --- a/INSTALL +++ b/INSTALL @@ -1,6 +1,6 @@ - This file describes how to build and install less using -the "configure" script. This only works on Unix systems. -To install on other systems, read the README file. +This file contains generic instructions on how to build and +install software using autoconf. For specific instructions +on how to build "less", see the README or README.VER file. Basic Installation @@ -24,8 +24,8 @@ diffs or instructions to the address given in the `README' so they can be considered for the next release. If at some point `config.cache' contains results you don't want to keep, you may remove or edit it. - The file `configure.in' is used to create `configure' by a program -called `autoconf'. You only need `configure.in' if you want to change + The file `configure.ac' is used to create `configure' by a program +called `autoconf'. You only need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: diff --git a/Makefile.aut b/Makefile.aut index 89309b583e2a..b6f2101cf10f 100644 --- a/Makefile.aut +++ b/Makefile.aut @@ -1,13 +1,21 @@ # Makefile for authoring less. EMAIL = bug-less@gnu.org -HOMEPAGE = http://www.greenwoodsoftware.com/less +HOMEPAGE = https://greenwoodsoftware.com/less SHELL = /bin/sh GIT = git NROFF = nroff -t -man srcdir = . +ifeq ($(USE_PYTHON),1) + MKHELP = mkhelp.py + MKFUNCS = mkfuncs.py +else + MKHELP = mkhelp.pl + MKFUNCS = mkfuncs.pl +endif + SRC = \ main.c screen.c brac.c ch.c charset.c cmdbuf.c \ command.c cvt.c decode.c edit.c filename.c forwback.c \ @@ -19,7 +27,7 @@ DISTFILES_W = \ defines.ds Makefile.dsb Makefile.dsg Makefile.dsu \ defines.o2 Makefile.o2e \ defines.o9 Makefile.o9c Makefile.o9u \ - defines.wn Makefile.wnm Makefile.wnb \ + defines.wn Makefile.wnm Makefile.wnb Makefile.wng \ configure UNICODE_FILES = \ compose.uni fmt.uni ubin.uni wide.uni @@ -33,6 +41,7 @@ DISTFILES = \ less.nro less.man lesskey.nro lesskey.man lessecho.nro lessecho.man \ less.hlp \ mkfuncs.pl mkhelp.pl \ + mkfuncs.py mkhelp.py \ mkutable $(UNICODE_FILES) \ ${DISTFILES_W} @@ -49,7 +58,7 @@ release: .FORCE help.c: less.hlp -mv -f ${srcdir}/help.c ${srcdir}/help.c.old rm -rf help.c - ${srcdir}/mkhelp.pl < less.hlp > help.c + ${srcdir}/${MKHELP} < less.hlp > help.c if cmp -s help.c help.c.old; then mv -f help.c.old help.c; fi ${srcdir}/configure ${srcdir}/defines.h.in: ${srcdir}/configure.ac ${srcdir}/Makefile.in @@ -57,7 +66,7 @@ ${srcdir}/configure ${srcdir}/defines.h.in: ${srcdir}/configure.ac ${srcdir}/Mak funcs.h: ${SRC:%=${srcdir}/%} -mv -f ${srcdir}/funcs.h ${srcdir}/funcs.h.old - perl ${srcdir}/mkfuncs.pl ${SRC:%=${srcdir}/%} >${srcdir}/funcs.h + ${srcdir}/${MKFUNCS} ${SRC:%=${srcdir}/%} >${srcdir}/funcs.h if cmp -s funcs.h funcs.h.old; then mv -f funcs.h.old funcs.h; fi lint: @@ -80,7 +89,6 @@ REPLACE_VERSION = \ sed \ -e "s;@@VERSION@@;$$REL;" \ -e "s;@@DATE@@;$$DT;" \ - -e "s;@@EMAIL@@;${EMAIL};" \ -e "s;@@HOMEPAGE@@;${HOMEPAGE};" >$@ ${srcdir}/README: ${srcdir}/README.VER ${srcdir}/version.c diff --git a/Makefile.wng b/Makefile.wng new file mode 100644 index 000000000000..85686068c57b --- /dev/null +++ b/Makefile.wng @@ -0,0 +1,132 @@ +# Makefile for less using mingw-w64 package: +# http://mingw-w64.org/doku.php +# +# Derived from Makefile.wnm +# +# Usage: mingw32-make -f Makefile.wng [REGEX_PACKAGE={posix|gnu|regcomp-local}] +# +# The optional command line parameter "REGEX_PACKAGE" is used to specify +# a regular expression package for compilation and linking. This parameter +# can assume one of three values. +# +# REGEX_PACKAGE == regcomp-local +# This choice selects the regular expression package written by Henry +# Spencer. It is implemented by the repository file "regexp.c". +# +# REGEX_PACKAGE == posix +# This choice selects the POSIX implementation and is provided by MingW. +# This is the default choice. +# +# REGEX_PACKAGE == gnu +# This choice selects the GNU implementation and is provided by MingW. +# + +#### Start of system configuration section. #### + +CC = gcc + +# Definitions specific to mingw +# +MINGW_DEFINES = -DMINGW -DWIN32 + +# This specifies the "root" directory of the MingW installation. +# It is defined so that the compiler and linker can find the header files +# and library that provide regular expression support. +# +MINGW_ROOT_PATH = /mingw-w64/mingw64 + +# Determine the regular expression package to be used. +# +REGEX_PACKAGE ?= posix +ifeq (${REGEX_PACKAGE},regcomp-local) + MINGW_DEFINES += -DUSE_REGEXP_C +else ifeq (${REGEX_PACKAGE},posix) + MINGW_DEFINES += -DUSE_POSIX_REGCOMP +else ifeq (${REGEX_PACKAGE},gnu) + MINGW_DEFINES += -DUSE_GNU_REGEX +else + $(error REGEX_PACKAGE must be posix, gnu or regcomp-local) +endif + +MINGW_REGEX_IPATH = -I${MINGW_ROOT_PATH}/opt/include +MINGW_REGEX_LPATH = -L${MINGW_ROOT_PATH}/opt/lib +MINGW_REGEX_LIB = -lregex + +CFLAGS_MINGW = ${MINGW_DEFINES} +ifneq (${REGEX_PACKAGE},regcomp-local) +CFLAGS_MINGW += ${MINGW_REGEX_IPATH} +endif + +# MingW may use sh.exe instead of cmd.exe. +# Make sure it does not. +# +SHELL = cmd.exe + +CFLAGS = -O2 ${CFLAGS_MINGW} +ifneq (${REGEX_PACKAGE},regcomp-local) +LDFLAGS = ${MINGW_REGEX_LPATH} +LIBS = ${MINGW_REGEX_LIB} +endif + +#### End of system configuration section. #### + +# This rule allows us to supply the necessary -D options +# in addition to whatever the user asks for. +.c.o: + ${CC} -c -I. ${CFLAGS} $< + +LESS_SRC = brac.c ch.c charset.c cmdbuf.c command.c \ + cvt.c decode.c edit.c filename.c forwback.c \ + ifile.c input.c jump.c line.c linenum.c \ + lsystem.c main.c mark.c optfunc.c option.c \ + opttbl.c os.c output.c pattern.c position.c \ + prompt.c screen.c scrsize.c search.c \ + signal.c tags.c ttyin.c version.c +ifeq (${REGEX_PACKAGE},regcomp-local) +LESS_SRC += regexp.c +endif + +OBJ = \ + main.o screen.o brac.o ch.o charset.o cmdbuf.o \ + command.o cvt.o decode.o edit.o filename.o forwback.o \ + help.o ifile.o input.o jump.o line.o linenum.o \ + lsystem.o mark.o optfunc.o option.o opttbl.o os.o \ + output.o pattern.o position.o prompt.o search.o signal.o \ + tags.o ttyin.o version.o +ifeq (${REGEX_PACKAGE},regcomp-local) +OBJ += regexp.o +endif + + +all: clean less lesskey lessecho + +less: ${OBJ} + ${CC} ${LDFLAGS} -o $@ ${OBJ} ${LIBS} + +lesskey: lesskey.o version.o + ${CC} ${LDFLAGS} -o $@ lesskey.o version.o + +lessecho: lessecho.o version.o + ${CC} ${LDFLAGS} -o $@ lessecho.o version.o + +defines.h: defines.wn + copy $< $@ + +funcs.h: + perl mkfuncs.pl ${LESS_SRC} > $@ + +help.c: less.hlp + perl mkhelp.pl < $< > $@ + +${OBJ}: less.h defines.h funcs.h + +TAGS: + etags *.c *.h + +clean: + -del *.o + -del *.exe + -del defines.h + -del funcs.h + -del help.c + -if exist TAGS del TAGS diff --git a/Makefile.wnm b/Makefile.wnm index 358fa9fed186..cc084a7c96b9 100644 --- a/Makefile.wnm +++ b/Makefile.wnm @@ -6,7 +6,7 @@ CC = cl # Normal flags -CFLAGS = /nologo /MD /W3 /EHsc /O2 /I "." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /c +CFLAGS = /nologo /W3 /EHsc /O2 /I "." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /c LDFLAGS = /nologo /subsystem:console /incremental:no # Debugging flags diff --git a/NEWS b/NEWS index b0644fd2e0de..fd214e62007d 100644 --- a/NEWS +++ b/NEWS @@ -4,10 +4,56 @@ ====================================================================== For the latest news about less, see the "less" Web page: - http://www.greenwoodsoftware.com/less + https://greenwoodsoftware.com/less You can also download the latest version of less from there. - To report bugs, suggestions or comments, send email to bug-less@gnu.org + Report bugs, suggestions or comments at + https://github.com/gwsw/less/issues. + +====================================================================== + + Major changes between "less" versions 563 and 581 + +* Change ESC-u command to toggle, not disable, highlighting per man page. + +* Add ESC-U command. + +* Add ctrl-W search modifier for wrapping search. + +* F command can be interrupted by ^X. + +* Support OSC 8 hyperlinks when -R is in effect. + +* g command with no number will ignore -j and put first line at top of screen. + +* Multiple + or -p command line options are handled better. + +* Add the --incsearch option. + +* Add the --line-num-width option. + +* Add the --status-col-width option. + +* Add the --use-color and --color options. + +* Display -w highlight even if highlighted line is empty. + +* If search result is in a long line, scroll to ensure it is visible. + +* Editing the same file under different names now creates only + one entry in the file list. + +* Make visual bell more visible on some terminals. + +* Ring end-of-file bell no more than once per second. + +* Build can use either Python or Perl for Makefile.aut operations. + +* Fix crash when using the @ search modifier. + +* Fix crash in the 's' command due to duplicate free. + +* Fix realpath crash on Darwin. ====================================================================== diff --git a/README b/README index a6ee1dfa62a4..c99d208960cc 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ - Less, version 563 + Less, version 581 - This is the distribution of less, version 563, released 13 Jun 2020. + This is the distribution of less, version 581, released 06 Apr 2021. This program is part of the GNU project (http://www.gnu.org). This program is free software. You may redistribute it and/or @@ -13,33 +13,29 @@ or 2. The Less License, in the file LICENSE. - Please report any problems to bug-less@gnu.org. - See http://www.greenwoodsoftware.com/less for the latest info. + Please report any problems at https://github.com/gwsw/less/issues. + See https://greenwoodsoftware.com/less for the latest info. Source repository is at https://github.com/gwsw/less.git. ========================================================================= -This is the distribution of "less", a paginator similar to "more" or "pg". - 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. ======================================================================= -PRE-INSTALLATION (when using git) - -If you are building from a clone of a git repository, -type "make -f Makefile.aut". -If you are building from a numbered release package (a tar or zip file -with a name like less-999.tar.gz or less-999.zip), you should skip this step. - -======================================================================= -INSTALLATION (Unix systems only): +INSTALLATION (Unix & Linux systems only): 1. Move the distributed source to its own directory and unpack it, if you have not already done so. -2. Type "sh configure". +2. If you are building from a clone of a git repository, + type "make -f Makefile.aut". + If you are building from a numbered release package (a tar or + zip file with a name like less-999.tar.gz or less-999.zip downloaded + from greenwoodsoftware.com, not from github), you should skip this step. + +3. Type "sh configure". This will generate a Makefile and a defines.h. Warning: if you have a GNU sed, make sure it is version 2.05 or later. @@ -71,7 +67,7 @@ INSTALLATION (Unix systems only): commands, etc. -3. It is a good idea to look over the generated Makefile and defines.h +4. It is a good idea to look over the generated Makefile and defines.h and make sure they look ok. If you know of any peculiarities of your system that configure might not have detected, you may fix the Makefile now. Take particular notice of the list of "terminal" @@ -85,13 +81,13 @@ INSTALLATION (Unix systems only): to remove the descriptions of the features which you are removing. If you edit less.hlp, you should run "make -f Makefile.aut help.c". -4. Type "make" and watch the fun. +5. Type "make" and watch the fun. -5. If the make succeeds, it will generate the programs "less", +6. If the make succeeds, it will generate the programs "less", "lesskey" and "lessecho" in your current directory. Test the generated programs. -6. When satisfied that it works, if you wish to install it +7. When satisfied that it works, if you wish to install it in a public place, type "make install". The default install destinations are: @@ -100,8 +96,6 @@ INSTALLATION (Unix systems only): If you want to install any of these files elsewhere, define bindir and/or mandir to the appropriate directories. -If you have any problems building or running "less", suggestions, -complaints, etc., you may mail to bug-less@gnu.org. Note to hackers: comments noting possible improvements are enclosed in double curly brackets {{ like this }}. diff --git a/brac.c b/brac.c index db3a2951db08..53ada50aab56 100644 --- a/brac.c +++ b/brac.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. diff --git a/ch.c b/ch.c index 70fad1002dbf..bab0692f7437 100644 --- a/ch.c +++ b/ch.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -41,7 +41,7 @@ struct bufnode { struct bufnode *hnext, *hprev; }; -#define LBUFSIZE 8192 +#define LBUFSIZE 8192 struct buf { struct bufnode node; BLOCKNUM block; @@ -54,7 +54,7 @@ struct buf { * The file state is maintained in a filestate structure. * A pointer to the filestate is kept in the ifile structure. */ -#define BUFHASH_SIZE 1024 +#define BUFHASH_SIZE 1024 struct filestate { struct bufnode buflist; struct bufnode hashtbl[BUFHASH_SIZE]; @@ -67,24 +67,24 @@ struct filestate { POSITION fsize; }; -#define ch_bufhead thisfile->buflist.next -#define ch_buftail thisfile->buflist.prev -#define ch_nbufs thisfile->nbufs -#define ch_block thisfile->block -#define ch_offset thisfile->offset -#define ch_fpos thisfile->fpos -#define ch_fsize thisfile->fsize -#define ch_flags thisfile->flags -#define ch_file thisfile->file +#define ch_bufhead thisfile->buflist.next +#define ch_buftail thisfile->buflist.prev +#define ch_nbufs thisfile->nbufs +#define ch_block thisfile->block +#define ch_offset thisfile->offset +#define ch_fpos thisfile->fpos +#define ch_fsize thisfile->fsize +#define ch_flags thisfile->flags +#define ch_file thisfile->file -#define END_OF_CHAIN (&thisfile->buflist) -#define END_OF_HCHAIN(h) (&thisfile->hashtbl[h]) -#define BUFHASH(blk) ((blk) & (BUFHASH_SIZE-1)) +#define END_OF_CHAIN (&thisfile->buflist) +#define END_OF_HCHAIN(h) (&thisfile->hashtbl[h]) +#define BUFHASH(blk) ((blk) & (BUFHASH_SIZE-1)) /* * Macros to manipulate the list of buffers in thisfile->buflist. */ -#define FOR_BUFS(bn) \ +#define FOR_BUFS(bn) \ for (bn = ch_bufhead; bn != END_OF_CHAIN; bn = bn->next) #define BUF_RM(bn) \ @@ -106,15 +106,15 @@ struct filestate { /* * Macros to manipulate the list of buffers in thisfile->hashtbl[n]. */ -#define FOR_BUFS_IN_CHAIN(h,bn) \ +#define FOR_BUFS_IN_CHAIN(h,bn) \ for (bn = thisfile->hashtbl[h].hnext; \ bn != END_OF_HCHAIN(h); bn = bn->hnext) -#define BUF_HASH_RM(bn) \ +#define BUF_HASH_RM(bn) \ (bn)->hnext->hprev = (bn)->hprev; \ (bn)->hprev->hnext = (bn)->hnext; -#define BUF_HASH_INS(bn,h) \ +#define BUF_HASH_INS(bn,h) \ (bn)->hnext = thisfile->hashtbl[h].hnext; \ (bn)->hprev = END_OF_HCHAIN(h); \ thisfile->hashtbl[h].hnext->hprev = (bn); \ @@ -240,12 +240,12 @@ ch_get(VOID_PARAM) return ('?'); if (lseek(ch_file, (off_t)pos, SEEK_SET) == BAD_LSEEK) { - error("seek error", NULL_PARG); + error("seek error", NULL_PARG); clear_eol(); return (EOI); - } - ch_fpos = pos; - } + } + ch_fpos = pos; + } /* * Read the block. @@ -311,13 +311,7 @@ ch_get(VOID_PARAM) parg.p_string = wait_message(); ierror("%s", &parg); } -#if !MSDOS_COMPILER - sleep(1); -#else -#if MSDOS_COMPILER==WIN32C - Sleep(1000); -#endif -#endif + sleep_ms(2); /* Reduce system load */ slept = TRUE; #if HAVE_STAT_INO diff --git a/charset.c b/charset.c index 4897cbaf6adc..b37c8a29cbd9 100644 --- a/charset.c +++ b/charset.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -40,27 +40,27 @@ struct charset { int *p_flag; char *desc; } charsets[] = { - { "ascii", NULL, "8bcccbcc18b95.b" }, - { "utf-8", &utf_mode, "8bcccbcc18b95.b126.bb" }, - { "iso8859", NULL, "8bcccbcc18b95.33b." }, - { "latin3", NULL, "8bcccbcc18b95.33b5.b8.b15.b4.b12.b18.b12.b." }, - { "arabic", NULL, "8bcccbcc18b95.33b.3b.7b2.13b.3b.b26.5b19.b" }, - { "greek", NULL, "8bcccbcc18b95.33b4.2b4.b3.b35.b44.b" }, - { "greek2005", NULL, "8bcccbcc18b95.33b14.b35.b44.b" }, - { "hebrew", NULL, "8bcccbcc18b95.33b.b29.32b28.2b2.b" }, - { "koi8-r", NULL, "8bcccbcc18b95.b." }, - { "KOI8-T", NULL, "8bcccbcc18b95.b8.b6.b8.b.b.5b7.3b4.b4.b3.b.b.3b." }, - { "georgianps", NULL, "8bcccbcc18b95.3b11.4b12.2b." }, - { "tcvn", NULL, "b..b...bcccbccbbb7.8b95.b48.5b." }, - { "TIS-620", NULL, "8bcccbcc18b95.b.4b.11b7.8b." }, - { "next", NULL, "8bcccbcc18b95.bb125.bb" }, - { "dos", NULL, "8bcccbcc12bc5b95.b." }, - { "windows-1251", NULL, "8bcccbcc12bc5b95.b24.b." }, - { "windows-1252", NULL, "8bcccbcc12bc5b95.b.b11.b.2b12.b." }, - { "windows-1255", NULL, "8bcccbcc12bc5b95.b.b8.b.5b9.b.4b." }, - { "ebcdic", NULL, "5bc6bcc7bcc41b.9b7.9b5.b..8b6.10b6.b9.7b9.8b8.17b3.3b9.7b9.8b8.6b10.b.b.b." }, - { "IBM-1047", NULL, "4cbcbc3b9cbccbccbb4c6bcc5b3cbbc4bc4bccbc191.b" }, - { NULL, NULL, NULL } + { "ascii", NULL, "8bcccbcc18b95.b" }, + { "utf-8", &utf_mode, "8bcccbcc18b95.b126.bb" }, + { "iso8859", NULL, "8bcccbcc18b95.33b." }, + { "latin3", NULL, "8bcccbcc18b95.33b5.b8.b15.b4.b12.b18.b12.b." }, + { "arabic", NULL, "8bcccbcc18b95.33b.3b.7b2.13b.3b.b26.5b19.b" }, + { "greek", NULL, "8bcccbcc18b95.33b4.2b4.b3.b35.b44.b" }, + { "greek2005", NULL, "8bcccbcc18b95.33b14.b35.b44.b" }, + { "hebrew", NULL, "8bcccbcc18b95.33b.b29.32b28.2b2.b" }, + { "koi8-r", NULL, "8bcccbcc18b95.b." }, + { "KOI8-T", NULL, "8bcccbcc18b95.b8.b6.b8.b.b.5b7.3b4.b4.b3.b.b.3b." }, + { "georgianps", NULL, "8bcccbcc18b95.3b11.4b12.2b." }, + { "tcvn", NULL, "b..b...bcccbccbbb7.8b95.b48.5b." }, + { "TIS-620", NULL, "8bcccbcc18b95.b.4b.11b7.8b." }, + { "next", NULL, "8bcccbcc18b95.bb125.bb" }, + { "dos", NULL, "8bcccbcc12bc5b95.b." }, + { "windows-1251", NULL, "8bcccbcc12bc5b95.b24.b." }, + { "windows-1252", NULL, "8bcccbcc12bc5b95.b.b11.b.2b12.b." }, + { "windows-1255", NULL, "8bcccbcc12bc5b95.b.b8.b.5b9.b.4b." }, + { "ebcdic", NULL, "5bc6bcc7bcc41b.9b7.9b5.b..8b6.10b6.b9.7b9.8b8.17b3.3b9.7b9.8b8.6b10.b.b.b." }, + { "IBM-1047", NULL, "4cbcbc3b9cbccbccbb4c6bcc5b3cbbc4bc4bccbc191.b" }, + { NULL, NULL, NULL } }; /* @@ -70,58 +70,58 @@ struct cs_alias { char *name; char *oname; } cs_aliases[] = { - { "UTF-8", "utf-8" }, - { "utf8", "utf-8" }, - { "UTF8", "utf-8" }, - { "ANSI_X3.4-1968", "ascii" }, - { "US-ASCII", "ascii" }, - { "latin1", "iso8859" }, - { "ISO-8859-1", "iso8859" }, - { "latin9", "iso8859" }, - { "ISO-8859-15", "iso8859" }, - { "latin2", "iso8859" }, - { "ISO-8859-2", "iso8859" }, - { "ISO-8859-3", "latin3" }, - { "latin4", "iso8859" }, - { "ISO-8859-4", "iso8859" }, - { "cyrillic", "iso8859" }, - { "ISO-8859-5", "iso8859" }, - { "ISO-8859-6", "arabic" }, - { "ISO-8859-7", "greek" }, - { "IBM9005", "greek2005" }, - { "ISO-8859-8", "hebrew" }, - { "latin5", "iso8859" }, - { "ISO-8859-9", "iso8859" }, - { "latin6", "iso8859" }, - { "ISO-8859-10", "iso8859" }, - { "latin7", "iso8859" }, - { "ISO-8859-13", "iso8859" }, - { "latin8", "iso8859" }, - { "ISO-8859-14", "iso8859" }, - { "latin10", "iso8859" }, - { "ISO-8859-16", "iso8859" }, - { "IBM437", "dos" }, - { "EBCDIC-US", "ebcdic" }, - { "IBM1047", "IBM-1047" }, - { "KOI8-R", "koi8-r" }, - { "KOI8-U", "koi8-r" }, - { "GEORGIAN-PS", "georgianps" }, - { "TCVN5712-1", "tcvn" }, - { "NEXTSTEP", "next" }, - { "windows", "windows-1252" }, /* backward compatibility */ - { "CP1251", "windows-1251" }, - { "CP1252", "windows-1252" }, - { "CP1255", "windows-1255" }, + { "UTF-8", "utf-8" }, + { "utf8", "utf-8" }, + { "UTF8", "utf-8" }, + { "ANSI_X3.4-1968", "ascii" }, + { "US-ASCII", "ascii" }, + { "latin1", "iso8859" }, + { "ISO-8859-1", "iso8859" }, + { "latin9", "iso8859" }, + { "ISO-8859-15", "iso8859" }, + { "latin2", "iso8859" }, + { "ISO-8859-2", "iso8859" }, + { "ISO-8859-3", "latin3" }, + { "latin4", "iso8859" }, + { "ISO-8859-4", "iso8859" }, + { "cyrillic", "iso8859" }, + { "ISO-8859-5", "iso8859" }, + { "ISO-8859-6", "arabic" }, + { "ISO-8859-7", "greek" }, + { "IBM9005", "greek2005" }, + { "ISO-8859-8", "hebrew" }, + { "latin5", "iso8859" }, + { "ISO-8859-9", "iso8859" }, + { "latin6", "iso8859" }, + { "ISO-8859-10", "iso8859" }, + { "latin7", "iso8859" }, + { "ISO-8859-13", "iso8859" }, + { "latin8", "iso8859" }, + { "ISO-8859-14", "iso8859" }, + { "latin10", "iso8859" }, + { "ISO-8859-16", "iso8859" }, + { "IBM437", "dos" }, + { "EBCDIC-US", "ebcdic" }, + { "IBM1047", "IBM-1047" }, + { "KOI8-R", "koi8-r" }, + { "KOI8-U", "koi8-r" }, + { "GEORGIAN-PS", "georgianps" }, + { "TCVN5712-1", "tcvn" }, + { "NEXTSTEP", "next" }, + { "windows", "windows-1252" }, /* backward compatibility */ + { "CP1251", "windows-1251" }, + { "CP1252", "windows-1252" }, + { "CP1255", "windows-1255" }, { NULL, NULL } }; -#define IS_BINARY_CHAR 01 -#define IS_CONTROL_CHAR 02 +#define IS_BINARY_CHAR 01 +#define IS_CONTROL_CHAR 02 static char chardef[256]; static char *binfmt = NULL; static char *utfbinfmt = NULL; -public int binattr = AT_STANDOUT; +public int binattr = AT_STANDOUT|AT_COLOR_BIN; /* @@ -134,9 +134,9 @@ public int binattr = AT_STANDOUT; * repetition of the letter. * * Each letter is one of: - * . normal character - * b binary character - * c control character + * . normal character + * b binary character + * c control character */ static void ichardef(s) @@ -457,16 +457,16 @@ prchar(c) SNPRINTF1(buf, sizeof(buf), "^%c", /* * This array roughly inverts CONTROL() #defined in less.h, - * and should be kept in sync with CONTROL() and IBM-1047. - */ + * and should be kept in sync with CONTROL() and IBM-1047. + */ "@ABC.I.?...KLMNO" "PQRS.JH.XY.." "\\]^_" "......W[.....EFG" "..V....D....TU.Z"[c]); #else - else if (c < 128 && !control_char(c ^ 0100)) - SNPRINTF1(buf, sizeof(buf), "^%c", (int) (c ^ 0100)); + else if (c < 128 && !control_char(c ^ 0100)) + SNPRINTF1(buf, sizeof(buf), "^%c", (int) (c ^ 0100)); #endif else SNPRINTF1(buf, sizeof(buf), binfmt, c); @@ -484,7 +484,7 @@ prutfchar(ch) if (ch == ESC) strcpy(buf, "ESC"); - else if (ch < 128 && control_char(ch)) + else if (ch < 128 && control_char(ch)) { if (!control_char(ch ^ 0100)) SNPRINTF1(buf, sizeof(buf), "^%c", ((char) ch) ^ 0100); @@ -732,9 +732,9 @@ step_char(pp, dir, limit) */ #define DECLARE_RANGE_TABLE_START(name) \ - static struct wchar_range name##_array[] = { + static struct wchar_range name##_array[] = { #define DECLARE_RANGE_TABLE_END(name) \ - }; struct wchar_range_table name##_table = { name##_array, sizeof(name##_array)/sizeof(*name##_array) }; + }; struct wchar_range_table name##_table = { name##_array, sizeof(name##_array)/sizeof(*name##_array) }; DECLARE_RANGE_TABLE_START(compose) #include "compose.uni" diff --git a/charset.h b/charset.h index cc0c3af59e89..3e7ecf73db94 100644 --- a/charset.h +++ b/charset.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. diff --git a/cmd.h b/cmd.h index 95a2e5801717..c51f0bc5c4f3 100644 --- a/cmd.h +++ b/cmd.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -31,7 +31,6 @@ #define A_HELP 19 #define A_NEXT_FILE 20 #define A_PERCENT 21 -#define A_PREFIX 22 #define A_PREV_FILE 23 #define A_QUIT 24 #define A_REPAINT 25 @@ -72,19 +71,19 @@ #define A_CLRMARK 62 #define A_SETMARKBOT 63 #define A_X11MOUSE_IN 64 -#define A_X11MOUSE_IGNORE 65 #define A_F_MOUSE 66 #define A_B_MOUSE 67 /* Note "X116" refers to extended (1006) X11 mouse reporting. */ #define A_X116MOUSE_IN 68 -#define A_X116MOUSE_IGNORE 69 +#define A_CLR_SEARCH 70 +/* These values must not conflict with any A_* or EC_* value. */ #define A_INVALID 100 #define A_NOACTION 101 #define A_UINVALID 102 #define A_END_LIST 103 #define A_SPECIAL_KEY 104 - +#define A_PREFIX 105 #define A_SKIP 127 #define A_EXTRA 0200 @@ -111,15 +110,16 @@ #define EC_B_COMPLETE 18 #define EC_LITERAL 19 #define EC_ABORT 20 +#define EC_X11MOUSE 21 +#define EC_X116MOUSE 22 -#define EC_NOACTION 101 #define EC_UINVALID 102 /* Flags for editchar() */ -#define EC_PEEK 01 -#define EC_NOHISTORY 02 -#define EC_NOCOMPLETE 04 -#define EC_NORIGHTLEFT 010 +#define ECF_PEEK 01 +#define ECF_NOHISTORY 02 +#define ECF_NOCOMPLETE 04 +#define ECF_NORIGHTLEFT 010 /* Environment variable stuff */ #define EV_OK 01 diff --git a/cmdbuf.c b/cmdbuf.c index ed78ded00307..9cc1f3e94977 100644 --- a/cmdbuf.c +++ b/cmdbuf.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -26,12 +26,12 @@ extern int no_hist_dups; extern int marks_modified; static char cmdbuf[CMDBUF_SIZE]; /* Buffer for holding a multi-char command */ -static int cmd_col; /* Current column of the cursor */ -static int prompt_col; /* Column of cursor just after prompt */ -static char *cp; /* Pointer into cmdbuf */ -static int cmd_offset; /* Index into cmdbuf of first displayed char */ -static int literal; /* Next input char should not be interpreted */ -static int updown_match = -1; /* Prefix length in up/down movement */ +static int cmd_col; /* Current column of the cursor */ +static int prompt_col; /* Column of cursor just after prompt */ +static char *cp; /* Pointer into cmdbuf */ +static int cmd_offset; /* Index into cmdbuf of first displayed char */ +static int literal; /* Next input char should not be interpreted */ +static int updown_match = -1; /* Prefix length in up/down movement */ #if TAB_COMPLETE_FILENAME static int cmd_complete LESSPARAMS((int action)); @@ -223,7 +223,7 @@ cmd_step_common(p, ch, len, pwidth, bswidth) } } if (pwidth != NULL) - *pwidth = width; + *pwidth = width; if (bswidth != NULL) *bswidth = width; return (pr); @@ -259,17 +259,42 @@ cmd_step_left(pp, pwidth, bswidth) return cmd_step_common(*pp, ch, p - *pp, pwidth, bswidth); } +/* + * Put the cursor at "home" (just after the prompt), + * and set cp to the corresponding char in cmdbuf. + */ + static void +cmd_home(VOID_PARAM) +{ + while (cmd_col > prompt_col) + { + int width, bswidth; + + cmd_step_left(&cp, &width, &bswidth); + while (bswidth-- > 0) + putbs(); + cmd_col -= width; + } + + cp = &cmdbuf[cmd_offset]; +} + /* * Repaint the line from cp onwards. * Then position the cursor just after the char old_cp (a pointer into cmdbuf). */ - static void + public void cmd_repaint(old_cp) constant char *old_cp; { /* * Repaint the line from the current position. */ + if (old_cp == NULL) + { + old_cp = cp; + cmd_home(); + } clear_eol(); while (*cp != '\0') { @@ -300,26 +325,6 @@ cmd_repaint(old_cp) cmd_left(); } -/* - * Put the cursor at "home" (just after the prompt), - * and set cp to the corresponding char in cmdbuf. - */ - static void -cmd_home(VOID_PARAM) -{ - while (cmd_col > prompt_col) - { - int width, bswidth; - - cmd_step_left(&cp, &width, &bswidth); - while (bswidth-- > 0) - putbs(); - cmd_col -= width; - } - - cp = &cmdbuf[cmd_offset]; -} - /* * Shift the cmdbuf display left a half-screen. */ @@ -826,9 +831,9 @@ cmd_accept(VOID_PARAM) * Try to perform a line-edit function on the command buffer, * using a specified char as a line-editing command. * Returns: - * CC_PASS The char does not invoke a line edit function. - * CC_OK Line edit function done. - * CC_QUIT The char requests the current command to be aborted. + * CC_PASS The char does not invoke a line edit function. + * CC_OK Line edit function done. + * CC_QUIT The char requests the current command to be aborted. */ static int cmd_edit(c) @@ -838,9 +843,9 @@ cmd_edit(c) int flags; #if TAB_COMPLETE_FILENAME -#define not_in_completion() in_completion = 0 +#define not_in_completion() in_completion = 0 #else -#define not_in_completion(VOID_PARAM) +#define not_in_completion(VOID_PARAM) #endif /* @@ -852,20 +857,22 @@ cmd_edit(c) /* * No current history; don't accept history manipulation cmds. */ - flags |= EC_NOHISTORY; + flags |= ECF_NOHISTORY; #endif #if TAB_COMPLETE_FILENAME if (curr_mlist == ml_search) /* * In a search command; don't accept file-completion cmds. */ - flags |= EC_NOCOMPLETE; + flags |= ECF_NOCOMPLETE; #endif action = editchar(c, flags); switch (action) { + case A_NOACTION: + return (CC_OK); case EC_RIGHT: not_in_completion(); return (cmd_right()); @@ -934,8 +941,6 @@ cmd_edit(c) case EC_EXPAND: return (cmd_complete(action)); #endif - case EC_NOACTION: - return (CC_OK); default: not_in_completion(); return (CC_PASS); @@ -1237,9 +1242,9 @@ cmd_complete(action) * 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. + * 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. */ public int cmd_char(c) diff --git a/command.c b/command.c index f578476c89a2..cf691a7988b3 100644 --- a/command.c +++ b/command.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -55,21 +55,22 @@ extern void *ml_shell; extern char *editor; extern char *editproto; #endif -extern int screen_trashed; /* The screen has been overwritten */ +extern int screen_trashed; /* The screen has been overwritten */ extern int shift_count; extern int oldbot; extern int forw_prompt; +extern int incr_search; #if MSDOS_COMPILER==WIN32C extern int utf_mode; #endif #if SHELL_ESCAPE -static char *shellcmd = NULL; /* For holding last shell command for "!!" */ +static char *shellcmd = NULL; /* For holding last shell command for "!!" */ #endif -static int mca; /* The multicharacter command (action) */ -static int search_type; /* The previous type of search */ -static LINENUM number; /* The number typed by the user */ -static long fraction; /* The fractional part of the number */ +static int mca; /* The multicharacter command (action) */ +static int search_type; /* The previous type of 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 int optflag; @@ -111,7 +112,6 @@ set_mca(action) int action; { mca = action; - deinit_mouse(); /* we don't want mouse events while entering a cmd */ clear_bot(); clear_cmd(); } @@ -125,7 +125,6 @@ clear_mca(VOID_PARAM) if (mca == 0) return; mca = 0; - init_mouse(); } /* @@ -175,6 +174,8 @@ mca_search(VOID_PARAM) cmd_putstr("Keep-pos "); if (search_type & SRCH_NO_REGEX) cmd_putstr("Regex-off "); + if (search_type & SRCH_WRAP) + cmd_putstr("Wrap "); #if HILITE_SEARCH if (search_type & SRCH_FILTER) @@ -518,9 +519,9 @@ mca_search_char(c) /* * Certain characters as the first char of * the pattern have special meaning: - * ! Toggle the NO_MATCH flag - * * Toggle the PAST_EOF flag - * @ Toggle the FIRST_FILE flag + * ! Toggle the NO_MATCH flag + * * Toggle the PAST_EOF flag + * @ Toggle the FIRST_FILE flag */ if (len_cmdbuf() > 0) return (NO_MCA); @@ -541,6 +542,10 @@ mca_search_char(c) if (mca != A_FILTER) flag = SRCH_NO_MOVE; break; + case CONTROL('W'): /* WRAP around */ + if (mca != A_FILTER) + flag = SRCH_WRAP; + break; case CONTROL('R'): /* Don't use REGULAR EXPRESSIONS */ flag = SRCH_NO_REGEX; break; @@ -552,7 +557,8 @@ mca_search_char(c) if (flag != 0) { - search_type ^= flag; + /* Toggle flag, but keep PAST_EOF and WRAP mutually exclusive. */ + search_type ^= flag | (search_type & (SRCH_PAST_EOF|SRCH_WRAP)); mca_search(); return (MCA_MORE); } @@ -590,9 +596,16 @@ mca_char(c) * Entering digits of a number. * Terminated by a non-digit. */ - if (!((c >= '0' && c <= '9') || c == '.') && - editchar(c, EC_PEEK|EC_NOHISTORY|EC_NOCOMPLETE|EC_NORIGHTLEFT) == A_INVALID) + if ((c >= '0' && c <= '9') || c == '.') + break; + switch (editchar(c, ECF_PEEK|ECF_NOHISTORY|ECF_NOCOMPLETE|ECF_NORIGHTLEFT)) { + case A_NOACTION: + /* + * Ignore this char and get another one. + */ + return (MCA_MORE); + case A_INVALID: /* * Not part of the number. * End the number and treat this char @@ -645,15 +658,44 @@ mca_char(c) */ return (MCA_DONE); - if ((mca == A_F_BRACKET || mca == A_B_BRACKET) && len_cmdbuf() >= 2) + switch (mca) { - /* - * Special case for the bracket-matching commands. - * Execute the command after getting exactly two - * characters from the user. - */ - exec_mca(); - return (MCA_DONE); + case A_F_BRACKET: + case A_B_BRACKET: + if (len_cmdbuf() >= 2) + { + /* + * Special case for the bracket-matching commands. + * Execute the command after getting exactly two + * characters from the user. + */ + exec_mca(); + return (MCA_DONE); + } + break; + case A_F_SEARCH: + case A_B_SEARCH: + if (incr_search) + { + /* Incremental search: do a search after every input char. */ + int st = (search_type & (SRCH_FORW|SRCH_BACK|SRCH_NO_MATCH|SRCH_NO_REGEX|SRCH_NO_MOVE|SRCH_WRAP)); + char *pattern = get_cmdbuf(); + cmd_exec(); + if (*pattern == '\0') + { + /* User has backspaced to an empty pattern. */ + undo_search(1); + } else + { + if (search(st | SRCH_INCR, pattern, 1) != 0) + /* No match, invalid pattern, etc. */ + undo_search(1); + } + /* Redraw the search prompt and search string. */ + mca_search(); + cmd_repaint(NULL); + } + break; } /* @@ -689,12 +731,6 @@ make_display(VOID_PARAM) if (empty_screen()) { if (initial_scrpos.pos == NULL_POSITION) - /* - * {{ Maybe this should be: - * jump_loc(ch_zero(), jump_sline); - * but this behavior seems rather unexpected - * on the first screen. }} - */ jump_loc(ch_zero(), 1); else jump_loc(initial_scrpos.pos, initial_scrpos.ln); @@ -787,11 +823,16 @@ prompt(VOID_PARAM) clear_cmd(); forw_prompt = 0; p = pr_string(); +#if HILITE_SEARCH if (is_filtering()) putstr("& "); +#endif if (p == NULL || *p == '\0') + { + at_enter(AT_NORMAL|AT_COLOR_PROMPT); putchr(':'); - else + at_exit(); + } else { #if MSDOS_COMPILER==WIN32C WCHAR w[MAX_PATH*2]; @@ -801,7 +842,7 @@ prompt(VOID_PARAM) 0, w, -1, a, sizeof(a), NULL, NULL); p = a; #endif - at_enter(AT_STANDOUT); + at_enter(AT_STANDOUT|AT_COLOR_PROMPT); putstr(p); at_exit(); } @@ -837,7 +878,7 @@ getcc_end_command(VOID_PARAM) return ('\n'); default: /* Some other incomplete command. Let user complete it. */ - return (getchr()); + return ((ungot == NULL) ? getchr() : 0); } } @@ -850,23 +891,26 @@ getcc_end_command(VOID_PARAM) static LWCHAR getccu(VOID_PARAM) { - LWCHAR c; - if (ungot == NULL) + LWCHAR c = 0; + while (c == 0) { - /* Normal case: no ungotten chars. - * Get char from the user. */ - c = getchr(); - } else - { - /* Ungotten chars available: - * Take the top of stack (most recent). */ - struct ungot *ug = ungot; - c = ug->ug_char; - ungot = ug->ug_next; - free(ug); + if (ungot == NULL) + { + /* Normal case: no ungotten chars. + * Get char from the user. */ + c = getchr(); + } else + { + /* Ungotten chars available: + * Take the top of stack (most recent). */ + struct ungot *ug = ungot; + c = ug->ug_char; + ungot = ug->ug_next; + free(ug); - if (c == CHAR_END_COMMAND) - c = getcc_end_command(); + if (c == CHAR_END_COMMAND) + c = getcc_end_command(); + } } return (c); } @@ -941,6 +985,28 @@ ungetcc(c) ungot = ug; } +/* + * "Unget" a command character. + * If any other chars are already ungotten, put this one after those. + */ + public void +ungetcc_back(c) + LWCHAR c; +{ + struct ungot *ug = (struct ungot *) ecalloc(1, sizeof(struct ungot)); + ug->ug_char = c; + ug->ug_next = NULL; + if (ungot == NULL) + ungot = ug; + else + { + struct ungot *pu; + for (pu = ungot; pu->ug_next != NULL; pu = pu->ug_next) + continue; + pu->ug_next = ug; + } +} + /* * Unget a whole string of command characters. * The next sequence of getcc()'s will return this string. @@ -949,10 +1015,8 @@ ungetcc(c) ungetsc(s) char *s; { - char *p; - - for (p = s + strlen(s) - 1; p >= s; p--) - ungetcc(*p); + while (*s != '\0') + ungetcc_back(*s++); } /* @@ -1116,6 +1180,7 @@ commands(VOID_PARAM) int action; char *cbuf; int newaction; + int save_jump_sline; int save_search_type; char *extra; char tbuf[2]; @@ -1417,11 +1482,18 @@ commands(VOID_PARAM) case A_GOLINE: /* * Go to line N, default beginning of file. + * If N <= 0, ignore jump_sline in order to avoid + * empty lines before the beginning of the file. */ + save_jump_sline = jump_sline; if (number <= 0) + { number = 1; + jump_sline = 0; + } cmd_exec(); jump_back(number); + jump_sline = save_jump_sline; break; case A_PERCENT: @@ -1487,7 +1559,7 @@ commands(VOID_PARAM) case A_VERSION: /* - * Print version number, without the "@(#)". + * Print version number. */ cmd_exec(); dispversion(); @@ -1518,10 +1590,10 @@ commands(VOID_PARAM) /* * Define abbreviation for a commonly used sequence below. */ -#define DO_SEARCH() \ - if (number <= 0) number = 1; \ - mca_search(); \ - cmd_exec(); \ +#define DO_SEARCH() \ + if (number <= 0) number = 1; \ + mca_search(); \ + cmd_exec(); \ multi_search((char *)NULL, (int) number, 0); @@ -1598,10 +1670,11 @@ commands(VOID_PARAM) break; case A_UNDO_SEARCH: + case A_CLR_SEARCH: /* * Clear search string highlighting. */ - undo_search(); + undo_search(action == A_CLR_SEARCH); break; case A_HELP: diff --git a/configure b/configure index fda7091c7952..e3be2c0faf1b 100755 --- a/configure +++ b/configure @@ -4189,7 +4189,7 @@ if test "x$TERMLIBS" = x; then LIBS="$LIBS $TERMLIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - +#include int main () { @@ -4855,7 +4855,7 @@ cat >>confdefs.h <<_ACEOF _ACEOF -for ac_func in fsync popen _setjmp sigprocmask sigsetmask snprintf stat system fchmod realpath +for ac_func in fchmod fsync nanosleep poll popen realpath _setjmp sigprocmask sigsetmask snprintf stat system ttyname usleep do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" diff --git a/configure.ac b/configure.ac index e9aa286fdc1f..34077366f2dd 100644 --- a/configure.ac +++ b/configure.ac @@ -110,7 +110,7 @@ if test "x$TERMLIBS" = x; then TERMLIBS="-lncurses" SAVE_LIBS=$LIBS LIBS="$LIBS $TERMLIBS" - AC_TRY_LINK(, [tgetent(0,0); tgetflag(0); tgetnum(0); tgetstr(0,0);], + AC_TRY_LINK([#include ], [tgetent(0,0); tgetflag(0); tgetnum(0); tgetstr(0,0);], [termok=yes], [termok=no]) LIBS=$SAVE_LIBS if test $termok = no; then TERMLIBS=""; fi @@ -274,7 +274,7 @@ AC_TRY_COMPILE([], [int f(int a) { return a; }], # Checks for library functions. AC_TYPE_SIGNAL -AC_CHECK_FUNCS([fsync popen _setjmp sigprocmask sigsetmask snprintf stat system fchmod realpath]) +AC_CHECK_FUNCS([fchmod fsync nanosleep poll popen realpath _setjmp sigprocmask sigsetmask snprintf stat system ttyname usleep]) # AC_CHECK_FUNCS may not work for inline functions, so test these separately. AC_MSG_CHECKING(for memcpy) diff --git a/cvt.c b/cvt.c index e850a51452a2..9cf44b894e7d 100644 --- a/cvt.c +++ b/cvt.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -77,6 +77,7 @@ cvt_text(odst, osrc, chpos, lenp, ops) { int src_pos = (int) (src - osrc); int dst_pos = (int) (dst - odst); + struct ansi_state *pansi; ch = step_char(&src, +1, src_end); if ((ops & CVT_BS) && ch == '\b' && dst > odst) { @@ -85,13 +86,16 @@ cvt_text(odst, osrc, chpos, lenp, ops) dst--; } while (dst > odst && utf_mode && !IS_ASCII_OCTET(*dst) && !IS_UTF8_LEAD(*dst)); - } else if ((ops & CVT_ANSI) && IS_CSI_START(ch)) + } else if ((ops & CVT_ANSI) && (pansi = ansi_start(ch)) != NULL) { /* Skip to end of ANSI escape sequence. */ - src++; /* skip the CSI start char */ while (src < src_end) - if (!is_ansi_middle(*src++)) + { + if (ansi_step(pansi, ch) != ANSI_MID) break; + ch = *src++; + } + ansi_done(pansi); } else { /* Just copy the char to the destination buffer. */ diff --git a/decode.c b/decode.c index c5467ffe2697..f3bfb7a8ead2 100644 --- a/decode.c +++ b/decode.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -14,7 +14,7 @@ * This is all table driven. * A command table is a sequence of command descriptors. * Each command descriptor is a sequence of bytes with the following format: - * ...<0> + * ...<0> * The characters c1,c2,...,cN are the command string; that is, * the characters which the user must type. * It is terminated by a null <0> byte. @@ -48,173 +48,176 @@ extern int sc_height; static unsigned char cmdtable[] = { - '\r',0, A_F_LINE, - '\n',0, A_F_LINE, - 'e',0, A_F_LINE, - 'j',0, A_F_LINE, - SK(SK_DOWN_ARROW),0, A_F_LINE, - CONTROL('E'),0, A_F_LINE, - CONTROL('N'),0, A_F_LINE, - 'k',0, A_B_LINE, - 'y',0, A_B_LINE, - CONTROL('Y'),0, A_B_LINE, - SK(SK_CONTROL_K),0, A_B_LINE, - CONTROL('P'),0, A_B_LINE, - SK(SK_UP_ARROW),0, A_B_LINE, - 'J',0, A_FF_LINE, - 'K',0, A_BF_LINE, - 'Y',0, A_BF_LINE, - 'd',0, A_F_SCROLL, - CONTROL('D'),0, A_F_SCROLL, - 'u',0, A_B_SCROLL, - CONTROL('U'),0, A_B_SCROLL, - ESC,'[','M',0, A_X11MOUSE_IN, - ESC,'[','<',0, A_X116MOUSE_IN, - ' ',0, A_F_SCREEN, - 'f',0, A_F_SCREEN, - CONTROL('F'),0, A_F_SCREEN, - CONTROL('V'),0, A_F_SCREEN, - SK(SK_PAGE_DOWN),0, A_F_SCREEN, - 'b',0, A_B_SCREEN, - CONTROL('B'),0, A_B_SCREEN, - ESC,'v',0, A_B_SCREEN, - SK(SK_PAGE_UP),0, A_B_SCREEN, - 'z',0, A_F_WINDOW, - 'w',0, A_B_WINDOW, - ESC,' ',0, A_FF_SCREEN, - 'F',0, A_F_FOREVER, - ESC,'F',0, A_F_UNTIL_HILITE, - 'R',0, A_FREPAINT, - 'r',0, A_REPAINT, - CONTROL('R'),0, A_REPAINT, - CONTROL('L'),0, A_REPAINT, - ESC,'u',0, A_UNDO_SEARCH, - 'g',0, A_GOLINE, - SK(SK_HOME),0, A_GOLINE, - '<',0, A_GOLINE, - ESC,'<',0, A_GOLINE, - 'p',0, A_PERCENT, - '%',0, A_PERCENT, - ESC,'[',0, A_LSHIFT, - ESC,']',0, A_RSHIFT, - ESC,'(',0, A_LSHIFT, - ESC,')',0, A_RSHIFT, - ESC,'{',0, A_LLSHIFT, - ESC,'}',0, A_RRSHIFT, - SK(SK_RIGHT_ARROW),0, A_RSHIFT, - SK(SK_LEFT_ARROW),0, A_LSHIFT, - SK(SK_CTL_RIGHT_ARROW),0, A_RRSHIFT, - SK(SK_CTL_LEFT_ARROW),0, A_LLSHIFT, - '{',0, A_F_BRACKET|A_EXTRA, '{','}',0, - '}',0, A_B_BRACKET|A_EXTRA, '{','}',0, - '(',0, A_F_BRACKET|A_EXTRA, '(',')',0, - ')',0, A_B_BRACKET|A_EXTRA, '(',')',0, - '[',0, A_F_BRACKET|A_EXTRA, '[',']',0, - ']',0, A_B_BRACKET|A_EXTRA, '[',']',0, - ESC,CONTROL('F'),0, A_F_BRACKET, - ESC,CONTROL('B'),0, A_B_BRACKET, - 'G',0, A_GOEND, - ESC,'G',0, A_GOEND_BUF, - ESC,'>',0, A_GOEND, - '>',0, A_GOEND, - SK(SK_END),0, A_GOEND, - 'P',0, A_GOPOS, + '\r',0, A_F_LINE, + '\n',0, A_F_LINE, + 'e',0, A_F_LINE, + 'j',0, A_F_LINE, + SK(SK_DOWN_ARROW),0, A_F_LINE, + CONTROL('E'),0, A_F_LINE, + CONTROL('N'),0, A_F_LINE, + 'k',0, A_B_LINE, + 'y',0, A_B_LINE, + CONTROL('Y'),0, A_B_LINE, + SK(SK_CONTROL_K),0, A_B_LINE, + CONTROL('P'),0, A_B_LINE, + SK(SK_UP_ARROW),0, A_B_LINE, + 'J',0, A_FF_LINE, + 'K',0, A_BF_LINE, + 'Y',0, A_BF_LINE, + 'd',0, A_F_SCROLL, + CONTROL('D'),0, A_F_SCROLL, + 'u',0, A_B_SCROLL, + CONTROL('U'),0, A_B_SCROLL, + ESC,'[','M',0, A_X11MOUSE_IN, + ESC,'[','<',0, A_X116MOUSE_IN, + ' ',0, A_F_SCREEN, + 'f',0, A_F_SCREEN, + CONTROL('F'),0, A_F_SCREEN, + CONTROL('V'),0, A_F_SCREEN, + SK(SK_PAGE_DOWN),0, A_F_SCREEN, + 'b',0, A_B_SCREEN, + CONTROL('B'),0, A_B_SCREEN, + ESC,'v',0, A_B_SCREEN, + SK(SK_PAGE_UP),0, A_B_SCREEN, + 'z',0, A_F_WINDOW, + 'w',0, A_B_WINDOW, + ESC,' ',0, A_FF_SCREEN, + 'F',0, A_F_FOREVER, + ESC,'F',0, A_F_UNTIL_HILITE, + 'R',0, A_FREPAINT, + 'r',0, A_REPAINT, + CONTROL('R'),0, A_REPAINT, + CONTROL('L'),0, A_REPAINT, + ESC,'u',0, A_UNDO_SEARCH, + ESC,'U',0, A_CLR_SEARCH, + 'g',0, A_GOLINE, + SK(SK_HOME),0, A_GOLINE, + '<',0, A_GOLINE, + ESC,'<',0, A_GOLINE, + 'p',0, A_PERCENT, + '%',0, A_PERCENT, + ESC,'[',0, A_LSHIFT, + ESC,']',0, A_RSHIFT, + ESC,'(',0, A_LSHIFT, + ESC,')',0, A_RSHIFT, + ESC,'{',0, A_LLSHIFT, + ESC,'}',0, A_RRSHIFT, + SK(SK_RIGHT_ARROW),0, A_RSHIFT, + SK(SK_LEFT_ARROW),0, A_LSHIFT, + SK(SK_CTL_RIGHT_ARROW),0, A_RRSHIFT, + SK(SK_CTL_LEFT_ARROW),0, A_LLSHIFT, + '{',0, A_F_BRACKET|A_EXTRA, '{','}',0, + '}',0, A_B_BRACKET|A_EXTRA, '{','}',0, + '(',0, A_F_BRACKET|A_EXTRA, '(',')',0, + ')',0, A_B_BRACKET|A_EXTRA, '(',')',0, + '[',0, A_F_BRACKET|A_EXTRA, '[',']',0, + ']',0, A_B_BRACKET|A_EXTRA, '[',']',0, + ESC,CONTROL('F'),0, A_F_BRACKET, + ESC,CONTROL('B'),0, A_B_BRACKET, + 'G',0, A_GOEND, + ESC,'G',0, A_GOEND_BUF, + ESC,'>',0, A_GOEND, + '>',0, A_GOEND, + SK(SK_END),0, A_GOEND, + 'P',0, A_GOPOS, - '0',0, A_DIGIT, - '1',0, A_DIGIT, - '2',0, A_DIGIT, - '3',0, A_DIGIT, - '4',0, A_DIGIT, - '5',0, A_DIGIT, - '6',0, A_DIGIT, - '7',0, A_DIGIT, - '8',0, A_DIGIT, - '9',0, A_DIGIT, - '.',0, A_DIGIT, + '0',0, A_DIGIT, + '1',0, A_DIGIT, + '2',0, A_DIGIT, + '3',0, A_DIGIT, + '4',0, A_DIGIT, + '5',0, A_DIGIT, + '6',0, A_DIGIT, + '7',0, A_DIGIT, + '8',0, A_DIGIT, + '9',0, A_DIGIT, + '.',0, A_DIGIT, - '=',0, A_STAT, - CONTROL('G'),0, A_STAT, - ':','f',0, A_STAT, - '/',0, A_F_SEARCH, - '?',0, A_B_SEARCH, - ESC,'/',0, A_F_SEARCH|A_EXTRA, '*',0, - ESC,'?',0, A_B_SEARCH|A_EXTRA, '*',0, - 'n',0, A_AGAIN_SEARCH, - ESC,'n',0, A_T_AGAIN_SEARCH, - 'N',0, A_REVERSE_SEARCH, - ESC,'N',0, A_T_REVERSE_SEARCH, - '&',0, A_FILTER, - 'm',0, A_SETMARK, - 'M',0, A_SETMARKBOT, - ESC,'m',0, A_CLRMARK, - '\'',0, A_GOMARK, - CONTROL('X'),CONTROL('X'),0, A_GOMARK, - 'E',0, A_EXAMINE, - ':','e',0, A_EXAMINE, - CONTROL('X'),CONTROL('V'),0, A_EXAMINE, - ':','n',0, A_NEXT_FILE, - ':','p',0, A_PREV_FILE, - 't',0, A_NEXT_TAG, - 'T',0, A_PREV_TAG, - ':','x',0, A_INDEX_FILE, - ':','d',0, A_REMOVE_FILE, - '-',0, A_OPT_TOGGLE, - ':','t',0, A_OPT_TOGGLE|A_EXTRA, 't',0, - 's',0, A_OPT_TOGGLE|A_EXTRA, 'o',0, - '_',0, A_DISP_OPTION, - '|',0, A_PIPE, - 'v',0, A_VISUAL, - '!',0, A_SHELL, - '+',0, A_FIRSTCMD, + '=',0, A_STAT, + CONTROL('G'),0, A_STAT, + ':','f',0, A_STAT, + '/',0, A_F_SEARCH, + '?',0, A_B_SEARCH, + ESC,'/',0, A_F_SEARCH|A_EXTRA, '*',0, + ESC,'?',0, A_B_SEARCH|A_EXTRA, '*',0, + 'n',0, A_AGAIN_SEARCH, + ESC,'n',0, A_T_AGAIN_SEARCH, + 'N',0, A_REVERSE_SEARCH, + ESC,'N',0, A_T_REVERSE_SEARCH, + '&',0, A_FILTER, + 'm',0, A_SETMARK, + 'M',0, A_SETMARKBOT, + ESC,'m',0, A_CLRMARK, + '\'',0, A_GOMARK, + CONTROL('X'),CONTROL('X'),0, A_GOMARK, + 'E',0, A_EXAMINE, + ':','e',0, A_EXAMINE, + CONTROL('X'),CONTROL('V'),0, A_EXAMINE, + ':','n',0, A_NEXT_FILE, + ':','p',0, A_PREV_FILE, + 't',0, A_NEXT_TAG, + 'T',0, A_PREV_TAG, + ':','x',0, A_INDEX_FILE, + ':','d',0, A_REMOVE_FILE, + '-',0, A_OPT_TOGGLE, + ':','t',0, A_OPT_TOGGLE|A_EXTRA, 't',0, + 's',0, A_OPT_TOGGLE|A_EXTRA, 'o',0, + '_',0, A_DISP_OPTION, + '|',0, A_PIPE, + 'v',0, A_VISUAL, + '!',0, A_SHELL, + '+',0, A_FIRSTCMD, - 'H',0, A_HELP, - 'h',0, A_HELP, - SK(SK_F1),0, A_HELP, - 'V',0, A_VERSION, - 'q',0, A_QUIT, - 'Q',0, A_QUIT, - ':','q',0, A_QUIT, - ':','Q',0, A_QUIT, - 'Z','Z',0, A_QUIT + 'H',0, A_HELP, + 'h',0, A_HELP, + SK(SK_F1),0, A_HELP, + 'V',0, A_VERSION, + 'q',0, A_QUIT, + 'Q',0, A_QUIT, + ':','q',0, A_QUIT, + ':','Q',0, A_QUIT, + 'Z','Z',0, A_QUIT }; static unsigned char edittable[] = { - '\t',0, EC_F_COMPLETE, /* TAB */ - '\17',0, EC_B_COMPLETE, /* BACKTAB */ - SK(SK_BACKTAB),0, EC_B_COMPLETE, /* BACKTAB */ - ESC,'\t',0, EC_B_COMPLETE, /* ESC TAB */ - CONTROL('L'),0, EC_EXPAND, /* CTRL-L */ - CONTROL('V'),0, EC_LITERAL, /* BACKSLASH */ - CONTROL('A'),0, EC_LITERAL, /* BACKSLASH */ - ESC,'l',0, EC_RIGHT, /* ESC l */ - SK(SK_RIGHT_ARROW),0, EC_RIGHT, /* RIGHTARROW */ - ESC,'h',0, EC_LEFT, /* ESC h */ - SK(SK_LEFT_ARROW),0, EC_LEFT, /* LEFTARROW */ - ESC,'b',0, EC_W_LEFT, /* ESC b */ - ESC,SK(SK_LEFT_ARROW),0, EC_W_LEFT, /* ESC LEFTARROW */ - SK(SK_CTL_LEFT_ARROW),0, EC_W_LEFT, /* CTRL-LEFTARROW */ - ESC,'w',0, EC_W_RIGHT, /* ESC w */ - ESC,SK(SK_RIGHT_ARROW),0, EC_W_RIGHT, /* ESC RIGHTARROW */ - SK(SK_CTL_RIGHT_ARROW),0, EC_W_RIGHT, /* CTRL-RIGHTARROW */ - ESC,'i',0, EC_INSERT, /* ESC i */ - SK(SK_INSERT),0, EC_INSERT, /* INSERT */ - ESC,'x',0, EC_DELETE, /* ESC x */ - SK(SK_DELETE),0, EC_DELETE, /* DELETE */ - ESC,'X',0, EC_W_DELETE, /* ESC X */ - ESC,SK(SK_DELETE),0, EC_W_DELETE, /* ESC DELETE */ - SK(SK_CTL_DELETE),0, EC_W_DELETE, /* CTRL-DELETE */ - SK(SK_CTL_BACKSPACE),0, EC_W_BACKSPACE, /* CTRL-BACKSPACE */ - ESC,'\b',0, EC_W_BACKSPACE, /* ESC BACKSPACE */ - ESC,'0',0, EC_HOME, /* ESC 0 */ - SK(SK_HOME),0, EC_HOME, /* HOME */ - ESC,'$',0, EC_END, /* ESC $ */ - SK(SK_END),0, EC_END, /* END */ - ESC,'k',0, EC_UP, /* ESC k */ - SK(SK_UP_ARROW),0, EC_UP, /* UPARROW */ - ESC,'j',0, EC_DOWN, /* ESC j */ - SK(SK_DOWN_ARROW),0, EC_DOWN, /* DOWNARROW */ - CONTROL('G'),0, EC_ABORT, /* CTRL-G */ + '\t',0, EC_F_COMPLETE, /* TAB */ + '\17',0, EC_B_COMPLETE, /* BACKTAB */ + SK(SK_BACKTAB),0, EC_B_COMPLETE, /* BACKTAB */ + ESC,'\t',0, EC_B_COMPLETE, /* ESC TAB */ + CONTROL('L'),0, EC_EXPAND, /* CTRL-L */ + CONTROL('V'),0, EC_LITERAL, /* BACKSLASH */ + CONTROL('A'),0, EC_LITERAL, /* BACKSLASH */ + ESC,'l',0, EC_RIGHT, /* ESC l */ + SK(SK_RIGHT_ARROW),0, EC_RIGHT, /* RIGHTARROW */ + ESC,'h',0, EC_LEFT, /* ESC h */ + SK(SK_LEFT_ARROW),0, EC_LEFT, /* LEFTARROW */ + ESC,'b',0, EC_W_LEFT, /* ESC b */ + ESC,SK(SK_LEFT_ARROW),0, EC_W_LEFT, /* ESC LEFTARROW */ + SK(SK_CTL_LEFT_ARROW),0, EC_W_LEFT, /* CTRL-LEFTARROW */ + ESC,'w',0, EC_W_RIGHT, /* ESC w */ + ESC,SK(SK_RIGHT_ARROW),0, EC_W_RIGHT, /* ESC RIGHTARROW */ + SK(SK_CTL_RIGHT_ARROW),0, EC_W_RIGHT, /* CTRL-RIGHTARROW */ + ESC,'i',0, EC_INSERT, /* ESC i */ + SK(SK_INSERT),0, EC_INSERT, /* INSERT */ + ESC,'x',0, EC_DELETE, /* ESC x */ + SK(SK_DELETE),0, EC_DELETE, /* DELETE */ + ESC,'X',0, EC_W_DELETE, /* ESC X */ + ESC,SK(SK_DELETE),0, EC_W_DELETE, /* ESC DELETE */ + SK(SK_CTL_DELETE),0, EC_W_DELETE, /* CTRL-DELETE */ + SK(SK_CTL_BACKSPACE),0, EC_W_BACKSPACE, /* CTRL-BACKSPACE */ + ESC,'\b',0, EC_W_BACKSPACE, /* ESC BACKSPACE */ + ESC,'0',0, EC_HOME, /* ESC 0 */ + SK(SK_HOME),0, EC_HOME, /* HOME */ + ESC,'$',0, EC_END, /* ESC $ */ + SK(SK_END),0, EC_END, /* END */ + ESC,'k',0, EC_UP, /* ESC k */ + SK(SK_UP_ARROW),0, EC_UP, /* UPARROW */ + ESC,'j',0, EC_DOWN, /* ESC j */ + SK(SK_DOWN_ARROW),0, EC_DOWN, /* DOWNARROW */ + CONTROL('G'),0, EC_ABORT, /* CTRL-G */ + ESC,'[','M',0, EC_X11MOUSE, /* X11 mouse report */ + ESC,'[','<',0, EC_X116MOUSE, /* X11 1006 mouse report */ }; /* @@ -487,11 +490,14 @@ getcc_int(pterm) * The prefix ("\e[M") has already been read. */ static int -x11mouse_action(VOID_PARAM) +x11mouse_action(skip) + int skip; { int b = getcc() - X11MOUSE_OFFSET; int x = getcc() - X11MOUSE_OFFSET-1; int y = getcc() - X11MOUSE_OFFSET-1; + if (skip) + return (A_NOACTION); switch (b) { default: return (A_NOACTION); @@ -509,7 +515,8 @@ x11mouse_action(VOID_PARAM) * The prefix ("\e[<") has already been read. */ static int -x116mouse_action(VOID_PARAM) +x116mouse_action(skip) + int skip; { char ch; int x, y; @@ -519,6 +526,8 @@ x116mouse_action(VOID_PARAM) if (x < 0 || ch != ';') return (A_NOACTION); y = getcc_int(&ch) - 1; if (y < 0) return (A_NOACTION); + if (skip) + return (A_NOACTION); switch (b) { case X11MOUSE_WHEEL_DOWN: return mouse_wheel_down(); @@ -580,9 +589,9 @@ cmd_search(cmd, table, endtable, sp) a &= ~A_EXTRA; } if (a == A_X11MOUSE_IN) - a = x11mouse_action(); + a = x11mouse_action(0); else if (a == A_X116MOUSE_IN) - a = x116mouse_action(); + a = x116mouse_action(0); return (a); } } else if (*q == '\0') @@ -924,7 +933,6 @@ editchar(c, flags) #if MSDOS_COMPILER==WIN32C if (!win32_kbhit()) #endif - return (EC_LINEKILL); } @@ -934,15 +942,20 @@ editchar(c, flags) */ nch = 0; do { - if (nch > 0) + if (nch > 0) c = getcc(); usercmd[nch] = c; usercmd[nch+1] = '\0'; nch++; action = ecmd_decode(usercmd, &s); - } while (action == A_PREFIX); - - if (flags & EC_NORIGHTLEFT) + } while (action == A_PREFIX && nch < MAX_CMDLEN); + + if (action == EC_X11MOUSE) + return (x11mouse_action(1)); + if (action == EC_X116MOUSE) + return (x116mouse_action(1)); + + if (flags & ECF_NORIGHTLEFT) { switch (action) { @@ -953,7 +966,7 @@ editchar(c, flags) } } #if CMD_HISTORY - if (flags & EC_NOHISTORY) + if (flags & ECF_NOHISTORY) { /* * The caller says there is no history list. @@ -969,7 +982,7 @@ editchar(c, flags) } #endif #if TAB_COMPLETE_FILENAME - if (flags & EC_NOCOMPLETE) + if (flags & ECF_NOCOMPLETE) { /* * The caller says we don't want any filename completion cmds. @@ -985,7 +998,7 @@ editchar(c, flags) } } #endif - if ((flags & EC_PEEK) || action == A_INVALID) + if ((flags & ECF_PEEK) || action == A_INVALID) { /* * We're just peeking, or we didn't understand the command. diff --git a/defines.ds b/defines.ds index 45512bce23b2..fb02c89b6065 100644 --- a/defines.ds +++ b/defines.ds @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. diff --git a/defines.h.in b/defines.h.in index 36822bc41148..389a24fc5e59 100644 --- a/defines.h.in +++ b/defines.h.in @@ -257,6 +257,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H +/* Define to 1 if you have the `nanosleep' function. */ +#undef HAVE_NANOSLEEP + /* Define HAVE_OSPEED if your termcap library has the ospeed variable. */ #undef HAVE_OSPEED @@ -266,6 +269,9 @@ /* PCRE2 (Perl-compatible regular expression) library */ #undef HAVE_PCRE2 +/* Define to 1 if you have the `poll' function. */ +#undef HAVE_POLL + /* Define to 1 if you have the `popen' function. */ #undef HAVE_POPEN @@ -359,12 +365,18 @@ /* Define HAVE_TIME_T if your system supports the "time_t" type. */ #undef HAVE_TIME_T +/* Define to 1 if you have the `ttyname' function. */ +#undef HAVE_TTYNAME + /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define HAVE_UPPER_LOWER if you have isupper, islower, toupper, tolower. */ #undef HAVE_UPPER_LOWER +/* Define to 1 if you have the `usleep' function. */ +#undef HAVE_USLEEP + /* Henry Spencer V8 regcomp() and regexp.h */ #undef HAVE_V8_REGCOMP diff --git a/defines.o2 b/defines.o2 index 0257f5fe2113..267ef5edae74 100644 --- a/defines.o2 +++ b/defines.o2 @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. diff --git a/defines.o9 b/defines.o9 index 5d36ca880e69..22740ef8fb29 100644 --- a/defines.o9 +++ b/defines.o9 @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. diff --git a/defines.wn b/defines.wn index 80966df89135..b8256e1d7cd2 100644 --- a/defines.wn +++ b/defines.wn @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. diff --git a/edit.c b/edit.c index 3702b5051cec..12631dba6bac 100644 --- a/edit.c +++ b/edit.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -20,13 +20,12 @@ public int fd0 = 0; extern int new_file; -extern int errmsgs; extern int cbufs; extern char *every_first_cmd; -extern int any_display; extern int force_open; extern int is_tty; extern int sigs; +extern int hshift; extern IFILE curr_ifile; extern IFILE old_ifile; extern struct scrpos initial_scrpos; @@ -47,7 +46,6 @@ public dev_t curr_dev; public ino_t curr_ino; #endif - /* * Textlist functions deal with a list of words separated by spaces. * init_textlist sets up a textlist structure. @@ -242,7 +240,6 @@ edit_ifile(ifile) { int f; int answer; - int no_display; int chflags; char *filename; char *open_filename; @@ -462,14 +459,12 @@ edit_ifile(ifile) #endif if (every_first_cmd != NULL) { - ungetcc(CHAR_END_COMMAND); ungetsc(every_first_cmd); + ungetcc_back(CHAR_END_COMMAND); } } - no_display = !any_display; flush(); - any_display = TRUE; if (is_tty) { @@ -485,6 +480,7 @@ edit_ifile(ifile) #if HILITE_SEARCH clr_hilite(); #endif + hshift = 0; if (strcmp(filename, FAKE_HELPFILE) && strcmp(filename, FAKE_EMPTYFILE)) { char *qfilename = shell_quote(filename); @@ -492,17 +488,6 @@ edit_ifile(ifile) free(qfilename); } - if (no_display && errmsgs > 0) - { - /* - * We displayed some messages on error output - * (file descriptor 2; see error() function). - * Before erasing the screen contents, - * display the file name and wait for a keystroke. - */ - parg.p_string = filename; - error("%s", &parg); - } } free(filename); return (0); @@ -784,6 +769,8 @@ cat_file(VOID_PARAM) #if LOGFILE +#define OVERWRITE_OPTIONS "Overwrite, Append, Don't log, or Quit?" + /* * If the user asked for a log file and our input file * is standard input, create the log file. @@ -827,7 +814,7 @@ use_logfile(filename) * Ask user what to do. */ parg.p_string = filename; - answer = query("Warning: \"%s\" exists; Overwrite, Append or Don't log? ", &parg); + answer = query("Warning: \"%s\" exists; "OVERWRITE_OPTIONS" ", &parg); } loop: @@ -855,14 +842,12 @@ use_logfile(filename) * Don't do anything. */ return; - case 'q': - quit(QUIT_OK); - /*NOTREACHED*/ default: /* * Eh? */ - answer = query("Overwrite, Append, or Don't log? (Type \"O\", \"A\", \"D\" or \"q\") ", NULL_PARG); + + answer = query(OVERWRITE_OPTIONS" (Type \"O\", \"A\", \"D\" or \"Q\") ", NULL_PARG); goto loop; } diff --git a/filename.c b/filename.c index adb5e646c112..177cb946364a 100644 --- a/filename.c +++ b/filename.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -23,7 +23,7 @@ #if MSDOS_COMPILER==DJGPPC #include #include -#define _MAX_PATH PATH_MAX +#define _MAX_PATH PATH_MAX #endif #endif #ifdef _OSK @@ -36,10 +36,10 @@ #if HAVE_STAT #include #ifndef S_ISDIR -#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #endif #ifndef S_ISREG -#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #endif #endif @@ -312,7 +312,7 @@ fexpand(s) char *e; IFILE ifile; -#define fchar_ifile(c) \ +#define fchar_ifile(c) \ ((c) == '%' ? curr_ifile : \ (c) == '#' ? old_ifile : NULL_IFILE) @@ -486,9 +486,12 @@ bin_file(f) } else { LWCHAR c = step_char(&p, +1, edata); - if (ctldisp == OPT_ONPLUS && IS_CSI_START(c)) - skip_ansi(&p, edata); - else if (binary_char(c)) + struct ansi_state *pansi; + if (ctldisp == OPT_ONPLUS && (pansi = ansi_start(c)) != NULL) + { + skip_ansi(pansi, &p, edata); + ansi_done(pansi); + } else if (binary_char(c)) bin_count++; } } @@ -648,7 +651,7 @@ lglob(filename) qfilename = shell_quote(p); if (qfilename != NULL) { - length += strlen(qfilename) + 1; + length += strlen(qfilename) + 1; free(qfilename); } } @@ -914,7 +917,7 @@ open_altfile(filename, pf, pfd) int f; /* - * The first time we open the file, read one char + * The alt file is a pipe. Read one char * to see if the pipe will produce any data. * If it does, push the char back on the pipe. */ @@ -931,18 +934,22 @@ open_altfile(filename, pf, pfd) */ int status = pclose(fd); if (returnfd > 1 && status == 0) { + /* File is empty. */ *pfd = NULL; *pf = -1; return (save(FAKE_EMPTYFILE)); } + /* No alt file. */ return (NULL); } + /* Alt pipe contains data, so use it. */ ch_ungetchar(c); *pfd = (void *) fd; *pf = f; return (save("-")); } #endif + /* The alt file is a regular file. Read its name from LESSOPEN. */ cmd = readfd(fd); pclose(fd); if (*cmd == '\0') @@ -972,7 +979,7 @@ close_altfile(altfilename, filename) return; ch_ungetchar(-1); if ((lessclose = lgetenv("LESSCLOSE")) == NULL) - return; + return; if (num_pct_s(lessclose) > 2) { error("LESSCLOSE ignored; must contain no more than 2 %%s", NULL_PARG); diff --git a/forwback.c b/forwback.c index 720054c0ebf3..e72172bf63db 100644 --- a/forwback.c +++ b/forwback.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -47,6 +47,13 @@ extern char *tagoption; static void eof_bell(VOID_PARAM) { +#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; +#endif if (quiet == NOT_QUIET) bell(); else @@ -185,7 +192,7 @@ forw(n, pos, force, only_last, nblank) { clear(); home(); - } else if (!first_time) + } else if (!first_time && !is_filtering()) { putstr("...skipping...\n"); } diff --git a/funcs.h b/funcs.h index fb3c7bbfed92..12930356c938 100644 --- a/funcs.h +++ b/funcs.h @@ -11,6 +11,7 @@ public void init_mouse LESSPARAMS ((VOID_PARAM)); public void deinit_mouse LESSPARAMS ((VOID_PARAM)); public void init LESSPARAMS ((VOID_PARAM)); public void deinit LESSPARAMS ((VOID_PARAM)); +public int interactive LESSPARAMS ((VOID_PARAM)); public void home LESSPARAMS ((VOID_PARAM)); public void add_line LESSPARAMS ((VOID_PARAM)); public void remove_top LESSPARAMS ((int n)); @@ -24,12 +25,12 @@ public void bell LESSPARAMS ((VOID_PARAM)); public void clear LESSPARAMS ((VOID_PARAM)); public void clear_eol LESSPARAMS ((VOID_PARAM)); public void clear_bot LESSPARAMS ((VOID_PARAM)); +public COLOR_TYPE parse_color LESSPARAMS ((char *str, int *p_fg, int *p_bg)); public void at_enter LESSPARAMS ((int attr)); public void at_exit LESSPARAMS ((VOID_PARAM)); public void at_switch LESSPARAMS ((int attr)); public int is_at_equiv LESSPARAMS ((int attr1, int attr2)); public int apply_at_specials LESSPARAMS ((int attr)); -public void backspace LESSPARAMS ((VOID_PARAM)); public void putbs LESSPARAMS ((VOID_PARAM)); public int win32_kbhit LESSPARAMS ((VOID_PARAM)); public char WIN32getch LESSPARAMS ((VOID_PARAM)); @@ -75,6 +76,7 @@ public void cmd_reset LESSPARAMS ((VOID_PARAM)); public void clear_cmd LESSPARAMS ((VOID_PARAM)); public void cmd_putstr LESSPARAMS ((constant char *s)); public int len_cmdbuf LESSPARAMS ((VOID_PARAM)); +public void cmd_repaint LESSPARAMS ((constant char *old_cp)); public void set_mlist LESSPARAMS ((void *mlist, int cmdflags)); public void cmd_addhist LESSPARAMS ((struct mlist *mlist, constant char *cmd, int modified)); public void cmd_accept LESSPARAMS ((VOID_PARAM)); @@ -88,6 +90,7 @@ public int in_mca LESSPARAMS ((VOID_PARAM)); public void dispversion LESSPARAMS ((VOID_PARAM)); public int getcc LESSPARAMS ((VOID_PARAM)); public void ungetcc LESSPARAMS ((LWCHAR c)); +public void ungetcc_back LESSPARAMS ((LWCHAR c)); public void ungetsc LESSPARAMS ((char *s)); public LWCHAR peekcc LESSPARAMS ((VOID_PARAM)); public void commands LESSPARAMS ((VOID_PARAM)); @@ -155,6 +158,7 @@ public IFILE getoff_ifile LESSPARAMS ((IFILE ifile)); public int nifile LESSPARAMS ((VOID_PARAM)); public IFILE get_ifile LESSPARAMS ((char *filename, IFILE prev)); public char * get_filename LESSPARAMS ((IFILE ifile)); +public char * get_real_filename LESSPARAMS ((IFILE ifile)); public int get_index LESSPARAMS ((IFILE ifile)); public void store_pos LESSPARAMS ((IFILE ifile, struct scrpos *scrpos)); public void get_pos LESSPARAMS ((IFILE ifile, struct scrpos *scrpos)); @@ -169,6 +173,7 @@ public void * get_altpipe LESSPARAMS ((IFILE ifile)); public void set_altfilename LESSPARAMS ((IFILE ifile, char *altfilename)); public char * get_altfilename LESSPARAMS ((IFILE ifile)); public void if_dump LESSPARAMS ((VOID_PARAM)); +public POSITION forw_line_seg LESSPARAMS ((POSITION curr_pos, int get_segpos)); public POSITION forw_line LESSPARAMS ((POSITION curr_pos)); public POSITION back_line LESSPARAMS ((POSITION curr_pos)); public void set_attnpos LESSPARAMS ((POSITION pos)); @@ -182,20 +187,27 @@ public void jump_loc LESSPARAMS ((POSITION pos, int sline)); public void init_line LESSPARAMS ((VOID_PARAM)); public int is_ascii_char LESSPARAMS ((LWCHAR ch)); public void prewind LESSPARAMS ((VOID_PARAM)); -public void plinenum LESSPARAMS ((POSITION pos)); +public void plinestart LESSPARAMS ((POSITION pos)); +public int line_pfx_width LESSPARAMS ((VOID_PARAM)); public void pshift_all LESSPARAMS ((VOID_PARAM)); +public int pwidth LESSPARAMS ((LWCHAR ch, int a, LWCHAR prev_ch, int prev_a)); public int is_ansi_end LESSPARAMS ((LWCHAR ch)); public int is_ansi_middle LESSPARAMS ((LWCHAR ch)); -public void skip_ansi LESSPARAMS ((char **pp, constant char *limit)); +public void skip_ansi LESSPARAMS ((struct ansi_state *pansi, char **pp, constant char *limit)); +public struct ansi_state * ansi_start LESSPARAMS ((LWCHAR ch)); +public int ansi_step LESSPARAMS ((struct ansi_state *pansi, LWCHAR ch)); +public void ansi_done LESSPARAMS ((struct ansi_state *pansi)); public int pappend LESSPARAMS ((int c, POSITION pos)); public int pflushmbc LESSPARAMS ((VOID_PARAM)); public void pdone LESSPARAMS ((int endline, int chopped, int forw)); -public void set_status_col LESSPARAMS ((int c)); +public void set_status_col LESSPARAMS ((int c, int attr)); public int gline LESSPARAMS ((int i, int *ap)); public void null_line LESSPARAMS ((VOID_PARAM)); public POSITION forw_raw_line LESSPARAMS ((POSITION curr_pos, char **linep, int *line_lenp)); public POSITION back_raw_line LESSPARAMS ((POSITION curr_pos, char **linep, int *line_lenp)); public int rrshift LESSPARAMS ((VOID_PARAM)); +public int set_color_map LESSPARAMS ((int attr, char *colorstr)); +public char * get_color_map LESSPARAMS ((int attr)); public void clr_linenum LESSPARAMS ((VOID_PARAM)); public void add_lnum LESSPARAMS ((LINENUM linenum, POSITION pos)); public LINENUM find_linenum LESSPARAMS ((POSITION pos)); @@ -237,6 +249,10 @@ public void opt_rscroll LESSPARAMS ((int type, char *s)); public void opt_query LESSPARAMS ((int type, char *s)); 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_ttyin_name LESSPARAMS ((int type, char *s)); +public void opt_rstat LESSPARAMS ((int type, char *s)); public int get_swindow LESSPARAMS ((VOID_PARAM)); public char * propt LESSPARAMS ((int c)); public void scan_option LESSPARAMS ((char *s)); @@ -259,15 +275,18 @@ public char * errno_message LESSPARAMS ((char *filename)); public int percentage LESSPARAMS ((POSITION num, POSITION den)); public POSITION percent_pos LESSPARAMS ((POSITION pos, int percent, long fraction)); public int os9_signal LESSPARAMS ((int type, RETSIGTYPE (*handler)())); +public void sleep_ms LESSPARAMS ((int ms)); 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 putstr LESSPARAMS ((constant char *s)); +public int less_printf LESSPARAMS ((char *fmt, PARG *parg)); public void get_return LESSPARAMS ((VOID_PARAM)); public void error LESSPARAMS ((char *fmt, PARG *parg)); public void ierror LESSPARAMS ((char *fmt, PARG *parg)); public int query LESSPARAMS ((char *fmt, PARG *parg)); -public int compile_pattern LESSPARAMS ((char *pattern, int search_type, PATTERN_TYPE *comp_pattern)); +public int compile_pattern LESSPARAMS ((char *pattern, int search_type, int show_error, PATTERN_TYPE *comp_pattern)); public void uncompile_pattern LESSPARAMS ((PATTERN_TYPE *pattern)); public int valid_pattern LESSPARAMS ((char *pattern)); public int is_null_pattern LESSPARAMS ((PATTERN_TYPE pattern)); @@ -291,14 +310,14 @@ public char * wait_message LESSPARAMS ((VOID_PARAM)); public void init_search LESSPARAMS ((VOID_PARAM)); public void repaint_hilite LESSPARAMS ((int on)); public void clear_attn LESSPARAMS ((VOID_PARAM)); -public void undo_search LESSPARAMS ((VOID_PARAM)); +public void undo_search LESSPARAMS ((int clear)); public void clr_hlist LESSPARAMS ((struct hilite_tree *anchor)); public void clr_hilite LESSPARAMS ((VOID_PARAM)); public void clr_filter LESSPARAMS ((VOID_PARAM)); public int is_filtered LESSPARAMS ((POSITION pos)); public POSITION next_unfiltered LESSPARAMS ((POSITION pos)); public POSITION prev_unfiltered LESSPARAMS ((POSITION pos)); -public int is_hilited LESSPARAMS ((POSITION pos, POSITION epos, int nohide, int *p_matches)); +public int is_hilited_attr LESSPARAMS ((POSITION pos, POSITION epos, int nohide, int *p_matches)); public void chg_hilite LESSPARAMS ((VOID_PARAM)); public void chg_caseless LESSPARAMS ((VOID_PARAM)); public int search LESSPARAMS ((int search_type, char *pattern, int n)); @@ -317,7 +336,9 @@ public char * prevtag LESSPARAMS ((int n)); public int ntags LESSPARAMS ((VOID_PARAM)); public int curr_tag LESSPARAMS ((VOID_PARAM)); public int edit_tagfile LESSPARAMS ((VOID_PARAM)); +public char * tty_device LESSPARAMS ((VOID_PARAM)); public void open_getchr LESSPARAMS ((VOID_PARAM)); 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)); diff --git a/help.c b/help.c index cfaa57855902..94b92cea69c2 100644 --- a/help.c +++ b/help.c @@ -1,4 +1,4 @@ -/* This file was generated by mkhelp.pl from less.hlp at 3:34 on 2020/6/14 */ +/* This file was generated by mkhelp.pl from less.hlp at 1:31 on 2021/4/7 */ #include "less.h" constant char helpdata[] = { '\n', @@ -45,7 +45,8 @@ constant char helpdata[] = { ' ',' ','E','S','C','-','n',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','R','e','p','e','a','t',' ','p','r','e','v','i','o','u','s',' ','s','e','a','r','c','h',',',' ','s','p','a','n','n','i','n','g',' ','f','i','l','e','s','.','\n', ' ',' ','E','S','C','-','N',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','R','e','p','e','a','t',' ','p','r','e','v','i','o','u','s',' ','s','e','a','r','c','h',',',' ','r','e','v','e','r','s','e',' ','d','i','r','.',' ','&',' ','s','p','a','n','n','i','n','g',' ','f','i','l','e','s','.','\n', ' ',' ','E','S','C','-','u',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','U','n','d','o',' ','(','t','o','g','g','l','e',')',' ','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', +' ',' ','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', ' ',' ',' ',' ',' ',' ',' ',' ','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', @@ -53,6 +54,7 @@ constant char helpdata[] = { ' ',' ',' ',' ',' ',' ',' ',' ','^','F',' ','o','r',' ','@',' ',' ','S','t','a','r','t',' ','s','e','a','r','c','h',' ','a','t',' ','F','I','R','S','T',' ','f','i','l','e',' ','(','f','o','r',' ','/',')',' ','o','r',' ','l','a','s','t',' ','f','i','l','e',' ','(','f','o','r',' ','?',')','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ','^','K',' ',' ',' ',' ',' ',' ',' ','H','i','g','h','l','i','g','h','t',' ','m','a','t','c','h','e','s',',',' ','b','u','t',' ','d','o','n','\'','t',' ','m','o','v','e',' ','(','K','E','E','P',' ','p','o','s','i','t','i','o','n',')','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ','^','R',' ',' ',' ',' ',' ',' ',' ','D','o','n','\'','t',' ','u','s','e',' ','R','E','G','U','L','A','R',' ','E','X','P','R','E','S','S','I','O','N','S','.','\n', +' ',' ',' ',' ',' ',' ',' ',' ','^','W',' ',' ',' ',' ',' ',' ',' ','W','R','A','P',' ','s','e','a','r','c','h',' ','i','f',' ','n','o',' ','m','a','t','c','h',' ','f','o','u','n','d','.','\n', ' ','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\n', '\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','J','\b','J','U','\b','U','M','\b','M','P','\b','P','I','\b','I','N','\b','N','G','\b','G','\n', @@ -65,7 +67,7 @@ constant char helpdata[] = { ' ',' ','{',' ',' ','(',' ',' ','[',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','F','i','n','d',' ','c','l','o','s','e',' ','b','r','a','c','k','e','t',' ','}',' ',')',' ',']','.','\n', ' ',' ','}',' ',' ',')',' ',' ',']',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','F','i','n','d',' ','o','p','e','n',' ','b','r','a','c','k','e','t',' ','{',' ','(',' ','[','.','\n', ' ',' ','E','S','C','-','^','F',' ','_','\b','<','_','\b','c','_','\b','1','_','\b','>',' ','_','\b','<','_','\b','c','_','\b','2','_','\b','>',' ',' ','*',' ',' ','F','i','n','d',' ','c','l','o','s','e',' ','b','r','a','c','k','e','t',' ','_','\b','<','_','\b','c','_','\b','2','_','\b','>','.','\n', -' ',' ','E','S','C','-','^','B',' ','_','\b','<','_','\b','c','_','\b','1','_','\b','>',' ','_','\b','<','_','\b','c','_','\b','2','_','\b','>',' ',' ','*',' ',' ','F','i','n','d',' ','o','p','e','n',' ','b','r','a','c','k','e','t',' ','_','\b','<','_','\b','c','_','\b','1','_','\b','>',' ','\n', +' ',' ','E','S','C','-','^','B',' ','_','\b','<','_','\b','c','_','\b','1','_','\b','>',' ','_','\b','<','_','\b','c','_','\b','2','_','\b','>',' ',' ','*',' ',' ','F','i','n','d',' ','o','p','e','n',' ','b','r','a','c','k','e','t',' ','_','\b','<','_','\b','c','_','\b','1','_','\b','>','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\n', ' ',' ',' ',' ',' ',' ',' ',' ','E','a','c','h',' ','"','f','i','n','d',' ','c','l','o','s','e',' ','b','r','a','c','k','e','t','"',' ','c','o','m','m','a','n','d',' ','g','o','e','s',' ','f','o','r','w','a','r','d',' ','t','o',' ','t','h','e',' ','c','l','o','s','e',' ','b','r','a','c','k','e','t',' ','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','m','a','t','c','h','i','n','g',' ','t','h','e',' ','(','_','\b','N','-','t','h',')',' ','o','p','e','n',' ','b','r','a','c','k','e','t',' ','i','n',' ','t','h','e',' ','t','o','p',' ','l','i','n','e','.','\n', @@ -132,8 +134,8 @@ constant char helpdata[] = { ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','R','e','p','a','i','n','t',' ','b','y',' ','c','l','e','a','r','i','n','g',' ','r','a','t','h','e','r',' ','t','h','a','n',' ','s','c','r','o','l','l','i','n','g','.','\n', ' ',' ','-','d',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','d','u','m','b','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','u','m','b',' ','t','e','r','m','i','n','a','l','.','\n', -' ',' ','-','D',' ','[','_','\b','x','_','\b','n','_','\b','.','_','\b','n',']',' ',' ','.',' ',' ','-','-','c','o','l','o','r','=','_','\b','x','_','\b','n','_','\b','.','_','\b','n','\n', -' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','t',' ','s','c','r','e','e','n',' ','c','o','l','o','r','s','.',' ','(','M','S','-','D','O','S',' ','o','n','l','y',')','\n', +' ',' ','-','D',' ','x','\b','x','_','\b','c','_','\b','o','_','\b','l','_','\b','o','_','\b','r',' ',' ','.',' ',' ','-','-','c','o','l','o','r','=','x','\b','x','_','\b','c','_','\b','o','_','\b','l','_','\b','o','_','\b','r','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','t',' ','s','c','r','e','e','n',' ','c','o','l','o','r','s','.','\n', ' ',' ','-','e',' ',' ','-','E',' ',' ','.','.','.','.',' ',' ','-','-','q','u','i','t','-','a','t','-','e','o','f',' ',' ','-','-','Q','U','I','T','-','A','T','-','E','O','F','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','Q','u','i','t',' ','a','t',' ','e','n','d',' ','o','f',' ','f','i','l','e','.','\n', ' ',' ','-','f',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','f','o','r','c','e','\n', @@ -205,9 +207,13 @@ constant char helpdata[] = { ' ',' ','-','~',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','t','i','l','d','e','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','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', -' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','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', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','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','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', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','a','r','c','h',' ','f','i','l','e',' ','a','s',' ','e','a','c','h',' ','p','a','t','t','e','r','n',' ','c','h','a','r','a','c','t','e','r',' ','i','s',' ','t','y','p','e','d',' ','i','n','.','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','l','i','n','e','-','n','u','m','-','w','i','d','t','h','=','N','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','t',' ','t','h','e',' ','w','i','d','t','h',' ','o','f',' ','t','h','e',' ','-','N',' ','l','i','n','e',' ','n','u','m','b','e','r',' ','f','i','e','l','d',' ','t','o',' ','N',' ','c','h','a','r','a','c','t','e','r','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','-','k','e','y','p','a','d','\n', @@ -218,8 +224,12 @@ constant char helpdata[] = { ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','t',' ','t','h','e',' ','c','h','a','r','a','c','t','e','r',' ','u','s','e','d',' ','t','o',' ','m','a','r','k',' ','t','r','u','n','c','a','t','e','d',' ','l','i','n','e','s','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','s','a','v','e','-','m','a','r','k','s','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','R','e','t','a','i','n',' ','m','a','r','k','s',' ','a','c','r','o','s','s',' ','i','n','v','o','c','a','t','i','o','n','s',' ','o','f',' ','l','e','s','s','.','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','s','t','a','t','u','s','-','c','o','l','-','w','i','d','t','h','=','N','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','t',' ','t','h','e',' ','w','i','d','t','h',' ','o','f',' ','t','h','e',' ','-','J',' ','s','t','a','t','u','s',' ','c','o','l','u','m','n',' ','t','o',' ','N',' ','c','h','a','r','a','c','t','e','r','s','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','u','s','e','-','b','a','c','k','s','l','a','s','h','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','u','b','s','e','q','u','e','n','t',' ','o','p','t','i','o','n','s',' ','u','s','e',' ','b','a','c','k','s','l','a','s','h',' ','a','s',' ','e','s','c','a','p','e',' ','c','h','a','r','.','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','u','s','e','-','c','o','l','o','r','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','E','n','a','b','l','e','s',' ','c','o','l','o','r','e','d',' ','t','e','x','t','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','w','h','e','e','l','-','l','i','n','e','s','=','N','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','E','a','c','h',' ','c','l','i','c','k',' ','o','f',' ','t','h','e',' ','m','o','u','s','e',' ','w','h','e','e','l',' ','m','o','v','e','s',' ','N',' ','l','i','n','e','s','.','\n', '\n', @@ -247,7 +257,5 @@ constant char helpdata[] = { ' ','T','A','B',' ','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',' ','C','o','m','p','l','e','t','e',' ','f','i','l','e','n','a','m','e',' ','&',' ','c','y','c','l','e','.','\n', ' ','S','H','I','F','T','-','T','A','B',' ','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',' ','E','S','C','-','T','A','B',' ',' ',' ','C','o','m','p','l','e','t','e',' ','f','i','l','e','n','a','m','e',' ','&',' ','r','e','v','e','r','s','e',' ','c','y','c','l','e','.','\n', ' ','c','t','r','l','-','L',' ','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',' ','C','o','m','p','l','e','t','e',' ','f','i','l','e','n','a','m','e',',',' ','l','i','s','t',' ','a','l','l','.','\n', -'\n', -'\n', 0 }; constant int size_helpdata = sizeof(helpdata) - 1; diff --git a/ifile.c b/ifile.c index 6006cb12bd20..bc47a666754f 100644 --- a/ifile.c +++ b/ifile.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -21,12 +21,13 @@ #include "less.h" -extern IFILE curr_ifile; +extern IFILE curr_ifile; struct ifile { struct ifile *h_next; /* Links for command line list */ struct ifile *h_prev; char *h_filename; /* Name of the file */ + char *h_rfilename; /* Canonical name of the file */ void *h_filestate; /* File state (used in ch.c) */ int h_index; /* Index within command line list */ int h_hold; /* Hold count */ @@ -40,13 +41,13 @@ struct ifile { * Convert an IFILE (external representation) * to a struct file (internal representation), and vice versa. */ -#define int_ifile(h) ((struct ifile *)(h)) -#define ext_ifile(h) ((IFILE)(h)) +#define int_ifile(h) ((struct ifile *)(h)) +#define ext_ifile(h) ((IFILE)(h)) /* * Anchor for linked list. */ -static struct ifile anchor = { &anchor, &anchor, NULL, NULL, 0, 0, '\0', +static struct ifile anchor = { &anchor, &anchor, NULL, NULL, NULL, 0, 0, '\0', { NULL_POSITION, 0 } }; static int ifiles = 0; @@ -116,10 +117,13 @@ new_ifile(filename, prev) */ p = (struct ifile *) ecalloc(1, sizeof(struct ifile)); p->h_filename = save(filename); + p->h_rfilename = lrealpath(filename); p->h_scrpos.pos = NULL_POSITION; p->h_opened = 0; p->h_hold = 0; p->h_filestate = NULL; + p->h_altfilename = NULL; + p->h_altpipe = NULL; link_ifile(p, prev); /* * {{ It's dodgy to call mark.c functions from here; @@ -150,6 +154,7 @@ del_ifile(h) curr_ifile = getoff_ifile(curr_ifile); p = int_ifile(h); unlink_ifile(p); + free(p->h_rfilename); free(p->h_filename); free(p); } @@ -221,15 +226,17 @@ find_ifile(filename) for (p = anchor.h_next; p != &anchor; p = p->h_next) { - if (strcmp(filename, p->h_filename) == 0 || - strcmp(rfilename, p->h_filename) == 0) + if (strcmp(rfilename, p->h_rfilename) == 0) { /* * If given name is shorter than the name we were * previously using for this file, adopt shorter name. */ if (strlen(filename) < strlen(p->h_filename)) - strcpy(p->h_filename, filename); + { + free(p->h_filename); + p->h_filename = save(filename); + } break; } } @@ -257,7 +264,7 @@ get_ifile(filename, prev) } /* - * Get the filename associated with a ifile. + * Get the display filename associated with a ifile. */ public char * get_filename(ifile) @@ -268,6 +275,18 @@ get_filename(ifile) return (int_ifile(ifile)->h_filename); } +/* + * Get the canonical filename associated with a ifile. + */ + public char * +get_real_filename(ifile) + IFILE ifile; +{ + if (ifile == NULL) + return (NULL); + return (int_ifile(ifile)->h_rfilename); +} + /* * Get the index of the file associated with a ifile. */ @@ -372,7 +391,7 @@ set_altfilename(ifile, altfilename) char *altfilename; { struct ifile *p = int_ifile(ifile); - if (p->h_altfilename != NULL) + if (p->h_altfilename != NULL && p->h_altfilename != altfilename) free(p->h_altfilename); p->h_altfilename = altfilename; } diff --git a/input.c b/input.c index 526fe4be3bdb..f57c9e3403f2 100644 --- a/input.c +++ b/input.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -31,6 +31,7 @@ extern POSITION end_attnpos; #if HILITE_SEARCH extern int hilite_search; extern int size_linebuf; +extern int show_attn; #endif /* @@ -41,8 +42,9 @@ extern int size_linebuf; * of the NEXT line. The line obtained is the line starting at curr_pos. */ public POSITION -forw_line(curr_pos) +forw_line_seg(curr_pos, get_segpos) POSITION curr_pos; + int get_segpos; { POSITION base_pos; POSITION new_pos; @@ -104,8 +106,8 @@ forw_line(curr_pos) /* * Read forward again to the position we should start at. */ - prewind(); - plinenum(base_pos); + prewind(); + plinestart(base_pos); (void) ch_seek(base_pos); new_pos = base_pos; while (new_pos < curr_pos) @@ -180,8 +182,9 @@ forw_line(curr_pos) * is too long to print in the screen width. * End the line here. */ - if (chopline || hshift > 0) + if ((chopline || hshift > 0) && !get_segpos) { + /* Read to end of line. */ do { if (ABORT_SIGS()) @@ -205,6 +208,13 @@ forw_line(curr_pos) c = ch_forw_get(); } +#if HILITE_SEARCH + if (blankline && show_attn) + { + /* Add spurious space to carry possible attn hilite. */ + pappend(' ', ch_tell()-1); + } +#endif pdone(endline, chopped, 1); #if HILITE_SEARCH @@ -218,8 +228,12 @@ forw_line(curr_pos) goto get_forw_line; } - if (status_col && is_hilited(base_pos, ch_tell()-1, 1, NULL)) - set_status_col('*'); + if (status_col) + { + int attr = is_hilited_attr(base_pos, ch_tell()-1, 1, NULL); + if (attr) + set_status_col('*', attr); + } #endif if (squeeze && blankline) @@ -243,6 +257,13 @@ forw_line(curr_pos) return (new_pos); } + public POSITION +forw_line(curr_pos) + POSITION curr_pos; +{ + return forw_line_seg(curr_pos, FALSE); +} + /* * Get the previous line. * A "current" position is passed and a "new" position is returned. @@ -358,7 +379,7 @@ back_line(curr_pos) } endline = FALSE; prewind(); - plinenum(new_pos); + plinestart(new_pos); loop: begin_new_pos = new_pos; (void) ch_seek(new_pos); @@ -423,8 +444,12 @@ back_line(curr_pos) goto get_back_line; } - if (status_col && curr_pos > 0 && is_hilited(base_pos, curr_pos-1, 1, NULL)) - set_status_col('*'); + if (status_col && curr_pos > 0) + { + int attr = is_hilited_attr(base_pos, curr_pos-1, 1, NULL); + if (attr) + set_status_col('*', attr); + } #endif return (begin_new_pos); diff --git a/jump.c b/jump.c index a8ed6a5303e5..a376486c5e23 100644 --- a/jump.c +++ b/jump.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. diff --git a/less.h b/less.h index 944df687cbec..4751976bac18 100644 --- a/less.h +++ b/less.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -16,10 +16,10 @@ /* * Defines for MSDOS_COMPILER. */ -#define MSOFTC 1 /* Microsoft C */ -#define BORLANDC 2 /* Borland C */ -#define WIN32C 3 /* Windows (Borland C or Microsoft C) */ -#define DJGPPC 4 /* DJGPP C */ +#define MSOFTC 1 /* Microsoft C */ +#define BORLANDC 2 /* Borland C */ +#define WIN32C 3 /* Windows (Borland C or Microsoft C) */ +#define DJGPPC 4 /* DJGPP C */ /* * Include the file of compile-time options. @@ -45,20 +45,20 @@ #define LESSPARAMS(a) () #endif #if HAVE_VOID -#define VOID_POINTER void * -#define VOID_PARAM void +#define VOID_POINTER void * +#define VOID_PARAM void #else -#define VOID_POINTER char * -#define VOID_PARAM -#define void int +#define VOID_POINTER char * +#define VOID_PARAM +#define void int #endif #if HAVE_CONST -#define constant const +#define constant const #else -#define constant +#define constant #endif -#define public /* PUBLIC FUNCTION */ +#define public /* PUBLIC FUNCTION */ /* Library function declarations */ @@ -122,10 +122,10 @@ void free(); * Simple lowercase test which can be used during option processing * (before options are parsed which might tell us what charset to use). */ -#define ASCII_IS_UPPER(c) ((c) >= 'A' && (c) <= 'Z') -#define ASCII_IS_LOWER(c) ((c) >= 'a' && (c) <= 'z') -#define ASCII_TO_UPPER(c) ((c) - 'a' + 'A') -#define ASCII_TO_LOWER(c) ((c) - 'A' + 'a') +#define ASCII_IS_UPPER(c) ((c) >= 'A' && (c) <= 'Z') +#define ASCII_IS_LOWER(c) ((c) >= 'a' && (c) <= 'z') +#define ASCII_TO_UPPER(c) ((c) - 'a' + 'A') +#define ASCII_TO_LOWER(c) ((c) - 'A' + 'a') #undef IS_UPPER #undef IS_LOWER @@ -135,56 +135,56 @@ void free(); #undef IS_DIGIT #if HAVE_WCTYPE -#define IS_UPPER(c) iswupper(c) -#define IS_LOWER(c) iswlower(c) -#define TO_UPPER(c) towupper(c) -#define TO_LOWER(c) towlower(c) +#define IS_UPPER(c) iswupper(c) +#define IS_LOWER(c) iswlower(c) +#define TO_UPPER(c) towupper(c) +#define TO_LOWER(c) towlower(c) #else #if HAVE_UPPER_LOWER -#define IS_UPPER(c) isupper((unsigned char) (c)) -#define IS_LOWER(c) islower((unsigned char) (c)) -#define TO_UPPER(c) toupper((unsigned char) (c)) -#define TO_LOWER(c) tolower((unsigned char) (c)) +#define IS_UPPER(c) isupper((unsigned char) (c)) +#define IS_LOWER(c) islower((unsigned char) (c)) +#define TO_UPPER(c) toupper((unsigned char) (c)) +#define TO_LOWER(c) tolower((unsigned char) (c)) #else -#define IS_UPPER(c) ASCII_IS_UPPER(c) -#define IS_LOWER(c) ASCII_IS_LOWER(c) -#define TO_UPPER(c) ASCII_TO_UPPER(c) -#define TO_LOWER(c) ASCII_TO_LOWER(c) +#define IS_UPPER(c) ASCII_IS_UPPER(c) +#define IS_LOWER(c) ASCII_IS_LOWER(c) +#define TO_UPPER(c) ASCII_TO_UPPER(c) +#define TO_LOWER(c) ASCII_TO_LOWER(c) #endif #endif #ifdef isspace -#define IS_SPACE(c) isspace((unsigned char)(c)) +#define IS_SPACE(c) isspace((unsigned char)(c)) #else -#define IS_SPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r' || (c) == '\f') +#define IS_SPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r' || (c) == '\f') #endif #ifdef isdigit -#define IS_DIGIT(c) isdigit((unsigned char)(c)) +#define IS_DIGIT(c) isdigit((unsigned char)(c)) #else -#define IS_DIGIT(c) ((c) >= '0' && (c) <= '9') +#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) (((LWCHAR)(c)) == ESC || (((LWCHAR)(c)) == CSI)) #ifndef NULL -#define NULL 0 +#define NULL 0 #endif #ifndef TRUE -#define TRUE 1 +#define TRUE 1 #endif #ifndef FALSE -#define FALSE 0 +#define FALSE 0 #endif -#define OPT_OFF 0 -#define OPT_ON 1 -#define OPT_ONPLUS 2 +#define OPT_OFF 0 +#define OPT_ON 1 +#define OPT_ONPLUS 2 #if !HAVE_MEMCPY #ifndef memcpy -#define memcpy(to,from,len) bcopy((from),(to),(len)) +#define memcpy(to,from,len) bcopy((from),(to),(len)) #endif #endif @@ -201,7 +201,7 @@ void free(); #define SNPRINTF4(str, size, fmt, v1, v2, v3, v4) sprintf((str), (fmt), (v1), (v2), (v3), (v4)) #endif -#define BAD_LSEEK ((off_t)-1) +#define BAD_LSEEK ((off_t)-1) #ifndef SEEK_SET #define SEEK_SET 0 @@ -225,37 +225,39 @@ void free(); * Special types and constants. */ typedef unsigned long LWCHAR; -typedef off_t POSITION; -typedef off_t LINENUM; -#define MIN_LINENUM_WIDTH 7 /* Min printing width of a line number */ -#define MAX_UTF_CHAR_LEN 6 /* Max bytes in one UTF-8 char */ +typedef off_t POSITION; +typedef off_t LINENUM; +#define MIN_LINENUM_WIDTH 7 /* Default min printing width of a line number */ +#define MAX_LINENUM_WIDTH 16 /* Max width of a line number */ +#define MAX_STATUSCOL_WIDTH 4 /* Max width of the status column */ +#define MAX_UTF_CHAR_LEN 6 /* Max bytes in one UTF-8 char */ -#define NULL_POSITION ((POSITION)(-1)) +#define NULL_POSITION ((POSITION)(-1)) /* * Flags for open() */ #if MSDOS_COMPILER || OS2 -#define OPEN_READ (O_RDONLY|O_BINARY) +#define OPEN_READ (O_RDONLY|O_BINARY) #else #ifdef _OSK -#define OPEN_READ (S_IREAD) +#define OPEN_READ (S_IREAD) #else #ifdef O_RDONLY -#define OPEN_READ (O_RDONLY) +#define OPEN_READ (O_RDONLY) #else -#define OPEN_READ (0) +#define OPEN_READ (0) #endif #endif #endif #if defined(O_WRONLY) && defined(O_APPEND) -#define OPEN_APPEND (O_APPEND|O_WRONLY) +#define OPEN_APPEND (O_APPEND|O_WRONLY) #else #ifdef _OSK -#define OPEN_APPEND (S_IWRITE) +#define OPEN_APPEND (S_IWRITE) #else -#define OPEN_APPEND (1) +#define OPEN_APPEND (1) #endif #endif @@ -263,12 +265,12 @@ typedef off_t LINENUM; * Set a file descriptor to binary mode. */ #if MSDOS_COMPILER==MSOFTC -#define SET_BINARY(f) _setmode(f, _O_BINARY); +#define SET_BINARY(f) _setmode(f, _O_BINARY); #else #if MSDOS_COMPILER || OS2 -#define SET_BINARY(f) setmode(f, O_BINARY) +#define SET_BINARY(f) setmode(f, O_BINARY) #else -#define SET_BINARY(f) +#define SET_BINARY(f) #endif #endif @@ -276,18 +278,18 @@ typedef off_t LINENUM; * Does the shell treat "?" as a metacharacter? */ #if MSDOS_COMPILER || OS2 || _OSK -#define SHELL_META_QUEST 0 +#define SHELL_META_QUEST 0 #else -#define SHELL_META_QUEST 1 +#define SHELL_META_QUEST 1 #endif -#define SPACES_IN_FILENAMES 1 +#define SPACES_IN_FILENAMES 1 /* * An IFILE represents an input file. */ -#define IFILE VOID_POINTER -#define NULL_IFILE ((IFILE)NULL) +#define IFILE VOID_POINTER +#define NULL_IFILE ((IFILE)NULL) /* * The structure used to represent a "screen position". @@ -298,63 +300,65 @@ typedef off_t LINENUM; */ struct scrpos { - POSITION pos; - int ln; + POSITION pos; + int ln; }; typedef union parg { - char *p_string; - int p_int; - LINENUM p_linenum; + char *p_string; + int p_int; + LINENUM p_linenum; + char p_char; } PARG; -#define NULL_PARG ((PARG *)NULL) +#define NULL_PARG ((PARG *)NULL) struct textlist { - char *string; - char *endstring; + char *string; + char *endstring; }; struct wchar_range { - LWCHAR first, last; + LWCHAR first, last; }; struct wchar_range_table { - struct wchar_range *table; - int count; + struct wchar_range *table; + int count; }; -#define EOI (-1) +#define EOI (-1) -#define READ_INTR (-2) +#define READ_INTR (-2) /* A fraction is represented by an int n; the fraction is n/NUM_FRAC_DENOM */ -#define NUM_FRAC_DENOM 1000000 -#define NUM_LOG_FRAC_DENOM 6 +#define NUM_FRAC_DENOM 1000000 +#define NUM_LOG_FRAC_DENOM 6 /* 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 */ -#define VERY_QUIET 2 /* Never ring bell */ +#define NOT_QUIET 0 /* Ring bell at eof and for errors */ +#define LITTLE_QUIET 1 /* Ring bell only for errors */ +#define VERY_QUIET 2 /* Never ring bell */ /* How should we prompt? */ -#define PR_SHORT 0 /* Prompt with colon */ -#define PR_MEDIUM 1 /* Prompt with message */ -#define PR_LONG 2 /* Prompt with longer message */ +#define PR_SHORT 0 /* Prompt with colon */ +#define PR_MEDIUM 1 /* Prompt with message */ +#define PR_LONG 2 /* Prompt with longer message */ /* How should we handle backspaces? */ -#define BS_SPECIAL 0 /* Do special things for underlining and bold */ -#define BS_NORMAL 1 /* \b treated as normal char; actually output */ -#define BS_CONTROL 2 /* \b treated as control char; prints as ^H */ +#define BS_SPECIAL 0 /* Do special things for underlining and bold */ +#define BS_NORMAL 1 /* \b treated as normal char; actually output */ +#define BS_CONTROL 2 /* \b treated as control char; prints as ^H */ /* How should we search? */ -#define SRCH_FORW (1 << 0) /* Search forward from current position */ -#define SRCH_BACK (1 << 1) /* Search backward from current position */ +#define SRCH_FORW (1 << 0) /* Search forward from current position */ +#define SRCH_BACK (1 << 1) /* Search backward from current position */ #define SRCH_NO_MOVE (1 << 2) /* Highlight, but don't move */ +#define SRCH_INCR (1 << 3) /* Incremental search */ #define SRCH_FIND_ALL (1 << 4) /* Find and highlight all matches */ #define SRCH_NO_MATCH (1 << 8) /* Search for non-matching lines */ #define SRCH_PAST_EOF (1 << 9) /* Search past end-of-file, into next file */ @@ -362,32 +366,62 @@ struct wchar_range_table #define SRCH_NO_REGEX (1 << 12) /* Don't use regular expressions */ #define SRCH_FILTER (1 << 13) /* Search is for '&' (filter) command */ #define SRCH_AFTER_TARGET (1 << 14) /* Start search after the target line */ +#define SRCH_WRAP (1 << 15) /* Wrap-around search (continue at BOF/EOF) */ -#define SRCH_REVERSE(t) (((t) & SRCH_FORW) ? \ - (((t) & ~SRCH_FORW) | SRCH_BACK) : \ - (((t) & ~SRCH_BACK) | SRCH_FORW)) +#define SRCH_REVERSE(t) (((t) & SRCH_FORW) ? \ + (((t) & ~SRCH_FORW) | SRCH_BACK) : \ + (((t) & ~SRCH_BACK) | SRCH_FORW)) /* */ -#define NO_MCA 0 -#define MCA_DONE 1 -#define MCA_MORE 2 +#define NO_MCA 0 +#define MCA_DONE 1 +#define MCA_MORE 2 -#define CC_OK 0 /* Char was accepted & processed */ -#define CC_QUIT 1 /* Char was a request to abort current cmd */ -#define CC_ERROR 2 /* Char could not be accepted due to error */ -#define CC_PASS 3 /* Char was rejected (internal) */ +#define CC_OK 0 /* Char was accepted & processed */ +#define CC_QUIT 1 /* Char was a request to abort current cmd */ +#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 */ /* Special char bit-flags used to tell put_line() to do something special */ -#define AT_NORMAL (0) -#define AT_UNDERLINE (1 << 0) -#define AT_BOLD (1 << 1) -#define AT_BLINK (1 << 2) -#define AT_STANDOUT (1 << 3) -#define AT_ANSI (1 << 4) /* Content-supplied "ANSI" escape sequence */ -#define AT_BINARY (1 << 5) /* LESS*BINFMT representation */ -#define AT_HILITE (1 << 6) /* Internal highlights (e.g., for search) */ +#define AT_NORMAL (0) +#define AT_UNDERLINE (1 << 0) +#define AT_BOLD (1 << 1) +#define AT_BLINK (1 << 2) +#define AT_STANDOUT (1 << 3) +#define AT_ANSI (1 << 4) /* Content-supplied "ANSI" escape sequence */ +#define AT_BINARY (1 << 5) /* LESS*BINFMT representation */ +#define AT_HILITE (1 << 6) /* Internal highlights (e.g., for search) */ + +#define AT_COLOR_SHIFT 8 +#define AT_NUM_COLORS 16 +#define AT_COLOR ((AT_NUM_COLORS-1) << AT_COLOR_SHIFT) +#define AT_COLOR_ATTN (1 << AT_COLOR_SHIFT) +#define AT_COLOR_BIN (2 << AT_COLOR_SHIFT) +#define AT_COLOR_CTRL (3 << AT_COLOR_SHIFT) +#define AT_COLOR_ERROR (4 << AT_COLOR_SHIFT) +#define AT_COLOR_LINENUM (5 << AT_COLOR_SHIFT) +#define AT_COLOR_MARK (6 << AT_COLOR_SHIFT) +#define AT_COLOR_PROMPT (7 << AT_COLOR_SHIFT) +#define AT_COLOR_RSCROLL (8 << AT_COLOR_SHIFT) +#define AT_COLOR_SEARCH (9 << AT_COLOR_SHIFT) + +typedef enum { CT_NULL, CT_4BIT, CT_6BIT } COLOR_TYPE; + +typedef enum { + CV_BLUE = 1, + CV_GREEN = 2, + CV_RED = 4, + CV_BRIGHT = 8, + CV_NOCHANGE = -2, + CV_ERROR = -1 +} COLOR_VALUE; + +/* ANSI states */ +#define ANSI_MID 1 +#define ANSI_ERR 2 +#define ANSI_END 3 #if '0' == 240 #define IS_EBCDIC_HOST 1 @@ -400,76 +434,76 @@ struct wchar_range_table * into a constant. */ #define CONTROL(c) ( \ - (c)=='[' ? '\047' : \ - (c)=='a' ? '\001' : \ - (c)=='b' ? '\002' : \ - (c)=='c' ? '\003' : \ - (c)=='d' ? '\067' : \ - (c)=='e' ? '\055' : \ - (c)=='f' ? '\056' : \ - (c)=='g' ? '\057' : \ - (c)=='h' ? '\026' : \ - (c)=='i' ? '\005' : \ - (c)=='j' ? '\025' : \ - (c)=='k' ? '\013' : \ - (c)=='l' ? '\014' : \ - (c)=='m' ? '\015' : \ - (c)=='n' ? '\016' : \ - (c)=='o' ? '\017' : \ - (c)=='p' ? '\020' : \ - (c)=='q' ? '\021' : \ - (c)=='r' ? '\022' : \ - (c)=='s' ? '\023' : \ - (c)=='t' ? '\074' : \ - (c)=='u' ? '\075' : \ - (c)=='v' ? '\062' : \ - (c)=='w' ? '\046' : \ - (c)=='x' ? '\030' : \ - (c)=='y' ? '\031' : \ - (c)=='z' ? '\077' : \ - (c)=='A' ? '\001' : \ - (c)=='B' ? '\002' : \ - (c)=='C' ? '\003' : \ - (c)=='D' ? '\067' : \ - (c)=='E' ? '\055' : \ - (c)=='F' ? '\056' : \ - (c)=='G' ? '\057' : \ - (c)=='H' ? '\026' : \ - (c)=='I' ? '\005' : \ - (c)=='J' ? '\025' : \ - (c)=='K' ? '\013' : \ - (c)=='L' ? '\014' : \ - (c)=='M' ? '\015' : \ - (c)=='N' ? '\016' : \ - (c)=='O' ? '\017' : \ - (c)=='P' ? '\020' : \ - (c)=='Q' ? '\021' : \ - (c)=='R' ? '\022' : \ - (c)=='S' ? '\023' : \ - (c)=='T' ? '\074' : \ - (c)=='U' ? '\075' : \ - (c)=='V' ? '\062' : \ - (c)=='W' ? '\046' : \ - (c)=='X' ? '\030' : \ - (c)=='Y' ? '\031' : \ - (c)=='Z' ? '\077' : \ - (c)=='|' ? '\031' : \ - (c)=='\\' ? '\034' : \ - (c)=='^' ? '\036' : \ - (c)&077) + (c)=='[' ? '\047' : \ + (c)=='a' ? '\001' : \ + (c)=='b' ? '\002' : \ + (c)=='c' ? '\003' : \ + (c)=='d' ? '\067' : \ + (c)=='e' ? '\055' : \ + (c)=='f' ? '\056' : \ + (c)=='g' ? '\057' : \ + (c)=='h' ? '\026' : \ + (c)=='i' ? '\005' : \ + (c)=='j' ? '\025' : \ + (c)=='k' ? '\013' : \ + (c)=='l' ? '\014' : \ + (c)=='m' ? '\015' : \ + (c)=='n' ? '\016' : \ + (c)=='o' ? '\017' : \ + (c)=='p' ? '\020' : \ + (c)=='q' ? '\021' : \ + (c)=='r' ? '\022' : \ + (c)=='s' ? '\023' : \ + (c)=='t' ? '\074' : \ + (c)=='u' ? '\075' : \ + (c)=='v' ? '\062' : \ + (c)=='w' ? '\046' : \ + (c)=='x' ? '\030' : \ + (c)=='y' ? '\031' : \ + (c)=='z' ? '\077' : \ + (c)=='A' ? '\001' : \ + (c)=='B' ? '\002' : \ + (c)=='C' ? '\003' : \ + (c)=='D' ? '\067' : \ + (c)=='E' ? '\055' : \ + (c)=='F' ? '\056' : \ + (c)=='G' ? '\057' : \ + (c)=='H' ? '\026' : \ + (c)=='I' ? '\005' : \ + (c)=='J' ? '\025' : \ + (c)=='K' ? '\013' : \ + (c)=='L' ? '\014' : \ + (c)=='M' ? '\015' : \ + (c)=='N' ? '\016' : \ + (c)=='O' ? '\017' : \ + (c)=='P' ? '\020' : \ + (c)=='Q' ? '\021' : \ + (c)=='R' ? '\022' : \ + (c)=='S' ? '\023' : \ + (c)=='T' ? '\074' : \ + (c)=='U' ? '\075' : \ + (c)=='V' ? '\062' : \ + (c)=='W' ? '\046' : \ + (c)=='X' ? '\030' : \ + (c)=='Y' ? '\031' : \ + (c)=='Z' ? '\077' : \ + (c)=='|' ? '\031' : \ + (c)=='\\' ? '\034' : \ + (c)=='^' ? '\036' : \ + (c)&077) #else -#define CONTROL(c) ((c)&037) +#define CONTROL(c) ((c)&037) #endif /* IS_EBCDIC_HOST */ -#define ESC CONTROL('[') -#define ESCS "\33" -#define CSI ((unsigned char)'\233') -#define CHAR_END_COMMAND 0x40000000 +#define ESC CONTROL('[') +#define ESCS "\33" +#define CSI ((unsigned char)'\233') +#define CHAR_END_COMMAND 0x40000000 #if _OSK_MWC32 -#define LSIGNAL(sig,func) os9_signal(sig,func) +#define LSIGNAL(sig,func) os9_signal(sig,func) #else -#define LSIGNAL(sig,func) signal(sig,func) +#define LSIGNAL(sig,func) signal(sig,func) #endif #if HAVE_SIGPROCMASK @@ -486,41 +520,41 @@ struct wchar_range_table #endif #endif -#define S_INTERRUPT 01 -#define S_STOP 02 -#define S_WINCH 04 -#define ABORT_SIGS() (sigs & (S_INTERRUPT|S_STOP)) +#define S_INTERRUPT 01 +#define S_STOP 02 +#define S_WINCH 04 +#define ABORT_SIGS() (sigs & (S_INTERRUPT|S_STOP)) -#define QUIT_OK 0 -#define QUIT_ERROR 1 -#define QUIT_INTERRUPT 2 -#define QUIT_SAVED_STATUS (-1) +#define QUIT_OK 0 +#define QUIT_ERROR 1 +#define QUIT_INTERRUPT 2 +#define QUIT_SAVED_STATUS (-1) #define FOLLOW_DESC 0 #define FOLLOW_NAME 1 /* filestate flags */ -#define CH_CANSEEK 001 -#define CH_KEEPOPEN 002 -#define CH_POPENED 004 -#define CH_HELPFILE 010 -#define CH_NODATA 020 /* Special case for zero length files */ +#define CH_CANSEEK 001 +#define CH_KEEPOPEN 002 +#define CH_POPENED 004 +#define CH_HELPFILE 010 +#define CH_NODATA 020 /* Special case for zero length files */ -#define ch_zero() ((POSITION)0) +#define ch_zero() ((POSITION)0) -#define FAKE_HELPFILE "@/\\less/\\help/\\file/\\@" -#define FAKE_EMPTYFILE "@/\\less/\\empty/\\file/\\@" +#define FAKE_HELPFILE "@/\\less/\\help/\\file/\\@" +#define FAKE_EMPTYFILE "@/\\less/\\empty/\\file/\\@" /* Flags for cvt_text */ -#define CVT_TO_LC 01 /* Convert upper-case to lower-case */ -#define CVT_BS 02 /* Do backspace processing */ -#define CVT_CRLF 04 /* Remove CR after LF */ -#define CVT_ANSI 010 /* Remove ANSI escape sequences */ +#define CVT_TO_LC 01 /* Convert upper-case to lower-case */ +#define CVT_BS 02 /* Do backspace processing */ +#define CVT_CRLF 04 /* Remove CR after LF */ +#define CVT_ANSI 010 /* Remove ANSI escape sequences */ #if HAVE_TIME_T -#define time_type time_t +#define time_type time_t #else -#define time_type long +#define time_type long #endif /* X11 mouse reporting definitions */ @@ -535,6 +569,7 @@ struct wchar_range_table struct mlist; struct loption; struct hilite_tree; +struct ansi_state; #include "pattern.h" #include "funcs.h" diff --git a/less.hlp b/less.hlp index a8f78adcdd7f..1e1ebf447711 100644 --- a/less.hlp +++ b/less.hlp @@ -42,7 +42,8 @@ ESC-n * Repeat previous search, spanning files. ESC-N * Repeat previous search, reverse dir. & spanning files. ESC-u Undo (toggle) search highlighting. - &_p_a_t_t_e_r_n * Display only matching lines + ESC-U Clear search highlighting. + &_p_a_t_t_e_r_n * Display only matching lines. --------------------------------------------------- A search pattern may begin with one or more of: ^N or ! Search for NON-matching lines. @@ -50,6 +51,7 @@ ^F or @ Start search at FIRST file (for /) or last file (for ?). ^K Highlight matches, but don't move (KEEP position). ^R Don't use REGULAR EXPRESSIONS. + ^W WRAP search if no match found. --------------------------------------------------------------------------- JJUUMMPPIINNGG @@ -62,7 +64,7 @@ { ( [ * Find close bracket } ) ]. } ) ] * Find open bracket { ( [. ESC-^F _<_c_1_> _<_c_2_> * Find close bracket _<_c_2_>. - ESC-^B _<_c_1_> _<_c_2_> * Find open bracket _<_c_1_> + ESC-^B _<_c_1_> _<_c_2_> * Find open bracket _<_c_1_>. --------------------------------------------------- Each "find close bracket" command goes forward to the close bracket matching the (_N-th) open bracket in the top line. @@ -129,8 +131,8 @@ Repaint by clearing rather than scrolling. -d ........ --dumb Dumb terminal. - -D [_x_n_._n] . --color=_x_n_._n - Set screen colors. (MS-DOS only) + -D xx_c_o_l_o_r . --color=xx_c_o_l_o_r + Set screen colors. -e -E .... --quit-at-eof --QUIT-AT-EOF Quit at end of file. -f ........ --force @@ -202,9 +204,13 @@ -~ ........ --tilde Don't display tildes after end of file. -# [_N] .... --shift=[_N] - Horizontal scroll amount (0 = one half screen width) + Set horizontal scroll amount (0 = one half screen width). --follow-name The F command changes files if the input file is renamed. + --incsearch + Search file as each pattern character is typed in. + --line-num-width=N + Set the width of the -N line number field to N characters. --mouse Enable mouse input. --no-keypad @@ -215,8 +221,12 @@ Set the character used to mark truncated lines. --save-marks Retain marks across invocations of less. + --status-col-width=N + Set the width of the -J status column to N characters. --use-backslash Subsequent options use backslash as escape char. + --use-color + Enables colored text. --wheel-lines=N Each click of the mouse wheel moves N lines. @@ -244,5 +254,3 @@ TAB ...................................... Complete filename & cycle. SHIFT-TAB ...................... ESC-TAB Complete filename & reverse cycle. ctrl-L ................................... Complete filename, list all. - - diff --git a/less.man b/less.man index 39656a2c17c6..5556488be6fa 100644 --- a/less.man +++ b/less.man @@ -107,17 +107,20 @@ LESS(1) General Commands Manual LESS(1) r or ^R or ^L Repaint the screen. - R Repaint the screen, discarding any buffered input. Useful if - the file is changing while it is being viewed. + R Repaint the screen, discarding any buffered input. That is, + reload the current file. Useful if the file is changing while + it is being viewed. - F Scroll forward, and keep trying to read when the end of file is - reached. Normally this command would be used when already at - the end of the file. It is a way to monitor the tail of a file - which is growing while it is being viewed. (The behavior is - similar to the "tail -f" command.) + F Scroll forward, and keep trying to read when the end of file is + reached. Normally this command would be used when already at + the end of the file. It is a way to monitor the tail of a file + which is growing while it is being viewed. (The behavior is + similar to the "tail -f" command.) To stop waiting for more + data, enter the interrupt character (usually ^C). On some sys- + tems you can also use ^X. - ESC-F Like F, but as soon as a line is found which matches the last - search pattern, the terminal bell is rung and forward scrolling + ESC-F Like F, but as soon as a line is found which matches the last + search pattern, the terminal bell is rung and forward scrolling stops. g or < or ESC-< @@ -125,12 +128,12 @@ LESS(1) General Commands Manual LESS(1) ing: this may be slow if N is large.) G or > or ESC-> - Go to line N in the file, default the end of the file. (Warn- - ing: this may be slow if N is large, or if N is not specified + Go to line N in the file, default the end of the file. (Warn- + ing: this may be slow if N is large, or if N is not specified and standard input, rather than a file, is being read.) - ESC-G Same as G, except if no number N is specified and the input is - standard input, goes to the last line which is currently + ESC-G Same as G, except if no number N is specified and the input is + standard input, goes to the last line which is currently buffered. p or % Go to a position N percent into the file. N should be between 0 @@ -139,93 +142,98 @@ LESS(1) General Commands Manual LESS(1) P Go to the line containing byte offset N in the file. { If a left curly bracket appears in the top line displayed on the - screen, the { command will go to the matching right curly - bracket. The matching right curly bracket is positioned on the + screen, the { command will go to the matching right curly + bracket. The matching right curly bracket is positioned on the bottom line of the screen. If there is more than one left curly - bracket on the top line, a number N may be used to specify the + bracket on the top line, a number N may be used to specify the N-th bracket on the line. } If a right curly bracket appears in the bottom line displayed on - the screen, the } command will go to the matching left curly - bracket. The matching left curly bracket is positioned on the - top line of the screen. If there is more than one right curly - bracket on the top line, a number N may be used to specify the + the screen, the } command will go to the matching left curly + bracket. The matching left curly bracket is positioned on the + top line of the screen. If there is more than one right curly + bracket on the top line, a number N may be used to specify the N-th bracket on the line. ( Like {, but applies to parentheses rather than curly brackets. ) Like }, but applies to parentheses rather than curly brackets. - [ Like {, but applies to square brackets rather than curly brack- + [ Like {, but applies to square brackets rather than curly brack- ets. - ] Like }, but applies to square brackets rather than curly brack- + ] Like }, but applies to square brackets rather than curly brack- ets. - ESC-^F Followed by two characters, acts like {, but uses the two char- - acters as open and close brackets, respectively. For example, - "ESC ^F < >" could be used to go forward to the > which matches + ESC-^F Followed by two characters, acts like {, but uses the two char- + acters as open and close brackets, respectively. For example, + "ESC ^F < >" could be used to go forward to the > which matches the < in the top displayed line. - ESC-^B Followed by two characters, acts like }, but uses the two char- - acters as open and close brackets, respectively. For example, + ESC-^B Followed by two characters, acts like }, but uses the two char- + acters as open and close brackets, respectively. For example, "ESC ^B < >" could be used to go backward to the < which matches the > in the bottom displayed line. - m Followed by any lowercase or uppercase letter, marks the first - displayed line with that letter. If the status column is en- - abled via the -J option, the status column shows the marked + m Followed by any lowercase or uppercase letter, marks the first + displayed line with that letter. If the status column is en- + abled via the -J option, the status column shows the marked line. - M Acts like m, except the last displayed line is marked rather + M Acts like m, except the last displayed line is marked rather than the first displayed line. - ' (Single quote.) Followed by any lowercase or uppercase letter, - returns to the position which was previously marked with that - letter. Followed by another single quote, returns to the posi- - tion at which the last "large" movement command was executed. - Followed by a ^ or $, jumps to the beginning or end of the file - respectively. Marks are preserved when a new file is examined, + ' (Single quote.) Followed by any lowercase or uppercase letter, + returns to the position which was previously marked with that + letter. Followed by another single quote, returns to the posi- + tion at which the last "large" movement command was executed. + Followed by a ^ or $, jumps to the beginning or end of the file + respectively. Marks are preserved when a new file is examined, so the ' command can be used to switch between input files. ^X^X Same as single quote. - ESC-m Followed by any lowercase or uppercase letter, clears the mark + ESC-m Followed by any lowercase or uppercase letter, clears the mark identified by that letter. /pattern Search forward in the file for the N-th line containing the pat- tern. N defaults to 1. The pattern is a regular expression, as - recognized by the regular expression library supplied by your - system. The search starts at the first line displayed (but see + recognized by the regular expression library supplied by your + system. The search starts at the first line displayed (but see the -a and -j options, which change this). - Certain characters are special if entered at the beginning of - the pattern; they modify the type of search rather than become + Certain characters are special if entered at the beginning of + the pattern; they modify the type of search rather than become part of the pattern: ^N or ! Search for lines which do NOT match the pattern. ^E or * - Search multiple files. That is, if the search reaches - the END of the current file without finding a match, the - search continues in the next file in the command line + Search multiple files. That is, if the search reaches + the END of the current file without finding a match, the + search continues in the next file in the command line list. ^F or @ - Begin the search at the first line of the FIRST file in - the command line list, regardless of what is currently - displayed on the screen or the settings of the -a or -j + Begin the search at the first line of the FIRST file in + the command line list, regardless of what is currently + displayed on the screen or the settings of the -a or -j options. - ^K Highlight any text which matches the pattern on the cur- + ^K Highlight any text which matches the pattern on the cur- rent screen, but don't move to the first match (KEEP cur- rent position). - ^R Don't interpret regular expression metacharacters; that + ^R Don't interpret regular expression metacharacters; that is, do a simple textual comparison. + ^W WRAP around the current file. That is, if the search + reaches the end of the current file without finding a + match, the search continues from the first line of the + current file up to the line where it started. + ?pattern Search backward in the file for the N-th line containing the pattern. The search starts at the last line displayed (but see @@ -252,141 +260,152 @@ LESS(1) General Commands Manual LESS(1) ^R As in forward searches. + ^W 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. + ESC-/pattern Same as "/*". ESC-?pattern Same as "?*". - n Repeat previous search, for N-th line containing the last pat- - tern. If the previous search was modified by ^N, the search is - made for the N-th line NOT containing the pattern. If the pre- - vious search was modified by ^E, the search continues in the - next (or previous) file if not satisfied in the current file. - If the previous search was modified by ^R, the search is done - without using regular expressions. There is no effect if the + n Repeat previous search, for N-th line containing the last pat- + tern. If the previous search was modified by ^N, the search is + made for the N-th line NOT containing the pattern. If the pre- + vious search was modified by ^E, the search continues in the + next (or previous) file if not satisfied in the current file. + If the previous search was modified by ^R, the search is done + without using regular expressions. There is no effect if the previous search was modified by ^F or ^K. N Repeat previous search, but in the reverse direction. - ESC-n Repeat previous search, but crossing file boundaries. The ef- + ESC-n Repeat previous search, but crossing file boundaries. The ef- fect is as if the previous search were modified by *. - ESC-N Repeat previous search, but in the reverse direction and cross- + ESC-N Repeat previous search, but in the reverse direction and cross- ing file boundaries. - ESC-u Undo search highlighting. Turn off highlighting of strings + ESC-u Undo search highlighting. Turn off highlighting of strings matching the current search pattern. If highlighting is already - off because of a previous ESC-u command, turn highlighting back - on. Any search command will also turn highlighting back on. + off because of a previous ESC-u command, turn highlighting back + on. Any search command will also turn highlighting back on. (Highlighting can also be disabled by toggling the -G option; in that case search commands do not turn highlighting back on.) + ESC-U Like ESC-u but also clears the saved search pattern. If the + status column is enabled via the -J option, this clears all + search matches marked in the status column. + &pattern - Display only lines which match the pattern; lines which do not - match the pattern are not displayed. If pattern is empty (if - you type & immediately followed by ENTER), any filtering is - turned off, and all lines are displayed. While filtering is in - effect, an ampersand is displayed at the beginning of the + Display only lines which match the pattern; lines which do not + match the pattern are not displayed. If pattern is empty (if + you type & immediately followed by ENTER), any filtering is + turned off, and all lines are displayed. While filtering is in + effect, an ampersand is displayed at the beginning of the prompt, as a reminder that some lines in the file may be hidden. + Multiple & commands may be entered, in which case only lines + which match all of the patterns will be displayed. Certain characters are special as in the / command: ^N or ! Display only lines which do NOT match the pattern. - ^R Don't interpret regular expression metacharacters; that + ^R Don't interpret regular expression metacharacters; that is, do a simple textual comparison. :e [filename] - Examine a new file. If the filename is missing, the "current" - file (see the :n and :p commands below) from the list of files - in the command line is re-examined. A percent sign (%) in the - filename is replaced by the name of the current file. A pound - sign (#) is replaced by the name of the previously examined - file. However, two consecutive percent signs are simply re- - placed with a single percent sign. This allows you to enter a - filename that contains a percent sign in the name. Similarly, - two consecutive pound signs are replaced with a single pound - sign. The filename is inserted into the command line list of - files so that it can be seen by subsequent :n and :p commands. + Examine a new file. If the filename is missing, the "current" + file (see the :n and :p commands below) from the list of files + in the command line is re-examined. A percent sign (%) in the + filename is replaced by the name of the current file. A pound + sign (#) is replaced by the name of the previously examined + file. However, two consecutive percent signs are simply re- + placed with a single percent sign. This allows you to enter a + filename that contains a percent sign in the name. Similarly, + two consecutive pound signs are replaced with a single pound + sign. The filename is inserted into the command line list of + files so that it can be seen by subsequent :n and :p commands. If the filename consists of several files, they are all inserted - into the list of files and the first one is examined. If the + into the list of files and the first one is examined. If the filename contains one or more spaces, the entire filename should be enclosed in double quotes (also see the -" option). ^X^V or E - Same as :e. Warning: some systems use ^V as a special literal- - ization character. On such systems, you may not be able to use + Same as :e. Warning: some systems use ^V as a special literal- + ization character. On such systems, you may not be able to use ^V. - :n Examine the next file (from the list of files given in the com- - mand line). If a number N is specified, the N-th next file is + :n Examine the next file (from the list of files given in the com- + mand line). If a number N is specified, the N-th next file is examined. :p Examine the previous file in the command line list. If a number N is specified, the N-th previous file is examined. - :x Examine the first file in the command line list. If a number N + :x Examine the first file in the command line list. If a number N is specified, the N-th file in the list is examined. :d Remove the current file from the list of files. - t Go to the next tag, if there were more than one matches for the + t Go to the next tag, if there were more than one matches for the current tag. See the -t option for more details about tags. - T Go to the previous tag, if there were more than one matches for + T Go to the previous tag, if there were more than one matches for the current tag. = or ^G or :f - Prints some information about the file being viewed, including - its name and the line number and byte offset of the bottom line - being displayed. If possible, it also prints the length of the - file, the number of lines in the file and the percent of the + Prints some information about the file being viewed, including + its name and the line number and byte offset of the bottom line + being displayed. If possible, it also prints the length of the + file, the number of lines in the file and the percent of the file above the last displayed line. - - Followed by one of the command line option letters (see OPTIONS - below), this will change the setting of that option and print a - message describing the new setting. If a ^P (CONTROL-P) is en- - tered immediately after the dash, the setting of the option is - changed but no message is printed. If the option letter has a - numeric value (such as -b or -h), or a string value (such as -P - or -t), a new value may be entered after the option letter. If - no new value is entered, a message describing the current set- + - Followed by one of the command line option letters (see OPTIONS + below), this will change the setting of that option and print a + message describing the new setting. If a ^P (CONTROL-P) is en- + tered immediately after the dash, the setting of the option is + changed but no message is printed. If the option letter has a + numeric value (such as -b or -h), or a string value (such as -P + or -t), a new value may be entered after the option letter. If + no new value is entered, a message describing the current set- ting is printed and nothing is changed. - -- Like the - command, but takes a long option name (see OPTIONS + -- 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. A ^P immediately after - the second dash suppresses printing of a message describing the + or RETURN after typing the option name. A ^P immediately after + the second dash suppresses printing of a message describing the new setting, as in the - command. -+ Followed by one of the command line option letters this will re- - set the option to its default setting and print a message de- - scribing the new setting. (The "-+X" command does the same - thing as "-+X" on the command line.) This does not work for + set the option to its default setting and print a message de- + scribing the new setting. (The "-+X" command does the same + thing as "-+X" on the command line.) This does not work for string-valued options. - --+ Like the -+ command, but takes a long option name rather than a + --+ Like the -+ command, but takes a long option name rather than a single option letter. - -! Followed by one of the command line option letters, this will - reset the option to the "opposite" of its default setting and - print a message describing the new setting. This does not work + -! Followed by one of the command line option letters, this will + reset the option to the "opposite" of its default setting and + print a message describing the new setting. This does not work for numeric or string-valued options. - --! Like the -! command, but takes a long option name rather than a + --! Like the -! command, but takes a long option name rather than a single option letter. - _ (Underscore.) Followed by one of the command line option let- - ters, this will print a message describing the current setting + _ (Underscore.) Followed by one of the command line option let- + ters, this will print a message describing the current setting of that option. The setting of the option is not changed. __ (Double underscore.) Like the _ (underscore) command, but takes a long option name rather than a single option letter. You must press ENTER or RETURN after typing the option name. - +cmd Causes the specified cmd to be executed each time a new file is + +cmd Causes the specified cmd to be executed each time a new file is examined. For example, +G causes less to initially display each file starting at the end rather than the beginning. @@ -395,51 +414,51 @@ LESS(1) General Commands Manual LESS(1) q or Q or :q or :Q or ZZ Exits less. - The following four commands may or may not be valid, depending on your + The following four commands may or may not be valid, depending on your particular installation. - v Invokes an editor to edit the current file being viewed. The + v Invokes an editor to edit the current file being viewed. The editor is taken from the environment variable VISUAL if defined, - or EDITOR if VISUAL is not defined, or defaults to "vi" if nei- - ther VISUAL nor EDITOR is defined. See also the discussion of + or EDITOR if VISUAL is not defined, or defaults to "vi" if nei- + ther VISUAL nor EDITOR is defined. See also the discussion of LESSEDIT under the section on PROMPTS below. ! shell-command - Invokes a shell to run the shell-command given. A percent sign - (%) in the command is replaced by the name of the current file. + Invokes a shell to run the shell-command given. 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 exam- - ined file. "!!" repeats the last shell command. "!" with no - shell command simply invokes a shell. On Unix systems, the - shell is taken from the environment variable SHELL, or defaults - to "sh". On MS-DOS and OS/2 systems, the shell is the normal + ined file. "!!" repeats the last shell command. "!" with no + shell command simply invokes a shell. On Unix systems, the + shell is taken from the environment variable SHELL, or defaults + to "sh". On MS-DOS and OS/2 systems, the shell is the normal command processor. | shell-command - represents any mark letter. Pipes a section of the input - file to the given shell command. The section of the file to be - piped is between the position marked by the letter and the cur- - rent screen. The entire current screen is included, regardless - of whether the marked position is before or after the current - screen. may also be ^ or $ to indicate beginning or end of - file respectively. If is . or newline, the current screen + represents any mark letter. Pipes a section of the input + file to the given shell command. The section of the file to be + piped is between the position marked by the letter and the cur- + rent screen. The entire current screen is included, regardless + of whether the marked position is before or after the current + screen. may also be ^ or $ to indicate beginning or end of + file respectively. If is . or newline, the current screen is piped. s filename - Save the input to a file. This only works if the input is a + Save the input to a file. This only works if the input is a pipe, not an ordinary file. OPTIONS - Command line options are described below. Most options may be changed + Command line options are described below. Most options may be changed while less is running, via the "-" command. - Most options may be given in one of two forms: 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 un- - ambiguous. For example, --quit-at-eof may be abbreviated --quit, but + Most options may be given in one of two forms: 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 un- + ambiguous. For example, --quit-at-eof may be abbreviated --quit, but not --qui, since both --quit-at-eof and --quiet begin with --qui. 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 let- - ter capitalized; the remainder of the name may be in either case. For + 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 let- + ter capitalized; the remainder of the name may be in either case. For example, --Quit-at-eof is equivalent to --QUIT-AT-EOF. Options are also taken from the environment variable "LESS". For exam- @@ -452,76 +471,76 @@ LESS(1) General Commands Manual LESS(1) LESS="-options"; export LESS - On MS-DOS, you don't need the quotes, but you should replace any per- + On MS-DOS, you don't need the quotes, but you should replace any per- cent signs in the options string by double percent signs. - The environment variable is parsed before the command line, so command - line options override the LESS environment variable. If an option ap- + The environment variable is parsed before the command line, so command + line options override the LESS environment variable. If an option ap- pears in the LESS variable, it can be reset to its default value on the command line by beginning the command line option with "-+". - Some options like -k or -D require a string to follow the option let- - ter. The string for that option is considered to end when a dollar - sign ($) is found. For example, you can set two -D options on MS-DOS + Some options like -k or -D require a string to follow the option let- + ter. The string for that option is considered to end when a dollar + sign ($) is found. For example, you can set two -D options on MS-DOS like this: LESS="Dn9.1$Ds4.1" - If the --use-backslash option appears earlier in the options, then a - dollar sign or backslash may be included literally in an option string + If the --use-backslash option appears earlier in the options, then a + dollar sign or backslash may be included literally in an option string by preceding it with a backslash. If the --use-backslash option is not - in effect, then backslashes are not treated specially, and there is no + in effect, then backslashes are not treated specially, and there is no way to include a dollar sign in the option string. -? or --help - This option displays a summary of the commands accepted by less - (the same as the h command). (Depending on how your shell in- - terprets the question mark, it may be necessary to quote the + This option displays a summary of the commands accepted by less + (the same as the h command). (Depending on how your shell in- + terprets the question mark, it may be necessary to quote the question mark, thus: "-\?".) -a or --search-skip-screen - By default, forward searches start at the top of the displayed - screen and backwards searches start at the bottom of the dis- - played screen (except for repeated searches invoked by the n or - N commands, which start after or before the "target" line re- - spectively; see the -j option for more about the target line). - The -a option causes forward searches to instead start at the - bottom of the screen and backward searches to start at the top + By default, forward searches start at the top of the displayed + screen and backwards searches start at the bottom of the dis- + played screen (except for repeated searches invoked by the n or + N commands, which start after or before the "target" line re- + spectively; see the -j option for more about the target line). + The -a option causes forward searches to instead start at the + bottom of the screen and backward searches to start at the top of the screen, thus skipping all lines displayed on the screen. -A or --SEARCH-SKIP-SCREEN - Causes all forward searches (not just non-repeated searches) to - start just after the target line, and all backward searches to - start just before the target line. Thus, forward searches will + Causes all forward searches (not just non-repeated searches) to + start just after the target line, and all backward searches to + start just before the target line. Thus, forward searches will skip part of the displayed screen (from the first line up to and - including the target line). Similarly backwards searches will + including the target line). Similarly backwards searches will skip the displayed screen from the last line up to and including the target line. This was the default behavior in less versions prior to 441. -bn or --buffers=n - Specifies the amount of buffer space less will use for each - file, in units of kilobytes (1024 bytes). By default 64 KB of - buffer space is used for each file (unless the file is a pipe; - see the -B option). The -b option specifies instead that n + Specifies the amount of buffer space less will use for each + file, in units of kilobytes (1024 bytes). By default 64 KB of + buffer space is used for each file (unless the file is a pipe; + see the -B option). The -b option specifies instead that n kilobytes of buffer space should be used for each file. If n is - -1, buffer space is unlimited; that is, the entire file can be + -1, buffer space is unlimited; that is, the entire file can be read into memory. -B or --auto-buffers By default, when data is read from a pipe, buffers are allocated automatically as needed. If a large amount of data is read from - the pipe, this can cause a large amount of memory to be allo- + the pipe, this can cause a large amount of memory to be allo- cated. The -B option disables this automatic allocation of buf- fers for pipes, so that only 64 KB (or the amount of space spec- - ified by the -b option) is used for the pipe. Warning: use of + ified by the -b option) is used for the pipe. Warning: use of -B can result in erroneous display, since only the most recently - viewed part of the piped data is kept in memory; any earlier + viewed part of the piped data is kept in memory; any earlier data is lost. -c or --clear-screen - Causes full screen repaints to be painted from the top line - down. By default, full screen repaints are done by scrolling + Causes full screen repaints to be painted from the top line + down. By default, full screen repaints are done by scrolling from the bottom of the screen. -C or --CLEAR-SCREEN @@ -529,26 +548,104 @@ LESS(1) General Commands Manual LESS(1) -d or --dumb The -d option suppresses the error message normally displayed if - the terminal is dumb; that is, lacks some important capability, + the terminal is dumb; that is, lacks some important capability, such as the ability to clear the screen or scroll backward. The - -d option does not otherwise change the behavior of less on a + -d option does not otherwise change the behavior of less on a dumb terminal. -Dxcolor or --color=xcolor - [MS-DOS only] Sets the color of the text displayed. x is a sin- - gle character which selects the type of text whose color is be- - ing set: n=normal, s=standout, d=bold, u=underlined, k=blink. - color is a pair of numbers separated by a period. The first - number selects the foreground color and the second selects the - background color of the text. A single number N is the same as - N.M, where M is the normal background color. The color may - start or end with u to use underline (with the normal color, if - by itself), if the system supports it (Windows only). x may - also be a to toggle strict ANSI sequence rendering (SGR mode). + Changes the color of different parts of the displayed text. x + is a single character which selects the type of text whose color + is being set: + + B Binary characters. + + C Control characters. + + E Errors and informational messages. + + M Mark letters in the status column. + + N Line numbers enabled via the -N option. + + P Prompts. + + R The rscroll character. + + S Search results. + + W The highlight enabled via the -w option. + + d Bold text. + + k Blinking text. + + s Standout text. + + u Underlined text. + + The uppercase letters can be used only when the --use-color op- + tion is enabled. When text color is specified by both an upper- + case letter and a lowercase letter, the uppercase letter takes + precedence. For example, error messages are normally displayed + as standout text. So if both "s" and "E" are given a color, the + "E" color applies to error messages, and the "s" color applies + to other standout text. The "d" and "u" letters refer to bold + and underline text formed by overstriking with backspaces (see + the -u option), not to text using ANSI escape sequences with the + -R option. + + A lowercase letter may be followed by a + to indicate that both + the normal format change and the specified color should both be + used. For example, -Dug displays underlined text as green with- + out underlining; the green color has replaced the usual under- + line formatting. But -Du+g displays underlined text as both + green and in underlined format. + + color is either a 4-bit color string or an 8-bit color string: + + A 4-bit color string is zero, one or two characters, where the + first character specifies the foreground color and the second + specifies the background color as follows: + + b Blue + + c Cyan + + g Green + + k Black + + m Magenta + + r Red + + w White + + y Yellow + + The corresponding upper-case letter denotes a brighter shade of + the color. For example, -DNGk displays line numbers as bright + green text on a black background, and -DEbR displays error mes- + sages as blue text on a bright red background. If either char- + acter is a "-" or is omitted, the corresponding color is set to + that of normal text. + + An 8-bit color string is one or two decimal integers separated + by a dot, 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 + https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters) + If either integer is a "-" or is omitted, the corresponding col- + or is set to that of normal text. On MS-DOS versions of less, + 8-bit color is not supported; instead, decimal values are inter- + preted as 4-bit CHAR_INFO.Attributes values (see + https://docs.microsoft.com/en-us/windows/console/char-info-str). -e or --quit-at-eof - Causes less to automatically exit the second time it reaches - end-of-file. By default, the only way to exit less is via the + Causes less to automatically exit the second time it reaches + end-of-file. By default, the only way to exit less is via the "q" command. -E or --QUIT-AT-EOF @@ -557,7 +654,7 @@ LESS(1) General Commands Manual LESS(1) -f or --force Forces non-regular files to be opened. (A non-regular file is a - directory or a device special file.) Also suppresses the warn- + directory or a device special file.) Also suppresses the warn- ing message when a binary file is opened. By default, less will refuse to open non-regular files. Note that some operating sys- tems will not allow directories to be read, even if -f is set. @@ -567,63 +664,62 @@ LESS(1) General Commands Manual LESS(1) played on the first screen. -g or --hilite-search - Normally, less will highlight ALL strings which match the last - search command. The -g option changes this behavior to high- - light only the particular string which was found by the last + Normally, less will highlight ALL strings which match the last + search command. The -g option changes this behavior to high- + light only the particular string which was found by the last search command. This can cause less to run somewhat faster than the default. -G or --HILITE-SEARCH - The -G option suppresses all highlighting of strings found by + The -G option suppresses all highlighting of strings found by search commands. -hn or --max-back-scroll=n - Specifies a maximum number of lines to scroll backward. If it + Specifies a maximum number of lines to scroll backward. If it is necessary to scroll backward more than n lines, the screen is repainted in a forward direction instead. (If the terminal does not have the ability to scroll backward, -h0 is implied.) -i or --ignore-case Causes searches to ignore case; that is, uppercase and lowercase - are considered identical. This option is ignored if any upper- - case letters appear in the search pattern; in other words, if a - pattern contains uppercase letters, then that search does not + are considered identical. This option is ignored if any upper- + case letters appear in the search pattern; in other words, if a + pattern contains uppercase letters, then that search does not ignore case. -I or --IGNORE-CASE - Like -i, but searches ignore case even if the pattern contains + Like -i, but searches ignore case even if the pattern contains uppercase letters. -jn or --jump-target=n - Specifies a line on the screen where the "target" line is to be - positioned. The target line is the line specified by any com- - mand to search for a pattern, jump to a line number, jump to a + Specifies a line on the screen where the "target" line is to be + positioned. The target line is the line specified by any com- + mand to search for a pattern, jump to a line number, jump to a file percentage or jump to a tag. The screen line may be speci- - fied by a number: the top line on the screen is 1, the next is + fied by a number: the top line on the screen is 1, the next is 2, and so on. The number may be negative to specify a line rel- ative to the bottom of the screen: the bottom line on the screen - is -1, the second to the bottom is -2, and so on. Alternately, - the screen line may be specified as a fraction of the height of - the screen, starting with a decimal point: .5 is in the middle - of the screen, .3 is three tenths down from the first line, and - so on. If the line is specified as a fraction, the actual line - number is recalculated if the terminal window is resized, so - that the target line remains at the specified fraction of the - screen height. If any form of the -j option is used, repeated + is -1, the second to the bottom is -2, and so on. Alternately, + the screen line may be specified as a fraction of the height of + the screen, starting with a decimal point: .5 is in the middle + of the screen, .3 is three tenths down from the first line, and + so on. If the line is specified as a fraction, the actual line + number is recalculated if the terminal window is resized, so + that the target line remains at the specified fraction of the + screen height. If any form of the -j option is used, repeated forward searches (invoked with "n" or "N") begin at the line im- - mediately after the target line, and repeated backward searches + mediately after the target line, and repeated backward searches begin at the target line, unless changed by -a or -A. For exam- ple, if "-j4" is used, the target line is the fourth line on the - screen, so forward searches begin at the fifth line on the - screen. However nonrepeated searches (invoked with "/" or "?") - always begin at the start or end of the current screen respec- + screen, so forward searches begin at the fifth line on the + screen. However nonrepeated searches (invoked with "/" or "?") + always begin at the start or end of the current screen respec- tively. -J or --status-column - Displays a status column at the left edge of the screen. The - status column shows the lines that matched the current search, - and any lines that are marked (via the m or M command). The - status column is also used if the -w or -W option is in effect. + Displays a status column at the left edge of the screen. The + status column shows the lines that matched the current search, + and any lines that are marked (via the m or M command). -kfilename or --lesskey-file=filename Causes less to open and interpret the named file as a lesskey(1) @@ -727,84 +823,101 @@ LESS(1) General Commands Manual LESS(1) play problems may result, such as long lines being split in the wrong place. + USE OF THE -r OPTION IS NOT RECOMMENDED. + -R or --RAW-CONTROL-CHARS - Like -r, but only ANSI "color" escape sequences are output in - "raw" form. Unlike -r, the screen appearance is maintained cor- - rectly in most cases. ANSI "color" escape sequences are se- - quences of the form: + Like -r, but only ANSI "color" escape sequences and OSC 8 hyper- + link 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 es- + cape sequences are assumed to not move the cursor. + + OSC 8 hyperlinks are sequences of the form: + + ESC ] 8 ; ... \7 + + The terminating sequence may be either a BEL character (\7) or + the two-character sequence "ESC \". + + ANSI color escape sequences are sequences of the form: ESC [ ... m - where the "..." is zero or more color specification characters - For the purpose of keeping track of screen appearance, ANSI - color escape sequences are assumed to not move the cursor. You - can make less think that characters other than "m" can end ANSI - color escape sequences by setting the environment variable + where the "..." is zero or more color specification characters. + You can make less think that characters other than "m" can end + ANSI color escape sequences by setting the environment variable LESSANSIENDCHARS to the list of characters which can end a color - escape sequence. And you can make less think that characters - other than the standard ones may appear between the ESC and the - m by setting the environment variable LESSANSIMIDCHARS to the + escape sequence. And you can make less 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. -s or --squeeze-blank-lines - Causes consecutive blank lines to be squeezed into a single + Causes consecutive blank lines to be squeezed into a single blank line. This is useful when viewing nroff output. -S or --chop-long-lines - Causes lines longer than the screen width to be chopped (trun- + Causes lines longer than the screen width to be chopped (trun- cated) rather than wrapped. That is, the portion of a long line that does not fit in the screen width is not displayed until you - press RIGHT-ARROW. The default is to wrap long lines; that is, + press RIGHT-ARROW. The default is to wrap long lines; that is, display the remainder on the next line. -ttag or --tag=tag The -t option, followed immediately by a TAG, will edit the file - containing that tag. For this to work, tag information must be - available; for example, there may be a file in the current di- + containing that tag. For this to work, tag information must be + available; for example, there may be a file in the current di- rectory called "tags", which was previously built by ctags(1) or an equivalent command. If the environment variable LESSGLOBALT- - AGS is set, it is taken to be the name of a command compatible - with global(1), and that command is executed to find the tag. + AGS is set, it is taken to be the name of a command compatible + with global(1), and that command is executed to find the tag. (See http://www.gnu.org/software/global/global.html). The -t - option may also be specified from within less (using the - com- - mand) as a way of examining a new file. The command ":t" is + option may also be specified from within less (using the - com- + mand) as a way of examining a new file. The command ":t" is equivalent to specifying -t from within less. -Ttagsfile or --tag-file=tagsfile Specifies a tags file to be used instead of "tags". -u or --underline-special - Causes backspaces and carriage returns to be treated as print- - able characters; that is, they are sent to the terminal when + Causes backspaces and carriage returns to be treated as print- + able characters; that is, they are sent to the terminal when they appear in the input. -U or --UNDERLINE-SPECIAL - Causes backspaces, tabs, carriage returns and "formatting char- + Causes backspaces, tabs, carriage returns and "formatting char- acters" (as defined by Unicode) to be treated as control charac- ters; that is, they are handled as specified by the -r option. - By default, if neither -u nor -U is given, backspaces which ap- - pear adjacent to an underscore character are treated specially: - the underlined text is displayed using the terminal's hardware - underlining capability. Also, backspaces which appear between - two identical characters are treated specially: the overstruck - text is printed using the terminal's hardware boldface capabil- - ity. Other backspaces are deleted, along with the preceding - character. Carriage returns immediately followed by a newline + By default, if neither -u nor -U is given, backspaces which ap- + pear adjacent to an underscore character are treated specially: + the underlined text is displayed using the terminal's hardware + underlining capability. Also, backspaces which appear between + two identical characters are treated specially: the overstruck + text is printed using the terminal's hardware boldface capabili- + ty. Other backspaces are deleted, along with the preceding + character. Carriage returns immediately followed by a newline are deleted. Other carriage returns are handled as specified by - the -r option. Text which is overstruck or underlined can be - searched for if neither -u nor -U is in effect. + the -r option. Unicode formatting characters, such as the Byte + Order Mark, are sent to the terminal. Text which is overstruck + or underlined can be searched for if neither -u nor -U is in ef- + fect. -V or --version Displays the version number of less. -w or --hilite-unread - Temporarily highlights the first "new" line after a forward + Temporarily highlights the first "new" line after a forward movement of a full page. The first "new" line is the line imme- - diately following the line previously at the bottom of the + diately following the line previously at the bottom of the screen. Also highlights the target line after a g or p command. - The highlight is removed at the next command which causes move- - ment. The entire line is highlighted, unless the -J option is + The highlight is removed at the next command which causes move- + ment. The entire line is highlighted, unless the -J option is in effect, in which case only the status column is highlighted. -W or --HILITE-UNREAD @@ -812,48 +925,48 @@ LESS(1) General Commands Manual LESS(1) forward movement command larger than one line. -xn,... or --tabs=n,... - Sets tab stops. If only one n is specified, tab stops are set - at multiples of n. If multiple values separated by commas are - specified, tab stops are set at those positions, and then con- - tinue with the same spacing as the last two. For example, - -x9,17 will set tabs at positions 9, 17, 25, 33, etc. The de- + Sets tab stops. If only one n is specified, tab stops are set + at multiples of n. If multiple values separated by commas are + specified, tab stops are set at those positions, and then con- + tinue with the same spacing as the last two. For example, + -x9,17 will set tabs at positions 9, 17, 25, 33, etc. The de- fault for n is 8. -X or --no-init Disables sending the termcap initialization and deinitialization - strings to the terminal. This is sometimes desirable if the - deinitialization string does something unnecessary, like clear- + strings to the terminal. This is sometimes desirable if the + deinitialization string does something unnecessary, like clear- ing the screen. -yn or --max-forw-scroll=n Specifies a maximum number of lines to scroll forward. If it is necessary to scroll forward more than n lines, the screen is re- - painted instead. The -c or -C option may be used to repaint - from the top of the screen if desired. By default, any forward + painted instead. The -c or -C option may be used to repaint + from the top of the screen if desired. By default, any forward movement causes scrolling. -zn or --window=n or -n - Changes the default scrolling window size to n lines. The de- - fault is one screenful. The z and w commands can also be used - to change the window size. The "z" may be omitted for compati- + Changes the default scrolling window size to n lines. The de- + fault is one screenful. The z and w commands can also be used + to change the window size. The "z" may be omitted for compati- bility with some versions of more. If the number n is negative, it indicates n lines less than the current screen size. For ex- ample, if the screen is 24 lines, -z-4 sets the scrolling window - to 20 lines. If the screen is resized to 40 lines, the + to 20 lines. If the screen is resized to 40 lines, the scrolling window automatically changes to 36 lines. -"cc or --quotes=cc - Changes the filename quoting character. This may be necessary - if you are trying to name a file which contains both spaces and - quote characters. Followed by a single character, this changes - the quote character to that character. Filenames containing a + Changes the filename quoting character. This may be necessary + if you are trying to name a file which contains both spaces and + quote characters. Followed by a single character, this changes + the quote character to that character. Filenames containing a space should then be surrounded by that character rather than by - double quotes. Followed by two characters, changes the open - quote to the first character, and the close quote to the second + double quotes. Followed by two characters, changes the open + quote to the first character, and the close quote to the second character. Filenames containing a space should then be preceded - by the open quote character and followed by the close quote - character. Note that even after the quote characters are - changed, this option remains -" (a dash followed by a double + by the open quote character and followed by the close quote + character. Note that even after the quote characters are + changed, this option remains -" (a dash followed by a double quote). -~ or --tilde @@ -863,12 +976,12 @@ LESS(1) General Commands Manual LESS(1) -# or --shift Specifies the default number of positions to scroll horizontally - in the RIGHTARROW and LEFTARROW commands. If the number speci- - fied is zero, it sets the default number of positions to one + in the RIGHTARROW and LEFTARROW commands. If the number speci- + fied is zero, it sets the default number of positions to one half of the screen width. Alternately, the number may be speci- - fied as a fraction of the width of the screen, starting with a - decimal point: .5 is half of the screen width, .3 is three - tenths of the screen width, and so on. If the number is speci- + fied as a fraction of the width of the screen, starting with a + decimal point: .5 is half of the screen width, .3 is three + tenths of the screen width, and so on. If the number is speci- fied as a fraction, the actual number of scroll positions is re- calculated if the terminal window is resized, so that the actual scroll remains at the specified fraction of the screen width. @@ -876,13 +989,22 @@ LESS(1) General Commands Manual LESS(1) --follow-name Normally, if the input file is renamed while an F command is ex- ecuting, less will continue to display the contents of the orig- - inal file despite its name change. If --follow-name is speci- - fied, during an F command less will periodically attempt to re- + inal file despite its name change. If --follow-name is speci- + fied, during an F command less will periodically attempt to re- open the file by name. If the reopen succeeds and the file is a - different file from the original (which means that a new file - has been created with the same name as the original (now re- + different file from the original (which means that a new file + has been created with the same name as the original (now re- named) file), less will display the contents of that new file. + --incsearch + Subsequent search commands will be "incremental"; that is, less + will advance to the next line containing the search pattern as + each character of the pattern is typed in. + + --line-num-width + Sets the minimum width of the line number field when the -N op- + tion is in effect. The default is 7 characters. + --mouse Enables mouse input: scrolling the mouse wheel down moves for- ward in the file, scrolling the mouse wheel up moves backwards @@ -919,45 +1041,57 @@ LESS(1) General Commands Manual LESS(1) Save marks in the history file, so marks are retained across different invocations of less. + --status-col-width + Sets the width of the status column when the -J option is in ef- + fect. The default is 2 characters. + --use-backslash - This option changes the interpretations of options which follow + This option changes the interpretations of options which follow this one. After the --use-backslash option, any backslash in an - option string is removed and the following character is taken - literally. This allows a dollar sign to be included in option + option string is removed and the following character is taken + literally. This allows a dollar sign to be included in option strings. + --use-color + Enables the 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 EC- + MA-48 SGR; see + https://www.ecma-international.org/publications-and- + standards/standards/ecma-48). + --wheel-lines=n - Set the number of lines to scroll when the mouse wheel is - scrolled and the --mouse or --MOUSE option is in effect. The + Set the number of lines to scroll when the mouse wheel is + scrolled and the --mouse or --MOUSE option is in effect. The default is 1 line. - -- A command line argument of "--" marks the end of option argu- - ments. Any arguments following this are interpreted as file- + -- A command line argument of "--" marks the end of option argu- + ments. Any arguments following this are interpreted as file- names. This can be useful when viewing a file whose name begins with a "-" or "+". - + If a command line option begins with +, the remainder of that - option is taken to be an initial command to less. For example, - +G tells less to start at the end of the file rather than the - beginning, and +/xyz tells it to start at the first occurrence - of "xyz" in the file. As a special case, + acts like + + If a command line option begins with +, the remainder of that + option is taken to be an initial command to less. For example, + +G tells less to start at the end of the file rather than the + beginning, and +/xyz tells it to start at the first occurrence + of "xyz" in the file. As a special case, + acts like +g; that is, it starts the display at the specified line - number (however, see the caveat under the "g" command above). + number (however, see the caveat under the "g" command above). If the option starts with ++, the initial command applies to ev- - ery file being viewed, not just the first one. The + command + ery file being viewed, not just the first one. The + command described previously may also be used to set (or change) an ini- tial command for every file. LINE EDITING - When entering command line at the bottom of the screen (for example, a - filename for the :e command, or the pattern for a search command), cer- - tain 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.) Any of these special keys may be entered - literally by preceding it with the "literal" character, either ^V or - ^A. A backslash itself may also be entered literally by entering two + When entering a command line at the bottom of the screen (for example, + a filename for the :e command, or the pattern for a search command), + 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.) Any of these special keys may be entered + literally by preceding it with the "literal" character, either ^V or + ^A. A backslash itself may also be entered literally by entering two backslashes. LEFTARROW [ ESC-h ] @@ -967,7 +1101,7 @@ LESS(1) General Commands Manual LESS(1) Move the cursor one space to the right. ^LEFTARROW [ ESC-b or ESC-LEFTARROW ] - (That is, CONTROL and LEFTARROW simultaneously.) Move the cur- + (That is, CONTROL and LEFTARROW simultaneously.) Move the cur- sor one word to the left. ^RIGHTARROW [ ESC-w or ESC-RIGHTARROW ] @@ -981,48 +1115,48 @@ LESS(1) General Commands Manual LESS(1) Move the cursor to the end of the line. BACKSPACE - Delete the character to the left of the cursor, or cancel the + Delete the character to the left of the cursor, or cancel the command if the command line is empty. DELETE or [ ESC-x ] Delete the character under the cursor. ^BACKSPACE [ ESC-BACKSPACE ] - (That is, CONTROL and BACKSPACE simultaneously.) Delete the + (That is, CONTROL and BACKSPACE simultaneously.) Delete the word to the left of the cursor. ^DELETE [ ESC-X or ESC-DELETE ] - (That is, CONTROL and DELETE simultaneously.) Delete the word + (That is, CONTROL and DELETE simultaneously.) Delete the word under the cursor. UPARROW [ ESC-k ] - Retrieve the previous command line. If you first enter some - text and then press UPARROW, it will retrieve the previous com- + Retrieve the previous command line. If you first enter some + text and then press UPARROW, it will retrieve the previous com- mand which begins with that text. DOWNARROW [ ESC-j ] - Retrieve the next command line. If you first enter some text - and then press DOWNARROW, it will retrieve the next command + Retrieve the next command line. If you first enter some text + and then press DOWNARROW, it will retrieve the next command which begins with that text. - TAB Complete the partial filename to the left of the cursor. If it - matches more than one filename, the first match is entered into - the command line. Repeated TABs will cycle thru the other + TAB Complete the partial filename to the left of the cursor. If it + matches more than one filename, the first match is entered into + the command line. Repeated TABs will cycle thru the other matching filenames. If the completed filename is a directory, a - "/" is appended to the filename. (On MS-DOS systems, a "\" is - appended.) The environment variable LESSSEPARATOR can be used + "/" is appended to the filename. (On MS-DOS systems, a "\" is + appended.) The environment variable LESSSEPARATOR can be used to specify a different character to append to a directory name. BACKTAB [ ESC-TAB ] Like, TAB, but cycles in the reverse direction thru the matching filenames. - ^L Complete the partial filename to the left of the cursor. If it + ^L Complete the partial filename to the left of the cursor. If it matches more than one filename, all matches are entered into the command line (if they fit). ^U (Unix and OS/2) or ESC (MS-DOS) - Delete the entire command line, or cancel the command if the + Delete the entire command line, or cancel the command if the command line is empty. If you have changed your line-kill char- acter in Unix to something other than ^U, that character is used instead of ^U. @@ -1030,70 +1164,70 @@ LESS(1) General Commands Manual LESS(1) ^G Delete the entire command line and return to the main prompt. KEY BINDINGS - You may define your own less commands by using the program lesskey(1) - to create a lesskey file. This file specifies a set of command keys - and an action associated with each key. You may also use lesskey to + You may define your own less commands by using the program lesskey(1) + to create a lesskey file. This file specifies a set of command keys + and an action associated with each key. You may also use lesskey to change the line-editing keys (see LINE EDITING), and to set environment - variables. If the environment variable LESSKEY is set, less uses that - as the name of the lesskey file. Otherwise, less looks in a standard - place for the lesskey file: On Unix systems, less looks for a lesskey - file called "$HOME/.less". On MS-DOS and Windows systems, less looks - for a lesskey file called "$HOME/_less", and if it is not found there, + variables. If the environment variable LESSKEY is set, less uses that + as the name of the lesskey file. Otherwise, less looks in a standard + place for the lesskey file: On Unix systems, less looks for a lesskey + file called "$HOME/.less". On MS-DOS and Windows systems, 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 - in the PATH environment variable. On OS/2 systems, 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 + in the PATH environment variable. On OS/2 systems, 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 in the INIT environment variable, and if it not found there, then looks - for a lesskey file called "less.ini" in any directory specified in the - PATH environment variable. See the lesskey manual page for more de- + for a lesskey file called "less.ini" in any directory specified in the + PATH environment variable. See the lesskey manual page for more de- tails. - A system-wide lesskey file may also be set up to provide key bindings. + A system-wide lesskey 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, + file, key bindings in the local file take precedence over those in the + system-wide file. If the environment variable LESSKEY_SYSTEM is set, less uses that as the name of the system-wide lesskey file. Otherwise, - 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. - (However, if less was built with a different sysconf directory than + 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. + (However, if 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:\_sys- + MS-DOS and Windows systems, the system-wide lesskey file is c:\_sys- less. On OS/2 systems, the system-wide lesskey file is c:\sysless.ini. INPUT PREPROCESSOR - You may define an "input preprocessor" for less. Before less opens a + You may define an "input preprocessor" for less. Before less opens a file, it first gives your input preprocessor a chance to modify the way - the contents of the file are displayed. An input preprocessor is sim- - ply an executable program (or shell script), which writes the contents + the contents of the file are displayed. An input preprocessor is sim- + ply an executable program (or shell script), which writes the contents of the file to a different file, called the replacement file. The con- - tents of the replacement file are then displayed in place of the con- - tents of the original file. However, it will appear to the user as if - the original file is opened; that is, less will display the original + tents of the replacement file are then displayed in place of the con- + tents of the original file. However, it will appear to the user as if + the original file is opened; that is, less will display the original filename as the name of the current file. - An input preprocessor receives one command line argument, the original - filename, as entered by the user. It should create the replacement - file, and when finished, print the name of the replacement file to its - standard output. If the input preprocessor does not output a replace- - ment filename, less uses the original file, as normal. The input pre- - processor is not called when viewing standard input. To set up an in- - put preprocessor, set the LESSOPEN environment variable to a command - line which will invoke your input preprocessor. This command line - should include one occurrence of the string "%s", which will be re- + An input preprocessor receives one command line argument, the original + filename, as entered by the user. It should create the replacement + file, and when finished, print the name of the replacement file to its + standard output. If the input preprocessor does not output a replace- + ment filename, less uses the original file, as normal. The input pre- + processor is not called when viewing standard input. To set up an in- + put preprocessor, set the LESSOPEN environment variable to a command + line which will invoke your input preprocessor. This command line + should include one occurrence of the string "%s", which will be re- placed by the filename when the input preprocessor command is invoked. When less closes a file opened in such a way, it will call another pro- - gram, called the input postprocessor, which may perform any desired - clean-up action (such as deleting the replacement file created by + gram, called the input postprocessor, which may perform any desired + clean-up action (such as deleting the replacement file created by LESSOPEN). This program receives two command line arguments, the orig- - inal filename as entered by the user, and the name of the replacement - file. To set up an input postprocessor, set the LESSCLOSE environment - variable to a command line which will invoke your input postprocessor. - It may include two occurrences of the string "%s"; the first is re- - placed with the original name of the file and the second with the name + inal filename as entered by the user, and the name of the replacement + file. To set up an input postprocessor, set the LESSCLOSE environment + variable to a command line which will invoke your input postprocessor. + It may include two occurrences of the string "%s"; the first is re- + placed with the original name of the file and the second with the name of the replacement file, which was output by LESSOPEN. - For example, on many Unix systems, these two scripts will allow you to + For example, on many Unix systems, these two scripts will allow you to keep files in compressed format, but still let less view them directly: lessopen.sh: @@ -1113,27 +1247,27 @@ LESS(1) General Commands Manual LESS(1) #! /bin/sh rm $2 - To use these scripts, put them both where they can be executed and set + To use these scripts, put them both where they can be executed and set LESSOPEN="lessopen.sh %s", and LESSCLOSE="lessclose.sh %s %s". More - complex LESSOPEN and LESSCLOSE scripts may be written to accept other + complex LESSOPEN and LESSCLOSE scripts may be written to accept other types of compressed files, and so on. - It is also possible to set up an input preprocessor to pipe the file - data directly to less, rather than putting the data into a replacement + It is also possible to set up an input preprocessor to pipe the file + data directly to less, rather than putting the data into a replacement file. This avoids the need to decompress the entire file before start- ing to view it. An input preprocessor that works this way is called an - input pipe. An input pipe, instead of writing the name of a replace- + input pipe. An input pipe, instead of writing the name of a replace- ment file on its standard output, writes the entire contents of the re- - placement file on its standard output. If the input pipe does not - write any characters on its standard output, then there is no replace- - ment file and less uses the original file, as normal. To use an input - pipe, make the first character in the LESSOPEN environment variable a - vertical bar (|) to signify that the input preprocessor is an input - pipe. As with non-pipe input preprocessors, the command string must - contain one occurrence of %s, which is replaced with the filename of + placement file on its standard output. If the input pipe does not + write any characters on its standard output, then there is no replace- + ment file and less uses the original file, as normal. To use an input + pipe, make the first character in the LESSOPEN environment variable a + vertical bar (|) to signify that the input preprocessor is an input + pipe. As with non-pipe input preprocessors, the command string must + contain one occurrence of %s, which is replaced with the filename of the input file. - For example, on many Unix systems, this script will work like the pre- + For example, on many Unix systems, this script will work like the pre- vious example scripts: lesspipe.sh: @@ -1150,29 +1284,29 @@ LESS(1) General Commands Manual LESS(1) LESSOPEN="|lesspipe.sh %s". Note that a preprocessor cannot output an empty file, since that is in- - terpreted as meaning there is no replacement, and the original file is - used. To avoid this, if LESSOPEN starts with two vertical bars, the - exit status of the script becomes meaningful. If the exit status is - zero, the output is considered to be replacement text, even if it is - empty. If the exit status is nonzero, any output is ignored and the - original file is used. For compatibility with previous versions of + terpreted as meaning there is no replacement, and the original file is + used. To avoid this, if LESSOPEN starts with two vertical bars, the + exit status of the script becomes meaningful. If the exit status is + zero, the output is considered to be replacement text, even if it is + empty. If the exit status is nonzero, any output is ignored and the + original file is used. For compatibility with previous versions of less, if LESSOPEN starts with only one vertical bar, the exit status of the preprocessor is ignored. - When an input pipe is used, a LESSCLOSE postprocessor can be used, but + When an input pipe is used, a LESSCLOSE postprocessor can be used, but it is usually not necessary since there is no replacement file to clean - up. In this case, the replacement file name passed to the LESSCLOSE + up. In this case, the replacement file name passed to the LESSCLOSE postprocessor is "-". - For compatibility with previous versions of less, the input preproces- + For compatibility with previous versions of less, the input preproces- sor or pipe is not used if less is viewing standard input. However, if - the first character of LESSOPEN is a dash (-), the input preprocessor - is used on standard input as well as other files. In this case, the - dash is not considered to be part of the preprocessor command. If + the first character of LESSOPEN is a dash (-), the input preprocessor + is used on standard input as well as other files. In this case, the + dash is not considered to be part of the preprocessor command. If standard input is being viewed, the input preprocessor is passed a file - name consisting of a single dash. Similarly, if the first two charac- - ters of LESSOPEN are vertical bar and dash (|-) or two vertical bars - and a dash (||-), the input pipe is used on standard input as well as + name consisting of a single dash. Similarly, if the first two charac- + ters of LESSOPEN are vertical bar and dash (|-) or two vertical bars + and a dash (||-), the input pipe is used on standard input as well as other files. Again, in this case the dash is not considered to be part of the input pipe command. @@ -1183,25 +1317,25 @@ LESS(1) General Commands Manual LESS(1) can be displayed directly to the screen. control characters - should not be displayed directly, but are expected to be found + should not be displayed directly, but are expected to be found in ordinary text files (such as backspace and tab). binary characters - should not be displayed directly and are not expected to be + should not be displayed directly and are not expected to be found in text files. A "character set" is simply a description of which characters are to be - considered normal, control, and binary. The LESSCHARSET environment - variable may be used to select a character set. Possible values for + considered normal, control, and binary. The LESSCHARSET environment + variable may be used to select a character set. Possible values for LESSCHARSET are: - ascii BS, TAB, NL, CR, and formfeed are control characters, all chars - with values between 32 and 126 are normal, and all others are + ascii BS, TAB, NL, CR, and formfeed are control characters, all chars + with values between 32 and 126 are normal, and all others are binary. iso8859 - Selects an ISO 8859 character set. This is the same as ASCII, - except characters between 160 and 255 are treated as normal + Selects an ISO 8859 character set. This is the same as ASCII, + except characters between 160 and 255 are treated as normal characters. latin1 Same as iso8859. @@ -1213,8 +1347,8 @@ LESS(1) General Commands Manual LESS(1) ebcdic Selects an EBCDIC character set. IBM-1047 - Selects an EBCDIC character set used by OS/390 Unix Services. - This is the EBCDIC analogue of latin1. You get similar results + Selects an EBCDIC character set used by OS/390 Unix Services. + This is the EBCDIC analogue of latin1. You get similar results by setting either LESSCHARSET=IBM-1047 or LC_CTYPE=en_US in your environment. @@ -1222,29 +1356,29 @@ LESS(1) General Commands Manual LESS(1) next Selects a character set appropriate for NeXT computers. - utf-8 Selects the UTF-8 encoding of the ISO 10646 character set. - UTF-8 is special in that it supports multi-byte characters in - the input file. It is the only character set that supports - multi-byte characters. + utf-8 Selects the UTF-8 encoding of the ISO 10646 character set. + UTF-8 is special in that it supports multi-byte characters in + the input file. It is the only character set that supports mul- + ti-byte characters. windows - Selects a character set appropriate for Microsoft Windows (cp + Selects a character set appropriate for Microsoft Windows (cp 1251). - In rare cases, it may be desired to tailor less to use a character set - other than the ones definable by LESSCHARSET. In this case, the envi- + In rare cases, it may be desired to tailor less to use a character set + other than the ones definable by LESSCHARSET. In this case, the envi- ronment variable LESSCHARDEF can be used to define a character set. It should be set to a string where each character in the string represents - one character in the character set. The character "." is used for a - normal character, "c" for control, and "b" for binary. A decimal num- - ber may be used for repetition. For example, "bccc4b." would mean - character 0 is binary, 1, 2 and 3 are control, 4, 5, 6 and 7 are bi- - nary, and 8 is normal. All characters after the last are taken to be - the same as the last, so characters 9 through 255 would be normal. - (This is an example, and does not necessarily represent any real char- - acter set.) + one character in the character set. The character "." is used for a + normal character, "c" for control, and "b" for binary. A decimal num- + ber may be used for repetition. For example, "bccc4b." would mean + character 0 is binary, 1, 2 and 3 are control, 4, 5, 6 and 7 are bina- + ry, and 8 is normal. All characters after the last are taken to be the + same as the last, so characters 9 through 255 would be normal. (This + is an example, and does not necessarily represent any real character + set.) - This table shows the value of LESSCHARDEF which is equivalent to each + This table shows the value of LESSCHARDEF which is equivalent to each of the possible values for LESSCHARSET: ascii 8bcccbcc18b95.b @@ -1258,65 +1392,65 @@ LESS(1) General Commands Manual LESS(1) latin1 8bcccbcc18b95.33b. next 8bcccbcc18b95.bb125.bb - If neither LESSCHARSET nor LESSCHARDEF is set, but any of the strings - "UTF-8", "UTF8", "utf-8" or "utf8" is found in the LC_ALL, LC_CTYPE or + If neither LESSCHARSET nor LESSCHARDEF is set, but any of the strings + "UTF-8", "UTF8", "utf-8" or "utf8" is found in the LC_ALL, LC_CTYPE or LANG environment variables, then the default character set is utf-8. If that string is not found, but your system supports the setlocale in- - terface, less will use setlocale to determine the character set. set- - locale is controlled by setting the LANG or LC_CTYPE environment vari- + terface, less will use setlocale to determine the character set. set- + locale is controlled by setting the LANG or LC_CTYPE environment vari- ables. - Finally, if the setlocale interface is also not available, the default + Finally, if the setlocale interface is also not available, the default character set is latin1. - Control and binary characters are displayed in standout (reverse + Control and binary characters are displayed in standout (reverse video). Each such character is displayed in caret notation if possible - (e.g. ^A for control-A). Caret notation is used only if inverting the + (e.g. ^A for control-A). Caret notation is used only if inverting the 0100 bit results in a normal printable character. Otherwise, the char- - acter is displayed as a hex number in angle brackets. This format can - be changed by setting the LESSBINFMT environment variable. LESSBINFMT + acter is displayed as a hex number in angle brackets. This format can + be changed by setting the LESSBINFMT environment variable. LESSBINFMT may begin with a "*" and one character to select the display attribute: - "*k" is blinking, "*d" is bold, "*u" is underlined, "*s" is standout, - and "*n" is normal. If LESSBINFMT does not begin with a "*", normal - attribute is assumed. The remainder of LESSBINFMT is a string which - may include one printf-style escape sequence (a % followed by x, X, o, - d, etc.). For example, if LESSBINFMT is "*u[%x]", binary characters - are displayed in underlined hexadecimal surrounded by brackets. The - default if no LESSBINFMT is specified is "*s<%02X>". Warning: the re- - sult of expanding the character via LESSBINFMT must be less than 31 + "*k" is blinking, "*d" is bold, "*u" is underlined, "*s" is standout, + and "*n" is normal. If LESSBINFMT does not begin with a "*", normal + attribute is assumed. The remainder of LESSBINFMT is a string which + may include one printf-style escape sequence (a % followed by x, X, o, + d, etc.). For example, if LESSBINFMT is "*u[%x]", binary characters + are displayed in underlined hexadecimal surrounded by brackets. The + default if no LESSBINFMT is specified is "*s<%02X>". Warning: the re- + sult of expanding the character via LESSBINFMT must be less than 31 characters. When the character set is utf-8, the LESSUTFBINFMT environment variable acts similarly to LESSBINFMT but it applies to Unicode code points that - were successfully decoded but are unsuitable for display (e.g., unas- - signed code points). Its default value is "". Note that - LESSUTFBINFMT and LESSBINFMT share their display attribute setting - ("*x") so specifying one will affect both; LESSUTFBINFMT is read after - LESSBINFMT so its setting, if any, will have priority. Problematic - octets in a UTF-8 file (octets of a truncated sequence, octets of a - complete but non-shortest form sequence, invalid octets, and stray - trailing octets) are displayed individually using LESSBINFMT so as to + were successfully decoded but are unsuitable for display (e.g., unas- + signed code points). Its default value is "". Note that + LESSUTFBINFMT and LESSBINFMT share their display attribute setting + ("*x") so specifying one will affect both; LESSUTFBINFMT is read after + LESSBINFMT so its setting, if any, will have priority. Problematic + octets in a UTF-8 file (octets of a truncated sequence, octets of a + complete but non-shortest form sequence, invalid octets, and stray + trailing octets) are displayed individually using LESSBINFMT so as to facilitate diagnostic of how the UTF-8 file is ill-formed. PROMPTS - The -P option allows you to tailor the prompt to your preference. The - string given to the -P option replaces the specified prompt string. + The -P option allows you to tailor the prompt to your preference. The + string given to the -P option replaces the specified prompt string. Certain characters in the string are interpreted specially. The prompt - mechanism is rather complicated to provide flexibility, but the ordi- - nary user need not understand the details of constructing personalized + mechanism is rather complicated to provide flexibility, but the ordi- + nary user need not understand the details of constructing personalized prompt strings. - A percent sign followed by a single character is expanded according to + A percent sign followed by a single character is expanded according to what the following character is: - %bX Replaced by the byte offset into the current input file. The b + %bX Replaced by the byte offset into the current input file. The b is followed by a single character (shown as X above) which spec- - ifies the line whose byte offset is to be used. If the charac- - ter is a "t", the byte offset of the top line in the display is + ifies the line whose byte offset is to be used. If the charac- + ter is a "t", the byte offset of the top line in the display is used, an "m" means use the middle line, a "b" means use the bot- - tom line, a "B" means use the line just after the bottom line, - and a "j" means use the "target" line, as specified by the -j + tom line, a "B" means use the line just after the bottom line, + and a "j" means use the "target" line, as specified by the -j option. %B Replaced by the size of the current input file. @@ -1324,50 +1458,50 @@ LESS(1) General Commands Manual LESS(1) %c Replaced by the column number of the text appearing in the first column of the screen. - %dX Replaced by the page number of a line in the input file. The + %dX Replaced by the page number of a line in the input file. The line to be used is determined by the X, as with the %b option. - %D Replaced by the number of pages in the input file, or equiva- + %D Replaced by the number of pages in the input file, or equiva- lently, the page number of the last line in the input file. - %E Replaced by the name of the editor (from the VISUAL environment - variable, or the EDITOR environment variable if VISUAL is not + %E Replaced by the name of the editor (from the VISUAL environment + variable, or the EDITOR environment variable if VISUAL is not defined). See the discussion of the LESSEDIT feature below. %f Replaced by the name of the current input file. - %F Replaced by the last component of the name of the current input + %F Replaced by the last component of the name of the current input file. - %g Replaced by the shell-escaped name of the current input file. - This is useful when the expanded string will be used in a shell + %g Replaced by the shell-escaped name of the current input file. + This is useful when the expanded string will be used in a shell command, such as in LESSEDIT. - %i Replaced by the index of the current file in the list of input + %i Replaced by the index of the current file in the list of input files. - %lX Replaced by the line number of a line in the input file. The + %lX Replaced by the line number of a line in the input file. The line to be used is determined by the X, as with the %b option. %L Replaced by the line number of the last line in the input file. %m Replaced by the total number of input files. - %pX Replaced by the percent into the current input file, based on - byte offsets. The line used is determined by the X as with the + %pX Replaced by the percent into the current input file, based on + byte offsets. The line used is determined by the X as with the %b option. - %PX Replaced by the percent into the current input file, based on - line numbers. The line used is determined by the X as with the + %PX Replaced by the percent into the current input file, based on + line numbers. The line used is determined by the X as with the %b option. %s Same as %B. - %t Causes any trailing spaces to be removed. Usually used at the + %t Causes any trailing spaces to be removed. Usually used at the end of the string, but may appear anywhere. - %T Normally expands to the word "file". However if viewing files - via a tags list using the -t option, it expands to the word + %T Normally expands to the word "file". However if viewing files + via a tags list using the -t option, it expands to the word "tag". %x Replaced by the name of the next input file in the list. @@ -1375,15 +1509,15 @@ LESS(1) General Commands Manual LESS(1) If any item is unknown (for example, the file size if input is a pipe), a question mark is printed instead. - The format of the prompt string can be changed depending on certain - conditions. A question mark followed by a single character acts like - an "IF": depending on the following character, a condition is evalu- - ated. If the condition is true, any characters following the question - mark and condition character, up to a period, are included in the - prompt. If the condition is false, such characters are not included. - A colon appearing between the question mark and the period can be used + The format of the prompt string can be changed depending on certain + conditions. A question mark followed by a single character acts like + an "IF": depending on the following character, a condition is evaluat- + ed. If the condition is true, any characters following the question + mark and condition character, up to a period, are included in the + prompt. If the condition is false, such characters are not included. + A colon appearing between the question mark and the period can be used to establish an "ELSE": any characters between the colon and the period - are included in the string if and only if the IF condition is false. + are included in the string if and only if the IF condition is false. Condition characters (which follow a question mark) may be: ?a True if any characters have been included in the prompt so far. @@ -1398,7 +1532,7 @@ LESS(1) General Commands Manual LESS(1) ?e True if at end-of-file. - ?f True if there is an input filename (that is, if input is not a + ?f True if there is an input filename (that is, if input is not a pipe). ?lX True if the line number of the specified line is known. @@ -1409,45 +1543,45 @@ LESS(1) General Commands Manual LESS(1) ?n True if this is the first prompt in a new input file. - ?pX True if the percent into the current input file, based on byte + ?pX True if the percent into the current input file, based on byte offsets, of the specified line is known. - ?PX True if the percent into the current input file, based on line + ?PX True if the percent into the current input file, based on line numbers, of the specified line is known. ?s Same as "?B". - ?x True if there is a next input file (that is, if the current in- + ?x True if there is a next input file (that is, if the current in- put file is not the last one). - Any characters other than the special ones (question mark, colon, pe- - riod, percent, and backslash) become literally part of the prompt. Any - of the special characters may be included in the prompt literally by + Any characters other than the special ones (question mark, colon, peri- + od, percent, and backslash) become literally part of the prompt. Any + of the special characters may be included in the prompt literally by preceding it with a backslash. Some examples: ?f%f:Standard input. - This prompt prints the filename, if known; otherwise the string "Stan- + This prompt prints the filename, if known; otherwise the string "Stan- dard input". ?f%f .?ltLine %lt:?pt%pt\%:?btByte %bt:-... - This prompt would print the filename, if known. The filename is fol- - lowed by the line number, if known, otherwise the percent if known, + This prompt would print the filename, if known. The filename is fol- + lowed by the line number, if known, otherwise the percent if known, otherwise the byte offset if known. Otherwise, a dash is printed. No- - tice how each question mark has a matching period, and how the % after + tice how each question mark has a matching period, and how the % after the %pt is included literally by escaping it with a backslash. ?n?f%f .?m(%T %i of %m) ..?e(END) ?x- Next\: %x..%t"; - This prints the filename if this is the first prompt in a file, fol- - lowed by the "file N of N" message if there is more than one input - file. Then, if we are at end-of-file, the string "(END)" is printed - followed by the name of the next file, if there is one. Finally, any + This prints the filename if this is the first prompt in a file, fol- + lowed by the "file N of N" message if there is more than one input + file. Then, if we are at end-of-file, the string "(END)" is printed + followed by the name of the next file, if there is one. Finally, any trailing spaces are truncated. This is the default prompt. For refer- - ence, here are the defaults for the other two prompts (-m and -M re- + ence, here are the defaults for the other two prompts (-m and -M re- spectively). Each is broken into two lines here for readability only. ?n?f%f .?m(%T %i of %m) ..?e(END) ?x- Next\: %x.: @@ -1461,22 +1595,22 @@ LESS(1) General Commands Manual LESS(1) ?f%f .?m(%T %i of %m) .?ltlines %lt-%lb?L/%L. . byte %bB?s/%s. ?e(END) :?pB%pB\%..%t - The prompt expansion features are also used for another purpose: if an - environment variable LESSEDIT is defined, it is used as the command to - be executed when the v command is invoked. The LESSEDIT string is ex- - panded in the same way as the prompt strings. The default value for + The prompt expansion features are also used for another purpose: if an + environment variable LESSEDIT is defined, it is used as the command to + be executed when the v command is invoked. The LESSEDIT string is ex- + panded in the same way as the prompt strings. The default value for LESSEDIT is: %E ?lm+%lm. %g Note that this expands to the editor name, followed by a + and the line - number, followed by the shell-escaped file name. If your editor does - not accept the "+linenumber" syntax, or has other differences in invo- - cation syntax, the LESSEDIT variable can be changed to modify this de- + number, followed by the shell-escaped file name. If your editor does + not accept the "+linenumber" syntax, or has other differences in invo- + cation syntax, the LESSEDIT variable can be changed to modify this de- fault. SECURITY - When the environment variable LESSSECURE is set to 1, less runs in a + When the environment variable LESSSECURE is set to 1, less runs in a "secure" mode. This means these features are disabled: ! the shell command @@ -1501,52 +1635,52 @@ LESS(1) General Commands Manual LESS(1) 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", less behaves (mostly) in con- - formance with the POSIX "more" command specification. In this mode, + is invoked via a file link named "more", less behaves (mostly) in con- + formance with the POSIX "more" command specification. In this mode, less behaves differently in these ways: The -e option works differently. If the -e option is not set, less be- - haves as if the -e option were set. If the -e option is set, less be- + haves as if the -e option were set. If the -e option is set, less be- haves as if the -E option were set. - The -m option works differently. If the -m option is not set, the - medium prompt is used, and it is prefixed with the string "--More--". + The -m option works differently. If the -m option is not set, the + medium prompt is used, and it is prefixed with the string "--More--". If the -m option is set, the short prompt is used. - The -n option acts like the -z option. The normal behavior of the -n + The -n option acts like the -z option. The normal behavior of the -n option is unavailable in this mode. - The parameter to the -p option is taken to be a less command rather + The parameter to the -p option is taken to be a less command rather than a search pattern. - The LESS environment variable is ignored, and the MORE environment + The LESS environment variable is ignored, and the MORE environment variable is used in its place. ENVIRONMENT VARIABLES Environment variables may be specified either in the system environment - as usual, or in a lesskey(1) file. If environment variables are de- + as usual, or in a lesskey(1) file. If environment variables are de- fined in more than one place, variables defined in a local lesskey file take precedence over variables defined in the system environment, which take precedence over variables defined in the system-wide lesskey file. COLUMNS Sets the number of columns on the screen. Takes precedence over - the number of columns specified by the TERM variable. (But if + the number of columns specified by the TERM variable. (But if you have a windowing system which supports TIOCGWINSZ or - WIOCGETD, the window system's idea of the screen size takes + WIOCGETD, the window system's idea of the screen size takes precedence over the LINES and COLUMNS environment variables.) EDITOR The name of the editor (used for the v command). - HOME Name of the user's home directory (used to find a lesskey file + HOME Name of the user's home directory (used to find a lesskey file on Unix and OS/2 systems). HOMEDRIVE, HOMEPATH - Concatenation of the HOMEDRIVE and HOMEPATH environment vari- + Concatenation of the HOMEDRIVE and HOMEPATH environment vari- ables is the name of the user's home directory if the HOME vari- able is not set (only in the Windows version). - INIT Name of the user's init directory (used to find a lesskey file + INIT Name of the user's init directory (used to find a lesskey file on OS/2 systems). LANG Language for determining the character set. @@ -1557,12 +1691,12 @@ LESS(1) General Commands Manual LESS(1) LESS Options which are passed to less automatically. LESSANSIENDCHARS - Characters which may end an ANSI color escape sequence (default + Characters which may end an ANSI color escape sequence (default "m"). LESSANSIMIDCHARS - Characters which may appear between the ESC character and the - end character in an ANSI color escape sequence (default + Characters which may appear between the ESC character and the + end character in an ANSI color escape sequence (default "0123456789:;[?!"'#%()*+ ". LESSBINFMT @@ -1579,24 +1713,24 @@ LESS(1) General Commands Manual LESS(1) LESSECHO Name of the lessecho program (default "lessecho"). The lessecho - program is needed to expand metacharacters, such as * and ?, in + program is needed to expand metacharacters, such as * and ?, in filenames on Unix systems. LESSEDIT - Editor prototype string (used for the v command). See discus- + Editor prototype string (used for the v command). See discus- sion under PROMPTS. LESSGLOBALTAGS - Name of the command used by the -t option to find global tags. - Normally should be set to "global" if your system has the - global(1) command. If not set, global tags are not used. + Name of the command used by the -t option to find global tags. + Normally should be set to "global" if your system has the glob- + al(1) command. If not set, global tags are not used. LESSHISTFILE - Name of the history file used to remember search commands and - shell commands between invocations of 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" + Name of the history file used to remember search commands and + shell commands between invocations of 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" on OS/2 systems. LESSHISTSIZE @@ -1610,13 +1744,13 @@ LESS(1) General Commands Manual LESS(1) Name of the default system-wide lesskey(1) file. LESSMETACHARS - List of characters which are considered "metacharacters" by the + List of characters which are considered "metacharacters" by the shell. LESSMETAESCAPE - Prefix which less will add before each metacharacter in a com- - mand sent to the shell. If LESSMETAESCAPE is an empty string, - commands containing metacharacters will not be passed to the + Prefix which less will add before each metacharacter in a com- + mand sent to the shell. If LESSMETAESCAPE is an empty string, + commands containing metacharacters will not be passed to the shell. LESSOPEN @@ -1626,7 +1760,7 @@ LESS(1) General Commands Manual LESS(1) Runs less in "secure" mode. See discussion under SECURITY. LESSSEPARATOR - String to be appended to a directory name in filename comple- + String to be appended to a directory name in filename comple- tion. LESSUTFBINFMT @@ -1635,19 +1769,19 @@ LESS(1) General Commands Manual LESS(1) LESS_IS_MORE Emulate the more(1) command. - LINES Sets the number of lines on the screen. Takes precedence over + LINES Sets the number of lines on the screen. Takes precedence over the number of lines specified by the TERM variable. (But if you - have a windowing system which supports TIOCGWINSZ or WIOCGETD, - the window system's idea of the screen size takes precedence + have a windowing system which supports TIOCGWINSZ or WIOCGETD, + the window system's idea of the screen size takes precedence over the LINES and COLUMNS environment variables.) - MORE Options which are passed to less automatically when running in + MORE Options which are passed to less automatically when running in more compatible mode. - PATH User's search path (used to find a lesskey file on MS-DOS and + PATH User's search path (used to find a lesskey file on MS-DOS and OS/2 systems). - SHELL The shell used to execute the ! command, as well as to expand + SHELL The shell used to execute the ! command, as well as to expand filenames. TERM The type of terminal on which less is being run. @@ -1658,29 +1792,29 @@ LESS(1) General Commands Manual LESS(1) lesskey(1) COPYRIGHT - Copyright (C) 1984-2020 Mark Nudelman + Copyright (C) 1984-2021 Mark Nudelman - less is part of the GNU project and is free software. You can redis- - tribute it and/or modify it under the terms of either (1) the GNU Gen- - eral Public License as published by the Free Software Foundation; or + less is part of the GNU project and is free software. You can redis- + tribute it and/or modify it under the terms of either (1) the GNU Gen- + eral Public License as published by the Free Software Foundation; or (2) the Less License. See the file README in the less distribution for more details regarding redistribution. You should have received a copy - of the GNU General Public License along with the source for less; see - the file COPYING. If not, write to the Free Software Foundation, 59 - Temple Place, Suite 330, Boston, MA 02111-1307, USA. You should also + of the GNU General Public License along with the source for less; see + the file COPYING. If not, write to the Free Software Foundation, 59 + Temple Place, Suite 330, Boston, MA 02111-1307, USA. You should also have received a copy of the Less License; see the file LICENSE. less is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FIT- - NESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + WARRANTY; without even the implied warranty of MERCHANTABILITY or FIT- + NESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. AUTHOR Mark Nudelman Report bugs at https://github.com/gwsw/less/issues. For more information, see the less homepage at - http://www.greenwoodsoftware.com/less. + https://greenwoodsoftware.com/less. - Version 563: 13 Jun 2020 LESS(1) + Version 581: 06 Apr 2021 LESS(1) diff --git a/less.nro b/less.nro index 70f99ce6f286..41021321964b 100644 --- a/less.nro +++ b/less.nro @@ -1,5 +1,5 @@ '\" t -.TH LESS 1 "Version 563: 13 Jun 2020" +.TH LESS 1 "Version 581: 06 Apr 2021" .SH NAME less \- opposite of more .SH SYNOPSIS @@ -109,6 +109,7 @@ Scroll horizontally left back to the first column. Repaint the screen. .IP R Repaint the screen, discarding any buffered input. +That is, reload the current file. Useful if the file is changing while it is being viewed. .IP "F" Scroll forward, and keep trying to read when the @@ -117,6 +118,8 @@ Normally this command would be used when already at the end of the file. It is a way to monitor the tail of a file which is growing while it is being viewed. (The behavior is similar to the "tail \-f" command.) +To stop waiting for more data, enter the interrupt character (usually ^C). +On some systems you can also use ^X. .IP "ESC-F" Like F, but as soon as a line is found which matches the last search pattern, the terminal bell is rung @@ -226,6 +229,11 @@ but don't move to the first match (KEEP current position). .IP "^R" Don't interpret regular expression metacharacters; that is, do a simple textual comparison. +.IP "^W" +WRAP around the current file. +That is, if the search reaches the end of the current file +without finding a match, the search continues from the first line of the +current file up to the line where it started. .RE .IP ?pattern Search backward in the file for the N-th line containing the pattern. @@ -250,6 +258,11 @@ or the settings of the \-a or \-j options. As in forward searches. .IP "^R" As in forward searches. +.IP "^W" +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. .RE .IP "ESC-/pattern" Same as "/*". @@ -280,6 +293,10 @@ turn highlighting back on. Any search command will also turn highlighting back on. (Highlighting can also be disabled by toggling the \-G option; in that case search commands do not turn highlighting back on.) +.IP "ESC-U" +Like ESC-u but also clears the saved search pattern. +If the status column is enabled via the \-J option, +this clears all search matches marked in the status column. .IP "&pattern" Display only lines which match the pattern; lines which do not match the pattern are not displayed. @@ -288,6 +305,8 @@ any filtering is turned off, and all lines are displayed. While filtering is in effect, an ampersand is displayed at the beginning of the prompt, as a reminder that some lines in the file may be hidden. +Multiple & commands may be entered, in which case only lines +which match all of the patterns will be displayed. .sp Certain characters are special as in the / command: .RS @@ -552,20 +571,105 @@ The \-d option does not otherwise change the behavior of .I less on a dumb terminal. .IP "\-D\fBx\fP\fIcolor\fP or \-\-color=\fBx\fP\fIcolor\fP" -[MS-DOS only] -Sets the color of the text displayed. -\fBx\fP is a single character which selects the type of text whose color is -being set: n=normal, s=standout, d=bold, u=underlined, k=blink. -\fIcolor\fP is a pair of numbers separated by a period. -The first number selects the foreground color and the second selects -the background color of the text. -A single number \fIN\fP is the same as \fIN.M\fP, -where \fIM\fP is the normal background color. -The color may start or end with \fBu\fP to use underline (with the normal -color, if by itself), if the system supports it (Windows only). -\fBx\fP may also be \fBa\fP to toggle strict ANSI sequence rendering -(SGR mode). -. +Changes the color of different parts of the displayed text. +\fBx\fP is a single character which selects the type of text +whose color is being set: +.RS +.IP "B" +Binary characters. +.IP "C" +Control characters. +.IP "E" +Errors and informational messages. +.IP "M" +Mark letters in the status column. +.IP "N" +Line numbers enabled via the \-N option. +.IP "P" +Prompts. +.IP "R" +The rscroll character. +.IP "S" +Search results. +.IP "W" +The highlight enabled via the \-w option. +.IP "d" +Bold text. +.IP "k" +Blinking text. +.IP "s" +Standout text. +.IP "u" +Underlined text. +.RE + +.RS +The uppercase letters can be used only when the \-\-use-color option is enabled. +When text color is specified by both an uppercase letter and a lowercase letter, +the uppercase letter takes precedence. +For example, error messages are normally displayed as standout text. +So if both "s" and "E" are given a color, the "E" color applies +to error messages, and the "s" color applies to other standout text. +The "d" and "u" letters refer to bold and underline text formed by +overstriking with backspaces (see the \-u option), +not to text using ANSI escape sequences with the \-R option. +.PP +A lowercase letter may be followed by a + to indicate that +both the normal format change and the specified color should both be used. +For example, \-Dug displays underlined text as green without underlining; +the green color has replaced the usual underline formatting. +But \-Du+g displays underlined text as both green and in underlined format. +.PP +\fIcolor\fP is either a 4-bit color string or an 8-bit color string: +.PP +A 4-bit color string is zero, one or two characters, where +the first character specifies the foreground color and +the second specifies the background color as follows: +.IP "b" +Blue +.IP "c" +Cyan +.IP "g" +Green +.IP "k" +Black +.IP "m" +Magenta +.IP "r" +Red +.IP "w" +White +.IP "y" +Yellow +.PP +The corresponding upper-case letter denotes a brighter shade of the color. +For example, \-DNGk displays line numbers as bright green text on a black +background, and \-DEbR displays error messages as blue text on a +bright red background. +If either character is a "-" or is omitted, the corresponding color +is set to that of normal text. +.PP +An 8-bit color string is one or two decimal integers separated by a dot, +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 +.br +.nh +https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters) +.hy +If either integer is a "-" or is omitted, +the corresponding color is set to that of normal text. +On MS-DOS versions of +.IR less , +8-bit color is not supported; instead, decimal values are interpreted as 4-bit +CHAR_INFO.Attributes values +(see +.br +.nh +https://docs.microsoft.com/en-us/windows/console/char-info-str). +.hy +.RE .IP "\-e or \-\-quit-at-eof" Causes .I less @@ -650,7 +754,6 @@ always begin at the start or end of the current screen respectively. Displays a status column at the left edge of the screen. The status column shows the lines that matched the current search, and any lines that are marked (via the m or M command). -The status column is also used if the \-w or \-W option is in effect. .IP "\-k\fIfilename\fP or \-\-lesskey-file=\fIfilename\fP" Causes .I less @@ -676,7 +779,8 @@ command prompt from the "F" command. .IP "\-L or \-\-no-lessopen" Ignore the LESSOPEN environment variable (see the INPUT PREPROCESSOR section below). -This option can be set from within \fIless\fP, +This option can be set from within +.IR less , but it will apply only to files opened subsequently, not to the file which is currently open. .IP "\-m or \-\-long-prompt" @@ -776,16 +880,33 @@ cannot keep track of the actual appearance of the screen 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. .IP "\-R or \-\-RAW-CONTROL-CHARS" -Like \-r, but only ANSI "color" escape sequences are output in "raw" form. -Unlike \-r, the screen appearance is maintained correctly in most cases. -ANSI "color" escape sequences are sequences of the form: +Like \-r, but only ANSI "color" escape sequences and OSC 8 hyperlink +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. +.sp +OSC 8 hyperlinks are sequences of the form: +.sp + ESC ] 8 ; \&...\& \\7 +.sp +The terminating sequence may be either a BEL character (\\7) +or the two-character sequence "ESC \\". +.sp +ANSI color escape sequences are sequences of the form: .sp ESC [ \&...\& m .sp -where the "...\&" is zero or more color specification characters -For the purpose of keeping track of screen appearance, -ANSI color escape sequences are assumed to not move the cursor. +where the "...\&" is zero or more color specification characters. You can make .I less think that characters other than "m" can end ANSI color escape sequences @@ -820,7 +941,10 @@ If the environment variable LESSGLOBALTAGS is set, it is taken to be the name of a command compatible with .IR global (1), and that command is executed to find the tag. -(See http://www.gnu.org/software/global/global.html). +(See +.nh +http://www.gnu.org/software/global/global.html). +.hy The \-t option may also be specified from within .I less (using the \- command) as a way of examining a new file. @@ -848,6 +972,8 @@ using the terminal's hardware boldface capability. Other backspaces are deleted, along with the preceding character. Carriage returns immediately followed by a newline are deleted. Other carriage returns are handled as specified by the \-r option. +Unicode formatting characters, such as the Byte Order Mark, +are sent to the terminal. Text which is overstruck or underlined can be searched for if neither \-u nor \-U is in effect. .IP "\-V or \-\-version" @@ -941,6 +1067,14 @@ If the reopen succeeds and the file is a different file from the original with the same name as the original (now renamed) file), .I less will display the contents of that new file. +.IP "\-\-incsearch" +Subsequent search commands will be "incremental"; that is, +.I less +will advance to the next line containing the search pattern +as each character of the pattern is typed in. +.IP "\-\-line-num-width" +Sets the minimum width of the line number field when the \-N option is in effect. +The default is 7 characters. .IP "\-\-mouse" Enables mouse input: scrolling the mouse wheel down moves forward in the file, @@ -973,12 +1107,26 @@ If there is no attribute indicator, standout is used. If set to "\-", truncated lines are not marked. .IP "\-\-save-marks" Save marks in the history file, so marks are retained -across different invocations of \fIless\fP. +across different invocations of +.IR less . +.IP "\-\-status-col-width" +Sets the width of the status column when the \-J option is in effect. +The default is 2 characters. .IP "\-\-use-backslash" This option changes the interpretations of options which follow this one. After the \-\-use-backslash option, any backslash in an option string is removed and the following character is taken literally. This allows a dollar sign to be included in option strings. +.IP "\-\-use-color" +Enables the 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 ECMA-48 SGR; +see +.br +.nh +https://www.ecma-international.org/publications-and-standards/standards/ecma-48). +.hy .IP "\-\-wheel-lines=\fIn\fP" Set the number of lines to scroll when the mouse wheel is scrolled and the \-\-mouse or \-\-MOUSE option is in effect. @@ -1004,7 +1152,7 @@ The + command described previously may also be used to set (or change) an initial command for every file. . .SH "LINE EDITING" -When entering command line at the bottom of the screen +When entering a command line at the bottom of the screen (for example, a filename for the :e command, or the pattern for a search command), certain keys can be used to manipulate the command line. @@ -1804,7 +1952,7 @@ The name of the editor (used for the v command). .BR lesskey (1) . .SH COPYRIGHT -Copyright (C) 1984-2020 Mark Nudelman +Copyright (C) 1984-2021 Mark Nudelman .PP less is part of the GNU project and is free software. You can redistribute it and/or modify it @@ -1833,4 +1981,4 @@ Report bugs at https://github.com/gwsw/less/issues. .br For more information, see the less homepage at .br -http://www.greenwoodsoftware.com/less. +https://greenwoodsoftware.com/less. diff --git a/lessecho.c b/lessecho.c index 6bf2e9c32b51..bfb0f729a8b8 100644 --- a/lessecho.c +++ b/lessecho.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -13,16 +13,16 @@ * Simply echos its filename arguments on standard output. * But any argument containing spaces is enclosed in quotes. * - * -ox Specifies "x" to be the open quote character. - * -cx Specifies "x" to be the close quote character. - * -pn Specifies "n" to be the open quote character, as an integer. - * -dn Specifies "n" to be the close quote character, as an integer. + * -ox Specifies "x" to be the open quote character. + * -cx Specifies "x" to be the close quote character. + * -pn Specifies "n" to be the open quote character, as an integer. + * -dn Specifies "n" to be the close quote character, as an integer. * -mx Specifies "x" to be a metachar. * -nn Specifies "n" to be a metachar, as an integer. * -ex Specifies "x" to be the escape char for metachars. * -fn Specifies "x" to be the escape char for metachars, as an integer. - * -a Specifies that all arguments are to be quoted. - * The default is that only arguments containing spaces are quoted. + * -a Specifies that all arguments are to be quoted. + * The default is that only arguments containing spaces are quoted. */ #include "less.h" diff --git a/lessecho.man b/lessecho.man index 2a4c45748016..878e7ad7e17e 100644 --- a/lessecho.man +++ b/lessecho.man @@ -38,7 +38,7 @@ LESSECHO(1) General Commands Manual LESSECHO(1) ger. -a Specifies that all arguments are to be quoted. The default is - that only arguments containing metacharacters are quoted + that only arguments containing metacharacters are quoted. SEE ALSO less(1) @@ -47,8 +47,8 @@ LESSECHO(1) General Commands Manual LESSECHO(1) This manual page was written by Thomas Schoepf , for the Debian GNU/Linux system (but may be used by others). - Send bug reports or comments to bug-less@gnu.org. + Report bugs at https://github.com/gwsw/less/issues. - Version 563: 13 Jun 2020 LESSECHO(1) + Version 581: 06 Apr 2021 LESSECHO(1) diff --git a/lessecho.nro b/lessecho.nro index d6d367b55429..ef822fabdafb 100644 --- a/lessecho.nro +++ b/lessecho.nro @@ -1,4 +1,4 @@ -.TH LESSECHO 1 "Version 563: 13 Jun 2020" +.TH LESSECHO 1 "Version 581: 06 Apr 2021" .SH NAME lessecho \- expand metacharacters .SH SYNOPSIS @@ -19,7 +19,7 @@ are surrounded by quotes instead. .TP .B \-ox Specifies "x", rather than double-quote, to be the open quote character, -which is used if the -e- option is specified. +which is used if the \-e- option is specified. .TP .B \-cx Specifies "x" to be the close quote character. @@ -42,11 +42,11 @@ Specifies "n" to be the escape char for metachars, as an integer. .TP .B \-a Specifies that all arguments are to be quoted. -The default is that only arguments containing metacharacters are quoted +The default is that only arguments containing metacharacters are quoted. .SH "SEE ALSO" .BR less (1) .SH AUTHOR This manual page was written by Thomas Schoepf , for the Debian GNU/Linux system (but may be used by others). .PP -Send bug reports or comments to bug-less@gnu.org. +Report bugs at https://github.com/gwsw/less/issues. diff --git a/lesskey.c b/lesskey.c index 74cdcb2cb2cf..de7a9bfc8311 100644 --- a/lesskey.c +++ b/lesskey.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -9,73 +9,73 @@ /* - * lesskey [-o output] [input] + * lesskey [-o output] [input] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Make a .less file. - * If no input file is specified, standard input is used. - * If no output file is specified, $HOME/.less is used. + * Make a .less file. + * If no input file is specified, standard input is used. + * If no output file is specified, $HOME/.less is used. * - * The .less file is used to specify (to "less") user-defined - * key bindings. Basically any sequence of 1 to MAX_CMDLEN - * keystrokes may be bound to an existing less function. + * The .less file is used to specify (to "less") user-defined + * key bindings. Basically any sequence of 1 to MAX_CMDLEN + * keystrokes may be bound to an existing less function. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * The input file is an ascii file consisting of a - * sequence of lines of the form: - * string action [chars] + * The input file is an ascii file consisting of a + * sequence of lines of the form: + * string action [chars] * - * "string" is a sequence of command characters which form - * the new user-defined command. The command - * characters may be: - * 1. The actual character itself. - * 2. A character preceded by ^ to specify a - * control character (e.g. ^X means control-X). - * 3. A backslash followed by one to three octal digits - * to specify a character by its octal value. - * 4. A backslash followed by b, e, n, r or t - * to specify \b, ESC, \n, \r or \t, respectively. - * 5. Any character (other than those mentioned above) preceded - * by a \ to specify the character itself (characters which - * must be preceded by \ include ^, \, and whitespace. - * "action" is the name of a "less" action, from the table below. - * "chars" is an optional sequence of characters which is treated - * as keyboard input after the command is executed. + * "string" is a sequence of command characters which form + * the new user-defined command. The command + * characters may be: + * 1. The actual character itself. + * 2. A character preceded by ^ to specify a + * control character (e.g. ^X means control-X). + * 3. A backslash followed by one to three octal digits + * to specify a character by its octal value. + * 4. A backslash followed by b, e, n, r or t + * to specify \b, ESC, \n, \r or \t, respectively. + * 5. Any character (other than those mentioned above) preceded + * by a \ to specify the character itself (characters which + * must be preceded by \ include ^, \, and whitespace. + * "action" is the name of a "less" action, from the table below. + * "chars" is an optional sequence of characters which is treated + * as keyboard input after the command is executed. * - * Blank lines and lines which start with # are ignored, - * except for the special control lines: - * #command Signals the beginning of the command - * keys section. - * #line-edit Signals the beginning of the line-editing - * keys section. - * #env Signals the beginning of the environment - * variable section. - * #stop Stops command parsing in less; - * causes all default keys to be disabled. + * Blank lines and lines which start with # are ignored, + * except for the special control lines: + * #command Signals the beginning of the command + * keys section. + * #line-edit Signals the beginning of the line-editing + * keys section. + * #env Signals the beginning of the environment + * variable section. + * #stop Stops command parsing in less; + * causes all default keys to be disabled. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * The output file is a non-ascii file, consisting of a header, - * one or more sections, and a trailer. - * Each section begins with a section header, a section length word - * and the section data. Normally there are three sections: - * CMD_SECTION Definition of command keys. - * EDIT_SECTION Definition of editing keys. - * END_SECTION A special section header, with no - * length word or section data. + * The output file is a non-ascii file, consisting of a header, + * one or more sections, and a trailer. + * Each section begins with a section header, a section length word + * and the section data. Normally there are three sections: + * CMD_SECTION Definition of command keys. + * EDIT_SECTION Definition of editing keys. + * END_SECTION A special section header, with no + * length word or section data. * - * Section data consists of zero or more byte sequences of the form: - * string <0> - * or - * string <0> chars <0> + * Section data consists of zero or more byte sequences of the form: + * string <0> + * or + * string <0> chars <0> * - * "string" is the command string. - * "<0>" is one null byte. - * "" is one byte containing the action code (the A_xxx value). - * If action is ORed with A_EXTRA, the action byte is followed - * by the null-terminated "chars" string. + * "string" is the command string. + * "<0>" is one null byte. + * "" is one byte containing the action code (the A_xxx value). + * If action is ORed with A_EXTRA, the action byte is followed + * by the null-terminated "chars" string. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @@ -153,6 +153,7 @@ struct cmdname cmdnames[] = { "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 } @@ -160,26 +161,26 @@ struct cmdname cmdnames[] = 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 }, + { "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 } }; @@ -206,10 +207,10 @@ char filetrailer[] = { C1_END_LESSKEY_MAGIC, C2_END_LESSKEY_MAGIC }; -char cmdsection[1] = { CMD_SECTION }; -char editsection[1] = { EDIT_SECTION }; -char varsection[1] = { VAR_SECTION }; -char endsection[1] = { END_SECTION }; +char cmdsection[1] = { CMD_SECTION }; +char editsection[1] = { EDIT_SECTION }; +char varsection[1] = { VAR_SECTION }; +char endsection[1] = { END_SECTION }; char *infile = NULL; char *outfile = NULL ; @@ -459,7 +460,7 @@ tstr(pp, xlate) *pp = p+2; buf[0] = CONTROL(p[1]); buf[1] = '\0'; - if (buf[0] == CONTROL('K')) + if (xlate && buf[0] == CONTROL('K')) return tstr_control_k; return (buf); } @@ -478,7 +479,7 @@ tstr(pp, xlate) skipsp(s) char *s; { - while (*s == ' ' || *s == '\t') + while (*s == ' ' || *s == '\t') s++; return (s); } @@ -546,7 +547,7 @@ add_cmd_str(s) control_line(s) char *s; { -#define PREFIX(str,pat) (strncmp(str,pat,strlen(pat)) == 0) +#define PREFIX(str,pat) (strncmp(str,pat,strlen(pat)) == 0) if (PREFIX(s, "#line-edit")) { diff --git a/lesskey.h b/lesskey.h index 2c4b5d6ddde2..3a8f83682a90 100644 --- a/lesskey.h +++ b/lesskey.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -11,29 +11,29 @@ /* * Format of a lesskey file: * - * LESSKEY_MAGIC (4 bytes) - * sections... - * END_LESSKEY_MAGIC (4 bytes) + * LESSKEY_MAGIC (4 bytes) + * sections... + * END_LESSKEY_MAGIC (4 bytes) * * Each section is: * - * section_MAGIC (1 byte) - * section_length (2 bytes) - * key table (section_length bytes) + * section_MAGIC (1 byte) + * section_length (2 bytes) + * key table (section_length bytes) */ -#define C0_LESSKEY_MAGIC '\0' -#define C1_LESSKEY_MAGIC 'M' -#define C2_LESSKEY_MAGIC '+' -#define C3_LESSKEY_MAGIC 'G' +#define C0_LESSKEY_MAGIC '\0' +#define C1_LESSKEY_MAGIC 'M' +#define C2_LESSKEY_MAGIC '+' +#define C3_LESSKEY_MAGIC 'G' -#define CMD_SECTION 'c' -#define EDIT_SECTION 'e' -#define VAR_SECTION 'v' -#define END_SECTION 'x' +#define CMD_SECTION 'c' +#define EDIT_SECTION 'e' +#define VAR_SECTION 'v' +#define END_SECTION 'x' -#define C0_END_LESSKEY_MAGIC 'E' -#define C1_END_LESSKEY_MAGIC 'n' -#define C2_END_LESSKEY_MAGIC 'd' +#define C0_END_LESSKEY_MAGIC 'E' +#define C1_END_LESSKEY_MAGIC 'n' +#define C2_END_LESSKEY_MAGIC 'd' /* */ -#define KRADIX 64 +#define KRADIX 64 diff --git a/lesskey.man b/lesskey.man index 413f6aa5a8a8..8692f3fead56 100644 --- a/lesskey.man +++ b/lesskey.man @@ -16,24 +16,25 @@ LESSKEY(1) General Commands Manual LESSKEY(1) 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 speci- fied, 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 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, lesskey will overwrite it. + 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 unde- + fined. The output file is a binary file which is used by 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. Other- + wise, 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, lesskey will overwrite + it. - The -V or --version option causes lesskey to print its version number + The -V or --version option causes lesskey to print its version number and immediately exit. If -V or --version is present, other options and arguments are ignored. - The input file consists of one or more sections. Each section starts - with a line that identifies the type of section. Possible sections + The input file consists of one or more sections. Each section starts + with a line that identifies the type of section. Possible sections are: #command @@ -44,7 +45,7 @@ LESSKEY(1) General Commands Manual LESSKEY(1) #env Defines environment variables. - Blank lines and lines which start with a pound sign (#) are ignored, + Blank lines and lines which start with a pound sign (#) are ignored, except for the special section header lines. COMMAND SECTION @@ -52,18 +53,18 @@ LESSKEY(1) General Commands Manual LESSKEY(1) #command - If the command section is the first section in the file, this line may + 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: string action [extra-string] - Whitespace is any sequence of one or more spaces and/or tabs. The - string is the command key(s) which invoke the action. The string may + Whitespace is any sequence of one or more spaces and/or tabs. The + string is the command key(s) which invoke the action. The string may be a single command key, or a sequence of up to 15 keys. The action is - the name of the less action, from the list below. The characters in - the string 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 specify a character by its octal value. A backslash fol- + the name of the less action, from the list below. The characters in + the string 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 specify a character by its octal value. A backslash fol- lowed by certain characters specifies input characters as follows: \b BACKSPACE @@ -95,16 +96,17 @@ LESSKEY(1) General Commands Manual LESSKEY(1) \kx DELETE A backslash followed by any other character indicates that character is - to be taken literally. Characters which must be preceded by backslash + to be taken literally. Characters which must be preceded by backslash include caret, space, tab and the backslash itself. An action may be followed by an "extra" string. When such a command is entered while running less, the action is performed, and then the extra - string is parsed, just as if it were typed in to less. This feature - can be used in certain cases to extend the functionality of a command. - For example, see the "{" and ":t" commands in the example below. The - extra string has a special meaning for the "quit" action: when less - quits, first character of the extra string is used as its exit status. + string is parsed, just as if it were typed in to less. This feature + can be used in certain cases to extend the functionality of a command. + For example, see the "{" and ":t" commands in the example below. The + extra string has a special meaning for the "quit" action: when less + quits, the first character of the extra string is used as its exit sta- + tus. EXAMPLE The following input file describes the set of default command keys used @@ -127,9 +129,9 @@ LESSKEY(1) General Commands Manual LESSKEY(1) J forw-line-force K back-line-force Y back-line-force + d forw-scroll ^D forw-scroll - u back-scroll ^U back-scroll \40 forw-screen @@ -151,6 +153,7 @@ LESSKEY(1) General Commands Manual LESSKEY(1) ^R repaint ^L repaint \eu undo-hilite + \eU clear-search g goto-line \kh goto-line < goto-line @@ -192,10 +195,10 @@ LESSKEY(1) General Commands Manual LESSKEY(1) & filter m set-mark M set-mark-bottom + \em clear-mark ' goto-mark ^X^X goto-mark - E examine :e examine ^X^V examine @@ -332,7 +335,7 @@ LESSKEY(1) General Commands Manual LESSKEY(1) represented as \340 in a lesskey file. COPYRIGHT - Copyright (C) 1984-2020 Mark Nudelman + Copyright (C) 1984-2021 Mark Nudelman less is part of the GNU project and is free software. You can redis- tribute it and/or modify it under the terms of either (1) the GNU Gen- @@ -351,8 +354,8 @@ LESSKEY(1) General Commands Manual LESSKEY(1) AUTHOR Mark Nudelman - Send bug reports or comments to . + Report bugs at https://github.com/gwsw/less/issues. - Version 563: 13 Jun 2020 LESSKEY(1) + Version 581: 06 Apr 2021 LESSKEY(1) diff --git a/lesskey.nro b/lesskey.nro index 5b8cbe4a2d2a..a9aec69fea0f 100644 --- a/lesskey.nro +++ b/lesskey.nro @@ -1,5 +1,5 @@ '\" t -.TH LESSKEY 1 "Version 563: 13 Jun 2020" +.TH LESSKEY 1 "Version 581: 06 Apr 2021" .SH NAME lesskey \- specify key bindings for less .SH SYNOPSIS @@ -18,10 +18,10 @@ 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. +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, @@ -29,10 +29,10 @@ 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. +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, .I lesskey will overwrite it. @@ -123,7 +123,7 @@ For example, see the "{" and ":t" commands in the example below. The extra string has a special meaning for the "quit" action: when .I less -quits, first character of the extra string is used as its exit status. +quits, the first character of the extra string is used as its exit status. . .SH EXAMPLE The following input file describes the set of @@ -171,6 +171,7 @@ r repaint ^R repaint ^L repaint \eeu undo-hilite +\eeU clear-search g goto-line \ekh goto-line < goto-line @@ -370,7 +371,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-2020 Mark Nudelman +Copyright (C) 1984-2021 Mark Nudelman .PP less is part of the GNU project and is free software. You can redistribute it and/or modify it @@ -395,4 +396,4 @@ See the GNU General Public License for more details. . Mark Nudelman .br -Send bug reports or comments to . +Report bugs at https://github.com/gwsw/less/issues. diff --git a/lglob.h b/lglob.h index e13e7982ffe9..2e5e74ec1900 100644 --- a/lglob.h +++ b/lglob.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -11,81 +11,81 @@ /* * Macros to define the method of doing filename "globbing". * There are three possible mechanisms: - * 1. GLOB_LIST - * This defines a function that returns a list of matching filenames. + * 1. GLOB_LIST + * This defines a function that returns a list of matching filenames. * 2. GLOB_NAME - * This defines a function that steps thru the list of matching - * filenames, returning one name each time it is called. + * This defines a function that steps thru the list of matching + * filenames, returning one name each time it is called. * 3. GLOB_STRING - * This defines a function that returns the complete list of - * matching filenames as a single space-separated string. + * This defines a function that returns the complete list of + * matching filenames as a single space-separated string. */ #if OS2 -#define DECL_GLOB_LIST(list) char **list; char **pp; -#define GLOB_LIST(filename,list) list = _fnexplode(filename) -#define GLOB_LIST_FAILED(list) list == NULL -#define SCAN_GLOB_LIST(list,p) pp = list; *pp != NULL; pp++ -#define INIT_GLOB_LIST(list,p) p = *pp -#define GLOB_LIST_DONE(list) _fnexplodefree(list) +#define DECL_GLOB_LIST(list) char **list; char **pp; +#define GLOB_LIST(filename,list) list = _fnexplode(filename) +#define GLOB_LIST_FAILED(list) list == NULL +#define SCAN_GLOB_LIST(list,p) pp = list; *pp != NULL; pp++ +#define INIT_GLOB_LIST(list,p) p = *pp +#define GLOB_LIST_DONE(list) _fnexplodefree(list) #else #if MSDOS_COMPILER==DJGPPC -#define DECL_GLOB_LIST(list) glob_t list; int i; -#define GLOB_LIST(filename,list) glob(filename,GLOB_NOCHECK,0,&list) -#define GLOB_LIST_FAILED(list) 0 -#define SCAN_GLOB_LIST(list,p) i = 0; i < list.gl_pathc; i++ -#define INIT_GLOB_LIST(list,p) p = list.gl_pathv[i] -#define GLOB_LIST_DONE(list) globfree(&list) +#define DECL_GLOB_LIST(list) glob_t list; int i; +#define GLOB_LIST(filename,list) glob(filename,GLOB_NOCHECK,0,&list) +#define GLOB_LIST_FAILED(list) 0 +#define SCAN_GLOB_LIST(list,p) i = 0; i < list.gl_pathc; i++ +#define INIT_GLOB_LIST(list,p) p = list.gl_pathv[i] +#define GLOB_LIST_DONE(list) globfree(&list) #else #if MSDOS_COMPILER==MSOFTC || MSDOS_COMPILER==BORLANDC -#define GLOB_FIRST_NAME(filename,fndp,h) h = _dos_findfirst(filename, ~_A_VOLID, fndp) -#define GLOB_FIRST_FAILED(handle) ((handle) != 0) -#define GLOB_NEXT_NAME(handle,fndp) _dos_findnext(fndp) -#define GLOB_NAME_DONE(handle) -#define GLOB_NAME name -#define DECL_GLOB_NAME(fnd,drive,dir,fname,ext,handle) \ - struct find_t fnd; \ - char drive[_MAX_DRIVE]; \ - char dir[_MAX_DIR]; \ - char fname[_MAX_FNAME]; \ - char ext[_MAX_EXT]; \ - int handle; +#define GLOB_FIRST_NAME(filename,fndp,h) h = _dos_findfirst(filename, ~_A_VOLID, fndp) +#define GLOB_FIRST_FAILED(handle) ((handle) != 0) +#define GLOB_NEXT_NAME(handle,fndp) _dos_findnext(fndp) +#define GLOB_NAME_DONE(handle) +#define GLOB_NAME name +#define DECL_GLOB_NAME(fnd,drive,dir,fname,ext,handle) \ + struct find_t fnd; \ + char drive[_MAX_DRIVE]; \ + char dir[_MAX_DIR]; \ + char fname[_MAX_FNAME]; \ + char ext[_MAX_EXT]; \ + int handle; #else #if MSDOS_COMPILER==WIN32C && (defined(_MSC_VER) || defined(MINGW)) -#define GLOB_FIRST_NAME(filename,fndp,h) h = _findfirst(filename, fndp) -#define GLOB_FIRST_FAILED(handle) ((handle) == -1) -#define GLOB_NEXT_NAME(handle,fndp) _findnext(handle, fndp) -#define GLOB_NAME_DONE(handle) _findclose(handle) -#define GLOB_NAME name -#define DECL_GLOB_NAME(fnd,drive,dir,fname,ext,handle) \ - struct _finddata_t fnd; \ - char drive[_MAX_DRIVE]; \ - char dir[_MAX_DIR]; \ - char fname[_MAX_FNAME]; \ - char ext[_MAX_EXT]; \ - intptr_t handle; +#define GLOB_FIRST_NAME(filename,fndp,h) h = _findfirst(filename, fndp) +#define GLOB_FIRST_FAILED(handle) ((handle) == -1) +#define GLOB_NEXT_NAME(handle,fndp) _findnext(handle, fndp) +#define GLOB_NAME_DONE(handle) _findclose(handle) +#define GLOB_NAME name +#define DECL_GLOB_NAME(fnd,drive,dir,fname,ext,handle) \ + struct _finddata_t fnd; \ + char drive[_MAX_DRIVE]; \ + char dir[_MAX_DIR]; \ + char fname[_MAX_FNAME]; \ + char ext[_MAX_EXT]; \ + intptr_t handle; #else #if MSDOS_COMPILER==WIN32C && !defined(_MSC_VER) /* Borland C for Windows */ -#define GLOB_FIRST_NAME(filename,fndp,h) h = findfirst(filename, fndp, ~FA_LABEL) -#define GLOB_FIRST_FAILED(handle) ((handle) != 0) -#define GLOB_NEXT_NAME(handle,fndp) findnext(fndp) -#define GLOB_NAME_DONE(handle) -#define GLOB_NAME ff_name -#define DECL_GLOB_NAME(fnd,drive,dir,fname,ext,handle) \ - struct ffblk fnd; \ - char drive[MAXDRIVE]; \ - char dir[MAXDIR]; \ - char fname[MAXFILE]; \ - char ext[MAXEXT]; \ - int handle; +#define GLOB_FIRST_NAME(filename,fndp,h) h = findfirst(filename, fndp, ~FA_LABEL) +#define GLOB_FIRST_FAILED(handle) ((handle) != 0) +#define GLOB_NEXT_NAME(handle,fndp) findnext(fndp) +#define GLOB_NAME_DONE(handle) +#define GLOB_NAME ff_name +#define DECL_GLOB_NAME(fnd,drive,dir,fname,ext,handle) \ + struct ffblk fnd; \ + char drive[MAXDRIVE]; \ + char dir[MAXDIR]; \ + char fname[MAXFILE]; \ + char ext[MAXEXT]; \ + int handle; #endif #endif diff --git a/line.c b/line.c index 4a552319359f..57d3cbef2f4d 100644 --- a/line.c +++ b/line.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -22,26 +22,38 @@ #include #endif -static char *linebuf = NULL; /* Buffer which holds the current output line */ -static char *attr = NULL; /* Extension of linebuf to hold attributes */ -public int size_linebuf = 0; /* Size of line buffer (and attr buffer) */ +#define MAX_PFX_WIDTH (MAX_LINENUM_WIDTH + MAX_STATUSCOL_WIDTH + 1) +static struct { + char *buf; /* Buffer which holds the current output line */ + int *attr; /* Parallel to buf, to hold attributes */ + int print; /* Index in buf of first printable char */ + int end; /* Number of chars in buf */ + char pfx[MAX_PFX_WIDTH]; /* Holds status column and line number */ + int pfx_attr[MAX_PFX_WIDTH]; + int pfx_end; /* Number of chars in pfx */ +} linebuf; -static int cshift; /* Current left-shift of output line buffer */ -public int hshift; /* Desired left-shift of output line buffer */ +static struct { + char *buf; + int size; + int end; +} shifted_ansi; + +public int size_linebuf = 0; /* Size of line buffer (and attr buffer) */ +static struct ansi_state *line_ansi = NULL; +static int cshift; /* Current left-shift of output line buffer */ +public int hshift; /* Desired left-shift of output line buffer */ public int tabstops[TABSTOP_MAX] = { 0 }; /* Custom tabstops */ -public int ntabstops = 1; /* Number of tabstops */ -public int tabdefault = 8; /* Default repeated tabstops */ -public POSITION highest_hilite; /* Pos of last hilite in file found so far */ +public int ntabstops = 1; /* Number of tabstops */ +public int tabdefault = 8; /* Default repeated tabstops */ +public POSITION highest_hilite; /* Pos of last hilite in file found so far */ -static int curr; /* Index into linebuf */ -static int column; /* Printable length, accounting for - backspaces, etc. */ +static int end_column; /* Printable length, accounting for backspaces, etc. */ static int right_curr; static int right_column; -static int overstrike; /* Next char should overstrike previous char */ +static int overstrike; /* Next char should overstrike previous char */ static int last_overstrike = AT_NORMAL; -static int is_null_line; /* There is no current line */ -static int lmargin; /* Left margin */ +static int is_null_line; /* There is no current line */ static LWCHAR pendc; static POSITION pendpos; static char *end_ansi_chars; @@ -58,6 +70,8 @@ extern int ctldisp; extern int twiddle; extern int binattr; extern int status_col; +extern int status_col_width; +extern int linenum_width; extern int auto_wrap, ignaw; extern int bo_s_width, bo_e_width; extern int ul_s_width, ul_e_width; @@ -69,12 +83,37 @@ extern POSITION start_attnpos; extern POSITION end_attnpos; extern char rscroll_char; extern int rscroll_attr; +extern int use_color; static char mbc_buf[MAX_UTF_CHAR_LEN]; static int mbc_buf_len = 0; static int mbc_buf_index = 0; static POSITION mbc_pos; +/* Configurable color map */ +static char color_map[AT_NUM_COLORS][12] = { + "Wm", /* AT_COLOR_ATTN */ + "kR", /* AT_COLOR_BIN */ + "kR", /* AT_COLOR_CTRL */ + "kY", /* AT_COLOR_ERROR */ + "c", /* AT_COLOR_LINENUM */ + "Wb", /* AT_COLOR_MARK */ + "kC", /* AT_COLOR_PROMPT */ + "kc", /* AT_COLOR_RSCROLL */ + "kG", /* AT_COLOR_SEARCH */ + "", /* AT_UNDERLINE */ + "", /* AT_BOLD */ + "", /* AT_BLINK */ + "", /* AT_STANDOUT */ +}; + +/* State while processing an ANSI escape sequence */ +struct ansi_state { + int hindex; /* Index into hyperlink prefix */ + int hlink; /* Processing hyperlink address? */ + int prev_esc; /* Prev char was ESC (to detect ESC-\ seq) */ +}; + /* * Initialize from environment variables. */ @@ -89,9 +128,11 @@ init_line(VOID_PARAM) if (isnullenv(mid_ansi_chars)) mid_ansi_chars = "0123456789:;[?!\"'#%()*+ "; - linebuf = (char *) ecalloc(LINEBUF_SIZE, sizeof(char)); - attr = (char *) ecalloc(LINEBUF_SIZE, sizeof(char)); + 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; } /* @@ -105,11 +146,11 @@ expand_linebuf(VOID_PARAM) /* Just realloc to expand the buffer, if we can. */ #if HAVE_REALLOC - char *new_buf = (char *) realloc(linebuf, new_size); - char *new_attr = (char *) realloc(attr, new_size); + char *new_buf = (char *) realloc(linebuf.buf, new_size); + int *new_attr = (int *) realloc(linebuf.attr, new_size*sizeof(int)); #else char *new_buf = (char *) calloc(new_size, sizeof(char)); - char *new_attr = (char *) calloc(new_size, sizeof(char)); + int *new_attr = (int *) calloc(new_size, sizeof(int)); #endif if (new_buf == NULL || new_attr == NULL) { @@ -123,13 +164,13 @@ expand_linebuf(VOID_PARAM) /* * We just calloc'd the buffers; copy the old contents. */ - memcpy(new_buf, linebuf, size_linebuf * sizeof(char)); - memcpy(new_attr, attr, size_linebuf * sizeof(char)); - free(attr); - free(linebuf); + memcpy(new_buf, linebuf.buf, size_linebuf * sizeof(char)); + memcpy(new_attr, linebuf.attr, size_linebuf * sizeof(int)); + free(linebuf.attr); + free(linebuf.buf); #endif - linebuf = new_buf; - attr = new_attr; + linebuf.buf = new_buf; + linebuf.attr = new_attr; size_linebuf = new_size; return 0; } @@ -144,14 +185,35 @@ is_ascii_char(ch) return (ch <= 0x7F); } +/* + */ + static void +inc_end_column(w) + int w; +{ + if (end_column > right_column && w > 0) + { + right_column = end_column; + right_curr = linebuf.end; + } + end_column += w; +} + /* * Rewind the line buffer. */ public void prewind(VOID_PARAM) { - curr = 0; - column = 0; + linebuf.print = 6; /* big enough for longest UTF-8 sequence */ + linebuf.pfx_end = 0; + for (linebuf.end = 0; linebuf.end < linebuf.print; linebuf.end++) + { + linebuf.buf[linebuf.end] = '\0'; + linebuf.attr[linebuf.end] = 0; + } + + end_column = 0; right_curr = 0; right_column = 0; cshift = 0; @@ -160,42 +222,64 @@ prewind(VOID_PARAM) mbc_buf_len = 0; is_null_line = 0; pendc = '\0'; - lmargin = 0; - if (status_col) - lmargin += 2; + shifted_ansi.end = 0; } /* * Set a character in the line buffer. */ static void -set_linebuf(n, ch, a) +set_linebuf(n, ch, attr) int n; char ch; - char a; + int attr; { - linebuf[n] = ch; - attr[n] = a; + linebuf.buf[n] = ch; + linebuf.attr[n] = attr; } /* * Append a character to the line buffer. */ static void -add_linebuf(ch, a, w) +add_linebuf(ch, attr, w) char ch; - char a; + int attr; int w; { - set_linebuf(curr++, ch, a); - column += w; + set_linebuf(linebuf.end++, ch, attr); + inc_end_column(w); } /* - * Insert the line number (of the given position) into the line buffer. + * Set a character in the line prefix buffer. + */ + static void +set_pfx(n, ch, attr) + int n; + char ch; + int attr; +{ + linebuf.pfx[n] = ch; + linebuf.pfx_attr[n] = attr; +} + +/* + * Append a character to the line prefix buffer. + */ + static void +add_pfx(ch, attr) + char ch; + int attr; +{ + set_pfx(linebuf.pfx_end++, ch, attr); +} + +/* + * Insert the status column and line number into the line buffer. */ public void -plinenum(pos) +plinestart(pos) POSITION pos; { LINENUM linenum = 0; @@ -207,7 +291,7 @@ plinenum(pos) * Get the line number and put it in the current line. * {{ Note: since find_linenum calls forw_raw_line, * it may seek in the input file, requiring the caller - * of plinenum to re-seek if necessary. }} + * of plinestart to re-seek if necessary. }} * {{ Since forw_raw_line modifies linebuf, we must * do this first, before storing anything in linebuf. }} */ @@ -222,16 +306,17 @@ plinenum(pos) int a = AT_NORMAL; char c = posmark(pos); if (c != 0) - a |= AT_HILITE; + a |= AT_HILITE|AT_COLOR_MARK; else { c = ' '; if (start_attnpos != NULL_POSITION && pos >= start_attnpos && pos <= end_attnpos) - a |= AT_HILITE; + a |= AT_HILITE|AT_COLOR_ATTN; } - add_linebuf(c, a, 1); /* column 0: status */ - add_linebuf(' ', AT_NORMAL, 1); /* column 1: empty */ + add_pfx(c, a); /* column 0: status */ + while (linebuf.pfx_end < status_col_width) + add_pfx(' ', AT_NORMAL); } /* @@ -241,155 +326,67 @@ plinenum(pos) if (linenums == OPT_ONPLUS) { char buf[INT_STRLEN_BOUND(linenum) + 2]; - int pad = 0; - int n; + int len; linenumtoa(linenum, buf); - n = (int) strlen(buf); - if (n < MIN_LINENUM_WIDTH) - pad = MIN_LINENUM_WIDTH - n; - for (i = 0; i < pad; i++) - add_linebuf(' ', AT_NORMAL, 1); - for (i = 0; i < n; i++) - add_linebuf(buf[i], AT_BOLD, 1); - add_linebuf(' ', AT_NORMAL, 1); - lmargin += n + pad + 1; - } - /* - * Append enough spaces to bring us to the lmargin. - */ - while (column < lmargin) - { - add_linebuf(' ', AT_NORMAL, 1); + len = (int) strlen(buf); + for (i = 0; i < linenum_width - len; i++) + add_pfx(' ', AT_NORMAL); + for (i = 0; i < len; i++) + add_pfx(buf[i], AT_NORMAL|AT_COLOR_LINENUM); + add_pfx(' ', AT_NORMAL); } + end_column = linebuf.pfx_end; } /* - * Shift the input line left. - * This means discarding N printable chars at the start of the buffer. + * Return the width of the line prefix (status column and line number). + * {{ Actual line number can be wider than linenum_width. }} + */ + public int +line_pfx_width(VOID_PARAM) +{ + int width = 0; + if (status_col) + width += status_col_width; + if (linenums == OPT_ONPLUS) + width += linenum_width + 1; + return width; +} + +/* + * Add char to the shifted_ansi buffer. */ static void -pshift(shift) - int shift; +add_ansi(ch) + char ch; { - LWCHAR prev_ch = 0; - unsigned char c; - int shifted = 0; - int to; - int from; - int len; - int width; - int prev_attr; - int next_attr; - - if (shift > column - lmargin) - shift = column - lmargin; - if (shift > curr - lmargin) - shift = curr - lmargin; - - to = from = lmargin; - /* - * We keep on going when shifted == shift - * to get all combining chars. - */ - while (shifted <= shift && from < curr) + if (shifted_ansi.end == shifted_ansi.size) { - c = linebuf[from]; - if (ctldisp == OPT_ONPLUS && IS_CSI_START(c)) - { - /* Keep cumulative effect. */ - linebuf[to] = c; - attr[to++] = attr[from++]; - while (from < curr && linebuf[from]) - { - linebuf[to] = linebuf[from]; - attr[to++] = attr[from]; - if (!is_ansi_middle(linebuf[from++])) - break; - } - continue; - } - - width = 0; - - if (!IS_ASCII_OCTET(c) && utf_mode) - { - /* Assumes well-formedness validation already done. */ - LWCHAR ch; - - len = utf_len(c); - if (from + len > curr) - break; - ch = get_wchar(linebuf + from); - if (!is_composing_char(ch) && !is_combining_char(prev_ch, ch)) - width = is_wide_char(ch) ? 2 : 1; - prev_ch = ch; - } else - { - len = 1; - if (c == '\b') - /* XXX - Incorrect if several '\b' in a row. */ - width = (utf_mode && is_wide_char(prev_ch)) ? -2 : -1; - else if (!control_char(c)) - width = 1; - prev_ch = 0; - } - - if (width == 2 && shift - shifted == 1) { - /* Should never happen when called by pshift_all(). */ - attr[to] = attr[from]; - /* - * Assume a wide_char will never be the first half of a - * combining_char pair, so reset prev_ch in case we're - * followed by a '\b'. - */ - prev_ch = linebuf[to++] = ' '; - from += len; - shifted++; - continue; - } - - /* Adjust width for magic cookies. */ - prev_attr = (to > 0) ? attr[to-1] : AT_NORMAL; - next_attr = (from + len < curr) ? attr[from + len] : prev_attr; - if (!is_at_equiv(attr[from], prev_attr) && - !is_at_equiv(attr[from], next_attr)) - { - width += attr_swidth(attr[from]); - if (from + len < curr) - width += attr_ewidth(attr[from]); - if (is_at_equiv(prev_attr, next_attr)) - { - width += attr_ewidth(prev_attr); - if (from + len < curr) - width += attr_swidth(next_attr); - } - } - - if (shift - shifted < width) - break; - from += len; - shifted += width; - if (shifted < 0) - shifted = 0; + /* 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; } - while (from < curr) - { - linebuf[to] = linebuf[from]; - attr[to++] = attr[from++]; - } - curr = to; - column -= shifted; - cshift += shifted; + 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. */ public void pshift_all(VOID_PARAM) { - pshift(column); + int i; + for (i = linebuf.print; i < linebuf.end; i++) + if (linebuf.attr[i] == AT_ANSI) + add_ansi(linebuf.buf[i]); + linebuf.end = linebuf.print; + end_column = linebuf.pfx_end; } /* @@ -442,24 +439,28 @@ attr_ewidth(a) /* * Return the printing width of a given character and attribute, - * if the character were added to the current position in the line buffer. + * if the character were added after prev_ch. * Adding a character with a given attribute may cause an enter or exit * attribute sequence to be inserted, so this must be taken into account. */ - static int -pwidth(ch, a, prev_ch) + public int +pwidth(ch, a, prev_ch, prev_a) LWCHAR ch; int a; LWCHAR prev_ch; + int prev_a; { int w; if (ch == '\b') + { /* * Backspace moves backwards one or two positions. - * XXX - Incorrect if several '\b' in a row. */ + if (prev_a & (AT_ANSI|AT_BINARY)) + return strlen(prchar('\b')); return (utf_mode && is_wide_char(prev_ch)) ? -2 : -1; + } if (!utf_mode || is_ascii_char(ch)) { @@ -481,7 +482,7 @@ pwidth(ch, a, prev_ch) * * Some terminals, upon failure to compose a * composing character with the character(s) that - * precede(s) it will actually take up one column + * precede(s) it will actually take up one end_column * for the composing character; there isn't much * we could do short of testing the (complex) * composition process ourselves and printing @@ -498,64 +499,42 @@ pwidth(ch, a, prev_ch) w = 1; if (is_wide_char(ch)) w++; - if (curr > 0 && !is_at_equiv(attr[curr-1], a)) - w += attr_ewidth(attr[curr-1]); - if ((apply_at_specials(a) != AT_NORMAL) && - (curr == 0 || !is_at_equiv(attr[curr-1], a))) + if (linebuf.end > 0 && !is_at_equiv(linebuf.attr[linebuf.end-1], a)) + w += attr_ewidth(linebuf.attr[linebuf.end-1]); + if (apply_at_specials(a) != AT_NORMAL && + (linebuf.end == 0 || !is_at_equiv(linebuf.attr[linebuf.end-1], a))) w += attr_swidth(a); return (w); } /* * Delete to the previous base character in the line buffer. - * Return 1 if one is found. */ static int backc(VOID_PARAM) { - LWCHAR prev_ch; - char *p = linebuf + curr; - LWCHAR ch = step_char(&p, -1, linebuf + lmargin); - int width; - - /* This assumes that there is no '\b' in linebuf. */ - while ( curr > lmargin - && column > lmargin - && (!(attr[curr - 1] & (AT_ANSI|AT_BINARY)))) - { - curr = (int) (p - linebuf); - prev_ch = step_char(&p, -1, linebuf + lmargin); - width = pwidth(ch, attr[curr], prev_ch); - column -= width; - if (width > 0) - return 1; - ch = prev_ch; - } - - return 0; -} - -/* - * Are we currently within a recognized ANSI escape sequence? - */ - static int -in_ansi_esc_seq(VOID_PARAM) -{ + LWCHAR ch; char *p; - /* - * Search backwards for either an ESC (which means we ARE in a seq); - * or an end char (which means we're NOT in a seq). - */ - for (p = &linebuf[curr]; p > linebuf; ) + if (linebuf.end == 0) + return (0); + p = &linebuf.buf[linebuf.end]; + ch = step_char(&p, -1, linebuf.buf); + /* Skip back to the next nonzero-width char. */ + while (p > linebuf.buf) { - LWCHAR ch = step_char(&p, -1, linebuf); - if (IS_CSI_START(ch)) - return (1); - if (!is_ansi_middle(ch)) - return (0); + LWCHAR prev_ch; + int width; + linebuf.end = (int) (p - linebuf.buf); + prev_ch = step_char(&p, -1, linebuf.buf); + width = pwidth(ch, linebuf.attr[linebuf.end], prev_ch, linebuf.attr[linebuf.end-1]); + end_column -= width; + /* {{ right_column? }} */ + if (width > 0) + break; + ch = prev_ch; } - return (0); + return (1); } /* @@ -589,22 +568,91 @@ is_ansi_middle(ch) * pp is initially positioned just after the CSI_START char. */ public void -skip_ansi(pp, limit) +skip_ansi(pansi, pp, limit) + struct ansi_state *pansi; char **pp; constant char *limit; { LWCHAR c; do { c = step_char(pp, +1, limit); - } while (*pp < limit && is_ansi_middle(c)); - /* Note that we discard final char, for which is_ansi_middle is false. */ + } while (*pp < limit && ansi_step(pansi, c) == ANSI_MID); + /* Note that we discard final char, for which is_ansi_end is true. */ } +/* + * Determine if a character starts an ANSI escape sequence. + * If so, return an ansi_state struct; otherwise return NULL. + */ + public struct ansi_state * +ansi_start(ch) + LWCHAR ch; +{ + struct ansi_state *pansi; + + if (!IS_CSI_START(ch)) + return NULL; + pansi = ecalloc(1, sizeof(struct ansi_state)); + pansi->hindex = 0; + pansi->hlink = 0; + pansi->prev_esc = 0; + return pansi; +} + +/* + * Determine whether the next char in an ANSI escape sequence + * ends the sequence. + */ + public int +ansi_step(pansi, ch) + struct ansi_state *pansi; + LWCHAR ch; +{ + if (pansi->hlink) + { + /* Hyperlink ends with \7 or ESC-backslash. */ + if (ch == '\7') + return ANSI_END; + if (pansi->prev_esc && ch == '\\') + return ANSI_END; + pansi->prev_esc = (ch == ESC); + return ANSI_MID; + } + if (pansi->hindex >= 0) + { + static char hlink_prefix[] = ESCS "]8;"; + if (ch == hlink_prefix[pansi->hindex] || + (pansi->hindex == 0 && IS_CSI_START(ch))) + { + pansi->hindex++; + if (hlink_prefix[pansi->hindex] == '\0') + pansi->hlink = 1; /* now processing hyperlink addr */ + return ANSI_MID; + } + pansi->hindex = -1; /* not a hyperlink */ + } + /* Check for SGR sequences */ + if (is_ansi_middle(ch)) + return ANSI_MID; + if (is_ansi_end(ch)) + return ANSI_END; + return ANSI_ERR; +} + +/* + * Free an ansi_state structure. + */ + public void +ansi_done(pansi) + struct ansi_state *pansi; +{ + free(pansi); +} /* * Append a character and attribute to the line buffer. */ -#define STORE_CHAR(ch,a,rep,pos) \ +#define STORE_CHAR(ch,a,rep,pos) \ do { \ if (store_char((ch),(a),(rep),(pos))) return (1); \ } while (0) @@ -617,17 +665,19 @@ store_char(ch, a, rep, pos) POSITION pos; { int w; + int i; int replen; char cs; - w = (a & (AT_UNDERLINE|AT_BOLD)); /* Pre-use w. */ - if (w != AT_NORMAL) - last_overstrike = w; + i = (a & (AT_UNDERLINE|AT_BOLD)); + if (i != AT_NORMAL) + last_overstrike = i; #if HILITE_SEARCH { int matches; - if (is_hilited(pos, pos+1, 0, &matches)) + int hl_attr = is_hilited_attr(pos, pos+1, 0, &matches); + if (hl_attr) { /* * This character should be highlighted. @@ -635,43 +685,24 @@ store_char(ch, a, rep, pos) */ if (a != AT_ANSI) { - if (highest_hilite != NULL_POSITION && - pos > highest_hilite) - highest_hilite = pos; - a |= AT_HILITE; + if (highest_hilite != NULL_POSITION && pos > highest_hilite) + highest_hilite = pos; + a |= hl_attr; } } } #endif - if (ctldisp == OPT_ONPLUS && in_ansi_esc_seq()) - { - if (!is_ansi_end(ch) && !is_ansi_middle(ch)) { - /* Remove whole unrecognized sequence. */ - char *p = &linebuf[curr]; - LWCHAR bch; - do { - bch = step_char(&p, -1, linebuf); - } while (p > linebuf && !IS_CSI_START(bch)); - curr = (int) (p - linebuf); - return 0; - } - a = AT_ANSI; /* Will force re-AT_'ing around it. */ + if (a == AT_ANSI) { w = 0; - } - else if (ctldisp == OPT_ONPLUS && IS_CSI_START(ch)) - { - a = AT_ANSI; /* Will force re-AT_'ing around it. */ - w = 0; - } - else - { - char *p = &linebuf[curr]; - LWCHAR prev_ch = step_char(&p, -1, linebuf); - w = pwidth(ch, a, prev_ch); + } else { + char *p = &linebuf.buf[linebuf.end]; + LWCHAR prev_ch = (linebuf.end > 0) ? step_char(&p, -1, linebuf.buf) : 0; + int prev_a = (linebuf.end > 0) ? linebuf.attr[linebuf.end-1] : 0; + w = pwidth(ch, a, prev_ch, prev_a); } - if (ctldisp != OPT_ON && column + w + attr_ewidth(a) > sc_width) + if (ctldisp != OPT_ON && end_column - cshift + w + attr_ewidth(a) > sc_width) /* * Won't fit on screen. */ @@ -686,7 +717,7 @@ store_char(ch, a, rep, pos) { replen = utf_len(rep[0]); } - if (curr + replen >= size_linebuf-6) + if (linebuf.end + replen >= size_linebuf-6) { /* * Won't fit in line buffer. @@ -696,17 +727,42 @@ store_char(ch, a, rep, pos) return (1); } - if (column > right_column && w > 0) + if (cshift == hshift && shifted_ansi.end > 0) { - right_column = column; - right_curr = curr; + /* 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; } - - while (replen-- > 0) - { + /* Add the char to the buf, even if we will left-shift it next. */ + inc_end_column(w); + for (i = 0; i < replen; i++) add_linebuf(*rep++, a, 0); + + if (cshift < hshift) + { + /* We haven't left-shifted enough yet. */ + if (a == AT_ANSI) + add_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); + linebuf.end -= replen; + cshift += w; + /* + * If the char we just left-shifted was double width, + * the 2 spaces we shifted may be too much. + * Represent the "half char" at start of line with a highlighted space. + */ + while (cshift > hshift) + { + add_linebuf(' ', rscroll_attr, 0); + cshift--; + } + } } - column += w; return (0); } @@ -714,7 +770,7 @@ store_char(ch, a, rep, pos) * Append a tab to the line buffer. * Store spaces to represent the tab. */ -#define STORE_TAB(a,pos) \ +#define STORE_TAB(a,pos) \ do { if (store_tab((a),(pos))) return (1); } while (0) static int @@ -722,23 +778,20 @@ store_tab(attr, pos) int attr; POSITION pos; { - int to_tab = column + cshift - lmargin; - int i; + int to_tab = end_column - linebuf.pfx_end; if (ntabstops < 2 || to_tab >= tabstops[ntabstops-1]) to_tab = tabdefault - ((to_tab - tabstops[ntabstops-1]) % tabdefault); else { + int i; for (i = ntabstops - 2; i >= 0; i--) if (to_tab >= tabstops[i]) break; to_tab = tabstops[i+1] - to_tab; } - if (column + to_tab - 1 + pwidth(' ', attr, 0) + attr_ewidth(attr) > sc_width) - return 1; - do { STORE_CHAR(' ', attr, " ", pos); } while (--to_tab > 0); @@ -759,18 +812,8 @@ store_prchar(c, pos) * Convert to printable representation. */ s = prchar(c); - - /* - * Make sure we can get the entire representation - * of the character on this line. - */ - if (column + (int) strlen(s) - 1 + - pwidth(' ', binattr, 0) + attr_ewidth(binattr) > sc_width) - return 1; - for ( ; *s != 0; s++) - STORE_CHAR(*s, AT_BINARY, NULL, pos); - + STORE_CHAR(*s, AT_BINARY|AT_COLOR_CTRL, NULL, pos); return 0; } @@ -783,7 +826,6 @@ flush_mbc_buf(pos) for (i = 0; i < mbc_buf_index; i++) if (store_prchar(mbc_buf[i], pos)) return mbc_buf_index - i; - return 0; } @@ -875,19 +917,7 @@ pappend(c, pos) /* Handle new char. */ if (!r) goto retry; - } - } - - /* - * If we need to shift the line, do it. - * But wait until we get to at least the middle of the screen, - * so shifting it doesn't affect the chars we're currently - * pappending. (Bold & underline can get messed up otherwise.) - */ - if (cshift < hshift && column > sc_width / 2) - { - linebuf[curr] = '\0'; - pshift(hshift - cshift); + } } if (r) { @@ -897,38 +927,92 @@ pappend(c, pos) return (r); } + static int +store_control_char(ch, rep, pos) + LWCHAR ch; + char *rep; + POSITION pos; +{ + if (ctldisp == OPT_ON) + { + /* Output the character itself. */ + STORE_CHAR(ch, AT_NORMAL, rep, pos); + } else + { + /* Output a printable representation of the character. */ + STORE_PRCHAR((char) ch, pos); + } + return (0); +} + + static int +store_ansi(ch, rep, pos) + LWCHAR ch; + char *rep; + POSITION pos; +{ + switch (ansi_step(line_ansi, ch)) + { + case ANSI_MID: + STORE_CHAR(ch, AT_ANSI, rep, pos); + break; + case ANSI_END: + 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; + int *end = (cshift < hshift) ? &shifted_ansi.end : &linebuf.end; + char *p = start + *end; + LWCHAR bch; + do { + bch = step_char(&p, -1, start); + } while (p > start && !IS_CSI_START(bch)); + *end = (int) (p - start); + ansi_done(line_ansi); + line_ansi = NULL; + break; } + } + return (0); +} + + static int +store_bs(ch, rep, pos) + LWCHAR ch; + char *rep; + POSITION pos; +{ + if (bs_mode == BS_CONTROL) + return store_control_char(ch, rep, pos); + if (linebuf.end > 0 && + ((linebuf.end <= linebuf.print && linebuf.buf[linebuf.end-1] == '\0') || + (linebuf.end > 0 && linebuf.attr[linebuf.end - 1] & (AT_ANSI|AT_BINARY)))) + STORE_PRCHAR('\b', pos); + else if (bs_mode == BS_NORMAL) + STORE_CHAR(ch, AT_NORMAL, NULL, pos); + else if (bs_mode == BS_SPECIAL) + overstrike = backc(); + return 0; +} + static int do_append(ch, rep, pos) LWCHAR ch; char *rep; POSITION pos; { - int a; - LWCHAR prev_ch; + int a = AT_NORMAL; - a = AT_NORMAL; + if (ctldisp == OPT_ONPLUS && line_ansi == NULL) + line_ansi = ansi_start(ch); + + if (line_ansi != NULL) + return store_ansi(ch, rep, pos); if (ch == '\b') - { - if (bs_mode == BS_CONTROL) - goto do_control_char; - - /* - * A better test is needed here so we don't - * backspace over part of the printed - * representation of a binary character. - */ - if ( curr <= lmargin - || column <= lmargin - || (attr[curr - 1] & (AT_ANSI|AT_BINARY))) - STORE_PRCHAR('\b', pos); - else if (bs_mode == BS_NORMAL) - STORE_CHAR(ch, AT_NORMAL, NULL, pos); - else if (bs_mode == BS_SPECIAL) - overstrike = backc(); - - return 0; - } + return store_bs(ch, rep, pos); if (overstrike > 0) { @@ -937,18 +1021,19 @@ do_append(ch, rep, pos) * in the line buffer. This will cause either * underline (if a "_" is overstruck), * bold (if an identical character is overstruck), - * or just deletion of the character in the buffer. + * or just replacing the character in the buffer. */ + LWCHAR prev_ch; overstrike = utf_mode ? -1 : 0; if (utf_mode) { /* To be correct, this must be a base character. */ - prev_ch = get_wchar(linebuf + curr); + prev_ch = get_wchar(&linebuf.buf[linebuf.end]); } else { - prev_ch = (unsigned char) linebuf[curr]; + prev_ch = (unsigned char) linebuf.buf[linebuf.end]; } - a = attr[curr]; + a = linebuf.attr[linebuf.end]; if (ch == prev_ch) { /* @@ -972,7 +1057,7 @@ do_append(ch, rep, pos) { a |= AT_UNDERLINE; ch = prev_ch; - rep = linebuf + curr; + rep = &linebuf.buf[linebuf.end]; } else if (prev_ch == '_') { a |= AT_UNDERLINE; @@ -981,14 +1066,14 @@ do_append(ch, rep, pos) } else if (overstrike < 0) { if ( is_composing_char(ch) - || is_combining_char(get_wchar(linebuf + curr), ch)) + || is_combining_char(get_wchar(&linebuf.buf[linebuf.end]), ch)) /* Continuation of the same overstrike. */ a = last_overstrike; else overstrike = 0; } - if (ch == '\t') + if (ch == '\t') { /* * Expand a tab into spaces. @@ -996,42 +1081,27 @@ do_append(ch, rep, pos) switch (bs_mode) { case BS_CONTROL: - goto do_control_char; + return store_control_char(ch, rep, pos); case BS_NORMAL: case BS_SPECIAL: STORE_TAB(a, pos); break; } - } else if ((!utf_mode || is_ascii_char(ch)) && control_char((char)ch)) + return (0); + } + if ((!utf_mode || is_ascii_char(ch)) && control_char((char)ch)) { - do_control_char: - if (ctldisp == OPT_ON || (ctldisp == OPT_ONPLUS && IS_CSI_START(ch))) - { - /* - * Output as a normal character. - */ - STORE_CHAR(ch, AT_NORMAL, rep, pos); - } else - { - STORE_PRCHAR((char) ch, pos); - } + return store_control_char(ch, rep, pos); } else if (utf_mode && ctldisp != OPT_ON && is_ubin_char(ch)) { - char *s; - - s = prutfchar(ch); - - if (column + (int) strlen(s) - 1 + - pwidth(' ', binattr, 0) + attr_ewidth(binattr) > sc_width) - return (1); - + char *s = prutfchar(ch); for ( ; *s != 0; s++) STORE_CHAR(*s, AT_BINARY, NULL, pos); - } else + } else { STORE_CHAR(ch, a, rep, pos); } - return (0); + return (0); } /* @@ -1084,12 +1154,6 @@ pdone(endline, chopped, forw) */ (void) do_append(pendc, NULL, pendpos); - /* - * Make sure we've shifted the line, if we need to. - */ - if (cshift < hshift) - pshift(hshift - cshift); - if (chopped && rscroll_char) { /* @@ -1097,21 +1161,21 @@ pdone(endline, chopped, forw) * If we've already filled the rightmost screen char * (in the buffer), overwrite it. */ - if (column >= sc_width) + if (end_column >= sc_width + cshift) { /* We've already written in the rightmost char. */ - column = right_column; - curr = right_curr; + end_column = right_column; + linebuf.end = right_curr; } add_attr_normal(); - while (column < sc_width-1) + while (end_column < sc_width-1 + cshift) { /* * Space to last (rightmost) char on screen. * This may be necessary if the char we overwrote * was double-width. */ - add_linebuf(' ', AT_NORMAL, 1); + add_linebuf(' ', rscroll_attr, 1); } /* Print rscroll char. It must be single-width. */ add_linebuf(rscroll_char, rscroll_attr, 1); @@ -1133,11 +1197,11 @@ pdone(endline, chopped, forw) * the next line is blank. In that case the single newline output for * that blank line would be ignored!) */ - if (column < sc_width || !auto_wrap || (endline && ignaw) || ctldisp == OPT_ON) + if (end_column < sc_width + cshift || !auto_wrap || (endline && ignaw) || ctldisp == OPT_ON) { add_linebuf('\n', AT_NORMAL, 0); } - else if (ignaw && column >= sc_width && forw) + else if (ignaw && end_column >= sc_width + cshift && forw) { /* * Terminals with "ignaw" don't wrap until they *really* need @@ -1156,17 +1220,18 @@ pdone(endline, chopped, forw) add_linebuf(' ', AT_NORMAL, 1); add_linebuf('\b', AT_NORMAL, -1); } - set_linebuf(curr, '\0', AT_NORMAL); + set_linebuf(linebuf.end, '\0', AT_NORMAL); } /* * */ public void -set_status_col(c) +set_status_col(c, attr) int c; + int attr; { - set_linebuf(0, c, AT_NORMAL|AT_HILITE); + set_pfx(0, c, attr); } /* @@ -1199,8 +1264,14 @@ gline(i, ap) return i ? '\0' : '\n'; } - *ap = attr[i]; - return (linebuf[i] & 0xFF); + if (i < linebuf.pfx_end) + { + *ap = linebuf.pfx_attr[i]; + return linebuf.pfx[i]; + } + i += linebuf.print - linebuf.pfx_end; + *ap = linebuf.attr[i]; + return (linebuf.buf[i] & 0xFF); } /* @@ -1252,12 +1323,12 @@ forw_raw_line(curr_pos, linep, line_lenp) break; } } - linebuf[n++] = c; + linebuf.buf[n++] = c; c = ch_forw_get(); } - linebuf[n] = '\0'; + linebuf.buf[n] = '\0'; if (linep != NULL) - *linep = linebuf; + *linep = linebuf.buf; if (line_lenp != NULL) *line_lenp = n; return (new_pos); @@ -1282,7 +1353,7 @@ back_raw_line(curr_pos, linep, line_lenp) return (NULL_POSITION); n = size_linebuf; - linebuf[--n] = '\0'; + linebuf.buf[--n] = '\0'; for (;;) { c = ch_back_get(); @@ -1322,16 +1393,16 @@ back_raw_line(curr_pos, linep, line_lenp) /* * Shift the data to the end of the new linebuf. */ - for (fm = linebuf + old_size_linebuf - 1, - to = linebuf + size_linebuf - 1; - fm >= linebuf; fm--, to--) + for (fm = linebuf.buf + old_size_linebuf - 1, + to = linebuf.buf + size_linebuf - 1; + fm >= linebuf.buf; fm--, to--) *to = *fm; n = size_linebuf - old_size_linebuf; } - linebuf[--n] = c; + linebuf.buf[--n] = c; } if (linep != NULL) - *linep = &linebuf[n]; + *linep = &linebuf.buf[n]; if (line_lenp != NULL) *line_lenp = size_linebuf - 1 - n; return (new_pos); @@ -1350,16 +1421,80 @@ rrshift(VOID_PARAM) save_width = sc_width; sc_width = INT_MAX; - hshift = 0; pos = position(TOP); for (line = 0; line < sc_height && pos != NULL_POSITION; line++) { pos = forw_line(pos); - if (column > longest) - longest = column; + if (end_column > longest) + longest = end_column; } sc_width = save_width; if (longest < sc_width) return 0; return longest - sc_width; } + +/* + * Get the color_map index associated with a given attribute. + */ + static int +color_index(attr) + int attr; +{ + if (use_color) + { + switch (attr & AT_COLOR) + { + case AT_COLOR_ATTN: return 0; + case AT_COLOR_BIN: return 1; + case AT_COLOR_CTRL: return 2; + case AT_COLOR_ERROR: return 3; + case AT_COLOR_LINENUM: return 4; + case AT_COLOR_MARK: return 5; + case AT_COLOR_PROMPT: return 6; + case AT_COLOR_RSCROLL: return 7; + case AT_COLOR_SEARCH: return 8; + } + } + if (attr & AT_UNDERLINE) + return 9; + if (attr & AT_BOLD) + return 10; + if (attr & AT_BLINK) + return 11; + if (attr & AT_STANDOUT) + return 12; + return -1; +} + +/* + * Set the color string to use for a given attribute. + */ + public int +set_color_map(attr, colorstr) + int attr; + char *colorstr; +{ + int cx = color_index(attr); + if (cx < 0) + return -1; + if (strlen(colorstr)+1 > sizeof(color_map[cx])) + return -1; + if (*colorstr != '\0' && parse_color(colorstr, NULL, NULL) == CT_NULL) + return -1; + strcpy(color_map[cx], colorstr); + return 0; +} + +/* + * Get the color string to use for a given attribute. + */ + public char * +get_color_map(attr) + int attr; +{ + int cx = color_index(attr); + if (cx < 0) + return NULL; + return color_map[cx]; +} diff --git a/linenum.c b/linenum.c index 46c315497ebd..00cac60d14d3 100644 --- a/linenum.c +++ b/linenum.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -40,11 +40,11 @@ */ struct linenum_info { - struct linenum_info *next; /* Link to next in the list */ - struct linenum_info *prev; /* Line to previous in the list */ - POSITION pos; /* File position */ - POSITION gap; /* Gap between prev and next */ - LINENUM line; /* Line number */ + struct linenum_info *next; /* Link to next in the list */ + struct linenum_info *prev; /* Line to previous in the list */ + POSITION pos; /* File position */ + POSITION gap; /* Gap between prev and next */ + LINENUM line; /* Line number */ }; /* * "gap" needs some explanation: the gap of any particular line number @@ -55,14 +55,14 @@ 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 NPOOL 200 /* Size of line number pool */ -#define LONGTIME (2) /* In seconds */ +#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 *spare; /* We always keep one spare entry */ +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 *spare; /* We always keep one spare entry */ extern int linenums; extern int sigs; @@ -248,6 +248,8 @@ longish(VOID_PARAM) static void abort_long(VOID_PARAM) { + if (loopcount >= 0) + return; if (linenums == OPT_ONPLUS) /* * We were displaying line numbers, so need to repaint. @@ -308,6 +310,7 @@ find_linenum(pos) #if HAVE_TIME startime = get_time(); #endif + loopcount = 0; if (p == &anchor || pos - p->prev->pos < p->pos - pos) { /* @@ -316,7 +319,6 @@ find_linenum(pos) p = p->prev; if (ch_seek(p->pos)) return (0); - loopcount = 0; for (linenum = p->line, cpos = p->pos; cpos < pos; linenum++) { /* @@ -348,7 +350,6 @@ find_linenum(pos) */ if (ch_seek(p->pos)) return (0); - loopcount = 0; for (linenum = p->line, cpos = p->pos; cpos > pos; linenum--) { /* @@ -368,7 +369,7 @@ find_linenum(pos) */ add_lnum(linenum, cpos); } - + loopcount = 0; return (linenum); } diff --git a/lsystem.c b/lsystem.c index 5e51c06d0aa5..5c67526e1030 100644 --- a/lsystem.c +++ b/lsystem.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -97,7 +97,7 @@ lsystem(cmd, donemsg) * De-initialize the terminal and take out of raw mode. */ deinit(); - flush(); /* Make sure the deinit chars get out */ + flush(); /* Make sure the deinit chars get out */ raw_mode(0); #if MSDOS_COMPILER==WIN32C close_getchr(); @@ -116,11 +116,13 @@ lsystem(cmd, donemsg) */ inp = dup(0); close(0); +#if !MSDOS_COMPILER #if OS2 /* The __open() system call translates "/dev/tty" to "con". */ - if (__open("/dev/tty", OPEN_READ) < 0) + if (__open(tty_device(), OPEN_READ) < 0) #else - if (open("/dev/tty", OPEN_READ) < 0) + if (open(tty_device(), OPEN_READ) < 0) +#endif #endif dup(inp); #endif @@ -169,7 +171,7 @@ lsystem(cmd, donemsg) * also makes trouble with some DPMI servers). */ __djgpp_exception_toggle(); - system(cmd); + system(cmd); __djgpp_exception_toggle(); #else system(cmd); @@ -274,14 +276,14 @@ pipe_mark(c, cmd) tpos = ch_zero(); bpos = position(BOTTOM); - if (c == '.') - return (pipe_data(cmd, tpos, bpos)); - else if (mpos <= tpos) - return (pipe_data(cmd, mpos, bpos)); - else if (bpos == NULL_POSITION) - return (pipe_data(cmd, tpos, bpos)); - else - return (pipe_data(cmd, tpos, mpos)); + if (c == '.') + return (pipe_data(cmd, tpos, bpos)); + else if (mpos <= tpos) + return (pipe_data(cmd, mpos, bpos)); + else if (bpos == NULL_POSITION) + return (pipe_data(cmd, tpos, bpos)); + else + return (pipe_data(cmd, tpos, mpos)); } /* @@ -346,14 +348,14 @@ pipe_data(cmd, spos, epos) /* * Finish up the last line. */ - while (c != '\n' && c != EOI ) - { - c = ch_forw_get(); - if (c == EOI) - break; - if (putc(c, f) == EOF) - break; - } + while (c != '\n' && c != EOI ) + { + c = ch_forw_get(); + if (c == EOI) + break; + if (putc(c, f) == EOF) + break; + } pclose(f); diff --git a/main.c b/main.c index 784ca5beb210..724884243ed3 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -18,49 +18,49 @@ #include #endif -public char * every_first_cmd = NULL; -public int new_file; -public int is_tty; -public IFILE curr_ifile = NULL_IFILE; -public IFILE old_ifile = NULL_IFILE; +public char * every_first_cmd = NULL; +public int new_file; +public int is_tty; +public IFILE curr_ifile = NULL_IFILE; +public IFILE old_ifile = NULL_IFILE; public struct scrpos initial_scrpos; -public int any_display = FALSE; -public POSITION start_attnpos = NULL_POSITION; -public POSITION end_attnpos = NULL_POSITION; -public int wscroll; -public char * progname; -public int quitting; -public int secure; -public int dohelp; +public POSITION start_attnpos = NULL_POSITION; +public POSITION end_attnpos = NULL_POSITION; +public int wscroll; +public char * progname; +public int quitting; +public int secure; +public int dohelp; #if LOGFILE -public int logfile = -1; -public int force_logfile = FALSE; -public char * namelogfile = NULL; +public int logfile = -1; +public int force_logfile = FALSE; +public char * namelogfile = NULL; #endif #if EDITOR -public char * editor; -public char * editproto; +public char * editor; +public char * editproto; #endif #if TAGS -extern char * tags; -extern char * tagoption; -extern int jump_sline; +extern char * tags; +extern char * tagoption; +extern int jump_sline; #endif #ifdef WIN32 static char consoleTitle[256]; #endif -public int one_screen; -extern int less_is_more; -extern int missing_cap; -extern int know_dumb; -extern int pr_type; -extern int quit_if_one_screen; -extern int no_init; +public int one_screen; +extern int less_is_more; +extern int missing_cap; +extern int know_dumb; +extern int pr_type; +extern int quit_if_one_screen; +extern int no_init; +extern int errmsgs; /* @@ -82,10 +82,14 @@ main(argc, argv) progname = *argv++; argc--; +#if SECURE + secure = 1; +#else secure = 0; s = lgetenv("LESSSECURE"); if (!isnullenv(s)) secure = 1; +#endif #ifdef WIN32 if (getenv("HOME") == NULL) @@ -137,7 +141,7 @@ main(argc, argv) if (s != NULL) scan_option(save(s)); -#define isoptstring(s) (((s)[0] == '-' || (s)[0] == '+') && (s)[1] != '\0') +#define isoptstring(s) (((s)[0] == '-' || (s)[0] == '+') && (s)[1] != '\0') while (argc > 0 && (isoptstring(*argv) || isoptpending())) { s = *argv++; @@ -219,6 +223,7 @@ main(argc, argv) * Output is not a tty. * Just copy the input file(s) to output. */ + set_output(1); /* write to stdout */ SET_BINARY(1); if (edit_first() == 0) { @@ -282,6 +287,18 @@ main(argc, argv) } } + if (errmsgs > 0) + { + /* + * We displayed some messages on error output + * (file descriptor 2; see flush()). + * Before erasing the screen contents, wait for a keystroke. + */ + less_printf("Press RETURN to continue ", NULL_PARG); + get_return(); + putchr('\n'); + } + set_output(1); init(); commands(); quit(QUIT_OK); @@ -331,7 +348,7 @@ ecalloc(count, size) skipsp(s) char *s; { - while (*s == ' ' || *s == '\t') + while (*s == ' ' || *s == '\t') s++; return (s); } @@ -388,10 +405,13 @@ quit(status) status = save_status; else save_status = status; +#if LESSTEST + rstat('Q'); +#endif /*LESSTEST*/ quitting = 1; edit((char*)NULL); save_cmdhist(); - if (any_display && is_tty) + if (interactive()) clear_bot(); deinit(); flush(); diff --git a/mark.c b/mark.c index e86d7b31e69e..cbb316f276e6 100644 --- a/mark.c +++ b/mark.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -38,10 +38,10 @@ struct mark * Each mark is identified by a lowercase or uppercase letter. * The final one is lmark, for the "last mark"; addressed by the apostrophe. */ -#define NMARKS ((2*26)+2) /* a-z, A-Z, mousemark, lastmark */ -#define NUMARKS ((2*26)+1) /* user marks (not lastmark) */ -#define MOUSEMARK (NMARKS-2) -#define LASTMARK (NMARKS-1) +#define NMARKS ((2*26)+2) /* a-z, A-Z, mousemark, lastmark */ +#define NUMARKS ((2*26)+1) /* user marks (not lastmark) */ +#define MOUSEMARK (NMARKS-2) +#define LASTMARK (NMARKS-1) static struct mark marks[NMARKS]; public int marks_modified = 0; @@ -116,13 +116,17 @@ mark_get_ifile(m) getumark(c) int c; { + PARG parg; if (c >= 'a' && c <= 'z') return (&marks[c-'a']); if (c >= 'A' && c <= 'Z') return (&marks[c-'A'+26]); + if (c == '\'') + return (&marks[LASTMARK]); if (c == '#') return (&marks[MOUSEMARK]); - error("Invalid mark letter", NULL_PARG); + parg.p_char = (char) c; + error("Invalid mark letter %c", &parg); return (NULL); } @@ -259,6 +263,7 @@ lastmark(VOID_PARAM) if (scrpos.pos == NULL_POSITION) return; cmark(&marks[LASTMARK], curr_ifile, scrpos.pos, scrpos.ln); + marks_modified = 1; } /* @@ -370,7 +375,7 @@ mark_check_ifile(ifile) IFILE ifile; { int i; - char *filename = lrealpath(get_filename(ifile)); + char *filename = get_real_filename(ifile); for (i = 0; i < NMARKS; i++) { @@ -384,7 +389,6 @@ mark_check_ifile(ifile) free(mark_filename); } } - free(filename); } #if CMD_HISTORY @@ -403,7 +407,7 @@ save_marks(fout, hdr) return; fprintf(fout, "%s\n", hdr); - for (i = 0; i < NUMARKS; i++) + for (i = 0; i < NMARKS; i++) { char *filename; struct mark *m = &marks[i]; @@ -413,12 +417,10 @@ save_marks(fout, hdr) postoa(m->m_scrpos.pos, pos_str); filename = m->m_filename; if (filename == NULL) - filename = get_filename(m->m_ifile); - filename = lrealpath(filename); + filename = get_real_filename(m->m_ifile); if (strcmp(filename, "-") != 0) fprintf(fout, "m %c %d %s %s\n", m->m_letter, m->m_scrpos.ln, pos_str, filename); - free(filename); } } diff --git a/mkfuncs.pl b/mkfuncs.pl old mode 100644 new mode 100755 diff --git a/mkfuncs.py b/mkfuncs.py new file mode 100755 index 000000000000..7a2da5ad19ed --- /dev/null +++ b/mkfuncs.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python + +import fileinput +import re + +definition = '' +state = 0 +params = 0 + +for line in fileinput.input(): + if test := re.search(r'^\tpublic\s+(.*)', line): + definition = 'public ' + test.group(1) + state = 1 + params = 0 + elif (state == 1) and (test := re.search(r'(\w+)\s*\(', line)): + definition = '{0} LESSPARAMS (('.format(test.group(1)) + state = 2 + elif state == 2: + if re.search(r'^{', line): + if not params: definition += 'VOID_PARAM' + print(f'{definition}));') + state = 0 + elif test := re.search(r'^\s*([^;]*)', line): + if (definition[-1:] != '('): definition += ', ' + definition += test.group(1) + params = 1 diff --git a/mkhelp.py b/mkhelp.py new file mode 100755 index 000000000000..029f1505c2b6 --- /dev/null +++ b/mkhelp.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python + +import time +import sys + +time = time.gmtime() +print("/* This file was generated by mkhelp.py from less.hlp at "\ + "%d:%02d GMT on %d/%d/%d */\n" % + (time.tm_hour, time.tm_min, time.tm_year, time.tm_mon, time.tm_mday)) +print("#include \"less.h\"") +print("constant char helpdata[] = {") +ch = 0 +while True: + prevch = ch + ch = sys.stdin.read(1) + if ch == '': + break + if (ch == "'"): + print("'\\'',", end='') + elif (ch == "\\"): + print("'\\\\',", end='') + elif (ch == "\b"): + print ("'\\b',", end='') + elif (ch == "\t"): + print ("'\\t',", end='') + elif (ch == "\n"): + if prevch != "\r": print("'\\n',") + elif (ch == "\r"): + if prevch != "\n": print("'\\n',") + else: + if ((ord(ch) >= ord(' ')) and (ord(ch) < 0x7f)): + print(f"'{ch}',", end='') + else: + print("0x%02x," % ord(ch), end='') +print(" '\\0' };") +print("constant int size_helpdata = sizeof(helpdata) - 1;") diff --git a/optfunc.c b/optfunc.c index c04f9d4a2480..768fe0e98aed 100644 --- a/optfunc.c +++ b/optfunc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -19,9 +19,9 @@ * Each handling function is passed a "type" and, if it is a string * option, the string which should be "assigned" to the option. * The type may be one of: - * INIT The option is being initialized from the command line. - * TOGGLE The option is being changed from within the program. - * QUERY The setting of the option is merely being queried. + * INIT The option is being initialized from the command line. + * TOGGLE The option is being changed from within the program. + * QUERY The setting of the option is merely being queried. */ #include "less.h" @@ -36,7 +36,7 @@ extern int sc_width; extern int sc_height; extern int secure; extern int dohelp; -extern int any_display; +extern int is_tty; extern char openquote; extern char closequote; extern char *prproto[]; @@ -55,6 +55,9 @@ extern int rscroll_attr; extern int mousecap; extern int wheel_lines; extern int less_is_more; +extern int linenum_width; +extern int status_col_width; +extern int use_color; #if LOGFILE extern char *namelogfile; extern int force_logfile; @@ -65,6 +68,10 @@ public char *tagoption = NULL; extern char *tags; extern char ztags[]; #endif +#if LESSTEST +extern char *ttyin_name; +extern int rstat_file; +#endif /*LESSTEST*/ #if MSDOS_COMPILER extern int nm_fg_color, nm_bg_color; extern int bo_fg_color, bo_bg_color; @@ -395,13 +402,13 @@ opt_p(type, s) } else { plusoption = TRUE; - ungetcc(CHAR_END_COMMAND); - ungetsc(s); /* * {{ This won't work if the "/" command is * changed or invalidated by a .lesskey file. }} */ ungetsc("/"); + ungetsc(s); + ungetcc_back(CHAR_END_COMMAND); } break; } @@ -427,13 +434,13 @@ opt__P(type, s) */ switch (*s) { - case 's': proto = &prproto[PR_SHORT]; s++; break; - case 'm': proto = &prproto[PR_MEDIUM]; s++; break; - case 'M': proto = &prproto[PR_LONG]; s++; break; - case '=': proto = &eqproto; s++; break; - case 'h': proto = &hproto; s++; break; - case 'w': proto = &wproto; s++; break; - default: proto = &prproto[PR_SHORT]; break; + case 's': proto = &prproto[PR_SHORT]; s++; break; + case 'm': proto = &prproto[PR_MEDIUM]; s++; break; + case 'M': proto = &prproto[PR_LONG]; s++; break; + case '=': proto = &eqproto; s++; break; + case 'h': proto = &hproto; s++; break; + case 'w': proto = &wproto; s++; break; + default: proto = &prproto[PR_SHORT]; break; } free(*proto); *proto = save(s); @@ -504,20 +511,28 @@ opt__V(type, s) dispversion(); break; case INIT: - /* - * Force output to stdout per GNU standard for --version output. - */ - any_display = 1; + set_output(1); /* Force output to stdout per GNU standard for --version output. */ putstr("less "); putstr(version); putstr(" ("); putstr(pattern_lib_name()); putstr(" regular expressions)\n"); - putstr("Copyright (C) 1984-2020 Mark Nudelman\n\n"); + { + char constant *copyright = "Copyright (C) 1984-2021 Mark Nudelman\n\n"; + if (copyright[0] == '@') + copyright = "Copyright (C) 1984 Mark Nudelman\n\n"; + putstr(copyright); + } + if (version[strlen(version)-1] == 'x') + { + putstr("** This is an EXPERIMENTAL build of the 'less' software,\n"); + putstr("** and may not function correctly.\n"); + putstr("** Obtain release builds from the web page below.\n\n"); + } putstr("less comes with NO WARRANTY, to the extent permitted by law.\n"); putstr("For information about the terms of redistribution,\n"); putstr("see the file named README in the less distribution.\n"); - putstr("Home page: http://www.greenwoodsoftware.com/less\n"); + putstr("Home page: https://greenwoodsoftware.com/less\n"); quit(QUIT_OK); break; } @@ -527,60 +542,70 @@ opt__V(type, s) /* * Parse an MSDOS color descriptor. */ - static void + static void colordesc(s, fg_color, bg_color) char *s; int *fg_color; int *bg_color; { int fg, bg; - int err; #if MSDOS_COMPILER==WIN32C int ul = 0; - + if (*s == 'u') { ul = COMMON_LVB_UNDERSCORE; - ++s; - } -#endif - fg = getnum(&s, "D", &err); - if (err) - { -#if MSDOS_COMPILER==WIN32C - if (ul) - fg = nm_fg_color; - else -#endif - { - error("Missing fg color in -D", NULL_PARG); - return; - } - } - if (*s != '.') - bg = nm_bg_color; - else - { s++; - bg = getnum(&s, "D", &err); - if (err) + if (*s == '\0') { - error("Missing bg color in -D", NULL_PARG); + *fg_color = nm_fg_color | ul; + *bg_color = nm_bg_color; return; } } -#if MSDOS_COMPILER==WIN32C - if (*s == 'u') - { - ul = COMMON_LVB_UNDERSCORE; - ++s; - } - fg |= ul; #endif - if (*s != '\0') - error("Extra characters at end of -D option", NULL_PARG); - *fg_color = fg; - *bg_color = bg; + if (parse_color(s, &fg, &bg) == CT_NULL) + { + PARG p; + p.p_string = s; + error("Invalid color string \"%s\"", &p); + } else + { + if (fg == CV_NOCHANGE) + fg = nm_fg_color; + if (bg == CV_NOCHANGE) + bg = nm_bg_color; +#if MSDOS_COMPILER==WIN32C + fg |= ul; +#endif + *fg_color = fg; + *bg_color = bg; + } +} +#endif + + static int +color_from_namechar(namechar) + char namechar; +{ + switch (namechar) + { + case 'A': return AT_COLOR_ATTN; + case 'B': return AT_COLOR_BIN; + case 'C': return AT_COLOR_CTRL; + case 'E': return AT_COLOR_ERROR; + case 'M': return AT_COLOR_MARK; + case 'N': return AT_COLOR_LINENUM; + case 'P': return AT_COLOR_PROMPT; + case 'R': return AT_COLOR_RSCROLL; + case 'S': return AT_COLOR_SEARCH; + case 'n': return AT_NORMAL; + case 's': return AT_STANDOUT; + case 'd': return AT_BOLD; + case 'u': return AT_UNDERLINE; + case 'k': return AT_BLINK; + default: return -1; + } } /* @@ -593,48 +618,75 @@ opt_D(type, s) char *s; { PARG p; + int attr; switch (type) { case INIT: case TOGGLE: - switch (*s++) +#if MSDOS_COMPILER + if (*s == 'a') { - case 'n': - colordesc(s, &nm_fg_color, &nm_bg_color); - break; - case 'd': - colordesc(s, &bo_fg_color, &bo_bg_color); - break; - case 'u': - colordesc(s, &ul_fg_color, &ul_bg_color); - break; - case 'k': - colordesc(s, &bl_fg_color, &bl_bg_color); - break; - case 's': - colordesc(s, &so_fg_color, &so_bg_color); - break; - case 'a': sgr_mode = !sgr_mode; break; - default: - error("-D must be followed by n, d, u, k, s or a", NULL_PARG); - break; } - if (type == TOGGLE) +#endif + attr = color_from_namechar(s[0]); + if (attr < 0) { - at_enter(AT_STANDOUT); - at_exit(); + p.p_char = s[0]; + error("Invalid color specifier '%c'", &p); + return; + } + if (!use_color && (attr & AT_COLOR)) + { + error("Set --use-color before changing colors", NULL_PARG); + return; + } + s++; +#if MSDOS_COMPILER + if (!(attr & AT_COLOR)) + { + switch (attr) + { + case AT_NORMAL: + colordesc(s, &nm_fg_color, &nm_bg_color); + break; + case AT_BOLD: + colordesc(s, &bo_fg_color, &bo_bg_color); + break; + case AT_UNDERLINE: + colordesc(s, &ul_fg_color, &ul_bg_color); + break; + case AT_BLINK: + colordesc(s, &bl_fg_color, &bl_bg_color); + break; + case AT_STANDOUT: + colordesc(s, &so_fg_color, &so_bg_color); + break; + } + if (type == TOGGLE) + { + at_enter(AT_STANDOUT); + at_exit(); + } + } else +#endif + if (set_color_map(attr, s) < 0) + { + p.p_string = s; + error("Invalid color string \"%s\"", &p); + return; } break; +#if MSDOS_COMPILER case QUERY: p.p_string = (sgr_mode) ? "on" : "off"; error("SGR mode is %s", &p); break; +#endif } } -#endif /* * Handler for the -x option. @@ -759,7 +811,7 @@ opt_rscroll(type, s) } else { rscroll_char = *fmt ? *fmt : '>'; - rscroll_attr = attr; + rscroll_attr = attr|AT_COLOR_RSCROLL; } break; } case QUERY: { @@ -834,6 +886,103 @@ opt_wheel_lines(type, s) } } +/* + * Handler for the --line-number-width option. + */ + /*ARGSUSED*/ + public void +opt_linenum_width(type, s) + int type; + char *s; +{ + PARG parg; + + switch (type) + { + case INIT: + case TOGGLE: + if (linenum_width > MAX_LINENUM_WIDTH) + { + parg.p_int = MAX_LINENUM_WIDTH; + error("Line number width must not be larger than %d", &parg); + linenum_width = MIN_LINENUM_WIDTH; + } + break; + case QUERY: + break; + } +} + +/* + * Handler for the --status-column-width option. + */ + /*ARGSUSED*/ + public void +opt_status_col_width(type, s) + int type; + char *s; +{ + PARG parg; + + switch (type) + { + case INIT: + case TOGGLE: + if (status_col_width > MAX_STATUSCOL_WIDTH) + { + parg.p_int = MAX_STATUSCOL_WIDTH; + error("Status column width must not be larger than %d", &parg); + status_col_width = 2; + } + break; + case QUERY: + break; + } +} + +#if LESSTEST +/* + * Handler for the --tty option. + */ + /*ARGSUSED*/ + public void +opt_ttyin_name(type, s) + int type; + char *s; +{ + switch (type) + { + case INIT: + ttyin_name = s; + is_tty = 1; + break; + } +} + +/* + * Handler for the --rstat option. + */ + /*ARGSUSED*/ + public void +opt_rstat(type, s) + int type; + char *s; +{ + switch (type) + { + case INIT: + rstat_file = open(s, O_WRONLY|O_CREAT, 0664); + if (rstat_file < 0) + { + PARG parg; + parg.p_string = s; + error("Cannot create rstat file \"%s\"", &parg); + } + break; + } +} +#endif /*LESSTEST*/ + /* * Get the "screen window" size. */ diff --git a/option.c b/option.c index 9cb19bc5472d..61247d81ee9b 100644 --- a/option.c +++ b/option.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -23,8 +23,7 @@ static struct loption *pendopt; public int plusoption = FALSE; -static char *optstring LESSPARAMS((char *s, char **p_str, char *printopt, - char *validchars)); +static char *optstring LESSPARAMS((char *s, char **p_str, char *printopt, char *validchars)); static int flip_triple LESSPARAMS((int val, int lc)); extern int screen_trashed; @@ -157,8 +156,8 @@ scan_option(s) every_first_cmd = save(str+1); } else { - ungetcc(CHAR_END_COMMAND); ungetsc(str); + ungetcc_back(CHAR_END_COMMAND); } free(str); continue; @@ -297,10 +296,10 @@ scan_option(s) * Toggle command line flags from within the program. * Used by the "-" and "_" commands. * how_toggle may be: - * OPT_NO_TOGGLE just report the current setting, without changing it. - * OPT_TOGGLE invert the current setting - * OPT_UNSET set to the default value - * OPT_SET set to the inverse of the default value + * OPT_NO_TOGGLE just report the current setting, without changing it. + * OPT_TOGGLE invert the current setting + * OPT_UNSET set to the default value + * OPT_SET set to the inverse of the default value */ public void toggle_option(o, lower, s, how_toggle) @@ -384,10 +383,10 @@ toggle_option(o, lower, s, how_toggle) case TRIPLE: /* * Triple: - * If user gave the lower case letter, then switch - * to 1 unless already 1, in which case make it 0. - * If user gave the upper case letter, then switch - * to 2 unless already 2, in which case make it 0. + * If user gave the lower case letter, then switch + * to 1 unless already 1, in which case make it 0. + * If user gave the upper case letter, then switch + * to 2 unless already 2, in which case make it 0. */ switch (how_toggle) { @@ -405,7 +404,7 @@ toggle_option(o, lower, s, how_toggle) case STRING: /* * String: don't do anything here. - * The handling function will do everything. + * The handling function will do everything. */ switch (how_toggle) { diff --git a/option.h b/option.h index c705aca19b48..4a10d6b8b228 100644 --- a/option.h +++ b/option.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -8,59 +8,59 @@ */ -#define END_OPTION_STRING ('$') +#define END_OPTION_STRING ('$') /* * 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 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 OTYPE (BOOL|TRIPLE|NUMBER|STRING|NOVAR) +#define OTYPE (BOOL|TRIPLE|NUMBER|STRING|NOVAR) #define OLETTER_NONE '\1' /* Invalid option letter */ /* * Argument to a handling function tells what type of activity: */ -#define INIT 0 /* Initialization (from command line) */ -#define QUERY 1 /* Query (from _ or - command) */ -#define TOGGLE 2 /* Change value (from - command) */ +#define INIT 0 /* Initialization (from command line) */ +#define QUERY 1 /* Query (from _ or - command) */ +#define TOGGLE 2 /* Change value (from - command) */ /* Flag to toggle_option to specify how to "toggle" */ -#define OPT_NO_TOGGLE 0 -#define OPT_TOGGLE 1 -#define OPT_UNSET 2 -#define OPT_SET 3 -#define OPT_NO_PROMPT 0100 +#define OPT_NO_TOGGLE 0 +#define OPT_TOGGLE 1 +#define OPT_UNSET 2 +#define OPT_SET 3 +#define OPT_NO_PROMPT 0100 /* Error code from findopt_name */ #define OPT_AMBIG 1 struct optname { - char *oname; /* Long (GNU-style) option name */ - struct optname *onext; /* List of synonymous option names */ + char *oname; /* Long (GNU-style) option name */ + struct optname *onext; /* List of synonymous option names */ }; -#define OPTNAME_MAX 32 /* Max length of long option name */ +#define OPTNAME_MAX 32 /* Max length of long option name */ struct loption { - char oletter; /* The controlling letter (a-z) */ - struct optname *onames; /* Long (GNU-style) option name */ - int otype; /* Type of the option */ - int odefault; /* Default value */ - int *ovar; /* Pointer to the associated variable */ - void (*ofunc) LESSPARAMS ((int, char*)); /* Pointer to special handling function */ - char *odesc[3]; /* Description of each value */ + char oletter; /* The controlling letter (a-z) */ + struct optname *onames; /* Long (GNU-style) option name */ + int otype; /* Type of the option */ + int odefault; /* Default value */ + int *ovar; /* Pointer to the associated variable */ + void (*ofunc) LESSPARAMS ((int, char*)); /* Pointer to special handling function */ + char *odesc[3]; /* Description of each value */ }; diff --git a/opttbl.c b/opttbl.c index 1871f8a027a3..3a5d28385162 100644 --- a/opttbl.c +++ b/opttbl.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -18,52 +18,56 @@ /* * Variables controlled by command line options. */ -public int quiet; /* Should we suppress the audible bell? */ -public int how_search; /* Where should forward searches start? */ -public int top_scroll; /* Repaint screen from top? - (alternative is scroll from bottom) */ -public int pr_type; /* Type of prompt (short, medium, long) */ -public int bs_mode; /* How to process backspaces */ -public int know_dumb; /* Don't complain about dumb terminals */ -public int quit_at_eof; /* Quit after hitting end of file twice */ -public int quit_if_one_screen; /* Quit if EOF on first screen */ -public int squeeze; /* Squeeze multiple blank lines into one */ -public int tabstop; /* Tab settings */ -public int back_scroll; /* Repaint screen on backwards movement */ -public int forw_scroll; /* Repaint screen on forward movement */ -public int caseless; /* Do "caseless" searches */ -public int linenums; /* Use line numbers */ -public int autobuf; /* Automatically allocate buffers as needed */ -public int bufspace; /* Max buffer space per file (K) */ -public int ctldisp; /* Send control chars to screen untranslated */ -public int force_open; /* Open the file even if not regular file */ -public int swindow; /* Size of scrolling window */ -public int jump_sline; /* Screen line of "jump target" */ +public int quiet; /* Should we suppress the audible bell? */ +public int how_search; /* Where should forward searches start? */ +public int top_scroll; /* Repaint screen from top? + (alternative is scroll from bottom) */ +public int pr_type; /* Type of prompt (short, medium, long) */ +public int bs_mode; /* How to process backspaces */ +public int know_dumb; /* Don't complain about dumb terminals */ +public int quit_at_eof; /* Quit after hitting end of file twice */ +public int quit_if_one_screen; /* Quit if EOF on first screen */ +public int squeeze; /* Squeeze multiple blank lines into one */ +public int tabstop; /* Tab settings */ +public int back_scroll; /* Repaint screen on backwards movement */ +public int forw_scroll; /* Repaint screen on forward movement */ +public int caseless; /* Do "caseless" searches */ +public int linenums; /* Use line numbers */ +public int autobuf; /* Automatically allocate buffers as needed */ +public int bufspace; /* Max buffer space per file (K) */ +public int ctldisp; /* Send control chars to screen untranslated */ +public int force_open; /* Open the file even if not regular file */ +public int swindow; /* Size of scrolling window */ +public int jump_sline; /* Screen line of "jump target" */ public long jump_sline_fraction = -1; public long shift_count_fraction = -1; -public int chopline; /* Truncate displayed lines at screen width */ -public int no_init; /* Disable sending ti/te termcap strings */ -public int no_keypad; /* Disable sending ks/ke termcap strings */ +public int chopline; /* Truncate displayed lines at screen width */ +public int no_init; /* Disable sending ti/te termcap strings */ +public int no_keypad; /* Disable sending ks/ke termcap strings */ public int twiddle; /* Show tildes after EOF */ -public int show_attn; /* Hilite first unread line */ -public int shift_count; /* Number of positions to shift horizontally */ -public int status_col; /* Display a status column */ -public int use_lessopen; /* Use the LESSOPEN filter */ -public int quit_on_intr; /* Quit on interrupt */ -public int follow_mode; /* F cmd Follows file desc or file name? */ -public int oldbot; /* Old bottom of screen behavior {{REMOVE}} */ -public int opt_use_backslash; /* Use backslash escaping in option parsing */ -public char rscroll_char; /* Char which marks chopped lines with -S */ -public int rscroll_attr; /* Attribute of rscroll_char */ -public int no_hist_dups; /* Remove dups from history list */ -public int mousecap; /* Allow mouse for scrolling */ -public int wheel_lines; /* Number of lines to scroll on mouse wheel scroll */ -public int perma_marks; /* Save marks in history file */ +public int show_attn; /* Hilite first unread line */ +public int shift_count; /* Number of positions to shift horizontally */ +public int status_col; /* Display a status column */ +public int use_lessopen; /* Use the LESSOPEN filter */ +public int quit_on_intr; /* Quit on interrupt */ +public int follow_mode; /* F cmd Follows file desc or file name? */ +public int oldbot; /* Old bottom of screen behavior {{REMOVE}} */ +public int opt_use_backslash; /* Use backslash escaping in option parsing */ +public char rscroll_char; /* Char which marks chopped lines with -S */ +public int rscroll_attr; /* Attribute of rscroll_char */ +public int no_hist_dups; /* Remove dups from history list */ +public int mousecap; /* Allow mouse for scrolling */ +public int wheel_lines; /* Number of lines to scroll on mouse wheel scroll */ +public int perma_marks; /* Save marks in history file */ +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 */ #if HILITE_SEARCH -public int hilite_search; /* Highlight matched search patterns? */ +public int hilite_search; /* Highlight matched search patterns? */ #endif -public int less_is_more = 0; /* Make compatible with POSIX more */ +public int less_is_more = 0; /* Make compatible with POSIX more */ /* * Long option names. @@ -73,9 +77,7 @@ static struct optname b_optname = { "buffers", NULL }; static struct optname B__optname = { "auto-buffers", NULL }; static struct optname c_optname = { "clear-screen", NULL }; static struct optname d_optname = { "dumb", NULL }; -#if MSDOS_COMPILER static struct optname D__optname = { "color", NULL }; -#endif static struct optname e_optname = { "quit-at-eof", NULL }; static struct optname f_optname = { "force", NULL }; static struct optname F__optname = { "quit-if-one-screen", NULL }; @@ -127,7 +129,15 @@ static struct optname rscroll_optname = { "rscroll", NULL }; static struct optname nohistdups_optname = { "no-histdups", NULL }; static struct optname mousecap_optname = { "mouse", NULL }; static struct optname wheel_lines_optname = { "wheel-lines", NULL }; -static struct optname perma_marks_optname = { "save-marks", NULL }; +static struct optname perma_marks_optname = { "save-marks", NULL }; +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 }; +#if LESSTEST +static struct optname ttyin_name_optname = { "tty", NULL }; +static struct optname rstat_optname = { "rstat", NULL }; +#endif /*LESSTEST*/ /* @@ -185,16 +195,14 @@ static struct loption option[] = NULL } }, -#if MSDOS_COMPILER { 'D', &D__optname, - STRING|REPAINT, 0, NULL, opt_D, + STRING|REPAINT|NO_QUERY, 0, NULL, opt_D, { "color desc: ", - "Dadknsu0123456789.", + NULL, NULL } }, -#endif { 'e', &e_optname, TRIPLE, OPT_OFF, &quit_at_eof, NULL, { @@ -503,6 +511,56 @@ static struct loption option[] = NULL } }, + { OLETTER_NONE, &linenum_width_optname, + NUMBER|REPAINT, MIN_LINENUM_WIDTH, &linenum_width, opt_linenum_width, + { + "Line number width: ", + "Line number width is %d chars", + NULL + } + }, + { OLETTER_NONE, &status_col_width_optname, + NUMBER|REPAINT, 2, &status_col_width, opt_status_col_width, + { + "Status column width: ", + "Status column width is %d chars", + NULL + } + }, + { OLETTER_NONE, &incr_search_optname, + BOOL, OPT_OFF, &incr_search, NULL, + { + "Incremental search is off", + "Incremental search is on", + NULL + } + }, + { OLETTER_NONE, &use_color_optname, + BOOL|REPAINT, OPT_OFF, &use_color, NULL, + { + "Don't use color", + "Use color", + NULL + } + }, +#if LESSTEST + { OLETTER_NONE, &ttyin_name_optname, + STRING|NO_TOGGLE, 0, NULL, opt_ttyin_name, + { + NULL, + NULL, + NULL + } + }, + { OLETTER_NONE, &rstat_optname, + STRING|NO_TOGGLE, 0, NULL, opt_rstat, + { + NULL, + NULL, + NULL + } + }, +#endif /*LESSTEST*/ { '\0', NULL, NOVAR, 0, NULL, NULL, { NULL, NULL, NULL } } }; diff --git a/os.c b/os.c index 1f33f4f3b39c..1723787b1c50 100644 --- a/os.c +++ b/os.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -23,6 +23,9 @@ #include "less.h" #include #include +#if MSDOS_COMPILER==WIN32C +#include +#endif #if HAVE_TIME_H #include #endif @@ -33,6 +36,15 @@ #include #endif +#if HAVE_POLL && !MSDOS_COMPILER && !defined(__APPLE__) +#define USE_POLL 1 +#else +#define USE_POLL 0 +#endif +#if USE_POLL +#include +#endif + /* * BSD setjmp() saves (and longjmp() restores) the signal mask. * This costs a system call or two per setjmp(), so if possible we clear the @@ -41,11 +53,11 @@ * _setjmp() does not exist; we just use setjmp(). */ #if HAVE__SETJMP && HAVE_SIGSETMASK -#define SET_JUMP _setjmp -#define LONG_JUMP _longjmp +#define SET_JUMP _setjmp +#define LONG_JUMP _longjmp #else -#define SET_JUMP setjmp -#define LONG_JUMP longjmp +#define SET_JUMP setjmp +#define LONG_JUMP longjmp #endif public int reading; @@ -53,6 +65,27 @@ public int reading; static jmp_buf read_label; extern int sigs; +extern int ignore_eoi; +#if !MSDOS_COMPILER +extern int tty; +#endif + +#if USE_POLL +/* + * Return true if one of the events has occurred on the specified file. + */ + static int +poll_events(fd, events) + int fd; + int events; +{ + struct pollfd poller = { fd, events, 0 }; + int n = poll(&poller, 1, 0); + if (n <= 0) + return 0; + return (poller.revents & events); +} +#endif /* * Like read() system call, but is deliberately interruptible. @@ -126,6 +159,29 @@ iread(fd, buf, len) if (select(fd+1, &readfds, 0, 0, 0) == -1) return (-1); } +#endif +#if USE_POLL + if (ignore_eoi && fd != tty) + { + if (poll_events(tty, POLLIN) && getchr() == CONTROL('X')) + { + sigs |= S_INTERRUPT; + return (READ_INTR); + } + if (poll_events(fd, POLLERR|POLLHUP)) + { + sigs |= S_INTERRUPT; + return (READ_INTR); + } + } +#else +#if MSDOS_COMPILER==WIN32C + if (win32_kbhit() && WIN32getch() == CONTROL('X')) + { + sigs |= S_INTERRUPT; + return (READ_INTR); + } +#endif #endif n = read(fd, buf, len); #if 1 @@ -135,7 +191,6 @@ iread(fd, buf, len) * start returning 0 forever, instead of -1. */ { - extern int ignore_eoi; if (!ignore_eoi) { static int consecutive_nulls = 0; @@ -204,18 +259,16 @@ get_time(VOID_PARAM) strerror(err) int err; { -#if HAVE_SYS_ERRLIST static char buf[16]; +#if HAVE_SYS_ERRLIST extern char *sys_errlist[]; extern int sys_nerr; if (err < sys_nerr) return sys_errlist[err]; +#endif sprintf(buf, "Error %d", err); return buf; -#else - return ("cannot open"); -#endif } #endif @@ -356,3 +409,24 @@ isatty(f) } #endif + + public void +sleep_ms(ms) + int ms; +{ +#if MSDOS_COMPILER==WIN32C + Sleep(ms); +#else +#if HAVE_NANOSLEEP + int sec = ms / 1000; + struct timespec t = { sec, (ms - sec*1000) * 1000000 }; + nanosleep(&t, NULL); +#else +#if HAVE_USLEEP + usleep(ms); +#else + sleep((ms+999) / 1000); +#endif +#endif +#endif +} diff --git a/output.c b/output.c index b3d192de0cf1..ddb6ad2779af 100644 --- a/output.c +++ b/output.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -20,7 +20,7 @@ #endif #endif -public int errmsgs; /* Count of messages displayed by error() */ +public int errmsgs; /* Count of messages displayed by error() */ public int need_clr; public int final_attr; public int at_prompt; @@ -29,7 +29,6 @@ extern int sigs; extern int sc_width; extern int so_s_width, so_e_width; extern int screen_trashed; -extern int any_display; extern int is_tty; extern int oldbot; @@ -42,7 +41,7 @@ extern int so_fg_color, so_bg_color; extern int bl_fg_color, bl_bg_color; extern int sgr_mode; #if MSDOS_COMPILER==WIN32C -extern int have_ul; +extern int vt_enabled; #endif #endif @@ -82,6 +81,269 @@ put_line(VOID_PARAM) static char obuf[OUTBUF_SIZE]; static char *ob = obuf; +static int outfd = 2; /* stderr */ + +#if MSDOS_COMPILER==WIN32C || MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC + static void +win_flush(VOID_PARAM) +{ + if (ctldisp != OPT_ONPLUS || (vt_enabled && sgr_mode)) + WIN32textout(obuf, ob - obuf); + else + { + /* + * Look for SGR escape sequences, and convert them + * to color commands. Replace bold, underline, + * and italic escapes into colors specified via + * the -D command-line option. + */ + char *anchor, *p, *p_next; + static int fg, fgi, bg, bgi; + static int at; + int f, b; +#if MSDOS_COMPILER==WIN32C + /* Screen colors used by 3x and 4x SGR commands. */ + static unsigned char screen_color[] = { + 0, /* BLACK */ + FOREGROUND_RED, + FOREGROUND_GREEN, + FOREGROUND_RED|FOREGROUND_GREEN, + FOREGROUND_BLUE, + FOREGROUND_BLUE|FOREGROUND_RED, + FOREGROUND_BLUE|FOREGROUND_GREEN, + FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED + }; +#else + static enum COLORS screen_color[] = { + BLACK, RED, GREEN, BROWN, + BLUE, MAGENTA, CYAN, LIGHTGRAY + }; +#endif + + if (fg == 0 && bg == 0) + { + fg = nm_fg_color & 7; + fgi = nm_fg_color & 8; + bg = nm_bg_color & 7; + bgi = nm_bg_color & 8; + } + for (anchor = p_next = obuf; + (p_next = memchr(p_next, ESC, ob - p_next)) != NULL; ) + { + p = p_next; + if (p[1] == '[') /* "ESC-[" sequence */ + { + if (p > anchor) + { + /* + * If some chars seen since + * the last escape sequence, + * write them out to the screen. + */ + WIN32textout(anchor, p-anchor); + anchor = p; + } + p += 2; /* Skip the "ESC-[" */ + if (is_ansi_end(*p)) + { + /* + * Handle null escape sequence + * "ESC[m", which restores + * the normal color. + */ + p++; + anchor = p_next = p; + fg = nm_fg_color & 7; + fgi = nm_fg_color & 8; + bg = nm_bg_color & 7; + bgi = nm_bg_color & 8; + at = 0; + WIN32setcolors(nm_fg_color, nm_bg_color); + continue; + } + p_next = p; + at &= ~32; + + /* + * Select foreground/background colors + * based on the escape sequence. + */ + while (!is_ansi_end(*p)) + { + char *q; + long code = strtol(p, &q, 10); + + if (*q == '\0') + { + /* + * Incomplete sequence. + * Leave it unprocessed + * in the buffer. + */ + int slop = (int) (q - anchor); + /* {{ strcpy args overlap! }} */ + strcpy(obuf, anchor); + ob = &obuf[slop]; + return; + } + + if (q == p || + code > 49 || code < 0 || + (!is_ansi_end(*q) && *q != ';')) + { + p_next = q; + break; + } + if (*q == ';') + { + q++; + at |= 32; + } + + switch (code) + { + default: + /* case 0: all attrs off */ + fg = nm_fg_color & 7; + bg = nm_bg_color & 7; + at &= 32; + /* + * \e[0m use normal + * intensities, but + * \e[0;...m resets them + */ + if (at & 32) + { + fgi = 0; + bgi = 0; + } else + { + fgi = nm_fg_color & 8; + bgi = nm_bg_color & 8; + } + break; + case 1: /* bold on */ + fgi = 8; + at |= 1; + break; + case 3: /* italic on */ + case 7: /* inverse on */ + at |= 2; + break; + case 4: /* underline on */ + bgi = 8; + at |= 4; + break; + case 5: /* slow blink on */ + case 6: /* fast blink on */ + bgi = 8; + at |= 8; + break; + case 8: /* concealed on */ + at |= 16; + break; + case 22: /* bold off */ + fgi = 0; + at &= ~1; + break; + case 23: /* italic off */ + case 27: /* inverse off */ + at &= ~2; + break; + case 24: /* underline off */ + bgi = 0; + at &= ~4; + break; + case 28: /* concealed off */ + at &= ~16; + break; + case 30: case 31: case 32: + case 33: case 34: case 35: + case 36: case 37: + fg = screen_color[code - 30]; + at |= 32; + break; + case 39: /* default fg */ + fg = nm_fg_color & 7; + at |= 32; + break; + case 40: case 41: case 42: + case 43: case 44: case 45: + case 46: case 47: + bg = screen_color[code - 40]; + at |= 32; + break; + case 49: /* default bg */ + bg = nm_bg_color & 7; + at |= 32; + break; + } + p = q; + } + if (!is_ansi_end(*p) || p == p_next) + break; + /* + * In SGR mode, the ANSI sequence is + * always honored; otherwise if an attr + * is used by itself ("\e[1m" versus + * "\e[1;33m", for example), set the + * color assigned to that attribute. + */ + if (sgr_mode || (at & 32)) + { + if (at & 2) + { + f = bg | bgi; + b = fg | fgi; + } else + { + f = fg | fgi; + b = bg | bgi; + } + } else + { + if (at & 1) + { + f = bo_fg_color; + b = bo_bg_color; + } else if (at & 2) + { + f = so_fg_color; + b = so_bg_color; + } else if (at & 4) + { + f = ul_fg_color; + b = ul_bg_color; + } else if (at & 8) + { + f = bl_fg_color; + b = bl_bg_color; + } else + { + f = nm_fg_color; + b = nm_bg_color; + } + } + if (at & 16) + f = b ^ 8; +#if MSDOS_COMPILER==WIN32C + f &= 0xf | COMMON_LVB_UNDERSCORE; +#else + f &= 0xf; +#endif + b &= 0xf; + WIN32setcolors(f, b); + p_next = anchor = p + 1; + } else + p_next++; + } + + /* Output what's left in the buffer. */ + WIN32textout(anchor, ob - anchor); + } + ob = obuf; +} +#endif /* * Flush buffered output. @@ -103,293 +365,44 @@ static char *ob = obuf; flush(VOID_PARAM) { int n; - int fd; n = (int) (ob - obuf); if (n == 0) return; + ob = obuf; #if MSDOS_COMPILER==MSOFTC - if (is_tty && any_display) + if (interactive()) { - *ob = '\0'; + obuf[n] = '\0'; _outtext(obuf); - ob = obuf; return; } #else #if MSDOS_COMPILER==WIN32C || MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC - if (is_tty && any_display) + if (interactive()) { + ob = obuf + n; *ob = '\0'; - if (ctldisp != OPT_ONPLUS) - WIN32textout(obuf, ob - obuf); - else - { - /* - * Look for SGR escape sequences, and convert them - * to color commands. Replace bold, underline, - * and italic escapes into colors specified via - * the -D command-line option. - */ - char *anchor, *p, *p_next; - static int fg, fgi, bg, bgi; - static int at; - int f, b; -#if MSDOS_COMPILER==WIN32C - /* Screen colors used by 3x and 4x SGR commands. */ - static unsigned char screen_color[] = { - 0, /* BLACK */ - FOREGROUND_RED, - FOREGROUND_GREEN, - FOREGROUND_RED|FOREGROUND_GREEN, - FOREGROUND_BLUE, - FOREGROUND_BLUE|FOREGROUND_RED, - FOREGROUND_BLUE|FOREGROUND_GREEN, - FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED - }; -#else - static enum COLORS screen_color[] = { - BLACK, RED, GREEN, BROWN, - BLUE, MAGENTA, CYAN, LIGHTGRAY - }; -#endif - - if (fg == 0 && bg == 0) - { - fg = nm_fg_color & 7; - fgi = nm_fg_color & 8; - bg = nm_bg_color & 7; - bgi = nm_bg_color & 8; - } - for (anchor = p_next = obuf; - (p_next = memchr(p_next, ESC, ob - p_next)) != NULL; ) - { - p = p_next; - if (p[1] == '[') /* "ESC-[" sequence */ - { - if (p > anchor) - { - /* - * If some chars seen since - * the last escape sequence, - * write them out to the screen. - */ - WIN32textout(anchor, p-anchor); - anchor = p; - } - p += 2; /* Skip the "ESC-[" */ - if (is_ansi_end(*p)) - { - /* - * Handle null escape sequence - * "ESC[m", which restores - * the normal color. - */ - p++; - anchor = p_next = p; - fg = nm_fg_color & 7; - fgi = nm_fg_color & 8; - bg = nm_bg_color & 7; - bgi = nm_bg_color & 8; - at = 0; - WIN32setcolors(nm_fg_color, nm_bg_color); - continue; - } - p_next = p; - at &= ~32; - - /* - * Select foreground/background colors - * based on the escape sequence. - */ - while (!is_ansi_end(*p)) - { - char *q; - long code = strtol(p, &q, 10); - - if (*q == '\0') - { - /* - * Incomplete sequence. - * Leave it unprocessed - * in the buffer. - */ - int slop = (int) (q - anchor); - /* {{ strcpy args overlap! }} */ - strcpy(obuf, anchor); - ob = &obuf[slop]; - return; - } - - if (q == p || - code > 49 || code < 0 || - (!is_ansi_end(*q) && *q != ';')) - { - p_next = q; - break; - } - if (*q == ';') - { - q++; - at |= 32; - } - - switch (code) - { - default: - /* case 0: all attrs off */ - fg = nm_fg_color & 7; - bg = nm_bg_color & 7; - at &= 32; - /* - * \e[0m use normal - * intensities, but - * \e[0;...m resets them - */ - if (at & 32) - { - fgi = 0; - bgi = 0; - } else - { - fgi = nm_fg_color & 8; - bgi = nm_bg_color & 8; - } - break; - case 1: /* bold on */ - fgi = 8; - at |= 1; - break; - case 3: /* italic on */ - case 7: /* inverse on */ - at |= 2; - break; - case 4: /* underline on */ -#if MSDOS_COMPILER==WIN32C - if (have_ul) - bgi = COMMON_LVB_UNDERSCORE >> 4; - else -#endif - bgi = 8; - at |= 4; - break; - case 5: /* slow blink on */ - case 6: /* fast blink on */ - bgi = 8; - at |= 8; - break; - case 8: /* concealed on */ - at |= 16; - break; - case 22: /* bold off */ - fgi = 0; - at &= ~1; - break; - case 23: /* italic off */ - case 27: /* inverse off */ - at &= ~2; - break; - case 24: /* underline off */ - bgi = 0; - at &= ~4; - break; - case 28: /* concealed off */ - at &= ~16; - break; - case 30: case 31: case 32: - case 33: case 34: case 35: - case 36: case 37: - fg = screen_color[code - 30]; - at |= 32; - break; - case 39: /* default fg */ - fg = nm_fg_color & 7; - at |= 32; - break; - case 40: case 41: case 42: - case 43: case 44: case 45: - case 46: case 47: - bg = screen_color[code - 40]; - at |= 32; - break; - case 49: /* default bg */ - bg = nm_bg_color & 7; - at |= 32; - break; - } - p = q; - } - if (!is_ansi_end(*p) || p == p_next) - break; - /* - * In SGR mode, the ANSI sequence is - * always honored; otherwise if an attr - * is used by itself ("\e[1m" versus - * "\e[1;33m", for example), set the - * color assigned to that attribute. - */ - if (sgr_mode || (at & 32)) - { - if (at & 2) - { - f = bg | bgi; - b = fg | fgi; - } else - { - f = fg | fgi; - b = bg | bgi; - } - } else - { - if (at & 1) - { - f = bo_fg_color; - b = bo_bg_color; - } else if (at & 2) - { - f = so_fg_color; - b = so_bg_color; - } else if (at & 4) - { - f = ul_fg_color; - b = ul_bg_color; - } else if (at & 8) - { - f = bl_fg_color; - b = bl_bg_color; - } else - { - f = nm_fg_color; - b = nm_bg_color; - } - } - if (at & 16) - f = b ^ 8; - f &= 0xf; -#if MSDOS_COMPILER==WIN32C - b &= 0xf | (COMMON_LVB_UNDERSCORE >> 4); -#else - b &= 0xf; -#endif - WIN32setcolors(f, b); - p_next = anchor = p + 1; - } else - p_next++; - } - - /* Output what's left in the buffer. */ - WIN32textout(anchor, ob - anchor); - } - ob = obuf; + win_flush(); return; } #endif #endif - fd = (any_display) ? 1 : 2; - if (write(fd, obuf, n) != n) + + if (write(outfd, obuf, n) != n) screen_trashed = 1; - ob = obuf; +} + +/* + * Set the output file descriptor (1=stdout or 2=stderr). + */ + public void +set_output(fd) + int fd; +{ + flush(); + outfd = fd; } /* @@ -491,8 +504,8 @@ type funcname(buf, ebuf) \ char **ebuf; \ { \ type val = 0; \ - for (;;) { \ - char c = *buf++; \ + for (;; buf++) { \ + char c = *buf; \ if (c < '0' || c > '9') break; \ val = 10 * val + c - '0'; \ } \ @@ -534,8 +547,11 @@ iprint_linenum(num) /* * This function implements printf-like functionality * using a more portable argument list mechanism than printf's. + * + * {{ This paranoia about the portability of printf dates from experiences + * with systems in the 1980s and is of course no longer necessary. }} */ - static int + public int less_printf(fmt, parg) char *fmt; PARG *parg; @@ -572,6 +588,10 @@ less_printf(fmt, parg) col += iprint_linenum(parg->p_linenum); parg++; break; + case 'c': + putchr(parg->p_char); + col++; + break; case '%': putchr('%'); break; @@ -615,24 +635,20 @@ error(fmt, parg) errmsgs++; - if (any_display && is_tty) - { - if (!oldbot) - squish_check(); - at_exit(); - clear_bot(); - at_enter(AT_STANDOUT); - col += so_s_width; - } - - col += less_printf(fmt, parg); - - if (!(any_display && is_tty)) + if (!interactive()) { + less_printf(fmt, parg); putchr('\n'); return; } + if (!oldbot) + squish_check(); + at_exit(); + clear_bot(); + at_enter(AT_STANDOUT|AT_COLOR_ERROR); + col += so_s_width; + col += less_printf(fmt, parg); putstr(return_to_continue); at_exit(); col += sizeof(return_to_continue) + so_e_width; @@ -667,7 +683,7 @@ ierror(fmt, parg) { at_exit(); clear_bot(); - at_enter(AT_STANDOUT); + at_enter(AT_STANDOUT|AT_COLOR_ERROR); (void) less_printf(fmt, parg); putstr(intr_to_abort); at_exit(); @@ -687,22 +703,24 @@ query(fmt, parg) int c; int col = 0; - if (any_display && is_tty) + if (interactive()) clear_bot(); (void) less_printf(fmt, parg); c = getchr(); - if (!(any_display && is_tty)) + if (interactive()) + { + lower_left(); + if (col >= sc_width) + screen_trashed = 1; + flush(); + } else { putchr('\n'); - return (c); } - lower_left(); - if (col >= sc_width) - screen_trashed = 1; - flush(); - + if (c == 'Q') + quit(QUIT_OK); return (c); } diff --git a/pattern.c b/pattern.c index b7fc05725a44..c2266fcf68c8 100644 --- a/pattern.c +++ b/pattern.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -145,9 +145,10 @@ compile_pattern2(pattern, search_type, comp_pattern, show_error) * Like compile_pattern2, but convert the pattern to lowercase if necessary. */ public int -compile_pattern(pattern, search_type, comp_pattern) +compile_pattern(pattern, search_type, show_error, comp_pattern) char *pattern; int search_type; + int show_error; PATTERN_TYPE *comp_pattern; { char *cvt_pattern; @@ -160,7 +161,7 @@ compile_pattern(pattern, search_type, comp_pattern) cvt_pattern = (char*) ecalloc(1, cvt_length(strlen(pattern), CVT_TO_LC)); cvt_text(cvt_pattern, pattern, (int *)NULL, (int *)NULL, CVT_TO_LC); } - result = compile_pattern2(cvt_pattern, search_type, comp_pattern, 1); + result = compile_pattern2(cvt_pattern, search_type, comp_pattern, show_error); if (cvt_pattern != pattern) free(cvt_pattern); return (result); @@ -214,6 +215,7 @@ uncompile_pattern(pattern) #endif } +#if 0 /* * Can a pattern be successfully compiled? */ @@ -224,13 +226,14 @@ valid_pattern(pattern) PATTERN_TYPE comp_pattern; int result; - CLEAR_PATTERN(comp_pattern); + SET_NULL_PATTERN(comp_pattern); result = compile_pattern2(pattern, 0, &comp_pattern, 0); if (result != 0) return (0); uncompile_pattern(&comp_pattern); return (1); } +#endif /* * Is a compiled pattern null? diff --git a/pattern.h b/pattern.h index 677f45b8c237..6cd9d1a11b0f 100644 --- a/pattern.h +++ b/pattern.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -11,7 +11,7 @@ #define __USE_GNU 1 #include #define PATTERN_TYPE struct re_pattern_buffer * -#define CLEAR_PATTERN(name) name = NULL +#define SET_NULL_PATTERN(name) name = NULL #endif #if HAVE_POSIX_REGCOMP @@ -22,27 +22,27 @@ #define REGCOMP_FLAG 0 #endif #define PATTERN_TYPE regex_t * -#define CLEAR_PATTERN(name) name = NULL +#define SET_NULL_PATTERN(name) name = NULL #endif #if HAVE_PCRE #include #define PATTERN_TYPE pcre * -#define CLEAR_PATTERN(name) name = NULL +#define SET_NULL_PATTERN(name) name = NULL #endif #if HAVE_PCRE2 #define PCRE2_CODE_UNIT_WIDTH 8 #include #define PATTERN_TYPE pcre2_code * -#define CLEAR_PATTERN(name) name = NULL +#define SET_NULL_PATTERN(name) name = NULL #endif #if HAVE_RE_COMP char *re_comp LESSPARAMS ((char*)); int re_exec LESSPARAMS ((char*)); #define PATTERN_TYPE int -#define CLEAR_PATTERN(name) name = 0 +#define SET_NULL_PATTERN(name) name = 0 #endif #if HAVE_REGCMP @@ -50,17 +50,17 @@ char *regcmp LESSPARAMS ((char*)); char *regex LESSPARAMS ((char**, char*)); extern char *__loc1; #define PATTERN_TYPE char ** -#define CLEAR_PATTERN(name) name = NULL +#define SET_NULL_PATTERN(name) name = NULL #endif #if HAVE_V8_REGCOMP #include "regexp.h" extern int reg_show_error; #define PATTERN_TYPE struct regexp * -#define CLEAR_PATTERN(name) name = NULL +#define SET_NULL_PATTERN(name) name = NULL #endif #if NO_REGEX #define PATTERN_TYPE void * -#define CLEAR_PATTERN(name) +#define SET_NULL_PATTERN(name) #endif diff --git a/pckeys.h b/pckeys.h index e41ca9acdc88..8b21d729935a 100644 --- a/pckeys.h +++ b/pckeys.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -13,21 +13,21 @@ * Special (non-ASCII) keys on the PC send a two-byte sequence, * where the first byte is 0 and the second is as defined below. */ -#define PCK_SHIFT_TAB '\017' -#define PCK_ALT_E '\022' -#define PCK_CAPS_LOCK '\072' -#define PCK_F1 '\073' -#define PCK_NUM_LOCK '\105' -#define PCK_HOME '\107' -#define PCK_UP '\110' -#define PCK_PAGEUP '\111' -#define PCK_LEFT '\113' -#define PCK_RIGHT '\115' -#define PCK_END '\117' -#define PCK_DOWN '\120' -#define PCK_PAGEDOWN '\121' -#define PCK_INSERT '\122' -#define PCK_DELETE '\123' -#define PCK_CTL_LEFT '\163' -#define PCK_CTL_RIGHT '\164' -#define PCK_CTL_DELETE '\223' +#define PCK_SHIFT_TAB '\017' +#define PCK_ALT_E '\022' +#define PCK_CAPS_LOCK '\072' +#define PCK_F1 '\073' +#define PCK_NUM_LOCK '\105' +#define PCK_HOME '\107' +#define PCK_UP '\110' +#define PCK_PAGEUP '\111' +#define PCK_LEFT '\113' +#define PCK_RIGHT '\115' +#define PCK_END '\117' +#define PCK_DOWN '\120' +#define PCK_PAGEDOWN '\121' +#define PCK_INSERT '\122' +#define PCK_DELETE '\123' +#define PCK_CTL_LEFT '\163' +#define PCK_CTL_RIGHT '\164' +#define PCK_CTL_DELETE '\223' diff --git a/position.c b/position.c index 6e37ec5d5187..8f6edc939377 100644 --- a/position.c +++ b/position.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -21,7 +21,7 @@ #include "less.h" #include "position.h" -static POSITION *table = NULL; /* The position table */ +static POSITION *table = NULL; /* The position table */ static int table_size = 0; extern int sc_width, sc_height; @@ -30,10 +30,10 @@ extern int sc_width, sc_height; * Return the starting file position of a line displayed on the screen. * The line may be specified as a line number relative to the top * of the screen, but is usually one of these special cases: - * the top (first) line on the screen - * the second line on the screen - * the bottom line on the screen - * the line after the bottom line on the screen + * the top (first) line on the screen + * the second line on the screen + * the bottom line on the screen + * the line after the bottom line on the screen */ public POSITION position(sindex) diff --git a/position.h b/position.h index 2e6c71bc766e..4e0efc7f4c0f 100644 --- a/position.h +++ b/position.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -11,8 +11,8 @@ /* * Include file for interfacing to position.c modules. */ -#define TOP (0) -#define TOP_PLUS_ONE (1) -#define BOTTOM (-1) -#define BOTTOM_PLUS_ONE (-2) -#define MIDDLE (-3) +#define TOP (0) +#define TOP_PLUS_ONE (1) +#define BOTTOM (-1) +#define BOTTOM_PLUS_ONE (-2) +#define MIDDLE (-3) diff --git a/prompt.c b/prompt.c index e587bd762000..0e38c0f6e438 100644 --- a/prompt.c +++ b/prompt.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -123,7 +123,7 @@ ap_pos(pos) /* * Append a line number to the end of the message. */ - static void + static void ap_linenum(linenum) LINENUM linenum; { @@ -187,48 +187,48 @@ cond(c, where) switch (c) { - case 'a': /* Anything in the message yet? */ + case 'a': /* Anything in the message yet? */ return (mp > message); - case 'b': /* Current byte offset known? */ + case 'b': /* Current byte offset known? */ return (curr_byte(where) != NULL_POSITION); case 'c': return (hshift != 0); - case 'e': /* At end of file? */ + case 'e': /* At end of file? */ return (eof_displayed()); - case 'f': /* Filename known? */ + case 'f': /* Filename known? */ case 'g': return (strcmp(get_filename(curr_ifile), "-") != 0); - case 'l': /* Line number known? */ - case 'd': /* Same as l */ + case 'l': /* Line number known? */ + case 'd': /* Same as l */ if (!linenums) return 0; return (currline(where) != 0); - case 'L': /* Final line number known? */ - case 'D': /* Final page number known? */ + case 'L': /* Final line number known? */ + case 'D': /* Final page number known? */ return (linenums && ch_length() != NULL_POSITION); - case 'm': /* More than one file? */ + case 'm': /* More than one file? */ #if TAGS return (ntags() ? (ntags() > 1) : (nifile() > 1)); #else return (nifile() > 1); #endif - case 'n': /* First prompt in a new file? */ + case 'n': /* First prompt in a new file? */ #if TAGS return (ntags() ? 1 : new_file); #else return (new_file); #endif - case 'p': /* Percent into file (bytes) known? */ + case 'p': /* Percent into file (bytes) known? */ return (curr_byte(where) != NULL_POSITION && ch_length() > 0); - case 'P': /* Percent into file (lines) known? */ + case 'P': /* Percent into file (lines) known? */ return (currline(where) != 0 && (len = ch_length()) > 0 && find_linenum(len) != 0); - case 's': /* Size of file known? */ + case 's': /* Size of file known? */ case 'B': return (ch_length() != NULL_POSITION); - case 'x': /* Is there a "next" file? */ + case 'x': /* Is there a "next" file? */ #if TAGS if (ntags()) return (0); @@ -264,7 +264,7 @@ protochar(c, where, iseditproto) switch (c) { - case 'b': /* Current byte offset */ + case 'b': /* Current byte offset */ pos = curr_byte(where); if (pos != NULL_POSITION) ap_pos(pos); @@ -274,14 +274,14 @@ protochar(c, where, iseditproto) case 'c': ap_int(hshift); break; - case 'd': /* Current page number */ + case 'd': /* Current page number */ linenum = currline(where); if (linenum > 0 && sc_height > 1) ap_linenum(PAGE_NUM(linenum)); else ap_quest(); break; - case 'D': /* Final page number */ + case 'D': /* Final page number */ /* Find the page number of the last byte in the file (len-1). */ len = ch_length(); if (len == NULL_POSITION) @@ -299,22 +299,22 @@ protochar(c, where, iseditproto) } break; #if EDITOR - case 'E': /* Editor name */ + case 'E': /* Editor name */ ap_str(editor); break; #endif - case 'f': /* File name */ + case 'f': /* File name */ ap_str(get_filename(curr_ifile)); break; - case 'F': /* Last component of file name */ + case 'F': /* Last component of file name */ ap_str(last_component(get_filename(curr_ifile))); break; - case 'g': /* Shell-escaped file name */ + case 'g': /* Shell-escaped file name */ s = shell_quote(get_filename(curr_ifile)); ap_str(s); free(s); break; - case 'i': /* Index into list of files */ + case 'i': /* Index into list of files */ #if TAGS if (ntags()) ap_int(curr_tag()); @@ -322,14 +322,14 @@ protochar(c, where, iseditproto) #endif ap_int(get_index(curr_ifile)); break; - case 'l': /* Current line number */ + case 'l': /* Current line number */ linenum = currline(where); if (linenum != 0) ap_linenum(linenum); else ap_quest(); break; - case 'L': /* Final line number */ + case 'L': /* Final line number */ len = ch_length(); if (len == NULL_POSITION || len == ch_zero() || (linenum = find_linenum(len)) <= 0) @@ -337,7 +337,7 @@ protochar(c, where, iseditproto) else ap_linenum(linenum-1); break; - case 'm': /* Number of files */ + case 'm': /* Number of files */ #if TAGS n = ntags(); if (n) @@ -346,7 +346,7 @@ protochar(c, where, iseditproto) #endif ap_int(nifile()); break; - case 'p': /* Percent into file (bytes) */ + case 'p': /* Percent into file (bytes) */ pos = curr_byte(where); len = ch_length(); if (pos != NULL_POSITION && len > 0) @@ -354,7 +354,7 @@ protochar(c, where, iseditproto) else ap_quest(); break; - case 'P': /* Percent into file (lines) */ + case 'P': /* Percent into file (lines) */ linenum = currline(where); if (linenum == 0 || (len = ch_length()) == NULL_POSITION || len == ch_zero() || @@ -363,7 +363,7 @@ protochar(c, where, iseditproto) else ap_int(percentage(linenum, last_linenum)); break; - case 's': /* Size of file */ + case 's': /* Size of file */ case 'B': len = ch_length(); if (len != NULL_POSITION) @@ -371,12 +371,12 @@ protochar(c, where, iseditproto) else ap_quest(); break; - case 't': /* Truncate trailing spaces in the message */ + case 't': /* Truncate trailing spaces in the message */ while (mp > message && mp[-1] == ' ') mp--; *mp = '\0'; break; - case 'T': /* Type of list */ + case 'T': /* Type of list */ #if TAGS if (ntags()) ap_str("tag"); @@ -384,7 +384,7 @@ protochar(c, where, iseditproto) #endif ap_str("file"); break; - case 'x': /* Name of next file */ + case 'x': /* Name of next file */ h = next_ifile(curr_ifile); if (h != NULL_IFILE) ap_str(get_filename(h)); @@ -469,12 +469,12 @@ wherechar(p, wp) case 'b': case 'd': case 'l': case 'p': case 'P': switch (*++p) { - case 't': *wp = TOP; break; - case 'm': *wp = MIDDLE; break; - case 'b': *wp = BOTTOM; break; - case 'B': *wp = BOTTOM_PLUS_ONE; break; + case 't': *wp = TOP; break; + case 'm': *wp = MIDDLE; break; + case 'b': *wp = BOTTOM; break; + case 'B': *wp = BOTTOM_PLUS_ONE; break; case 'j': *wp = sindex_from_sline(jump_sline); break; - default: *wp = TOP; p--; break; + default: *wp = TOP; p--; break; } } return (p); @@ -501,14 +501,14 @@ pr_expand(proto, maxwidth) { switch (*p) { - default: /* Just put the character in the message */ + default: /* Just put the character in the message */ ap_char(*p); break; - case '\\': /* Backslash escapes the next character */ + case '\\': /* Backslash escapes the next character */ p++; ap_char(*p); break; - case '?': /* Conditional (IF) */ + case '?': /* Conditional (IF) */ if ((c = *++p) == '\0') --p; else @@ -519,12 +519,12 @@ pr_expand(proto, maxwidth) p = skipcond(p); } break; - case ':': /* ELSE */ + case ':': /* ELSE */ p = skipcond(p); break; - case '.': /* ENDIF */ + case '.': /* ENDIF */ break; - case '%': /* Percent escape */ + case '%': /* Percent escape */ if ((c = *++p) == '\0') --p; else diff --git a/regexp.h b/regexp.h index bcef6d1ebc77..283ff2aad6b7 100644 --- a/regexp.h +++ b/regexp.h @@ -10,13 +10,13 @@ #define NSUBEXP 10 typedef struct regexp { - char *startp[NSUBEXP]; - char *endp[NSUBEXP]; - char regstart; /* Internal use only. */ - char reganch; /* Internal use only. */ - char *regmust; /* Internal use only. */ - int regmlen; /* Internal use only. */ - char program[1]; /* Unwarranted chumminess with compiler. */ + char *startp[NSUBEXP]; + char *endp[NSUBEXP]; + char regstart; /* Internal use only. */ + char reganch; /* Internal use only. */ + char *regmust; /* Internal use only. */ + int regmlen; /* Internal use only. */ + char program[1]; /* Unwarranted chumminess with compiler. */ } regexp; #if defined(__STDC__) || defined(__cplusplus) diff --git a/screen.c b/screen.c index c9635f438106..7e8f8af4f463 100644 --- a/screen.c +++ b/screen.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -35,6 +35,19 @@ extern int fd0; #endif #include +#ifndef FOREGROUND_BLUE +#define FOREGROUND_BLUE 0x0001 +#endif +#ifndef FOREGROUND_GREEN +#define FOREGROUND_GREEN 0x0002 +#endif +#ifndef FOREGROUND_RED +#define FOREGROUND_RED 0x0004 +#endif +#ifndef FOREGROUND_INTENSITY +#define FOREGROUND_INTENSITY 0x0008 +#endif + #else #if HAVE_SYS_IOCTL_H @@ -85,17 +98,19 @@ extern int fd0; #endif #if OS2 -#define DEFAULT_TERM "ansi" +#define DEFAULT_TERM "ansi" static char *windowid; #else -#define DEFAULT_TERM "unknown" +#define DEFAULT_TERM "unknown" #endif #if MSDOS_COMPILER==MSOFTC static int videopages; static long msec_loops; static int flash_created = 0; -#define SETCOLORS(fg,bg) { _settextcolor(fg); _setbkcolor(bg); } +#define SET_FG_COLOR(fg) _settextcolor(fg) +#define SET_BG_COLOR(bg) _setbkcolor(bg) +#define SETCOLORS(fg,bg) { SET_FG_COLOR(fg); SET_BG_COLOR(bg); } #endif #if MSDOS_COMPILER==BORLANDC @@ -106,7 +121,9 @@ static int flash_created = 0; #define _settextposition(y,x) gotoxy(x,y) #define _clearscreen(m) clrscr() #define _outtext(s) cputs(s) -#define SETCOLORS(fg,bg) { textcolor(fg); textbackground(bg); } +#define SET_FG_COLOR(fg) textcolor(fg) +#define SET_BG_COLOR(bg) textbackground(bg) +#define SETCOLORS(fg,bg) { SET_FG_COLOR(fg); SET_BG_COLOR(bg); } extern int sc_height; #endif @@ -138,28 +155,31 @@ static void win32_deinit_term(); #define FG_COLORS (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY) #define BG_COLORS (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY) -#define MAKEATTR(fg,bg) ((WORD)((fg)|((bg)<<4))) -#define SETCOLORS(fg,bg) { curr_attr = MAKEATTR(fg,bg); \ - if (SetConsoleTextAttribute(con_out, curr_attr) == 0) \ - error("SETCOLORS failed", NULL_PARG); } +#define MAKEATTR(fg,bg) ((WORD)((fg)|((bg)<<4))) +#define APPLY_COLORS() { if (SetConsoleTextAttribute(con_out, curr_attr) == 0) \ + error("SETCOLORS failed", NULL_PARG); } +#define SET_FG_COLOR(fg) { curr_attr |= (fg); APPLY_COLORS(); } +#define SET_BG_COLOR(bg) { curr_attr |= ((bg)<<4); APPLY_COLORS(); } +#define SETCOLORS(fg,bg) { curr_attr = MAKEATTR(fg,bg); APPLY_COLORS(); } #endif #if MSDOS_COMPILER -public int nm_fg_color; /* Color of normal text */ +public int nm_fg_color; /* Color of normal text */ public int nm_bg_color; -public int bo_fg_color; /* Color of bold text */ +public int bo_fg_color; /* Color of bold text */ public int bo_bg_color; -public int ul_fg_color; /* Color of underlined text */ +public int ul_fg_color; /* Color of underlined text */ public int ul_bg_color; -public int so_fg_color; /* Color of standout text */ +public int so_fg_color; /* Color of standout text */ public int so_bg_color; -public int bl_fg_color; /* Color of blinking text */ +public int bl_fg_color; /* Color of blinking text */ public int bl_bg_color; -static int sy_fg_color; /* Color of system text (before less) */ +static int sy_fg_color; /* Color of system text (before less) */ static int sy_bg_color; -public int sgr_mode; /* Honor ANSI sequences rather than using above */ +public int sgr_mode; /* Honor ANSI sequences rather than using above */ #if MSDOS_COMPILER==WIN32C -public int have_ul; /* Is underline available? */ +static DWORD init_output_mode; /* The initial console output mode */ +public int vt_enabled = -1; /* Is virtual terminal processing available? */ #endif #else @@ -167,56 +187,61 @@ public int have_ul; /* Is underline available? */ * Strings passed to tputs() to do various terminal functions. */ static char - *sc_pad, /* Pad string */ - *sc_home, /* Cursor home */ - *sc_addline, /* Add line, scroll down following lines */ - *sc_lower_left, /* Cursor to last line, first column */ - *sc_return, /* Cursor to beginning of current line */ - *sc_move, /* General cursor positioning */ - *sc_clear, /* Clear screen */ - *sc_eol_clear, /* Clear to end of line */ - *sc_eos_clear, /* Clear to end of screen */ - *sc_s_in, /* Enter standout (highlighted) mode */ - *sc_s_out, /* Exit standout mode */ - *sc_u_in, /* Enter underline mode */ - *sc_u_out, /* Exit underline mode */ - *sc_b_in, /* Enter bold mode */ - *sc_b_out, /* Exit bold mode */ - *sc_bl_in, /* Enter blink mode */ - *sc_bl_out, /* Exit blink mode */ - *sc_visual_bell, /* Visual bell (flash screen) sequence */ - *sc_backspace, /* Backspace cursor */ - *sc_s_keypad, /* Start keypad mode */ - *sc_e_keypad, /* End keypad mode */ - *sc_s_mousecap, /* Start mouse capture mode */ - *sc_e_mousecap, /* End mouse capture mode */ - *sc_init, /* Startup terminal initialization */ - *sc_deinit; /* Exit terminal de-initialization */ + *sc_pad, /* Pad string */ + *sc_home, /* Cursor home */ + *sc_addline, /* Add line, scroll down following lines */ + *sc_lower_left, /* Cursor to last line, first column */ + *sc_return, /* Cursor to beginning of current line */ + *sc_move, /* General cursor positioning */ + *sc_clear, /* Clear screen */ + *sc_eol_clear, /* Clear to end of line */ + *sc_eos_clear, /* Clear to end of screen */ + *sc_s_in, /* Enter standout (highlighted) mode */ + *sc_s_out, /* Exit standout mode */ + *sc_u_in, /* Enter underline mode */ + *sc_u_out, /* Exit underline mode */ + *sc_b_in, /* Enter bold mode */ + *sc_b_out, /* Exit bold mode */ + *sc_bl_in, /* Enter blink mode */ + *sc_bl_out, /* Exit blink mode */ + *sc_visual_bell, /* Visual bell (flash screen) sequence */ + *sc_backspace, /* Backspace cursor */ + *sc_s_keypad, /* Start keypad mode */ + *sc_e_keypad, /* End keypad mode */ + *sc_s_mousecap, /* Start mouse capture mode */ + *sc_e_mousecap, /* End mouse capture mode */ + *sc_init, /* Startup terminal initialization */ + *sc_deinit; /* Exit terminal de-initialization */ + +static int attrcolor = -1; #endif static int init_done = 0; -public int auto_wrap; /* Terminal does \r\n when write past margin */ -public int ignaw; /* Terminal ignores \n immediately after wrap */ -public int erase_char; /* The user's erase char */ -public int erase2_char; /* The user's other erase char */ -public int kill_char; /* The user's line-kill char */ -public int werase_char; /* The user's word-erase char */ -public int sc_width, sc_height; /* Height & width of screen */ -public int bo_s_width, bo_e_width; /* Printing width of boldface seq */ -public int ul_s_width, ul_e_width; /* Printing width of underline seq */ -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 char *kent = NULL; /* Keypad ENTER sequence */ +public int auto_wrap; /* Terminal does \r\n when write past margin */ +public int ignaw; /* Terminal ignores \n immediately after wrap */ +public int erase_char; /* The user's erase char */ +public int erase2_char; /* The user's other erase char */ +public int kill_char; /* The user's line-kill char */ +public int werase_char; /* The user's word-erase char */ +public int sc_width, sc_height; /* Height & width of screen */ +public int bo_s_width, bo_e_width; /* Printing width of boldface seq */ +public int ul_s_width, ul_e_width; /* Printing width of underline seq */ +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 char *kent = NULL; /* Keypad ENTER sequence */ static int attrmode = AT_NORMAL; static int termcap_debug = -1; extern int binattr; extern int one_screen; +#if LESSTEST +extern char *ttyin_name; +#endif /*LESSTEST*/ #if !MSDOS_COMPILER static char *cheaper LESSPARAMS((char *t1, char *t2, char *def)); @@ -229,15 +254,15 @@ static void tmodes LESSPARAMS((char *incap, char *outcap, char **instr, * and needed by, the termcap library. */ #if MUST_DEFINE_OSPEED -extern short ospeed; /* Terminal output baud rate */ -extern char PC; /* Pad character */ +extern short ospeed; /* Terminal output baud rate */ +extern char PC; /* Pad character */ #endif #ifdef _OSK short ospeed; char PC_, *UP, *BC; #endif -extern int quiet; /* If VERY_QUIET, use visual bell for bell */ +extern int quiet; /* If VERY_QUIET, use visual bell for bell */ extern int no_back_scroll; extern int swindow; extern int no_init; @@ -249,6 +274,8 @@ extern int top_scroll; extern int quit_if_one_screen; extern int oldbot; extern int mousecap; +extern int is_tty; +extern int use_color; #if HILITE_SEARCH extern int hilite_search; #endif @@ -270,12 +297,12 @@ extern char *tgoto(); /* * Change terminal to "raw mode", or restore to "normal" mode. * "Raw mode" means - * 1. An outstanding read will complete on receipt of a single keystroke. - * 2. Input is not echoed. - * 3. On output, \n is mapped to \r\n. - * 4. \t is NOT expanded into spaces. - * 5. Signal-causing characters such as ctrl-C (interrupt), - * etc. are NOT disabled. + * 1. An outstanding read will complete on receipt of a single keystroke. + * 2. Input is not echoed. + * 3. On output, \n is mapped to \r\n. + * 4. \t is NOT expanded into spaces. + * 5. Signal-causing characters such as ctrl-C (interrupt), + * etc. are NOT disabled. * It doesn't matter whether an input \n is mapped to \r, or vice versa. */ public void @@ -285,7 +312,7 @@ raw_mode(on) static int curr_on = 0; if (on == curr_on) - return; + return; erase2_char = '\b'; /* in case OS doesn't know about erase2 */ #if HAVE_TERMIOS_H && HAVE_TERMIOS_FUNCS { @@ -723,11 +750,11 @@ scrsize(VOID_PARAM) int n; #endif -#define DEF_SC_WIDTH 80 +#define DEF_SC_WIDTH 80 #if MSDOS_COMPILER -#define DEF_SC_HEIGHT 25 +#define DEF_SC_HEIGHT 25 #else -#define DEF_SC_HEIGHT 24 +#define DEF_SC_HEIGHT 24 #endif @@ -816,24 +843,24 @@ scrsize(VOID_PARAM) #endif #endif - if (sys_height > 0) - sc_height = sys_height; - else if ((s = lgetenv("LINES")) != NULL) + if ((s = lgetenv("LINES")) != NULL) sc_height = atoi(s); + else if (sys_height > 0) + sc_height = sys_height; #if !MSDOS_COMPILER else if ((n = ltgetnum("li")) > 0) - sc_height = n; + sc_height = n; #endif if (sc_height <= 0) sc_height = DEF_SC_HEIGHT; - if (sys_width > 0) - sc_width = sys_width; - else if ((s = lgetenv("COLUMNS")) != NULL) + if ((s = lgetenv("COLUMNS")) != NULL) sc_width = atoi(s); + else if (sys_width > 0) + sc_width = sys_width; #if !MSDOS_COMPILER else if ((n = ltgetnum("co")) > 0) - sc_width = n; + sc_width = n; #endif if (sc_width <= 0) sc_width = DEF_SC_WIDTH; @@ -895,22 +922,22 @@ special_key_str(key) static char tbuf[40]; char *s; #if MSDOS_COMPILER || OS2 - static char k_right[] = { '\340', PCK_RIGHT, 0 }; - static char k_left[] = { '\340', PCK_LEFT, 0 }; - static char k_ctl_right[] = { '\340', PCK_CTL_RIGHT, 0 }; - static char k_ctl_left[] = { '\340', PCK_CTL_LEFT, 0 }; - static char k_insert[] = { '\340', PCK_INSERT, 0 }; - static char k_delete[] = { '\340', PCK_DELETE, 0 }; - static char k_ctl_delete[] = { '\340', PCK_CTL_DELETE, 0 }; - static char k_ctl_backspace[] = { '\177', 0 }; - static char k_home[] = { '\340', PCK_HOME, 0 }; - static char k_end[] = { '\340', PCK_END, 0 }; - static char k_up[] = { '\340', PCK_UP, 0 }; - static char k_down[] = { '\340', PCK_DOWN, 0 }; - static char k_backtab[] = { '\340', PCK_SHIFT_TAB, 0 }; - static char k_pagedown[] = { '\340', PCK_PAGEDOWN, 0 }; - static char k_pageup[] = { '\340', PCK_PAGEUP, 0 }; - static char k_f1[] = { '\340', PCK_F1, 0 }; + static char k_right[] = { '\340', PCK_RIGHT, 0 }; + static char k_left[] = { '\340', PCK_LEFT, 0 }; + static char k_ctl_right[] = { '\340', PCK_CTL_RIGHT, 0 }; + static char k_ctl_left[] = { '\340', PCK_CTL_LEFT, 0 }; + static char k_insert[] = { '\340', PCK_INSERT, 0 }; + static char k_delete[] = { '\340', PCK_DELETE, 0 }; + static char k_ctl_delete[] = { '\340', PCK_CTL_DELETE, 0 }; + static char k_ctl_backspace[] = { '\177', 0 }; + static char k_home[] = { '\340', PCK_HOME, 0 }; + static char k_end[] = { '\340', PCK_END, 0 }; + static char k_up[] = { '\340', PCK_UP, 0 }; + static char k_down[] = { '\340', PCK_DOWN, 0 }; + static char k_backtab[] = { '\340', PCK_SHIFT_TAB, 0 }; + static char k_pagedown[] = { '\340', PCK_PAGEDOWN, 0 }; + static char k_pageup[] = { '\340', PCK_PAGEUP, 0 }; + static char k_f1[] = { '\340', PCK_F1, 0 }; #endif #if !MSDOS_COMPILER char *sp = tbuf; @@ -951,9 +978,9 @@ special_key_str(key) s = windowid ? ltgetstr("kD", &sp) : k_delete; if (s == NULL) { - tbuf[0] = '\177'; - tbuf[1] = '\0'; - s = tbuf; + tbuf[0] = '\177'; + tbuf[1] = '\0'; + s = tbuf; } break; #endif @@ -1037,9 +1064,9 @@ special_key_str(key) s = ltgetstr("kD", &sp); if (s == NULL) { - tbuf[0] = '\177'; - tbuf[1] = '\0'; - s = tbuf; + tbuf[0] = '\177'; + tbuf[1] = '\0'; + s = tbuf; } break; #endif @@ -1093,6 +1120,7 @@ get_term(VOID_PARAM) * before any file operations have been done on fd0. */ SET_BINARY(0); + GetConsoleMode(con_out, &init_output_mode); GetConsoleScreenBufferInfo(con_out, &scr); curr_attr = scr.wAttributes; sy_bg_color = (curr_attr & BG_COLORS) >> 4; /* normalize */ @@ -1497,6 +1525,34 @@ initcolor(VOID_PARAM) #if MSDOS_COMPILER==WIN32C +/* + * Enable virtual terminal processing, if available. + */ + static void +win32_init_vt_term(VOID_PARAM) +{ + DWORD output_mode; + + if (vt_enabled == 0 || (vt_enabled == 1 && con_out == con_out_ours)) + return; + + GetConsoleMode(con_out, &output_mode); + vt_enabled = SetConsoleMode(con_out, + output_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING); + if (vt_enabled) + { + auto_wrap = 0; + ignaw = 1; + } +} + + static void +win32_deinit_vt_term(VOID_PARAM) +{ + if (vt_enabled == 1 && con_out == con_out_save) + SetConsoleMode(con_out, init_output_mode); +} + /* * Termcap-like init with a private win32 console. */ @@ -1513,8 +1569,6 @@ win32_init_term(VOID_PARAM) if (con_out_ours == INVALID_HANDLE_VALUE) { - DWORD output_mode; - /* * Create our own screen buffer, so that we * may restore the original when done. @@ -1525,12 +1579,6 @@ win32_init_term(VOID_PARAM) (LPSECURITY_ATTRIBUTES) NULL, CONSOLE_TEXTMODE_BUFFER, (LPVOID) NULL); - /* - * Enable underline, if available. - */ - GetConsoleMode(con_out_ours, &output_mode); - have_ul = SetConsoleMode(con_out_ours, - output_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING); } size.X = scr.srWindow.Right - scr.srWindow.Left + 1; @@ -1556,6 +1604,68 @@ win32_deinit_term(VOID_PARAM) #endif +#if !MSDOS_COMPILER + static void +do_tputs(str, affcnt, f_putc) + char *str; + int affcnt; + int (*f_putc)(int); +{ +#if LESSTEST + if (ttyin_name != NULL) + putstr(str); + else +#endif /*LESSTEST*/ + tputs(str, affcnt, f_putc); +} + +/* + * Like tputs but we handle $<...> delay strings here because + * some implementations of tputs don't perform delays correctly. + */ + static void +ltputs(str, affcnt, f_putc) + char *str; + int affcnt; + int (*f_putc)(int); +{ + while (str != NULL && *str != '\0') + { +#if HAVE_STRSTR + char *obrac = strstr(str, "$<"); + if (obrac != NULL) + { + char str2[64]; + int slen = obrac - str; + if (slen < sizeof(str2)) + { + int delay; + /* Output first part of string (before "$<"). */ + memcpy(str2, str, slen); + str2[slen] = '\0'; + do_tputs(str2, affcnt, f_putc); + str += slen + 2; + /* Perform the delay. */ + delay = lstrtoi(str, &str); + if (*str == '*') + delay *= affcnt; + flush(); + sleep_ms(delay); + /* Skip past closing ">" at end of delay string. */ + str = strstr(str, ">"); + if (str != NULL) + str++; + continue; + } + } +#endif + /* Pass the rest of the string to tputs and we're done. */ + do_tputs(str, affcnt, f_putc); + break; + } +} +#endif /* MSDOS_COMPILER */ + /* * Configure the termimal so mouse clicks and wheel moves * produce input to less. @@ -1566,7 +1676,7 @@ init_mouse(VOID_PARAM) if (!mousecap) return; #if !MSDOS_COMPILER - tputs(sc_s_mousecap, sc_height, putchr); + ltputs(sc_s_mousecap, sc_height, putchr); #else #if MSDOS_COMPILER==WIN32C SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT @@ -1586,7 +1696,7 @@ deinit_mouse(VOID_PARAM) if (!mousecap) return; #if !MSDOS_COMPILER - tputs(sc_e_mousecap, sc_height, putchr); + ltputs(sc_e_mousecap, sc_height, putchr); #else #if MSDOS_COMPILER==WIN32C SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_EXTENDED_FLAGS @@ -1605,11 +1715,12 @@ init(VOID_PARAM) if (!(quit_if_one_screen && one_screen)) { if (!no_init) - tputs(sc_init, sc_height, putchr); + ltputs(sc_init, sc_height, putchr); if (!no_keypad) - tputs(sc_s_keypad, sc_height, putchr); + ltputs(sc_s_keypad, sc_height, putchr); init_mouse(); } + init_done = 1; if (top_scroll) { int i; @@ -1633,11 +1744,12 @@ init(VOID_PARAM) init_mouse(); } + win32_init_vt_term(); #endif + init_done = 1; initcolor(); flush(); #endif - init_done = 1; } /* @@ -1653,14 +1765,15 @@ deinit(VOID_PARAM) { deinit_mouse(); if (!no_keypad) - tputs(sc_e_keypad, sc_height, putchr); + ltputs(sc_e_keypad, sc_height, putchr); if (!no_init) - tputs(sc_deinit, sc_height, putchr); + ltputs(sc_deinit, sc_height, putchr); } #else /* Restore system colors. */ SETCOLORS(sy_fg_color, sy_bg_color); #if MSDOS_COMPILER==WIN32C + win32_deinit_vt_term(); if (!(quit_if_one_screen && one_screen)) { deinit_mouse(); @@ -1675,14 +1788,31 @@ deinit(VOID_PARAM) init_done = 0; } +/* + * Are we interactive (ie. writing to an initialized tty)? + */ + public int +interactive(VOID_PARAM) +{ + return (is_tty && init_done); +} + + static void +assert_interactive(VOID_PARAM) +{ + if (interactive()) return; + /* abort(); */ +} + /* * Home cursor (move to upper left corner of screen). */ public void home(VOID_PARAM) { + assert_interactive(); #if !MSDOS_COMPILER - tputs(sc_home, 1, putchr); + ltputs(sc_home, 1, putchr); #else flush(); _settextposition(1,1); @@ -1696,8 +1826,9 @@ home(VOID_PARAM) public void add_line(VOID_PARAM) { + assert_interactive(); #if !MSDOS_COMPILER - tputs(sc_addline, sc_height, putchr); + ltputs(sc_addline, sc_height, putchr); #else flush(); #if MSDOS_COMPILER==MSOFTC @@ -1905,10 +2036,9 @@ win32_scroll_up(n) public void lower_left(VOID_PARAM) { - if (!init_done) - return; + assert_interactive(); #if !MSDOS_COMPILER - tputs(sc_lower_left, 1, putchr); + ltputs(sc_lower_left, 1, putchr); #else flush(); _settextposition(sc_height, 1); @@ -1921,29 +2051,32 @@ lower_left(VOID_PARAM) public void line_left(VOID_PARAM) { + assert_interactive(); #if !MSDOS_COMPILER - tputs(sc_return, 1, putchr); + ltputs(sc_return, 1, putchr); #else - int row; - flush(); -#if MSDOS_COMPILER==WIN32C { - CONSOLE_SCREEN_BUFFER_INFO scr; - GetConsoleScreenBufferInfo(con_out, &scr); - row = scr.dwCursorPosition.Y - scr.srWindow.Top + 1; - } + int row; + flush(); +#if MSDOS_COMPILER==WIN32C + { + CONSOLE_SCREEN_BUFFER_INFO scr; + GetConsoleScreenBufferInfo(con_out, &scr); + row = scr.dwCursorPosition.Y - scr.srWindow.Top + 1; + } #else #if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC - row = wherey(); + row = wherey(); #else - { - struct rccoord tpos = _gettextposition(); - row = tpos.row; + { + struct rccoord tpos = _gettextposition(); + row = tpos.row; + } +#endif +#endif + _settextposition(row, 1); } #endif -#endif - _settextposition(row, 1); -#endif } /* @@ -1984,8 +2117,9 @@ check_winch(VOID_PARAM) goto_line(sindex) int sindex; { + assert_interactive(); #if !MSDOS_COMPILER - tputs(tgoto(sc_move, 0, sindex), 1, putchr); + ltputs(tgoto(sc_move, 0, sindex), 1, putchr); #else flush(); _settextposition(sindex+1, 1); @@ -2052,7 +2186,7 @@ vbell(VOID_PARAM) #if !MSDOS_COMPILER if (*sc_visual_bell == '\0') return; - tputs(sc_visual_bell, sc_height, putchr); + ltputs(sc_visual_bell, sc_height, putchr); #else #if MSDOS_COMPILER==DJGPPC ScreenVisualBell(); @@ -2142,8 +2276,9 @@ bell(VOID_PARAM) public void clear(VOID_PARAM) { + assert_interactive(); #if !MSDOS_COMPILER - tputs(sc_clear, sc_height, putchr); + ltputs(sc_clear, sc_height, putchr); #else flush(); #if MSDOS_COMPILER==WIN32C @@ -2161,8 +2296,9 @@ clear(VOID_PARAM) public void clear_eol(VOID_PARAM) { + /* assert_interactive();*/ #if !MSDOS_COMPILER - tputs(sc_eol_clear, 1, putchr); + ltputs(sc_eol_clear, 1, putchr); #else #if MSDOS_COMPILER==MSOFTC short top, left; @@ -2220,13 +2356,14 @@ clear_eol(VOID_PARAM) static void clear_eol_bot(VOID_PARAM) { + assert_interactive(); #if MSDOS_COMPILER clear_eol(); #else if (below_mem) - tputs(sc_eos_clear, 1, putchr); + ltputs(sc_eos_clear, 1, putchr); else - tputs(sc_eol_clear, 1, putchr); + ltputs(sc_eol_clear, 1, putchr); #endif } @@ -2259,42 +2396,305 @@ clear_bot(VOID_PARAM) } } +/* + * 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> + * Any of x,y,N,M may also be "-" to mean "unchanged". + */ + +/* + * Parse a 4-bit color char. + */ + static int +parse_color4(ch) + char ch; +{ + switch (ch) + { + case 'k': return 0; + case 'r': return CV_RED; + case 'g': return CV_GREEN; + case 'y': return CV_RED|CV_GREEN; + case 'b': return CV_BLUE; + case 'm': return CV_RED|CV_BLUE; + case 'c': return CV_GREEN|CV_BLUE; + case 'w': return CV_RED|CV_GREEN|CV_BLUE; + case 'K': return 0|CV_BRIGHT; + case 'R': return CV_RED|CV_BRIGHT; + case 'G': return CV_GREEN|CV_BRIGHT; + case 'Y': return CV_RED|CV_GREEN|CV_BRIGHT; + case 'B': return CV_BLUE|CV_BRIGHT; + case 'M': return CV_RED|CV_BLUE|CV_BRIGHT; + case 'C': return CV_GREEN|CV_BLUE|CV_BRIGHT; + case 'W': return CV_RED|CV_GREEN|CV_BLUE|CV_BRIGHT; + case '-': return CV_NOCHANGE; + default: return CV_ERROR; + } +} + +/* + * Parse a color as a decimal integer. + */ + static int +parse_color6(ps) + char **ps; +{ + if (**ps == '-') + { + (*ps)++; + return CV_NOCHANGE; + } else + { + char *ops = *ps; + int color = lstrtoi(ops, ps); + if (*ps == ops) + return CV_ERROR; + return color; + } +} + +/* + * Parse a color pair and return the foreground/background values. + * Return type of color specifier: + * CV_4BIT: fg/bg values are OR of CV_{RGB} bits. + * CV_6BIT: fg/bg values are integers entered by user. + */ + public COLOR_TYPE +parse_color(str, p_fg, p_bg) + char *str; + int *p_fg; + int *p_bg; +{ + int fg; + int bg; + COLOR_TYPE type = CT_NULL; + + if (str == NULL || *str == '\0') + return CT_NULL; + if (*str == '+') + str++; /* ignore leading + */ + + fg = parse_color4(str[0]); + bg = parse_color4((strlen(str) < 2) ? '-' : str[1]); + if (fg != CV_ERROR && bg != CV_ERROR) + type = CT_4BIT; + else + { + fg = parse_color6(&str); + bg = (fg != CV_ERROR && *str++ == '.') ? parse_color6(&str) : CV_NOCHANGE; + if (fg != CV_ERROR && bg != CV_ERROR) + type = CT_6BIT; + } + if (p_fg != NULL) *p_fg = fg; + if (p_bg != NULL) *p_bg = bg; + return type; +} + +#if !MSDOS_COMPILER + + static int +sgr_color(color) + int color; +{ + switch (color) + { + case 0: return 30; + case CV_RED: return 31; + case CV_GREEN: return 32; + case CV_RED|CV_GREEN: return 33; + case CV_BLUE: return 34; + case CV_RED|CV_BLUE: return 35; + case CV_GREEN|CV_BLUE: return 36; + case CV_RED|CV_GREEN|CV_BLUE: return 37; + + case CV_BRIGHT: return 90; + case CV_RED|CV_BRIGHT: return 91; + case CV_GREEN|CV_BRIGHT: return 92; + case CV_RED|CV_GREEN|CV_BRIGHT: return 93; + case CV_BLUE|CV_BRIGHT: return 94; + case CV_RED|CV_BLUE|CV_BRIGHT: return 95; + case CV_GREEN|CV_BLUE|CV_BRIGHT: return 96; + case CV_RED|CV_GREEN|CV_BLUE|CV_BRIGHT: return 97; + + default: return color; + } +} + + static void +tput_fmt(fmt, color, f_putc) + char *fmt; + int color; + int (*f_putc)(int); +{ + char buf[16]; + if (color == attrcolor) + return; + SNPRINTF1(buf, sizeof(buf), fmt, color); + ltputs(buf, 1, f_putc); + attrcolor = color; +} + + static void +tput_color(str, f_putc) + char *str; + int (*f_putc)(int); +{ + int fg; + int bg; + + if (str != NULL && strcmp(str, "*") == 0) + { + /* Special case: reset to normal */ + tput_fmt(ESCS"[m", -1, f_putc); + return; + } + switch (parse_color(str, &fg, &bg)) + { + case CT_4BIT: + if (fg >= 0) + tput_fmt(ESCS"[%dm", sgr_color(fg), f_putc); + if (bg >= 0) + tput_fmt(ESCS"[%dm", sgr_color(bg)+10, f_putc); + break; + case CT_6BIT: + if (fg >= 0) + tput_fmt(ESCS"[38;5;%dm", fg, f_putc); + if (bg >= 0) + tput_fmt(ESCS"[48;5;%dm", bg, f_putc); + break; + default: + break; + } +} + + static void +tput_inmode(mode_str, attr, attr_bit, f_putc) + char *mode_str; + int attr; + int attr_bit; + int (*f_putc)(int); +{ + char *color_str; + if ((attr & attr_bit) == 0) + return; + color_str = get_color_map(attr_bit); + if (color_str == NULL || *color_str == '\0' || *color_str == '+') + { + ltputs(mode_str, 1, f_putc); + if (color_str == NULL || *color_str++ != '+') + return; + } + /* Color overrides mode string */ + tput_color(color_str, f_putc); +} + + static void +tput_outmode(mode_str, attr_bit, f_putc) + char *mode_str; + int attr_bit; + int (*f_putc)(int); +{ + if ((attrmode & attr_bit) == 0) + return; + ltputs(mode_str, 1, f_putc); +} + +#else /* MSDOS_COMPILER */ + +#if MSDOS_COMPILER==WIN32C + static int +WIN32put_fmt(fmt, color) + char *fmt; + int color; +{ + char buf[16]; + int len = SNPRINTF1(buf, sizeof(buf), fmt, color); + WIN32textout(buf, len); + return TRUE; +} +#endif + + static int +win_set_color(attr) + int attr; +{ + int fg; + int bg; + int out = FALSE; + char *str = get_color_map(attr); + if (str == NULL || str[0] == '\0') + return FALSE; + switch (parse_color(str, &fg, &bg)) + { + case CT_4BIT: + if (fg >= 0 && bg >= 0) + { + SETCOLORS(fg, bg); + out = TRUE; + } else if (fg >= 0) + { + SET_FG_COLOR(fg); + out = TRUE; + } else if (bg >= 0) + { + SET_BG_COLOR(bg); + out = TRUE; + } + break; +#if MSDOS_COMPILER==WIN32C + case CT_6BIT: + if (vt_enabled) + { + if (fg > 0) + out = WIN32put_fmt(ESCS"[38;5;%dm", fg); + if (bg > 0) + out = WIN32put_fmt(ESCS"[48;5;%dm", bg); + } + break; +#endif + default: + break; + } + return out; +} + +#endif /* MSDOS_COMPILER */ + public void at_enter(attr) int attr; { attr = apply_at_specials(attr); - #if !MSDOS_COMPILER /* The one with the most priority is last. */ - if (attr & AT_UNDERLINE) - tputs(sc_u_in, 1, putchr); - if (attr & AT_BOLD) - tputs(sc_b_in, 1, putchr); - if (attr & AT_BLINK) - tputs(sc_bl_in, 1, putchr); - if (attr & AT_STANDOUT) - tputs(sc_s_in, 1, putchr); + tput_inmode(sc_u_in, attr, AT_UNDERLINE, putchr); + tput_inmode(sc_b_in, attr, AT_BOLD, putchr); + tput_inmode(sc_bl_in, attr, AT_BLINK, putchr); + /* Don't use standout and color at the same time. */ + if (use_color && (attr & AT_COLOR)) + tput_color(get_color_map(attr), putchr); + else + tput_inmode(sc_s_in, attr, AT_STANDOUT, putchr); #else flush(); /* The one with the most priority is first. */ - if (attr & AT_STANDOUT) + if ((attr & AT_COLOR) && use_color) + { + win_set_color(attr); + } else if (attr & AT_STANDOUT) { SETCOLORS(so_fg_color, so_bg_color); } else if (attr & AT_BLINK) { SETCOLORS(bl_fg_color, bl_bg_color); - } - else if (attr & AT_BOLD) + } else if (attr & AT_BOLD) { SETCOLORS(bo_fg_color, bo_bg_color); - } - else if (attr & AT_UNDERLINE) + } else if (attr & AT_UNDERLINE) { SETCOLORS(ul_fg_color, ul_bg_color); } #endif - attrmode = attr; } @@ -2303,19 +2703,15 @@ at_exit(VOID_PARAM) { #if !MSDOS_COMPILER /* Undo things in the reverse order we did them. */ - if (attrmode & AT_STANDOUT) - tputs(sc_s_out, 1, putchr); - if (attrmode & AT_BLINK) - tputs(sc_bl_out, 1, putchr); - if (attrmode & AT_BOLD) - tputs(sc_b_out, 1, putchr); - if (attrmode & AT_UNDERLINE) - tputs(sc_u_out, 1, putchr); + tput_color("*", putchr); + tput_outmode(sc_s_out, AT_STANDOUT, putchr); + tput_outmode(sc_bl_out, AT_BLINK, putchr); + tput_outmode(sc_b_out, AT_BOLD, putchr); + tput_outmode(sc_u_out, AT_UNDERLINE, putchr); #else flush(); SETCOLORS(nm_fg_color, nm_bg_color); #endif - attrmode = AT_NORMAL; } @@ -2357,57 +2753,6 @@ apply_at_specials(attr) return attr; } -#if 0 /* No longer used */ -/* - * Erase the character to the left of the cursor - * and move the cursor left. - */ - public void -backspace(VOID_PARAM) -{ -#if !MSDOS_COMPILER - /* - * Erase the previous character by overstriking with a space. - */ - tputs(sc_backspace, 1, putchr); - putchr(' '); - tputs(sc_backspace, 1, putchr); -#else -#if MSDOS_COMPILER==MSOFTC - struct rccoord tpos; - - flush(); - tpos = _gettextposition(); - if (tpos.col <= 1) - return; - _settextposition(tpos.row, tpos.col-1); - _outtext(" "); - _settextposition(tpos.row, tpos.col-1); -#else -#if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC - cputs("\b"); -#else -#if MSDOS_COMPILER==WIN32C - COORD cpos; - DWORD cChars; - CONSOLE_SCREEN_BUFFER_INFO scr; - - flush(); - GetConsoleScreenBufferInfo(con_out, &scr); - cpos = scr.dwCursorPosition; - if (cpos.X <= 0) - return; - cpos.X--; - SetConsoleCursorPosition(con_out, cpos); - FillConsoleOutputCharacter(con_out, (TCHAR)' ', 1, cpos, &cChars); - SetConsoleCursorPosition(con_out, cpos); -#endif -#endif -#endif -#endif -} -#endif /* 0 */ - /* * Output a plain backspace, without erasing the previous char. */ @@ -2419,7 +2764,7 @@ putbs(VOID_PARAM) else { #if !MSDOS_COMPILER - tputs(sc_backspace, 1, putchr); + ltputs(sc_backspace, 1, putchr); #else int row, col; @@ -2638,3 +2983,4 @@ WIN32textout(text, len) #endif } #endif + diff --git a/scrsize.c b/scrsize.c index 2063aa376bb3..ee07cb8af1e6 100644 --- a/scrsize.c +++ b/scrsize.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. diff --git a/search.c b/search.c index 7650ab379508..f619fbebeae8 100644 --- a/search.c +++ b/search.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -16,8 +16,8 @@ #include "position.h" #include "charset.h" -#define MINPOS(a,b) (((a) < (b)) ? (a) : (b)) -#define MAXPOS(a,b) (((a) > (b)) ? (a) : (b)) +#define MINPOS(a,b) (((a) < (b)) ? (a) : (b)) +#define MAXPOS(a,b) (((a) > (b)) ? (a) : (b)) extern int sigs; extern int how_search; @@ -33,6 +33,10 @@ extern POSITION start_attnpos; extern POSITION end_attnpos; extern int utf_mode; extern int screen_trashed; +extern int sc_width; +extern int sc_height; +extern int chopline; +extern int hshift; #if HILITE_SEARCH extern int hilite_search; extern int size_linebuf; @@ -41,8 +45,7 @@ extern int can_goto_line; static int hide_hilite; static POSITION prep_startpos; static POSITION prep_endpos; -static int is_caseless; -static int is_ucase_pattern; +extern POSITION xxpos; /* * Structures for maintaining a set of ranges for hilites and filtered-out @@ -94,6 +97,7 @@ struct hilite_tree static struct hilite_tree hilite_anchor = HILITE_INITIALIZER(); static struct hilite_tree filter_anchor = HILITE_INITIALIZER(); +static struct pattern_info *filter_infos = NULL; #endif @@ -105,6 +109,7 @@ struct pattern_info { PATTERN_TYPE compiled; char* text; int search_type; + struct pattern_info *next; }; #if NO_REGEX @@ -114,7 +119,8 @@ struct pattern_info { #endif static struct pattern_info search_info; -static struct pattern_info filter_info; +static int is_ucase_pattern; +static int is_caseless; /* * Are there any uppercase letters in this string? @@ -135,19 +141,35 @@ is_ucase(str) return (0); } +/* + * Discard a saved pattern. + */ + static void +clear_pattern(info) + struct pattern_info *info; +{ + if (info->text != NULL) + free(info->text); + info->text = NULL; +#if !NO_REGEX + uncompile_pattern(&info->compiled); +#endif +} + /* * Compile and save a search pattern. */ static int -set_pattern(info, pattern, search_type) +set_pattern(info, pattern, search_type, show_error) struct pattern_info *info; char *pattern; int search_type; + int show_error; { #if !NO_REGEX if (pattern == NULL) - CLEAR_PATTERN(info->compiled); - else if (compile_pattern(pattern, search_type, &info->compiled) < 0) + SET_NULL_PATTERN(info->compiled); + else if (compile_pattern(pattern, search_type, show_error, &info->compiled) < 0) return -1; #endif /* Pattern compiled successfully; save the text too. */ @@ -173,21 +195,6 @@ set_pattern(info, pattern, search_type) return 0; } -/* - * Discard a saved pattern. - */ - static void -clear_pattern(info) - struct pattern_info *info; -{ - if (info->text != NULL) - free(info->text); - info->text = NULL; -#if !NO_REGEX - uncompile_pattern(&info->compiled); -#endif -} - /* * Initialize saved pattern to nothing. */ @@ -195,9 +202,10 @@ clear_pattern(info) init_pattern(info) struct pattern_info *info; { - CLEAR_PATTERN(info->compiled); + SET_NULL_PATTERN(info->compiled); info->text = NULL; info->search_type = 0; + info->next = NULL; } /* @@ -207,7 +215,6 @@ init_pattern(info) init_search(VOID_PARAM) { init_pattern(&search_info); - init_pattern(&filter_info); } /* @@ -217,18 +224,13 @@ init_search(VOID_PARAM) get_cvt_ops(VOID_PARAM) { int ops = 0; - if (is_caseless || bs_mode == BS_SPECIAL) - { - if (is_caseless) - ops |= CVT_TO_LC; - if (bs_mode == BS_SPECIAL) - ops |= CVT_BS; - if (bs_mode != BS_CONTROL) - ops |= CVT_CRLF; - } else if (bs_mode != BS_CONTROL) - { + + if (is_caseless) + ops |= CVT_TO_LC; + if (bs_mode == BS_SPECIAL) + ops |= CVT_BS; + if (bs_mode != BS_CONTROL) ops |= CVT_CRLF; - } if (ctldisp == OPT_ONPLUS) ops |= CVT_ANSI; return (ops); @@ -292,6 +294,7 @@ repaint_hilite(on) lower_left(); hide_hilite = save_hide_hilite; } +#endif /* * Clear the attn hilite. @@ -299,6 +302,7 @@ repaint_hilite(on) public void clear_attn(VOID_PARAM) { +#if HILITE_SEARCH int sindex; POSITION old_start_attnpos; POSITION old_end_attnpos; @@ -337,27 +341,30 @@ clear_attn(VOID_PARAM) } if (moved) lower_left(); -} #endif +} /* - * Hide search string highlighting. + * Toggle or clear search string highlighting. */ public void -undo_search(VOID_PARAM) +undo_search(clear) + int clear; { - if (!prev_pattern(&search_info)) + clear_pattern(&search_info); +#if HILITE_SEARCH + if (clear) + { + clr_hilite(); + } else { if (hilite_anchor.first == NULL) { error("No previous regular expression", NULL_PARG); return; } - clr_hilite(); /* Next time, hilite_anchor.first will be NULL. */ + hide_hilite = !hide_hilite; } - clear_pattern(&search_info); -#if HILITE_SEARCH - hide_hilite = !hide_hilite; repaint_hilite(1); #endif } @@ -601,7 +608,7 @@ prev_unfiltered(pos) * If nohide is nonzero, don't consider hide_hilite. */ public int -is_hilited(pos, epos, nohide, p_matches) +is_hilited_attr(pos, epos, nohide, p_matches) POSITION pos; POSITION epos; int nohide; @@ -614,12 +621,12 @@ is_hilited(pos, epos, nohide, p_matches) if (!status_col && start_attnpos != NULL_POSITION && - pos < end_attnpos && - (epos == NULL_POSITION || epos > start_attnpos)) + pos <= end_attnpos && + (epos == NULL_POSITION || epos >= start_attnpos)) /* * The attn line overlaps this range. */ - return (1); + return (AT_HILITE|AT_COLOR_ATTN); match = is_hilited_range(pos, epos); if (!match) @@ -631,7 +638,7 @@ is_hilited(pos, epos, nohide, p_matches) * hilite in status column. In this case we want to return * hilite status even if hiliting is disabled or hidden. */ - return (1); + return (AT_HILITE|AT_COLOR_SEARCH); /* * Report matches, even if we're hiding highlights. @@ -650,7 +657,7 @@ is_hilited(pos, epos, nohide, p_matches) */ return (0); - return (1); + return (AT_HILITE|AT_COLOR_SEARCH); } /* @@ -1155,11 +1162,92 @@ search_pos(search_type) return (pos); } +/* + * Check to see if the line matches the filter pattern. + * If so, add an entry to the filter list. + */ +#if HILITE_SEARCH + static int +matches_filters(pos, cline, line_len, chpos, linepos, sp, ep) + POSITION pos; + char *cline; + int line_len; + int *chpos; + POSITION linepos; + char **sp; + char **ep; +{ + 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, 0, filter->search_type); + if (line_filter) + { + struct hilite hl; + hl.hl_startpos = linepos; + hl.hl_endpos = pos; + add_hilite(&filter_anchor, &hl); + free(cline); + free(chpos); + return (1); + } + } + return (0); +} +#endif + +/* + * Get the position of the first char in the screen line which + * puts tpos on screen. + */ + static POSITION +get_lastlinepos(pos, tpos, sheight) + POSITION pos; + POSITION tpos; + int sheight; +{ + int nlines; + + for (nlines = 0;; nlines++) + { + POSITION npos = forw_line(pos); + if (npos > tpos) + { + if (nlines < sheight) + return NULL_POSITION; + return pos; + } + pos = npos; + } +} + +/* + * Get the segment index of tpos in the line starting at pos. + * A segment is a string of printable chars that fills the screen width. + */ + static int +get_seg(pos, tpos) + POSITION pos; + POSITION tpos; +{ + int seg; + + for (seg = 0;; seg++) + { + POSITION npos = forw_line_seg(pos, TRUE); + if (npos > tpos) + return seg; + pos = npos; + } +} + /* * Search a subset of the file, specified by start/end position. */ static int -search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos) +search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos, plastlinepos) POSITION pos; POSITION endpos; int search_type; @@ -1167,6 +1255,7 @@ search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos) int maxlines; POSITION *plinepos; POSITION *pendpos; + POSITION *plastlinepos; { char *line; char *cline; @@ -1178,9 +1267,14 @@ search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos) int cvt_len; int *chpos; POSITION linepos, oldpos; + int swidth = sc_width - line_pfx_width(); + int sheight = sc_height - sindex_from_sline(jump_sline); linenum = find_linenum(pos); oldpos = pos; + /* When the search wraps around, end at starting position. */ + if ((search_type & SRCH_WRAP) && endpos == NULL_POSITION) + endpos = pos; for (;;) { /* @@ -1196,7 +1290,9 @@ search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos) return (-1); } - if ((endpos != NULL_POSITION && pos >= endpos) || maxlines == 0) + if ((endpos != NULL_POSITION && !(search_type & SRCH_WRAP) && + (((search_type & SRCH_FORW) && pos >= endpos) || + ((search_type & SRCH_BACK) && pos <= endpos))) || maxlines == 0) { /* * Reached end position without a match. @@ -1235,6 +1331,35 @@ search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos) /* * Reached EOF/BOF without a match. */ + if (search_type & SRCH_WRAP) + { + /* + * The search wraps around the current file, so + * try to continue at BOF/EOF. + */ + if (search_type & SRCH_FORW) + { + pos = ch_zero(); + } else + { + pos = ch_length(); + if (pos == NULL_POSITION) + { + (void) ch_end_seek(); + pos = ch_length(); + } + } + if (pos != NULL_POSITION) { + /* + * Wrap-around was successful. Clear + * the flag so we don't wrap again, and + * continue the search at new pos. + */ + search_type &= ~SRCH_WRAP; + linenum = find_linenum(pos); + continue; + } + } if (pendpos != NULL) *pendpos = oldpos; return (matches); @@ -1252,8 +1377,10 @@ search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos) add_lnum(linenum, pos); oldpos = pos; +#if HILITE_SEARCH if (is_filtered(linepos)) continue; +#endif /* * If it's a caseless search, convert the line to lowercase. @@ -1267,25 +1394,14 @@ search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos) #if HILITE_SEARCH /* - * Check to see if the line matches the filter pattern. - * If so, add an entry to the filter list. + * If any filters are in effect, ignore non-matching lines. */ - if (((search_type & SRCH_FIND_ALL) || + if (filter_infos != NULL && + ((search_type & SRCH_FIND_ALL) || prep_startpos == NULL_POSITION || - linepos < prep_startpos || linepos >= prep_endpos) && - prev_pattern(&filter_info)) { - int line_filter = match_pattern(info_compiled(&filter_info), filter_info.text, - cline, line_len, &sp, &ep, 0, filter_info.search_type); - if (line_filter) - { - struct hilite hl; - hl.hl_startpos = linepos; - hl.hl_endpos = pos; - add_hilite(&filter_anchor, &hl); - free(cline); - free(chpos); + linepos < prep_startpos || linepos >= prep_endpos)) { + if (matches_filters(pos, cline, line_len, chpos, linepos, &sp, &ep)) continue; - } } #endif @@ -1330,6 +1446,50 @@ search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos) hilite_line(linepos, cline, line_len, chpos, sp, ep, cvt_ops); } #endif + if (chopline) + { + /* + * If necessary, shift horizontally to make sure + * search match is fully visible. + */ + if (sp != NULL && ep != NULL) + { + int start_off = sp - cline; + int end_off = ep - cline; + int save_hshift = hshift; + int sshift; + int eshift; + hshift = 0; /* make get_seg count screen lines */ + chopline = FALSE; + sshift = swidth * get_seg(linepos, linepos + chpos[start_off]); + eshift = swidth * get_seg(linepos, linepos + chpos[end_off]); + chopline = TRUE; + if (sshift >= save_hshift && eshift <= save_hshift) + { + hshift = save_hshift; + } else + { + hshift = sshift; + screen_trashed = 1; + } + } + } else if (plastlinepos != NULL) + { + /* + * If the line is so long that the highlighted match + * won't be seen when the line is displayed normally + * (starting at the first char) because it fills the whole + * screen and more, scroll forward until the last char + * of the match appears in the last line on the screen. + * lastlinepos is the position of the first char of that last line. + */ + if (ep != NULL) + { + int end_off = ep - cline; + if (end_off >= swidth * sheight / 4) /* heuristic */ + *plastlinepos = get_lastlinepos(linepos, linepos + chpos[end_off], sheight); + } + } free(cline); free(chpos); if (plinepos != NULL) @@ -1358,8 +1518,8 @@ hist_pattern(search_type) if (pattern == NULL) return (0); - if (set_pattern(&search_info, pattern, search_type) < 0) - return (0); + if (set_pattern(&search_info, pattern, search_type, 1) < 0) + return (-1); #if HILITE_SEARCH if (hilite_search == OPT_ONPLUS && !hide_hilite) @@ -1392,7 +1552,7 @@ chg_caseless(VOID_PARAM) * Regenerate the pattern using the new state. */ clear_pattern(&search_info); - hist_pattern(search_info.search_type); + (void) hist_pattern(search_info.search_type); } } @@ -1412,6 +1572,8 @@ search(search_type, pattern, n) int n; { POSITION pos; + POSITION opos; + POSITION lastlinepos = NULL_POSITION; if (pattern == NULL || *pattern == '\0') { @@ -1419,10 +1581,13 @@ search(search_type, pattern, n) * A null pattern means use the previously compiled pattern. */ search_type |= SRCH_AFTER_TARGET; - if (!prev_pattern(&search_info) && !hist_pattern(search_type)) + if (!prev_pattern(&search_info)) { - error("No previous regular expression", NULL_PARG); - return (-1); + int r = hist_pattern(search_type); + if (r == 0) + error("No previous regular expression", NULL_PARG); + if (r <= 0) + return (-1); } if ((search_type & SRCH_NO_REGEX) != (search_info.search_type & SRCH_NO_REGEX)) @@ -1455,7 +1620,8 @@ search(search_type, pattern, n) /* * Compile the pattern. */ - if (set_pattern(&search_info, pattern, search_type) < 0) + int show_error = !(search_type & SRCH_INCR); + if (set_pattern(&search_info, pattern, search_type, show_error) < 0) return (-1); #if HILITE_SEARCH if (hilite_search || status_col) @@ -1483,6 +1649,7 @@ search(search_type, pattern, n) * Figure out where to start the search. */ pos = search_pos(search_type); + opos = position(sindex_from_sline(jump_sline)); if (pos == NULL_POSITION) { /* @@ -1490,14 +1657,16 @@ search(search_type, pattern, n) */ if (search_type & SRCH_PAST_EOF) return (n); +#if HILITE_SEARCH if (hilite_search == OPT_ON || status_col) repaint_hilite(1); +#endif error("Nothing to search", NULL_PARG); return (-1); } n = search_range(pos, NULL_POSITION, search_type, n, -1, - &pos, (POSITION*)NULL); + &pos, (POSITION*)NULL, &lastlinepos); if (n != 0) { /* @@ -1518,7 +1687,10 @@ search(search_type, pattern, n) /* * Go to the matching line. */ - jump_loc(pos, jump_sline); + if (lastlinepos != NULL_POSITION) + jump_loc(lastlinepos, BOTTOM); + else if (pos != opos) + jump_loc(pos, jump_sline); } #if HILITE_SEARCH @@ -1531,7 +1703,6 @@ search(search_type, pattern, n) return (0); } - #if HILITE_SEARCH /* * Prepare hilites in a given range of the file. @@ -1560,7 +1731,7 @@ prep_hilite(spos, epos, maxlines) * 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. */ -#define SEARCH_MORE (3*size_linebuf) +#define SEARCH_MORE (3*size_linebuf) if (!prev_pattern(&search_info) && !is_filtering()) return; @@ -1665,7 +1836,7 @@ prep_hilite(spos, epos, maxlines) search_type |= (search_info.search_type & SRCH_NO_REGEX); for (;;) { - result = search_range(spos, epos, search_type, 0, maxlines, (POSITION*)NULL, &new_epos); + result = search_range(spos, epos, search_type, 0, maxlines, (POSITION*)NULL, &new_epos, (POSITION*)NULL); if (result < 0) return; if (prep_endpos == NULL_POSITION || new_epos > prep_endpos) @@ -1718,11 +1889,29 @@ set_filter_pattern(pattern, search_type) char *pattern; int search_type; { + struct pattern_info *filter; + clr_filter(); if (pattern == NULL || *pattern == '\0') - clear_pattern(&filter_info); - else - set_pattern(&filter_info, pattern, search_type); + { + /* Clear and free all filters. */ + for (filter = filter_infos; filter != NULL; ) + { + struct pattern_info *next_filter = filter->next; + clear_pattern(filter); + free(filter); + filter = next_filter; + } + filter_infos = NULL; + } else + { + /* Create a new filter and add it to the filter_infos list. */ + filter = ecalloc(1, sizeof(struct pattern_info)); + init_pattern(filter); + set_pattern(filter, pattern, search_type, 1); + filter->next = filter_infos; + filter_infos = filter; + } screen_trashed = 1; } @@ -1734,7 +1923,7 @@ is_filtering(VOID_PARAM) { if (ch_getflags() & CH_HELPFILE) return (0); - return prev_pattern(&filter_info); + return (filter_infos != NULL); } #endif diff --git a/signal.c b/signal.c index 49c843d34d2e..dd666832e3f5 100644 --- a/signal.c +++ b/signal.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -33,6 +33,7 @@ extern int linenums; extern int wscroll; extern int reading; extern int quit_on_intr; +extern int secure; extern long jump_sline_fraction; /* @@ -58,6 +59,9 @@ u_interrupt(type) */ if (kbhit()) getkey(); +#endif +#if HILITE_SEARCH + set_filter_pattern(NULL, 0); #endif if (reading) intread(); /* May longjmp */ @@ -121,6 +125,9 @@ wbreak_handler(dwCtrlType) case CTRL_C_EVENT: case CTRL_BREAK_EVENT: sigs |= S_INTERRUPT; +#if HILITE_SEARCH + set_filter_pattern(NULL, 0); +#endif return (TRUE); default: break; @@ -154,7 +161,7 @@ init_signals(on) (void) LSIGNAL(SIGINT, u_interrupt); #endif #ifdef SIGTSTP - (void) LSIGNAL(SIGTSTP, stop); + (void) LSIGNAL(SIGTSTP, secure ? SIG_IGN : stop); #endif #ifdef SIGWINCH (void) LSIGNAL(SIGWINCH, winch); diff --git a/tags.c b/tags.c index fdc82da24e82..d449c0333deb 100644 --- a/tags.c +++ b/tags.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -10,7 +10,7 @@ #include "less.h" -#define WHITESP(c) ((c)==' ' || (c)=='\t') +#define WHITESP(c) ((c)==' ' || (c)=='\t') #if TAGS @@ -36,12 +36,12 @@ enum tag_result { * Tag type */ enum { - T_CTAGS, /* 'tags': standard and extended format (ctags) */ - T_CTAGS_X, /* stdin: cross reference format (ctags) */ - T_GTAGS, /* 'GTAGS': function definition (global) */ - T_GRTAGS, /* 'GRTAGS': function reference (global) */ - T_GSYMS, /* 'GSYMS': other symbols (global) */ - T_GPATH /* 'GPATH': path name (global) */ + T_CTAGS, /* 'tags': standard and extended format (ctags) */ + T_CTAGS_X, /* stdin: cross reference format (ctags) */ + T_GTAGS, /* 'GTAGS': function definition (global) */ + T_GRTAGS, /* 'GRTAGS': function reference (global) */ + T_GSYMS, /* 'GSYMS': other symbols (global) */ + T_GPATH /* 'GPATH': path name (global) */ }; static enum tag_result findctag LESSPARAMS((char *tag)); @@ -50,8 +50,7 @@ static char *nextgtag(VOID_PARAM); static char *prevgtag(VOID_PARAM); static POSITION ctagsearch(VOID_PARAM); static POSITION gtagsearch(VOID_PARAM); -static int getentry LESSPARAMS((char *buf, char **tag, char **file, - char **line)); +static int getentry LESSPARAMS((char *buf, char **tag, char **file, char **line)); /* * The list of tags generated by the last findgtag() call. @@ -67,10 +66,10 @@ struct taglist { }; struct tag { struct tag *next, *prev; /* List links */ - char *tag_file; /* Source file containing the tag */ - LINENUM tag_linenum; /* Appropriate line number in source file */ - char *tag_pattern; /* Pattern used to find the tag */ - char tag_endline; /* True if the pattern includes '$' */ + char *tag_file; /* Source file containing the tag */ + LINENUM tag_linenum; /* Appropriate line number in source file */ + char *tag_pattern; /* Pattern used to find the tag */ + char tag_endline; /* True if the pattern includes '$' */ }; #define TAG_END ((struct tag *) &taglist) static struct taglist taglist = { TAG_END, TAG_END }; @@ -412,10 +411,10 @@ curtag_match(char const *line, POSITION linepos) * Search for a tag. * This is a stripped-down version of search(). * We don't use search() for several reasons: - * - We don't want to blow away any search string we may have saved. - * - The various regular-expression functions (from different systems: - * regcmp vs. re_comp) behave differently in the presence of - * parentheses (which are almost always found in a tag). + * - We don't want to blow away any search string we may have saved. + * - The various regular-expression functions (from different systems: + * regcmp vs. re_comp) behave differently in the presence of + * parentheses (which are almost always found in a tag). */ static POSITION ctagsearch(VOID_PARAM) @@ -498,8 +497,8 @@ ctagsearch(VOID_PARAM) */ static enum tag_result findgtag(tag, type) - char *tag; /* tag to load */ - int type; /* tags type */ + char *tag; /* tag to load */ + int type; /* tags type */ { char buf[256]; FILE *fp; @@ -590,7 +589,7 @@ findgtag(tag, type) } while (c != '\n' && c != EOF); } - if (getentry(buf, &name, &file, &line)) + if (getentry(buf, &name, &file, &line)) { /* * Couldn't parse this line for some reason. @@ -624,7 +623,7 @@ findgtag(tag, type) return TAG_FOUND; } -static int circular = 0; /* 1: circular tag structure */ +static int circular = 0; /* 1: circular tag structure */ /* * Return the filename required for the next gtag in the queue that was setup @@ -709,9 +708,9 @@ gtagsearch(VOID_PARAM) * |func 21 subr.c func(arg) * * The following commands write this format. - * o Traditinal Ctags with -x option - * o Global with -x option - * See + * o Traditinal Ctags with -x option + * o Global with -x option + * See * * [extended format] * @@ -720,8 +719,8 @@ gtagsearch(VOID_PARAM) * |func function 21 subr.c func(arg) * * The following commands write this format. - * o Exuberant Ctags with -x option - * See + * o Exuberant Ctags with -x option + * See * * Returns 0 on success, -1 on error. * The tag, file, and line will each be NUL-terminated pointers @@ -729,19 +728,19 @@ gtagsearch(VOID_PARAM) */ static int getentry(buf, tag, file, line) - char *buf; /* standard or extended ctags -x format data */ - char **tag; /* name of the tag we actually found */ - char **file; /* file in which to find this tag */ - char **line; /* line number of file where this tag is found */ + char *buf; /* standard or extended ctags -x format data */ + char **tag; /* name of the tag we actually found */ + char **file; /* file in which to find this tag */ + char **line; /* line number of file where this tag is found */ { char *p = buf; - for (*tag = p; *p && !IS_SPACE(*p); p++) /* tag name */ + for (*tag = p; *p && !IS_SPACE(*p); p++) /* tag name */ ; if (*p == 0) return (-1); *p++ = 0; - for ( ; *p && IS_SPACE(*p); p++) /* (skip blanks) */ + for ( ; *p && IS_SPACE(*p); p++) /* (skip blanks) */ ; if (*p == 0) return (-1); @@ -751,24 +750,24 @@ getentry(buf, tag, file, line) */ if (!IS_DIGIT(*p)) { - for ( ; *p && !IS_SPACE(*p); p++) /* (skip tag type) */ + for ( ; *p && !IS_SPACE(*p); p++) /* (skip tag type) */ ; - for (; *p && IS_SPACE(*p); p++) /* (skip blanks) */ + for (; *p && IS_SPACE(*p); p++) /* (skip blanks) */ ; } if (!IS_DIGIT(*p)) return (-1); - *line = p; /* line number */ + *line = p; /* line number */ for (*line = p; *p && !IS_SPACE(*p); p++) ; if (*p == 0) return (-1); *p++ = 0; - for ( ; *p && IS_SPACE(*p); p++) /* (skip blanks) */ + for ( ; *p && IS_SPACE(*p); p++) /* (skip blanks) */ ; if (*p == 0) return (-1); - *file = p; /* file name */ + *file = p; /* file name */ for (*file = p; *p && !IS_SPACE(*p); p++) ; if (*p == 0) @@ -780,5 +779,5 @@ getentry(buf, tag, file, line) return (0); return (-1); } - + #endif diff --git a/ttyin.c b/ttyin.c index 3bb99ecca6fb..5bd3385ceadb 100644 --- a/ttyin.c +++ b/ttyin.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -28,10 +28,35 @@ public HANDLE tty; #else public int tty; #endif +#if LESSTEST +public char *ttyin_name = NULL; +public int rstat_file = -1; +#endif /*LESSTEST*/ extern int sigs; extern int utf_mode; extern int wheel_lines; +/* + * Get name of tty device. + */ +#if !MSDOS_COMPILER + public char * +tty_device(VOID_PARAM) +{ + char *dev = NULL; +#if HAVE_TTYNAME + dev = ttyname(2); +#endif + if (dev == NULL) + dev = "/dev/tty"; +#if LESSTEST + if (ttyin_name != NULL) + dev = ttyin_name; +#endif /*LESSTEST*/ + return dev; +} +#endif /* MSDOS_COMPILER */ + /* * Open keyboard for input. */ @@ -76,9 +101,9 @@ open_getchr(VOID_PARAM) */ #if OS2 /* The __open() system call translates "/dev/tty" to "con". */ - tty = __open("/dev/tty", OPEN_READ); + tty = __open(tty_device(), OPEN_READ); #else - tty = open("/dev/tty", OPEN_READ); + tty = open(tty_device(), OPEN_READ); #endif if (tty < 0) tty = 2; @@ -131,6 +156,18 @@ default_wheel_lines(VOID_PARAM) return lines; } +#if LESSTEST + public void +rstat(st) + char st; +{ + if (rstat_file < 0) + return; + lseek(rstat_file, SEEK_SET, 0); + write(rstat_file, &st, 1); +} +#endif /*LESSTEST*/ + /* * Get a character from the keyboard. */ @@ -142,11 +179,11 @@ getchr(VOID_PARAM) do { + flush(); #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC /* * In raw read, we don't see ^C so look here for it. */ - flush(); #if MSDOS_COMPILER==WIN32C if (ABORT_SIGS()) return (READ_INTR); @@ -158,11 +195,17 @@ getchr(VOID_PARAM) if (c == '\003') return (READ_INTR); #else +#if LESSTEST + rstat('R'); +#endif /*LESSTEST*/ { unsigned char uc; result = iread(tty, &uc, sizeof(char)); c = (char) uc; } +#if LESSTEST + rstat('B'); +#endif /*LESSTEST*/ if (result == READ_INTR) return (READ_INTR); if (result < 0) diff --git a/version.c b/version.c index 73169ac44024..cb7d69ffcda7 100644 --- a/version.c +++ b/version.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * 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. @@ -894,6 +894,31 @@ v560 5/3/20 Fix regression when command results in no movement; v561 5/11/20 Fix erroneous EOF calculation when F command is interrupted. v562 5/19/20 Update Unicode tables; minor doc formatting. v563 6/13/20 Fix crash due to realpath() incompatibility. +v564 8/25/20 Handle realpath consistently; update docs. +v565 11/3/20 Add ESC-U command, optimize calls to realpath(). +v566 11/25/20 Fix crash when reopening a file while using LESSOPEN; + support OSC 8 hyperlinks. +v567 11/25/20 Fix typo. +v568 11/29/20 Fix some hyperlink bugs; add ^W search modifier + (thanks to Arminius); allow Makefile.aut to use Python + instead of Perl (thanks to Charlie Lin). +v569 12/1/20 Allow multiple & filters (thanks to Mattias Johansson), + allow ^X to exit F command. +v570 12/12/20 Better handling of multiple + or -p options; + fix bugs in horizontal scrolling. +v571 12/30/20 Add --line-num-width and --status-col-width options. +v572 1/4/21 Save lastmark in history file; don't toggle mouse reporting; + implement termcap delays. +v573 1/9/21 Limit eof bell to 1 per second. +v574 1/13/21 Add incremental search. +v575 1/17/21 Fix build without HILITE_SEARCH; + fix bug with ^K in lesskey extra string. +v576 2/4/21 Make sure search result is visible; add --use-color and --color. +v577 2/9/21 Use ttyname to get name of tty device. +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. */ -char version[] = "563"; +char version[] = "581";