less: upgrade to v581.

MFC after:	2 weeks
This commit is contained in:
Xin LI 2021-04-18 19:46:19 -07:00
commit 2235c7feac
55 changed files with 3772 additions and 2297 deletions

View File

@ -1,6 +1,6 @@
This file describes how to build and install less using This file contains generic instructions on how to build and
the "configure" script. This only works on Unix systems. install software using autoconf. For specific instructions
To install on other systems, read the README file. on how to build "less", see the README or README.VER file.
Basic Installation 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' 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. 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 The file `configure.ac' is used to create `configure' by a program
called `autoconf'. You only need `configure.in' if you want to change called `autoconf'. You only need `configure.ac' if you want to change
it or regenerate `configure' using a newer version of `autoconf'. it or regenerate `configure' using a newer version of `autoconf'.
The simplest way to compile this package is: The simplest way to compile this package is:

View File

@ -4,10 +4,56 @@
====================================================================== ======================================================================
For the latest news about less, see the "less" Web page: 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. 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.
====================================================================== ======================================================================

View File

@ -7,9 +7,9 @@
************************************************************************** **************************************************************************
************************************************************************** **************************************************************************
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 part of the GNU project (http://www.gnu.org).
This program is free software. You may redistribute it and/or This program is free software. You may redistribute it and/or
@ -21,33 +21,29 @@
or or
2. The Less License, in the file LICENSE. 2. The Less License, in the file LICENSE.
Please report any problems to bug-less@gnu.org. Please report any problems at https://github.com/gwsw/less/issues.
See http://www.greenwoodsoftware.com/less for the latest info. See https://greenwoodsoftware.com/less for the latest info.
Source repository is at https://github.com/gwsw/less.git. 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 formatted manual page is in less.man.
The manual page nroff source is in less.nro. The manual page nroff source is in less.nro.
Major changes made since the last posted version are in NEWS. Major changes made since the last posted version are in NEWS.
======================================================================= =======================================================================
PRE-INSTALLATION (when using git) INSTALLATION (Unix & Linux systems only):
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):
1. Move the distributed source to its own directory and unpack it, 1. Move the distributed source to its own directory and unpack it,
if you have not already done so. 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. 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. Warning: if you have a GNU sed, make sure it is version 2.05 or later.
@ -79,7 +75,7 @@ INSTALLATION (Unix systems only):
commands, etc. 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 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 your system that configure might not have detected, you may fix the
Makefile now. Take particular notice of the list of "terminal" Makefile now. Take particular notice of the list of "terminal"
@ -93,13 +89,13 @@ INSTALLATION (Unix systems only):
to remove the descriptions of the features which you are removing. 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". 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 "lesskey" and "lessecho" in your current directory. Test the
generated programs. 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". in a public place, type "make install".
The default install destinations are: The default install destinations are:
@ -108,8 +104,6 @@ INSTALLATION (Unix systems only):
If you want to install any of these files elsewhere, define If you want to install any of these files elsewhere, define
bindir and/or mandir to the appropriate directories. 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 Note to hackers: comments noting possible improvements are enclosed
in double curly brackets {{ like this }}. in double curly brackets {{ like this }}.

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -41,7 +41,7 @@ struct bufnode {
struct bufnode *hnext, *hprev; struct bufnode *hnext, *hprev;
}; };
#define LBUFSIZE 8192 #define LBUFSIZE 8192
struct buf { struct buf {
struct bufnode node; struct bufnode node;
BLOCKNUM block; BLOCKNUM block;
@ -54,7 +54,7 @@ struct buf {
* The file state is maintained in a filestate structure. * The file state is maintained in a filestate structure.
* A pointer to the filestate is kept in the ifile structure. * A pointer to the filestate is kept in the ifile structure.
*/ */
#define BUFHASH_SIZE 1024 #define BUFHASH_SIZE 1024
struct filestate { struct filestate {
struct bufnode buflist; struct bufnode buflist;
struct bufnode hashtbl[BUFHASH_SIZE]; struct bufnode hashtbl[BUFHASH_SIZE];
@ -67,24 +67,24 @@ struct filestate {
POSITION fsize; POSITION fsize;
}; };
#define ch_bufhead thisfile->buflist.next #define ch_bufhead thisfile->buflist.next
#define ch_buftail thisfile->buflist.prev #define ch_buftail thisfile->buflist.prev
#define ch_nbufs thisfile->nbufs #define ch_nbufs thisfile->nbufs
#define ch_block thisfile->block #define ch_block thisfile->block
#define ch_offset thisfile->offset #define ch_offset thisfile->offset
#define ch_fpos thisfile->fpos #define ch_fpos thisfile->fpos
#define ch_fsize thisfile->fsize #define ch_fsize thisfile->fsize
#define ch_flags thisfile->flags #define ch_flags thisfile->flags
#define ch_file thisfile->file #define ch_file thisfile->file
#define END_OF_CHAIN (&thisfile->buflist) #define END_OF_CHAIN (&thisfile->buflist)
#define END_OF_HCHAIN(h) (&thisfile->hashtbl[h]) #define END_OF_HCHAIN(h) (&thisfile->hashtbl[h])
#define BUFHASH(blk) ((blk) & (BUFHASH_SIZE-1)) #define BUFHASH(blk) ((blk) & (BUFHASH_SIZE-1))
/* /*
* Macros to manipulate the list of buffers in thisfile->buflist. * 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) for (bn = ch_bufhead; bn != END_OF_CHAIN; bn = bn->next)
#define BUF_RM(bn) \ #define BUF_RM(bn) \
@ -106,15 +106,15 @@ struct filestate {
/* /*
* Macros to manipulate the list of buffers in thisfile->hashtbl[n]. * 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; \ for (bn = thisfile->hashtbl[h].hnext; \
bn != END_OF_HCHAIN(h); bn = bn->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)->hnext->hprev = (bn)->hprev; \
(bn)->hprev->hnext = (bn)->hnext; (bn)->hprev->hnext = (bn)->hnext;
#define BUF_HASH_INS(bn,h) \ #define BUF_HASH_INS(bn,h) \
(bn)->hnext = thisfile->hashtbl[h].hnext; \ (bn)->hnext = thisfile->hashtbl[h].hnext; \
(bn)->hprev = END_OF_HCHAIN(h); \ (bn)->hprev = END_OF_HCHAIN(h); \
thisfile->hashtbl[h].hnext->hprev = (bn); \ thisfile->hashtbl[h].hnext->hprev = (bn); \
@ -240,12 +240,12 @@ ch_get(VOID_PARAM)
return ('?'); return ('?');
if (lseek(ch_file, (off_t)pos, SEEK_SET) == BAD_LSEEK) if (lseek(ch_file, (off_t)pos, SEEK_SET) == BAD_LSEEK)
{ {
error("seek error", NULL_PARG); error("seek error", NULL_PARG);
clear_eol(); clear_eol();
return (EOI); return (EOI);
} }
ch_fpos = pos; ch_fpos = pos;
} }
/* /*
* Read the block. * Read the block.
@ -311,13 +311,7 @@ ch_get(VOID_PARAM)
parg.p_string = wait_message(); parg.p_string = wait_message();
ierror("%s", &parg); ierror("%s", &parg);
} }
#if !MSDOS_COMPILER sleep_ms(2); /* Reduce system load */
sleep(1);
#else
#if MSDOS_COMPILER==WIN32C
Sleep(1000);
#endif
#endif
slept = TRUE; slept = TRUE;
#if HAVE_STAT_INO #if HAVE_STAT_INO

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -40,27 +40,27 @@ struct charset {
int *p_flag; int *p_flag;
char *desc; char *desc;
} charsets[] = { } charsets[] = {
{ "ascii", NULL, "8bcccbcc18b95.b" }, { "ascii", NULL, "8bcccbcc18b95.b" },
{ "utf-8", &utf_mode, "8bcccbcc18b95.b126.bb" }, { "utf-8", &utf_mode, "8bcccbcc18b95.b126.bb" },
{ "iso8859", NULL, "8bcccbcc18b95.33b." }, { "iso8859", NULL, "8bcccbcc18b95.33b." },
{ "latin3", NULL, "8bcccbcc18b95.33b5.b8.b15.b4.b12.b18.b12.b." }, { "latin3", NULL, "8bcccbcc18b95.33b5.b8.b15.b4.b12.b18.b12.b." },
{ "arabic", NULL, "8bcccbcc18b95.33b.3b.7b2.13b.3b.b26.5b19.b" }, { "arabic", NULL, "8bcccbcc18b95.33b.3b.7b2.13b.3b.b26.5b19.b" },
{ "greek", NULL, "8bcccbcc18b95.33b4.2b4.b3.b35.b44.b" }, { "greek", NULL, "8bcccbcc18b95.33b4.2b4.b3.b35.b44.b" },
{ "greek2005", NULL, "8bcccbcc18b95.33b14.b35.b44.b" }, { "greek2005", NULL, "8bcccbcc18b95.33b14.b35.b44.b" },
{ "hebrew", NULL, "8bcccbcc18b95.33b.b29.32b28.2b2.b" }, { "hebrew", NULL, "8bcccbcc18b95.33b.b29.32b28.2b2.b" },
{ "koi8-r", NULL, "8bcccbcc18b95.b." }, { "koi8-r", NULL, "8bcccbcc18b95.b." },
{ "KOI8-T", NULL, "8bcccbcc18b95.b8.b6.b8.b.b.5b7.3b4.b4.b3.b.b.3b." }, { "KOI8-T", NULL, "8bcccbcc18b95.b8.b6.b8.b.b.5b7.3b4.b4.b3.b.b.3b." },
{ "georgianps", NULL, "8bcccbcc18b95.3b11.4b12.2b." }, { "georgianps", NULL, "8bcccbcc18b95.3b11.4b12.2b." },
{ "tcvn", NULL, "b..b...bcccbccbbb7.8b95.b48.5b." }, { "tcvn", NULL, "b..b...bcccbccbbb7.8b95.b48.5b." },
{ "TIS-620", NULL, "8bcccbcc18b95.b.4b.11b7.8b." }, { "TIS-620", NULL, "8bcccbcc18b95.b.4b.11b7.8b." },
{ "next", NULL, "8bcccbcc18b95.bb125.bb" }, { "next", NULL, "8bcccbcc18b95.bb125.bb" },
{ "dos", NULL, "8bcccbcc12bc5b95.b." }, { "dos", NULL, "8bcccbcc12bc5b95.b." },
{ "windows-1251", NULL, "8bcccbcc12bc5b95.b24.b." }, { "windows-1251", NULL, "8bcccbcc12bc5b95.b24.b." },
{ "windows-1252", NULL, "8bcccbcc12bc5b95.b.b11.b.2b12.b." }, { "windows-1252", NULL, "8bcccbcc12bc5b95.b.b11.b.2b12.b." },
{ "windows-1255", NULL, "8bcccbcc12bc5b95.b.b8.b.5b9.b.4b." }, { "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." }, { "ebcdic", NULL, "5bc6bcc7bcc41b.9b7.9b5.b..8b6.10b6.b9.7b9.8b8.17b3.3b9.7b9.8b8.6b10.b.b.b." },
{ "IBM-1047", NULL, "4cbcbc3b9cbccbccbb4c6bcc5b3cbbc4bc4bccbc191.b" }, { "IBM-1047", NULL, "4cbcbc3b9cbccbccbb4c6bcc5b3cbbc4bc4bccbc191.b" },
{ NULL, NULL, NULL } { NULL, NULL, NULL }
}; };
/* /*
@ -70,58 +70,58 @@ struct cs_alias {
char *name; char *name;
char *oname; char *oname;
} cs_aliases[] = { } cs_aliases[] = {
{ "UTF-8", "utf-8" }, { "UTF-8", "utf-8" },
{ "utf8", "utf-8" }, { "utf8", "utf-8" },
{ "UTF8", "utf-8" }, { "UTF8", "utf-8" },
{ "ANSI_X3.4-1968", "ascii" }, { "ANSI_X3.4-1968", "ascii" },
{ "US-ASCII", "ascii" }, { "US-ASCII", "ascii" },
{ "latin1", "iso8859" }, { "latin1", "iso8859" },
{ "ISO-8859-1", "iso8859" }, { "ISO-8859-1", "iso8859" },
{ "latin9", "iso8859" }, { "latin9", "iso8859" },
{ "ISO-8859-15", "iso8859" }, { "ISO-8859-15", "iso8859" },
{ "latin2", "iso8859" }, { "latin2", "iso8859" },
{ "ISO-8859-2", "iso8859" }, { "ISO-8859-2", "iso8859" },
{ "ISO-8859-3", "latin3" }, { "ISO-8859-3", "latin3" },
{ "latin4", "iso8859" }, { "latin4", "iso8859" },
{ "ISO-8859-4", "iso8859" }, { "ISO-8859-4", "iso8859" },
{ "cyrillic", "iso8859" }, { "cyrillic", "iso8859" },
{ "ISO-8859-5", "iso8859" }, { "ISO-8859-5", "iso8859" },
{ "ISO-8859-6", "arabic" }, { "ISO-8859-6", "arabic" },
{ "ISO-8859-7", "greek" }, { "ISO-8859-7", "greek" },
{ "IBM9005", "greek2005" }, { "IBM9005", "greek2005" },
{ "ISO-8859-8", "hebrew" }, { "ISO-8859-8", "hebrew" },
{ "latin5", "iso8859" }, { "latin5", "iso8859" },
{ "ISO-8859-9", "iso8859" }, { "ISO-8859-9", "iso8859" },
{ "latin6", "iso8859" }, { "latin6", "iso8859" },
{ "ISO-8859-10", "iso8859" }, { "ISO-8859-10", "iso8859" },
{ "latin7", "iso8859" }, { "latin7", "iso8859" },
{ "ISO-8859-13", "iso8859" }, { "ISO-8859-13", "iso8859" },
{ "latin8", "iso8859" }, { "latin8", "iso8859" },
{ "ISO-8859-14", "iso8859" }, { "ISO-8859-14", "iso8859" },
{ "latin10", "iso8859" }, { "latin10", "iso8859" },
{ "ISO-8859-16", "iso8859" }, { "ISO-8859-16", "iso8859" },
{ "IBM437", "dos" }, { "IBM437", "dos" },
{ "EBCDIC-US", "ebcdic" }, { "EBCDIC-US", "ebcdic" },
{ "IBM1047", "IBM-1047" }, { "IBM1047", "IBM-1047" },
{ "KOI8-R", "koi8-r" }, { "KOI8-R", "koi8-r" },
{ "KOI8-U", "koi8-r" }, { "KOI8-U", "koi8-r" },
{ "GEORGIAN-PS", "georgianps" }, { "GEORGIAN-PS", "georgianps" },
{ "TCVN5712-1", "tcvn" }, { "TCVN5712-1", "tcvn" },
{ "NEXTSTEP", "next" }, { "NEXTSTEP", "next" },
{ "windows", "windows-1252" }, /* backward compatibility */ { "windows", "windows-1252" }, /* backward compatibility */
{ "CP1251", "windows-1251" }, { "CP1251", "windows-1251" },
{ "CP1252", "windows-1252" }, { "CP1252", "windows-1252" },
{ "CP1255", "windows-1255" }, { "CP1255", "windows-1255" },
{ NULL, NULL } { NULL, NULL }
}; };
#define IS_BINARY_CHAR 01 #define IS_BINARY_CHAR 01
#define IS_CONTROL_CHAR 02 #define IS_CONTROL_CHAR 02
static char chardef[256]; static char chardef[256];
static char *binfmt = NULL; static char *binfmt = NULL;
static char *utfbinfmt = 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. * repetition of the letter.
* *
* Each letter is one of: * Each letter is one of:
* . normal character * . normal character
* b binary character * b binary character
* c control character * c control character
*/ */
static void static void
ichardef(s) ichardef(s)
@ -457,16 +457,16 @@ prchar(c)
SNPRINTF1(buf, sizeof(buf), "^%c", SNPRINTF1(buf, sizeof(buf), "^%c",
/* /*
* This array roughly inverts CONTROL() #defined in less.h, * 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" "@ABC.I.?...KLMNO"
"PQRS.JH.XY.." "PQRS.JH.XY.."
"\\]^_" "\\]^_"
"......W[.....EFG" "......W[.....EFG"
"..V....D....TU.Z"[c]); "..V....D....TU.Z"[c]);
#else #else
else if (c < 128 && !control_char(c ^ 0100)) else if (c < 128 && !control_char(c ^ 0100))
SNPRINTF1(buf, sizeof(buf), "^%c", (int) (c ^ 0100)); SNPRINTF1(buf, sizeof(buf), "^%c", (int) (c ^ 0100));
#endif #endif
else else
SNPRINTF1(buf, sizeof(buf), binfmt, c); SNPRINTF1(buf, sizeof(buf), binfmt, c);
@ -484,7 +484,7 @@ prutfchar(ch)
if (ch == ESC) if (ch == ESC)
strcpy(buf, "ESC"); strcpy(buf, "ESC");
else if (ch < 128 && control_char(ch)) else if (ch < 128 && control_char(ch))
{ {
if (!control_char(ch ^ 0100)) if (!control_char(ch ^ 0100))
SNPRINTF1(buf, sizeof(buf), "^%c", ((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) \ #define DECLARE_RANGE_TABLE_START(name) \
static struct wchar_range name##_array[] = { static struct wchar_range name##_array[] = {
#define DECLARE_RANGE_TABLE_END(name) \ #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) DECLARE_RANGE_TABLE_START(compose)
#include "compose.uni" #include "compose.uni"

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -31,7 +31,6 @@
#define A_HELP 19 #define A_HELP 19
#define A_NEXT_FILE 20 #define A_NEXT_FILE 20
#define A_PERCENT 21 #define A_PERCENT 21
#define A_PREFIX 22
#define A_PREV_FILE 23 #define A_PREV_FILE 23
#define A_QUIT 24 #define A_QUIT 24
#define A_REPAINT 25 #define A_REPAINT 25
@ -72,19 +71,19 @@
#define A_CLRMARK 62 #define A_CLRMARK 62
#define A_SETMARKBOT 63 #define A_SETMARKBOT 63
#define A_X11MOUSE_IN 64 #define A_X11MOUSE_IN 64
#define A_X11MOUSE_IGNORE 65
#define A_F_MOUSE 66 #define A_F_MOUSE 66
#define A_B_MOUSE 67 #define A_B_MOUSE 67
/* Note "X116" refers to extended (1006) X11 mouse reporting. */ /* Note "X116" refers to extended (1006) X11 mouse reporting. */
#define A_X116MOUSE_IN 68 #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_INVALID 100
#define A_NOACTION 101 #define A_NOACTION 101
#define A_UINVALID 102 #define A_UINVALID 102
#define A_END_LIST 103 #define A_END_LIST 103
#define A_SPECIAL_KEY 104 #define A_SPECIAL_KEY 104
#define A_PREFIX 105
#define A_SKIP 127 #define A_SKIP 127
#define A_EXTRA 0200 #define A_EXTRA 0200
@ -111,15 +110,16 @@
#define EC_B_COMPLETE 18 #define EC_B_COMPLETE 18
#define EC_LITERAL 19 #define EC_LITERAL 19
#define EC_ABORT 20 #define EC_ABORT 20
#define EC_X11MOUSE 21
#define EC_X116MOUSE 22
#define EC_NOACTION 101
#define EC_UINVALID 102 #define EC_UINVALID 102
/* Flags for editchar() */ /* Flags for editchar() */
#define EC_PEEK 01 #define ECF_PEEK 01
#define EC_NOHISTORY 02 #define ECF_NOHISTORY 02
#define EC_NOCOMPLETE 04 #define ECF_NOCOMPLETE 04
#define EC_NORIGHTLEFT 010 #define ECF_NORIGHTLEFT 010
/* Environment variable stuff */ /* Environment variable stuff */
#define EV_OK 01 #define EV_OK 01

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -26,12 +26,12 @@ extern int no_hist_dups;
extern int marks_modified; extern int marks_modified;
static char cmdbuf[CMDBUF_SIZE]; /* Buffer for holding a multi-char command */ static char cmdbuf[CMDBUF_SIZE]; /* Buffer for holding a multi-char command */
static int cmd_col; /* Current column of the cursor */ static int cmd_col; /* Current column of the cursor */
static int prompt_col; /* Column of cursor just after prompt */ static int prompt_col; /* Column of cursor just after prompt */
static char *cp; /* Pointer into cmdbuf */ static char *cp; /* Pointer into cmdbuf */
static int cmd_offset; /* Index into cmdbuf of first displayed char */ static int cmd_offset; /* Index into cmdbuf of first displayed char */
static int literal; /* Next input char should not be interpreted */ static int literal; /* Next input char should not be interpreted */
static int updown_match = -1; /* Prefix length in up/down movement */ static int updown_match = -1; /* Prefix length in up/down movement */
#if TAB_COMPLETE_FILENAME #if TAB_COMPLETE_FILENAME
static int cmd_complete LESSPARAMS((int action)); static int cmd_complete LESSPARAMS((int action));
@ -223,7 +223,7 @@ cmd_step_common(p, ch, len, pwidth, bswidth)
} }
} }
if (pwidth != NULL) if (pwidth != NULL)
*pwidth = width; *pwidth = width;
if (bswidth != NULL) if (bswidth != NULL)
*bswidth = width; *bswidth = width;
return (pr); return (pr);
@ -259,17 +259,42 @@ cmd_step_left(pp, pwidth, bswidth)
return cmd_step_common(*pp, ch, p - *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. * Repaint the line from cp onwards.
* Then position the cursor just after the char old_cp (a pointer into cmdbuf). * Then position the cursor just after the char old_cp (a pointer into cmdbuf).
*/ */
static void public void
cmd_repaint(old_cp) cmd_repaint(old_cp)
constant char *old_cp; constant char *old_cp;
{ {
/* /*
* Repaint the line from the current position. * Repaint the line from the current position.
*/ */
if (old_cp == NULL)
{
old_cp = cp;
cmd_home();
}
clear_eol(); clear_eol();
while (*cp != '\0') while (*cp != '\0')
{ {
@ -300,26 +325,6 @@ cmd_repaint(old_cp)
cmd_left(); 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. * 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, * Try to perform a line-edit function on the command buffer,
* using a specified char as a line-editing command. * using a specified char as a line-editing command.
* Returns: * Returns:
* CC_PASS The char does not invoke a line edit function. * CC_PASS The char does not invoke a line edit function.
* CC_OK Line edit function done. * CC_OK Line edit function done.
* CC_QUIT The char requests the current command to be aborted. * CC_QUIT The char requests the current command to be aborted.
*/ */
static int static int
cmd_edit(c) cmd_edit(c)
@ -838,9 +843,9 @@ cmd_edit(c)
int flags; int flags;
#if TAB_COMPLETE_FILENAME #if TAB_COMPLETE_FILENAME
#define not_in_completion() in_completion = 0 #define not_in_completion() in_completion = 0
#else #else
#define not_in_completion(VOID_PARAM) #define not_in_completion(VOID_PARAM)
#endif #endif
/* /*
@ -852,20 +857,22 @@ cmd_edit(c)
/* /*
* No current history; don't accept history manipulation cmds. * No current history; don't accept history manipulation cmds.
*/ */
flags |= EC_NOHISTORY; flags |= ECF_NOHISTORY;
#endif #endif
#if TAB_COMPLETE_FILENAME #if TAB_COMPLETE_FILENAME
if (curr_mlist == ml_search) if (curr_mlist == ml_search)
/* /*
* In a search command; don't accept file-completion cmds. * In a search command; don't accept file-completion cmds.
*/ */
flags |= EC_NOCOMPLETE; flags |= ECF_NOCOMPLETE;
#endif #endif
action = editchar(c, flags); action = editchar(c, flags);
switch (action) switch (action)
{ {
case A_NOACTION:
return (CC_OK);
case EC_RIGHT: case EC_RIGHT:
not_in_completion(); not_in_completion();
return (cmd_right()); return (cmd_right());
@ -934,8 +941,6 @@ cmd_edit(c)
case EC_EXPAND: case EC_EXPAND:
return (cmd_complete(action)); return (cmd_complete(action));
#endif #endif
case EC_NOACTION:
return (CC_OK);
default: default:
not_in_completion(); not_in_completion();
return (CC_PASS); return (CC_PASS);
@ -1237,9 +1242,9 @@ cmd_complete(action)
* Process a single character of a multi-character command, such as * Process a single character of a multi-character command, such as
* a number, or the pattern of a search command. * a number, or the pattern of a search command.
* Returns: * Returns:
* CC_OK The char was accepted. * CC_OK The char was accepted.
* CC_QUIT The char requests the command to be aborted. * CC_QUIT The char requests the command to be aborted.
* CC_ERROR The char could not be accepted due to an error. * CC_ERROR The char could not be accepted due to an error.
*/ */
public int public int
cmd_char(c) cmd_char(c)

View File

@ -1,6 +1,6 @@
/* $FreeBSD$ */ /* $FreeBSD$ */
/* /*
* Copyright (C) 1984-2020 Mark Nudelman * Copyright (C) 1984-2021 Mark Nudelman
* *
* You may distribute under the terms of either the GNU General Public * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -57,21 +57,22 @@ extern void *ml_shell;
extern char *editor; extern char *editor;
extern char *editproto; extern char *editproto;
#endif #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 shift_count;
extern int oldbot; extern int oldbot;
extern int forw_prompt; extern int forw_prompt;
extern int incr_search;
#if MSDOS_COMPILER==WIN32C #if MSDOS_COMPILER==WIN32C
extern int utf_mode; extern int utf_mode;
#endif #endif
#if SHELL_ESCAPE #if SHELL_ESCAPE
static char *shellcmd = NULL; /* For holding last shell command for "!!" */ static char *shellcmd = NULL; /* For holding last shell command for "!!" */
#endif #endif
static int mca; /* The multicharacter command (action) */ static int mca; /* The multicharacter command (action) */
static int search_type; /* The previous type of search */ static int search_type; /* The previous type of search */
static LINENUM number; /* The number typed by the user */ static LINENUM number; /* The number typed by the user */
static long fraction; /* The fractional part of the number */ static long fraction; /* The fractional part of the number */
static struct loption *curropt; static struct loption *curropt;
static int opt_lower; static int opt_lower;
static int optflag; static int optflag;
@ -113,7 +114,6 @@ set_mca(action)
int action; int action;
{ {
mca = action; mca = action;
deinit_mouse(); /* we don't want mouse events while entering a cmd */
clear_bot(); clear_bot();
clear_cmd(); clear_cmd();
} }
@ -127,7 +127,6 @@ clear_mca(VOID_PARAM)
if (mca == 0) if (mca == 0)
return; return;
mca = 0; mca = 0;
init_mouse();
} }
/* /*
@ -177,6 +176,8 @@ mca_search(VOID_PARAM)
cmd_putstr("Keep-pos "); cmd_putstr("Keep-pos ");
if (search_type & SRCH_NO_REGEX) if (search_type & SRCH_NO_REGEX)
cmd_putstr("Regex-off "); cmd_putstr("Regex-off ");
if (search_type & SRCH_WRAP)
cmd_putstr("Wrap ");
#if HILITE_SEARCH #if HILITE_SEARCH
if (search_type & SRCH_FILTER) if (search_type & SRCH_FILTER)
@ -520,9 +521,9 @@ mca_search_char(c)
/* /*
* Certain characters as the first char of * Certain characters as the first char of
* the pattern have special meaning: * the pattern have special meaning:
* ! Toggle the NO_MATCH flag * ! Toggle the NO_MATCH flag
* * Toggle the PAST_EOF flag * * Toggle the PAST_EOF flag
* @ Toggle the FIRST_FILE flag * @ Toggle the FIRST_FILE flag
*/ */
if (len_cmdbuf() > 0) if (len_cmdbuf() > 0)
return (NO_MCA); return (NO_MCA);
@ -547,6 +548,10 @@ mca_search_char(c)
if (mca != A_FILTER) if (mca != A_FILTER)
flag = SRCH_NO_MOVE; flag = SRCH_NO_MOVE;
break; break;
case CONTROL('W'): /* WRAP around */
if (mca != A_FILTER)
flag = SRCH_WRAP;
break;
case CONTROL('R'): /* Don't use REGULAR EXPRESSIONS */ case CONTROL('R'): /* Don't use REGULAR EXPRESSIONS */
flag = SRCH_NO_REGEX; flag = SRCH_NO_REGEX;
break; break;
@ -558,7 +563,8 @@ mca_search_char(c)
if (flag != 0) 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(); mca_search();
return (MCA_MORE); return (MCA_MORE);
} }
@ -596,9 +602,16 @@ mca_char(c)
* Entering digits of a number. * Entering digits of a number.
* Terminated by a non-digit. * Terminated by a non-digit.
*/ */
if (!((c >= '0' && c <= '9') || c == '.') && if ((c >= '0' && c <= '9') || c == '.')
editchar(c, EC_PEEK|EC_NOHISTORY|EC_NOCOMPLETE|EC_NORIGHTLEFT) == A_INVALID) 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. * Not part of the number.
* End the number and treat this char * End the number and treat this char
@ -651,15 +664,44 @@ mca_char(c)
*/ */
return (MCA_DONE); return (MCA_DONE);
if ((mca == A_F_BRACKET || mca == A_B_BRACKET) && len_cmdbuf() >= 2) switch (mca)
{ {
/* case A_F_BRACKET:
* Special case for the bracket-matching commands. case A_B_BRACKET:
* Execute the command after getting exactly two if (len_cmdbuf() >= 2)
* characters from the user. {
*/ /*
exec_mca(); * Special case for the bracket-matching commands.
return (MCA_DONE); * 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;
} }
/* /*
@ -695,12 +737,6 @@ make_display(VOID_PARAM)
if (empty_screen()) if (empty_screen())
{ {
if (initial_scrpos.pos == NULL_POSITION) 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); jump_loc(ch_zero(), 1);
else else
jump_loc(initial_scrpos.pos, initial_scrpos.ln); jump_loc(initial_scrpos.pos, initial_scrpos.ln);
@ -793,11 +829,16 @@ prompt(VOID_PARAM)
clear_cmd(); clear_cmd();
forw_prompt = 0; forw_prompt = 0;
p = pr_string(); p = pr_string();
#if HILITE_SEARCH
if (is_filtering()) if (is_filtering())
putstr("& "); putstr("& ");
#endif
if (p == NULL || *p == '\0') if (p == NULL || *p == '\0')
{
at_enter(AT_NORMAL|AT_COLOR_PROMPT);
putchr(':'); putchr(':');
else at_exit();
} else
{ {
#if MSDOS_COMPILER==WIN32C #if MSDOS_COMPILER==WIN32C
WCHAR w[MAX_PATH*2]; WCHAR w[MAX_PATH*2];
@ -807,7 +848,7 @@ prompt(VOID_PARAM)
0, w, -1, a, sizeof(a), NULL, NULL); 0, w, -1, a, sizeof(a), NULL, NULL);
p = a; p = a;
#endif #endif
at_enter(AT_STANDOUT); at_enter(AT_STANDOUT|AT_COLOR_PROMPT);
putstr(p); putstr(p);
at_exit(); at_exit();
} }
@ -843,7 +884,7 @@ getcc_end_command(VOID_PARAM)
return ('\n'); return ('\n');
default: default:
/* Some other incomplete command. Let user complete it. */ /* Some other incomplete command. Let user complete it. */
return (getchr()); return ((ungot == NULL) ? getchr() : 0);
} }
} }
@ -856,23 +897,26 @@ getcc_end_command(VOID_PARAM)
static LWCHAR static LWCHAR
getccu(VOID_PARAM) getccu(VOID_PARAM)
{ {
LWCHAR c; LWCHAR c = 0;
if (ungot == NULL) while (c == 0)
{ {
/* Normal case: no ungotten chars. if (ungot == NULL)
* Get char from the user. */ {
c = getchr(); /* Normal case: no ungotten chars.
} else * Get char from the user. */
{ c = getchr();
/* Ungotten chars available: } else
* Take the top of stack (most recent). */ {
struct ungot *ug = ungot; /* Ungotten chars available:
c = ug->ug_char; * Take the top of stack (most recent). */
ungot = ug->ug_next; struct ungot *ug = ungot;
free(ug); c = ug->ug_char;
ungot = ug->ug_next;
free(ug);
if (c == CHAR_END_COMMAND) if (c == CHAR_END_COMMAND)
c = getcc_end_command(); c = getcc_end_command();
}
} }
return (c); return (c);
} }
@ -947,6 +991,28 @@ ungetcc(c)
ungot = ug; 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. * Unget a whole string of command characters.
* The next sequence of getcc()'s will return this string. * The next sequence of getcc()'s will return this string.
@ -955,10 +1021,8 @@ ungetcc(c)
ungetsc(s) ungetsc(s)
char *s; char *s;
{ {
char *p; while (*s != '\0')
ungetcc_back(*s++);
for (p = s + strlen(s) - 1; p >= s; p--)
ungetcc(*p);
} }
/* /*
@ -1122,6 +1186,7 @@ commands(VOID_PARAM)
int action; int action;
char *cbuf; char *cbuf;
int newaction; int newaction;
int save_jump_sline;
int save_search_type; int save_search_type;
char *extra; char *extra;
char tbuf[2]; char tbuf[2];
@ -1423,11 +1488,18 @@ commands(VOID_PARAM)
case A_GOLINE: case A_GOLINE:
/* /*
* Go to line N, default beginning of file. * 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) if (number <= 0)
{
number = 1; number = 1;
jump_sline = 0;
}
cmd_exec(); cmd_exec();
jump_back(number); jump_back(number);
jump_sline = save_jump_sline;
break; break;
case A_PERCENT: case A_PERCENT:
@ -1493,7 +1565,7 @@ commands(VOID_PARAM)
case A_VERSION: case A_VERSION:
/* /*
* Print version number, without the "@(#)". * Print version number.
*/ */
cmd_exec(); cmd_exec();
dispversion(); dispversion();
@ -1524,10 +1596,10 @@ commands(VOID_PARAM)
/* /*
* Define abbreviation for a commonly used sequence below. * Define abbreviation for a commonly used sequence below.
*/ */
#define DO_SEARCH() \ #define DO_SEARCH() \
if (number <= 0) number = 1; \ if (number <= 0) number = 1; \
mca_search(); \ mca_search(); \
cmd_exec(); \ cmd_exec(); \
multi_search((char *)NULL, (int) number, 0); multi_search((char *)NULL, (int) number, 0);
@ -1604,10 +1676,11 @@ commands(VOID_PARAM)
break; break;
case A_UNDO_SEARCH: case A_UNDO_SEARCH:
case A_CLR_SEARCH:
/* /*
* Clear search string highlighting. * Clear search string highlighting.
*/ */
undo_search(); undo_search(action == A_CLR_SEARCH);
break; break;
case A_HELP: case A_HELP:

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * 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 src_pos = (int) (src - osrc);
int dst_pos = (int) (dst - odst); int dst_pos = (int) (dst - odst);
struct ansi_state *pansi;
ch = step_char(&src, +1, src_end); ch = step_char(&src, +1, src_end);
if ((ops & CVT_BS) && ch == '\b' && dst > odst) if ((ops & CVT_BS) && ch == '\b' && dst > odst)
{ {
@ -85,13 +86,16 @@ cvt_text(odst, osrc, chpos, lenp, ops)
dst--; dst--;
} while (dst > odst && utf_mode && } while (dst > odst && utf_mode &&
!IS_ASCII_OCTET(*dst) && !IS_UTF8_LEAD(*dst)); !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. */ /* Skip to end of ANSI escape sequence. */
src++; /* skip the CSI start char */
while (src < src_end) while (src < src_end)
if (!is_ansi_middle(*src++)) {
if (ansi_step(pansi, ch) != ANSI_MID)
break; break;
ch = *src++;
}
ansi_done(pansi);
} else } else
{ {
/* Just copy the char to the destination buffer. */ /* Just copy the char to the destination buffer. */

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -14,7 +14,7 @@
* This is all table driven. * This is all table driven.
* A command table is a sequence of command descriptors. * A command table is a sequence of command descriptors.
* Each command descriptor is a sequence of bytes with the following format: * Each command descriptor is a sequence of bytes with the following format:
* <c1><c2>...<cN><0><action> * <c1><c2>...<cN><0><action>
* The characters c1,c2,...,cN are the command string; that is, * The characters c1,c2,...,cN are the command string; that is,
* the characters which the user must type. * the characters which the user must type.
* It is terminated by a null <0> byte. * It is terminated by a null <0> byte.
@ -48,173 +48,176 @@ extern int sc_height;
static unsigned char cmdtable[] = static unsigned char cmdtable[] =
{ {
'\r',0, A_F_LINE, '\r',0, A_F_LINE,
'\n',0, A_F_LINE, '\n',0, A_F_LINE,
'e',0, A_F_LINE, 'e',0, A_F_LINE,
'j',0, A_F_LINE, 'j',0, A_F_LINE,
SK(SK_DOWN_ARROW),0, A_F_LINE, SK(SK_DOWN_ARROW),0, A_F_LINE,
CONTROL('E'),0, A_F_LINE, CONTROL('E'),0, A_F_LINE,
CONTROL('N'),0, A_F_LINE, CONTROL('N'),0, A_F_LINE,
'k',0, A_B_LINE, 'k',0, A_B_LINE,
'y',0, A_B_LINE, 'y',0, A_B_LINE,
CONTROL('Y'),0, A_B_LINE, CONTROL('Y'),0, A_B_LINE,
SK(SK_CONTROL_K),0, A_B_LINE, SK(SK_CONTROL_K),0, A_B_LINE,
CONTROL('P'),0, A_B_LINE, CONTROL('P'),0, A_B_LINE,
SK(SK_UP_ARROW),0, A_B_LINE, SK(SK_UP_ARROW),0, A_B_LINE,
'J',0, A_FF_LINE, 'J',0, A_FF_LINE,
'K',0, A_BF_LINE, 'K',0, A_BF_LINE,
'Y',0, A_BF_LINE, 'Y',0, A_BF_LINE,
'd',0, A_F_SCROLL, 'd',0, A_F_SCROLL,
CONTROL('D'),0, A_F_SCROLL, CONTROL('D'),0, A_F_SCROLL,
'u',0, A_B_SCROLL, 'u',0, A_B_SCROLL,
CONTROL('U'),0, A_B_SCROLL, CONTROL('U'),0, A_B_SCROLL,
ESC,'[','M',0, A_X11MOUSE_IN, ESC,'[','M',0, A_X11MOUSE_IN,
ESC,'[','<',0, A_X116MOUSE_IN, ESC,'[','<',0, A_X116MOUSE_IN,
' ',0, A_F_SCREEN, ' ',0, A_F_SCREEN,
'f',0, A_F_SCREEN, 'f',0, A_F_SCREEN,
CONTROL('F'),0, A_F_SCREEN, CONTROL('F'),0, A_F_SCREEN,
CONTROL('V'),0, A_F_SCREEN, CONTROL('V'),0, A_F_SCREEN,
SK(SK_PAGE_DOWN),0, A_F_SCREEN, SK(SK_PAGE_DOWN),0, A_F_SCREEN,
'b',0, A_B_SCREEN, 'b',0, A_B_SCREEN,
CONTROL('B'),0, A_B_SCREEN, CONTROL('B'),0, A_B_SCREEN,
ESC,'v',0, A_B_SCREEN, ESC,'v',0, A_B_SCREEN,
SK(SK_PAGE_UP),0, A_B_SCREEN, SK(SK_PAGE_UP),0, A_B_SCREEN,
'z',0, A_F_WINDOW, 'z',0, A_F_WINDOW,
'w',0, A_B_WINDOW, 'w',0, A_B_WINDOW,
ESC,' ',0, A_FF_SCREEN, ESC,' ',0, A_FF_SCREEN,
'F',0, A_F_FOREVER, 'F',0, A_F_FOREVER,
ESC,'F',0, A_F_UNTIL_HILITE, ESC,'F',0, A_F_UNTIL_HILITE,
'R',0, A_FREPAINT, 'R',0, A_FREPAINT,
'r',0, A_REPAINT, 'r',0, A_REPAINT,
CONTROL('R'),0, A_REPAINT, CONTROL('R'),0, A_REPAINT,
CONTROL('L'),0, A_REPAINT, CONTROL('L'),0, A_REPAINT,
ESC,'u',0, A_UNDO_SEARCH, ESC,'u',0, A_UNDO_SEARCH,
'g',0, A_GOLINE, ESC,'U',0, A_CLR_SEARCH,
SK(SK_HOME),0, A_GOLINE, 'g',0, A_GOLINE,
'<',0, A_GOLINE, SK(SK_HOME),0, A_GOLINE,
ESC,'<',0, A_GOLINE, '<',0, A_GOLINE,
'p',0, A_PERCENT, ESC,'<',0, A_GOLINE,
'%',0, A_PERCENT, 'p',0, A_PERCENT,
ESC,'[',0, A_LSHIFT, '%',0, A_PERCENT,
ESC,']',0, A_RSHIFT, ESC,'[',0, A_LSHIFT,
ESC,'(',0, A_LSHIFT, ESC,']',0, A_RSHIFT,
ESC,')',0, A_RSHIFT, ESC,'(',0, A_LSHIFT,
ESC,'{',0, A_LLSHIFT, ESC,')',0, A_RSHIFT,
ESC,'}',0, A_RRSHIFT, ESC,'{',0, A_LLSHIFT,
SK(SK_RIGHT_ARROW),0, A_RSHIFT, ESC,'}',0, A_RRSHIFT,
SK(SK_LEFT_ARROW),0, A_LSHIFT, SK(SK_RIGHT_ARROW),0, A_RSHIFT,
SK(SK_CTL_RIGHT_ARROW),0, A_RRSHIFT, SK(SK_LEFT_ARROW),0, A_LSHIFT,
SK(SK_CTL_LEFT_ARROW),0, A_LLSHIFT, SK(SK_CTL_RIGHT_ARROW),0, A_RRSHIFT,
'{',0, A_F_BRACKET|A_EXTRA, '{','}',0, SK(SK_CTL_LEFT_ARROW),0, A_LLSHIFT,
'}',0, A_B_BRACKET|A_EXTRA, '{','}',0, '{',0, A_F_BRACKET|A_EXTRA, '{','}',0,
'(',0, A_F_BRACKET|A_EXTRA, '(',')',0, '}',0, A_B_BRACKET|A_EXTRA, '{','}',0,
')',0, A_B_BRACKET|A_EXTRA, '(',')',0, '(',0, A_F_BRACKET|A_EXTRA, '(',')',0,
'[',0, A_F_BRACKET|A_EXTRA, '[',']',0, ')',0, A_B_BRACKET|A_EXTRA, '(',')',0,
']',0, A_B_BRACKET|A_EXTRA, '[',']',0, '[',0, A_F_BRACKET|A_EXTRA, '[',']',0,
ESC,CONTROL('F'),0, A_F_BRACKET, ']',0, A_B_BRACKET|A_EXTRA, '[',']',0,
ESC,CONTROL('B'),0, A_B_BRACKET, ESC,CONTROL('F'),0, A_F_BRACKET,
'G',0, A_GOEND, ESC,CONTROL('B'),0, A_B_BRACKET,
ESC,'G',0, A_GOEND_BUF, 'G',0, A_GOEND,
ESC,'>',0, A_GOEND, ESC,'G',0, A_GOEND_BUF,
'>',0, A_GOEND, ESC,'>',0, A_GOEND,
SK(SK_END),0, A_GOEND, '>',0, A_GOEND,
'P',0, A_GOPOS, SK(SK_END),0, A_GOEND,
'P',0, A_GOPOS,
'0',0, A_DIGIT, '0',0, A_DIGIT,
'1',0, A_DIGIT, '1',0, A_DIGIT,
'2',0, A_DIGIT, '2',0, A_DIGIT,
'3',0, A_DIGIT, '3',0, A_DIGIT,
'4',0, A_DIGIT, '4',0, A_DIGIT,
'5',0, A_DIGIT, '5',0, A_DIGIT,
'6',0, A_DIGIT, '6',0, A_DIGIT,
'7',0, A_DIGIT, '7',0, A_DIGIT,
'8',0, A_DIGIT, '8',0, A_DIGIT,
'9',0, A_DIGIT, '9',0, A_DIGIT,
'.',0, A_DIGIT, '.',0, A_DIGIT,
'=',0, A_STAT, '=',0, A_STAT,
CONTROL('G'),0, A_STAT, CONTROL('G'),0, A_STAT,
':','f',0, A_STAT, ':','f',0, A_STAT,
'/',0, A_F_SEARCH, '/',0, A_F_SEARCH,
'?',0, A_B_SEARCH, '?',0, A_B_SEARCH,
ESC,'/',0, A_F_SEARCH|A_EXTRA, '*',0, ESC,'/',0, A_F_SEARCH|A_EXTRA, '*',0,
ESC,'?',0, A_B_SEARCH|A_EXTRA, '*',0, ESC,'?',0, A_B_SEARCH|A_EXTRA, '*',0,
'n',0, A_AGAIN_SEARCH, 'n',0, A_AGAIN_SEARCH,
ESC,'n',0, A_T_AGAIN_SEARCH, ESC,'n',0, A_T_AGAIN_SEARCH,
'N',0, A_REVERSE_SEARCH, 'N',0, A_REVERSE_SEARCH,
ESC,'N',0, A_T_REVERSE_SEARCH, ESC,'N',0, A_T_REVERSE_SEARCH,
'&',0, A_FILTER, '&',0, A_FILTER,
'm',0, A_SETMARK, 'm',0, A_SETMARK,
'M',0, A_SETMARKBOT, 'M',0, A_SETMARKBOT,
ESC,'m',0, A_CLRMARK, ESC,'m',0, A_CLRMARK,
'\'',0, A_GOMARK, '\'',0, A_GOMARK,
CONTROL('X'),CONTROL('X'),0, A_GOMARK, CONTROL('X'),CONTROL('X'),0, A_GOMARK,
'E',0, A_EXAMINE, 'E',0, A_EXAMINE,
':','e',0, A_EXAMINE, ':','e',0, A_EXAMINE,
CONTROL('X'),CONTROL('V'),0, A_EXAMINE, CONTROL('X'),CONTROL('V'),0, A_EXAMINE,
':','n',0, A_NEXT_FILE, ':','n',0, A_NEXT_FILE,
':','p',0, A_PREV_FILE, ':','p',0, A_PREV_FILE,
't',0, A_NEXT_TAG, 't',0, A_NEXT_TAG,
'T',0, A_PREV_TAG, 'T',0, A_PREV_TAG,
':','x',0, A_INDEX_FILE, ':','x',0, A_INDEX_FILE,
':','d',0, A_REMOVE_FILE, ':','d',0, A_REMOVE_FILE,
'-',0, A_OPT_TOGGLE, '-',0, A_OPT_TOGGLE,
':','t',0, A_OPT_TOGGLE|A_EXTRA, 't',0, ':','t',0, A_OPT_TOGGLE|A_EXTRA, 't',0,
's',0, A_OPT_TOGGLE|A_EXTRA, 'o',0, 's',0, A_OPT_TOGGLE|A_EXTRA, 'o',0,
'_',0, A_DISP_OPTION, '_',0, A_DISP_OPTION,
'|',0, A_PIPE, '|',0, A_PIPE,
'v',0, A_VISUAL, 'v',0, A_VISUAL,
'!',0, A_SHELL, '!',0, A_SHELL,
'+',0, A_FIRSTCMD, '+',0, A_FIRSTCMD,
'H',0, A_HELP, 'H',0, A_HELP,
'h',0, A_HELP, 'h',0, A_HELP,
SK(SK_F1),0, A_HELP, SK(SK_F1),0, A_HELP,
'V',0, A_VERSION, 'V',0, A_VERSION,
'q',0, A_QUIT, 'q',0, A_QUIT,
'Q',0, A_QUIT, 'Q',0, A_QUIT,
':','q',0, A_QUIT, ':','q',0, A_QUIT,
':','Q',0, A_QUIT, ':','Q',0, A_QUIT,
'Z','Z',0, A_QUIT 'Z','Z',0, A_QUIT
}; };
static unsigned char edittable[] = static unsigned char edittable[] =
{ {
'\t',0, EC_F_COMPLETE, /* TAB */ '\t',0, EC_F_COMPLETE, /* TAB */
'\17',0, EC_B_COMPLETE, /* BACKTAB */ '\17',0, EC_B_COMPLETE, /* BACKTAB */
SK(SK_BACKTAB),0, EC_B_COMPLETE, /* BACKTAB */ SK(SK_BACKTAB),0, EC_B_COMPLETE, /* BACKTAB */
ESC,'\t',0, EC_B_COMPLETE, /* ESC TAB */ ESC,'\t',0, EC_B_COMPLETE, /* ESC TAB */
CONTROL('L'),0, EC_EXPAND, /* CTRL-L */ CONTROL('L'),0, EC_EXPAND, /* CTRL-L */
CONTROL('V'),0, EC_LITERAL, /* BACKSLASH */ CONTROL('V'),0, EC_LITERAL, /* BACKSLASH */
CONTROL('A'),0, EC_LITERAL, /* BACKSLASH */ CONTROL('A'),0, EC_LITERAL, /* BACKSLASH */
ESC,'l',0, EC_RIGHT, /* ESC l */ ESC,'l',0, EC_RIGHT, /* ESC l */
SK(SK_RIGHT_ARROW),0, EC_RIGHT, /* RIGHTARROW */ SK(SK_RIGHT_ARROW),0, EC_RIGHT, /* RIGHTARROW */
ESC,'h',0, EC_LEFT, /* ESC h */ ESC,'h',0, EC_LEFT, /* ESC h */
SK(SK_LEFT_ARROW),0, EC_LEFT, /* LEFTARROW */ SK(SK_LEFT_ARROW),0, EC_LEFT, /* LEFTARROW */
ESC,'b',0, EC_W_LEFT, /* ESC b */ ESC,'b',0, EC_W_LEFT, /* ESC b */
ESC,SK(SK_LEFT_ARROW),0, EC_W_LEFT, /* ESC LEFTARROW */ ESC,SK(SK_LEFT_ARROW),0, EC_W_LEFT, /* ESC LEFTARROW */
SK(SK_CTL_LEFT_ARROW),0, EC_W_LEFT, /* CTRL-LEFTARROW */ SK(SK_CTL_LEFT_ARROW),0, EC_W_LEFT, /* CTRL-LEFTARROW */
ESC,'w',0, EC_W_RIGHT, /* ESC w */ ESC,'w',0, EC_W_RIGHT, /* ESC w */
ESC,SK(SK_RIGHT_ARROW),0, EC_W_RIGHT, /* ESC RIGHTARROW */ ESC,SK(SK_RIGHT_ARROW),0, EC_W_RIGHT, /* ESC RIGHTARROW */
SK(SK_CTL_RIGHT_ARROW),0, EC_W_RIGHT, /* CTRL-RIGHTARROW */ SK(SK_CTL_RIGHT_ARROW),0, EC_W_RIGHT, /* CTRL-RIGHTARROW */
ESC,'i',0, EC_INSERT, /* ESC i */ ESC,'i',0, EC_INSERT, /* ESC i */
SK(SK_INSERT),0, EC_INSERT, /* INSERT */ SK(SK_INSERT),0, EC_INSERT, /* INSERT */
ESC,'x',0, EC_DELETE, /* ESC x */ ESC,'x',0, EC_DELETE, /* ESC x */
SK(SK_DELETE),0, EC_DELETE, /* DELETE */ SK(SK_DELETE),0, EC_DELETE, /* DELETE */
ESC,'X',0, EC_W_DELETE, /* ESC X */ ESC,'X',0, EC_W_DELETE, /* ESC X */
ESC,SK(SK_DELETE),0, EC_W_DELETE, /* ESC DELETE */ ESC,SK(SK_DELETE),0, EC_W_DELETE, /* ESC DELETE */
SK(SK_CTL_DELETE),0, EC_W_DELETE, /* CTRL-DELETE */ SK(SK_CTL_DELETE),0, EC_W_DELETE, /* CTRL-DELETE */
SK(SK_CTL_BACKSPACE),0, EC_W_BACKSPACE, /* CTRL-BACKSPACE */ SK(SK_CTL_BACKSPACE),0, EC_W_BACKSPACE, /* CTRL-BACKSPACE */
ESC,'\b',0, EC_W_BACKSPACE, /* ESC BACKSPACE */ ESC,'\b',0, EC_W_BACKSPACE, /* ESC BACKSPACE */
ESC,'0',0, EC_HOME, /* ESC 0 */ ESC,'0',0, EC_HOME, /* ESC 0 */
SK(SK_HOME),0, EC_HOME, /* HOME */ SK(SK_HOME),0, EC_HOME, /* HOME */
ESC,'$',0, EC_END, /* ESC $ */ ESC,'$',0, EC_END, /* ESC $ */
SK(SK_END),0, EC_END, /* END */ SK(SK_END),0, EC_END, /* END */
ESC,'k',0, EC_UP, /* ESC k */ ESC,'k',0, EC_UP, /* ESC k */
SK(SK_UP_ARROW),0, EC_UP, /* UPARROW */ SK(SK_UP_ARROW),0, EC_UP, /* UPARROW */
ESC,'j',0, EC_DOWN, /* ESC j */ ESC,'j',0, EC_DOWN, /* ESC j */
SK(SK_DOWN_ARROW),0, EC_DOWN, /* DOWNARROW */ SK(SK_DOWN_ARROW),0, EC_DOWN, /* DOWNARROW */
CONTROL('G'),0, EC_ABORT, /* CTRL-G */ 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. * The prefix ("\e[M") has already been read.
*/ */
static int static int
x11mouse_action(VOID_PARAM) x11mouse_action(skip)
int skip;
{ {
int b = getcc() - X11MOUSE_OFFSET; int b = getcc() - X11MOUSE_OFFSET;
int x = getcc() - X11MOUSE_OFFSET-1; int x = getcc() - X11MOUSE_OFFSET-1;
int y = getcc() - X11MOUSE_OFFSET-1; int y = getcc() - X11MOUSE_OFFSET-1;
if (skip)
return (A_NOACTION);
switch (b) { switch (b) {
default: default:
return (A_NOACTION); return (A_NOACTION);
@ -509,7 +515,8 @@ x11mouse_action(VOID_PARAM)
* The prefix ("\e[<") has already been read. * The prefix ("\e[<") has already been read.
*/ */
static int static int
x116mouse_action(VOID_PARAM) x116mouse_action(skip)
int skip;
{ {
char ch; char ch;
int x, y; int x, y;
@ -519,6 +526,8 @@ x116mouse_action(VOID_PARAM)
if (x < 0 || ch != ';') return (A_NOACTION); if (x < 0 || ch != ';') return (A_NOACTION);
y = getcc_int(&ch) - 1; y = getcc_int(&ch) - 1;
if (y < 0) return (A_NOACTION); if (y < 0) return (A_NOACTION);
if (skip)
return (A_NOACTION);
switch (b) { switch (b) {
case X11MOUSE_WHEEL_DOWN: case X11MOUSE_WHEEL_DOWN:
return mouse_wheel_down(); return mouse_wheel_down();
@ -580,9 +589,9 @@ cmd_search(cmd, table, endtable, sp)
a &= ~A_EXTRA; a &= ~A_EXTRA;
} }
if (a == A_X11MOUSE_IN) if (a == A_X11MOUSE_IN)
a = x11mouse_action(); a = x11mouse_action(0);
else if (a == A_X116MOUSE_IN) else if (a == A_X116MOUSE_IN)
a = x116mouse_action(); a = x116mouse_action(0);
return (a); return (a);
} }
} else if (*q == '\0') } else if (*q == '\0')
@ -924,7 +933,6 @@ editchar(c, flags)
#if MSDOS_COMPILER==WIN32C #if MSDOS_COMPILER==WIN32C
if (!win32_kbhit()) if (!win32_kbhit())
#endif #endif
return (EC_LINEKILL); return (EC_LINEKILL);
} }
@ -934,15 +942,20 @@ editchar(c, flags)
*/ */
nch = 0; nch = 0;
do { do {
if (nch > 0) if (nch > 0)
c = getcc(); c = getcc();
usercmd[nch] = c; usercmd[nch] = c;
usercmd[nch+1] = '\0'; usercmd[nch+1] = '\0';
nch++; nch++;
action = ecmd_decode(usercmd, &s); action = ecmd_decode(usercmd, &s);
} while (action == A_PREFIX); } while (action == A_PREFIX && nch < MAX_CMDLEN);
if (flags & EC_NORIGHTLEFT) if (action == EC_X11MOUSE)
return (x11mouse_action(1));
if (action == EC_X116MOUSE)
return (x116mouse_action(1));
if (flags & ECF_NORIGHTLEFT)
{ {
switch (action) switch (action)
{ {
@ -953,7 +966,7 @@ editchar(c, flags)
} }
} }
#if CMD_HISTORY #if CMD_HISTORY
if (flags & EC_NOHISTORY) if (flags & ECF_NOHISTORY)
{ {
/* /*
* The caller says there is no history list. * The caller says there is no history list.
@ -969,7 +982,7 @@ editchar(c, flags)
} }
#endif #endif
#if TAB_COMPLETE_FILENAME #if TAB_COMPLETE_FILENAME
if (flags & EC_NOCOMPLETE) if (flags & ECF_NOCOMPLETE)
{ {
/* /*
* The caller says we don't want any filename completion cmds. * The caller says we don't want any filename completion cmds.
@ -985,7 +998,7 @@ editchar(c, flags)
} }
} }
#endif #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. * We're just peeking, or we didn't understand the command.

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -20,13 +20,12 @@
public int fd0 = 0; public int fd0 = 0;
extern int new_file; extern int new_file;
extern int errmsgs;
extern int cbufs; extern int cbufs;
extern char *every_first_cmd; extern char *every_first_cmd;
extern int any_display;
extern int force_open; extern int force_open;
extern int is_tty; extern int is_tty;
extern int sigs; extern int sigs;
extern int hshift;
extern IFILE curr_ifile; extern IFILE curr_ifile;
extern IFILE old_ifile; extern IFILE old_ifile;
extern struct scrpos initial_scrpos; extern struct scrpos initial_scrpos;
@ -47,7 +46,6 @@ public dev_t curr_dev;
public ino_t curr_ino; public ino_t curr_ino;
#endif #endif
/* /*
* Textlist functions deal with a list of words separated by spaces. * Textlist functions deal with a list of words separated by spaces.
* init_textlist sets up a textlist structure. * init_textlist sets up a textlist structure.
@ -242,7 +240,6 @@ edit_ifile(ifile)
{ {
int f; int f;
int answer; int answer;
int no_display;
int chflags; int chflags;
char *filename; char *filename;
char *open_filename; char *open_filename;
@ -462,14 +459,12 @@ edit_ifile(ifile)
#endif #endif
if (every_first_cmd != NULL) if (every_first_cmd != NULL)
{ {
ungetcc(CHAR_END_COMMAND);
ungetsc(every_first_cmd); ungetsc(every_first_cmd);
ungetcc_back(CHAR_END_COMMAND);
} }
} }
no_display = !any_display;
flush(); flush();
any_display = TRUE;
if (is_tty) if (is_tty)
{ {
@ -485,6 +480,7 @@ edit_ifile(ifile)
#if HILITE_SEARCH #if HILITE_SEARCH
clr_hilite(); clr_hilite();
#endif #endif
hshift = 0;
if (strcmp(filename, FAKE_HELPFILE) && strcmp(filename, FAKE_EMPTYFILE)) if (strcmp(filename, FAKE_HELPFILE) && strcmp(filename, FAKE_EMPTYFILE))
{ {
char *qfilename = shell_quote(filename); char *qfilename = shell_quote(filename);
@ -492,17 +488,6 @@ edit_ifile(ifile)
free(qfilename); 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); free(filename);
return (0); return (0);
@ -784,6 +769,8 @@ cat_file(VOID_PARAM)
#if LOGFILE #if LOGFILE
#define OVERWRITE_OPTIONS "Overwrite, Append, Don't log, or Quit?"
/* /*
* If the user asked for a log file and our input file * If the user asked for a log file and our input file
* is standard input, create the log file. * is standard input, create the log file.
@ -827,7 +814,7 @@ use_logfile(filename)
* Ask user what to do. * Ask user what to do.
*/ */
parg.p_string = filename; 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: loop:
@ -855,14 +842,12 @@ use_logfile(filename)
* Don't do anything. * Don't do anything.
*/ */
return; return;
case 'q':
quit(QUIT_OK);
/*NOTREACHED*/
default: default:
/* /*
* Eh? * 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; goto loop;
} }

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -23,7 +23,7 @@
#if MSDOS_COMPILER==DJGPPC #if MSDOS_COMPILER==DJGPPC
#include <glob.h> #include <glob.h>
#include <dir.h> #include <dir.h>
#define _MAX_PATH PATH_MAX #define _MAX_PATH PATH_MAX
#endif #endif
#endif #endif
#ifdef _OSK #ifdef _OSK
@ -36,10 +36,10 @@
#if HAVE_STAT #if HAVE_STAT
#include <sys/stat.h> #include <sys/stat.h>
#ifndef S_ISDIR #ifndef S_ISDIR
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif #endif
#ifndef S_ISREG #ifndef S_ISREG
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif #endif
#endif #endif
@ -312,7 +312,7 @@ fexpand(s)
char *e; char *e;
IFILE ifile; IFILE ifile;
#define fchar_ifile(c) \ #define fchar_ifile(c) \
((c) == '%' ? curr_ifile : \ ((c) == '%' ? curr_ifile : \
(c) == '#' ? old_ifile : NULL_IFILE) (c) == '#' ? old_ifile : NULL_IFILE)
@ -486,9 +486,12 @@ bin_file(f)
} else } else
{ {
LWCHAR c = step_char(&p, +1, edata); LWCHAR c = step_char(&p, +1, edata);
if (ctldisp == OPT_ONPLUS && IS_CSI_START(c)) struct ansi_state *pansi;
skip_ansi(&p, edata); if (ctldisp == OPT_ONPLUS && (pansi = ansi_start(c)) != NULL)
else if (binary_char(c)) {
skip_ansi(pansi, &p, edata);
ansi_done(pansi);
} else if (binary_char(c))
bin_count++; bin_count++;
} }
} }
@ -648,7 +651,7 @@ lglob(filename)
qfilename = shell_quote(p); qfilename = shell_quote(p);
if (qfilename != NULL) if (qfilename != NULL)
{ {
length += strlen(qfilename) + 1; length += strlen(qfilename) + 1;
free(qfilename); free(qfilename);
} }
} }
@ -914,7 +917,7 @@ open_altfile(filename, pf, pfd)
int f; 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. * to see if the pipe will produce any data.
* If it does, push the char back on the pipe. * If it does, push the char back on the pipe.
*/ */
@ -931,18 +934,22 @@ open_altfile(filename, pf, pfd)
*/ */
int status = pclose(fd); int status = pclose(fd);
if (returnfd > 1 && status == 0) { if (returnfd > 1 && status == 0) {
/* File is empty. */
*pfd = NULL; *pfd = NULL;
*pf = -1; *pf = -1;
return (save(FAKE_EMPTYFILE)); return (save(FAKE_EMPTYFILE));
} }
/* No alt file. */
return (NULL); return (NULL);
} }
/* Alt pipe contains data, so use it. */
ch_ungetchar(c); ch_ungetchar(c);
*pfd = (void *) fd; *pfd = (void *) fd;
*pf = f; *pf = f;
return (save("-")); return (save("-"));
} }
#endif #endif
/* The alt file is a regular file. Read its name from LESSOPEN. */
cmd = readfd(fd); cmd = readfd(fd);
pclose(fd); pclose(fd);
if (*cmd == '\0') if (*cmd == '\0')
@ -972,7 +979,7 @@ close_altfile(altfilename, filename)
return; return;
ch_ungetchar(-1); ch_ungetchar(-1);
if ((lessclose = lgetenv("LESSCLOSE")) == NULL) if ((lessclose = lgetenv("LESSCLOSE")) == NULL)
return; return;
if (num_pct_s(lessclose) > 2) if (num_pct_s(lessclose) > 2)
{ {
error("LESSCLOSE ignored; must contain no more than 2 %%s", NULL_PARG); error("LESSCLOSE ignored; must contain no more than 2 %%s", NULL_PARG);

View File

@ -1,6 +1,6 @@
/* $FreeBSD$ */ /* $FreeBSD$ */
/* /*
* Copyright (C) 1984-2020 Mark Nudelman * Copyright (C) 1984-2021 Mark Nudelman
* *
* You may distribute under the terms of either the GNU General Public * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -49,6 +49,13 @@ extern char *tagoption;
static void static void
eof_bell(VOID_PARAM) 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) if (quiet == NOT_QUIET)
bell(); bell();
else else
@ -189,7 +196,7 @@ forw(n, pos, force, only_last, nblank)
{ {
clear(); clear();
home(); home();
} else if (!first_time) } else if (!first_time && !is_filtering())
{ {
putstr("...skipping...\n"); putstr("...skipping...\n");
} }

View File

@ -11,6 +11,7 @@ public void init_mouse LESSPARAMS ((VOID_PARAM));
public void deinit_mouse LESSPARAMS ((VOID_PARAM)); public void deinit_mouse LESSPARAMS ((VOID_PARAM));
public void init LESSPARAMS ((VOID_PARAM)); public void init LESSPARAMS ((VOID_PARAM));
public void deinit LESSPARAMS ((VOID_PARAM)); public void deinit LESSPARAMS ((VOID_PARAM));
public int interactive LESSPARAMS ((VOID_PARAM));
public void home LESSPARAMS ((VOID_PARAM)); public void home LESSPARAMS ((VOID_PARAM));
public void add_line LESSPARAMS ((VOID_PARAM)); public void add_line LESSPARAMS ((VOID_PARAM));
public void remove_top LESSPARAMS ((int n)); 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 LESSPARAMS ((VOID_PARAM));
public void clear_eol LESSPARAMS ((VOID_PARAM)); public void clear_eol LESSPARAMS ((VOID_PARAM));
public void clear_bot 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_enter LESSPARAMS ((int attr));
public void at_exit LESSPARAMS ((VOID_PARAM)); public void at_exit LESSPARAMS ((VOID_PARAM));
public void at_switch LESSPARAMS ((int attr)); public void at_switch LESSPARAMS ((int attr));
public int is_at_equiv LESSPARAMS ((int attr1, int attr2)); public int is_at_equiv LESSPARAMS ((int attr1, int attr2));
public int apply_at_specials LESSPARAMS ((int attr)); public int apply_at_specials LESSPARAMS ((int attr));
public void backspace LESSPARAMS ((VOID_PARAM));
public void putbs LESSPARAMS ((VOID_PARAM)); public void putbs LESSPARAMS ((VOID_PARAM));
public int win32_kbhit LESSPARAMS ((VOID_PARAM)); public int win32_kbhit LESSPARAMS ((VOID_PARAM));
public char WIN32getch 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 clear_cmd LESSPARAMS ((VOID_PARAM));
public void cmd_putstr LESSPARAMS ((constant char *s)); public void cmd_putstr LESSPARAMS ((constant char *s));
public int len_cmdbuf LESSPARAMS ((VOID_PARAM)); 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 set_mlist LESSPARAMS ((void *mlist, int cmdflags));
public void cmd_addhist LESSPARAMS ((struct mlist *mlist, constant char *cmd, int modified)); public void cmd_addhist LESSPARAMS ((struct mlist *mlist, constant char *cmd, int modified));
public void cmd_accept LESSPARAMS ((VOID_PARAM)); 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 void dispversion LESSPARAMS ((VOID_PARAM));
public int getcc LESSPARAMS ((VOID_PARAM)); public int getcc LESSPARAMS ((VOID_PARAM));
public void ungetcc LESSPARAMS ((LWCHAR c)); public void ungetcc LESSPARAMS ((LWCHAR c));
public void ungetcc_back LESSPARAMS ((LWCHAR c));
public void ungetsc LESSPARAMS ((char *s)); public void ungetsc LESSPARAMS ((char *s));
public LWCHAR peekcc LESSPARAMS ((VOID_PARAM)); public LWCHAR peekcc LESSPARAMS ((VOID_PARAM));
public void commands 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 int nifile LESSPARAMS ((VOID_PARAM));
public IFILE get_ifile LESSPARAMS ((char *filename, IFILE prev)); public IFILE get_ifile LESSPARAMS ((char *filename, IFILE prev));
public char * get_filename LESSPARAMS ((IFILE ifile)); public char * get_filename LESSPARAMS ((IFILE ifile));
public char * get_real_filename LESSPARAMS ((IFILE ifile));
public int get_index LESSPARAMS ((IFILE ifile)); public int get_index LESSPARAMS ((IFILE ifile));
public void store_pos LESSPARAMS ((IFILE ifile, struct scrpos *scrpos)); public void store_pos LESSPARAMS ((IFILE ifile, struct scrpos *scrpos));
public void get_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 void set_altfilename LESSPARAMS ((IFILE ifile, char *altfilename));
public char * get_altfilename LESSPARAMS ((IFILE ifile)); public char * get_altfilename LESSPARAMS ((IFILE ifile));
public void if_dump LESSPARAMS ((VOID_PARAM)); 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 forw_line LESSPARAMS ((POSITION curr_pos));
public POSITION back_line LESSPARAMS ((POSITION curr_pos)); public POSITION back_line LESSPARAMS ((POSITION curr_pos));
public void set_attnpos LESSPARAMS ((POSITION 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 void init_line LESSPARAMS ((VOID_PARAM));
public int is_ascii_char LESSPARAMS ((LWCHAR ch)); public int is_ascii_char LESSPARAMS ((LWCHAR ch));
public void prewind LESSPARAMS ((VOID_PARAM)); 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 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_end LESSPARAMS ((LWCHAR ch));
public int is_ansi_middle 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 pappend LESSPARAMS ((int c, POSITION pos));
public int pflushmbc LESSPARAMS ((VOID_PARAM)); public int pflushmbc LESSPARAMS ((VOID_PARAM));
public void pdone LESSPARAMS ((int endline, int chopped, int forw)); 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 int gline LESSPARAMS ((int i, int *ap));
public void null_line LESSPARAMS ((VOID_PARAM)); public void null_line LESSPARAMS ((VOID_PARAM));
public POSITION forw_raw_line LESSPARAMS ((POSITION curr_pos, char **linep, int *line_lenp)); 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 POSITION back_raw_line LESSPARAMS ((POSITION curr_pos, char **linep, int *line_lenp));
public int rrshift LESSPARAMS ((VOID_PARAM)); 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 clr_linenum LESSPARAMS ((VOID_PARAM));
public void add_lnum LESSPARAMS ((LINENUM linenum, POSITION pos)); public void add_lnum LESSPARAMS ((LINENUM linenum, POSITION pos));
public LINENUM find_linenum LESSPARAMS ((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_query LESSPARAMS ((int type, char *s));
public void opt_mousecap 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_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 int get_swindow LESSPARAMS ((VOID_PARAM));
public char * propt LESSPARAMS ((int c)); public char * propt LESSPARAMS ((int c));
public void scan_option LESSPARAMS ((char *s)); 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 int percentage LESSPARAMS ((POSITION num, POSITION den));
public POSITION percent_pos LESSPARAMS ((POSITION pos, int percent, long fraction)); public POSITION percent_pos LESSPARAMS ((POSITION pos, int percent, long fraction));
public int os9_signal LESSPARAMS ((int type, RETSIGTYPE (*handler)())); 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 put_line LESSPARAMS ((VOID_PARAM));
public void flush LESSPARAMS ((VOID_PARAM)); public void flush LESSPARAMS ((VOID_PARAM));
public void set_output LESSPARAMS ((int fd));
public int putchr LESSPARAMS ((int c)); public int putchr LESSPARAMS ((int c));
public void putstr LESSPARAMS ((constant char *s)); 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 get_return LESSPARAMS ((VOID_PARAM));
public void error LESSPARAMS ((char *fmt, PARG *parg)); public void error LESSPARAMS ((char *fmt, PARG *parg));
public void ierror LESSPARAMS ((char *fmt, PARG *parg)); public void ierror LESSPARAMS ((char *fmt, PARG *parg));
public int query 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 void uncompile_pattern LESSPARAMS ((PATTERN_TYPE *pattern));
public int valid_pattern LESSPARAMS ((char *pattern)); public int valid_pattern LESSPARAMS ((char *pattern));
public int is_null_pattern LESSPARAMS ((PATTERN_TYPE 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 init_search LESSPARAMS ((VOID_PARAM));
public void repaint_hilite LESSPARAMS ((int on)); public void repaint_hilite LESSPARAMS ((int on));
public void clear_attn LESSPARAMS ((VOID_PARAM)); 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_hlist LESSPARAMS ((struct hilite_tree *anchor));
public void clr_hilite LESSPARAMS ((VOID_PARAM)); public void clr_hilite LESSPARAMS ((VOID_PARAM));
public void clr_filter LESSPARAMS ((VOID_PARAM)); public void clr_filter LESSPARAMS ((VOID_PARAM));
public int is_filtered LESSPARAMS ((POSITION pos)); public int is_filtered LESSPARAMS ((POSITION pos));
public POSITION next_unfiltered LESSPARAMS ((POSITION pos)); public POSITION next_unfiltered LESSPARAMS ((POSITION pos));
public POSITION prev_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_hilite LESSPARAMS ((VOID_PARAM));
public void chg_caseless LESSPARAMS ((VOID_PARAM)); public void chg_caseless LESSPARAMS ((VOID_PARAM));
public int search LESSPARAMS ((int search_type, char *pattern, int n)); 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 ntags LESSPARAMS ((VOID_PARAM));
public int curr_tag LESSPARAMS ((VOID_PARAM)); public int curr_tag LESSPARAMS ((VOID_PARAM));
public int edit_tagfile 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 open_getchr LESSPARAMS ((VOID_PARAM));
public void close_getchr LESSPARAMS ((VOID_PARAM)); public void close_getchr LESSPARAMS ((VOID_PARAM));
public int default_wheel_lines LESSPARAMS ((VOID_PARAM)); public int default_wheel_lines LESSPARAMS ((VOID_PARAM));
public void rstat LESSPARAMS ((char st));
public int getchr LESSPARAMS ((VOID_PARAM)); public int getchr LESSPARAMS ((VOID_PARAM));

View File

@ -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" #include "less.h"
constant char helpdata[] = { constant char helpdata[] = {
'\n', '\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',',',' ','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','-','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', ' ',' ','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', ' ',' ',' ',' ',' ',' ',' ',' ','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\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', ' ',' ',' ',' ',' ',' ',' ',' ','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', ' ',' ',' ',' ',' ',' ',' ',' ','^','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', ' ',' ',' ',' ',' ',' ',' ',' ','^','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', ' ',' ',' ',' ',' ',' ',' ',' ','^','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', ' ',' ',' ',' ',' ',' ',' ',' ','^','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',
'\n', '\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','J','\b','J','U','\b','U','M','\b','M','P','\b','P','I','\b','I','N','\b','N','G','\b','G','\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',' ','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', ' ',' ','}',' ',' ',')',' ',' ',']',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','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','-','^','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', ' ',' ',' ',' ',' ',' ',' ',' ','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\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', ' ',' ',' ',' ',' ',' ',' ',' ','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', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','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', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','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',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','d','u','m','b','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','u','m','b',' ','t','e','r','m','i','n','a','l','.','\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', ' ',' ','-','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','.',' ','(','M','S','-','D','O','S',' ','o','n','l','y',')','\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', ' ',' ','-','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', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','Q','u','i','t',' ','a','t',' ','e','n','d',' ','o','f',' ','f','i','l','e','.','\n',
' ',' ','-','f',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','f','o','r','c','e','\n', ' ',' ','-','f',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','f','o','r','c','e','\n',
@ -205,9 +207,13 @@ constant char helpdata[] = {
' ',' ','-','~',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','t','i','l','d','e','\n', ' ',' ','-','~',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','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', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','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', ' ',' ','-','#',' ','[','_','\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', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','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', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','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', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','m','o','u','s','e','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','E','n','a','b','l','e',' ','m','o','u','s','e',' ','i','n','p','u','t','.','\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', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','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','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', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','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', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','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', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','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', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','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', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','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', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','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', '\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', ' ','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', ' ','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', ' ','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 }; 0 };
constant int size_helpdata = sizeof(helpdata) - 1; constant int size_helpdata = sizeof(helpdata) - 1;

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -21,12 +21,13 @@
#include "less.h" #include "less.h"
extern IFILE curr_ifile; extern IFILE curr_ifile;
struct ifile { struct ifile {
struct ifile *h_next; /* Links for command line list */ struct ifile *h_next; /* Links for command line list */
struct ifile *h_prev; struct ifile *h_prev;
char *h_filename; /* Name of the file */ char *h_filename; /* Name of the file */
char *h_rfilename; /* Canonical name of the file */
void *h_filestate; /* File state (used in ch.c) */ void *h_filestate; /* File state (used in ch.c) */
int h_index; /* Index within command line list */ int h_index; /* Index within command line list */
int h_hold; /* Hold count */ int h_hold; /* Hold count */
@ -40,13 +41,13 @@ struct ifile {
* Convert an IFILE (external representation) * Convert an IFILE (external representation)
* to a struct file (internal representation), and vice versa. * to a struct file (internal representation), and vice versa.
*/ */
#define int_ifile(h) ((struct ifile *)(h)) #define int_ifile(h) ((struct ifile *)(h))
#define ext_ifile(h) ((IFILE)(h)) #define ext_ifile(h) ((IFILE)(h))
/* /*
* Anchor for linked list. * 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 } }; { NULL_POSITION, 0 } };
static int ifiles = 0; static int ifiles = 0;
@ -116,10 +117,13 @@ new_ifile(filename, prev)
*/ */
p = (struct ifile *) ecalloc(1, sizeof(struct ifile)); p = (struct ifile *) ecalloc(1, sizeof(struct ifile));
p->h_filename = save(filename); p->h_filename = save(filename);
p->h_rfilename = lrealpath(filename);
p->h_scrpos.pos = NULL_POSITION; p->h_scrpos.pos = NULL_POSITION;
p->h_opened = 0; p->h_opened = 0;
p->h_hold = 0; p->h_hold = 0;
p->h_filestate = NULL; p->h_filestate = NULL;
p->h_altfilename = NULL;
p->h_altpipe = NULL;
link_ifile(p, prev); link_ifile(p, prev);
/* /*
* {{ It's dodgy to call mark.c functions from here; * {{ It's dodgy to call mark.c functions from here;
@ -150,6 +154,7 @@ del_ifile(h)
curr_ifile = getoff_ifile(curr_ifile); curr_ifile = getoff_ifile(curr_ifile);
p = int_ifile(h); p = int_ifile(h);
unlink_ifile(p); unlink_ifile(p);
free(p->h_rfilename);
free(p->h_filename); free(p->h_filename);
free(p); free(p);
} }
@ -221,15 +226,17 @@ find_ifile(filename)
for (p = anchor.h_next; p != &anchor; p = p->h_next) for (p = anchor.h_next; p != &anchor; p = p->h_next)
{ {
if (strcmp(filename, p->h_filename) == 0 || if (strcmp(rfilename, p->h_rfilename) == 0)
strcmp(rfilename, p->h_filename) == 0)
{ {
/* /*
* If given name is shorter than the name we were * If given name is shorter than the name we were
* previously using for this file, adopt shorter name. * previously using for this file, adopt shorter name.
*/ */
if (strlen(filename) < strlen(p->h_filename)) if (strlen(filename) < strlen(p->h_filename))
strcpy(p->h_filename, filename); {
free(p->h_filename);
p->h_filename = save(filename);
}
break; 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 * public char *
get_filename(ifile) get_filename(ifile)
@ -268,6 +275,18 @@ get_filename(ifile)
return (int_ifile(ifile)->h_filename); 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. * Get the index of the file associated with a ifile.
*/ */
@ -372,7 +391,7 @@ set_altfilename(ifile, altfilename)
char *altfilename; char *altfilename;
{ {
struct ifile *p = int_ifile(ifile); struct ifile *p = int_ifile(ifile);
if (p->h_altfilename != NULL) if (p->h_altfilename != NULL && p->h_altfilename != altfilename)
free(p->h_altfilename); free(p->h_altfilename);
p->h_altfilename = altfilename; p->h_altfilename = altfilename;
} }

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -31,6 +31,7 @@ extern POSITION end_attnpos;
#if HILITE_SEARCH #if HILITE_SEARCH
extern int hilite_search; extern int hilite_search;
extern int size_linebuf; extern int size_linebuf;
extern int show_attn;
#endif #endif
/* /*
@ -41,8 +42,9 @@ extern int size_linebuf;
* of the NEXT line. The line obtained is the line starting at curr_pos. * of the NEXT line. The line obtained is the line starting at curr_pos.
*/ */
public POSITION public POSITION
forw_line(curr_pos) forw_line_seg(curr_pos, get_segpos)
POSITION curr_pos; POSITION curr_pos;
int get_segpos;
{ {
POSITION base_pos; POSITION base_pos;
POSITION new_pos; POSITION new_pos;
@ -104,8 +106,8 @@ forw_line(curr_pos)
/* /*
* Read forward again to the position we should start at. * Read forward again to the position we should start at.
*/ */
prewind(); prewind();
plinenum(base_pos); plinestart(base_pos);
(void) ch_seek(base_pos); (void) ch_seek(base_pos);
new_pos = base_pos; new_pos = base_pos;
while (new_pos < curr_pos) while (new_pos < curr_pos)
@ -180,8 +182,9 @@ forw_line(curr_pos)
* is too long to print in the screen width. * is too long to print in the screen width.
* End the line here. * End the line here.
*/ */
if (chopline || hshift > 0) if ((chopline || hshift > 0) && !get_segpos)
{ {
/* Read to end of line. */
do do
{ {
if (ABORT_SIGS()) if (ABORT_SIGS())
@ -205,6 +208,13 @@ forw_line(curr_pos)
c = ch_forw_get(); 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); pdone(endline, chopped, 1);
#if HILITE_SEARCH #if HILITE_SEARCH
@ -218,8 +228,12 @@ forw_line(curr_pos)
goto get_forw_line; goto get_forw_line;
} }
if (status_col && is_hilited(base_pos, ch_tell()-1, 1, NULL)) if (status_col)
set_status_col('*'); {
int attr = is_hilited_attr(base_pos, ch_tell()-1, 1, NULL);
if (attr)
set_status_col('*', attr);
}
#endif #endif
if (squeeze && blankline) if (squeeze && blankline)
@ -243,6 +257,13 @@ forw_line(curr_pos)
return (new_pos); return (new_pos);
} }
public POSITION
forw_line(curr_pos)
POSITION curr_pos;
{
return forw_line_seg(curr_pos, FALSE);
}
/* /*
* Get the previous line. * Get the previous line.
* A "current" position is passed and a "new" position is returned. * A "current" position is passed and a "new" position is returned.
@ -358,7 +379,7 @@ back_line(curr_pos)
} }
endline = FALSE; endline = FALSE;
prewind(); prewind();
plinenum(new_pos); plinestart(new_pos);
loop: loop:
begin_new_pos = new_pos; begin_new_pos = new_pos;
(void) ch_seek(new_pos); (void) ch_seek(new_pos);
@ -423,8 +444,12 @@ back_line(curr_pos)
goto get_back_line; goto get_back_line;
} }
if (status_col && curr_pos > 0 && is_hilited(base_pos, curr_pos-1, 1, NULL)) if (status_col && curr_pos > 0)
set_status_col('*'); {
int attr = is_hilited_attr(base_pos, curr_pos-1, 1, NULL);
if (attr)
set_status_col('*', attr);
}
#endif #endif
return (begin_new_pos); return (begin_new_pos);

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -16,10 +16,10 @@
/* /*
* Defines for MSDOS_COMPILER. * Defines for MSDOS_COMPILER.
*/ */
#define MSOFTC 1 /* Microsoft C */ #define MSOFTC 1 /* Microsoft C */
#define BORLANDC 2 /* Borland C */ #define BORLANDC 2 /* Borland C */
#define WIN32C 3 /* Windows (Borland C or Microsoft C) */ #define WIN32C 3 /* Windows (Borland C or Microsoft C) */
#define DJGPPC 4 /* DJGPP C */ #define DJGPPC 4 /* DJGPP C */
/* /*
* Include the file of compile-time options. * Include the file of compile-time options.
@ -45,20 +45,20 @@
#define LESSPARAMS(a) () #define LESSPARAMS(a) ()
#endif #endif
#if HAVE_VOID #if HAVE_VOID
#define VOID_POINTER void * #define VOID_POINTER void *
#define VOID_PARAM void #define VOID_PARAM void
#else #else
#define VOID_POINTER char * #define VOID_POINTER char *
#define VOID_PARAM #define VOID_PARAM
#define void int #define void int
#endif #endif
#if HAVE_CONST #if HAVE_CONST
#define constant const #define constant const
#else #else
#define constant #define constant
#endif #endif
#define public /* PUBLIC FUNCTION */ #define public /* PUBLIC FUNCTION */
/* Library function declarations */ /* Library function declarations */
@ -122,10 +122,10 @@ void free();
* Simple lowercase test which can be used during option processing * Simple lowercase test which can be used during option processing
* (before options are parsed which might tell us what charset to use). * (before options are parsed which might tell us what charset to use).
*/ */
#define ASCII_IS_UPPER(c) ((c) >= 'A' && (c) <= 'Z') #define ASCII_IS_UPPER(c) ((c) >= 'A' && (c) <= 'Z')
#define ASCII_IS_LOWER(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_UPPER(c) ((c) - 'a' + 'A')
#define ASCII_TO_LOWER(c) ((c) - 'A' + 'a') #define ASCII_TO_LOWER(c) ((c) - 'A' + 'a')
#undef IS_UPPER #undef IS_UPPER
#undef IS_LOWER #undef IS_LOWER
@ -135,56 +135,56 @@ void free();
#undef IS_DIGIT #undef IS_DIGIT
#if HAVE_WCTYPE #if HAVE_WCTYPE
#define IS_UPPER(c) iswupper(c) #define IS_UPPER(c) iswupper(c)
#define IS_LOWER(c) iswlower(c) #define IS_LOWER(c) iswlower(c)
#define TO_UPPER(c) towupper(c) #define TO_UPPER(c) towupper(c)
#define TO_LOWER(c) towlower(c) #define TO_LOWER(c) towlower(c)
#else #else
#if HAVE_UPPER_LOWER #if HAVE_UPPER_LOWER
#define IS_UPPER(c) isupper((unsigned char) (c)) #define IS_UPPER(c) isupper((unsigned char) (c))
#define IS_LOWER(c) islower((unsigned char) (c)) #define IS_LOWER(c) islower((unsigned char) (c))
#define TO_UPPER(c) toupper((unsigned char) (c)) #define TO_UPPER(c) toupper((unsigned char) (c))
#define TO_LOWER(c) tolower((unsigned char) (c)) #define TO_LOWER(c) tolower((unsigned char) (c))
#else #else
#define IS_UPPER(c) ASCII_IS_UPPER(c) #define IS_UPPER(c) ASCII_IS_UPPER(c)
#define IS_LOWER(c) ASCII_IS_LOWER(c) #define IS_LOWER(c) ASCII_IS_LOWER(c)
#define TO_UPPER(c) ASCII_TO_UPPER(c) #define TO_UPPER(c) ASCII_TO_UPPER(c)
#define TO_LOWER(c) ASCII_TO_LOWER(c) #define TO_LOWER(c) ASCII_TO_LOWER(c)
#endif #endif
#endif #endif
#ifdef isspace #ifdef isspace
#define IS_SPACE(c) isspace((unsigned char)(c)) #define IS_SPACE(c) isspace((unsigned char)(c))
#else #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 #endif
#ifdef isdigit #ifdef isdigit
#define IS_DIGIT(c) isdigit((unsigned char)(c)) #define IS_DIGIT(c) isdigit((unsigned char)(c))
#else #else
#define IS_DIGIT(c) ((c) >= '0' && (c) <= '9') #define IS_DIGIT(c) ((c) >= '0' && (c) <= '9')
#endif #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 #ifndef NULL
#define NULL 0 #define NULL 0
#endif #endif
#ifndef TRUE #ifndef TRUE
#define TRUE 1 #define TRUE 1
#endif #endif
#ifndef FALSE #ifndef FALSE
#define FALSE 0 #define FALSE 0
#endif #endif
#define OPT_OFF 0 #define OPT_OFF 0
#define OPT_ON 1 #define OPT_ON 1
#define OPT_ONPLUS 2 #define OPT_ONPLUS 2
#if !HAVE_MEMCPY #if !HAVE_MEMCPY
#ifndef memcpy #ifndef memcpy
#define memcpy(to,from,len) bcopy((from),(to),(len)) #define memcpy(to,from,len) bcopy((from),(to),(len))
#endif #endif
#endif #endif
@ -201,7 +201,7 @@ void free();
#define SNPRINTF4(str, size, fmt, v1, v2, v3, v4) sprintf((str), (fmt), (v1), (v2), (v3), (v4)) #define SNPRINTF4(str, size, fmt, v1, v2, v3, v4) sprintf((str), (fmt), (v1), (v2), (v3), (v4))
#endif #endif
#define BAD_LSEEK ((off_t)-1) #define BAD_LSEEK ((off_t)-1)
#ifndef SEEK_SET #ifndef SEEK_SET
#define SEEK_SET 0 #define SEEK_SET 0
@ -225,37 +225,39 @@ void free();
* Special types and constants. * Special types and constants.
*/ */
typedef unsigned long LWCHAR; typedef unsigned long LWCHAR;
typedef off_t POSITION; typedef off_t POSITION;
typedef off_t LINENUM; typedef off_t LINENUM;
#define MIN_LINENUM_WIDTH 7 /* Min printing width of a line number */ #define MIN_LINENUM_WIDTH 7 /* Default min printing width of a line number */
#define MAX_UTF_CHAR_LEN 6 /* Max bytes in one UTF-8 char */ #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() * Flags for open()
*/ */
#if MSDOS_COMPILER || OS2 #if MSDOS_COMPILER || OS2
#define OPEN_READ (O_RDONLY|O_BINARY) #define OPEN_READ (O_RDONLY|O_BINARY)
#else #else
#ifdef _OSK #ifdef _OSK
#define OPEN_READ (S_IREAD) #define OPEN_READ (S_IREAD)
#else #else
#ifdef O_RDONLY #ifdef O_RDONLY
#define OPEN_READ (O_RDONLY) #define OPEN_READ (O_RDONLY)
#else #else
#define OPEN_READ (0) #define OPEN_READ (0)
#endif #endif
#endif #endif
#endif #endif
#if defined(O_WRONLY) && defined(O_APPEND) #if defined(O_WRONLY) && defined(O_APPEND)
#define OPEN_APPEND (O_APPEND|O_WRONLY) #define OPEN_APPEND (O_APPEND|O_WRONLY)
#else #else
#ifdef _OSK #ifdef _OSK
#define OPEN_APPEND (S_IWRITE) #define OPEN_APPEND (S_IWRITE)
#else #else
#define OPEN_APPEND (1) #define OPEN_APPEND (1)
#endif #endif
#endif #endif
@ -263,12 +265,12 @@ typedef off_t LINENUM;
* Set a file descriptor to binary mode. * Set a file descriptor to binary mode.
*/ */
#if MSDOS_COMPILER==MSOFTC #if MSDOS_COMPILER==MSOFTC
#define SET_BINARY(f) _setmode(f, _O_BINARY); #define SET_BINARY(f) _setmode(f, _O_BINARY);
#else #else
#if MSDOS_COMPILER || OS2 #if MSDOS_COMPILER || OS2
#define SET_BINARY(f) setmode(f, O_BINARY) #define SET_BINARY(f) setmode(f, O_BINARY)
#else #else
#define SET_BINARY(f) #define SET_BINARY(f)
#endif #endif
#endif #endif
@ -276,18 +278,18 @@ typedef off_t LINENUM;
* Does the shell treat "?" as a metacharacter? * Does the shell treat "?" as a metacharacter?
*/ */
#if MSDOS_COMPILER || OS2 || _OSK #if MSDOS_COMPILER || OS2 || _OSK
#define SHELL_META_QUEST 0 #define SHELL_META_QUEST 0
#else #else
#define SHELL_META_QUEST 1 #define SHELL_META_QUEST 1
#endif #endif
#define SPACES_IN_FILENAMES 1 #define SPACES_IN_FILENAMES 1
/* /*
* An IFILE represents an input file. * An IFILE represents an input file.
*/ */
#define IFILE VOID_POINTER #define IFILE VOID_POINTER
#define NULL_IFILE ((IFILE)NULL) #define NULL_IFILE ((IFILE)NULL)
/* /*
* The structure used to represent a "screen position". * The structure used to represent a "screen position".
@ -298,63 +300,65 @@ typedef off_t LINENUM;
*/ */
struct scrpos struct scrpos
{ {
POSITION pos; POSITION pos;
int ln; int ln;
}; };
typedef union parg typedef union parg
{ {
char *p_string; char *p_string;
int p_int; int p_int;
LINENUM p_linenum; LINENUM p_linenum;
char p_char;
} PARG; } PARG;
#define NULL_PARG ((PARG *)NULL) #define NULL_PARG ((PARG *)NULL)
struct textlist struct textlist
{ {
char *string; char *string;
char *endstring; char *endstring;
}; };
struct wchar_range struct wchar_range
{ {
LWCHAR first, last; LWCHAR first, last;
}; };
struct wchar_range_table struct wchar_range_table
{ {
struct wchar_range *table; struct wchar_range *table;
int count; 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 */ /* A fraction is represented by an int n; the fraction is n/NUM_FRAC_DENOM */
#define NUM_FRAC_DENOM 1000000 #define NUM_FRAC_DENOM 1000000
#define NUM_LOG_FRAC_DENOM 6 #define NUM_LOG_FRAC_DENOM 6
/* How quiet should we be? */ /* How quiet should we be? */
#define NOT_QUIET 0 /* Ring bell at eof and for errors */ #define NOT_QUIET 0 /* Ring bell at eof and for errors */
#define LITTLE_QUIET 1 /* Ring bell only for errors */ #define LITTLE_QUIET 1 /* Ring bell only for errors */
#define VERY_QUIET 2 /* Never ring bell */ #define VERY_QUIET 2 /* Never ring bell */
/* How should we prompt? */ /* How should we prompt? */
#define PR_SHORT 0 /* Prompt with colon */ #define PR_SHORT 0 /* Prompt with colon */
#define PR_MEDIUM 1 /* Prompt with message */ #define PR_MEDIUM 1 /* Prompt with message */
#define PR_LONG 2 /* Prompt with longer message */ #define PR_LONG 2 /* Prompt with longer message */
/* How should we handle backspaces? */ /* How should we handle backspaces? */
#define BS_SPECIAL 0 /* Do special things for underlining and bold */ #define BS_SPECIAL 0 /* Do special things for underlining and bold */
#define BS_NORMAL 1 /* \b treated as normal char; actually output */ #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_CONTROL 2 /* \b treated as control char; prints as ^H */
/* How should we search? */ /* How should we search? */
#define SRCH_FORW (1 << 0) /* Search forward 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_BACK (1 << 1) /* Search backward from current position */
#define SRCH_NO_MOVE (1 << 2) /* Highlight, but don't move */ #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_FIND_ALL (1 << 4) /* Find and highlight all matches */
#define SRCH_NO_MATCH (1 << 8) /* Search for non-matching lines */ #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 */ #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_NO_REGEX (1 << 12) /* Don't use regular expressions */
#define SRCH_FILTER (1 << 13) /* Search is for '&' (filter) command */ #define SRCH_FILTER (1 << 13) /* Search is for '&' (filter) command */
#define SRCH_AFTER_TARGET (1 << 14) /* Start search after the target line */ #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) ? \ #define SRCH_REVERSE(t) (((t) & SRCH_FORW) ? \
(((t) & ~SRCH_FORW) | SRCH_BACK) : \ (((t) & ~SRCH_FORW) | SRCH_BACK) : \
(((t) & ~SRCH_BACK) | SRCH_FORW)) (((t) & ~SRCH_BACK) | SRCH_FORW))
/* */ /* */
#define NO_MCA 0 #define NO_MCA 0
#define MCA_DONE 1 #define MCA_DONE 1
#define MCA_MORE 2 #define MCA_MORE 2
#define CC_OK 0 /* Char was accepted & processed */ #define CC_OK 0 /* Char was accepted & processed */
#define CC_QUIT 1 /* Char was a request to abort current cmd */ #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_ERROR 2 /* Char could not be accepted due to error */
#define CC_PASS 3 /* Char was rejected (internal) */ #define CC_PASS 3 /* Char was rejected (internal) */
#define CF_QUIT_ON_ERASE 0001 /* Abort cmd if its entirely erased */ #define CF_QUIT_ON_ERASE 0001 /* Abort cmd if its entirely erased */
/* Special char bit-flags used to tell put_line() to do something special */ /* Special char bit-flags used to tell put_line() to do something special */
#define AT_NORMAL (0) #define AT_NORMAL (0)
#define AT_UNDERLINE (1 << 0) #define AT_UNDERLINE (1 << 0)
#define AT_BOLD (1 << 1) #define AT_BOLD (1 << 1)
#define AT_BLINK (1 << 2) #define AT_BLINK (1 << 2)
#define AT_STANDOUT (1 << 3) #define AT_STANDOUT (1 << 3)
#define AT_ANSI (1 << 4) /* Content-supplied "ANSI" escape sequence */ #define AT_ANSI (1 << 4) /* Content-supplied "ANSI" escape sequence */
#define AT_BINARY (1 << 5) /* LESS*BINFMT representation */ #define AT_BINARY (1 << 5) /* LESS*BINFMT representation */
#define AT_HILITE (1 << 6) /* Internal highlights (e.g., for search) */ #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 #if '0' == 240
#define IS_EBCDIC_HOST 1 #define IS_EBCDIC_HOST 1
@ -400,76 +434,76 @@ struct wchar_range_table
* into a constant. * into a constant.
*/ */
#define CONTROL(c) ( \ #define CONTROL(c) ( \
(c)=='[' ? '\047' : \ (c)=='[' ? '\047' : \
(c)=='a' ? '\001' : \ (c)=='a' ? '\001' : \
(c)=='b' ? '\002' : \ (c)=='b' ? '\002' : \
(c)=='c' ? '\003' : \ (c)=='c' ? '\003' : \
(c)=='d' ? '\067' : \ (c)=='d' ? '\067' : \
(c)=='e' ? '\055' : \ (c)=='e' ? '\055' : \
(c)=='f' ? '\056' : \ (c)=='f' ? '\056' : \
(c)=='g' ? '\057' : \ (c)=='g' ? '\057' : \
(c)=='h' ? '\026' : \ (c)=='h' ? '\026' : \
(c)=='i' ? '\005' : \ (c)=='i' ? '\005' : \
(c)=='j' ? '\025' : \ (c)=='j' ? '\025' : \
(c)=='k' ? '\013' : \ (c)=='k' ? '\013' : \
(c)=='l' ? '\014' : \ (c)=='l' ? '\014' : \
(c)=='m' ? '\015' : \ (c)=='m' ? '\015' : \
(c)=='n' ? '\016' : \ (c)=='n' ? '\016' : \
(c)=='o' ? '\017' : \ (c)=='o' ? '\017' : \
(c)=='p' ? '\020' : \ (c)=='p' ? '\020' : \
(c)=='q' ? '\021' : \ (c)=='q' ? '\021' : \
(c)=='r' ? '\022' : \ (c)=='r' ? '\022' : \
(c)=='s' ? '\023' : \ (c)=='s' ? '\023' : \
(c)=='t' ? '\074' : \ (c)=='t' ? '\074' : \
(c)=='u' ? '\075' : \ (c)=='u' ? '\075' : \
(c)=='v' ? '\062' : \ (c)=='v' ? '\062' : \
(c)=='w' ? '\046' : \ (c)=='w' ? '\046' : \
(c)=='x' ? '\030' : \ (c)=='x' ? '\030' : \
(c)=='y' ? '\031' : \ (c)=='y' ? '\031' : \
(c)=='z' ? '\077' : \ (c)=='z' ? '\077' : \
(c)=='A' ? '\001' : \ (c)=='A' ? '\001' : \
(c)=='B' ? '\002' : \ (c)=='B' ? '\002' : \
(c)=='C' ? '\003' : \ (c)=='C' ? '\003' : \
(c)=='D' ? '\067' : \ (c)=='D' ? '\067' : \
(c)=='E' ? '\055' : \ (c)=='E' ? '\055' : \
(c)=='F' ? '\056' : \ (c)=='F' ? '\056' : \
(c)=='G' ? '\057' : \ (c)=='G' ? '\057' : \
(c)=='H' ? '\026' : \ (c)=='H' ? '\026' : \
(c)=='I' ? '\005' : \ (c)=='I' ? '\005' : \
(c)=='J' ? '\025' : \ (c)=='J' ? '\025' : \
(c)=='K' ? '\013' : \ (c)=='K' ? '\013' : \
(c)=='L' ? '\014' : \ (c)=='L' ? '\014' : \
(c)=='M' ? '\015' : \ (c)=='M' ? '\015' : \
(c)=='N' ? '\016' : \ (c)=='N' ? '\016' : \
(c)=='O' ? '\017' : \ (c)=='O' ? '\017' : \
(c)=='P' ? '\020' : \ (c)=='P' ? '\020' : \
(c)=='Q' ? '\021' : \ (c)=='Q' ? '\021' : \
(c)=='R' ? '\022' : \ (c)=='R' ? '\022' : \
(c)=='S' ? '\023' : \ (c)=='S' ? '\023' : \
(c)=='T' ? '\074' : \ (c)=='T' ? '\074' : \
(c)=='U' ? '\075' : \ (c)=='U' ? '\075' : \
(c)=='V' ? '\062' : \ (c)=='V' ? '\062' : \
(c)=='W' ? '\046' : \ (c)=='W' ? '\046' : \
(c)=='X' ? '\030' : \ (c)=='X' ? '\030' : \
(c)=='Y' ? '\031' : \ (c)=='Y' ? '\031' : \
(c)=='Z' ? '\077' : \ (c)=='Z' ? '\077' : \
(c)=='|' ? '\031' : \ (c)=='|' ? '\031' : \
(c)=='\\' ? '\034' : \ (c)=='\\' ? '\034' : \
(c)=='^' ? '\036' : \ (c)=='^' ? '\036' : \
(c)&077) (c)&077)
#else #else
#define CONTROL(c) ((c)&037) #define CONTROL(c) ((c)&037)
#endif /* IS_EBCDIC_HOST */ #endif /* IS_EBCDIC_HOST */
#define ESC CONTROL('[') #define ESC CONTROL('[')
#define ESCS "\33" #define ESCS "\33"
#define CSI ((unsigned char)'\233') #define CSI ((unsigned char)'\233')
#define CHAR_END_COMMAND 0x40000000 #define CHAR_END_COMMAND 0x40000000
#if _OSK_MWC32 #if _OSK_MWC32
#define LSIGNAL(sig,func) os9_signal(sig,func) #define LSIGNAL(sig,func) os9_signal(sig,func)
#else #else
#define LSIGNAL(sig,func) signal(sig,func) #define LSIGNAL(sig,func) signal(sig,func)
#endif #endif
#if HAVE_SIGPROCMASK #if HAVE_SIGPROCMASK
@ -486,41 +520,41 @@ struct wchar_range_table
#endif #endif
#endif #endif
#define S_INTERRUPT 01 #define S_INTERRUPT 01
#define S_STOP 02 #define S_STOP 02
#define S_WINCH 04 #define S_WINCH 04
#define ABORT_SIGS() (sigs & (S_INTERRUPT|S_STOP)) #define ABORT_SIGS() (sigs & (S_INTERRUPT|S_STOP))
#define QUIT_OK 0 #define QUIT_OK 0
#define QUIT_ERROR 1 #define QUIT_ERROR 1
#define QUIT_INTERRUPT 2 #define QUIT_INTERRUPT 2
#define QUIT_SAVED_STATUS (-1) #define QUIT_SAVED_STATUS (-1)
#define FOLLOW_DESC 0 #define FOLLOW_DESC 0
#define FOLLOW_NAME 1 #define FOLLOW_NAME 1
/* filestate flags */ /* filestate flags */
#define CH_CANSEEK 001 #define CH_CANSEEK 001
#define CH_KEEPOPEN 002 #define CH_KEEPOPEN 002
#define CH_POPENED 004 #define CH_POPENED 004
#define CH_HELPFILE 010 #define CH_HELPFILE 010
#define CH_NODATA 020 /* Special case for zero length files */ #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_HELPFILE "@/\\less/\\help/\\file/\\@"
#define FAKE_EMPTYFILE "@/\\less/\\empty/\\file/\\@" #define FAKE_EMPTYFILE "@/\\less/\\empty/\\file/\\@"
/* Flags for cvt_text */ /* Flags for cvt_text */
#define CVT_TO_LC 01 /* Convert upper-case to lower-case */ #define CVT_TO_LC 01 /* Convert upper-case to lower-case */
#define CVT_BS 02 /* Do backspace processing */ #define CVT_BS 02 /* Do backspace processing */
#define CVT_CRLF 04 /* Remove CR after LF */ #define CVT_CRLF 04 /* Remove CR after LF */
#define CVT_ANSI 010 /* Remove ANSI escape sequences */ #define CVT_ANSI 010 /* Remove ANSI escape sequences */
#if HAVE_TIME_T #if HAVE_TIME_T
#define time_type time_t #define time_type time_t
#else #else
#define time_type long #define time_type long
#endif #endif
/* X11 mouse reporting definitions */ /* X11 mouse reporting definitions */
@ -535,6 +569,7 @@ struct wchar_range_table
struct mlist; struct mlist;
struct loption; struct loption;
struct hilite_tree; struct hilite_tree;
struct ansi_state;
#include "pattern.h" #include "pattern.h"
#include "funcs.h" #include "funcs.h"

View File

@ -42,7 +42,8 @@
ESC-n * Repeat previous search, spanning files. ESC-n * Repeat previous search, spanning files.
ESC-N * Repeat previous search, reverse dir. & spanning files. ESC-N * Repeat previous search, reverse dir. & spanning files.
ESC-u Undo (toggle) search highlighting. 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: A search pattern may begin with one or more of:
^N or ! Search for NON-matching lines. ^N or ! Search for NON-matching lines.
@ -50,6 +51,7 @@
^F or @ Start search at FIRST file (for /) or last file (for ?). ^F or @ Start search at FIRST file (for /) or last file (for ?).
^K Highlight matches, but don't move (KEEP position). ^K Highlight matches, but don't move (KEEP position).
^R Don't use REGULAR EXPRESSIONS. ^R Don't use REGULAR EXPRESSIONS.
^W WRAP search if no match found.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
JJUUMMPPIINNGG JJUUMMPPIINNGG
@ -62,7 +64,7 @@
{ ( [ * Find close bracket } ) ]. { ( [ * Find close bracket } ) ].
} ) ] * Find open bracket { ( [. } ) ] * Find open bracket { ( [.
ESC-^F _<_c_1_> _<_c_2_> * Find close bracket _<_c_2_>. 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 Each "find close bracket" command goes forward to the close bracket
matching the (_N-th) open bracket in the top line. matching the (_N-th) open bracket in the top line.
@ -129,8 +131,8 @@
Repaint by clearing rather than scrolling. Repaint by clearing rather than scrolling.
-d ........ --dumb -d ........ --dumb
Dumb terminal. Dumb terminal.
-D [_x_n_._n] . --color=_x_n_._n -D xx_c_o_l_o_r . --color=xx_c_o_l_o_r
Set screen colors. (MS-DOS only) Set screen colors.
-e -E .... --quit-at-eof --QUIT-AT-EOF -e -E .... --quit-at-eof --QUIT-AT-EOF
Quit at end of file. Quit at end of file.
-f ........ --force -f ........ --force
@ -202,9 +204,13 @@
-~ ........ --tilde -~ ........ --tilde
Don't display tildes after end of file. Don't display tildes after end of file.
-# [_N] .... --shift=[_N] -# [_N] .... --shift=[_N]
Horizontal scroll amount (0 = one half screen width) Set horizontal scroll amount (0 = one half screen width).
--follow-name --follow-name
The F command changes files if the input file is renamed. 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 --mouse
Enable mouse input. Enable mouse input.
--no-keypad --no-keypad
@ -215,8 +221,12 @@
Set the character used to mark truncated lines. Set the character used to mark truncated lines.
--save-marks --save-marks
Retain marks across invocations of less. Retain marks across invocations of less.
--status-col-width=N
Set the width of the -J status column to N characters.
--use-backslash --use-backslash
Subsequent options use backslash as escape char. Subsequent options use backslash as escape char.
--use-color
Enables colored text.
--wheel-lines=N --wheel-lines=N
Each click of the mouse wheel moves N lines. Each click of the mouse wheel moves N lines.
@ -244,5 +254,3 @@
TAB ...................................... Complete filename & cycle. TAB ...................................... Complete filename & cycle.
SHIFT-TAB ...................... ESC-TAB Complete filename & reverse cycle. SHIFT-TAB ...................... ESC-TAB Complete filename & reverse cycle.
ctrl-L ................................... Complete filename, list all. ctrl-L ................................... Complete filename, list all.

View File

@ -1,5 +1,5 @@
'\" t '\" t
.TH LESS 1 "Version 563: 13 Jun 2020" .TH LESS 1 "Version 581: 06 Apr 2021"
.SH NAME .SH NAME
less \- opposite of more less \- opposite of more
.SH SYNOPSIS .SH SYNOPSIS
@ -109,6 +109,7 @@ Scroll horizontally left back to the first column.
Repaint the screen. Repaint the screen.
.IP R .IP R
Repaint the screen, discarding any buffered input. Repaint the screen, discarding any buffered input.
That is, reload the current file.
Useful if the file is changing while it is being viewed. Useful if the file is changing while it is being viewed.
.IP "F" .IP "F"
Scroll forward, and keep trying to read when the 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 It is a way to monitor the tail of a file which is growing
while it is being viewed. while it is being viewed.
(The behavior is similar to the "tail \-f" command.) (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" .IP "ESC-F"
Like F, but as soon as a line is found which matches Like F, but as soon as a line is found which matches
the last search pattern, the terminal bell is rung 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" .IP "^R"
Don't interpret regular expression metacharacters; Don't interpret regular expression metacharacters;
that is, do a simple textual comparison. 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 .RE
.IP ?pattern .IP ?pattern
Search backward in the file for the N-th line containing the 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. As in forward searches.
.IP "^R" .IP "^R"
As in forward searches. 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 .RE
.IP "ESC-/pattern" .IP "ESC-/pattern"
Same as "/*". Same as "/*".
@ -280,6 +293,10 @@ turn highlighting back on.
Any search command will also turn highlighting back on. Any search command will also turn highlighting back on.
(Highlighting can also be disabled by toggling the \-G option; (Highlighting can also be disabled by toggling the \-G option;
in that case search commands do not turn highlighting back on.) 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" .IP "&pattern"
Display only lines which match the pattern; Display only lines which match the pattern;
lines which do not match the pattern are not displayed. 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 While filtering is in effect, an ampersand is displayed at the
beginning of the prompt, beginning of the prompt,
as a reminder that some lines in the file may be hidden. 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 .sp
Certain characters are special as in the / command: Certain characters are special as in the / command:
.RS .RS
@ -552,20 +571,105 @@ The \-d option does not otherwise change the behavior of
.I less .I less
on a dumb terminal. on a dumb terminal.
.IP "\-D\fBx\fP\fIcolor\fP or \-\-color=\fBx\fP\fIcolor\fP" .IP "\-D\fBx\fP\fIcolor\fP or \-\-color=\fBx\fP\fIcolor\fP"
[MS-DOS only] Changes the color of different parts of the displayed text.
Sets the color of the text displayed. \fBx\fP is a single character which selects the type of text
\fBx\fP is a single character which selects the type of text whose color is whose color is being set:
being set: n=normal, s=standout, d=bold, u=underlined, k=blink. .RS
\fIcolor\fP is a pair of numbers separated by a period. .IP "B"
The first number selects the foreground color and the second selects Binary characters.
the background color of the text. .IP "C"
A single number \fIN\fP is the same as \fIN.M\fP, Control characters.
where \fIM\fP is the normal background color. .IP "E"
The color may start or end with \fBu\fP to use underline (with the normal Errors and informational messages.
color, if by itself), if the system supports it (Windows only). .IP "M"
\fBx\fP may also be \fBa\fP to toggle strict ANSI sequence rendering Mark letters in the status column.
(SGR mode). .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" .IP "\-e or \-\-quit-at-eof"
Causes Causes
.I less .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. Displays a status column at the left edge of the screen.
The status column shows the lines that matched the current search, The status column shows the lines that matched the current search,
and any lines that are marked (via the m or M command). 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" .IP "\-k\fIfilename\fP or \-\-lesskey-file=\fIfilename\fP"
Causes Causes
.I less .I less
@ -676,7 +779,8 @@ command prompt from the "F" command.
.IP "\-L or \-\-no-lessopen" .IP "\-L or \-\-no-lessopen"
Ignore the LESSOPEN environment variable Ignore the LESSOPEN environment variable
(see the INPUT PREPROCESSOR section below). (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 but it will apply only to files opened subsequently, not to the
file which is currently open. file which is currently open.
.IP "\-m or \-\-long-prompt" .IP "\-m or \-\-long-prompt"
@ -776,16 +880,33 @@ cannot keep track of the actual appearance of the screen
each type of control character). each type of control character).
Thus, various display problems may result, Thus, various display problems may result,
such as long lines being split in the wrong place. 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" .IP "\-R or \-\-RAW-CONTROL-CHARS"
Like \-r, but only ANSI "color" escape sequences are output in "raw" form. Like \-r, but only ANSI "color" escape sequences and OSC 8 hyperlink
Unlike \-r, the screen appearance is maintained correctly in most cases. sequences are output in "raw" form.
ANSI "color" escape sequences are sequences of the 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 .sp
ESC [ \&...\& m ESC [ \&...\& m
.sp .sp
where the "...\&" is zero or more color specification characters 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 You can make
.I less .I less
think that characters other than "m" can end ANSI color escape sequences 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 the name of a command compatible with
.IR global (1), .IR global (1),
and that command is executed to find the tag. 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 The \-t option may also be specified from within
.I less .I less
(using the \- command) as a way of examining a new file. (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. Other backspaces are deleted, along with the preceding character.
Carriage returns immediately followed by a newline are deleted. Carriage returns immediately followed by a newline are deleted.
Other carriage returns are handled as specified by the \-r option. 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 Text which is overstruck or underlined can be searched for
if neither \-u nor \-U is in effect. if neither \-u nor \-U is in effect.
.IP "\-V or \-\-version" .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), with the same name as the original (now renamed) file),
.I less .I less
will display the contents of that new file. 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" .IP "\-\-mouse"
Enables mouse input: Enables mouse input:
scrolling the mouse wheel down moves forward in the file, 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. If set to "\-", truncated lines are not marked.
.IP "\-\-save-marks" .IP "\-\-save-marks"
Save marks in the history file, so marks are retained 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" .IP "\-\-use-backslash"
This option changes the interpretations of options which follow this one. This option changes the interpretations of options which follow this one.
After the \-\-use-backslash option, any backslash in an option string is After the \-\-use-backslash option, any backslash in an option string is
removed and the following character is taken literally. removed and the following character is taken literally.
This allows a dollar sign to be included in option strings. 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" .IP "\-\-wheel-lines=\fIn\fP"
Set the number of lines to scroll when the mouse wheel is scrolled Set the number of lines to scroll when the mouse wheel is scrolled
and the \-\-mouse or \-\-MOUSE option is in effect. 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. may also be used to set (or change) an initial command for every file.
. .
.SH "LINE EDITING" .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, (for example, a filename for the :e command,
or the pattern for a search command), or the pattern for a search command),
certain keys can be used to manipulate the command line. 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) .BR lesskey (1)
. .
.SH COPYRIGHT .SH COPYRIGHT
Copyright (C) 1984-2020 Mark Nudelman Copyright (C) 1984-2021 Mark Nudelman
.PP .PP
less is part of the GNU project and is free software. less is part of the GNU project and is free software.
You can redistribute it and/or modify it You can redistribute it and/or modify it
@ -1833,4 +1981,4 @@ Report bugs at https://github.com/gwsw/less/issues.
.br .br
For more information, see the less homepage at For more information, see the less homepage at
.br .br
http://www.greenwoodsoftware.com/less. https://greenwoodsoftware.com/less.

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -13,16 +13,16 @@
* Simply echos its filename arguments on standard output. * Simply echos its filename arguments on standard output.
* But any argument containing spaces is enclosed in quotes. * But any argument containing spaces is enclosed in quotes.
* *
* -ox Specifies "x" to be the open quote character. * -ox Specifies "x" to be the open quote character.
* -cx Specifies "x" to be the close quote character. * -cx Specifies "x" to be the close quote character.
* -pn Specifies "n" to be the open quote character, as an integer. * -pn Specifies "n" to be the open quote character, as an integer.
* -dn Specifies "n" to be the close quote character, as an integer. * -dn Specifies "n" to be the close quote character, as an integer.
* -mx Specifies "x" to be a metachar. * -mx Specifies "x" to be a metachar.
* -nn Specifies "n" to be a metachar, as an integer. * -nn Specifies "n" to be a metachar, as an integer.
* -ex Specifies "x" to be the escape char for metachars. * -ex Specifies "x" to be the escape char for metachars.
* -fn Specifies "x" to be the escape char for metachars, as an integer. * -fn Specifies "x" to be the escape char for metachars, as an integer.
* -a Specifies that all arguments are to be quoted. * -a Specifies that all arguments are to be quoted.
* The default is that only arguments containing spaces are quoted. * The default is that only arguments containing spaces are quoted.
*/ */
#include "less.h" #include "less.h"

View File

@ -1,4 +1,4 @@
.TH LESSECHO 1 "Version 563: 13 Jun 2020" .TH LESSECHO 1 "Version 581: 06 Apr 2021"
.SH NAME .SH NAME
lessecho \- expand metacharacters lessecho \- expand metacharacters
.SH SYNOPSIS .SH SYNOPSIS
@ -19,7 +19,7 @@ are surrounded by quotes instead.
.TP .TP
.B \-ox .B \-ox
Specifies "x", rather than double-quote, to be the open quote character, 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 .TP
.B \-cx .B \-cx
Specifies "x" to be the close quote character. 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 .TP
.B \-a .B \-a
Specifies that all arguments are to be quoted. 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" .SH "SEE ALSO"
.BR less (1) .BR less (1)
.SH AUTHOR .SH AUTHOR
This manual page was written by Thomas Schoepf <schoepf@debian.org>, This manual page was written by Thomas Schoepf <schoepf@debian.org>,
for the Debian GNU/Linux system (but may be used by others). for the Debian GNU/Linux system (but may be used by others).
.PP .PP
Send bug reports or comments to bug-less@gnu.org. Report bugs at https://github.com/gwsw/less/issues.

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * 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. * Make a .less file.
* If no input file is specified, standard input is used. * If no input file is specified, standard input is used.
* If no output file is specified, $HOME/.less is used. * If no output file is specified, $HOME/.less is used.
* *
* The .less file is used to specify (to "less") user-defined * The .less file is used to specify (to "less") user-defined
* key bindings. Basically any sequence of 1 to MAX_CMDLEN * key bindings. Basically any sequence of 1 to MAX_CMDLEN
* keystrokes may be bound to an existing less function. * keystrokes may be bound to an existing less function.
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* The input file is an ascii file consisting of a * The input file is an ascii file consisting of a
* sequence of lines of the form: * sequence of lines of the form:
* string <whitespace> action [chars] <newline> * string <whitespace> action [chars] <newline>
* *
* "string" is a sequence of command characters which form * "string" is a sequence of command characters which form
* the new user-defined command. The command * the new user-defined command. The command
* characters may be: * characters may be:
* 1. The actual character itself. * 1. The actual character itself.
* 2. A character preceded by ^ to specify a * 2. A character preceded by ^ to specify a
* control character (e.g. ^X means control-X). * control character (e.g. ^X means control-X).
* 3. A backslash followed by one to three octal digits * 3. A backslash followed by one to three octal digits
* to specify a character by its octal value. * to specify a character by its octal value.
* 4. A backslash followed by b, e, n, r or t * 4. A backslash followed by b, e, n, r or t
* to specify \b, ESC, \n, \r or \t, respectively. * to specify \b, ESC, \n, \r or \t, respectively.
* 5. Any character (other than those mentioned above) preceded * 5. Any character (other than those mentioned above) preceded
* by a \ to specify the character itself (characters which * by a \ to specify the character itself (characters which
* must be preceded by \ include ^, \, and whitespace. * must be preceded by \ include ^, \, and whitespace.
* "action" is the name of a "less" action, from the table below. * "action" is the name of a "less" action, from the table below.
* "chars" is an optional sequence of characters which is treated * "chars" is an optional sequence of characters which is treated
* as keyboard input after the command is executed. * as keyboard input after the command is executed.
* *
* Blank lines and lines which start with # are ignored, * Blank lines and lines which start with # are ignored,
* except for the special control lines: * except for the special control lines:
* #command Signals the beginning of the command * #command Signals the beginning of the command
* keys section. * keys section.
* #line-edit Signals the beginning of the line-editing * #line-edit Signals the beginning of the line-editing
* keys section. * keys section.
* #env Signals the beginning of the environment * #env Signals the beginning of the environment
* variable section. * variable section.
* #stop Stops command parsing in less; * #stop Stops command parsing in less;
* causes all default keys to be disabled. * causes all default keys to be disabled.
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* The output file is a non-ascii file, consisting of a header, * The output file is a non-ascii file, consisting of a header,
* one or more sections, and a trailer. * one or more sections, and a trailer.
* Each section begins with a section header, a section length word * Each section begins with a section header, a section length word
* and the section data. Normally there are three sections: * and the section data. Normally there are three sections:
* CMD_SECTION Definition of command keys. * CMD_SECTION Definition of command keys.
* EDIT_SECTION Definition of editing keys. * EDIT_SECTION Definition of editing keys.
* END_SECTION A special section header, with no * END_SECTION A special section header, with no
* length word or section data. * length word or section data.
* *
* Section data consists of zero or more byte sequences of the form: * Section data consists of zero or more byte sequences of the form:
* string <0> <action> * string <0> <action>
* or * or
* string <0> <action|A_EXTRA> chars <0> * string <0> <action|A_EXTRA> chars <0>
* *
* "string" is the command string. * "string" is the command string.
* "<0>" is one null byte. * "<0>" is one null byte.
* "<action>" is one byte containing the action code (the A_xxx value). * "<action>" is one byte containing the action code (the A_xxx value).
* If action is ORed with A_EXTRA, the action byte is followed * If action is ORed with A_EXTRA, the action byte is followed
* by the null-terminated "chars" string. * by the null-terminated "chars" string.
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/ */
@ -153,6 +153,7 @@ struct cmdname cmdnames[] =
{ "toggle-flag", A_OPT_TOGGLE }, { "toggle-flag", A_OPT_TOGGLE },
{ "toggle-option", A_OPT_TOGGLE }, { "toggle-option", A_OPT_TOGGLE },
{ "undo-hilite", A_UNDO_SEARCH }, { "undo-hilite", A_UNDO_SEARCH },
{ "clear-search", A_CLR_SEARCH },
{ "version", A_VERSION }, { "version", A_VERSION },
{ "visual", A_VISUAL }, { "visual", A_VISUAL },
{ NULL, 0 } { NULL, 0 }
@ -160,26 +161,26 @@ struct cmdname cmdnames[] =
struct cmdname editnames[] = struct cmdname editnames[] =
{ {
{ "back-complete", EC_B_COMPLETE }, { "back-complete", EC_B_COMPLETE },
{ "backspace", EC_BACKSPACE }, { "backspace", EC_BACKSPACE },
{ "delete", EC_DELETE }, { "delete", EC_DELETE },
{ "down", EC_DOWN }, { "down", EC_DOWN },
{ "end", EC_END }, { "end", EC_END },
{ "expand", EC_EXPAND }, { "expand", EC_EXPAND },
{ "forw-complete", EC_F_COMPLETE }, { "forw-complete", EC_F_COMPLETE },
{ "home", EC_HOME }, { "home", EC_HOME },
{ "insert", EC_INSERT }, { "insert", EC_INSERT },
{ "invalid", EC_UINVALID }, { "invalid", EC_UINVALID },
{ "kill-line", EC_LINEKILL }, { "kill-line", EC_LINEKILL },
{ "abort", EC_ABORT }, { "abort", EC_ABORT },
{ "left", EC_LEFT }, { "left", EC_LEFT },
{ "literal", EC_LITERAL }, { "literal", EC_LITERAL },
{ "right", EC_RIGHT }, { "right", EC_RIGHT },
{ "up", EC_UP }, { "up", EC_UP },
{ "word-backspace", EC_W_BACKSPACE }, { "word-backspace", EC_W_BACKSPACE },
{ "word-delete", EC_W_DELETE }, { "word-delete", EC_W_DELETE },
{ "word-left", EC_W_LEFT }, { "word-left", EC_W_LEFT },
{ "word-right", EC_W_RIGHT }, { "word-right", EC_W_RIGHT },
{ NULL, 0 } { NULL, 0 }
}; };
@ -206,10 +207,10 @@ char filetrailer[] = {
C1_END_LESSKEY_MAGIC, C1_END_LESSKEY_MAGIC,
C2_END_LESSKEY_MAGIC C2_END_LESSKEY_MAGIC
}; };
char cmdsection[1] = { CMD_SECTION }; char cmdsection[1] = { CMD_SECTION };
char editsection[1] = { EDIT_SECTION }; char editsection[1] = { EDIT_SECTION };
char varsection[1] = { VAR_SECTION }; char varsection[1] = { VAR_SECTION };
char endsection[1] = { END_SECTION }; char endsection[1] = { END_SECTION };
char *infile = NULL; char *infile = NULL;
char *outfile = NULL ; char *outfile = NULL ;
@ -459,7 +460,7 @@ tstr(pp, xlate)
*pp = p+2; *pp = p+2;
buf[0] = CONTROL(p[1]); buf[0] = CONTROL(p[1]);
buf[1] = '\0'; buf[1] = '\0';
if (buf[0] == CONTROL('K')) if (xlate && buf[0] == CONTROL('K'))
return tstr_control_k; return tstr_control_k;
return (buf); return (buf);
} }
@ -478,7 +479,7 @@ tstr(pp, xlate)
skipsp(s) skipsp(s)
char *s; char *s;
{ {
while (*s == ' ' || *s == '\t') while (*s == ' ' || *s == '\t')
s++; s++;
return (s); return (s);
} }
@ -546,7 +547,7 @@ add_cmd_str(s)
control_line(s) control_line(s)
char *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")) if (PREFIX(s, "#line-edit"))
{ {

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -11,29 +11,29 @@
/* /*
* Format of a lesskey file: * Format of a lesskey file:
* *
* LESSKEY_MAGIC (4 bytes) * LESSKEY_MAGIC (4 bytes)
* sections... * sections...
* END_LESSKEY_MAGIC (4 bytes) * END_LESSKEY_MAGIC (4 bytes)
* *
* Each section is: * Each section is:
* *
* section_MAGIC (1 byte) * section_MAGIC (1 byte)
* section_length (2 bytes) * section_length (2 bytes)
* key table (section_length bytes) * key table (section_length bytes)
*/ */
#define C0_LESSKEY_MAGIC '\0' #define C0_LESSKEY_MAGIC '\0'
#define C1_LESSKEY_MAGIC 'M' #define C1_LESSKEY_MAGIC 'M'
#define C2_LESSKEY_MAGIC '+' #define C2_LESSKEY_MAGIC '+'
#define C3_LESSKEY_MAGIC 'G' #define C3_LESSKEY_MAGIC 'G'
#define CMD_SECTION 'c' #define CMD_SECTION 'c'
#define EDIT_SECTION 'e' #define EDIT_SECTION 'e'
#define VAR_SECTION 'v' #define VAR_SECTION 'v'
#define END_SECTION 'x' #define END_SECTION 'x'
#define C0_END_LESSKEY_MAGIC 'E' #define C0_END_LESSKEY_MAGIC 'E'
#define C1_END_LESSKEY_MAGIC 'n' #define C1_END_LESSKEY_MAGIC 'n'
#define C2_END_LESSKEY_MAGIC 'd' #define C2_END_LESSKEY_MAGIC 'd'
/* */ /* */
#define KRADIX 64 #define KRADIX 64

View File

@ -1,5 +1,5 @@
'\" t '\" t
.TH LESSKEY 1 "Version 563: 13 Jun 2020" .TH LESSKEY 1 "Version 581: 06 Apr 2021"
.SH NAME .SH NAME
lesskey \- specify key bindings for less lesskey \- specify key bindings for less
.SH SYNOPSIS .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 the input file is "\-", standard input is read.
If no input file is specified, a standard filename is used 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: as the name of the input file, which depends on the system being used:
On Unix systems, $HOME/.lesskey is used; On Unix systems, "$HOME/.lesskey" is used;
on MS-DOS systems, $HOME/_lesskey is used; on MS-DOS systems, "$HOME/_lesskey" is used;
and on OS/2 systems $HOME/lesskey.ini is used, and on OS/2 systems "$HOME/lesskey.ini" is used,
or $INIT/lesskey.ini if $HOME is undefined. or "$INIT/lesskey.ini" if $HOME is undefined.
The output file is a binary file which is used by The output file is a binary file which is used by
.IR less . .IR less .
If no output file is specified, 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. 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, Otherwise, a standard filename is used as the name of the output file,
which depends on the system being used: which depends on the system being used:
On Unix and OS-9 systems, $HOME/.less is used; On Unix and OS-9 systems, "$HOME/.less" is used;
on MS-DOS systems, $HOME/_less is used; on MS-DOS systems, "$HOME/_less" is used;
and on OS/2 systems, $HOME/less.ini is used, and on OS/2 systems, "$HOME/less.ini" is used,
or $INIT/less.ini if $HOME is undefined. or "$INIT/less.ini" if $HOME is undefined.
If the output file already exists, If the output file already exists,
.I lesskey .I lesskey
will overwrite it. 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: The extra string has a special meaning for the "quit" action:
when when
.I less .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 .SH EXAMPLE
The following input file describes the set of The following input file describes the set of
@ -171,6 +171,7 @@ r repaint
^R repaint ^R repaint
^L repaint ^L repaint
\eeu undo-hilite \eeu undo-hilite
\eeU clear-search
g goto-line g goto-line
\ekh goto-line \ekh goto-line
< 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. This NUL character should be represented as \e340 in a lesskey file.
. .
.SH COPYRIGHT .SH COPYRIGHT
Copyright (C) 1984-2020 Mark Nudelman Copyright (C) 1984-2021 Mark Nudelman
.PP .PP
less is part of the GNU project and is free software. less is part of the GNU project and is free software.
You can redistribute it and/or modify it You can redistribute it and/or modify it
@ -395,4 +396,4 @@ See the GNU General Public License for more details.
. .
Mark Nudelman Mark Nudelman
.br .br
Send bug reports or comments to <bug-less@gnu.org>. Report bugs at https://github.com/gwsw/less/issues.

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -11,81 +11,81 @@
/* /*
* Macros to define the method of doing filename "globbing". * Macros to define the method of doing filename "globbing".
* There are three possible mechanisms: * There are three possible mechanisms:
* 1. GLOB_LIST * 1. GLOB_LIST
* This defines a function that returns a list of matching filenames. * This defines a function that returns a list of matching filenames.
* 2. GLOB_NAME * 2. GLOB_NAME
* This defines a function that steps thru the list of matching * This defines a function that steps thru the list of matching
* filenames, returning one name each time it is called. * filenames, returning one name each time it is called.
* 3. GLOB_STRING * 3. GLOB_STRING
* This defines a function that returns the complete list of * This defines a function that returns the complete list of
* matching filenames as a single space-separated string. * matching filenames as a single space-separated string.
*/ */
#if OS2 #if OS2
#define DECL_GLOB_LIST(list) char **list; char **pp; #define DECL_GLOB_LIST(list) char **list; char **pp;
#define GLOB_LIST(filename,list) list = _fnexplode(filename) #define GLOB_LIST(filename,list) list = _fnexplode(filename)
#define GLOB_LIST_FAILED(list) list == NULL #define GLOB_LIST_FAILED(list) list == NULL
#define SCAN_GLOB_LIST(list,p) pp = list; *pp != NULL; pp++ #define SCAN_GLOB_LIST(list,p) pp = list; *pp != NULL; pp++
#define INIT_GLOB_LIST(list,p) p = *pp #define INIT_GLOB_LIST(list,p) p = *pp
#define GLOB_LIST_DONE(list) _fnexplodefree(list) #define GLOB_LIST_DONE(list) _fnexplodefree(list)
#else #else
#if MSDOS_COMPILER==DJGPPC #if MSDOS_COMPILER==DJGPPC
#define DECL_GLOB_LIST(list) glob_t list; int i; #define DECL_GLOB_LIST(list) glob_t list; int i;
#define GLOB_LIST(filename,list) glob(filename,GLOB_NOCHECK,0,&list) #define GLOB_LIST(filename,list) glob(filename,GLOB_NOCHECK,0,&list)
#define GLOB_LIST_FAILED(list) 0 #define GLOB_LIST_FAILED(list) 0
#define SCAN_GLOB_LIST(list,p) i = 0; i < list.gl_pathc; i++ #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 INIT_GLOB_LIST(list,p) p = list.gl_pathv[i]
#define GLOB_LIST_DONE(list) globfree(&list) #define GLOB_LIST_DONE(list) globfree(&list)
#else #else
#if MSDOS_COMPILER==MSOFTC || MSDOS_COMPILER==BORLANDC #if MSDOS_COMPILER==MSOFTC || MSDOS_COMPILER==BORLANDC
#define GLOB_FIRST_NAME(filename,fndp,h) h = _dos_findfirst(filename, ~_A_VOLID, fndp) #define GLOB_FIRST_NAME(filename,fndp,h) h = _dos_findfirst(filename, ~_A_VOLID, fndp)
#define GLOB_FIRST_FAILED(handle) ((handle) != 0) #define GLOB_FIRST_FAILED(handle) ((handle) != 0)
#define GLOB_NEXT_NAME(handle,fndp) _dos_findnext(fndp) #define GLOB_NEXT_NAME(handle,fndp) _dos_findnext(fndp)
#define GLOB_NAME_DONE(handle) #define GLOB_NAME_DONE(handle)
#define GLOB_NAME name #define GLOB_NAME name
#define DECL_GLOB_NAME(fnd,drive,dir,fname,ext,handle) \ #define DECL_GLOB_NAME(fnd,drive,dir,fname,ext,handle) \
struct find_t fnd; \ struct find_t fnd; \
char drive[_MAX_DRIVE]; \ char drive[_MAX_DRIVE]; \
char dir[_MAX_DIR]; \ char dir[_MAX_DIR]; \
char fname[_MAX_FNAME]; \ char fname[_MAX_FNAME]; \
char ext[_MAX_EXT]; \ char ext[_MAX_EXT]; \
int handle; int handle;
#else #else
#if MSDOS_COMPILER==WIN32C && (defined(_MSC_VER) || defined(MINGW)) #if MSDOS_COMPILER==WIN32C && (defined(_MSC_VER) || defined(MINGW))
#define GLOB_FIRST_NAME(filename,fndp,h) h = _findfirst(filename, fndp) #define GLOB_FIRST_NAME(filename,fndp,h) h = _findfirst(filename, fndp)
#define GLOB_FIRST_FAILED(handle) ((handle) == -1) #define GLOB_FIRST_FAILED(handle) ((handle) == -1)
#define GLOB_NEXT_NAME(handle,fndp) _findnext(handle, fndp) #define GLOB_NEXT_NAME(handle,fndp) _findnext(handle, fndp)
#define GLOB_NAME_DONE(handle) _findclose(handle) #define GLOB_NAME_DONE(handle) _findclose(handle)
#define GLOB_NAME name #define GLOB_NAME name
#define DECL_GLOB_NAME(fnd,drive,dir,fname,ext,handle) \ #define DECL_GLOB_NAME(fnd,drive,dir,fname,ext,handle) \
struct _finddata_t fnd; \ struct _finddata_t fnd; \
char drive[_MAX_DRIVE]; \ char drive[_MAX_DRIVE]; \
char dir[_MAX_DIR]; \ char dir[_MAX_DIR]; \
char fname[_MAX_FNAME]; \ char fname[_MAX_FNAME]; \
char ext[_MAX_EXT]; \ char ext[_MAX_EXT]; \
intptr_t handle; intptr_t handle;
#else #else
#if MSDOS_COMPILER==WIN32C && !defined(_MSC_VER) /* Borland C for Windows */ #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_NAME(filename,fndp,h) h = findfirst(filename, fndp, ~FA_LABEL)
#define GLOB_FIRST_FAILED(handle) ((handle) != 0) #define GLOB_FIRST_FAILED(handle) ((handle) != 0)
#define GLOB_NEXT_NAME(handle,fndp) findnext(fndp) #define GLOB_NEXT_NAME(handle,fndp) findnext(fndp)
#define GLOB_NAME_DONE(handle) #define GLOB_NAME_DONE(handle)
#define GLOB_NAME ff_name #define GLOB_NAME ff_name
#define DECL_GLOB_NAME(fnd,drive,dir,fname,ext,handle) \ #define DECL_GLOB_NAME(fnd,drive,dir,fname,ext,handle) \
struct ffblk fnd; \ struct ffblk fnd; \
char drive[MAXDRIVE]; \ char drive[MAXDRIVE]; \
char dir[MAXDIR]; \ char dir[MAXDIR]; \
char fname[MAXFILE]; \ char fname[MAXFILE]; \
char ext[MAXEXT]; \ char ext[MAXEXT]; \
int handle; int handle;
#endif #endif
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -40,11 +40,11 @@
*/ */
struct linenum_info struct linenum_info
{ {
struct linenum_info *next; /* Link to next in the list */ struct linenum_info *next; /* Link to next in the list */
struct linenum_info *prev; /* Line to previous in the list */ struct linenum_info *prev; /* Line to previous in the list */
POSITION pos; /* File position */ POSITION pos; /* File position */
POSITION gap; /* Gap between prev and next */ POSITION gap; /* Gap between prev and next */
LINENUM line; /* Line number */ LINENUM line; /* Line number */
}; };
/* /*
* "gap" needs some explanation: the gap of any particular 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. * 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 anchor; /* Anchor of the list */
static struct linenum_info *freelist; /* Anchor of the unused entries */ static struct linenum_info *freelist; /* Anchor of the unused entries */
static struct linenum_info pool[NPOOL]; /* The pool itself */ static struct linenum_info pool[NPOOL]; /* The pool itself */
static struct linenum_info *spare; /* We always keep one spare entry */ static struct linenum_info *spare; /* We always keep one spare entry */
extern int linenums; extern int linenums;
extern int sigs; extern int sigs;
@ -248,6 +248,8 @@ longish(VOID_PARAM)
static void static void
abort_long(VOID_PARAM) abort_long(VOID_PARAM)
{ {
if (loopcount >= 0)
return;
if (linenums == OPT_ONPLUS) if (linenums == OPT_ONPLUS)
/* /*
* We were displaying line numbers, so need to repaint. * We were displaying line numbers, so need to repaint.
@ -308,6 +310,7 @@ find_linenum(pos)
#if HAVE_TIME #if HAVE_TIME
startime = get_time(); startime = get_time();
#endif #endif
loopcount = 0;
if (p == &anchor || pos - p->prev->pos < p->pos - pos) if (p == &anchor || pos - p->prev->pos < p->pos - pos)
{ {
/* /*
@ -316,7 +319,6 @@ find_linenum(pos)
p = p->prev; p = p->prev;
if (ch_seek(p->pos)) if (ch_seek(p->pos))
return (0); return (0);
loopcount = 0;
for (linenum = p->line, cpos = p->pos; cpos < pos; linenum++) for (linenum = p->line, cpos = p->pos; cpos < pos; linenum++)
{ {
/* /*
@ -348,7 +350,6 @@ find_linenum(pos)
*/ */
if (ch_seek(p->pos)) if (ch_seek(p->pos))
return (0); return (0);
loopcount = 0;
for (linenum = p->line, cpos = p->pos; cpos > pos; linenum--) for (linenum = p->line, cpos = p->pos; cpos > pos; linenum--)
{ {
/* /*
@ -368,7 +369,7 @@ find_linenum(pos)
*/ */
add_lnum(linenum, cpos); add_lnum(linenum, cpos);
} }
loopcount = 0;
return (linenum); return (linenum);
} }

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * 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. * De-initialize the terminal and take out of raw mode.
*/ */
deinit(); deinit();
flush(); /* Make sure the deinit chars get out */ flush(); /* Make sure the deinit chars get out */
raw_mode(0); raw_mode(0);
#if MSDOS_COMPILER==WIN32C #if MSDOS_COMPILER==WIN32C
close_getchr(); close_getchr();
@ -116,11 +116,13 @@ lsystem(cmd, donemsg)
*/ */
inp = dup(0); inp = dup(0);
close(0); close(0);
#if !MSDOS_COMPILER
#if OS2 #if OS2
/* The __open() system call translates "/dev/tty" to "con". */ /* The __open() system call translates "/dev/tty" to "con". */
if (__open("/dev/tty", OPEN_READ) < 0) if (__open(tty_device(), OPEN_READ) < 0)
#else #else
if (open("/dev/tty", OPEN_READ) < 0) if (open(tty_device(), OPEN_READ) < 0)
#endif
#endif #endif
dup(inp); dup(inp);
#endif #endif
@ -169,7 +171,7 @@ lsystem(cmd, donemsg)
* also makes trouble with some DPMI servers). * also makes trouble with some DPMI servers).
*/ */
__djgpp_exception_toggle(); __djgpp_exception_toggle();
system(cmd); system(cmd);
__djgpp_exception_toggle(); __djgpp_exception_toggle();
#else #else
system(cmd); system(cmd);
@ -274,14 +276,14 @@ pipe_mark(c, cmd)
tpos = ch_zero(); tpos = ch_zero();
bpos = position(BOTTOM); bpos = position(BOTTOM);
if (c == '.') if (c == '.')
return (pipe_data(cmd, tpos, bpos)); return (pipe_data(cmd, tpos, bpos));
else if (mpos <= tpos) else if (mpos <= tpos)
return (pipe_data(cmd, mpos, bpos)); return (pipe_data(cmd, mpos, bpos));
else if (bpos == NULL_POSITION) else if (bpos == NULL_POSITION)
return (pipe_data(cmd, tpos, bpos)); return (pipe_data(cmd, tpos, bpos));
else else
return (pipe_data(cmd, tpos, mpos)); return (pipe_data(cmd, tpos, mpos));
} }
/* /*
@ -346,14 +348,14 @@ pipe_data(cmd, spos, epos)
/* /*
* Finish up the last line. * Finish up the last line.
*/ */
while (c != '\n' && c != EOI ) while (c != '\n' && c != EOI )
{ {
c = ch_forw_get(); c = ch_forw_get();
if (c == EOI) if (c == EOI)
break; break;
if (putc(c, f) == EOF) if (putc(c, f) == EOF)
break; break;
} }
pclose(f); pclose(f);

View File

@ -1,6 +1,6 @@
/* $FreeBSD$ */ /* $FreeBSD$ */
/* /*
* Copyright (C) 1984-2020 Mark Nudelman * Copyright (C) 1984-2021 Mark Nudelman
* *
* You may distribute under the terms of either the GNU General Public * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -19,50 +19,49 @@
#include <windows.h> #include <windows.h>
#endif #endif
public char * every_first_cmd = NULL; public char * every_first_cmd = NULL;
public int new_file; public int new_file;
public int is_tty; public int is_tty;
public IFILE curr_ifile = NULL_IFILE; public IFILE curr_ifile = NULL_IFILE;
public IFILE old_ifile = NULL_IFILE; public IFILE old_ifile = NULL_IFILE;
public struct scrpos initial_scrpos; public struct scrpos initial_scrpos;
public int any_display = FALSE; public POSITION start_attnpos = NULL_POSITION;
public POSITION start_attnpos = NULL_POSITION; public POSITION end_attnpos = NULL_POSITION;
public POSITION end_attnpos = NULL_POSITION; public int wscroll;
public int wscroll; public char * progname;
public char * progname; public int quitting;
public int quitting; public int secure;
public int secure; public int dohelp;
public int dohelp;
#if LOGFILE #if LOGFILE
public int logfile = -1; public int logfile = -1;
public int force_logfile = FALSE; public int force_logfile = FALSE;
public char * namelogfile = NULL; public char * namelogfile = NULL;
#endif #endif
#if EDITOR #if EDITOR
public char * editor; public char * editor;
public char * editproto; public char * editproto;
#endif #endif
#if TAGS #if TAGS
extern char * tags; extern char * tags;
extern char * tagoption; extern char * tagoption;
extern int jump_sline; extern int jump_sline;
#endif #endif
#ifdef WIN32 #ifdef WIN32
static char consoleTitle[256]; static char consoleTitle[256];
#endif #endif
public int one_screen; public int one_screen;
extern int less_is_more; extern int less_is_more;
extern int missing_cap; extern int missing_cap;
extern int know_dumb; extern int know_dumb;
extern int no_init; extern int pr_type;
extern int pr_type; extern int quit_if_one_screen;
extern int quit_if_one_screen; extern int no_init;
extern int no_init; extern int errmsgs;
/* /*
@ -84,10 +83,14 @@ main(argc, argv)
progname = *argv++; progname = *argv++;
argc--; argc--;
#if SECURE
secure = 1;
#else
secure = 0; secure = 0;
s = lgetenv("LESSSECURE"); s = lgetenv("LESSSECURE");
if (!isnullenv(s)) if (!isnullenv(s))
secure = 1; secure = 1;
#endif
#ifdef WIN32 #ifdef WIN32
if (getenv("HOME") == NULL) if (getenv("HOME") == NULL)
@ -142,7 +145,7 @@ main(argc, argv)
if (s != NULL) if (s != NULL)
scan_option(save(s)); scan_option(save(s));
#define isoptstring(s) less_is_more ? (((s)[0] == '-') && (s)[1] != '\0') : \ #define isoptstring(s) less_is_more ? (((s)[0] == '-') && (s)[1] != '\0') : \
(((s)[0] == '-' || (s)[0] == '+') && (s)[1] != '\0') (((s)[0] == '-' || (s)[0] == '+') && (s)[1] != '\0')
while (argc > 0 && (isoptstring(*argv) || isoptpending())) while (argc > 0 && (isoptstring(*argv) || isoptpending()))
{ {
@ -228,6 +231,7 @@ main(argc, argv)
* Output is not a tty. * Output is not a tty.
* Just copy the input file(s) to output. * Just copy the input file(s) to output.
*/ */
set_output(1); /* write to stdout */
SET_BINARY(1); SET_BINARY(1);
if (edit_first() == 0) if (edit_first() == 0)
{ {
@ -291,6 +295,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(); init();
commands(); commands();
quit(QUIT_OK); quit(QUIT_OK);
@ -340,7 +356,7 @@ ecalloc(count, size)
skipsp(s) skipsp(s)
char *s; char *s;
{ {
while (*s == ' ' || *s == '\t') while (*s == ' ' || *s == '\t')
s++; s++;
return (s); return (s);
} }
@ -397,10 +413,13 @@ quit(status)
status = save_status; status = save_status;
else else
save_status = status; save_status = status;
#if LESSTEST
rstat('Q');
#endif /*LESSTEST*/
quitting = 1; quitting = 1;
edit((char*)NULL); edit((char*)NULL);
save_cmdhist(); save_cmdhist();
if (any_display && is_tty) if (interactive())
clear_bot(); clear_bot();
deinit(); deinit();
flush(); flush();

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * 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. * Each mark is identified by a lowercase or uppercase letter.
* The final one is lmark, for the "last mark"; addressed by the apostrophe. * 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 NMARKS ((2*26)+2) /* a-z, A-Z, mousemark, lastmark */
#define NUMARKS ((2*26)+1) /* user marks (not lastmark) */ #define NUMARKS ((2*26)+1) /* user marks (not lastmark) */
#define MOUSEMARK (NMARKS-2) #define MOUSEMARK (NMARKS-2)
#define LASTMARK (NMARKS-1) #define LASTMARK (NMARKS-1)
static struct mark marks[NMARKS]; static struct mark marks[NMARKS];
public int marks_modified = 0; public int marks_modified = 0;
@ -116,13 +116,17 @@ mark_get_ifile(m)
getumark(c) getumark(c)
int c; int c;
{ {
PARG parg;
if (c >= 'a' && c <= 'z') if (c >= 'a' && c <= 'z')
return (&marks[c-'a']); return (&marks[c-'a']);
if (c >= 'A' && c <= 'Z') if (c >= 'A' && c <= 'Z')
return (&marks[c-'A'+26]); return (&marks[c-'A'+26]);
if (c == '\'')
return (&marks[LASTMARK]);
if (c == '#') if (c == '#')
return (&marks[MOUSEMARK]); return (&marks[MOUSEMARK]);
error("Invalid mark letter", NULL_PARG); parg.p_char = (char) c;
error("Invalid mark letter %c", &parg);
return (NULL); return (NULL);
} }
@ -259,6 +263,7 @@ lastmark(VOID_PARAM)
if (scrpos.pos == NULL_POSITION) if (scrpos.pos == NULL_POSITION)
return; return;
cmark(&marks[LASTMARK], curr_ifile, scrpos.pos, scrpos.ln); cmark(&marks[LASTMARK], curr_ifile, scrpos.pos, scrpos.ln);
marks_modified = 1;
} }
/* /*
@ -370,7 +375,7 @@ mark_check_ifile(ifile)
IFILE ifile; IFILE ifile;
{ {
int i; int i;
char *filename = lrealpath(get_filename(ifile)); char *filename = get_real_filename(ifile);
for (i = 0; i < NMARKS; i++) for (i = 0; i < NMARKS; i++)
{ {
@ -384,7 +389,6 @@ mark_check_ifile(ifile)
free(mark_filename); free(mark_filename);
} }
} }
free(filename);
} }
#if CMD_HISTORY #if CMD_HISTORY
@ -403,7 +407,7 @@ save_marks(fout, hdr)
return; return;
fprintf(fout, "%s\n", hdr); fprintf(fout, "%s\n", hdr);
for (i = 0; i < NUMARKS; i++) for (i = 0; i < NMARKS; i++)
{ {
char *filename; char *filename;
struct mark *m = &marks[i]; struct mark *m = &marks[i];
@ -413,12 +417,10 @@ save_marks(fout, hdr)
postoa(m->m_scrpos.pos, pos_str); postoa(m->m_scrpos.pos, pos_str);
filename = m->m_filename; filename = m->m_filename;
if (filename == NULL) if (filename == NULL)
filename = get_filename(m->m_ifile); filename = get_real_filename(m->m_ifile);
filename = lrealpath(filename);
if (strcmp(filename, "-") != 0) if (strcmp(filename, "-") != 0)
fprintf(fout, "m %c %d %s %s\n", fprintf(fout, "m %c %d %s %s\n",
m->m_letter, m->m_scrpos.ln, pos_str, filename); m->m_letter, m->m_scrpos.ln, pos_str, filename);
free(filename);
} }
} }

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * 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 * Each handling function is passed a "type" and, if it is a string
* option, the string which should be "assigned" to the option. * option, the string which should be "assigned" to the option.
* The type may be one of: * The type may be one of:
* INIT The option is being initialized from the command line. * INIT The option is being initialized from the command line.
* TOGGLE The option is being changed from within the program. * TOGGLE The option is being changed from within the program.
* QUERY The setting of the option is merely being queried. * QUERY The setting of the option is merely being queried.
*/ */
#include "less.h" #include "less.h"
@ -36,7 +36,7 @@ extern int sc_width;
extern int sc_height; extern int sc_height;
extern int secure; extern int secure;
extern int dohelp; extern int dohelp;
extern int any_display; extern int is_tty;
extern char openquote; extern char openquote;
extern char closequote; extern char closequote;
extern char *prproto[]; extern char *prproto[];
@ -55,6 +55,9 @@ extern int rscroll_attr;
extern int mousecap; extern int mousecap;
extern int wheel_lines; extern int wheel_lines;
extern int less_is_more; extern int less_is_more;
extern int linenum_width;
extern int status_col_width;
extern int use_color;
#if LOGFILE #if LOGFILE
extern char *namelogfile; extern char *namelogfile;
extern int force_logfile; extern int force_logfile;
@ -65,6 +68,10 @@ public char *tagoption = NULL;
extern char *tags; extern char *tags;
extern char ztags[]; extern char ztags[];
#endif #endif
#if LESSTEST
extern char *ttyin_name;
extern int rstat_file;
#endif /*LESSTEST*/
#if MSDOS_COMPILER #if MSDOS_COMPILER
extern int nm_fg_color, nm_bg_color; extern int nm_fg_color, nm_bg_color;
extern int bo_fg_color, bo_bg_color; extern int bo_fg_color, bo_bg_color;
@ -395,13 +402,13 @@ opt_p(type, s)
} else } else
{ {
plusoption = TRUE; plusoption = TRUE;
ungetcc(CHAR_END_COMMAND);
ungetsc(s);
/* /*
* {{ This won't work if the "/" command is * {{ This won't work if the "/" command is
* changed or invalidated by a .lesskey file. }} * changed or invalidated by a .lesskey file. }}
*/ */
ungetsc("/"); ungetsc("/");
ungetsc(s);
ungetcc_back(CHAR_END_COMMAND);
} }
break; break;
} }
@ -427,13 +434,13 @@ opt__P(type, s)
*/ */
switch (*s) switch (*s)
{ {
case 's': proto = &prproto[PR_SHORT]; s++; break; case 's': proto = &prproto[PR_SHORT]; s++; break;
case 'm': proto = &prproto[PR_MEDIUM]; s++; break; case 'm': proto = &prproto[PR_MEDIUM]; s++; break;
case 'M': proto = &prproto[PR_LONG]; s++; break; case 'M': proto = &prproto[PR_LONG]; s++; break;
case '=': proto = &eqproto; s++; break; case '=': proto = &eqproto; s++; break;
case 'h': proto = &hproto; s++; break; case 'h': proto = &hproto; s++; break;
case 'w': proto = &wproto; s++; break; case 'w': proto = &wproto; s++; break;
default: proto = &prproto[PR_SHORT]; break; default: proto = &prproto[PR_SHORT]; break;
} }
free(*proto); free(*proto);
*proto = save(s); *proto = save(s);
@ -504,20 +511,28 @@ opt__V(type, s)
dispversion(); dispversion();
break; break;
case INIT: case INIT:
/* set_output(1); /* Force output to stdout per GNU standard for --version output. */
* Force output to stdout per GNU standard for --version output.
*/
any_display = 1;
putstr("less "); putstr("less ");
putstr(version); putstr(version);
putstr(" ("); putstr(" (");
putstr(pattern_lib_name()); putstr(pattern_lib_name());
putstr(" regular expressions)\n"); 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("less comes with NO WARRANTY, to the extent permitted by law.\n");
putstr("For information about the terms of redistribution,\n"); putstr("For information about the terms of redistribution,\n");
putstr("see the file named README in the less distribution.\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); quit(QUIT_OK);
break; break;
} }
@ -527,60 +542,70 @@ opt__V(type, s)
/* /*
* Parse an MSDOS color descriptor. * Parse an MSDOS color descriptor.
*/ */
static void static void
colordesc(s, fg_color, bg_color) colordesc(s, fg_color, bg_color)
char *s; char *s;
int *fg_color; int *fg_color;
int *bg_color; int *bg_color;
{ {
int fg, bg; int fg, bg;
int err;
#if MSDOS_COMPILER==WIN32C #if MSDOS_COMPILER==WIN32C
int ul = 0; int ul = 0;
if (*s == 'u') if (*s == 'u')
{ {
ul = COMMON_LVB_UNDERSCORE; 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++; s++;
bg = getnum(&s, "D", &err); if (*s == '\0')
if (err)
{ {
error("Missing bg color in -D", NULL_PARG); *fg_color = nm_fg_color | ul;
*bg_color = nm_bg_color;
return; return;
} }
} }
#if MSDOS_COMPILER==WIN32C
if (*s == 'u')
{
ul = COMMON_LVB_UNDERSCORE;
++s;
}
fg |= ul;
#endif #endif
if (*s != '\0') if (parse_color(s, &fg, &bg) == CT_NULL)
error("Extra characters at end of -D option", NULL_PARG); {
*fg_color = fg; PARG p;
*bg_color = bg; 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; char *s;
{ {
PARG p; PARG p;
int attr;
switch (type) switch (type)
{ {
case INIT: case INIT:
case TOGGLE: 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; sgr_mode = !sgr_mode;
break; 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); p.p_char = s[0];
at_exit(); 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; break;
#if MSDOS_COMPILER
case QUERY: case QUERY:
p.p_string = (sgr_mode) ? "on" : "off"; p.p_string = (sgr_mode) ? "on" : "off";
error("SGR mode is %s", &p); error("SGR mode is %s", &p);
break; break;
#endif
} }
} }
#endif
/* /*
* Handler for the -x option. * Handler for the -x option.
@ -759,7 +811,7 @@ opt_rscroll(type, s)
} else } else
{ {
rscroll_char = *fmt ? *fmt : '>'; rscroll_char = *fmt ? *fmt : '>';
rscroll_attr = attr; rscroll_attr = attr|AT_COLOR_RSCROLL;
} }
break; } break; }
case QUERY: { 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. * Get the "screen window" size.
*/ */

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -23,8 +23,7 @@
static struct loption *pendopt; static struct loption *pendopt;
public int plusoption = FALSE; public int plusoption = FALSE;
static char *optstring LESSPARAMS((char *s, char **p_str, char *printopt, static char *optstring LESSPARAMS((char *s, char **p_str, char *printopt, char *validchars));
char *validchars));
static int flip_triple LESSPARAMS((int val, int lc)); static int flip_triple LESSPARAMS((int val, int lc));
extern int screen_trashed; extern int screen_trashed;
@ -157,8 +156,8 @@ scan_option(s)
every_first_cmd = save(str+1); every_first_cmd = save(str+1);
} else } else
{ {
ungetcc(CHAR_END_COMMAND);
ungetsc(str); ungetsc(str);
ungetcc_back(CHAR_END_COMMAND);
} }
free(str); free(str);
continue; continue;
@ -297,10 +296,10 @@ scan_option(s)
* Toggle command line flags from within the program. * Toggle command line flags from within the program.
* Used by the "-" and "_" commands. * Used by the "-" and "_" commands.
* how_toggle may be: * how_toggle may be:
* OPT_NO_TOGGLE just report the current setting, without changing it. * OPT_NO_TOGGLE just report the current setting, without changing it.
* OPT_TOGGLE invert the current setting * OPT_TOGGLE invert the current setting
* OPT_UNSET set to the default value * OPT_UNSET set to the default value
* OPT_SET set to the inverse of the default value * OPT_SET set to the inverse of the default value
*/ */
public void public void
toggle_option(o, lower, s, how_toggle) toggle_option(o, lower, s, how_toggle)
@ -384,10 +383,10 @@ toggle_option(o, lower, s, how_toggle)
case TRIPLE: case TRIPLE:
/* /*
* Triple: * Triple:
* If user gave the lower case letter, then switch * If user gave the lower case letter, then switch
* to 1 unless already 1, in which case make it 0. * to 1 unless already 1, in which case make it 0.
* If user gave the upper case letter, then switch * If user gave the upper case letter, then switch
* to 2 unless already 2, in which case make it 0. * to 2 unless already 2, in which case make it 0.
*/ */
switch (how_toggle) switch (how_toggle)
{ {
@ -405,7 +404,7 @@ toggle_option(o, lower, s, how_toggle)
case STRING: case STRING:
/* /*
* String: don't do anything here. * String: don't do anything here.
* The handling function will do everything. * The handling function will do everything.
*/ */
switch (how_toggle) switch (how_toggle)
{ {

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * 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. * Types of options.
*/ */
#define BOOL 01 /* Boolean option: 0 or 1 */ #define BOOL 01 /* Boolean option: 0 or 1 */
#define TRIPLE 02 /* Triple-valued option: 0, 1 or 2 */ #define TRIPLE 02 /* Triple-valued option: 0, 1 or 2 */
#define NUMBER 04 /* Numeric option */ #define NUMBER 04 /* Numeric option */
#define STRING 010 /* String-valued option */ #define STRING 010 /* String-valued option */
#define NOVAR 020 /* No associated variable */ #define NOVAR 020 /* No associated variable */
#define REPAINT 040 /* Repaint screen after toggling option */ #define REPAINT 040 /* Repaint screen after toggling option */
#define NO_TOGGLE 0100 /* Option cannot be toggled with "-" cmd */ #define NO_TOGGLE 0100 /* Option cannot be toggled with "-" cmd */
#define HL_REPAINT 0200 /* Repaint hilites after toggling option */ #define HL_REPAINT 0200 /* Repaint hilites after toggling option */
#define NO_QUERY 0400 /* Option cannot be queried with "_" cmd */ #define NO_QUERY 0400 /* Option cannot be queried with "_" cmd */
#define INIT_HANDLER 01000 /* Call option handler function at startup */ #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 */ #define OLETTER_NONE '\1' /* Invalid option letter */
/* /*
* Argument to a handling function tells what type of activity: * Argument to a handling function tells what type of activity:
*/ */
#define INIT 0 /* Initialization (from command line) */ #define INIT 0 /* Initialization (from command line) */
#define QUERY 1 /* Query (from _ or - command) */ #define QUERY 1 /* Query (from _ or - command) */
#define TOGGLE 2 /* Change value (from - command) */ #define TOGGLE 2 /* Change value (from - command) */
/* Flag to toggle_option to specify how to "toggle" */ /* Flag to toggle_option to specify how to "toggle" */
#define OPT_NO_TOGGLE 0 #define OPT_NO_TOGGLE 0
#define OPT_TOGGLE 1 #define OPT_TOGGLE 1
#define OPT_UNSET 2 #define OPT_UNSET 2
#define OPT_SET 3 #define OPT_SET 3
#define OPT_NO_PROMPT 0100 #define OPT_NO_PROMPT 0100
/* Error code from findopt_name */ /* Error code from findopt_name */
#define OPT_AMBIG 1 #define OPT_AMBIG 1
struct optname struct optname
{ {
char *oname; /* Long (GNU-style) option name */ char *oname; /* Long (GNU-style) option name */
struct optname *onext; /* List of synonymous option names */ 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 struct loption
{ {
char oletter; /* The controlling letter (a-z) */ char oletter; /* The controlling letter (a-z) */
struct optname *onames; /* Long (GNU-style) option name */ struct optname *onames; /* Long (GNU-style) option name */
int otype; /* Type of the option */ int otype; /* Type of the option */
int odefault; /* Default value */ int odefault; /* Default value */
int *ovar; /* Pointer to the associated variable */ int *ovar; /* Pointer to the associated variable */
void (*ofunc) LESSPARAMS ((int, char*)); /* Pointer to special handling function */ void (*ofunc) LESSPARAMS ((int, char*)); /* Pointer to special handling function */
char *odesc[3]; /* Description of each value */ char *odesc[3]; /* Description of each value */
}; };

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -18,52 +18,56 @@
/* /*
* Variables controlled by command line options. * Variables controlled by command line options.
*/ */
public int quiet; /* Should we suppress the audible bell? */ public int quiet; /* Should we suppress the audible bell? */
public int how_search; /* Where should forward searches start? */ public int how_search; /* Where should forward searches start? */
public int top_scroll; /* Repaint screen from top? public int top_scroll; /* Repaint screen from top?
(alternative is scroll from bottom) */ (alternative is scroll from bottom) */
public int pr_type; /* Type of prompt (short, medium, long) */ public int pr_type; /* Type of prompt (short, medium, long) */
public int bs_mode; /* How to process backspaces */ public int bs_mode; /* How to process backspaces */
public int know_dumb; /* Don't complain about dumb terminals */ 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_at_eof; /* Quit after hitting end of file twice */
public int quit_if_one_screen; /* Quit if EOF on first screen */ public int quit_if_one_screen; /* Quit if EOF on first screen */
public int squeeze; /* Squeeze multiple blank lines into one */ public int squeeze; /* Squeeze multiple blank lines into one */
public int tabstop; /* Tab settings */ public int tabstop; /* Tab settings */
public int back_scroll; /* Repaint screen on backwards movement */ public int back_scroll; /* Repaint screen on backwards movement */
public int forw_scroll; /* Repaint screen on forward movement */ public int forw_scroll; /* Repaint screen on forward movement */
public int caseless; /* Do "caseless" searches */ public int caseless; /* Do "caseless" searches */
public int linenums; /* Use line numbers */ public int linenums; /* Use line numbers */
public int autobuf; /* Automatically allocate buffers as needed */ public int autobuf; /* Automatically allocate buffers as needed */
public int bufspace; /* Max buffer space per file (K) */ public int bufspace; /* Max buffer space per file (K) */
public int ctldisp; /* Send control chars to screen untranslated */ public int ctldisp; /* Send control chars to screen untranslated */
public int force_open; /* Open the file even if not regular file */ public int force_open; /* Open the file even if not regular file */
public int swindow; /* Size of scrolling window */ public int swindow; /* Size of scrolling window */
public int jump_sline; /* Screen line of "jump target" */ public int jump_sline; /* Screen line of "jump target" */
public long jump_sline_fraction = -1; public long jump_sline_fraction = -1;
public long shift_count_fraction = -1; public long shift_count_fraction = -1;
public int chopline; /* Truncate displayed lines at screen width */ public int chopline; /* Truncate displayed lines at screen width */
public int no_init; /* Disable sending ti/te termcap strings */ public int no_init; /* Disable sending ti/te termcap strings */
public int no_keypad; /* Disable sending ks/ke termcap strings */ public int no_keypad; /* Disable sending ks/ke termcap strings */
public int twiddle; /* Show tildes after EOF */ public int twiddle; /* Show tildes after EOF */
public int show_attn; /* Hilite first unread line */ public int show_attn; /* Hilite first unread line */
public int shift_count; /* Number of positions to shift horizontally */ public int shift_count; /* Number of positions to shift horizontally */
public int status_col; /* Display a status column */ public int status_col; /* Display a status column */
public int use_lessopen; /* Use the LESSOPEN filter */ public int use_lessopen; /* Use the LESSOPEN filter */
public int quit_on_intr; /* Quit on interrupt */ public int quit_on_intr; /* Quit on interrupt */
public int follow_mode; /* F cmd Follows file desc or file name? */ public int follow_mode; /* F cmd Follows file desc or file name? */
public int oldbot; /* Old bottom of screen behavior {{REMOVE}} */ public int oldbot; /* Old bottom of screen behavior {{REMOVE}} */
public int opt_use_backslash; /* Use backslash escaping in option parsing */ public int opt_use_backslash; /* Use backslash escaping in option parsing */
public char rscroll_char; /* Char which marks chopped lines with -S */ public char rscroll_char; /* Char which marks chopped lines with -S */
public int rscroll_attr; /* Attribute of rscroll_char */ public int rscroll_attr; /* Attribute of rscroll_char */
public int no_hist_dups; /* Remove dups from history list */ public int no_hist_dups; /* Remove dups from history list */
public int mousecap; /* Allow mouse for scrolling */ public int mousecap; /* Allow mouse for scrolling */
public int wheel_lines; /* Number of lines to scroll on mouse wheel scroll */ public int wheel_lines; /* Number of lines to scroll on mouse wheel scroll */
public int perma_marks; /* Save marks in history file */ 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 #if HILITE_SEARCH
public int hilite_search; /* Highlight matched search patterns? */ public int hilite_search; /* Highlight matched search patterns? */
#endif #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. * 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 B__optname = { "auto-buffers", NULL };
static struct optname c_optname = { "clear-screen", NULL }; static struct optname c_optname = { "clear-screen", NULL };
static struct optname d_optname = { "dumb", NULL }; static struct optname d_optname = { "dumb", NULL };
#if MSDOS_COMPILER
static struct optname D__optname = { "color", NULL }; static struct optname D__optname = { "color", NULL };
#endif
static struct optname e_optname = { "quit-at-eof", NULL }; static struct optname e_optname = { "quit-at-eof", NULL };
static struct optname f_optname = { "force", NULL }; static struct optname f_optname = { "force", NULL };
static struct optname F__optname = { "quit-if-one-screen", 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 nohistdups_optname = { "no-histdups", NULL };
static struct optname mousecap_optname = { "mouse", NULL }; static struct optname mousecap_optname = { "mouse", NULL };
static struct optname wheel_lines_optname = { "wheel-lines", 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 NULL
} }
}, },
#if MSDOS_COMPILER
{ 'D', &D__optname, { 'D', &D__optname,
STRING|REPAINT, 0, NULL, opt_D, STRING|REPAINT|NO_QUERY, 0, NULL, opt_D,
{ {
"color desc: ", "color desc: ",
"Dadknsu0123456789.", NULL,
NULL NULL
} }
}, },
#endif
{ 'e', &e_optname, { 'e', &e_optname,
TRIPLE, OPT_OFF, &quit_at_eof, NULL, TRIPLE, OPT_OFF, &quit_at_eof, NULL,
{ {
@ -503,6 +511,56 @@ static struct loption option[] =
NULL 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 } } { '\0', NULL, NOVAR, 0, NULL, NULL, { NULL, NULL, NULL } }
}; };

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -23,6 +23,9 @@
#include "less.h" #include "less.h"
#include <signal.h> #include <signal.h>
#include <setjmp.h> #include <setjmp.h>
#if MSDOS_COMPILER==WIN32C
#include <windows.h>
#endif
#if HAVE_TIME_H #if HAVE_TIME_H
#include <time.h> #include <time.h>
#endif #endif
@ -33,6 +36,15 @@
#include <values.h> #include <values.h>
#endif #endif
#if HAVE_POLL && !MSDOS_COMPILER && !defined(__APPLE__)
#define USE_POLL 1
#else
#define USE_POLL 0
#endif
#if USE_POLL
#include <poll.h>
#endif
/* /*
* BSD setjmp() saves (and longjmp() restores) the signal mask. * BSD setjmp() saves (and longjmp() restores) the signal mask.
* This costs a system call or two per setjmp(), so if possible we clear the * 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(). * _setjmp() does not exist; we just use setjmp().
*/ */
#if HAVE__SETJMP && HAVE_SIGSETMASK #if HAVE__SETJMP && HAVE_SIGSETMASK
#define SET_JUMP _setjmp #define SET_JUMP _setjmp
#define LONG_JUMP _longjmp #define LONG_JUMP _longjmp
#else #else
#define SET_JUMP setjmp #define SET_JUMP setjmp
#define LONG_JUMP longjmp #define LONG_JUMP longjmp
#endif #endif
public int reading; public int reading;
@ -53,6 +65,27 @@ public int reading;
static jmp_buf read_label; static jmp_buf read_label;
extern int sigs; 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. * 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) if (select(fd+1, &readfds, 0, 0, 0) == -1)
return (-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 #endif
n = read(fd, buf, len); n = read(fd, buf, len);
#if 1 #if 1
@ -135,7 +191,6 @@ iread(fd, buf, len)
* start returning 0 forever, instead of -1. * start returning 0 forever, instead of -1.
*/ */
{ {
extern int ignore_eoi;
if (!ignore_eoi) if (!ignore_eoi)
{ {
static int consecutive_nulls = 0; static int consecutive_nulls = 0;
@ -204,18 +259,16 @@ get_time(VOID_PARAM)
strerror(err) strerror(err)
int err; int err;
{ {
#if HAVE_SYS_ERRLIST
static char buf[16]; static char buf[16];
#if HAVE_SYS_ERRLIST
extern char *sys_errlist[]; extern char *sys_errlist[];
extern int sys_nerr; extern int sys_nerr;
if (err < sys_nerr) if (err < sys_nerr)
return sys_errlist[err]; return sys_errlist[err];
#endif
sprintf(buf, "Error %d", err); sprintf(buf, "Error %d", err);
return buf; return buf;
#else
return ("cannot open");
#endif
} }
#endif #endif
@ -356,3 +409,24 @@ isatty(f)
} }
#endif #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
}

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -20,7 +20,7 @@
#endif #endif
#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 need_clr;
public int final_attr; public int final_attr;
public int at_prompt; public int at_prompt;
@ -29,7 +29,6 @@ extern int sigs;
extern int sc_width; extern int sc_width;
extern int so_s_width, so_e_width; extern int so_s_width, so_e_width;
extern int screen_trashed; extern int screen_trashed;
extern int any_display;
extern int is_tty; extern int is_tty;
extern int oldbot; 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 bl_fg_color, bl_bg_color;
extern int sgr_mode; extern int sgr_mode;
#if MSDOS_COMPILER==WIN32C #if MSDOS_COMPILER==WIN32C
extern int have_ul; extern int vt_enabled;
#endif #endif
#endif #endif
@ -82,6 +81,269 @@ put_line(VOID_PARAM)
static char obuf[OUTBUF_SIZE]; static char obuf[OUTBUF_SIZE];
static char *ob = obuf; 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. * Flush buffered output.
@ -103,293 +365,44 @@ static char *ob = obuf;
flush(VOID_PARAM) flush(VOID_PARAM)
{ {
int n; int n;
int fd;
n = (int) (ob - obuf); n = (int) (ob - obuf);
if (n == 0) if (n == 0)
return; return;
ob = obuf;
#if MSDOS_COMPILER==MSOFTC #if MSDOS_COMPILER==MSOFTC
if (is_tty && any_display) if (interactive())
{ {
*ob = '\0'; obuf[n] = '\0';
_outtext(obuf); _outtext(obuf);
ob = obuf;
return; return;
} }
#else #else
#if MSDOS_COMPILER==WIN32C || MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC #if MSDOS_COMPILER==WIN32C || MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC
if (is_tty && any_display) if (interactive())
{ {
ob = obuf + n;
*ob = '\0'; *ob = '\0';
if (ctldisp != OPT_ONPLUS) win_flush();
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;
return; return;
} }
#endif #endif
#endif #endif
fd = (any_display) ? 1 : 2;
if (write(fd, obuf, n) != n) if (write(outfd, obuf, n) != n)
screen_trashed = 1; 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; \ char **ebuf; \
{ \ { \
type val = 0; \ type val = 0; \
for (;;) { \ for (;; buf++) { \
char c = *buf++; \ char c = *buf; \
if (c < '0' || c > '9') break; \ if (c < '0' || c > '9') break; \
val = 10 * val + c - '0'; \ val = 10 * val + c - '0'; \
} \ } \
@ -534,8 +547,11 @@ iprint_linenum(num)
/* /*
* This function implements printf-like functionality * This function implements printf-like functionality
* using a more portable argument list mechanism than printf's. * 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) less_printf(fmt, parg)
char *fmt; char *fmt;
PARG *parg; PARG *parg;
@ -572,6 +588,10 @@ less_printf(fmt, parg)
col += iprint_linenum(parg->p_linenum); col += iprint_linenum(parg->p_linenum);
parg++; parg++;
break; break;
case 'c':
putchr(parg->p_char);
col++;
break;
case '%': case '%':
putchr('%'); putchr('%');
break; break;
@ -615,24 +635,20 @@ error(fmt, parg)
errmsgs++; errmsgs++;
if (any_display && is_tty) if (!interactive())
{
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))
{ {
less_printf(fmt, parg);
putchr('\n'); putchr('\n');
return; 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); putstr(return_to_continue);
at_exit(); at_exit();
col += sizeof(return_to_continue) + so_e_width; col += sizeof(return_to_continue) + so_e_width;
@ -667,7 +683,7 @@ ierror(fmt, parg)
{ {
at_exit(); at_exit();
clear_bot(); clear_bot();
at_enter(AT_STANDOUT); at_enter(AT_STANDOUT|AT_COLOR_ERROR);
(void) less_printf(fmt, parg); (void) less_printf(fmt, parg);
putstr(intr_to_abort); putstr(intr_to_abort);
at_exit(); at_exit();
@ -687,22 +703,24 @@ query(fmt, parg)
int c; int c;
int col = 0; int col = 0;
if (any_display && is_tty) if (interactive())
clear_bot(); clear_bot();
(void) less_printf(fmt, parg); (void) less_printf(fmt, parg);
c = getchr(); c = getchr();
if (!(any_display && is_tty)) if (interactive())
{
lower_left();
if (col >= sc_width)
screen_trashed = 1;
flush();
} else
{ {
putchr('\n'); putchr('\n');
return (c);
} }
lower_left(); if (c == 'Q')
if (col >= sc_width) quit(QUIT_OK);
screen_trashed = 1;
flush();
return (c); return (c);
} }

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * 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. * Like compile_pattern2, but convert the pattern to lowercase if necessary.
*/ */
public int public int
compile_pattern(pattern, search_type, comp_pattern) compile_pattern(pattern, search_type, show_error, comp_pattern)
char *pattern; char *pattern;
int search_type; int search_type;
int show_error;
PATTERN_TYPE *comp_pattern; PATTERN_TYPE *comp_pattern;
{ {
char *cvt_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_pattern = (char*) ecalloc(1, cvt_length(strlen(pattern), CVT_TO_LC));
cvt_text(cvt_pattern, pattern, (int *)NULL, (int *)NULL, 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) if (cvt_pattern != pattern)
free(cvt_pattern); free(cvt_pattern);
return (result); return (result);
@ -214,6 +215,7 @@ uncompile_pattern(pattern)
#endif #endif
} }
#if 0
/* /*
* Can a pattern be successfully compiled? * Can a pattern be successfully compiled?
*/ */
@ -224,13 +226,14 @@ valid_pattern(pattern)
PATTERN_TYPE comp_pattern; PATTERN_TYPE comp_pattern;
int result; int result;
CLEAR_PATTERN(comp_pattern); SET_NULL_PATTERN(comp_pattern);
result = compile_pattern2(pattern, 0, &comp_pattern, 0); result = compile_pattern2(pattern, 0, &comp_pattern, 0);
if (result != 0) if (result != 0)
return (0); return (0);
uncompile_pattern(&comp_pattern); uncompile_pattern(&comp_pattern);
return (1); return (1);
} }
#endif
/* /*
* Is a compiled pattern null? * Is a compiled pattern null?

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -11,7 +11,7 @@
#define __USE_GNU 1 #define __USE_GNU 1
#include <regex.h> #include <regex.h>
#define PATTERN_TYPE struct re_pattern_buffer * #define PATTERN_TYPE struct re_pattern_buffer *
#define CLEAR_PATTERN(name) name = NULL #define SET_NULL_PATTERN(name) name = NULL
#endif #endif
#if HAVE_POSIX_REGCOMP #if HAVE_POSIX_REGCOMP
@ -23,27 +23,27 @@ extern int less_is_more;
#define REGCOMP_FLAG 0 #define REGCOMP_FLAG 0
#endif #endif
#define PATTERN_TYPE regex_t * #define PATTERN_TYPE regex_t *
#define CLEAR_PATTERN(name) name = NULL #define SET_NULL_PATTERN(name) name = NULL
#endif #endif
#if HAVE_PCRE #if HAVE_PCRE
#include <pcre.h> #include <pcre.h>
#define PATTERN_TYPE pcre * #define PATTERN_TYPE pcre *
#define CLEAR_PATTERN(name) name = NULL #define SET_NULL_PATTERN(name) name = NULL
#endif #endif
#if HAVE_PCRE2 #if HAVE_PCRE2
#define PCRE2_CODE_UNIT_WIDTH 8 #define PCRE2_CODE_UNIT_WIDTH 8
#include <pcre2.h> #include <pcre2.h>
#define PATTERN_TYPE pcre2_code * #define PATTERN_TYPE pcre2_code *
#define CLEAR_PATTERN(name) name = NULL #define SET_NULL_PATTERN(name) name = NULL
#endif #endif
#if HAVE_RE_COMP #if HAVE_RE_COMP
char *re_comp LESSPARAMS ((char*)); char *re_comp LESSPARAMS ((char*));
int re_exec LESSPARAMS ((char*)); int re_exec LESSPARAMS ((char*));
#define PATTERN_TYPE int #define PATTERN_TYPE int
#define CLEAR_PATTERN(name) name = 0 #define SET_NULL_PATTERN(name) name = 0
#endif #endif
#if HAVE_REGCMP #if HAVE_REGCMP
@ -51,17 +51,17 @@ char *regcmp LESSPARAMS ((char*));
char *regex LESSPARAMS ((char**, char*)); char *regex LESSPARAMS ((char**, char*));
extern char *__loc1; extern char *__loc1;
#define PATTERN_TYPE char ** #define PATTERN_TYPE char **
#define CLEAR_PATTERN(name) name = NULL #define SET_NULL_PATTERN(name) name = NULL
#endif #endif
#if HAVE_V8_REGCOMP #if HAVE_V8_REGCOMP
#include "regexp.h" #include "regexp.h"
extern int reg_show_error; extern int reg_show_error;
#define PATTERN_TYPE struct regexp * #define PATTERN_TYPE struct regexp *
#define CLEAR_PATTERN(name) name = NULL #define SET_NULL_PATTERN(name) name = NULL
#endif #endif
#if NO_REGEX #if NO_REGEX
#define PATTERN_TYPE void * #define PATTERN_TYPE void *
#define CLEAR_PATTERN(name) #define SET_NULL_PATTERN(name)
#endif #endif

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * 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, * 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. * where the first byte is 0 and the second is as defined below.
*/ */
#define PCK_SHIFT_TAB '\017' #define PCK_SHIFT_TAB '\017'
#define PCK_ALT_E '\022' #define PCK_ALT_E '\022'
#define PCK_CAPS_LOCK '\072' #define PCK_CAPS_LOCK '\072'
#define PCK_F1 '\073' #define PCK_F1 '\073'
#define PCK_NUM_LOCK '\105' #define PCK_NUM_LOCK '\105'
#define PCK_HOME '\107' #define PCK_HOME '\107'
#define PCK_UP '\110' #define PCK_UP '\110'
#define PCK_PAGEUP '\111' #define PCK_PAGEUP '\111'
#define PCK_LEFT '\113' #define PCK_LEFT '\113'
#define PCK_RIGHT '\115' #define PCK_RIGHT '\115'
#define PCK_END '\117' #define PCK_END '\117'
#define PCK_DOWN '\120' #define PCK_DOWN '\120'
#define PCK_PAGEDOWN '\121' #define PCK_PAGEDOWN '\121'
#define PCK_INSERT '\122' #define PCK_INSERT '\122'
#define PCK_DELETE '\123' #define PCK_DELETE '\123'
#define PCK_CTL_LEFT '\163' #define PCK_CTL_LEFT '\163'
#define PCK_CTL_RIGHT '\164' #define PCK_CTL_RIGHT '\164'
#define PCK_CTL_DELETE '\223' #define PCK_CTL_DELETE '\223'

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -21,7 +21,7 @@
#include "less.h" #include "less.h"
#include "position.h" #include "position.h"
static POSITION *table = NULL; /* The position table */ static POSITION *table = NULL; /* The position table */
static int table_size = 0; static int table_size = 0;
extern int sc_width, sc_height; 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. * 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 * The line may be specified as a line number relative to the top
* of the screen, but is usually one of these special cases: * of the screen, but is usually one of these special cases:
* the top (first) line on the screen * the top (first) line on the screen
* the second line on the screen * the second line on the screen
* the bottom line on the screen * the bottom line on the screen
* the line after the bottom line on the screen * the line after the bottom line on the screen
*/ */
public POSITION public POSITION
position(sindex) position(sindex)

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -11,8 +11,8 @@
/* /*
* Include file for interfacing to position.c modules. * Include file for interfacing to position.c modules.
*/ */
#define TOP (0) #define TOP (0)
#define TOP_PLUS_ONE (1) #define TOP_PLUS_ONE (1)
#define BOTTOM (-1) #define BOTTOM (-1)
#define BOTTOM_PLUS_ONE (-2) #define BOTTOM_PLUS_ONE (-2)
#define MIDDLE (-3) #define MIDDLE (-3)

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * 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. * Append a line number to the end of the message.
*/ */
static void static void
ap_linenum(linenum) ap_linenum(linenum)
LINENUM linenum; LINENUM linenum;
{ {
@ -187,48 +187,48 @@ cond(c, where)
switch (c) switch (c)
{ {
case 'a': /* Anything in the message yet? */ case 'a': /* Anything in the message yet? */
return (mp > message); return (mp > message);
case 'b': /* Current byte offset known? */ case 'b': /* Current byte offset known? */
return (curr_byte(where) != NULL_POSITION); return (curr_byte(where) != NULL_POSITION);
case 'c': case 'c':
return (hshift != 0); return (hshift != 0);
case 'e': /* At end of file? */ case 'e': /* At end of file? */
return (eof_displayed()); return (eof_displayed());
case 'f': /* Filename known? */ case 'f': /* Filename known? */
case 'g': case 'g':
return (strcmp(get_filename(curr_ifile), "-") != 0); return (strcmp(get_filename(curr_ifile), "-") != 0);
case 'l': /* Line number known? */ case 'l': /* Line number known? */
case 'd': /* Same as l */ case 'd': /* Same as l */
if (!linenums) if (!linenums)
return 0; return 0;
return (currline(where) != 0); return (currline(where) != 0);
case 'L': /* Final line number known? */ case 'L': /* Final line number known? */
case 'D': /* Final page number known? */ case 'D': /* Final page number known? */
return (linenums && ch_length() != NULL_POSITION); return (linenums && ch_length() != NULL_POSITION);
case 'm': /* More than one file? */ case 'm': /* More than one file? */
#if TAGS #if TAGS
return (ntags() ? (ntags() > 1) : (nifile() > 1)); return (ntags() ? (ntags() > 1) : (nifile() > 1));
#else #else
return (nifile() > 1); return (nifile() > 1);
#endif #endif
case 'n': /* First prompt in a new file? */ case 'n': /* First prompt in a new file? */
#if TAGS #if TAGS
return (ntags() ? 1 : new_file); return (ntags() ? 1 : new_file);
#else #else
return (new_file); return (new_file);
#endif #endif
case 'p': /* Percent into file (bytes) known? */ case 'p': /* Percent into file (bytes) known? */
return (curr_byte(where) != NULL_POSITION && return (curr_byte(where) != NULL_POSITION &&
ch_length() > 0); ch_length() > 0);
case 'P': /* Percent into file (lines) known? */ case 'P': /* Percent into file (lines) known? */
return (currline(where) != 0 && return (currline(where) != 0 &&
(len = ch_length()) > 0 && (len = ch_length()) > 0 &&
find_linenum(len) != 0); find_linenum(len) != 0);
case 's': /* Size of file known? */ case 's': /* Size of file known? */
case 'B': case 'B':
return (ch_length() != NULL_POSITION); return (ch_length() != NULL_POSITION);
case 'x': /* Is there a "next" file? */ case 'x': /* Is there a "next" file? */
#if TAGS #if TAGS
if (ntags()) if (ntags())
return (0); return (0);
@ -264,7 +264,7 @@ protochar(c, where, iseditproto)
switch (c) switch (c)
{ {
case 'b': /* Current byte offset */ case 'b': /* Current byte offset */
pos = curr_byte(where); pos = curr_byte(where);
if (pos != NULL_POSITION) if (pos != NULL_POSITION)
ap_pos(pos); ap_pos(pos);
@ -274,14 +274,14 @@ protochar(c, where, iseditproto)
case 'c': case 'c':
ap_int(hshift); ap_int(hshift);
break; break;
case 'd': /* Current page number */ case 'd': /* Current page number */
linenum = currline(where); linenum = currline(where);
if (linenum > 0 && sc_height > 1) if (linenum > 0 && sc_height > 1)
ap_linenum(PAGE_NUM(linenum)); ap_linenum(PAGE_NUM(linenum));
else else
ap_quest(); ap_quest();
break; break;
case 'D': /* Final page number */ case 'D': /* Final page number */
/* Find the page number of the last byte in the file (len-1). */ /* Find the page number of the last byte in the file (len-1). */
len = ch_length(); len = ch_length();
if (len == NULL_POSITION) if (len == NULL_POSITION)
@ -299,22 +299,22 @@ protochar(c, where, iseditproto)
} }
break; break;
#if EDITOR #if EDITOR
case 'E': /* Editor name */ case 'E': /* Editor name */
ap_str(editor); ap_str(editor);
break; break;
#endif #endif
case 'f': /* File name */ case 'f': /* File name */
ap_str(get_filename(curr_ifile)); ap_str(get_filename(curr_ifile));
break; break;
case 'F': /* Last component of file name */ case 'F': /* Last component of file name */
ap_str(last_component(get_filename(curr_ifile))); ap_str(last_component(get_filename(curr_ifile)));
break; break;
case 'g': /* Shell-escaped file name */ case 'g': /* Shell-escaped file name */
s = shell_quote(get_filename(curr_ifile)); s = shell_quote(get_filename(curr_ifile));
ap_str(s); ap_str(s);
free(s); free(s);
break; break;
case 'i': /* Index into list of files */ case 'i': /* Index into list of files */
#if TAGS #if TAGS
if (ntags()) if (ntags())
ap_int(curr_tag()); ap_int(curr_tag());
@ -322,14 +322,14 @@ protochar(c, where, iseditproto)
#endif #endif
ap_int(get_index(curr_ifile)); ap_int(get_index(curr_ifile));
break; break;
case 'l': /* Current line number */ case 'l': /* Current line number */
linenum = currline(where); linenum = currline(where);
if (linenum != 0) if (linenum != 0)
ap_linenum(linenum); ap_linenum(linenum);
else else
ap_quest(); ap_quest();
break; break;
case 'L': /* Final line number */ case 'L': /* Final line number */
len = ch_length(); len = ch_length();
if (len == NULL_POSITION || len == ch_zero() || if (len == NULL_POSITION || len == ch_zero() ||
(linenum = find_linenum(len)) <= 0) (linenum = find_linenum(len)) <= 0)
@ -337,7 +337,7 @@ protochar(c, where, iseditproto)
else else
ap_linenum(linenum-1); ap_linenum(linenum-1);
break; break;
case 'm': /* Number of files */ case 'm': /* Number of files */
#if TAGS #if TAGS
n = ntags(); n = ntags();
if (n) if (n)
@ -346,7 +346,7 @@ protochar(c, where, iseditproto)
#endif #endif
ap_int(nifile()); ap_int(nifile());
break; break;
case 'p': /* Percent into file (bytes) */ case 'p': /* Percent into file (bytes) */
pos = curr_byte(where); pos = curr_byte(where);
len = ch_length(); len = ch_length();
if (pos != NULL_POSITION && len > 0) if (pos != NULL_POSITION && len > 0)
@ -354,7 +354,7 @@ protochar(c, where, iseditproto)
else else
ap_quest(); ap_quest();
break; break;
case 'P': /* Percent into file (lines) */ case 'P': /* Percent into file (lines) */
linenum = currline(where); linenum = currline(where);
if (linenum == 0 || if (linenum == 0 ||
(len = ch_length()) == NULL_POSITION || len == ch_zero() || (len = ch_length()) == NULL_POSITION || len == ch_zero() ||
@ -363,7 +363,7 @@ protochar(c, where, iseditproto)
else else
ap_int(percentage(linenum, last_linenum)); ap_int(percentage(linenum, last_linenum));
break; break;
case 's': /* Size of file */ case 's': /* Size of file */
case 'B': case 'B':
len = ch_length(); len = ch_length();
if (len != NULL_POSITION) if (len != NULL_POSITION)
@ -371,12 +371,12 @@ protochar(c, where, iseditproto)
else else
ap_quest(); ap_quest();
break; break;
case 't': /* Truncate trailing spaces in the message */ case 't': /* Truncate trailing spaces in the message */
while (mp > message && mp[-1] == ' ') while (mp > message && mp[-1] == ' ')
mp--; mp--;
*mp = '\0'; *mp = '\0';
break; break;
case 'T': /* Type of list */ case 'T': /* Type of list */
#if TAGS #if TAGS
if (ntags()) if (ntags())
ap_str("tag"); ap_str("tag");
@ -384,7 +384,7 @@ protochar(c, where, iseditproto)
#endif #endif
ap_str("file"); ap_str("file");
break; break;
case 'x': /* Name of next file */ case 'x': /* Name of next file */
h = next_ifile(curr_ifile); h = next_ifile(curr_ifile);
if (h != NULL_IFILE) if (h != NULL_IFILE)
ap_str(get_filename(h)); ap_str(get_filename(h));
@ -469,12 +469,12 @@ wherechar(p, wp)
case 'b': case 'd': case 'l': case 'p': case 'P': case 'b': case 'd': case 'l': case 'p': case 'P':
switch (*++p) switch (*++p)
{ {
case 't': *wp = TOP; break; case 't': *wp = TOP; break;
case 'm': *wp = MIDDLE; break; case 'm': *wp = MIDDLE; break;
case 'b': *wp = BOTTOM; break; case 'b': *wp = BOTTOM; break;
case 'B': *wp = BOTTOM_PLUS_ONE; break; case 'B': *wp = BOTTOM_PLUS_ONE; break;
case 'j': *wp = sindex_from_sline(jump_sline); break; case 'j': *wp = sindex_from_sline(jump_sline); break;
default: *wp = TOP; p--; break; default: *wp = TOP; p--; break;
} }
} }
return (p); return (p);
@ -501,14 +501,14 @@ pr_expand(proto, maxwidth)
{ {
switch (*p) switch (*p)
{ {
default: /* Just put the character in the message */ default: /* Just put the character in the message */
ap_char(*p); ap_char(*p);
break; break;
case '\\': /* Backslash escapes the next character */ case '\\': /* Backslash escapes the next character */
p++; p++;
ap_char(*p); ap_char(*p);
break; break;
case '?': /* Conditional (IF) */ case '?': /* Conditional (IF) */
if ((c = *++p) == '\0') if ((c = *++p) == '\0')
--p; --p;
else else
@ -519,12 +519,12 @@ pr_expand(proto, maxwidth)
p = skipcond(p); p = skipcond(p);
} }
break; break;
case ':': /* ELSE */ case ':': /* ELSE */
p = skipcond(p); p = skipcond(p);
break; break;
case '.': /* ENDIF */ case '.': /* ENDIF */
break; break;
case '%': /* Percent escape */ case '%': /* Percent escape */
if ((c = *++p) == '\0') if ((c = *++p) == '\0')
--p; --p;
else else

View File

@ -10,13 +10,13 @@
#define NSUBEXP 10 #define NSUBEXP 10
typedef struct regexp { typedef struct regexp {
char *startp[NSUBEXP]; char *startp[NSUBEXP];
char *endp[NSUBEXP]; char *endp[NSUBEXP];
char regstart; /* Internal use only. */ char regstart; /* Internal use only. */
char reganch; /* Internal use only. */ char reganch; /* Internal use only. */
char *regmust; /* Internal use only. */ char *regmust; /* Internal use only. */
int regmlen; /* Internal use only. */ int regmlen; /* Internal use only. */
char program[1]; /* Unwarranted chumminess with compiler. */ char program[1]; /* Unwarranted chumminess with compiler. */
} regexp; } regexp;
#if defined(__STDC__) || defined(__cplusplus) #if defined(__STDC__) || defined(__cplusplus)

File diff suppressed because it is too large Load Diff

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -16,8 +16,8 @@
#include "position.h" #include "position.h"
#include "charset.h" #include "charset.h"
#define MINPOS(a,b) (((a) < (b)) ? (a) : (b)) #define MINPOS(a,b) (((a) < (b)) ? (a) : (b))
#define MAXPOS(a,b) (((a) > (b)) ? (a) : (b)) #define MAXPOS(a,b) (((a) > (b)) ? (a) : (b))
extern int sigs; extern int sigs;
extern int how_search; extern int how_search;
@ -33,6 +33,10 @@ extern POSITION start_attnpos;
extern POSITION end_attnpos; extern POSITION end_attnpos;
extern int utf_mode; extern int utf_mode;
extern int screen_trashed; extern int screen_trashed;
extern int sc_width;
extern int sc_height;
extern int chopline;
extern int hshift;
#if HILITE_SEARCH #if HILITE_SEARCH
extern int hilite_search; extern int hilite_search;
extern int size_linebuf; extern int size_linebuf;
@ -41,8 +45,7 @@ extern int can_goto_line;
static int hide_hilite; static int hide_hilite;
static POSITION prep_startpos; static POSITION prep_startpos;
static POSITION prep_endpos; static POSITION prep_endpos;
static int is_caseless; extern POSITION xxpos;
static int is_ucase_pattern;
/* /*
* Structures for maintaining a set of ranges for hilites and filtered-out * 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 hilite_anchor = HILITE_INITIALIZER();
static struct hilite_tree filter_anchor = HILITE_INITIALIZER(); static struct hilite_tree filter_anchor = HILITE_INITIALIZER();
static struct pattern_info *filter_infos = NULL;
#endif #endif
@ -105,6 +109,7 @@ struct pattern_info {
PATTERN_TYPE compiled; PATTERN_TYPE compiled;
char* text; char* text;
int search_type; int search_type;
struct pattern_info *next;
}; };
#if NO_REGEX #if NO_REGEX
@ -114,7 +119,8 @@ struct pattern_info {
#endif #endif
static struct pattern_info search_info; 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? * Are there any uppercase letters in this string?
@ -135,19 +141,35 @@ is_ucase(str)
return (0); 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. * Compile and save a search pattern.
*/ */
static int static int
set_pattern(info, pattern, search_type) set_pattern(info, pattern, search_type, show_error)
struct pattern_info *info; struct pattern_info *info;
char *pattern; char *pattern;
int search_type; int search_type;
int show_error;
{ {
#if !NO_REGEX #if !NO_REGEX
if (pattern == NULL) if (pattern == NULL)
CLEAR_PATTERN(info->compiled); SET_NULL_PATTERN(info->compiled);
else if (compile_pattern(pattern, search_type, &info->compiled) < 0) else if (compile_pattern(pattern, search_type, show_error, &info->compiled) < 0)
return -1; return -1;
#endif #endif
/* Pattern compiled successfully; save the text too. */ /* Pattern compiled successfully; save the text too. */
@ -173,21 +195,6 @@ set_pattern(info, pattern, search_type)
return 0; 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. * Initialize saved pattern to nothing.
*/ */
@ -195,9 +202,10 @@ clear_pattern(info)
init_pattern(info) init_pattern(info)
struct pattern_info *info; struct pattern_info *info;
{ {
CLEAR_PATTERN(info->compiled); SET_NULL_PATTERN(info->compiled);
info->text = NULL; info->text = NULL;
info->search_type = 0; info->search_type = 0;
info->next = NULL;
} }
/* /*
@ -207,7 +215,6 @@ init_pattern(info)
init_search(VOID_PARAM) init_search(VOID_PARAM)
{ {
init_pattern(&search_info); init_pattern(&search_info);
init_pattern(&filter_info);
} }
/* /*
@ -217,18 +224,13 @@ init_search(VOID_PARAM)
get_cvt_ops(VOID_PARAM) get_cvt_ops(VOID_PARAM)
{ {
int ops = 0; int ops = 0;
if (is_caseless || bs_mode == BS_SPECIAL)
{ if (is_caseless)
if (is_caseless) ops |= CVT_TO_LC;
ops |= CVT_TO_LC; if (bs_mode == BS_SPECIAL)
if (bs_mode == BS_SPECIAL) ops |= CVT_BS;
ops |= CVT_BS; if (bs_mode != BS_CONTROL)
if (bs_mode != BS_CONTROL)
ops |= CVT_CRLF;
} else if (bs_mode != BS_CONTROL)
{
ops |= CVT_CRLF; ops |= CVT_CRLF;
}
if (ctldisp == OPT_ONPLUS) if (ctldisp == OPT_ONPLUS)
ops |= CVT_ANSI; ops |= CVT_ANSI;
return (ops); return (ops);
@ -292,6 +294,7 @@ repaint_hilite(on)
lower_left(); lower_left();
hide_hilite = save_hide_hilite; hide_hilite = save_hide_hilite;
} }
#endif
/* /*
* Clear the attn hilite. * Clear the attn hilite.
@ -299,6 +302,7 @@ repaint_hilite(on)
public void public void
clear_attn(VOID_PARAM) clear_attn(VOID_PARAM)
{ {
#if HILITE_SEARCH
int sindex; int sindex;
POSITION old_start_attnpos; POSITION old_start_attnpos;
POSITION old_end_attnpos; POSITION old_end_attnpos;
@ -337,27 +341,30 @@ clear_attn(VOID_PARAM)
} }
if (moved) if (moved)
lower_left(); lower_left();
}
#endif #endif
}
/* /*
* Hide search string highlighting. * Toggle or clear search string highlighting.
*/ */
public void 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) if (hilite_anchor.first == NULL)
{ {
error("No previous regular expression", NULL_PARG); error("No previous regular expression", NULL_PARG);
return; 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); repaint_hilite(1);
#endif #endif
} }
@ -601,7 +608,7 @@ prev_unfiltered(pos)
* If nohide is nonzero, don't consider hide_hilite. * If nohide is nonzero, don't consider hide_hilite.
*/ */
public int public int
is_hilited(pos, epos, nohide, p_matches) is_hilited_attr(pos, epos, nohide, p_matches)
POSITION pos; POSITION pos;
POSITION epos; POSITION epos;
int nohide; int nohide;
@ -614,12 +621,12 @@ is_hilited(pos, epos, nohide, p_matches)
if (!status_col && if (!status_col &&
start_attnpos != NULL_POSITION && start_attnpos != NULL_POSITION &&
pos < end_attnpos && pos <= end_attnpos &&
(epos == NULL_POSITION || epos > start_attnpos)) (epos == NULL_POSITION || epos >= start_attnpos))
/* /*
* The attn line overlaps this range. * The attn line overlaps this range.
*/ */
return (1); return (AT_HILITE|AT_COLOR_ATTN);
match = is_hilited_range(pos, epos); match = is_hilited_range(pos, epos);
if (!match) 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 in status column. In this case we want to return
* hilite status even if hiliting is disabled or hidden. * 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. * Report matches, even if we're hiding highlights.
@ -650,7 +657,7 @@ is_hilited(pos, epos, nohide, p_matches)
*/ */
return (0); return (0);
return (1); return (AT_HILITE|AT_COLOR_SEARCH);
} }
/* /*
@ -1155,11 +1162,92 @@ search_pos(search_type)
return (pos); 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. * Search a subset of the file, specified by start/end position.
*/ */
static int 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 pos;
POSITION endpos; POSITION endpos;
int search_type; int search_type;
@ -1167,6 +1255,7 @@ search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos)
int maxlines; int maxlines;
POSITION *plinepos; POSITION *plinepos;
POSITION *pendpos; POSITION *pendpos;
POSITION *plastlinepos;
{ {
char *line; char *line;
char *cline; char *cline;
@ -1178,9 +1267,14 @@ search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos)
int cvt_len; int cvt_len;
int *chpos; int *chpos;
POSITION linepos, oldpos; POSITION linepos, oldpos;
int swidth = sc_width - line_pfx_width();
int sheight = sc_height - sindex_from_sline(jump_sline);
linenum = find_linenum(pos); linenum = find_linenum(pos);
oldpos = pos; oldpos = pos;
/* When the search wraps around, end at starting position. */
if ((search_type & SRCH_WRAP) && endpos == NULL_POSITION)
endpos = pos;
for (;;) for (;;)
{ {
/* /*
@ -1196,7 +1290,9 @@ search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos)
return (-1); 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. * 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. * 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) if (pendpos != NULL)
*pendpos = oldpos; *pendpos = oldpos;
return (matches); return (matches);
@ -1252,8 +1377,10 @@ search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos)
add_lnum(linenum, pos); add_lnum(linenum, pos);
oldpos = pos; oldpos = pos;
#if HILITE_SEARCH
if (is_filtered(linepos)) if (is_filtered(linepos))
continue; continue;
#endif
/* /*
* If it's a caseless search, convert the line to lowercase. * 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 #if HILITE_SEARCH
/* /*
* Check to see if the line matches the filter pattern. * If any filters are in effect, ignore non-matching lines.
* If so, add an entry to the filter list.
*/ */
if (((search_type & SRCH_FIND_ALL) || if (filter_infos != NULL &&
((search_type & SRCH_FIND_ALL) ||
prep_startpos == NULL_POSITION || prep_startpos == NULL_POSITION ||
linepos < prep_startpos || linepos >= prep_endpos) && linepos < prep_startpos || linepos >= prep_endpos)) {
prev_pattern(&filter_info)) { if (matches_filters(pos, cline, line_len, chpos, linepos, &sp, &ep))
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);
continue; continue;
}
} }
#endif #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); hilite_line(linepos, cline, line_len, chpos, sp, ep, cvt_ops);
} }
#endif #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(cline);
free(chpos); free(chpos);
if (plinepos != NULL) if (plinepos != NULL)
@ -1358,8 +1518,8 @@ hist_pattern(search_type)
if (pattern == NULL) if (pattern == NULL)
return (0); return (0);
if (set_pattern(&search_info, pattern, search_type) < 0) if (set_pattern(&search_info, pattern, search_type, 1) < 0)
return (0); return (-1);
#if HILITE_SEARCH #if HILITE_SEARCH
if (hilite_search == OPT_ONPLUS && !hide_hilite) if (hilite_search == OPT_ONPLUS && !hide_hilite)
@ -1392,7 +1552,7 @@ chg_caseless(VOID_PARAM)
* Regenerate the pattern using the new state. * Regenerate the pattern using the new state.
*/ */
clear_pattern(&search_info); 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; int n;
{ {
POSITION pos; POSITION pos;
POSITION opos;
POSITION lastlinepos = NULL_POSITION;
if (pattern == NULL || *pattern == '\0') if (pattern == NULL || *pattern == '\0')
{ {
@ -1419,10 +1581,13 @@ search(search_type, pattern, n)
* A null pattern means use the previously compiled pattern. * A null pattern means use the previously compiled pattern.
*/ */
search_type |= SRCH_AFTER_TARGET; 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); int r = hist_pattern(search_type);
return (-1); if (r == 0)
error("No previous regular expression", NULL_PARG);
if (r <= 0)
return (-1);
} }
if ((search_type & SRCH_NO_REGEX) != if ((search_type & SRCH_NO_REGEX) !=
(search_info.search_type & SRCH_NO_REGEX)) (search_info.search_type & SRCH_NO_REGEX))
@ -1455,7 +1620,8 @@ search(search_type, pattern, n)
/* /*
* Compile the pattern. * 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); return (-1);
#if HILITE_SEARCH #if HILITE_SEARCH
if (hilite_search || status_col) if (hilite_search || status_col)
@ -1483,6 +1649,7 @@ search(search_type, pattern, n)
* Figure out where to start the search. * Figure out where to start the search.
*/ */
pos = search_pos(search_type); pos = search_pos(search_type);
opos = position(sindex_from_sline(jump_sline));
if (pos == NULL_POSITION) if (pos == NULL_POSITION)
{ {
/* /*
@ -1490,14 +1657,16 @@ search(search_type, pattern, n)
*/ */
if (search_type & SRCH_PAST_EOF) if (search_type & SRCH_PAST_EOF)
return (n); return (n);
#if HILITE_SEARCH
if (hilite_search == OPT_ON || status_col) if (hilite_search == OPT_ON || status_col)
repaint_hilite(1); repaint_hilite(1);
#endif
error("Nothing to search", NULL_PARG); error("Nothing to search", NULL_PARG);
return (-1); return (-1);
} }
n = search_range(pos, NULL_POSITION, search_type, n, -1, n = search_range(pos, NULL_POSITION, search_type, n, -1,
&pos, (POSITION*)NULL); &pos, (POSITION*)NULL, &lastlinepos);
if (n != 0) if (n != 0)
{ {
/* /*
@ -1518,7 +1687,10 @@ search(search_type, pattern, n)
/* /*
* Go to the matching line. * 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 #if HILITE_SEARCH
@ -1531,7 +1703,6 @@ search(search_type, pattern, n)
return (0); return (0);
} }
#if HILITE_SEARCH #if HILITE_SEARCH
/* /*
* Prepare hilites in a given range of the file. * 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 * 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. * 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()) if (!prev_pattern(&search_info) && !is_filtering())
return; return;
@ -1665,7 +1836,7 @@ prep_hilite(spos, epos, maxlines)
search_type |= (search_info.search_type & SRCH_NO_REGEX); search_type |= (search_info.search_type & SRCH_NO_REGEX);
for (;;) 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) if (result < 0)
return; return;
if (prep_endpos == NULL_POSITION || new_epos > prep_endpos) if (prep_endpos == NULL_POSITION || new_epos > prep_endpos)
@ -1718,11 +1889,29 @@ set_filter_pattern(pattern, search_type)
char *pattern; char *pattern;
int search_type; int search_type;
{ {
struct pattern_info *filter;
clr_filter(); clr_filter();
if (pattern == NULL || *pattern == '\0') if (pattern == NULL || *pattern == '\0')
clear_pattern(&filter_info); {
else /* Clear and free all filters. */
set_pattern(&filter_info, pattern, search_type); 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; screen_trashed = 1;
} }
@ -1734,7 +1923,7 @@ is_filtering(VOID_PARAM)
{ {
if (ch_getflags() & CH_HELPFILE) if (ch_getflags() & CH_HELPFILE)
return (0); return (0);
return prev_pattern(&filter_info); return (filter_infos != NULL);
} }
#endif #endif

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -34,9 +34,11 @@ extern int linenums;
extern int wscroll; extern int wscroll;
extern int reading; extern int reading;
extern int quit_on_intr; extern int quit_on_intr;
extern int less_is_more; extern int secure;
extern long jump_sline_fraction; extern long jump_sline_fraction;
extern int less_is_more;
/* /*
* Interrupt signal handler. * Interrupt signal handler.
*/ */
@ -63,6 +65,9 @@ u_interrupt(type)
#endif #endif
if (less_is_more) if (less_is_more)
quit(0); quit(0);
#if HILITE_SEARCH
set_filter_pattern(NULL, 0);
#endif
if (reading) if (reading)
intread(); /* May longjmp */ intread(); /* May longjmp */
} }
@ -125,6 +130,9 @@ wbreak_handler(dwCtrlType)
case CTRL_C_EVENT: case CTRL_C_EVENT:
case CTRL_BREAK_EVENT: case CTRL_BREAK_EVENT:
sigs |= S_INTERRUPT; sigs |= S_INTERRUPT;
#if HILITE_SEARCH
set_filter_pattern(NULL, 0);
#endif
return (TRUE); return (TRUE);
default: default:
break; break;
@ -158,7 +166,7 @@ init_signals(on)
(void) LSIGNAL(SIGINT, u_interrupt); (void) LSIGNAL(SIGINT, u_interrupt);
#endif #endif
#ifdef SIGTSTP #ifdef SIGTSTP
(void) LSIGNAL(SIGTSTP, stop); (void) LSIGNAL(SIGTSTP, secure ? SIG_IGN : stop);
#endif #endif
#ifdef SIGWINCH #ifdef SIGWINCH
(void) LSIGNAL(SIGWINCH, winch); (void) LSIGNAL(SIGWINCH, winch);

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -10,7 +10,7 @@
#include "less.h" #include "less.h"
#define WHITESP(c) ((c)==' ' || (c)=='\t') #define WHITESP(c) ((c)==' ' || (c)=='\t')
#if TAGS #if TAGS
@ -36,12 +36,12 @@ enum tag_result {
* Tag type * Tag type
*/ */
enum { enum {
T_CTAGS, /* 'tags': standard and extended format (ctags) */ T_CTAGS, /* 'tags': standard and extended format (ctags) */
T_CTAGS_X, /* stdin: cross reference format (ctags) */ T_CTAGS_X, /* stdin: cross reference format (ctags) */
T_GTAGS, /* 'GTAGS': function definition (global) */ T_GTAGS, /* 'GTAGS': function definition (global) */
T_GRTAGS, /* 'GRTAGS': function reference (global) */ T_GRTAGS, /* 'GRTAGS': function reference (global) */
T_GSYMS, /* 'GSYMS': other symbols (global) */ T_GSYMS, /* 'GSYMS': other symbols (global) */
T_GPATH /* 'GPATH': path name (global) */ T_GPATH /* 'GPATH': path name (global) */
}; };
static enum tag_result findctag LESSPARAMS((char *tag)); static enum tag_result findctag LESSPARAMS((char *tag));
@ -50,8 +50,7 @@ static char *nextgtag(VOID_PARAM);
static char *prevgtag(VOID_PARAM); static char *prevgtag(VOID_PARAM);
static POSITION ctagsearch(VOID_PARAM); static POSITION ctagsearch(VOID_PARAM);
static POSITION gtagsearch(VOID_PARAM); static POSITION gtagsearch(VOID_PARAM);
static int getentry LESSPARAMS((char *buf, char **tag, char **file, static int getentry LESSPARAMS((char *buf, char **tag, char **file, char **line));
char **line));
/* /*
* The list of tags generated by the last findgtag() call. * The list of tags generated by the last findgtag() call.
@ -67,10 +66,10 @@ struct taglist {
}; };
struct tag { struct tag {
struct tag *next, *prev; /* List links */ struct tag *next, *prev; /* List links */
char *tag_file; /* Source file containing the tag */ char *tag_file; /* Source file containing the tag */
LINENUM tag_linenum; /* Appropriate line number in source file */ LINENUM tag_linenum; /* Appropriate line number in source file */
char *tag_pattern; /* Pattern used to find the tag */ char *tag_pattern; /* Pattern used to find the tag */
char tag_endline; /* True if the pattern includes '$' */ char tag_endline; /* True if the pattern includes '$' */
}; };
#define TAG_END ((struct tag *) &taglist) #define TAG_END ((struct tag *) &taglist)
static struct taglist taglist = { TAG_END, TAG_END }; static struct taglist taglist = { TAG_END, TAG_END };
@ -412,10 +411,10 @@ curtag_match(char const *line, POSITION linepos)
* Search for a tag. * Search for a tag.
* This is a stripped-down version of search(). * This is a stripped-down version of search().
* We don't use search() for several reasons: * We don't use search() for several reasons:
* - We don't want to blow away any search string we may have saved. * - We don't want to blow away any search string we may have saved.
* - The various regular-expression functions (from different systems: * - The various regular-expression functions (from different systems:
* regcmp vs. re_comp) behave differently in the presence of * regcmp vs. re_comp) behave differently in the presence of
* parentheses (which are almost always found in a tag). * parentheses (which are almost always found in a tag).
*/ */
static POSITION static POSITION
ctagsearch(VOID_PARAM) ctagsearch(VOID_PARAM)
@ -498,8 +497,8 @@ ctagsearch(VOID_PARAM)
*/ */
static enum tag_result static enum tag_result
findgtag(tag, type) findgtag(tag, type)
char *tag; /* tag to load */ char *tag; /* tag to load */
int type; /* tags type */ int type; /* tags type */
{ {
char buf[256]; char buf[256];
FILE *fp; FILE *fp;
@ -590,7 +589,7 @@ findgtag(tag, type)
} while (c != '\n' && c != EOF); } 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. * Couldn't parse this line for some reason.
@ -624,7 +623,7 @@ findgtag(tag, type)
return TAG_FOUND; 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 * 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) * |func 21 subr.c func(arg)
* *
* The following commands write this format. * The following commands write this format.
* o Traditinal Ctags with -x option * o Traditinal Ctags with -x option
* o Global with -x option * o Global with -x option
* See <http://www.gnu.org/software/global/global.html> * See <http://www.gnu.org/software/global/global.html>
* *
* [extended format] * [extended format]
* <tag> <type> <lineno> <file> <image> * <tag> <type> <lineno> <file> <image>
@ -720,8 +719,8 @@ gtagsearch(VOID_PARAM)
* |func function 21 subr.c func(arg) * |func function 21 subr.c func(arg)
* *
* The following commands write this format. * The following commands write this format.
* o Exuberant Ctags with -x option * o Exuberant Ctags with -x option
* See <http://ctags.sourceforge.net> * See <http://ctags.sourceforge.net>
* *
* Returns 0 on success, -1 on error. * Returns 0 on success, -1 on error.
* The tag, file, and line will each be NUL-terminated pointers * The tag, file, and line will each be NUL-terminated pointers
@ -729,19 +728,19 @@ gtagsearch(VOID_PARAM)
*/ */
static int static int
getentry(buf, tag, file, line) getentry(buf, tag, file, line)
char *buf; /* standard or extended ctags -x format data */ char *buf; /* standard or extended ctags -x format data */
char **tag; /* name of the tag we actually found */ char **tag; /* name of the tag we actually found */
char **file; /* file in which to find this tag */ char **file; /* file in which to find this tag */
char **line; /* line number of file where this tag is found */ char **line; /* line number of file where this tag is found */
{ {
char *p = buf; 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) if (*p == 0)
return (-1); return (-1);
*p++ = 0; *p++ = 0;
for ( ; *p && IS_SPACE(*p); p++) /* (skip blanks) */ for ( ; *p && IS_SPACE(*p); p++) /* (skip blanks) */
; ;
if (*p == 0) if (*p == 0)
return (-1); return (-1);
@ -751,24 +750,24 @@ getentry(buf, tag, file, line)
*/ */
if (!IS_DIGIT(*p)) 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)) if (!IS_DIGIT(*p))
return (-1); return (-1);
*line = p; /* line number */ *line = p; /* line number */
for (*line = p; *p && !IS_SPACE(*p); p++) for (*line = p; *p && !IS_SPACE(*p); p++)
; ;
if (*p == 0) if (*p == 0)
return (-1); return (-1);
*p++ = 0; *p++ = 0;
for ( ; *p && IS_SPACE(*p); p++) /* (skip blanks) */ for ( ; *p && IS_SPACE(*p); p++) /* (skip blanks) */
; ;
if (*p == 0) if (*p == 0)
return (-1); return (-1);
*file = p; /* file name */ *file = p; /* file name */
for (*file = p; *p && !IS_SPACE(*p); p++) for (*file = p; *p && !IS_SPACE(*p); p++)
; ;
if (*p == 0) if (*p == 0)
@ -780,5 +779,5 @@ getentry(buf, tag, file, line)
return (0); return (0);
return (-1); return (-1);
} }
#endif #endif

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * License or the Less License, as specified in the README file.
@ -28,10 +28,35 @@ public HANDLE tty;
#else #else
public int tty; public int tty;
#endif #endif
#if LESSTEST
public char *ttyin_name = NULL;
public int rstat_file = -1;
#endif /*LESSTEST*/
extern int sigs; extern int sigs;
extern int utf_mode; extern int utf_mode;
extern int wheel_lines; 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. * Open keyboard for input.
*/ */
@ -76,9 +101,9 @@ open_getchr(VOID_PARAM)
*/ */
#if OS2 #if OS2
/* The __open() system call translates "/dev/tty" to "con". */ /* The __open() system call translates "/dev/tty" to "con". */
tty = __open("/dev/tty", OPEN_READ); tty = __open(tty_device(), OPEN_READ);
#else #else
tty = open("/dev/tty", OPEN_READ); tty = open(tty_device(), OPEN_READ);
#endif #endif
if (tty < 0) if (tty < 0)
tty = 2; tty = 2;
@ -131,6 +156,18 @@ default_wheel_lines(VOID_PARAM)
return lines; 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. * Get a character from the keyboard.
*/ */
@ -142,11 +179,11 @@ getchr(VOID_PARAM)
do do
{ {
flush();
#if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
/* /*
* In raw read, we don't see ^C so look here for it. * In raw read, we don't see ^C so look here for it.
*/ */
flush();
#if MSDOS_COMPILER==WIN32C #if MSDOS_COMPILER==WIN32C
if (ABORT_SIGS()) if (ABORT_SIGS())
return (READ_INTR); return (READ_INTR);
@ -158,11 +195,17 @@ getchr(VOID_PARAM)
if (c == '\003') if (c == '\003')
return (READ_INTR); return (READ_INTR);
#else #else
#if LESSTEST
rstat('R');
#endif /*LESSTEST*/
{ {
unsigned char uc; unsigned char uc;
result = iread(tty, &uc, sizeof(char)); result = iread(tty, &uc, sizeof(char));
c = (char) uc; c = (char) uc;
} }
#if LESSTEST
rstat('B');
#endif /*LESSTEST*/
if (result == READ_INTR) if (result == READ_INTR)
return (READ_INTR); return (READ_INTR);
if (result < 0) if (result < 0)

View File

@ -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 * You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file. * 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. v561 5/11/20 Fix erroneous EOF calculation when F command is interrupted.
v562 5/19/20 Update Unicode tables; minor doc formatting. v562 5/19/20 Update Unicode tables; minor doc formatting.
v563 6/13/20 Fix crash due to realpath() incompatibility. 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";

View File

@ -1,4 +1,3 @@
/* $FreeBSD$ */
/* defines.h. Generated from defines.h.in by configure. */ /* defines.h. Generated from defines.h.in by configure. */
/* defines.h.in. Generated from configure.ac by autoheader. */ /* defines.h.in. Generated from configure.ac by autoheader. */
@ -259,6 +258,9 @@
/* Define to 1 if you have the <memory.h> header file. */ /* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1 #define HAVE_MEMORY_H 1
/* Define to 1 if you have the `nanosleep' function. */
#define HAVE_NANOSLEEP 1
/* Define HAVE_OSPEED if your termcap library has the ospeed variable. */ /* Define HAVE_OSPEED if your termcap library has the ospeed variable. */
#define HAVE_OSPEED 1 #define HAVE_OSPEED 1
@ -268,6 +270,9 @@
/* PCRE2 (Perl-compatible regular expression) library */ /* PCRE2 (Perl-compatible regular expression) library */
/* #undef HAVE_PCRE2 */ /* #undef HAVE_PCRE2 */
/* Define to 1 if you have the `poll' function. */
#define HAVE_POLL 1
/* Define to 1 if you have the `popen' function. */ /* Define to 1 if you have the `popen' function. */
#define HAVE_POPEN 1 #define HAVE_POPEN 1
@ -361,12 +366,18 @@
/* Define HAVE_TIME_T if your system supports the "time_t" type. */ /* Define HAVE_TIME_T if your system supports the "time_t" type. */
#define HAVE_TIME_T 1 #define HAVE_TIME_T 1
/* Define to 1 if you have the `ttyname' function. */
#define HAVE_TTYNAME 1
/* Define to 1 if you have the <unistd.h> header file. */ /* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1 #define HAVE_UNISTD_H 1
/* Define HAVE_UPPER_LOWER if you have isupper, islower, toupper, tolower. */ /* Define HAVE_UPPER_LOWER if you have isupper, islower, toupper, tolower. */
#define HAVE_UPPER_LOWER 1 #define HAVE_UPPER_LOWER 1
/* Define to 1 if you have the `usleep' function. */
#define HAVE_USLEEP 1
/* Henry Spencer V8 regcomp() and regexp.h */ /* Henry Spencer V8 regcomp() and regexp.h */
/* #undef HAVE_V8_REGCOMP */ /* #undef HAVE_V8_REGCOMP */