diff --git a/contrib/less/INSTALL b/contrib/less/INSTALL index c2ab230e4470..78ae93246d88 100644 --- a/contrib/less/INSTALL +++ b/contrib/less/INSTALL @@ -1,6 +1,6 @@ - This file describes how to build and install less using -the "configure" script. This only works on Unix systems. -To install on other systems, read the README file. +This file contains generic instructions on how to build and +install software using autoconf. For specific instructions +on how to build "less", see the README or README.VER file. Basic Installation @@ -24,8 +24,8 @@ diffs or instructions to the address given in the `README' so they can be considered for the next release. If at some point `config.cache' contains results you don't want to keep, you may remove or edit it. - The file `configure.in' is used to create `configure' by a program -called `autoconf'. You only need `configure.in' if you want to change + The file `configure.ac' is used to create `configure' by a program +called `autoconf'. You only need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: diff --git a/contrib/less/NEWS b/contrib/less/NEWS index b0644fd2e0de..fd214e62007d 100644 --- a/contrib/less/NEWS +++ b/contrib/less/NEWS @@ -4,10 +4,56 @@ ====================================================================== For the latest news about less, see the "less" Web page: - http://www.greenwoodsoftware.com/less + https://greenwoodsoftware.com/less You can also download the latest version of less from there. - To report bugs, suggestions or comments, send email to bug-less@gnu.org + Report bugs, suggestions or comments at + https://github.com/gwsw/less/issues. + +====================================================================== + + Major changes between "less" versions 563 and 581 + +* Change ESC-u command to toggle, not disable, highlighting per man page. + +* Add ESC-U command. + +* Add ctrl-W search modifier for wrapping search. + +* F command can be interrupted by ^X. + +* Support OSC 8 hyperlinks when -R is in effect. + +* g command with no number will ignore -j and put first line at top of screen. + +* Multiple + or -p command line options are handled better. + +* Add the --incsearch option. + +* Add the --line-num-width option. + +* Add the --status-col-width option. + +* Add the --use-color and --color options. + +* Display -w highlight even if highlighted line is empty. + +* If search result is in a long line, scroll to ensure it is visible. + +* Editing the same file under different names now creates only + one entry in the file list. + +* Make visual bell more visible on some terminals. + +* Ring end-of-file bell no more than once per second. + +* Build can use either Python or Perl for Makefile.aut operations. + +* Fix crash when using the @ search modifier. + +* Fix crash in the 's' command due to duplicate free. + +* Fix realpath crash on Darwin. ====================================================================== diff --git a/contrib/less/README b/contrib/less/README index 81cb7e091296..0c1acfd5d3f6 100644 --- a/contrib/less/README +++ b/contrib/less/README @@ -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 free software. You may redistribute it and/or @@ -21,33 +21,29 @@ or 2. The Less License, in the file LICENSE. - Please report any problems to bug-less@gnu.org. - See http://www.greenwoodsoftware.com/less for the latest info. + Please report any problems at https://github.com/gwsw/less/issues. + See https://greenwoodsoftware.com/less for the latest info. Source repository is at https://github.com/gwsw/less.git. ========================================================================= -This is the distribution of "less", a paginator similar to "more" or "pg". - The formatted manual page is in less.man. The manual page nroff source is in less.nro. Major changes made since the last posted version are in NEWS. ======================================================================= -PRE-INSTALLATION (when using git) - -If you are building from a clone of a git repository, -type "make -f Makefile.aut". -If you are building from a numbered release package (a tar or zip file -with a name like less-999.tar.gz or less-999.zip), you should skip this step. - -======================================================================= -INSTALLATION (Unix systems only): +INSTALLATION (Unix & Linux systems only): 1. Move the distributed source to its own directory and unpack it, if you have not already done so. -2. Type "sh configure". +2. If you are building from a clone of a git repository, + type "make -f Makefile.aut". + If you are building from a numbered release package (a tar or + zip file with a name like less-999.tar.gz or less-999.zip downloaded + from greenwoodsoftware.com, not from github), you should skip this step. + +3. Type "sh configure". This will generate a Makefile and a defines.h. Warning: if you have a GNU sed, make sure it is version 2.05 or later. @@ -79,7 +75,7 @@ INSTALLATION (Unix systems only): commands, etc. -3. It is a good idea to look over the generated Makefile and defines.h +4. It is a good idea to look over the generated Makefile and defines.h and make sure they look ok. If you know of any peculiarities of your system that configure might not have detected, you may fix the Makefile now. Take particular notice of the list of "terminal" @@ -93,13 +89,13 @@ INSTALLATION (Unix systems only): to remove the descriptions of the features which you are removing. If you edit less.hlp, you should run "make -f Makefile.aut help.c". -4. Type "make" and watch the fun. +5. Type "make" and watch the fun. -5. If the make succeeds, it will generate the programs "less", +6. If the make succeeds, it will generate the programs "less", "lesskey" and "lessecho" in your current directory. Test the generated programs. -6. When satisfied that it works, if you wish to install it +7. When satisfied that it works, if you wish to install it in a public place, type "make install". The default install destinations are: @@ -108,8 +104,6 @@ INSTALLATION (Unix systems only): If you want to install any of these files elsewhere, define bindir and/or mandir to the appropriate directories. -If you have any problems building or running "less", suggestions, -complaints, etc., you may mail to bug-less@gnu.org. Note to hackers: comments noting possible improvements are enclosed in double curly brackets {{ like this }}. diff --git a/contrib/less/brac.c b/contrib/less/brac.c index db3a2951db08..53ada50aab56 100644 --- a/contrib/less/brac.c +++ b/contrib/less/brac.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. diff --git a/contrib/less/ch.c b/contrib/less/ch.c index 70fad1002dbf..bab0692f7437 100644 --- a/contrib/less/ch.c +++ b/contrib/less/ch.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -41,7 +41,7 @@ struct bufnode { struct bufnode *hnext, *hprev; }; -#define LBUFSIZE 8192 +#define LBUFSIZE 8192 struct buf { struct bufnode node; BLOCKNUM block; @@ -54,7 +54,7 @@ struct buf { * The file state is maintained in a filestate structure. * A pointer to the filestate is kept in the ifile structure. */ -#define BUFHASH_SIZE 1024 +#define BUFHASH_SIZE 1024 struct filestate { struct bufnode buflist; struct bufnode hashtbl[BUFHASH_SIZE]; @@ -67,24 +67,24 @@ struct filestate { POSITION fsize; }; -#define ch_bufhead thisfile->buflist.next -#define ch_buftail thisfile->buflist.prev -#define ch_nbufs thisfile->nbufs -#define ch_block thisfile->block -#define ch_offset thisfile->offset -#define ch_fpos thisfile->fpos -#define ch_fsize thisfile->fsize -#define ch_flags thisfile->flags -#define ch_file thisfile->file +#define ch_bufhead thisfile->buflist.next +#define ch_buftail thisfile->buflist.prev +#define ch_nbufs thisfile->nbufs +#define ch_block thisfile->block +#define ch_offset thisfile->offset +#define ch_fpos thisfile->fpos +#define ch_fsize thisfile->fsize +#define ch_flags thisfile->flags +#define ch_file thisfile->file -#define END_OF_CHAIN (&thisfile->buflist) -#define END_OF_HCHAIN(h) (&thisfile->hashtbl[h]) -#define BUFHASH(blk) ((blk) & (BUFHASH_SIZE-1)) +#define END_OF_CHAIN (&thisfile->buflist) +#define END_OF_HCHAIN(h) (&thisfile->hashtbl[h]) +#define BUFHASH(blk) ((blk) & (BUFHASH_SIZE-1)) /* * Macros to manipulate the list of buffers in thisfile->buflist. */ -#define FOR_BUFS(bn) \ +#define FOR_BUFS(bn) \ for (bn = ch_bufhead; bn != END_OF_CHAIN; bn = bn->next) #define BUF_RM(bn) \ @@ -106,15 +106,15 @@ struct filestate { /* * Macros to manipulate the list of buffers in thisfile->hashtbl[n]. */ -#define FOR_BUFS_IN_CHAIN(h,bn) \ +#define FOR_BUFS_IN_CHAIN(h,bn) \ for (bn = thisfile->hashtbl[h].hnext; \ bn != END_OF_HCHAIN(h); bn = bn->hnext) -#define BUF_HASH_RM(bn) \ +#define BUF_HASH_RM(bn) \ (bn)->hnext->hprev = (bn)->hprev; \ (bn)->hprev->hnext = (bn)->hnext; -#define BUF_HASH_INS(bn,h) \ +#define BUF_HASH_INS(bn,h) \ (bn)->hnext = thisfile->hashtbl[h].hnext; \ (bn)->hprev = END_OF_HCHAIN(h); \ thisfile->hashtbl[h].hnext->hprev = (bn); \ @@ -240,12 +240,12 @@ ch_get(VOID_PARAM) return ('?'); if (lseek(ch_file, (off_t)pos, SEEK_SET) == BAD_LSEEK) { - error("seek error", NULL_PARG); + error("seek error", NULL_PARG); clear_eol(); return (EOI); - } - ch_fpos = pos; - } + } + ch_fpos = pos; + } /* * Read the block. @@ -311,13 +311,7 @@ ch_get(VOID_PARAM) parg.p_string = wait_message(); ierror("%s", &parg); } -#if !MSDOS_COMPILER - sleep(1); -#else -#if MSDOS_COMPILER==WIN32C - Sleep(1000); -#endif -#endif + sleep_ms(2); /* Reduce system load */ slept = TRUE; #if HAVE_STAT_INO diff --git a/contrib/less/charset.c b/contrib/less/charset.c index 4897cbaf6adc..b37c8a29cbd9 100644 --- a/contrib/less/charset.c +++ b/contrib/less/charset.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -40,27 +40,27 @@ struct charset { int *p_flag; char *desc; } charsets[] = { - { "ascii", NULL, "8bcccbcc18b95.b" }, - { "utf-8", &utf_mode, "8bcccbcc18b95.b126.bb" }, - { "iso8859", NULL, "8bcccbcc18b95.33b." }, - { "latin3", NULL, "8bcccbcc18b95.33b5.b8.b15.b4.b12.b18.b12.b." }, - { "arabic", NULL, "8bcccbcc18b95.33b.3b.7b2.13b.3b.b26.5b19.b" }, - { "greek", NULL, "8bcccbcc18b95.33b4.2b4.b3.b35.b44.b" }, - { "greek2005", NULL, "8bcccbcc18b95.33b14.b35.b44.b" }, - { "hebrew", NULL, "8bcccbcc18b95.33b.b29.32b28.2b2.b" }, - { "koi8-r", NULL, "8bcccbcc18b95.b." }, - { "KOI8-T", NULL, "8bcccbcc18b95.b8.b6.b8.b.b.5b7.3b4.b4.b3.b.b.3b." }, - { "georgianps", NULL, "8bcccbcc18b95.3b11.4b12.2b." }, - { "tcvn", NULL, "b..b...bcccbccbbb7.8b95.b48.5b." }, - { "TIS-620", NULL, "8bcccbcc18b95.b.4b.11b7.8b." }, - { "next", NULL, "8bcccbcc18b95.bb125.bb" }, - { "dos", NULL, "8bcccbcc12bc5b95.b." }, - { "windows-1251", NULL, "8bcccbcc12bc5b95.b24.b." }, - { "windows-1252", NULL, "8bcccbcc12bc5b95.b.b11.b.2b12.b." }, - { "windows-1255", NULL, "8bcccbcc12bc5b95.b.b8.b.5b9.b.4b." }, - { "ebcdic", NULL, "5bc6bcc7bcc41b.9b7.9b5.b..8b6.10b6.b9.7b9.8b8.17b3.3b9.7b9.8b8.6b10.b.b.b." }, - { "IBM-1047", NULL, "4cbcbc3b9cbccbccbb4c6bcc5b3cbbc4bc4bccbc191.b" }, - { NULL, NULL, NULL } + { "ascii", NULL, "8bcccbcc18b95.b" }, + { "utf-8", &utf_mode, "8bcccbcc18b95.b126.bb" }, + { "iso8859", NULL, "8bcccbcc18b95.33b." }, + { "latin3", NULL, "8bcccbcc18b95.33b5.b8.b15.b4.b12.b18.b12.b." }, + { "arabic", NULL, "8bcccbcc18b95.33b.3b.7b2.13b.3b.b26.5b19.b" }, + { "greek", NULL, "8bcccbcc18b95.33b4.2b4.b3.b35.b44.b" }, + { "greek2005", NULL, "8bcccbcc18b95.33b14.b35.b44.b" }, + { "hebrew", NULL, "8bcccbcc18b95.33b.b29.32b28.2b2.b" }, + { "koi8-r", NULL, "8bcccbcc18b95.b." }, + { "KOI8-T", NULL, "8bcccbcc18b95.b8.b6.b8.b.b.5b7.3b4.b4.b3.b.b.3b." }, + { "georgianps", NULL, "8bcccbcc18b95.3b11.4b12.2b." }, + { "tcvn", NULL, "b..b...bcccbccbbb7.8b95.b48.5b." }, + { "TIS-620", NULL, "8bcccbcc18b95.b.4b.11b7.8b." }, + { "next", NULL, "8bcccbcc18b95.bb125.bb" }, + { "dos", NULL, "8bcccbcc12bc5b95.b." }, + { "windows-1251", NULL, "8bcccbcc12bc5b95.b24.b." }, + { "windows-1252", NULL, "8bcccbcc12bc5b95.b.b11.b.2b12.b." }, + { "windows-1255", NULL, "8bcccbcc12bc5b95.b.b8.b.5b9.b.4b." }, + { "ebcdic", NULL, "5bc6bcc7bcc41b.9b7.9b5.b..8b6.10b6.b9.7b9.8b8.17b3.3b9.7b9.8b8.6b10.b.b.b." }, + { "IBM-1047", NULL, "4cbcbc3b9cbccbccbb4c6bcc5b3cbbc4bc4bccbc191.b" }, + { NULL, NULL, NULL } }; /* @@ -70,58 +70,58 @@ struct cs_alias { char *name; char *oname; } cs_aliases[] = { - { "UTF-8", "utf-8" }, - { "utf8", "utf-8" }, - { "UTF8", "utf-8" }, - { "ANSI_X3.4-1968", "ascii" }, - { "US-ASCII", "ascii" }, - { "latin1", "iso8859" }, - { "ISO-8859-1", "iso8859" }, - { "latin9", "iso8859" }, - { "ISO-8859-15", "iso8859" }, - { "latin2", "iso8859" }, - { "ISO-8859-2", "iso8859" }, - { "ISO-8859-3", "latin3" }, - { "latin4", "iso8859" }, - { "ISO-8859-4", "iso8859" }, - { "cyrillic", "iso8859" }, - { "ISO-8859-5", "iso8859" }, - { "ISO-8859-6", "arabic" }, - { "ISO-8859-7", "greek" }, - { "IBM9005", "greek2005" }, - { "ISO-8859-8", "hebrew" }, - { "latin5", "iso8859" }, - { "ISO-8859-9", "iso8859" }, - { "latin6", "iso8859" }, - { "ISO-8859-10", "iso8859" }, - { "latin7", "iso8859" }, - { "ISO-8859-13", "iso8859" }, - { "latin8", "iso8859" }, - { "ISO-8859-14", "iso8859" }, - { "latin10", "iso8859" }, - { "ISO-8859-16", "iso8859" }, - { "IBM437", "dos" }, - { "EBCDIC-US", "ebcdic" }, - { "IBM1047", "IBM-1047" }, - { "KOI8-R", "koi8-r" }, - { "KOI8-U", "koi8-r" }, - { "GEORGIAN-PS", "georgianps" }, - { "TCVN5712-1", "tcvn" }, - { "NEXTSTEP", "next" }, - { "windows", "windows-1252" }, /* backward compatibility */ - { "CP1251", "windows-1251" }, - { "CP1252", "windows-1252" }, - { "CP1255", "windows-1255" }, + { "UTF-8", "utf-8" }, + { "utf8", "utf-8" }, + { "UTF8", "utf-8" }, + { "ANSI_X3.4-1968", "ascii" }, + { "US-ASCII", "ascii" }, + { "latin1", "iso8859" }, + { "ISO-8859-1", "iso8859" }, + { "latin9", "iso8859" }, + { "ISO-8859-15", "iso8859" }, + { "latin2", "iso8859" }, + { "ISO-8859-2", "iso8859" }, + { "ISO-8859-3", "latin3" }, + { "latin4", "iso8859" }, + { "ISO-8859-4", "iso8859" }, + { "cyrillic", "iso8859" }, + { "ISO-8859-5", "iso8859" }, + { "ISO-8859-6", "arabic" }, + { "ISO-8859-7", "greek" }, + { "IBM9005", "greek2005" }, + { "ISO-8859-8", "hebrew" }, + { "latin5", "iso8859" }, + { "ISO-8859-9", "iso8859" }, + { "latin6", "iso8859" }, + { "ISO-8859-10", "iso8859" }, + { "latin7", "iso8859" }, + { "ISO-8859-13", "iso8859" }, + { "latin8", "iso8859" }, + { "ISO-8859-14", "iso8859" }, + { "latin10", "iso8859" }, + { "ISO-8859-16", "iso8859" }, + { "IBM437", "dos" }, + { "EBCDIC-US", "ebcdic" }, + { "IBM1047", "IBM-1047" }, + { "KOI8-R", "koi8-r" }, + { "KOI8-U", "koi8-r" }, + { "GEORGIAN-PS", "georgianps" }, + { "TCVN5712-1", "tcvn" }, + { "NEXTSTEP", "next" }, + { "windows", "windows-1252" }, /* backward compatibility */ + { "CP1251", "windows-1251" }, + { "CP1252", "windows-1252" }, + { "CP1255", "windows-1255" }, { NULL, NULL } }; -#define IS_BINARY_CHAR 01 -#define IS_CONTROL_CHAR 02 +#define IS_BINARY_CHAR 01 +#define IS_CONTROL_CHAR 02 static char chardef[256]; static char *binfmt = NULL; static char *utfbinfmt = NULL; -public int binattr = AT_STANDOUT; +public int binattr = AT_STANDOUT|AT_COLOR_BIN; /* @@ -134,9 +134,9 @@ public int binattr = AT_STANDOUT; * repetition of the letter. * * Each letter is one of: - * . normal character - * b binary character - * c control character + * . normal character + * b binary character + * c control character */ static void ichardef(s) @@ -457,16 +457,16 @@ prchar(c) SNPRINTF1(buf, sizeof(buf), "^%c", /* * This array roughly inverts CONTROL() #defined in less.h, - * and should be kept in sync with CONTROL() and IBM-1047. - */ + * and should be kept in sync with CONTROL() and IBM-1047. + */ "@ABC.I.?...KLMNO" "PQRS.JH.XY.." "\\]^_" "......W[.....EFG" "..V....D....TU.Z"[c]); #else - else if (c < 128 && !control_char(c ^ 0100)) - SNPRINTF1(buf, sizeof(buf), "^%c", (int) (c ^ 0100)); + else if (c < 128 && !control_char(c ^ 0100)) + SNPRINTF1(buf, sizeof(buf), "^%c", (int) (c ^ 0100)); #endif else SNPRINTF1(buf, sizeof(buf), binfmt, c); @@ -484,7 +484,7 @@ prutfchar(ch) if (ch == ESC) strcpy(buf, "ESC"); - else if (ch < 128 && control_char(ch)) + else if (ch < 128 && control_char(ch)) { if (!control_char(ch ^ 0100)) SNPRINTF1(buf, sizeof(buf), "^%c", ((char) ch) ^ 0100); @@ -732,9 +732,9 @@ step_char(pp, dir, limit) */ #define DECLARE_RANGE_TABLE_START(name) \ - static struct wchar_range name##_array[] = { + static struct wchar_range name##_array[] = { #define DECLARE_RANGE_TABLE_END(name) \ - }; struct wchar_range_table name##_table = { name##_array, sizeof(name##_array)/sizeof(*name##_array) }; + }; struct wchar_range_table name##_table = { name##_array, sizeof(name##_array)/sizeof(*name##_array) }; DECLARE_RANGE_TABLE_START(compose) #include "compose.uni" diff --git a/contrib/less/charset.h b/contrib/less/charset.h index cc0c3af59e89..3e7ecf73db94 100644 --- a/contrib/less/charset.h +++ b/contrib/less/charset.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. diff --git a/contrib/less/cmd.h b/contrib/less/cmd.h index 95a2e5801717..c51f0bc5c4f3 100644 --- a/contrib/less/cmd.h +++ b/contrib/less/cmd.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -31,7 +31,6 @@ #define A_HELP 19 #define A_NEXT_FILE 20 #define A_PERCENT 21 -#define A_PREFIX 22 #define A_PREV_FILE 23 #define A_QUIT 24 #define A_REPAINT 25 @@ -72,19 +71,19 @@ #define A_CLRMARK 62 #define A_SETMARKBOT 63 #define A_X11MOUSE_IN 64 -#define A_X11MOUSE_IGNORE 65 #define A_F_MOUSE 66 #define A_B_MOUSE 67 /* Note "X116" refers to extended (1006) X11 mouse reporting. */ #define A_X116MOUSE_IN 68 -#define A_X116MOUSE_IGNORE 69 +#define A_CLR_SEARCH 70 +/* These values must not conflict with any A_* or EC_* value. */ #define A_INVALID 100 #define A_NOACTION 101 #define A_UINVALID 102 #define A_END_LIST 103 #define A_SPECIAL_KEY 104 - +#define A_PREFIX 105 #define A_SKIP 127 #define A_EXTRA 0200 @@ -111,15 +110,16 @@ #define EC_B_COMPLETE 18 #define EC_LITERAL 19 #define EC_ABORT 20 +#define EC_X11MOUSE 21 +#define EC_X116MOUSE 22 -#define EC_NOACTION 101 #define EC_UINVALID 102 /* Flags for editchar() */ -#define EC_PEEK 01 -#define EC_NOHISTORY 02 -#define EC_NOCOMPLETE 04 -#define EC_NORIGHTLEFT 010 +#define ECF_PEEK 01 +#define ECF_NOHISTORY 02 +#define ECF_NOCOMPLETE 04 +#define ECF_NORIGHTLEFT 010 /* Environment variable stuff */ #define EV_OK 01 diff --git a/contrib/less/cmdbuf.c b/contrib/less/cmdbuf.c index ed78ded00307..9cc1f3e94977 100644 --- a/contrib/less/cmdbuf.c +++ b/contrib/less/cmdbuf.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -26,12 +26,12 @@ extern int no_hist_dups; extern int marks_modified; static char cmdbuf[CMDBUF_SIZE]; /* Buffer for holding a multi-char command */ -static int cmd_col; /* Current column of the cursor */ -static int prompt_col; /* Column of cursor just after prompt */ -static char *cp; /* Pointer into cmdbuf */ -static int cmd_offset; /* Index into cmdbuf of first displayed char */ -static int literal; /* Next input char should not be interpreted */ -static int updown_match = -1; /* Prefix length in up/down movement */ +static int cmd_col; /* Current column of the cursor */ +static int prompt_col; /* Column of cursor just after prompt */ +static char *cp; /* Pointer into cmdbuf */ +static int cmd_offset; /* Index into cmdbuf of first displayed char */ +static int literal; /* Next input char should not be interpreted */ +static int updown_match = -1; /* Prefix length in up/down movement */ #if TAB_COMPLETE_FILENAME static int cmd_complete LESSPARAMS((int action)); @@ -223,7 +223,7 @@ cmd_step_common(p, ch, len, pwidth, bswidth) } } if (pwidth != NULL) - *pwidth = width; + *pwidth = width; if (bswidth != NULL) *bswidth = width; return (pr); @@ -259,17 +259,42 @@ cmd_step_left(pp, pwidth, bswidth) return cmd_step_common(*pp, ch, p - *pp, pwidth, bswidth); } +/* + * Put the cursor at "home" (just after the prompt), + * and set cp to the corresponding char in cmdbuf. + */ + static void +cmd_home(VOID_PARAM) +{ + while (cmd_col > prompt_col) + { + int width, bswidth; + + cmd_step_left(&cp, &width, &bswidth); + while (bswidth-- > 0) + putbs(); + cmd_col -= width; + } + + cp = &cmdbuf[cmd_offset]; +} + /* * Repaint the line from cp onwards. * Then position the cursor just after the char old_cp (a pointer into cmdbuf). */ - static void + public void cmd_repaint(old_cp) constant char *old_cp; { /* * Repaint the line from the current position. */ + if (old_cp == NULL) + { + old_cp = cp; + cmd_home(); + } clear_eol(); while (*cp != '\0') { @@ -300,26 +325,6 @@ cmd_repaint(old_cp) cmd_left(); } -/* - * Put the cursor at "home" (just after the prompt), - * and set cp to the corresponding char in cmdbuf. - */ - static void -cmd_home(VOID_PARAM) -{ - while (cmd_col > prompt_col) - { - int width, bswidth; - - cmd_step_left(&cp, &width, &bswidth); - while (bswidth-- > 0) - putbs(); - cmd_col -= width; - } - - cp = &cmdbuf[cmd_offset]; -} - /* * Shift the cmdbuf display left a half-screen. */ @@ -826,9 +831,9 @@ cmd_accept(VOID_PARAM) * Try to perform a line-edit function on the command buffer, * using a specified char as a line-editing command. * Returns: - * CC_PASS The char does not invoke a line edit function. - * CC_OK Line edit function done. - * CC_QUIT The char requests the current command to be aborted. + * CC_PASS The char does not invoke a line edit function. + * CC_OK Line edit function done. + * CC_QUIT The char requests the current command to be aborted. */ static int cmd_edit(c) @@ -838,9 +843,9 @@ cmd_edit(c) int flags; #if TAB_COMPLETE_FILENAME -#define not_in_completion() in_completion = 0 +#define not_in_completion() in_completion = 0 #else -#define not_in_completion(VOID_PARAM) +#define not_in_completion(VOID_PARAM) #endif /* @@ -852,20 +857,22 @@ cmd_edit(c) /* * No current history; don't accept history manipulation cmds. */ - flags |= EC_NOHISTORY; + flags |= ECF_NOHISTORY; #endif #if TAB_COMPLETE_FILENAME if (curr_mlist == ml_search) /* * In a search command; don't accept file-completion cmds. */ - flags |= EC_NOCOMPLETE; + flags |= ECF_NOCOMPLETE; #endif action = editchar(c, flags); switch (action) { + case A_NOACTION: + return (CC_OK); case EC_RIGHT: not_in_completion(); return (cmd_right()); @@ -934,8 +941,6 @@ cmd_edit(c) case EC_EXPAND: return (cmd_complete(action)); #endif - case EC_NOACTION: - return (CC_OK); default: not_in_completion(); return (CC_PASS); @@ -1237,9 +1242,9 @@ cmd_complete(action) * Process a single character of a multi-character command, such as * a number, or the pattern of a search command. * Returns: - * CC_OK The char was accepted. - * CC_QUIT The char requests the command to be aborted. - * CC_ERROR The char could not be accepted due to an error. + * CC_OK The char was accepted. + * CC_QUIT The char requests the command to be aborted. + * CC_ERROR The char could not be accepted due to an error. */ public int cmd_char(c) diff --git a/contrib/less/command.c b/contrib/less/command.c index 8e0ae4b34d67..ae59181c2827 100644 --- a/contrib/less/command.c +++ b/contrib/less/command.c @@ -1,6 +1,6 @@ /* $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 * License or the Less License, as specified in the README file. @@ -57,21 +57,22 @@ extern void *ml_shell; extern char *editor; extern char *editproto; #endif -extern int screen_trashed; /* The screen has been overwritten */ +extern int screen_trashed; /* The screen has been overwritten */ extern int shift_count; extern int oldbot; extern int forw_prompt; +extern int incr_search; #if MSDOS_COMPILER==WIN32C extern int utf_mode; #endif #if SHELL_ESCAPE -static char *shellcmd = NULL; /* For holding last shell command for "!!" */ +static char *shellcmd = NULL; /* For holding last shell command for "!!" */ #endif -static int mca; /* The multicharacter command (action) */ -static int search_type; /* The previous type of search */ -static LINENUM number; /* The number typed by the user */ -static long fraction; /* The fractional part of the number */ +static int mca; /* The multicharacter command (action) */ +static int search_type; /* The previous type of search */ +static LINENUM number; /* The number typed by the user */ +static long fraction; /* The fractional part of the number */ static struct loption *curropt; static int opt_lower; static int optflag; @@ -113,7 +114,6 @@ set_mca(action) int action; { mca = action; - deinit_mouse(); /* we don't want mouse events while entering a cmd */ clear_bot(); clear_cmd(); } @@ -127,7 +127,6 @@ clear_mca(VOID_PARAM) if (mca == 0) return; mca = 0; - init_mouse(); } /* @@ -177,6 +176,8 @@ mca_search(VOID_PARAM) cmd_putstr("Keep-pos "); if (search_type & SRCH_NO_REGEX) cmd_putstr("Regex-off "); + if (search_type & SRCH_WRAP) + cmd_putstr("Wrap "); #if HILITE_SEARCH if (search_type & SRCH_FILTER) @@ -520,9 +521,9 @@ mca_search_char(c) /* * Certain characters as the first char of * the pattern have special meaning: - * ! Toggle the NO_MATCH flag - * * Toggle the PAST_EOF flag - * @ Toggle the FIRST_FILE flag + * ! Toggle the NO_MATCH flag + * * Toggle the PAST_EOF flag + * @ Toggle the FIRST_FILE flag */ if (len_cmdbuf() > 0) return (NO_MCA); @@ -547,6 +548,10 @@ mca_search_char(c) if (mca != A_FILTER) flag = SRCH_NO_MOVE; break; + case CONTROL('W'): /* WRAP around */ + if (mca != A_FILTER) + flag = SRCH_WRAP; + break; case CONTROL('R'): /* Don't use REGULAR EXPRESSIONS */ flag = SRCH_NO_REGEX; break; @@ -558,7 +563,8 @@ mca_search_char(c) if (flag != 0) { - search_type ^= flag; + /* Toggle flag, but keep PAST_EOF and WRAP mutually exclusive. */ + search_type ^= flag | (search_type & (SRCH_PAST_EOF|SRCH_WRAP)); mca_search(); return (MCA_MORE); } @@ -596,9 +602,16 @@ mca_char(c) * Entering digits of a number. * Terminated by a non-digit. */ - if (!((c >= '0' && c <= '9') || c == '.') && - editchar(c, EC_PEEK|EC_NOHISTORY|EC_NOCOMPLETE|EC_NORIGHTLEFT) == A_INVALID) + if ((c >= '0' && c <= '9') || c == '.') + break; + switch (editchar(c, ECF_PEEK|ECF_NOHISTORY|ECF_NOCOMPLETE|ECF_NORIGHTLEFT)) { + case A_NOACTION: + /* + * Ignore this char and get another one. + */ + return (MCA_MORE); + case A_INVALID: /* * Not part of the number. * End the number and treat this char @@ -651,15 +664,44 @@ mca_char(c) */ return (MCA_DONE); - if ((mca == A_F_BRACKET || mca == A_B_BRACKET) && len_cmdbuf() >= 2) + switch (mca) { - /* - * Special case for the bracket-matching commands. - * Execute the command after getting exactly two - * characters from the user. - */ - exec_mca(); - return (MCA_DONE); + case A_F_BRACKET: + case A_B_BRACKET: + if (len_cmdbuf() >= 2) + { + /* + * Special case for the bracket-matching commands. + * Execute the command after getting exactly two + * characters from the user. + */ + exec_mca(); + return (MCA_DONE); + } + break; + case A_F_SEARCH: + case A_B_SEARCH: + if (incr_search) + { + /* Incremental search: do a search after every input char. */ + int st = (search_type & (SRCH_FORW|SRCH_BACK|SRCH_NO_MATCH|SRCH_NO_REGEX|SRCH_NO_MOVE|SRCH_WRAP)); + char *pattern = get_cmdbuf(); + cmd_exec(); + if (*pattern == '\0') + { + /* User has backspaced to an empty pattern. */ + undo_search(1); + } else + { + if (search(st | SRCH_INCR, pattern, 1) != 0) + /* No match, invalid pattern, etc. */ + undo_search(1); + } + /* Redraw the search prompt and search string. */ + mca_search(); + cmd_repaint(NULL); + } + break; } /* @@ -695,12 +737,6 @@ make_display(VOID_PARAM) if (empty_screen()) { if (initial_scrpos.pos == NULL_POSITION) - /* - * {{ Maybe this should be: - * jump_loc(ch_zero(), jump_sline); - * but this behavior seems rather unexpected - * on the first screen. }} - */ jump_loc(ch_zero(), 1); else jump_loc(initial_scrpos.pos, initial_scrpos.ln); @@ -793,11 +829,16 @@ prompt(VOID_PARAM) clear_cmd(); forw_prompt = 0; p = pr_string(); +#if HILITE_SEARCH if (is_filtering()) putstr("& "); +#endif if (p == NULL || *p == '\0') + { + at_enter(AT_NORMAL|AT_COLOR_PROMPT); putchr(':'); - else + at_exit(); + } else { #if MSDOS_COMPILER==WIN32C WCHAR w[MAX_PATH*2]; @@ -807,7 +848,7 @@ prompt(VOID_PARAM) 0, w, -1, a, sizeof(a), NULL, NULL); p = a; #endif - at_enter(AT_STANDOUT); + at_enter(AT_STANDOUT|AT_COLOR_PROMPT); putstr(p); at_exit(); } @@ -843,7 +884,7 @@ getcc_end_command(VOID_PARAM) return ('\n'); default: /* 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 getccu(VOID_PARAM) { - LWCHAR c; - if (ungot == NULL) + LWCHAR c = 0; + while (c == 0) { - /* Normal case: no ungotten chars. - * Get char from the user. */ - c = getchr(); - } else - { - /* Ungotten chars available: - * Take the top of stack (most recent). */ - struct ungot *ug = ungot; - c = ug->ug_char; - ungot = ug->ug_next; - free(ug); + if (ungot == NULL) + { + /* Normal case: no ungotten chars. + * Get char from the user. */ + c = getchr(); + } else + { + /* Ungotten chars available: + * Take the top of stack (most recent). */ + struct ungot *ug = ungot; + c = ug->ug_char; + ungot = ug->ug_next; + free(ug); - if (c == CHAR_END_COMMAND) - c = getcc_end_command(); + if (c == CHAR_END_COMMAND) + c = getcc_end_command(); + } } return (c); } @@ -947,6 +991,28 @@ ungetcc(c) ungot = ug; } +/* + * "Unget" a command character. + * If any other chars are already ungotten, put this one after those. + */ + public void +ungetcc_back(c) + LWCHAR c; +{ + struct ungot *ug = (struct ungot *) ecalloc(1, sizeof(struct ungot)); + ug->ug_char = c; + ug->ug_next = NULL; + if (ungot == NULL) + ungot = ug; + else + { + struct ungot *pu; + for (pu = ungot; pu->ug_next != NULL; pu = pu->ug_next) + continue; + pu->ug_next = ug; + } +} + /* * Unget a whole string of command characters. * The next sequence of getcc()'s will return this string. @@ -955,10 +1021,8 @@ ungetcc(c) ungetsc(s) char *s; { - char *p; - - for (p = s + strlen(s) - 1; p >= s; p--) - ungetcc(*p); + while (*s != '\0') + ungetcc_back(*s++); } /* @@ -1122,6 +1186,7 @@ commands(VOID_PARAM) int action; char *cbuf; int newaction; + int save_jump_sline; int save_search_type; char *extra; char tbuf[2]; @@ -1423,11 +1488,18 @@ commands(VOID_PARAM) case A_GOLINE: /* * Go to line N, default beginning of file. + * If N <= 0, ignore jump_sline in order to avoid + * empty lines before the beginning of the file. */ + save_jump_sline = jump_sline; if (number <= 0) + { number = 1; + jump_sline = 0; + } cmd_exec(); jump_back(number); + jump_sline = save_jump_sline; break; case A_PERCENT: @@ -1493,7 +1565,7 @@ commands(VOID_PARAM) case A_VERSION: /* - * Print version number, without the "@(#)". + * Print version number. */ cmd_exec(); dispversion(); @@ -1524,10 +1596,10 @@ commands(VOID_PARAM) /* * Define abbreviation for a commonly used sequence below. */ -#define DO_SEARCH() \ - if (number <= 0) number = 1; \ - mca_search(); \ - cmd_exec(); \ +#define DO_SEARCH() \ + if (number <= 0) number = 1; \ + mca_search(); \ + cmd_exec(); \ multi_search((char *)NULL, (int) number, 0); @@ -1604,10 +1676,11 @@ commands(VOID_PARAM) break; case A_UNDO_SEARCH: + case A_CLR_SEARCH: /* * Clear search string highlighting. */ - undo_search(); + undo_search(action == A_CLR_SEARCH); break; case A_HELP: diff --git a/contrib/less/cvt.c b/contrib/less/cvt.c index e850a51452a2..9cf44b894e7d 100644 --- a/contrib/less/cvt.c +++ b/contrib/less/cvt.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -77,6 +77,7 @@ cvt_text(odst, osrc, chpos, lenp, ops) { int src_pos = (int) (src - osrc); int dst_pos = (int) (dst - odst); + struct ansi_state *pansi; ch = step_char(&src, +1, src_end); if ((ops & CVT_BS) && ch == '\b' && dst > odst) { @@ -85,13 +86,16 @@ cvt_text(odst, osrc, chpos, lenp, ops) dst--; } while (dst > odst && utf_mode && !IS_ASCII_OCTET(*dst) && !IS_UTF8_LEAD(*dst)); - } else if ((ops & CVT_ANSI) && IS_CSI_START(ch)) + } else if ((ops & CVT_ANSI) && (pansi = ansi_start(ch)) != NULL) { /* Skip to end of ANSI escape sequence. */ - src++; /* skip the CSI start char */ while (src < src_end) - if (!is_ansi_middle(*src++)) + { + if (ansi_step(pansi, ch) != ANSI_MID) break; + ch = *src++; + } + ansi_done(pansi); } else { /* Just copy the char to the destination buffer. */ diff --git a/contrib/less/decode.c b/contrib/less/decode.c index c5467ffe2697..f3bfb7a8ead2 100644 --- a/contrib/less/decode.c +++ b/contrib/less/decode.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -14,7 +14,7 @@ * This is all table driven. * A command table is a sequence of command descriptors. * Each command descriptor is a sequence of bytes with the following format: - * ...<0> + * ...<0> * The characters c1,c2,...,cN are the command string; that is, * the characters which the user must type. * It is terminated by a null <0> byte. @@ -48,173 +48,176 @@ extern int sc_height; static unsigned char cmdtable[] = { - '\r',0, A_F_LINE, - '\n',0, A_F_LINE, - 'e',0, A_F_LINE, - 'j',0, A_F_LINE, - SK(SK_DOWN_ARROW),0, A_F_LINE, - CONTROL('E'),0, A_F_LINE, - CONTROL('N'),0, A_F_LINE, - 'k',0, A_B_LINE, - 'y',0, A_B_LINE, - CONTROL('Y'),0, A_B_LINE, - SK(SK_CONTROL_K),0, A_B_LINE, - CONTROL('P'),0, A_B_LINE, - SK(SK_UP_ARROW),0, A_B_LINE, - 'J',0, A_FF_LINE, - 'K',0, A_BF_LINE, - 'Y',0, A_BF_LINE, - 'd',0, A_F_SCROLL, - CONTROL('D'),0, A_F_SCROLL, - 'u',0, A_B_SCROLL, - CONTROL('U'),0, A_B_SCROLL, - ESC,'[','M',0, A_X11MOUSE_IN, - ESC,'[','<',0, A_X116MOUSE_IN, - ' ',0, A_F_SCREEN, - 'f',0, A_F_SCREEN, - CONTROL('F'),0, A_F_SCREEN, - CONTROL('V'),0, A_F_SCREEN, - SK(SK_PAGE_DOWN),0, A_F_SCREEN, - 'b',0, A_B_SCREEN, - CONTROL('B'),0, A_B_SCREEN, - ESC,'v',0, A_B_SCREEN, - SK(SK_PAGE_UP),0, A_B_SCREEN, - 'z',0, A_F_WINDOW, - 'w',0, A_B_WINDOW, - ESC,' ',0, A_FF_SCREEN, - 'F',0, A_F_FOREVER, - ESC,'F',0, A_F_UNTIL_HILITE, - 'R',0, A_FREPAINT, - 'r',0, A_REPAINT, - CONTROL('R'),0, A_REPAINT, - CONTROL('L'),0, A_REPAINT, - ESC,'u',0, A_UNDO_SEARCH, - 'g',0, A_GOLINE, - SK(SK_HOME),0, A_GOLINE, - '<',0, A_GOLINE, - ESC,'<',0, A_GOLINE, - 'p',0, A_PERCENT, - '%',0, A_PERCENT, - ESC,'[',0, A_LSHIFT, - ESC,']',0, A_RSHIFT, - ESC,'(',0, A_LSHIFT, - ESC,')',0, A_RSHIFT, - ESC,'{',0, A_LLSHIFT, - ESC,'}',0, A_RRSHIFT, - SK(SK_RIGHT_ARROW),0, A_RSHIFT, - SK(SK_LEFT_ARROW),0, A_LSHIFT, - SK(SK_CTL_RIGHT_ARROW),0, A_RRSHIFT, - SK(SK_CTL_LEFT_ARROW),0, A_LLSHIFT, - '{',0, A_F_BRACKET|A_EXTRA, '{','}',0, - '}',0, A_B_BRACKET|A_EXTRA, '{','}',0, - '(',0, A_F_BRACKET|A_EXTRA, '(',')',0, - ')',0, A_B_BRACKET|A_EXTRA, '(',')',0, - '[',0, A_F_BRACKET|A_EXTRA, '[',']',0, - ']',0, A_B_BRACKET|A_EXTRA, '[',']',0, - ESC,CONTROL('F'),0, A_F_BRACKET, - ESC,CONTROL('B'),0, A_B_BRACKET, - 'G',0, A_GOEND, - ESC,'G',0, A_GOEND_BUF, - ESC,'>',0, A_GOEND, - '>',0, A_GOEND, - SK(SK_END),0, A_GOEND, - 'P',0, A_GOPOS, + '\r',0, A_F_LINE, + '\n',0, A_F_LINE, + 'e',0, A_F_LINE, + 'j',0, A_F_LINE, + SK(SK_DOWN_ARROW),0, A_F_LINE, + CONTROL('E'),0, A_F_LINE, + CONTROL('N'),0, A_F_LINE, + 'k',0, A_B_LINE, + 'y',0, A_B_LINE, + CONTROL('Y'),0, A_B_LINE, + SK(SK_CONTROL_K),0, A_B_LINE, + CONTROL('P'),0, A_B_LINE, + SK(SK_UP_ARROW),0, A_B_LINE, + 'J',0, A_FF_LINE, + 'K',0, A_BF_LINE, + 'Y',0, A_BF_LINE, + 'd',0, A_F_SCROLL, + CONTROL('D'),0, A_F_SCROLL, + 'u',0, A_B_SCROLL, + CONTROL('U'),0, A_B_SCROLL, + ESC,'[','M',0, A_X11MOUSE_IN, + ESC,'[','<',0, A_X116MOUSE_IN, + ' ',0, A_F_SCREEN, + 'f',0, A_F_SCREEN, + CONTROL('F'),0, A_F_SCREEN, + CONTROL('V'),0, A_F_SCREEN, + SK(SK_PAGE_DOWN),0, A_F_SCREEN, + 'b',0, A_B_SCREEN, + CONTROL('B'),0, A_B_SCREEN, + ESC,'v',0, A_B_SCREEN, + SK(SK_PAGE_UP),0, A_B_SCREEN, + 'z',0, A_F_WINDOW, + 'w',0, A_B_WINDOW, + ESC,' ',0, A_FF_SCREEN, + 'F',0, A_F_FOREVER, + ESC,'F',0, A_F_UNTIL_HILITE, + 'R',0, A_FREPAINT, + 'r',0, A_REPAINT, + CONTROL('R'),0, A_REPAINT, + CONTROL('L'),0, A_REPAINT, + ESC,'u',0, A_UNDO_SEARCH, + ESC,'U',0, A_CLR_SEARCH, + 'g',0, A_GOLINE, + SK(SK_HOME),0, A_GOLINE, + '<',0, A_GOLINE, + ESC,'<',0, A_GOLINE, + 'p',0, A_PERCENT, + '%',0, A_PERCENT, + ESC,'[',0, A_LSHIFT, + ESC,']',0, A_RSHIFT, + ESC,'(',0, A_LSHIFT, + ESC,')',0, A_RSHIFT, + ESC,'{',0, A_LLSHIFT, + ESC,'}',0, A_RRSHIFT, + SK(SK_RIGHT_ARROW),0, A_RSHIFT, + SK(SK_LEFT_ARROW),0, A_LSHIFT, + SK(SK_CTL_RIGHT_ARROW),0, A_RRSHIFT, + SK(SK_CTL_LEFT_ARROW),0, A_LLSHIFT, + '{',0, A_F_BRACKET|A_EXTRA, '{','}',0, + '}',0, A_B_BRACKET|A_EXTRA, '{','}',0, + '(',0, A_F_BRACKET|A_EXTRA, '(',')',0, + ')',0, A_B_BRACKET|A_EXTRA, '(',')',0, + '[',0, A_F_BRACKET|A_EXTRA, '[',']',0, + ']',0, A_B_BRACKET|A_EXTRA, '[',']',0, + ESC,CONTROL('F'),0, A_F_BRACKET, + ESC,CONTROL('B'),0, A_B_BRACKET, + 'G',0, A_GOEND, + ESC,'G',0, A_GOEND_BUF, + ESC,'>',0, A_GOEND, + '>',0, A_GOEND, + SK(SK_END),0, A_GOEND, + 'P',0, A_GOPOS, - '0',0, A_DIGIT, - '1',0, A_DIGIT, - '2',0, A_DIGIT, - '3',0, A_DIGIT, - '4',0, A_DIGIT, - '5',0, A_DIGIT, - '6',0, A_DIGIT, - '7',0, A_DIGIT, - '8',0, A_DIGIT, - '9',0, A_DIGIT, - '.',0, A_DIGIT, + '0',0, A_DIGIT, + '1',0, A_DIGIT, + '2',0, A_DIGIT, + '3',0, A_DIGIT, + '4',0, A_DIGIT, + '5',0, A_DIGIT, + '6',0, A_DIGIT, + '7',0, A_DIGIT, + '8',0, A_DIGIT, + '9',0, A_DIGIT, + '.',0, A_DIGIT, - '=',0, A_STAT, - CONTROL('G'),0, A_STAT, - ':','f',0, A_STAT, - '/',0, A_F_SEARCH, - '?',0, A_B_SEARCH, - ESC,'/',0, A_F_SEARCH|A_EXTRA, '*',0, - ESC,'?',0, A_B_SEARCH|A_EXTRA, '*',0, - 'n',0, A_AGAIN_SEARCH, - ESC,'n',0, A_T_AGAIN_SEARCH, - 'N',0, A_REVERSE_SEARCH, - ESC,'N',0, A_T_REVERSE_SEARCH, - '&',0, A_FILTER, - 'm',0, A_SETMARK, - 'M',0, A_SETMARKBOT, - ESC,'m',0, A_CLRMARK, - '\'',0, A_GOMARK, - CONTROL('X'),CONTROL('X'),0, A_GOMARK, - 'E',0, A_EXAMINE, - ':','e',0, A_EXAMINE, - CONTROL('X'),CONTROL('V'),0, A_EXAMINE, - ':','n',0, A_NEXT_FILE, - ':','p',0, A_PREV_FILE, - 't',0, A_NEXT_TAG, - 'T',0, A_PREV_TAG, - ':','x',0, A_INDEX_FILE, - ':','d',0, A_REMOVE_FILE, - '-',0, A_OPT_TOGGLE, - ':','t',0, A_OPT_TOGGLE|A_EXTRA, 't',0, - 's',0, A_OPT_TOGGLE|A_EXTRA, 'o',0, - '_',0, A_DISP_OPTION, - '|',0, A_PIPE, - 'v',0, A_VISUAL, - '!',0, A_SHELL, - '+',0, A_FIRSTCMD, + '=',0, A_STAT, + CONTROL('G'),0, A_STAT, + ':','f',0, A_STAT, + '/',0, A_F_SEARCH, + '?',0, A_B_SEARCH, + ESC,'/',0, A_F_SEARCH|A_EXTRA, '*',0, + ESC,'?',0, A_B_SEARCH|A_EXTRA, '*',0, + 'n',0, A_AGAIN_SEARCH, + ESC,'n',0, A_T_AGAIN_SEARCH, + 'N',0, A_REVERSE_SEARCH, + ESC,'N',0, A_T_REVERSE_SEARCH, + '&',0, A_FILTER, + 'm',0, A_SETMARK, + 'M',0, A_SETMARKBOT, + ESC,'m',0, A_CLRMARK, + '\'',0, A_GOMARK, + CONTROL('X'),CONTROL('X'),0, A_GOMARK, + 'E',0, A_EXAMINE, + ':','e',0, A_EXAMINE, + CONTROL('X'),CONTROL('V'),0, A_EXAMINE, + ':','n',0, A_NEXT_FILE, + ':','p',0, A_PREV_FILE, + 't',0, A_NEXT_TAG, + 'T',0, A_PREV_TAG, + ':','x',0, A_INDEX_FILE, + ':','d',0, A_REMOVE_FILE, + '-',0, A_OPT_TOGGLE, + ':','t',0, A_OPT_TOGGLE|A_EXTRA, 't',0, + 's',0, A_OPT_TOGGLE|A_EXTRA, 'o',0, + '_',0, A_DISP_OPTION, + '|',0, A_PIPE, + 'v',0, A_VISUAL, + '!',0, A_SHELL, + '+',0, A_FIRSTCMD, - 'H',0, A_HELP, - 'h',0, A_HELP, - SK(SK_F1),0, A_HELP, - 'V',0, A_VERSION, - 'q',0, A_QUIT, - 'Q',0, A_QUIT, - ':','q',0, A_QUIT, - ':','Q',0, A_QUIT, - 'Z','Z',0, A_QUIT + 'H',0, A_HELP, + 'h',0, A_HELP, + SK(SK_F1),0, A_HELP, + 'V',0, A_VERSION, + 'q',0, A_QUIT, + 'Q',0, A_QUIT, + ':','q',0, A_QUIT, + ':','Q',0, A_QUIT, + 'Z','Z',0, A_QUIT }; static unsigned char edittable[] = { - '\t',0, EC_F_COMPLETE, /* TAB */ - '\17',0, EC_B_COMPLETE, /* BACKTAB */ - SK(SK_BACKTAB),0, EC_B_COMPLETE, /* BACKTAB */ - ESC,'\t',0, EC_B_COMPLETE, /* ESC TAB */ - CONTROL('L'),0, EC_EXPAND, /* CTRL-L */ - CONTROL('V'),0, EC_LITERAL, /* BACKSLASH */ - CONTROL('A'),0, EC_LITERAL, /* BACKSLASH */ - ESC,'l',0, EC_RIGHT, /* ESC l */ - SK(SK_RIGHT_ARROW),0, EC_RIGHT, /* RIGHTARROW */ - ESC,'h',0, EC_LEFT, /* ESC h */ - SK(SK_LEFT_ARROW),0, EC_LEFT, /* LEFTARROW */ - ESC,'b',0, EC_W_LEFT, /* ESC b */ - ESC,SK(SK_LEFT_ARROW),0, EC_W_LEFT, /* ESC LEFTARROW */ - SK(SK_CTL_LEFT_ARROW),0, EC_W_LEFT, /* CTRL-LEFTARROW */ - ESC,'w',0, EC_W_RIGHT, /* ESC w */ - ESC,SK(SK_RIGHT_ARROW),0, EC_W_RIGHT, /* ESC RIGHTARROW */ - SK(SK_CTL_RIGHT_ARROW),0, EC_W_RIGHT, /* CTRL-RIGHTARROW */ - ESC,'i',0, EC_INSERT, /* ESC i */ - SK(SK_INSERT),0, EC_INSERT, /* INSERT */ - ESC,'x',0, EC_DELETE, /* ESC x */ - SK(SK_DELETE),0, EC_DELETE, /* DELETE */ - ESC,'X',0, EC_W_DELETE, /* ESC X */ - ESC,SK(SK_DELETE),0, EC_W_DELETE, /* ESC DELETE */ - SK(SK_CTL_DELETE),0, EC_W_DELETE, /* CTRL-DELETE */ - SK(SK_CTL_BACKSPACE),0, EC_W_BACKSPACE, /* CTRL-BACKSPACE */ - ESC,'\b',0, EC_W_BACKSPACE, /* ESC BACKSPACE */ - ESC,'0',0, EC_HOME, /* ESC 0 */ - SK(SK_HOME),0, EC_HOME, /* HOME */ - ESC,'$',0, EC_END, /* ESC $ */ - SK(SK_END),0, EC_END, /* END */ - ESC,'k',0, EC_UP, /* ESC k */ - SK(SK_UP_ARROW),0, EC_UP, /* UPARROW */ - ESC,'j',0, EC_DOWN, /* ESC j */ - SK(SK_DOWN_ARROW),0, EC_DOWN, /* DOWNARROW */ - CONTROL('G'),0, EC_ABORT, /* CTRL-G */ + '\t',0, EC_F_COMPLETE, /* TAB */ + '\17',0, EC_B_COMPLETE, /* BACKTAB */ + SK(SK_BACKTAB),0, EC_B_COMPLETE, /* BACKTAB */ + ESC,'\t',0, EC_B_COMPLETE, /* ESC TAB */ + CONTROL('L'),0, EC_EXPAND, /* CTRL-L */ + CONTROL('V'),0, EC_LITERAL, /* BACKSLASH */ + CONTROL('A'),0, EC_LITERAL, /* BACKSLASH */ + ESC,'l',0, EC_RIGHT, /* ESC l */ + SK(SK_RIGHT_ARROW),0, EC_RIGHT, /* RIGHTARROW */ + ESC,'h',0, EC_LEFT, /* ESC h */ + SK(SK_LEFT_ARROW),0, EC_LEFT, /* LEFTARROW */ + ESC,'b',0, EC_W_LEFT, /* ESC b */ + ESC,SK(SK_LEFT_ARROW),0, EC_W_LEFT, /* ESC LEFTARROW */ + SK(SK_CTL_LEFT_ARROW),0, EC_W_LEFT, /* CTRL-LEFTARROW */ + ESC,'w',0, EC_W_RIGHT, /* ESC w */ + ESC,SK(SK_RIGHT_ARROW),0, EC_W_RIGHT, /* ESC RIGHTARROW */ + SK(SK_CTL_RIGHT_ARROW),0, EC_W_RIGHT, /* CTRL-RIGHTARROW */ + ESC,'i',0, EC_INSERT, /* ESC i */ + SK(SK_INSERT),0, EC_INSERT, /* INSERT */ + ESC,'x',0, EC_DELETE, /* ESC x */ + SK(SK_DELETE),0, EC_DELETE, /* DELETE */ + ESC,'X',0, EC_W_DELETE, /* ESC X */ + ESC,SK(SK_DELETE),0, EC_W_DELETE, /* ESC DELETE */ + SK(SK_CTL_DELETE),0, EC_W_DELETE, /* CTRL-DELETE */ + SK(SK_CTL_BACKSPACE),0, EC_W_BACKSPACE, /* CTRL-BACKSPACE */ + ESC,'\b',0, EC_W_BACKSPACE, /* ESC BACKSPACE */ + ESC,'0',0, EC_HOME, /* ESC 0 */ + SK(SK_HOME),0, EC_HOME, /* HOME */ + ESC,'$',0, EC_END, /* ESC $ */ + SK(SK_END),0, EC_END, /* END */ + ESC,'k',0, EC_UP, /* ESC k */ + SK(SK_UP_ARROW),0, EC_UP, /* UPARROW */ + ESC,'j',0, EC_DOWN, /* ESC j */ + SK(SK_DOWN_ARROW),0, EC_DOWN, /* DOWNARROW */ + CONTROL('G'),0, EC_ABORT, /* CTRL-G */ + ESC,'[','M',0, EC_X11MOUSE, /* X11 mouse report */ + ESC,'[','<',0, EC_X116MOUSE, /* X11 1006 mouse report */ }; /* @@ -487,11 +490,14 @@ getcc_int(pterm) * The prefix ("\e[M") has already been read. */ static int -x11mouse_action(VOID_PARAM) +x11mouse_action(skip) + int skip; { int b = getcc() - X11MOUSE_OFFSET; int x = getcc() - X11MOUSE_OFFSET-1; int y = getcc() - X11MOUSE_OFFSET-1; + if (skip) + return (A_NOACTION); switch (b) { default: return (A_NOACTION); @@ -509,7 +515,8 @@ x11mouse_action(VOID_PARAM) * The prefix ("\e[<") has already been read. */ static int -x116mouse_action(VOID_PARAM) +x116mouse_action(skip) + int skip; { char ch; int x, y; @@ -519,6 +526,8 @@ x116mouse_action(VOID_PARAM) if (x < 0 || ch != ';') return (A_NOACTION); y = getcc_int(&ch) - 1; if (y < 0) return (A_NOACTION); + if (skip) + return (A_NOACTION); switch (b) { case X11MOUSE_WHEEL_DOWN: return mouse_wheel_down(); @@ -580,9 +589,9 @@ cmd_search(cmd, table, endtable, sp) a &= ~A_EXTRA; } if (a == A_X11MOUSE_IN) - a = x11mouse_action(); + a = x11mouse_action(0); else if (a == A_X116MOUSE_IN) - a = x116mouse_action(); + a = x116mouse_action(0); return (a); } } else if (*q == '\0') @@ -924,7 +933,6 @@ editchar(c, flags) #if MSDOS_COMPILER==WIN32C if (!win32_kbhit()) #endif - return (EC_LINEKILL); } @@ -934,15 +942,20 @@ editchar(c, flags) */ nch = 0; do { - if (nch > 0) + if (nch > 0) c = getcc(); usercmd[nch] = c; usercmd[nch+1] = '\0'; nch++; action = ecmd_decode(usercmd, &s); - } while (action == A_PREFIX); - - if (flags & EC_NORIGHTLEFT) + } while (action == A_PREFIX && nch < MAX_CMDLEN); + + if (action == EC_X11MOUSE) + return (x11mouse_action(1)); + if (action == EC_X116MOUSE) + return (x116mouse_action(1)); + + if (flags & ECF_NORIGHTLEFT) { switch (action) { @@ -953,7 +966,7 @@ editchar(c, flags) } } #if CMD_HISTORY - if (flags & EC_NOHISTORY) + if (flags & ECF_NOHISTORY) { /* * The caller says there is no history list. @@ -969,7 +982,7 @@ editchar(c, flags) } #endif #if TAB_COMPLETE_FILENAME - if (flags & EC_NOCOMPLETE) + if (flags & ECF_NOCOMPLETE) { /* * The caller says we don't want any filename completion cmds. @@ -985,7 +998,7 @@ editchar(c, flags) } } #endif - if ((flags & EC_PEEK) || action == A_INVALID) + if ((flags & ECF_PEEK) || action == A_INVALID) { /* * We're just peeking, or we didn't understand the command. diff --git a/contrib/less/edit.c b/contrib/less/edit.c index 3702b5051cec..12631dba6bac 100644 --- a/contrib/less/edit.c +++ b/contrib/less/edit.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -20,13 +20,12 @@ public int fd0 = 0; extern int new_file; -extern int errmsgs; extern int cbufs; extern char *every_first_cmd; -extern int any_display; extern int force_open; extern int is_tty; extern int sigs; +extern int hshift; extern IFILE curr_ifile; extern IFILE old_ifile; extern struct scrpos initial_scrpos; @@ -47,7 +46,6 @@ public dev_t curr_dev; public ino_t curr_ino; #endif - /* * Textlist functions deal with a list of words separated by spaces. * init_textlist sets up a textlist structure. @@ -242,7 +240,6 @@ edit_ifile(ifile) { int f; int answer; - int no_display; int chflags; char *filename; char *open_filename; @@ -462,14 +459,12 @@ edit_ifile(ifile) #endif if (every_first_cmd != NULL) { - ungetcc(CHAR_END_COMMAND); ungetsc(every_first_cmd); + ungetcc_back(CHAR_END_COMMAND); } } - no_display = !any_display; flush(); - any_display = TRUE; if (is_tty) { @@ -485,6 +480,7 @@ edit_ifile(ifile) #if HILITE_SEARCH clr_hilite(); #endif + hshift = 0; if (strcmp(filename, FAKE_HELPFILE) && strcmp(filename, FAKE_EMPTYFILE)) { char *qfilename = shell_quote(filename); @@ -492,17 +488,6 @@ edit_ifile(ifile) free(qfilename); } - if (no_display && errmsgs > 0) - { - /* - * We displayed some messages on error output - * (file descriptor 2; see error() function). - * Before erasing the screen contents, - * display the file name and wait for a keystroke. - */ - parg.p_string = filename; - error("%s", &parg); - } } free(filename); return (0); @@ -784,6 +769,8 @@ cat_file(VOID_PARAM) #if LOGFILE +#define OVERWRITE_OPTIONS "Overwrite, Append, Don't log, or Quit?" + /* * If the user asked for a log file and our input file * is standard input, create the log file. @@ -827,7 +814,7 @@ use_logfile(filename) * Ask user what to do. */ parg.p_string = filename; - answer = query("Warning: \"%s\" exists; Overwrite, Append or Don't log? ", &parg); + answer = query("Warning: \"%s\" exists; "OVERWRITE_OPTIONS" ", &parg); } loop: @@ -855,14 +842,12 @@ use_logfile(filename) * Don't do anything. */ return; - case 'q': - quit(QUIT_OK); - /*NOTREACHED*/ default: /* * Eh? */ - answer = query("Overwrite, Append, or Don't log? (Type \"O\", \"A\", \"D\" or \"q\") ", NULL_PARG); + + answer = query(OVERWRITE_OPTIONS" (Type \"O\", \"A\", \"D\" or \"Q\") ", NULL_PARG); goto loop; } diff --git a/contrib/less/filename.c b/contrib/less/filename.c index adb5e646c112..177cb946364a 100644 --- a/contrib/less/filename.c +++ b/contrib/less/filename.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -23,7 +23,7 @@ #if MSDOS_COMPILER==DJGPPC #include #include -#define _MAX_PATH PATH_MAX +#define _MAX_PATH PATH_MAX #endif #endif #ifdef _OSK @@ -36,10 +36,10 @@ #if HAVE_STAT #include #ifndef S_ISDIR -#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #endif #ifndef S_ISREG -#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #endif #endif @@ -312,7 +312,7 @@ fexpand(s) char *e; IFILE ifile; -#define fchar_ifile(c) \ +#define fchar_ifile(c) \ ((c) == '%' ? curr_ifile : \ (c) == '#' ? old_ifile : NULL_IFILE) @@ -486,9 +486,12 @@ bin_file(f) } else { LWCHAR c = step_char(&p, +1, edata); - if (ctldisp == OPT_ONPLUS && IS_CSI_START(c)) - skip_ansi(&p, edata); - else if (binary_char(c)) + struct ansi_state *pansi; + if (ctldisp == OPT_ONPLUS && (pansi = ansi_start(c)) != NULL) + { + skip_ansi(pansi, &p, edata); + ansi_done(pansi); + } else if (binary_char(c)) bin_count++; } } @@ -648,7 +651,7 @@ lglob(filename) qfilename = shell_quote(p); if (qfilename != NULL) { - length += strlen(qfilename) + 1; + length += strlen(qfilename) + 1; free(qfilename); } } @@ -914,7 +917,7 @@ open_altfile(filename, pf, pfd) int f; /* - * The first time we open the file, read one char + * The alt file is a pipe. Read one char * to see if the pipe will produce any data. * If it does, push the char back on the pipe. */ @@ -931,18 +934,22 @@ open_altfile(filename, pf, pfd) */ int status = pclose(fd); if (returnfd > 1 && status == 0) { + /* File is empty. */ *pfd = NULL; *pf = -1; return (save(FAKE_EMPTYFILE)); } + /* No alt file. */ return (NULL); } + /* Alt pipe contains data, so use it. */ ch_ungetchar(c); *pfd = (void *) fd; *pf = f; return (save("-")); } #endif + /* The alt file is a regular file. Read its name from LESSOPEN. */ cmd = readfd(fd); pclose(fd); if (*cmd == '\0') @@ -972,7 +979,7 @@ close_altfile(altfilename, filename) return; ch_ungetchar(-1); if ((lessclose = lgetenv("LESSCLOSE")) == NULL) - return; + return; if (num_pct_s(lessclose) > 2) { error("LESSCLOSE ignored; must contain no more than 2 %%s", NULL_PARG); diff --git a/contrib/less/forwback.c b/contrib/less/forwback.c index 76ecc162c3ca..db16da4a4aff 100644 --- a/contrib/less/forwback.c +++ b/contrib/less/forwback.c @@ -1,6 +1,6 @@ /* $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 * License or the Less License, as specified in the README file. @@ -49,6 +49,13 @@ extern char *tagoption; static void eof_bell(VOID_PARAM) { +#if HAVE_TIME + static time_type last_eof_bell = 0; + time_type now = get_time(); + if (now == last_eof_bell) /* max once per second */ + return; + last_eof_bell = now; +#endif if (quiet == NOT_QUIET) bell(); else @@ -189,7 +196,7 @@ forw(n, pos, force, only_last, nblank) { clear(); home(); - } else if (!first_time) + } else if (!first_time && !is_filtering()) { putstr("...skipping...\n"); } diff --git a/contrib/less/funcs.h b/contrib/less/funcs.h index fb3c7bbfed92..12930356c938 100644 --- a/contrib/less/funcs.h +++ b/contrib/less/funcs.h @@ -11,6 +11,7 @@ public void init_mouse LESSPARAMS ((VOID_PARAM)); public void deinit_mouse LESSPARAMS ((VOID_PARAM)); public void init LESSPARAMS ((VOID_PARAM)); public void deinit LESSPARAMS ((VOID_PARAM)); +public int interactive LESSPARAMS ((VOID_PARAM)); public void home LESSPARAMS ((VOID_PARAM)); public void add_line LESSPARAMS ((VOID_PARAM)); public void remove_top LESSPARAMS ((int n)); @@ -24,12 +25,12 @@ public void bell LESSPARAMS ((VOID_PARAM)); public void clear LESSPARAMS ((VOID_PARAM)); public void clear_eol LESSPARAMS ((VOID_PARAM)); public void clear_bot LESSPARAMS ((VOID_PARAM)); +public COLOR_TYPE parse_color LESSPARAMS ((char *str, int *p_fg, int *p_bg)); public void at_enter LESSPARAMS ((int attr)); public void at_exit LESSPARAMS ((VOID_PARAM)); public void at_switch LESSPARAMS ((int attr)); public int is_at_equiv LESSPARAMS ((int attr1, int attr2)); public int apply_at_specials LESSPARAMS ((int attr)); -public void backspace LESSPARAMS ((VOID_PARAM)); public void putbs LESSPARAMS ((VOID_PARAM)); public int win32_kbhit LESSPARAMS ((VOID_PARAM)); public char WIN32getch LESSPARAMS ((VOID_PARAM)); @@ -75,6 +76,7 @@ public void cmd_reset LESSPARAMS ((VOID_PARAM)); public void clear_cmd LESSPARAMS ((VOID_PARAM)); public void cmd_putstr LESSPARAMS ((constant char *s)); public int len_cmdbuf LESSPARAMS ((VOID_PARAM)); +public void cmd_repaint LESSPARAMS ((constant char *old_cp)); public void set_mlist LESSPARAMS ((void *mlist, int cmdflags)); public void cmd_addhist LESSPARAMS ((struct mlist *mlist, constant char *cmd, int modified)); public void cmd_accept LESSPARAMS ((VOID_PARAM)); @@ -88,6 +90,7 @@ public int in_mca LESSPARAMS ((VOID_PARAM)); public void dispversion LESSPARAMS ((VOID_PARAM)); public int getcc LESSPARAMS ((VOID_PARAM)); public void ungetcc LESSPARAMS ((LWCHAR c)); +public void ungetcc_back LESSPARAMS ((LWCHAR c)); public void ungetsc LESSPARAMS ((char *s)); public LWCHAR peekcc LESSPARAMS ((VOID_PARAM)); public void commands LESSPARAMS ((VOID_PARAM)); @@ -155,6 +158,7 @@ public IFILE getoff_ifile LESSPARAMS ((IFILE ifile)); public int nifile LESSPARAMS ((VOID_PARAM)); public IFILE get_ifile LESSPARAMS ((char *filename, IFILE prev)); public char * get_filename LESSPARAMS ((IFILE ifile)); +public char * get_real_filename LESSPARAMS ((IFILE ifile)); public int get_index LESSPARAMS ((IFILE ifile)); public void store_pos LESSPARAMS ((IFILE ifile, struct scrpos *scrpos)); public void get_pos LESSPARAMS ((IFILE ifile, struct scrpos *scrpos)); @@ -169,6 +173,7 @@ public void * get_altpipe LESSPARAMS ((IFILE ifile)); public void set_altfilename LESSPARAMS ((IFILE ifile, char *altfilename)); public char * get_altfilename LESSPARAMS ((IFILE ifile)); public void if_dump LESSPARAMS ((VOID_PARAM)); +public POSITION forw_line_seg LESSPARAMS ((POSITION curr_pos, int get_segpos)); public POSITION forw_line LESSPARAMS ((POSITION curr_pos)); public POSITION back_line LESSPARAMS ((POSITION curr_pos)); public void set_attnpos LESSPARAMS ((POSITION pos)); @@ -182,20 +187,27 @@ public void jump_loc LESSPARAMS ((POSITION pos, int sline)); public void init_line LESSPARAMS ((VOID_PARAM)); public int is_ascii_char LESSPARAMS ((LWCHAR ch)); public void prewind LESSPARAMS ((VOID_PARAM)); -public void plinenum LESSPARAMS ((POSITION pos)); +public void plinestart LESSPARAMS ((POSITION pos)); +public int line_pfx_width LESSPARAMS ((VOID_PARAM)); public void pshift_all LESSPARAMS ((VOID_PARAM)); +public int pwidth LESSPARAMS ((LWCHAR ch, int a, LWCHAR prev_ch, int prev_a)); public int is_ansi_end LESSPARAMS ((LWCHAR ch)); public int is_ansi_middle LESSPARAMS ((LWCHAR ch)); -public void skip_ansi LESSPARAMS ((char **pp, constant char *limit)); +public void skip_ansi LESSPARAMS ((struct ansi_state *pansi, char **pp, constant char *limit)); +public struct ansi_state * ansi_start LESSPARAMS ((LWCHAR ch)); +public int ansi_step LESSPARAMS ((struct ansi_state *pansi, LWCHAR ch)); +public void ansi_done LESSPARAMS ((struct ansi_state *pansi)); public int pappend LESSPARAMS ((int c, POSITION pos)); public int pflushmbc LESSPARAMS ((VOID_PARAM)); public void pdone LESSPARAMS ((int endline, int chopped, int forw)); -public void set_status_col LESSPARAMS ((int c)); +public void set_status_col LESSPARAMS ((int c, int attr)); public int gline LESSPARAMS ((int i, int *ap)); public void null_line LESSPARAMS ((VOID_PARAM)); public POSITION forw_raw_line LESSPARAMS ((POSITION curr_pos, char **linep, int *line_lenp)); public POSITION back_raw_line LESSPARAMS ((POSITION curr_pos, char **linep, int *line_lenp)); public int rrshift LESSPARAMS ((VOID_PARAM)); +public int set_color_map LESSPARAMS ((int attr, char *colorstr)); +public char * get_color_map LESSPARAMS ((int attr)); public void clr_linenum LESSPARAMS ((VOID_PARAM)); public void add_lnum LESSPARAMS ((LINENUM linenum, POSITION pos)); public LINENUM find_linenum LESSPARAMS ((POSITION pos)); @@ -237,6 +249,10 @@ public void opt_rscroll LESSPARAMS ((int type, char *s)); public void opt_query LESSPARAMS ((int type, char *s)); public void opt_mousecap LESSPARAMS ((int type, char *s)); public void opt_wheel_lines LESSPARAMS ((int type, char *s)); +public void opt_linenum_width LESSPARAMS ((int type, char *s)); +public void opt_status_col_width LESSPARAMS ((int type, char *s)); +public void opt_ttyin_name LESSPARAMS ((int type, char *s)); +public void opt_rstat LESSPARAMS ((int type, char *s)); public int get_swindow LESSPARAMS ((VOID_PARAM)); public char * propt LESSPARAMS ((int c)); public void scan_option LESSPARAMS ((char *s)); @@ -259,15 +275,18 @@ public char * errno_message LESSPARAMS ((char *filename)); public int percentage LESSPARAMS ((POSITION num, POSITION den)); public POSITION percent_pos LESSPARAMS ((POSITION pos, int percent, long fraction)); public int os9_signal LESSPARAMS ((int type, RETSIGTYPE (*handler)())); +public void sleep_ms LESSPARAMS ((int ms)); public void put_line LESSPARAMS ((VOID_PARAM)); public void flush LESSPARAMS ((VOID_PARAM)); +public void set_output LESSPARAMS ((int fd)); public int putchr LESSPARAMS ((int c)); public void putstr LESSPARAMS ((constant char *s)); +public int less_printf LESSPARAMS ((char *fmt, PARG *parg)); public void get_return LESSPARAMS ((VOID_PARAM)); public void error LESSPARAMS ((char *fmt, PARG *parg)); public void ierror LESSPARAMS ((char *fmt, PARG *parg)); public int query LESSPARAMS ((char *fmt, PARG *parg)); -public int compile_pattern LESSPARAMS ((char *pattern, int search_type, PATTERN_TYPE *comp_pattern)); +public int compile_pattern LESSPARAMS ((char *pattern, int search_type, int show_error, PATTERN_TYPE *comp_pattern)); public void uncompile_pattern LESSPARAMS ((PATTERN_TYPE *pattern)); public int valid_pattern LESSPARAMS ((char *pattern)); public int is_null_pattern LESSPARAMS ((PATTERN_TYPE pattern)); @@ -291,14 +310,14 @@ public char * wait_message LESSPARAMS ((VOID_PARAM)); public void init_search LESSPARAMS ((VOID_PARAM)); public void repaint_hilite LESSPARAMS ((int on)); public void clear_attn LESSPARAMS ((VOID_PARAM)); -public void undo_search LESSPARAMS ((VOID_PARAM)); +public void undo_search LESSPARAMS ((int clear)); public void clr_hlist LESSPARAMS ((struct hilite_tree *anchor)); public void clr_hilite LESSPARAMS ((VOID_PARAM)); public void clr_filter LESSPARAMS ((VOID_PARAM)); public int is_filtered LESSPARAMS ((POSITION pos)); public POSITION next_unfiltered LESSPARAMS ((POSITION pos)); public POSITION prev_unfiltered LESSPARAMS ((POSITION pos)); -public int is_hilited LESSPARAMS ((POSITION pos, POSITION epos, int nohide, int *p_matches)); +public int is_hilited_attr LESSPARAMS ((POSITION pos, POSITION epos, int nohide, int *p_matches)); public void chg_hilite LESSPARAMS ((VOID_PARAM)); public void chg_caseless LESSPARAMS ((VOID_PARAM)); public int search LESSPARAMS ((int search_type, char *pattern, int n)); @@ -317,7 +336,9 @@ public char * prevtag LESSPARAMS ((int n)); public int ntags LESSPARAMS ((VOID_PARAM)); public int curr_tag LESSPARAMS ((VOID_PARAM)); public int edit_tagfile LESSPARAMS ((VOID_PARAM)); +public char * tty_device LESSPARAMS ((VOID_PARAM)); public void open_getchr LESSPARAMS ((VOID_PARAM)); public void close_getchr LESSPARAMS ((VOID_PARAM)); public int default_wheel_lines LESSPARAMS ((VOID_PARAM)); +public void rstat LESSPARAMS ((char st)); public int getchr LESSPARAMS ((VOID_PARAM)); diff --git a/contrib/less/help.c b/contrib/less/help.c index cfaa57855902..94b92cea69c2 100644 --- a/contrib/less/help.c +++ b/contrib/less/help.c @@ -1,4 +1,4 @@ -/* This file was generated by mkhelp.pl from less.hlp at 3:34 on 2020/6/14 */ +/* This file was generated by mkhelp.pl from less.hlp at 1:31 on 2021/4/7 */ #include "less.h" constant char helpdata[] = { '\n', @@ -45,7 +45,8 @@ constant char helpdata[] = { ' ',' ','E','S','C','-','n',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','R','e','p','e','a','t',' ','p','r','e','v','i','o','u','s',' ','s','e','a','r','c','h',',',' ','s','p','a','n','n','i','n','g',' ','f','i','l','e','s','.','\n', ' ',' ','E','S','C','-','N',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','R','e','p','e','a','t',' ','p','r','e','v','i','o','u','s',' ','s','e','a','r','c','h',',',' ','r','e','v','e','r','s','e',' ','d','i','r','.',' ','&',' ','s','p','a','n','n','i','n','g',' ','f','i','l','e','s','.','\n', ' ',' ','E','S','C','-','u',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','U','n','d','o',' ','(','t','o','g','g','l','e',')',' ','s','e','a','r','c','h',' ','h','i','g','h','l','i','g','h','t','i','n','g','.','\n', -' ',' ','&','_','\b','p','_','\b','a','_','\b','t','_','\b','t','_','\b','e','_','\b','r','_','\b','n',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','D','i','s','p','l','a','y',' ','o','n','l','y',' ','m','a','t','c','h','i','n','g',' ','l','i','n','e','s','\n', +' ',' ','E','S','C','-','U',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','C','l','e','a','r',' ','s','e','a','r','c','h',' ','h','i','g','h','l','i','g','h','t','i','n','g','.','\n', +' ',' ','&','_','\b','p','_','\b','a','_','\b','t','_','\b','t','_','\b','e','_','\b','r','_','\b','n',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','D','i','s','p','l','a','y',' ','o','n','l','y',' ','m','a','t','c','h','i','n','g',' ','l','i','n','e','s','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\n', ' ',' ',' ',' ',' ',' ',' ',' ','A',' ','s','e','a','r','c','h',' ','p','a','t','t','e','r','n',' ','m','a','y',' ','b','e','g','i','n',' ','w','i','t','h',' ','o','n','e',' ','o','r',' ','m','o','r','e',' ','o','f',':','\n', ' ',' ',' ',' ',' ',' ',' ',' ','^','N',' ','o','r',' ','!',' ',' ','S','e','a','r','c','h',' ','f','o','r',' ','N','O','N','-','m','a','t','c','h','i','n','g',' ','l','i','n','e','s','.','\n', @@ -53,6 +54,7 @@ constant char helpdata[] = { ' ',' ',' ',' ',' ',' ',' ',' ','^','F',' ','o','r',' ','@',' ',' ','S','t','a','r','t',' ','s','e','a','r','c','h',' ','a','t',' ','F','I','R','S','T',' ','f','i','l','e',' ','(','f','o','r',' ','/',')',' ','o','r',' ','l','a','s','t',' ','f','i','l','e',' ','(','f','o','r',' ','?',')','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ','^','K',' ',' ',' ',' ',' ',' ',' ','H','i','g','h','l','i','g','h','t',' ','m','a','t','c','h','e','s',',',' ','b','u','t',' ','d','o','n','\'','t',' ','m','o','v','e',' ','(','K','E','E','P',' ','p','o','s','i','t','i','o','n',')','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ','^','R',' ',' ',' ',' ',' ',' ',' ','D','o','n','\'','t',' ','u','s','e',' ','R','E','G','U','L','A','R',' ','E','X','P','R','E','S','S','I','O','N','S','.','\n', +' ',' ',' ',' ',' ',' ',' ',' ','^','W',' ',' ',' ',' ',' ',' ',' ','W','R','A','P',' ','s','e','a','r','c','h',' ','i','f',' ','n','o',' ','m','a','t','c','h',' ','f','o','u','n','d','.','\n', ' ','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\n', '\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','J','\b','J','U','\b','U','M','\b','M','P','\b','P','I','\b','I','N','\b','N','G','\b','G','\n', @@ -65,7 +67,7 @@ constant char helpdata[] = { ' ',' ','{',' ',' ','(',' ',' ','[',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','F','i','n','d',' ','c','l','o','s','e',' ','b','r','a','c','k','e','t',' ','}',' ',')',' ',']','.','\n', ' ',' ','}',' ',' ',')',' ',' ',']',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','F','i','n','d',' ','o','p','e','n',' ','b','r','a','c','k','e','t',' ','{',' ','(',' ','[','.','\n', ' ',' ','E','S','C','-','^','F',' ','_','\b','<','_','\b','c','_','\b','1','_','\b','>',' ','_','\b','<','_','\b','c','_','\b','2','_','\b','>',' ',' ','*',' ',' ','F','i','n','d',' ','c','l','o','s','e',' ','b','r','a','c','k','e','t',' ','_','\b','<','_','\b','c','_','\b','2','_','\b','>','.','\n', -' ',' ','E','S','C','-','^','B',' ','_','\b','<','_','\b','c','_','\b','1','_','\b','>',' ','_','\b','<','_','\b','c','_','\b','2','_','\b','>',' ',' ','*',' ',' ','F','i','n','d',' ','o','p','e','n',' ','b','r','a','c','k','e','t',' ','_','\b','<','_','\b','c','_','\b','1','_','\b','>',' ','\n', +' ',' ','E','S','C','-','^','B',' ','_','\b','<','_','\b','c','_','\b','1','_','\b','>',' ','_','\b','<','_','\b','c','_','\b','2','_','\b','>',' ',' ','*',' ',' ','F','i','n','d',' ','o','p','e','n',' ','b','r','a','c','k','e','t',' ','_','\b','<','_','\b','c','_','\b','1','_','\b','>','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\n', ' ',' ',' ',' ',' ',' ',' ',' ','E','a','c','h',' ','"','f','i','n','d',' ','c','l','o','s','e',' ','b','r','a','c','k','e','t','"',' ','c','o','m','m','a','n','d',' ','g','o','e','s',' ','f','o','r','w','a','r','d',' ','t','o',' ','t','h','e',' ','c','l','o','s','e',' ','b','r','a','c','k','e','t',' ','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','m','a','t','c','h','i','n','g',' ','t','h','e',' ','(','_','\b','N','-','t','h',')',' ','o','p','e','n',' ','b','r','a','c','k','e','t',' ','i','n',' ','t','h','e',' ','t','o','p',' ','l','i','n','e','.','\n', @@ -132,8 +134,8 @@ constant char helpdata[] = { ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','R','e','p','a','i','n','t',' ','b','y',' ','c','l','e','a','r','i','n','g',' ','r','a','t','h','e','r',' ','t','h','a','n',' ','s','c','r','o','l','l','i','n','g','.','\n', ' ',' ','-','d',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','d','u','m','b','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','u','m','b',' ','t','e','r','m','i','n','a','l','.','\n', -' ',' ','-','D',' ','[','_','\b','x','_','\b','n','_','\b','.','_','\b','n',']',' ',' ','.',' ',' ','-','-','c','o','l','o','r','=','_','\b','x','_','\b','n','_','\b','.','_','\b','n','\n', -' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','t',' ','s','c','r','e','e','n',' ','c','o','l','o','r','s','.',' ','(','M','S','-','D','O','S',' ','o','n','l','y',')','\n', +' ',' ','-','D',' ','x','\b','x','_','\b','c','_','\b','o','_','\b','l','_','\b','o','_','\b','r',' ',' ','.',' ',' ','-','-','c','o','l','o','r','=','x','\b','x','_','\b','c','_','\b','o','_','\b','l','_','\b','o','_','\b','r','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','t',' ','s','c','r','e','e','n',' ','c','o','l','o','r','s','.','\n', ' ',' ','-','e',' ',' ','-','E',' ',' ','.','.','.','.',' ',' ','-','-','q','u','i','t','-','a','t','-','e','o','f',' ',' ','-','-','Q','U','I','T','-','A','T','-','E','O','F','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','Q','u','i','t',' ','a','t',' ','e','n','d',' ','o','f',' ','f','i','l','e','.','\n', ' ',' ','-','f',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','f','o','r','c','e','\n', @@ -205,9 +207,13 @@ constant char helpdata[] = { ' ',' ','-','~',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','t','i','l','d','e','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','o','n','\'','t',' ','d','i','s','p','l','a','y',' ','t','i','l','d','e','s',' ','a','f','t','e','r',' ','e','n','d',' ','o','f',' ','f','i','l','e','.','\n', ' ',' ','-','#',' ','[','_','\b','N',']',' ',' ','.','.','.','.',' ',' ','-','-','s','h','i','f','t','=','[','_','\b','N',']','\n', -' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','H','o','r','i','z','o','n','t','a','l',' ','s','c','r','o','l','l',' ','a','m','o','u','n','t',' ','(','0',' ','=',' ','o','n','e',' ','h','a','l','f',' ','s','c','r','e','e','n',' ','w','i','d','t','h',')','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','t',' ','h','o','r','i','z','o','n','t','a','l',' ','s','c','r','o','l','l',' ','a','m','o','u','n','t',' ','(','0',' ','=',' ','o','n','e',' ','h','a','l','f',' ','s','c','r','e','e','n',' ','w','i','d','t','h',')','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','f','o','l','l','o','w','-','n','a','m','e','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','T','h','e',' ','F',' ','c','o','m','m','a','n','d',' ','c','h','a','n','g','e','s',' ','f','i','l','e','s',' ','i','f',' ','t','h','e',' ','i','n','p','u','t',' ','f','i','l','e',' ','i','s',' ','r','e','n','a','m','e','d','.','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','i','n','c','s','e','a','r','c','h','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','a','r','c','h',' ','f','i','l','e',' ','a','s',' ','e','a','c','h',' ','p','a','t','t','e','r','n',' ','c','h','a','r','a','c','t','e','r',' ','i','s',' ','t','y','p','e','d',' ','i','n','.','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','l','i','n','e','-','n','u','m','-','w','i','d','t','h','=','N','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','t',' ','t','h','e',' ','w','i','d','t','h',' ','o','f',' ','t','h','e',' ','-','N',' ','l','i','n','e',' ','n','u','m','b','e','r',' ','f','i','e','l','d',' ','t','o',' ','N',' ','c','h','a','r','a','c','t','e','r','s','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','m','o','u','s','e','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','E','n','a','b','l','e',' ','m','o','u','s','e',' ','i','n','p','u','t','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','n','o','-','k','e','y','p','a','d','\n', @@ -218,8 +224,12 @@ constant char helpdata[] = { ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','t',' ','t','h','e',' ','c','h','a','r','a','c','t','e','r',' ','u','s','e','d',' ','t','o',' ','m','a','r','k',' ','t','r','u','n','c','a','t','e','d',' ','l','i','n','e','s','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','s','a','v','e','-','m','a','r','k','s','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','R','e','t','a','i','n',' ','m','a','r','k','s',' ','a','c','r','o','s','s',' ','i','n','v','o','c','a','t','i','o','n','s',' ','o','f',' ','l','e','s','s','.','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','s','t','a','t','u','s','-','c','o','l','-','w','i','d','t','h','=','N','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','t',' ','t','h','e',' ','w','i','d','t','h',' ','o','f',' ','t','h','e',' ','-','J',' ','s','t','a','t','u','s',' ','c','o','l','u','m','n',' ','t','o',' ','N',' ','c','h','a','r','a','c','t','e','r','s','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','u','s','e','-','b','a','c','k','s','l','a','s','h','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','u','b','s','e','q','u','e','n','t',' ','o','p','t','i','o','n','s',' ','u','s','e',' ','b','a','c','k','s','l','a','s','h',' ','a','s',' ','e','s','c','a','p','e',' ','c','h','a','r','.','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','u','s','e','-','c','o','l','o','r','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','E','n','a','b','l','e','s',' ','c','o','l','o','r','e','d',' ','t','e','x','t','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','w','h','e','e','l','-','l','i','n','e','s','=','N','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','E','a','c','h',' ','c','l','i','c','k',' ','o','f',' ','t','h','e',' ','m','o','u','s','e',' ','w','h','e','e','l',' ','m','o','v','e','s',' ','N',' ','l','i','n','e','s','.','\n', '\n', @@ -247,7 +257,5 @@ constant char helpdata[] = { ' ','T','A','B',' ','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',' ','C','o','m','p','l','e','t','e',' ','f','i','l','e','n','a','m','e',' ','&',' ','c','y','c','l','e','.','\n', ' ','S','H','I','F','T','-','T','A','B',' ','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',' ','E','S','C','-','T','A','B',' ',' ',' ','C','o','m','p','l','e','t','e',' ','f','i','l','e','n','a','m','e',' ','&',' ','r','e','v','e','r','s','e',' ','c','y','c','l','e','.','\n', ' ','c','t','r','l','-','L',' ','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',' ','C','o','m','p','l','e','t','e',' ','f','i','l','e','n','a','m','e',',',' ','l','i','s','t',' ','a','l','l','.','\n', -'\n', -'\n', 0 }; constant int size_helpdata = sizeof(helpdata) - 1; diff --git a/contrib/less/ifile.c b/contrib/less/ifile.c index 6006cb12bd20..bc47a666754f 100644 --- a/contrib/less/ifile.c +++ b/contrib/less/ifile.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -21,12 +21,13 @@ #include "less.h" -extern IFILE curr_ifile; +extern IFILE curr_ifile; struct ifile { struct ifile *h_next; /* Links for command line list */ struct ifile *h_prev; char *h_filename; /* Name of the file */ + char *h_rfilename; /* Canonical name of the file */ void *h_filestate; /* File state (used in ch.c) */ int h_index; /* Index within command line list */ int h_hold; /* Hold count */ @@ -40,13 +41,13 @@ struct ifile { * Convert an IFILE (external representation) * to a struct file (internal representation), and vice versa. */ -#define int_ifile(h) ((struct ifile *)(h)) -#define ext_ifile(h) ((IFILE)(h)) +#define int_ifile(h) ((struct ifile *)(h)) +#define ext_ifile(h) ((IFILE)(h)) /* * Anchor for linked list. */ -static struct ifile anchor = { &anchor, &anchor, NULL, NULL, 0, 0, '\0', +static struct ifile anchor = { &anchor, &anchor, NULL, NULL, NULL, 0, 0, '\0', { NULL_POSITION, 0 } }; static int ifiles = 0; @@ -116,10 +117,13 @@ new_ifile(filename, prev) */ p = (struct ifile *) ecalloc(1, sizeof(struct ifile)); p->h_filename = save(filename); + p->h_rfilename = lrealpath(filename); p->h_scrpos.pos = NULL_POSITION; p->h_opened = 0; p->h_hold = 0; p->h_filestate = NULL; + p->h_altfilename = NULL; + p->h_altpipe = NULL; link_ifile(p, prev); /* * {{ It's dodgy to call mark.c functions from here; @@ -150,6 +154,7 @@ del_ifile(h) curr_ifile = getoff_ifile(curr_ifile); p = int_ifile(h); unlink_ifile(p); + free(p->h_rfilename); free(p->h_filename); free(p); } @@ -221,15 +226,17 @@ find_ifile(filename) for (p = anchor.h_next; p != &anchor; p = p->h_next) { - if (strcmp(filename, p->h_filename) == 0 || - strcmp(rfilename, p->h_filename) == 0) + if (strcmp(rfilename, p->h_rfilename) == 0) { /* * If given name is shorter than the name we were * previously using for this file, adopt shorter name. */ if (strlen(filename) < strlen(p->h_filename)) - strcpy(p->h_filename, filename); + { + free(p->h_filename); + p->h_filename = save(filename); + } break; } } @@ -257,7 +264,7 @@ get_ifile(filename, prev) } /* - * Get the filename associated with a ifile. + * Get the display filename associated with a ifile. */ public char * get_filename(ifile) @@ -268,6 +275,18 @@ get_filename(ifile) return (int_ifile(ifile)->h_filename); } +/* + * Get the canonical filename associated with a ifile. + */ + public char * +get_real_filename(ifile) + IFILE ifile; +{ + if (ifile == NULL) + return (NULL); + return (int_ifile(ifile)->h_rfilename); +} + /* * Get the index of the file associated with a ifile. */ @@ -372,7 +391,7 @@ set_altfilename(ifile, altfilename) char *altfilename; { struct ifile *p = int_ifile(ifile); - if (p->h_altfilename != NULL) + if (p->h_altfilename != NULL && p->h_altfilename != altfilename) free(p->h_altfilename); p->h_altfilename = altfilename; } diff --git a/contrib/less/input.c b/contrib/less/input.c index 526fe4be3bdb..f57c9e3403f2 100644 --- a/contrib/less/input.c +++ b/contrib/less/input.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -31,6 +31,7 @@ extern POSITION end_attnpos; #if HILITE_SEARCH extern int hilite_search; extern int size_linebuf; +extern int show_attn; #endif /* @@ -41,8 +42,9 @@ extern int size_linebuf; * of the NEXT line. The line obtained is the line starting at curr_pos. */ public POSITION -forw_line(curr_pos) +forw_line_seg(curr_pos, get_segpos) POSITION curr_pos; + int get_segpos; { POSITION base_pos; POSITION new_pos; @@ -104,8 +106,8 @@ forw_line(curr_pos) /* * Read forward again to the position we should start at. */ - prewind(); - plinenum(base_pos); + prewind(); + plinestart(base_pos); (void) ch_seek(base_pos); new_pos = base_pos; while (new_pos < curr_pos) @@ -180,8 +182,9 @@ forw_line(curr_pos) * is too long to print in the screen width. * End the line here. */ - if (chopline || hshift > 0) + if ((chopline || hshift > 0) && !get_segpos) { + /* Read to end of line. */ do { if (ABORT_SIGS()) @@ -205,6 +208,13 @@ forw_line(curr_pos) c = ch_forw_get(); } +#if HILITE_SEARCH + if (blankline && show_attn) + { + /* Add spurious space to carry possible attn hilite. */ + pappend(' ', ch_tell()-1); + } +#endif pdone(endline, chopped, 1); #if HILITE_SEARCH @@ -218,8 +228,12 @@ forw_line(curr_pos) goto get_forw_line; } - if (status_col && is_hilited(base_pos, ch_tell()-1, 1, NULL)) - set_status_col('*'); + if (status_col) + { + int attr = is_hilited_attr(base_pos, ch_tell()-1, 1, NULL); + if (attr) + set_status_col('*', attr); + } #endif if (squeeze && blankline) @@ -243,6 +257,13 @@ forw_line(curr_pos) return (new_pos); } + public POSITION +forw_line(curr_pos) + POSITION curr_pos; +{ + return forw_line_seg(curr_pos, FALSE); +} + /* * Get the previous line. * A "current" position is passed and a "new" position is returned. @@ -358,7 +379,7 @@ back_line(curr_pos) } endline = FALSE; prewind(); - plinenum(new_pos); + plinestart(new_pos); loop: begin_new_pos = new_pos; (void) ch_seek(new_pos); @@ -423,8 +444,12 @@ back_line(curr_pos) goto get_back_line; } - if (status_col && curr_pos > 0 && is_hilited(base_pos, curr_pos-1, 1, NULL)) - set_status_col('*'); + if (status_col && curr_pos > 0) + { + int attr = is_hilited_attr(base_pos, curr_pos-1, 1, NULL); + if (attr) + set_status_col('*', attr); + } #endif return (begin_new_pos); diff --git a/contrib/less/jump.c b/contrib/less/jump.c index a8ed6a5303e5..a376486c5e23 100644 --- a/contrib/less/jump.c +++ b/contrib/less/jump.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. diff --git a/contrib/less/less.h b/contrib/less/less.h index 944df687cbec..4751976bac18 100644 --- a/contrib/less/less.h +++ b/contrib/less/less.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -16,10 +16,10 @@ /* * Defines for MSDOS_COMPILER. */ -#define MSOFTC 1 /* Microsoft C */ -#define BORLANDC 2 /* Borland C */ -#define WIN32C 3 /* Windows (Borland C or Microsoft C) */ -#define DJGPPC 4 /* DJGPP C */ +#define MSOFTC 1 /* Microsoft C */ +#define BORLANDC 2 /* Borland C */ +#define WIN32C 3 /* Windows (Borland C or Microsoft C) */ +#define DJGPPC 4 /* DJGPP C */ /* * Include the file of compile-time options. @@ -45,20 +45,20 @@ #define LESSPARAMS(a) () #endif #if HAVE_VOID -#define VOID_POINTER void * -#define VOID_PARAM void +#define VOID_POINTER void * +#define VOID_PARAM void #else -#define VOID_POINTER char * -#define VOID_PARAM -#define void int +#define VOID_POINTER char * +#define VOID_PARAM +#define void int #endif #if HAVE_CONST -#define constant const +#define constant const #else -#define constant +#define constant #endif -#define public /* PUBLIC FUNCTION */ +#define public /* PUBLIC FUNCTION */ /* Library function declarations */ @@ -122,10 +122,10 @@ void free(); * Simple lowercase test which can be used during option processing * (before options are parsed which might tell us what charset to use). */ -#define ASCII_IS_UPPER(c) ((c) >= 'A' && (c) <= 'Z') -#define ASCII_IS_LOWER(c) ((c) >= 'a' && (c) <= 'z') -#define ASCII_TO_UPPER(c) ((c) - 'a' + 'A') -#define ASCII_TO_LOWER(c) ((c) - 'A' + 'a') +#define ASCII_IS_UPPER(c) ((c) >= 'A' && (c) <= 'Z') +#define ASCII_IS_LOWER(c) ((c) >= 'a' && (c) <= 'z') +#define ASCII_TO_UPPER(c) ((c) - 'a' + 'A') +#define ASCII_TO_LOWER(c) ((c) - 'A' + 'a') #undef IS_UPPER #undef IS_LOWER @@ -135,56 +135,56 @@ void free(); #undef IS_DIGIT #if HAVE_WCTYPE -#define IS_UPPER(c) iswupper(c) -#define IS_LOWER(c) iswlower(c) -#define TO_UPPER(c) towupper(c) -#define TO_LOWER(c) towlower(c) +#define IS_UPPER(c) iswupper(c) +#define IS_LOWER(c) iswlower(c) +#define TO_UPPER(c) towupper(c) +#define TO_LOWER(c) towlower(c) #else #if HAVE_UPPER_LOWER -#define IS_UPPER(c) isupper((unsigned char) (c)) -#define IS_LOWER(c) islower((unsigned char) (c)) -#define TO_UPPER(c) toupper((unsigned char) (c)) -#define TO_LOWER(c) tolower((unsigned char) (c)) +#define IS_UPPER(c) isupper((unsigned char) (c)) +#define IS_LOWER(c) islower((unsigned char) (c)) +#define TO_UPPER(c) toupper((unsigned char) (c)) +#define TO_LOWER(c) tolower((unsigned char) (c)) #else -#define IS_UPPER(c) ASCII_IS_UPPER(c) -#define IS_LOWER(c) ASCII_IS_LOWER(c) -#define TO_UPPER(c) ASCII_TO_UPPER(c) -#define TO_LOWER(c) ASCII_TO_LOWER(c) +#define IS_UPPER(c) ASCII_IS_UPPER(c) +#define IS_LOWER(c) ASCII_IS_LOWER(c) +#define TO_UPPER(c) ASCII_TO_UPPER(c) +#define TO_LOWER(c) ASCII_TO_LOWER(c) #endif #endif #ifdef isspace -#define IS_SPACE(c) isspace((unsigned char)(c)) +#define IS_SPACE(c) isspace((unsigned char)(c)) #else -#define IS_SPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r' || (c) == '\f') +#define IS_SPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r' || (c) == '\f') #endif #ifdef isdigit -#define IS_DIGIT(c) isdigit((unsigned char)(c)) +#define IS_DIGIT(c) isdigit((unsigned char)(c)) #else -#define IS_DIGIT(c) ((c) >= '0' && (c) <= '9') +#define IS_DIGIT(c) ((c) >= '0' && (c) <= '9') #endif -#define IS_CSI_START(c) (((LWCHAR)(c)) == ESC || (((LWCHAR)(c)) == CSI)) +#define IS_CSI_START(c) (((LWCHAR)(c)) == ESC || (((LWCHAR)(c)) == CSI)) #ifndef NULL -#define NULL 0 +#define NULL 0 #endif #ifndef TRUE -#define TRUE 1 +#define TRUE 1 #endif #ifndef FALSE -#define FALSE 0 +#define FALSE 0 #endif -#define OPT_OFF 0 -#define OPT_ON 1 -#define OPT_ONPLUS 2 +#define OPT_OFF 0 +#define OPT_ON 1 +#define OPT_ONPLUS 2 #if !HAVE_MEMCPY #ifndef memcpy -#define memcpy(to,from,len) bcopy((from),(to),(len)) +#define memcpy(to,from,len) bcopy((from),(to),(len)) #endif #endif @@ -201,7 +201,7 @@ void free(); #define SNPRINTF4(str, size, fmt, v1, v2, v3, v4) sprintf((str), (fmt), (v1), (v2), (v3), (v4)) #endif -#define BAD_LSEEK ((off_t)-1) +#define BAD_LSEEK ((off_t)-1) #ifndef SEEK_SET #define SEEK_SET 0 @@ -225,37 +225,39 @@ void free(); * Special types and constants. */ typedef unsigned long LWCHAR; -typedef off_t POSITION; -typedef off_t LINENUM; -#define MIN_LINENUM_WIDTH 7 /* Min printing width of a line number */ -#define MAX_UTF_CHAR_LEN 6 /* Max bytes in one UTF-8 char */ +typedef off_t POSITION; +typedef off_t LINENUM; +#define MIN_LINENUM_WIDTH 7 /* Default min printing width of a line number */ +#define MAX_LINENUM_WIDTH 16 /* Max width of a line number */ +#define MAX_STATUSCOL_WIDTH 4 /* Max width of the status column */ +#define MAX_UTF_CHAR_LEN 6 /* Max bytes in one UTF-8 char */ -#define NULL_POSITION ((POSITION)(-1)) +#define NULL_POSITION ((POSITION)(-1)) /* * Flags for open() */ #if MSDOS_COMPILER || OS2 -#define OPEN_READ (O_RDONLY|O_BINARY) +#define OPEN_READ (O_RDONLY|O_BINARY) #else #ifdef _OSK -#define OPEN_READ (S_IREAD) +#define OPEN_READ (S_IREAD) #else #ifdef O_RDONLY -#define OPEN_READ (O_RDONLY) +#define OPEN_READ (O_RDONLY) #else -#define OPEN_READ (0) +#define OPEN_READ (0) #endif #endif #endif #if defined(O_WRONLY) && defined(O_APPEND) -#define OPEN_APPEND (O_APPEND|O_WRONLY) +#define OPEN_APPEND (O_APPEND|O_WRONLY) #else #ifdef _OSK -#define OPEN_APPEND (S_IWRITE) +#define OPEN_APPEND (S_IWRITE) #else -#define OPEN_APPEND (1) +#define OPEN_APPEND (1) #endif #endif @@ -263,12 +265,12 @@ typedef off_t LINENUM; * Set a file descriptor to binary mode. */ #if MSDOS_COMPILER==MSOFTC -#define SET_BINARY(f) _setmode(f, _O_BINARY); +#define SET_BINARY(f) _setmode(f, _O_BINARY); #else #if MSDOS_COMPILER || OS2 -#define SET_BINARY(f) setmode(f, O_BINARY) +#define SET_BINARY(f) setmode(f, O_BINARY) #else -#define SET_BINARY(f) +#define SET_BINARY(f) #endif #endif @@ -276,18 +278,18 @@ typedef off_t LINENUM; * Does the shell treat "?" as a metacharacter? */ #if MSDOS_COMPILER || OS2 || _OSK -#define SHELL_META_QUEST 0 +#define SHELL_META_QUEST 0 #else -#define SHELL_META_QUEST 1 +#define SHELL_META_QUEST 1 #endif -#define SPACES_IN_FILENAMES 1 +#define SPACES_IN_FILENAMES 1 /* * An IFILE represents an input file. */ -#define IFILE VOID_POINTER -#define NULL_IFILE ((IFILE)NULL) +#define IFILE VOID_POINTER +#define NULL_IFILE ((IFILE)NULL) /* * The structure used to represent a "screen position". @@ -298,63 +300,65 @@ typedef off_t LINENUM; */ struct scrpos { - POSITION pos; - int ln; + POSITION pos; + int ln; }; typedef union parg { - char *p_string; - int p_int; - LINENUM p_linenum; + char *p_string; + int p_int; + LINENUM p_linenum; + char p_char; } PARG; -#define NULL_PARG ((PARG *)NULL) +#define NULL_PARG ((PARG *)NULL) struct textlist { - char *string; - char *endstring; + char *string; + char *endstring; }; struct wchar_range { - LWCHAR first, last; + LWCHAR first, last; }; struct wchar_range_table { - struct wchar_range *table; - int count; + struct wchar_range *table; + int count; }; -#define EOI (-1) +#define EOI (-1) -#define READ_INTR (-2) +#define READ_INTR (-2) /* A fraction is represented by an int n; the fraction is n/NUM_FRAC_DENOM */ -#define NUM_FRAC_DENOM 1000000 -#define NUM_LOG_FRAC_DENOM 6 +#define NUM_FRAC_DENOM 1000000 +#define NUM_LOG_FRAC_DENOM 6 /* How quiet should we be? */ -#define NOT_QUIET 0 /* Ring bell at eof and for errors */ -#define LITTLE_QUIET 1 /* Ring bell only for errors */ -#define VERY_QUIET 2 /* Never ring bell */ +#define NOT_QUIET 0 /* Ring bell at eof and for errors */ +#define LITTLE_QUIET 1 /* Ring bell only for errors */ +#define VERY_QUIET 2 /* Never ring bell */ /* How should we prompt? */ -#define PR_SHORT 0 /* Prompt with colon */ -#define PR_MEDIUM 1 /* Prompt with message */ -#define PR_LONG 2 /* Prompt with longer message */ +#define PR_SHORT 0 /* Prompt with colon */ +#define PR_MEDIUM 1 /* Prompt with message */ +#define PR_LONG 2 /* Prompt with longer message */ /* How should we handle backspaces? */ -#define BS_SPECIAL 0 /* Do special things for underlining and bold */ -#define BS_NORMAL 1 /* \b treated as normal char; actually output */ -#define BS_CONTROL 2 /* \b treated as control char; prints as ^H */ +#define BS_SPECIAL 0 /* Do special things for underlining and bold */ +#define BS_NORMAL 1 /* \b treated as normal char; actually output */ +#define BS_CONTROL 2 /* \b treated as control char; prints as ^H */ /* How should we search? */ -#define SRCH_FORW (1 << 0) /* Search forward from current position */ -#define SRCH_BACK (1 << 1) /* Search backward from current position */ +#define SRCH_FORW (1 << 0) /* Search forward from current position */ +#define SRCH_BACK (1 << 1) /* Search backward from current position */ #define SRCH_NO_MOVE (1 << 2) /* Highlight, but don't move */ +#define SRCH_INCR (1 << 3) /* Incremental search */ #define SRCH_FIND_ALL (1 << 4) /* Find and highlight all matches */ #define SRCH_NO_MATCH (1 << 8) /* Search for non-matching lines */ #define SRCH_PAST_EOF (1 << 9) /* Search past end-of-file, into next file */ @@ -362,32 +366,62 @@ struct wchar_range_table #define SRCH_NO_REGEX (1 << 12) /* Don't use regular expressions */ #define SRCH_FILTER (1 << 13) /* Search is for '&' (filter) command */ #define SRCH_AFTER_TARGET (1 << 14) /* Start search after the target line */ +#define SRCH_WRAP (1 << 15) /* Wrap-around search (continue at BOF/EOF) */ -#define SRCH_REVERSE(t) (((t) & SRCH_FORW) ? \ - (((t) & ~SRCH_FORW) | SRCH_BACK) : \ - (((t) & ~SRCH_BACK) | SRCH_FORW)) +#define SRCH_REVERSE(t) (((t) & SRCH_FORW) ? \ + (((t) & ~SRCH_FORW) | SRCH_BACK) : \ + (((t) & ~SRCH_BACK) | SRCH_FORW)) /* */ -#define NO_MCA 0 -#define MCA_DONE 1 -#define MCA_MORE 2 +#define NO_MCA 0 +#define MCA_DONE 1 +#define MCA_MORE 2 -#define CC_OK 0 /* Char was accepted & processed */ -#define CC_QUIT 1 /* Char was a request to abort current cmd */ -#define CC_ERROR 2 /* Char could not be accepted due to error */ -#define CC_PASS 3 /* Char was rejected (internal) */ +#define CC_OK 0 /* Char was accepted & processed */ +#define CC_QUIT 1 /* Char was a request to abort current cmd */ +#define CC_ERROR 2 /* Char could not be accepted due to error */ +#define CC_PASS 3 /* Char was rejected (internal) */ #define CF_QUIT_ON_ERASE 0001 /* Abort cmd if its entirely erased */ /* Special char bit-flags used to tell put_line() to do something special */ -#define AT_NORMAL (0) -#define AT_UNDERLINE (1 << 0) -#define AT_BOLD (1 << 1) -#define AT_BLINK (1 << 2) -#define AT_STANDOUT (1 << 3) -#define AT_ANSI (1 << 4) /* Content-supplied "ANSI" escape sequence */ -#define AT_BINARY (1 << 5) /* LESS*BINFMT representation */ -#define AT_HILITE (1 << 6) /* Internal highlights (e.g., for search) */ +#define AT_NORMAL (0) +#define AT_UNDERLINE (1 << 0) +#define AT_BOLD (1 << 1) +#define AT_BLINK (1 << 2) +#define AT_STANDOUT (1 << 3) +#define AT_ANSI (1 << 4) /* Content-supplied "ANSI" escape sequence */ +#define AT_BINARY (1 << 5) /* LESS*BINFMT representation */ +#define AT_HILITE (1 << 6) /* Internal highlights (e.g., for search) */ + +#define AT_COLOR_SHIFT 8 +#define AT_NUM_COLORS 16 +#define AT_COLOR ((AT_NUM_COLORS-1) << AT_COLOR_SHIFT) +#define AT_COLOR_ATTN (1 << AT_COLOR_SHIFT) +#define AT_COLOR_BIN (2 << AT_COLOR_SHIFT) +#define AT_COLOR_CTRL (3 << AT_COLOR_SHIFT) +#define AT_COLOR_ERROR (4 << AT_COLOR_SHIFT) +#define AT_COLOR_LINENUM (5 << AT_COLOR_SHIFT) +#define AT_COLOR_MARK (6 << AT_COLOR_SHIFT) +#define AT_COLOR_PROMPT (7 << AT_COLOR_SHIFT) +#define AT_COLOR_RSCROLL (8 << AT_COLOR_SHIFT) +#define AT_COLOR_SEARCH (9 << AT_COLOR_SHIFT) + +typedef enum { CT_NULL, CT_4BIT, CT_6BIT } COLOR_TYPE; + +typedef enum { + CV_BLUE = 1, + CV_GREEN = 2, + CV_RED = 4, + CV_BRIGHT = 8, + CV_NOCHANGE = -2, + CV_ERROR = -1 +} COLOR_VALUE; + +/* ANSI states */ +#define ANSI_MID 1 +#define ANSI_ERR 2 +#define ANSI_END 3 #if '0' == 240 #define IS_EBCDIC_HOST 1 @@ -400,76 +434,76 @@ struct wchar_range_table * into a constant. */ #define CONTROL(c) ( \ - (c)=='[' ? '\047' : \ - (c)=='a' ? '\001' : \ - (c)=='b' ? '\002' : \ - (c)=='c' ? '\003' : \ - (c)=='d' ? '\067' : \ - (c)=='e' ? '\055' : \ - (c)=='f' ? '\056' : \ - (c)=='g' ? '\057' : \ - (c)=='h' ? '\026' : \ - (c)=='i' ? '\005' : \ - (c)=='j' ? '\025' : \ - (c)=='k' ? '\013' : \ - (c)=='l' ? '\014' : \ - (c)=='m' ? '\015' : \ - (c)=='n' ? '\016' : \ - (c)=='o' ? '\017' : \ - (c)=='p' ? '\020' : \ - (c)=='q' ? '\021' : \ - (c)=='r' ? '\022' : \ - (c)=='s' ? '\023' : \ - (c)=='t' ? '\074' : \ - (c)=='u' ? '\075' : \ - (c)=='v' ? '\062' : \ - (c)=='w' ? '\046' : \ - (c)=='x' ? '\030' : \ - (c)=='y' ? '\031' : \ - (c)=='z' ? '\077' : \ - (c)=='A' ? '\001' : \ - (c)=='B' ? '\002' : \ - (c)=='C' ? '\003' : \ - (c)=='D' ? '\067' : \ - (c)=='E' ? '\055' : \ - (c)=='F' ? '\056' : \ - (c)=='G' ? '\057' : \ - (c)=='H' ? '\026' : \ - (c)=='I' ? '\005' : \ - (c)=='J' ? '\025' : \ - (c)=='K' ? '\013' : \ - (c)=='L' ? '\014' : \ - (c)=='M' ? '\015' : \ - (c)=='N' ? '\016' : \ - (c)=='O' ? '\017' : \ - (c)=='P' ? '\020' : \ - (c)=='Q' ? '\021' : \ - (c)=='R' ? '\022' : \ - (c)=='S' ? '\023' : \ - (c)=='T' ? '\074' : \ - (c)=='U' ? '\075' : \ - (c)=='V' ? '\062' : \ - (c)=='W' ? '\046' : \ - (c)=='X' ? '\030' : \ - (c)=='Y' ? '\031' : \ - (c)=='Z' ? '\077' : \ - (c)=='|' ? '\031' : \ - (c)=='\\' ? '\034' : \ - (c)=='^' ? '\036' : \ - (c)&077) + (c)=='[' ? '\047' : \ + (c)=='a' ? '\001' : \ + (c)=='b' ? '\002' : \ + (c)=='c' ? '\003' : \ + (c)=='d' ? '\067' : \ + (c)=='e' ? '\055' : \ + (c)=='f' ? '\056' : \ + (c)=='g' ? '\057' : \ + (c)=='h' ? '\026' : \ + (c)=='i' ? '\005' : \ + (c)=='j' ? '\025' : \ + (c)=='k' ? '\013' : \ + (c)=='l' ? '\014' : \ + (c)=='m' ? '\015' : \ + (c)=='n' ? '\016' : \ + (c)=='o' ? '\017' : \ + (c)=='p' ? '\020' : \ + (c)=='q' ? '\021' : \ + (c)=='r' ? '\022' : \ + (c)=='s' ? '\023' : \ + (c)=='t' ? '\074' : \ + (c)=='u' ? '\075' : \ + (c)=='v' ? '\062' : \ + (c)=='w' ? '\046' : \ + (c)=='x' ? '\030' : \ + (c)=='y' ? '\031' : \ + (c)=='z' ? '\077' : \ + (c)=='A' ? '\001' : \ + (c)=='B' ? '\002' : \ + (c)=='C' ? '\003' : \ + (c)=='D' ? '\067' : \ + (c)=='E' ? '\055' : \ + (c)=='F' ? '\056' : \ + (c)=='G' ? '\057' : \ + (c)=='H' ? '\026' : \ + (c)=='I' ? '\005' : \ + (c)=='J' ? '\025' : \ + (c)=='K' ? '\013' : \ + (c)=='L' ? '\014' : \ + (c)=='M' ? '\015' : \ + (c)=='N' ? '\016' : \ + (c)=='O' ? '\017' : \ + (c)=='P' ? '\020' : \ + (c)=='Q' ? '\021' : \ + (c)=='R' ? '\022' : \ + (c)=='S' ? '\023' : \ + (c)=='T' ? '\074' : \ + (c)=='U' ? '\075' : \ + (c)=='V' ? '\062' : \ + (c)=='W' ? '\046' : \ + (c)=='X' ? '\030' : \ + (c)=='Y' ? '\031' : \ + (c)=='Z' ? '\077' : \ + (c)=='|' ? '\031' : \ + (c)=='\\' ? '\034' : \ + (c)=='^' ? '\036' : \ + (c)&077) #else -#define CONTROL(c) ((c)&037) +#define CONTROL(c) ((c)&037) #endif /* IS_EBCDIC_HOST */ -#define ESC CONTROL('[') -#define ESCS "\33" -#define CSI ((unsigned char)'\233') -#define CHAR_END_COMMAND 0x40000000 +#define ESC CONTROL('[') +#define ESCS "\33" +#define CSI ((unsigned char)'\233') +#define CHAR_END_COMMAND 0x40000000 #if _OSK_MWC32 -#define LSIGNAL(sig,func) os9_signal(sig,func) +#define LSIGNAL(sig,func) os9_signal(sig,func) #else -#define LSIGNAL(sig,func) signal(sig,func) +#define LSIGNAL(sig,func) signal(sig,func) #endif #if HAVE_SIGPROCMASK @@ -486,41 +520,41 @@ struct wchar_range_table #endif #endif -#define S_INTERRUPT 01 -#define S_STOP 02 -#define S_WINCH 04 -#define ABORT_SIGS() (sigs & (S_INTERRUPT|S_STOP)) +#define S_INTERRUPT 01 +#define S_STOP 02 +#define S_WINCH 04 +#define ABORT_SIGS() (sigs & (S_INTERRUPT|S_STOP)) -#define QUIT_OK 0 -#define QUIT_ERROR 1 -#define QUIT_INTERRUPT 2 -#define QUIT_SAVED_STATUS (-1) +#define QUIT_OK 0 +#define QUIT_ERROR 1 +#define QUIT_INTERRUPT 2 +#define QUIT_SAVED_STATUS (-1) #define FOLLOW_DESC 0 #define FOLLOW_NAME 1 /* filestate flags */ -#define CH_CANSEEK 001 -#define CH_KEEPOPEN 002 -#define CH_POPENED 004 -#define CH_HELPFILE 010 -#define CH_NODATA 020 /* Special case for zero length files */ +#define CH_CANSEEK 001 +#define CH_KEEPOPEN 002 +#define CH_POPENED 004 +#define CH_HELPFILE 010 +#define CH_NODATA 020 /* Special case for zero length files */ -#define ch_zero() ((POSITION)0) +#define ch_zero() ((POSITION)0) -#define FAKE_HELPFILE "@/\\less/\\help/\\file/\\@" -#define FAKE_EMPTYFILE "@/\\less/\\empty/\\file/\\@" +#define FAKE_HELPFILE "@/\\less/\\help/\\file/\\@" +#define FAKE_EMPTYFILE "@/\\less/\\empty/\\file/\\@" /* Flags for cvt_text */ -#define CVT_TO_LC 01 /* Convert upper-case to lower-case */ -#define CVT_BS 02 /* Do backspace processing */ -#define CVT_CRLF 04 /* Remove CR after LF */ -#define CVT_ANSI 010 /* Remove ANSI escape sequences */ +#define CVT_TO_LC 01 /* Convert upper-case to lower-case */ +#define CVT_BS 02 /* Do backspace processing */ +#define CVT_CRLF 04 /* Remove CR after LF */ +#define CVT_ANSI 010 /* Remove ANSI escape sequences */ #if HAVE_TIME_T -#define time_type time_t +#define time_type time_t #else -#define time_type long +#define time_type long #endif /* X11 mouse reporting definitions */ @@ -535,6 +569,7 @@ struct wchar_range_table struct mlist; struct loption; struct hilite_tree; +struct ansi_state; #include "pattern.h" #include "funcs.h" diff --git a/contrib/less/less.hlp b/contrib/less/less.hlp index a8f78adcdd7f..1e1ebf447711 100644 --- a/contrib/less/less.hlp +++ b/contrib/less/less.hlp @@ -42,7 +42,8 @@ ESC-n * Repeat previous search, spanning files. ESC-N * Repeat previous search, reverse dir. & spanning files. ESC-u Undo (toggle) search highlighting. - &_p_a_t_t_e_r_n * Display only matching lines + ESC-U Clear search highlighting. + &_p_a_t_t_e_r_n * Display only matching lines. --------------------------------------------------- A search pattern may begin with one or more of: ^N or ! Search for NON-matching lines. @@ -50,6 +51,7 @@ ^F or @ Start search at FIRST file (for /) or last file (for ?). ^K Highlight matches, but don't move (KEEP position). ^R Don't use REGULAR EXPRESSIONS. + ^W WRAP search if no match found. --------------------------------------------------------------------------- JJUUMMPPIINNGG @@ -62,7 +64,7 @@ { ( [ * Find close bracket } ) ]. } ) ] * Find open bracket { ( [. ESC-^F _<_c_1_> _<_c_2_> * Find close bracket _<_c_2_>. - ESC-^B _<_c_1_> _<_c_2_> * Find open bracket _<_c_1_> + ESC-^B _<_c_1_> _<_c_2_> * Find open bracket _<_c_1_>. --------------------------------------------------- Each "find close bracket" command goes forward to the close bracket matching the (_N-th) open bracket in the top line. @@ -129,8 +131,8 @@ Repaint by clearing rather than scrolling. -d ........ --dumb Dumb terminal. - -D [_x_n_._n] . --color=_x_n_._n - Set screen colors. (MS-DOS only) + -D xx_c_o_l_o_r . --color=xx_c_o_l_o_r + Set screen colors. -e -E .... --quit-at-eof --QUIT-AT-EOF Quit at end of file. -f ........ --force @@ -202,9 +204,13 @@ -~ ........ --tilde Don't display tildes after end of file. -# [_N] .... --shift=[_N] - Horizontal scroll amount (0 = one half screen width) + Set horizontal scroll amount (0 = one half screen width). --follow-name The F command changes files if the input file is renamed. + --incsearch + Search file as each pattern character is typed in. + --line-num-width=N + Set the width of the -N line number field to N characters. --mouse Enable mouse input. --no-keypad @@ -215,8 +221,12 @@ Set the character used to mark truncated lines. --save-marks Retain marks across invocations of less. + --status-col-width=N + Set the width of the -J status column to N characters. --use-backslash Subsequent options use backslash as escape char. + --use-color + Enables colored text. --wheel-lines=N Each click of the mouse wheel moves N lines. @@ -244,5 +254,3 @@ TAB ...................................... Complete filename & cycle. SHIFT-TAB ...................... ESC-TAB Complete filename & reverse cycle. ctrl-L ................................... Complete filename, list all. - - diff --git a/contrib/less/less.nro b/contrib/less/less.nro index 70f99ce6f286..41021321964b 100644 --- a/contrib/less/less.nro +++ b/contrib/less/less.nro @@ -1,5 +1,5 @@ '\" t -.TH LESS 1 "Version 563: 13 Jun 2020" +.TH LESS 1 "Version 581: 06 Apr 2021" .SH NAME less \- opposite of more .SH SYNOPSIS @@ -109,6 +109,7 @@ Scroll horizontally left back to the first column. Repaint the screen. .IP R Repaint the screen, discarding any buffered input. +That is, reload the current file. Useful if the file is changing while it is being viewed. .IP "F" Scroll forward, and keep trying to read when the @@ -117,6 +118,8 @@ Normally this command would be used when already at the end of the file. It is a way to monitor the tail of a file which is growing while it is being viewed. (The behavior is similar to the "tail \-f" command.) +To stop waiting for more data, enter the interrupt character (usually ^C). +On some systems you can also use ^X. .IP "ESC-F" Like F, but as soon as a line is found which matches the last search pattern, the terminal bell is rung @@ -226,6 +229,11 @@ but don't move to the first match (KEEP current position). .IP "^R" Don't interpret regular expression metacharacters; that is, do a simple textual comparison. +.IP "^W" +WRAP around the current file. +That is, if the search reaches the end of the current file +without finding a match, the search continues from the first line of the +current file up to the line where it started. .RE .IP ?pattern Search backward in the file for the N-th line containing the pattern. @@ -250,6 +258,11 @@ or the settings of the \-a or \-j options. As in forward searches. .IP "^R" As in forward searches. +.IP "^W" +WRAP around the current file. +That is, if the search reaches the beginning of the current file +without finding a match, the search continues from the last line of the +current file up to the line where it started. .RE .IP "ESC-/pattern" Same as "/*". @@ -280,6 +293,10 @@ turn highlighting back on. Any search command will also turn highlighting back on. (Highlighting can also be disabled by toggling the \-G option; in that case search commands do not turn highlighting back on.) +.IP "ESC-U" +Like ESC-u but also clears the saved search pattern. +If the status column is enabled via the \-J option, +this clears all search matches marked in the status column. .IP "&pattern" Display only lines which match the pattern; lines which do not match the pattern are not displayed. @@ -288,6 +305,8 @@ any filtering is turned off, and all lines are displayed. While filtering is in effect, an ampersand is displayed at the beginning of the prompt, as a reminder that some lines in the file may be hidden. +Multiple & commands may be entered, in which case only lines +which match all of the patterns will be displayed. .sp Certain characters are special as in the / command: .RS @@ -552,20 +571,105 @@ The \-d option does not otherwise change the behavior of .I less on a dumb terminal. .IP "\-D\fBx\fP\fIcolor\fP or \-\-color=\fBx\fP\fIcolor\fP" -[MS-DOS only] -Sets the color of the text displayed. -\fBx\fP is a single character which selects the type of text whose color is -being set: n=normal, s=standout, d=bold, u=underlined, k=blink. -\fIcolor\fP is a pair of numbers separated by a period. -The first number selects the foreground color and the second selects -the background color of the text. -A single number \fIN\fP is the same as \fIN.M\fP, -where \fIM\fP is the normal background color. -The color may start or end with \fBu\fP to use underline (with the normal -color, if by itself), if the system supports it (Windows only). -\fBx\fP may also be \fBa\fP to toggle strict ANSI sequence rendering -(SGR mode). -. +Changes the color of different parts of the displayed text. +\fBx\fP is a single character which selects the type of text +whose color is being set: +.RS +.IP "B" +Binary characters. +.IP "C" +Control characters. +.IP "E" +Errors and informational messages. +.IP "M" +Mark letters in the status column. +.IP "N" +Line numbers enabled via the \-N option. +.IP "P" +Prompts. +.IP "R" +The rscroll character. +.IP "S" +Search results. +.IP "W" +The highlight enabled via the \-w option. +.IP "d" +Bold text. +.IP "k" +Blinking text. +.IP "s" +Standout text. +.IP "u" +Underlined text. +.RE + +.RS +The uppercase letters can be used only when the \-\-use-color option is enabled. +When text color is specified by both an uppercase letter and a lowercase letter, +the uppercase letter takes precedence. +For example, error messages are normally displayed as standout text. +So if both "s" and "E" are given a color, the "E" color applies +to error messages, and the "s" color applies to other standout text. +The "d" and "u" letters refer to bold and underline text formed by +overstriking with backspaces (see the \-u option), +not to text using ANSI escape sequences with the \-R option. +.PP +A lowercase letter may be followed by a + to indicate that +both the normal format change and the specified color should both be used. +For example, \-Dug displays underlined text as green without underlining; +the green color has replaced the usual underline formatting. +But \-Du+g displays underlined text as both green and in underlined format. +.PP +\fIcolor\fP is either a 4-bit color string or an 8-bit color string: +.PP +A 4-bit color string is zero, one or two characters, where +the first character specifies the foreground color and +the second specifies the background color as follows: +.IP "b" +Blue +.IP "c" +Cyan +.IP "g" +Green +.IP "k" +Black +.IP "m" +Magenta +.IP "r" +Red +.IP "w" +White +.IP "y" +Yellow +.PP +The corresponding upper-case letter denotes a brighter shade of the color. +For example, \-DNGk displays line numbers as bright green text on a black +background, and \-DEbR displays error messages as blue text on a +bright red background. +If either character is a "-" or is omitted, the corresponding color +is set to that of normal text. +.PP +An 8-bit color string is one or two decimal integers separated by a dot, +where the first integer specifies the foreground color and +the second specifies the background color. +Each integer is a value between 0 and 255 inclusive which selects +a "CSI 38;5" color value (see +.br +.nh +https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters) +.hy +If either integer is a "-" or is omitted, +the corresponding color is set to that of normal text. +On MS-DOS versions of +.IR less , +8-bit color is not supported; instead, decimal values are interpreted as 4-bit +CHAR_INFO.Attributes values +(see +.br +.nh +https://docs.microsoft.com/en-us/windows/console/char-info-str). +.hy +.RE .IP "\-e or \-\-quit-at-eof" Causes .I less @@ -650,7 +754,6 @@ always begin at the start or end of the current screen respectively. Displays a status column at the left edge of the screen. The status column shows the lines that matched the current search, and any lines that are marked (via the m or M command). -The status column is also used if the \-w or \-W option is in effect. .IP "\-k\fIfilename\fP or \-\-lesskey-file=\fIfilename\fP" Causes .I less @@ -676,7 +779,8 @@ command prompt from the "F" command. .IP "\-L or \-\-no-lessopen" Ignore the LESSOPEN environment variable (see the INPUT PREPROCESSOR section below). -This option can be set from within \fIless\fP, +This option can be set from within +.IR less , but it will apply only to files opened subsequently, not to the file which is currently open. .IP "\-m or \-\-long-prompt" @@ -776,16 +880,33 @@ cannot keep track of the actual appearance of the screen each type of control character). Thus, various display problems may result, such as long lines being split in the wrong place. +.sp +USE OF THE \-r OPTION IS NOT RECOMMENDED. .IP "\-R or \-\-RAW-CONTROL-CHARS" -Like \-r, but only ANSI "color" escape sequences are output in "raw" form. -Unlike \-r, the screen appearance is maintained correctly in most cases. -ANSI "color" escape sequences are sequences of the form: +Like \-r, but only ANSI "color" escape sequences and OSC 8 hyperlink +sequences are output in "raw" form. +Unlike \-r, the screen appearance is maintained correctly, +provided that there are no escape sequences in the file +other than these types of escape sequences. +Color escape sequences are only supported when the color +is changed within one line, not across lines. +In other words, the beginning of each line is assumed to be +normal (non-colored), regardless of any escape sequences in previous lines. +For the purpose of keeping track of screen appearance, +these escape sequences are assumed to not move the cursor. +.sp +OSC 8 hyperlinks are sequences of the form: +.sp + ESC ] 8 ; \&...\& \\7 +.sp +The terminating sequence may be either a BEL character (\\7) +or the two-character sequence "ESC \\". +.sp +ANSI color escape sequences are sequences of the form: .sp ESC [ \&...\& m .sp -where the "...\&" is zero or more color specification characters -For the purpose of keeping track of screen appearance, -ANSI color escape sequences are assumed to not move the cursor. +where the "...\&" is zero or more color specification characters. You can make .I less think that characters other than "m" can end ANSI color escape sequences @@ -820,7 +941,10 @@ If the environment variable LESSGLOBALTAGS is set, it is taken to be the name of a command compatible with .IR global (1), and that command is executed to find the tag. -(See http://www.gnu.org/software/global/global.html). +(See +.nh +http://www.gnu.org/software/global/global.html). +.hy The \-t option may also be specified from within .I less (using the \- command) as a way of examining a new file. @@ -848,6 +972,8 @@ using the terminal's hardware boldface capability. Other backspaces are deleted, along with the preceding character. Carriage returns immediately followed by a newline are deleted. Other carriage returns are handled as specified by the \-r option. +Unicode formatting characters, such as the Byte Order Mark, +are sent to the terminal. Text which is overstruck or underlined can be searched for if neither \-u nor \-U is in effect. .IP "\-V or \-\-version" @@ -941,6 +1067,14 @@ If the reopen succeeds and the file is a different file from the original with the same name as the original (now renamed) file), .I less will display the contents of that new file. +.IP "\-\-incsearch" +Subsequent search commands will be "incremental"; that is, +.I less +will advance to the next line containing the search pattern +as each character of the pattern is typed in. +.IP "\-\-line-num-width" +Sets the minimum width of the line number field when the \-N option is in effect. +The default is 7 characters. .IP "\-\-mouse" Enables mouse input: scrolling the mouse wheel down moves forward in the file, @@ -973,12 +1107,26 @@ If there is no attribute indicator, standout is used. If set to "\-", truncated lines are not marked. .IP "\-\-save-marks" Save marks in the history file, so marks are retained -across different invocations of \fIless\fP. +across different invocations of +.IR less . +.IP "\-\-status-col-width" +Sets the width of the status column when the \-J option is in effect. +The default is 2 characters. .IP "\-\-use-backslash" This option changes the interpretations of options which follow this one. After the \-\-use-backslash option, any backslash in an option string is removed and the following character is taken literally. This allows a dollar sign to be included in option strings. +.IP "\-\-use-color" +Enables the colored text in various places. +The -D option can be used to change the colors. +Colored text works only if the terminal supports +ANSI color escape sequences (as defined in ECMA-48 SGR; +see +.br +.nh +https://www.ecma-international.org/publications-and-standards/standards/ecma-48). +.hy .IP "\-\-wheel-lines=\fIn\fP" Set the number of lines to scroll when the mouse wheel is scrolled and the \-\-mouse or \-\-MOUSE option is in effect. @@ -1004,7 +1152,7 @@ The + command described previously may also be used to set (or change) an initial command for every file. . .SH "LINE EDITING" -When entering command line at the bottom of the screen +When entering a command line at the bottom of the screen (for example, a filename for the :e command, or the pattern for a search command), certain keys can be used to manipulate the command line. @@ -1804,7 +1952,7 @@ The name of the editor (used for the v command). .BR lesskey (1) . .SH COPYRIGHT -Copyright (C) 1984-2020 Mark Nudelman +Copyright (C) 1984-2021 Mark Nudelman .PP less is part of the GNU project and is free software. You can redistribute it and/or modify it @@ -1833,4 +1981,4 @@ Report bugs at https://github.com/gwsw/less/issues. .br For more information, see the less homepage at .br -http://www.greenwoodsoftware.com/less. +https://greenwoodsoftware.com/less. diff --git a/contrib/less/lessecho.c b/contrib/less/lessecho.c index 6bf2e9c32b51..bfb0f729a8b8 100644 --- a/contrib/less/lessecho.c +++ b/contrib/less/lessecho.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -13,16 +13,16 @@ * Simply echos its filename arguments on standard output. * But any argument containing spaces is enclosed in quotes. * - * -ox Specifies "x" to be the open quote character. - * -cx Specifies "x" to be the close quote character. - * -pn Specifies "n" to be the open quote character, as an integer. - * -dn Specifies "n" to be the close quote character, as an integer. + * -ox Specifies "x" to be the open quote character. + * -cx Specifies "x" to be the close quote character. + * -pn Specifies "n" to be the open quote character, as an integer. + * -dn Specifies "n" to be the close quote character, as an integer. * -mx Specifies "x" to be a metachar. * -nn Specifies "n" to be a metachar, as an integer. * -ex Specifies "x" to be the escape char for metachars. * -fn Specifies "x" to be the escape char for metachars, as an integer. - * -a Specifies that all arguments are to be quoted. - * The default is that only arguments containing spaces are quoted. + * -a Specifies that all arguments are to be quoted. + * The default is that only arguments containing spaces are quoted. */ #include "less.h" diff --git a/contrib/less/lessecho.nro b/contrib/less/lessecho.nro index d6d367b55429..ef822fabdafb 100644 --- a/contrib/less/lessecho.nro +++ b/contrib/less/lessecho.nro @@ -1,4 +1,4 @@ -.TH LESSECHO 1 "Version 563: 13 Jun 2020" +.TH LESSECHO 1 "Version 581: 06 Apr 2021" .SH NAME lessecho \- expand metacharacters .SH SYNOPSIS @@ -19,7 +19,7 @@ are surrounded by quotes instead. .TP .B \-ox Specifies "x", rather than double-quote, to be the open quote character, -which is used if the -e- option is specified. +which is used if the \-e- option is specified. .TP .B \-cx Specifies "x" to be the close quote character. @@ -42,11 +42,11 @@ Specifies "n" to be the escape char for metachars, as an integer. .TP .B \-a Specifies that all arguments are to be quoted. -The default is that only arguments containing metacharacters are quoted +The default is that only arguments containing metacharacters are quoted. .SH "SEE ALSO" .BR less (1) .SH AUTHOR This manual page was written by Thomas Schoepf , for the Debian GNU/Linux system (but may be used by others). .PP -Send bug reports or comments to bug-less@gnu.org. +Report bugs at https://github.com/gwsw/less/issues. diff --git a/contrib/less/lesskey.c b/contrib/less/lesskey.c index 74cdcb2cb2cf..de7a9bfc8311 100644 --- a/contrib/less/lesskey.c +++ b/contrib/less/lesskey.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -9,73 +9,73 @@ /* - * lesskey [-o output] [input] + * lesskey [-o output] [input] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Make a .less file. - * If no input file is specified, standard input is used. - * If no output file is specified, $HOME/.less is used. + * Make a .less file. + * If no input file is specified, standard input is used. + * If no output file is specified, $HOME/.less is used. * - * The .less file is used to specify (to "less") user-defined - * key bindings. Basically any sequence of 1 to MAX_CMDLEN - * keystrokes may be bound to an existing less function. + * The .less file is used to specify (to "less") user-defined + * key bindings. Basically any sequence of 1 to MAX_CMDLEN + * keystrokes may be bound to an existing less function. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * The input file is an ascii file consisting of a - * sequence of lines of the form: - * string action [chars] + * The input file is an ascii file consisting of a + * sequence of lines of the form: + * string action [chars] * - * "string" is a sequence of command characters which form - * the new user-defined command. The command - * characters may be: - * 1. The actual character itself. - * 2. A character preceded by ^ to specify a - * control character (e.g. ^X means control-X). - * 3. A backslash followed by one to three octal digits - * to specify a character by its octal value. - * 4. A backslash followed by b, e, n, r or t - * to specify \b, ESC, \n, \r or \t, respectively. - * 5. Any character (other than those mentioned above) preceded - * by a \ to specify the character itself (characters which - * must be preceded by \ include ^, \, and whitespace. - * "action" is the name of a "less" action, from the table below. - * "chars" is an optional sequence of characters which is treated - * as keyboard input after the command is executed. + * "string" is a sequence of command characters which form + * the new user-defined command. The command + * characters may be: + * 1. The actual character itself. + * 2. A character preceded by ^ to specify a + * control character (e.g. ^X means control-X). + * 3. A backslash followed by one to three octal digits + * to specify a character by its octal value. + * 4. A backslash followed by b, e, n, r or t + * to specify \b, ESC, \n, \r or \t, respectively. + * 5. Any character (other than those mentioned above) preceded + * by a \ to specify the character itself (characters which + * must be preceded by \ include ^, \, and whitespace. + * "action" is the name of a "less" action, from the table below. + * "chars" is an optional sequence of characters which is treated + * as keyboard input after the command is executed. * - * Blank lines and lines which start with # are ignored, - * except for the special control lines: - * #command Signals the beginning of the command - * keys section. - * #line-edit Signals the beginning of the line-editing - * keys section. - * #env Signals the beginning of the environment - * variable section. - * #stop Stops command parsing in less; - * causes all default keys to be disabled. + * Blank lines and lines which start with # are ignored, + * except for the special control lines: + * #command Signals the beginning of the command + * keys section. + * #line-edit Signals the beginning of the line-editing + * keys section. + * #env Signals the beginning of the environment + * variable section. + * #stop Stops command parsing in less; + * causes all default keys to be disabled. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * The output file is a non-ascii file, consisting of a header, - * one or more sections, and a trailer. - * Each section begins with a section header, a section length word - * and the section data. Normally there are three sections: - * CMD_SECTION Definition of command keys. - * EDIT_SECTION Definition of editing keys. - * END_SECTION A special section header, with no - * length word or section data. + * The output file is a non-ascii file, consisting of a header, + * one or more sections, and a trailer. + * Each section begins with a section header, a section length word + * and the section data. Normally there are three sections: + * CMD_SECTION Definition of command keys. + * EDIT_SECTION Definition of editing keys. + * END_SECTION A special section header, with no + * length word or section data. * - * Section data consists of zero or more byte sequences of the form: - * string <0> - * or - * string <0> chars <0> + * Section data consists of zero or more byte sequences of the form: + * string <0> + * or + * string <0> chars <0> * - * "string" is the command string. - * "<0>" is one null byte. - * "" is one byte containing the action code (the A_xxx value). - * If action is ORed with A_EXTRA, the action byte is followed - * by the null-terminated "chars" string. + * "string" is the command string. + * "<0>" is one null byte. + * "" is one byte containing the action code (the A_xxx value). + * If action is ORed with A_EXTRA, the action byte is followed + * by the null-terminated "chars" string. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @@ -153,6 +153,7 @@ struct cmdname cmdnames[] = { "toggle-flag", A_OPT_TOGGLE }, { "toggle-option", A_OPT_TOGGLE }, { "undo-hilite", A_UNDO_SEARCH }, + { "clear-search", A_CLR_SEARCH }, { "version", A_VERSION }, { "visual", A_VISUAL }, { NULL, 0 } @@ -160,26 +161,26 @@ struct cmdname cmdnames[] = struct cmdname editnames[] = { - { "back-complete", EC_B_COMPLETE }, - { "backspace", EC_BACKSPACE }, - { "delete", EC_DELETE }, - { "down", EC_DOWN }, - { "end", EC_END }, - { "expand", EC_EXPAND }, - { "forw-complete", EC_F_COMPLETE }, - { "home", EC_HOME }, - { "insert", EC_INSERT }, - { "invalid", EC_UINVALID }, - { "kill-line", EC_LINEKILL }, - { "abort", EC_ABORT }, - { "left", EC_LEFT }, - { "literal", EC_LITERAL }, - { "right", EC_RIGHT }, - { "up", EC_UP }, - { "word-backspace", EC_W_BACKSPACE }, - { "word-delete", EC_W_DELETE }, - { "word-left", EC_W_LEFT }, - { "word-right", EC_W_RIGHT }, + { "back-complete", EC_B_COMPLETE }, + { "backspace", EC_BACKSPACE }, + { "delete", EC_DELETE }, + { "down", EC_DOWN }, + { "end", EC_END }, + { "expand", EC_EXPAND }, + { "forw-complete", EC_F_COMPLETE }, + { "home", EC_HOME }, + { "insert", EC_INSERT }, + { "invalid", EC_UINVALID }, + { "kill-line", EC_LINEKILL }, + { "abort", EC_ABORT }, + { "left", EC_LEFT }, + { "literal", EC_LITERAL }, + { "right", EC_RIGHT }, + { "up", EC_UP }, + { "word-backspace", EC_W_BACKSPACE }, + { "word-delete", EC_W_DELETE }, + { "word-left", EC_W_LEFT }, + { "word-right", EC_W_RIGHT }, { NULL, 0 } }; @@ -206,10 +207,10 @@ char filetrailer[] = { C1_END_LESSKEY_MAGIC, C2_END_LESSKEY_MAGIC }; -char cmdsection[1] = { CMD_SECTION }; -char editsection[1] = { EDIT_SECTION }; -char varsection[1] = { VAR_SECTION }; -char endsection[1] = { END_SECTION }; +char cmdsection[1] = { CMD_SECTION }; +char editsection[1] = { EDIT_SECTION }; +char varsection[1] = { VAR_SECTION }; +char endsection[1] = { END_SECTION }; char *infile = NULL; char *outfile = NULL ; @@ -459,7 +460,7 @@ tstr(pp, xlate) *pp = p+2; buf[0] = CONTROL(p[1]); buf[1] = '\0'; - if (buf[0] == CONTROL('K')) + if (xlate && buf[0] == CONTROL('K')) return tstr_control_k; return (buf); } @@ -478,7 +479,7 @@ tstr(pp, xlate) skipsp(s) char *s; { - while (*s == ' ' || *s == '\t') + while (*s == ' ' || *s == '\t') s++; return (s); } @@ -546,7 +547,7 @@ add_cmd_str(s) control_line(s) char *s; { -#define PREFIX(str,pat) (strncmp(str,pat,strlen(pat)) == 0) +#define PREFIX(str,pat) (strncmp(str,pat,strlen(pat)) == 0) if (PREFIX(s, "#line-edit")) { diff --git a/contrib/less/lesskey.h b/contrib/less/lesskey.h index 2c4b5d6ddde2..3a8f83682a90 100644 --- a/contrib/less/lesskey.h +++ b/contrib/less/lesskey.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -11,29 +11,29 @@ /* * Format of a lesskey file: * - * LESSKEY_MAGIC (4 bytes) - * sections... - * END_LESSKEY_MAGIC (4 bytes) + * LESSKEY_MAGIC (4 bytes) + * sections... + * END_LESSKEY_MAGIC (4 bytes) * * Each section is: * - * section_MAGIC (1 byte) - * section_length (2 bytes) - * key table (section_length bytes) + * section_MAGIC (1 byte) + * section_length (2 bytes) + * key table (section_length bytes) */ -#define C0_LESSKEY_MAGIC '\0' -#define C1_LESSKEY_MAGIC 'M' -#define C2_LESSKEY_MAGIC '+' -#define C3_LESSKEY_MAGIC 'G' +#define C0_LESSKEY_MAGIC '\0' +#define C1_LESSKEY_MAGIC 'M' +#define C2_LESSKEY_MAGIC '+' +#define C3_LESSKEY_MAGIC 'G' -#define CMD_SECTION 'c' -#define EDIT_SECTION 'e' -#define VAR_SECTION 'v' -#define END_SECTION 'x' +#define CMD_SECTION 'c' +#define EDIT_SECTION 'e' +#define VAR_SECTION 'v' +#define END_SECTION 'x' -#define C0_END_LESSKEY_MAGIC 'E' -#define C1_END_LESSKEY_MAGIC 'n' -#define C2_END_LESSKEY_MAGIC 'd' +#define C0_END_LESSKEY_MAGIC 'E' +#define C1_END_LESSKEY_MAGIC 'n' +#define C2_END_LESSKEY_MAGIC 'd' /* */ -#define KRADIX 64 +#define KRADIX 64 diff --git a/contrib/less/lesskey.nro b/contrib/less/lesskey.nro index 5b8cbe4a2d2a..a9aec69fea0f 100644 --- a/contrib/less/lesskey.nro +++ b/contrib/less/lesskey.nro @@ -1,5 +1,5 @@ '\" t -.TH LESSKEY 1 "Version 563: 13 Jun 2020" +.TH LESSKEY 1 "Version 581: 06 Apr 2021" .SH NAME lesskey \- specify key bindings for less .SH SYNOPSIS @@ -18,10 +18,10 @@ The input file is a text file which describes the key bindings. If the input file is "\-", standard input is read. If no input file is specified, a standard filename is used as the name of the input file, which depends on the system being used: -On Unix systems, $HOME/.lesskey is used; -on MS-DOS systems, $HOME/_lesskey is used; -and on OS/2 systems $HOME/lesskey.ini is used, -or $INIT/lesskey.ini if $HOME is undefined. +On Unix systems, "$HOME/.lesskey" is used; +on MS-DOS systems, "$HOME/_lesskey" is used; +and on OS/2 systems "$HOME/lesskey.ini" is used, +or "$INIT/lesskey.ini" if $HOME is undefined. The output file is a binary file which is used by .IR less . If no output file is specified, @@ -29,10 +29,10 @@ and the environment variable LESSKEY is set, the value of LESSKEY is used as the name of the output file. Otherwise, a standard filename is used as the name of the output file, which depends on the system being used: -On Unix and OS-9 systems, $HOME/.less is used; -on MS-DOS systems, $HOME/_less is used; -and on OS/2 systems, $HOME/less.ini is used, -or $INIT/less.ini if $HOME is undefined. +On Unix and OS-9 systems, "$HOME/.less" is used; +on MS-DOS systems, "$HOME/_less" is used; +and on OS/2 systems, "$HOME/less.ini" is used, +or "$INIT/less.ini" if $HOME is undefined. If the output file already exists, .I lesskey will overwrite it. @@ -123,7 +123,7 @@ For example, see the "{" and ":t" commands in the example below. The extra string has a special meaning for the "quit" action: when .I less -quits, first character of the extra string is used as its exit status. +quits, the first character of the extra string is used as its exit status. . .SH EXAMPLE The following input file describes the set of @@ -171,6 +171,7 @@ r repaint ^R repaint ^L repaint \eeu undo-hilite +\eeU clear-search g goto-line \ekh goto-line < goto-line @@ -370,7 +371,7 @@ which start with a NUL character (0). This NUL character should be represented as \e340 in a lesskey file. . .SH COPYRIGHT -Copyright (C) 1984-2020 Mark Nudelman +Copyright (C) 1984-2021 Mark Nudelman .PP less is part of the GNU project and is free software. You can redistribute it and/or modify it @@ -395,4 +396,4 @@ See the GNU General Public License for more details. . Mark Nudelman .br -Send bug reports or comments to . +Report bugs at https://github.com/gwsw/less/issues. diff --git a/contrib/less/lglob.h b/contrib/less/lglob.h index e13e7982ffe9..2e5e74ec1900 100644 --- a/contrib/less/lglob.h +++ b/contrib/less/lglob.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -11,81 +11,81 @@ /* * Macros to define the method of doing filename "globbing". * There are three possible mechanisms: - * 1. GLOB_LIST - * This defines a function that returns a list of matching filenames. + * 1. GLOB_LIST + * This defines a function that returns a list of matching filenames. * 2. GLOB_NAME - * This defines a function that steps thru the list of matching - * filenames, returning one name each time it is called. + * This defines a function that steps thru the list of matching + * filenames, returning one name each time it is called. * 3. GLOB_STRING - * This defines a function that returns the complete list of - * matching filenames as a single space-separated string. + * This defines a function that returns the complete list of + * matching filenames as a single space-separated string. */ #if OS2 -#define DECL_GLOB_LIST(list) char **list; char **pp; -#define GLOB_LIST(filename,list) list = _fnexplode(filename) -#define GLOB_LIST_FAILED(list) list == NULL -#define SCAN_GLOB_LIST(list,p) pp = list; *pp != NULL; pp++ -#define INIT_GLOB_LIST(list,p) p = *pp -#define GLOB_LIST_DONE(list) _fnexplodefree(list) +#define DECL_GLOB_LIST(list) char **list; char **pp; +#define GLOB_LIST(filename,list) list = _fnexplode(filename) +#define GLOB_LIST_FAILED(list) list == NULL +#define SCAN_GLOB_LIST(list,p) pp = list; *pp != NULL; pp++ +#define INIT_GLOB_LIST(list,p) p = *pp +#define GLOB_LIST_DONE(list) _fnexplodefree(list) #else #if MSDOS_COMPILER==DJGPPC -#define DECL_GLOB_LIST(list) glob_t list; int i; -#define GLOB_LIST(filename,list) glob(filename,GLOB_NOCHECK,0,&list) -#define GLOB_LIST_FAILED(list) 0 -#define SCAN_GLOB_LIST(list,p) i = 0; i < list.gl_pathc; i++ -#define INIT_GLOB_LIST(list,p) p = list.gl_pathv[i] -#define GLOB_LIST_DONE(list) globfree(&list) +#define DECL_GLOB_LIST(list) glob_t list; int i; +#define GLOB_LIST(filename,list) glob(filename,GLOB_NOCHECK,0,&list) +#define GLOB_LIST_FAILED(list) 0 +#define SCAN_GLOB_LIST(list,p) i = 0; i < list.gl_pathc; i++ +#define INIT_GLOB_LIST(list,p) p = list.gl_pathv[i] +#define GLOB_LIST_DONE(list) globfree(&list) #else #if MSDOS_COMPILER==MSOFTC || MSDOS_COMPILER==BORLANDC -#define GLOB_FIRST_NAME(filename,fndp,h) h = _dos_findfirst(filename, ~_A_VOLID, fndp) -#define GLOB_FIRST_FAILED(handle) ((handle) != 0) -#define GLOB_NEXT_NAME(handle,fndp) _dos_findnext(fndp) -#define GLOB_NAME_DONE(handle) -#define GLOB_NAME name -#define DECL_GLOB_NAME(fnd,drive,dir,fname,ext,handle) \ - struct find_t fnd; \ - char drive[_MAX_DRIVE]; \ - char dir[_MAX_DIR]; \ - char fname[_MAX_FNAME]; \ - char ext[_MAX_EXT]; \ - int handle; +#define GLOB_FIRST_NAME(filename,fndp,h) h = _dos_findfirst(filename, ~_A_VOLID, fndp) +#define GLOB_FIRST_FAILED(handle) ((handle) != 0) +#define GLOB_NEXT_NAME(handle,fndp) _dos_findnext(fndp) +#define GLOB_NAME_DONE(handle) +#define GLOB_NAME name +#define DECL_GLOB_NAME(fnd,drive,dir,fname,ext,handle) \ + struct find_t fnd; \ + char drive[_MAX_DRIVE]; \ + char dir[_MAX_DIR]; \ + char fname[_MAX_FNAME]; \ + char ext[_MAX_EXT]; \ + int handle; #else #if MSDOS_COMPILER==WIN32C && (defined(_MSC_VER) || defined(MINGW)) -#define GLOB_FIRST_NAME(filename,fndp,h) h = _findfirst(filename, fndp) -#define GLOB_FIRST_FAILED(handle) ((handle) == -1) -#define GLOB_NEXT_NAME(handle,fndp) _findnext(handle, fndp) -#define GLOB_NAME_DONE(handle) _findclose(handle) -#define GLOB_NAME name -#define DECL_GLOB_NAME(fnd,drive,dir,fname,ext,handle) \ - struct _finddata_t fnd; \ - char drive[_MAX_DRIVE]; \ - char dir[_MAX_DIR]; \ - char fname[_MAX_FNAME]; \ - char ext[_MAX_EXT]; \ - intptr_t handle; +#define GLOB_FIRST_NAME(filename,fndp,h) h = _findfirst(filename, fndp) +#define GLOB_FIRST_FAILED(handle) ((handle) == -1) +#define GLOB_NEXT_NAME(handle,fndp) _findnext(handle, fndp) +#define GLOB_NAME_DONE(handle) _findclose(handle) +#define GLOB_NAME name +#define DECL_GLOB_NAME(fnd,drive,dir,fname,ext,handle) \ + struct _finddata_t fnd; \ + char drive[_MAX_DRIVE]; \ + char dir[_MAX_DIR]; \ + char fname[_MAX_FNAME]; \ + char ext[_MAX_EXT]; \ + intptr_t handle; #else #if MSDOS_COMPILER==WIN32C && !defined(_MSC_VER) /* Borland C for Windows */ -#define GLOB_FIRST_NAME(filename,fndp,h) h = findfirst(filename, fndp, ~FA_LABEL) -#define GLOB_FIRST_FAILED(handle) ((handle) != 0) -#define GLOB_NEXT_NAME(handle,fndp) findnext(fndp) -#define GLOB_NAME_DONE(handle) -#define GLOB_NAME ff_name -#define DECL_GLOB_NAME(fnd,drive,dir,fname,ext,handle) \ - struct ffblk fnd; \ - char drive[MAXDRIVE]; \ - char dir[MAXDIR]; \ - char fname[MAXFILE]; \ - char ext[MAXEXT]; \ - int handle; +#define GLOB_FIRST_NAME(filename,fndp,h) h = findfirst(filename, fndp, ~FA_LABEL) +#define GLOB_FIRST_FAILED(handle) ((handle) != 0) +#define GLOB_NEXT_NAME(handle,fndp) findnext(fndp) +#define GLOB_NAME_DONE(handle) +#define GLOB_NAME ff_name +#define DECL_GLOB_NAME(fnd,drive,dir,fname,ext,handle) \ + struct ffblk fnd; \ + char drive[MAXDRIVE]; \ + char dir[MAXDIR]; \ + char fname[MAXFILE]; \ + char ext[MAXEXT]; \ + int handle; #endif #endif diff --git a/contrib/less/line.c b/contrib/less/line.c index 4a552319359f..57d3cbef2f4d 100644 --- a/contrib/less/line.c +++ b/contrib/less/line.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -22,26 +22,38 @@ #include #endif -static char *linebuf = NULL; /* Buffer which holds the current output line */ -static char *attr = NULL; /* Extension of linebuf to hold attributes */ -public int size_linebuf = 0; /* Size of line buffer (and attr buffer) */ +#define MAX_PFX_WIDTH (MAX_LINENUM_WIDTH + MAX_STATUSCOL_WIDTH + 1) +static struct { + char *buf; /* Buffer which holds the current output line */ + int *attr; /* Parallel to buf, to hold attributes */ + int print; /* Index in buf of first printable char */ + int end; /* Number of chars in buf */ + char pfx[MAX_PFX_WIDTH]; /* Holds status column and line number */ + int pfx_attr[MAX_PFX_WIDTH]; + int pfx_end; /* Number of chars in pfx */ +} linebuf; -static int cshift; /* Current left-shift of output line buffer */ -public int hshift; /* Desired left-shift of output line buffer */ +static struct { + char *buf; + int size; + int end; +} shifted_ansi; + +public int size_linebuf = 0; /* Size of line buffer (and attr buffer) */ +static struct ansi_state *line_ansi = NULL; +static int cshift; /* Current left-shift of output line buffer */ +public int hshift; /* Desired left-shift of output line buffer */ public int tabstops[TABSTOP_MAX] = { 0 }; /* Custom tabstops */ -public int ntabstops = 1; /* Number of tabstops */ -public int tabdefault = 8; /* Default repeated tabstops */ -public POSITION highest_hilite; /* Pos of last hilite in file found so far */ +public int ntabstops = 1; /* Number of tabstops */ +public int tabdefault = 8; /* Default repeated tabstops */ +public POSITION highest_hilite; /* Pos of last hilite in file found so far */ -static int curr; /* Index into linebuf */ -static int column; /* Printable length, accounting for - backspaces, etc. */ +static int end_column; /* Printable length, accounting for backspaces, etc. */ static int right_curr; static int right_column; -static int overstrike; /* Next char should overstrike previous char */ +static int overstrike; /* Next char should overstrike previous char */ static int last_overstrike = AT_NORMAL; -static int is_null_line; /* There is no current line */ -static int lmargin; /* Left margin */ +static int is_null_line; /* There is no current line */ static LWCHAR pendc; static POSITION pendpos; static char *end_ansi_chars; @@ -58,6 +70,8 @@ extern int ctldisp; extern int twiddle; extern int binattr; extern int status_col; +extern int status_col_width; +extern int linenum_width; extern int auto_wrap, ignaw; extern int bo_s_width, bo_e_width; extern int ul_s_width, ul_e_width; @@ -69,12 +83,37 @@ extern POSITION start_attnpos; extern POSITION end_attnpos; extern char rscroll_char; extern int rscroll_attr; +extern int use_color; static char mbc_buf[MAX_UTF_CHAR_LEN]; static int mbc_buf_len = 0; static int mbc_buf_index = 0; static POSITION mbc_pos; +/* Configurable color map */ +static char color_map[AT_NUM_COLORS][12] = { + "Wm", /* AT_COLOR_ATTN */ + "kR", /* AT_COLOR_BIN */ + "kR", /* AT_COLOR_CTRL */ + "kY", /* AT_COLOR_ERROR */ + "c", /* AT_COLOR_LINENUM */ + "Wb", /* AT_COLOR_MARK */ + "kC", /* AT_COLOR_PROMPT */ + "kc", /* AT_COLOR_RSCROLL */ + "kG", /* AT_COLOR_SEARCH */ + "", /* AT_UNDERLINE */ + "", /* AT_BOLD */ + "", /* AT_BLINK */ + "", /* AT_STANDOUT */ +}; + +/* State while processing an ANSI escape sequence */ +struct ansi_state { + int hindex; /* Index into hyperlink prefix */ + int hlink; /* Processing hyperlink address? */ + int prev_esc; /* Prev char was ESC (to detect ESC-\ seq) */ +}; + /* * Initialize from environment variables. */ @@ -89,9 +128,11 @@ init_line(VOID_PARAM) if (isnullenv(mid_ansi_chars)) mid_ansi_chars = "0123456789:;[?!\"'#%()*+ "; - linebuf = (char *) ecalloc(LINEBUF_SIZE, sizeof(char)); - attr = (char *) ecalloc(LINEBUF_SIZE, sizeof(char)); + linebuf.buf = (char *) ecalloc(LINEBUF_SIZE, sizeof(char)); + linebuf.attr = (int *) ecalloc(LINEBUF_SIZE, sizeof(int)); size_linebuf = LINEBUF_SIZE; + shifted_ansi.buf = NULL; + shifted_ansi.size = 0; } /* @@ -105,11 +146,11 @@ expand_linebuf(VOID_PARAM) /* Just realloc to expand the buffer, if we can. */ #if HAVE_REALLOC - char *new_buf = (char *) realloc(linebuf, new_size); - char *new_attr = (char *) realloc(attr, new_size); + char *new_buf = (char *) realloc(linebuf.buf, new_size); + int *new_attr = (int *) realloc(linebuf.attr, new_size*sizeof(int)); #else char *new_buf = (char *) calloc(new_size, sizeof(char)); - char *new_attr = (char *) calloc(new_size, sizeof(char)); + int *new_attr = (int *) calloc(new_size, sizeof(int)); #endif if (new_buf == NULL || new_attr == NULL) { @@ -123,13 +164,13 @@ expand_linebuf(VOID_PARAM) /* * We just calloc'd the buffers; copy the old contents. */ - memcpy(new_buf, linebuf, size_linebuf * sizeof(char)); - memcpy(new_attr, attr, size_linebuf * sizeof(char)); - free(attr); - free(linebuf); + memcpy(new_buf, linebuf.buf, size_linebuf * sizeof(char)); + memcpy(new_attr, linebuf.attr, size_linebuf * sizeof(int)); + free(linebuf.attr); + free(linebuf.buf); #endif - linebuf = new_buf; - attr = new_attr; + linebuf.buf = new_buf; + linebuf.attr = new_attr; size_linebuf = new_size; return 0; } @@ -144,14 +185,35 @@ is_ascii_char(ch) return (ch <= 0x7F); } +/* + */ + static void +inc_end_column(w) + int w; +{ + if (end_column > right_column && w > 0) + { + right_column = end_column; + right_curr = linebuf.end; + } + end_column += w; +} + /* * Rewind the line buffer. */ public void prewind(VOID_PARAM) { - curr = 0; - column = 0; + linebuf.print = 6; /* big enough for longest UTF-8 sequence */ + linebuf.pfx_end = 0; + for (linebuf.end = 0; linebuf.end < linebuf.print; linebuf.end++) + { + linebuf.buf[linebuf.end] = '\0'; + linebuf.attr[linebuf.end] = 0; + } + + end_column = 0; right_curr = 0; right_column = 0; cshift = 0; @@ -160,42 +222,64 @@ prewind(VOID_PARAM) mbc_buf_len = 0; is_null_line = 0; pendc = '\0'; - lmargin = 0; - if (status_col) - lmargin += 2; + shifted_ansi.end = 0; } /* * Set a character in the line buffer. */ static void -set_linebuf(n, ch, a) +set_linebuf(n, ch, attr) int n; char ch; - char a; + int attr; { - linebuf[n] = ch; - attr[n] = a; + linebuf.buf[n] = ch; + linebuf.attr[n] = attr; } /* * Append a character to the line buffer. */ static void -add_linebuf(ch, a, w) +add_linebuf(ch, attr, w) char ch; - char a; + int attr; int w; { - set_linebuf(curr++, ch, a); - column += w; + set_linebuf(linebuf.end++, ch, attr); + inc_end_column(w); } /* - * Insert the line number (of the given position) into the line buffer. + * Set a character in the line prefix buffer. + */ + static void +set_pfx(n, ch, attr) + int n; + char ch; + int attr; +{ + linebuf.pfx[n] = ch; + linebuf.pfx_attr[n] = attr; +} + +/* + * Append a character to the line prefix buffer. + */ + static void +add_pfx(ch, attr) + char ch; + int attr; +{ + set_pfx(linebuf.pfx_end++, ch, attr); +} + +/* + * Insert the status column and line number into the line buffer. */ public void -plinenum(pos) +plinestart(pos) POSITION pos; { LINENUM linenum = 0; @@ -207,7 +291,7 @@ plinenum(pos) * Get the line number and put it in the current line. * {{ Note: since find_linenum calls forw_raw_line, * it may seek in the input file, requiring the caller - * of plinenum to re-seek if necessary. }} + * of plinestart to re-seek if necessary. }} * {{ Since forw_raw_line modifies linebuf, we must * do this first, before storing anything in linebuf. }} */ @@ -222,16 +306,17 @@ plinenum(pos) int a = AT_NORMAL; char c = posmark(pos); if (c != 0) - a |= AT_HILITE; + a |= AT_HILITE|AT_COLOR_MARK; else { c = ' '; if (start_attnpos != NULL_POSITION && pos >= start_attnpos && pos <= end_attnpos) - a |= AT_HILITE; + a |= AT_HILITE|AT_COLOR_ATTN; } - add_linebuf(c, a, 1); /* column 0: status */ - add_linebuf(' ', AT_NORMAL, 1); /* column 1: empty */ + add_pfx(c, a); /* column 0: status */ + while (linebuf.pfx_end < status_col_width) + add_pfx(' ', AT_NORMAL); } /* @@ -241,155 +326,67 @@ plinenum(pos) if (linenums == OPT_ONPLUS) { char buf[INT_STRLEN_BOUND(linenum) + 2]; - int pad = 0; - int n; + int len; linenumtoa(linenum, buf); - n = (int) strlen(buf); - if (n < MIN_LINENUM_WIDTH) - pad = MIN_LINENUM_WIDTH - n; - for (i = 0; i < pad; i++) - add_linebuf(' ', AT_NORMAL, 1); - for (i = 0; i < n; i++) - add_linebuf(buf[i], AT_BOLD, 1); - add_linebuf(' ', AT_NORMAL, 1); - lmargin += n + pad + 1; - } - /* - * Append enough spaces to bring us to the lmargin. - */ - while (column < lmargin) - { - add_linebuf(' ', AT_NORMAL, 1); + len = (int) strlen(buf); + for (i = 0; i < linenum_width - len; i++) + add_pfx(' ', AT_NORMAL); + for (i = 0; i < len; i++) + add_pfx(buf[i], AT_NORMAL|AT_COLOR_LINENUM); + add_pfx(' ', AT_NORMAL); } + end_column = linebuf.pfx_end; } /* - * Shift the input line left. - * This means discarding N printable chars at the start of the buffer. + * Return the width of the line prefix (status column and line number). + * {{ Actual line number can be wider than linenum_width. }} + */ + public int +line_pfx_width(VOID_PARAM) +{ + int width = 0; + if (status_col) + width += status_col_width; + if (linenums == OPT_ONPLUS) + width += linenum_width + 1; + return width; +} + +/* + * Add char to the shifted_ansi buffer. */ static void -pshift(shift) - int shift; +add_ansi(ch) + char ch; { - LWCHAR prev_ch = 0; - unsigned char c; - int shifted = 0; - int to; - int from; - int len; - int width; - int prev_attr; - int next_attr; - - if (shift > column - lmargin) - shift = column - lmargin; - if (shift > curr - lmargin) - shift = curr - lmargin; - - to = from = lmargin; - /* - * We keep on going when shifted == shift - * to get all combining chars. - */ - while (shifted <= shift && from < curr) + if (shifted_ansi.end == shifted_ansi.size) { - c = linebuf[from]; - if (ctldisp == OPT_ONPLUS && IS_CSI_START(c)) - { - /* Keep cumulative effect. */ - linebuf[to] = c; - attr[to++] = attr[from++]; - while (from < curr && linebuf[from]) - { - linebuf[to] = linebuf[from]; - attr[to++] = attr[from]; - if (!is_ansi_middle(linebuf[from++])) - break; - } - continue; - } - - width = 0; - - if (!IS_ASCII_OCTET(c) && utf_mode) - { - /* Assumes well-formedness validation already done. */ - LWCHAR ch; - - len = utf_len(c); - if (from + len > curr) - break; - ch = get_wchar(linebuf + from); - if (!is_composing_char(ch) && !is_combining_char(prev_ch, ch)) - width = is_wide_char(ch) ? 2 : 1; - prev_ch = ch; - } else - { - len = 1; - if (c == '\b') - /* XXX - Incorrect if several '\b' in a row. */ - width = (utf_mode && is_wide_char(prev_ch)) ? -2 : -1; - else if (!control_char(c)) - width = 1; - prev_ch = 0; - } - - if (width == 2 && shift - shifted == 1) { - /* Should never happen when called by pshift_all(). */ - attr[to] = attr[from]; - /* - * Assume a wide_char will never be the first half of a - * combining_char pair, so reset prev_ch in case we're - * followed by a '\b'. - */ - prev_ch = linebuf[to++] = ' '; - from += len; - shifted++; - continue; - } - - /* Adjust width for magic cookies. */ - prev_attr = (to > 0) ? attr[to-1] : AT_NORMAL; - next_attr = (from + len < curr) ? attr[from + len] : prev_attr; - if (!is_at_equiv(attr[from], prev_attr) && - !is_at_equiv(attr[from], next_attr)) - { - width += attr_swidth(attr[from]); - if (from + len < curr) - width += attr_ewidth(attr[from]); - if (is_at_equiv(prev_attr, next_attr)) - { - width += attr_ewidth(prev_attr); - if (from + len < curr) - width += attr_swidth(next_attr); - } - } - - if (shift - shifted < width) - break; - from += len; - shifted += width; - if (shifted < 0) - shifted = 0; + /* Expand shifted_ansi buffer. */ + int size = (shifted_ansi.size == 0) ? 8 : shifted_ansi.size * 2; + char *buf = (char *) ecalloc(size, sizeof(char)); + memcpy(buf, shifted_ansi.buf, shifted_ansi.size); + if (shifted_ansi.buf != NULL) free(shifted_ansi.buf); + shifted_ansi.buf = buf; + shifted_ansi.size = size; } - while (from < curr) - { - linebuf[to] = linebuf[from]; - attr[to++] = attr[from++]; - } - curr = to; - column -= shifted; - cshift += shifted; + shifted_ansi.buf[shifted_ansi.end++] = ch; } /* - * + * Shift line left so that the last char is just to the left + * of the first visible column. */ public void pshift_all(VOID_PARAM) { - pshift(column); + int i; + for (i = linebuf.print; i < linebuf.end; i++) + if (linebuf.attr[i] == AT_ANSI) + add_ansi(linebuf.buf[i]); + linebuf.end = linebuf.print; + end_column = linebuf.pfx_end; } /* @@ -442,24 +439,28 @@ attr_ewidth(a) /* * Return the printing width of a given character and attribute, - * if the character were added to the current position in the line buffer. + * if the character were added after prev_ch. * Adding a character with a given attribute may cause an enter or exit * attribute sequence to be inserted, so this must be taken into account. */ - static int -pwidth(ch, a, prev_ch) + public int +pwidth(ch, a, prev_ch, prev_a) LWCHAR ch; int a; LWCHAR prev_ch; + int prev_a; { int w; if (ch == '\b') + { /* * Backspace moves backwards one or two positions. - * XXX - Incorrect if several '\b' in a row. */ + if (prev_a & (AT_ANSI|AT_BINARY)) + return strlen(prchar('\b')); return (utf_mode && is_wide_char(prev_ch)) ? -2 : -1; + } if (!utf_mode || is_ascii_char(ch)) { @@ -481,7 +482,7 @@ pwidth(ch, a, prev_ch) * * Some terminals, upon failure to compose a * composing character with the character(s) that - * precede(s) it will actually take up one column + * precede(s) it will actually take up one end_column * for the composing character; there isn't much * we could do short of testing the (complex) * composition process ourselves and printing @@ -498,64 +499,42 @@ pwidth(ch, a, prev_ch) w = 1; if (is_wide_char(ch)) w++; - if (curr > 0 && !is_at_equiv(attr[curr-1], a)) - w += attr_ewidth(attr[curr-1]); - if ((apply_at_specials(a) != AT_NORMAL) && - (curr == 0 || !is_at_equiv(attr[curr-1], a))) + if (linebuf.end > 0 && !is_at_equiv(linebuf.attr[linebuf.end-1], a)) + w += attr_ewidth(linebuf.attr[linebuf.end-1]); + if (apply_at_specials(a) != AT_NORMAL && + (linebuf.end == 0 || !is_at_equiv(linebuf.attr[linebuf.end-1], a))) w += attr_swidth(a); return (w); } /* * Delete to the previous base character in the line buffer. - * Return 1 if one is found. */ static int backc(VOID_PARAM) { - LWCHAR prev_ch; - char *p = linebuf + curr; - LWCHAR ch = step_char(&p, -1, linebuf + lmargin); - int width; - - /* This assumes that there is no '\b' in linebuf. */ - while ( curr > lmargin - && column > lmargin - && (!(attr[curr - 1] & (AT_ANSI|AT_BINARY)))) - { - curr = (int) (p - linebuf); - prev_ch = step_char(&p, -1, linebuf + lmargin); - width = pwidth(ch, attr[curr], prev_ch); - column -= width; - if (width > 0) - return 1; - ch = prev_ch; - } - - return 0; -} - -/* - * Are we currently within a recognized ANSI escape sequence? - */ - static int -in_ansi_esc_seq(VOID_PARAM) -{ + LWCHAR ch; char *p; - /* - * Search backwards for either an ESC (which means we ARE in a seq); - * or an end char (which means we're NOT in a seq). - */ - for (p = &linebuf[curr]; p > linebuf; ) + if (linebuf.end == 0) + return (0); + p = &linebuf.buf[linebuf.end]; + ch = step_char(&p, -1, linebuf.buf); + /* Skip back to the next nonzero-width char. */ + while (p > linebuf.buf) { - LWCHAR ch = step_char(&p, -1, linebuf); - if (IS_CSI_START(ch)) - return (1); - if (!is_ansi_middle(ch)) - return (0); + LWCHAR prev_ch; + int width; + linebuf.end = (int) (p - linebuf.buf); + prev_ch = step_char(&p, -1, linebuf.buf); + width = pwidth(ch, linebuf.attr[linebuf.end], prev_ch, linebuf.attr[linebuf.end-1]); + end_column -= width; + /* {{ right_column? }} */ + if (width > 0) + break; + ch = prev_ch; } - return (0); + return (1); } /* @@ -589,22 +568,91 @@ is_ansi_middle(ch) * pp is initially positioned just after the CSI_START char. */ public void -skip_ansi(pp, limit) +skip_ansi(pansi, pp, limit) + struct ansi_state *pansi; char **pp; constant char *limit; { LWCHAR c; do { c = step_char(pp, +1, limit); - } while (*pp < limit && is_ansi_middle(c)); - /* Note that we discard final char, for which is_ansi_middle is false. */ + } while (*pp < limit && ansi_step(pansi, c) == ANSI_MID); + /* Note that we discard final char, for which is_ansi_end is true. */ } +/* + * Determine if a character starts an ANSI escape sequence. + * If so, return an ansi_state struct; otherwise return NULL. + */ + public struct ansi_state * +ansi_start(ch) + LWCHAR ch; +{ + struct ansi_state *pansi; + + if (!IS_CSI_START(ch)) + return NULL; + pansi = ecalloc(1, sizeof(struct ansi_state)); + pansi->hindex = 0; + pansi->hlink = 0; + pansi->prev_esc = 0; + return pansi; +} + +/* + * Determine whether the next char in an ANSI escape sequence + * ends the sequence. + */ + public int +ansi_step(pansi, ch) + struct ansi_state *pansi; + LWCHAR ch; +{ + if (pansi->hlink) + { + /* Hyperlink ends with \7 or ESC-backslash. */ + if (ch == '\7') + return ANSI_END; + if (pansi->prev_esc && ch == '\\') + return ANSI_END; + pansi->prev_esc = (ch == ESC); + return ANSI_MID; + } + if (pansi->hindex >= 0) + { + static char hlink_prefix[] = ESCS "]8;"; + if (ch == hlink_prefix[pansi->hindex] || + (pansi->hindex == 0 && IS_CSI_START(ch))) + { + pansi->hindex++; + if (hlink_prefix[pansi->hindex] == '\0') + pansi->hlink = 1; /* now processing hyperlink addr */ + return ANSI_MID; + } + pansi->hindex = -1; /* not a hyperlink */ + } + /* Check for SGR sequences */ + if (is_ansi_middle(ch)) + return ANSI_MID; + if (is_ansi_end(ch)) + return ANSI_END; + return ANSI_ERR; +} + +/* + * Free an ansi_state structure. + */ + public void +ansi_done(pansi) + struct ansi_state *pansi; +{ + free(pansi); +} /* * Append a character and attribute to the line buffer. */ -#define STORE_CHAR(ch,a,rep,pos) \ +#define STORE_CHAR(ch,a,rep,pos) \ do { \ if (store_char((ch),(a),(rep),(pos))) return (1); \ } while (0) @@ -617,17 +665,19 @@ store_char(ch, a, rep, pos) POSITION pos; { int w; + int i; int replen; char cs; - w = (a & (AT_UNDERLINE|AT_BOLD)); /* Pre-use w. */ - if (w != AT_NORMAL) - last_overstrike = w; + i = (a & (AT_UNDERLINE|AT_BOLD)); + if (i != AT_NORMAL) + last_overstrike = i; #if HILITE_SEARCH { int matches; - if (is_hilited(pos, pos+1, 0, &matches)) + int hl_attr = is_hilited_attr(pos, pos+1, 0, &matches); + if (hl_attr) { /* * This character should be highlighted. @@ -635,43 +685,24 @@ store_char(ch, a, rep, pos) */ if (a != AT_ANSI) { - if (highest_hilite != NULL_POSITION && - pos > highest_hilite) - highest_hilite = pos; - a |= AT_HILITE; + if (highest_hilite != NULL_POSITION && pos > highest_hilite) + highest_hilite = pos; + a |= hl_attr; } } } #endif - if (ctldisp == OPT_ONPLUS && in_ansi_esc_seq()) - { - if (!is_ansi_end(ch) && !is_ansi_middle(ch)) { - /* Remove whole unrecognized sequence. */ - char *p = &linebuf[curr]; - LWCHAR bch; - do { - bch = step_char(&p, -1, linebuf); - } while (p > linebuf && !IS_CSI_START(bch)); - curr = (int) (p - linebuf); - return 0; - } - a = AT_ANSI; /* Will force re-AT_'ing around it. */ + if (a == AT_ANSI) { w = 0; - } - else if (ctldisp == OPT_ONPLUS && IS_CSI_START(ch)) - { - a = AT_ANSI; /* Will force re-AT_'ing around it. */ - w = 0; - } - else - { - char *p = &linebuf[curr]; - LWCHAR prev_ch = step_char(&p, -1, linebuf); - w = pwidth(ch, a, prev_ch); + } else { + char *p = &linebuf.buf[linebuf.end]; + LWCHAR prev_ch = (linebuf.end > 0) ? step_char(&p, -1, linebuf.buf) : 0; + int prev_a = (linebuf.end > 0) ? linebuf.attr[linebuf.end-1] : 0; + w = pwidth(ch, a, prev_ch, prev_a); } - if (ctldisp != OPT_ON && column + w + attr_ewidth(a) > sc_width) + if (ctldisp != OPT_ON && end_column - cshift + w + attr_ewidth(a) > sc_width) /* * Won't fit on screen. */ @@ -686,7 +717,7 @@ store_char(ch, a, rep, pos) { replen = utf_len(rep[0]); } - if (curr + replen >= size_linebuf-6) + if (linebuf.end + replen >= size_linebuf-6) { /* * Won't fit in line buffer. @@ -696,17 +727,42 @@ store_char(ch, a, rep, pos) return (1); } - if (column > right_column && w > 0) + if (cshift == hshift && shifted_ansi.end > 0) { - right_column = column; - right_curr = curr; + /* Copy shifted ANSI sequences to beginning of line. */ + for (i = 0; i < shifted_ansi.end; i++) + add_linebuf(shifted_ansi.buf[i], AT_ANSI, 0); + shifted_ansi.end = 0; } - - while (replen-- > 0) - { + /* Add the char to the buf, even if we will left-shift it next. */ + inc_end_column(w); + for (i = 0; i < replen; i++) add_linebuf(*rep++, a, 0); + + if (cshift < hshift) + { + /* We haven't left-shifted enough yet. */ + if (a == AT_ANSI) + add_ansi(ch); /* Save ANSI attributes */ + if (linebuf.end > linebuf.print) + { + /* Shift left enough to put last byte of this char at print-1. */ + memcpy(&linebuf.buf[0], &linebuf.buf[replen], linebuf.print); + memcpy(&linebuf.attr[0], &linebuf.attr[replen], linebuf.print); + linebuf.end -= replen; + cshift += w; + /* + * If the char we just left-shifted was double width, + * the 2 spaces we shifted may be too much. + * Represent the "half char" at start of line with a highlighted space. + */ + while (cshift > hshift) + { + add_linebuf(' ', rscroll_attr, 0); + cshift--; + } + } } - column += w; return (0); } @@ -714,7 +770,7 @@ store_char(ch, a, rep, pos) * Append a tab to the line buffer. * Store spaces to represent the tab. */ -#define STORE_TAB(a,pos) \ +#define STORE_TAB(a,pos) \ do { if (store_tab((a),(pos))) return (1); } while (0) static int @@ -722,23 +778,20 @@ store_tab(attr, pos) int attr; POSITION pos; { - int to_tab = column + cshift - lmargin; - int i; + int to_tab = end_column - linebuf.pfx_end; if (ntabstops < 2 || to_tab >= tabstops[ntabstops-1]) to_tab = tabdefault - ((to_tab - tabstops[ntabstops-1]) % tabdefault); else { + int i; for (i = ntabstops - 2; i >= 0; i--) if (to_tab >= tabstops[i]) break; to_tab = tabstops[i+1] - to_tab; } - if (column + to_tab - 1 + pwidth(' ', attr, 0) + attr_ewidth(attr) > sc_width) - return 1; - do { STORE_CHAR(' ', attr, " ", pos); } while (--to_tab > 0); @@ -759,18 +812,8 @@ store_prchar(c, pos) * Convert to printable representation. */ s = prchar(c); - - /* - * Make sure we can get the entire representation - * of the character on this line. - */ - if (column + (int) strlen(s) - 1 + - pwidth(' ', binattr, 0) + attr_ewidth(binattr) > sc_width) - return 1; - for ( ; *s != 0; s++) - STORE_CHAR(*s, AT_BINARY, NULL, pos); - + STORE_CHAR(*s, AT_BINARY|AT_COLOR_CTRL, NULL, pos); return 0; } @@ -783,7 +826,6 @@ flush_mbc_buf(pos) for (i = 0; i < mbc_buf_index; i++) if (store_prchar(mbc_buf[i], pos)) return mbc_buf_index - i; - return 0; } @@ -875,19 +917,7 @@ pappend(c, pos) /* Handle new char. */ if (!r) goto retry; - } - } - - /* - * If we need to shift the line, do it. - * But wait until we get to at least the middle of the screen, - * so shifting it doesn't affect the chars we're currently - * pappending. (Bold & underline can get messed up otherwise.) - */ - if (cshift < hshift && column > sc_width / 2) - { - linebuf[curr] = '\0'; - pshift(hshift - cshift); + } } if (r) { @@ -897,38 +927,92 @@ pappend(c, pos) return (r); } + static int +store_control_char(ch, rep, pos) + LWCHAR ch; + char *rep; + POSITION pos; +{ + if (ctldisp == OPT_ON) + { + /* Output the character itself. */ + STORE_CHAR(ch, AT_NORMAL, rep, pos); + } else + { + /* Output a printable representation of the character. */ + STORE_PRCHAR((char) ch, pos); + } + return (0); +} + + static int +store_ansi(ch, rep, pos) + LWCHAR ch; + char *rep; + POSITION pos; +{ + switch (ansi_step(line_ansi, ch)) + { + case ANSI_MID: + STORE_CHAR(ch, AT_ANSI, rep, pos); + break; + case ANSI_END: + STORE_CHAR(ch, AT_ANSI, rep, pos); + ansi_done(line_ansi); + line_ansi = NULL; + break; + case ANSI_ERR: { + /* Remove whole unrecognized sequence. */ + char *start = (cshift < hshift) ? shifted_ansi.buf : linebuf.buf; + int *end = (cshift < hshift) ? &shifted_ansi.end : &linebuf.end; + char *p = start + *end; + LWCHAR bch; + do { + bch = step_char(&p, -1, start); + } while (p > start && !IS_CSI_START(bch)); + *end = (int) (p - start); + ansi_done(line_ansi); + line_ansi = NULL; + break; } + } + return (0); +} + + static int +store_bs(ch, rep, pos) + LWCHAR ch; + char *rep; + POSITION pos; +{ + if (bs_mode == BS_CONTROL) + return store_control_char(ch, rep, pos); + if (linebuf.end > 0 && + ((linebuf.end <= linebuf.print && linebuf.buf[linebuf.end-1] == '\0') || + (linebuf.end > 0 && linebuf.attr[linebuf.end - 1] & (AT_ANSI|AT_BINARY)))) + STORE_PRCHAR('\b', pos); + else if (bs_mode == BS_NORMAL) + STORE_CHAR(ch, AT_NORMAL, NULL, pos); + else if (bs_mode == BS_SPECIAL) + overstrike = backc(); + return 0; +} + static int do_append(ch, rep, pos) LWCHAR ch; char *rep; POSITION pos; { - int a; - LWCHAR prev_ch; + int a = AT_NORMAL; - a = AT_NORMAL; + if (ctldisp == OPT_ONPLUS && line_ansi == NULL) + line_ansi = ansi_start(ch); + + if (line_ansi != NULL) + return store_ansi(ch, rep, pos); if (ch == '\b') - { - if (bs_mode == BS_CONTROL) - goto do_control_char; - - /* - * A better test is needed here so we don't - * backspace over part of the printed - * representation of a binary character. - */ - if ( curr <= lmargin - || column <= lmargin - || (attr[curr - 1] & (AT_ANSI|AT_BINARY))) - STORE_PRCHAR('\b', pos); - else if (bs_mode == BS_NORMAL) - STORE_CHAR(ch, AT_NORMAL, NULL, pos); - else if (bs_mode == BS_SPECIAL) - overstrike = backc(); - - return 0; - } + return store_bs(ch, rep, pos); if (overstrike > 0) { @@ -937,18 +1021,19 @@ do_append(ch, rep, pos) * in the line buffer. This will cause either * underline (if a "_" is overstruck), * bold (if an identical character is overstruck), - * or just deletion of the character in the buffer. + * or just replacing the character in the buffer. */ + LWCHAR prev_ch; overstrike = utf_mode ? -1 : 0; if (utf_mode) { /* To be correct, this must be a base character. */ - prev_ch = get_wchar(linebuf + curr); + prev_ch = get_wchar(&linebuf.buf[linebuf.end]); } else { - prev_ch = (unsigned char) linebuf[curr]; + prev_ch = (unsigned char) linebuf.buf[linebuf.end]; } - a = attr[curr]; + a = linebuf.attr[linebuf.end]; if (ch == prev_ch) { /* @@ -972,7 +1057,7 @@ do_append(ch, rep, pos) { a |= AT_UNDERLINE; ch = prev_ch; - rep = linebuf + curr; + rep = &linebuf.buf[linebuf.end]; } else if (prev_ch == '_') { a |= AT_UNDERLINE; @@ -981,14 +1066,14 @@ do_append(ch, rep, pos) } else if (overstrike < 0) { if ( is_composing_char(ch) - || is_combining_char(get_wchar(linebuf + curr), ch)) + || is_combining_char(get_wchar(&linebuf.buf[linebuf.end]), ch)) /* Continuation of the same overstrike. */ a = last_overstrike; else overstrike = 0; } - if (ch == '\t') + if (ch == '\t') { /* * Expand a tab into spaces. @@ -996,42 +1081,27 @@ do_append(ch, rep, pos) switch (bs_mode) { case BS_CONTROL: - goto do_control_char; + return store_control_char(ch, rep, pos); case BS_NORMAL: case BS_SPECIAL: STORE_TAB(a, pos); break; } - } else if ((!utf_mode || is_ascii_char(ch)) && control_char((char)ch)) + return (0); + } + if ((!utf_mode || is_ascii_char(ch)) && control_char((char)ch)) { - do_control_char: - if (ctldisp == OPT_ON || (ctldisp == OPT_ONPLUS && IS_CSI_START(ch))) - { - /* - * Output as a normal character. - */ - STORE_CHAR(ch, AT_NORMAL, rep, pos); - } else - { - STORE_PRCHAR((char) ch, pos); - } + return store_control_char(ch, rep, pos); } else if (utf_mode && ctldisp != OPT_ON && is_ubin_char(ch)) { - char *s; - - s = prutfchar(ch); - - if (column + (int) strlen(s) - 1 + - pwidth(' ', binattr, 0) + attr_ewidth(binattr) > sc_width) - return (1); - + char *s = prutfchar(ch); for ( ; *s != 0; s++) STORE_CHAR(*s, AT_BINARY, NULL, pos); - } else + } else { STORE_CHAR(ch, a, rep, pos); } - return (0); + return (0); } /* @@ -1084,12 +1154,6 @@ pdone(endline, chopped, forw) */ (void) do_append(pendc, NULL, pendpos); - /* - * Make sure we've shifted the line, if we need to. - */ - if (cshift < hshift) - pshift(hshift - cshift); - if (chopped && rscroll_char) { /* @@ -1097,21 +1161,21 @@ pdone(endline, chopped, forw) * If we've already filled the rightmost screen char * (in the buffer), overwrite it. */ - if (column >= sc_width) + if (end_column >= sc_width + cshift) { /* We've already written in the rightmost char. */ - column = right_column; - curr = right_curr; + end_column = right_column; + linebuf.end = right_curr; } add_attr_normal(); - while (column < sc_width-1) + while (end_column < sc_width-1 + cshift) { /* * Space to last (rightmost) char on screen. * This may be necessary if the char we overwrote * was double-width. */ - add_linebuf(' ', AT_NORMAL, 1); + add_linebuf(' ', rscroll_attr, 1); } /* Print rscroll char. It must be single-width. */ add_linebuf(rscroll_char, rscroll_attr, 1); @@ -1133,11 +1197,11 @@ pdone(endline, chopped, forw) * the next line is blank. In that case the single newline output for * that blank line would be ignored!) */ - if (column < sc_width || !auto_wrap || (endline && ignaw) || ctldisp == OPT_ON) + if (end_column < sc_width + cshift || !auto_wrap || (endline && ignaw) || ctldisp == OPT_ON) { add_linebuf('\n', AT_NORMAL, 0); } - else if (ignaw && column >= sc_width && forw) + else if (ignaw && end_column >= sc_width + cshift && forw) { /* * Terminals with "ignaw" don't wrap until they *really* need @@ -1156,17 +1220,18 @@ pdone(endline, chopped, forw) add_linebuf(' ', AT_NORMAL, 1); add_linebuf('\b', AT_NORMAL, -1); } - set_linebuf(curr, '\0', AT_NORMAL); + set_linebuf(linebuf.end, '\0', AT_NORMAL); } /* * */ public void -set_status_col(c) +set_status_col(c, attr) int c; + int attr; { - set_linebuf(0, c, AT_NORMAL|AT_HILITE); + set_pfx(0, c, attr); } /* @@ -1199,8 +1264,14 @@ gline(i, ap) return i ? '\0' : '\n'; } - *ap = attr[i]; - return (linebuf[i] & 0xFF); + if (i < linebuf.pfx_end) + { + *ap = linebuf.pfx_attr[i]; + return linebuf.pfx[i]; + } + i += linebuf.print - linebuf.pfx_end; + *ap = linebuf.attr[i]; + return (linebuf.buf[i] & 0xFF); } /* @@ -1252,12 +1323,12 @@ forw_raw_line(curr_pos, linep, line_lenp) break; } } - linebuf[n++] = c; + linebuf.buf[n++] = c; c = ch_forw_get(); } - linebuf[n] = '\0'; + linebuf.buf[n] = '\0'; if (linep != NULL) - *linep = linebuf; + *linep = linebuf.buf; if (line_lenp != NULL) *line_lenp = n; return (new_pos); @@ -1282,7 +1353,7 @@ back_raw_line(curr_pos, linep, line_lenp) return (NULL_POSITION); n = size_linebuf; - linebuf[--n] = '\0'; + linebuf.buf[--n] = '\0'; for (;;) { c = ch_back_get(); @@ -1322,16 +1393,16 @@ back_raw_line(curr_pos, linep, line_lenp) /* * Shift the data to the end of the new linebuf. */ - for (fm = linebuf + old_size_linebuf - 1, - to = linebuf + size_linebuf - 1; - fm >= linebuf; fm--, to--) + for (fm = linebuf.buf + old_size_linebuf - 1, + to = linebuf.buf + size_linebuf - 1; + fm >= linebuf.buf; fm--, to--) *to = *fm; n = size_linebuf - old_size_linebuf; } - linebuf[--n] = c; + linebuf.buf[--n] = c; } if (linep != NULL) - *linep = &linebuf[n]; + *linep = &linebuf.buf[n]; if (line_lenp != NULL) *line_lenp = size_linebuf - 1 - n; return (new_pos); @@ -1350,16 +1421,80 @@ rrshift(VOID_PARAM) save_width = sc_width; sc_width = INT_MAX; - hshift = 0; pos = position(TOP); for (line = 0; line < sc_height && pos != NULL_POSITION; line++) { pos = forw_line(pos); - if (column > longest) - longest = column; + if (end_column > longest) + longest = end_column; } sc_width = save_width; if (longest < sc_width) return 0; return longest - sc_width; } + +/* + * Get the color_map index associated with a given attribute. + */ + static int +color_index(attr) + int attr; +{ + if (use_color) + { + switch (attr & AT_COLOR) + { + case AT_COLOR_ATTN: return 0; + case AT_COLOR_BIN: return 1; + case AT_COLOR_CTRL: return 2; + case AT_COLOR_ERROR: return 3; + case AT_COLOR_LINENUM: return 4; + case AT_COLOR_MARK: return 5; + case AT_COLOR_PROMPT: return 6; + case AT_COLOR_RSCROLL: return 7; + case AT_COLOR_SEARCH: return 8; + } + } + if (attr & AT_UNDERLINE) + return 9; + if (attr & AT_BOLD) + return 10; + if (attr & AT_BLINK) + return 11; + if (attr & AT_STANDOUT) + return 12; + return -1; +} + +/* + * Set the color string to use for a given attribute. + */ + public int +set_color_map(attr, colorstr) + int attr; + char *colorstr; +{ + int cx = color_index(attr); + if (cx < 0) + return -1; + if (strlen(colorstr)+1 > sizeof(color_map[cx])) + return -1; + if (*colorstr != '\0' && parse_color(colorstr, NULL, NULL) == CT_NULL) + return -1; + strcpy(color_map[cx], colorstr); + return 0; +} + +/* + * Get the color string to use for a given attribute. + */ + public char * +get_color_map(attr) + int attr; +{ + int cx = color_index(attr); + if (cx < 0) + return NULL; + return color_map[cx]; +} diff --git a/contrib/less/linenum.c b/contrib/less/linenum.c index 46c315497ebd..00cac60d14d3 100644 --- a/contrib/less/linenum.c +++ b/contrib/less/linenum.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -40,11 +40,11 @@ */ struct linenum_info { - struct linenum_info *next; /* Link to next in the list */ - struct linenum_info *prev; /* Line to previous in the list */ - POSITION pos; /* File position */ - POSITION gap; /* Gap between prev and next */ - LINENUM line; /* Line number */ + struct linenum_info *next; /* Link to next in the list */ + struct linenum_info *prev; /* Line to previous in the list */ + POSITION pos; /* File position */ + POSITION gap; /* Gap between prev and next */ + LINENUM line; /* Line number */ }; /* * "gap" needs some explanation: the gap of any particular line number @@ -55,14 +55,14 @@ struct linenum_info * when we have a new one to insert and the table is full. */ -#define NPOOL 200 /* Size of line number pool */ +#define NPOOL 200 /* Size of line number pool */ -#define LONGTIME (2) /* In seconds */ +#define LONGTIME (2) /* In seconds */ -static struct linenum_info anchor; /* Anchor of the list */ -static struct linenum_info *freelist; /* Anchor of the unused entries */ -static struct linenum_info pool[NPOOL]; /* The pool itself */ -static struct linenum_info *spare; /* We always keep one spare entry */ +static struct linenum_info anchor; /* Anchor of the list */ +static struct linenum_info *freelist; /* Anchor of the unused entries */ +static struct linenum_info pool[NPOOL]; /* The pool itself */ +static struct linenum_info *spare; /* We always keep one spare entry */ extern int linenums; extern int sigs; @@ -248,6 +248,8 @@ longish(VOID_PARAM) static void abort_long(VOID_PARAM) { + if (loopcount >= 0) + return; if (linenums == OPT_ONPLUS) /* * We were displaying line numbers, so need to repaint. @@ -308,6 +310,7 @@ find_linenum(pos) #if HAVE_TIME startime = get_time(); #endif + loopcount = 0; if (p == &anchor || pos - p->prev->pos < p->pos - pos) { /* @@ -316,7 +319,6 @@ find_linenum(pos) p = p->prev; if (ch_seek(p->pos)) return (0); - loopcount = 0; for (linenum = p->line, cpos = p->pos; cpos < pos; linenum++) { /* @@ -348,7 +350,6 @@ find_linenum(pos) */ if (ch_seek(p->pos)) return (0); - loopcount = 0; for (linenum = p->line, cpos = p->pos; cpos > pos; linenum--) { /* @@ -368,7 +369,7 @@ find_linenum(pos) */ add_lnum(linenum, cpos); } - + loopcount = 0; return (linenum); } diff --git a/contrib/less/lsystem.c b/contrib/less/lsystem.c index 5e51c06d0aa5..5c67526e1030 100644 --- a/contrib/less/lsystem.c +++ b/contrib/less/lsystem.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -97,7 +97,7 @@ lsystem(cmd, donemsg) * De-initialize the terminal and take out of raw mode. */ deinit(); - flush(); /* Make sure the deinit chars get out */ + flush(); /* Make sure the deinit chars get out */ raw_mode(0); #if MSDOS_COMPILER==WIN32C close_getchr(); @@ -116,11 +116,13 @@ lsystem(cmd, donemsg) */ inp = dup(0); close(0); +#if !MSDOS_COMPILER #if OS2 /* The __open() system call translates "/dev/tty" to "con". */ - if (__open("/dev/tty", OPEN_READ) < 0) + if (__open(tty_device(), OPEN_READ) < 0) #else - if (open("/dev/tty", OPEN_READ) < 0) + if (open(tty_device(), OPEN_READ) < 0) +#endif #endif dup(inp); #endif @@ -169,7 +171,7 @@ lsystem(cmd, donemsg) * also makes trouble with some DPMI servers). */ __djgpp_exception_toggle(); - system(cmd); + system(cmd); __djgpp_exception_toggle(); #else system(cmd); @@ -274,14 +276,14 @@ pipe_mark(c, cmd) tpos = ch_zero(); bpos = position(BOTTOM); - if (c == '.') - return (pipe_data(cmd, tpos, bpos)); - else if (mpos <= tpos) - return (pipe_data(cmd, mpos, bpos)); - else if (bpos == NULL_POSITION) - return (pipe_data(cmd, tpos, bpos)); - else - return (pipe_data(cmd, tpos, mpos)); + if (c == '.') + return (pipe_data(cmd, tpos, bpos)); + else if (mpos <= tpos) + return (pipe_data(cmd, mpos, bpos)); + else if (bpos == NULL_POSITION) + return (pipe_data(cmd, tpos, bpos)); + else + return (pipe_data(cmd, tpos, mpos)); } /* @@ -346,14 +348,14 @@ pipe_data(cmd, spos, epos) /* * Finish up the last line. */ - while (c != '\n' && c != EOI ) - { - c = ch_forw_get(); - if (c == EOI) - break; - if (putc(c, f) == EOF) - break; - } + while (c != '\n' && c != EOI ) + { + c = ch_forw_get(); + if (c == EOI) + break; + if (putc(c, f) == EOF) + break; + } pclose(f); diff --git a/contrib/less/main.c b/contrib/less/main.c index 44b217610778..4f8526b69225 100644 --- a/contrib/less/main.c +++ b/contrib/less/main.c @@ -1,6 +1,6 @@ /* $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 * License or the Less License, as specified in the README file. @@ -19,50 +19,49 @@ #include #endif -public char * every_first_cmd = NULL; -public int new_file; -public int is_tty; -public IFILE curr_ifile = NULL_IFILE; -public IFILE old_ifile = NULL_IFILE; +public char * every_first_cmd = NULL; +public int new_file; +public int is_tty; +public IFILE curr_ifile = NULL_IFILE; +public IFILE old_ifile = NULL_IFILE; public struct scrpos initial_scrpos; -public int any_display = FALSE; -public POSITION start_attnpos = NULL_POSITION; -public POSITION end_attnpos = NULL_POSITION; -public int wscroll; -public char * progname; -public int quitting; -public int secure; -public int dohelp; +public POSITION start_attnpos = NULL_POSITION; +public POSITION end_attnpos = NULL_POSITION; +public int wscroll; +public char * progname; +public int quitting; +public int secure; +public int dohelp; #if LOGFILE -public int logfile = -1; -public int force_logfile = FALSE; -public char * namelogfile = NULL; +public int logfile = -1; +public int force_logfile = FALSE; +public char * namelogfile = NULL; #endif #if EDITOR -public char * editor; -public char * editproto; +public char * editor; +public char * editproto; #endif #if TAGS -extern char * tags; -extern char * tagoption; -extern int jump_sline; +extern char * tags; +extern char * tagoption; +extern int jump_sline; #endif #ifdef WIN32 static char consoleTitle[256]; #endif -public int one_screen; -extern int less_is_more; -extern int missing_cap; -extern int know_dumb; -extern int no_init; -extern int pr_type; -extern int quit_if_one_screen; -extern int no_init; +public int one_screen; +extern int less_is_more; +extern int missing_cap; +extern int know_dumb; +extern int pr_type; +extern int quit_if_one_screen; +extern int no_init; +extern int errmsgs; /* @@ -84,10 +83,14 @@ main(argc, argv) progname = *argv++; argc--; +#if SECURE + secure = 1; +#else secure = 0; s = lgetenv("LESSSECURE"); if (!isnullenv(s)) secure = 1; +#endif #ifdef WIN32 if (getenv("HOME") == NULL) @@ -142,7 +145,7 @@ main(argc, argv) if (s != NULL) 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') while (argc > 0 && (isoptstring(*argv) || isoptpending())) { @@ -228,6 +231,7 @@ main(argc, argv) * Output is not a tty. * Just copy the input file(s) to output. */ + set_output(1); /* write to stdout */ SET_BINARY(1); if (edit_first() == 0) { @@ -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(); commands(); quit(QUIT_OK); @@ -340,7 +356,7 @@ ecalloc(count, size) skipsp(s) char *s; { - while (*s == ' ' || *s == '\t') + while (*s == ' ' || *s == '\t') s++; return (s); } @@ -397,10 +413,13 @@ quit(status) status = save_status; else save_status = status; +#if LESSTEST + rstat('Q'); +#endif /*LESSTEST*/ quitting = 1; edit((char*)NULL); save_cmdhist(); - if (any_display && is_tty) + if (interactive()) clear_bot(); deinit(); flush(); diff --git a/contrib/less/mark.c b/contrib/less/mark.c index e86d7b31e69e..cbb316f276e6 100644 --- a/contrib/less/mark.c +++ b/contrib/less/mark.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -38,10 +38,10 @@ struct mark * Each mark is identified by a lowercase or uppercase letter. * The final one is lmark, for the "last mark"; addressed by the apostrophe. */ -#define NMARKS ((2*26)+2) /* a-z, A-Z, mousemark, lastmark */ -#define NUMARKS ((2*26)+1) /* user marks (not lastmark) */ -#define MOUSEMARK (NMARKS-2) -#define LASTMARK (NMARKS-1) +#define NMARKS ((2*26)+2) /* a-z, A-Z, mousemark, lastmark */ +#define NUMARKS ((2*26)+1) /* user marks (not lastmark) */ +#define MOUSEMARK (NMARKS-2) +#define LASTMARK (NMARKS-1) static struct mark marks[NMARKS]; public int marks_modified = 0; @@ -116,13 +116,17 @@ mark_get_ifile(m) getumark(c) int c; { + PARG parg; if (c >= 'a' && c <= 'z') return (&marks[c-'a']); if (c >= 'A' && c <= 'Z') return (&marks[c-'A'+26]); + if (c == '\'') + return (&marks[LASTMARK]); if (c == '#') return (&marks[MOUSEMARK]); - error("Invalid mark letter", NULL_PARG); + parg.p_char = (char) c; + error("Invalid mark letter %c", &parg); return (NULL); } @@ -259,6 +263,7 @@ lastmark(VOID_PARAM) if (scrpos.pos == NULL_POSITION) return; cmark(&marks[LASTMARK], curr_ifile, scrpos.pos, scrpos.ln); + marks_modified = 1; } /* @@ -370,7 +375,7 @@ mark_check_ifile(ifile) IFILE ifile; { int i; - char *filename = lrealpath(get_filename(ifile)); + char *filename = get_real_filename(ifile); for (i = 0; i < NMARKS; i++) { @@ -384,7 +389,6 @@ mark_check_ifile(ifile) free(mark_filename); } } - free(filename); } #if CMD_HISTORY @@ -403,7 +407,7 @@ save_marks(fout, hdr) return; fprintf(fout, "%s\n", hdr); - for (i = 0; i < NUMARKS; i++) + for (i = 0; i < NMARKS; i++) { char *filename; struct mark *m = &marks[i]; @@ -413,12 +417,10 @@ save_marks(fout, hdr) postoa(m->m_scrpos.pos, pos_str); filename = m->m_filename; if (filename == NULL) - filename = get_filename(m->m_ifile); - filename = lrealpath(filename); + filename = get_real_filename(m->m_ifile); if (strcmp(filename, "-") != 0) fprintf(fout, "m %c %d %s %s\n", m->m_letter, m->m_scrpos.ln, pos_str, filename); - free(filename); } } diff --git a/contrib/less/optfunc.c b/contrib/less/optfunc.c index c04f9d4a2480..768fe0e98aed 100644 --- a/contrib/less/optfunc.c +++ b/contrib/less/optfunc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -19,9 +19,9 @@ * Each handling function is passed a "type" and, if it is a string * option, the string which should be "assigned" to the option. * The type may be one of: - * INIT The option is being initialized from the command line. - * TOGGLE The option is being changed from within the program. - * QUERY The setting of the option is merely being queried. + * INIT The option is being initialized from the command line. + * TOGGLE The option is being changed from within the program. + * QUERY The setting of the option is merely being queried. */ #include "less.h" @@ -36,7 +36,7 @@ extern int sc_width; extern int sc_height; extern int secure; extern int dohelp; -extern int any_display; +extern int is_tty; extern char openquote; extern char closequote; extern char *prproto[]; @@ -55,6 +55,9 @@ extern int rscroll_attr; extern int mousecap; extern int wheel_lines; extern int less_is_more; +extern int linenum_width; +extern int status_col_width; +extern int use_color; #if LOGFILE extern char *namelogfile; extern int force_logfile; @@ -65,6 +68,10 @@ public char *tagoption = NULL; extern char *tags; extern char ztags[]; #endif +#if LESSTEST +extern char *ttyin_name; +extern int rstat_file; +#endif /*LESSTEST*/ #if MSDOS_COMPILER extern int nm_fg_color, nm_bg_color; extern int bo_fg_color, bo_bg_color; @@ -395,13 +402,13 @@ opt_p(type, s) } else { plusoption = TRUE; - ungetcc(CHAR_END_COMMAND); - ungetsc(s); /* * {{ This won't work if the "/" command is * changed or invalidated by a .lesskey file. }} */ ungetsc("/"); + ungetsc(s); + ungetcc_back(CHAR_END_COMMAND); } break; } @@ -427,13 +434,13 @@ opt__P(type, s) */ switch (*s) { - case 's': proto = &prproto[PR_SHORT]; s++; break; - case 'm': proto = &prproto[PR_MEDIUM]; s++; break; - case 'M': proto = &prproto[PR_LONG]; s++; break; - case '=': proto = &eqproto; s++; break; - case 'h': proto = &hproto; s++; break; - case 'w': proto = &wproto; s++; break; - default: proto = &prproto[PR_SHORT]; break; + case 's': proto = &prproto[PR_SHORT]; s++; break; + case 'm': proto = &prproto[PR_MEDIUM]; s++; break; + case 'M': proto = &prproto[PR_LONG]; s++; break; + case '=': proto = &eqproto; s++; break; + case 'h': proto = &hproto; s++; break; + case 'w': proto = &wproto; s++; break; + default: proto = &prproto[PR_SHORT]; break; } free(*proto); *proto = save(s); @@ -504,20 +511,28 @@ opt__V(type, s) dispversion(); break; case INIT: - /* - * Force output to stdout per GNU standard for --version output. - */ - any_display = 1; + set_output(1); /* Force output to stdout per GNU standard for --version output. */ putstr("less "); putstr(version); putstr(" ("); putstr(pattern_lib_name()); putstr(" regular expressions)\n"); - putstr("Copyright (C) 1984-2020 Mark Nudelman\n\n"); + { + char constant *copyright = "Copyright (C) 1984-2021 Mark Nudelman\n\n"; + if (copyright[0] == '@') + copyright = "Copyright (C) 1984 Mark Nudelman\n\n"; + putstr(copyright); + } + if (version[strlen(version)-1] == 'x') + { + putstr("** This is an EXPERIMENTAL build of the 'less' software,\n"); + putstr("** and may not function correctly.\n"); + putstr("** Obtain release builds from the web page below.\n\n"); + } putstr("less comes with NO WARRANTY, to the extent permitted by law.\n"); putstr("For information about the terms of redistribution,\n"); putstr("see the file named README in the less distribution.\n"); - putstr("Home page: http://www.greenwoodsoftware.com/less\n"); + putstr("Home page: https://greenwoodsoftware.com/less\n"); quit(QUIT_OK); break; } @@ -527,60 +542,70 @@ opt__V(type, s) /* * Parse an MSDOS color descriptor. */ - static void + static void colordesc(s, fg_color, bg_color) char *s; int *fg_color; int *bg_color; { int fg, bg; - int err; #if MSDOS_COMPILER==WIN32C int ul = 0; - + if (*s == 'u') { ul = COMMON_LVB_UNDERSCORE; - ++s; - } -#endif - fg = getnum(&s, "D", &err); - if (err) - { -#if MSDOS_COMPILER==WIN32C - if (ul) - fg = nm_fg_color; - else -#endif - { - error("Missing fg color in -D", NULL_PARG); - return; - } - } - if (*s != '.') - bg = nm_bg_color; - else - { s++; - bg = getnum(&s, "D", &err); - if (err) + if (*s == '\0') { - error("Missing bg color in -D", NULL_PARG); + *fg_color = nm_fg_color | ul; + *bg_color = nm_bg_color; return; } } -#if MSDOS_COMPILER==WIN32C - if (*s == 'u') - { - ul = COMMON_LVB_UNDERSCORE; - ++s; - } - fg |= ul; #endif - if (*s != '\0') - error("Extra characters at end of -D option", NULL_PARG); - *fg_color = fg; - *bg_color = bg; + if (parse_color(s, &fg, &bg) == CT_NULL) + { + PARG p; + p.p_string = s; + error("Invalid color string \"%s\"", &p); + } else + { + if (fg == CV_NOCHANGE) + fg = nm_fg_color; + if (bg == CV_NOCHANGE) + bg = nm_bg_color; +#if MSDOS_COMPILER==WIN32C + fg |= ul; +#endif + *fg_color = fg; + *bg_color = bg; + } +} +#endif + + static int +color_from_namechar(namechar) + char namechar; +{ + switch (namechar) + { + case 'A': return AT_COLOR_ATTN; + case 'B': return AT_COLOR_BIN; + case 'C': return AT_COLOR_CTRL; + case 'E': return AT_COLOR_ERROR; + case 'M': return AT_COLOR_MARK; + case 'N': return AT_COLOR_LINENUM; + case 'P': return AT_COLOR_PROMPT; + case 'R': return AT_COLOR_RSCROLL; + case 'S': return AT_COLOR_SEARCH; + case 'n': return AT_NORMAL; + case 's': return AT_STANDOUT; + case 'd': return AT_BOLD; + case 'u': return AT_UNDERLINE; + case 'k': return AT_BLINK; + default: return -1; + } } /* @@ -593,48 +618,75 @@ opt_D(type, s) char *s; { PARG p; + int attr; switch (type) { case INIT: case TOGGLE: - switch (*s++) +#if MSDOS_COMPILER + if (*s == 'a') { - case 'n': - colordesc(s, &nm_fg_color, &nm_bg_color); - break; - case 'd': - colordesc(s, &bo_fg_color, &bo_bg_color); - break; - case 'u': - colordesc(s, &ul_fg_color, &ul_bg_color); - break; - case 'k': - colordesc(s, &bl_fg_color, &bl_bg_color); - break; - case 's': - colordesc(s, &so_fg_color, &so_bg_color); - break; - case 'a': sgr_mode = !sgr_mode; break; - default: - error("-D must be followed by n, d, u, k, s or a", NULL_PARG); - break; } - if (type == TOGGLE) +#endif + attr = color_from_namechar(s[0]); + if (attr < 0) { - at_enter(AT_STANDOUT); - at_exit(); + p.p_char = s[0]; + error("Invalid color specifier '%c'", &p); + return; + } + if (!use_color && (attr & AT_COLOR)) + { + error("Set --use-color before changing colors", NULL_PARG); + return; + } + s++; +#if MSDOS_COMPILER + if (!(attr & AT_COLOR)) + { + switch (attr) + { + case AT_NORMAL: + colordesc(s, &nm_fg_color, &nm_bg_color); + break; + case AT_BOLD: + colordesc(s, &bo_fg_color, &bo_bg_color); + break; + case AT_UNDERLINE: + colordesc(s, &ul_fg_color, &ul_bg_color); + break; + case AT_BLINK: + colordesc(s, &bl_fg_color, &bl_bg_color); + break; + case AT_STANDOUT: + colordesc(s, &so_fg_color, &so_bg_color); + break; + } + if (type == TOGGLE) + { + at_enter(AT_STANDOUT); + at_exit(); + } + } else +#endif + if (set_color_map(attr, s) < 0) + { + p.p_string = s; + error("Invalid color string \"%s\"", &p); + return; } break; +#if MSDOS_COMPILER case QUERY: p.p_string = (sgr_mode) ? "on" : "off"; error("SGR mode is %s", &p); break; +#endif } } -#endif /* * Handler for the -x option. @@ -759,7 +811,7 @@ opt_rscroll(type, s) } else { rscroll_char = *fmt ? *fmt : '>'; - rscroll_attr = attr; + rscroll_attr = attr|AT_COLOR_RSCROLL; } break; } case QUERY: { @@ -834,6 +886,103 @@ opt_wheel_lines(type, s) } } +/* + * Handler for the --line-number-width option. + */ + /*ARGSUSED*/ + public void +opt_linenum_width(type, s) + int type; + char *s; +{ + PARG parg; + + switch (type) + { + case INIT: + case TOGGLE: + if (linenum_width > MAX_LINENUM_WIDTH) + { + parg.p_int = MAX_LINENUM_WIDTH; + error("Line number width must not be larger than %d", &parg); + linenum_width = MIN_LINENUM_WIDTH; + } + break; + case QUERY: + break; + } +} + +/* + * Handler for the --status-column-width option. + */ + /*ARGSUSED*/ + public void +opt_status_col_width(type, s) + int type; + char *s; +{ + PARG parg; + + switch (type) + { + case INIT: + case TOGGLE: + if (status_col_width > MAX_STATUSCOL_WIDTH) + { + parg.p_int = MAX_STATUSCOL_WIDTH; + error("Status column width must not be larger than %d", &parg); + status_col_width = 2; + } + break; + case QUERY: + break; + } +} + +#if LESSTEST +/* + * Handler for the --tty option. + */ + /*ARGSUSED*/ + public void +opt_ttyin_name(type, s) + int type; + char *s; +{ + switch (type) + { + case INIT: + ttyin_name = s; + is_tty = 1; + break; + } +} + +/* + * Handler for the --rstat option. + */ + /*ARGSUSED*/ + public void +opt_rstat(type, s) + int type; + char *s; +{ + switch (type) + { + case INIT: + rstat_file = open(s, O_WRONLY|O_CREAT, 0664); + if (rstat_file < 0) + { + PARG parg; + parg.p_string = s; + error("Cannot create rstat file \"%s\"", &parg); + } + break; + } +} +#endif /*LESSTEST*/ + /* * Get the "screen window" size. */ diff --git a/contrib/less/option.c b/contrib/less/option.c index 9cb19bc5472d..61247d81ee9b 100644 --- a/contrib/less/option.c +++ b/contrib/less/option.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -23,8 +23,7 @@ static struct loption *pendopt; public int plusoption = FALSE; -static char *optstring LESSPARAMS((char *s, char **p_str, char *printopt, - char *validchars)); +static char *optstring LESSPARAMS((char *s, char **p_str, char *printopt, char *validchars)); static int flip_triple LESSPARAMS((int val, int lc)); extern int screen_trashed; @@ -157,8 +156,8 @@ scan_option(s) every_first_cmd = save(str+1); } else { - ungetcc(CHAR_END_COMMAND); ungetsc(str); + ungetcc_back(CHAR_END_COMMAND); } free(str); continue; @@ -297,10 +296,10 @@ scan_option(s) * Toggle command line flags from within the program. * Used by the "-" and "_" commands. * how_toggle may be: - * OPT_NO_TOGGLE just report the current setting, without changing it. - * OPT_TOGGLE invert the current setting - * OPT_UNSET set to the default value - * OPT_SET set to the inverse of the default value + * OPT_NO_TOGGLE just report the current setting, without changing it. + * OPT_TOGGLE invert the current setting + * OPT_UNSET set to the default value + * OPT_SET set to the inverse of the default value */ public void toggle_option(o, lower, s, how_toggle) @@ -384,10 +383,10 @@ toggle_option(o, lower, s, how_toggle) case TRIPLE: /* * Triple: - * If user gave the lower case letter, then switch - * to 1 unless already 1, in which case make it 0. - * If user gave the upper case letter, then switch - * to 2 unless already 2, in which case make it 0. + * If user gave the lower case letter, then switch + * to 1 unless already 1, in which case make it 0. + * If user gave the upper case letter, then switch + * to 2 unless already 2, in which case make it 0. */ switch (how_toggle) { @@ -405,7 +404,7 @@ toggle_option(o, lower, s, how_toggle) case STRING: /* * String: don't do anything here. - * The handling function will do everything. + * The handling function will do everything. */ switch (how_toggle) { diff --git a/contrib/less/option.h b/contrib/less/option.h index c705aca19b48..4a10d6b8b228 100644 --- a/contrib/less/option.h +++ b/contrib/less/option.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -8,59 +8,59 @@ */ -#define END_OPTION_STRING ('$') +#define END_OPTION_STRING ('$') /* * Types of options. */ -#define BOOL 01 /* Boolean option: 0 or 1 */ -#define TRIPLE 02 /* Triple-valued option: 0, 1 or 2 */ -#define NUMBER 04 /* Numeric option */ -#define STRING 010 /* String-valued option */ -#define NOVAR 020 /* No associated variable */ -#define REPAINT 040 /* Repaint screen after toggling option */ -#define NO_TOGGLE 0100 /* Option cannot be toggled with "-" cmd */ -#define HL_REPAINT 0200 /* Repaint hilites after toggling option */ -#define NO_QUERY 0400 /* Option cannot be queried with "_" cmd */ -#define INIT_HANDLER 01000 /* Call option handler function at startup */ +#define BOOL 01 /* Boolean option: 0 or 1 */ +#define TRIPLE 02 /* Triple-valued option: 0, 1 or 2 */ +#define NUMBER 04 /* Numeric option */ +#define STRING 010 /* String-valued option */ +#define NOVAR 020 /* No associated variable */ +#define REPAINT 040 /* Repaint screen after toggling option */ +#define NO_TOGGLE 0100 /* Option cannot be toggled with "-" cmd */ +#define HL_REPAINT 0200 /* Repaint hilites after toggling option */ +#define NO_QUERY 0400 /* Option cannot be queried with "_" cmd */ +#define INIT_HANDLER 01000 /* Call option handler function at startup */ -#define OTYPE (BOOL|TRIPLE|NUMBER|STRING|NOVAR) +#define OTYPE (BOOL|TRIPLE|NUMBER|STRING|NOVAR) #define OLETTER_NONE '\1' /* Invalid option letter */ /* * Argument to a handling function tells what type of activity: */ -#define INIT 0 /* Initialization (from command line) */ -#define QUERY 1 /* Query (from _ or - command) */ -#define TOGGLE 2 /* Change value (from - command) */ +#define INIT 0 /* Initialization (from command line) */ +#define QUERY 1 /* Query (from _ or - command) */ +#define TOGGLE 2 /* Change value (from - command) */ /* Flag to toggle_option to specify how to "toggle" */ -#define OPT_NO_TOGGLE 0 -#define OPT_TOGGLE 1 -#define OPT_UNSET 2 -#define OPT_SET 3 -#define OPT_NO_PROMPT 0100 +#define OPT_NO_TOGGLE 0 +#define OPT_TOGGLE 1 +#define OPT_UNSET 2 +#define OPT_SET 3 +#define OPT_NO_PROMPT 0100 /* Error code from findopt_name */ #define OPT_AMBIG 1 struct optname { - char *oname; /* Long (GNU-style) option name */ - struct optname *onext; /* List of synonymous option names */ + char *oname; /* Long (GNU-style) option name */ + struct optname *onext; /* List of synonymous option names */ }; -#define OPTNAME_MAX 32 /* Max length of long option name */ +#define OPTNAME_MAX 32 /* Max length of long option name */ struct loption { - char oletter; /* The controlling letter (a-z) */ - struct optname *onames; /* Long (GNU-style) option name */ - int otype; /* Type of the option */ - int odefault; /* Default value */ - int *ovar; /* Pointer to the associated variable */ - void (*ofunc) LESSPARAMS ((int, char*)); /* Pointer to special handling function */ - char *odesc[3]; /* Description of each value */ + char oletter; /* The controlling letter (a-z) */ + struct optname *onames; /* Long (GNU-style) option name */ + int otype; /* Type of the option */ + int odefault; /* Default value */ + int *ovar; /* Pointer to the associated variable */ + void (*ofunc) LESSPARAMS ((int, char*)); /* Pointer to special handling function */ + char *odesc[3]; /* Description of each value */ }; diff --git a/contrib/less/opttbl.c b/contrib/less/opttbl.c index 1871f8a027a3..3a5d28385162 100644 --- a/contrib/less/opttbl.c +++ b/contrib/less/opttbl.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -18,52 +18,56 @@ /* * Variables controlled by command line options. */ -public int quiet; /* Should we suppress the audible bell? */ -public int how_search; /* Where should forward searches start? */ -public int top_scroll; /* Repaint screen from top? - (alternative is scroll from bottom) */ -public int pr_type; /* Type of prompt (short, medium, long) */ -public int bs_mode; /* How to process backspaces */ -public int know_dumb; /* Don't complain about dumb terminals */ -public int quit_at_eof; /* Quit after hitting end of file twice */ -public int quit_if_one_screen; /* Quit if EOF on first screen */ -public int squeeze; /* Squeeze multiple blank lines into one */ -public int tabstop; /* Tab settings */ -public int back_scroll; /* Repaint screen on backwards movement */ -public int forw_scroll; /* Repaint screen on forward movement */ -public int caseless; /* Do "caseless" searches */ -public int linenums; /* Use line numbers */ -public int autobuf; /* Automatically allocate buffers as needed */ -public int bufspace; /* Max buffer space per file (K) */ -public int ctldisp; /* Send control chars to screen untranslated */ -public int force_open; /* Open the file even if not regular file */ -public int swindow; /* Size of scrolling window */ -public int jump_sline; /* Screen line of "jump target" */ +public int quiet; /* Should we suppress the audible bell? */ +public int how_search; /* Where should forward searches start? */ +public int top_scroll; /* Repaint screen from top? + (alternative is scroll from bottom) */ +public int pr_type; /* Type of prompt (short, medium, long) */ +public int bs_mode; /* How to process backspaces */ +public int know_dumb; /* Don't complain about dumb terminals */ +public int quit_at_eof; /* Quit after hitting end of file twice */ +public int quit_if_one_screen; /* Quit if EOF on first screen */ +public int squeeze; /* Squeeze multiple blank lines into one */ +public int tabstop; /* Tab settings */ +public int back_scroll; /* Repaint screen on backwards movement */ +public int forw_scroll; /* Repaint screen on forward movement */ +public int caseless; /* Do "caseless" searches */ +public int linenums; /* Use line numbers */ +public int autobuf; /* Automatically allocate buffers as needed */ +public int bufspace; /* Max buffer space per file (K) */ +public int ctldisp; /* Send control chars to screen untranslated */ +public int force_open; /* Open the file even if not regular file */ +public int swindow; /* Size of scrolling window */ +public int jump_sline; /* Screen line of "jump target" */ public long jump_sline_fraction = -1; public long shift_count_fraction = -1; -public int chopline; /* Truncate displayed lines at screen width */ -public int no_init; /* Disable sending ti/te termcap strings */ -public int no_keypad; /* Disable sending ks/ke termcap strings */ +public int chopline; /* Truncate displayed lines at screen width */ +public int no_init; /* Disable sending ti/te termcap strings */ +public int no_keypad; /* Disable sending ks/ke termcap strings */ public int twiddle; /* Show tildes after EOF */ -public int show_attn; /* Hilite first unread line */ -public int shift_count; /* Number of positions to shift horizontally */ -public int status_col; /* Display a status column */ -public int use_lessopen; /* Use the LESSOPEN filter */ -public int quit_on_intr; /* Quit on interrupt */ -public int follow_mode; /* F cmd Follows file desc or file name? */ -public int oldbot; /* Old bottom of screen behavior {{REMOVE}} */ -public int opt_use_backslash; /* Use backslash escaping in option parsing */ -public char rscroll_char; /* Char which marks chopped lines with -S */ -public int rscroll_attr; /* Attribute of rscroll_char */ -public int no_hist_dups; /* Remove dups from history list */ -public int mousecap; /* Allow mouse for scrolling */ -public int wheel_lines; /* Number of lines to scroll on mouse wheel scroll */ -public int perma_marks; /* Save marks in history file */ +public int show_attn; /* Hilite first unread line */ +public int shift_count; /* Number of positions to shift horizontally */ +public int status_col; /* Display a status column */ +public int use_lessopen; /* Use the LESSOPEN filter */ +public int quit_on_intr; /* Quit on interrupt */ +public int follow_mode; /* F cmd Follows file desc or file name? */ +public int oldbot; /* Old bottom of screen behavior {{REMOVE}} */ +public int opt_use_backslash; /* Use backslash escaping in option parsing */ +public char rscroll_char; /* Char which marks chopped lines with -S */ +public int rscroll_attr; /* Attribute of rscroll_char */ +public int no_hist_dups; /* Remove dups from history list */ +public int mousecap; /* Allow mouse for scrolling */ +public int wheel_lines; /* Number of lines to scroll on mouse wheel scroll */ +public int perma_marks; /* Save marks in history file */ +public int linenum_width; /* Width of line numbers */ +public int status_col_width; /* Width of status column */ +public int incr_search; /* Incremental search */ +public int use_color; /* Use UI color */ #if HILITE_SEARCH -public int hilite_search; /* Highlight matched search patterns? */ +public int hilite_search; /* Highlight matched search patterns? */ #endif -public int less_is_more = 0; /* Make compatible with POSIX more */ +public int less_is_more = 0; /* Make compatible with POSIX more */ /* * Long option names. @@ -73,9 +77,7 @@ static struct optname b_optname = { "buffers", NULL }; static struct optname B__optname = { "auto-buffers", NULL }; static struct optname c_optname = { "clear-screen", NULL }; static struct optname d_optname = { "dumb", NULL }; -#if MSDOS_COMPILER static struct optname D__optname = { "color", NULL }; -#endif static struct optname e_optname = { "quit-at-eof", NULL }; static struct optname f_optname = { "force", NULL }; static struct optname F__optname = { "quit-if-one-screen", NULL }; @@ -127,7 +129,15 @@ static struct optname rscroll_optname = { "rscroll", NULL }; static struct optname nohistdups_optname = { "no-histdups", NULL }; static struct optname mousecap_optname = { "mouse", NULL }; static struct optname wheel_lines_optname = { "wheel-lines", NULL }; -static struct optname perma_marks_optname = { "save-marks", NULL }; +static struct optname perma_marks_optname = { "save-marks", NULL }; +static struct optname linenum_width_optname = { "line-num-width", NULL }; +static struct optname status_col_width_optname = { "status-col-width", NULL }; +static struct optname incr_search_optname = { "incsearch", NULL }; +static struct optname use_color_optname = { "use-color", NULL }; +#if LESSTEST +static struct optname ttyin_name_optname = { "tty", NULL }; +static struct optname rstat_optname = { "rstat", NULL }; +#endif /*LESSTEST*/ /* @@ -185,16 +195,14 @@ static struct loption option[] = NULL } }, -#if MSDOS_COMPILER { 'D', &D__optname, - STRING|REPAINT, 0, NULL, opt_D, + STRING|REPAINT|NO_QUERY, 0, NULL, opt_D, { "color desc: ", - "Dadknsu0123456789.", + NULL, NULL } }, -#endif { 'e', &e_optname, TRIPLE, OPT_OFF, &quit_at_eof, NULL, { @@ -503,6 +511,56 @@ static struct loption option[] = NULL } }, + { OLETTER_NONE, &linenum_width_optname, + NUMBER|REPAINT, MIN_LINENUM_WIDTH, &linenum_width, opt_linenum_width, + { + "Line number width: ", + "Line number width is %d chars", + NULL + } + }, + { OLETTER_NONE, &status_col_width_optname, + NUMBER|REPAINT, 2, &status_col_width, opt_status_col_width, + { + "Status column width: ", + "Status column width is %d chars", + NULL + } + }, + { OLETTER_NONE, &incr_search_optname, + BOOL, OPT_OFF, &incr_search, NULL, + { + "Incremental search is off", + "Incremental search is on", + NULL + } + }, + { OLETTER_NONE, &use_color_optname, + BOOL|REPAINT, OPT_OFF, &use_color, NULL, + { + "Don't use color", + "Use color", + NULL + } + }, +#if LESSTEST + { OLETTER_NONE, &ttyin_name_optname, + STRING|NO_TOGGLE, 0, NULL, opt_ttyin_name, + { + NULL, + NULL, + NULL + } + }, + { OLETTER_NONE, &rstat_optname, + STRING|NO_TOGGLE, 0, NULL, opt_rstat, + { + NULL, + NULL, + NULL + } + }, +#endif /*LESSTEST*/ { '\0', NULL, NOVAR, 0, NULL, NULL, { NULL, NULL, NULL } } }; diff --git a/contrib/less/os.c b/contrib/less/os.c index 1f33f4f3b39c..1723787b1c50 100644 --- a/contrib/less/os.c +++ b/contrib/less/os.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -23,6 +23,9 @@ #include "less.h" #include #include +#if MSDOS_COMPILER==WIN32C +#include +#endif #if HAVE_TIME_H #include #endif @@ -33,6 +36,15 @@ #include #endif +#if HAVE_POLL && !MSDOS_COMPILER && !defined(__APPLE__) +#define USE_POLL 1 +#else +#define USE_POLL 0 +#endif +#if USE_POLL +#include +#endif + /* * BSD setjmp() saves (and longjmp() restores) the signal mask. * This costs a system call or two per setjmp(), so if possible we clear the @@ -41,11 +53,11 @@ * _setjmp() does not exist; we just use setjmp(). */ #if HAVE__SETJMP && HAVE_SIGSETMASK -#define SET_JUMP _setjmp -#define LONG_JUMP _longjmp +#define SET_JUMP _setjmp +#define LONG_JUMP _longjmp #else -#define SET_JUMP setjmp -#define LONG_JUMP longjmp +#define SET_JUMP setjmp +#define LONG_JUMP longjmp #endif public int reading; @@ -53,6 +65,27 @@ public int reading; static jmp_buf read_label; extern int sigs; +extern int ignore_eoi; +#if !MSDOS_COMPILER +extern int tty; +#endif + +#if USE_POLL +/* + * Return true if one of the events has occurred on the specified file. + */ + static int +poll_events(fd, events) + int fd; + int events; +{ + struct pollfd poller = { fd, events, 0 }; + int n = poll(&poller, 1, 0); + if (n <= 0) + return 0; + return (poller.revents & events); +} +#endif /* * Like read() system call, but is deliberately interruptible. @@ -126,6 +159,29 @@ iread(fd, buf, len) if (select(fd+1, &readfds, 0, 0, 0) == -1) return (-1); } +#endif +#if USE_POLL + if (ignore_eoi && fd != tty) + { + if (poll_events(tty, POLLIN) && getchr() == CONTROL('X')) + { + sigs |= S_INTERRUPT; + return (READ_INTR); + } + if (poll_events(fd, POLLERR|POLLHUP)) + { + sigs |= S_INTERRUPT; + return (READ_INTR); + } + } +#else +#if MSDOS_COMPILER==WIN32C + if (win32_kbhit() && WIN32getch() == CONTROL('X')) + { + sigs |= S_INTERRUPT; + return (READ_INTR); + } +#endif #endif n = read(fd, buf, len); #if 1 @@ -135,7 +191,6 @@ iread(fd, buf, len) * start returning 0 forever, instead of -1. */ { - extern int ignore_eoi; if (!ignore_eoi) { static int consecutive_nulls = 0; @@ -204,18 +259,16 @@ get_time(VOID_PARAM) strerror(err) int err; { -#if HAVE_SYS_ERRLIST static char buf[16]; +#if HAVE_SYS_ERRLIST extern char *sys_errlist[]; extern int sys_nerr; if (err < sys_nerr) return sys_errlist[err]; +#endif sprintf(buf, "Error %d", err); return buf; -#else - return ("cannot open"); -#endif } #endif @@ -356,3 +409,24 @@ isatty(f) } #endif + + public void +sleep_ms(ms) + int ms; +{ +#if MSDOS_COMPILER==WIN32C + Sleep(ms); +#else +#if HAVE_NANOSLEEP + int sec = ms / 1000; + struct timespec t = { sec, (ms - sec*1000) * 1000000 }; + nanosleep(&t, NULL); +#else +#if HAVE_USLEEP + usleep(ms); +#else + sleep((ms+999) / 1000); +#endif +#endif +#endif +} diff --git a/contrib/less/output.c b/contrib/less/output.c index b3d192de0cf1..ddb6ad2779af 100644 --- a/contrib/less/output.c +++ b/contrib/less/output.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -20,7 +20,7 @@ #endif #endif -public int errmsgs; /* Count of messages displayed by error() */ +public int errmsgs; /* Count of messages displayed by error() */ public int need_clr; public int final_attr; public int at_prompt; @@ -29,7 +29,6 @@ extern int sigs; extern int sc_width; extern int so_s_width, so_e_width; extern int screen_trashed; -extern int any_display; extern int is_tty; extern int oldbot; @@ -42,7 +41,7 @@ extern int so_fg_color, so_bg_color; extern int bl_fg_color, bl_bg_color; extern int sgr_mode; #if MSDOS_COMPILER==WIN32C -extern int have_ul; +extern int vt_enabled; #endif #endif @@ -82,6 +81,269 @@ put_line(VOID_PARAM) static char obuf[OUTBUF_SIZE]; static char *ob = obuf; +static int outfd = 2; /* stderr */ + +#if MSDOS_COMPILER==WIN32C || MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC + static void +win_flush(VOID_PARAM) +{ + if (ctldisp != OPT_ONPLUS || (vt_enabled && sgr_mode)) + WIN32textout(obuf, ob - obuf); + else + { + /* + * Look for SGR escape sequences, and convert them + * to color commands. Replace bold, underline, + * and italic escapes into colors specified via + * the -D command-line option. + */ + char *anchor, *p, *p_next; + static int fg, fgi, bg, bgi; + static int at; + int f, b; +#if MSDOS_COMPILER==WIN32C + /* Screen colors used by 3x and 4x SGR commands. */ + static unsigned char screen_color[] = { + 0, /* BLACK */ + FOREGROUND_RED, + FOREGROUND_GREEN, + FOREGROUND_RED|FOREGROUND_GREEN, + FOREGROUND_BLUE, + FOREGROUND_BLUE|FOREGROUND_RED, + FOREGROUND_BLUE|FOREGROUND_GREEN, + FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED + }; +#else + static enum COLORS screen_color[] = { + BLACK, RED, GREEN, BROWN, + BLUE, MAGENTA, CYAN, LIGHTGRAY + }; +#endif + + if (fg == 0 && bg == 0) + { + fg = nm_fg_color & 7; + fgi = nm_fg_color & 8; + bg = nm_bg_color & 7; + bgi = nm_bg_color & 8; + } + for (anchor = p_next = obuf; + (p_next = memchr(p_next, ESC, ob - p_next)) != NULL; ) + { + p = p_next; + if (p[1] == '[') /* "ESC-[" sequence */ + { + if (p > anchor) + { + /* + * If some chars seen since + * the last escape sequence, + * write them out to the screen. + */ + WIN32textout(anchor, p-anchor); + anchor = p; + } + p += 2; /* Skip the "ESC-[" */ + if (is_ansi_end(*p)) + { + /* + * Handle null escape sequence + * "ESC[m", which restores + * the normal color. + */ + p++; + anchor = p_next = p; + fg = nm_fg_color & 7; + fgi = nm_fg_color & 8; + bg = nm_bg_color & 7; + bgi = nm_bg_color & 8; + at = 0; + WIN32setcolors(nm_fg_color, nm_bg_color); + continue; + } + p_next = p; + at &= ~32; + + /* + * Select foreground/background colors + * based on the escape sequence. + */ + while (!is_ansi_end(*p)) + { + char *q; + long code = strtol(p, &q, 10); + + if (*q == '\0') + { + /* + * Incomplete sequence. + * Leave it unprocessed + * in the buffer. + */ + int slop = (int) (q - anchor); + /* {{ strcpy args overlap! }} */ + strcpy(obuf, anchor); + ob = &obuf[slop]; + return; + } + + if (q == p || + code > 49 || code < 0 || + (!is_ansi_end(*q) && *q != ';')) + { + p_next = q; + break; + } + if (*q == ';') + { + q++; + at |= 32; + } + + switch (code) + { + default: + /* case 0: all attrs off */ + fg = nm_fg_color & 7; + bg = nm_bg_color & 7; + at &= 32; + /* + * \e[0m use normal + * intensities, but + * \e[0;...m resets them + */ + if (at & 32) + { + fgi = 0; + bgi = 0; + } else + { + fgi = nm_fg_color & 8; + bgi = nm_bg_color & 8; + } + break; + case 1: /* bold on */ + fgi = 8; + at |= 1; + break; + case 3: /* italic on */ + case 7: /* inverse on */ + at |= 2; + break; + case 4: /* underline on */ + bgi = 8; + at |= 4; + break; + case 5: /* slow blink on */ + case 6: /* fast blink on */ + bgi = 8; + at |= 8; + break; + case 8: /* concealed on */ + at |= 16; + break; + case 22: /* bold off */ + fgi = 0; + at &= ~1; + break; + case 23: /* italic off */ + case 27: /* inverse off */ + at &= ~2; + break; + case 24: /* underline off */ + bgi = 0; + at &= ~4; + break; + case 28: /* concealed off */ + at &= ~16; + break; + case 30: case 31: case 32: + case 33: case 34: case 35: + case 36: case 37: + fg = screen_color[code - 30]; + at |= 32; + break; + case 39: /* default fg */ + fg = nm_fg_color & 7; + at |= 32; + break; + case 40: case 41: case 42: + case 43: case 44: case 45: + case 46: case 47: + bg = screen_color[code - 40]; + at |= 32; + break; + case 49: /* default bg */ + bg = nm_bg_color & 7; + at |= 32; + break; + } + p = q; + } + if (!is_ansi_end(*p) || p == p_next) + break; + /* + * In SGR mode, the ANSI sequence is + * always honored; otherwise if an attr + * is used by itself ("\e[1m" versus + * "\e[1;33m", for example), set the + * color assigned to that attribute. + */ + if (sgr_mode || (at & 32)) + { + if (at & 2) + { + f = bg | bgi; + b = fg | fgi; + } else + { + f = fg | fgi; + b = bg | bgi; + } + } else + { + if (at & 1) + { + f = bo_fg_color; + b = bo_bg_color; + } else if (at & 2) + { + f = so_fg_color; + b = so_bg_color; + } else if (at & 4) + { + f = ul_fg_color; + b = ul_bg_color; + } else if (at & 8) + { + f = bl_fg_color; + b = bl_bg_color; + } else + { + f = nm_fg_color; + b = nm_bg_color; + } + } + if (at & 16) + f = b ^ 8; +#if MSDOS_COMPILER==WIN32C + f &= 0xf | COMMON_LVB_UNDERSCORE; +#else + f &= 0xf; +#endif + b &= 0xf; + WIN32setcolors(f, b); + p_next = anchor = p + 1; + } else + p_next++; + } + + /* Output what's left in the buffer. */ + WIN32textout(anchor, ob - anchor); + } + ob = obuf; +} +#endif /* * Flush buffered output. @@ -103,293 +365,44 @@ static char *ob = obuf; flush(VOID_PARAM) { int n; - int fd; n = (int) (ob - obuf); if (n == 0) return; + ob = obuf; #if MSDOS_COMPILER==MSOFTC - if (is_tty && any_display) + if (interactive()) { - *ob = '\0'; + obuf[n] = '\0'; _outtext(obuf); - ob = obuf; return; } #else #if MSDOS_COMPILER==WIN32C || MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC - if (is_tty && any_display) + if (interactive()) { + ob = obuf + n; *ob = '\0'; - if (ctldisp != OPT_ONPLUS) - WIN32textout(obuf, ob - obuf); - else - { - /* - * Look for SGR escape sequences, and convert them - * to color commands. Replace bold, underline, - * and italic escapes into colors specified via - * the -D command-line option. - */ - char *anchor, *p, *p_next; - static int fg, fgi, bg, bgi; - static int at; - int f, b; -#if MSDOS_COMPILER==WIN32C - /* Screen colors used by 3x and 4x SGR commands. */ - static unsigned char screen_color[] = { - 0, /* BLACK */ - FOREGROUND_RED, - FOREGROUND_GREEN, - FOREGROUND_RED|FOREGROUND_GREEN, - FOREGROUND_BLUE, - FOREGROUND_BLUE|FOREGROUND_RED, - FOREGROUND_BLUE|FOREGROUND_GREEN, - FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED - }; -#else - static enum COLORS screen_color[] = { - BLACK, RED, GREEN, BROWN, - BLUE, MAGENTA, CYAN, LIGHTGRAY - }; -#endif - - if (fg == 0 && bg == 0) - { - fg = nm_fg_color & 7; - fgi = nm_fg_color & 8; - bg = nm_bg_color & 7; - bgi = nm_bg_color & 8; - } - for (anchor = p_next = obuf; - (p_next = memchr(p_next, ESC, ob - p_next)) != NULL; ) - { - p = p_next; - if (p[1] == '[') /* "ESC-[" sequence */ - { - if (p > anchor) - { - /* - * If some chars seen since - * the last escape sequence, - * write them out to the screen. - */ - WIN32textout(anchor, p-anchor); - anchor = p; - } - p += 2; /* Skip the "ESC-[" */ - if (is_ansi_end(*p)) - { - /* - * Handle null escape sequence - * "ESC[m", which restores - * the normal color. - */ - p++; - anchor = p_next = p; - fg = nm_fg_color & 7; - fgi = nm_fg_color & 8; - bg = nm_bg_color & 7; - bgi = nm_bg_color & 8; - at = 0; - WIN32setcolors(nm_fg_color, nm_bg_color); - continue; - } - p_next = p; - at &= ~32; - - /* - * Select foreground/background colors - * based on the escape sequence. - */ - while (!is_ansi_end(*p)) - { - char *q; - long code = strtol(p, &q, 10); - - if (*q == '\0') - { - /* - * Incomplete sequence. - * Leave it unprocessed - * in the buffer. - */ - int slop = (int) (q - anchor); - /* {{ strcpy args overlap! }} */ - strcpy(obuf, anchor); - ob = &obuf[slop]; - return; - } - - if (q == p || - code > 49 || code < 0 || - (!is_ansi_end(*q) && *q != ';')) - { - p_next = q; - break; - } - if (*q == ';') - { - q++; - at |= 32; - } - - switch (code) - { - default: - /* case 0: all attrs off */ - fg = nm_fg_color & 7; - bg = nm_bg_color & 7; - at &= 32; - /* - * \e[0m use normal - * intensities, but - * \e[0;...m resets them - */ - if (at & 32) - { - fgi = 0; - bgi = 0; - } else - { - fgi = nm_fg_color & 8; - bgi = nm_bg_color & 8; - } - break; - case 1: /* bold on */ - fgi = 8; - at |= 1; - break; - case 3: /* italic on */ - case 7: /* inverse on */ - at |= 2; - break; - case 4: /* underline on */ -#if MSDOS_COMPILER==WIN32C - if (have_ul) - bgi = COMMON_LVB_UNDERSCORE >> 4; - else -#endif - bgi = 8; - at |= 4; - break; - case 5: /* slow blink on */ - case 6: /* fast blink on */ - bgi = 8; - at |= 8; - break; - case 8: /* concealed on */ - at |= 16; - break; - case 22: /* bold off */ - fgi = 0; - at &= ~1; - break; - case 23: /* italic off */ - case 27: /* inverse off */ - at &= ~2; - break; - case 24: /* underline off */ - bgi = 0; - at &= ~4; - break; - case 28: /* concealed off */ - at &= ~16; - break; - case 30: case 31: case 32: - case 33: case 34: case 35: - case 36: case 37: - fg = screen_color[code - 30]; - at |= 32; - break; - case 39: /* default fg */ - fg = nm_fg_color & 7; - at |= 32; - break; - case 40: case 41: case 42: - case 43: case 44: case 45: - case 46: case 47: - bg = screen_color[code - 40]; - at |= 32; - break; - case 49: /* default bg */ - bg = nm_bg_color & 7; - at |= 32; - break; - } - p = q; - } - if (!is_ansi_end(*p) || p == p_next) - break; - /* - * In SGR mode, the ANSI sequence is - * always honored; otherwise if an attr - * is used by itself ("\e[1m" versus - * "\e[1;33m", for example), set the - * color assigned to that attribute. - */ - if (sgr_mode || (at & 32)) - { - if (at & 2) - { - f = bg | bgi; - b = fg | fgi; - } else - { - f = fg | fgi; - b = bg | bgi; - } - } else - { - if (at & 1) - { - f = bo_fg_color; - b = bo_bg_color; - } else if (at & 2) - { - f = so_fg_color; - b = so_bg_color; - } else if (at & 4) - { - f = ul_fg_color; - b = ul_bg_color; - } else if (at & 8) - { - f = bl_fg_color; - b = bl_bg_color; - } else - { - f = nm_fg_color; - b = nm_bg_color; - } - } - if (at & 16) - f = b ^ 8; - f &= 0xf; -#if MSDOS_COMPILER==WIN32C - b &= 0xf | (COMMON_LVB_UNDERSCORE >> 4); -#else - b &= 0xf; -#endif - WIN32setcolors(f, b); - p_next = anchor = p + 1; - } else - p_next++; - } - - /* Output what's left in the buffer. */ - WIN32textout(anchor, ob - anchor); - } - ob = obuf; + win_flush(); return; } #endif #endif - fd = (any_display) ? 1 : 2; - if (write(fd, obuf, n) != n) + + if (write(outfd, obuf, n) != n) screen_trashed = 1; - ob = obuf; +} + +/* + * Set the output file descriptor (1=stdout or 2=stderr). + */ + public void +set_output(fd) + int fd; +{ + flush(); + outfd = fd; } /* @@ -491,8 +504,8 @@ type funcname(buf, ebuf) \ char **ebuf; \ { \ type val = 0; \ - for (;;) { \ - char c = *buf++; \ + for (;; buf++) { \ + char c = *buf; \ if (c < '0' || c > '9') break; \ val = 10 * val + c - '0'; \ } \ @@ -534,8 +547,11 @@ iprint_linenum(num) /* * This function implements printf-like functionality * using a more portable argument list mechanism than printf's. + * + * {{ This paranoia about the portability of printf dates from experiences + * with systems in the 1980s and is of course no longer necessary. }} */ - static int + public int less_printf(fmt, parg) char *fmt; PARG *parg; @@ -572,6 +588,10 @@ less_printf(fmt, parg) col += iprint_linenum(parg->p_linenum); parg++; break; + case 'c': + putchr(parg->p_char); + col++; + break; case '%': putchr('%'); break; @@ -615,24 +635,20 @@ error(fmt, parg) errmsgs++; - if (any_display && is_tty) - { - if (!oldbot) - squish_check(); - at_exit(); - clear_bot(); - at_enter(AT_STANDOUT); - col += so_s_width; - } - - col += less_printf(fmt, parg); - - if (!(any_display && is_tty)) + if (!interactive()) { + less_printf(fmt, parg); putchr('\n'); return; } + if (!oldbot) + squish_check(); + at_exit(); + clear_bot(); + at_enter(AT_STANDOUT|AT_COLOR_ERROR); + col += so_s_width; + col += less_printf(fmt, parg); putstr(return_to_continue); at_exit(); col += sizeof(return_to_continue) + so_e_width; @@ -667,7 +683,7 @@ ierror(fmt, parg) { at_exit(); clear_bot(); - at_enter(AT_STANDOUT); + at_enter(AT_STANDOUT|AT_COLOR_ERROR); (void) less_printf(fmt, parg); putstr(intr_to_abort); at_exit(); @@ -687,22 +703,24 @@ query(fmt, parg) int c; int col = 0; - if (any_display && is_tty) + if (interactive()) clear_bot(); (void) less_printf(fmt, parg); c = getchr(); - if (!(any_display && is_tty)) + if (interactive()) + { + lower_left(); + if (col >= sc_width) + screen_trashed = 1; + flush(); + } else { putchr('\n'); - return (c); } - lower_left(); - if (col >= sc_width) - screen_trashed = 1; - flush(); - + if (c == 'Q') + quit(QUIT_OK); return (c); } diff --git a/contrib/less/pattern.c b/contrib/less/pattern.c index b7fc05725a44..c2266fcf68c8 100644 --- a/contrib/less/pattern.c +++ b/contrib/less/pattern.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -145,9 +145,10 @@ compile_pattern2(pattern, search_type, comp_pattern, show_error) * Like compile_pattern2, but convert the pattern to lowercase if necessary. */ public int -compile_pattern(pattern, search_type, comp_pattern) +compile_pattern(pattern, search_type, show_error, comp_pattern) char *pattern; int search_type; + int show_error; PATTERN_TYPE *comp_pattern; { char *cvt_pattern; @@ -160,7 +161,7 @@ compile_pattern(pattern, search_type, comp_pattern) cvt_pattern = (char*) ecalloc(1, cvt_length(strlen(pattern), CVT_TO_LC)); cvt_text(cvt_pattern, pattern, (int *)NULL, (int *)NULL, CVT_TO_LC); } - result = compile_pattern2(cvt_pattern, search_type, comp_pattern, 1); + result = compile_pattern2(cvt_pattern, search_type, comp_pattern, show_error); if (cvt_pattern != pattern) free(cvt_pattern); return (result); @@ -214,6 +215,7 @@ uncompile_pattern(pattern) #endif } +#if 0 /* * Can a pattern be successfully compiled? */ @@ -224,13 +226,14 @@ valid_pattern(pattern) PATTERN_TYPE comp_pattern; int result; - CLEAR_PATTERN(comp_pattern); + SET_NULL_PATTERN(comp_pattern); result = compile_pattern2(pattern, 0, &comp_pattern, 0); if (result != 0) return (0); uncompile_pattern(&comp_pattern); return (1); } +#endif /* * Is a compiled pattern null? diff --git a/contrib/less/pattern.h b/contrib/less/pattern.h index 1f2ef5181b2b..96d4494d783f 100644 --- a/contrib/less/pattern.h +++ b/contrib/less/pattern.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -11,7 +11,7 @@ #define __USE_GNU 1 #include #define PATTERN_TYPE struct re_pattern_buffer * -#define CLEAR_PATTERN(name) name = NULL +#define SET_NULL_PATTERN(name) name = NULL #endif #if HAVE_POSIX_REGCOMP @@ -23,27 +23,27 @@ extern int less_is_more; #define REGCOMP_FLAG 0 #endif #define PATTERN_TYPE regex_t * -#define CLEAR_PATTERN(name) name = NULL +#define SET_NULL_PATTERN(name) name = NULL #endif #if HAVE_PCRE #include #define PATTERN_TYPE pcre * -#define CLEAR_PATTERN(name) name = NULL +#define SET_NULL_PATTERN(name) name = NULL #endif #if HAVE_PCRE2 #define PCRE2_CODE_UNIT_WIDTH 8 #include #define PATTERN_TYPE pcre2_code * -#define CLEAR_PATTERN(name) name = NULL +#define SET_NULL_PATTERN(name) name = NULL #endif #if HAVE_RE_COMP char *re_comp LESSPARAMS ((char*)); int re_exec LESSPARAMS ((char*)); #define PATTERN_TYPE int -#define CLEAR_PATTERN(name) name = 0 +#define SET_NULL_PATTERN(name) name = 0 #endif #if HAVE_REGCMP @@ -51,17 +51,17 @@ char *regcmp LESSPARAMS ((char*)); char *regex LESSPARAMS ((char**, char*)); extern char *__loc1; #define PATTERN_TYPE char ** -#define CLEAR_PATTERN(name) name = NULL +#define SET_NULL_PATTERN(name) name = NULL #endif #if HAVE_V8_REGCOMP #include "regexp.h" extern int reg_show_error; #define PATTERN_TYPE struct regexp * -#define CLEAR_PATTERN(name) name = NULL +#define SET_NULL_PATTERN(name) name = NULL #endif #if NO_REGEX #define PATTERN_TYPE void * -#define CLEAR_PATTERN(name) +#define SET_NULL_PATTERN(name) #endif diff --git a/contrib/less/pckeys.h b/contrib/less/pckeys.h index e41ca9acdc88..8b21d729935a 100644 --- a/contrib/less/pckeys.h +++ b/contrib/less/pckeys.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -13,21 +13,21 @@ * Special (non-ASCII) keys on the PC send a two-byte sequence, * where the first byte is 0 and the second is as defined below. */ -#define PCK_SHIFT_TAB '\017' -#define PCK_ALT_E '\022' -#define PCK_CAPS_LOCK '\072' -#define PCK_F1 '\073' -#define PCK_NUM_LOCK '\105' -#define PCK_HOME '\107' -#define PCK_UP '\110' -#define PCK_PAGEUP '\111' -#define PCK_LEFT '\113' -#define PCK_RIGHT '\115' -#define PCK_END '\117' -#define PCK_DOWN '\120' -#define PCK_PAGEDOWN '\121' -#define PCK_INSERT '\122' -#define PCK_DELETE '\123' -#define PCK_CTL_LEFT '\163' -#define PCK_CTL_RIGHT '\164' -#define PCK_CTL_DELETE '\223' +#define PCK_SHIFT_TAB '\017' +#define PCK_ALT_E '\022' +#define PCK_CAPS_LOCK '\072' +#define PCK_F1 '\073' +#define PCK_NUM_LOCK '\105' +#define PCK_HOME '\107' +#define PCK_UP '\110' +#define PCK_PAGEUP '\111' +#define PCK_LEFT '\113' +#define PCK_RIGHT '\115' +#define PCK_END '\117' +#define PCK_DOWN '\120' +#define PCK_PAGEDOWN '\121' +#define PCK_INSERT '\122' +#define PCK_DELETE '\123' +#define PCK_CTL_LEFT '\163' +#define PCK_CTL_RIGHT '\164' +#define PCK_CTL_DELETE '\223' diff --git a/contrib/less/position.c b/contrib/less/position.c index 6e37ec5d5187..8f6edc939377 100644 --- a/contrib/less/position.c +++ b/contrib/less/position.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -21,7 +21,7 @@ #include "less.h" #include "position.h" -static POSITION *table = NULL; /* The position table */ +static POSITION *table = NULL; /* The position table */ static int table_size = 0; extern int sc_width, sc_height; @@ -30,10 +30,10 @@ extern int sc_width, sc_height; * Return the starting file position of a line displayed on the screen. * The line may be specified as a line number relative to the top * of the screen, but is usually one of these special cases: - * the top (first) line on the screen - * the second line on the screen - * the bottom line on the screen - * the line after the bottom line on the screen + * the top (first) line on the screen + * the second line on the screen + * the bottom line on the screen + * the line after the bottom line on the screen */ public POSITION position(sindex) diff --git a/contrib/less/position.h b/contrib/less/position.h index 2e6c71bc766e..4e0efc7f4c0f 100644 --- a/contrib/less/position.h +++ b/contrib/less/position.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -11,8 +11,8 @@ /* * Include file for interfacing to position.c modules. */ -#define TOP (0) -#define TOP_PLUS_ONE (1) -#define BOTTOM (-1) -#define BOTTOM_PLUS_ONE (-2) -#define MIDDLE (-3) +#define TOP (0) +#define TOP_PLUS_ONE (1) +#define BOTTOM (-1) +#define BOTTOM_PLUS_ONE (-2) +#define MIDDLE (-3) diff --git a/contrib/less/prompt.c b/contrib/less/prompt.c index e587bd762000..0e38c0f6e438 100644 --- a/contrib/less/prompt.c +++ b/contrib/less/prompt.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -123,7 +123,7 @@ ap_pos(pos) /* * Append a line number to the end of the message. */ - static void + static void ap_linenum(linenum) LINENUM linenum; { @@ -187,48 +187,48 @@ cond(c, where) switch (c) { - case 'a': /* Anything in the message yet? */ + case 'a': /* Anything in the message yet? */ return (mp > message); - case 'b': /* Current byte offset known? */ + case 'b': /* Current byte offset known? */ return (curr_byte(where) != NULL_POSITION); case 'c': return (hshift != 0); - case 'e': /* At end of file? */ + case 'e': /* At end of file? */ return (eof_displayed()); - case 'f': /* Filename known? */ + case 'f': /* Filename known? */ case 'g': return (strcmp(get_filename(curr_ifile), "-") != 0); - case 'l': /* Line number known? */ - case 'd': /* Same as l */ + case 'l': /* Line number known? */ + case 'd': /* Same as l */ if (!linenums) return 0; return (currline(where) != 0); - case 'L': /* Final line number known? */ - case 'D': /* Final page number known? */ + case 'L': /* Final line number known? */ + case 'D': /* Final page number known? */ return (linenums && ch_length() != NULL_POSITION); - case 'm': /* More than one file? */ + case 'm': /* More than one file? */ #if TAGS return (ntags() ? (ntags() > 1) : (nifile() > 1)); #else return (nifile() > 1); #endif - case 'n': /* First prompt in a new file? */ + case 'n': /* First prompt in a new file? */ #if TAGS return (ntags() ? 1 : new_file); #else return (new_file); #endif - case 'p': /* Percent into file (bytes) known? */ + case 'p': /* Percent into file (bytes) known? */ return (curr_byte(where) != NULL_POSITION && ch_length() > 0); - case 'P': /* Percent into file (lines) known? */ + case 'P': /* Percent into file (lines) known? */ return (currline(where) != 0 && (len = ch_length()) > 0 && find_linenum(len) != 0); - case 's': /* Size of file known? */ + case 's': /* Size of file known? */ case 'B': return (ch_length() != NULL_POSITION); - case 'x': /* Is there a "next" file? */ + case 'x': /* Is there a "next" file? */ #if TAGS if (ntags()) return (0); @@ -264,7 +264,7 @@ protochar(c, where, iseditproto) switch (c) { - case 'b': /* Current byte offset */ + case 'b': /* Current byte offset */ pos = curr_byte(where); if (pos != NULL_POSITION) ap_pos(pos); @@ -274,14 +274,14 @@ protochar(c, where, iseditproto) case 'c': ap_int(hshift); break; - case 'd': /* Current page number */ + case 'd': /* Current page number */ linenum = currline(where); if (linenum > 0 && sc_height > 1) ap_linenum(PAGE_NUM(linenum)); else ap_quest(); break; - case 'D': /* Final page number */ + case 'D': /* Final page number */ /* Find the page number of the last byte in the file (len-1). */ len = ch_length(); if (len == NULL_POSITION) @@ -299,22 +299,22 @@ protochar(c, where, iseditproto) } break; #if EDITOR - case 'E': /* Editor name */ + case 'E': /* Editor name */ ap_str(editor); break; #endif - case 'f': /* File name */ + case 'f': /* File name */ ap_str(get_filename(curr_ifile)); break; - case 'F': /* Last component of file name */ + case 'F': /* Last component of file name */ ap_str(last_component(get_filename(curr_ifile))); break; - case 'g': /* Shell-escaped file name */ + case 'g': /* Shell-escaped file name */ s = shell_quote(get_filename(curr_ifile)); ap_str(s); free(s); break; - case 'i': /* Index into list of files */ + case 'i': /* Index into list of files */ #if TAGS if (ntags()) ap_int(curr_tag()); @@ -322,14 +322,14 @@ protochar(c, where, iseditproto) #endif ap_int(get_index(curr_ifile)); break; - case 'l': /* Current line number */ + case 'l': /* Current line number */ linenum = currline(where); if (linenum != 0) ap_linenum(linenum); else ap_quest(); break; - case 'L': /* Final line number */ + case 'L': /* Final line number */ len = ch_length(); if (len == NULL_POSITION || len == ch_zero() || (linenum = find_linenum(len)) <= 0) @@ -337,7 +337,7 @@ protochar(c, where, iseditproto) else ap_linenum(linenum-1); break; - case 'm': /* Number of files */ + case 'm': /* Number of files */ #if TAGS n = ntags(); if (n) @@ -346,7 +346,7 @@ protochar(c, where, iseditproto) #endif ap_int(nifile()); break; - case 'p': /* Percent into file (bytes) */ + case 'p': /* Percent into file (bytes) */ pos = curr_byte(where); len = ch_length(); if (pos != NULL_POSITION && len > 0) @@ -354,7 +354,7 @@ protochar(c, where, iseditproto) else ap_quest(); break; - case 'P': /* Percent into file (lines) */ + case 'P': /* Percent into file (lines) */ linenum = currline(where); if (linenum == 0 || (len = ch_length()) == NULL_POSITION || len == ch_zero() || @@ -363,7 +363,7 @@ protochar(c, where, iseditproto) else ap_int(percentage(linenum, last_linenum)); break; - case 's': /* Size of file */ + case 's': /* Size of file */ case 'B': len = ch_length(); if (len != NULL_POSITION) @@ -371,12 +371,12 @@ protochar(c, where, iseditproto) else ap_quest(); break; - case 't': /* Truncate trailing spaces in the message */ + case 't': /* Truncate trailing spaces in the message */ while (mp > message && mp[-1] == ' ') mp--; *mp = '\0'; break; - case 'T': /* Type of list */ + case 'T': /* Type of list */ #if TAGS if (ntags()) ap_str("tag"); @@ -384,7 +384,7 @@ protochar(c, where, iseditproto) #endif ap_str("file"); break; - case 'x': /* Name of next file */ + case 'x': /* Name of next file */ h = next_ifile(curr_ifile); if (h != NULL_IFILE) ap_str(get_filename(h)); @@ -469,12 +469,12 @@ wherechar(p, wp) case 'b': case 'd': case 'l': case 'p': case 'P': switch (*++p) { - case 't': *wp = TOP; break; - case 'm': *wp = MIDDLE; break; - case 'b': *wp = BOTTOM; break; - case 'B': *wp = BOTTOM_PLUS_ONE; break; + case 't': *wp = TOP; break; + case 'm': *wp = MIDDLE; break; + case 'b': *wp = BOTTOM; break; + case 'B': *wp = BOTTOM_PLUS_ONE; break; case 'j': *wp = sindex_from_sline(jump_sline); break; - default: *wp = TOP; p--; break; + default: *wp = TOP; p--; break; } } return (p); @@ -501,14 +501,14 @@ pr_expand(proto, maxwidth) { switch (*p) { - default: /* Just put the character in the message */ + default: /* Just put the character in the message */ ap_char(*p); break; - case '\\': /* Backslash escapes the next character */ + case '\\': /* Backslash escapes the next character */ p++; ap_char(*p); break; - case '?': /* Conditional (IF) */ + case '?': /* Conditional (IF) */ if ((c = *++p) == '\0') --p; else @@ -519,12 +519,12 @@ pr_expand(proto, maxwidth) p = skipcond(p); } break; - case ':': /* ELSE */ + case ':': /* ELSE */ p = skipcond(p); break; - case '.': /* ENDIF */ + case '.': /* ENDIF */ break; - case '%': /* Percent escape */ + case '%': /* Percent escape */ if ((c = *++p) == '\0') --p; else diff --git a/contrib/less/regexp.h b/contrib/less/regexp.h index bcef6d1ebc77..283ff2aad6b7 100644 --- a/contrib/less/regexp.h +++ b/contrib/less/regexp.h @@ -10,13 +10,13 @@ #define NSUBEXP 10 typedef struct regexp { - char *startp[NSUBEXP]; - char *endp[NSUBEXP]; - char regstart; /* Internal use only. */ - char reganch; /* Internal use only. */ - char *regmust; /* Internal use only. */ - int regmlen; /* Internal use only. */ - char program[1]; /* Unwarranted chumminess with compiler. */ + char *startp[NSUBEXP]; + char *endp[NSUBEXP]; + char regstart; /* Internal use only. */ + char reganch; /* Internal use only. */ + char *regmust; /* Internal use only. */ + int regmlen; /* Internal use only. */ + char program[1]; /* Unwarranted chumminess with compiler. */ } regexp; #if defined(__STDC__) || defined(__cplusplus) diff --git a/contrib/less/screen.c b/contrib/less/screen.c index c9635f438106..7e8f8af4f463 100644 --- a/contrib/less/screen.c +++ b/contrib/less/screen.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -35,6 +35,19 @@ extern int fd0; #endif #include +#ifndef FOREGROUND_BLUE +#define FOREGROUND_BLUE 0x0001 +#endif +#ifndef FOREGROUND_GREEN +#define FOREGROUND_GREEN 0x0002 +#endif +#ifndef FOREGROUND_RED +#define FOREGROUND_RED 0x0004 +#endif +#ifndef FOREGROUND_INTENSITY +#define FOREGROUND_INTENSITY 0x0008 +#endif + #else #if HAVE_SYS_IOCTL_H @@ -85,17 +98,19 @@ extern int fd0; #endif #if OS2 -#define DEFAULT_TERM "ansi" +#define DEFAULT_TERM "ansi" static char *windowid; #else -#define DEFAULT_TERM "unknown" +#define DEFAULT_TERM "unknown" #endif #if MSDOS_COMPILER==MSOFTC static int videopages; static long msec_loops; static int flash_created = 0; -#define SETCOLORS(fg,bg) { _settextcolor(fg); _setbkcolor(bg); } +#define SET_FG_COLOR(fg) _settextcolor(fg) +#define SET_BG_COLOR(bg) _setbkcolor(bg) +#define SETCOLORS(fg,bg) { SET_FG_COLOR(fg); SET_BG_COLOR(bg); } #endif #if MSDOS_COMPILER==BORLANDC @@ -106,7 +121,9 @@ static int flash_created = 0; #define _settextposition(y,x) gotoxy(x,y) #define _clearscreen(m) clrscr() #define _outtext(s) cputs(s) -#define SETCOLORS(fg,bg) { textcolor(fg); textbackground(bg); } +#define SET_FG_COLOR(fg) textcolor(fg) +#define SET_BG_COLOR(bg) textbackground(bg) +#define SETCOLORS(fg,bg) { SET_FG_COLOR(fg); SET_BG_COLOR(bg); } extern int sc_height; #endif @@ -138,28 +155,31 @@ static void win32_deinit_term(); #define FG_COLORS (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY) #define BG_COLORS (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY) -#define MAKEATTR(fg,bg) ((WORD)((fg)|((bg)<<4))) -#define SETCOLORS(fg,bg) { curr_attr = MAKEATTR(fg,bg); \ - if (SetConsoleTextAttribute(con_out, curr_attr) == 0) \ - error("SETCOLORS failed", NULL_PARG); } +#define MAKEATTR(fg,bg) ((WORD)((fg)|((bg)<<4))) +#define APPLY_COLORS() { if (SetConsoleTextAttribute(con_out, curr_attr) == 0) \ + error("SETCOLORS failed", NULL_PARG); } +#define SET_FG_COLOR(fg) { curr_attr |= (fg); APPLY_COLORS(); } +#define SET_BG_COLOR(bg) { curr_attr |= ((bg)<<4); APPLY_COLORS(); } +#define SETCOLORS(fg,bg) { curr_attr = MAKEATTR(fg,bg); APPLY_COLORS(); } #endif #if MSDOS_COMPILER -public int nm_fg_color; /* Color of normal text */ +public int nm_fg_color; /* Color of normal text */ public int nm_bg_color; -public int bo_fg_color; /* Color of bold text */ +public int bo_fg_color; /* Color of bold text */ public int bo_bg_color; -public int ul_fg_color; /* Color of underlined text */ +public int ul_fg_color; /* Color of underlined text */ public int ul_bg_color; -public int so_fg_color; /* Color of standout text */ +public int so_fg_color; /* Color of standout text */ public int so_bg_color; -public int bl_fg_color; /* Color of blinking text */ +public int bl_fg_color; /* Color of blinking text */ public int bl_bg_color; -static int sy_fg_color; /* Color of system text (before less) */ +static int sy_fg_color; /* Color of system text (before less) */ static int sy_bg_color; -public int sgr_mode; /* Honor ANSI sequences rather than using above */ +public int sgr_mode; /* Honor ANSI sequences rather than using above */ #if MSDOS_COMPILER==WIN32C -public int have_ul; /* Is underline available? */ +static DWORD init_output_mode; /* The initial console output mode */ +public int vt_enabled = -1; /* Is virtual terminal processing available? */ #endif #else @@ -167,56 +187,61 @@ public int have_ul; /* Is underline available? */ * Strings passed to tputs() to do various terminal functions. */ static char - *sc_pad, /* Pad string */ - *sc_home, /* Cursor home */ - *sc_addline, /* Add line, scroll down following lines */ - *sc_lower_left, /* Cursor to last line, first column */ - *sc_return, /* Cursor to beginning of current line */ - *sc_move, /* General cursor positioning */ - *sc_clear, /* Clear screen */ - *sc_eol_clear, /* Clear to end of line */ - *sc_eos_clear, /* Clear to end of screen */ - *sc_s_in, /* Enter standout (highlighted) mode */ - *sc_s_out, /* Exit standout mode */ - *sc_u_in, /* Enter underline mode */ - *sc_u_out, /* Exit underline mode */ - *sc_b_in, /* Enter bold mode */ - *sc_b_out, /* Exit bold mode */ - *sc_bl_in, /* Enter blink mode */ - *sc_bl_out, /* Exit blink mode */ - *sc_visual_bell, /* Visual bell (flash screen) sequence */ - *sc_backspace, /* Backspace cursor */ - *sc_s_keypad, /* Start keypad mode */ - *sc_e_keypad, /* End keypad mode */ - *sc_s_mousecap, /* Start mouse capture mode */ - *sc_e_mousecap, /* End mouse capture mode */ - *sc_init, /* Startup terminal initialization */ - *sc_deinit; /* Exit terminal de-initialization */ + *sc_pad, /* Pad string */ + *sc_home, /* Cursor home */ + *sc_addline, /* Add line, scroll down following lines */ + *sc_lower_left, /* Cursor to last line, first column */ + *sc_return, /* Cursor to beginning of current line */ + *sc_move, /* General cursor positioning */ + *sc_clear, /* Clear screen */ + *sc_eol_clear, /* Clear to end of line */ + *sc_eos_clear, /* Clear to end of screen */ + *sc_s_in, /* Enter standout (highlighted) mode */ + *sc_s_out, /* Exit standout mode */ + *sc_u_in, /* Enter underline mode */ + *sc_u_out, /* Exit underline mode */ + *sc_b_in, /* Enter bold mode */ + *sc_b_out, /* Exit bold mode */ + *sc_bl_in, /* Enter blink mode */ + *sc_bl_out, /* Exit blink mode */ + *sc_visual_bell, /* Visual bell (flash screen) sequence */ + *sc_backspace, /* Backspace cursor */ + *sc_s_keypad, /* Start keypad mode */ + *sc_e_keypad, /* End keypad mode */ + *sc_s_mousecap, /* Start mouse capture mode */ + *sc_e_mousecap, /* End mouse capture mode */ + *sc_init, /* Startup terminal initialization */ + *sc_deinit; /* Exit terminal de-initialization */ + +static int attrcolor = -1; #endif static int init_done = 0; -public int auto_wrap; /* Terminal does \r\n when write past margin */ -public int ignaw; /* Terminal ignores \n immediately after wrap */ -public int erase_char; /* The user's erase char */ -public int erase2_char; /* The user's other erase char */ -public int kill_char; /* The user's line-kill char */ -public int werase_char; /* The user's word-erase char */ -public int sc_width, sc_height; /* Height & width of screen */ -public int bo_s_width, bo_e_width; /* Printing width of boldface seq */ -public int ul_s_width, ul_e_width; /* Printing width of underline seq */ -public int so_s_width, so_e_width; /* Printing width of standout seq */ -public int bl_s_width, bl_e_width; /* Printing width of blink seq */ -public int above_mem, below_mem; /* Memory retained above/below screen */ -public int can_goto_line; /* Can move cursor to any line */ -public int clear_bg; /* Clear fills with background color */ -public int missing_cap = 0; /* Some capability is missing */ -public char *kent = NULL; /* Keypad ENTER sequence */ +public int auto_wrap; /* Terminal does \r\n when write past margin */ +public int ignaw; /* Terminal ignores \n immediately after wrap */ +public int erase_char; /* The user's erase char */ +public int erase2_char; /* The user's other erase char */ +public int kill_char; /* The user's line-kill char */ +public int werase_char; /* The user's word-erase char */ +public int sc_width, sc_height; /* Height & width of screen */ +public int bo_s_width, bo_e_width; /* Printing width of boldface seq */ +public int ul_s_width, ul_e_width; /* Printing width of underline seq */ +public int so_s_width, so_e_width; /* Printing width of standout seq */ +public int bl_s_width, bl_e_width; /* Printing width of blink seq */ +public int above_mem, below_mem; /* Memory retained above/below screen */ +public int can_goto_line; /* Can move cursor to any line */ +public int clear_bg; /* Clear fills with background color */ +public int missing_cap = 0; /* Some capability is missing */ +public char *kent = NULL; /* Keypad ENTER sequence */ static int attrmode = AT_NORMAL; static int termcap_debug = -1; extern int binattr; extern int one_screen; +#if LESSTEST +extern char *ttyin_name; +#endif /*LESSTEST*/ #if !MSDOS_COMPILER static char *cheaper LESSPARAMS((char *t1, char *t2, char *def)); @@ -229,15 +254,15 @@ static void tmodes LESSPARAMS((char *incap, char *outcap, char **instr, * and needed by, the termcap library. */ #if MUST_DEFINE_OSPEED -extern short ospeed; /* Terminal output baud rate */ -extern char PC; /* Pad character */ +extern short ospeed; /* Terminal output baud rate */ +extern char PC; /* Pad character */ #endif #ifdef _OSK short ospeed; char PC_, *UP, *BC; #endif -extern int quiet; /* If VERY_QUIET, use visual bell for bell */ +extern int quiet; /* If VERY_QUIET, use visual bell for bell */ extern int no_back_scroll; extern int swindow; extern int no_init; @@ -249,6 +274,8 @@ extern int top_scroll; extern int quit_if_one_screen; extern int oldbot; extern int mousecap; +extern int is_tty; +extern int use_color; #if HILITE_SEARCH extern int hilite_search; #endif @@ -270,12 +297,12 @@ extern char *tgoto(); /* * Change terminal to "raw mode", or restore to "normal" mode. * "Raw mode" means - * 1. An outstanding read will complete on receipt of a single keystroke. - * 2. Input is not echoed. - * 3. On output, \n is mapped to \r\n. - * 4. \t is NOT expanded into spaces. - * 5. Signal-causing characters such as ctrl-C (interrupt), - * etc. are NOT disabled. + * 1. An outstanding read will complete on receipt of a single keystroke. + * 2. Input is not echoed. + * 3. On output, \n is mapped to \r\n. + * 4. \t is NOT expanded into spaces. + * 5. Signal-causing characters such as ctrl-C (interrupt), + * etc. are NOT disabled. * It doesn't matter whether an input \n is mapped to \r, or vice versa. */ public void @@ -285,7 +312,7 @@ raw_mode(on) static int curr_on = 0; if (on == curr_on) - return; + return; erase2_char = '\b'; /* in case OS doesn't know about erase2 */ #if HAVE_TERMIOS_H && HAVE_TERMIOS_FUNCS { @@ -723,11 +750,11 @@ scrsize(VOID_PARAM) int n; #endif -#define DEF_SC_WIDTH 80 +#define DEF_SC_WIDTH 80 #if MSDOS_COMPILER -#define DEF_SC_HEIGHT 25 +#define DEF_SC_HEIGHT 25 #else -#define DEF_SC_HEIGHT 24 +#define DEF_SC_HEIGHT 24 #endif @@ -816,24 +843,24 @@ scrsize(VOID_PARAM) #endif #endif - if (sys_height > 0) - sc_height = sys_height; - else if ((s = lgetenv("LINES")) != NULL) + if ((s = lgetenv("LINES")) != NULL) sc_height = atoi(s); + else if (sys_height > 0) + sc_height = sys_height; #if !MSDOS_COMPILER else if ((n = ltgetnum("li")) > 0) - sc_height = n; + sc_height = n; #endif if (sc_height <= 0) sc_height = DEF_SC_HEIGHT; - if (sys_width > 0) - sc_width = sys_width; - else if ((s = lgetenv("COLUMNS")) != NULL) + if ((s = lgetenv("COLUMNS")) != NULL) sc_width = atoi(s); + else if (sys_width > 0) + sc_width = sys_width; #if !MSDOS_COMPILER else if ((n = ltgetnum("co")) > 0) - sc_width = n; + sc_width = n; #endif if (sc_width <= 0) sc_width = DEF_SC_WIDTH; @@ -895,22 +922,22 @@ special_key_str(key) static char tbuf[40]; char *s; #if MSDOS_COMPILER || OS2 - static char k_right[] = { '\340', PCK_RIGHT, 0 }; - static char k_left[] = { '\340', PCK_LEFT, 0 }; - static char k_ctl_right[] = { '\340', PCK_CTL_RIGHT, 0 }; - static char k_ctl_left[] = { '\340', PCK_CTL_LEFT, 0 }; - static char k_insert[] = { '\340', PCK_INSERT, 0 }; - static char k_delete[] = { '\340', PCK_DELETE, 0 }; - static char k_ctl_delete[] = { '\340', PCK_CTL_DELETE, 0 }; - static char k_ctl_backspace[] = { '\177', 0 }; - static char k_home[] = { '\340', PCK_HOME, 0 }; - static char k_end[] = { '\340', PCK_END, 0 }; - static char k_up[] = { '\340', PCK_UP, 0 }; - static char k_down[] = { '\340', PCK_DOWN, 0 }; - static char k_backtab[] = { '\340', PCK_SHIFT_TAB, 0 }; - static char k_pagedown[] = { '\340', PCK_PAGEDOWN, 0 }; - static char k_pageup[] = { '\340', PCK_PAGEUP, 0 }; - static char k_f1[] = { '\340', PCK_F1, 0 }; + static char k_right[] = { '\340', PCK_RIGHT, 0 }; + static char k_left[] = { '\340', PCK_LEFT, 0 }; + static char k_ctl_right[] = { '\340', PCK_CTL_RIGHT, 0 }; + static char k_ctl_left[] = { '\340', PCK_CTL_LEFT, 0 }; + static char k_insert[] = { '\340', PCK_INSERT, 0 }; + static char k_delete[] = { '\340', PCK_DELETE, 0 }; + static char k_ctl_delete[] = { '\340', PCK_CTL_DELETE, 0 }; + static char k_ctl_backspace[] = { '\177', 0 }; + static char k_home[] = { '\340', PCK_HOME, 0 }; + static char k_end[] = { '\340', PCK_END, 0 }; + static char k_up[] = { '\340', PCK_UP, 0 }; + static char k_down[] = { '\340', PCK_DOWN, 0 }; + static char k_backtab[] = { '\340', PCK_SHIFT_TAB, 0 }; + static char k_pagedown[] = { '\340', PCK_PAGEDOWN, 0 }; + static char k_pageup[] = { '\340', PCK_PAGEUP, 0 }; + static char k_f1[] = { '\340', PCK_F1, 0 }; #endif #if !MSDOS_COMPILER char *sp = tbuf; @@ -951,9 +978,9 @@ special_key_str(key) s = windowid ? ltgetstr("kD", &sp) : k_delete; if (s == NULL) { - tbuf[0] = '\177'; - tbuf[1] = '\0'; - s = tbuf; + tbuf[0] = '\177'; + tbuf[1] = '\0'; + s = tbuf; } break; #endif @@ -1037,9 +1064,9 @@ special_key_str(key) s = ltgetstr("kD", &sp); if (s == NULL) { - tbuf[0] = '\177'; - tbuf[1] = '\0'; - s = tbuf; + tbuf[0] = '\177'; + tbuf[1] = '\0'; + s = tbuf; } break; #endif @@ -1093,6 +1120,7 @@ get_term(VOID_PARAM) * before any file operations have been done on fd0. */ SET_BINARY(0); + GetConsoleMode(con_out, &init_output_mode); GetConsoleScreenBufferInfo(con_out, &scr); curr_attr = scr.wAttributes; sy_bg_color = (curr_attr & BG_COLORS) >> 4; /* normalize */ @@ -1497,6 +1525,34 @@ initcolor(VOID_PARAM) #if MSDOS_COMPILER==WIN32C +/* + * Enable virtual terminal processing, if available. + */ + static void +win32_init_vt_term(VOID_PARAM) +{ + DWORD output_mode; + + if (vt_enabled == 0 || (vt_enabled == 1 && con_out == con_out_ours)) + return; + + GetConsoleMode(con_out, &output_mode); + vt_enabled = SetConsoleMode(con_out, + output_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING); + if (vt_enabled) + { + auto_wrap = 0; + ignaw = 1; + } +} + + static void +win32_deinit_vt_term(VOID_PARAM) +{ + if (vt_enabled == 1 && con_out == con_out_save) + SetConsoleMode(con_out, init_output_mode); +} + /* * Termcap-like init with a private win32 console. */ @@ -1513,8 +1569,6 @@ win32_init_term(VOID_PARAM) if (con_out_ours == INVALID_HANDLE_VALUE) { - DWORD output_mode; - /* * Create our own screen buffer, so that we * may restore the original when done. @@ -1525,12 +1579,6 @@ win32_init_term(VOID_PARAM) (LPSECURITY_ATTRIBUTES) NULL, CONSOLE_TEXTMODE_BUFFER, (LPVOID) NULL); - /* - * Enable underline, if available. - */ - GetConsoleMode(con_out_ours, &output_mode); - have_ul = SetConsoleMode(con_out_ours, - output_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING); } size.X = scr.srWindow.Right - scr.srWindow.Left + 1; @@ -1556,6 +1604,68 @@ win32_deinit_term(VOID_PARAM) #endif +#if !MSDOS_COMPILER + static void +do_tputs(str, affcnt, f_putc) + char *str; + int affcnt; + int (*f_putc)(int); +{ +#if LESSTEST + if (ttyin_name != NULL) + putstr(str); + else +#endif /*LESSTEST*/ + tputs(str, affcnt, f_putc); +} + +/* + * Like tputs but we handle $<...> delay strings here because + * some implementations of tputs don't perform delays correctly. + */ + static void +ltputs(str, affcnt, f_putc) + char *str; + int affcnt; + int (*f_putc)(int); +{ + while (str != NULL && *str != '\0') + { +#if HAVE_STRSTR + char *obrac = strstr(str, "$<"); + if (obrac != NULL) + { + char str2[64]; + int slen = obrac - str; + if (slen < sizeof(str2)) + { + int delay; + /* Output first part of string (before "$<"). */ + memcpy(str2, str, slen); + str2[slen] = '\0'; + do_tputs(str2, affcnt, f_putc); + str += slen + 2; + /* Perform the delay. */ + delay = lstrtoi(str, &str); + if (*str == '*') + delay *= affcnt; + flush(); + sleep_ms(delay); + /* Skip past closing ">" at end of delay string. */ + str = strstr(str, ">"); + if (str != NULL) + str++; + continue; + } + } +#endif + /* Pass the rest of the string to tputs and we're done. */ + do_tputs(str, affcnt, f_putc); + break; + } +} +#endif /* MSDOS_COMPILER */ + /* * Configure the termimal so mouse clicks and wheel moves * produce input to less. @@ -1566,7 +1676,7 @@ init_mouse(VOID_PARAM) if (!mousecap) return; #if !MSDOS_COMPILER - tputs(sc_s_mousecap, sc_height, putchr); + ltputs(sc_s_mousecap, sc_height, putchr); #else #if MSDOS_COMPILER==WIN32C SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT @@ -1586,7 +1696,7 @@ deinit_mouse(VOID_PARAM) if (!mousecap) return; #if !MSDOS_COMPILER - tputs(sc_e_mousecap, sc_height, putchr); + ltputs(sc_e_mousecap, sc_height, putchr); #else #if MSDOS_COMPILER==WIN32C SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_EXTENDED_FLAGS @@ -1605,11 +1715,12 @@ init(VOID_PARAM) if (!(quit_if_one_screen && one_screen)) { if (!no_init) - tputs(sc_init, sc_height, putchr); + ltputs(sc_init, sc_height, putchr); if (!no_keypad) - tputs(sc_s_keypad, sc_height, putchr); + ltputs(sc_s_keypad, sc_height, putchr); init_mouse(); } + init_done = 1; if (top_scroll) { int i; @@ -1633,11 +1744,12 @@ init(VOID_PARAM) init_mouse(); } + win32_init_vt_term(); #endif + init_done = 1; initcolor(); flush(); #endif - init_done = 1; } /* @@ -1653,14 +1765,15 @@ deinit(VOID_PARAM) { deinit_mouse(); if (!no_keypad) - tputs(sc_e_keypad, sc_height, putchr); + ltputs(sc_e_keypad, sc_height, putchr); if (!no_init) - tputs(sc_deinit, sc_height, putchr); + ltputs(sc_deinit, sc_height, putchr); } #else /* Restore system colors. */ SETCOLORS(sy_fg_color, sy_bg_color); #if MSDOS_COMPILER==WIN32C + win32_deinit_vt_term(); if (!(quit_if_one_screen && one_screen)) { deinit_mouse(); @@ -1675,14 +1788,31 @@ deinit(VOID_PARAM) init_done = 0; } +/* + * Are we interactive (ie. writing to an initialized tty)? + */ + public int +interactive(VOID_PARAM) +{ + return (is_tty && init_done); +} + + static void +assert_interactive(VOID_PARAM) +{ + if (interactive()) return; + /* abort(); */ +} + /* * Home cursor (move to upper left corner of screen). */ public void home(VOID_PARAM) { + assert_interactive(); #if !MSDOS_COMPILER - tputs(sc_home, 1, putchr); + ltputs(sc_home, 1, putchr); #else flush(); _settextposition(1,1); @@ -1696,8 +1826,9 @@ home(VOID_PARAM) public void add_line(VOID_PARAM) { + assert_interactive(); #if !MSDOS_COMPILER - tputs(sc_addline, sc_height, putchr); + ltputs(sc_addline, sc_height, putchr); #else flush(); #if MSDOS_COMPILER==MSOFTC @@ -1905,10 +2036,9 @@ win32_scroll_up(n) public void lower_left(VOID_PARAM) { - if (!init_done) - return; + assert_interactive(); #if !MSDOS_COMPILER - tputs(sc_lower_left, 1, putchr); + ltputs(sc_lower_left, 1, putchr); #else flush(); _settextposition(sc_height, 1); @@ -1921,29 +2051,32 @@ lower_left(VOID_PARAM) public void line_left(VOID_PARAM) { + assert_interactive(); #if !MSDOS_COMPILER - tputs(sc_return, 1, putchr); + ltputs(sc_return, 1, putchr); #else - int row; - flush(); -#if MSDOS_COMPILER==WIN32C { - CONSOLE_SCREEN_BUFFER_INFO scr; - GetConsoleScreenBufferInfo(con_out, &scr); - row = scr.dwCursorPosition.Y - scr.srWindow.Top + 1; - } + int row; + flush(); +#if MSDOS_COMPILER==WIN32C + { + CONSOLE_SCREEN_BUFFER_INFO scr; + GetConsoleScreenBufferInfo(con_out, &scr); + row = scr.dwCursorPosition.Y - scr.srWindow.Top + 1; + } #else #if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC - row = wherey(); + row = wherey(); #else - { - struct rccoord tpos = _gettextposition(); - row = tpos.row; + { + struct rccoord tpos = _gettextposition(); + row = tpos.row; + } +#endif +#endif + _settextposition(row, 1); } #endif -#endif - _settextposition(row, 1); -#endif } /* @@ -1984,8 +2117,9 @@ check_winch(VOID_PARAM) goto_line(sindex) int sindex; { + assert_interactive(); #if !MSDOS_COMPILER - tputs(tgoto(sc_move, 0, sindex), 1, putchr); + ltputs(tgoto(sc_move, 0, sindex), 1, putchr); #else flush(); _settextposition(sindex+1, 1); @@ -2052,7 +2186,7 @@ vbell(VOID_PARAM) #if !MSDOS_COMPILER if (*sc_visual_bell == '\0') return; - tputs(sc_visual_bell, sc_height, putchr); + ltputs(sc_visual_bell, sc_height, putchr); #else #if MSDOS_COMPILER==DJGPPC ScreenVisualBell(); @@ -2142,8 +2276,9 @@ bell(VOID_PARAM) public void clear(VOID_PARAM) { + assert_interactive(); #if !MSDOS_COMPILER - tputs(sc_clear, sc_height, putchr); + ltputs(sc_clear, sc_height, putchr); #else flush(); #if MSDOS_COMPILER==WIN32C @@ -2161,8 +2296,9 @@ clear(VOID_PARAM) public void clear_eol(VOID_PARAM) { + /* assert_interactive();*/ #if !MSDOS_COMPILER - tputs(sc_eol_clear, 1, putchr); + ltputs(sc_eol_clear, 1, putchr); #else #if MSDOS_COMPILER==MSOFTC short top, left; @@ -2220,13 +2356,14 @@ clear_eol(VOID_PARAM) static void clear_eol_bot(VOID_PARAM) { + assert_interactive(); #if MSDOS_COMPILER clear_eol(); #else if (below_mem) - tputs(sc_eos_clear, 1, putchr); + ltputs(sc_eos_clear, 1, putchr); else - tputs(sc_eol_clear, 1, putchr); + ltputs(sc_eol_clear, 1, putchr); #endif } @@ -2259,42 +2396,305 @@ clear_bot(VOID_PARAM) } } +/* + * Color string may be "x[y]" where x and y are 4-bit color chars, + * or "N[.M]" where N and M are decimal integers> + * Any of x,y,N,M may also be "-" to mean "unchanged". + */ + +/* + * Parse a 4-bit color char. + */ + static int +parse_color4(ch) + char ch; +{ + switch (ch) + { + case 'k': return 0; + case 'r': return CV_RED; + case 'g': return CV_GREEN; + case 'y': return CV_RED|CV_GREEN; + case 'b': return CV_BLUE; + case 'm': return CV_RED|CV_BLUE; + case 'c': return CV_GREEN|CV_BLUE; + case 'w': return CV_RED|CV_GREEN|CV_BLUE; + case 'K': return 0|CV_BRIGHT; + case 'R': return CV_RED|CV_BRIGHT; + case 'G': return CV_GREEN|CV_BRIGHT; + case 'Y': return CV_RED|CV_GREEN|CV_BRIGHT; + case 'B': return CV_BLUE|CV_BRIGHT; + case 'M': return CV_RED|CV_BLUE|CV_BRIGHT; + case 'C': return CV_GREEN|CV_BLUE|CV_BRIGHT; + case 'W': return CV_RED|CV_GREEN|CV_BLUE|CV_BRIGHT; + case '-': return CV_NOCHANGE; + default: return CV_ERROR; + } +} + +/* + * Parse a color as a decimal integer. + */ + static int +parse_color6(ps) + char **ps; +{ + if (**ps == '-') + { + (*ps)++; + return CV_NOCHANGE; + } else + { + char *ops = *ps; + int color = lstrtoi(ops, ps); + if (*ps == ops) + return CV_ERROR; + return color; + } +} + +/* + * Parse a color pair and return the foreground/background values. + * Return type of color specifier: + * CV_4BIT: fg/bg values are OR of CV_{RGB} bits. + * CV_6BIT: fg/bg values are integers entered by user. + */ + public COLOR_TYPE +parse_color(str, p_fg, p_bg) + char *str; + int *p_fg; + int *p_bg; +{ + int fg; + int bg; + COLOR_TYPE type = CT_NULL; + + if (str == NULL || *str == '\0') + return CT_NULL; + if (*str == '+') + str++; /* ignore leading + */ + + fg = parse_color4(str[0]); + bg = parse_color4((strlen(str) < 2) ? '-' : str[1]); + if (fg != CV_ERROR && bg != CV_ERROR) + type = CT_4BIT; + else + { + fg = parse_color6(&str); + bg = (fg != CV_ERROR && *str++ == '.') ? parse_color6(&str) : CV_NOCHANGE; + if (fg != CV_ERROR && bg != CV_ERROR) + type = CT_6BIT; + } + if (p_fg != NULL) *p_fg = fg; + if (p_bg != NULL) *p_bg = bg; + return type; +} + +#if !MSDOS_COMPILER + + static int +sgr_color(color) + int color; +{ + switch (color) + { + case 0: return 30; + case CV_RED: return 31; + case CV_GREEN: return 32; + case CV_RED|CV_GREEN: return 33; + case CV_BLUE: return 34; + case CV_RED|CV_BLUE: return 35; + case CV_GREEN|CV_BLUE: return 36; + case CV_RED|CV_GREEN|CV_BLUE: return 37; + + case CV_BRIGHT: return 90; + case CV_RED|CV_BRIGHT: return 91; + case CV_GREEN|CV_BRIGHT: return 92; + case CV_RED|CV_GREEN|CV_BRIGHT: return 93; + case CV_BLUE|CV_BRIGHT: return 94; + case CV_RED|CV_BLUE|CV_BRIGHT: return 95; + case CV_GREEN|CV_BLUE|CV_BRIGHT: return 96; + case CV_RED|CV_GREEN|CV_BLUE|CV_BRIGHT: return 97; + + default: return color; + } +} + + static void +tput_fmt(fmt, color, f_putc) + char *fmt; + int color; + int (*f_putc)(int); +{ + char buf[16]; + if (color == attrcolor) + return; + SNPRINTF1(buf, sizeof(buf), fmt, color); + ltputs(buf, 1, f_putc); + attrcolor = color; +} + + static void +tput_color(str, f_putc) + char *str; + int (*f_putc)(int); +{ + int fg; + int bg; + + if (str != NULL && strcmp(str, "*") == 0) + { + /* Special case: reset to normal */ + tput_fmt(ESCS"[m", -1, f_putc); + return; + } + switch (parse_color(str, &fg, &bg)) + { + case CT_4BIT: + if (fg >= 0) + tput_fmt(ESCS"[%dm", sgr_color(fg), f_putc); + if (bg >= 0) + tput_fmt(ESCS"[%dm", sgr_color(bg)+10, f_putc); + break; + case CT_6BIT: + if (fg >= 0) + tput_fmt(ESCS"[38;5;%dm", fg, f_putc); + if (bg >= 0) + tput_fmt(ESCS"[48;5;%dm", bg, f_putc); + break; + default: + break; + } +} + + static void +tput_inmode(mode_str, attr, attr_bit, f_putc) + char *mode_str; + int attr; + int attr_bit; + int (*f_putc)(int); +{ + char *color_str; + if ((attr & attr_bit) == 0) + return; + color_str = get_color_map(attr_bit); + if (color_str == NULL || *color_str == '\0' || *color_str == '+') + { + ltputs(mode_str, 1, f_putc); + if (color_str == NULL || *color_str++ != '+') + return; + } + /* Color overrides mode string */ + tput_color(color_str, f_putc); +} + + static void +tput_outmode(mode_str, attr_bit, f_putc) + char *mode_str; + int attr_bit; + int (*f_putc)(int); +{ + if ((attrmode & attr_bit) == 0) + return; + ltputs(mode_str, 1, f_putc); +} + +#else /* MSDOS_COMPILER */ + +#if MSDOS_COMPILER==WIN32C + static int +WIN32put_fmt(fmt, color) + char *fmt; + int color; +{ + char buf[16]; + int len = SNPRINTF1(buf, sizeof(buf), fmt, color); + WIN32textout(buf, len); + return TRUE; +} +#endif + + static int +win_set_color(attr) + int attr; +{ + int fg; + int bg; + int out = FALSE; + char *str = get_color_map(attr); + if (str == NULL || str[0] == '\0') + return FALSE; + switch (parse_color(str, &fg, &bg)) + { + case CT_4BIT: + if (fg >= 0 && bg >= 0) + { + SETCOLORS(fg, bg); + out = TRUE; + } else if (fg >= 0) + { + SET_FG_COLOR(fg); + out = TRUE; + } else if (bg >= 0) + { + SET_BG_COLOR(bg); + out = TRUE; + } + break; +#if MSDOS_COMPILER==WIN32C + case CT_6BIT: + if (vt_enabled) + { + if (fg > 0) + out = WIN32put_fmt(ESCS"[38;5;%dm", fg); + if (bg > 0) + out = WIN32put_fmt(ESCS"[48;5;%dm", bg); + } + break; +#endif + default: + break; + } + return out; +} + +#endif /* MSDOS_COMPILER */ + public void at_enter(attr) int attr; { attr = apply_at_specials(attr); - #if !MSDOS_COMPILER /* The one with the most priority is last. */ - if (attr & AT_UNDERLINE) - tputs(sc_u_in, 1, putchr); - if (attr & AT_BOLD) - tputs(sc_b_in, 1, putchr); - if (attr & AT_BLINK) - tputs(sc_bl_in, 1, putchr); - if (attr & AT_STANDOUT) - tputs(sc_s_in, 1, putchr); + tput_inmode(sc_u_in, attr, AT_UNDERLINE, putchr); + tput_inmode(sc_b_in, attr, AT_BOLD, putchr); + tput_inmode(sc_bl_in, attr, AT_BLINK, putchr); + /* Don't use standout and color at the same time. */ + if (use_color && (attr & AT_COLOR)) + tput_color(get_color_map(attr), putchr); + else + tput_inmode(sc_s_in, attr, AT_STANDOUT, putchr); #else flush(); /* The one with the most priority is first. */ - if (attr & AT_STANDOUT) + if ((attr & AT_COLOR) && use_color) + { + win_set_color(attr); + } else if (attr & AT_STANDOUT) { SETCOLORS(so_fg_color, so_bg_color); } else if (attr & AT_BLINK) { SETCOLORS(bl_fg_color, bl_bg_color); - } - else if (attr & AT_BOLD) + } else if (attr & AT_BOLD) { SETCOLORS(bo_fg_color, bo_bg_color); - } - else if (attr & AT_UNDERLINE) + } else if (attr & AT_UNDERLINE) { SETCOLORS(ul_fg_color, ul_bg_color); } #endif - attrmode = attr; } @@ -2303,19 +2703,15 @@ at_exit(VOID_PARAM) { #if !MSDOS_COMPILER /* Undo things in the reverse order we did them. */ - if (attrmode & AT_STANDOUT) - tputs(sc_s_out, 1, putchr); - if (attrmode & AT_BLINK) - tputs(sc_bl_out, 1, putchr); - if (attrmode & AT_BOLD) - tputs(sc_b_out, 1, putchr); - if (attrmode & AT_UNDERLINE) - tputs(sc_u_out, 1, putchr); + tput_color("*", putchr); + tput_outmode(sc_s_out, AT_STANDOUT, putchr); + tput_outmode(sc_bl_out, AT_BLINK, putchr); + tput_outmode(sc_b_out, AT_BOLD, putchr); + tput_outmode(sc_u_out, AT_UNDERLINE, putchr); #else flush(); SETCOLORS(nm_fg_color, nm_bg_color); #endif - attrmode = AT_NORMAL; } @@ -2357,57 +2753,6 @@ apply_at_specials(attr) return attr; } -#if 0 /* No longer used */ -/* - * Erase the character to the left of the cursor - * and move the cursor left. - */ - public void -backspace(VOID_PARAM) -{ -#if !MSDOS_COMPILER - /* - * Erase the previous character by overstriking with a space. - */ - tputs(sc_backspace, 1, putchr); - putchr(' '); - tputs(sc_backspace, 1, putchr); -#else -#if MSDOS_COMPILER==MSOFTC - struct rccoord tpos; - - flush(); - tpos = _gettextposition(); - if (tpos.col <= 1) - return; - _settextposition(tpos.row, tpos.col-1); - _outtext(" "); - _settextposition(tpos.row, tpos.col-1); -#else -#if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC - cputs("\b"); -#else -#if MSDOS_COMPILER==WIN32C - COORD cpos; - DWORD cChars; - CONSOLE_SCREEN_BUFFER_INFO scr; - - flush(); - GetConsoleScreenBufferInfo(con_out, &scr); - cpos = scr.dwCursorPosition; - if (cpos.X <= 0) - return; - cpos.X--; - SetConsoleCursorPosition(con_out, cpos); - FillConsoleOutputCharacter(con_out, (TCHAR)' ', 1, cpos, &cChars); - SetConsoleCursorPosition(con_out, cpos); -#endif -#endif -#endif -#endif -} -#endif /* 0 */ - /* * Output a plain backspace, without erasing the previous char. */ @@ -2419,7 +2764,7 @@ putbs(VOID_PARAM) else { #if !MSDOS_COMPILER - tputs(sc_backspace, 1, putchr); + ltputs(sc_backspace, 1, putchr); #else int row, col; @@ -2638,3 +2983,4 @@ WIN32textout(text, len) #endif } #endif + diff --git a/contrib/less/scrsize.c b/contrib/less/scrsize.c index 2063aa376bb3..ee07cb8af1e6 100644 --- a/contrib/less/scrsize.c +++ b/contrib/less/scrsize.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. diff --git a/contrib/less/search.c b/contrib/less/search.c index 7650ab379508..f619fbebeae8 100644 --- a/contrib/less/search.c +++ b/contrib/less/search.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -16,8 +16,8 @@ #include "position.h" #include "charset.h" -#define MINPOS(a,b) (((a) < (b)) ? (a) : (b)) -#define MAXPOS(a,b) (((a) > (b)) ? (a) : (b)) +#define MINPOS(a,b) (((a) < (b)) ? (a) : (b)) +#define MAXPOS(a,b) (((a) > (b)) ? (a) : (b)) extern int sigs; extern int how_search; @@ -33,6 +33,10 @@ extern POSITION start_attnpos; extern POSITION end_attnpos; extern int utf_mode; extern int screen_trashed; +extern int sc_width; +extern int sc_height; +extern int chopline; +extern int hshift; #if HILITE_SEARCH extern int hilite_search; extern int size_linebuf; @@ -41,8 +45,7 @@ extern int can_goto_line; static int hide_hilite; static POSITION prep_startpos; static POSITION prep_endpos; -static int is_caseless; -static int is_ucase_pattern; +extern POSITION xxpos; /* * Structures for maintaining a set of ranges for hilites and filtered-out @@ -94,6 +97,7 @@ struct hilite_tree static struct hilite_tree hilite_anchor = HILITE_INITIALIZER(); static struct hilite_tree filter_anchor = HILITE_INITIALIZER(); +static struct pattern_info *filter_infos = NULL; #endif @@ -105,6 +109,7 @@ struct pattern_info { PATTERN_TYPE compiled; char* text; int search_type; + struct pattern_info *next; }; #if NO_REGEX @@ -114,7 +119,8 @@ struct pattern_info { #endif static struct pattern_info search_info; -static struct pattern_info filter_info; +static int is_ucase_pattern; +static int is_caseless; /* * Are there any uppercase letters in this string? @@ -135,19 +141,35 @@ is_ucase(str) return (0); } +/* + * Discard a saved pattern. + */ + static void +clear_pattern(info) + struct pattern_info *info; +{ + if (info->text != NULL) + free(info->text); + info->text = NULL; +#if !NO_REGEX + uncompile_pattern(&info->compiled); +#endif +} + /* * Compile and save a search pattern. */ static int -set_pattern(info, pattern, search_type) +set_pattern(info, pattern, search_type, show_error) struct pattern_info *info; char *pattern; int search_type; + int show_error; { #if !NO_REGEX if (pattern == NULL) - CLEAR_PATTERN(info->compiled); - else if (compile_pattern(pattern, search_type, &info->compiled) < 0) + SET_NULL_PATTERN(info->compiled); + else if (compile_pattern(pattern, search_type, show_error, &info->compiled) < 0) return -1; #endif /* Pattern compiled successfully; save the text too. */ @@ -173,21 +195,6 @@ set_pattern(info, pattern, search_type) return 0; } -/* - * Discard a saved pattern. - */ - static void -clear_pattern(info) - struct pattern_info *info; -{ - if (info->text != NULL) - free(info->text); - info->text = NULL; -#if !NO_REGEX - uncompile_pattern(&info->compiled); -#endif -} - /* * Initialize saved pattern to nothing. */ @@ -195,9 +202,10 @@ clear_pattern(info) init_pattern(info) struct pattern_info *info; { - CLEAR_PATTERN(info->compiled); + SET_NULL_PATTERN(info->compiled); info->text = NULL; info->search_type = 0; + info->next = NULL; } /* @@ -207,7 +215,6 @@ init_pattern(info) init_search(VOID_PARAM) { init_pattern(&search_info); - init_pattern(&filter_info); } /* @@ -217,18 +224,13 @@ init_search(VOID_PARAM) get_cvt_ops(VOID_PARAM) { int ops = 0; - if (is_caseless || bs_mode == BS_SPECIAL) - { - if (is_caseless) - ops |= CVT_TO_LC; - if (bs_mode == BS_SPECIAL) - ops |= CVT_BS; - if (bs_mode != BS_CONTROL) - ops |= CVT_CRLF; - } else if (bs_mode != BS_CONTROL) - { + + if (is_caseless) + ops |= CVT_TO_LC; + if (bs_mode == BS_SPECIAL) + ops |= CVT_BS; + if (bs_mode != BS_CONTROL) ops |= CVT_CRLF; - } if (ctldisp == OPT_ONPLUS) ops |= CVT_ANSI; return (ops); @@ -292,6 +294,7 @@ repaint_hilite(on) lower_left(); hide_hilite = save_hide_hilite; } +#endif /* * Clear the attn hilite. @@ -299,6 +302,7 @@ repaint_hilite(on) public void clear_attn(VOID_PARAM) { +#if HILITE_SEARCH int sindex; POSITION old_start_attnpos; POSITION old_end_attnpos; @@ -337,27 +341,30 @@ clear_attn(VOID_PARAM) } if (moved) lower_left(); -} #endif +} /* - * Hide search string highlighting. + * Toggle or clear search string highlighting. */ public void -undo_search(VOID_PARAM) +undo_search(clear) + int clear; { - if (!prev_pattern(&search_info)) + clear_pattern(&search_info); +#if HILITE_SEARCH + if (clear) + { + clr_hilite(); + } else { if (hilite_anchor.first == NULL) { error("No previous regular expression", NULL_PARG); return; } - clr_hilite(); /* Next time, hilite_anchor.first will be NULL. */ + hide_hilite = !hide_hilite; } - clear_pattern(&search_info); -#if HILITE_SEARCH - hide_hilite = !hide_hilite; repaint_hilite(1); #endif } @@ -601,7 +608,7 @@ prev_unfiltered(pos) * If nohide is nonzero, don't consider hide_hilite. */ public int -is_hilited(pos, epos, nohide, p_matches) +is_hilited_attr(pos, epos, nohide, p_matches) POSITION pos; POSITION epos; int nohide; @@ -614,12 +621,12 @@ is_hilited(pos, epos, nohide, p_matches) if (!status_col && start_attnpos != NULL_POSITION && - pos < end_attnpos && - (epos == NULL_POSITION || epos > start_attnpos)) + pos <= end_attnpos && + (epos == NULL_POSITION || epos >= start_attnpos)) /* * The attn line overlaps this range. */ - return (1); + return (AT_HILITE|AT_COLOR_ATTN); match = is_hilited_range(pos, epos); if (!match) @@ -631,7 +638,7 @@ is_hilited(pos, epos, nohide, p_matches) * hilite in status column. In this case we want to return * hilite status even if hiliting is disabled or hidden. */ - return (1); + return (AT_HILITE|AT_COLOR_SEARCH); /* * Report matches, even if we're hiding highlights. @@ -650,7 +657,7 @@ is_hilited(pos, epos, nohide, p_matches) */ return (0); - return (1); + return (AT_HILITE|AT_COLOR_SEARCH); } /* @@ -1155,11 +1162,92 @@ search_pos(search_type) return (pos); } +/* + * Check to see if the line matches the filter pattern. + * If so, add an entry to the filter list. + */ +#if HILITE_SEARCH + static int +matches_filters(pos, cline, line_len, chpos, linepos, sp, ep) + POSITION pos; + char *cline; + int line_len; + int *chpos; + POSITION linepos; + char **sp; + char **ep; +{ + struct pattern_info *filter; + + for (filter = filter_infos; filter != NULL; filter = filter->next) + { + int line_filter = match_pattern(info_compiled(filter), filter->text, + cline, line_len, sp, ep, 0, filter->search_type); + if (line_filter) + { + struct hilite hl; + hl.hl_startpos = linepos; + hl.hl_endpos = pos; + add_hilite(&filter_anchor, &hl); + free(cline); + free(chpos); + return (1); + } + } + return (0); +} +#endif + +/* + * Get the position of the first char in the screen line which + * puts tpos on screen. + */ + static POSITION +get_lastlinepos(pos, tpos, sheight) + POSITION pos; + POSITION tpos; + int sheight; +{ + int nlines; + + for (nlines = 0;; nlines++) + { + POSITION npos = forw_line(pos); + if (npos > tpos) + { + if (nlines < sheight) + return NULL_POSITION; + return pos; + } + pos = npos; + } +} + +/* + * Get the segment index of tpos in the line starting at pos. + * A segment is a string of printable chars that fills the screen width. + */ + static int +get_seg(pos, tpos) + POSITION pos; + POSITION tpos; +{ + int seg; + + for (seg = 0;; seg++) + { + POSITION npos = forw_line_seg(pos, TRUE); + if (npos > tpos) + return seg; + pos = npos; + } +} + /* * Search a subset of the file, specified by start/end position. */ static int -search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos) +search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos, plastlinepos) POSITION pos; POSITION endpos; int search_type; @@ -1167,6 +1255,7 @@ search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos) int maxlines; POSITION *plinepos; POSITION *pendpos; + POSITION *plastlinepos; { char *line; char *cline; @@ -1178,9 +1267,14 @@ search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos) int cvt_len; int *chpos; POSITION linepos, oldpos; + int swidth = sc_width - line_pfx_width(); + int sheight = sc_height - sindex_from_sline(jump_sline); linenum = find_linenum(pos); oldpos = pos; + /* When the search wraps around, end at starting position. */ + if ((search_type & SRCH_WRAP) && endpos == NULL_POSITION) + endpos = pos; for (;;) { /* @@ -1196,7 +1290,9 @@ search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos) return (-1); } - if ((endpos != NULL_POSITION && pos >= endpos) || maxlines == 0) + if ((endpos != NULL_POSITION && !(search_type & SRCH_WRAP) && + (((search_type & SRCH_FORW) && pos >= endpos) || + ((search_type & SRCH_BACK) && pos <= endpos))) || maxlines == 0) { /* * Reached end position without a match. @@ -1235,6 +1331,35 @@ search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos) /* * Reached EOF/BOF without a match. */ + if (search_type & SRCH_WRAP) + { + /* + * The search wraps around the current file, so + * try to continue at BOF/EOF. + */ + if (search_type & SRCH_FORW) + { + pos = ch_zero(); + } else + { + pos = ch_length(); + if (pos == NULL_POSITION) + { + (void) ch_end_seek(); + pos = ch_length(); + } + } + if (pos != NULL_POSITION) { + /* + * Wrap-around was successful. Clear + * the flag so we don't wrap again, and + * continue the search at new pos. + */ + search_type &= ~SRCH_WRAP; + linenum = find_linenum(pos); + continue; + } + } if (pendpos != NULL) *pendpos = oldpos; return (matches); @@ -1252,8 +1377,10 @@ search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos) add_lnum(linenum, pos); oldpos = pos; +#if HILITE_SEARCH if (is_filtered(linepos)) continue; +#endif /* * If it's a caseless search, convert the line to lowercase. @@ -1267,25 +1394,14 @@ search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos) #if HILITE_SEARCH /* - * Check to see if the line matches the filter pattern. - * If so, add an entry to the filter list. + * If any filters are in effect, ignore non-matching lines. */ - if (((search_type & SRCH_FIND_ALL) || + if (filter_infos != NULL && + ((search_type & SRCH_FIND_ALL) || prep_startpos == NULL_POSITION || - linepos < prep_startpos || linepos >= prep_endpos) && - prev_pattern(&filter_info)) { - int line_filter = match_pattern(info_compiled(&filter_info), filter_info.text, - cline, line_len, &sp, &ep, 0, filter_info.search_type); - if (line_filter) - { - struct hilite hl; - hl.hl_startpos = linepos; - hl.hl_endpos = pos; - add_hilite(&filter_anchor, &hl); - free(cline); - free(chpos); + linepos < prep_startpos || linepos >= prep_endpos)) { + if (matches_filters(pos, cline, line_len, chpos, linepos, &sp, &ep)) continue; - } } #endif @@ -1330,6 +1446,50 @@ search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos) hilite_line(linepos, cline, line_len, chpos, sp, ep, cvt_ops); } #endif + if (chopline) + { + /* + * If necessary, shift horizontally to make sure + * search match is fully visible. + */ + if (sp != NULL && ep != NULL) + { + int start_off = sp - cline; + int end_off = ep - cline; + int save_hshift = hshift; + int sshift; + int eshift; + hshift = 0; /* make get_seg count screen lines */ + chopline = FALSE; + sshift = swidth * get_seg(linepos, linepos + chpos[start_off]); + eshift = swidth * get_seg(linepos, linepos + chpos[end_off]); + chopline = TRUE; + if (sshift >= save_hshift && eshift <= save_hshift) + { + hshift = save_hshift; + } else + { + hshift = sshift; + screen_trashed = 1; + } + } + } else if (plastlinepos != NULL) + { + /* + * If the line is so long that the highlighted match + * won't be seen when the line is displayed normally + * (starting at the first char) because it fills the whole + * screen and more, scroll forward until the last char + * of the match appears in the last line on the screen. + * lastlinepos is the position of the first char of that last line. + */ + if (ep != NULL) + { + int end_off = ep - cline; + if (end_off >= swidth * sheight / 4) /* heuristic */ + *plastlinepos = get_lastlinepos(linepos, linepos + chpos[end_off], sheight); + } + } free(cline); free(chpos); if (plinepos != NULL) @@ -1358,8 +1518,8 @@ hist_pattern(search_type) if (pattern == NULL) return (0); - if (set_pattern(&search_info, pattern, search_type) < 0) - return (0); + if (set_pattern(&search_info, pattern, search_type, 1) < 0) + return (-1); #if HILITE_SEARCH if (hilite_search == OPT_ONPLUS && !hide_hilite) @@ -1392,7 +1552,7 @@ chg_caseless(VOID_PARAM) * Regenerate the pattern using the new state. */ clear_pattern(&search_info); - hist_pattern(search_info.search_type); + (void) hist_pattern(search_info.search_type); } } @@ -1412,6 +1572,8 @@ search(search_type, pattern, n) int n; { POSITION pos; + POSITION opos; + POSITION lastlinepos = NULL_POSITION; if (pattern == NULL || *pattern == '\0') { @@ -1419,10 +1581,13 @@ search(search_type, pattern, n) * A null pattern means use the previously compiled pattern. */ search_type |= SRCH_AFTER_TARGET; - if (!prev_pattern(&search_info) && !hist_pattern(search_type)) + if (!prev_pattern(&search_info)) { - error("No previous regular expression", NULL_PARG); - return (-1); + int r = hist_pattern(search_type); + if (r == 0) + error("No previous regular expression", NULL_PARG); + if (r <= 0) + return (-1); } if ((search_type & SRCH_NO_REGEX) != (search_info.search_type & SRCH_NO_REGEX)) @@ -1455,7 +1620,8 @@ search(search_type, pattern, n) /* * Compile the pattern. */ - if (set_pattern(&search_info, pattern, search_type) < 0) + int show_error = !(search_type & SRCH_INCR); + if (set_pattern(&search_info, pattern, search_type, show_error) < 0) return (-1); #if HILITE_SEARCH if (hilite_search || status_col) @@ -1483,6 +1649,7 @@ search(search_type, pattern, n) * Figure out where to start the search. */ pos = search_pos(search_type); + opos = position(sindex_from_sline(jump_sline)); if (pos == NULL_POSITION) { /* @@ -1490,14 +1657,16 @@ search(search_type, pattern, n) */ if (search_type & SRCH_PAST_EOF) return (n); +#if HILITE_SEARCH if (hilite_search == OPT_ON || status_col) repaint_hilite(1); +#endif error("Nothing to search", NULL_PARG); return (-1); } n = search_range(pos, NULL_POSITION, search_type, n, -1, - &pos, (POSITION*)NULL); + &pos, (POSITION*)NULL, &lastlinepos); if (n != 0) { /* @@ -1518,7 +1687,10 @@ search(search_type, pattern, n) /* * Go to the matching line. */ - jump_loc(pos, jump_sline); + if (lastlinepos != NULL_POSITION) + jump_loc(lastlinepos, BOTTOM); + else if (pos != opos) + jump_loc(pos, jump_sline); } #if HILITE_SEARCH @@ -1531,7 +1703,6 @@ search(search_type, pattern, n) return (0); } - #if HILITE_SEARCH /* * Prepare hilites in a given range of the file. @@ -1560,7 +1731,7 @@ prep_hilite(spos, epos, maxlines) * Search beyond where we're asked to search, so the prep region covers * more than we need. Do one big search instead of a bunch of small ones. */ -#define SEARCH_MORE (3*size_linebuf) +#define SEARCH_MORE (3*size_linebuf) if (!prev_pattern(&search_info) && !is_filtering()) return; @@ -1665,7 +1836,7 @@ prep_hilite(spos, epos, maxlines) search_type |= (search_info.search_type & SRCH_NO_REGEX); for (;;) { - result = search_range(spos, epos, search_type, 0, maxlines, (POSITION*)NULL, &new_epos); + result = search_range(spos, epos, search_type, 0, maxlines, (POSITION*)NULL, &new_epos, (POSITION*)NULL); if (result < 0) return; if (prep_endpos == NULL_POSITION || new_epos > prep_endpos) @@ -1718,11 +1889,29 @@ set_filter_pattern(pattern, search_type) char *pattern; int search_type; { + struct pattern_info *filter; + clr_filter(); if (pattern == NULL || *pattern == '\0') - clear_pattern(&filter_info); - else - set_pattern(&filter_info, pattern, search_type); + { + /* Clear and free all filters. */ + for (filter = filter_infos; filter != NULL; ) + { + struct pattern_info *next_filter = filter->next; + clear_pattern(filter); + free(filter); + filter = next_filter; + } + filter_infos = NULL; + } else + { + /* Create a new filter and add it to the filter_infos list. */ + filter = ecalloc(1, sizeof(struct pattern_info)); + init_pattern(filter); + set_pattern(filter, pattern, search_type, 1); + filter->next = filter_infos; + filter_infos = filter; + } screen_trashed = 1; } @@ -1734,7 +1923,7 @@ is_filtering(VOID_PARAM) { if (ch_getflags() & CH_HELPFILE) return (0); - return prev_pattern(&filter_info); + return (filter_infos != NULL); } #endif diff --git a/contrib/less/signal.c b/contrib/less/signal.c index 04799b87bb8c..9e580e00fe36 100644 --- a/contrib/less/signal.c +++ b/contrib/less/signal.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -34,9 +34,11 @@ extern int linenums; extern int wscroll; extern int reading; extern int quit_on_intr; -extern int less_is_more; +extern int secure; extern long jump_sline_fraction; +extern int less_is_more; + /* * Interrupt signal handler. */ @@ -63,6 +65,9 @@ u_interrupt(type) #endif if (less_is_more) quit(0); +#if HILITE_SEARCH + set_filter_pattern(NULL, 0); +#endif if (reading) intread(); /* May longjmp */ } @@ -125,6 +130,9 @@ wbreak_handler(dwCtrlType) case CTRL_C_EVENT: case CTRL_BREAK_EVENT: sigs |= S_INTERRUPT; +#if HILITE_SEARCH + set_filter_pattern(NULL, 0); +#endif return (TRUE); default: break; @@ -158,7 +166,7 @@ init_signals(on) (void) LSIGNAL(SIGINT, u_interrupt); #endif #ifdef SIGTSTP - (void) LSIGNAL(SIGTSTP, stop); + (void) LSIGNAL(SIGTSTP, secure ? SIG_IGN : stop); #endif #ifdef SIGWINCH (void) LSIGNAL(SIGWINCH, winch); diff --git a/contrib/less/tags.c b/contrib/less/tags.c index fdc82da24e82..d449c0333deb 100644 --- a/contrib/less/tags.c +++ b/contrib/less/tags.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -10,7 +10,7 @@ #include "less.h" -#define WHITESP(c) ((c)==' ' || (c)=='\t') +#define WHITESP(c) ((c)==' ' || (c)=='\t') #if TAGS @@ -36,12 +36,12 @@ enum tag_result { * Tag type */ enum { - T_CTAGS, /* 'tags': standard and extended format (ctags) */ - T_CTAGS_X, /* stdin: cross reference format (ctags) */ - T_GTAGS, /* 'GTAGS': function definition (global) */ - T_GRTAGS, /* 'GRTAGS': function reference (global) */ - T_GSYMS, /* 'GSYMS': other symbols (global) */ - T_GPATH /* 'GPATH': path name (global) */ + T_CTAGS, /* 'tags': standard and extended format (ctags) */ + T_CTAGS_X, /* stdin: cross reference format (ctags) */ + T_GTAGS, /* 'GTAGS': function definition (global) */ + T_GRTAGS, /* 'GRTAGS': function reference (global) */ + T_GSYMS, /* 'GSYMS': other symbols (global) */ + T_GPATH /* 'GPATH': path name (global) */ }; static enum tag_result findctag LESSPARAMS((char *tag)); @@ -50,8 +50,7 @@ static char *nextgtag(VOID_PARAM); static char *prevgtag(VOID_PARAM); static POSITION ctagsearch(VOID_PARAM); static POSITION gtagsearch(VOID_PARAM); -static int getentry LESSPARAMS((char *buf, char **tag, char **file, - char **line)); +static int getentry LESSPARAMS((char *buf, char **tag, char **file, char **line)); /* * The list of tags generated by the last findgtag() call. @@ -67,10 +66,10 @@ struct taglist { }; struct tag { struct tag *next, *prev; /* List links */ - char *tag_file; /* Source file containing the tag */ - LINENUM tag_linenum; /* Appropriate line number in source file */ - char *tag_pattern; /* Pattern used to find the tag */ - char tag_endline; /* True if the pattern includes '$' */ + char *tag_file; /* Source file containing the tag */ + LINENUM tag_linenum; /* Appropriate line number in source file */ + char *tag_pattern; /* Pattern used to find the tag */ + char tag_endline; /* True if the pattern includes '$' */ }; #define TAG_END ((struct tag *) &taglist) static struct taglist taglist = { TAG_END, TAG_END }; @@ -412,10 +411,10 @@ curtag_match(char const *line, POSITION linepos) * Search for a tag. * This is a stripped-down version of search(). * We don't use search() for several reasons: - * - We don't want to blow away any search string we may have saved. - * - The various regular-expression functions (from different systems: - * regcmp vs. re_comp) behave differently in the presence of - * parentheses (which are almost always found in a tag). + * - We don't want to blow away any search string we may have saved. + * - The various regular-expression functions (from different systems: + * regcmp vs. re_comp) behave differently in the presence of + * parentheses (which are almost always found in a tag). */ static POSITION ctagsearch(VOID_PARAM) @@ -498,8 +497,8 @@ ctagsearch(VOID_PARAM) */ static enum tag_result findgtag(tag, type) - char *tag; /* tag to load */ - int type; /* tags type */ + char *tag; /* tag to load */ + int type; /* tags type */ { char buf[256]; FILE *fp; @@ -590,7 +589,7 @@ findgtag(tag, type) } while (c != '\n' && c != EOF); } - if (getentry(buf, &name, &file, &line)) + if (getentry(buf, &name, &file, &line)) { /* * Couldn't parse this line for some reason. @@ -624,7 +623,7 @@ findgtag(tag, type) return TAG_FOUND; } -static int circular = 0; /* 1: circular tag structure */ +static int circular = 0; /* 1: circular tag structure */ /* * Return the filename required for the next gtag in the queue that was setup @@ -709,9 +708,9 @@ gtagsearch(VOID_PARAM) * |func 21 subr.c func(arg) * * The following commands write this format. - * o Traditinal Ctags with -x option - * o Global with -x option - * See + * o Traditinal Ctags with -x option + * o Global with -x option + * See * * [extended format] * @@ -720,8 +719,8 @@ gtagsearch(VOID_PARAM) * |func function 21 subr.c func(arg) * * The following commands write this format. - * o Exuberant Ctags with -x option - * See + * o Exuberant Ctags with -x option + * See * * Returns 0 on success, -1 on error. * The tag, file, and line will each be NUL-terminated pointers @@ -729,19 +728,19 @@ gtagsearch(VOID_PARAM) */ static int getentry(buf, tag, file, line) - char *buf; /* standard or extended ctags -x format data */ - char **tag; /* name of the tag we actually found */ - char **file; /* file in which to find this tag */ - char **line; /* line number of file where this tag is found */ + char *buf; /* standard or extended ctags -x format data */ + char **tag; /* name of the tag we actually found */ + char **file; /* file in which to find this tag */ + char **line; /* line number of file where this tag is found */ { char *p = buf; - for (*tag = p; *p && !IS_SPACE(*p); p++) /* tag name */ + for (*tag = p; *p && !IS_SPACE(*p); p++) /* tag name */ ; if (*p == 0) return (-1); *p++ = 0; - for ( ; *p && IS_SPACE(*p); p++) /* (skip blanks) */ + for ( ; *p && IS_SPACE(*p); p++) /* (skip blanks) */ ; if (*p == 0) return (-1); @@ -751,24 +750,24 @@ getentry(buf, tag, file, line) */ if (!IS_DIGIT(*p)) { - for ( ; *p && !IS_SPACE(*p); p++) /* (skip tag type) */ + for ( ; *p && !IS_SPACE(*p); p++) /* (skip tag type) */ ; - for (; *p && IS_SPACE(*p); p++) /* (skip blanks) */ + for (; *p && IS_SPACE(*p); p++) /* (skip blanks) */ ; } if (!IS_DIGIT(*p)) return (-1); - *line = p; /* line number */ + *line = p; /* line number */ for (*line = p; *p && !IS_SPACE(*p); p++) ; if (*p == 0) return (-1); *p++ = 0; - for ( ; *p && IS_SPACE(*p); p++) /* (skip blanks) */ + for ( ; *p && IS_SPACE(*p); p++) /* (skip blanks) */ ; if (*p == 0) return (-1); - *file = p; /* file name */ + *file = p; /* file name */ for (*file = p; *p && !IS_SPACE(*p); p++) ; if (*p == 0) @@ -780,5 +779,5 @@ getentry(buf, tag, file, line) return (0); return (-1); } - + #endif diff --git a/contrib/less/ttyin.c b/contrib/less/ttyin.c index 3bb99ecca6fb..5bd3385ceadb 100644 --- a/contrib/less/ttyin.c +++ b/contrib/less/ttyin.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -28,10 +28,35 @@ public HANDLE tty; #else public int tty; #endif +#if LESSTEST +public char *ttyin_name = NULL; +public int rstat_file = -1; +#endif /*LESSTEST*/ extern int sigs; extern int utf_mode; extern int wheel_lines; +/* + * Get name of tty device. + */ +#if !MSDOS_COMPILER + public char * +tty_device(VOID_PARAM) +{ + char *dev = NULL; +#if HAVE_TTYNAME + dev = ttyname(2); +#endif + if (dev == NULL) + dev = "/dev/tty"; +#if LESSTEST + if (ttyin_name != NULL) + dev = ttyin_name; +#endif /*LESSTEST*/ + return dev; +} +#endif /* MSDOS_COMPILER */ + /* * Open keyboard for input. */ @@ -76,9 +101,9 @@ open_getchr(VOID_PARAM) */ #if OS2 /* The __open() system call translates "/dev/tty" to "con". */ - tty = __open("/dev/tty", OPEN_READ); + tty = __open(tty_device(), OPEN_READ); #else - tty = open("/dev/tty", OPEN_READ); + tty = open(tty_device(), OPEN_READ); #endif if (tty < 0) tty = 2; @@ -131,6 +156,18 @@ default_wheel_lines(VOID_PARAM) return lines; } +#if LESSTEST + public void +rstat(st) + char st; +{ + if (rstat_file < 0) + return; + lseek(rstat_file, SEEK_SET, 0); + write(rstat_file, &st, 1); +} +#endif /*LESSTEST*/ + /* * Get a character from the keyboard. */ @@ -142,11 +179,11 @@ getchr(VOID_PARAM) do { + flush(); #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC /* * In raw read, we don't see ^C so look here for it. */ - flush(); #if MSDOS_COMPILER==WIN32C if (ABORT_SIGS()) return (READ_INTR); @@ -158,11 +195,17 @@ getchr(VOID_PARAM) if (c == '\003') return (READ_INTR); #else +#if LESSTEST + rstat('R'); +#endif /*LESSTEST*/ { unsigned char uc; result = iread(tty, &uc, sizeof(char)); c = (char) uc; } +#if LESSTEST + rstat('B'); +#endif /*LESSTEST*/ if (result == READ_INTR) return (READ_INTR); if (result < 0) diff --git a/contrib/less/version.c b/contrib/less/version.c index 73169ac44024..cb7d69ffcda7 100644 --- a/contrib/less/version.c +++ b/contrib/less/version.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2020 Mark Nudelman + * Copyright (C) 1984-2021 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -894,6 +894,31 @@ v560 5/3/20 Fix regression when command results in no movement; v561 5/11/20 Fix erroneous EOF calculation when F command is interrupted. v562 5/19/20 Update Unicode tables; minor doc formatting. v563 6/13/20 Fix crash due to realpath() incompatibility. +v564 8/25/20 Handle realpath consistently; update docs. +v565 11/3/20 Add ESC-U command, optimize calls to realpath(). +v566 11/25/20 Fix crash when reopening a file while using LESSOPEN; + support OSC 8 hyperlinks. +v567 11/25/20 Fix typo. +v568 11/29/20 Fix some hyperlink bugs; add ^W search modifier + (thanks to Arminius); allow Makefile.aut to use Python + instead of Perl (thanks to Charlie Lin). +v569 12/1/20 Allow multiple & filters (thanks to Mattias Johansson), + allow ^X to exit F command. +v570 12/12/20 Better handling of multiple + or -p options; + fix bugs in horizontal scrolling. +v571 12/30/20 Add --line-num-width and --status-col-width options. +v572 1/4/21 Save lastmark in history file; don't toggle mouse reporting; + implement termcap delays. +v573 1/9/21 Limit eof bell to 1 per second. +v574 1/13/21 Add incremental search. +v575 1/17/21 Fix build without HILITE_SEARCH; + fix bug with ^K in lesskey extra string. +v576 2/4/21 Make sure search result is visible; add --use-color and --color. +v577 2/9/21 Use ttyname to get name of tty device. +v578 2/9/21 Doc +v579 2/14/21 Fix double-width char bugs and non-match search crash. +v580 3/2/21 Some color fixes; fix compiler warnings; some lesstest support. +v581 4/6/21 Ignore SIGTSTP in secure mode; don't print "skipping" when filtering. */ -char version[] = "563"; +char version[] = "581"; diff --git a/usr.bin/less/defines.h b/usr.bin/less/defines.h index 9a58a043afc2..a3a44cd15875 100644 --- a/usr.bin/less/defines.h +++ b/usr.bin/less/defines.h @@ -1,4 +1,3 @@ -/* $FreeBSD$ */ /* defines.h. Generated from defines.h.in by configure. */ /* defines.h.in. Generated from configure.ac by autoheader. */ @@ -259,6 +258,9 @@ /* Define to 1 if you have the header file. */ #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 1 @@ -268,6 +270,9 @@ /* PCRE2 (Perl-compatible regular expression) library */ /* #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 HAVE_POPEN 1 @@ -361,12 +366,18 @@ /* Define HAVE_TIME_T if your system supports the "time_t" type. */ #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 header file. */ #define HAVE_UNISTD_H 1 /* Define HAVE_UPPER_LOWER if you have isupper, islower, toupper, tolower. */ #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 */ /* #undef HAVE_V8_REGCOMP */