mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Add less 643
This commit is contained in:
parent
0ed7309fdb
commit
128be2bd2e
61 changed files with 33791 additions and 2853 deletions
1
Makefile
1
Makefile
|
@ -226,6 +226,7 @@ include third_party/mbedtls/BUILD.mk # │
|
|||
include third_party/ncurses/BUILD.mk # │
|
||||
include third_party/libcxx/BUILD.mk # │
|
||||
include third_party/pcre/BUILD.mk # │
|
||||
include third_party/less/BUILD.mk # │
|
||||
include net/https/BUILD.mk # │
|
||||
include third_party/regex/BUILD.mk #─┘
|
||||
include third_party/tidy/BUILD.mk
|
||||
|
|
1
third_party/BUILD.mk
vendored
1
third_party/BUILD.mk
vendored
|
@ -14,6 +14,7 @@ o/$(MODE)/third_party: \
|
|||
o/$(MODE)/third_party/gdtoa \
|
||||
o/$(MODE)/third_party/getopt \
|
||||
o/$(MODE)/third_party/hiredis \
|
||||
o/$(MODE)/third_party/less \
|
||||
o/$(MODE)/third_party/libcxx \
|
||||
o/$(MODE)/third_party/linenoise \
|
||||
o/$(MODE)/third_party/lua \
|
||||
|
|
86
third_party/less/BUILD.mk
vendored
Normal file
86
third_party/less/BUILD.mk
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
#-*-mode:lessfile-gless;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=less ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
|
||||
PKGS += THIRD_PARTY_LESS
|
||||
|
||||
THIRD_PARTY_LESS_A = o/$(MODE)/third_party/less/less.a
|
||||
THIRD_PARTY_LESS_FILES := $(wildcard third_party/less/*)
|
||||
THIRD_PARTY_LESS_HDRS = $(filter %.h,$(THIRD_PARTY_LESS_FILES))
|
||||
THIRD_PARTY_LESS_INCS = $(filter %.inc,$(THIRD_PARTY_LESS_FILES))
|
||||
THIRD_PARTY_LESS_SRCS = $(filter %.c,$(THIRD_PARTY_LESS_FILES))
|
||||
THIRD_PARTY_LESS_OBJS = $(THIRD_PARTY_LESS_SRCS:%.c=o/$(MODE)/%.o)
|
||||
THIRD_PARTY_LESS_COMS = o/$(MODE)/third_party/less/less.com
|
||||
THIRD_PARTY_LESS_CHECKS = $(THIRD_PARTY_LESS_A).pkg
|
||||
|
||||
THIRD_PARTY_LESS_BINS = \
|
||||
$(THIRD_PARTY_LESS_COMS) \
|
||||
$(THIRD_PARTY_LESS_COMS:%=%.dbg)
|
||||
|
||||
THIRD_PARTY_LESS_DIRECTDEPS = \
|
||||
LIBC_CALLS \
|
||||
LIBC_FMT \
|
||||
LIBC_INTRIN \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_PROC \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_STDIO \
|
||||
LIBC_STR \
|
||||
LIBC_SYSV \
|
||||
THIRD_PARTY_NCURSES \
|
||||
THIRD_PARTY_PCRE
|
||||
|
||||
THIRD_PARTY_LESS_DEPS := \
|
||||
$(call uniq,$(foreach x,$(THIRD_PARTY_LESS_DIRECTDEPS),$($(x))))
|
||||
|
||||
$(THIRD_PARTY_LESS_A).pkg: \
|
||||
$(THIRD_PARTY_LESS_OBJS) \
|
||||
$(foreach x,$(THIRD_PARTY_LESS_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
$(THIRD_PARTY_LESS_A): \
|
||||
third_party/less/ \
|
||||
$(THIRD_PARTY_LESS_A).pkg \
|
||||
$(filter-out %main.o,$(THIRD_PARTY_LESS_OBJS))
|
||||
|
||||
o/$(MODE)/third_party/less/less.com.dbg: \
|
||||
$(THIRD_PARTY_LESS_DEPS) \
|
||||
$(THIRD_PARTY_LESS_A) \
|
||||
$(THIRD_PARTY_LESS_A).pkg \
|
||||
o/$(MODE)/third_party/less/main.o \
|
||||
$(CRT) \
|
||||
$(APE_NO_MODIFY_SELF)
|
||||
@$(APELINK)
|
||||
|
||||
o/$(MODE)/third_party/less/lesskey.com.dbg: \
|
||||
$(THIRD_PARTY_LESS_DEPS) \
|
||||
$(THIRD_PARTY_LESS_A) \
|
||||
$(THIRD_PARTY_LESS_A).pkg \
|
||||
o/$(MODE)/third_party/less/lesskey.o \
|
||||
$(CRT) \
|
||||
$(APE_NO_MODIFY_SELF)
|
||||
@$(APELINK)
|
||||
|
||||
o/$(MODE)/third_party/less/lessecho.com.dbg: \
|
||||
$(THIRD_PARTY_LESS_DEPS) \
|
||||
$(THIRD_PARTY_LESS_A) \
|
||||
$(THIRD_PARTY_LESS_A).pkg \
|
||||
o/$(MODE)/third_party/less/lessecho.o \
|
||||
$(CRT) \
|
||||
$(APE_NO_MODIFY_SELF)
|
||||
@$(APELINK)
|
||||
|
||||
o/$(MODE)/third_party/less/screen.o: private \
|
||||
CFLAGS += \
|
||||
-fportcosmo
|
||||
|
||||
$(THIRD_PARTY_LESS_OBJS): private \
|
||||
CPPFLAGS += \
|
||||
-DBINDIR=\"/opt/cosmos/bin\" \
|
||||
-DSYSDIR=\"/opt/cosmos/etc\"
|
||||
|
||||
$(THIRD_PARTY_LESS_OBJS): third_party/less/BUILD.mk
|
||||
|
||||
.PHONY: o/$(MODE)/third_party/less
|
||||
o/$(MODE)/third_party/less: \
|
||||
$(THIRD_PARTY_LESS_BINS) \
|
||||
$(THIRD_PARTY_LESS_CHECKS)
|
27
third_party/less/LICENSE
vendored
Normal file
27
third_party/less/LICENSE
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
Less License
|
||||
------------
|
||||
|
||||
Less
|
||||
Copyright (C) 1984-2023 Mark Nudelman
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice in the documentation and/or other materials provided with
|
||||
the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
15
third_party/less/README.cosmo
vendored
Normal file
15
third_party/less/README.cosmo
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
DESCRIPTION
|
||||
|
||||
less is a text paginator for the terminal
|
||||
|
||||
LICENSE
|
||||
|
||||
BSD-2 license
|
||||
|
||||
ORIGIN
|
||||
|
||||
https://ftp.gnu.org/gnu/less/less-643.tar.gz
|
||||
|
||||
LOCAL CHANGES
|
||||
|
||||
None.
|
99
third_party/less/brac.c
vendored
Normal file
99
third_party/less/brac.c
vendored
Normal file
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Routines to perform bracket matching functions.
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
#include "position.h"
|
||||
|
||||
/*
|
||||
* Try to match the n-th open bracket
|
||||
* which appears in the top displayed line (forwdir),
|
||||
* or the n-th close bracket
|
||||
* which appears in the bottom displayed line (!forwdir).
|
||||
* The characters which serve as "open bracket" and
|
||||
* "close bracket" are given.
|
||||
*/
|
||||
public void match_brac(char obrac, char cbrac, int forwdir, int n)
|
||||
{
|
||||
int c;
|
||||
int nest;
|
||||
POSITION pos;
|
||||
int (*chget)();
|
||||
|
||||
extern int ch_forw_get(), ch_back_get();
|
||||
|
||||
/*
|
||||
* Seek to the line containing the open bracket.
|
||||
* This is either the top or bottom line on the screen,
|
||||
* depending on the type of bracket.
|
||||
*/
|
||||
pos = position((forwdir) ? TOP : BOTTOM);
|
||||
if (pos == NULL_POSITION || ch_seek(pos))
|
||||
{
|
||||
if (forwdir)
|
||||
error("Nothing in top line", NULL_PARG);
|
||||
else
|
||||
error("Nothing in bottom line", NULL_PARG);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look thru the line to find the open bracket to match.
|
||||
*/
|
||||
do
|
||||
{
|
||||
if ((c = ch_forw_get()) == '\n' || c == EOI)
|
||||
{
|
||||
if (forwdir)
|
||||
error("No bracket in top line", NULL_PARG);
|
||||
else
|
||||
error("No bracket in bottom line", NULL_PARG);
|
||||
return;
|
||||
}
|
||||
} while (c != obrac || --n > 0);
|
||||
|
||||
/*
|
||||
* Position the file just "after" the open bracket
|
||||
* (in the direction in which we will be searching).
|
||||
* If searching forward, we are already after the bracket.
|
||||
* If searching backward, skip back over the open bracket.
|
||||
*/
|
||||
if (!forwdir)
|
||||
(void) ch_back_get();
|
||||
|
||||
/*
|
||||
* Search the file for the matching bracket.
|
||||
*/
|
||||
chget = (forwdir) ? ch_forw_get : ch_back_get;
|
||||
nest = 0;
|
||||
while ((c = (*chget)()) != EOI)
|
||||
{
|
||||
if (c == obrac)
|
||||
{
|
||||
if (nest == INT_MAX)
|
||||
break;
|
||||
nest++;
|
||||
}
|
||||
else if (c == cbrac && --nest < 0)
|
||||
{
|
||||
/*
|
||||
* Found the matching bracket.
|
||||
* If searching backward, put it on the top line.
|
||||
* If searching forward, put it on the bottom line.
|
||||
*/
|
||||
jump_line_loc(ch_tell(), forwdir ? -1 : 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
error("No matching bracket", NULL_PARG);
|
||||
}
|
939
third_party/less/ch.c
vendored
Normal file
939
third_party/less/ch.c
vendored
Normal file
|
@ -0,0 +1,939 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Low level character input from the input file.
|
||||
* We use these special purpose routines which optimize moving
|
||||
* both forward and backward from the current read pointer.
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
#include <errno.h>
|
||||
/* #include <windows.h> */
|
||||
#endif
|
||||
|
||||
#if HAVE_PROCFS
|
||||
#include <sys/statfs.h>
|
||||
#if HAVE_LINUX_MAGIC_H
|
||||
#include <linux/magic.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef POSITION BLOCKNUM;
|
||||
|
||||
public int ignore_eoi;
|
||||
|
||||
/*
|
||||
* Pool of buffers holding the most recently used blocks of the input file.
|
||||
* The buffer pool is kept as a doubly-linked circular list,
|
||||
* in order from most- to least-recently used.
|
||||
* The circular list is anchored by the file state "thisfile".
|
||||
*/
|
||||
struct bufnode {
|
||||
struct bufnode *next, *prev;
|
||||
struct bufnode *hnext, *hprev;
|
||||
};
|
||||
|
||||
#define LBUFSIZE 8192
|
||||
struct buf {
|
||||
struct bufnode node;
|
||||
BLOCKNUM block;
|
||||
unsigned int datasize;
|
||||
unsigned char data[LBUFSIZE];
|
||||
};
|
||||
#define bufnode_buf(bn) ((struct buf *) bn)
|
||||
|
||||
/*
|
||||
* The file state is maintained in a filestate structure.
|
||||
* A pointer to the filestate is kept in the ifile structure.
|
||||
*/
|
||||
#define BUFHASH_SIZE 1024
|
||||
struct filestate {
|
||||
struct bufnode buflist;
|
||||
struct bufnode hashtbl[BUFHASH_SIZE];
|
||||
int file;
|
||||
int flags;
|
||||
POSITION fpos;
|
||||
int nbufs;
|
||||
BLOCKNUM block;
|
||||
unsigned int offset;
|
||||
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 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) \
|
||||
for (bn = ch_bufhead; bn != END_OF_CHAIN; bn = bn->next)
|
||||
|
||||
#define BUF_RM(bn) \
|
||||
(bn)->next->prev = (bn)->prev; \
|
||||
(bn)->prev->next = (bn)->next;
|
||||
|
||||
#define BUF_INS_HEAD(bn) \
|
||||
(bn)->next = ch_bufhead; \
|
||||
(bn)->prev = END_OF_CHAIN; \
|
||||
ch_bufhead->prev = (bn); \
|
||||
ch_bufhead = (bn);
|
||||
|
||||
#define BUF_INS_TAIL(bn) \
|
||||
(bn)->next = END_OF_CHAIN; \
|
||||
(bn)->prev = ch_buftail; \
|
||||
ch_buftail->next = (bn); \
|
||||
ch_buftail = (bn);
|
||||
|
||||
/*
|
||||
* Macros to manipulate the list of buffers in thisfile->hashtbl[n].
|
||||
*/
|
||||
#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) \
|
||||
(bn)->hnext->hprev = (bn)->hprev; \
|
||||
(bn)->hprev->hnext = (bn)->hnext;
|
||||
|
||||
#define BUF_HASH_INS(bn,h) \
|
||||
(bn)->hnext = thisfile->hashtbl[h].hnext; \
|
||||
(bn)->hprev = END_OF_HCHAIN(h); \
|
||||
thisfile->hashtbl[h].hnext->hprev = (bn); \
|
||||
thisfile->hashtbl[h].hnext = (bn);
|
||||
|
||||
static struct filestate *thisfile;
|
||||
static int ch_ungotchar = -1;
|
||||
static int maxbufs = -1;
|
||||
|
||||
extern int autobuf;
|
||||
extern int sigs;
|
||||
extern int secure;
|
||||
extern int screen_trashed;
|
||||
extern int follow_mode;
|
||||
extern int waiting_for_data;
|
||||
extern constant char helpdata[];
|
||||
extern constant int size_helpdata;
|
||||
extern IFILE curr_ifile;
|
||||
#if LOGFILE
|
||||
extern int logfile;
|
||||
extern char *namelogfile;
|
||||
#endif
|
||||
|
||||
static int ch_addbuf();
|
||||
|
||||
|
||||
/*
|
||||
* Get the character pointed to by the read pointer.
|
||||
*/
|
||||
static int ch_get(void)
|
||||
{
|
||||
struct buf *bp;
|
||||
struct bufnode *bn;
|
||||
int n;
|
||||
int read_again;
|
||||
int h;
|
||||
POSITION pos;
|
||||
POSITION len;
|
||||
|
||||
if (thisfile == NULL)
|
||||
return (EOI);
|
||||
|
||||
/*
|
||||
* Quick check for the common case where
|
||||
* the desired char is in the head buffer.
|
||||
*/
|
||||
if (ch_bufhead != END_OF_CHAIN)
|
||||
{
|
||||
bp = bufnode_buf(ch_bufhead);
|
||||
if (ch_block == bp->block && ch_offset < bp->datasize)
|
||||
return bp->data[ch_offset];
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for a buffer holding the desired block.
|
||||
*/
|
||||
waiting_for_data = FALSE;
|
||||
h = BUFHASH(ch_block);
|
||||
FOR_BUFS_IN_CHAIN(h, bn)
|
||||
{
|
||||
bp = bufnode_buf(bn);
|
||||
if (bp->block == ch_block)
|
||||
{
|
||||
if (ch_offset >= bp->datasize)
|
||||
/*
|
||||
* Need more data in this buffer.
|
||||
*/
|
||||
break;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
if (bn == END_OF_HCHAIN(h))
|
||||
{
|
||||
/*
|
||||
* Block is not in a buffer.
|
||||
* Take the least recently used buffer
|
||||
* and read the desired block into it.
|
||||
* If the LRU buffer has data in it,
|
||||
* then maybe allocate a new buffer.
|
||||
*/
|
||||
if (ch_buftail == END_OF_CHAIN ||
|
||||
bufnode_buf(ch_buftail)->block != -1)
|
||||
{
|
||||
/*
|
||||
* There is no empty buffer to use.
|
||||
* Allocate a new buffer if:
|
||||
* 1. We can't seek on this file and -b is not in effect; or
|
||||
* 2. We haven't allocated the max buffers for this file yet.
|
||||
*/
|
||||
if ((autobuf && !(ch_flags & CH_CANSEEK)) ||
|
||||
(maxbufs < 0 || ch_nbufs < maxbufs))
|
||||
if (ch_addbuf())
|
||||
/*
|
||||
* Allocation failed: turn off autobuf.
|
||||
*/
|
||||
autobuf = OPT_OFF;
|
||||
}
|
||||
bn = ch_buftail;
|
||||
bp = bufnode_buf(bn);
|
||||
BUF_HASH_RM(bn); /* Remove from old hash chain. */
|
||||
bp->block = ch_block;
|
||||
bp->datasize = 0;
|
||||
BUF_HASH_INS(bn, h); /* Insert into new hash chain. */
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
pos = (ch_block * LBUFSIZE) + bp->datasize;
|
||||
if ((len = ch_length()) != NULL_POSITION && pos >= len)
|
||||
/*
|
||||
* At end of file.
|
||||
*/
|
||||
return (EOI);
|
||||
|
||||
if (pos != ch_fpos)
|
||||
{
|
||||
/*
|
||||
* Not at the correct position: must seek.
|
||||
* If input is a pipe, we're in trouble (can't seek on a pipe).
|
||||
* Some data has been lost: just return "?".
|
||||
*/
|
||||
if (!(ch_flags & CH_CANSEEK))
|
||||
return ('?');
|
||||
if (lseek(ch_file, (off_t)pos, SEEK_SET) == BAD_LSEEK)
|
||||
{
|
||||
error("seek error", NULL_PARG);
|
||||
clear_eol();
|
||||
return (EOI);
|
||||
}
|
||||
ch_fpos = pos;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the block.
|
||||
* If we read less than a full block, that's ok.
|
||||
* We use partial block and pick up the rest next time.
|
||||
*/
|
||||
if (ch_ungotchar != -1)
|
||||
{
|
||||
bp->data[bp->datasize] = ch_ungotchar;
|
||||
n = 1;
|
||||
ch_ungotchar = -1;
|
||||
} else if (ch_flags & CH_HELPFILE)
|
||||
{
|
||||
bp->data[bp->datasize] = helpdata[ch_fpos];
|
||||
n = 1;
|
||||
} else
|
||||
{
|
||||
n = iread(ch_file, &bp->data[bp->datasize],
|
||||
(unsigned int)(LBUFSIZE - bp->datasize));
|
||||
}
|
||||
|
||||
read_again = FALSE;
|
||||
if (n == READ_INTR)
|
||||
{
|
||||
ch_fsize = pos;
|
||||
return (EOI);
|
||||
}
|
||||
if (n == READ_AGAIN)
|
||||
{
|
||||
read_again = TRUE;
|
||||
n = 0;
|
||||
}
|
||||
if (n < 0)
|
||||
{
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
if (errno != EPIPE)
|
||||
#endif
|
||||
{
|
||||
error("read error", NULL_PARG);
|
||||
clear_eol();
|
||||
}
|
||||
n = 0;
|
||||
}
|
||||
|
||||
#if LOGFILE
|
||||
/*
|
||||
* If we have a log file, write the new data to it.
|
||||
*/
|
||||
if (!secure && logfile >= 0 && n > 0)
|
||||
write(logfile, (char *) &bp->data[bp->datasize], n);
|
||||
#endif
|
||||
|
||||
ch_fpos += n;
|
||||
bp->datasize += n;
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
/* Either end of file or no data available.
|
||||
* read_again indicates the latter. */
|
||||
if (!read_again)
|
||||
ch_fsize = pos;
|
||||
if (ignore_eoi || read_again)
|
||||
{
|
||||
/* Wait a while, then try again. */
|
||||
if (!waiting_for_data)
|
||||
{
|
||||
PARG parg;
|
||||
parg.p_string = wait_message();
|
||||
ixerror("%s", &parg);
|
||||
waiting_for_data = TRUE;
|
||||
}
|
||||
sleep_ms(50); /* Reduce system load */
|
||||
}
|
||||
if (ignore_eoi && follow_mode == FOLLOW_NAME && curr_ifile_changed())
|
||||
{
|
||||
/* screen_trashed=2 causes make_display to reopen the file. */
|
||||
screen_trashed = 2;
|
||||
return (EOI);
|
||||
}
|
||||
if (sigs)
|
||||
return (EOI);
|
||||
}
|
||||
|
||||
found:
|
||||
if (ch_bufhead != bn)
|
||||
{
|
||||
/*
|
||||
* Move the buffer to the head of the buffer chain.
|
||||
* This orders the buffer chain, most- to least-recently used.
|
||||
*/
|
||||
BUF_RM(bn);
|
||||
BUF_INS_HEAD(bn);
|
||||
|
||||
/*
|
||||
* Move to head of hash chain too.
|
||||
*/
|
||||
BUF_HASH_RM(bn);
|
||||
BUF_HASH_INS(bn, h);
|
||||
}
|
||||
|
||||
if (ch_offset < bp->datasize)
|
||||
break;
|
||||
/*
|
||||
* After all that, we still don't have enough data.
|
||||
* Go back and try again.
|
||||
*/
|
||||
}
|
||||
return (bp->data[ch_offset]);
|
||||
}
|
||||
|
||||
/*
|
||||
* ch_ungetchar is a rather kludgy and limited way to push
|
||||
* a single char onto an input file descriptor.
|
||||
*/
|
||||
public void ch_ungetchar(int c)
|
||||
{
|
||||
if (c != -1 && ch_ungotchar != -1)
|
||||
error("ch_ungetchar overrun", NULL_PARG);
|
||||
ch_ungotchar = c;
|
||||
}
|
||||
|
||||
#if LOGFILE
|
||||
/*
|
||||
* Close the logfile.
|
||||
* If we haven't read all of standard input into it, do that now.
|
||||
*/
|
||||
public void end_logfile(void)
|
||||
{
|
||||
static int tried = FALSE;
|
||||
|
||||
if (logfile < 0)
|
||||
return;
|
||||
if (!tried && ch_fsize == NULL_POSITION)
|
||||
{
|
||||
tried = TRUE;
|
||||
ierror("Finishing logfile", NULL_PARG);
|
||||
while (ch_forw_get() != EOI)
|
||||
if (ABORT_SIGS())
|
||||
break;
|
||||
}
|
||||
close(logfile);
|
||||
logfile = -1;
|
||||
free(namelogfile);
|
||||
namelogfile = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start a log file AFTER less has already been running.
|
||||
* Invoked from the - command; see toggle_option().
|
||||
* Write all the existing buffered data to the log file.
|
||||
*/
|
||||
public void sync_logfile(void)
|
||||
{
|
||||
struct buf *bp;
|
||||
struct bufnode *bn;
|
||||
int warned = FALSE;
|
||||
BLOCKNUM block;
|
||||
BLOCKNUM nblocks;
|
||||
|
||||
if (logfile < 0)
|
||||
return;
|
||||
nblocks = (ch_fpos + LBUFSIZE - 1) / LBUFSIZE;
|
||||
for (block = 0; block < nblocks; block++)
|
||||
{
|
||||
int wrote = FALSE;
|
||||
FOR_BUFS(bn)
|
||||
{
|
||||
bp = bufnode_buf(bn);
|
||||
if (bp->block == block)
|
||||
{
|
||||
write(logfile, (char *) bp->data, bp->datasize);
|
||||
wrote = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!wrote && !warned)
|
||||
{
|
||||
error("Warning: log file is incomplete",
|
||||
NULL_PARG);
|
||||
warned = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Determine if a specific block is currently in one of the buffers.
|
||||
*/
|
||||
static int buffered(BLOCKNUM block)
|
||||
{
|
||||
struct buf *bp;
|
||||
struct bufnode *bn;
|
||||
int h;
|
||||
|
||||
h = BUFHASH(block);
|
||||
FOR_BUFS_IN_CHAIN(h, bn)
|
||||
{
|
||||
bp = bufnode_buf(bn);
|
||||
if (bp->block == block)
|
||||
return (TRUE);
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Seek to a specified position in the file.
|
||||
* Return 0 if successful, non-zero if can't seek there.
|
||||
*/
|
||||
public int ch_seek(POSITION pos)
|
||||
{
|
||||
BLOCKNUM new_block;
|
||||
POSITION len;
|
||||
|
||||
if (thisfile == NULL)
|
||||
return (0);
|
||||
|
||||
len = ch_length();
|
||||
if (pos < ch_zero() || (len != NULL_POSITION && pos > len))
|
||||
return (1);
|
||||
|
||||
new_block = pos / LBUFSIZE;
|
||||
if (!(ch_flags & CH_CANSEEK) && pos != ch_fpos && !buffered(new_block))
|
||||
{
|
||||
if (ch_fpos > pos)
|
||||
return (1);
|
||||
while (ch_fpos < pos)
|
||||
{
|
||||
if (ch_forw_get() == EOI)
|
||||
return (1);
|
||||
if (ABORT_SIGS())
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
/*
|
||||
* Set read pointer.
|
||||
*/
|
||||
ch_block = new_block;
|
||||
ch_offset = pos % LBUFSIZE;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Seek to the end of the file.
|
||||
*/
|
||||
public int ch_end_seek(void)
|
||||
{
|
||||
POSITION len;
|
||||
|
||||
if (thisfile == NULL)
|
||||
return (0);
|
||||
|
||||
if (ch_flags & CH_CANSEEK)
|
||||
ch_fsize = filesize(ch_file);
|
||||
|
||||
len = ch_length();
|
||||
if (len != NULL_POSITION)
|
||||
return (ch_seek(len));
|
||||
|
||||
/*
|
||||
* Do it the slow way: read till end of data.
|
||||
*/
|
||||
while (ch_forw_get() != EOI)
|
||||
if (ABORT_SIGS())
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Seek to the last position in the file that is currently buffered.
|
||||
*/
|
||||
public int ch_end_buffer_seek(void)
|
||||
{
|
||||
struct buf *bp;
|
||||
struct bufnode *bn;
|
||||
POSITION buf_pos;
|
||||
POSITION end_pos;
|
||||
|
||||
if (thisfile == NULL || (ch_flags & CH_CANSEEK))
|
||||
return (ch_end_seek());
|
||||
|
||||
end_pos = 0;
|
||||
FOR_BUFS(bn)
|
||||
{
|
||||
bp = bufnode_buf(bn);
|
||||
buf_pos = (bp->block * LBUFSIZE) + bp->datasize;
|
||||
if (buf_pos > end_pos)
|
||||
end_pos = buf_pos;
|
||||
}
|
||||
|
||||
return (ch_seek(end_pos));
|
||||
}
|
||||
|
||||
/*
|
||||
* Seek to the beginning of the file, or as close to it as we can get.
|
||||
* We may not be able to seek there if input is a pipe and the
|
||||
* beginning of the pipe is no longer buffered.
|
||||
*/
|
||||
public int ch_beg_seek(void)
|
||||
{
|
||||
struct bufnode *bn;
|
||||
struct bufnode *firstbn;
|
||||
|
||||
/*
|
||||
* Try a plain ch_seek first.
|
||||
*/
|
||||
if (ch_seek(ch_zero()) == 0)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* Can't get to position 0.
|
||||
* Look thru the buffers for the one closest to position 0.
|
||||
*/
|
||||
firstbn = ch_bufhead;
|
||||
if (firstbn == END_OF_CHAIN)
|
||||
return (1);
|
||||
FOR_BUFS(bn)
|
||||
{
|
||||
if (bufnode_buf(bn)->block < bufnode_buf(firstbn)->block)
|
||||
firstbn = bn;
|
||||
}
|
||||
ch_block = bufnode_buf(firstbn)->block;
|
||||
ch_offset = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the length of the file, if known.
|
||||
*/
|
||||
public POSITION ch_length(void)
|
||||
{
|
||||
if (thisfile == NULL)
|
||||
return (NULL_POSITION);
|
||||
if (ignore_eoi)
|
||||
return (NULL_POSITION);
|
||||
if (ch_flags & CH_HELPFILE)
|
||||
return (size_helpdata);
|
||||
if (ch_flags & CH_NODATA)
|
||||
return (0);
|
||||
return (ch_fsize);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the current position in the file.
|
||||
*/
|
||||
public POSITION ch_tell(void)
|
||||
{
|
||||
if (thisfile == NULL)
|
||||
return (NULL_POSITION);
|
||||
return (ch_block * LBUFSIZE) + ch_offset;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current char and post-increment the read pointer.
|
||||
*/
|
||||
public int ch_forw_get(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (thisfile == NULL)
|
||||
return (EOI);
|
||||
c = ch_get();
|
||||
if (c == EOI)
|
||||
return (EOI);
|
||||
if (ch_offset < LBUFSIZE-1)
|
||||
ch_offset++;
|
||||
else
|
||||
{
|
||||
ch_block ++;
|
||||
ch_offset = 0;
|
||||
}
|
||||
return (c);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pre-decrement the read pointer and get the new current char.
|
||||
*/
|
||||
public int ch_back_get(void)
|
||||
{
|
||||
if (thisfile == NULL)
|
||||
return (EOI);
|
||||
if (ch_offset > 0)
|
||||
ch_offset --;
|
||||
else
|
||||
{
|
||||
if (ch_block <= 0)
|
||||
return (EOI);
|
||||
if (!(ch_flags & CH_CANSEEK) && !buffered(ch_block-1))
|
||||
return (EOI);
|
||||
ch_block--;
|
||||
ch_offset = LBUFSIZE-1;
|
||||
}
|
||||
return (ch_get());
|
||||
}
|
||||
|
||||
/*
|
||||
* Set max amount of buffer space.
|
||||
* bufspace is in units of 1024 bytes. -1 mean no limit.
|
||||
*/
|
||||
public void ch_setbufspace(int bufspace)
|
||||
{
|
||||
if (bufspace < 0)
|
||||
maxbufs = -1;
|
||||
else
|
||||
{
|
||||
int lbufk = LBUFSIZE / 1024;
|
||||
maxbufs = bufspace / lbufk + (bufspace % lbufk != 0);
|
||||
if (maxbufs < 1)
|
||||
maxbufs = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush (discard) any saved file state, including buffer contents.
|
||||
*/
|
||||
public void ch_flush(void)
|
||||
{
|
||||
struct bufnode *bn;
|
||||
|
||||
if (thisfile == NULL)
|
||||
return;
|
||||
|
||||
if (!(ch_flags & CH_CANSEEK))
|
||||
{
|
||||
/*
|
||||
* If input is a pipe, we don't flush buffer contents,
|
||||
* since the contents can't be recovered.
|
||||
*/
|
||||
ch_fsize = NULL_POSITION;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize all the buffers.
|
||||
*/
|
||||
FOR_BUFS(bn)
|
||||
{
|
||||
bufnode_buf(bn)->block = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Figure out the size of the file, if we can.
|
||||
*/
|
||||
ch_fsize = filesize(ch_file);
|
||||
|
||||
/*
|
||||
* Seek to a known position: the beginning of the file.
|
||||
*/
|
||||
ch_fpos = 0;
|
||||
ch_block = 0; /* ch_fpos / LBUFSIZE; */
|
||||
ch_offset = 0; /* ch_fpos % LBUFSIZE; */
|
||||
|
||||
#if HAVE_PROCFS
|
||||
/*
|
||||
* This is a kludge to workaround a Linux kernel bug: files in
|
||||
* /proc have a size of 0 according to fstat() but have readable
|
||||
* data. They are sometimes, but not always, seekable.
|
||||
* Force them to be non-seekable here.
|
||||
*/
|
||||
if (ch_fsize == 0)
|
||||
{
|
||||
struct statfs st;
|
||||
if (fstatfs(ch_file, &st) == 0)
|
||||
{
|
||||
if (st.f_type == PROC_SUPER_MAGIC)
|
||||
{
|
||||
ch_fsize = NULL_POSITION;
|
||||
ch_flags &= ~CH_CANSEEK;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (lseek(ch_file, (off_t)0, SEEK_SET) == BAD_LSEEK)
|
||||
{
|
||||
/*
|
||||
* Warning only; even if the seek fails for some reason,
|
||||
* there's a good chance we're at the beginning anyway.
|
||||
* {{ I think this is bogus reasoning. }}
|
||||
*/
|
||||
error("seek error to 0", NULL_PARG);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a new buffer.
|
||||
* The buffer is added to the tail of the buffer chain.
|
||||
*/
|
||||
static int ch_addbuf(void)
|
||||
{
|
||||
struct buf *bp;
|
||||
struct bufnode *bn;
|
||||
|
||||
/*
|
||||
* Allocate and initialize a new buffer and link it
|
||||
* onto the tail of the buffer list.
|
||||
*/
|
||||
bp = (struct buf *) calloc(1, sizeof(struct buf));
|
||||
if (bp == NULL)
|
||||
return (1);
|
||||
ch_nbufs++;
|
||||
bp->block = -1;
|
||||
bn = &bp->node;
|
||||
|
||||
BUF_INS_TAIL(bn);
|
||||
BUF_HASH_INS(bn, 0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static void init_hashtbl(void)
|
||||
{
|
||||
int h;
|
||||
|
||||
for (h = 0; h < BUFHASH_SIZE; h++)
|
||||
{
|
||||
thisfile->hashtbl[h].hnext = END_OF_HCHAIN(h);
|
||||
thisfile->hashtbl[h].hprev = END_OF_HCHAIN(h);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete all buffers for this file.
|
||||
*/
|
||||
static void ch_delbufs(void)
|
||||
{
|
||||
struct bufnode *bn;
|
||||
|
||||
while (ch_bufhead != END_OF_CHAIN)
|
||||
{
|
||||
bn = ch_bufhead;
|
||||
BUF_RM(bn);
|
||||
free(bufnode_buf(bn));
|
||||
}
|
||||
ch_nbufs = 0;
|
||||
init_hashtbl();
|
||||
}
|
||||
|
||||
/*
|
||||
* Is it possible to seek on a file descriptor?
|
||||
*/
|
||||
public int seekable(int f)
|
||||
{
|
||||
#if MSDOS_COMPILER
|
||||
extern int fd0;
|
||||
if (f == fd0 && !isatty(fd0))
|
||||
{
|
||||
/*
|
||||
* In MS-DOS, pipes are seekable. Check for
|
||||
* standard input, and pretend it is not seekable.
|
||||
*/
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
return (lseek(f, (off_t)1, SEEK_SET) != BAD_LSEEK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Force EOF to be at the current read position.
|
||||
* This is used after an ignore_eof read, during which the EOF may change.
|
||||
*/
|
||||
public void ch_set_eof(void)
|
||||
{
|
||||
if (ch_fsize != NULL_POSITION && ch_fsize < ch_fpos)
|
||||
ch_fsize = ch_fpos;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize file state for a new file.
|
||||
*/
|
||||
public void ch_init(int f, int flags)
|
||||
{
|
||||
/*
|
||||
* See if we already have a filestate for this file.
|
||||
*/
|
||||
thisfile = (struct filestate *) get_filestate(curr_ifile);
|
||||
if (thisfile == NULL)
|
||||
{
|
||||
/*
|
||||
* Allocate and initialize a new filestate.
|
||||
*/
|
||||
thisfile = (struct filestate *)
|
||||
ecalloc(1, sizeof(struct filestate));
|
||||
thisfile->buflist.next = thisfile->buflist.prev = END_OF_CHAIN;
|
||||
thisfile->nbufs = 0;
|
||||
thisfile->flags = flags;
|
||||
thisfile->fpos = 0;
|
||||
thisfile->block = 0;
|
||||
thisfile->offset = 0;
|
||||
thisfile->file = -1;
|
||||
thisfile->fsize = NULL_POSITION;
|
||||
init_hashtbl();
|
||||
/*
|
||||
* Try to seek; set CH_CANSEEK if it works.
|
||||
*/
|
||||
if ((flags & CH_CANSEEK) && !seekable(f))
|
||||
ch_flags &= ~CH_CANSEEK;
|
||||
set_filestate(curr_ifile, (void *) thisfile);
|
||||
}
|
||||
if (thisfile->file == -1)
|
||||
thisfile->file = f;
|
||||
ch_flush();
|
||||
}
|
||||
|
||||
/*
|
||||
* Close a filestate.
|
||||
*/
|
||||
public void ch_close(void)
|
||||
{
|
||||
int keepstate = FALSE;
|
||||
|
||||
if (thisfile == NULL)
|
||||
return;
|
||||
|
||||
if ((ch_flags & (CH_CANSEEK|CH_POPENED|CH_HELPFILE)) && !(ch_flags & CH_KEEPOPEN))
|
||||
{
|
||||
/*
|
||||
* We can seek or re-open, so we don't need to keep buffers.
|
||||
*/
|
||||
ch_delbufs();
|
||||
} else
|
||||
keepstate = TRUE;
|
||||
if (!(ch_flags & CH_KEEPOPEN))
|
||||
{
|
||||
/*
|
||||
* We don't need to keep the file descriptor open
|
||||
* (because we can re-open it.)
|
||||
* But don't really close it if it was opened via popen(),
|
||||
* because pclose() wants to close it.
|
||||
*/
|
||||
if (!(ch_flags & (CH_POPENED|CH_HELPFILE)))
|
||||
close(ch_file);
|
||||
ch_file = -1;
|
||||
} else
|
||||
keepstate = TRUE;
|
||||
if (!keepstate)
|
||||
{
|
||||
/*
|
||||
* We don't even need to keep the filestate structure.
|
||||
*/
|
||||
free(thisfile);
|
||||
thisfile = NULL;
|
||||
set_filestate(curr_ifile, (void *) NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return ch_flags for the current file.
|
||||
*/
|
||||
public int ch_getflags(void)
|
||||
{
|
||||
if (thisfile == NULL)
|
||||
return (0);
|
||||
return (ch_flags);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void ch_dump(struct filestate *fs)
|
||||
{
|
||||
struct buf *bp;
|
||||
struct bufnode *bn;
|
||||
unsigned char *s;
|
||||
|
||||
if (fs == NULL)
|
||||
{
|
||||
printf(" --no filestate\n");
|
||||
return;
|
||||
}
|
||||
printf(" file %d, flags %x, fpos %x, fsize %x, blk/off %x/%x\n",
|
||||
fs->file, fs->flags, fs->fpos,
|
||||
fs->fsize, fs->block, fs->offset);
|
||||
printf(" %d bufs:\n", fs->nbufs);
|
||||
for (bn = fs->next; bn != &fs->buflist; bn = bn->next)
|
||||
{
|
||||
bp = bufnode_buf(bn);
|
||||
printf("%x: blk %x, size %x \"",
|
||||
bp, bp->block, bp->datasize);
|
||||
for (s = bp->data; s < bp->data + 30; s++)
|
||||
if (*s >= ' ' && *s < 0x7F)
|
||||
printf("%c", *s);
|
||||
else
|
||||
printf(".");
|
||||
printf("\"\n");
|
||||
}
|
||||
}
|
||||
#endif
|
905
third_party/less/charset.c
vendored
Normal file
905
third_party/less/charset.c
vendored
Normal file
|
@ -0,0 +1,905 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Functions to define the character set
|
||||
* and do things specific to the character set.
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
#if HAVE_LOCALE
|
||||
#include <locale.h>
|
||||
#include <ctype.h>
|
||||
#include <langinfo.h>
|
||||
#endif
|
||||
|
||||
#include "charset.h"
|
||||
#include "xbuf.h"
|
||||
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
/* #include <windows.h> */
|
||||
#endif
|
||||
|
||||
extern int bs_mode;
|
||||
|
||||
public int utf_mode = 0;
|
||||
|
||||
/*
|
||||
* Predefined character sets,
|
||||
* selected by the LESSCHARSET environment variable.
|
||||
*/
|
||||
struct charset {
|
||||
char *name;
|
||||
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 }
|
||||
};
|
||||
|
||||
/*
|
||||
* Support "locale charmap"/nl_langinfo(CODESET) values, as well as others.
|
||||
*/
|
||||
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" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
#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|AT_COLOR_BIN;
|
||||
|
||||
static struct xbuffer user_wide_array;
|
||||
static struct xbuffer user_ubin_array;
|
||||
static struct xbuffer user_compose_array;
|
||||
static struct xbuffer user_prt_array;
|
||||
static struct wchar_range_table user_wide_table;
|
||||
static struct wchar_range_table user_ubin_table;
|
||||
static struct wchar_range_table user_compose_table;
|
||||
static struct wchar_range_table user_prt_table;
|
||||
|
||||
/*
|
||||
* Set a wchar_range_table to the table in an xbuffer.
|
||||
*/
|
||||
static void wchar_range_table_set(struct wchar_range_table *tbl, struct xbuffer *arr)
|
||||
{
|
||||
tbl->table = (struct wchar_range *) arr->data;
|
||||
tbl->count = arr->end / sizeof(struct wchar_range);
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip over a "U" or "U+" prefix before a hex codepoint.
|
||||
*/
|
||||
static char * skip_uprefix(char *s)
|
||||
{
|
||||
if (*s == 'U' || *s == 'u')
|
||||
if (*++s == '+') ++s;
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a dash-separated range of hex values.
|
||||
*/
|
||||
static void wchar_range_get(char **ss, struct wchar_range *range)
|
||||
{
|
||||
char *s = skip_uprefix(*ss);
|
||||
range->first = lstrtoul(s, &s, 16);
|
||||
if (s[0] == '-')
|
||||
{
|
||||
s = skip_uprefix(&s[1]);
|
||||
range->last = lstrtoul(s, &s, 16);
|
||||
} else
|
||||
{
|
||||
range->last = range->first;
|
||||
}
|
||||
*ss = s;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the LESSUTFCHARDEF variable.
|
||||
*/
|
||||
static void ichardef_utf(char *s)
|
||||
{
|
||||
xbuf_init(&user_wide_array);
|
||||
xbuf_init(&user_ubin_array);
|
||||
xbuf_init(&user_compose_array);
|
||||
xbuf_init(&user_prt_array);
|
||||
|
||||
if (s != NULL)
|
||||
{
|
||||
while (s[0] != '\0')
|
||||
{
|
||||
struct wchar_range range;
|
||||
wchar_range_get(&s, &range);
|
||||
if (range.last == 0)
|
||||
{
|
||||
error("invalid hex number(s) in LESSUTFCHARDEF", NULL_PARG);
|
||||
quit(QUIT_ERROR);
|
||||
}
|
||||
if (*s++ != ':')
|
||||
{
|
||||
error("missing colon in LESSUTFCHARDEF", NULL_PARG);
|
||||
quit(QUIT_ERROR);
|
||||
}
|
||||
switch (*s++)
|
||||
{
|
||||
case 'b':
|
||||
xbuf_add_data(&user_ubin_array, (unsigned char *) &range, sizeof(range));
|
||||
break;
|
||||
case 'c':
|
||||
xbuf_add_data(&user_compose_array, (unsigned char *) &range, sizeof(range));
|
||||
break;
|
||||
case 'w':
|
||||
xbuf_add_data(&user_wide_array, (unsigned char *) &range, sizeof(range));
|
||||
xbuf_add_data(&user_prt_array, (unsigned char *) &range, sizeof(range));
|
||||
break;
|
||||
case 'p': case '.':
|
||||
xbuf_add_data(&user_prt_array, (unsigned char *) &range, sizeof(range));
|
||||
break;
|
||||
case '\0':
|
||||
s--;
|
||||
break;
|
||||
default:
|
||||
/* Ignore unknown character attribute. */
|
||||
break;
|
||||
}
|
||||
if (s[0] == ',') ++s;
|
||||
}
|
||||
}
|
||||
wchar_range_table_set(&user_wide_table, &user_wide_array);
|
||||
wchar_range_table_set(&user_ubin_table, &user_ubin_array);
|
||||
wchar_range_table_set(&user_compose_table, &user_compose_array);
|
||||
wchar_range_table_set(&user_prt_table, &user_prt_array);
|
||||
}
|
||||
|
||||
/*
|
||||
* Define a charset, given a description string.
|
||||
* The string consists of 256 letters,
|
||||
* one for each character in the charset.
|
||||
* If the string is shorter than 256 letters, missing letters
|
||||
* are taken to be identical to the last one.
|
||||
* A decimal number followed by a letter is taken to be a
|
||||
* repetition of the letter.
|
||||
*
|
||||
* Each letter is one of:
|
||||
* . normal character
|
||||
* b binary character
|
||||
* c control character
|
||||
*/
|
||||
static void ichardef(char *s)
|
||||
{
|
||||
char *cp;
|
||||
int n;
|
||||
char v;
|
||||
|
||||
n = 0;
|
||||
v = 0;
|
||||
cp = chardef;
|
||||
while (*s != '\0')
|
||||
{
|
||||
switch (*s++)
|
||||
{
|
||||
case '.':
|
||||
v = 0;
|
||||
break;
|
||||
case 'c':
|
||||
v = IS_CONTROL_CHAR;
|
||||
break;
|
||||
case 'b':
|
||||
v = IS_BINARY_CHAR|IS_CONTROL_CHAR;
|
||||
break;
|
||||
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
if (ckd_mul(&n, n, 10) || ckd_add(&n, n, s[-1] - '0'))
|
||||
goto invalid_chardef;
|
||||
continue;
|
||||
|
||||
default:
|
||||
invalid_chardef:
|
||||
error("invalid chardef", NULL_PARG);
|
||||
quit(QUIT_ERROR);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (cp >= chardef + sizeof(chardef))
|
||||
{
|
||||
error("chardef longer than 256", NULL_PARG);
|
||||
quit(QUIT_ERROR);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
*cp++ = v;
|
||||
} while (--n > 0);
|
||||
n = 0;
|
||||
}
|
||||
|
||||
while (cp < chardef + sizeof(chardef))
|
||||
*cp++ = v;
|
||||
}
|
||||
|
||||
/*
|
||||
* Define a charset, given a charset name.
|
||||
* The valid charset names are listed in the "charsets" array.
|
||||
*/
|
||||
static int icharset(char *name, int no_error)
|
||||
{
|
||||
struct charset *p;
|
||||
struct cs_alias *a;
|
||||
|
||||
if (name == NULL || *name == '\0')
|
||||
return (0);
|
||||
|
||||
/* First see if the name is an alias. */
|
||||
for (a = cs_aliases; a->name != NULL; a++)
|
||||
{
|
||||
if (strcmp(name, a->name) == 0)
|
||||
{
|
||||
name = a->oname;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (p = charsets; p->name != NULL; p++)
|
||||
{
|
||||
if (strcmp(name, p->name) == 0)
|
||||
{
|
||||
ichardef(p->desc);
|
||||
if (p->p_flag != NULL)
|
||||
{
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
*(p->p_flag) = 1 + (GetConsoleOutputCP() != CP_UTF8);
|
||||
#else
|
||||
*(p->p_flag) = 1;
|
||||
#endif
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!no_error) {
|
||||
error("invalid charset name", NULL_PARG);
|
||||
quit(QUIT_ERROR);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if HAVE_LOCALE
|
||||
/*
|
||||
* Define a charset, given a locale name.
|
||||
*/
|
||||
static void ilocale(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
for (c = 0; c < (int) sizeof(chardef); c++)
|
||||
{
|
||||
if (isprint(c))
|
||||
chardef[c] = 0;
|
||||
else if (iscntrl(c))
|
||||
chardef[c] = IS_CONTROL_CHAR;
|
||||
else
|
||||
chardef[c] = IS_BINARY_CHAR|IS_CONTROL_CHAR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define the printing format for control (or binary utf) chars.
|
||||
*/
|
||||
public void setfmt(char *s, char **fmtvarptr, int *attrptr, char *default_fmt, int for_printf)
|
||||
{
|
||||
if (s && utf_mode)
|
||||
{
|
||||
/* It would be too hard to account for width otherwise. */
|
||||
char constant *t = s;
|
||||
while (*t)
|
||||
{
|
||||
if (*t < ' ' || *t > '~')
|
||||
{
|
||||
s = default_fmt;
|
||||
goto attr;
|
||||
}
|
||||
t++;
|
||||
}
|
||||
}
|
||||
|
||||
if (s == NULL || *s == '\0')
|
||||
s = default_fmt;
|
||||
else if (for_printf &&
|
||||
((*s == '*' && (s[1] == '\0' || s[2] == '\0' || strchr(s + 2, 'n'))) ||
|
||||
(*s != '*' && strchr(s, 'n'))))
|
||||
/* %n is evil */
|
||||
s = default_fmt;
|
||||
|
||||
/*
|
||||
* Select the attributes if it starts with "*".
|
||||
*/
|
||||
attr:
|
||||
if (*s == '*' && s[1] != '\0')
|
||||
{
|
||||
switch (s[1])
|
||||
{
|
||||
case 'd': *attrptr = AT_BOLD; break;
|
||||
case 'k': *attrptr = AT_BLINK; break;
|
||||
case 's': *attrptr = AT_STANDOUT; break;
|
||||
case 'u': *attrptr = AT_UNDERLINE; break;
|
||||
default: *attrptr = AT_NORMAL; break;
|
||||
}
|
||||
s += 2;
|
||||
}
|
||||
*fmtvarptr = s;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static void set_charset(void)
|
||||
{
|
||||
char *s;
|
||||
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
/*
|
||||
* If the Windows console is using UTF-8, we'll use it too.
|
||||
*/
|
||||
if (GetConsoleOutputCP() == CP_UTF8)
|
||||
if (icharset("utf-8", 1))
|
||||
return;
|
||||
#endif
|
||||
|
||||
ichardef_utf(lgetenv("LESSUTFCHARDEF"));
|
||||
|
||||
/*
|
||||
* See if environment variable LESSCHARSET is defined.
|
||||
*/
|
||||
s = lgetenv("LESSCHARSET");
|
||||
if (icharset(s, 0))
|
||||
return;
|
||||
|
||||
/*
|
||||
* LESSCHARSET is not defined: try LESSCHARDEF.
|
||||
*/
|
||||
s = lgetenv("LESSCHARDEF");
|
||||
if (!isnullenv(s))
|
||||
{
|
||||
ichardef(s);
|
||||
return;
|
||||
}
|
||||
|
||||
#if HAVE_LOCALE
|
||||
#ifdef CODESET
|
||||
/*
|
||||
* Try using the codeset name as the charset name.
|
||||
*/
|
||||
s = nl_langinfo(CODESET);
|
||||
if (icharset(s, 1))
|
||||
return;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAVE_STRSTR
|
||||
/*
|
||||
* Check whether LC_ALL, LC_CTYPE or LANG look like UTF-8 is used.
|
||||
*/
|
||||
if ((s = lgetenv("LC_ALL")) != NULL ||
|
||||
(s = lgetenv("LC_CTYPE")) != NULL ||
|
||||
(s = lgetenv("LANG")) != NULL)
|
||||
{
|
||||
if ( strstr(s, "UTF-8") != NULL || strstr(s, "utf-8") != NULL
|
||||
|| strstr(s, "UTF8") != NULL || strstr(s, "utf8") != NULL)
|
||||
if (icharset("utf-8", 1))
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_LOCALE
|
||||
/*
|
||||
* Get character definitions from locale functions,
|
||||
* rather than from predefined charset entry.
|
||||
*/
|
||||
ilocale();
|
||||
#else
|
||||
#if MSDOS_COMPILER
|
||||
/*
|
||||
* Default to "dos".
|
||||
*/
|
||||
(void) icharset("dos", 1);
|
||||
#else
|
||||
/*
|
||||
* Default to "latin1".
|
||||
*/
|
||||
(void) icharset("latin1", 1);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize charset data structures.
|
||||
*/
|
||||
public void init_charset(void)
|
||||
{
|
||||
char *s;
|
||||
|
||||
#if HAVE_LOCALE
|
||||
setlocale(LC_ALL, "");
|
||||
#endif
|
||||
|
||||
set_charset();
|
||||
|
||||
s = lgetenv("LESSBINFMT");
|
||||
setfmt(s, &binfmt, &binattr, "*s<%02X>", TRUE);
|
||||
|
||||
s = lgetenv("LESSUTFBINFMT");
|
||||
setfmt(s, &utfbinfmt, &binattr, "<U+%04lX>", TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Is a given character a "binary" character?
|
||||
*/
|
||||
public int binary_char(LWCHAR c)
|
||||
{
|
||||
if (utf_mode)
|
||||
return (is_ubin_char(c));
|
||||
c &= 0377;
|
||||
return (chardef[c] & IS_BINARY_CHAR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Is a given character a "control" character?
|
||||
*/
|
||||
public int control_char(LWCHAR c)
|
||||
{
|
||||
c &= 0377;
|
||||
return (chardef[c] & IS_CONTROL_CHAR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the printable form of a character.
|
||||
* For example, in the "ascii" charset '\3' is printed as "^C".
|
||||
*/
|
||||
public char * prchar(LWCHAR c)
|
||||
{
|
||||
/* {{ This buffer can be overrun if LESSBINFMT is a long string. }} */
|
||||
static char buf[MAX_PRCHAR_LEN+1];
|
||||
|
||||
c &= 0377;
|
||||
if ((c < 128 || !utf_mode) && !control_char(c))
|
||||
SNPRINTF1(buf, sizeof(buf), "%c", (int) c);
|
||||
else if (c == ESC)
|
||||
strcpy(buf, "ESC");
|
||||
#if IS_EBCDIC_HOST
|
||||
else if (!binary_char(c) && c < 64)
|
||||
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.
|
||||
*/
|
||||
"@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));
|
||||
#endif
|
||||
else
|
||||
SNPRINTF1(buf, sizeof(buf), binfmt, c);
|
||||
return (buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the printable form of a UTF-8 character.
|
||||
*/
|
||||
public char * prutfchar(LWCHAR ch)
|
||||
{
|
||||
static char buf[MAX_PRCHAR_LEN+1];
|
||||
|
||||
if (ch == ESC)
|
||||
strcpy(buf, "ESC");
|
||||
else if (ch < 128 && control_char(ch))
|
||||
{
|
||||
if (!control_char(ch ^ 0100))
|
||||
SNPRINTF1(buf, sizeof(buf), "^%c", ((char) ch) ^ 0100);
|
||||
else
|
||||
SNPRINTF1(buf, sizeof(buf), binfmt, (char) ch);
|
||||
} else if (is_ubin_char(ch))
|
||||
{
|
||||
SNPRINTF1(buf, sizeof(buf), utfbinfmt, ch);
|
||||
} else
|
||||
{
|
||||
char *p = buf;
|
||||
if (ch >= 0x80000000)
|
||||
ch = 0xFFFD; /* REPLACEMENT CHARACTER */
|
||||
put_wchar(&p, ch);
|
||||
*p = '\0';
|
||||
}
|
||||
return (buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the length of a UTF-8 character in bytes.
|
||||
*/
|
||||
public int utf_len(int ch)
|
||||
{
|
||||
if ((ch & 0x80) == 0)
|
||||
return 1;
|
||||
if ((ch & 0xE0) == 0xC0)
|
||||
return 2;
|
||||
if ((ch & 0xF0) == 0xE0)
|
||||
return 3;
|
||||
if ((ch & 0xF8) == 0xF0)
|
||||
return 4;
|
||||
if ((ch & 0xFC) == 0xF8)
|
||||
return 5;
|
||||
if ((ch & 0xFE) == 0xFC)
|
||||
return 6;
|
||||
/* Invalid UTF-8 encoding. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Does the parameter point to the lead byte of a well-formed UTF-8 character?
|
||||
*/
|
||||
public int is_utf8_well_formed(char *ss, int slen)
|
||||
{
|
||||
int i;
|
||||
int len;
|
||||
unsigned char *s = (unsigned char *) ss;
|
||||
|
||||
if (IS_UTF8_INVALID(s[0]))
|
||||
return (0);
|
||||
|
||||
len = utf_len(s[0]);
|
||||
if (len > slen)
|
||||
return (0);
|
||||
if (len == 1)
|
||||
return (1);
|
||||
if (len == 2)
|
||||
{
|
||||
if (s[0] < 0xC2)
|
||||
return (0);
|
||||
} else
|
||||
{
|
||||
unsigned char mask;
|
||||
mask = (~((1 << (8-len)) - 1)) & 0xFF;
|
||||
if (s[0] == mask && (s[1] & mask) == 0x80)
|
||||
return (0);
|
||||
}
|
||||
|
||||
for (i = 1; i < len; i++)
|
||||
if (!IS_UTF8_TRAIL(s[i]))
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip bytes until a UTF-8 lead byte (11xxxxxx) or ASCII byte (0xxxxxxx) is found.
|
||||
*/
|
||||
public void utf_skip_to_lead(char **pp, char *limit)
|
||||
{
|
||||
do {
|
||||
++(*pp);
|
||||
} while (*pp < limit && !IS_UTF8_LEAD((*pp)[0] & 0377) && !IS_ASCII_OCTET((*pp)[0]));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get the value of a UTF-8 character.
|
||||
*/
|
||||
public LWCHAR get_wchar(constant char *p)
|
||||
{
|
||||
switch (utf_len(p[0]))
|
||||
{
|
||||
case 1:
|
||||
default:
|
||||
/* 0xxxxxxx */
|
||||
return (LWCHAR)
|
||||
(p[0] & 0xFF);
|
||||
case 2:
|
||||
/* 110xxxxx 10xxxxxx */
|
||||
return (LWCHAR) (
|
||||
((p[0] & 0x1F) << 6) |
|
||||
(p[1] & 0x3F));
|
||||
case 3:
|
||||
/* 1110xxxx 10xxxxxx 10xxxxxx */
|
||||
return (LWCHAR) (
|
||||
((p[0] & 0x0F) << 12) |
|
||||
((p[1] & 0x3F) << 6) |
|
||||
(p[2] & 0x3F));
|
||||
case 4:
|
||||
/* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
|
||||
return (LWCHAR) (
|
||||
((p[0] & 0x07) << 18) |
|
||||
((p[1] & 0x3F) << 12) |
|
||||
((p[2] & 0x3F) << 6) |
|
||||
(p[3] & 0x3F));
|
||||
case 5:
|
||||
/* 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */
|
||||
return (LWCHAR) (
|
||||
((p[0] & 0x03) << 24) |
|
||||
((p[1] & 0x3F) << 18) |
|
||||
((p[2] & 0x3F) << 12) |
|
||||
((p[3] & 0x3F) << 6) |
|
||||
(p[4] & 0x3F));
|
||||
case 6:
|
||||
/* 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */
|
||||
return (LWCHAR) (
|
||||
((p[0] & 0x01) << 30) |
|
||||
((p[1] & 0x3F) << 24) |
|
||||
((p[2] & 0x3F) << 18) |
|
||||
((p[3] & 0x3F) << 12) |
|
||||
((p[4] & 0x3F) << 6) |
|
||||
(p[5] & 0x3F));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Store a character into a UTF-8 string.
|
||||
*/
|
||||
public void put_wchar(char **pp, LWCHAR ch)
|
||||
{
|
||||
if (!utf_mode || ch < 0x80)
|
||||
{
|
||||
/* 0xxxxxxx */
|
||||
*(*pp)++ = (char) ch;
|
||||
} else if (ch < 0x800)
|
||||
{
|
||||
/* 110xxxxx 10xxxxxx */
|
||||
*(*pp)++ = (char) (0xC0 | ((ch >> 6) & 0x1F));
|
||||
*(*pp)++ = (char) (0x80 | (ch & 0x3F));
|
||||
} else if (ch < 0x10000)
|
||||
{
|
||||
/* 1110xxxx 10xxxxxx 10xxxxxx */
|
||||
*(*pp)++ = (char) (0xE0 | ((ch >> 12) & 0x0F));
|
||||
*(*pp)++ = (char) (0x80 | ((ch >> 6) & 0x3F));
|
||||
*(*pp)++ = (char) (0x80 | (ch & 0x3F));
|
||||
} else if (ch < 0x200000)
|
||||
{
|
||||
/* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
|
||||
*(*pp)++ = (char) (0xF0 | ((ch >> 18) & 0x07));
|
||||
*(*pp)++ = (char) (0x80 | ((ch >> 12) & 0x3F));
|
||||
*(*pp)++ = (char) (0x80 | ((ch >> 6) & 0x3F));
|
||||
*(*pp)++ = (char) (0x80 | (ch & 0x3F));
|
||||
} else if (ch < 0x4000000)
|
||||
{
|
||||
/* 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */
|
||||
*(*pp)++ = (char) (0xF0 | ((ch >> 24) & 0x03));
|
||||
*(*pp)++ = (char) (0x80 | ((ch >> 18) & 0x3F));
|
||||
*(*pp)++ = (char) (0x80 | ((ch >> 12) & 0x3F));
|
||||
*(*pp)++ = (char) (0x80 | ((ch >> 6) & 0x3F));
|
||||
*(*pp)++ = (char) (0x80 | (ch & 0x3F));
|
||||
} else
|
||||
{
|
||||
/* 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */
|
||||
*(*pp)++ = (char) (0xF0 | ((ch >> 30) & 0x01));
|
||||
*(*pp)++ = (char) (0x80 | ((ch >> 24) & 0x3F));
|
||||
*(*pp)++ = (char) (0x80 | ((ch >> 18) & 0x3F));
|
||||
*(*pp)++ = (char) (0x80 | ((ch >> 12) & 0x3F));
|
||||
*(*pp)++ = (char) (0x80 | ((ch >> 6) & 0x3F));
|
||||
*(*pp)++ = (char) (0x80 | (ch & 0x3F));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Step forward or backward one character in a string.
|
||||
*/
|
||||
public LWCHAR step_char(char **pp, signed int dir, constant char *limit)
|
||||
{
|
||||
LWCHAR ch;
|
||||
int len;
|
||||
char *p = *pp;
|
||||
|
||||
if (!utf_mode)
|
||||
{
|
||||
/* It's easy if chars are one byte. */
|
||||
if (dir > 0)
|
||||
ch = (LWCHAR) (unsigned char) ((p < limit) ? *p++ : 0);
|
||||
else
|
||||
ch = (LWCHAR) (unsigned char) ((p > limit) ? *--p : 0);
|
||||
} else if (dir > 0)
|
||||
{
|
||||
len = utf_len(*p);
|
||||
if (p + len > limit)
|
||||
{
|
||||
ch = 0;
|
||||
p = (char *) limit;
|
||||
} else
|
||||
{
|
||||
ch = get_wchar(p);
|
||||
p += len;
|
||||
}
|
||||
} else
|
||||
{
|
||||
while (p > limit && IS_UTF8_TRAIL(p[-1]))
|
||||
p--;
|
||||
if (p > limit)
|
||||
ch = get_wchar(--p);
|
||||
else
|
||||
ch = 0;
|
||||
}
|
||||
*pp = p;
|
||||
return ch;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unicode characters data
|
||||
* Actual data is in the generated *.uni files.
|
||||
*/
|
||||
|
||||
#define DECLARE_RANGE_TABLE_START(name) \
|
||||
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) };
|
||||
|
||||
DECLARE_RANGE_TABLE_START(compose)
|
||||
#include "compose.inc"
|
||||
DECLARE_RANGE_TABLE_END(compose)
|
||||
|
||||
DECLARE_RANGE_TABLE_START(ubin)
|
||||
#include "ubin.inc"
|
||||
DECLARE_RANGE_TABLE_END(ubin)
|
||||
|
||||
DECLARE_RANGE_TABLE_START(wide)
|
||||
#include "wide.inc"
|
||||
DECLARE_RANGE_TABLE_END(wide)
|
||||
|
||||
DECLARE_RANGE_TABLE_START(fmt)
|
||||
#include "fmt.inc"
|
||||
DECLARE_RANGE_TABLE_END(fmt)
|
||||
|
||||
/* comb_table is special pairs, not ranges. */
|
||||
static struct wchar_range comb_table[] = {
|
||||
{0x0644,0x0622}, {0x0644,0x0623}, {0x0644,0x0625}, {0x0644,0x0627},
|
||||
};
|
||||
|
||||
|
||||
static int is_in_table(LWCHAR ch, struct wchar_range_table *table)
|
||||
{
|
||||
int hi;
|
||||
int lo;
|
||||
|
||||
/* Binary search in the table. */
|
||||
if (table->table == NULL || table->count == 0 || ch < table->table[0].first)
|
||||
return 0;
|
||||
lo = 0;
|
||||
hi = table->count - 1;
|
||||
while (lo <= hi)
|
||||
{
|
||||
int mid = (lo + hi) / 2;
|
||||
if (ch > table->table[mid].last)
|
||||
lo = mid + 1;
|
||||
else if (ch < table->table[mid].first)
|
||||
hi = mid - 1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is a character a UTF-8 composing character?
|
||||
* If a composing character follows any char, the two combine into one glyph.
|
||||
*/
|
||||
public int is_composing_char(LWCHAR ch)
|
||||
{
|
||||
if (is_in_table(ch, &user_prt_table)) return 0;
|
||||
return is_in_table(ch, &user_compose_table) ||
|
||||
is_in_table(ch, &compose_table) ||
|
||||
(bs_mode != BS_CONTROL && is_in_table(ch, &fmt_table));
|
||||
}
|
||||
|
||||
/*
|
||||
* Should this UTF-8 character be treated as binary?
|
||||
*/
|
||||
public int is_ubin_char(LWCHAR ch)
|
||||
{
|
||||
if (is_in_table(ch, &user_prt_table)) return 0;
|
||||
return is_in_table(ch, &user_ubin_table) ||
|
||||
is_in_table(ch, &ubin_table) ||
|
||||
(bs_mode == BS_CONTROL && is_in_table(ch, &fmt_table));
|
||||
}
|
||||
|
||||
/*
|
||||
* Is this a double width UTF-8 character?
|
||||
*/
|
||||
public int is_wide_char(LWCHAR ch)
|
||||
{
|
||||
return is_in_table(ch, &user_wide_table) ||
|
||||
is_in_table(ch, &wide_table);
|
||||
}
|
||||
|
||||
/*
|
||||
* Is a character a UTF-8 combining character?
|
||||
* A combining char acts like an ordinary char, but if it follows
|
||||
* a specific char (not any char), the two combine into one glyph.
|
||||
*/
|
||||
public int is_combining_char(LWCHAR ch1, LWCHAR ch2)
|
||||
{
|
||||
/* The table is small; use linear search. */
|
||||
int i;
|
||||
for (i = 0; i < sizeof(comb_table)/sizeof(*comb_table); i++)
|
||||
{
|
||||
if (ch1 == comb_table[i].first &&
|
||||
ch2 == comb_table[i].last)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
18
third_party/less/charset.h
vendored
Normal file
18
third_party/less/charset.h
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
#define IS_ASCII_OCTET(c) (((c) & 0x80) == 0)
|
||||
#define IS_UTF8_TRAIL(c) (((c) & 0xC0) == 0x80)
|
||||
#define IS_UTF8_LEAD2(c) (((c) & 0xE0) == 0xC0)
|
||||
#define IS_UTF8_LEAD3(c) (((c) & 0xF0) == 0xE0)
|
||||
#define IS_UTF8_LEAD4(c) (((c) & 0xF8) == 0xF0)
|
||||
#define IS_UTF8_LEAD5(c) (((c) & 0xFC) == 0xF8)
|
||||
#define IS_UTF8_LEAD6(c) (((c) & 0xFE) == 0xFC)
|
||||
#define IS_UTF8_INVALID(c) (((c) & 0xFE) == 0xFE)
|
||||
#define IS_UTF8_LEAD(c) (((c) & 0xC0) == 0xC0 && !IS_UTF8_INVALID(c))
|
147
third_party/less/cmd.h
vendored
Normal file
147
third_party/less/cmd.h
vendored
Normal file
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
#define MAX_USERCMD 1000
|
||||
#define MAX_CMDLEN 16
|
||||
|
||||
#define A_B_LINE 2
|
||||
#define A_B_SCREEN 3
|
||||
#define A_B_SCROLL 4
|
||||
#define A_B_SEARCH 5
|
||||
#define A_DIGIT 6
|
||||
#define A_DISP_OPTION 7
|
||||
#define A_DEBUG 8
|
||||
#define A_EXAMINE 9
|
||||
#define A_FIRSTCMD 10
|
||||
#define A_FREPAINT 11
|
||||
#define A_F_LINE 12
|
||||
#define A_F_SCREEN 13
|
||||
#define A_F_SCROLL 14
|
||||
#define A_F_SEARCH 15
|
||||
#define A_GOEND 16
|
||||
#define A_GOLINE 17
|
||||
#define A_GOMARK 18
|
||||
#define A_HELP 19
|
||||
#define A_NEXT_FILE 20
|
||||
#define A_PERCENT 21
|
||||
#define A_PREV_FILE 23
|
||||
#define A_QUIT 24
|
||||
#define A_REPAINT 25
|
||||
#define A_SETMARK 26
|
||||
#define A_SHELL 27
|
||||
#define A_STAT 28
|
||||
#define A_FF_LINE 29
|
||||
#define A_BF_LINE 30
|
||||
#define A_VERSION 31
|
||||
#define A_VISUAL 32
|
||||
#define A_F_WINDOW 33
|
||||
#define A_B_WINDOW 34
|
||||
#define A_F_BRACKET 35
|
||||
#define A_B_BRACKET 36
|
||||
#define A_PIPE 37
|
||||
#define A_INDEX_FILE 38
|
||||
#define A_UNDO_SEARCH 39
|
||||
#define A_FF_SCREEN 40
|
||||
#define A_LSHIFT 41
|
||||
#define A_RSHIFT 42
|
||||
#define A_AGAIN_SEARCH 43
|
||||
#define A_T_AGAIN_SEARCH 44
|
||||
#define A_REVERSE_SEARCH 45
|
||||
#define A_T_REVERSE_SEARCH 46
|
||||
#define A_OPT_TOGGLE 47
|
||||
#define A_OPT_SET 48
|
||||
#define A_OPT_UNSET 49
|
||||
#define A_F_FOREVER 50
|
||||
#define A_GOPOS 51
|
||||
#define A_REMOVE_FILE 52
|
||||
#define A_NEXT_TAG 53
|
||||
#define A_PREV_TAG 54
|
||||
#define A_FILTER 55
|
||||
#define A_F_UNTIL_HILITE 56
|
||||
#define A_GOEND_BUF 57
|
||||
#define A_LLSHIFT 58
|
||||
#define A_RRSHIFT 59
|
||||
#define A_CLRMARK 62
|
||||
#define A_SETMARKBOT 63
|
||||
#define A_X11MOUSE_IN 64
|
||||
#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_PSHELL 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
|
||||
|
||||
|
||||
/* Line editing characters */
|
||||
|
||||
#define EC_BACKSPACE 1
|
||||
#define EC_LINEKILL 2
|
||||
#define EC_RIGHT 3
|
||||
#define EC_LEFT 4
|
||||
#define EC_W_LEFT 5
|
||||
#define EC_W_RIGHT 6
|
||||
#define EC_INSERT 7
|
||||
#define EC_DELETE 8
|
||||
#define EC_HOME 9
|
||||
#define EC_END 10
|
||||
#define EC_W_BACKSPACE 11
|
||||
#define EC_W_DELETE 12
|
||||
#define EC_UP 13
|
||||
#define EC_DOWN 14
|
||||
#define EC_EXPAND 15
|
||||
#define EC_F_COMPLETE 17
|
||||
#define EC_B_COMPLETE 18
|
||||
#define EC_LITERAL 19
|
||||
#define EC_ABORT 20
|
||||
#define EC_X11MOUSE 21
|
||||
#define EC_X116MOUSE 22
|
||||
|
||||
#define EC_UINVALID 102
|
||||
|
||||
/* Flags for editchar() */
|
||||
#define ECF_PEEK 01
|
||||
#define ECF_NOHISTORY 02
|
||||
#define ECF_NOCOMPLETE 04
|
||||
#define ECF_NORIGHTLEFT 010
|
||||
|
||||
/* Environment variable stuff */
|
||||
#define EV_OK 01
|
||||
|
||||
/* Special keys (keys which output different strings on different terminals) */
|
||||
#define SK_SPECIAL_KEY CONTROL('K')
|
||||
#define SK_RIGHT_ARROW 1
|
||||
#define SK_LEFT_ARROW 2
|
||||
#define SK_UP_ARROW 3
|
||||
#define SK_DOWN_ARROW 4
|
||||
#define SK_PAGE_UP 5
|
||||
#define SK_PAGE_DOWN 6
|
||||
#define SK_HOME 7
|
||||
#define SK_END 8
|
||||
#define SK_DELETE 9
|
||||
#define SK_INSERT 10
|
||||
#define SK_CTL_LEFT_ARROW 11
|
||||
#define SK_CTL_RIGHT_ARROW 12
|
||||
#define SK_CTL_DELETE 13
|
||||
#define SK_F1 14
|
||||
#define SK_BACKTAB 15
|
||||
#define SK_CTL_BACKSPACE 16
|
||||
#define SK_BACKSPACE 17
|
||||
#define SK_CONTROL_K 40
|
1677
third_party/less/cmdbuf.c
vendored
Normal file
1677
third_party/less/cmdbuf.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
2090
third_party/less/command.c
vendored
Normal file
2090
third_party/less/command.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
355
third_party/less/compose.inc
vendored
Normal file
355
third_party/less/compose.inc
vendored
Normal file
|
@ -0,0 +1,355 @@
|
|||
/* Generated by "./mkutable -f2 Mn Me -- unicode/UnicodeData.txt" on Mon Nov 14 18:19:23 PST 2022 */
|
||||
{ 0x0300, 0x036f }, /* Mn */
|
||||
{ 0x0483, 0x0487 }, /* Mn */
|
||||
{ 0x0488, 0x0489 }, /* Me */
|
||||
{ 0x0591, 0x05bd }, /* Mn */
|
||||
{ 0x05bf, 0x05bf }, /* Mn */
|
||||
{ 0x05c1, 0x05c2 }, /* Mn */
|
||||
{ 0x05c4, 0x05c5 }, /* Mn */
|
||||
{ 0x05c7, 0x05c7 }, /* Mn */
|
||||
{ 0x0610, 0x061a }, /* Mn */
|
||||
{ 0x064b, 0x065f }, /* Mn */
|
||||
{ 0x0670, 0x0670 }, /* Mn */
|
||||
{ 0x06d6, 0x06dc }, /* Mn */
|
||||
{ 0x06df, 0x06e4 }, /* Mn */
|
||||
{ 0x06e7, 0x06e8 }, /* Mn */
|
||||
{ 0x06ea, 0x06ed }, /* Mn */
|
||||
{ 0x0711, 0x0711 }, /* Mn */
|
||||
{ 0x0730, 0x074a }, /* Mn */
|
||||
{ 0x07a6, 0x07b0 }, /* Mn */
|
||||
{ 0x07eb, 0x07f3 }, /* Mn */
|
||||
{ 0x07fd, 0x07fd }, /* Mn */
|
||||
{ 0x0816, 0x0819 }, /* Mn */
|
||||
{ 0x081b, 0x0823 }, /* Mn */
|
||||
{ 0x0825, 0x0827 }, /* Mn */
|
||||
{ 0x0829, 0x082d }, /* Mn */
|
||||
{ 0x0859, 0x085b }, /* Mn */
|
||||
{ 0x0898, 0x089f }, /* Mn */
|
||||
{ 0x08ca, 0x08e1 }, /* Mn */
|
||||
{ 0x08e3, 0x0902 }, /* Mn */
|
||||
{ 0x093a, 0x093a }, /* Mn */
|
||||
{ 0x093c, 0x093c }, /* Mn */
|
||||
{ 0x0941, 0x0948 }, /* Mn */
|
||||
{ 0x094d, 0x094d }, /* Mn */
|
||||
{ 0x0951, 0x0957 }, /* Mn */
|
||||
{ 0x0962, 0x0963 }, /* Mn */
|
||||
{ 0x0981, 0x0981 }, /* Mn */
|
||||
{ 0x09bc, 0x09bc }, /* Mn */
|
||||
{ 0x09c1, 0x09c4 }, /* Mn */
|
||||
{ 0x09cd, 0x09cd }, /* Mn */
|
||||
{ 0x09e2, 0x09e3 }, /* Mn */
|
||||
{ 0x09fe, 0x09fe }, /* Mn */
|
||||
{ 0x0a01, 0x0a02 }, /* Mn */
|
||||
{ 0x0a3c, 0x0a3c }, /* Mn */
|
||||
{ 0x0a41, 0x0a42 }, /* Mn */
|
||||
{ 0x0a47, 0x0a48 }, /* Mn */
|
||||
{ 0x0a4b, 0x0a4d }, /* Mn */
|
||||
{ 0x0a51, 0x0a51 }, /* Mn */
|
||||
{ 0x0a70, 0x0a71 }, /* Mn */
|
||||
{ 0x0a75, 0x0a75 }, /* Mn */
|
||||
{ 0x0a81, 0x0a82 }, /* Mn */
|
||||
{ 0x0abc, 0x0abc }, /* Mn */
|
||||
{ 0x0ac1, 0x0ac5 }, /* Mn */
|
||||
{ 0x0ac7, 0x0ac8 }, /* Mn */
|
||||
{ 0x0acd, 0x0acd }, /* Mn */
|
||||
{ 0x0ae2, 0x0ae3 }, /* Mn */
|
||||
{ 0x0afa, 0x0aff }, /* Mn */
|
||||
{ 0x0b01, 0x0b01 }, /* Mn */
|
||||
{ 0x0b3c, 0x0b3c }, /* Mn */
|
||||
{ 0x0b3f, 0x0b3f }, /* Mn */
|
||||
{ 0x0b41, 0x0b44 }, /* Mn */
|
||||
{ 0x0b4d, 0x0b4d }, /* Mn */
|
||||
{ 0x0b55, 0x0b56 }, /* Mn */
|
||||
{ 0x0b62, 0x0b63 }, /* Mn */
|
||||
{ 0x0b82, 0x0b82 }, /* Mn */
|
||||
{ 0x0bc0, 0x0bc0 }, /* Mn */
|
||||
{ 0x0bcd, 0x0bcd }, /* Mn */
|
||||
{ 0x0c00, 0x0c00 }, /* Mn */
|
||||
{ 0x0c04, 0x0c04 }, /* Mn */
|
||||
{ 0x0c3c, 0x0c3c }, /* Mn */
|
||||
{ 0x0c3e, 0x0c40 }, /* Mn */
|
||||
{ 0x0c46, 0x0c48 }, /* Mn */
|
||||
{ 0x0c4a, 0x0c4d }, /* Mn */
|
||||
{ 0x0c55, 0x0c56 }, /* Mn */
|
||||
{ 0x0c62, 0x0c63 }, /* Mn */
|
||||
{ 0x0c81, 0x0c81 }, /* Mn */
|
||||
{ 0x0cbc, 0x0cbc }, /* Mn */
|
||||
{ 0x0cbf, 0x0cbf }, /* Mn */
|
||||
{ 0x0cc6, 0x0cc6 }, /* Mn */
|
||||
{ 0x0ccc, 0x0ccd }, /* Mn */
|
||||
{ 0x0ce2, 0x0ce3 }, /* Mn */
|
||||
{ 0x0d00, 0x0d01 }, /* Mn */
|
||||
{ 0x0d3b, 0x0d3c }, /* Mn */
|
||||
{ 0x0d41, 0x0d44 }, /* Mn */
|
||||
{ 0x0d4d, 0x0d4d }, /* Mn */
|
||||
{ 0x0d62, 0x0d63 }, /* Mn */
|
||||
{ 0x0d81, 0x0d81 }, /* Mn */
|
||||
{ 0x0dca, 0x0dca }, /* Mn */
|
||||
{ 0x0dd2, 0x0dd4 }, /* Mn */
|
||||
{ 0x0dd6, 0x0dd6 }, /* Mn */
|
||||
{ 0x0e31, 0x0e31 }, /* Mn */
|
||||
{ 0x0e34, 0x0e3a }, /* Mn */
|
||||
{ 0x0e47, 0x0e4e }, /* Mn */
|
||||
{ 0x0eb1, 0x0eb1 }, /* Mn */
|
||||
{ 0x0eb4, 0x0ebc }, /* Mn */
|
||||
{ 0x0ec8, 0x0ece }, /* Mn */
|
||||
{ 0x0f18, 0x0f19 }, /* Mn */
|
||||
{ 0x0f35, 0x0f35 }, /* Mn */
|
||||
{ 0x0f37, 0x0f37 }, /* Mn */
|
||||
{ 0x0f39, 0x0f39 }, /* Mn */
|
||||
{ 0x0f71, 0x0f7e }, /* Mn */
|
||||
{ 0x0f80, 0x0f84 }, /* Mn */
|
||||
{ 0x0f86, 0x0f87 }, /* Mn */
|
||||
{ 0x0f8d, 0x0f97 }, /* Mn */
|
||||
{ 0x0f99, 0x0fbc }, /* Mn */
|
||||
{ 0x0fc6, 0x0fc6 }, /* Mn */
|
||||
{ 0x102d, 0x1030 }, /* Mn */
|
||||
{ 0x1032, 0x1037 }, /* Mn */
|
||||
{ 0x1039, 0x103a }, /* Mn */
|
||||
{ 0x103d, 0x103e }, /* Mn */
|
||||
{ 0x1058, 0x1059 }, /* Mn */
|
||||
{ 0x105e, 0x1060 }, /* Mn */
|
||||
{ 0x1071, 0x1074 }, /* Mn */
|
||||
{ 0x1082, 0x1082 }, /* Mn */
|
||||
{ 0x1085, 0x1086 }, /* Mn */
|
||||
{ 0x108d, 0x108d }, /* Mn */
|
||||
{ 0x109d, 0x109d }, /* Mn */
|
||||
{ 0x1160, 0x11ff }, /* Mn */
|
||||
{ 0x135d, 0x135f }, /* Mn */
|
||||
{ 0x1712, 0x1714 }, /* Mn */
|
||||
{ 0x1732, 0x1733 }, /* Mn */
|
||||
{ 0x1752, 0x1753 }, /* Mn */
|
||||
{ 0x1772, 0x1773 }, /* Mn */
|
||||
{ 0x17b4, 0x17b5 }, /* Mn */
|
||||
{ 0x17b7, 0x17bd }, /* Mn */
|
||||
{ 0x17c6, 0x17c6 }, /* Mn */
|
||||
{ 0x17c9, 0x17d3 }, /* Mn */
|
||||
{ 0x17dd, 0x17dd }, /* Mn */
|
||||
{ 0x180b, 0x180d }, /* Mn */
|
||||
{ 0x180f, 0x180f }, /* Mn */
|
||||
{ 0x1885, 0x1886 }, /* Mn */
|
||||
{ 0x18a9, 0x18a9 }, /* Mn */
|
||||
{ 0x1920, 0x1922 }, /* Mn */
|
||||
{ 0x1927, 0x1928 }, /* Mn */
|
||||
{ 0x1932, 0x1932 }, /* Mn */
|
||||
{ 0x1939, 0x193b }, /* Mn */
|
||||
{ 0x1a17, 0x1a18 }, /* Mn */
|
||||
{ 0x1a1b, 0x1a1b }, /* Mn */
|
||||
{ 0x1a56, 0x1a56 }, /* Mn */
|
||||
{ 0x1a58, 0x1a5e }, /* Mn */
|
||||
{ 0x1a60, 0x1a60 }, /* Mn */
|
||||
{ 0x1a62, 0x1a62 }, /* Mn */
|
||||
{ 0x1a65, 0x1a6c }, /* Mn */
|
||||
{ 0x1a73, 0x1a7c }, /* Mn */
|
||||
{ 0x1a7f, 0x1a7f }, /* Mn */
|
||||
{ 0x1ab0, 0x1abd }, /* Mn */
|
||||
{ 0x1abe, 0x1abe }, /* Me */
|
||||
{ 0x1abf, 0x1ace }, /* Mn */
|
||||
{ 0x1b00, 0x1b03 }, /* Mn */
|
||||
{ 0x1b34, 0x1b34 }, /* Mn */
|
||||
{ 0x1b36, 0x1b3a }, /* Mn */
|
||||
{ 0x1b3c, 0x1b3c }, /* Mn */
|
||||
{ 0x1b42, 0x1b42 }, /* Mn */
|
||||
{ 0x1b6b, 0x1b73 }, /* Mn */
|
||||
{ 0x1b80, 0x1b81 }, /* Mn */
|
||||
{ 0x1ba2, 0x1ba5 }, /* Mn */
|
||||
{ 0x1ba8, 0x1ba9 }, /* Mn */
|
||||
{ 0x1bab, 0x1bad }, /* Mn */
|
||||
{ 0x1be6, 0x1be6 }, /* Mn */
|
||||
{ 0x1be8, 0x1be9 }, /* Mn */
|
||||
{ 0x1bed, 0x1bed }, /* Mn */
|
||||
{ 0x1bef, 0x1bf1 }, /* Mn */
|
||||
{ 0x1c2c, 0x1c33 }, /* Mn */
|
||||
{ 0x1c36, 0x1c37 }, /* Mn */
|
||||
{ 0x1cd0, 0x1cd2 }, /* Mn */
|
||||
{ 0x1cd4, 0x1ce0 }, /* Mn */
|
||||
{ 0x1ce2, 0x1ce8 }, /* Mn */
|
||||
{ 0x1ced, 0x1ced }, /* Mn */
|
||||
{ 0x1cf4, 0x1cf4 }, /* Mn */
|
||||
{ 0x1cf8, 0x1cf9 }, /* Mn */
|
||||
{ 0x1dc0, 0x1dff }, /* Mn */
|
||||
{ 0x20d0, 0x20dc }, /* Mn */
|
||||
{ 0x20dd, 0x20e0 }, /* Me */
|
||||
{ 0x20e1, 0x20e1 }, /* Mn */
|
||||
{ 0x20e2, 0x20e4 }, /* Me */
|
||||
{ 0x20e5, 0x20f0 }, /* Mn */
|
||||
{ 0x2cef, 0x2cf1 }, /* Mn */
|
||||
{ 0x2d7f, 0x2d7f }, /* Mn */
|
||||
{ 0x2de0, 0x2dff }, /* Mn */
|
||||
{ 0x302a, 0x302d }, /* Mn */
|
||||
{ 0x3099, 0x309a }, /* Mn */
|
||||
{ 0xa66f, 0xa66f }, /* Mn */
|
||||
{ 0xa670, 0xa672 }, /* Me */
|
||||
{ 0xa674, 0xa67d }, /* Mn */
|
||||
{ 0xa69e, 0xa69f }, /* Mn */
|
||||
{ 0xa6f0, 0xa6f1 }, /* Mn */
|
||||
{ 0xa802, 0xa802 }, /* Mn */
|
||||
{ 0xa806, 0xa806 }, /* Mn */
|
||||
{ 0xa80b, 0xa80b }, /* Mn */
|
||||
{ 0xa825, 0xa826 }, /* Mn */
|
||||
{ 0xa82c, 0xa82c }, /* Mn */
|
||||
{ 0xa8c4, 0xa8c5 }, /* Mn */
|
||||
{ 0xa8e0, 0xa8f1 }, /* Mn */
|
||||
{ 0xa8ff, 0xa8ff }, /* Mn */
|
||||
{ 0xa926, 0xa92d }, /* Mn */
|
||||
{ 0xa947, 0xa951 }, /* Mn */
|
||||
{ 0xa980, 0xa982 }, /* Mn */
|
||||
{ 0xa9b3, 0xa9b3 }, /* Mn */
|
||||
{ 0xa9b6, 0xa9b9 }, /* Mn */
|
||||
{ 0xa9bc, 0xa9bd }, /* Mn */
|
||||
{ 0xa9e5, 0xa9e5 }, /* Mn */
|
||||
{ 0xaa29, 0xaa2e }, /* Mn */
|
||||
{ 0xaa31, 0xaa32 }, /* Mn */
|
||||
{ 0xaa35, 0xaa36 }, /* Mn */
|
||||
{ 0xaa43, 0xaa43 }, /* Mn */
|
||||
{ 0xaa4c, 0xaa4c }, /* Mn */
|
||||
{ 0xaa7c, 0xaa7c }, /* Mn */
|
||||
{ 0xaab0, 0xaab0 }, /* Mn */
|
||||
{ 0xaab2, 0xaab4 }, /* Mn */
|
||||
{ 0xaab7, 0xaab8 }, /* Mn */
|
||||
{ 0xaabe, 0xaabf }, /* Mn */
|
||||
{ 0xaac1, 0xaac1 }, /* Mn */
|
||||
{ 0xaaec, 0xaaed }, /* Mn */
|
||||
{ 0xaaf6, 0xaaf6 }, /* Mn */
|
||||
{ 0xabe5, 0xabe5 }, /* Mn */
|
||||
{ 0xabe8, 0xabe8 }, /* Mn */
|
||||
{ 0xabed, 0xabed }, /* Mn */
|
||||
{ 0xd7b0, 0xd7c6 }, /* Mn */
|
||||
{ 0xd7cb, 0xd7fb }, /* Mn */
|
||||
{ 0xfb1e, 0xfb1e }, /* Mn */
|
||||
{ 0xfe00, 0xfe0f }, /* Mn */
|
||||
{ 0xfe20, 0xfe2f }, /* Mn */
|
||||
{ 0x101fd, 0x101fd }, /* Mn */
|
||||
{ 0x102e0, 0x102e0 }, /* Mn */
|
||||
{ 0x10376, 0x1037a }, /* Mn */
|
||||
{ 0x10a01, 0x10a03 }, /* Mn */
|
||||
{ 0x10a05, 0x10a06 }, /* Mn */
|
||||
{ 0x10a0c, 0x10a0f }, /* Mn */
|
||||
{ 0x10a38, 0x10a3a }, /* Mn */
|
||||
{ 0x10a3f, 0x10a3f }, /* Mn */
|
||||
{ 0x10ae5, 0x10ae6 }, /* Mn */
|
||||
{ 0x10d24, 0x10d27 }, /* Mn */
|
||||
{ 0x10eab, 0x10eac }, /* Mn */
|
||||
{ 0x10efd, 0x10eff }, /* Mn */
|
||||
{ 0x10f46, 0x10f50 }, /* Mn */
|
||||
{ 0x10f82, 0x10f85 }, /* Mn */
|
||||
{ 0x11001, 0x11001 }, /* Mn */
|
||||
{ 0x11038, 0x11046 }, /* Mn */
|
||||
{ 0x11070, 0x11070 }, /* Mn */
|
||||
{ 0x11073, 0x11074 }, /* Mn */
|
||||
{ 0x1107f, 0x11081 }, /* Mn */
|
||||
{ 0x110b3, 0x110b6 }, /* Mn */
|
||||
{ 0x110b9, 0x110ba }, /* Mn */
|
||||
{ 0x110c2, 0x110c2 }, /* Mn */
|
||||
{ 0x11100, 0x11102 }, /* Mn */
|
||||
{ 0x11127, 0x1112b }, /* Mn */
|
||||
{ 0x1112d, 0x11134 }, /* Mn */
|
||||
{ 0x11173, 0x11173 }, /* Mn */
|
||||
{ 0x11180, 0x11181 }, /* Mn */
|
||||
{ 0x111b6, 0x111be }, /* Mn */
|
||||
{ 0x111c9, 0x111cc }, /* Mn */
|
||||
{ 0x111cf, 0x111cf }, /* Mn */
|
||||
{ 0x1122f, 0x11231 }, /* Mn */
|
||||
{ 0x11234, 0x11234 }, /* Mn */
|
||||
{ 0x11236, 0x11237 }, /* Mn */
|
||||
{ 0x1123e, 0x1123e }, /* Mn */
|
||||
{ 0x11241, 0x11241 }, /* Mn */
|
||||
{ 0x112df, 0x112df }, /* Mn */
|
||||
{ 0x112e3, 0x112ea }, /* Mn */
|
||||
{ 0x11300, 0x11301 }, /* Mn */
|
||||
{ 0x1133b, 0x1133c }, /* Mn */
|
||||
{ 0x11340, 0x11340 }, /* Mn */
|
||||
{ 0x11366, 0x1136c }, /* Mn */
|
||||
{ 0x11370, 0x11374 }, /* Mn */
|
||||
{ 0x11438, 0x1143f }, /* Mn */
|
||||
{ 0x11442, 0x11444 }, /* Mn */
|
||||
{ 0x11446, 0x11446 }, /* Mn */
|
||||
{ 0x1145e, 0x1145e }, /* Mn */
|
||||
{ 0x114b3, 0x114b8 }, /* Mn */
|
||||
{ 0x114ba, 0x114ba }, /* Mn */
|
||||
{ 0x114bf, 0x114c0 }, /* Mn */
|
||||
{ 0x114c2, 0x114c3 }, /* Mn */
|
||||
{ 0x115b2, 0x115b5 }, /* Mn */
|
||||
{ 0x115bc, 0x115bd }, /* Mn */
|
||||
{ 0x115bf, 0x115c0 }, /* Mn */
|
||||
{ 0x115dc, 0x115dd }, /* Mn */
|
||||
{ 0x11633, 0x1163a }, /* Mn */
|
||||
{ 0x1163d, 0x1163d }, /* Mn */
|
||||
{ 0x1163f, 0x11640 }, /* Mn */
|
||||
{ 0x116ab, 0x116ab }, /* Mn */
|
||||
{ 0x116ad, 0x116ad }, /* Mn */
|
||||
{ 0x116b0, 0x116b5 }, /* Mn */
|
||||
{ 0x116b7, 0x116b7 }, /* Mn */
|
||||
{ 0x1171d, 0x1171f }, /* Mn */
|
||||
{ 0x11722, 0x11725 }, /* Mn */
|
||||
{ 0x11727, 0x1172b }, /* Mn */
|
||||
{ 0x1182f, 0x11837 }, /* Mn */
|
||||
{ 0x11839, 0x1183a }, /* Mn */
|
||||
{ 0x1193b, 0x1193c }, /* Mn */
|
||||
{ 0x1193e, 0x1193e }, /* Mn */
|
||||
{ 0x11943, 0x11943 }, /* Mn */
|
||||
{ 0x119d4, 0x119d7 }, /* Mn */
|
||||
{ 0x119da, 0x119db }, /* Mn */
|
||||
{ 0x119e0, 0x119e0 }, /* Mn */
|
||||
{ 0x11a01, 0x11a0a }, /* Mn */
|
||||
{ 0x11a33, 0x11a38 }, /* Mn */
|
||||
{ 0x11a3b, 0x11a3e }, /* Mn */
|
||||
{ 0x11a47, 0x11a47 }, /* Mn */
|
||||
{ 0x11a51, 0x11a56 }, /* Mn */
|
||||
{ 0x11a59, 0x11a5b }, /* Mn */
|
||||
{ 0x11a8a, 0x11a96 }, /* Mn */
|
||||
{ 0x11a98, 0x11a99 }, /* Mn */
|
||||
{ 0x11c30, 0x11c36 }, /* Mn */
|
||||
{ 0x11c38, 0x11c3d }, /* Mn */
|
||||
{ 0x11c3f, 0x11c3f }, /* Mn */
|
||||
{ 0x11c92, 0x11ca7 }, /* Mn */
|
||||
{ 0x11caa, 0x11cb0 }, /* Mn */
|
||||
{ 0x11cb2, 0x11cb3 }, /* Mn */
|
||||
{ 0x11cb5, 0x11cb6 }, /* Mn */
|
||||
{ 0x11d31, 0x11d36 }, /* Mn */
|
||||
{ 0x11d3a, 0x11d3a }, /* Mn */
|
||||
{ 0x11d3c, 0x11d3d }, /* Mn */
|
||||
{ 0x11d3f, 0x11d45 }, /* Mn */
|
||||
{ 0x11d47, 0x11d47 }, /* Mn */
|
||||
{ 0x11d90, 0x11d91 }, /* Mn */
|
||||
{ 0x11d95, 0x11d95 }, /* Mn */
|
||||
{ 0x11d97, 0x11d97 }, /* Mn */
|
||||
{ 0x11ef3, 0x11ef4 }, /* Mn */
|
||||
{ 0x11f00, 0x11f01 }, /* Mn */
|
||||
{ 0x11f36, 0x11f3a }, /* Mn */
|
||||
{ 0x11f40, 0x11f40 }, /* Mn */
|
||||
{ 0x11f42, 0x11f42 }, /* Mn */
|
||||
{ 0x13440, 0x13440 }, /* Mn */
|
||||
{ 0x13447, 0x13455 }, /* Mn */
|
||||
{ 0x16af0, 0x16af4 }, /* Mn */
|
||||
{ 0x16b30, 0x16b36 }, /* Mn */
|
||||
{ 0x16f4f, 0x16f4f }, /* Mn */
|
||||
{ 0x16f8f, 0x16f92 }, /* Mn */
|
||||
{ 0x16fe4, 0x16fe4 }, /* Mn */
|
||||
{ 0x1bc9d, 0x1bc9e }, /* Mn */
|
||||
{ 0x1cf00, 0x1cf2d }, /* Mn */
|
||||
{ 0x1cf30, 0x1cf46 }, /* Mn */
|
||||
{ 0x1d167, 0x1d169 }, /* Mn */
|
||||
{ 0x1d17b, 0x1d182 }, /* Mn */
|
||||
{ 0x1d185, 0x1d18b }, /* Mn */
|
||||
{ 0x1d1aa, 0x1d1ad }, /* Mn */
|
||||
{ 0x1d242, 0x1d244 }, /* Mn */
|
||||
{ 0x1da00, 0x1da36 }, /* Mn */
|
||||
{ 0x1da3b, 0x1da6c }, /* Mn */
|
||||
{ 0x1da75, 0x1da75 }, /* Mn */
|
||||
{ 0x1da84, 0x1da84 }, /* Mn */
|
||||
{ 0x1da9b, 0x1da9f }, /* Mn */
|
||||
{ 0x1daa1, 0x1daaf }, /* Mn */
|
||||
{ 0x1e000, 0x1e006 }, /* Mn */
|
||||
{ 0x1e008, 0x1e018 }, /* Mn */
|
||||
{ 0x1e01b, 0x1e021 }, /* Mn */
|
||||
{ 0x1e023, 0x1e024 }, /* Mn */
|
||||
{ 0x1e026, 0x1e02a }, /* Mn */
|
||||
{ 0x1e08f, 0x1e08f }, /* Mn */
|
||||
{ 0x1e130, 0x1e136 }, /* Mn */
|
||||
{ 0x1e2ae, 0x1e2ae }, /* Mn */
|
||||
{ 0x1e2ec, 0x1e2ef }, /* Mn */
|
||||
{ 0x1e4ec, 0x1e4ef }, /* Mn */
|
||||
{ 0x1e8d0, 0x1e8d6 }, /* Mn */
|
||||
{ 0x1e944, 0x1e94a }, /* Mn */
|
||||
{ 0xe0100, 0xe01ef }, /* Mn */
|
107
third_party/less/cvt.c
vendored
Normal file
107
third_party/less/cvt.c
vendored
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Routines to convert text in various ways. Used by search.
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
#include "charset.h"
|
||||
|
||||
extern int utf_mode;
|
||||
|
||||
/*
|
||||
* Get the length of a buffer needed to convert a string.
|
||||
*/
|
||||
public int cvt_length(int len, int ops)
|
||||
{
|
||||
if (utf_mode)
|
||||
/*
|
||||
* Just copying a string in UTF-8 mode can cause it to grow
|
||||
* in length.
|
||||
* Four output bytes for one input byte is the worst case.
|
||||
*/
|
||||
len *= 4;
|
||||
return (len + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a chpos array for use by cvt_text.
|
||||
*/
|
||||
public int * cvt_alloc_chpos(int len)
|
||||
{
|
||||
int i;
|
||||
int *chpos = (int *) ecalloc(sizeof(int), len);
|
||||
/* Initialize all entries to an invalid position. */
|
||||
for (i = 0; i < len; i++)
|
||||
chpos[i] = -1;
|
||||
return (chpos);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert text. Perform the transformations specified by ops.
|
||||
* Returns converted text in odst. The original offset of each
|
||||
* odst character (when it was in osrc) is returned in the chpos array.
|
||||
*/
|
||||
public void cvt_text(char *odst, char *osrc, int *chpos, int *lenp, int ops)
|
||||
{
|
||||
char *dst;
|
||||
char *edst = odst;
|
||||
char *src;
|
||||
char *src_end;
|
||||
LWCHAR ch;
|
||||
|
||||
if (lenp != NULL)
|
||||
src_end = osrc + *lenp;
|
||||
else
|
||||
src_end = osrc + strlen(osrc);
|
||||
|
||||
for (src = osrc, dst = odst; src < src_end; )
|
||||
{
|
||||
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)
|
||||
{
|
||||
/* Delete backspace and preceding char. */
|
||||
do {
|
||||
dst--;
|
||||
} while (dst > odst && utf_mode &&
|
||||
!IS_ASCII_OCTET(*dst) && !IS_UTF8_LEAD(*dst));
|
||||
} else if ((ops & CVT_ANSI) && (pansi = ansi_start(ch)) != NULL)
|
||||
{
|
||||
/* Skip to end of ANSI escape sequence. */
|
||||
while (src < src_end)
|
||||
{
|
||||
if (ansi_step(pansi, ch) != ANSI_MID)
|
||||
break;
|
||||
ch = *src++;
|
||||
}
|
||||
ansi_done(pansi);
|
||||
} else
|
||||
{
|
||||
/* Just copy the char to the destination buffer. */
|
||||
if ((ops & CVT_TO_LC) && IS_UPPER(ch))
|
||||
ch = TO_LOWER(ch);
|
||||
put_wchar(&dst, ch);
|
||||
/* Record the original position of the char. */
|
||||
if (chpos != NULL)
|
||||
chpos[dst_pos] = src_pos;
|
||||
}
|
||||
if (dst > edst)
|
||||
edst = dst;
|
||||
}
|
||||
if ((ops & CVT_CRLF) && edst > odst && edst[-1] == '\r')
|
||||
edst--;
|
||||
*edst = '\0';
|
||||
if (lenp != NULL)
|
||||
*lenp = (int) (edst - odst);
|
||||
/* FIXME: why was this here? if (chpos != NULL) chpos[dst - odst] = src - osrc; */
|
||||
}
|
1017
third_party/less/decode.c
vendored
Normal file
1017
third_party/less/decode.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
475
third_party/less/defines.h
vendored
Normal file
475
third_party/less/defines.h
vendored
Normal file
|
@ -0,0 +1,475 @@
|
|||
/* defines.h. Generated from defines.h.in by configure. */
|
||||
/* defines.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
|
||||
/* Unix definition file for less. -*- C -*-
|
||||
*
|
||||
* This file has 3 sections:
|
||||
* User preferences.
|
||||
* Settings always true on Unix.
|
||||
* Settings automatically determined by configure.
|
||||
*
|
||||
* * * * * * WARNING * * * * * *
|
||||
* If you edit defines.h by hand, do "touch stamp-h" before you run make
|
||||
* so config.status doesn't overwrite your changes.
|
||||
*/
|
||||
|
||||
/* User preferences. */
|
||||
|
||||
/*
|
||||
* SECURE is 1 if you wish to disable a bunch of features in order to
|
||||
* be safe to run by unprivileged users.
|
||||
* SECURE_COMPILE is set by the --with-secure configure option.
|
||||
*/
|
||||
#define SECURE SECURE_COMPILE
|
||||
|
||||
/*
|
||||
* SHELL_ESCAPE is 1 if you wish to allow shell escapes.
|
||||
* (This is possible only if your system supplies the system() function.)
|
||||
*/
|
||||
#define SHELL_ESCAPE (!SECURE)
|
||||
|
||||
/*
|
||||
* EXAMINE is 1 if you wish to allow examining files by name from within less.
|
||||
*/
|
||||
#define EXAMINE (!SECURE)
|
||||
|
||||
/*
|
||||
* TAB_COMPLETE_FILENAME is 1 if you wish to allow the TAB key
|
||||
* to complete filenames at prompts.
|
||||
*/
|
||||
#define TAB_COMPLETE_FILENAME (!SECURE)
|
||||
|
||||
/*
|
||||
* CMD_HISTORY is 1 if you wish to allow keys to cycle through
|
||||
* previous commands at prompts.
|
||||
*/
|
||||
#define CMD_HISTORY 1
|
||||
|
||||
/*
|
||||
* HILITE_SEARCH is 1 if you wish to have search targets to be
|
||||
* displayed in standout mode.
|
||||
*/
|
||||
#define HILITE_SEARCH 1
|
||||
|
||||
/*
|
||||
* EDITOR is 1 if you wish to allow editor invocation (the "v" command).
|
||||
* (This is possible only if your system supplies the system() function.)
|
||||
* EDIT_PGM is the name of the (default) editor to be invoked.
|
||||
*/
|
||||
#define EDITOR (!SECURE)
|
||||
|
||||
/*
|
||||
* TAGS is 1 if you wish to support tag files.
|
||||
*/
|
||||
#define TAGS (!SECURE)
|
||||
|
||||
/*
|
||||
* USERFILE is 1 if you wish to allow a .less file to specify
|
||||
* user-defined key bindings.
|
||||
*/
|
||||
#define USERFILE (!SECURE)
|
||||
|
||||
/*
|
||||
* GLOB is 1 if you wish to have shell metacharacters expanded in filenames.
|
||||
* This will generally work if your system provides the "popen" function
|
||||
* and the "echo" shell command.
|
||||
*/
|
||||
#define GLOB (!SECURE)
|
||||
|
||||
/*
|
||||
* PIPEC is 1 if you wish to have the "|" command
|
||||
* which allows the user to pipe data into a shell command.
|
||||
*/
|
||||
#define PIPEC (!SECURE && HAVE_POPEN)
|
||||
|
||||
/*
|
||||
* LOGFILE is 1 if you wish to allow the -o option (to create log files).
|
||||
*/
|
||||
#define LOGFILE (!SECURE)
|
||||
|
||||
/*
|
||||
* GNU_OPTIONS is 1 if you wish to support the GNU-style command
|
||||
* line options --help and --version.
|
||||
*/
|
||||
#define GNU_OPTIONS 1
|
||||
|
||||
/*
|
||||
* ONLY_RETURN is 1 if you want RETURN to be the only input which
|
||||
* will continue past an error message.
|
||||
* Otherwise, any key will continue past an error message.
|
||||
*/
|
||||
#define ONLY_RETURN 0
|
||||
|
||||
/*
|
||||
* LESSKEYFILE is the filename of the default lesskey output file
|
||||
* (in the HOME directory).
|
||||
* LESSKEYFILE_SYS is the filename of the system-wide lesskey output file.
|
||||
* DEF_LESSKEYINFILE is the filename of the default lesskey input
|
||||
* (in the HOME directory).
|
||||
* LESSHISTFILE is the filename of the history file
|
||||
* (in the HOME directory).
|
||||
*/
|
||||
#define LESSKEYFILE ".less"
|
||||
#define LESSKEYFILE_SYS SYSDIR "/sysless"
|
||||
#define DEF_LESSKEYINFILE ".lesskey"
|
||||
#define LESSKEYINFILE_SYS SYSDIR "/syslesskey"
|
||||
#define LESSHISTFILE ".lesshst"
|
||||
|
||||
|
||||
/* Settings always true on Unix. */
|
||||
|
||||
/*
|
||||
* Define MSDOS_COMPILER if compiling under Microsoft C.
|
||||
*/
|
||||
#define MSDOS_COMPILER 0
|
||||
|
||||
/*
|
||||
* Pathname separator character.
|
||||
*/
|
||||
#define PATHNAME_SEP "/"
|
||||
|
||||
/*
|
||||
* The value returned from tgetent on success.
|
||||
* Some HP-UX systems return 0 on success.
|
||||
*/
|
||||
#define TGETENT_OK 1
|
||||
|
||||
/*
|
||||
* HAVE_ANSI_PROTOS is 1 if your compiler supports ANSI function prototypes.
|
||||
*/
|
||||
#define HAVE_ANSI_PROTOS 1
|
||||
|
||||
/*
|
||||
* HAVE_SYS_TYPES_H is 1 if your system has <sys/types.h>.
|
||||
*/
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/*
|
||||
* Define if you have the <sgstat.h> header file.
|
||||
*/
|
||||
/* #undef HAVE_SGSTAT_H */
|
||||
|
||||
/*
|
||||
* HAVE_PERROR is 1 if your system has the perror() call.
|
||||
* (Actually, if it has sys_errlist, sys_nerr and errno.)
|
||||
*/
|
||||
#define HAVE_PERROR 1
|
||||
|
||||
/*
|
||||
* HAVE_TIME is 1 if your system has the time() call.
|
||||
*/
|
||||
#define HAVE_TIME 1
|
||||
|
||||
/*
|
||||
* HAVE_SHELL is 1 if your system supports a SHELL command interpreter.
|
||||
*/
|
||||
#define HAVE_SHELL 1
|
||||
|
||||
/*
|
||||
* Default shell metacharacters and meta-escape character.
|
||||
*/
|
||||
#define DEF_METACHARS "; *?\t\n'\"()<>[]|&^`#\\$%=~{},"
|
||||
#define DEF_METAESCAPE "\\"
|
||||
|
||||
/*
|
||||
* HAVE_DUP is 1 if your system has the dup() call.
|
||||
*/
|
||||
#define HAVE_DUP 1
|
||||
|
||||
/* Define to 1 if you have the memcpy() function. */
|
||||
#define HAVE_MEMCPY 1
|
||||
|
||||
/* Define to 1 if you have the strchr() function. */
|
||||
#define HAVE_STRCHR 1
|
||||
|
||||
/* Define to 1 if you have the strstr() function. */
|
||||
#define HAVE_STRSTR 1
|
||||
|
||||
/* Define to 1 to support reading lesskey source files (not just binary). */
|
||||
#define HAVE_LESSKEYSRC 1
|
||||
|
||||
/*
|
||||
* Sizes of various buffers.
|
||||
*/
|
||||
#if 0 /* old sizes for small memory machines */
|
||||
#define CMDBUF_SIZE 512 /* Buffer for multichar commands */
|
||||
#define UNGOT_SIZE 100 /* Max chars to unget() */
|
||||
#define LINEBUF_SIZE 1024 /* Max size of line in input file */
|
||||
#define OUTBUF_SIZE 1024 /* Output buffer */
|
||||
#define PROMPT_SIZE 200 /* Max size of prompt string */
|
||||
#define TERMBUF_SIZE 2048 /* Termcap buffer for tgetent */
|
||||
#define TERMSBUF_SIZE 1024 /* Buffer to hold termcap strings */
|
||||
#define TAGLINE_SIZE 512 /* Max size of line in tags file */
|
||||
#define TABSTOP_MAX 32 /* Max number of custom tab stops */
|
||||
#else /* more reasonable sizes for modern machines */
|
||||
#define CMDBUF_SIZE 2048 /* Buffer for multichar commands */
|
||||
#define UNGOT_SIZE 200 /* Max chars to unget() */
|
||||
#define LINEBUF_SIZE 1024 /* Initial max size of line in input file */
|
||||
#define OUTBUF_SIZE 1024 /* Output buffer */
|
||||
#define PROMPT_SIZE 2048 /* Max size of prompt string */
|
||||
#define TERMBUF_SIZE 2048 /* Termcap buffer for tgetent */
|
||||
#define TERMSBUF_SIZE 1024 /* Buffer to hold termcap strings */
|
||||
#define TAGLINE_SIZE 1024 /* Max size of line in tags file */
|
||||
#define TABSTOP_MAX 128 /* Max number of custom tab stops */
|
||||
#endif
|
||||
|
||||
/* Define as the return type of signal handlers (int or void). */
|
||||
#define RETSIGTYPE void
|
||||
|
||||
/* Settings automatically determined by configure. */
|
||||
|
||||
|
||||
/* Define EDIT_PGM to your editor. */
|
||||
#define EDIT_PGM "vi"
|
||||
|
||||
/* Define HAVE_CONST if your compiler supports the "const" modifier. */
|
||||
#define HAVE_CONST 1
|
||||
|
||||
/* Define to 1 if you have the <ctype.h> header file. */
|
||||
#define HAVE_CTYPE_H 1
|
||||
|
||||
/* Define HAVE_ERRNO if you have the errno variable. */
|
||||
#define HAVE_ERRNO 1
|
||||
|
||||
/* Define to 1 if you have the <errno.h> header file. */
|
||||
#define HAVE_ERRNO_H 1
|
||||
|
||||
/* Define to 1 if you have the `fchmod' function. */
|
||||
#define HAVE_FCHMOD 1
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#define HAVE_FCNTL_H 1
|
||||
|
||||
/* Define HAVE_FILENO if you have the fileno() macro. */
|
||||
#define HAVE_FILENO 1
|
||||
|
||||
/* Define to 1 if you have the `fsync' function. */
|
||||
#define HAVE_FSYNC 1
|
||||
|
||||
/* GNU regex library */
|
||||
/* #undef HAVE_GNU_REGEX */
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <limits.h> header file. */
|
||||
#define HAVE_LIMITS_H 1
|
||||
|
||||
/* Define to 1 if you have the <linux/magic.h> header file. */
|
||||
/* #undef HAVE_LINUX_MAGIC_H */
|
||||
|
||||
/* Define HAVE_LOCALE if you have locale.h and setlocale. */
|
||||
#define HAVE_LOCALE 1
|
||||
|
||||
/* Define to 1 if you have the `nanosleep' function. */
|
||||
#define HAVE_NANOSLEEP 1
|
||||
|
||||
/* Define to 1 if you have the <ncursesw/termcap.h> header file. */
|
||||
/* #undef HAVE_NCURSESW_TERMCAP_H */
|
||||
|
||||
/* Define to 1 if you have the "third_party/ncurses/termcap.h" header file. */
|
||||
#define HAVE_NCURSES_TERMCAP_H 1
|
||||
|
||||
/* Define HAVE_OSPEED if your termcap library has the ospeed variable. */
|
||||
#define HAVE_OSPEED 1
|
||||
|
||||
/* PCRE (Perl-compatible regular expression) library */
|
||||
/* #undef HAVE_PCRE */
|
||||
|
||||
/* PCRE2 (Perl-compatible regular expression) library */
|
||||
#define HAVE_PCRE2 1
|
||||
|
||||
/* 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
|
||||
|
||||
/* POSIX regcomp() and regex.h */
|
||||
/* #undef HAVE_POSIX_REGCOMP */
|
||||
|
||||
/* Define HAVE_PROCFS if have have fstatfs with f_type and PROC_SUPER_MAGIC.
|
||||
*/
|
||||
/* #undef HAVE_PROCFS */
|
||||
|
||||
/* Define to 1 if you have the `realpath' function. */
|
||||
#define HAVE_REALPATH 1
|
||||
|
||||
/* System V regcmp() */
|
||||
/* #undef HAVE_REGCMP */
|
||||
|
||||
/* */
|
||||
/* #undef HAVE_REGEXEC2 */
|
||||
|
||||
/* BSD re_comp() */
|
||||
/* #undef HAVE_RE_COMP */
|
||||
|
||||
/* Define HAVE_SIGEMPTYSET if you have the sigemptyset macro. */
|
||||
#define HAVE_SIGEMPTYSET 1
|
||||
|
||||
/* Define to 1 if you have the `sigprocmask' function. */
|
||||
#define HAVE_SIGPROCMASK 1
|
||||
|
||||
/* Define to 1 if you have the `sigsetmask' function. */
|
||||
/* #undef HAVE_SIGSETMASK */
|
||||
|
||||
/* Define to 1 if the system has the type `sigset_t'. */
|
||||
#define HAVE_SIGSET_T 1
|
||||
|
||||
/* Define to 1 if you have the `snprintf' function. */
|
||||
#define HAVE_SNPRINTF 1
|
||||
|
||||
/* Define to 1 if you have the `stat' function. */
|
||||
#define HAVE_STAT 1
|
||||
|
||||
/* Define HAVE_STAT_INO if your struct stat has st_ino and st_dev. */
|
||||
#define HAVE_STAT_INO 1
|
||||
|
||||
/* Define to 1 if you have the <stdckdint.h> header file. */
|
||||
#define HAVE_STDCKDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */
|
||||
#define HAVE_STDIO_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define HAVE_STRERROR if you have the strerror() function. */
|
||||
#define HAVE_STRERROR 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the `strsignal' function. */
|
||||
#define HAVE_STRSIGNAL 1
|
||||
|
||||
/* Define to 1 if you have the `system' function. */
|
||||
#define HAVE_SYSTEM 1
|
||||
|
||||
/* Define HAVE_SYS_ERRLIST if you have the sys_errlist[] variable. */
|
||||
#define HAVE_SYS_ERRLIST 1
|
||||
|
||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||
#define HAVE_SYS_IOCTL_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stream.h> header file. */
|
||||
/* #undef HAVE_SYS_STREAM_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/wait.h> header file. */
|
||||
#define HAVE_SYS_WAIT_H 1
|
||||
|
||||
/* Define to 1 if you have the <termcap.h> header file. */
|
||||
/* #undef HAVE_TERMCAP_H */
|
||||
|
||||
/* Define HAVE_TERMIOS_FUNCS if you have tcgetattr/tcsetattr. */
|
||||
#define HAVE_TERMIOS_FUNCS 1
|
||||
|
||||
/* Define to 1 if you have the <termios.h> header file. */
|
||||
#define HAVE_TERMIOS_H 1
|
||||
|
||||
/* Define to 1 if you have the <termio.h> header file. */
|
||||
/* #undef HAVE_TERMIO_H */
|
||||
|
||||
/* Define to 1 if you have the <time.h> header file. */
|
||||
#define HAVE_TIME_H 1
|
||||
|
||||
/* 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 <unistd.h> 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 */
|
||||
|
||||
/* Define to 1 if you have the <values.h> header file. */
|
||||
/* #undef HAVE_VALUES_H */
|
||||
|
||||
/* Define HAVE_VOID if your compiler supports the "void" type. */
|
||||
#define HAVE_VOID 1
|
||||
|
||||
/* Define HAVE_WCTYPE if you have iswupper, iswlower, towupper, towlower. */
|
||||
#define HAVE_WCTYPE 1
|
||||
|
||||
/* Define to 1 if you have the <wctype.h> header file. */
|
||||
#define HAVE_WCTYPE_H 1
|
||||
|
||||
/* Define to 1 if you have the `_setjmp' function. */
|
||||
#define HAVE__SETJMP 1
|
||||
|
||||
/* Define MUST_DEFINE_ERRNO if you have errno but it is not define in errno.h.
|
||||
*/
|
||||
/* #undef MUST_DEFINE_ERRNO */
|
||||
|
||||
/* Define MUST_DEFINE_OSPEED if you have ospeed but it is not defined in
|
||||
termcap.h. */
|
||||
#define MUST_DEFINE_OSPEED 1
|
||||
|
||||
/* pattern matching is supported, but without metacharacters. */
|
||||
/* #undef NO_REGEX */
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT ""
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "less"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "less 1"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "less"
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "1"
|
||||
|
||||
/* Define SECURE_COMPILE=1 to build a secure version of less. */
|
||||
#define SECURE_COMPILE 0
|
||||
|
||||
/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
|
||||
/* #undef STAT_MACROS_BROKEN */
|
||||
|
||||
/* Define to 1 if all of the C90 standard headers exist (not just the ones
|
||||
required in a freestanding environment). This macro is provided for
|
||||
backward compatibility; new code need not use it. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
/* #undef _FILE_OFFSET_BITS */
|
||||
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
/* #undef _LARGE_FILES */
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
/* #undef const */
|
||||
|
||||
/* Define to `long int' if <sys/types.h> does not define. */
|
||||
/* #undef off_t */
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
/* #undef size_t */
|
1017
third_party/less/edit.c
vendored
Normal file
1017
third_party/less/edit.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
1118
third_party/less/filename.c
vendored
Normal file
1118
third_party/less/filename.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
22
third_party/less/fmt.inc
vendored
Normal file
22
third_party/less/fmt.inc
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
/* Generated by "./mkutable -f2 Cf -- unicode/UnicodeData.txt" on Mon Nov 14 18:19:23 PST 2022 */
|
||||
{ 0x00ad, 0x00ad }, /* Cf */
|
||||
{ 0x0600, 0x0605 }, /* Cf */
|
||||
{ 0x061c, 0x061c }, /* Cf */
|
||||
{ 0x06dd, 0x06dd }, /* Cf */
|
||||
{ 0x070f, 0x070f }, /* Cf */
|
||||
{ 0x0890, 0x0891 }, /* Cf */
|
||||
{ 0x08e2, 0x08e2 }, /* Cf */
|
||||
{ 0x180e, 0x180e }, /* Cf */
|
||||
{ 0x200b, 0x200f }, /* Cf */
|
||||
{ 0x202a, 0x202e }, /* Cf */
|
||||
{ 0x2060, 0x2064 }, /* Cf */
|
||||
{ 0x2066, 0x206f }, /* Cf */
|
||||
{ 0xfeff, 0xfeff }, /* Cf */
|
||||
{ 0xfff9, 0xfffb }, /* Cf */
|
||||
{ 0x110bd, 0x110bd }, /* Cf */
|
||||
{ 0x110cd, 0x110cd }, /* Cf */
|
||||
{ 0x13430, 0x1343f }, /* Cf */
|
||||
{ 0x1bca0, 0x1bca3 }, /* Cf */
|
||||
{ 0x1d173, 0x1d17a }, /* Cf */
|
||||
{ 0xe0001, 0xe0001 }, /* Cf */
|
||||
{ 0xe0020, 0xe007f }, /* Cf */
|
549
third_party/less/forwback.c
vendored
Normal file
549
third_party/less/forwback.c
vendored
Normal file
|
@ -0,0 +1,549 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Primitives for displaying the file on the screen,
|
||||
* scrolling either forward or backward.
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
#include "position.h"
|
||||
|
||||
public int screen_trashed;
|
||||
public int squished;
|
||||
public int no_back_scroll = 0;
|
||||
public int forw_prompt;
|
||||
public int first_time = 1;
|
||||
|
||||
extern int sigs;
|
||||
extern int top_scroll;
|
||||
extern int quiet;
|
||||
extern int sc_width, sc_height;
|
||||
extern int hshift;
|
||||
extern int auto_wrap;
|
||||
extern int plusoption;
|
||||
extern int forw_scroll;
|
||||
extern int back_scroll;
|
||||
extern int ignore_eoi;
|
||||
extern int clear_bg;
|
||||
extern int final_attr;
|
||||
extern int header_lines;
|
||||
extern int header_cols;
|
||||
extern int full_screen;
|
||||
#if HILITE_SEARCH
|
||||
extern int size_linebuf;
|
||||
extern int hilite_search;
|
||||
extern int status_col;
|
||||
#endif
|
||||
#if TAGS
|
||||
extern char *tagoption;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Sound the bell to indicate user is trying to move past end of file.
|
||||
*/
|
||||
public void eof_bell(void)
|
||||
{
|
||||
#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
|
||||
vbell();
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if the end of file is currently displayed.
|
||||
*/
|
||||
public int eof_displayed(void)
|
||||
{
|
||||
POSITION pos;
|
||||
|
||||
if (ignore_eoi)
|
||||
return (0);
|
||||
|
||||
if (ch_length() == NULL_POSITION)
|
||||
/*
|
||||
* If the file length is not known,
|
||||
* we can't possibly be displaying EOF.
|
||||
*/
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* If the bottom line is empty, we are at EOF.
|
||||
* If the bottom line ends at the file length,
|
||||
* we must be just at EOF.
|
||||
*/
|
||||
pos = position(BOTTOM_PLUS_ONE);
|
||||
return (pos == NULL_POSITION || pos == ch_length());
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if the entire file is currently displayed.
|
||||
*/
|
||||
public int entire_file_displayed(void)
|
||||
{
|
||||
POSITION pos;
|
||||
|
||||
/* Make sure last line of file is displayed. */
|
||||
if (!eof_displayed())
|
||||
return (0);
|
||||
|
||||
/* Make sure first line of file is displayed. */
|
||||
pos = position(0);
|
||||
return (pos == NULL_POSITION || pos == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the screen is "squished", repaint it.
|
||||
* "Squished" means the first displayed line is not at the top
|
||||
* of the screen; this can happen when we display a short file
|
||||
* for the first time.
|
||||
*/
|
||||
public void squish_check(void)
|
||||
{
|
||||
if (!squished)
|
||||
return;
|
||||
squished = 0;
|
||||
repaint();
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the first pfx columns of the next line.
|
||||
* If skipeol==0 stop there, otherwise read and discard chars to end of line.
|
||||
*/
|
||||
static POSITION forw_line_pfx(POSITION pos, int pfx, int skipeol)
|
||||
{
|
||||
int save_sc_width = sc_width;
|
||||
int save_auto_wrap = auto_wrap;
|
||||
int save_hshift = hshift;
|
||||
/* Set fake sc_width to force only pfx chars to be read. */
|
||||
sc_width = pfx + line_pfx_width();
|
||||
auto_wrap = 0;
|
||||
hshift = 0;
|
||||
pos = forw_line_seg(pos, skipeol, FALSE, FALSE);
|
||||
sc_width = save_sc_width;
|
||||
auto_wrap = save_auto_wrap;
|
||||
hshift = save_hshift;
|
||||
return pos;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set header text color.
|
||||
* Underline last line of headers, but not at beginning of file
|
||||
* (where there is no gap between the last header line and the next line).
|
||||
*/
|
||||
static void set_attr_header(int ln)
|
||||
{
|
||||
set_attr_line(AT_COLOR_HEADER);
|
||||
if (ln+1 == header_lines && position(0) != ch_zero())
|
||||
set_attr_line(AT_UNDERLINE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Display file headers, overlaying text already drawn
|
||||
* at top and left of screen.
|
||||
*/
|
||||
public int overlay_header(void)
|
||||
{
|
||||
POSITION pos = ch_zero(); /* header lines are at beginning of file */
|
||||
int ln;
|
||||
int moved = FALSE;
|
||||
|
||||
if (header_lines > 0)
|
||||
{
|
||||
/* Draw header_lines lines from start of file at top of screen. */
|
||||
home();
|
||||
for (ln = 0; ln < header_lines; ++ln)
|
||||
{
|
||||
pos = forw_line(pos);
|
||||
set_attr_header(ln);
|
||||
clear_eol();
|
||||
put_line();
|
||||
}
|
||||
moved = TRUE;
|
||||
}
|
||||
if (header_cols > 0)
|
||||
{
|
||||
/* Draw header_cols columns at left of each line. */
|
||||
home();
|
||||
pos = ch_zero();
|
||||
for (ln = 0; ln < sc_height-1; ++ln)
|
||||
{
|
||||
if (ln >= header_lines) /* switch from header lines to normal lines */
|
||||
pos = position(ln);
|
||||
if (pos == NULL_POSITION)
|
||||
putchr('\n');
|
||||
else
|
||||
{
|
||||
/* Need skipeol for all header lines except the last one. */
|
||||
pos = forw_line_pfx(pos, header_cols, ln+1 < header_lines);
|
||||
set_attr_header(ln);
|
||||
put_line();
|
||||
}
|
||||
}
|
||||
moved = TRUE;
|
||||
}
|
||||
if (moved)
|
||||
lower_left();
|
||||
return moved;
|
||||
}
|
||||
|
||||
/*
|
||||
* Display n lines, scrolling forward,
|
||||
* starting at position pos in the input file.
|
||||
* "force" means display the n lines even if we hit end of file.
|
||||
* "only_last" means display only the last screenful if n > screen size.
|
||||
* "nblank" is the number of blank lines to draw before the first
|
||||
* real line. If nblank > 0, the pos must be NULL_POSITION.
|
||||
* The first real line after the blanks will start at ch_zero().
|
||||
*/
|
||||
public void forw(int n, POSITION pos, int force, int only_last, int nblank)
|
||||
{
|
||||
int nlines = 0;
|
||||
int do_repaint;
|
||||
|
||||
squish_check();
|
||||
|
||||
/*
|
||||
* do_repaint tells us not to display anything till the end,
|
||||
* then just repaint the entire screen.
|
||||
* We repaint if we are supposed to display only the last
|
||||
* screenful and the request is for more than a screenful.
|
||||
* Also if the request exceeds the forward scroll limit
|
||||
* (but not if the request is for exactly a screenful, since
|
||||
* repainting itself involves scrolling forward a screenful).
|
||||
*/
|
||||
do_repaint = (only_last && n > sc_height-1) ||
|
||||
(forw_scroll >= 0 && n > forw_scroll && n != sc_height-1);
|
||||
|
||||
#if HILITE_SEARCH
|
||||
if (pos != NULL_POSITION && (hilite_search == OPT_ONPLUS || is_filtering() || status_col)) {
|
||||
prep_hilite(pos, pos + 4*size_linebuf, ignore_eoi ? 1 : -1);
|
||||
pos = next_unfiltered(pos);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!do_repaint)
|
||||
{
|
||||
if (top_scroll && n >= sc_height - 1 && pos != ch_length())
|
||||
{
|
||||
/*
|
||||
* Start a new screen.
|
||||
* {{ This is not really desirable if we happen
|
||||
* to hit eof in the middle of this screen,
|
||||
* but we don't yet know if that will happen. }}
|
||||
*/
|
||||
pos_clear();
|
||||
add_forw_pos(pos);
|
||||
force = 1;
|
||||
clear();
|
||||
home();
|
||||
}
|
||||
|
||||
if (pos != position(BOTTOM_PLUS_ONE) || empty_screen())
|
||||
{
|
||||
/*
|
||||
* This is not contiguous with what is
|
||||
* currently displayed. Clear the screen image
|
||||
* (position table) and start a new screen.
|
||||
*/
|
||||
pos_clear();
|
||||
add_forw_pos(pos);
|
||||
force = 1;
|
||||
if (top_scroll)
|
||||
{
|
||||
clear();
|
||||
home();
|
||||
} else if (!first_time && !is_filtering() && full_screen)
|
||||
{
|
||||
putstr("...skipping...\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (--n >= 0)
|
||||
{
|
||||
/*
|
||||
* Read the next line of input.
|
||||
*/
|
||||
if (nblank > 0)
|
||||
{
|
||||
/*
|
||||
* Still drawing blanks; don't get a line
|
||||
* from the file yet.
|
||||
* If this is the last blank line, get ready to
|
||||
* read a line starting at ch_zero() next time.
|
||||
*/
|
||||
if (--nblank == 0)
|
||||
pos = ch_zero();
|
||||
} else
|
||||
{
|
||||
/*
|
||||
* Get the next line from the file.
|
||||
*/
|
||||
pos = forw_line(pos);
|
||||
#if HILITE_SEARCH
|
||||
pos = next_unfiltered(pos);
|
||||
#endif
|
||||
if (pos == NULL_POSITION)
|
||||
{
|
||||
/*
|
||||
* End of file: stop here unless the top line
|
||||
* is still empty, or "force" is true.
|
||||
* Even if force is true, stop when the last
|
||||
* line in the file reaches the top of screen.
|
||||
*/
|
||||
if (!force && position(TOP) != NULL_POSITION)
|
||||
break;
|
||||
if (!empty_lines(0, 0) &&
|
||||
!empty_lines(1, 1) &&
|
||||
empty_lines(2, sc_height-1))
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Add the position of the next line to the position table.
|
||||
* Display the current line on the screen.
|
||||
*/
|
||||
add_forw_pos(pos);
|
||||
nlines++;
|
||||
if (do_repaint)
|
||||
continue;
|
||||
/*
|
||||
* If this is the first screen displayed and
|
||||
* we hit an early EOF (i.e. before the requested
|
||||
* number of lines), we "squish" the display down
|
||||
* at the bottom of the screen.
|
||||
* But don't do this if a + option or a -t option
|
||||
* was given. These options can cause us to
|
||||
* start the display after the beginning of the file,
|
||||
* and it is not appropriate to squish in that case.
|
||||
*/
|
||||
if (first_time && pos == NULL_POSITION && !top_scroll &&
|
||||
header_lines == 0 && header_cols == 0 &&
|
||||
#if TAGS
|
||||
tagoption == NULL &&
|
||||
#endif
|
||||
!plusoption)
|
||||
{
|
||||
squished = 1;
|
||||
continue;
|
||||
}
|
||||
put_line();
|
||||
#if 0
|
||||
/* {{
|
||||
* Can't call clear_eol here. The cursor might be at end of line
|
||||
* on an ignaw terminal, so clear_eol would clear the last char
|
||||
* of the current line instead of all of the next line.
|
||||
* If we really need to do this on clear_bg terminals, we need
|
||||
* to find a better way.
|
||||
* }}
|
||||
*/
|
||||
if (clear_bg && apply_at_specials(final_attr) != AT_NORMAL)
|
||||
{
|
||||
/*
|
||||
* Writing the last character on the last line
|
||||
* of the display may have scrolled the screen.
|
||||
* If we were in standout mode, clear_bg terminals
|
||||
* will fill the new line with the standout color.
|
||||
* Now we're in normal mode again, so clear the line.
|
||||
*/
|
||||
clear_eol();
|
||||
}
|
||||
#endif
|
||||
forw_prompt = 1;
|
||||
}
|
||||
|
||||
if (header_lines > 0)
|
||||
{
|
||||
/*
|
||||
* Don't allow ch_zero to appear on screen except at top of screen.
|
||||
* Otherwise duplicate header lines may be displayed.
|
||||
*/
|
||||
if (onscreen(ch_zero()) > 0)
|
||||
{
|
||||
jump_loc(ch_zero(), 0); /* {{ yuck }} */
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (nlines == 0 && !ignore_eoi)
|
||||
eof_bell();
|
||||
else if (do_repaint)
|
||||
repaint();
|
||||
else
|
||||
{
|
||||
overlay_header();
|
||||
/* lower_left(); {{ considered harmful? }} */
|
||||
}
|
||||
first_time = 0;
|
||||
(void) currline(BOTTOM);
|
||||
}
|
||||
|
||||
/*
|
||||
* Display n lines, scrolling backward.
|
||||
*/
|
||||
public void back(int n, POSITION pos, int force, int only_last)
|
||||
{
|
||||
int nlines = 0;
|
||||
int do_repaint;
|
||||
|
||||
squish_check();
|
||||
do_repaint = (n > get_back_scroll() || (only_last && n > sc_height-1) || header_lines > 0);
|
||||
#if HILITE_SEARCH
|
||||
if (pos != NULL_POSITION && (hilite_search == OPT_ONPLUS || is_filtering() || status_col)) {
|
||||
prep_hilite((pos < 3*size_linebuf) ? 0 : pos - 3*size_linebuf, pos, -1);
|
||||
}
|
||||
#endif
|
||||
while (--n >= 0)
|
||||
{
|
||||
/*
|
||||
* Get the previous line of input.
|
||||
*/
|
||||
#if HILITE_SEARCH
|
||||
pos = prev_unfiltered(pos);
|
||||
#endif
|
||||
|
||||
pos = back_line(pos);
|
||||
if (pos == NULL_POSITION)
|
||||
{
|
||||
/*
|
||||
* Beginning of file: stop here unless "force" is true.
|
||||
*/
|
||||
if (!force)
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Add the position of the previous line to the position table.
|
||||
* Display the line on the screen.
|
||||
*/
|
||||
add_back_pos(pos);
|
||||
nlines++;
|
||||
if (!do_repaint)
|
||||
{
|
||||
home();
|
||||
add_line();
|
||||
put_line();
|
||||
}
|
||||
}
|
||||
if (nlines == 0)
|
||||
eof_bell();
|
||||
else if (do_repaint)
|
||||
repaint();
|
||||
else
|
||||
{
|
||||
overlay_header();
|
||||
lower_left();
|
||||
}
|
||||
(void) currline(BOTTOM);
|
||||
}
|
||||
|
||||
/*
|
||||
* Display n more lines, forward.
|
||||
* Start just after the line currently displayed at the bottom of the screen.
|
||||
*/
|
||||
public void forward(int n, int force, int only_last)
|
||||
{
|
||||
POSITION pos;
|
||||
|
||||
if (get_quit_at_eof() && eof_displayed() && !(ch_getflags() & CH_HELPFILE))
|
||||
{
|
||||
/*
|
||||
* If the -e flag is set and we're trying to go
|
||||
* forward from end-of-file, go on to the next file.
|
||||
*/
|
||||
if (edit_next(1))
|
||||
quit(QUIT_OK);
|
||||
return;
|
||||
}
|
||||
|
||||
pos = position(BOTTOM_PLUS_ONE);
|
||||
if (pos == NULL_POSITION && (!force || empty_lines(2, sc_height-1)))
|
||||
{
|
||||
if (ignore_eoi)
|
||||
{
|
||||
/*
|
||||
* ignore_eoi is to support A_F_FOREVER.
|
||||
* Back up until there is a line at the bottom
|
||||
* of the screen.
|
||||
*/
|
||||
if (empty_screen())
|
||||
pos = ch_zero();
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
back(1, position(TOP), 1, 0);
|
||||
pos = position(BOTTOM_PLUS_ONE);
|
||||
} while (pos == NULL_POSITION && !ABORT_SIGS());
|
||||
}
|
||||
} else
|
||||
{
|
||||
eof_bell();
|
||||
return;
|
||||
}
|
||||
}
|
||||
forw(n, pos, force, only_last, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Display n more lines, backward.
|
||||
* Start just before the line currently displayed at the top of the screen.
|
||||
*/
|
||||
public void backward(int n, int force, int only_last)
|
||||
{
|
||||
POSITION pos;
|
||||
|
||||
pos = position(TOP);
|
||||
if (pos == NULL_POSITION && (!force || position(BOTTOM) == 0))
|
||||
{
|
||||
eof_bell();
|
||||
return;
|
||||
}
|
||||
back(n, pos, force, only_last);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the backwards scroll limit.
|
||||
* Must call this function instead of just using the value of
|
||||
* back_scroll, because the default case depends on sc_height and
|
||||
* top_scroll, as well as back_scroll.
|
||||
*/
|
||||
public int get_back_scroll(void)
|
||||
{
|
||||
if (no_back_scroll)
|
||||
return (0);
|
||||
if (back_scroll >= 0)
|
||||
return (back_scroll);
|
||||
if (top_scroll)
|
||||
return (sc_height - 2);
|
||||
return (10000); /* infinity */
|
||||
}
|
||||
|
||||
/*
|
||||
* Will the entire file fit on one screen?
|
||||
*/
|
||||
public int get_one_screen(void)
|
||||
{
|
||||
int nlines;
|
||||
POSITION pos = ch_zero();
|
||||
|
||||
for (nlines = 0; nlines < sc_height; nlines++)
|
||||
{
|
||||
pos = forw_line(pos);
|
||||
if (pos == NULL_POSITION) break;
|
||||
}
|
||||
return (nlines < sc_height);
|
||||
}
|
385
third_party/less/funcs.h
vendored
Normal file
385
third_party/less/funcs.h
vendored
Normal file
|
@ -0,0 +1,385 @@
|
|||
public char * save(constant char *s);
|
||||
public void out_of_memory(void);
|
||||
public void * ecalloc(int count, unsigned int size);
|
||||
public char * skipsp(char *s);
|
||||
public int sprefix(char *ps, char *s, int uppercase);
|
||||
public void quit(int status);
|
||||
public void raw_mode(int on);
|
||||
public void scrsize(void);
|
||||
public char * special_key_str(int key);
|
||||
public void get_term(void);
|
||||
public void init_mouse(void);
|
||||
public void deinit_mouse(void);
|
||||
public void init(void);
|
||||
public void deinit(void);
|
||||
public int interactive(void);
|
||||
public void home(void);
|
||||
public void dump_screen(void);
|
||||
public void add_line(void);
|
||||
public void remove_top(int n);
|
||||
public void win32_scroll_up(int n);
|
||||
public void lower_left(void);
|
||||
public void line_left(void);
|
||||
public void check_winch(void);
|
||||
public void goto_line(int sindex);
|
||||
public void vbell(void);
|
||||
public void bell(void);
|
||||
public void clear(void);
|
||||
public void clear_eol(void);
|
||||
public void clear_bot(void);
|
||||
public COLOR_TYPE parse_color(char *str, int *p_fg, int *p_bg);
|
||||
public void at_enter(int attr);
|
||||
public void at_exit(void);
|
||||
public void at_switch(int attr);
|
||||
public int is_at_equiv(int attr1, int attr2);
|
||||
public int apply_at_specials(int attr);
|
||||
public void putbs(void);
|
||||
public int win32_kbhit(void);
|
||||
public char WIN32getch(void);
|
||||
public void WIN32ungetch(int ch);
|
||||
public void WIN32setcolors(int fg, int bg);
|
||||
public void WIN32textout(char *text, int len);
|
||||
public void match_brac(char obrac, char cbrac, int forwdir, int n);
|
||||
public void ch_ungetchar(int c);
|
||||
public void end_logfile(void);
|
||||
public void sync_logfile(void);
|
||||
public int ch_seek(POSITION pos);
|
||||
public int ch_end_seek(void);
|
||||
public int ch_end_buffer_seek(void);
|
||||
public int ch_beg_seek(void);
|
||||
public POSITION ch_length(void);
|
||||
public POSITION ch_tell(void);
|
||||
public int ch_forw_get(void);
|
||||
public int ch_back_get(void);
|
||||
public void ch_setbufspace(int bufspace);
|
||||
public void ch_flush(void);
|
||||
public int seekable(int f);
|
||||
public void ch_set_eof(void);
|
||||
public void ch_init(int f, int flags);
|
||||
public void ch_close(void);
|
||||
public int ch_getflags(void);
|
||||
public void setfmt(char *s, char **fmtvarptr, int *attrptr, char *default_fmt, int for_printf);
|
||||
public void init_charset(void);
|
||||
public int binary_char(LWCHAR c);
|
||||
public int control_char(LWCHAR c);
|
||||
public char * prchar(LWCHAR c);
|
||||
public char * prutfchar(LWCHAR ch);
|
||||
public int utf_len(int ch);
|
||||
public int is_utf8_well_formed(char *ss, int slen);
|
||||
public void utf_skip_to_lead(char **pp, char *limit);
|
||||
public LWCHAR get_wchar(constant char *p);
|
||||
public void put_wchar(char **pp, LWCHAR ch);
|
||||
public LWCHAR step_char(char **pp, signed int dir, constant char *limit);
|
||||
public int is_composing_char(LWCHAR ch);
|
||||
public int is_ubin_char(LWCHAR ch);
|
||||
public int is_wide_char(LWCHAR ch);
|
||||
public int is_combining_char(LWCHAR ch1, LWCHAR ch2);
|
||||
public void cmd_reset(void);
|
||||
public void clear_cmd(void);
|
||||
public void cmd_putstr(constant char *s);
|
||||
public int len_cmdbuf(void);
|
||||
public void cmd_repaint(constant char *old_cp);
|
||||
public void set_mlist(void *mlist, int cmdflags);
|
||||
public void cmd_addhist(struct mlist *mlist, constant char *cmd, int modified);
|
||||
public void cmd_accept(void);
|
||||
public int cmd_char(int c);
|
||||
public LINENUM cmd_int(long *frac);
|
||||
public char * get_cmdbuf(void);
|
||||
public char * cmd_lastpattern(void);
|
||||
public void init_cmdhist(void);
|
||||
public void save_cmdhist(void);
|
||||
public int in_mca(void);
|
||||
public int norm_search_type(int st);
|
||||
public void dispversion(void);
|
||||
public int getcc(void);
|
||||
public void ungetcc(LWCHAR c);
|
||||
public void ungetcc_back(LWCHAR c);
|
||||
public void ungetsc(char *s);
|
||||
public LWCHAR peekcc(void);
|
||||
public void commands(void);
|
||||
public int cvt_length(int len, int ops);
|
||||
public int * cvt_alloc_chpos(int len);
|
||||
public void cvt_text(char *odst, char *osrc, int *chpos, int *lenp, int ops);
|
||||
public void expand_cmd_tables(void);
|
||||
public void init_cmds(void);
|
||||
public void add_fcmd_table(char *buf, int len);
|
||||
public void add_ecmd_table(char *buf, int len);
|
||||
public int fcmd_decode(char *cmd, char **sp);
|
||||
public int ecmd_decode(char *cmd, char **sp);
|
||||
public char * lgetenv(char *var);
|
||||
public int isnullenv(char *s);
|
||||
public int lesskey(char *filename, int sysvar);
|
||||
public int lesskey_src(char *filename, int sysvar);
|
||||
public int add_hometable(int (*call_lesskey)(char *, int), char *envname, char *def_filename, int sysvar);
|
||||
public int editchar(int c, int flags);
|
||||
public void init_textlist(struct textlist *tlist, char *str);
|
||||
public char * forw_textlist(struct textlist *tlist, char *prev);
|
||||
public char * back_textlist(struct textlist *tlist, char *prev);
|
||||
public void close_altpipe(IFILE ifile);
|
||||
public void check_altpipe_error(void);
|
||||
public int edit(char *filename);
|
||||
public int edit_ifile(IFILE ifile);
|
||||
public int edit_list(char *filelist);
|
||||
public int edit_first(void);
|
||||
public int edit_last(void);
|
||||
public int edit_next(int n);
|
||||
public int edit_prev(int n);
|
||||
public int edit_index(int n);
|
||||
public IFILE save_curr_ifile(void);
|
||||
public void unsave_ifile(IFILE save_ifile);
|
||||
public void reedit_ifile(IFILE save_ifile);
|
||||
public void reopen_curr_ifile(void);
|
||||
public int edit_stdin(void);
|
||||
public void cat_file(void);
|
||||
public void use_logfile(char *filename);
|
||||
public char * shell_unquote(char *str);
|
||||
public char * get_meta_escape(void);
|
||||
public char * shell_quote(char *s);
|
||||
public char * dirfile(char *dirname, char *filename, int must_exist);
|
||||
public char * homefile(char *filename);
|
||||
public char * fexpand(char *s);
|
||||
public char * fcomplete(char *s);
|
||||
public int bin_file(int f);
|
||||
public char * lglob(char *filename);
|
||||
public int is_fake_pathname(char *path);
|
||||
public char * lrealpath(char *path);
|
||||
public char * open_altfile(char *filename, int *pf, void **pfd);
|
||||
public void close_altfile(char *altfilename, char *filename);
|
||||
public int is_dir(char *filename);
|
||||
public char * bad_file(char *filename);
|
||||
public POSITION filesize(int f);
|
||||
public int curr_ifile_changed(void);
|
||||
public char * shell_coption(void);
|
||||
public char * last_component(char *name);
|
||||
public void eof_bell(void);
|
||||
public int eof_displayed(void);
|
||||
public int entire_file_displayed(void);
|
||||
public void squish_check(void);
|
||||
public int overlay_header(void);
|
||||
public void forw(int n, POSITION pos, int force, int only_last, int nblank);
|
||||
public void back(int n, POSITION pos, int force, int only_last);
|
||||
public void forward(int n, int force, int only_last);
|
||||
public void backward(int n, int force, int only_last);
|
||||
public int get_back_scroll(void);
|
||||
public int get_one_screen(void);
|
||||
public void del_ifile(IFILE h);
|
||||
public IFILE next_ifile(IFILE h);
|
||||
public IFILE prev_ifile(IFILE h);
|
||||
public IFILE getoff_ifile(IFILE ifile);
|
||||
public int nifile(void);
|
||||
public IFILE get_ifile(char *filename, IFILE prev);
|
||||
public char * get_filename(IFILE ifile);
|
||||
public char * get_real_filename(IFILE ifile);
|
||||
public int get_index(IFILE ifile);
|
||||
public void store_pos(IFILE ifile, struct scrpos *scrpos);
|
||||
public void get_pos(IFILE ifile, struct scrpos *scrpos);
|
||||
public void set_open(IFILE ifile);
|
||||
public int opened(IFILE ifile);
|
||||
public void hold_ifile(IFILE ifile, int incr);
|
||||
public int held_ifile(IFILE ifile);
|
||||
public void * get_filestate(IFILE ifile);
|
||||
public void set_filestate(IFILE ifile, void *filestate);
|
||||
public void set_altpipe(IFILE ifile, void *p);
|
||||
public void *get_altpipe(IFILE ifile);
|
||||
public void set_altfilename(IFILE ifile, char *altfilename);
|
||||
public char * get_altfilename(IFILE ifile);
|
||||
public void if_dump(void);
|
||||
public POSITION forw_line_seg(POSITION curr_pos, int skipeol, int rscroll, int nochop);
|
||||
public POSITION forw_line(POSITION curr_pos);
|
||||
public POSITION back_line(POSITION curr_pos);
|
||||
public void set_attnpos(POSITION pos);
|
||||
public void jump_forw(void);
|
||||
public void jump_forw_buffered(void);
|
||||
public void jump_back(LINENUM linenum);
|
||||
public void repaint(void);
|
||||
public void jump_percent(int percent, long fraction);
|
||||
public void jump_line_loc(POSITION pos, int sline);
|
||||
public void jump_loc(POSITION pos, int sline);
|
||||
public void init_line(void);
|
||||
public int is_ascii_char(LWCHAR ch);
|
||||
public POSITION line_position(void);
|
||||
public void prewind(void);
|
||||
public void plinestart(POSITION pos);
|
||||
public int line_pfx_width(void);
|
||||
public void pshift_all(void);
|
||||
public int pwidth(LWCHAR ch, int a, LWCHAR prev_ch, int prev_a);
|
||||
public void savec(void);
|
||||
public void loadc(void);
|
||||
public int is_ansi_end(LWCHAR ch);
|
||||
public int is_ansi_middle(LWCHAR ch);
|
||||
public void skip_ansi(struct ansi_state *pansi, char **pp, constant char *limit);
|
||||
public struct ansi_state * ansi_start(LWCHAR ch);
|
||||
public int ansi_step(struct ansi_state *pansi, LWCHAR ch);
|
||||
public void ansi_done(struct ansi_state *pansi);
|
||||
public int pappend(int c, POSITION pos);
|
||||
public int pflushmbc(void);
|
||||
public void pdone(int endline, int chopped, int forw);
|
||||
public void set_attr_line(int a);
|
||||
public void set_status_col(char c, int attr);
|
||||
public int gline(int i, int *ap);
|
||||
public void null_line(void);
|
||||
public POSITION forw_raw_line(POSITION curr_pos, char **linep, int *line_lenp);
|
||||
public POSITION back_raw_line(POSITION curr_pos, char **linep, int *line_lenp);
|
||||
public int skip_columns(int cols, char **linep, int *line_lenp);
|
||||
public void load_line(constant char *str);
|
||||
public int rrshift(void);
|
||||
public int set_color_map(int attr, char *colorstr);
|
||||
public char * get_color_map(int attr);
|
||||
public void clr_linenum(void);
|
||||
public void add_lnum(LINENUM linenum, POSITION pos);
|
||||
public LINENUM find_linenum(POSITION pos);
|
||||
public POSITION find_pos(LINENUM linenum);
|
||||
public LINENUM currline(int where);
|
||||
public void scan_eof(void);
|
||||
public LINENUM vlinenum(LINENUM linenum);
|
||||
public void lsystem(char *cmd, char *donemsg);
|
||||
public int pipe_mark(int c, char *cmd);
|
||||
public int pipe_data(char *cmd, POSITION spos, POSITION epos);
|
||||
public void init_mark(void);
|
||||
public int badmark(LWCHAR c);
|
||||
public void setmark(LWCHAR c, int where);
|
||||
public void clrmark(LWCHAR c);
|
||||
public void lastmark(void);
|
||||
public void gomark(LWCHAR c);
|
||||
public POSITION markpos(LWCHAR c);
|
||||
public char posmark(POSITION pos);
|
||||
public void unmark(IFILE ifile);
|
||||
public void mark_check_ifile(IFILE ifile);
|
||||
public void save_marks(FILE *fout, char *hdr);
|
||||
public void restore_mark(char *line);
|
||||
public void opt_o(int type, char *s);
|
||||
public void opt__O(int type, char *s);
|
||||
public void opt_j(int type, char *s);
|
||||
public void calc_jump_sline(void);
|
||||
public void opt_shift(int type, char *s);
|
||||
public void calc_shift_count(void);
|
||||
public void opt_k(int type, char *s);
|
||||
public void opt_ks(int type, char *s);
|
||||
public void opt_t(int type, char *s);
|
||||
public void opt__T(int type, char *s);
|
||||
public void opt_p(int type, char *s);
|
||||
public void opt__P(int type, char *s);
|
||||
public void opt_b(int type, char *s);
|
||||
public void opt_i(int type, char *s);
|
||||
public void opt__V(int type, char *s);
|
||||
public void opt_D(int type, char *s);
|
||||
public void set_tabs(char *s, int len);
|
||||
public void opt_x(int type, char *s);
|
||||
public void opt_quote(int type, char *s);
|
||||
public void opt_rscroll(int type, char *s);
|
||||
public void opt_query(int type, char *s);
|
||||
public void opt_mousecap(int type, char *s);
|
||||
public void opt_wheel_lines(int type, char *s);
|
||||
public void opt_linenum_width(int type, char *s);
|
||||
public void opt_status_col_width(int type, char *s);
|
||||
public void opt_filesize(int type, char *s);
|
||||
public void opt_intr(int type, char *s);
|
||||
public void opt_header(int type, char *s);
|
||||
public void opt_search_type(int type, char *s);
|
||||
public void opt_ttyin_name(int type, char *s);
|
||||
public int chop_line(void);
|
||||
public int get_swindow(void);
|
||||
public char * propt(int c);
|
||||
public void scan_option(char *s);
|
||||
public void toggle_option(struct loption *o, int lower, char *s, int how_toggle);
|
||||
public int opt_has_param(struct loption *o);
|
||||
public char * opt_prompt(struct loption *o);
|
||||
public char * opt_toggle_disallowed(int c);
|
||||
public int isoptpending(void);
|
||||
public void nopendopt(void);
|
||||
public int getnum(char **sp, char *printopt, int *errp);
|
||||
public long getfraction(char **sp, char *printopt, int *errp);
|
||||
public int get_quit_at_eof(void);
|
||||
public void init_option(void);
|
||||
public struct loption * findopt(int c);
|
||||
public struct loption * findopt_name(char **p_optname, char **p_oname, int *p_err);
|
||||
public void init_poll(void);
|
||||
public int supports_ctrl_x(void);
|
||||
public int iread(int fd, unsigned char *buf, unsigned int len);
|
||||
public void intread(void);
|
||||
public time_type get_time(void);
|
||||
public char * errno_message(char *filename);
|
||||
public char * signal_message(int sig);
|
||||
public uintmax muldiv(uintmax val, uintmax num, uintmax den);
|
||||
public int percentage(POSITION num, POSITION den);
|
||||
public POSITION percent_pos(POSITION pos, int percent, long fraction);
|
||||
public int os9_signal(int type, RETSIGTYPE (*handler)());
|
||||
public void sleep_ms(int ms);
|
||||
public void put_line(void);
|
||||
public void flush(void);
|
||||
public void set_output(int fd);
|
||||
public int putchr(int c);
|
||||
public void clear_bot_if_needed(void);
|
||||
public void putstr(constant char *s);
|
||||
public int less_printf(char *fmt, PARG *parg);
|
||||
public void get_return(void);
|
||||
public void error(char *fmt, PARG *parg);
|
||||
public void ierror(char *fmt, PARG *parg);
|
||||
public void ixerror(char *fmt, PARG *parg);
|
||||
public int query(char *fmt, PARG *parg);
|
||||
public int compile_pattern(char *pattern, int search_type, int show_error, PATTERN_TYPE *comp_pattern);
|
||||
public void uncompile_pattern(PATTERN_TYPE *pattern);
|
||||
public int valid_pattern(char *pattern);
|
||||
public int is_null_pattern(PATTERN_TYPE pattern);
|
||||
public int match_pattern(PATTERN_TYPE pattern, char *tpattern, char *line, int line_len, char **sp, char **ep, int nsp, int notbol, int search_type);
|
||||
public char * pattern_lib_name(void);
|
||||
public POSITION position(int sindex);
|
||||
public void add_forw_pos(POSITION pos);
|
||||
public void add_back_pos(POSITION pos);
|
||||
public void pos_clear(void);
|
||||
public void pos_init(void);
|
||||
public int onscreen(POSITION pos);
|
||||
public int empty_screen(void);
|
||||
public int empty_lines(int s, int e);
|
||||
public void get_scrpos(struct scrpos *scrpos, int where);
|
||||
public int sindex_from_sline(int sline);
|
||||
public void init_prompt(void);
|
||||
public char * pr_expand(constant char *proto);
|
||||
public char * eq_message(void);
|
||||
public char * pr_string(void);
|
||||
public char * wait_message(void);
|
||||
public void init_search(void);
|
||||
public void repaint_hilite(int on);
|
||||
public void clear_attn(void);
|
||||
public void undo_search(int clear);
|
||||
public void clr_hlist(struct hilite_tree *anchor);
|
||||
public void clr_hilite(void);
|
||||
public void clr_filter(void);
|
||||
public int is_filtered(POSITION pos);
|
||||
public POSITION next_unfiltered(POSITION pos);
|
||||
public POSITION prev_unfiltered(POSITION pos);
|
||||
public int is_hilited_attr(POSITION pos, POSITION epos, int nohide, int *p_matches);
|
||||
public void chg_hilite(void);
|
||||
public void chg_caseless(void);
|
||||
public int search(int search_type, char *pattern, int n);
|
||||
public void prep_hilite(POSITION spos, POSITION epos, int maxlines);
|
||||
public void set_filter_pattern(char *pattern, int search_type);
|
||||
public int is_filtering(void);
|
||||
public RETSIGTYPE winch(int type);
|
||||
public void init_signals(int on);
|
||||
public void psignals(void);
|
||||
public void cleantags(void);
|
||||
public int gettagtype(void);
|
||||
public void findtag(char *tag);
|
||||
public POSITION tagsearch(void);
|
||||
public char * nexttag(int n);
|
||||
public char * prevtag(int n);
|
||||
public int ntags(void);
|
||||
public int curr_tag(void);
|
||||
public int edit_tagfile(void);
|
||||
public int open_tty(void);
|
||||
public void open_getchr(void);
|
||||
public void close_getchr(void);
|
||||
public int pclose(FILE *f);
|
||||
public int default_wheel_lines(void);
|
||||
public int getchr(void);
|
||||
public void xbuf_init(struct xbuffer *xbuf);
|
||||
public void xbuf_deinit(struct xbuffer *xbuf);
|
||||
public void xbuf_reset(struct xbuffer *xbuf);
|
||||
public void xbuf_add_byte(struct xbuffer *xbuf, unsigned char b);
|
||||
public void xbuf_add_data(struct xbuffer *xbuf, unsigned char *data, int len);
|
||||
public int xbuf_pop(struct xbuffer *buf);
|
||||
public void xbuf_set(struct xbuffer *dst, struct xbuffer *src);
|
||||
public char * xbuf_char_data(struct xbuffer *xbuf);
|
||||
public int help_ckd_add(void *r, uintmax a, uintmax b, int rsize, int rsigned);
|
||||
public int help_ckd_mul(void *r, uintmax a, uintmax b, int rsize, int rsigned);
|
303
third_party/less/help.c
vendored
Normal file
303
third_party/less/help.c
vendored
Normal file
|
@ -0,0 +1,303 @@
|
|||
/* This file was generated by mkhelp.pl from less.hlp at 22:43 on 2023/7/20 */
|
||||
#include "less.h"
|
||||
constant char helpdata[] = {
|
||||
'\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','\b','S','U','\b','U','M','\b','M','M','\b','M','A','\b','A','R','\b','R','Y','\b','Y',' ','O','\b','O','F','\b','F',' ','L','\b','L','E','\b','E','S','\b','S','S','\b','S',' ','C','\b','C','O','\b','O','M','\b','M','M','\b','M','A','\b','A','N','\b','N','D','\b','D','S','\b','S','\n',
|
||||
'\n',
|
||||
' ',' ',' ',' ',' ',' ','C','o','m','m','a','n','d','s',' ','m','a','r','k','e','d',' ','w','i','t','h',' ','*',' ','m','a','y',' ','b','e',' ','p','r','e','c','e','d','e','d',' ','b','y',' ','a',' ','n','u','m','b','e','r',',',' ','_','\b','N','.','\n',
|
||||
' ',' ',' ',' ',' ',' ','N','o','t','e','s',' ','i','n',' ','p','a','r','e','n','t','h','e','s','e','s',' ','i','n','d','i','c','a','t','e',' ','t','h','e',' ','b','e','h','a','v','i','o','r',' ','i','f',' ','_','\b','N',' ','i','s',' ','g','i','v','e','n','.','\n',
|
||||
' ',' ',' ',' ',' ',' ','A',' ','k','e','y',' ','p','r','e','c','e','d','e','d',' ','b','y',' ','a',' ','c','a','r','e','t',' ','i','n','d','i','c','a','t','e','s',' ','t','h','e',' ','C','t','r','l',' ','k','e','y',';',' ','t','h','u','s',' ','^','K',' ','i','s',' ','c','t','r','l','-','K','.','\n',
|
||||
'\n',
|
||||
' ',' ','h',' ',' ','H',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','i','s','p','l','a','y',' ','t','h','i','s',' ','h','e','l','p','.','\n',
|
||||
' ',' ','q',' ',' ',':','q',' ',' ','Q',' ',' ',':','Q',' ',' ','Z','Z',' ',' ',' ',' ',' ','E','x','i','t','.','\n',
|
||||
' ','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\n',
|
||||
'\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','M','\b','M','O','\b','O','V','\b','V','I','\b','I','N','\b','N','G','\b','G','\n',
|
||||
'\n',
|
||||
' ',' ','e',' ',' ','^','E',' ',' ','j',' ',' ','^','N',' ',' ','C','R',' ',' ','*',' ',' ','F','o','r','w','a','r','d',' ',' ','o','n','e',' ','l','i','n','e',' ',' ',' ','(','o','r',' ','_','\b','N',' ','l','i','n','e','s',')','.','\n',
|
||||
' ',' ','y',' ',' ','^','Y',' ',' ','k',' ',' ','^','K',' ',' ','^','P',' ',' ','*',' ',' ','B','a','c','k','w','a','r','d',' ','o','n','e',' ','l','i','n','e',' ',' ',' ','(','o','r',' ','_','\b','N',' ','l','i','n','e','s',')','.','\n',
|
||||
' ',' ','f',' ',' ','^','F',' ',' ','^','V',' ',' ','S','P','A','C','E',' ',' ','*',' ',' ','F','o','r','w','a','r','d',' ',' ','o','n','e',' ','w','i','n','d','o','w',' ','(','o','r',' ','_','\b','N',' ','l','i','n','e','s',')','.','\n',
|
||||
' ',' ','b',' ',' ','^','B',' ',' ','E','S','C','-','v',' ',' ',' ',' ',' ',' ','*',' ',' ','B','a','c','k','w','a','r','d',' ','o','n','e',' ','w','i','n','d','o','w',' ','(','o','r',' ','_','\b','N',' ','l','i','n','e','s',')','.','\n',
|
||||
' ',' ','z',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','F','o','r','w','a','r','d',' ',' ','o','n','e',' ','w','i','n','d','o','w',' ','(','a','n','d',' ','s','e','t',' ','w','i','n','d','o','w',' ','t','o',' ','_','\b','N',')','.','\n',
|
||||
' ',' ','w',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','B','a','c','k','w','a','r','d',' ','o','n','e',' ','w','i','n','d','o','w',' ','(','a','n','d',' ','s','e','t',' ','w','i','n','d','o','w',' ','t','o',' ','_','\b','N',')','.','\n',
|
||||
' ',' ','E','S','C','-','S','P','A','C','E',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','F','o','r','w','a','r','d',' ',' ','o','n','e',' ','w','i','n','d','o','w',',',' ','b','u','t',' ','d','o','n','\'','t',' ','s','t','o','p',' ','a','t',' ','e','n','d','-','o','f','-','f','i','l','e','.','\n',
|
||||
' ',' ','d',' ',' ','^','D',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','F','o','r','w','a','r','d',' ',' ','o','n','e',' ','h','a','l','f','-','w','i','n','d','o','w',' ','(','a','n','d',' ','s','e','t',' ','h','a','l','f','-','w','i','n','d','o','w',' ','t','o',' ','_','\b','N',')','.','\n',
|
||||
' ',' ','u',' ',' ','^','U',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','B','a','c','k','w','a','r','d',' ','o','n','e',' ','h','a','l','f','-','w','i','n','d','o','w',' ','(','a','n','d',' ','s','e','t',' ','h','a','l','f','-','w','i','n','d','o','w',' ','t','o',' ','_','\b','N',')','.','\n',
|
||||
' ',' ','E','S','C','-',')',' ',' ','R','i','g','h','t','A','r','r','o','w',' ','*',' ',' ','R','i','g','h','t',' ','o','n','e',' ','h','a','l','f',' ','s','c','r','e','e','n',' ','w','i','d','t','h',' ','(','o','r',' ','_','\b','N',' ','p','o','s','i','t','i','o','n','s',')','.','\n',
|
||||
' ',' ','E','S','C','-','(',' ',' ','L','e','f','t','A','r','r','o','w',' ',' ','*',' ',' ','L','e','f','t',' ',' ','o','n','e',' ','h','a','l','f',' ','s','c','r','e','e','n',' ','w','i','d','t','h',' ','(','o','r',' ','_','\b','N',' ','p','o','s','i','t','i','o','n','s',')','.','\n',
|
||||
' ',' ','E','S','C','-','}',' ',' ','^','R','i','g','h','t','A','r','r','o','w',' ',' ',' ','R','i','g','h','t',' ','t','o',' ','l','a','s','t',' ','c','o','l','u','m','n',' ','d','i','s','p','l','a','y','e','d','.','\n',
|
||||
' ',' ','E','S','C','-','{',' ',' ','^','L','e','f','t','A','r','r','o','w',' ',' ',' ',' ','L','e','f','t',' ',' ','t','o',' ','f','i','r','s','t',' ','c','o','l','u','m','n','.','\n',
|
||||
' ',' ','F',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','F','o','r','w','a','r','d',' ','f','o','r','e','v','e','r',';',' ','l','i','k','e',' ','"','t','a','i','l',' ','-','f','"','.','\n',
|
||||
' ',' ','E','S','C','-','F',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','L','i','k','e',' ','F',' ','b','u','t',' ','s','t','o','p',' ','w','h','e','n',' ','s','e','a','r','c','h',' ','p','a','t','t','e','r','n',' ','i','s',' ','f','o','u','n','d','.','\n',
|
||||
' ',' ','r',' ',' ','^','R',' ',' ','^','L',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','R','e','p','a','i','n','t',' ','s','c','r','e','e','n','.','\n',
|
||||
' ',' ','R',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','R','e','p','a','i','n','t',' ','s','c','r','e','e','n',',',' ','d','i','s','c','a','r','d','i','n','g',' ','b','u','f','f','e','r','e','d',' ','i','n','p','u','t','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ','D','e','f','a','u','l','t',' ','"','w','i','n','d','o','w','"',' ','i','s',' ','t','h','e',' ','s','c','r','e','e','n',' ','h','e','i','g','h','t','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ','D','e','f','a','u','l','t',' ','"','h','a','l','f','-','w','i','n','d','o','w','"',' ','i','s',' ','h','a','l','f',' ','o','f',' ','t','h','e',' ','s','c','r','e','e','n',' ','h','e','i','g','h','t','.','\n',
|
||||
' ','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\n',
|
||||
'\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','\b','S','E','\b','E','A','\b','A','R','\b','R','C','\b','C','H','\b','H','I','\b','I','N','\b','N','G','\b','G','\n',
|
||||
'\n',
|
||||
' ',' ','/','_','\b','p','_','\b','a','_','\b','t','_','\b','t','_','\b','e','_','\b','r','_','\b','n',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','S','e','a','r','c','h',' ','f','o','r','w','a','r','d',' ','f','o','r',' ','(','_','\b','N','-','t','h',')',' ','m','a','t','c','h','i','n','g',' ','l','i','n','e','.','\n',
|
||||
' ',' ','?','_','\b','p','_','\b','a','_','\b','t','_','\b','t','_','\b','e','_','\b','r','_','\b','n',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','S','e','a','r','c','h',' ','b','a','c','k','w','a','r','d',' ','f','o','r',' ','(','_','\b','N','-','t','h',')',' ','m','a','t','c','h','i','n','g',' ','l','i','n','e','.','\n',
|
||||
' ',' ','n',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','R','e','p','e','a','t',' ','p','r','e','v','i','o','u','s',' ','s','e','a','r','c','h',' ','(','f','o','r',' ','_','\b','N','-','t','h',' ','o','c','c','u','r','r','e','n','c','e',')','.','\n',
|
||||
' ',' ','N',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','R','e','p','e','a','t',' ','p','r','e','v','i','o','u','s',' ','s','e','a','r','c','h',' ','i','n',' ','r','e','v','e','r','s','e',' ','d','i','r','e','c','t','i','o','n','.','\n',
|
||||
' ',' ','E','S','C','-','n',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','R','e','p','e','a','t',' ','p','r','e','v','i','o','u','s',' ','s','e','a','r','c','h',',',' ','s','p','a','n','n','i','n','g',' ','f','i','l','e','s','.','\n',
|
||||
' ',' ','E','S','C','-','N',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','R','e','p','e','a','t',' ','p','r','e','v','i','o','u','s',' ','s','e','a','r','c','h',',',' ','r','e','v','e','r','s','e',' ','d','i','r','.',' ','&',' ','s','p','a','n','n','i','n','g',' ','f','i','l','e','s','.','\n',
|
||||
' ',' ','E','S','C','-','u',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','U','n','d','o',' ','(','t','o','g','g','l','e',')',' ','s','e','a','r','c','h',' ','h','i','g','h','l','i','g','h','t','i','n','g','.','\n',
|
||||
' ',' ','E','S','C','-','U',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','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',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ','^','E',' ','o','r',' ','*',' ',' ','S','e','a','r','c','h',' ','m','u','l','t','i','p','l','e',' ','f','i','l','e','s',' ','(','p','a','s','s',' ','t','h','r','u',' ','E','N','D',' ','O','F',' ','F','I','L','E',')','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ','^','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',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ','^','S',' ','_','\b','n',' ',' ',' ',' ',' ','S','e','a','r','c','h',' ','f','o','r',' ','m','a','t','c','h',' ','i','n',' ','_','\b','n','-','t','h',' ','p','a','r','e','n','t','h','e','s','i','z','e','d',' ','s','u','b','p','a','t','t','e','r','n','.','\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',
|
||||
'\n',
|
||||
' ',' ','g',' ',' ','<',' ',' ','E','S','C','-','<',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','G','o',' ','t','o',' ','f','i','r','s','t',' ','l','i','n','e',' ','i','n',' ','f','i','l','e',' ','(','o','r',' ','l','i','n','e',' ','_','\b','N',')','.','\n',
|
||||
' ',' ','G',' ',' ','>',' ',' ','E','S','C','-','>',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','G','o',' ','t','o',' ','l','a','s','t',' ','l','i','n','e',' ','i','n',' ','f','i','l','e',' ','(','o','r',' ','l','i','n','e',' ','_','\b','N',')','.','\n',
|
||||
' ',' ','p',' ',' ','%',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','G','o',' ','t','o',' ','b','e','g','i','n','n','i','n','g',' ','o','f',' ','f','i','l','e',' ','(','o','r',' ','_','\b','N',' ','p','e','r','c','e','n','t',' ','i','n','t','o',' ','f','i','l','e',')','.','\n',
|
||||
' ',' ','t',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','G','o',' ','t','o',' ','t','h','e',' ','(','_','\b','N','-','t','h',')',' ','n','e','x','t',' ','t','a','g','.','\n',
|
||||
' ',' ','T',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','G','o',' ','t','o',' ','t','h','e',' ','(','_','\b','N','-','t','h',')',' ','p','r','e','v','i','o','u','s',' ','t','a','g','.','\n',
|
||||
' ',' ','{',' ',' ','(',' ',' ','[',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','F','i','n','d',' ','c','l','o','s','e',' ','b','r','a','c','k','e','t',' ','}',' ',')',' ',']','.','\n',
|
||||
' ',' ','}',' ',' ',')',' ',' ',']',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','F','i','n','d',' ','o','p','e','n',' ','b','r','a','c','k','e','t',' ','{',' ','(',' ','[','.','\n',
|
||||
' ',' ','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',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\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',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ','E','a','c','h',' ','"','f','i','n','d',' ','o','p','e','n',' ','b','r','a','c','k','e','t','"',' ','c','o','m','m','a','n','d',' ','g','o','e','s',' ','b','a','c','k','w','a','r','d',' ','t','o',' ','t','h','e',' ','o','p','e','n',' ','b','r','a','c','k','e','t',' ','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','m','a','t','c','h','i','n','g',' ','t','h','e',' ','(','_','\b','N','-','t','h',')',' ','c','l','o','s','e',' ','b','r','a','c','k','e','t',' ','i','n',' ','t','h','e',' ','b','o','t','t','o','m',' ','l','i','n','e','.','\n',
|
||||
'\n',
|
||||
' ',' ','m','_','\b','<','_','\b','l','_','\b','e','_','\b','t','_','\b','t','_','\b','e','_','\b','r','_','\b','>',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','M','a','r','k',' ','t','h','e',' ','c','u','r','r','e','n','t',' ','t','o','p',' ','l','i','n','e',' ','w','i','t','h',' ','<','l','e','t','t','e','r','>','.','\n',
|
||||
' ',' ','M','_','\b','<','_','\b','l','_','\b','e','_','\b','t','_','\b','t','_','\b','e','_','\b','r','_','\b','>',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','M','a','r','k',' ','t','h','e',' ','c','u','r','r','e','n','t',' ','b','o','t','t','o','m',' ','l','i','n','e',' ','w','i','t','h',' ','<','l','e','t','t','e','r','>','.','\n',
|
||||
' ',' ','\'','_','\b','<','_','\b','l','_','\b','e','_','\b','t','_','\b','t','_','\b','e','_','\b','r','_','\b','>',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','G','o',' ','t','o',' ','a',' ','p','r','e','v','i','o','u','s','l','y',' ','m','a','r','k','e','d',' ','p','o','s','i','t','i','o','n','.','\n',
|
||||
' ',' ','\'','\'',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','G','o',' ','t','o',' ','t','h','e',' ','p','r','e','v','i','o','u','s',' ','p','o','s','i','t','i','o','n','.','\n',
|
||||
' ',' ','^','X','^','X',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','a','m','e',' ','a','s',' ','\'','.','\n',
|
||||
' ',' ','E','S','C','-','m','_','\b','<','_','\b','l','_','\b','e','_','\b','t','_','\b','t','_','\b','e','_','\b','r','_','\b','>',' ',' ',' ',' ',' ',' ',' ',' ','C','l','e','a','r',' ','a',' ','m','a','r','k','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ','A',' ','m','a','r','k',' ','i','s',' ','a','n','y',' ','u','p','p','e','r','-','c','a','s','e',' ','o','r',' ','l','o','w','e','r','-','c','a','s','e',' ','l','e','t','t','e','r','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ','C','e','r','t','a','i','n',' ','m','a','r','k','s',' ','a','r','e',' ','p','r','e','d','e','f','i','n','e','d',':','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','^',' ',' ','m','e','a','n','s',' ',' ','b','e','g','i','n','n','i','n','g',' ','o','f',' ','t','h','e',' ','f','i','l','e','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','$',' ',' ','m','e','a','n','s',' ',' ','e','n','d',' ','o','f',' ','t','h','e',' ','f','i','l','e','\n',
|
||||
' ','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\n',
|
||||
'\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','C','\b','C','H','\b','H','A','\b','A','N','\b','N','G','\b','G','I','\b','I','N','\b','N','G','\b','G',' ','F','\b','F','I','\b','I','L','\b','L','E','\b','E','S','\b','S','\n',
|
||||
'\n',
|
||||
' ',' ',':','e',' ','[','_','\b','f','_','\b','i','_','\b','l','_','\b','e',']',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','E','x','a','m','i','n','e',' ','a',' ','n','e','w',' ','f','i','l','e','.','\n',
|
||||
' ',' ','^','X','^','V',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','a','m','e',' ','a','s',' ',':','e','.','\n',
|
||||
' ',' ',':','n',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','E','x','a','m','i','n','e',' ','t','h','e',' ','(','_','\b','N','-','t','h',')',' ','n','e','x','t',' ','f','i','l','e',' ','f','r','o','m',' ','t','h','e',' ','c','o','m','m','a','n','d',' ','l','i','n','e','.','\n',
|
||||
' ',' ',':','p',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','E','x','a','m','i','n','e',' ','t','h','e',' ','(','_','\b','N','-','t','h',')',' ','p','r','e','v','i','o','u','s',' ','f','i','l','e',' ','f','r','o','m',' ','t','h','e',' ','c','o','m','m','a','n','d',' ','l','i','n','e','.','\n',
|
||||
' ',' ',':','x',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','E','x','a','m','i','n','e',' ','t','h','e',' ','f','i','r','s','t',' ','(','o','r',' ','_','\b','N','-','t','h',')',' ','f','i','l','e',' ','f','r','o','m',' ','t','h','e',' ','c','o','m','m','a','n','d',' ','l','i','n','e','.','\n',
|
||||
' ',' ',':','d',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','e','l','e','t','e',' ','t','h','e',' ','c','u','r','r','e','n','t',' ','f','i','l','e',' ','f','r','o','m',' ','t','h','e',' ','c','o','m','m','a','n','d',' ','l','i','n','e',' ','l','i','s','t','.','\n',
|
||||
' ',' ','=',' ',' ','^','G',' ',' ',':','f',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','P','r','i','n','t',' ','c','u','r','r','e','n','t',' ','f','i','l','e',' ','n','a','m','e','.','\n',
|
||||
' ','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\n',
|
||||
'\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','M','\b','M','I','\b','I','S','\b','S','C','\b','C','E','\b','E','L','\b','L','L','\b','L','A','\b','A','N','\b','N','E','\b','E','O','\b','O','U','\b','U','S','\b','S',' ','C','\b','C','O','\b','O','M','\b','M','M','\b','M','A','\b','A','N','\b','N','D','\b','D','S','\b','S','\n',
|
||||
'\n',
|
||||
' ',' ','-','_','\b','<','_','\b','f','_','\b','l','_','\b','a','_','\b','g','_','\b','>',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','T','o','g','g','l','e',' ','a',' ','c','o','m','m','a','n','d',' ','l','i','n','e',' ','o','p','t','i','o','n',' ','[','s','e','e',' ','O','P','T','I','O','N','S',' ','b','e','l','o','w',']','.','\n',
|
||||
' ',' ','-','-','_','\b','<','_','\b','n','_','\b','a','_','\b','m','_','\b','e','_','\b','>',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','T','o','g','g','l','e',' ','a',' ','c','o','m','m','a','n','d',' ','l','i','n','e',' ','o','p','t','i','o','n',',',' ','b','y',' ','n','a','m','e','.','\n',
|
||||
' ',' ','_','_','\b','<','_','\b','f','_','\b','l','_','\b','a','_','\b','g','_','\b','>',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','i','s','p','l','a','y',' ','t','h','e',' ','s','e','t','t','i','n','g',' ','o','f',' ','a',' ','c','o','m','m','a','n','d',' ','l','i','n','e',' ','o','p','t','i','o','n','.','\n',
|
||||
' ',' ','_','_','_','\b','<','_','\b','n','_','\b','a','_','\b','m','_','\b','e','_','\b','>',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','i','s','p','l','a','y',' ','t','h','e',' ','s','e','t','t','i','n','g',' ','o','f',' ','a','n',' ','o','p','t','i','o','n',',',' ','b','y',' ','n','a','m','e','.','\n',
|
||||
' ',' ','+','_','\b','c','_','\b','m','_','\b','d',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','E','x','e','c','u','t','e',' ','t','h','e',' ','l','e','s','s',' ','c','m','d',' ','e','a','c','h',' ','t','i','m','e',' ','a',' ','n','e','w',' ','f','i','l','e',' ','i','s',' ','e','x','a','m','i','n','e','d','.','\n',
|
||||
'\n',
|
||||
' ',' ','!','_','\b','c','_','\b','o','_','\b','m','_','\b','m','_','\b','a','_','\b','n','_','\b','d',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','E','x','e','c','u','t','e',' ','t','h','e',' ','s','h','e','l','l',' ','c','o','m','m','a','n','d',' ','w','i','t','h',' ','$','S','H','E','L','L','.','\n',
|
||||
' ',' ','#','_','\b','c','_','\b','o','_','\b','m','_','\b','m','_','\b','a','_','\b','n','_','\b','d',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','E','x','e','c','u','t','e',' ','t','h','e',' ','s','h','e','l','l',' ','c','o','m','m','a','n','d',',',' ','e','x','p','a','n','d','e','d',' ','l','i','k','e',' ','a',' ','p','r','o','m','p','t','.','\n',
|
||||
' ',' ','|','X','\b','X','_','\b','c','_','\b','o','_','\b','m','_','\b','m','_','\b','a','_','\b','n','_','\b','d',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','P','i','p','e',' ','f','i','l','e',' ','b','e','t','w','e','e','n',' ','c','u','r','r','e','n','t',' ','p','o','s',' ','&',' ','m','a','r','k',' ','X','\b','X',' ','t','o',' ','s','h','e','l','l',' ','c','o','m','m','a','n','d','.','\n',
|
||||
' ',' ','s',' ','_','\b','f','_','\b','i','_','\b','l','_','\b','e',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','a','v','e',' ','i','n','p','u','t',' ','t','o',' ','a',' ','f','i','l','e','.','\n',
|
||||
' ',' ','v',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','E','d','i','t',' ','t','h','e',' ','c','u','r','r','e','n','t',' ','f','i','l','e',' ','w','i','t','h',' ','$','V','I','S','U','A','L',' ','o','r',' ','$','E','D','I','T','O','R','.','\n',
|
||||
' ',' ','V',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','P','r','i','n','t',' ','v','e','r','s','i','o','n',' ','n','u','m','b','e','r',' ','o','f',' ','"','l','e','s','s','"','.','\n',
|
||||
' ','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\n',
|
||||
'\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','O','\b','O','P','\b','P','T','\b','T','I','\b','I','O','\b','O','N','\b','N','S','\b','S','\n',
|
||||
'\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ','M','o','s','t',' ','o','p','t','i','o','n','s',' ','m','a','y',' ','b','e',' ','c','h','a','n','g','e','d',' ','e','i','t','h','e','r',' ','o','n',' ','t','h','e',' ','c','o','m','m','a','n','d',' ','l','i','n','e',',','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ','o','r',' ','f','r','o','m',' ','w','i','t','h','i','n',' ','l','e','s','s',' ','b','y',' ','u','s','i','n','g',' ','t','h','e',' ','-',' ','o','r',' ','-','-',' ','c','o','m','m','a','n','d','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ','O','p','t','i','o','n','s',' ','m','a','y',' ','b','e',' ','g','i','v','e','n',' ','i','n',' ','o','n','e',' ','o','f',' ','t','w','o',' ','f','o','r','m','s',':',' ','e','i','t','h','e','r',' ','a',' ','s','i','n','g','l','e','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ','c','h','a','r','a','c','t','e','r',' ','p','r','e','c','e','d','e','d',' ','b','y',' ','a',' ','-',',',' ','o','r',' ','a',' ','n','a','m','e',' ','p','r','e','c','e','d','e','d',' ','b','y',' ','-','-','.','\n',
|
||||
'\n',
|
||||
' ',' ','-','?',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','h','e','l','p','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','i','s','p','l','a','y',' ','h','e','l','p',' ','(','f','r','o','m',' ','c','o','m','m','a','n','d',' ','l','i','n','e',')','.','\n',
|
||||
' ',' ','-','a',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','s','e','a','r','c','h','-','s','k','i','p','-','s','c','r','e','e','n','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','a','r','c','h',' ','s','k','i','p','s',' ','c','u','r','r','e','n','t',' ','s','c','r','e','e','n','.','\n',
|
||||
' ',' ','-','A',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','S','E','A','R','C','H','-','S','K','I','P','-','S','C','R','E','E','N','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','a','r','c','h',' ','s','t','a','r','t','s',' ','j','u','s','t',' ','a','f','t','e','r',' ','t','a','r','g','e','t',' ','l','i','n','e','.','\n',
|
||||
' ',' ','-','b',' ','[','_','\b','N',']',' ',' ','.','.','.','.',' ',' ','-','-','b','u','f','f','e','r','s','=','[','_','\b','N',']','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','N','u','m','b','e','r',' ','o','f',' ','b','u','f','f','e','r','s','.','\n',
|
||||
' ',' ','-','B',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','a','u','t','o','-','b','u','f','f','e','r','s','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','o','n','\'','t',' ','a','u','t','o','m','a','t','i','c','a','l','l','y',' ','a','l','l','o','c','a','t','e',' ','b','u','f','f','e','r','s',' ','f','o','r',' ','p','i','p','e','s','.','\n',
|
||||
' ',' ','-','c',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','c','l','e','a','r','-','s','c','r','e','e','n','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','R','e','p','a','i','n','t',' ','b','y',' ','c','l','e','a','r','i','n','g',' ','r','a','t','h','e','r',' ','t','h','a','n',' ','s','c','r','o','l','l','i','n','g','.','\n',
|
||||
' ',' ','-','d',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','d','u','m','b','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','u','m','b',' ','t','e','r','m','i','n','a','l','.','\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',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','F','o','r','c','e',' ','o','p','e','n',' ','n','o','n','-','r','e','g','u','l','a','r',' ','f','i','l','e','s','.','\n',
|
||||
' ',' ','-','F',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','q','u','i','t','-','i','f','-','o','n','e','-','s','c','r','e','e','n','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','Q','u','i','t',' ','i','f',' ','e','n','t','i','r','e',' ','f','i','l','e',' ','f','i','t','s',' ','o','n',' ','f','i','r','s','t',' ','s','c','r','e','e','n','.','\n',
|
||||
' ',' ','-','g',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','h','i','l','i','t','e','-','s','e','a','r','c','h','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','H','i','g','h','l','i','g','h','t',' ','o','n','l','y',' ','l','a','s','t',' ','m','a','t','c','h',' ','f','o','r',' ','s','e','a','r','c','h','e','s','.','\n',
|
||||
' ',' ','-','G',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','H','I','L','I','T','E','-','S','E','A','R','C','H','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','o','n','\'','t',' ','h','i','g','h','l','i','g','h','t',' ','a','n','y',' ','m','a','t','c','h','e','s',' ','f','o','r',' ','s','e','a','r','c','h','e','s','.','\n',
|
||||
' ',' ','-','h',' ','[','_','\b','N',']',' ',' ','.','.','.','.',' ',' ','-','-','m','a','x','-','b','a','c','k','-','s','c','r','o','l','l','=','[','_','\b','N',']','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','B','a','c','k','w','a','r','d',' ','s','c','r','o','l','l',' ','l','i','m','i','t','.','\n',
|
||||
' ',' ','-','i',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','i','g','n','o','r','e','-','c','a','s','e','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','I','g','n','o','r','e',' ','c','a','s','e',' ','i','n',' ','s','e','a','r','c','h','e','s',' ','t','h','a','t',' ','d','o',' ','n','o','t',' ','c','o','n','t','a','i','n',' ','u','p','p','e','r','c','a','s','e','.','\n',
|
||||
' ',' ','-','I',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','I','G','N','O','R','E','-','C','A','S','E','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','I','g','n','o','r','e',' ','c','a','s','e',' ','i','n',' ','a','l','l',' ','s','e','a','r','c','h','e','s','.','\n',
|
||||
' ',' ','-','j',' ','[','_','\b','N',']',' ',' ','.','.','.','.',' ',' ','-','-','j','u','m','p','-','t','a','r','g','e','t','=','[','_','\b','N',']','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','c','r','e','e','n',' ','p','o','s','i','t','i','o','n',' ','o','f',' ','t','a','r','g','e','t',' ','l','i','n','e','s','.','\n',
|
||||
' ',' ','-','J',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','s','t','a','t','u','s','-','c','o','l','u','m','n','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','i','s','p','l','a','y',' ','a',' ','s','t','a','t','u','s',' ','c','o','l','u','m','n',' ','a','t',' ','l','e','f','t',' ','e','d','g','e',' ','o','f',' ','s','c','r','e','e','n','.','\n',
|
||||
' ',' ','-','k',' ','[','_','\b','f','_','\b','i','_','\b','l','_','\b','e',']',' ',' ','.',' ',' ','-','-','l','e','s','s','k','e','y','-','f','i','l','e','=','[','_','\b','f','_','\b','i','_','\b','l','_','\b','e',']','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','U','s','e',' ','a',' ','l','e','s','s','k','e','y',' ','f','i','l','e','.','\n',
|
||||
' ',' ','-','K',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','q','u','i','t','-','o','n','-','i','n','t','r','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','E','x','i','t',' ','l','e','s','s',' ','i','n',' ','r','e','s','p','o','n','s','e',' ','t','o',' ','c','t','r','l','-','C','.','\n',
|
||||
' ',' ','-','L',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','n','o','-','l','e','s','s','o','p','e','n','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','I','g','n','o','r','e',' ','t','h','e',' ','L','E','S','S','O','P','E','N',' ','e','n','v','i','r','o','n','m','e','n','t',' ','v','a','r','i','a','b','l','e','.','\n',
|
||||
' ',' ','-','m',' ',' ','-','M',' ',' ','.','.','.','.',' ',' ','-','-','l','o','n','g','-','p','r','o','m','p','t',' ',' ','-','-','L','O','N','G','-','P','R','O','M','P','T','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','t',' ','p','r','o','m','p','t',' ','s','t','y','l','e','.','\n',
|
||||
' ',' ','-','n',' ','.','.','.','.','.','.','.','.','.',' ',' ','-','-','l','i','n','e','-','n','u','m','b','e','r','s','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','u','p','p','r','e','s','s',' ','l','i','n','e',' ','n','u','m','b','e','r','s',' ','i','n',' ','p','r','o','m','p','t','s',' ','a','n','d',' ','m','e','s','s','a','g','e','s','.','\n',
|
||||
' ',' ','-','N',' ','.','.','.','.','.','.','.','.','.',' ',' ','-','-','L','I','N','E','-','N','U','M','B','E','R','S','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','i','s','p','l','a','y',' ','l','i','n','e',' ','n','u','m','b','e','r',' ','a','t',' ','s','t','a','r','t',' ','o','f',' ','e','a','c','h',' ','l','i','n','e','.','\n',
|
||||
' ',' ','-','o',' ','[','_','\b','f','_','\b','i','_','\b','l','_','\b','e',']',' ',' ','.',' ',' ','-','-','l','o','g','-','f','i','l','e','=','[','_','\b','f','_','\b','i','_','\b','l','_','\b','e',']','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','C','o','p','y',' ','t','o',' ','l','o','g',' ','f','i','l','e',' ','(','s','t','a','n','d','a','r','d',' ','i','n','p','u','t',' ','o','n','l','y',')','.','\n',
|
||||
' ',' ','-','O',' ','[','_','\b','f','_','\b','i','_','\b','l','_','\b','e',']',' ',' ','.',' ',' ','-','-','L','O','G','-','F','I','L','E','=','[','_','\b','f','_','\b','i','_','\b','l','_','\b','e',']','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','C','o','p','y',' ','t','o',' ','l','o','g',' ','f','i','l','e',' ','(','u','n','c','o','n','d','i','t','i','o','n','a','l','l','y',' ','o','v','e','r','w','r','i','t','e',')','.','\n',
|
||||
' ',' ','-','p',' ','[','_','\b','p','_','\b','a','_','\b','t','_','\b','t','_','\b','e','_','\b','r','_','\b','n',']',' ',' ','-','-','p','a','t','t','e','r','n','=','[','_','\b','p','_','\b','a','_','\b','t','_','\b','t','_','\b','e','_','\b','r','_','\b','n',']','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','t','a','r','t',' ','a','t',' ','p','a','t','t','e','r','n',' ','(','f','r','o','m',' ','c','o','m','m','a','n','d',' ','l','i','n','e',')','.','\n',
|
||||
' ',' ','-','P',' ','[','_','\b','p','_','\b','r','_','\b','o','_','\b','m','_','\b','p','_','\b','t',']',' ',' ',' ','-','-','p','r','o','m','p','t','=','[','_','\b','p','_','\b','r','_','\b','o','_','\b','m','_','\b','p','_','\b','t',']','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','e','f','i','n','e',' ','n','e','w',' ','p','r','o','m','p','t','.','\n',
|
||||
' ',' ','-','q',' ',' ','-','Q',' ',' ','.','.','.','.',' ',' ','-','-','q','u','i','e','t',' ',' ','-','-','Q','U','I','E','T',' ',' ','-','-','s','i','l','e','n','t',' ','-','-','S','I','L','E','N','T','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','Q','u','i','e','t',' ','t','h','e',' ','t','e','r','m','i','n','a','l',' ','b','e','l','l','.','\n',
|
||||
' ',' ','-','r',' ',' ','-','R',' ',' ','.','.','.','.',' ',' ','-','-','r','a','w','-','c','o','n','t','r','o','l','-','c','h','a','r','s',' ',' ','-','-','R','A','W','-','C','O','N','T','R','O','L','-','C','H','A','R','S','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','O','u','t','p','u','t',' ','"','r','a','w','"',' ','c','o','n','t','r','o','l',' ','c','h','a','r','a','c','t','e','r','s','.','\n',
|
||||
' ',' ','-','s',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','s','q','u','e','e','z','e','-','b','l','a','n','k','-','l','i','n','e','s','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','q','u','e','e','z','e',' ','m','u','l','t','i','p','l','e',' ','b','l','a','n','k',' ','l','i','n','e','s','.','\n',
|
||||
' ',' ','-','S',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','c','h','o','p','-','l','o','n','g','-','l','i','n','e','s','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','C','h','o','p',' ','(','t','r','u','n','c','a','t','e',')',' ','l','o','n','g',' ','l','i','n','e','s',' ','r','a','t','h','e','r',' ','t','h','a','n',' ','w','r','a','p','p','i','n','g','.','\n',
|
||||
' ',' ','-','t',' ','[','_','\b','t','_','\b','a','_','\b','g',']',' ',' ','.','.',' ',' ','-','-','t','a','g','=','[','_','\b','t','_','\b','a','_','\b','g',']','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','F','i','n','d',' ','a',' ','t','a','g','.','\n',
|
||||
' ',' ','-','T',' ','[','_','\b','t','_','\b','a','_','\b','g','_','\b','s','_','\b','f','_','\b','i','_','\b','l','_','\b','e',']',' ','-','-','t','a','g','-','f','i','l','e','=','[','_','\b','t','_','\b','a','_','\b','g','_','\b','s','_','\b','f','_','\b','i','_','\b','l','_','\b','e',']','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','U','s','e',' ','a','n',' ','a','l','t','e','r','n','a','t','e',' ','t','a','g','s',' ','f','i','l','e','.','\n',
|
||||
' ',' ','-','u',' ',' ','-','U',' ',' ','.','.','.','.',' ',' ','-','-','u','n','d','e','r','l','i','n','e','-','s','p','e','c','i','a','l',' ',' ','-','-','U','N','D','E','R','L','I','N','E','-','S','P','E','C','I','A','L','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','C','h','a','n','g','e',' ','h','a','n','d','l','i','n','g',' ','o','f',' ','b','a','c','k','s','p','a','c','e','s',',',' ','t','a','b','s',' ','a','n','d',' ','c','a','r','r','i','a','g','e',' ','r','e','t','u','r','n','s','.','\n',
|
||||
' ',' ','-','V',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','v','e','r','s','i','o','n','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','i','s','p','l','a','y',' ','t','h','e',' ','v','e','r','s','i','o','n',' ','n','u','m','b','e','r',' ','o','f',' ','"','l','e','s','s','"','.','\n',
|
||||
' ',' ','-','w',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','h','i','l','i','t','e','-','u','n','r','e','a','d','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','H','i','g','h','l','i','g','h','t',' ','f','i','r','s','t',' ','n','e','w',' ','l','i','n','e',' ','a','f','t','e','r',' ','f','o','r','w','a','r','d','-','s','c','r','e','e','n','.','\n',
|
||||
' ',' ','-','W',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','H','I','L','I','T','E','-','U','N','R','E','A','D','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','H','i','g','h','l','i','g','h','t',' ','f','i','r','s','t',' ','n','e','w',' ','l','i','n','e',' ','a','f','t','e','r',' ','a','n','y',' ','f','o','r','w','a','r','d',' ','m','o','v','e','m','e','n','t','.','\n',
|
||||
' ',' ','-','x',' ','[','_','\b','N','[',',','.','.','.',']',']',' ',' ','-','-','t','a','b','s','=','[','_','\b','N','[',',','.','.','.',']',']','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','t',' ','t','a','b',' ','s','t','o','p','s','.','\n',
|
||||
' ',' ','-','X',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','n','o','-','i','n','i','t','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','o','n','\'','t',' ','u','s','e',' ','t','e','r','m','c','a','p',' ','i','n','i','t','/','d','e','i','n','i','t',' ','s','t','r','i','n','g','s','.','\n',
|
||||
' ',' ','-','y',' ','[','_','\b','N',']',' ',' ','.','.','.','.',' ',' ','-','-','m','a','x','-','f','o','r','w','-','s','c','r','o','l','l','=','[','_','\b','N',']','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','F','o','r','w','a','r','d',' ','s','c','r','o','l','l',' ','l','i','m','i','t','.','\n',
|
||||
' ',' ','-','z',' ','[','_','\b','N',']',' ',' ','.','.','.','.',' ',' ','-','-','w','i','n','d','o','w','=','[','_','\b','N',']','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','t',' ','s','i','z','e',' ','o','f',' ','w','i','n','d','o','w','.','\n',
|
||||
' ',' ','-','"',' ','[','_','\b','c','[','_','\b','c',']',']',' ',' ','.',' ',' ','-','-','q','u','o','t','e','s','=','[','_','\b','c','[','_','\b','c',']',']','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','t',' ','s','h','e','l','l',' ','q','u','o','t','e',' ','c','h','a','r','a','c','t','e','r','s','.','\n',
|
||||
' ',' ','-','~',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','t','i','l','d','e','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','o','n','\'','t',' ','d','i','s','p','l','a','y',' ','t','i','l','d','e','s',' ','a','f','t','e','r',' ','e','n','d',' ','o','f',' ','f','i','l','e','.','\n',
|
||||
' ',' ','-','#',' ','[','_','\b','N',']',' ',' ','.','.','.','.',' ',' ','-','-','s','h','i','f','t','=','[','_','\b','N',']','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','t',' ','h','o','r','i','z','o','n','t','a','l',' ','s','c','r','o','l','l',' ','a','m','o','u','n','t',' ','(','0',' ','=',' ','o','n','e',' ','h','a','l','f',' ','s','c','r','e','e','n',' ','w','i','d','t','h',')','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','e','x','i','t','-','f','o','l','l','o','w','-','o','n','-','c','l','o','s','e','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','E','x','i','t',' ','F',' ','c','o','m','m','a','n','d',' ','o','n',' ','a',' ','p','i','p','e',' ','w','h','e','n',' ','w','r','i','t','e','r',' ','c','l','o','s','e','s',' ','p','i','p','e','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','f','i','l','e','-','s','i','z','e','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','A','u','t','o','m','a','t','i','c','a','l','l','y',' ','d','e','t','e','r','m','i','n','e',' ','t','h','e',' ','s','i','z','e',' ','o','f',' ','t','h','e',' ','i','n','p','u','t',' ','f','i','l','e','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','f','o','l','l','o','w','-','n','a','m','e','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','T','h','e',' ','F',' ','c','o','m','m','a','n','d',' ','c','h','a','n','g','e','s',' ','f','i','l','e','s',' ','i','f',' ','t','h','e',' ','i','n','p','u','t',' ','f','i','l','e',' ','i','s',' ','r','e','n','a','m','e','d','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','h','e','a','d','e','r','=','[','_','\b','N','[',',','_','\b','M',']',']','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','U','s','e',' ','N',' ','l','i','n','e','s',' ','a','n','d',' ','M',' ','c','o','l','u','m','n','s',' ','t','o',' ','d','i','s','p','l','a','y',' ','f','i','l','e',' ','h','e','a','d','e','r','s','.','\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',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','i','n','t','r','=','_','\b','C','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','U','s','e',' ','_','\b','C',' ','i','n','s','t','e','a','d',' ','o','f',' ','^','X',' ','t','o',' ','i','n','t','e','r','r','u','p','t',' ','a',' ','r','e','a','d','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','l','i','n','e','-','n','u','m','-','w','i','d','t','h','=','_','\b','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',' ','_','\b','N',' ','c','h','a','r','a','c','t','e','r','s','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','m','o','d','e','l','i','n','e','s','=','_','\b','N','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','R','e','a','d',' ','_','\b','N',' ','l','i','n','e','s',' ','f','r','o','m',' ','t','h','e',' ','i','n','p','u','t',' ','f','i','l','e',' ','a','n','d',' ','l','o','o','k',' ','f','o','r',' ','v','i','m',' ','m','o','d','e','l','i','n','e','s','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','m','o','u','s','e','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','E','n','a','b','l','e',' ','m','o','u','s','e',' ','i','n','p','u','t','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','n','o','-','k','e','y','p','a','d','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','o','n','\'','t',' ','s','e','n','d',' ','t','e','r','m','c','a','p',' ','k','e','y','p','a','d',' ','i','n','i','t','/','d','e','i','n','i','t',' ','s','t','r','i','n','g','s','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','n','o','-','h','i','s','t','d','u','p','s','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','R','e','m','o','v','e',' ','d','u','p','l','i','c','a','t','e','s',' ','f','r','o','m',' ','c','o','m','m','a','n','d',' ','h','i','s','t','o','r','y','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','n','o','-','n','u','m','b','e','r','-','h','e','a','d','e','r','s','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','o','n','\'','t',' ','g','i','v','e',' ','l','i','n','e',' ','n','u','m','b','e','r','s',' ','t','o',' ','h','e','a','d','e','r',' ','l','i','n','e','s','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','n','o','-','s','e','a','r','c','h','-','h','e','a','d','e','r','s','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','o','n','\'','t',' ','s','e','a','r','c','h',' ','i','n',' ','h','e','a','d','e','r',' ','l','i','n','e','s',' ','o','r',' ','c','o','l','u','m','n','s','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','n','o','-','v','b','e','l','l','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','i','s','a','b','l','e',' ','t','h','e',' ','t','e','r','m','i','n','a','l','\'','s',' ','v','i','s','u','a','l',' ','b','e','l','l','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','r','e','d','r','a','w','-','o','n','-','q','u','i','t','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','R','e','d','r','a','w',' ','f','i','n','a','l',' ','s','c','r','e','e','n',' ','w','h','e','n',' ','q','u','i','t','t','i','n','g','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','r','s','c','r','o','l','l','=','_','\b','C','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','t',' ','t','h','e',' ','c','h','a','r','a','c','t','e','r',' ','u','s','e','d',' ','t','o',' ','m','a','r','k',' ','t','r','u','n','c','a','t','e','d',' ','l','i','n','e','s','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','s','a','v','e','-','m','a','r','k','s','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','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','e','a','r','c','h','-','o','p','t','i','o','n','s','=','[','E','F','K','N','R','W','-',']','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','t',' ','d','e','f','a','u','l','t',' ','o','p','t','i','o','n','s',' ','f','o','r',' ','e','v','e','r','y',' ','s','e','a','r','c','h','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','s','h','o','w','-','p','r','e','p','r','o','c','-','e','r','r','o','r','s','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','i','s','p','l','a','y',' ','a',' ','m','e','s','s','a','g','e',' ','i','f',' ','p','r','e','p','r','o','c','e','s','s','o','r',' ','e','x','i','t','s',' ','w','i','t','h',' ','a','n',' ','e','r','r','o','r',' ','s','t','a','t','u','s','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','p','r','o','c','-','b','a','c','k','s','p','a','c','e','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','P','r','o','c','e','s','s',' ','b','a','c','k','s','p','a','c','e','s',' ','f','o','r',' ','b','o','l','d','/','u','n','d','e','r','l','i','n','e','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','S','P','E','C','I','A','L','-','B','A','C','K','S','P','A','C','E','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','T','r','e','a','t',' ','b','a','c','k','s','p','a','c','e','s',' ','a','s',' ','c','o','n','t','r','o','l',' ','c','h','a','r','a','c','t','e','r','s','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','p','r','o','c','-','r','e','t','u','r','n','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','e','l','e','t','e',' ','c','a','r','r','i','a','g','e',' ','r','e','t','u','r','n','s',' ','b','e','f','o','r','e',' ','n','e','w','l','i','n','e','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','S','P','E','C','I','A','L','-','R','E','T','U','R','N','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','T','r','e','a','t',' ','c','a','r','r','i','a','g','e',' ','r','e','t','u','r','n','s',' ','a','s',' ','c','o','n','t','r','o','l',' ','c','h','a','r','a','c','t','e','r','s','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','p','r','o','c','-','t','a','b','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','E','x','p','a','n','d',' ','t','a','b','s',' ','t','o',' ','s','p','a','c','e','s','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','S','P','E','C','I','A','L','-','T','A','B','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','T','r','e','a','t',' ','t','a','b','s',' ','a','s',' ','c','o','n','t','r','o','l',' ','c','h','a','r','a','c','t','e','r','s','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','s','t','a','t','u','s','-','c','o','l','-','w','i','d','t','h','=','_','\b','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',' ','_','\b','N',' ','c','h','a','r','a','c','t','e','r','s','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','s','t','a','t','u','s','-','l','i','n','e','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','H','i','g','h','l','i','g','h','t',' ','o','r',' ','c','o','l','o','r',' ','t','h','e',' ','e','n','t','i','r','e',' ','l','i','n','e',' ','c','o','n','t','a','i','n','i','n','g',' ','a',' ','m','a','r','k','.','\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','=','_','\b','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',' ','_','\b','N',' ','l','i','n','e','s','.','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','w','o','r','d','w','r','a','p','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','W','r','a','p',' ','l','i','n','e','s',' ','a','t',' ','s','p','a','c','e','s','.','\n',
|
||||
'\n',
|
||||
'\n',
|
||||
' ','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\n',
|
||||
'\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','L','\b','L','I','\b','I','N','\b','N','E','\b','E',' ','E','\b','E','D','\b','D','I','\b','I','T','\b','T','I','\b','I','N','\b','N','G','\b','G','\n',
|
||||
'\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ','T','h','e','s','e',' ','k','e','y','s',' ','c','a','n',' ','b','e',' ','u','s','e','d',' ','t','o',' ','e','d','i','t',' ','t','e','x','t',' ','b','e','i','n','g',' ','e','n','t','e','r','e','d',' ','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ','o','n',' ','t','h','e',' ','"','c','o','m','m','a','n','d',' ','l','i','n','e','"',' ','a','t',' ','t','h','e',' ','b','o','t','t','o','m',' ','o','f',' ','t','h','e',' ','s','c','r','e','e','n','.','\n',
|
||||
'\n',
|
||||
' ','R','i','g','h','t','A','r','r','o','w',' ','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',' ','E','S','C','-','l',' ','.','.','.',' ','M','o','v','e',' ','c','u','r','s','o','r',' ','r','i','g','h','t',' ','o','n','e',' ','c','h','a','r','a','c','t','e','r','.','\n',
|
||||
' ','L','e','f','t','A','r','r','o','w',' ','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',' ','E','S','C','-','h',' ','.','.','.',' ','M','o','v','e',' ','c','u','r','s','o','r',' ','l','e','f','t',' ','o','n','e',' ','c','h','a','r','a','c','t','e','r','.','\n',
|
||||
' ','c','t','r','l','-','R','i','g','h','t','A','r','r','o','w',' ',' ','E','S','C','-','R','i','g','h','t','A','r','r','o','w',' ',' ','E','S','C','-','w',' ','.','.','.',' ','M','o','v','e',' ','c','u','r','s','o','r',' ','r','i','g','h','t',' ','o','n','e',' ','w','o','r','d','.','\n',
|
||||
' ','c','t','r','l','-','L','e','f','t','A','r','r','o','w',' ',' ',' ','E','S','C','-','L','e','f','t','A','r','r','o','w',' ',' ',' ','E','S','C','-','b',' ','.','.','.',' ','M','o','v','e',' ','c','u','r','s','o','r',' ','l','e','f','t',' ','o','n','e',' ','w','o','r','d','.','\n',
|
||||
' ','H','O','M','E',' ','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',' ','E','S','C','-','0',' ','.','.','.',' ','M','o','v','e',' ','c','u','r','s','o','r',' ','t','o',' ','s','t','a','r','t',' ','o','f',' ','l','i','n','e','.','\n',
|
||||
' ','E','N','D',' ','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',' ','E','S','C','-','$',' ','.','.','.',' ','M','o','v','e',' ','c','u','r','s','o','r',' ','t','o',' ','e','n','d',' ','o','f',' ','l','i','n','e','.','\n',
|
||||
' ','B','A','C','K','S','P','A','C','E',' ','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',' ','D','e','l','e','t','e',' ','c','h','a','r',' ','t','o',' ','l','e','f','t',' ','o','f',' ','c','u','r','s','o','r','.','\n',
|
||||
' ','D','E','L','E','T','E',' ','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',' ','E','S','C','-','x',' ','.','.','.',' ','D','e','l','e','t','e',' ','c','h','a','r',' ','u','n','d','e','r',' ','c','u','r','s','o','r','.','\n',
|
||||
' ','c','t','r','l','-','B','A','C','K','S','P','A','C','E',' ',' ',' ','E','S','C','-','B','A','C','K','S','P','A','C','E',' ','.','.','.','.','.','.','.','.','.','.','.',' ','D','e','l','e','t','e',' ','w','o','r','d',' ','t','o',' ','l','e','f','t',' ','o','f',' ','c','u','r','s','o','r','.','\n',
|
||||
' ','c','t','r','l','-','D','E','L','E','T','E',' ','.','.','.','.',' ','E','S','C','-','D','E','L','E','T','E',' ','.','.','.','.',' ','E','S','C','-','X',' ','.','.','.',' ','D','e','l','e','t','e',' ','w','o','r','d',' ','u','n','d','e','r',' ','c','u','r','s','o','r','.','\n',
|
||||
' ','c','t','r','l','-','U',' ','.','.','.','.','.','.','.','.','.',' ','E','S','C',' ','(','M','S','-','D','O','S',' ','o','n','l','y',')',' ','.','.','.','.','.','.','.',' ','D','e','l','e','t','e',' ','e','n','t','i','r','e',' ','l','i','n','e','.','\n',
|
||||
' ','U','p','A','r','r','o','w',' ','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',' ','E','S','C','-','k',' ','.','.','.',' ','R','e','t','r','i','e','v','e',' ','p','r','e','v','i','o','u','s',' ','c','o','m','m','a','n','d',' ','l','i','n','e','.','\n',
|
||||
' ','D','o','w','n','A','r','r','o','w',' ','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',' ','E','S','C','-','j',' ','.','.','.',' ','R','e','t','r','i','e','v','e',' ','n','e','x','t',' ','c','o','m','m','a','n','d',' ','l','i','n','e','.','\n',
|
||||
' ','T','A','B',' ','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',' ','C','o','m','p','l','e','t','e',' ','f','i','l','e','n','a','m','e',' ','&',' ','c','y','c','l','e','.','\n',
|
||||
' ','S','H','I','F','T','-','T','A','B',' ','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',' ','E','S','C','-','T','A','B',' ',' ',' ','C','o','m','p','l','e','t','e',' ','f','i','l','e','n','a','m','e',' ','&',' ','r','e','v','e','r','s','e',' ','c','y','c','l','e','.','\n',
|
||||
' ','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',
|
||||
0 };
|
||||
constant int size_helpdata = sizeof(helpdata) - 1;
|
358
third_party/less/ifile.c
vendored
Normal file
358
third_party/less/ifile.c
vendored
Normal file
|
@ -0,0 +1,358 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* An IFILE represents an input file.
|
||||
*
|
||||
* It is actually a pointer to an ifile structure,
|
||||
* but is opaque outside this module.
|
||||
* Ifile structures are kept in a linked list in the order they
|
||||
* appear on the command line.
|
||||
* Any new file which does not already appear in the list is
|
||||
* inserted after the current file.
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
|
||||
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 */
|
||||
char h_opened; /* Has this ifile been opened? */
|
||||
struct scrpos h_scrpos; /* Saved position within the file */
|
||||
void *h_altpipe; /* Alt pipe */
|
||||
char *h_altfilename; /* Alt filename */
|
||||
};
|
||||
|
||||
/*
|
||||
* 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))
|
||||
|
||||
/*
|
||||
* Anchor for linked list.
|
||||
*/
|
||||
static struct ifile anchor = { &anchor, &anchor, NULL, NULL, NULL, 0, 0, '\0',
|
||||
{ NULL_POSITION, 0 } };
|
||||
static int ifiles = 0;
|
||||
|
||||
static void incr_index(struct ifile *p, int incr)
|
||||
{
|
||||
for (; p != &anchor; p = p->h_next)
|
||||
p->h_index += incr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Link an ifile into the ifile list.
|
||||
*/
|
||||
static void link_ifile(struct ifile *p, struct ifile *prev)
|
||||
{
|
||||
/*
|
||||
* Link into list.
|
||||
*/
|
||||
if (prev == NULL)
|
||||
prev = &anchor;
|
||||
p->h_next = prev->h_next;
|
||||
p->h_prev = prev;
|
||||
prev->h_next->h_prev = p;
|
||||
prev->h_next = p;
|
||||
/*
|
||||
* Calculate index for the new one,
|
||||
* and adjust the indexes for subsequent ifiles in the list.
|
||||
*/
|
||||
p->h_index = prev->h_index + 1;
|
||||
incr_index(p->h_next, 1);
|
||||
ifiles++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unlink an ifile from the ifile list.
|
||||
*/
|
||||
static void unlink_ifile(struct ifile *p)
|
||||
{
|
||||
p->h_next->h_prev = p->h_prev;
|
||||
p->h_prev->h_next = p->h_next;
|
||||
incr_index(p->h_next, -1);
|
||||
ifiles--;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a new ifile structure and stick a filename in it.
|
||||
* It should go after "prev" in the list
|
||||
* (or at the beginning of the list if "prev" is NULL).
|
||||
* Return a pointer to the new ifile structure.
|
||||
*/
|
||||
static struct ifile * new_ifile(char *filename, struct ifile *prev)
|
||||
{
|
||||
struct ifile *p;
|
||||
|
||||
/*
|
||||
* Allocate and initialize structure.
|
||||
*/
|
||||
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;
|
||||
* there is potentially dangerous recursion.
|
||||
* Probably need to revisit this design. }}
|
||||
*/
|
||||
mark_check_ifile(ext_ifile(p));
|
||||
return (p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete an existing ifile structure.
|
||||
*/
|
||||
public void del_ifile(IFILE h)
|
||||
{
|
||||
struct ifile *p;
|
||||
|
||||
if (h == NULL_IFILE)
|
||||
return;
|
||||
/*
|
||||
* If the ifile we're deleting is the currently open ifile,
|
||||
* move off it.
|
||||
*/
|
||||
unmark(h);
|
||||
if (h == curr_ifile)
|
||||
curr_ifile = getoff_ifile(curr_ifile);
|
||||
p = int_ifile(h);
|
||||
unlink_ifile(p);
|
||||
free(p->h_rfilename);
|
||||
free(p->h_filename);
|
||||
free(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the ifile after a given one in the list.
|
||||
*/
|
||||
public IFILE next_ifile(IFILE h)
|
||||
{
|
||||
struct ifile *p;
|
||||
|
||||
p = (h == NULL_IFILE) ? &anchor : int_ifile(h);
|
||||
if (p->h_next == &anchor)
|
||||
return (NULL_IFILE);
|
||||
return (ext_ifile(p->h_next));
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the ifile before a given one in the list.
|
||||
*/
|
||||
public IFILE prev_ifile(IFILE h)
|
||||
{
|
||||
struct ifile *p;
|
||||
|
||||
p = (h == NULL_IFILE) ? &anchor : int_ifile(h);
|
||||
if (p->h_prev == &anchor)
|
||||
return (NULL_IFILE);
|
||||
return (ext_ifile(p->h_prev));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a different ifile from the given one.
|
||||
*/
|
||||
public IFILE getoff_ifile(IFILE ifile)
|
||||
{
|
||||
IFILE newifile;
|
||||
|
||||
if ((newifile = prev_ifile(ifile)) != NULL_IFILE)
|
||||
return (newifile);
|
||||
if ((newifile = next_ifile(ifile)) != NULL_IFILE)
|
||||
return (newifile);
|
||||
return (NULL_IFILE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the number of ifiles.
|
||||
*/
|
||||
public int nifile(void)
|
||||
{
|
||||
return (ifiles);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find an ifile structure, given a filename.
|
||||
*/
|
||||
static struct ifile * find_ifile(char *filename)
|
||||
{
|
||||
struct ifile *p;
|
||||
char *rfilename = lrealpath(filename);
|
||||
|
||||
for (p = anchor.h_next; p != &anchor; p = p->h_next)
|
||||
{
|
||||
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))
|
||||
{
|
||||
free(p->h_filename);
|
||||
p->h_filename = save(filename);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(rfilename);
|
||||
if (p == &anchor)
|
||||
p = NULL;
|
||||
return (p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the ifile associated with a filename.
|
||||
* If the filename has not been seen before,
|
||||
* insert the new ifile after "prev" in the list.
|
||||
*/
|
||||
public IFILE get_ifile(char *filename, IFILE prev)
|
||||
{
|
||||
struct ifile *p;
|
||||
|
||||
if ((p = find_ifile(filename)) == NULL)
|
||||
p = new_ifile(filename, int_ifile(prev));
|
||||
return (ext_ifile(p));
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the display filename associated with a ifile.
|
||||
*/
|
||||
public char * get_filename(IFILE ifile)
|
||||
{
|
||||
if (ifile == NULL)
|
||||
return (NULL);
|
||||
return (int_ifile(ifile)->h_filename);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the canonical filename associated with a ifile.
|
||||
*/
|
||||
public char * get_real_filename(IFILE ifile)
|
||||
{
|
||||
if (ifile == NULL)
|
||||
return (NULL);
|
||||
return (int_ifile(ifile)->h_rfilename);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the index of the file associated with a ifile.
|
||||
*/
|
||||
public int get_index(IFILE ifile)
|
||||
{
|
||||
return (int_ifile(ifile)->h_index);
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the file position to be associated with a given file.
|
||||
*/
|
||||
public void store_pos(IFILE ifile, struct scrpos *scrpos)
|
||||
{
|
||||
int_ifile(ifile)->h_scrpos = *scrpos;
|
||||
}
|
||||
|
||||
/*
|
||||
* Recall the file position associated with a file.
|
||||
* If no position has been associated with the file, return NULL_POSITION.
|
||||
*/
|
||||
public void get_pos(IFILE ifile, struct scrpos *scrpos)
|
||||
{
|
||||
*scrpos = int_ifile(ifile)->h_scrpos;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark the ifile as "opened".
|
||||
*/
|
||||
public void set_open(IFILE ifile)
|
||||
{
|
||||
int_ifile(ifile)->h_opened = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return whether the ifile has been opened previously.
|
||||
*/
|
||||
public int opened(IFILE ifile)
|
||||
{
|
||||
return (int_ifile(ifile)->h_opened);
|
||||
}
|
||||
|
||||
public void hold_ifile(IFILE ifile, int incr)
|
||||
{
|
||||
int_ifile(ifile)->h_hold += incr;
|
||||
}
|
||||
|
||||
public int held_ifile(IFILE ifile)
|
||||
{
|
||||
return (int_ifile(ifile)->h_hold);
|
||||
}
|
||||
|
||||
public void * get_filestate(IFILE ifile)
|
||||
{
|
||||
return (int_ifile(ifile)->h_filestate);
|
||||
}
|
||||
|
||||
public void set_filestate(IFILE ifile, void *filestate)
|
||||
{
|
||||
int_ifile(ifile)->h_filestate = filestate;
|
||||
}
|
||||
|
||||
public void set_altpipe(IFILE ifile, void *p)
|
||||
{
|
||||
int_ifile(ifile)->h_altpipe = p;
|
||||
}
|
||||
|
||||
public void *get_altpipe(IFILE ifile)
|
||||
{
|
||||
return (int_ifile(ifile)->h_altpipe);
|
||||
}
|
||||
|
||||
public void set_altfilename(IFILE ifile, char *altfilename)
|
||||
{
|
||||
struct ifile *p = int_ifile(ifile);
|
||||
if (p->h_altfilename != NULL && p->h_altfilename != altfilename)
|
||||
free(p->h_altfilename);
|
||||
p->h_altfilename = altfilename;
|
||||
}
|
||||
|
||||
public char * get_altfilename(IFILE ifile)
|
||||
{
|
||||
return (int_ifile(ifile)->h_altfilename);
|
||||
}
|
||||
|
||||
#if 0
|
||||
public void if_dump(void)
|
||||
{
|
||||
struct ifile *p;
|
||||
|
||||
for (p = anchor.h_next; p != &anchor; p = p->h_next)
|
||||
{
|
||||
printf("%x: %d. <%s> pos %d,%x\n",
|
||||
p, p->h_index, p->h_filename,
|
||||
p->h_scrpos.ln, p->h_scrpos.pos);
|
||||
ch_dump(p->h_filestate);
|
||||
}
|
||||
}
|
||||
#endif
|
624
third_party/less/input.c
vendored
Normal file
624
third_party/less/input.c
vendored
Normal file
|
@ -0,0 +1,624 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* High level routines dealing with getting lines of input
|
||||
* from the file being viewed.
|
||||
*
|
||||
* When we speak of "lines" here, we mean PRINTABLE lines;
|
||||
* lines processed with respect to the screen width.
|
||||
* We use the term "raw line" to refer to lines simply
|
||||
* delimited by newlines; not processed with respect to screen width.
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
|
||||
extern int squeeze;
|
||||
extern int hshift;
|
||||
extern int quit_if_one_screen;
|
||||
extern int sigs;
|
||||
extern int ignore_eoi;
|
||||
extern int status_col;
|
||||
extern int wordwrap;
|
||||
extern POSITION start_attnpos;
|
||||
extern POSITION end_attnpos;
|
||||
#if HILITE_SEARCH
|
||||
extern int hilite_search;
|
||||
extern int size_linebuf;
|
||||
extern int show_attn;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set the status column.
|
||||
* base Position of first char in line.
|
||||
* disp First visible char.
|
||||
* Different than base_pos if line is shifted.
|
||||
* edisp Last visible char.
|
||||
* eol End of line. Normally the newline.
|
||||
* Different than edisp if line is chopped.
|
||||
*/
|
||||
static void init_status_col(POSITION base_pos, POSITION disp_pos, POSITION edisp_pos, POSITION eol_pos)
|
||||
{
|
||||
int hl_before = (chop_line() && disp_pos != NULL_POSITION) ?
|
||||
is_hilited_attr(base_pos, disp_pos, TRUE, NULL) : 0;
|
||||
int hl_after = (chop_line()) ?
|
||||
is_hilited_attr(edisp_pos, eol_pos, TRUE, NULL) : 0;
|
||||
int attr;
|
||||
char ch;
|
||||
|
||||
if (hl_before && hl_after)
|
||||
{
|
||||
attr = hl_after;
|
||||
ch = '=';
|
||||
} else if (hl_before)
|
||||
{
|
||||
attr = hl_before;
|
||||
ch = '<';
|
||||
} else if (hl_after)
|
||||
{
|
||||
attr = hl_after;
|
||||
ch = '>';
|
||||
} else
|
||||
{
|
||||
attr = is_hilited_attr(base_pos, eol_pos, TRUE, NULL);
|
||||
ch = '*';
|
||||
}
|
||||
if (attr)
|
||||
set_status_col(ch, attr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the next line.
|
||||
* A "current" position is passed and a "new" position is returned.
|
||||
* The current position is the position of the first character of
|
||||
* a line. The new position is the position of the first character
|
||||
* of the NEXT line. The line obtained is the line starting at curr_pos.
|
||||
*/
|
||||
public POSITION forw_line_seg(POSITION curr_pos, int skipeol, int rscroll, int nochop)
|
||||
{
|
||||
POSITION base_pos;
|
||||
POSITION new_pos;
|
||||
POSITION edisp_pos = 0;
|
||||
int c;
|
||||
int blankline;
|
||||
int endline;
|
||||
int chopped;
|
||||
int backchars;
|
||||
POSITION wrap_pos;
|
||||
int skipped_leading;
|
||||
|
||||
get_forw_line:
|
||||
if (curr_pos == NULL_POSITION)
|
||||
{
|
||||
null_line();
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
#if HILITE_SEARCH
|
||||
if (hilite_search == OPT_ONPLUS || is_filtering() || status_col)
|
||||
{
|
||||
/*
|
||||
* If we are ignoring EOI (command F), only prepare
|
||||
* one line ahead, to avoid getting stuck waiting for
|
||||
* slow data without displaying the data we already have.
|
||||
* If we're not ignoring EOI, we *could* do the same, but
|
||||
* for efficiency we prepare several lines ahead at once.
|
||||
*/
|
||||
prep_hilite(curr_pos, curr_pos + 3*size_linebuf,
|
||||
ignore_eoi ? 1 : -1);
|
||||
curr_pos = next_unfiltered(curr_pos);
|
||||
}
|
||||
#endif
|
||||
if (ch_seek(curr_pos))
|
||||
{
|
||||
null_line();
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Step back to the beginning of the line.
|
||||
*/
|
||||
base_pos = curr_pos;
|
||||
for (;;)
|
||||
{
|
||||
if (ABORT_SIGS())
|
||||
{
|
||||
null_line();
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
c = ch_back_get();
|
||||
if (c == EOI)
|
||||
break;
|
||||
if (c == '\n')
|
||||
{
|
||||
(void) ch_forw_get();
|
||||
break;
|
||||
}
|
||||
--base_pos;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read forward again to the position we should start at.
|
||||
*/
|
||||
prewind();
|
||||
plinestart(base_pos);
|
||||
(void) ch_seek(base_pos);
|
||||
new_pos = base_pos;
|
||||
while (new_pos < curr_pos)
|
||||
{
|
||||
if (ABORT_SIGS())
|
||||
{
|
||||
null_line();
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
c = ch_forw_get();
|
||||
backchars = pappend(c, new_pos);
|
||||
new_pos++;
|
||||
if (backchars > 0)
|
||||
{
|
||||
pshift_all();
|
||||
if (wordwrap && (c == ' ' || c == '\t'))
|
||||
{
|
||||
do
|
||||
{
|
||||
new_pos++;
|
||||
c = ch_forw_get();
|
||||
} while (c == ' ' || c == '\t');
|
||||
backchars = 1;
|
||||
}
|
||||
new_pos -= backchars;
|
||||
while (--backchars >= 0)
|
||||
(void) ch_back_get();
|
||||
}
|
||||
}
|
||||
(void) pflushmbc();
|
||||
pshift_all();
|
||||
|
||||
/*
|
||||
* Read the first character to display.
|
||||
*/
|
||||
c = ch_forw_get();
|
||||
if (c == EOI)
|
||||
{
|
||||
null_line();
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
blankline = (c == '\n' || c == '\r');
|
||||
wrap_pos = NULL_POSITION;
|
||||
skipped_leading = FALSE;
|
||||
|
||||
/*
|
||||
* Read each character in the line and append to the line buffer.
|
||||
*/
|
||||
chopped = FALSE;
|
||||
for (;;)
|
||||
{
|
||||
if (ABORT_SIGS())
|
||||
{
|
||||
null_line();
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
if (c == '\n' || c == EOI)
|
||||
{
|
||||
/*
|
||||
* End of the line.
|
||||
*/
|
||||
backchars = pflushmbc();
|
||||
new_pos = ch_tell();
|
||||
if (backchars > 0 && (nochop || !chop_line()) && hshift == 0)
|
||||
{
|
||||
new_pos -= backchars + 1;
|
||||
endline = FALSE;
|
||||
} else
|
||||
endline = TRUE;
|
||||
edisp_pos = new_pos;
|
||||
break;
|
||||
}
|
||||
if (c != '\r')
|
||||
blankline = 0;
|
||||
|
||||
/*
|
||||
* Append the char to the line and get the next char.
|
||||
*/
|
||||
backchars = pappend(c, ch_tell()-1);
|
||||
if (backchars > 0)
|
||||
{
|
||||
/*
|
||||
* The char won't fit in the line; the line
|
||||
* is too long to print in the screen width.
|
||||
* End the line here.
|
||||
*/
|
||||
if (skipeol)
|
||||
{
|
||||
/* Read to end of line. */
|
||||
edisp_pos = ch_tell();
|
||||
do
|
||||
{
|
||||
if (ABORT_SIGS())
|
||||
{
|
||||
null_line();
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
c = ch_forw_get();
|
||||
} while (c != '\n' && c != EOI);
|
||||
new_pos = ch_tell();
|
||||
endline = TRUE;
|
||||
quit_if_one_screen = FALSE;
|
||||
chopped = TRUE;
|
||||
} else
|
||||
{
|
||||
if (!wordwrap)
|
||||
new_pos = ch_tell() - backchars;
|
||||
else
|
||||
{
|
||||
/*
|
||||
* We're word-wrapping, so go back to the last space.
|
||||
* However, if it's the space itself that couldn't fit,
|
||||
* simply ignore it and any subsequent spaces.
|
||||
*/
|
||||
if (c == ' ' || c == '\t')
|
||||
{
|
||||
do
|
||||
{
|
||||
new_pos = ch_tell();
|
||||
c = ch_forw_get();
|
||||
} while (c == ' ' || c == '\t');
|
||||
if (c == '\r')
|
||||
c = ch_forw_get();
|
||||
if (c == '\n')
|
||||
new_pos = ch_tell();
|
||||
} else if (wrap_pos == NULL_POSITION)
|
||||
new_pos = ch_tell() - backchars;
|
||||
else
|
||||
{
|
||||
new_pos = wrap_pos;
|
||||
loadc();
|
||||
}
|
||||
}
|
||||
endline = FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (wordwrap)
|
||||
{
|
||||
if (c == ' ' || c == '\t')
|
||||
{
|
||||
if (skipped_leading)
|
||||
{
|
||||
wrap_pos = ch_tell();
|
||||
savec();
|
||||
}
|
||||
} else
|
||||
skipped_leading = TRUE;
|
||||
}
|
||||
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, rscroll && chopped, 1);
|
||||
|
||||
#if HILITE_SEARCH
|
||||
if (is_filtered(base_pos))
|
||||
{
|
||||
/*
|
||||
* We don't want to display this line.
|
||||
* Get the next line.
|
||||
*/
|
||||
curr_pos = new_pos;
|
||||
goto get_forw_line;
|
||||
}
|
||||
if (status_col)
|
||||
init_status_col(base_pos, line_position(), edisp_pos, new_pos);
|
||||
#endif
|
||||
|
||||
if (squeeze && blankline)
|
||||
{
|
||||
/*
|
||||
* This line is blank.
|
||||
* Skip down to the last contiguous blank line
|
||||
* and pretend it is the one which we are returning.
|
||||
*/
|
||||
while ((c = ch_forw_get()) == '\n' || c == '\r')
|
||||
if (ABORT_SIGS())
|
||||
{
|
||||
null_line();
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
if (c != EOI)
|
||||
(void) ch_back_get();
|
||||
new_pos = ch_tell();
|
||||
}
|
||||
|
||||
return (new_pos);
|
||||
}
|
||||
|
||||
public POSITION forw_line(POSITION curr_pos)
|
||||
{
|
||||
|
||||
return forw_line_seg(curr_pos, (chop_line() || hshift > 0), TRUE, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the previous line.
|
||||
* A "current" position is passed and a "new" position is returned.
|
||||
* The current position is the position of the first character of
|
||||
* a line. The new position is the position of the first character
|
||||
* of the PREVIOUS line. The line obtained is the one starting at new_pos.
|
||||
*/
|
||||
public POSITION back_line(POSITION curr_pos)
|
||||
{
|
||||
POSITION base_pos;
|
||||
POSITION new_pos;
|
||||
POSITION edisp_pos = 0;
|
||||
POSITION begin_new_pos;
|
||||
int c;
|
||||
int endline;
|
||||
int chopped;
|
||||
int backchars;
|
||||
POSITION wrap_pos;
|
||||
int skipped_leading;
|
||||
|
||||
get_back_line:
|
||||
if (curr_pos == NULL_POSITION || curr_pos <= ch_zero())
|
||||
{
|
||||
null_line();
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
#if HILITE_SEARCH
|
||||
if (hilite_search == OPT_ONPLUS || is_filtering() || status_col)
|
||||
prep_hilite((curr_pos < 3*size_linebuf) ?
|
||||
0 : curr_pos - 3*size_linebuf, curr_pos, -1);
|
||||
#endif
|
||||
if (ch_seek(curr_pos-1))
|
||||
{
|
||||
null_line();
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
|
||||
if (squeeze)
|
||||
{
|
||||
/*
|
||||
* Find out if the "current" line was blank.
|
||||
*/
|
||||
(void) ch_forw_get(); /* Skip the newline */
|
||||
c = ch_forw_get(); /* First char of "current" line */
|
||||
(void) ch_back_get(); /* Restore our position */
|
||||
(void) ch_back_get();
|
||||
|
||||
if (c == '\n' || c == '\r')
|
||||
{
|
||||
/*
|
||||
* The "current" line was blank.
|
||||
* Skip over any preceding blank lines,
|
||||
* since we skipped them in forw_line().
|
||||
*/
|
||||
while ((c = ch_back_get()) == '\n' || c == '\r')
|
||||
if (ABORT_SIGS())
|
||||
{
|
||||
null_line();
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
if (c == EOI)
|
||||
{
|
||||
null_line();
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
(void) ch_forw_get();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan backwards until we hit the beginning of the line.
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
if (ABORT_SIGS())
|
||||
{
|
||||
null_line();
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
c = ch_back_get();
|
||||
if (c == '\n')
|
||||
{
|
||||
/*
|
||||
* This is the newline ending the previous line.
|
||||
* We have hit the beginning of the line.
|
||||
*/
|
||||
base_pos = ch_tell() + 1;
|
||||
break;
|
||||
}
|
||||
if (c == EOI)
|
||||
{
|
||||
/*
|
||||
* We have hit the beginning of the file.
|
||||
* This must be the first line in the file.
|
||||
* This must, of course, be the beginning of the line.
|
||||
*/
|
||||
base_pos = ch_tell();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now scan forwards from the beginning of this line.
|
||||
* We keep discarding "printable lines" (based on screen width)
|
||||
* until we reach the curr_pos.
|
||||
*
|
||||
* {{ This algorithm is pretty inefficient if the lines
|
||||
* are much longer than the screen width,
|
||||
* but I don't know of any better way. }}
|
||||
*/
|
||||
new_pos = base_pos;
|
||||
if (ch_seek(new_pos))
|
||||
{
|
||||
null_line();
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
endline = FALSE;
|
||||
prewind();
|
||||
plinestart(new_pos);
|
||||
loop:
|
||||
wrap_pos = NULL_POSITION;
|
||||
skipped_leading = FALSE;
|
||||
begin_new_pos = new_pos;
|
||||
(void) ch_seek(new_pos);
|
||||
chopped = FALSE;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
c = ch_forw_get();
|
||||
if (c == EOI || ABORT_SIGS())
|
||||
{
|
||||
null_line();
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
new_pos++;
|
||||
if (c == '\n')
|
||||
{
|
||||
backchars = pflushmbc();
|
||||
if (backchars > 0 && !chop_line() && hshift == 0)
|
||||
{
|
||||
backchars++;
|
||||
goto shift;
|
||||
}
|
||||
endline = TRUE;
|
||||
edisp_pos = new_pos;
|
||||
break;
|
||||
}
|
||||
backchars = pappend(c, ch_tell()-1);
|
||||
if (backchars > 0)
|
||||
{
|
||||
/*
|
||||
* Got a full printable line, but we haven't
|
||||
* reached our curr_pos yet. Discard the line
|
||||
* and start a new one.
|
||||
*/
|
||||
if (chop_line() || hshift > 0)
|
||||
{
|
||||
endline = TRUE;
|
||||
chopped = TRUE;
|
||||
quit_if_one_screen = FALSE;
|
||||
edisp_pos = new_pos;
|
||||
break;
|
||||
}
|
||||
shift:
|
||||
if (!wordwrap)
|
||||
{
|
||||
pshift_all();
|
||||
new_pos -= backchars;
|
||||
} else
|
||||
{
|
||||
if (c == ' ' || c == '\t')
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
c = ch_forw_get();
|
||||
if (c == ' ' || c == '\t')
|
||||
new_pos++;
|
||||
else
|
||||
{
|
||||
if (c == '\r')
|
||||
{
|
||||
c = ch_forw_get();
|
||||
if (c == '\n')
|
||||
new_pos++;
|
||||
}
|
||||
if (c == '\n')
|
||||
new_pos++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (new_pos >= curr_pos)
|
||||
break;
|
||||
pshift_all();
|
||||
} else
|
||||
{
|
||||
pshift_all();
|
||||
if (wrap_pos == NULL_POSITION)
|
||||
new_pos -= backchars;
|
||||
else
|
||||
new_pos = wrap_pos;
|
||||
}
|
||||
}
|
||||
goto loop;
|
||||
}
|
||||
if (wordwrap)
|
||||
{
|
||||
if (c == ' ' || c == '\t')
|
||||
{
|
||||
if (skipped_leading)
|
||||
wrap_pos = new_pos;
|
||||
} else
|
||||
skipped_leading = TRUE;
|
||||
}
|
||||
if (new_pos >= curr_pos)
|
||||
{
|
||||
edisp_pos = new_pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pdone(endline, chopped, 0);
|
||||
|
||||
#if HILITE_SEARCH
|
||||
if (is_filtered(base_pos))
|
||||
{
|
||||
/*
|
||||
* We don't want to display this line.
|
||||
* Get the previous line.
|
||||
*/
|
||||
curr_pos = begin_new_pos;
|
||||
goto get_back_line;
|
||||
}
|
||||
if (status_col)
|
||||
init_status_col(base_pos, line_position(), edisp_pos, new_pos);
|
||||
#endif
|
||||
|
||||
return (begin_new_pos);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set attnpos.
|
||||
*/
|
||||
public void set_attnpos(POSITION pos)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (pos != NULL_POSITION)
|
||||
{
|
||||
if (ch_seek(pos))
|
||||
return;
|
||||
for (;;)
|
||||
{
|
||||
c = ch_forw_get();
|
||||
if (c == EOI)
|
||||
break;
|
||||
if (c == '\n' || c == '\r')
|
||||
{
|
||||
(void) ch_back_get();
|
||||
break;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
end_attnpos = pos;
|
||||
for (;;)
|
||||
{
|
||||
c = ch_back_get();
|
||||
if (c == EOI || c == '\n' || c == '\r')
|
||||
break;
|
||||
pos--;
|
||||
}
|
||||
}
|
||||
start_attnpos = pos;
|
||||
}
|
325
third_party/less/jump.c
vendored
Normal file
325
third_party/less/jump.c
vendored
Normal file
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Routines which jump to a new location in the file.
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
#include "position.h"
|
||||
|
||||
extern int jump_sline;
|
||||
extern int squished;
|
||||
extern int screen_trashed;
|
||||
extern int sc_width, sc_height;
|
||||
extern int show_attn;
|
||||
extern int top_scroll;
|
||||
|
||||
/*
|
||||
* Jump to the end of the file.
|
||||
*/
|
||||
public void jump_forw(void)
|
||||
{
|
||||
POSITION pos;
|
||||
POSITION end_pos;
|
||||
|
||||
if (ch_end_seek())
|
||||
{
|
||||
error("Cannot seek to end of file", NULL_PARG);
|
||||
return;
|
||||
}
|
||||
end_pos = ch_tell();
|
||||
if (position(sc_height-1) == end_pos)
|
||||
{
|
||||
eof_bell();
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Note; lastmark will be called later by jump_loc, but it fails
|
||||
* because the position table has been cleared by pos_clear below.
|
||||
* So call it here before calling pos_clear.
|
||||
*/
|
||||
lastmark();
|
||||
/*
|
||||
* Position the last line in the file at the last screen line.
|
||||
* Go back one line from the end of the file
|
||||
* to get to the beginning of the last line.
|
||||
*/
|
||||
pos_clear();
|
||||
pos = back_line(end_pos);
|
||||
if (pos == NULL_POSITION)
|
||||
jump_loc(ch_zero(), sc_height-1);
|
||||
else
|
||||
{
|
||||
jump_loc(pos, sc_height-1);
|
||||
if (position(sc_height-1) != end_pos)
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Jump to the last buffered line in the file.
|
||||
*/
|
||||
public void jump_forw_buffered(void)
|
||||
{
|
||||
POSITION end;
|
||||
|
||||
if (ch_end_buffer_seek())
|
||||
{
|
||||
error("Cannot seek to end of buffers", NULL_PARG);
|
||||
return;
|
||||
}
|
||||
end = ch_tell();
|
||||
if (end != NULL_POSITION && end > 0)
|
||||
jump_line_loc(end-1, sc_height-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Jump to line n in the file.
|
||||
*/
|
||||
public void jump_back(LINENUM linenum)
|
||||
{
|
||||
POSITION pos;
|
||||
PARG parg;
|
||||
|
||||
/*
|
||||
* Find the position of the specified line.
|
||||
* If we can seek there, just jump to it.
|
||||
* If we can't seek, but we're trying to go to line number 1,
|
||||
* use ch_beg_seek() to get as close as we can.
|
||||
*/
|
||||
pos = find_pos(linenum);
|
||||
if (pos != NULL_POSITION && ch_seek(pos) == 0)
|
||||
{
|
||||
if (show_attn)
|
||||
set_attnpos(pos);
|
||||
jump_loc(pos, jump_sline);
|
||||
} else if (linenum <= 1 && ch_beg_seek() == 0)
|
||||
{
|
||||
jump_loc(ch_tell(), jump_sline);
|
||||
error("Cannot seek to beginning of file", NULL_PARG);
|
||||
} else
|
||||
{
|
||||
parg.p_linenum = linenum;
|
||||
error("Cannot seek to line number %n", &parg);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Repaint the screen.
|
||||
*/
|
||||
public void repaint(void)
|
||||
{
|
||||
struct scrpos scrpos;
|
||||
/*
|
||||
* Start at the line currently at the top of the screen
|
||||
* and redisplay the screen.
|
||||
*/
|
||||
get_scrpos(&scrpos, TOP);
|
||||
pos_clear();
|
||||
if (scrpos.pos == NULL_POSITION)
|
||||
/* Screen hasn't been drawn yet. */
|
||||
jump_loc(ch_zero(), 1);
|
||||
else
|
||||
jump_loc(scrpos.pos, scrpos.ln);
|
||||
}
|
||||
|
||||
/*
|
||||
* Jump to a specified percentage into the file.
|
||||
*/
|
||||
public void jump_percent(int percent, long fraction)
|
||||
{
|
||||
POSITION pos, len;
|
||||
|
||||
/*
|
||||
* Determine the position in the file
|
||||
* (the specified percentage of the file's length).
|
||||
*/
|
||||
if ((len = ch_length()) == NULL_POSITION)
|
||||
{
|
||||
ierror("Determining length of file", NULL_PARG);
|
||||
ch_end_seek();
|
||||
}
|
||||
if ((len = ch_length()) == NULL_POSITION)
|
||||
{
|
||||
error("Don't know length of file", NULL_PARG);
|
||||
return;
|
||||
}
|
||||
pos = percent_pos(len, percent, fraction);
|
||||
if (pos >= len)
|
||||
pos = len-1;
|
||||
|
||||
jump_line_loc(pos, jump_sline);
|
||||
}
|
||||
|
||||
/*
|
||||
* Jump to a specified position in the file.
|
||||
* Like jump_loc, but the position need not be
|
||||
* the first character in a line.
|
||||
*/
|
||||
public void jump_line_loc(POSITION pos, int sline)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (ch_seek(pos) == 0)
|
||||
{
|
||||
/*
|
||||
* Back up to the beginning of the line.
|
||||
*/
|
||||
while ((c = ch_back_get()) != '\n' && c != EOI)
|
||||
;
|
||||
if (c == '\n')
|
||||
(void) ch_forw_get();
|
||||
pos = ch_tell();
|
||||
}
|
||||
if (show_attn)
|
||||
set_attnpos(pos);
|
||||
jump_loc(pos, sline);
|
||||
}
|
||||
|
||||
/*
|
||||
* Jump to a specified position in the file.
|
||||
* The position must be the first character in a line.
|
||||
* Place the target line on a specified line on the screen.
|
||||
*/
|
||||
public void jump_loc(POSITION pos, int sline)
|
||||
{
|
||||
int nline;
|
||||
int sindex;
|
||||
POSITION tpos;
|
||||
POSITION bpos;
|
||||
|
||||
/*
|
||||
* Normalize sline.
|
||||
*/
|
||||
sindex = sindex_from_sline(sline);
|
||||
|
||||
if ((nline = onscreen(pos)) >= 0)
|
||||
{
|
||||
/*
|
||||
* The line is currently displayed.
|
||||
* Just scroll there.
|
||||
*/
|
||||
nline -= sindex;
|
||||
if (nline > 0)
|
||||
forw(nline, position(BOTTOM_PLUS_ONE), 1, 0, 0);
|
||||
else
|
||||
back(-nline, position(TOP), 1, 0);
|
||||
#if HILITE_SEARCH
|
||||
if (show_attn)
|
||||
repaint_hilite(1);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Line is not on screen.
|
||||
* Seek to the desired location.
|
||||
*/
|
||||
if (ch_seek(pos))
|
||||
{
|
||||
error("Cannot seek to that file position", NULL_PARG);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* See if the desired line is before or after
|
||||
* the currently displayed screen.
|
||||
*/
|
||||
tpos = position(TOP);
|
||||
bpos = position(BOTTOM_PLUS_ONE);
|
||||
if (tpos == NULL_POSITION || pos >= tpos)
|
||||
{
|
||||
/*
|
||||
* The desired line is after the current screen.
|
||||
* Move back in the file far enough so that we can
|
||||
* call forw() and put the desired line at the
|
||||
* sline-th line on the screen.
|
||||
*/
|
||||
for (nline = 0; nline < sindex; nline++)
|
||||
{
|
||||
if (bpos != NULL_POSITION && pos <= bpos)
|
||||
{
|
||||
/*
|
||||
* Surprise! The desired line is
|
||||
* close enough to the current screen
|
||||
* that we can just scroll there after all.
|
||||
*/
|
||||
forw(sc_height-sindex+nline-1, bpos, 1, 0, 0);
|
||||
#if HILITE_SEARCH
|
||||
if (show_attn)
|
||||
repaint_hilite(1);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
pos = back_line(pos);
|
||||
if (pos == NULL_POSITION)
|
||||
{
|
||||
/*
|
||||
* Oops. Ran into the beginning of the file.
|
||||
* Exit the loop here and rely on forw()
|
||||
* below to draw the required number of
|
||||
* blank lines at the top of the screen.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
lastmark();
|
||||
squished = 0;
|
||||
screen_trashed = 0;
|
||||
forw(sc_height-1, pos, 1, 0, sindex-nline);
|
||||
} else
|
||||
{
|
||||
/*
|
||||
* The desired line is before the current screen.
|
||||
* Move forward in the file far enough so that we
|
||||
* can call back() and put the desired line at the
|
||||
* sindex-th line on the screen.
|
||||
*/
|
||||
for (nline = sindex; nline < sc_height - 1; nline++)
|
||||
{
|
||||
pos = forw_line(pos);
|
||||
if (pos == NULL_POSITION)
|
||||
{
|
||||
/*
|
||||
* Ran into end of file.
|
||||
* This shouldn't normally happen,
|
||||
* but may if there is some kind of read error.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
#if HILITE_SEARCH
|
||||
pos = next_unfiltered(pos);
|
||||
#endif
|
||||
if (pos >= tpos)
|
||||
{
|
||||
/*
|
||||
* Surprise! The desired line is
|
||||
* close enough to the current screen
|
||||
* that we can just scroll there after all.
|
||||
*/
|
||||
back(nline+1, tpos, 1, 0);
|
||||
#if HILITE_SEARCH
|
||||
if (show_attn)
|
||||
repaint_hilite(1);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
lastmark();
|
||||
if (!top_scroll)
|
||||
clear();
|
||||
else
|
||||
home();
|
||||
screen_trashed = 0;
|
||||
add_back_pos(pos);
|
||||
back(sc_height-1, pos, 1, 0);
|
||||
}
|
||||
}
|
635
third_party/less/less.h
vendored
Normal file
635
third_party/less/less.h
vendored
Normal file
|
@ -0,0 +1,635 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
#define NEWBOT 1
|
||||
|
||||
/*
|
||||
* Standard include file for "less".
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
|
||||
/*
|
||||
* Include the file of compile-time options.
|
||||
* The <> make cc search for it in -I., not srcdir.
|
||||
*/
|
||||
#include "defines.h"
|
||||
|
||||
#ifdef _SEQUENT_
|
||||
/*
|
||||
* Kludge for Sequent Dynix systems that have sigsetmask, but
|
||||
* it's not compatible with the way less calls it.
|
||||
* {{ Do other systems need this? }}
|
||||
*/
|
||||
#undef HAVE_SIGSETMASK
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Language details.
|
||||
*/
|
||||
#if HAVE_CONST
|
||||
#define constant const
|
||||
#else
|
||||
#define constant
|
||||
#endif
|
||||
|
||||
#define public /* PUBLIC FUNCTION */
|
||||
|
||||
/* Library function declarations */
|
||||
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#if HAVE_STDIO_H
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#if HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if HAVE_CTYPE_H
|
||||
#include <ctype.h>
|
||||
#endif
|
||||
#if HAVE_WCTYPE_H
|
||||
#include <wctype.h>
|
||||
#endif
|
||||
#if HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#if HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#if HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#if HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_STDCKDINT_H
|
||||
#include <stdckdint.h>
|
||||
#else
|
||||
/*
|
||||
* These substitutes for C23 stdckdint macros do not set *R on overflow,
|
||||
* and they assume A and B are nonnegative. That is good enough for us.
|
||||
*/
|
||||
#define ckd_add(r, a, b) help_ckd_add(r, a, b, sizeof *(r), signed_expr(*(r)))
|
||||
#define ckd_mul(r, a, b) help_ckd_mul(r, a, b, sizeof *(r), signed_expr(*(r)))
|
||||
/* True if the integer expression E, after promotion, is signed. */
|
||||
#define signed_expr(e) ((TRUE ? 0 : e) - 1 < 0)
|
||||
#endif
|
||||
|
||||
#if defined UINTMAX_MAX
|
||||
typedef uintmax_t uintmax;
|
||||
#elif defined ULLONG_MAX
|
||||
typedef unsigned long long uintmax;
|
||||
#else
|
||||
typedef unsigned long uintmax;
|
||||
#endif
|
||||
|
||||
/* OS-specific includes */
|
||||
#ifdef _OSK
|
||||
#include <modes.h>
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#ifdef __TANDEM
|
||||
#include <floss.h>
|
||||
#endif
|
||||
|
||||
#if MSDOS_COMPILER==WIN32C || OS2
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#if MSDOS_COMPILER==DJGPPC
|
||||
#include <io.h>
|
||||
#include <sys/exceptn.h>
|
||||
#include <conio.h>
|
||||
#include <pc.h>
|
||||
#endif
|
||||
|
||||
#if !HAVE_STDLIB_H
|
||||
char *getenv();
|
||||
off_t lseek();
|
||||
void *calloc();
|
||||
void free();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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')
|
||||
|
||||
#undef IS_UPPER
|
||||
#undef IS_LOWER
|
||||
#undef TO_UPPER
|
||||
#undef TO_LOWER
|
||||
#undef IS_SPACE
|
||||
#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)
|
||||
#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))
|
||||
#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)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef isspace
|
||||
#define IS_SPACE(c) isspace((unsigned char)(c))
|
||||
#else
|
||||
#define IS_SPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r' || (c) == '\f')
|
||||
#endif
|
||||
|
||||
#ifdef isdigit
|
||||
#define IS_DIGIT(c) isdigit((unsigned char)(c))
|
||||
#else
|
||||
#define IS_DIGIT(c) ((c) >= '0' && (c) <= '9')
|
||||
#endif
|
||||
|
||||
#define IS_CSI_START(c) (((LWCHAR)(c)) == ESC || (((LWCHAR)(c)) == CSI))
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#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))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAVE_SNPRINTF
|
||||
#define SNPRINTF1(str, size, fmt, v1) snprintf((str), (size), (fmt), (v1))
|
||||
#define SNPRINTF2(str, size, fmt, v1, v2) snprintf((str), (size), (fmt), (v1), (v2))
|
||||
#define SNPRINTF3(str, size, fmt, v1, v2, v3) snprintf((str), (size), (fmt), (v1), (v2), (v3))
|
||||
#define SNPRINTF4(str, size, fmt, v1, v2, v3, v4) snprintf((str), (size), (fmt), (v1), (v2), (v3), (v4))
|
||||
#else
|
||||
/* Use unsafe sprintf if we don't have snprintf. */
|
||||
#define SNPRINTF1(str, size, fmt, v1) sprintf((str), (fmt), (v1))
|
||||
#define SNPRINTF2(str, size, fmt, v1, v2) sprintf((str), (fmt), (v1), (v2))
|
||||
#define SNPRINTF3(str, size, fmt, v1, v2, v3) sprintf((str), (fmt), (v1), (v2), (v3))
|
||||
#define SNPRINTF4(str, size, fmt, v1, v2, v3, v4) sprintf((str), (fmt), (v1), (v2), (v3), (v4))
|
||||
#endif
|
||||
|
||||
#define BAD_LSEEK ((off_t)-1)
|
||||
|
||||
#ifndef SEEK_SET
|
||||
#define SEEK_SET 0
|
||||
#endif
|
||||
#ifndef SEEK_END
|
||||
#define SEEK_END 2
|
||||
#endif
|
||||
|
||||
#ifndef CHAR_BIT
|
||||
#define CHAR_BIT 8
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Upper bound on the string length of an integer converted to string.
|
||||
* 302 / 1000 is ceil (log10 (2.0)). Subtract 1 for the sign bit;
|
||||
* add 1 for integer division truncation; add 1 more for a minus sign.
|
||||
*/
|
||||
#define INT_STRLEN_BOUND(t) ((sizeof(t) * CHAR_BIT - 1) * 302 / 1000 + 1 + 1)
|
||||
|
||||
/*
|
||||
* Special types and constants.
|
||||
*/
|
||||
typedef unsigned long LWCHAR;
|
||||
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 MAX_PRCHAR_LEN 31 /* Max chars in prchar() result */
|
||||
|
||||
#define NULL_POSITION ((POSITION)(-1))
|
||||
|
||||
/*
|
||||
* Flags for open()
|
||||
*/
|
||||
#if MSDOS_COMPILER || OS2
|
||||
#define OPEN_READ (O_RDONLY|O_BINARY)
|
||||
#else
|
||||
#ifdef _OSK
|
||||
#define OPEN_READ (S_IREAD)
|
||||
#else
|
||||
#ifdef O_RDONLY
|
||||
#define OPEN_READ (O_RDONLY)
|
||||
#else
|
||||
#define OPEN_READ (0)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(O_WRONLY) && defined(O_APPEND)
|
||||
#define OPEN_APPEND (O_APPEND|O_WRONLY)
|
||||
#else
|
||||
#ifdef _OSK
|
||||
#define OPEN_APPEND (S_IWRITE)
|
||||
#else
|
||||
#define OPEN_APPEND (1)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Flags for creat()
|
||||
*/
|
||||
#if MSDOS_COMPILER
|
||||
#define CREAT_RW (S_IREAD|S_IWRITE)
|
||||
#else
|
||||
#define CREAT_RW 0644
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set a file descriptor to binary mode.
|
||||
*/
|
||||
#if MSDOS_COMPILER==MSOFTC
|
||||
#define SET_BINARY(f) _setmode(f, _O_BINARY);
|
||||
#else
|
||||
#if MSDOS_COMPILER || OS2
|
||||
#define SET_BINARY(f) setmode(f, O_BINARY)
|
||||
#else
|
||||
#define SET_BINARY(f)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Does the shell treat "?" as a metacharacter?
|
||||
*/
|
||||
#if MSDOS_COMPILER || OS2 || _OSK
|
||||
#define SHELL_META_QUEST 0
|
||||
#else
|
||||
#define SHELL_META_QUEST 1
|
||||
#endif
|
||||
|
||||
#define SPACES_IN_FILENAMES 1
|
||||
|
||||
/*
|
||||
* An IFILE represents an input file.
|
||||
*/
|
||||
#define IFILE void*
|
||||
#define NULL_IFILE ((IFILE)NULL)
|
||||
|
||||
/*
|
||||
* The structure used to represent a "screen position".
|
||||
* This consists of a file position, and a screen line number.
|
||||
* The meaning is that the line starting at the given file
|
||||
* position is displayed on the ln-th line of the screen.
|
||||
* (Screen lines before ln are empty.)
|
||||
*/
|
||||
struct scrpos
|
||||
{
|
||||
POSITION pos;
|
||||
int ln;
|
||||
};
|
||||
|
||||
typedef union parg
|
||||
{
|
||||
char *p_string;
|
||||
int p_int;
|
||||
LINENUM p_linenum;
|
||||
char p_char;
|
||||
} PARG;
|
||||
|
||||
#define NULL_PARG ((PARG *)NULL)
|
||||
|
||||
struct textlist
|
||||
{
|
||||
char *string;
|
||||
char *endstring;
|
||||
};
|
||||
|
||||
struct wchar_range
|
||||
{
|
||||
LWCHAR first, last;
|
||||
};
|
||||
|
||||
struct wchar_range_table
|
||||
{
|
||||
struct wchar_range *table;
|
||||
int count;
|
||||
};
|
||||
|
||||
#if HAVE_POLL
|
||||
typedef short POLL_EVENTS;
|
||||
#endif
|
||||
|
||||
#define EOI (-1)
|
||||
|
||||
#define READ_ERR (-1)
|
||||
#define READ_INTR (-2)
|
||||
#define READ_AGAIN (-3)
|
||||
|
||||
/*
|
||||
* A fraction is represented by a long n; the fraction is n/NUM_FRAC_DENOM.
|
||||
* To avoid overflow problems, 0 <= n < NUM_FRAC_DENUM <= LONG_MAX/100.
|
||||
*/
|
||||
#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 */
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* 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_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 */
|
||||
#define SRCH_FIRST_FILE (1 << 10) /* Search starting at the first file */
|
||||
#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_SUBSEARCH(i) (1 << (16+(i))) /* Search for subpattern */
|
||||
/* {{ Depends on NUM_SEARCH_COLORS==5 }} */
|
||||
#define SRCH_SUBSEARCH_ALL (SRCH_SUBSEARCH(1)|SRCH_SUBSEARCH(2)|SRCH_SUBSEARCH(3)|SRCH_SUBSEARCH(4)|SRCH_SUBSEARCH(5))
|
||||
|
||||
#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 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_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_HEADER (9 << AT_COLOR_SHIFT)
|
||||
#define AT_COLOR_SEARCH (10 << AT_COLOR_SHIFT)
|
||||
#define AT_COLOR_SUBSEARCH(i) ((10+(i)) << AT_COLOR_SHIFT)
|
||||
#define NUM_SEARCH_COLORS (AT_NUM_COLORS-10-1)
|
||||
|
||||
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
|
||||
#endif
|
||||
|
||||
#if IS_EBCDIC_HOST
|
||||
/*
|
||||
* Long definition for EBCDIC.
|
||||
* Since the argument is usually a constant, this macro normally compiles
|
||||
* 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)
|
||||
#else
|
||||
#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
|
||||
|
||||
#if _OSK_MWC32
|
||||
#define LSIGNAL(sig,func) os9_signal(sig,func)
|
||||
#else
|
||||
#define LSIGNAL(sig,func) signal(sig,func)
|
||||
#endif
|
||||
|
||||
#if HAVE_SIGPROCMASK
|
||||
#if HAVE_SIGSET_T
|
||||
#else
|
||||
#undef HAVE_SIGPROCMASK
|
||||
#endif
|
||||
#endif
|
||||
#if HAVE_SIGPROCMASK
|
||||
#if HAVE_SIGEMPTYSET
|
||||
#else
|
||||
#undef sigemptyset
|
||||
#define sigemptyset(mp) *(mp) = 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define S_INTERRUPT 01
|
||||
#define S_STOP 02
|
||||
#define S_WINCH 04
|
||||
#define ABORT_SIGS() (sigs & (S_INTERRUPT|S_STOP))
|
||||
|
||||
#ifdef EXIT_SUCCESS
|
||||
#define QUIT_OK EXIT_SUCCESS
|
||||
#else
|
||||
#define QUIT_OK 0
|
||||
#endif
|
||||
#ifdef EXIT_FAILURE
|
||||
#define QUIT_ERROR EXIT_FAILURE
|
||||
#define QUIT_INTERRUPT (EXIT_FAILURE+1)
|
||||
#else
|
||||
#define QUIT_ERROR 1
|
||||
#define QUIT_INTERRUPT 2
|
||||
#endif
|
||||
#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_zero() ((POSITION)0)
|
||||
|
||||
#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 */
|
||||
|
||||
#if HAVE_TIME_T
|
||||
#define time_type time_t
|
||||
#else
|
||||
#define time_type long
|
||||
#endif
|
||||
|
||||
/* X11 mouse reporting definitions */
|
||||
#define X11MOUSE_BUTTON1 0 /* Left button press */
|
||||
#define X11MOUSE_BUTTON2 1 /* Middle button press */
|
||||
#define X11MOUSE_BUTTON3 2 /* Right button press */
|
||||
#define X11MOUSE_BUTTON_REL 3 /* Button release */
|
||||
#define X11MOUSE_WHEEL_UP 0x40 /* Wheel scroll up */
|
||||
#define X11MOUSE_WHEEL_DOWN 0x41 /* Wheel scroll down */
|
||||
#define X11MOUSE_OFFSET 0x20 /* Added to button & pos bytes to create a char */
|
||||
|
||||
#if LESSTEST
|
||||
#define LESS_DUMP_CHAR CONTROL(']')
|
||||
#endif
|
||||
|
||||
struct mlist;
|
||||
struct loption;
|
||||
struct hilite_tree;
|
||||
struct ansi_state;
|
||||
#include "pattern.h"
|
||||
#include "xbuf.h"
|
||||
#include "funcs.h"
|
||||
|
||||
/* Functions not included in funcs.h */
|
||||
void postoa(POSITION, char*, int);
|
||||
void linenumtoa(LINENUM, char*, int);
|
||||
void inttoa(int, char*, int);
|
||||
int lstrtoi(char*, char**, int);
|
||||
POSITION lstrtopos(char*, char**, int);
|
||||
unsigned long lstrtoul(char*, char**, int);
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
int pclose(FILE*);
|
||||
#endif
|
282
third_party/less/lessecho.c
vendored
Normal file
282
third_party/less/lessecho.c
vendored
Normal file
|
@ -0,0 +1,282 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* lessecho [-ox] [-cx] [-pn] [-dn] [-a] file ...
|
||||
* 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.
|
||||
* -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.
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
|
||||
static char *version = "$Revision: 1.15 $";
|
||||
|
||||
static int quote_all = 0;
|
||||
static char openquote = '"';
|
||||
static char closequote = '"';
|
||||
static char *meta_escape = "\\";
|
||||
static char meta_escape_buf[2];
|
||||
static char* metachars = NULL;
|
||||
static int num_metachars = 0;
|
||||
static int size_metachars = 0;
|
||||
|
||||
static void pr_usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: lessecho [-ox] [-cx] [-pn] [-dn] [-mx] [-nn] [-ex] [-fn] [-a] file ...\n");
|
||||
}
|
||||
|
||||
static void pr_version(void)
|
||||
{
|
||||
char *p;
|
||||
char buf[10];
|
||||
char *pbuf = buf;
|
||||
|
||||
for (p = version; *p != ' '; p++)
|
||||
if (*p == '\0')
|
||||
return;
|
||||
for (p++; *p != '$' && *p != ' ' && *p != '\0'; p++)
|
||||
*pbuf++ = *p;
|
||||
*pbuf = '\0';
|
||||
printf("%s\n", buf);
|
||||
}
|
||||
|
||||
static void pr_error(char *s)
|
||||
{
|
||||
fprintf(stderr, "%s\n", s);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static long lstrtol(char *s, char **pend, int radix)
|
||||
{
|
||||
int v;
|
||||
int neg = 0;
|
||||
long n = 0;
|
||||
|
||||
/* Skip leading white space. */
|
||||
while (*s == ' ' || *s == '\t')
|
||||
s++;
|
||||
|
||||
/* Check for a leading + or -. */
|
||||
if (*s == '-')
|
||||
{
|
||||
neg = 1;
|
||||
s++;
|
||||
} else if (*s == '+')
|
||||
{
|
||||
s++;
|
||||
}
|
||||
|
||||
/* Determine radix if caller does not specify. */
|
||||
if (radix == 0)
|
||||
{
|
||||
radix = 10;
|
||||
if (*s == '0')
|
||||
{
|
||||
switch (*++s)
|
||||
{
|
||||
case 'x':
|
||||
radix = 16;
|
||||
s++;
|
||||
break;
|
||||
default:
|
||||
radix = 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse the digits of the number. */
|
||||
for (;;)
|
||||
{
|
||||
if (*s >= '0' && *s <= '9')
|
||||
v = *s - '0';
|
||||
else if (*s >= 'a' && *s <= 'f')
|
||||
v = *s - 'a' + 10;
|
||||
else if (*s >= 'A' && *s <= 'F')
|
||||
v = *s - 'A' + 10;
|
||||
else
|
||||
break;
|
||||
if (v >= radix)
|
||||
break;
|
||||
n = n * radix + v;
|
||||
s++;
|
||||
}
|
||||
|
||||
if (pend != NULL)
|
||||
{
|
||||
/* Skip trailing white space. */
|
||||
while (*s == ' ' || *s == '\t')
|
||||
s++;
|
||||
*pend = s;
|
||||
}
|
||||
if (neg)
|
||||
return (-n);
|
||||
return (n);
|
||||
}
|
||||
|
||||
static void add_metachar(int ch)
|
||||
{
|
||||
if (num_metachars+1 >= size_metachars)
|
||||
{
|
||||
char *p;
|
||||
size_metachars = (size_metachars > 0) ? size_metachars*2 : 16;
|
||||
p = (char *) malloc(size_metachars);
|
||||
if (p == NULL)
|
||||
pr_error("Cannot allocate memory");
|
||||
|
||||
if (metachars != NULL)
|
||||
{
|
||||
strcpy(p, metachars);
|
||||
free(metachars);
|
||||
}
|
||||
metachars = p;
|
||||
}
|
||||
metachars[num_metachars++] = ch;
|
||||
metachars[num_metachars] = '\0';
|
||||
}
|
||||
|
||||
static int is_metachar(int ch)
|
||||
{
|
||||
return (metachars != NULL && strchr(metachars, ch) != NULL);
|
||||
}
|
||||
|
||||
#if !HAVE_STRCHR
|
||||
char * strchr(char *s, char c)
|
||||
{
|
||||
for ( ; *s != '\0'; s++)
|
||||
if (*s == c)
|
||||
return (s);
|
||||
if (c == '\0')
|
||||
return (s);
|
||||
return (NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *arg;
|
||||
char *s;
|
||||
int no_more_options;
|
||||
|
||||
no_more_options = 0;
|
||||
while (--argc > 0)
|
||||
{
|
||||
arg = *++argv;
|
||||
if (*arg != '-' || no_more_options)
|
||||
break;
|
||||
switch (*++arg)
|
||||
{
|
||||
case 'a':
|
||||
quote_all = 1;
|
||||
break;
|
||||
case 'c':
|
||||
closequote = *++arg;
|
||||
break;
|
||||
case 'd':
|
||||
closequote = lstrtol(++arg, &s, 0);
|
||||
if (s == arg)
|
||||
pr_error("Missing number after -d");
|
||||
break;
|
||||
case 'e':
|
||||
if (strcmp(++arg, "-") == 0)
|
||||
meta_escape = "";
|
||||
else
|
||||
meta_escape = arg;
|
||||
break;
|
||||
case 'f':
|
||||
meta_escape_buf[0] = lstrtol(++arg, &s, 0);
|
||||
meta_escape_buf[1] = '\0';
|
||||
meta_escape = meta_escape_buf;
|
||||
if (s == arg)
|
||||
pr_error("Missing number after -f");
|
||||
break;
|
||||
case 'o':
|
||||
openquote = *++arg;
|
||||
break;
|
||||
case 'p':
|
||||
openquote = lstrtol(++arg, &s, 0);
|
||||
if (s == arg)
|
||||
pr_error("Missing number after -p");
|
||||
break;
|
||||
case 'm':
|
||||
add_metachar(*++arg);
|
||||
break;
|
||||
case 'n':
|
||||
add_metachar(lstrtol(++arg, &s, 0));
|
||||
if (s == arg)
|
||||
pr_error("Missing number after -n");
|
||||
break;
|
||||
case '?':
|
||||
pr_usage();
|
||||
return (0);
|
||||
case '-':
|
||||
if (*++arg == '\0')
|
||||
{
|
||||
no_more_options = 1;
|
||||
break;
|
||||
}
|
||||
if (strcmp(arg, "version") == 0)
|
||||
{
|
||||
pr_version();
|
||||
return (0);
|
||||
}
|
||||
if (strcmp(arg, "help") == 0)
|
||||
{
|
||||
pr_usage();
|
||||
return (0);
|
||||
}
|
||||
pr_error("Invalid option after --");
|
||||
default:
|
||||
pr_error("Invalid option letter");
|
||||
}
|
||||
}
|
||||
|
||||
while (argc-- > 0)
|
||||
{
|
||||
int has_meta = 0;
|
||||
arg = *argv++;
|
||||
for (s = arg; *s != '\0'; s++)
|
||||
{
|
||||
if (is_metachar(*s))
|
||||
{
|
||||
has_meta = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (quote_all || (has_meta && strlen(meta_escape) == 0))
|
||||
printf("%c%s%c", openquote, arg, closequote);
|
||||
else
|
||||
{
|
||||
for (s = arg; *s != '\0'; s++)
|
||||
{
|
||||
if (is_metachar(*s))
|
||||
printf("%s", meta_escape);
|
||||
printf("%c", *s);
|
||||
}
|
||||
}
|
||||
if (argc > 0)
|
||||
printf(" ");
|
||||
else
|
||||
printf("\n");
|
||||
}
|
||||
return (0);
|
||||
}
|
357
third_party/less/lesskey.c
vendored
Normal file
357
third_party/less/lesskey.c
vendored
Normal file
|
@ -0,0 +1,357 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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 <whitespace> action [chars] <newline>
|
||||
*
|
||||
* "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.
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* 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> <action>
|
||||
* or
|
||||
* string <0> <action|A_EXTRA> chars <0>
|
||||
*
|
||||
* "string" is the command string.
|
||||
* "<0>" is one null byte.
|
||||
* "<action>" 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.
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*/
|
||||
|
||||
#include "defines.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "lesskey.h"
|
||||
#include "cmd.h"
|
||||
|
||||
char fileheader[] = {
|
||||
C0_LESSKEY_MAGIC,
|
||||
C1_LESSKEY_MAGIC,
|
||||
C2_LESSKEY_MAGIC,
|
||||
C3_LESSKEY_MAGIC
|
||||
};
|
||||
char filetrailer[] = {
|
||||
C0_END_LESSKEY_MAGIC,
|
||||
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 *infile = NULL;
|
||||
char *outfile = NULL ;
|
||||
|
||||
extern char version[];
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(stderr, "usage: lesskey [-o output] [input]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void lesskey_parse_error(char *s)
|
||||
{
|
||||
fprintf(stderr, "%s\n", s);
|
||||
}
|
||||
|
||||
int lstrtoi(char *buf, char **ebuf, int radix)
|
||||
{
|
||||
return (int) strtol(buf, ebuf, radix);
|
||||
}
|
||||
|
||||
void out_of_memory(void)
|
||||
{
|
||||
fprintf(stderr, "lesskey: cannot allocate memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void * ecalloc(int count, unsigned int size)
|
||||
{
|
||||
void *p;
|
||||
|
||||
p = calloc(count, size);
|
||||
if (p == NULL)
|
||||
out_of_memory();
|
||||
return (p);
|
||||
}
|
||||
|
||||
static char * mkpathname(char *dirname, char *filename)
|
||||
{
|
||||
char *pathname;
|
||||
|
||||
pathname = ecalloc(strlen(dirname) + strlen(filename) + 2, sizeof(char));
|
||||
strcpy(pathname, dirname);
|
||||
strcat(pathname, PATHNAME_SEP);
|
||||
strcat(pathname, filename);
|
||||
return (pathname);
|
||||
}
|
||||
|
||||
/*
|
||||
* Figure out the name of a default file (in the user's HOME directory).
|
||||
*/
|
||||
char * homefile(char *filename)
|
||||
{
|
||||
char *p;
|
||||
char *pathname;
|
||||
|
||||
if ((p = getenv("HOME")) != NULL && *p != '\0')
|
||||
pathname = mkpathname(p, filename);
|
||||
#if OS2
|
||||
else if ((p = getenv("INIT")) != NULL && *p != '\0')
|
||||
pathname = mkpathname(p, filename);
|
||||
#endif
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "cannot find $HOME - using current directory\n");
|
||||
pathname = mkpathname(".", filename);
|
||||
}
|
||||
return (pathname);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse command line arguments.
|
||||
*/
|
||||
static void parse_args(int argc, char **argv)
|
||||
{
|
||||
char *arg;
|
||||
|
||||
outfile = NULL;
|
||||
while (--argc > 0)
|
||||
{
|
||||
arg = *++argv;
|
||||
if (arg[0] != '-')
|
||||
/* Arg does not start with "-"; it's not an option. */
|
||||
break;
|
||||
if (arg[1] == '\0')
|
||||
/* "-" means standard input. */
|
||||
break;
|
||||
if (arg[1] == '-' && arg[2] == '\0')
|
||||
{
|
||||
/* "--" means end of options. */
|
||||
argc--;
|
||||
argv++;
|
||||
break;
|
||||
}
|
||||
switch (arg[1])
|
||||
{
|
||||
case '-':
|
||||
if (strncmp(arg, "--output", 8) == 0)
|
||||
{
|
||||
if (arg[8] == '\0')
|
||||
outfile = &arg[8];
|
||||
else if (arg[8] == '=')
|
||||
outfile = &arg[9];
|
||||
else
|
||||
usage();
|
||||
goto opt_o;
|
||||
}
|
||||
if (strcmp(arg, "--version") == 0)
|
||||
{
|
||||
goto opt_V;
|
||||
}
|
||||
usage();
|
||||
break;
|
||||
case 'o':
|
||||
outfile = &argv[0][2];
|
||||
opt_o:
|
||||
if (*outfile == '\0')
|
||||
{
|
||||
if (--argc <= 0)
|
||||
usage();
|
||||
outfile = *(++argv);
|
||||
}
|
||||
break;
|
||||
case 'V':
|
||||
opt_V:
|
||||
printf("lesskey version %s\n", version);
|
||||
exit(0);
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
if (argc > 1)
|
||||
usage();
|
||||
/*
|
||||
* Open the input file, or use DEF_LESSKEYINFILE if none specified.
|
||||
*/
|
||||
if (argc > 0)
|
||||
infile = *argv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Output some bytes.
|
||||
*/
|
||||
static void fputbytes(FILE *fd, char *buf, int len)
|
||||
{
|
||||
while (len-- > 0)
|
||||
{
|
||||
fwrite(buf, sizeof(char), 1, fd);
|
||||
buf++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Output an integer, in special KRADIX form.
|
||||
*/
|
||||
static void fputint(FILE *fd, unsigned int val)
|
||||
{
|
||||
char c;
|
||||
|
||||
if (val >= KRADIX*KRADIX)
|
||||
{
|
||||
fprintf(stderr, "error: cannot write %d, max %d\n",
|
||||
val, KRADIX*KRADIX);
|
||||
exit(1);
|
||||
}
|
||||
c = val % KRADIX;
|
||||
fwrite(&c, sizeof(char), 1, fd);
|
||||
c = val / KRADIX;
|
||||
fwrite(&c, sizeof(char), 1, fd);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct lesskey_tables tables;
|
||||
FILE *out;
|
||||
int errors;
|
||||
|
||||
#ifdef WIN32
|
||||
if (getenv("HOME") == NULL)
|
||||
{
|
||||
/*
|
||||
* If there is no HOME environment variable,
|
||||
* try the concatenation of HOMEDRIVE + HOMEPATH.
|
||||
*/
|
||||
char *drive = getenv("HOMEDRIVE");
|
||||
char *path = getenv("HOMEPATH");
|
||||
if (drive != NULL && path != NULL)
|
||||
{
|
||||
char *env = (char *) ecalloc(strlen(drive) +
|
||||
strlen(path) + 6, sizeof(char));
|
||||
strcpy(env, "HOME=");
|
||||
strcat(env, drive);
|
||||
strcat(env, path);
|
||||
putenv(env);
|
||||
}
|
||||
}
|
||||
#endif /* WIN32 */
|
||||
|
||||
/*
|
||||
* Process command line arguments.
|
||||
*/
|
||||
parse_args(argc, argv);
|
||||
errors = parse_lesskey(infile, &tables);
|
||||
if (errors)
|
||||
{
|
||||
fprintf(stderr, "%d errors; no output produced\n", errors);
|
||||
return (1);
|
||||
}
|
||||
|
||||
fprintf(stderr, "NOTE: lesskey is deprecated.\n It is no longer necessary to run lesskey,\n when using less version 582 and later.\n");
|
||||
|
||||
/*
|
||||
* Write the output file.
|
||||
* If no output file was specified, use "$HOME/.less"
|
||||
*/
|
||||
if (outfile == NULL)
|
||||
outfile = getenv("LESSKEY");
|
||||
if (outfile == NULL)
|
||||
outfile = homefile(LESSKEYFILE);
|
||||
if ((out = fopen(outfile, "wb")) == NULL)
|
||||
{
|
||||
#if HAVE_PERROR
|
||||
perror(outfile);
|
||||
#else
|
||||
fprintf(stderr, "Cannot open %s\n", outfile);
|
||||
#endif
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* File header */
|
||||
fputbytes(out, fileheader, sizeof(fileheader));
|
||||
|
||||
/* Command key section */
|
||||
fputbytes(out, cmdsection, sizeof(cmdsection));
|
||||
fputint(out, tables.cmdtable.buf.end);
|
||||
fputbytes(out, (char *)tables.cmdtable.buf.data, tables.cmdtable.buf.end);
|
||||
/* Edit key section */
|
||||
fputbytes(out, editsection, sizeof(editsection));
|
||||
fputint(out, tables.edittable.buf.end);
|
||||
fputbytes(out, (char *)tables.edittable.buf.data, tables.edittable.buf.end);
|
||||
|
||||
/* Environment variable section */
|
||||
fputbytes(out, varsection, sizeof(varsection));
|
||||
fputint(out, tables.vartable.buf.end);
|
||||
fputbytes(out, (char *)tables.vartable.buf.data, tables.vartable.buf.end);
|
||||
|
||||
/* File trailer */
|
||||
fputbytes(out, endsection, sizeof(endsection));
|
||||
fputbytes(out, filetrailer, sizeof(filetrailer));
|
||||
fclose(out);
|
||||
return (0);
|
||||
}
|
63
third_party/less/lesskey.h
vendored
Normal file
63
third_party/less/lesskey.h
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
#include "xbuf.h"
|
||||
|
||||
/*
|
||||
* Format of a lesskey file:
|
||||
*
|
||||
* 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)
|
||||
*/
|
||||
#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 C0_END_LESSKEY_MAGIC 'E'
|
||||
#define C1_END_LESSKEY_MAGIC 'n'
|
||||
#define C2_END_LESSKEY_MAGIC 'd'
|
||||
|
||||
/* */
|
||||
#define KRADIX 64
|
||||
|
||||
struct lesskey_cmdname
|
||||
{
|
||||
char *cn_name;
|
||||
int cn_action;
|
||||
};
|
||||
|
||||
struct lesskey_table
|
||||
{
|
||||
struct lesskey_cmdname *names;
|
||||
struct xbuffer buf;
|
||||
int is_var;
|
||||
};
|
||||
|
||||
struct lesskey_tables
|
||||
{
|
||||
struct lesskey_table *currtable;
|
||||
struct lesskey_table cmdtable;
|
||||
struct lesskey_table edittable;
|
||||
struct lesskey_table vartable;
|
||||
};
|
||||
|
||||
extern int parse_lesskey(char *infile, struct lesskey_tables *tables);
|
651
third_party/less/lesskey_parse.c
vendored
Normal file
651
third_party/less/lesskey_parse.c
vendored
Normal file
|
@ -0,0 +1,651 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
#include "defines.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "lesskey.h"
|
||||
#include "cmd.h"
|
||||
#include "xbuf.h"
|
||||
|
||||
#define CONTROL(c) ((c)&037)
|
||||
#define ESC CONTROL('[')
|
||||
|
||||
extern void lesskey_parse_error(char *msg);
|
||||
extern char *homefile(char *filename);
|
||||
extern void *ecalloc(int count, unsigned int size);
|
||||
extern int lstrtoi(char *str, char **end, int radix);
|
||||
extern char version[];
|
||||
|
||||
static int linenum;
|
||||
static int errors;
|
||||
static int less_version = 0;
|
||||
static char *lesskey_file;
|
||||
|
||||
static struct lesskey_cmdname cmdnames[] =
|
||||
{
|
||||
{ "back-bracket", A_B_BRACKET },
|
||||
{ "back-line", A_B_LINE },
|
||||
{ "back-line-force", A_BF_LINE },
|
||||
{ "back-screen", A_B_SCREEN },
|
||||
{ "back-scroll", A_B_SCROLL },
|
||||
{ "back-search", A_B_SEARCH },
|
||||
{ "back-window", A_B_WINDOW },
|
||||
{ "clear-mark", A_CLRMARK },
|
||||
{ "debug", A_DEBUG },
|
||||
{ "digit", A_DIGIT },
|
||||
{ "display-flag", A_DISP_OPTION },
|
||||
{ "display-option", A_DISP_OPTION },
|
||||
{ "end", A_GOEND },
|
||||
{ "end-scroll", A_RRSHIFT },
|
||||
{ "examine", A_EXAMINE },
|
||||
{ "filter", A_FILTER },
|
||||
{ "first-cmd", A_FIRSTCMD },
|
||||
{ "firstcmd", A_FIRSTCMD },
|
||||
{ "flush-repaint", A_FREPAINT },
|
||||
{ "forw-bracket", A_F_BRACKET },
|
||||
{ "forw-forever", A_F_FOREVER },
|
||||
{ "forw-until-hilite", A_F_UNTIL_HILITE },
|
||||
{ "forw-line", A_F_LINE },
|
||||
{ "forw-line-force", A_FF_LINE },
|
||||
{ "forw-screen", A_F_SCREEN },
|
||||
{ "forw-screen-force", A_FF_SCREEN },
|
||||
{ "forw-scroll", A_F_SCROLL },
|
||||
{ "forw-search", A_F_SEARCH },
|
||||
{ "forw-window", A_F_WINDOW },
|
||||
{ "goto-end", A_GOEND },
|
||||
{ "goto-end-buffered", A_GOEND_BUF },
|
||||
{ "goto-line", A_GOLINE },
|
||||
{ "goto-mark", A_GOMARK },
|
||||
{ "help", A_HELP },
|
||||
{ "index-file", A_INDEX_FILE },
|
||||
{ "invalid", A_UINVALID },
|
||||
{ "left-scroll", A_LSHIFT },
|
||||
{ "next-file", A_NEXT_FILE },
|
||||
{ "next-tag", A_NEXT_TAG },
|
||||
{ "noaction", A_NOACTION },
|
||||
{ "no-scroll", A_LLSHIFT },
|
||||
{ "percent", A_PERCENT },
|
||||
{ "pipe", A_PIPE },
|
||||
{ "prev-file", A_PREV_FILE },
|
||||
{ "prev-tag", A_PREV_TAG },
|
||||
{ "quit", A_QUIT },
|
||||
{ "remove-file", A_REMOVE_FILE },
|
||||
{ "repaint", A_REPAINT },
|
||||
{ "repaint-flush", A_FREPAINT },
|
||||
{ "repeat-search", A_AGAIN_SEARCH },
|
||||
{ "repeat-search-all", A_T_AGAIN_SEARCH },
|
||||
{ "reverse-search", A_REVERSE_SEARCH },
|
||||
{ "reverse-search-all", A_T_REVERSE_SEARCH },
|
||||
{ "right-scroll", A_RSHIFT },
|
||||
{ "set-mark", A_SETMARK },
|
||||
{ "set-mark-bottom", A_SETMARKBOT },
|
||||
{ "shell", A_SHELL },
|
||||
{ "pshell", A_PSHELL },
|
||||
{ "status", A_STAT },
|
||||
{ "toggle-flag", A_OPT_TOGGLE },
|
||||
{ "toggle-option", A_OPT_TOGGLE },
|
||||
{ "undo-hilite", A_UNDO_SEARCH },
|
||||
{ "clear-search", A_CLR_SEARCH },
|
||||
{ "version", A_VERSION },
|
||||
{ "visual", A_VISUAL },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static struct lesskey_cmdname editnames[] =
|
||||
{
|
||||
{ "back-complete", EC_B_COMPLETE },
|
||||
{ "backspace", EC_BACKSPACE },
|
||||
{ "delete", EC_DELETE },
|
||||
{ "down", EC_DOWN },
|
||||
{ "end", EC_END },
|
||||
{ "expand", EC_EXPAND },
|
||||
{ "forw-complete", EC_F_COMPLETE },
|
||||
{ "home", EC_HOME },
|
||||
{ "insert", EC_INSERT },
|
||||
{ "invalid", EC_UINVALID },
|
||||
{ "kill-line", EC_LINEKILL },
|
||||
{ "abort", EC_ABORT },
|
||||
{ "left", EC_LEFT },
|
||||
{ "literal", EC_LITERAL },
|
||||
{ "right", EC_RIGHT },
|
||||
{ "up", EC_UP },
|
||||
{ "word-backspace", EC_W_BACKSPACE },
|
||||
{ "word-delete", EC_W_DELETE },
|
||||
{ "word-left", EC_W_LEFT },
|
||||
{ "word-right", EC_W_RIGHT },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
/*
|
||||
* Print a parse error message.
|
||||
*/
|
||||
static void parse_error(char *fmt, char *arg1)
|
||||
{
|
||||
char buf[1024];
|
||||
int n = snprintf(buf, sizeof(buf), "%s: line %d: ", lesskey_file, linenum);
|
||||
if (n >= 0 && n < sizeof(buf))
|
||||
snprintf(buf+n, sizeof(buf)-n, fmt, arg1);
|
||||
++errors;
|
||||
lesskey_parse_error(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize lesskey_tables.
|
||||
*/
|
||||
static void init_tables(struct lesskey_tables *tables)
|
||||
{
|
||||
tables->currtable = &tables->cmdtable;
|
||||
|
||||
tables->cmdtable.names = cmdnames;
|
||||
tables->cmdtable.is_var = 0;
|
||||
xbuf_init(&tables->cmdtable.buf);
|
||||
|
||||
tables->edittable.names = editnames;
|
||||
tables->edittable.is_var = 0;
|
||||
xbuf_init(&tables->edittable.buf);
|
||||
|
||||
tables->vartable.names = NULL;
|
||||
tables->vartable.is_var = 1;
|
||||
xbuf_init(&tables->vartable.buf);
|
||||
}
|
||||
|
||||
#define CHAR_STRING_LEN 8
|
||||
|
||||
static char * char_string(char *buf, int ch, int lit)
|
||||
{
|
||||
if (lit || (ch >= 0x20 && ch < 0x7f))
|
||||
{
|
||||
buf[0] = ch;
|
||||
buf[1] = '\0';
|
||||
} else
|
||||
{
|
||||
snprintf(buf, CHAR_STRING_LEN, "\\x%02x", ch);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Increment char pointer by one up to terminating nul byte.
|
||||
*/
|
||||
static char * increment_pointer(char *p)
|
||||
{
|
||||
if (*p == '\0')
|
||||
return p;
|
||||
return p+1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse one character of a string.
|
||||
*/
|
||||
static char * tstr(char **pp, int xlate)
|
||||
{
|
||||
char *p;
|
||||
char ch;
|
||||
int i;
|
||||
static char buf[CHAR_STRING_LEN];
|
||||
static char tstr_control_k[] =
|
||||
{ SK_SPECIAL_KEY, SK_CONTROL_K, 6, 1, 1, 1, '\0' };
|
||||
|
||||
p = *pp;
|
||||
switch (*p)
|
||||
{
|
||||
case '\\':
|
||||
++p;
|
||||
switch (*p)
|
||||
{
|
||||
case '0': case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
/*
|
||||
* Parse an octal number.
|
||||
*/
|
||||
ch = 0;
|
||||
i = 0;
|
||||
do
|
||||
ch = 8*ch + (*p - '0');
|
||||
while (*++p >= '0' && *p <= '7' && ++i < 3);
|
||||
*pp = p;
|
||||
if (xlate && ch == CONTROL('K'))
|
||||
return tstr_control_k;
|
||||
return char_string(buf, ch, 1);
|
||||
case 'b':
|
||||
*pp = p+1;
|
||||
return ("\b");
|
||||
case 'e':
|
||||
*pp = p+1;
|
||||
return char_string(buf, ESC, 1);
|
||||
case 'n':
|
||||
*pp = p+1;
|
||||
return ("\n");
|
||||
case 'r':
|
||||
*pp = p+1;
|
||||
return ("\r");
|
||||
case 't':
|
||||
*pp = p+1;
|
||||
return ("\t");
|
||||
case 'k':
|
||||
if (xlate)
|
||||
{
|
||||
switch (*++p)
|
||||
{
|
||||
case 'b': ch = SK_BACKSPACE; break;
|
||||
case 'B': ch = SK_CTL_BACKSPACE; break;
|
||||
case 'd': ch = SK_DOWN_ARROW; break;
|
||||
case 'D': ch = SK_PAGE_DOWN; break;
|
||||
case 'e': ch = SK_END; break;
|
||||
case 'h': ch = SK_HOME; break;
|
||||
case 'i': ch = SK_INSERT; break;
|
||||
case 'l': ch = SK_LEFT_ARROW; break;
|
||||
case 'L': ch = SK_CTL_LEFT_ARROW; break;
|
||||
case 'r': ch = SK_RIGHT_ARROW; break;
|
||||
case 'R': ch = SK_CTL_RIGHT_ARROW; break;
|
||||
case 't': ch = SK_BACKTAB; break;
|
||||
case 'u': ch = SK_UP_ARROW; break;
|
||||
case 'U': ch = SK_PAGE_UP; break;
|
||||
case 'x': ch = SK_DELETE; break;
|
||||
case 'X': ch = SK_CTL_DELETE; break;
|
||||
case '1': ch = SK_F1; break;
|
||||
default:
|
||||
parse_error("invalid escape sequence \"\\k%s\"", char_string(buf, *p, 0));
|
||||
*pp = increment_pointer(p);
|
||||
return ("");
|
||||
}
|
||||
*pp = p+1;
|
||||
buf[0] = SK_SPECIAL_KEY;
|
||||
buf[1] = ch;
|
||||
buf[2] = 6;
|
||||
buf[3] = 1;
|
||||
buf[4] = 1;
|
||||
buf[5] = 1;
|
||||
buf[6] = '\0';
|
||||
return (buf);
|
||||
}
|
||||
/* FALLTHRU */
|
||||
default:
|
||||
/*
|
||||
* Backslash followed by any other char
|
||||
* just means that char.
|
||||
*/
|
||||
*pp = increment_pointer(p);
|
||||
char_string(buf, *p, 1);
|
||||
if (xlate && buf[0] == CONTROL('K'))
|
||||
return tstr_control_k;
|
||||
return (buf);
|
||||
}
|
||||
case '^':
|
||||
/*
|
||||
* Caret means CONTROL.
|
||||
*/
|
||||
*pp = increment_pointer(p+1);
|
||||
char_string(buf, CONTROL(p[1]), 1);
|
||||
if (xlate && buf[0] == CONTROL('K'))
|
||||
return tstr_control_k;
|
||||
return (buf);
|
||||
}
|
||||
*pp = increment_pointer(p);
|
||||
char_string(buf, *p, 1);
|
||||
if (xlate && buf[0] == CONTROL('K'))
|
||||
return tstr_control_k;
|
||||
return (buf);
|
||||
}
|
||||
|
||||
static int issp(char ch)
|
||||
{
|
||||
return (ch == ' ' || ch == '\t');
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip leading spaces in a string.
|
||||
*/
|
||||
static char * skipsp(char *s)
|
||||
{
|
||||
while (issp(*s))
|
||||
s++;
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip non-space characters in a string.
|
||||
*/
|
||||
static char * skipnsp(char *s)
|
||||
{
|
||||
while (*s != '\0' && !issp(*s))
|
||||
s++;
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up an input line:
|
||||
* strip off the trailing newline & any trailing # comment.
|
||||
*/
|
||||
static char * clean_line(char *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
s = skipsp(s);
|
||||
for (i = 0; s[i] != '\0' && s[i] != '\n' && s[i] != '\r'; i++)
|
||||
if (s[i] == '#' && (i == 0 || s[i-1] != '\\'))
|
||||
break;
|
||||
s[i] = '\0';
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a byte to the output command table.
|
||||
*/
|
||||
static void add_cmd_char(unsigned char c, struct lesskey_tables *tables)
|
||||
{
|
||||
xbuf_add_byte(&tables->currtable->buf, c);
|
||||
}
|
||||
|
||||
static void erase_cmd_char(struct lesskey_tables *tables)
|
||||
{
|
||||
xbuf_pop(&tables->currtable->buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a string to the output command table.
|
||||
*/
|
||||
static void add_cmd_str(char *s, struct lesskey_tables *tables)
|
||||
{
|
||||
for ( ; *s != '\0'; s++)
|
||||
add_cmd_char(*s, tables);
|
||||
}
|
||||
|
||||
/*
|
||||
* Does a given version number match the running version?
|
||||
* Operator compares the running version to the given version.
|
||||
*/
|
||||
static int match_version(char op, int ver)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case '>': return less_version > ver;
|
||||
case '<': return less_version < ver;
|
||||
case '+': return less_version >= ver;
|
||||
case '-': return less_version <= ver;
|
||||
case '=': return less_version == ver;
|
||||
case '!': return less_version != ver;
|
||||
default: return 0; /* cannot happen */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle a #version line.
|
||||
* If the version matches, return the part of the line that should be executed.
|
||||
* Otherwise, return NULL.
|
||||
*/
|
||||
static char * version_line(char *s, struct lesskey_tables *tables)
|
||||
{
|
||||
char op;
|
||||
int ver;
|
||||
char *e;
|
||||
char buf[CHAR_STRING_LEN];
|
||||
|
||||
s += strlen("#version");
|
||||
s = skipsp(s);
|
||||
op = *s++;
|
||||
/* Simplify 2-char op to one char. */
|
||||
switch (op)
|
||||
{
|
||||
case '<': if (*s == '=') { s++; op = '-'; } break;
|
||||
case '>': if (*s == '=') { s++; op = '+'; } break;
|
||||
case '=': if (*s == '=') { s++; } break;
|
||||
case '!': if (*s == '=') { s++; } break;
|
||||
default:
|
||||
parse_error("invalid operator '%s' in #version line", char_string(buf, op, 0));
|
||||
return (NULL);
|
||||
}
|
||||
s = skipsp(s);
|
||||
ver = lstrtoi(s, &e, 10);
|
||||
if (e == s)
|
||||
{
|
||||
parse_error("non-numeric version number in #version line", "");
|
||||
return (NULL);
|
||||
}
|
||||
if (!match_version(op, ver))
|
||||
return (NULL);
|
||||
return (e);
|
||||
}
|
||||
|
||||
/*
|
||||
* See if we have a special "control" line.
|
||||
*/
|
||||
static char * control_line(char *s, struct lesskey_tables *tables)
|
||||
{
|
||||
#define PREFIX(str,pat) (strncmp(str,pat,strlen(pat)) == 0)
|
||||
|
||||
if (PREFIX(s, "#line-edit"))
|
||||
{
|
||||
tables->currtable = &tables->edittable;
|
||||
return (NULL);
|
||||
}
|
||||
if (PREFIX(s, "#command"))
|
||||
{
|
||||
tables->currtable = &tables->cmdtable;
|
||||
return (NULL);
|
||||
}
|
||||
if (PREFIX(s, "#env"))
|
||||
{
|
||||
tables->currtable = &tables->vartable;
|
||||
return (NULL);
|
||||
}
|
||||
if (PREFIX(s, "#stop"))
|
||||
{
|
||||
add_cmd_char('\0', tables);
|
||||
add_cmd_char(A_END_LIST, tables);
|
||||
return (NULL);
|
||||
}
|
||||
if (PREFIX(s, "#version"))
|
||||
{
|
||||
return (version_line(s, tables));
|
||||
}
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find an action, given the name of the action.
|
||||
*/
|
||||
static int findaction(char *actname, struct lesskey_tables *tables)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; tables->currtable->names[i].cn_name != NULL; i++)
|
||||
if (strcmp(tables->currtable->names[i].cn_name, actname) == 0)
|
||||
return (tables->currtable->names[i].cn_action);
|
||||
parse_error("unknown action: \"%s\"", actname);
|
||||
return (A_INVALID);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a line describing one key binding, of the form
|
||||
* KEY ACTION [EXTRA]
|
||||
* where KEY is the user key sequence, ACTION is the
|
||||
* resulting less action, and EXTRA is an "extra" user
|
||||
* key sequence injected after the action.
|
||||
*/
|
||||
static void parse_cmdline(char *p, struct lesskey_tables *tables)
|
||||
{
|
||||
char *actname;
|
||||
int action;
|
||||
char *s;
|
||||
char c;
|
||||
|
||||
/*
|
||||
* Parse the command string and store it in the current table.
|
||||
*/
|
||||
do
|
||||
{
|
||||
s = tstr(&p, 1);
|
||||
add_cmd_str(s, tables);
|
||||
} while (*p != '\0' && !issp(*p));
|
||||
/*
|
||||
* Terminate the command string with a null byte.
|
||||
*/
|
||||
add_cmd_char('\0', tables);
|
||||
|
||||
/*
|
||||
* Skip white space between the command string
|
||||
* and the action name.
|
||||
* Terminate the action name with a null byte.
|
||||
*/
|
||||
p = skipsp(p);
|
||||
if (*p == '\0')
|
||||
{
|
||||
parse_error("missing action", "");
|
||||
return;
|
||||
}
|
||||
actname = p;
|
||||
p = skipnsp(p);
|
||||
c = *p;
|
||||
*p = '\0';
|
||||
|
||||
/*
|
||||
* Parse the action name and store it in the current table.
|
||||
*/
|
||||
action = findaction(actname, tables);
|
||||
|
||||
/*
|
||||
* See if an extra string follows the action name.
|
||||
*/
|
||||
*p = c;
|
||||
p = skipsp(p);
|
||||
if (*p == '\0')
|
||||
{
|
||||
add_cmd_char((unsigned char) action, tables);
|
||||
} else
|
||||
{
|
||||
/*
|
||||
* OR the special value A_EXTRA into the action byte.
|
||||
* Put the extra string after the action byte.
|
||||
*/
|
||||
add_cmd_char((unsigned char) (action | A_EXTRA), tables);
|
||||
while (*p != '\0')
|
||||
add_cmd_str(tstr(&p, 0), tables);
|
||||
add_cmd_char('\0', tables);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a variable definition line, of the form
|
||||
* NAME = VALUE
|
||||
*/
|
||||
static void parse_varline(char *line, struct lesskey_tables *tables)
|
||||
{
|
||||
char *s;
|
||||
char *p = line;
|
||||
char *eq;
|
||||
|
||||
eq = strchr(line, '=');
|
||||
if (eq != NULL && eq > line && eq[-1] == '+')
|
||||
{
|
||||
/*
|
||||
* Rather ugly way of handling a += line.
|
||||
* {{ Note that we ignore the variable name and
|
||||
* just append to the previously defined variable. }}
|
||||
*/
|
||||
erase_cmd_char(tables); /* backspace over the final null */
|
||||
p = eq+1;
|
||||
} else
|
||||
{
|
||||
do
|
||||
{
|
||||
s = tstr(&p, 0);
|
||||
add_cmd_str(s, tables);
|
||||
} while (*p != '\0' && !issp(*p) && *p != '=');
|
||||
/*
|
||||
* Terminate the variable name with a null byte.
|
||||
*/
|
||||
add_cmd_char('\0', tables);
|
||||
p = skipsp(p);
|
||||
if (*p++ != '=')
|
||||
{
|
||||
parse_error("missing = in variable definition", "");
|
||||
return;
|
||||
}
|
||||
add_cmd_char(EV_OK|A_EXTRA, tables);
|
||||
}
|
||||
p = skipsp(p);
|
||||
while (*p != '\0')
|
||||
{
|
||||
s = tstr(&p, 0);
|
||||
add_cmd_str(s, tables);
|
||||
}
|
||||
add_cmd_char('\0', tables);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a line from the lesskey file.
|
||||
*/
|
||||
static void parse_line(char *line, struct lesskey_tables *tables)
|
||||
{
|
||||
char *p;
|
||||
|
||||
/*
|
||||
* See if it is a control line.
|
||||
*/
|
||||
p = control_line(line, tables);
|
||||
if (p == NULL)
|
||||
return;
|
||||
/*
|
||||
* Skip leading white space.
|
||||
* Replace the final newline with a null byte.
|
||||
* Ignore blank lines and comments.
|
||||
*/
|
||||
p = clean_line(p);
|
||||
if (*p == '\0')
|
||||
return;
|
||||
|
||||
if (tables->currtable->is_var)
|
||||
parse_varline(p, tables);
|
||||
else
|
||||
parse_cmdline(p, tables);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a lesskey source file and store result in tables.
|
||||
*/
|
||||
int parse_lesskey(char *infile, struct lesskey_tables *tables)
|
||||
{
|
||||
FILE *desc;
|
||||
char line[1024];
|
||||
|
||||
if (infile == NULL)
|
||||
infile = homefile(DEF_LESSKEYINFILE);
|
||||
lesskey_file = infile;
|
||||
|
||||
init_tables(tables);
|
||||
errors = 0;
|
||||
linenum = 0;
|
||||
if (less_version == 0)
|
||||
less_version = lstrtoi(version, NULL, 10);
|
||||
|
||||
/*
|
||||
* Open the input file.
|
||||
*/
|
||||
if (strcmp(infile, "-") == 0)
|
||||
desc = stdin;
|
||||
else if ((desc = fopen(infile, "r")) == NULL)
|
||||
{
|
||||
/* parse_error("cannot open lesskey file %s", infile); */
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read and parse the input file, one line at a time.
|
||||
*/
|
||||
while (fgets(line, sizeof(line), desc) != NULL)
|
||||
{
|
||||
++linenum;
|
||||
parse_line(line, tables);
|
||||
}
|
||||
fclose(desc);
|
||||
return (errors);
|
||||
}
|
94
third_party/less/lglob.h
vendored
Normal file
94
third_party/less/lglob.h
vendored
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* 2. GLOB_NAME
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#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)
|
||||
|
||||
#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)
|
||||
|
||||
#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;
|
||||
#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;
|
||||
|
||||
#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;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
1593
third_party/less/line.c
vendored
Normal file
1593
third_party/less/line.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
498
third_party/less/linenum.c
vendored
Normal file
498
third_party/less/linenum.c
vendored
Normal file
|
@ -0,0 +1,498 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Code to handle displaying line numbers.
|
||||
*
|
||||
* Finding the line number of a given file position is rather tricky.
|
||||
* We don't want to just start at the beginning of the file and
|
||||
* count newlines, because that is slow for large files (and also
|
||||
* wouldn't work if we couldn't get to the start of the file; e.g.
|
||||
* if input is a long pipe).
|
||||
*
|
||||
* So we use the function add_lnum to cache line numbers.
|
||||
* We try to be very clever and keep only the more interesting
|
||||
* line numbers when we run out of space in our table. A line
|
||||
* number is more interesting than another when it is far from
|
||||
* other line numbers. For example, we'd rather keep lines
|
||||
* 100,200,300 than 100,101,300. 200 is more interesting than
|
||||
* 101 because 101 can be derived very cheaply from 100, while
|
||||
* 200 is more expensive to derive from 100.
|
||||
*
|
||||
* The function currline() returns the line number of a given
|
||||
* position in the file. As a side effect, it calls add_lnum
|
||||
* to cache the line number. Therefore currline is occasionally
|
||||
* called to make sure we cache line numbers often enough.
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
|
||||
/*
|
||||
* Structure to keep track of a line number and the associated file position.
|
||||
* A doubly-linked circular list of line numbers is kept ordered by line number.
|
||||
*/
|
||||
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 */
|
||||
};
|
||||
/*
|
||||
* "gap" needs some explanation: the gap of any particular line number
|
||||
* is the distance between the previous one and the next one in the list.
|
||||
* ("Distance" means difference in file position.) In other words, the
|
||||
* gap of a line number is the gap which would be introduced if this
|
||||
* line number were deleted. It is used to decide which one to replace
|
||||
* when we have a new one to insert and the table is full.
|
||||
*/
|
||||
|
||||
#define NPOOL 200 /* Size of line number pool */
|
||||
|
||||
#define LONGTIME (2) /* In seconds */
|
||||
|
||||
static struct linenum_info anchor; /* Anchor of the list */
|
||||
static struct linenum_info *freelist; /* Anchor of the unused entries */
|
||||
static struct linenum_info pool[NPOOL]; /* The pool itself */
|
||||
static struct linenum_info *spare; /* We always keep one spare entry */
|
||||
public int scanning_eof = FALSE;
|
||||
|
||||
extern int linenums;
|
||||
extern int sigs;
|
||||
extern int sc_height;
|
||||
extern int screen_trashed;
|
||||
extern int header_lines;
|
||||
extern int nonum_headers;
|
||||
|
||||
/*
|
||||
* Initialize the line number structures.
|
||||
*/
|
||||
public void clr_linenum(void)
|
||||
{
|
||||
struct linenum_info *p;
|
||||
|
||||
/*
|
||||
* Put all the entries on the free list.
|
||||
* Leave one for the "spare".
|
||||
*/
|
||||
for (p = pool; p < &pool[NPOOL-2]; p++)
|
||||
p->next = p+1;
|
||||
pool[NPOOL-2].next = NULL;
|
||||
freelist = pool;
|
||||
|
||||
spare = &pool[NPOOL-1];
|
||||
|
||||
/*
|
||||
* Initialize the anchor.
|
||||
*/
|
||||
anchor.next = anchor.prev = &anchor;
|
||||
anchor.gap = 0;
|
||||
anchor.pos = (POSITION)0;
|
||||
anchor.line = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the gap for an entry.
|
||||
*/
|
||||
static void calcgap(struct linenum_info *p)
|
||||
{
|
||||
/*
|
||||
* Don't bother to compute a gap for the anchor.
|
||||
* Also don't compute a gap for the last one in the list.
|
||||
* The gap for that last one should be considered infinite,
|
||||
* but we never look at it anyway.
|
||||
*/
|
||||
if (p == &anchor || p->next == &anchor)
|
||||
return;
|
||||
p->gap = p->next->pos - p->prev->pos;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a new line number to the cache.
|
||||
* The specified position (pos) should be the file position of the
|
||||
* FIRST character in the specified line.
|
||||
*/
|
||||
public void add_lnum(LINENUM linenum, POSITION pos)
|
||||
{
|
||||
struct linenum_info *p;
|
||||
struct linenum_info *new;
|
||||
struct linenum_info *nextp;
|
||||
struct linenum_info *prevp;
|
||||
POSITION mingap;
|
||||
|
||||
/*
|
||||
* Find the proper place in the list for the new one.
|
||||
* The entries are sorted by position.
|
||||
*/
|
||||
for (p = anchor.next; p != &anchor && p->pos < pos; p = p->next)
|
||||
if (p->line == linenum)
|
||||
/* We already have this one. */
|
||||
return;
|
||||
nextp = p;
|
||||
prevp = p->prev;
|
||||
|
||||
if (freelist != NULL)
|
||||
{
|
||||
/*
|
||||
* We still have free (unused) entries.
|
||||
* Use one of them.
|
||||
*/
|
||||
new = freelist;
|
||||
freelist = freelist->next;
|
||||
} else
|
||||
{
|
||||
/*
|
||||
* No free entries.
|
||||
* Use the "spare" entry.
|
||||
*/
|
||||
new = spare;
|
||||
spare = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in the fields of the new entry,
|
||||
* and insert it into the proper place in the list.
|
||||
*/
|
||||
new->next = nextp;
|
||||
new->prev = prevp;
|
||||
new->pos = pos;
|
||||
new->line = linenum;
|
||||
|
||||
nextp->prev = new;
|
||||
prevp->next = new;
|
||||
|
||||
/*
|
||||
* Recalculate gaps for the new entry and the neighboring entries.
|
||||
*/
|
||||
calcgap(new);
|
||||
calcgap(nextp);
|
||||
calcgap(prevp);
|
||||
|
||||
if (spare == NULL)
|
||||
{
|
||||
/*
|
||||
* We have used the spare entry.
|
||||
* Scan the list to find the one with the smallest
|
||||
* gap, take it out and make it the spare.
|
||||
* We should never remove the last one, so stop when
|
||||
* we get to p->next == &anchor. This also avoids
|
||||
* looking at the gap of the last one, which is
|
||||
* not computed by calcgap.
|
||||
*/
|
||||
mingap = anchor.next->gap;
|
||||
for (p = anchor.next; p->next != &anchor; p = p->next)
|
||||
{
|
||||
if (p->gap <= mingap)
|
||||
{
|
||||
spare = p;
|
||||
mingap = p->gap;
|
||||
}
|
||||
}
|
||||
spare->next->prev = spare->prev;
|
||||
spare->prev->next = spare->next;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we get stuck in a long loop trying to figure out the
|
||||
* line number, print a message to tell the user what we're doing.
|
||||
*/
|
||||
static void longloopmessage(void)
|
||||
{
|
||||
ierror("Calculating line numbers", NULL_PARG);
|
||||
}
|
||||
|
||||
static int loopcount;
|
||||
#if HAVE_TIME
|
||||
static time_type startime;
|
||||
#endif
|
||||
|
||||
static void longish(void)
|
||||
{
|
||||
#if HAVE_TIME
|
||||
if (loopcount >= 0 && ++loopcount > 100)
|
||||
{
|
||||
loopcount = 0;
|
||||
if (get_time() >= startime + LONGTIME)
|
||||
{
|
||||
longloopmessage();
|
||||
loopcount = -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (loopcount >= 0 && ++loopcount > LONGLOOP)
|
||||
{
|
||||
longloopmessage();
|
||||
loopcount = -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Turn off line numbers because the user has interrupted
|
||||
* a lengthy line number calculation.
|
||||
*/
|
||||
static void abort_long(void)
|
||||
{
|
||||
if (loopcount >= 0)
|
||||
return;
|
||||
if (linenums == OPT_ONPLUS)
|
||||
/*
|
||||
* We were displaying line numbers, so need to repaint.
|
||||
*/
|
||||
screen_trashed = 1;
|
||||
linenums = 0;
|
||||
error("Line numbers turned off", NULL_PARG);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the line number associated with a given position.
|
||||
* Return 0 if we can't figure it out.
|
||||
*/
|
||||
public LINENUM find_linenum(POSITION pos)
|
||||
{
|
||||
struct linenum_info *p;
|
||||
LINENUM linenum;
|
||||
POSITION cpos;
|
||||
|
||||
if (!linenums)
|
||||
/*
|
||||
* We're not using line numbers.
|
||||
*/
|
||||
return (0);
|
||||
if (pos == NULL_POSITION)
|
||||
/*
|
||||
* Caller doesn't know what he's talking about.
|
||||
*/
|
||||
return (0);
|
||||
if (pos <= ch_zero())
|
||||
/*
|
||||
* Beginning of file is always line number 1.
|
||||
*/
|
||||
return (1);
|
||||
|
||||
/*
|
||||
* Find the entry nearest to the position we want.
|
||||
*/
|
||||
for (p = anchor.next; p != &anchor && p->pos < pos; p = p->next)
|
||||
continue;
|
||||
if (p->pos == pos)
|
||||
/* Found it exactly. */
|
||||
return (p->line);
|
||||
|
||||
/*
|
||||
* This is the (possibly) time-consuming part.
|
||||
* We start at the line we just found and start
|
||||
* reading the file forward or backward till we
|
||||
* get to the place we want.
|
||||
*
|
||||
* First decide whether we should go forward from the
|
||||
* previous one or backwards from the next one.
|
||||
* The decision is based on which way involves
|
||||
* traversing fewer bytes in the file.
|
||||
*/
|
||||
#if HAVE_TIME
|
||||
startime = get_time();
|
||||
#endif
|
||||
loopcount = 0;
|
||||
if (p == &anchor || pos - p->prev->pos < p->pos - pos)
|
||||
{
|
||||
/*
|
||||
* Go forward.
|
||||
*/
|
||||
p = p->prev;
|
||||
if (ch_seek(p->pos))
|
||||
return (0);
|
||||
for (linenum = p->line, cpos = p->pos; cpos < pos; linenum++)
|
||||
{
|
||||
/*
|
||||
* Allow a signal to abort this loop.
|
||||
*/
|
||||
cpos = forw_raw_line(cpos, (char **)NULL, (int *)NULL);
|
||||
if (ABORT_SIGS()) {
|
||||
abort_long();
|
||||
return (0);
|
||||
}
|
||||
if (cpos == NULL_POSITION)
|
||||
return (0);
|
||||
longish();
|
||||
}
|
||||
/*
|
||||
* We might as well cache it.
|
||||
*/
|
||||
add_lnum(linenum, cpos);
|
||||
/*
|
||||
* If the given position is not at the start of a line,
|
||||
* make sure we return the correct line number.
|
||||
*/
|
||||
if (cpos > pos)
|
||||
linenum--;
|
||||
} else
|
||||
{
|
||||
/*
|
||||
* Go backward.
|
||||
*/
|
||||
if (ch_seek(p->pos))
|
||||
return (0);
|
||||
for (linenum = p->line, cpos = p->pos; cpos > pos; linenum--)
|
||||
{
|
||||
/*
|
||||
* Allow a signal to abort this loop.
|
||||
*/
|
||||
cpos = back_raw_line(cpos, (char **)NULL, (int *)NULL);
|
||||
if (ABORT_SIGS()) {
|
||||
abort_long();
|
||||
return (0);
|
||||
}
|
||||
if (cpos == NULL_POSITION)
|
||||
return (0);
|
||||
longish();
|
||||
}
|
||||
/*
|
||||
* We might as well cache it.
|
||||
*/
|
||||
add_lnum(linenum, cpos);
|
||||
}
|
||||
loopcount = 0;
|
||||
return (linenum);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the position of a given line number.
|
||||
* Return NULL_POSITION if we can't figure it out.
|
||||
*/
|
||||
public POSITION find_pos(LINENUM linenum)
|
||||
{
|
||||
struct linenum_info *p;
|
||||
POSITION cpos;
|
||||
LINENUM clinenum;
|
||||
|
||||
if (linenum <= 1)
|
||||
/*
|
||||
* Line number 1 is beginning of file.
|
||||
*/
|
||||
return (ch_zero());
|
||||
|
||||
/*
|
||||
* Find the entry nearest to the line number we want.
|
||||
*/
|
||||
for (p = anchor.next; p != &anchor && p->line < linenum; p = p->next)
|
||||
continue;
|
||||
if (p->line == linenum)
|
||||
/* Found it exactly. */
|
||||
return (p->pos);
|
||||
|
||||
if (p == &anchor || linenum - p->prev->line < p->line - linenum)
|
||||
{
|
||||
/*
|
||||
* Go forward.
|
||||
*/
|
||||
p = p->prev;
|
||||
if (ch_seek(p->pos))
|
||||
return (NULL_POSITION);
|
||||
for (clinenum = p->line, cpos = p->pos; clinenum < linenum; clinenum++)
|
||||
{
|
||||
/*
|
||||
* Allow a signal to abort this loop.
|
||||
*/
|
||||
cpos = forw_raw_line(cpos, (char **)NULL, (int *)NULL);
|
||||
if (ABORT_SIGS())
|
||||
return (NULL_POSITION);
|
||||
if (cpos == NULL_POSITION)
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
} else
|
||||
{
|
||||
/*
|
||||
* Go backward.
|
||||
*/
|
||||
if (ch_seek(p->pos))
|
||||
return (NULL_POSITION);
|
||||
for (clinenum = p->line, cpos = p->pos; clinenum > linenum; clinenum--)
|
||||
{
|
||||
/*
|
||||
* Allow a signal to abort this loop.
|
||||
*/
|
||||
cpos = back_raw_line(cpos, (char **)NULL, (int *)NULL);
|
||||
if (ABORT_SIGS())
|
||||
return (NULL_POSITION);
|
||||
if (cpos == NULL_POSITION)
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* We might as well cache it.
|
||||
*/
|
||||
add_lnum(clinenum, cpos);
|
||||
return (cpos);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the line number of the "current" line.
|
||||
* The argument "where" tells which line is to be considered
|
||||
* the "current" line (e.g. TOP, BOTTOM, MIDDLE, etc).
|
||||
*/
|
||||
public LINENUM currline(int where)
|
||||
{
|
||||
POSITION pos;
|
||||
POSITION len;
|
||||
LINENUM linenum;
|
||||
|
||||
pos = position(where);
|
||||
len = ch_length();
|
||||
while (pos == NULL_POSITION && where >= 0 && where < sc_height)
|
||||
pos = position(++where);
|
||||
if (pos == NULL_POSITION)
|
||||
pos = len;
|
||||
linenum = find_linenum(pos);
|
||||
if (pos == len)
|
||||
linenum--;
|
||||
return (linenum);
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan entire file, counting line numbers.
|
||||
*/
|
||||
public void scan_eof(void)
|
||||
{
|
||||
POSITION pos = ch_zero();
|
||||
LINENUM linenum = 0;
|
||||
|
||||
if (ch_seek(0))
|
||||
return;
|
||||
ierror("Determining length of file", NULL_PARG);
|
||||
/*
|
||||
* scanning_eof prevents the "Waiting for data" message from
|
||||
* overwriting "Determining length of file".
|
||||
*/
|
||||
scanning_eof = TRUE;
|
||||
while (pos != NULL_POSITION)
|
||||
{
|
||||
/* For efficiency, only add one every 256 line numbers. */
|
||||
if ((linenum++ % 256) == 0)
|
||||
add_lnum(linenum, pos);
|
||||
pos = forw_raw_line(pos, (char **)NULL, (int *)NULL);
|
||||
if (ABORT_SIGS())
|
||||
break;
|
||||
}
|
||||
scanning_eof = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a line number adjusted for display
|
||||
* (handles the --no-number-headers option).
|
||||
*/
|
||||
public LINENUM vlinenum(LINENUM linenum)
|
||||
{
|
||||
if (nonum_headers)
|
||||
linenum = (linenum < header_lines) ? 0 : linenum - header_lines;
|
||||
return linenum;
|
||||
}
|
364
third_party/less/lsystem.c
vendored
Normal file
364
third_party/less/lsystem.c
vendored
Normal file
|
@ -0,0 +1,364 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Routines to execute other programs.
|
||||
* Necessarily very OS dependent.
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
#include <signal.h>
|
||||
#include "position.h"
|
||||
|
||||
#if MSDOS_COMPILER
|
||||
#include <dos.h>
|
||||
#if MSDOS_COMPILER==WIN32C && defined(MINGW)
|
||||
#include <direct.h>
|
||||
#define setdisk(n) _chdrive((n)+1)
|
||||
#else
|
||||
#ifdef _MSC_VER
|
||||
#include <direct.h>
|
||||
#define setdisk(n) _chdrive((n)+1)
|
||||
#else
|
||||
#include <dir.h>
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern int screen_trashed;
|
||||
extern IFILE curr_ifile;
|
||||
|
||||
|
||||
#if HAVE_SYSTEM
|
||||
|
||||
/*
|
||||
* Pass the specified command to a shell to be executed.
|
||||
* Like plain "system()", but handles resetting terminal modes, etc.
|
||||
*/
|
||||
public void lsystem(char *cmd, char *donemsg)
|
||||
{
|
||||
int inp;
|
||||
#if HAVE_SHELL
|
||||
char *shell;
|
||||
char *p;
|
||||
#endif
|
||||
IFILE save_ifile;
|
||||
#if MSDOS_COMPILER && MSDOS_COMPILER!=WIN32C
|
||||
char cwd[FILENAME_MAX+1];
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Print the command which is to be executed,
|
||||
* unless the command starts with a "-".
|
||||
*/
|
||||
if (cmd[0] == '-')
|
||||
cmd++;
|
||||
else
|
||||
{
|
||||
clear_bot();
|
||||
putstr("!");
|
||||
putstr(cmd);
|
||||
putstr("\n");
|
||||
}
|
||||
|
||||
#if MSDOS_COMPILER
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
if (*cmd == '\0')
|
||||
cmd = getenv("COMSPEC");
|
||||
#else
|
||||
/*
|
||||
* Working directory is global on MSDOS.
|
||||
* The child might change the working directory, so we
|
||||
* must save and restore CWD across calls to "system",
|
||||
* or else we won't find our file when we return and
|
||||
* try to "reedit_ifile" it.
|
||||
*/
|
||||
getcwd(cwd, FILENAME_MAX);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Close the current input file.
|
||||
*/
|
||||
save_ifile = save_curr_ifile();
|
||||
(void) edit_ifile(NULL_IFILE);
|
||||
|
||||
/*
|
||||
* De-initialize the terminal and take out of raw mode.
|
||||
*/
|
||||
deinit();
|
||||
flush(); /* Make sure the deinit chars get out */
|
||||
raw_mode(0);
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
close_getchr();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Restore signals to their defaults.
|
||||
*/
|
||||
init_signals(0);
|
||||
|
||||
#if HAVE_DUP
|
||||
/*
|
||||
* Force standard input to be the user's terminal
|
||||
* (the normal standard input), even if less's standard input
|
||||
* is coming from a pipe.
|
||||
*/
|
||||
inp = dup(0);
|
||||
close(0);
|
||||
#if !MSDOS_COMPILER
|
||||
if (open_tty() < 0)
|
||||
#endif
|
||||
dup(inp);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Pass the command to the system to be executed.
|
||||
* If we have a SHELL environment variable, use
|
||||
* <$SHELL -c "command"> instead of just <command>.
|
||||
* If the command is empty, just invoke a shell.
|
||||
*/
|
||||
#if HAVE_SHELL
|
||||
p = NULL;
|
||||
if ((shell = lgetenv("SHELL")) != NULL && *shell != '\0')
|
||||
{
|
||||
if (*cmd == '\0')
|
||||
p = save(shell);
|
||||
else
|
||||
{
|
||||
char *esccmd = shell_quote(cmd);
|
||||
if (esccmd != NULL)
|
||||
{
|
||||
int len = (int) (strlen(shell) + strlen(esccmd) + 5);
|
||||
p = (char *) ecalloc(len, sizeof(char));
|
||||
SNPRINTF3(p, len, "%s %s %s", shell, shell_coption(), esccmd);
|
||||
free(esccmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (p == NULL)
|
||||
{
|
||||
if (*cmd == '\0')
|
||||
p = save("sh");
|
||||
else
|
||||
p = save(cmd);
|
||||
}
|
||||
system(p);
|
||||
free(p);
|
||||
#else
|
||||
#if MSDOS_COMPILER==DJGPPC
|
||||
/*
|
||||
* Make stdin of the child be in cooked mode.
|
||||
*/
|
||||
setmode(0, O_TEXT);
|
||||
/*
|
||||
* We don't need to catch signals of the child (it
|
||||
* also makes trouble with some DPMI servers).
|
||||
*/
|
||||
__djgpp_exception_toggle();
|
||||
system(cmd);
|
||||
__djgpp_exception_toggle();
|
||||
#else
|
||||
system(cmd);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAVE_DUP
|
||||
/*
|
||||
* Restore standard input, reset signals, raw mode, etc.
|
||||
*/
|
||||
close(0);
|
||||
dup(inp);
|
||||
close(inp);
|
||||
#endif
|
||||
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
open_getchr();
|
||||
#endif
|
||||
init_signals(1);
|
||||
raw_mode(1);
|
||||
if (donemsg != NULL)
|
||||
{
|
||||
putstr(donemsg);
|
||||
putstr(" (press RETURN)");
|
||||
get_return();
|
||||
putchr('\n');
|
||||
flush();
|
||||
}
|
||||
init();
|
||||
screen_trashed = 1;
|
||||
|
||||
#if MSDOS_COMPILER && MSDOS_COMPILER!=WIN32C
|
||||
/*
|
||||
* Restore the previous directory (possibly
|
||||
* changed by the child program we just ran).
|
||||
*/
|
||||
chdir(cwd);
|
||||
#if MSDOS_COMPILER != DJGPPC
|
||||
/*
|
||||
* Some versions of chdir() don't change to the drive
|
||||
* which is part of CWD. (DJGPP does this in chdir.)
|
||||
*/
|
||||
if (cwd[1] == ':')
|
||||
{
|
||||
if (cwd[0] >= 'a' && cwd[0] <= 'z')
|
||||
setdisk(cwd[0] - 'a');
|
||||
else if (cwd[0] >= 'A' && cwd[0] <= 'Z')
|
||||
setdisk(cwd[0] - 'A');
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Reopen the current input file.
|
||||
*/
|
||||
reedit_ifile(save_ifile);
|
||||
|
||||
#if defined(SIGWINCH) || defined(SIGWIND)
|
||||
/*
|
||||
* Since we were ignoring window change signals while we executed
|
||||
* the system command, we must assume the window changed.
|
||||
* Warning: this leaves a signal pending (in "sigs"),
|
||||
* so psignals() should be called soon after lsystem().
|
||||
*/
|
||||
winch(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if PIPEC
|
||||
|
||||
/*
|
||||
* Pipe a section of the input file into the given shell command.
|
||||
* The section to be piped is the section "between" the current
|
||||
* position and the position marked by the given letter.
|
||||
*
|
||||
* If the mark is after the current screen, the section between
|
||||
* the top line displayed and the mark is piped.
|
||||
* If the mark is before the current screen, the section between
|
||||
* the mark and the bottom line displayed is piped.
|
||||
* If the mark is on the current screen, or if the mark is ".",
|
||||
* the whole current screen is piped.
|
||||
*/
|
||||
public int pipe_mark(int c, char *cmd)
|
||||
{
|
||||
POSITION mpos, tpos, bpos;
|
||||
|
||||
/*
|
||||
* mpos = the marked position.
|
||||
* tpos = top of screen.
|
||||
* bpos = bottom of screen.
|
||||
*/
|
||||
mpos = markpos(c);
|
||||
if (mpos == NULL_POSITION)
|
||||
return (-1);
|
||||
tpos = position(TOP);
|
||||
if (tpos == NULL_POSITION)
|
||||
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));
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a pipe to the given shell command.
|
||||
* Feed it the file contents between the positions spos and epos.
|
||||
*/
|
||||
public int pipe_data(char *cmd, POSITION spos, POSITION epos)
|
||||
{
|
||||
FILE *f;
|
||||
int c;
|
||||
|
||||
/*
|
||||
* This is structured much like lsystem().
|
||||
* Since we're running a shell program, we must be careful
|
||||
* to perform the necessary deinitialization before running
|
||||
* the command, and reinitialization after it.
|
||||
*/
|
||||
if (ch_seek(spos) != 0)
|
||||
{
|
||||
error("Cannot seek to start position", NULL_PARG);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if ((f = popen(cmd, "w")) == NULL)
|
||||
{
|
||||
error("Cannot create pipe", NULL_PARG);
|
||||
return (-1);
|
||||
}
|
||||
clear_bot();
|
||||
putstr("!");
|
||||
putstr(cmd);
|
||||
putstr("\n");
|
||||
|
||||
deinit();
|
||||
flush();
|
||||
raw_mode(0);
|
||||
init_signals(0);
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
close_getchr();
|
||||
#endif
|
||||
#ifdef SIGPIPE
|
||||
LSIGNAL(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
|
||||
c = EOI;
|
||||
while (epos == NULL_POSITION || spos++ <= epos)
|
||||
{
|
||||
/*
|
||||
* Read a character from the file and give it to the pipe.
|
||||
*/
|
||||
c = ch_forw_get();
|
||||
if (c == EOI)
|
||||
break;
|
||||
if (putc(c, f) == EOF)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finish up the last line.
|
||||
*/
|
||||
while (c != '\n' && c != EOI )
|
||||
{
|
||||
c = ch_forw_get();
|
||||
if (c == EOI)
|
||||
break;
|
||||
if (putc(c, f) == EOF)
|
||||
break;
|
||||
}
|
||||
|
||||
pclose(f);
|
||||
|
||||
#ifdef SIGPIPE
|
||||
LSIGNAL(SIGPIPE, SIG_DFL);
|
||||
#endif
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
open_getchr();
|
||||
#endif
|
||||
init_signals(1);
|
||||
raw_mode(1);
|
||||
init();
|
||||
screen_trashed = 1;
|
||||
#if defined(SIGWINCH) || defined(SIGWIND)
|
||||
/* {{ Probably don't need this here. }} */
|
||||
winch(0);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
#endif
|
457
third_party/less/main.c
vendored
Normal file
457
third_party/less/main.c
vendored
Normal file
|
@ -0,0 +1,457 @@
|
|||
asm(".ident\t\"\\n\\n\
|
||||
Less\\n\
|
||||
Copyright (C) 1984-2023 Mark Nudelman\\n\
|
||||
\\n\
|
||||
Redistribution and use in source and binary forms, with or without\\n\
|
||||
modification, are permitted provided that the following conditions\\n\
|
||||
are met:\\n\
|
||||
1. Redistributions of source code must retain the above copyright\\n\
|
||||
notice, this list of conditions and the following disclaimer.\\n\
|
||||
2. Redistributions in binary form must reproduce the above copyright\\n\
|
||||
notice in the documentation and/or other materials provided with\\n\
|
||||
the distribution.\\n\
|
||||
\\n\
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY\\n\
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\\n\
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\\n\
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE\\n\
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\\n\
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT\\n\
|
||||
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\\n\
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\\n\
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\\n\
|
||||
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN\\n\
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\"");
|
||||
|
||||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Entry point, initialization, miscellaneous routines.
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
/* #include <windows.h> */
|
||||
#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 struct scrpos initial_scrpos;
|
||||
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;
|
||||
#endif
|
||||
|
||||
#if EDITOR
|
||||
public char * editor;
|
||||
public char * editproto;
|
||||
#endif
|
||||
|
||||
#if TAGS
|
||||
extern char * tags;
|
||||
extern char * tagoption;
|
||||
extern int jump_sline;
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
static char consoleTitle[256];
|
||||
#endif
|
||||
|
||||
public int one_screen;
|
||||
extern int less_is_more;
|
||||
extern int missing_cap;
|
||||
extern int know_dumb;
|
||||
extern int pr_type;
|
||||
extern int quit_if_one_screen;
|
||||
extern int no_init;
|
||||
extern int errmsgs;
|
||||
extern int redraw_on_quit;
|
||||
extern int term_init_done;
|
||||
extern int first_time;
|
||||
|
||||
/*
|
||||
* Entry point.
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
IFILE ifile;
|
||||
char *s;
|
||||
|
||||
#ifdef __EMX__
|
||||
_response(&argc, &argv);
|
||||
_wildcard(&argc, &argv);
|
||||
#endif
|
||||
|
||||
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)
|
||||
{
|
||||
/*
|
||||
* If there is no HOME environment variable,
|
||||
* try the concatenation of HOMEDRIVE + HOMEPATH.
|
||||
*/
|
||||
char *drive = getenv("HOMEDRIVE");
|
||||
char *path = getenv("HOMEPATH");
|
||||
if (drive != NULL && path != NULL)
|
||||
{
|
||||
char *env = (char *) ecalloc(strlen(drive) +
|
||||
strlen(path) + 6, sizeof(char));
|
||||
strcpy(env, "HOME=");
|
||||
strcat(env, drive);
|
||||
strcat(env, path);
|
||||
putenv(env);
|
||||
}
|
||||
}
|
||||
GetConsoleTitle(consoleTitle, sizeof(consoleTitle)/sizeof(char));
|
||||
#endif /* WIN32 */
|
||||
|
||||
/*
|
||||
* Process command line arguments and LESS environment arguments.
|
||||
* Command line arguments override environment arguments.
|
||||
*/
|
||||
is_tty = isatty(1);
|
||||
init_mark();
|
||||
init_cmds();
|
||||
init_poll();
|
||||
get_term();
|
||||
init_charset();
|
||||
init_line();
|
||||
init_cmdhist();
|
||||
init_option();
|
||||
init_search();
|
||||
|
||||
/*
|
||||
* If the name of the executable program is "more",
|
||||
* act like LESS_IS_MORE is set.
|
||||
*/
|
||||
s = last_component(progname);
|
||||
if (strcmp(s, "more") == 0)
|
||||
less_is_more = 1;
|
||||
|
||||
init_prompt();
|
||||
|
||||
s = lgetenv(less_is_more ? "MORE" : "LESS");
|
||||
if (s != NULL)
|
||||
scan_option(s);
|
||||
|
||||
#define isoptstring(s) (((s)[0] == '-' || (s)[0] == '+') && (s)[1] != '\0')
|
||||
while (argc > 0 && (isoptstring(*argv) || isoptpending()))
|
||||
{
|
||||
s = *argv++;
|
||||
argc--;
|
||||
if (strcmp(s, "--") == 0)
|
||||
break;
|
||||
scan_option(s);
|
||||
}
|
||||
#undef isoptstring
|
||||
|
||||
if (isoptpending())
|
||||
{
|
||||
/*
|
||||
* Last command line option was a flag requiring a
|
||||
* following string, but there was no following string.
|
||||
*/
|
||||
nopendopt();
|
||||
quit(QUIT_OK);
|
||||
}
|
||||
|
||||
expand_cmd_tables();
|
||||
|
||||
#if EDITOR
|
||||
editor = lgetenv("VISUAL");
|
||||
if (editor == NULL || *editor == '\0')
|
||||
{
|
||||
editor = lgetenv("EDITOR");
|
||||
if (isnullenv(editor))
|
||||
editor = EDIT_PGM;
|
||||
}
|
||||
editproto = lgetenv("LESSEDIT");
|
||||
if (isnullenv(editproto))
|
||||
editproto = "%E ?lm+%lm. %g";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Call get_ifile with all the command line filenames
|
||||
* to "register" them with the ifile system.
|
||||
*/
|
||||
ifile = NULL_IFILE;
|
||||
if (dohelp)
|
||||
ifile = get_ifile(FAKE_HELPFILE, ifile);
|
||||
while (argc-- > 0)
|
||||
{
|
||||
#if (MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC)
|
||||
/*
|
||||
* Because the "shell" doesn't expand filename patterns,
|
||||
* treat each argument as a filename pattern rather than
|
||||
* a single filename.
|
||||
* Expand the pattern and iterate over the expanded list.
|
||||
*/
|
||||
struct textlist tlist;
|
||||
char *filename;
|
||||
char *gfilename;
|
||||
char *qfilename;
|
||||
|
||||
gfilename = lglob(*argv++);
|
||||
init_textlist(&tlist, gfilename);
|
||||
filename = NULL;
|
||||
while ((filename = forw_textlist(&tlist, filename)) != NULL)
|
||||
{
|
||||
qfilename = shell_unquote(filename);
|
||||
(void) get_ifile(qfilename, ifile);
|
||||
free(qfilename);
|
||||
ifile = prev_ifile(NULL_IFILE);
|
||||
}
|
||||
free(gfilename);
|
||||
#else
|
||||
(void) get_ifile(*argv++, ifile);
|
||||
ifile = prev_ifile(NULL_IFILE);
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Set up terminal, etc.
|
||||
*/
|
||||
if (!is_tty)
|
||||
{
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
do {
|
||||
cat_file();
|
||||
} while (edit_next(1) == 0);
|
||||
}
|
||||
quit(QUIT_OK);
|
||||
}
|
||||
|
||||
if (missing_cap && !know_dumb)
|
||||
error("WARNING: terminal is not fully functional", NULL_PARG);
|
||||
open_getchr();
|
||||
raw_mode(1);
|
||||
init_signals(1);
|
||||
|
||||
/*
|
||||
* Select the first file to examine.
|
||||
*/
|
||||
#if TAGS
|
||||
if (tagoption != NULL || strcmp(tags, "-") == 0)
|
||||
{
|
||||
/*
|
||||
* A -t option was given.
|
||||
* Verify that no filenames were also given.
|
||||
* Edit the file selected by the "tags" search,
|
||||
* and search for the proper line in the file.
|
||||
*/
|
||||
if (nifile() > 0)
|
||||
{
|
||||
error("No filenames allowed with -t option", NULL_PARG);
|
||||
quit(QUIT_ERROR);
|
||||
}
|
||||
findtag(tagoption);
|
||||
if (edit_tagfile()) /* Edit file which contains the tag */
|
||||
quit(QUIT_ERROR);
|
||||
/*
|
||||
* Search for the line which contains the tag.
|
||||
* Set up initial_scrpos so we display that line.
|
||||
*/
|
||||
initial_scrpos.pos = tagsearch();
|
||||
if (initial_scrpos.pos == NULL_POSITION)
|
||||
quit(QUIT_ERROR);
|
||||
initial_scrpos.ln = jump_sline;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (edit_first())
|
||||
quit(QUIT_ERROR);
|
||||
/*
|
||||
* See if file fits on one screen to decide whether
|
||||
* to send terminal init. But don't need this
|
||||
* if -X (no_init) overrides this (see init()).
|
||||
*/
|
||||
if (quit_if_one_screen)
|
||||
{
|
||||
if (nifile() > 1) /* If more than one file, -F cannot be used */
|
||||
quit_if_one_screen = FALSE;
|
||||
else if (!no_init)
|
||||
one_screen = get_one_screen();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
/*NOTREACHED*/
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy a string to a "safe" place
|
||||
* (that is, to a buffer allocated by calloc).
|
||||
*/
|
||||
public char * save(constant char *s)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = (char *) ecalloc(strlen(s)+1, sizeof(char));
|
||||
strcpy(p, s);
|
||||
return (p);
|
||||
}
|
||||
|
||||
public void out_of_memory(void)
|
||||
{
|
||||
error("Cannot allocate memory", NULL_PARG);
|
||||
quit(QUIT_ERROR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate memory.
|
||||
* Like calloc(), but never returns an error (NULL).
|
||||
*/
|
||||
public void * ecalloc(int count, unsigned int size)
|
||||
{
|
||||
void * p;
|
||||
|
||||
p = (void *) calloc(count, size);
|
||||
if (p == NULL)
|
||||
out_of_memory();
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip leading spaces in a string.
|
||||
*/
|
||||
public char * skipsp(char *s)
|
||||
{
|
||||
while (*s == ' ' || *s == '\t')
|
||||
s++;
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* See how many characters of two strings are identical.
|
||||
* If uppercase is true, the first string must begin with an uppercase
|
||||
* character; the remainder of the first string may be either case.
|
||||
*/
|
||||
public int sprefix(char *ps, char *s, int uppercase)
|
||||
{
|
||||
int c;
|
||||
int sc;
|
||||
int len = 0;
|
||||
|
||||
for ( ; *s != '\0'; s++, ps++)
|
||||
{
|
||||
c = *ps;
|
||||
if (uppercase)
|
||||
{
|
||||
if (len == 0 && ASCII_IS_LOWER(c))
|
||||
return (-1);
|
||||
if (ASCII_IS_UPPER(c))
|
||||
c = ASCII_TO_LOWER(c);
|
||||
}
|
||||
sc = *s;
|
||||
if (len > 0 && ASCII_IS_UPPER(sc))
|
||||
sc = ASCII_TO_LOWER(sc);
|
||||
if (c != sc)
|
||||
break;
|
||||
len++;
|
||||
}
|
||||
return (len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Exit the program.
|
||||
*/
|
||||
public void quit(int status)
|
||||
{
|
||||
static int save_status;
|
||||
|
||||
/*
|
||||
* Put cursor at bottom left corner, clear the line,
|
||||
* reset the terminal modes, and exit.
|
||||
*/
|
||||
if (status < 0)
|
||||
status = save_status;
|
||||
else
|
||||
save_status = status;
|
||||
quitting = 1;
|
||||
check_altpipe_error();
|
||||
if (interactive())
|
||||
clear_bot();
|
||||
deinit();
|
||||
flush();
|
||||
if (redraw_on_quit && term_init_done)
|
||||
{
|
||||
/*
|
||||
* The last file text displayed might have been on an
|
||||
* alternate screen, which now (since deinit) cannot be seen.
|
||||
* redraw_on_quit tells us to redraw it on the main screen.
|
||||
*/
|
||||
first_time = 1; /* Don't print "skipping" or tildes */
|
||||
repaint();
|
||||
flush();
|
||||
}
|
||||
edit((char*)NULL);
|
||||
save_cmdhist();
|
||||
raw_mode(0);
|
||||
#if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
|
||||
/*
|
||||
* If we don't close 2, we get some garbage from
|
||||
* 2's buffer when it flushes automatically.
|
||||
* I cannot track this one down RB
|
||||
* The same bug shows up if we use ^C^C to abort.
|
||||
*/
|
||||
close(2);
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
SetConsoleTitle(consoleTitle);
|
||||
#endif
|
||||
close_getchr();
|
||||
exit(status);
|
||||
}
|
427
third_party/less/mark.c
vendored
Normal file
427
third_party/less/mark.c
vendored
Normal file
|
@ -0,0 +1,427 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
#include "less.h"
|
||||
#include "position.h"
|
||||
|
||||
extern IFILE curr_ifile;
|
||||
extern int sc_height;
|
||||
extern int jump_sline;
|
||||
extern int perma_marks;
|
||||
|
||||
/*
|
||||
* A mark is an ifile (input file) plus a position within the file.
|
||||
*/
|
||||
struct mark
|
||||
{
|
||||
/*
|
||||
* Normally m_ifile != IFILE_NULL and m_filename == NULL.
|
||||
* For restored marks we set m_filename instead of m_ifile
|
||||
* because we don't want to create an ifile until the
|
||||
* user explicitly requests the file (by name or mark).
|
||||
*/
|
||||
char m_letter; /* Associated character */
|
||||
IFILE m_ifile; /* Input file being marked */
|
||||
char *m_filename; /* Name of the input file */
|
||||
struct scrpos m_scrpos; /* Position of the mark */
|
||||
};
|
||||
|
||||
/*
|
||||
* The table of marks.
|
||||
* 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)
|
||||
static struct mark marks[NMARKS];
|
||||
public int marks_modified = 0;
|
||||
|
||||
|
||||
/*
|
||||
* Initialize a mark struct.
|
||||
*/
|
||||
static void cmark(struct mark *m, IFILE ifile, POSITION pos, int ln)
|
||||
{
|
||||
m->m_ifile = ifile;
|
||||
m->m_scrpos.pos = pos;
|
||||
m->m_scrpos.ln = ln;
|
||||
if (m->m_filename != NULL)
|
||||
/* Normally should not happen but a corrupt lesshst file can do it. */
|
||||
free(m->m_filename);
|
||||
m->m_filename = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the mark table to show no marks are set.
|
||||
*/
|
||||
public void init_mark(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NMARKS; i++)
|
||||
{
|
||||
char letter;
|
||||
switch (i) {
|
||||
case MOUSEMARK: letter = '#'; break;
|
||||
case LASTMARK: letter = '\''; break;
|
||||
default: letter = (i < 26) ? 'a'+i : 'A'+i-26; break;
|
||||
}
|
||||
marks[i].m_letter = letter;
|
||||
cmark(&marks[i], NULL_IFILE, NULL_POSITION, -1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set m_ifile and clear m_filename.
|
||||
*/
|
||||
static void mark_set_ifile(struct mark *m, IFILE ifile)
|
||||
{
|
||||
m->m_ifile = ifile;
|
||||
/* With m_ifile set, m_filename is no longer needed. */
|
||||
free(m->m_filename);
|
||||
m->m_filename = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Populate the m_ifile member of a mark struct from m_filename.
|
||||
*/
|
||||
static void mark_get_ifile(struct mark *m)
|
||||
{
|
||||
if (m->m_ifile != NULL_IFILE)
|
||||
return; /* m_ifile is already set */
|
||||
mark_set_ifile(m, get_ifile(m->m_filename, prev_ifile(NULL_IFILE)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the user mark struct identified by a character.
|
||||
*/
|
||||
static struct mark * getumark(LWCHAR 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]);
|
||||
parg.p_char = (char) c;
|
||||
error("Invalid mark letter %c", &parg);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the mark structure identified by a character.
|
||||
* The mark struct may either be in the mark table (user mark)
|
||||
* or may be constructed on the fly for certain characters like ^, $.
|
||||
*/
|
||||
static struct mark * getmark(LWCHAR c)
|
||||
{
|
||||
struct mark *m;
|
||||
static struct mark sm;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '^':
|
||||
/*
|
||||
* Beginning of the current file.
|
||||
*/
|
||||
m = &sm;
|
||||
cmark(m, curr_ifile, ch_zero(), 0);
|
||||
break;
|
||||
case '$':
|
||||
/*
|
||||
* End of the current file.
|
||||
*/
|
||||
if (ch_end_seek())
|
||||
{
|
||||
error("Cannot seek to end of file", NULL_PARG);
|
||||
return (NULL);
|
||||
}
|
||||
m = &sm;
|
||||
cmark(m, curr_ifile, ch_tell(), sc_height);
|
||||
break;
|
||||
case '.':
|
||||
/*
|
||||
* Current position in the current file.
|
||||
*/
|
||||
m = &sm;
|
||||
get_scrpos(&m->m_scrpos, TOP);
|
||||
cmark(m, curr_ifile, m->m_scrpos.pos, m->m_scrpos.ln);
|
||||
break;
|
||||
case '\'':
|
||||
/*
|
||||
* The "last mark".
|
||||
*/
|
||||
m = &marks[LASTMARK];
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* Must be a user-defined mark.
|
||||
*/
|
||||
m = getumark(c);
|
||||
if (m == NULL)
|
||||
break;
|
||||
if (m->m_scrpos.pos == NULL_POSITION)
|
||||
{
|
||||
error("Mark not set", NULL_PARG);
|
||||
return (NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return (m);
|
||||
}
|
||||
|
||||
/*
|
||||
* Is a mark letter invalid?
|
||||
*/
|
||||
public int badmark(LWCHAR c)
|
||||
{
|
||||
return (getmark(c) == NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a user-defined mark.
|
||||
*/
|
||||
public void setmark(LWCHAR c, int where)
|
||||
{
|
||||
struct mark *m;
|
||||
struct scrpos scrpos;
|
||||
|
||||
m = getumark(c);
|
||||
if (m == NULL)
|
||||
return;
|
||||
get_scrpos(&scrpos, where);
|
||||
if (scrpos.pos == NULL_POSITION)
|
||||
{
|
||||
bell();
|
||||
return;
|
||||
}
|
||||
cmark(m, curr_ifile, scrpos.pos, scrpos.ln);
|
||||
marks_modified = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear a user-defined mark.
|
||||
*/
|
||||
public void clrmark(LWCHAR c)
|
||||
{
|
||||
struct mark *m;
|
||||
|
||||
m = getumark(c);
|
||||
if (m == NULL)
|
||||
return;
|
||||
if (m->m_scrpos.pos == NULL_POSITION)
|
||||
{
|
||||
bell();
|
||||
return;
|
||||
}
|
||||
m->m_scrpos.pos = NULL_POSITION;
|
||||
marks_modified = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set lmark (the mark named by the apostrophe).
|
||||
*/
|
||||
public void lastmark(void)
|
||||
{
|
||||
struct scrpos scrpos;
|
||||
|
||||
if (ch_getflags() & CH_HELPFILE)
|
||||
return;
|
||||
get_scrpos(&scrpos, TOP);
|
||||
if (scrpos.pos == NULL_POSITION)
|
||||
return;
|
||||
cmark(&marks[LASTMARK], curr_ifile, scrpos.pos, scrpos.ln);
|
||||
marks_modified = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Go to a mark.
|
||||
*/
|
||||
public void gomark(LWCHAR c)
|
||||
{
|
||||
struct mark *m;
|
||||
struct scrpos scrpos;
|
||||
|
||||
m = getmark(c);
|
||||
if (m == NULL)
|
||||
return;
|
||||
|
||||
/*
|
||||
* If we're trying to go to the lastmark and
|
||||
* it has not been set to anything yet,
|
||||
* set it to the beginning of the current file.
|
||||
* {{ Couldn't we instead set marks[LASTMARK] in edit()? }}
|
||||
*/
|
||||
if (m == &marks[LASTMARK] && m->m_scrpos.pos == NULL_POSITION)
|
||||
cmark(m, curr_ifile, ch_zero(), jump_sline);
|
||||
|
||||
mark_get_ifile(m);
|
||||
|
||||
/* Save scrpos; if it's LASTMARK it could change in edit_ifile. */
|
||||
scrpos = m->m_scrpos;
|
||||
if (m->m_ifile != curr_ifile)
|
||||
{
|
||||
/*
|
||||
* Not in the current file; edit the correct file.
|
||||
*/
|
||||
if (edit_ifile(m->m_ifile))
|
||||
return;
|
||||
}
|
||||
|
||||
jump_loc(scrpos.pos, scrpos.ln);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the position associated with a given mark letter.
|
||||
*
|
||||
* We don't return which screen line the position
|
||||
* is associated with, but this doesn't matter much,
|
||||
* because it's always the first non-blank line on the screen.
|
||||
*/
|
||||
public POSITION markpos(LWCHAR c)
|
||||
{
|
||||
struct mark *m;
|
||||
|
||||
m = getmark(c);
|
||||
if (m == NULL)
|
||||
return (NULL_POSITION);
|
||||
|
||||
if (m->m_ifile != curr_ifile)
|
||||
{
|
||||
error("Mark not in current file", NULL_PARG);
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
return (m->m_scrpos.pos);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the mark associated with a given position, if any.
|
||||
*/
|
||||
public char posmark(POSITION pos)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Only user marks */
|
||||
for (i = 0; i < NUMARKS; i++)
|
||||
{
|
||||
if (marks[i].m_ifile == curr_ifile && marks[i].m_scrpos.pos == pos)
|
||||
{
|
||||
if (i < 26) return 'a' + i;
|
||||
if (i < 26*2) return 'A' + (i - 26);
|
||||
return '#';
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear the marks associated with a specified ifile.
|
||||
*/
|
||||
public void unmark(IFILE ifile)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NMARKS; i++)
|
||||
if (marks[i].m_ifile == ifile)
|
||||
marks[i].m_scrpos.pos = NULL_POSITION;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if any marks refer to a specified ifile vi m_filename
|
||||
* rather than m_ifile.
|
||||
*/
|
||||
public void mark_check_ifile(IFILE ifile)
|
||||
{
|
||||
int i;
|
||||
char *filename = get_real_filename(ifile);
|
||||
|
||||
for (i = 0; i < NMARKS; i++)
|
||||
{
|
||||
struct mark *m = &marks[i];
|
||||
char *mark_filename = m->m_filename;
|
||||
if (mark_filename != NULL)
|
||||
{
|
||||
mark_filename = lrealpath(mark_filename);
|
||||
if (strcmp(filename, mark_filename) == 0)
|
||||
mark_set_ifile(m, ifile);
|
||||
free(mark_filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if CMD_HISTORY
|
||||
|
||||
/*
|
||||
* Save marks to history file.
|
||||
*/
|
||||
public void save_marks(FILE *fout, char *hdr)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!perma_marks)
|
||||
return;
|
||||
|
||||
fprintf(fout, "%s\n", hdr);
|
||||
for (i = 0; i < NMARKS; i++)
|
||||
{
|
||||
char *filename;
|
||||
struct mark *m = &marks[i];
|
||||
char pos_str[INT_STRLEN_BOUND(m->m_scrpos.pos) + 2];
|
||||
if (m->m_scrpos.pos == NULL_POSITION)
|
||||
continue;
|
||||
postoa(m->m_scrpos.pos, pos_str, 10);
|
||||
filename = m->m_filename;
|
||||
if (filename == NULL)
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore one mark from the history file.
|
||||
*/
|
||||
public void restore_mark(char *line)
|
||||
{
|
||||
struct mark *m;
|
||||
int ln;
|
||||
POSITION pos;
|
||||
|
||||
#define skip_whitespace while (*line == ' ') line++
|
||||
if (*line++ != 'm')
|
||||
return;
|
||||
skip_whitespace;
|
||||
m = getumark(*line++);
|
||||
if (m == NULL)
|
||||
return;
|
||||
skip_whitespace;
|
||||
ln = lstrtoi(line, &line, 10);
|
||||
if (ln < 0)
|
||||
return;
|
||||
if (ln < 1)
|
||||
ln = 1;
|
||||
if (ln > sc_height)
|
||||
ln = sc_height;
|
||||
skip_whitespace;
|
||||
pos = lstrtopos(line, &line, 10);
|
||||
if (pos < 0)
|
||||
return;
|
||||
skip_whitespace;
|
||||
cmark(m, NULL_IFILE, pos, ln);
|
||||
m->m_filename = save(line);
|
||||
}
|
||||
|
||||
#endif /* CMD_HISTORY */
|
1096
third_party/less/optfunc.c
vendored
Normal file
1096
third_party/less/optfunc.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
688
third_party/less/option.c
vendored
Normal file
688
third_party/less/option.c
vendored
Normal file
|
@ -0,0 +1,688 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Process command line options.
|
||||
*
|
||||
* Each option is a single letter which controls a program variable.
|
||||
* The options have defaults which may be changed via
|
||||
* the command line option, toggled via the "-" command,
|
||||
* or queried via the "_" command.
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
#include "option.h"
|
||||
|
||||
static struct loption *pendopt;
|
||||
public int plusoption = FALSE;
|
||||
|
||||
static char *optstring(char *s, char **p_str, char *printopt, char *validchars);
|
||||
static int flip_triple(int val, int lc);
|
||||
|
||||
extern int screen_trashed;
|
||||
extern int less_is_more;
|
||||
extern int quit_at_eof;
|
||||
extern char *every_first_cmd;
|
||||
extern int opt_use_backslash;
|
||||
|
||||
/*
|
||||
* Return a printable description of an option.
|
||||
*/
|
||||
static char * opt_desc(struct loption *o)
|
||||
{
|
||||
static char buf[OPTNAME_MAX + 10];
|
||||
if (o->oletter == OLETTER_NONE)
|
||||
SNPRINTF1(buf, sizeof(buf), "--%s", o->onames->oname);
|
||||
else
|
||||
SNPRINTF2(buf, sizeof(buf), "-%c (--%s)", o->oletter, o->onames->oname);
|
||||
return (buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a string suitable for printing as the "name" of an option.
|
||||
* For example, if the option letter is 'x', just return "-x".
|
||||
*/
|
||||
public char * propt(int c)
|
||||
{
|
||||
static char buf[MAX_PRCHAR_LEN+2];
|
||||
|
||||
sprintf(buf, "-%s", prchar(c));
|
||||
return (buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan an argument (either from the command line or from the
|
||||
* LESS environment variable) and process it.
|
||||
*/
|
||||
public void scan_option(char *s)
|
||||
{
|
||||
struct loption *o;
|
||||
int optc;
|
||||
char *optname;
|
||||
char *printopt;
|
||||
char *str;
|
||||
int set_default;
|
||||
int lc;
|
||||
int err;
|
||||
PARG parg;
|
||||
|
||||
if (s == NULL)
|
||||
return;
|
||||
|
||||
/*
|
||||
* If we have a pending option which requires an argument,
|
||||
* handle it now.
|
||||
* This happens if the previous option was, for example, "-P"
|
||||
* without a following string. In that case, the current
|
||||
* option is simply the argument for the previous option.
|
||||
*/
|
||||
if (pendopt != NULL)
|
||||
{
|
||||
switch (pendopt->otype & OTYPE)
|
||||
{
|
||||
case STRING:
|
||||
(*pendopt->ofunc)(INIT, s);
|
||||
break;
|
||||
case NUMBER:
|
||||
printopt = opt_desc(pendopt);
|
||||
*(pendopt->ovar) = getnum(&s, printopt, (int*)NULL);
|
||||
break;
|
||||
}
|
||||
pendopt = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
set_default = FALSE;
|
||||
optname = NULL;
|
||||
|
||||
while (*s != '\0')
|
||||
{
|
||||
/*
|
||||
* Check some special cases first.
|
||||
*/
|
||||
switch (optc = *s++)
|
||||
{
|
||||
case ' ':
|
||||
case '\t':
|
||||
case END_OPTION_STRING:
|
||||
continue;
|
||||
case '-':
|
||||
/*
|
||||
* "--" indicates an option name instead of a letter.
|
||||
*/
|
||||
if (*s == '-')
|
||||
{
|
||||
optname = ++s;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* "-+" means set these options back to their defaults.
|
||||
* (They may have been set otherwise by previous
|
||||
* options.)
|
||||
*/
|
||||
set_default = (*s == '+');
|
||||
if (set_default)
|
||||
s++;
|
||||
continue;
|
||||
case '+':
|
||||
/*
|
||||
* An option prefixed by a "+" is ungotten, so
|
||||
* that it is interpreted as less commands
|
||||
* processed at the start of the first input file.
|
||||
* "++" means process the commands at the start of
|
||||
* EVERY input file.
|
||||
*/
|
||||
plusoption = TRUE;
|
||||
s = optstring(s, &str, propt('+'), NULL);
|
||||
if (s == NULL)
|
||||
return;
|
||||
if (*str == '+')
|
||||
{
|
||||
if (every_first_cmd != NULL)
|
||||
free(every_first_cmd);
|
||||
every_first_cmd = save(str+1);
|
||||
} else
|
||||
{
|
||||
ungetsc(str);
|
||||
ungetcc_back(CHAR_END_COMMAND);
|
||||
}
|
||||
free(str);
|
||||
continue;
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
/*
|
||||
* Special "more" compatibility form "-<number>"
|
||||
* instead of -z<number> to set the scrolling
|
||||
* window size.
|
||||
*/
|
||||
s--;
|
||||
optc = 'z';
|
||||
break;
|
||||
case 'n':
|
||||
if (less_is_more)
|
||||
optc = 'z';
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Not a special case.
|
||||
* Look up the option letter in the option table.
|
||||
*/
|
||||
err = 0;
|
||||
if (optname == NULL)
|
||||
{
|
||||
printopt = propt(optc);
|
||||
lc = ASCII_IS_LOWER(optc);
|
||||
o = findopt(optc);
|
||||
} else
|
||||
{
|
||||
printopt = optname;
|
||||
lc = ASCII_IS_LOWER(optname[0]);
|
||||
o = findopt_name(&optname, NULL, &err);
|
||||
s = optname;
|
||||
optname = NULL;
|
||||
if (*s == '\0' || *s == ' ')
|
||||
{
|
||||
/*
|
||||
* The option name matches exactly.
|
||||
*/
|
||||
;
|
||||
} else if (*s == '=')
|
||||
{
|
||||
/*
|
||||
* The option name is followed by "=value".
|
||||
*/
|
||||
if (o != NULL &&
|
||||
(o->otype & OTYPE) != STRING &&
|
||||
(o->otype & OTYPE) != NUMBER)
|
||||
{
|
||||
parg.p_string = printopt;
|
||||
error("The %s option should not be followed by =",
|
||||
&parg);
|
||||
return;
|
||||
}
|
||||
s++;
|
||||
} else
|
||||
{
|
||||
/*
|
||||
* The specified name is longer than the
|
||||
* real option name.
|
||||
*/
|
||||
o = NULL;
|
||||
}
|
||||
}
|
||||
if (o == NULL)
|
||||
{
|
||||
parg.p_string = printopt;
|
||||
if (err == OPT_AMBIG)
|
||||
error("%s is an ambiguous abbreviation (\"less --help\" for help)",
|
||||
&parg);
|
||||
else
|
||||
error("There is no %s option (\"less --help\" for help)",
|
||||
&parg);
|
||||
return;
|
||||
}
|
||||
|
||||
str = NULL;
|
||||
switch (o->otype & OTYPE)
|
||||
{
|
||||
case BOOL:
|
||||
if (set_default)
|
||||
*(o->ovar) = o->odefault;
|
||||
else
|
||||
*(o->ovar) = ! o->odefault;
|
||||
break;
|
||||
case TRIPLE:
|
||||
if (set_default)
|
||||
*(o->ovar) = o->odefault;
|
||||
else
|
||||
*(o->ovar) = flip_triple(o->odefault, lc);
|
||||
break;
|
||||
case STRING:
|
||||
if (*s == '\0')
|
||||
{
|
||||
/*
|
||||
* Set pendopt and return.
|
||||
* We will get the string next time
|
||||
* scan_option is called.
|
||||
*/
|
||||
pendopt = o;
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Don't do anything here.
|
||||
* All processing of STRING options is done by
|
||||
* the handling function.
|
||||
*/
|
||||
while (*s == ' ')
|
||||
s++;
|
||||
s = optstring(s, &str, printopt, o->odesc[1]);
|
||||
if (s == NULL)
|
||||
return;
|
||||
break;
|
||||
case NUMBER:
|
||||
if (*s == '\0')
|
||||
{
|
||||
pendopt = o;
|
||||
return;
|
||||
}
|
||||
*(o->ovar) = getnum(&s, printopt, (int*)NULL);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* If the option has a handling function, call it.
|
||||
*/
|
||||
if (o->ofunc != NULL)
|
||||
(*o->ofunc)(INIT, str);
|
||||
if (str != NULL)
|
||||
free(str);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
public void toggle_option(struct loption *o, int lower, char *s, int how_toggle)
|
||||
{
|
||||
int num;
|
||||
int no_prompt;
|
||||
int err;
|
||||
PARG parg;
|
||||
|
||||
no_prompt = (how_toggle & OPT_NO_PROMPT);
|
||||
how_toggle &= ~OPT_NO_PROMPT;
|
||||
|
||||
if (o == NULL)
|
||||
{
|
||||
error("No such option", NULL_PARG);
|
||||
return;
|
||||
}
|
||||
|
||||
if (how_toggle == OPT_TOGGLE && (o->otype & NO_TOGGLE))
|
||||
{
|
||||
parg.p_string = opt_desc(o);
|
||||
error("Cannot change the %s option", &parg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (how_toggle == OPT_NO_TOGGLE && (o->otype & NO_QUERY))
|
||||
{
|
||||
parg.p_string = opt_desc(o);
|
||||
error("Cannot query the %s option", &parg);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for something which appears to be a do_toggle
|
||||
* (because the "-" command was used), but really is not.
|
||||
* This could be a string option with no string, or
|
||||
* a number option with no number.
|
||||
*/
|
||||
switch (o->otype & OTYPE)
|
||||
{
|
||||
case STRING:
|
||||
case NUMBER:
|
||||
if (how_toggle == OPT_TOGGLE && *s == '\0')
|
||||
how_toggle = OPT_NO_TOGGLE;
|
||||
break;
|
||||
}
|
||||
|
||||
#if HILITE_SEARCH
|
||||
if (how_toggle != OPT_NO_TOGGLE && (o->otype & HL_REPAINT))
|
||||
repaint_hilite(0);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Now actually toggle (change) the variable.
|
||||
*/
|
||||
if (how_toggle != OPT_NO_TOGGLE)
|
||||
{
|
||||
switch (o->otype & OTYPE)
|
||||
{
|
||||
case BOOL:
|
||||
/*
|
||||
* Boolean.
|
||||
*/
|
||||
switch (how_toggle)
|
||||
{
|
||||
case OPT_TOGGLE:
|
||||
*(o->ovar) = ! *(o->ovar);
|
||||
break;
|
||||
case OPT_UNSET:
|
||||
*(o->ovar) = o->odefault;
|
||||
break;
|
||||
case OPT_SET:
|
||||
*(o->ovar) = ! o->odefault;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
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.
|
||||
*/
|
||||
switch (how_toggle)
|
||||
{
|
||||
case OPT_TOGGLE:
|
||||
*(o->ovar) = flip_triple(*(o->ovar), lower);
|
||||
break;
|
||||
case OPT_UNSET:
|
||||
*(o->ovar) = o->odefault;
|
||||
break;
|
||||
case OPT_SET:
|
||||
*(o->ovar) = flip_triple(o->odefault, lower);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case STRING:
|
||||
/*
|
||||
* String: don't do anything here.
|
||||
* The handling function will do everything.
|
||||
*/
|
||||
switch (how_toggle)
|
||||
{
|
||||
case OPT_SET:
|
||||
case OPT_UNSET:
|
||||
error("Cannot use \"-+\" or \"--\" for a string option",
|
||||
NULL_PARG);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case NUMBER:
|
||||
/*
|
||||
* Number: set the variable to the given number.
|
||||
*/
|
||||
switch (how_toggle)
|
||||
{
|
||||
case OPT_TOGGLE:
|
||||
num = getnum(&s, NULL, &err);
|
||||
if (!err)
|
||||
*(o->ovar) = num;
|
||||
break;
|
||||
case OPT_UNSET:
|
||||
*(o->ovar) = o->odefault;
|
||||
break;
|
||||
case OPT_SET:
|
||||
error("Can't use \"-!\" for a numeric option",
|
||||
NULL_PARG);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Call the handling function for any special action
|
||||
* specific to this option.
|
||||
*/
|
||||
if (o->ofunc != NULL)
|
||||
(*o->ofunc)((how_toggle==OPT_NO_TOGGLE) ? QUERY : TOGGLE, s);
|
||||
|
||||
#if HILITE_SEARCH
|
||||
if (how_toggle != OPT_NO_TOGGLE && (o->otype & HL_REPAINT))
|
||||
chg_hilite();
|
||||
#endif
|
||||
|
||||
if (!no_prompt)
|
||||
{
|
||||
/*
|
||||
* Print a message describing the new setting.
|
||||
*/
|
||||
switch (o->otype & OTYPE)
|
||||
{
|
||||
case BOOL:
|
||||
case TRIPLE:
|
||||
/*
|
||||
* Print the odesc message.
|
||||
*/
|
||||
error(o->odesc[*(o->ovar)], NULL_PARG);
|
||||
break;
|
||||
case NUMBER:
|
||||
/*
|
||||
* The message is in odesc[1] and has a %d for
|
||||
* the value of the variable.
|
||||
*/
|
||||
parg.p_int = *(o->ovar);
|
||||
error(o->odesc[1], &parg);
|
||||
break;
|
||||
case STRING:
|
||||
/*
|
||||
* Message was already printed by the handling function.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (how_toggle != OPT_NO_TOGGLE && (o->otype & REPAINT))
|
||||
screen_trashed = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* "Toggle" a triple-valued option.
|
||||
*/
|
||||
static int flip_triple(int val, int lc)
|
||||
{
|
||||
if (lc)
|
||||
return ((val == OPT_ON) ? OPT_OFF : OPT_ON);
|
||||
else
|
||||
return ((val == OPT_ONPLUS) ? OPT_OFF : OPT_ONPLUS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if an option takes a parameter.
|
||||
*/
|
||||
public int opt_has_param(struct loption *o)
|
||||
{
|
||||
if (o == NULL)
|
||||
return (0);
|
||||
if (o->otype & (BOOL|TRIPLE|NOVAR|NO_TOGGLE))
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the prompt to be used for a given option letter.
|
||||
* Only string and number valued options have prompts.
|
||||
*/
|
||||
public char * opt_prompt(struct loption *o)
|
||||
{
|
||||
if (o == NULL || (o->otype & (STRING|NUMBER)) == 0)
|
||||
return ("?");
|
||||
return (o->odesc[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the specified option can be toggled, return NULL.
|
||||
* Otherwise return an appropriate error message.
|
||||
*/
|
||||
public char * opt_toggle_disallowed(int c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'o':
|
||||
if (ch_getflags() & CH_CANSEEK)
|
||||
return "Input is not a pipe";
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return whether or not there is a string option pending;
|
||||
* that is, if the previous option was a string-valued option letter
|
||||
* (like -P) without a following string.
|
||||
* In that case, the current option is taken to be the string for
|
||||
* the previous option.
|
||||
*/
|
||||
public int isoptpending(void)
|
||||
{
|
||||
return (pendopt != NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print error message about missing string.
|
||||
*/
|
||||
static void nostring(char *printopt)
|
||||
{
|
||||
PARG parg;
|
||||
parg.p_string = printopt;
|
||||
error("Value is required after %s", &parg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print error message if a STRING type option is not followed by a string.
|
||||
*/
|
||||
public void nopendopt(void)
|
||||
{
|
||||
nostring(opt_desc(pendopt));
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan to end of string or to an END_OPTION_STRING character.
|
||||
* In the latter case, replace the char with a null char.
|
||||
* Return a pointer to the remainder of the string, if any.
|
||||
*/
|
||||
static char * optstring(char *s, char **p_str, char *printopt, char *validchars)
|
||||
{
|
||||
char *p;
|
||||
char *out;
|
||||
|
||||
if (*s == '\0')
|
||||
{
|
||||
nostring(printopt);
|
||||
return (NULL);
|
||||
}
|
||||
/* Alloc could be more than needed, but not worth trimming. */
|
||||
*p_str = (char *) ecalloc(strlen(s)+1, sizeof(char));
|
||||
out = *p_str;
|
||||
|
||||
for (p = s; *p != '\0'; p++)
|
||||
{
|
||||
if (opt_use_backslash && *p == '\\' && p[1] != '\0')
|
||||
{
|
||||
/* Take next char literally. */
|
||||
++p;
|
||||
} else
|
||||
{
|
||||
if (*p == END_OPTION_STRING ||
|
||||
(validchars != NULL && strchr(validchars, *p) == NULL))
|
||||
/* End of option string. */
|
||||
break;
|
||||
}
|
||||
*out++ = *p;
|
||||
}
|
||||
*out = '\0';
|
||||
return (p);
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
static int num_error(char *printopt, int *errp, int overflow)
|
||||
{
|
||||
PARG parg;
|
||||
|
||||
if (errp != NULL)
|
||||
{
|
||||
*errp = TRUE;
|
||||
return (-1);
|
||||
}
|
||||
if (printopt != NULL)
|
||||
{
|
||||
parg.p_string = printopt;
|
||||
error((overflow
|
||||
? "Number too large in '%s'"
|
||||
: "Number is required after %s"),
|
||||
&parg);
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate a string into a number.
|
||||
* Like atoi(), but takes a pointer to a char *, and updates
|
||||
* the char * to point after the translated number.
|
||||
*/
|
||||
public int getnum(char **sp, char *printopt, int *errp)
|
||||
{
|
||||
char *s;
|
||||
int n;
|
||||
int neg;
|
||||
|
||||
s = skipsp(*sp);
|
||||
neg = FALSE;
|
||||
if (*s == '-')
|
||||
{
|
||||
neg = TRUE;
|
||||
s++;
|
||||
}
|
||||
if (*s < '0' || *s > '9')
|
||||
return (num_error(printopt, errp, FALSE));
|
||||
|
||||
n = lstrtoi(s, sp, 10);
|
||||
if (n < 0)
|
||||
return (num_error(printopt, errp, TRUE));
|
||||
if (errp != NULL)
|
||||
*errp = FALSE;
|
||||
if (neg)
|
||||
n = -n;
|
||||
return (n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate a string into a fraction, represented by the part of a
|
||||
* number which would follow a decimal point.
|
||||
* The value of the fraction is returned as parts per NUM_FRAC_DENOM.
|
||||
* That is, if "n" is returned, the fraction intended is n/NUM_FRAC_DENOM.
|
||||
*/
|
||||
public long getfraction(char **sp, char *printopt, int *errp)
|
||||
{
|
||||
char *s;
|
||||
long frac = 0;
|
||||
int fraclen = 0;
|
||||
|
||||
s = skipsp(*sp);
|
||||
if (*s < '0' || *s > '9')
|
||||
return (num_error(printopt, errp, FALSE));
|
||||
|
||||
for ( ; *s >= '0' && *s <= '9'; s++)
|
||||
{
|
||||
if (NUM_LOG_FRAC_DENOM <= fraclen)
|
||||
continue;
|
||||
frac = (frac * 10) + (*s - '0');
|
||||
fraclen++;
|
||||
}
|
||||
while (fraclen++ < NUM_LOG_FRAC_DENOM)
|
||||
frac *= 10;
|
||||
*sp = s;
|
||||
if (errp != NULL)
|
||||
*errp = FALSE;
|
||||
return (frac);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get the value of the -e flag.
|
||||
*/
|
||||
public int get_quit_at_eof(void)
|
||||
{
|
||||
if (!less_is_more)
|
||||
return quit_at_eof;
|
||||
/* When less_is_more is set, the -e flag semantics are different. */
|
||||
return quit_at_eof ? OPT_ONPLUS : OPT_ON;
|
||||
}
|
66
third_party/less/option.h
vendored
Normal file
66
third_party/less/option.h
vendored
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
#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 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) */
|
||||
|
||||
/* 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
|
||||
|
||||
/* 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 */
|
||||
};
|
||||
|
||||
#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)(int, char*); /* Pointer to special handling function */
|
||||
char *odesc[3]; /* Description of each value */
|
||||
};
|
||||
|
861
third_party/less/opttbl.c
vendored
Normal file
861
third_party/less/opttbl.c
vendored
Normal file
|
@ -0,0 +1,861 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* The option table.
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
#include "option.h"
|
||||
|
||||
/*
|
||||
* Variables controlled by command line options.
|
||||
*/
|
||||
public int quiet; /* Should we suppress the audible bell? */
|
||||
public int no_vbell; /* Should we suppress the visual 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 wordwrap; /* Wrap lines at space */
|
||||
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 linenum_width; /* Width of line numbers */
|
||||
public int status_col_width; /* Width of status column */
|
||||
public int incr_search; /* Incremental search */
|
||||
public int use_color; /* Use UI color */
|
||||
public int want_filesize; /* Scan to EOF if necessary to get file size */
|
||||
public int status_line; /* Highlight entire marked lines */
|
||||
public int header_lines; /* Freeze header lines at top of screen */
|
||||
public int header_cols; /* Freeze header columns at left of screen */
|
||||
public int nonum_headers; /* Don't give headers line numbers */
|
||||
public int nosearch_headers; /* Don't search in header lines or columns */
|
||||
public int redraw_on_quit; /* Redraw last screen after term deinit */
|
||||
public int def_search_type; /* */
|
||||
public int exit_F_on_close; /* Exit F command when input closes */
|
||||
public int modelines; /* Lines to read looking for modelines */
|
||||
public int show_preproc_error; /* Display msg when preproc exits with error */
|
||||
public int proc_backspace; /* Special handling of backspace */
|
||||
public int proc_tab; /* Special handling of tab */
|
||||
public int proc_return; /* Special handling of carriage return */
|
||||
public char intr_char = CONTROL('X'); /* Char to interrupt reads */
|
||||
#if HILITE_SEARCH
|
||||
public int hilite_search; /* Highlight matched search patterns? */
|
||||
#endif
|
||||
|
||||
public int less_is_more = 0; /* Make compatible with POSIX more */
|
||||
|
||||
/*
|
||||
* Long option names.
|
||||
*/
|
||||
static struct optname a_optname = { "search-skip-screen", NULL };
|
||||
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 };
|
||||
static struct optname D__optname = { "color", NULL };
|
||||
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 };
|
||||
#if HILITE_SEARCH
|
||||
static struct optname g_optname = { "hilite-search", NULL };
|
||||
#endif
|
||||
static struct optname h_optname = { "max-back-scroll", NULL };
|
||||
static struct optname i_optname = { "ignore-case", NULL };
|
||||
static struct optname j_optname = { "jump-target", NULL };
|
||||
static struct optname J__optname = { "status-column", NULL };
|
||||
#if USERFILE
|
||||
static struct optname k_optname = { "lesskey-file", NULL };
|
||||
#if HAVE_LESSKEYSRC
|
||||
static struct optname ks_optname = { "lesskey-src", NULL };
|
||||
#endif /* HAVE_LESSKEYSRC */
|
||||
#endif
|
||||
static struct optname K__optname = { "quit-on-intr", NULL };
|
||||
static struct optname L__optname = { "no-lessopen", NULL };
|
||||
static struct optname m_optname = { "long-prompt", NULL };
|
||||
static struct optname n_optname = { "line-numbers", NULL };
|
||||
#if LOGFILE
|
||||
static struct optname o_optname = { "log-file", NULL };
|
||||
static struct optname O__optname = { "LOG-FILE", NULL };
|
||||
#endif
|
||||
static struct optname p_optname = { "pattern", NULL };
|
||||
static struct optname P__optname = { "prompt", NULL };
|
||||
static struct optname q2_optname = { "silent", NULL };
|
||||
static struct optname q_optname = { "quiet", &q2_optname };
|
||||
static struct optname r_optname = { "raw-control-chars", NULL };
|
||||
static struct optname s_optname = { "squeeze-blank-lines", NULL };
|
||||
static struct optname S__optname = { "chop-long-lines", NULL };
|
||||
#if TAGS
|
||||
static struct optname t_optname = { "tag", NULL };
|
||||
static struct optname T__optname = { "tag-file", NULL };
|
||||
#endif
|
||||
static struct optname u_optname = { "underline-special", NULL };
|
||||
static struct optname V__optname = { "version", NULL };
|
||||
static struct optname w_optname = { "hilite-unread", NULL };
|
||||
static struct optname x_optname = { "tabs", NULL };
|
||||
static struct optname X__optname = { "no-init", NULL };
|
||||
static struct optname y_optname = { "max-forw-scroll", NULL };
|
||||
static struct optname z_optname = { "window", NULL };
|
||||
static struct optname quote_optname = { "quotes", NULL };
|
||||
static struct optname tilde_optname = { "tilde", NULL };
|
||||
static struct optname query_optname = { "help", NULL };
|
||||
static struct optname pound_optname = { "shift", NULL };
|
||||
static struct optname keypad_optname = { "no-keypad", NULL };
|
||||
static struct optname oldbot_optname = { "old-bot", NULL };
|
||||
static struct optname follow_optname = { "follow-name", NULL };
|
||||
static struct optname use_backslash_optname = { "use-backslash", NULL };
|
||||
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 linenum_width_optname = { "line-num-width", NULL };
|
||||
static struct optname status_col_width_optname = { "status-col-width", NULL };
|
||||
static struct optname incr_search_optname = { "incsearch", NULL };
|
||||
static struct optname use_color_optname = { "use-color", NULL };
|
||||
static struct optname want_filesize_optname = { "file-size", NULL };
|
||||
static struct optname status_line_optname = { "status-line", NULL };
|
||||
static struct optname header_optname = { "header", NULL };
|
||||
static struct optname nonum_headers_optname = { "no-number-headers", NULL };
|
||||
static struct optname nosearch_headers_optname = { "no-search-headers", NULL };
|
||||
static struct optname redraw_on_quit_optname = { "redraw-on-quit", NULL };
|
||||
static struct optname search_type_optname = { "search-options", NULL };
|
||||
static struct optname exit_F_on_close_optname = { "exit-follow-on-close", NULL };
|
||||
static struct optname modelines_optname = { "modelines", NULL };
|
||||
static struct optname no_vbell_optname = { "no-vbell", NULL };
|
||||
static struct optname intr_optname = { "intr", NULL };
|
||||
static struct optname wordwrap_optname = { "wordwrap", NULL };
|
||||
static struct optname show_preproc_error_optname = { "show-preproc-errors", NULL };
|
||||
static struct optname proc_backspace_optname = { "proc-backspace", NULL };
|
||||
static struct optname proc_tab_optname = { "proc-tab", NULL };
|
||||
static struct optname proc_return_optname = { "proc-return", NULL };
|
||||
#if LESSTEST
|
||||
static struct optname ttyin_name_optname = { "tty", NULL };
|
||||
#endif /*LESSTEST*/
|
||||
|
||||
|
||||
/*
|
||||
* Table of all options and their semantics.
|
||||
*
|
||||
* For BOOL and TRIPLE options, odesc[0], odesc[1], odesc[2] are
|
||||
* the description of the option when set to 0, 1 or 2, respectively.
|
||||
* For NUMBER options, odesc[0] is the prompt to use when entering
|
||||
* a new value, and odesc[1] is the description, which should contain
|
||||
* one %d which is replaced by the value of the number.
|
||||
* For STRING options, odesc[0] is the prompt to use when entering
|
||||
* a new value, and odesc[1], if not NULL, is the set of characters
|
||||
* that are valid in the string.
|
||||
*/
|
||||
static struct loption option[] =
|
||||
{
|
||||
{ 'a', &a_optname,
|
||||
TRIPLE, OPT_ONPLUS, &how_search, NULL,
|
||||
{
|
||||
"Search includes displayed screen",
|
||||
"Search skips displayed screen",
|
||||
"Search includes all of displayed screen"
|
||||
}
|
||||
},
|
||||
|
||||
{ 'b', &b_optname,
|
||||
NUMBER|INIT_HANDLER, 64, &bufspace, opt_b,
|
||||
{
|
||||
"Max buffer space per file (K): ",
|
||||
"Max buffer space per file: %dK",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ 'B', &B__optname,
|
||||
BOOL, OPT_ON, &autobuf, NULL,
|
||||
{
|
||||
"Don't automatically allocate buffers",
|
||||
"Automatically allocate buffers when needed",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ 'c', &c_optname,
|
||||
TRIPLE, OPT_OFF, &top_scroll, NULL,
|
||||
{
|
||||
"Repaint by scrolling from bottom of screen",
|
||||
"Repaint by painting from top of screen",
|
||||
"Repaint by painting from top of screen"
|
||||
}
|
||||
},
|
||||
{ 'd', &d_optname,
|
||||
BOOL|NO_TOGGLE, OPT_OFF, &know_dumb, NULL,
|
||||
{
|
||||
"Assume intelligent terminal",
|
||||
"Assume dumb terminal",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ 'D', &D__optname,
|
||||
STRING|REPAINT|NO_QUERY, 0, NULL, opt_D,
|
||||
{
|
||||
"color desc: ",
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ 'e', &e_optname,
|
||||
TRIPLE, OPT_OFF, &quit_at_eof, NULL,
|
||||
{
|
||||
"Don't quit at end-of-file",
|
||||
"Quit at end-of-file",
|
||||
"Quit immediately at end-of-file"
|
||||
}
|
||||
},
|
||||
{ 'f', &f_optname,
|
||||
BOOL, OPT_OFF, &force_open, NULL,
|
||||
{
|
||||
"Open only regular files",
|
||||
"Open even non-regular files",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ 'F', &F__optname,
|
||||
BOOL, OPT_OFF, &quit_if_one_screen, NULL,
|
||||
{
|
||||
"Don't quit if end-of-file on first screen",
|
||||
"Quit if end-of-file on first screen",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
#if HILITE_SEARCH
|
||||
{ 'g', &g_optname,
|
||||
TRIPLE|HL_REPAINT, OPT_ONPLUS, &hilite_search, NULL,
|
||||
{
|
||||
"Don't highlight search matches",
|
||||
"Highlight matches for previous search only",
|
||||
"Highlight all matches for previous search pattern",
|
||||
}
|
||||
},
|
||||
#endif
|
||||
{ 'h', &h_optname,
|
||||
NUMBER, -1, &back_scroll, NULL,
|
||||
{
|
||||
"Backwards scroll limit: ",
|
||||
"Backwards scroll limit is %d lines",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ 'i', &i_optname,
|
||||
TRIPLE|HL_REPAINT, OPT_OFF, &caseless, opt_i,
|
||||
{
|
||||
"Case is significant in searches",
|
||||
"Ignore case in searches",
|
||||
"Ignore case in searches and in patterns"
|
||||
}
|
||||
},
|
||||
{ 'j', &j_optname,
|
||||
STRING, 0, NULL, opt_j,
|
||||
{
|
||||
"Target line: ",
|
||||
"0123456789.-",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ 'J', &J__optname,
|
||||
BOOL|REPAINT, OPT_OFF, &status_col, NULL,
|
||||
{
|
||||
"Don't display a status column",
|
||||
"Display a status column",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
#if USERFILE
|
||||
{ 'k', &k_optname,
|
||||
STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_k,
|
||||
{ NULL, NULL, NULL }
|
||||
},
|
||||
#if HAVE_LESSKEYSRC
|
||||
{ OLETTER_NONE, &ks_optname,
|
||||
STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_ks,
|
||||
{ NULL, NULL, NULL }
|
||||
},
|
||||
#endif /* HAVE_LESSKEYSRC */
|
||||
#endif
|
||||
{ 'K', &K__optname,
|
||||
BOOL, OPT_OFF, &quit_on_intr, NULL,
|
||||
{
|
||||
"Interrupt (ctrl-C) returns to prompt",
|
||||
"Interrupt (ctrl-C) exits less",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ 'L', &L__optname,
|
||||
BOOL, OPT_ON, &use_lessopen, NULL,
|
||||
{
|
||||
"Don't use the LESSOPEN filter",
|
||||
"Use the LESSOPEN filter",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ 'm', &m_optname,
|
||||
TRIPLE, OPT_OFF, &pr_type, NULL,
|
||||
{
|
||||
"Short prompt",
|
||||
"Medium prompt",
|
||||
"Long prompt"
|
||||
}
|
||||
},
|
||||
{ 'n', &n_optname,
|
||||
TRIPLE|REPAINT, OPT_ON, &linenums, NULL,
|
||||
{
|
||||
"Don't use line numbers",
|
||||
"Use line numbers",
|
||||
"Constantly display line numbers"
|
||||
}
|
||||
},
|
||||
#if LOGFILE
|
||||
{ 'o', &o_optname,
|
||||
STRING, 0, NULL, opt_o,
|
||||
{ "log file: ", NULL, NULL }
|
||||
},
|
||||
{ 'O', &O__optname,
|
||||
STRING, 0, NULL, opt__O,
|
||||
{ "Log file: ", NULL, NULL }
|
||||
},
|
||||
#endif
|
||||
{ 'p', &p_optname,
|
||||
STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_p,
|
||||
{ NULL, NULL, NULL }
|
||||
},
|
||||
{ 'P', &P__optname,
|
||||
STRING, 0, NULL, opt__P,
|
||||
{ "prompt: ", NULL, NULL }
|
||||
},
|
||||
{ 'q', &q_optname,
|
||||
TRIPLE, OPT_OFF, &quiet, NULL,
|
||||
{
|
||||
"Ring the bell for errors AND at eof/bof",
|
||||
"Ring the bell for errors but not at eof/bof",
|
||||
"Never ring the bell"
|
||||
}
|
||||
},
|
||||
{ 'r', &r_optname,
|
||||
TRIPLE|REPAINT, OPT_OFF, &ctldisp, NULL,
|
||||
{
|
||||
"Display control characters as ^X",
|
||||
"Display control characters directly (not recommended)",
|
||||
"Display ANSI sequences directly, other control characters as ^X"
|
||||
}
|
||||
},
|
||||
{ 's', &s_optname,
|
||||
BOOL|REPAINT, OPT_OFF, &squeeze, NULL,
|
||||
{
|
||||
"Display all blank lines",
|
||||
"Squeeze multiple blank lines",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ 'S', &S__optname,
|
||||
BOOL|REPAINT, OPT_OFF, &chopline, NULL,
|
||||
{
|
||||
"Fold long lines",
|
||||
"Chop long lines",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
#if TAGS
|
||||
{ 't', &t_optname,
|
||||
STRING|NO_QUERY, 0, NULL, opt_t,
|
||||
{ "tag: ", NULL, NULL }
|
||||
},
|
||||
{ 'T', &T__optname,
|
||||
STRING, 0, NULL, opt__T,
|
||||
{ "tags file: ", NULL, NULL }
|
||||
},
|
||||
#endif
|
||||
{ 'u', &u_optname,
|
||||
TRIPLE|REPAINT|HL_REPAINT, OPT_OFF, &bs_mode, NULL,
|
||||
{
|
||||
"Display underlined text in underline mode",
|
||||
"Backspaces cause overstrike",
|
||||
"Print backspace as ^H"
|
||||
}
|
||||
},
|
||||
{ 'V', &V__optname,
|
||||
NOVAR, 0, NULL, opt__V,
|
||||
{ NULL, NULL, NULL }
|
||||
},
|
||||
{ 'w', &w_optname,
|
||||
TRIPLE|REPAINT, OPT_OFF, &show_attn, NULL,
|
||||
{
|
||||
"Don't highlight first unread line",
|
||||
"Highlight first unread line after forward-screen",
|
||||
"Highlight first unread line after any forward movement",
|
||||
}
|
||||
},
|
||||
{ 'x', &x_optname,
|
||||
STRING|REPAINT, 0, NULL, opt_x,
|
||||
{
|
||||
"Tab stops: ",
|
||||
"0123456789,",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ 'X', &X__optname,
|
||||
BOOL|NO_TOGGLE, OPT_OFF, &no_init, NULL,
|
||||
{
|
||||
"Send init/deinit strings to terminal",
|
||||
"Don't use init/deinit strings",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ 'y', &y_optname,
|
||||
NUMBER, -1, &forw_scroll, NULL,
|
||||
{
|
||||
"Forward scroll limit: ",
|
||||
"Forward scroll limit is %d lines",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ 'z', &z_optname,
|
||||
NUMBER, -1, &swindow, NULL,
|
||||
{
|
||||
"Scroll window size: ",
|
||||
"Scroll window size is %d lines",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ '"', "e_optname,
|
||||
STRING, 0, NULL, opt_quote,
|
||||
{ "quotes: ", NULL, NULL }
|
||||
},
|
||||
{ '~', &tilde_optname,
|
||||
BOOL|REPAINT, OPT_ON, &twiddle, NULL,
|
||||
{
|
||||
"Don't show tildes after end of file",
|
||||
"Show tildes after end of file",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ '?', &query_optname,
|
||||
NOVAR, 0, NULL, opt_query,
|
||||
{ NULL, NULL, NULL }
|
||||
},
|
||||
{ '#', £_optname,
|
||||
STRING, 0, NULL, opt_shift,
|
||||
{
|
||||
"Horizontal shift: ",
|
||||
"0123456789.",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ OLETTER_NONE, &keypad_optname,
|
||||
BOOL|NO_TOGGLE, OPT_OFF, &no_keypad, NULL,
|
||||
{
|
||||
"Use keypad mode",
|
||||
"Don't use keypad mode",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ OLETTER_NONE, &oldbot_optname,
|
||||
BOOL, OPT_OFF, &oldbot, NULL,
|
||||
{
|
||||
"Use new bottom of screen behavior",
|
||||
"Use old bottom of screen behavior",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ OLETTER_NONE, &follow_optname,
|
||||
BOOL, FOLLOW_DESC, &follow_mode, NULL,
|
||||
{
|
||||
"F command follows file descriptor",
|
||||
"F command follows file name",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ OLETTER_NONE, &use_backslash_optname,
|
||||
BOOL, OPT_OFF, &opt_use_backslash, NULL,
|
||||
{
|
||||
"Use backslash escaping in command line parameters",
|
||||
"Don't use backslash escaping in command line parameters",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ OLETTER_NONE, &rscroll_optname,
|
||||
STRING|REPAINT|INIT_HANDLER, 0, NULL, opt_rscroll,
|
||||
{ "rscroll character: ", NULL, NULL }
|
||||
},
|
||||
{ OLETTER_NONE, &nohistdups_optname,
|
||||
BOOL, OPT_OFF, &no_hist_dups, NULL,
|
||||
{
|
||||
"Allow duplicates in history list",
|
||||
"Remove duplicates from history list",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ OLETTER_NONE, &mousecap_optname,
|
||||
TRIPLE, OPT_OFF, &mousecap, opt_mousecap,
|
||||
{
|
||||
"Ignore mouse input",
|
||||
"Use the mouse for scrolling",
|
||||
"Use the mouse for scrolling (reverse)"
|
||||
}
|
||||
},
|
||||
{ OLETTER_NONE, &wheel_lines_optname,
|
||||
NUMBER|INIT_HANDLER, 0, &wheel_lines, opt_wheel_lines,
|
||||
{
|
||||
"Lines to scroll on mouse wheel: ",
|
||||
"Scroll %d line(s) on mouse wheel",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ OLETTER_NONE, &perma_marks_optname,
|
||||
BOOL, OPT_OFF, &perma_marks, NULL,
|
||||
{
|
||||
"Don't save marks in history file",
|
||||
"Save marks in history file",
|
||||
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
|
||||
}
|
||||
},
|
||||
{ OLETTER_NONE, &want_filesize_optname,
|
||||
BOOL|REPAINT, OPT_OFF, &want_filesize, opt_filesize,
|
||||
{
|
||||
"Don't get size of each file",
|
||||
"Get size of each file",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ OLETTER_NONE, &status_line_optname,
|
||||
BOOL|REPAINT, OPT_OFF, &status_line, NULL,
|
||||
{
|
||||
"Don't color each line with its status column color",
|
||||
"Color each line with its status column color",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ OLETTER_NONE, &header_optname,
|
||||
STRING|REPAINT, 0, NULL, opt_header,
|
||||
{
|
||||
"Header lines: ",
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ OLETTER_NONE, &nonum_headers_optname,
|
||||
BOOL|REPAINT, 0, &nonum_headers, NULL,
|
||||
{
|
||||
"Number header lines",
|
||||
"Don't number header lines",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ OLETTER_NONE, &nosearch_headers_optname,
|
||||
BOOL|HL_REPAINT, 0, &nosearch_headers, NULL,
|
||||
{
|
||||
"Search includes header lines",
|
||||
"Search does not include header lines",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ OLETTER_NONE, &redraw_on_quit_optname,
|
||||
BOOL, OPT_OFF, &redraw_on_quit, NULL,
|
||||
{
|
||||
"Don't redraw screen when quitting",
|
||||
"Redraw last screen when quitting",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ OLETTER_NONE, &search_type_optname,
|
||||
STRING, 0, NULL, opt_search_type,
|
||||
{
|
||||
"Search options: ",
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ OLETTER_NONE, &exit_F_on_close_optname,
|
||||
BOOL, OPT_OFF, &exit_F_on_close, NULL,
|
||||
{
|
||||
"Don't exit F command when input closes",
|
||||
"Exit F command when input closes",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ OLETTER_NONE, &no_vbell_optname,
|
||||
BOOL, OPT_OFF, &no_vbell, NULL,
|
||||
{
|
||||
"Display visual bell",
|
||||
"Don't display visual bell",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ OLETTER_NONE, &modelines_optname,
|
||||
NUMBER, 0, &modelines, NULL,
|
||||
{
|
||||
"Lines to read looking for modelines: ",
|
||||
"Read %d lines looking for modelines",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ OLETTER_NONE, &intr_optname,
|
||||
STRING, 0, NULL, opt_intr,
|
||||
{ "interrupt character: ", NULL, NULL }
|
||||
},
|
||||
{ OLETTER_NONE, &wordwrap_optname,
|
||||
BOOL|REPAINT, OPT_OFF, &wordwrap, NULL,
|
||||
{
|
||||
"Wrap lines at any character",
|
||||
"Wrap lines at spaces",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ OLETTER_NONE, &show_preproc_error_optname,
|
||||
BOOL, OPT_OFF, &show_preproc_error, NULL,
|
||||
{
|
||||
"Don't show error message if preprocessor fails",
|
||||
"Show error message if preprocessor fails",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ OLETTER_NONE, &proc_backspace_optname,
|
||||
TRIPLE|REPAINT|HL_REPAINT, OPT_OFF, &proc_backspace, NULL,
|
||||
{
|
||||
"Backspace handling is specified by the -U option",
|
||||
"Display underline text in underline mode",
|
||||
"Print backspaces as ^H"
|
||||
}
|
||||
},
|
||||
{ OLETTER_NONE, &proc_tab_optname,
|
||||
TRIPLE|REPAINT|HL_REPAINT, OPT_OFF, &proc_tab, NULL,
|
||||
{
|
||||
"Tab handling is specified by the -U option",
|
||||
"Expand tabs to spaces",
|
||||
"Print tabs as ^I"
|
||||
}
|
||||
},
|
||||
{ OLETTER_NONE, &proc_return_optname,
|
||||
TRIPLE|REPAINT|HL_REPAINT, OPT_OFF, &proc_return, NULL,
|
||||
{
|
||||
"Carriage return handling is specified by the -U option",
|
||||
"Delete carriage return before newline",
|
||||
"Print carriage return as ^M"
|
||||
}
|
||||
},
|
||||
#if LESSTEST
|
||||
{ OLETTER_NONE, &ttyin_name_optname,
|
||||
STRING|NO_TOGGLE, 0, NULL, opt_ttyin_name,
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
#endif /*LESSTEST*/
|
||||
{ '\0', NULL, NOVAR, 0, NULL, NULL, { NULL, NULL, NULL } }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Initialize each option to its default value.
|
||||
*/
|
||||
public void init_option(void)
|
||||
{
|
||||
struct loption *o;
|
||||
char *p;
|
||||
|
||||
p = lgetenv("LESS_IS_MORE");
|
||||
if (!isnullenv(p))
|
||||
less_is_more = 1;
|
||||
|
||||
for (o = option; o->oletter != '\0'; o++)
|
||||
{
|
||||
/*
|
||||
* Set each variable to its default.
|
||||
*/
|
||||
if (o->ovar != NULL)
|
||||
*(o->ovar) = o->odefault;
|
||||
if (o->otype & INIT_HANDLER)
|
||||
(*(o->ofunc))(INIT, (char *) NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Find an option in the option table, given its option letter.
|
||||
*/
|
||||
public struct loption * findopt(int c)
|
||||
{
|
||||
struct loption *o;
|
||||
|
||||
for (o = option; o->oletter != '\0'; o++)
|
||||
{
|
||||
if (o->oletter == c)
|
||||
return (o);
|
||||
if ((o->otype & TRIPLE) && ASCII_TO_UPPER(o->oletter) == c)
|
||||
return (o);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static int is_optchar(char c)
|
||||
{
|
||||
if (ASCII_IS_UPPER(c))
|
||||
return 1;
|
||||
if (ASCII_IS_LOWER(c))
|
||||
return 1;
|
||||
if (c == '-')
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find an option in the option table, given its option name.
|
||||
* p_optname is the (possibly partial) name to look for, and
|
||||
* is updated to point after the matched name.
|
||||
* p_oname if non-NULL is set to point to the full option name.
|
||||
*/
|
||||
public struct loption * findopt_name(char **p_optname, char **p_oname, int *p_err)
|
||||
{
|
||||
char *optname = *p_optname;
|
||||
struct loption *o;
|
||||
struct optname *oname;
|
||||
int len;
|
||||
int uppercase;
|
||||
struct loption *maxo = NULL;
|
||||
struct optname *maxoname = NULL;
|
||||
int maxlen = 0;
|
||||
int ambig = 0;
|
||||
int exact = 0;
|
||||
|
||||
/*
|
||||
* Check all options.
|
||||
*/
|
||||
for (o = option; o->oletter != '\0'; o++)
|
||||
{
|
||||
/*
|
||||
* Check all names for this option.
|
||||
*/
|
||||
for (oname = o->onames; oname != NULL; oname = oname->onext)
|
||||
{
|
||||
/*
|
||||
* Try normal match first (uppercase == 0),
|
||||
* then, then if it's a TRIPLE option,
|
||||
* try uppercase match (uppercase == 1).
|
||||
*/
|
||||
for (uppercase = 0; uppercase <= 1; uppercase++)
|
||||
{
|
||||
len = sprefix(optname, oname->oname, uppercase);
|
||||
if (len <= 0 || is_optchar(optname[len]))
|
||||
{
|
||||
/*
|
||||
* We didn't use all of the option name.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
if (!exact && len == maxlen)
|
||||
/*
|
||||
* Already had a partial match,
|
||||
* and now there's another one that
|
||||
* matches the same length.
|
||||
*/
|
||||
ambig = 1;
|
||||
else if (len > maxlen)
|
||||
{
|
||||
/*
|
||||
* Found a better match than
|
||||
* the one we had.
|
||||
*/
|
||||
maxo = o;
|
||||
maxoname = oname;
|
||||
maxlen = len;
|
||||
ambig = 0;
|
||||
exact = (len == (int)strlen(oname->oname));
|
||||
}
|
||||
if (!(o->otype & TRIPLE))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ambig)
|
||||
{
|
||||
/*
|
||||
* Name matched more than one option.
|
||||
*/
|
||||
if (p_err != NULL)
|
||||
*p_err = OPT_AMBIG;
|
||||
return (NULL);
|
||||
}
|
||||
*p_optname = optname + maxlen;
|
||||
if (p_oname != NULL)
|
||||
*p_oname = maxoname == NULL ? NULL : maxoname->oname;
|
||||
return (maxo);
|
||||
}
|
507
third_party/less/os.c
vendored
Normal file
507
third_party/less/os.c
vendored
Normal file
|
@ -0,0 +1,507 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Operating system dependent routines.
|
||||
*
|
||||
* Most of the stuff in here is based on Unix, but an attempt
|
||||
* has been made to make things work on other operating systems.
|
||||
* This will sometimes result in a loss of functionality, unless
|
||||
* someone rewrites code specifically for the new operating system.
|
||||
*
|
||||
* The makefile provides defines to decide whether various
|
||||
* Unix features are present.
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
#include <signal.h>
|
||||
#include <setjmp.h>
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
/* #include <windows.h> */
|
||||
#endif
|
||||
#if HAVE_TIME_H
|
||||
#include <time.h>
|
||||
#endif
|
||||
#if HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#if HAVE_VALUES_H
|
||||
#include <values.h>
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <sys/utsname.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_POLL && !MSDOS_COMPILER
|
||||
#define USE_POLL 1
|
||||
static int use_poll = TRUE;
|
||||
#else
|
||||
#define USE_POLL 0
|
||||
#endif
|
||||
#if USE_POLL
|
||||
#include <poll.h>
|
||||
static int any_data = FALSE;
|
||||
#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
|
||||
* signal mask with sigsetmask(), and use _setjmp()/_longjmp() instead.
|
||||
* On other systems, setjmp() doesn't affect the signal mask and so
|
||||
* _setjmp() does not exist; we just use setjmp().
|
||||
*/
|
||||
#if HAVE__SETJMP && HAVE_SIGSETMASK
|
||||
#define SET_JUMP _setjmp
|
||||
#define LONG_JUMP _longjmp
|
||||
#else
|
||||
#define SET_JUMP setjmp
|
||||
#define LONG_JUMP longjmp
|
||||
#endif
|
||||
|
||||
public int reading;
|
||||
public int waiting_for_data;
|
||||
public int consecutive_nulls = 0;
|
||||
|
||||
/* Milliseconds to wait for data before displaying "waiting for data" message. */
|
||||
static int waiting_for_data_delay = 4000;
|
||||
static jmp_buf read_label;
|
||||
|
||||
extern int sigs;
|
||||
extern int ignore_eoi;
|
||||
extern int exit_F_on_close;
|
||||
extern int follow_mode;
|
||||
extern int scanning_eof;
|
||||
extern char intr_char;
|
||||
#if !MSDOS_COMPILER
|
||||
extern int tty;
|
||||
#endif
|
||||
#if LESSTEST
|
||||
extern char *ttyin_name;
|
||||
#endif /*LESSTEST*/
|
||||
|
||||
public void init_poll(void)
|
||||
{
|
||||
char *delay = lgetenv("LESS_DATA_DELAY");
|
||||
int idelay = (delay == NULL) ? 0 : atoi(delay);
|
||||
if (idelay > 0)
|
||||
waiting_for_data_delay = idelay;
|
||||
#if USE_POLL
|
||||
#if defined(__APPLE__)
|
||||
/* In old versions of MacOS, poll() does not work with /dev/tty. */
|
||||
struct utsname uts;
|
||||
if (uname(&uts) < 0 || lstrtoi(uts.release, NULL, 10) < 20)
|
||||
use_poll = FALSE;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#if USE_POLL
|
||||
/*
|
||||
* Check whether data is available, either from a file/pipe or from the tty.
|
||||
* Return READ_AGAIN if no data currently available, but caller should retry later.
|
||||
* Return READ_INTR to abort F command (forw_loop).
|
||||
* Return 0 if safe to read from fd.
|
||||
*/
|
||||
static int check_poll(int fd, int tty)
|
||||
{
|
||||
struct pollfd poller[2] = { { fd, POLLIN, 0 }, { tty, POLLIN, 0 } };
|
||||
int timeout = (waiting_for_data && !(scanning_eof && follow_mode == FOLLOW_NAME)) ? -1 : waiting_for_data_delay;
|
||||
if (!any_data)
|
||||
{
|
||||
/*
|
||||
* Don't do polling if no data has yet been received,
|
||||
* to allow a program piping data into less to have temporary
|
||||
* access to the tty (like sudo asking for a password).
|
||||
*/
|
||||
return (0);
|
||||
}
|
||||
poll(poller, 2, timeout);
|
||||
#if LESSTEST
|
||||
if (ttyin_name == NULL) /* Check for ^X only on a real tty. */
|
||||
#endif /*LESSTEST*/
|
||||
{
|
||||
if (poller[1].revents & POLLIN)
|
||||
{
|
||||
LWCHAR ch = getchr();
|
||||
if (ch == intr_char)
|
||||
/* Break out of "waiting for data". */
|
||||
return (READ_INTR);
|
||||
ungetcc_back(ch);
|
||||
}
|
||||
}
|
||||
if (ignore_eoi && exit_F_on_close && (poller[0].revents & (POLLHUP|POLLIN)) == POLLHUP)
|
||||
/* Break out of F loop on HUP due to --exit-follow-on-close. */
|
||||
return (READ_INTR);
|
||||
if ((poller[0].revents & (POLLIN|POLLHUP|POLLERR)) == 0)
|
||||
/* No data available; let caller take action, then try again. */
|
||||
return (READ_AGAIN);
|
||||
/* There is data (or HUP/ERR) available. Safe to call read() without blocking. */
|
||||
return (0);
|
||||
}
|
||||
#endif /* USE_POLL */
|
||||
|
||||
public int supports_ctrl_x(void)
|
||||
{
|
||||
#if USE_POLL
|
||||
return (use_poll);
|
||||
#else
|
||||
return (FALSE);
|
||||
#endif /* USE_POLL */
|
||||
}
|
||||
|
||||
/*
|
||||
* Like read() system call, but is deliberately interruptible.
|
||||
* A call to intread() from a signal handler will interrupt
|
||||
* any pending iread().
|
||||
*/
|
||||
public int iread(int fd, unsigned char *buf, unsigned int len)
|
||||
{
|
||||
int n;
|
||||
|
||||
start:
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
if (ABORT_SIGS())
|
||||
return (READ_INTR);
|
||||
#else
|
||||
#if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
|
||||
if (kbhit())
|
||||
{
|
||||
int c;
|
||||
|
||||
c = getch();
|
||||
if (c == '\003')
|
||||
return (READ_INTR);
|
||||
ungetch(c);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
if (!reading && SET_JUMP(read_label))
|
||||
{
|
||||
/*
|
||||
* We jumped here from intread.
|
||||
*/
|
||||
reading = 0;
|
||||
#if HAVE_SIGPROCMASK
|
||||
{
|
||||
sigset_t mask;
|
||||
sigemptyset(&mask);
|
||||
sigprocmask(SIG_SETMASK, &mask, NULL);
|
||||
}
|
||||
#else
|
||||
#if HAVE_SIGSETMASK
|
||||
sigsetmask(0);
|
||||
#else
|
||||
#ifdef _OSK
|
||||
sigmask(~0);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#if !MSDOS_COMPILER
|
||||
if (fd != tty && !ABORT_SIGS())
|
||||
/* Non-interrupt signal like SIGWINCH. */
|
||||
return (READ_AGAIN);
|
||||
#endif
|
||||
return (READ_INTR);
|
||||
}
|
||||
|
||||
flush();
|
||||
reading = 1;
|
||||
#if MSDOS_COMPILER==DJGPPC
|
||||
if (isatty(fd))
|
||||
{
|
||||
/*
|
||||
* Don't try reading from a TTY until a character is
|
||||
* available, because that makes some background programs
|
||||
* believe DOS is busy in a way that prevents those
|
||||
* programs from working while "less" waits.
|
||||
* {{ This code was added 12 Jan 2007; still needed? }}
|
||||
*/
|
||||
fd_set readfds;
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(fd, &readfds);
|
||||
if (select(fd+1, &readfds, 0, 0, 0) == -1)
|
||||
{
|
||||
reading = 0;
|
||||
return (READ_ERR);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if USE_POLL
|
||||
if (fd != tty && use_poll)
|
||||
{
|
||||
int ret = check_poll(fd, tty);
|
||||
if (ret != 0)
|
||||
{
|
||||
if (ret == READ_INTR)
|
||||
sigs |= S_INTERRUPT;
|
||||
reading = 0;
|
||||
return (ret);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
if (win32_kbhit())
|
||||
{
|
||||
int c;
|
||||
|
||||
c = WIN32getch();
|
||||
if (c == intr_char)
|
||||
{
|
||||
sigs |= S_INTERRUPT;
|
||||
reading = 0;
|
||||
return (READ_INTR);
|
||||
}
|
||||
WIN32ungetch(c);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
n = read(fd, buf, len);
|
||||
reading = 0;
|
||||
#if 1
|
||||
/*
|
||||
* This is a kludge to workaround a problem on some systems
|
||||
* where terminating a remote tty connection causes read() to
|
||||
* start returning 0 forever, instead of -1.
|
||||
*/
|
||||
{
|
||||
if (!ignore_eoi)
|
||||
{
|
||||
if (n == 0)
|
||||
consecutive_nulls++;
|
||||
else
|
||||
consecutive_nulls = 0;
|
||||
if (consecutive_nulls > 20)
|
||||
quit(QUIT_ERROR);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (n < 0)
|
||||
{
|
||||
#if HAVE_ERRNO
|
||||
/*
|
||||
* Certain values of errno indicate we should just retry the read.
|
||||
*/
|
||||
#if MUST_DEFINE_ERRNO
|
||||
extern int errno;
|
||||
#endif
|
||||
#ifdef EINTR
|
||||
if (errno == EINTR)
|
||||
goto start;
|
||||
#endif
|
||||
#ifdef EAGAIN
|
||||
if (errno == EAGAIN)
|
||||
goto start;
|
||||
#endif
|
||||
#endif
|
||||
return (READ_ERR);
|
||||
}
|
||||
#if USE_POLL
|
||||
if (fd != tty && n > 0)
|
||||
any_data = TRUE;
|
||||
#endif
|
||||
return (n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt a pending iread().
|
||||
*/
|
||||
public void intread(void)
|
||||
{
|
||||
LONG_JUMP(read_label, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the current time.
|
||||
*/
|
||||
#if HAVE_TIME
|
||||
public time_type get_time(void)
|
||||
{
|
||||
time_type t;
|
||||
|
||||
time(&t);
|
||||
return (t);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if !HAVE_STRERROR
|
||||
/*
|
||||
* Local version of strerror, if not available from the system.
|
||||
*/
|
||||
static char * strerror(int err)
|
||||
{
|
||||
static char buf[INT_STRLEN_BOUND(int)+12];
|
||||
#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;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* errno_message: Return an error message based on the value of "errno".
|
||||
*/
|
||||
public char * errno_message(char *filename)
|
||||
{
|
||||
char *p;
|
||||
char *m;
|
||||
int len;
|
||||
#if HAVE_ERRNO
|
||||
#if MUST_DEFINE_ERRNO
|
||||
extern int errno;
|
||||
#endif
|
||||
p = strerror(errno);
|
||||
#else
|
||||
p = "cannot open";
|
||||
#endif
|
||||
len = (int) (strlen(filename) + strlen(p) + 3);
|
||||
m = (char *) ecalloc(len, sizeof(char));
|
||||
SNPRINTF2(m, len, "%s: %s", filename, p);
|
||||
return (m);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a description of a signal.
|
||||
* The return value is good until the next call to this function.
|
||||
*/
|
||||
public char * signal_message(int sig)
|
||||
{
|
||||
static char sigbuf[sizeof("Signal ") + INT_STRLEN_BOUND(sig) + 1];
|
||||
#if HAVE_STRSIGNAL
|
||||
char *description = strsignal(sig);
|
||||
if (description)
|
||||
return description;
|
||||
#endif
|
||||
sprintf(sigbuf, "Signal %d", sig);
|
||||
return sigbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return (VAL * NUM) / DEN, where DEN is positive
|
||||
* and min(VAL, NUM) <= DEN so the result cannot overflow.
|
||||
* Round to the nearest integer, breaking ties by rounding to even.
|
||||
*/
|
||||
public uintmax muldiv(uintmax val, uintmax num, uintmax den)
|
||||
{
|
||||
/*
|
||||
* Like round(val * (double) num / den), but without rounding error.
|
||||
* Overflow cannot occur, so there is no need for floating point.
|
||||
*/
|
||||
uintmax q = val / den;
|
||||
uintmax r = val % den;
|
||||
uintmax qnum = q * num;
|
||||
uintmax rnum = r * num;
|
||||
uintmax quot = qnum + rnum / den;
|
||||
uintmax rem = rnum % den;
|
||||
return quot + (den / 2 < rem + (quot & ~den & 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the ratio of two POSITIONS, as a percentage.
|
||||
* {{ Assumes a POSITION is a long int. }}
|
||||
*/
|
||||
public int percentage(POSITION num, POSITION den)
|
||||
{
|
||||
return (int) muldiv(num, (POSITION) 100, den);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the specified percentage of a POSITION.
|
||||
* Assume (0 <= POS && 0 <= PERCENT <= 100
|
||||
* && 0 <= FRACTION < (PERCENT == 100 ? 1 : NUM_FRAC_DENOM)),
|
||||
* so the result cannot overflow. Round to even.
|
||||
*/
|
||||
public POSITION percent_pos(POSITION pos, int percent, long fraction)
|
||||
{
|
||||
/*
|
||||
* Change from percent (parts per 100)
|
||||
* to pctden (parts per 100 * NUM_FRAC_DENOM).
|
||||
*/
|
||||
POSITION pctden = (percent * NUM_FRAC_DENOM) + fraction;
|
||||
|
||||
return (POSITION) muldiv(pos, pctden, 100 * (POSITION) NUM_FRAC_DENOM);
|
||||
}
|
||||
|
||||
#if !HAVE_STRCHR
|
||||
/*
|
||||
* strchr is used by regexp.c.
|
||||
*/
|
||||
char * strchr(char *s, char c)
|
||||
{
|
||||
for ( ; *s != '\0'; s++)
|
||||
if (*s == c)
|
||||
return (s);
|
||||
if (c == '\0')
|
||||
return (s);
|
||||
return (NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !HAVE_MEMCPY
|
||||
void * memcpy(void *dst, void *src, int len)
|
||||
{
|
||||
char *dstp = (char *) dst;
|
||||
char *srcp = (char *) src;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
dstp[i] = srcp[i];
|
||||
return (dst);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _OSK_MWC32
|
||||
|
||||
/*
|
||||
* This implements an ANSI-style intercept setup for Microware C 3.2
|
||||
*/
|
||||
public int os9_signal(int type, RETSIGTYPE (*handler)())
|
||||
{
|
||||
intercept(handler);
|
||||
}
|
||||
|
||||
#include <sgstat.h>
|
||||
|
||||
int isatty(int f)
|
||||
{
|
||||
struct sgbuf sgbuf;
|
||||
|
||||
if (_gs_opt(f, &sgbuf) < 0)
|
||||
return -1;
|
||||
return (sgbuf.sg_class == 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
public void sleep_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 / 1000 + (ms % 1000 != 0));
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
719
third_party/less/output.c
vendored
Normal file
719
third_party/less/output.c
vendored
Normal file
|
@ -0,0 +1,719 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* High level routines dealing with the output to the screen.
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
/* #include "windows.h" */
|
||||
#ifndef COMMON_LVB_UNDERSCORE
|
||||
#define COMMON_LVB_UNDERSCORE 0x8000
|
||||
#endif
|
||||
#endif
|
||||
|
||||
public int errmsgs; /* Count of messages displayed by error() */
|
||||
public int need_clr;
|
||||
public int final_attr;
|
||||
public int at_prompt;
|
||||
|
||||
extern int sigs;
|
||||
extern int sc_width;
|
||||
extern int so_s_width, so_e_width;
|
||||
extern int screen_trashed;
|
||||
extern int is_tty;
|
||||
extern int oldbot;
|
||||
extern char intr_char;
|
||||
|
||||
#if MSDOS_COMPILER==WIN32C || MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC
|
||||
extern int ctldisp;
|
||||
extern int nm_fg_color, nm_bg_color;
|
||||
extern int bo_fg_color, bo_bg_color;
|
||||
extern int ul_fg_color, ul_bg_color;
|
||||
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 vt_enabled;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Display the line which is in the line buffer.
|
||||
*/
|
||||
public void put_line(void)
|
||||
{
|
||||
int c;
|
||||
int i;
|
||||
int a;
|
||||
|
||||
if (ABORT_SIGS())
|
||||
{
|
||||
/*
|
||||
* Don't output if a signal is pending.
|
||||
*/
|
||||
screen_trashed = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
final_attr = AT_NORMAL;
|
||||
|
||||
for (i = 0; (c = gline(i, &a)) != '\0'; i++)
|
||||
{
|
||||
at_switch(a);
|
||||
final_attr = a;
|
||||
if (c == '\b')
|
||||
putbs();
|
||||
else
|
||||
putchr(c);
|
||||
}
|
||||
|
||||
at_exit();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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.
|
||||
*
|
||||
* If we haven't displayed any file data yet,
|
||||
* output messages on error output (file descriptor 2),
|
||||
* otherwise output on standard output (file descriptor 1).
|
||||
*
|
||||
* This has the desirable effect of producing all
|
||||
* error messages on error output if standard output
|
||||
* is directed to a file. It also does the same if
|
||||
* we never produce any real output; for example, if
|
||||
* the input file(s) cannot be opened. If we do
|
||||
* eventually produce output, code in edit() makes
|
||||
* sure these messages can be seen before they are
|
||||
* overwritten or scrolled away.
|
||||
*/
|
||||
public void flush(void)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = (int) (ob - obuf);
|
||||
if (n == 0)
|
||||
return;
|
||||
ob = obuf;
|
||||
|
||||
#if MSDOS_COMPILER==MSOFTC
|
||||
if (interactive())
|
||||
{
|
||||
obuf[n] = '\0';
|
||||
_outtext(obuf);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
#if MSDOS_COMPILER==WIN32C || MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC
|
||||
if (interactive())
|
||||
{
|
||||
ob = obuf + n;
|
||||
*ob = '\0';
|
||||
win_flush();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (write(outfd, obuf, n) != n)
|
||||
screen_trashed = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the output file descriptor (1=stdout or 2=stderr).
|
||||
*/
|
||||
public void set_output(int fd)
|
||||
{
|
||||
flush();
|
||||
outfd = fd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Output a character.
|
||||
*/
|
||||
public int putchr(int c)
|
||||
{
|
||||
#if 0 /* fake UTF-8 output for testing */
|
||||
extern int utf_mode;
|
||||
if (utf_mode)
|
||||
{
|
||||
static char ubuf[MAX_UTF_CHAR_LEN];
|
||||
static int ubuf_len = 0;
|
||||
static int ubuf_index = 0;
|
||||
if (ubuf_len == 0)
|
||||
{
|
||||
ubuf_len = utf_len(c);
|
||||
ubuf_index = 0;
|
||||
}
|
||||
ubuf[ubuf_index++] = c;
|
||||
if (ubuf_index < ubuf_len)
|
||||
return c;
|
||||
c = get_wchar(ubuf) & 0xFF;
|
||||
ubuf_len = 0;
|
||||
}
|
||||
#endif
|
||||
clear_bot_if_needed();
|
||||
#if MSDOS_COMPILER
|
||||
if (c == '\n' && is_tty)
|
||||
{
|
||||
/* remove_top(1); */
|
||||
putchr('\r');
|
||||
}
|
||||
#else
|
||||
#ifdef _OSK
|
||||
if (c == '\n' && is_tty) /* In OS-9, '\n' == 0x0D */
|
||||
putchr(0x0A);
|
||||
#endif
|
||||
#endif
|
||||
/*
|
||||
* Some versions of flush() write to *ob, so we must flush
|
||||
* when we are still one char from the end of obuf.
|
||||
*/
|
||||
if (ob >= &obuf[sizeof(obuf)-1])
|
||||
flush();
|
||||
*ob++ = c;
|
||||
at_prompt = 0;
|
||||
return (c);
|
||||
}
|
||||
|
||||
public void clear_bot_if_needed(void)
|
||||
{
|
||||
if (!need_clr)
|
||||
return;
|
||||
need_clr = 0;
|
||||
clear_bot();
|
||||
}
|
||||
|
||||
/*
|
||||
* Output a string.
|
||||
*/
|
||||
public void putstr(constant char *s)
|
||||
{
|
||||
while (*s != '\0')
|
||||
putchr(*s++);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert an integral type to a string.
|
||||
*/
|
||||
#define TYPE_TO_A_FUNC(funcname, type) \
|
||||
void funcname(type num, char *buf, int radix) \
|
||||
{ \
|
||||
int neg = (num < 0); \
|
||||
char tbuf[INT_STRLEN_BOUND(num)+2]; \
|
||||
char *s = tbuf + sizeof(tbuf); \
|
||||
if (neg) num = -num; \
|
||||
*--s = '\0'; \
|
||||
do { \
|
||||
*--s = "0123456789ABCDEF"[num % radix]; \
|
||||
} while ((num /= radix) != 0); \
|
||||
if (neg) *--s = '-'; \
|
||||
strcpy(buf, s); \
|
||||
}
|
||||
|
||||
TYPE_TO_A_FUNC(postoa, POSITION)
|
||||
TYPE_TO_A_FUNC(linenumtoa, LINENUM)
|
||||
TYPE_TO_A_FUNC(inttoa, int)
|
||||
|
||||
/*
|
||||
* Convert a string to an integral type. Return ((type) -1) on overflow.
|
||||
*/
|
||||
#define STR_TO_TYPE_FUNC(funcname, type) \
|
||||
type funcname(char *buf, char **ebuf, int radix) \
|
||||
{ \
|
||||
type val = 0; \
|
||||
int v = 0; \
|
||||
for (;; buf++) { \
|
||||
char c = *buf; \
|
||||
int digit = (c >= '0' && c <= '9') ? c - '0' : (c >= 'a' && c <= 'f') ? c - 'a' + 10 : (c >= 'A' && c <= 'F') ? c - 'A' + 10 : -1; \
|
||||
if (digit < 0 || digit >= radix) break; \
|
||||
v |= ckd_mul(&val, val, radix); \
|
||||
v |= ckd_add(&val, val, digit); \
|
||||
} \
|
||||
if (ebuf != NULL) *ebuf = buf; \
|
||||
return v ? -1 : val; \
|
||||
}
|
||||
|
||||
STR_TO_TYPE_FUNC(lstrtopos, POSITION)
|
||||
STR_TO_TYPE_FUNC(lstrtoi, int)
|
||||
STR_TO_TYPE_FUNC(lstrtoul, unsigned long)
|
||||
|
||||
/*
|
||||
* Print an integral type.
|
||||
*/
|
||||
#define IPRINT_FUNC(funcname, type, typetoa) \
|
||||
static int funcname(type num, int radix) \
|
||||
{ \
|
||||
char buf[INT_STRLEN_BOUND(num)]; \
|
||||
typetoa(num, buf, radix); \
|
||||
putstr(buf); \
|
||||
return (int) strlen(buf); \
|
||||
}
|
||||
|
||||
IPRINT_FUNC(iprint_int, int, inttoa)
|
||||
IPRINT_FUNC(iprint_linenum, LINENUM, linenumtoa)
|
||||
|
||||
/*
|
||||
* 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. }}
|
||||
*/
|
||||
public int less_printf(char *fmt, PARG *parg)
|
||||
{
|
||||
char *s;
|
||||
int col;
|
||||
|
||||
col = 0;
|
||||
while (*fmt != '\0')
|
||||
{
|
||||
if (*fmt != '%')
|
||||
{
|
||||
putchr(*fmt++);
|
||||
col++;
|
||||
} else
|
||||
{
|
||||
++fmt;
|
||||
switch (*fmt++)
|
||||
{
|
||||
case 's':
|
||||
s = parg->p_string;
|
||||
parg++;
|
||||
while (*s != '\0')
|
||||
{
|
||||
putchr(*s++);
|
||||
col++;
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
col += iprint_int(parg->p_int, 10);
|
||||
parg++;
|
||||
break;
|
||||
case 'x':
|
||||
col += iprint_int(parg->p_int, 16);
|
||||
parg++;
|
||||
break;
|
||||
case 'n':
|
||||
col += iprint_linenum(parg->p_linenum, 10);
|
||||
parg++;
|
||||
break;
|
||||
case 'c':
|
||||
s = prchar(parg->p_char);
|
||||
parg++;
|
||||
while (*s != '\0')
|
||||
{
|
||||
putchr(*s++);
|
||||
col++;
|
||||
}
|
||||
break;
|
||||
case '%':
|
||||
putchr('%');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (col);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a RETURN.
|
||||
* If some other non-trivial char is pressed, unget it, so it will
|
||||
* become the next command.
|
||||
*/
|
||||
public void get_return(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
#if ONLY_RETURN
|
||||
while ((c = getchr()) != '\n' && c != '\r')
|
||||
bell();
|
||||
#else
|
||||
c = getchr();
|
||||
if (c != '\n' && c != '\r' && c != ' ' && c != READ_INTR)
|
||||
ungetcc(c);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Output a message in the lower left corner of the screen
|
||||
* and wait for carriage return.
|
||||
*/
|
||||
public void error(char *fmt, PARG *parg)
|
||||
{
|
||||
int col = 0;
|
||||
static char return_to_continue[] = " (press RETURN)";
|
||||
|
||||
errmsgs++;
|
||||
|
||||
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;
|
||||
|
||||
get_return();
|
||||
lower_left();
|
||||
clear_eol();
|
||||
|
||||
if (col >= sc_width)
|
||||
/*
|
||||
* Printing the message has probably scrolled the screen.
|
||||
* {{ Unless the terminal doesn't have auto margins,
|
||||
* in which case we just hammered on the right margin. }}
|
||||
*/
|
||||
screen_trashed = 1;
|
||||
|
||||
flush();
|
||||
}
|
||||
|
||||
/*
|
||||
* Output a message in the lower left corner of the screen
|
||||
* and don't wait for carriage return.
|
||||
* Usually used to warn that we are beginning a potentially
|
||||
* time-consuming operation.
|
||||
*/
|
||||
static void ierror_suffix(char *fmt, PARG *parg, char *suffix1, char *suffix2, char *suffix3)
|
||||
{
|
||||
at_exit();
|
||||
clear_bot();
|
||||
at_enter(AT_STANDOUT|AT_COLOR_ERROR);
|
||||
(void) less_printf(fmt, parg);
|
||||
putstr(suffix1);
|
||||
putstr(suffix2);
|
||||
putstr(suffix3);
|
||||
at_exit();
|
||||
flush();
|
||||
need_clr = 1;
|
||||
}
|
||||
|
||||
public void ierror(char *fmt, PARG *parg)
|
||||
{
|
||||
ierror_suffix(fmt, parg, "... (interrupt to abort)", "", "");
|
||||
}
|
||||
|
||||
public void ixerror(char *fmt, PARG *parg)
|
||||
{
|
||||
if (!supports_ctrl_x())
|
||||
ierror(fmt, parg);
|
||||
else
|
||||
ierror_suffix(fmt, parg,
|
||||
"... (", prchar(intr_char), " or interrupt to abort)");
|
||||
}
|
||||
|
||||
/*
|
||||
* Output a message in the lower left corner of the screen
|
||||
* and return a single-character response.
|
||||
*/
|
||||
public int query(char *fmt, PARG *parg)
|
||||
{
|
||||
int c;
|
||||
int col = 0;
|
||||
|
||||
if (interactive())
|
||||
clear_bot();
|
||||
|
||||
(void) less_printf(fmt, parg);
|
||||
c = getchr();
|
||||
|
||||
if (interactive())
|
||||
{
|
||||
lower_left();
|
||||
if (col >= sc_width)
|
||||
screen_trashed = 1;
|
||||
flush();
|
||||
} else
|
||||
{
|
||||
putchr('\n');
|
||||
}
|
||||
|
||||
if (c == 'Q')
|
||||
quit(QUIT_OK);
|
||||
return (c);
|
||||
}
|
491
third_party/less/pattern.c
vendored
Normal file
491
third_party/less/pattern.c
vendored
Normal file
|
@ -0,0 +1,491 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Routines to do pattern matching.
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
|
||||
extern int caseless;
|
||||
extern int is_caseless;
|
||||
extern int utf_mode;
|
||||
|
||||
/*
|
||||
* Compile a search pattern, for future use by match_pattern.
|
||||
*/
|
||||
static int compile_pattern2(char *pattern, int search_type, PATTERN_TYPE *comp_pattern, int show_error)
|
||||
{
|
||||
if (search_type & SRCH_NO_REGEX)
|
||||
return (0);
|
||||
{
|
||||
#if HAVE_GNU_REGEX
|
||||
struct re_pattern_buffer *comp = (struct re_pattern_buffer *)
|
||||
ecalloc(1, sizeof(struct re_pattern_buffer));
|
||||
re_set_syntax(RE_SYNTAX_POSIX_EXTENDED);
|
||||
if (re_compile_pattern(pattern, strlen(pattern), comp))
|
||||
{
|
||||
free(comp);
|
||||
if (show_error)
|
||||
error("Invalid pattern", NULL_PARG);
|
||||
return (-1);
|
||||
}
|
||||
if (*comp_pattern != NULL)
|
||||
{
|
||||
regfree(*comp_pattern);
|
||||
free(*comp_pattern);
|
||||
}
|
||||
*comp_pattern = comp;
|
||||
#endif
|
||||
#if HAVE_POSIX_REGCOMP
|
||||
regex_t *comp = (regex_t *) ecalloc(1, sizeof(regex_t));
|
||||
if (regcomp(comp, pattern, REGCOMP_FLAG | (is_caseless ? REG_ICASE : 0)))
|
||||
{
|
||||
free(comp);
|
||||
if (show_error)
|
||||
error("Invalid pattern", NULL_PARG);
|
||||
return (-1);
|
||||
}
|
||||
if (*comp_pattern != NULL)
|
||||
{
|
||||
regfree(*comp_pattern);
|
||||
free(*comp_pattern);
|
||||
}
|
||||
*comp_pattern = comp;
|
||||
#endif
|
||||
#if HAVE_PCRE
|
||||
constant char *errstring;
|
||||
int erroffset;
|
||||
PARG parg;
|
||||
pcre *comp = pcre_compile(pattern,
|
||||
((utf_mode) ? PCRE_UTF8 | PCRE_NO_UTF8_CHECK : 0) |
|
||||
(is_caseless ? PCRE_CASELESS : 0),
|
||||
&errstring, &erroffset, NULL);
|
||||
if (comp == NULL)
|
||||
{
|
||||
parg.p_string = (char *) errstring;
|
||||
if (show_error)
|
||||
error("%s", &parg);
|
||||
return (-1);
|
||||
}
|
||||
*comp_pattern = comp;
|
||||
#endif
|
||||
#if HAVE_PCRE2
|
||||
int errcode;
|
||||
PCRE2_SIZE erroffset;
|
||||
PARG parg;
|
||||
pcre2_code *comp = pcre2_compile((PCRE2_SPTR)pattern, strlen(pattern),
|
||||
(is_caseless ? PCRE2_CASELESS : 0),
|
||||
&errcode, &erroffset, NULL);
|
||||
if (comp == NULL)
|
||||
{
|
||||
if (show_error)
|
||||
{
|
||||
char msg[160];
|
||||
pcre2_get_error_message(errcode, (PCRE2_UCHAR*)msg, sizeof(msg));
|
||||
parg.p_string = msg;
|
||||
error("%s", &parg);
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
*comp_pattern = comp;
|
||||
#endif
|
||||
#if HAVE_RE_COMP
|
||||
PARG parg;
|
||||
if ((parg.p_string = re_comp(pattern)) != NULL)
|
||||
{
|
||||
if (show_error)
|
||||
error("%s", &parg);
|
||||
return (-1);
|
||||
}
|
||||
*comp_pattern = 1;
|
||||
#endif
|
||||
#if HAVE_REGCMP
|
||||
char *comp;
|
||||
if ((comp = regcmp(pattern, 0)) == NULL)
|
||||
{
|
||||
if (show_error)
|
||||
error("Invalid pattern", NULL_PARG);
|
||||
return (-1);
|
||||
}
|
||||
if (comp_pattern != NULL)
|
||||
free(*comp_pattern);
|
||||
*comp_pattern = comp;
|
||||
#endif
|
||||
#if HAVE_V8_REGCOMP
|
||||
struct regexp *comp;
|
||||
reg_show_error = show_error;
|
||||
comp = regcomp(pattern);
|
||||
reg_show_error = 1;
|
||||
if (comp == NULL)
|
||||
{
|
||||
/*
|
||||
* regcomp has already printed an error message
|
||||
* via regerror().
|
||||
*/
|
||||
return (-1);
|
||||
}
|
||||
if (*comp_pattern != NULL)
|
||||
free(*comp_pattern);
|
||||
*comp_pattern = comp;
|
||||
#endif
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Like compile_pattern2, but convert the pattern to lowercase if necessary.
|
||||
*/
|
||||
public int compile_pattern(char *pattern, int search_type, int show_error, PATTERN_TYPE *comp_pattern)
|
||||
{
|
||||
char *cvt_pattern;
|
||||
int result;
|
||||
|
||||
if (caseless != OPT_ONPLUS || (re_handles_caseless && !(search_type & SRCH_NO_REGEX)))
|
||||
cvt_pattern = pattern;
|
||||
else
|
||||
{
|
||||
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, show_error);
|
||||
if (cvt_pattern != pattern)
|
||||
free(cvt_pattern);
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Forget that we have a compiled pattern.
|
||||
*/
|
||||
public void uncompile_pattern(PATTERN_TYPE *pattern)
|
||||
{
|
||||
#if HAVE_GNU_REGEX
|
||||
if (*pattern != NULL)
|
||||
{
|
||||
regfree(*pattern);
|
||||
free(*pattern);
|
||||
}
|
||||
*pattern = NULL;
|
||||
#endif
|
||||
#if HAVE_POSIX_REGCOMP
|
||||
if (*pattern != NULL)
|
||||
{
|
||||
regfree(*pattern);
|
||||
free(*pattern);
|
||||
}
|
||||
*pattern = NULL;
|
||||
#endif
|
||||
#if HAVE_PCRE
|
||||
if (*pattern != NULL)
|
||||
pcre_free(*pattern);
|
||||
*pattern = NULL;
|
||||
#endif
|
||||
#if HAVE_PCRE2
|
||||
if (*pattern != NULL)
|
||||
pcre2_code_free(*pattern);
|
||||
*pattern = NULL;
|
||||
#endif
|
||||
#if HAVE_RE_COMP
|
||||
*pattern = 0;
|
||||
#endif
|
||||
#if HAVE_REGCMP
|
||||
if (*pattern != NULL)
|
||||
free(*pattern);
|
||||
*pattern = NULL;
|
||||
#endif
|
||||
#if HAVE_V8_REGCOMP
|
||||
if (*pattern != NULL)
|
||||
free(*pattern);
|
||||
*pattern = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Can a pattern be successfully compiled?
|
||||
*/
|
||||
public int valid_pattern(char *pattern)
|
||||
{
|
||||
PATTERN_TYPE comp_pattern;
|
||||
int result;
|
||||
|
||||
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?
|
||||
*/
|
||||
public int is_null_pattern(PATTERN_TYPE pattern)
|
||||
{
|
||||
#if HAVE_GNU_REGEX
|
||||
return (pattern == NULL);
|
||||
#endif
|
||||
#if HAVE_POSIX_REGCOMP
|
||||
return (pattern == NULL);
|
||||
#endif
|
||||
#if HAVE_PCRE
|
||||
return (pattern == NULL);
|
||||
#endif
|
||||
#if HAVE_PCRE2
|
||||
return (pattern == NULL);
|
||||
#endif
|
||||
#if HAVE_RE_COMP
|
||||
return (pattern == 0);
|
||||
#endif
|
||||
#if HAVE_REGCMP
|
||||
return (pattern == NULL);
|
||||
#endif
|
||||
#if HAVE_V8_REGCOMP
|
||||
return (pattern == NULL);
|
||||
#endif
|
||||
#if NO_REGEX
|
||||
return (pattern == NULL);
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Simple pattern matching function.
|
||||
* It supports no metacharacters like *, etc.
|
||||
*/
|
||||
static int match(char *pattern, int pattern_len, char *buf, int buf_len, char ***sp, char ***ep, int nsubs)
|
||||
{
|
||||
char *pp, *lp;
|
||||
char *pattern_end = pattern + pattern_len;
|
||||
char *buf_end = buf + buf_len;
|
||||
|
||||
for ( ; buf < buf_end; buf++)
|
||||
{
|
||||
for (pp = pattern, lp = buf; ; pp++, lp++)
|
||||
{
|
||||
char cp = *pp;
|
||||
char cl = *lp;
|
||||
if (caseless == OPT_ONPLUS && ASCII_IS_UPPER(cp))
|
||||
cp = ASCII_TO_LOWER(cp);
|
||||
if (cp != cl)
|
||||
break;
|
||||
if (pp == pattern_end || lp == buf_end)
|
||||
break;
|
||||
}
|
||||
if (pp == pattern_end)
|
||||
{
|
||||
*(*sp)++ = buf;
|
||||
*(*ep)++ = lp;
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
**sp = **ep = NULL;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform a pattern match with the previously compiled pattern.
|
||||
* Set sp[0] and ep[0] to the start and end of the matched string.
|
||||
* Set sp[i] and ep[i] to the start and end of the i-th matched subpattern.
|
||||
* Subpatterns are defined by parentheses in the regex language.
|
||||
*/
|
||||
static int match_pattern1(PATTERN_TYPE pattern, char *tpattern, char *line, int line_len, char **sp, char **ep, int nsp, int notbol, int search_type)
|
||||
{
|
||||
int matched;
|
||||
|
||||
#if NO_REGEX
|
||||
search_type |= SRCH_NO_REGEX;
|
||||
#endif
|
||||
if (search_type & SRCH_NO_REGEX)
|
||||
matched = match(tpattern, strlen(tpattern), line, line_len, &sp, &ep, nsp);
|
||||
else
|
||||
{
|
||||
#if HAVE_GNU_REGEX
|
||||
{
|
||||
struct re_registers search_regs;
|
||||
pattern->not_bol = notbol;
|
||||
pattern->regs_allocated = REGS_UNALLOCATED;
|
||||
matched = re_search(pattern, line, line_len, 0, line_len, &search_regs) >= 0;
|
||||
if (matched)
|
||||
{
|
||||
*sp++ = line + search_regs.start[0];
|
||||
*ep++ = line + search_regs.end[0];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if HAVE_POSIX_REGCOMP
|
||||
{
|
||||
#define RM_COUNT (NUM_SEARCH_COLORS+2)
|
||||
regmatch_t rm[RM_COUNT];
|
||||
int flags = (notbol) ? REG_NOTBOL : 0;
|
||||
#ifdef REG_STARTEND
|
||||
flags |= REG_STARTEND;
|
||||
rm[0].rm_so = 0;
|
||||
rm[0].rm_eo = line_len;
|
||||
#endif
|
||||
matched = !regexec(pattern, line, RM_COUNT, rm, flags);
|
||||
if (matched)
|
||||
{
|
||||
int i;
|
||||
int ecount;
|
||||
for (ecount = RM_COUNT; ecount > 0; ecount--)
|
||||
if (rm[ecount-1].rm_so >= 0)
|
||||
break;
|
||||
if (ecount >= nsp)
|
||||
ecount = nsp-1;
|
||||
for (i = 0; i < ecount; i++)
|
||||
{
|
||||
if (rm[i].rm_so < 0)
|
||||
{
|
||||
*sp++ = *ep++ = line;
|
||||
} else
|
||||
{
|
||||
#ifndef __WATCOMC__
|
||||
*sp++ = line + rm[i].rm_so;
|
||||
*ep++ = line + rm[i].rm_eo;
|
||||
#else
|
||||
*sp++ = rm[i].rm_sp;
|
||||
*ep++ = rm[i].rm_ep;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if HAVE_PCRE
|
||||
{
|
||||
#define OVECTOR_COUNT ((3*NUM_SEARCH_COLORS)+3)
|
||||
int ovector[OVECTOR_COUNT];
|
||||
int flags = (notbol) ? PCRE_NOTBOL : 0;
|
||||
int i;
|
||||
int ecount;
|
||||
int mcount = pcre_exec(pattern, NULL, line, line_len,
|
||||
0, flags, ovector, OVECTOR_COUNT);
|
||||
matched = (mcount > 0);
|
||||
ecount = nsp-1;
|
||||
if (ecount > mcount) ecount = mcount;
|
||||
for (i = 0; i < ecount*2; )
|
||||
{
|
||||
if (ovector[i] < 0 || ovector[i+1] < 0)
|
||||
{
|
||||
*sp++ = *ep++ = line;
|
||||
i += 2;
|
||||
} else
|
||||
{
|
||||
*sp++ = line + ovector[i++];
|
||||
*ep++ = line + ovector[i++];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if HAVE_PCRE2
|
||||
{
|
||||
int flags = (notbol) ? PCRE2_NOTBOL : 0;
|
||||
pcre2_match_data *md = pcre2_match_data_create(nsp-1, NULL);
|
||||
int mcount = pcre2_match(pattern, (PCRE2_SPTR)line, line_len,
|
||||
0, flags, md, NULL);
|
||||
matched = (mcount > 0);
|
||||
if (matched)
|
||||
{
|
||||
PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(md);
|
||||
int i;
|
||||
int ecount = nsp-1;
|
||||
if (ecount > mcount) ecount = mcount;
|
||||
for (i = 0; i < ecount*2; )
|
||||
{
|
||||
if (ovector[i] < 0 || ovector[i+1] < 0)
|
||||
{
|
||||
*sp++ = *ep++ = line;
|
||||
i += 2;
|
||||
} else
|
||||
{
|
||||
*sp++ = line + ovector[i++];
|
||||
*ep++ = line + ovector[i++];
|
||||
}
|
||||
}
|
||||
}
|
||||
pcre2_match_data_free(md);
|
||||
}
|
||||
#endif
|
||||
#if HAVE_RE_COMP
|
||||
matched = (re_exec(line) == 1);
|
||||
/*
|
||||
* re_exec doesn't seem to provide a way to get the matched string.
|
||||
*/
|
||||
#endif
|
||||
#if HAVE_REGCMP
|
||||
matched = ((*ep++ = regex(pattern, line)) != NULL);
|
||||
if (matched)
|
||||
*sp++ = __loc1;
|
||||
#endif
|
||||
#if HAVE_V8_REGCOMP
|
||||
#if HAVE_REGEXEC2
|
||||
matched = regexec2(pattern, line, notbol);
|
||||
#else
|
||||
matched = regexec(pattern, line);
|
||||
#endif
|
||||
if (matched)
|
||||
{
|
||||
*sp++ = pattern->startp[0];
|
||||
*ep++ = pattern->endp[0];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
*sp = *ep = NULL;
|
||||
matched = (!(search_type & SRCH_NO_MATCH) && matched) ||
|
||||
((search_type & SRCH_NO_MATCH) && !matched);
|
||||
return (matched);
|
||||
}
|
||||
|
||||
public int match_pattern(PATTERN_TYPE pattern, char *tpattern, char *line, int line_len, char **sp, char **ep, int nsp, int notbol, int search_type)
|
||||
{
|
||||
int matched = match_pattern1(pattern, tpattern, line, line_len, sp, ep, nsp, notbol, search_type);
|
||||
int i;
|
||||
for (i = 1; i <= NUM_SEARCH_COLORS; i++)
|
||||
{
|
||||
if ((search_type & SRCH_SUBSEARCH(i)) && ep[i] == sp[i])
|
||||
matched = 0;
|
||||
}
|
||||
return matched;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the name of the pattern matching library.
|
||||
*/
|
||||
public char * pattern_lib_name(void)
|
||||
{
|
||||
#if HAVE_GNU_REGEX
|
||||
return ("GNU");
|
||||
#else
|
||||
#if HAVE_POSIX_REGCOMP
|
||||
return ("POSIX");
|
||||
#else
|
||||
#if HAVE_PCRE2
|
||||
return ("PCRE2");
|
||||
#else
|
||||
#if HAVE_PCRE
|
||||
return ("PCRE");
|
||||
#else
|
||||
#if HAVE_RE_COMP
|
||||
return ("BSD");
|
||||
#else
|
||||
#if HAVE_REGCMP
|
||||
return ("V8");
|
||||
#else
|
||||
#if HAVE_V8_REGCOMP
|
||||
return ("Spencer V8");
|
||||
#else
|
||||
return ("no");
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
80
third_party/less/pattern.h
vendored
Normal file
80
third_party/less/pattern.h
vendored
Normal file
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
#if HAVE_GNU_REGEX
|
||||
#define __USE_GNU 1
|
||||
#include <regex.h>
|
||||
#define PATTERN_TYPE struct re_pattern_buffer *
|
||||
#define SET_NULL_PATTERN(name) name = NULL
|
||||
#endif
|
||||
|
||||
/* ---- POSIX ---- */
|
||||
#if HAVE_POSIX_REGCOMP
|
||||
#include <regex.h>
|
||||
#ifdef REG_EXTENDED
|
||||
#define REGCOMP_FLAG REG_EXTENDED
|
||||
#else
|
||||
#define REGCOMP_FLAG 0
|
||||
#endif
|
||||
#define PATTERN_TYPE regex_t *
|
||||
#define SET_NULL_PATTERN(name) name = NULL
|
||||
#define re_handles_caseless TRUE
|
||||
#endif
|
||||
|
||||
/* ---- PCRE ---- */
|
||||
#if HAVE_PCRE
|
||||
#include <pcre.h>
|
||||
#define PATTERN_TYPE pcre *
|
||||
#define SET_NULL_PATTERN(name) name = NULL
|
||||
#define re_handles_caseless TRUE
|
||||
#endif
|
||||
|
||||
/* ---- PCRE2 ---- */
|
||||
#if HAVE_PCRE2
|
||||
#define PCRE2_CODE_UNIT_WIDTH 8
|
||||
#include "third_party/pcre/pcre2.h"
|
||||
#define PATTERN_TYPE pcre2_code *
|
||||
#define SET_NULL_PATTERN(name) name = NULL
|
||||
#define re_handles_caseless TRUE
|
||||
#endif
|
||||
|
||||
/* ---- RE_COMP ---- */
|
||||
#if HAVE_RE_COMP
|
||||
char *re_comp(char*);
|
||||
int re_exec(char*);
|
||||
#define PATTERN_TYPE int
|
||||
#define SET_NULL_PATTERN(name) name = 0
|
||||
#endif
|
||||
|
||||
/* ---- REGCMP ---- */
|
||||
#if HAVE_REGCMP
|
||||
char *regcmp(char*);
|
||||
char *regex(char**, char*);
|
||||
extern char *__loc1;
|
||||
#define PATTERN_TYPE char **
|
||||
#define SET_NULL_PATTERN(name) name = NULL
|
||||
#endif
|
||||
|
||||
/* ---- REGCOMP ---- */
|
||||
#if HAVE_V8_REGCOMP
|
||||
#include "regexp.h"
|
||||
extern int reg_show_error;
|
||||
#define PATTERN_TYPE struct regexp *
|
||||
#define SET_NULL_PATTERN(name) name = NULL
|
||||
#endif
|
||||
|
||||
/* ---- NONE ---- */
|
||||
#if NO_REGEX
|
||||
#define PATTERN_TYPE void *
|
||||
#define SET_NULL_PATTERN(name)
|
||||
#endif
|
||||
|
||||
#ifndef re_handles_caseless
|
||||
#define re_handles_caseless FALSE
|
||||
#endif
|
33
third_party/less/pckeys.h
vendored
Normal file
33
third_party/less/pckeys.h
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Definitions of keys on the PC.
|
||||
* 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'
|
238
third_party/less/position.c
vendored
Normal file
238
third_party/less/position.c
vendored
Normal file
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Routines dealing with the "position" table.
|
||||
* This is a table which tells the position (in the input file) of the
|
||||
* first char on each currently displayed line.
|
||||
*
|
||||
* {{ The position table is scrolled by moving all the entries.
|
||||
* Would be better to have a circular table
|
||||
* and just change a couple of pointers. }}
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
#include "position.h"
|
||||
|
||||
static POSITION *table = NULL; /* The position table */
|
||||
static int table_size = 0;
|
||||
|
||||
extern int sc_width, sc_height;
|
||||
extern int header_lines;
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
public POSITION position(int sindex)
|
||||
{
|
||||
switch (sindex)
|
||||
{
|
||||
case BOTTOM:
|
||||
sindex = sc_height - 2;
|
||||
break;
|
||||
case BOTTOM_PLUS_ONE:
|
||||
sindex = sc_height - 1;
|
||||
break;
|
||||
case MIDDLE:
|
||||
sindex = (sc_height - 1) / 2;
|
||||
break;
|
||||
}
|
||||
return (table[sindex]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a new file position to the bottom of the position table.
|
||||
*/
|
||||
public void add_forw_pos(POSITION pos)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Scroll the position table up.
|
||||
*/
|
||||
for (i = 1; i < sc_height; i++)
|
||||
table[i-1] = table[i];
|
||||
table[sc_height - 1] = pos;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a new file position to the top of the position table.
|
||||
*/
|
||||
public void add_back_pos(POSITION pos)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Scroll the position table down.
|
||||
*/
|
||||
for (i = sc_height - 1; i > 0; i--)
|
||||
table[i] = table[i-1];
|
||||
table[0] = pos;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the position table, done whenever we clear the screen.
|
||||
*/
|
||||
public void pos_clear(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sc_height; i++)
|
||||
table[i] = NULL_POSITION;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate or reallocate the position table.
|
||||
*/
|
||||
public void pos_init(void)
|
||||
{
|
||||
struct scrpos scrpos;
|
||||
|
||||
if (sc_height <= table_size)
|
||||
return;
|
||||
/*
|
||||
* If we already have a table, remember the first line in it
|
||||
* before we free it, so we can copy that line to the new table.
|
||||
*/
|
||||
if (table != NULL)
|
||||
{
|
||||
get_scrpos(&scrpos, TOP);
|
||||
free((char*)table);
|
||||
} else
|
||||
scrpos.pos = NULL_POSITION;
|
||||
table = (POSITION *) ecalloc(sc_height, sizeof(POSITION));
|
||||
table_size = sc_height;
|
||||
pos_clear();
|
||||
if (scrpos.pos != NULL_POSITION)
|
||||
table[scrpos.ln-1] = scrpos.pos;
|
||||
}
|
||||
|
||||
/*
|
||||
* See if the byte at a specified position is currently on the screen.
|
||||
* Check the position table to see if the position falls within its range.
|
||||
* Return the position table entry if found, -1 if not.
|
||||
*/
|
||||
public int onscreen(POSITION pos)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (pos < table[0])
|
||||
return (-1);
|
||||
for (i = 1; i < sc_height; i++)
|
||||
if (pos < table[i])
|
||||
return (i-1);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* See if the entire screen is empty.
|
||||
*/
|
||||
public int empty_screen(void)
|
||||
{
|
||||
return (empty_lines(0, sc_height-1));
|
||||
}
|
||||
|
||||
public int empty_lines(int s, int e)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = s; i <= e; i++)
|
||||
if (table[i] != NULL_POSITION && table[i] != 0)
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current screen position.
|
||||
* The screen position consists of both a file position and
|
||||
* a screen line number where the file position is placed on the screen.
|
||||
* Normally the screen line number is 0, but if we are positioned
|
||||
* such that the top few lines are empty, we may have to set
|
||||
* the screen line to a number > 0.
|
||||
*/
|
||||
public void get_scrpos(struct scrpos *scrpos, int where)
|
||||
{
|
||||
int i;
|
||||
int dir;
|
||||
int last;
|
||||
|
||||
switch (where)
|
||||
{
|
||||
case TOP:
|
||||
i = 0; dir = +1; last = sc_height-2;
|
||||
break;
|
||||
case BOTTOM: case BOTTOM_PLUS_ONE:
|
||||
i = sc_height-2; dir = -1; last = 0;
|
||||
break;
|
||||
default:
|
||||
i = where;
|
||||
if (table[i] == NULL_POSITION) {
|
||||
scrpos->pos = NULL_POSITION;
|
||||
return;
|
||||
}
|
||||
/* Values of dir and last don't matter after this. */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the first line on the screen which has something on it,
|
||||
* and return the screen line number and the file position.
|
||||
*/
|
||||
for (;; i += dir)
|
||||
{
|
||||
if (table[i] != NULL_POSITION)
|
||||
{
|
||||
scrpos->ln = i+1;
|
||||
scrpos->pos = table[i];
|
||||
return;
|
||||
}
|
||||
if (i == last) break;
|
||||
}
|
||||
/*
|
||||
* The screen is empty.
|
||||
*/
|
||||
scrpos->pos = NULL_POSITION;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust a screen line number to be a simple positive integer
|
||||
* in the range { 0 .. sc_height-2 }.
|
||||
* (The bottom line, sc_height-1, is reserved for prompts, etc.)
|
||||
* The given "sline" may be in the range { 1 .. sc_height-1 }
|
||||
* to refer to lines relative to the top of the screen (starting from 1),
|
||||
* or it may be in { -1 .. -(sc_height-1) } to refer to lines
|
||||
* relative to the bottom of the screen.
|
||||
*/
|
||||
public int sindex_from_sline(int sline)
|
||||
{
|
||||
/*
|
||||
* Negative screen line number means
|
||||
* relative to the bottom of the screen.
|
||||
*/
|
||||
if (sline < 0)
|
||||
sline += sc_height;
|
||||
/*
|
||||
* Can't be less than 1 or greater than sc_height.
|
||||
*/
|
||||
if (sline <= 0)
|
||||
sline = 1;
|
||||
if (sline > sc_height)
|
||||
sline = sc_height;
|
||||
/*
|
||||
* Return zero-based line number, not one-based.
|
||||
*/
|
||||
return (sline-1);
|
||||
}
|
18
third_party/less/position.h
vendored
Normal file
18
third_party/less/position.h
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Include 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)
|
556
third_party/less/prompt.c
vendored
Normal file
556
third_party/less/prompt.c
vendored
Normal file
|
@ -0,0 +1,556 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Prompting and other messages.
|
||||
* There are three flavors of prompts, SHORT, MEDIUM and LONG,
|
||||
* selected by the -m/-M options.
|
||||
* There is also the "equals message", printed by the = command.
|
||||
* A prompt is a message composed of various pieces, such as the
|
||||
* name of the file being viewed, the percentage into the file, etc.
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
#include "position.h"
|
||||
|
||||
extern int pr_type;
|
||||
extern int new_file;
|
||||
extern int sc_width;
|
||||
extern int so_s_width, so_e_width;
|
||||
extern int linenums;
|
||||
extern int hshift;
|
||||
extern int sc_height;
|
||||
extern int jump_sline;
|
||||
extern int less_is_more;
|
||||
extern int header_lines;
|
||||
extern IFILE curr_ifile;
|
||||
#if EDITOR
|
||||
extern char *editor;
|
||||
extern char *editproto;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Prototypes for the three flavors of prompts.
|
||||
* These strings are expanded by pr_expand().
|
||||
*/
|
||||
static constant char s_proto[] =
|
||||
"?n?f%f .?m(%T %i of %m) ..?e(END) ?x- Next\\: %x..%t";
|
||||
static constant char m_proto[] =
|
||||
"?n?f%f .?m(%T %i of %m) ..?e(END) ?x- Next\\: %x.:?pB%pB\\%:byte %bB?s/%s...%t";
|
||||
static constant char M_proto[] =
|
||||
"?f%f .?n?m(%T %i of %m) ..?ltlines %lt-%lb?L/%L. :byte %bB?s/%s. .?e(END) ?x- Next\\: %x.:?pB%pB\\%..%t";
|
||||
static constant char e_proto[] =
|
||||
"?f%f .?m(%T %i of %m) .?ltlines %lt-%lb?L/%L. .byte %bB?s/%s. ?e(END) :?pB%pB\\%..%t";
|
||||
static constant char h_proto[] =
|
||||
"HELP -- ?eEND -- Press g to see it again:Press RETURN for more., or q when done";
|
||||
static constant char w_proto[] =
|
||||
"Waiting for data";
|
||||
static constant char more_proto[] =
|
||||
"--More--(?eEND ?x- Next\\: %x.:?pB%pB\\%:byte %bB?s/%s...%t)";
|
||||
|
||||
public char *prproto[3];
|
||||
public char constant *eqproto = e_proto;
|
||||
public char constant *hproto = h_proto;
|
||||
public char constant *wproto = w_proto;
|
||||
|
||||
static char message[PROMPT_SIZE];
|
||||
static char *mp;
|
||||
|
||||
/*
|
||||
* Initialize the prompt prototype strings.
|
||||
*/
|
||||
public void init_prompt(void)
|
||||
{
|
||||
prproto[0] = save(s_proto);
|
||||
prproto[1] = save(less_is_more ? more_proto : m_proto);
|
||||
prproto[2] = save(M_proto);
|
||||
eqproto = save(e_proto);
|
||||
hproto = save(h_proto);
|
||||
wproto = save(w_proto);
|
||||
}
|
||||
|
||||
/*
|
||||
* Append a string to the end of the message.
|
||||
*/
|
||||
static void ap_str(char *s)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = (int) strlen(s);
|
||||
if (mp + len >= message + PROMPT_SIZE)
|
||||
len = (int) (message + PROMPT_SIZE - mp - 1);
|
||||
strncpy(mp, s, len);
|
||||
mp += len;
|
||||
*mp = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* Append a character to the end of the message.
|
||||
*/
|
||||
static void ap_char(char c)
|
||||
{
|
||||
char buf[2];
|
||||
|
||||
buf[0] = c;
|
||||
buf[1] = '\0';
|
||||
ap_str(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Append a POSITION (as a decimal integer) to the end of the message.
|
||||
*/
|
||||
static void ap_pos(POSITION pos)
|
||||
{
|
||||
char buf[INT_STRLEN_BOUND(pos) + 2];
|
||||
|
||||
postoa(pos, buf, 10);
|
||||
ap_str(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Append a line number to the end of the message.
|
||||
*/
|
||||
static void ap_linenum(LINENUM linenum)
|
||||
{
|
||||
char buf[INT_STRLEN_BOUND(linenum) + 2];
|
||||
|
||||
linenumtoa(linenum, buf, 10);
|
||||
ap_str(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Append an integer to the end of the message.
|
||||
*/
|
||||
static void ap_int(int num)
|
||||
{
|
||||
char buf[INT_STRLEN_BOUND(num) + 2];
|
||||
|
||||
inttoa(num, buf, 10);
|
||||
ap_str(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Append a question mark to the end of the message.
|
||||
*/
|
||||
static void ap_quest(void)
|
||||
{
|
||||
ap_str("?");
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the "current" byte offset in the file.
|
||||
*/
|
||||
static POSITION curr_byte(int where)
|
||||
{
|
||||
POSITION pos;
|
||||
|
||||
pos = position(where);
|
||||
while (pos == NULL_POSITION && where >= 0 && where < sc_height-1)
|
||||
pos = position(++where);
|
||||
if (pos == NULL_POSITION)
|
||||
pos = ch_length();
|
||||
return (pos);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the value of a prototype conditional.
|
||||
* A prototype string may include conditionals which consist of a
|
||||
* question mark followed by a single letter.
|
||||
* Here we decode that letter and return the appropriate boolean value.
|
||||
*/
|
||||
static int cond(char c, int where)
|
||||
{
|
||||
POSITION len;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 'a': /* Anything in the message yet? */
|
||||
return (mp > message);
|
||||
case 'b': /* Current byte offset known? */
|
||||
return (curr_byte(where) != NULL_POSITION);
|
||||
case 'c':
|
||||
return (hshift != 0);
|
||||
case 'e': /* At end of file? */
|
||||
return (eof_displayed());
|
||||
case 'f': /* Filename known? */
|
||||
case 'g':
|
||||
return (strcmp(get_filename(curr_ifile), "-") != 0);
|
||||
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? */
|
||||
return (linenums && ch_length() != NULL_POSITION);
|
||||
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? */
|
||||
#if TAGS
|
||||
return (ntags() ? 1 : new_file);
|
||||
#else
|
||||
return (new_file);
|
||||
#endif
|
||||
case 'p': /* Percent into file (bytes) known? */
|
||||
return (curr_byte(where) != NULL_POSITION &&
|
||||
ch_length() > 0);
|
||||
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 'B':
|
||||
return (ch_length() != NULL_POSITION);
|
||||
case 'x': /* Is there a "next" file? */
|
||||
#if TAGS
|
||||
if (ntags())
|
||||
return (0);
|
||||
#endif
|
||||
return (next_ifile(curr_ifile) != NULL_IFILE);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode a "percent" prototype character.
|
||||
* A prototype string may include various "percent" escapes;
|
||||
* that is, a percent sign followed by a single letter.
|
||||
* Here we decode that letter and take the appropriate action,
|
||||
* usually by appending something to the message being built.
|
||||
*/
|
||||
static void protochar(int c, int where, int iseditproto)
|
||||
{
|
||||
POSITION pos;
|
||||
POSITION len;
|
||||
int n;
|
||||
LINENUM linenum;
|
||||
LINENUM last_linenum;
|
||||
IFILE h;
|
||||
char *s;
|
||||
|
||||
#undef PAGE_NUM
|
||||
#define PAGE_NUM(linenum) ((((linenum) - 1) / (sc_height - header_lines - 1)) + 1)
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 'b': /* Current byte offset */
|
||||
pos = curr_byte(where);
|
||||
if (pos != NULL_POSITION)
|
||||
ap_pos(pos);
|
||||
else
|
||||
ap_quest();
|
||||
break;
|
||||
case 'c':
|
||||
ap_int(hshift);
|
||||
break;
|
||||
case 'd': /* Current page number */
|
||||
linenum = currline(where);
|
||||
if (linenum > 0 && sc_height > header_lines + 1)
|
||||
ap_linenum(PAGE_NUM(linenum));
|
||||
else
|
||||
ap_quest();
|
||||
break;
|
||||
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)
|
||||
ap_quest();
|
||||
else if (len == 0)
|
||||
/* An empty file has no pages. */
|
||||
ap_linenum(0);
|
||||
else
|
||||
{
|
||||
linenum = find_linenum(len - 1);
|
||||
if (linenum <= 0)
|
||||
ap_quest();
|
||||
else
|
||||
ap_linenum(PAGE_NUM(linenum));
|
||||
}
|
||||
break;
|
||||
#if EDITOR
|
||||
case 'E': /* Editor name */
|
||||
ap_str(editor);
|
||||
break;
|
||||
#endif
|
||||
case 'f': /* File name */
|
||||
ap_str(get_filename(curr_ifile));
|
||||
break;
|
||||
case 'F': /* Last component of file name */
|
||||
ap_str(last_component(get_filename(curr_ifile)));
|
||||
break;
|
||||
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 */
|
||||
#if TAGS
|
||||
if (ntags())
|
||||
ap_int(curr_tag());
|
||||
else
|
||||
#endif
|
||||
ap_int(get_index(curr_ifile));
|
||||
break;
|
||||
case 'l': /* Current line number */
|
||||
linenum = currline(where);
|
||||
if (linenum != 0)
|
||||
ap_linenum(vlinenum(linenum));
|
||||
else
|
||||
ap_quest();
|
||||
break;
|
||||
case 'L': /* Final line number */
|
||||
len = ch_length();
|
||||
if (len == NULL_POSITION || len == ch_zero() ||
|
||||
(linenum = find_linenum(len)) <= 0)
|
||||
ap_quest();
|
||||
else
|
||||
ap_linenum(vlinenum(linenum-1));
|
||||
break;
|
||||
case 'm': /* Number of files */
|
||||
#if TAGS
|
||||
n = ntags();
|
||||
if (n)
|
||||
ap_int(n);
|
||||
else
|
||||
#endif
|
||||
ap_int(nifile());
|
||||
break;
|
||||
case 'p': /* Percent into file (bytes) */
|
||||
pos = curr_byte(where);
|
||||
len = ch_length();
|
||||
if (pos != NULL_POSITION && len > 0)
|
||||
ap_int(percentage(pos,len));
|
||||
else
|
||||
ap_quest();
|
||||
break;
|
||||
case 'P': /* Percent into file (lines) */
|
||||
linenum = currline(where);
|
||||
if (linenum == 0 ||
|
||||
(len = ch_length()) == NULL_POSITION || len == ch_zero() ||
|
||||
(last_linenum = find_linenum(len)) <= 0)
|
||||
ap_quest();
|
||||
else
|
||||
ap_int(percentage(linenum, last_linenum));
|
||||
break;
|
||||
case 's': /* Size of file */
|
||||
case 'B':
|
||||
len = ch_length();
|
||||
if (len != NULL_POSITION)
|
||||
ap_pos(len);
|
||||
else
|
||||
ap_quest();
|
||||
break;
|
||||
case 't': /* Truncate trailing spaces in the message */
|
||||
while (mp > message && mp[-1] == ' ')
|
||||
mp--;
|
||||
*mp = '\0';
|
||||
break;
|
||||
case 'T': /* Type of list */
|
||||
#if TAGS
|
||||
if (ntags())
|
||||
ap_str("tag");
|
||||
else
|
||||
#endif
|
||||
ap_str("file");
|
||||
break;
|
||||
case 'x': /* Name of next file */
|
||||
h = next_ifile(curr_ifile);
|
||||
if (h != NULL_IFILE)
|
||||
ap_str(get_filename(h));
|
||||
else
|
||||
ap_quest();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip a false conditional.
|
||||
* When a false condition is found (either a false IF or the ELSE part
|
||||
* of a true IF), this routine scans the prototype string to decide
|
||||
* where to resume parsing the string.
|
||||
* We must keep track of nested IFs and skip them properly.
|
||||
*/
|
||||
static constant char * skipcond(constant char *p)
|
||||
{
|
||||
int iflevel;
|
||||
|
||||
/*
|
||||
* We came in here after processing a ? or :,
|
||||
* so we start nested one level deep.
|
||||
*/
|
||||
iflevel = 1;
|
||||
|
||||
for (;;) switch (*++p)
|
||||
{
|
||||
case '?':
|
||||
/*
|
||||
* Start of a nested IF.
|
||||
*/
|
||||
iflevel++;
|
||||
break;
|
||||
case ':':
|
||||
/*
|
||||
* Else.
|
||||
* If this matches the IF we came in here with,
|
||||
* then we're done.
|
||||
*/
|
||||
if (iflevel == 1)
|
||||
return (p);
|
||||
break;
|
||||
case '.':
|
||||
/*
|
||||
* Endif.
|
||||
* If this matches the IF we came in here with,
|
||||
* then we're done.
|
||||
*/
|
||||
if (--iflevel == 0)
|
||||
return (p);
|
||||
break;
|
||||
case '\\':
|
||||
/*
|
||||
* Backslash escapes the next character.
|
||||
*/
|
||||
if (p[1] != '\0')
|
||||
++p;
|
||||
break;
|
||||
case '\0':
|
||||
/*
|
||||
* Whoops. Hit end of string.
|
||||
* This is a malformed conditional, but just treat it
|
||||
* as if all active conditionals ends here.
|
||||
*/
|
||||
return (p-1);
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode a char that represents a position on the screen.
|
||||
*/
|
||||
static constant char * wherechar(char constant *p, int *wp)
|
||||
{
|
||||
switch (*p)
|
||||
{
|
||||
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 'j': *wp = sindex_from_sline(jump_sline); break;
|
||||
default: *wp = TOP; p--; break;
|
||||
}
|
||||
}
|
||||
return (p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct a message based on a prototype string.
|
||||
*/
|
||||
public char * pr_expand(constant char *proto)
|
||||
{
|
||||
constant char *p;
|
||||
int c;
|
||||
int where;
|
||||
|
||||
mp = message;
|
||||
|
||||
if (*proto == '\0')
|
||||
return ("");
|
||||
|
||||
for (p = proto; *p != '\0'; p++)
|
||||
{
|
||||
switch (*p)
|
||||
{
|
||||
default: /* Just put the character in the message */
|
||||
ap_char(*p);
|
||||
break;
|
||||
case '\\': /* Backslash escapes the next character */
|
||||
if (p[1] != '\0')
|
||||
ap_char(*++p);
|
||||
break;
|
||||
case '?': /* Conditional (IF) */
|
||||
if ((c = *++p) == '\0')
|
||||
--p;
|
||||
else
|
||||
{
|
||||
where = 0;
|
||||
p = wherechar(p, &where);
|
||||
if (!cond(c, where))
|
||||
p = skipcond(p);
|
||||
}
|
||||
break;
|
||||
case ':': /* ELSE */
|
||||
p = skipcond(p);
|
||||
break;
|
||||
case '.': /* ENDIF */
|
||||
break;
|
||||
case '%': /* Percent escape */
|
||||
if ((c = *++p) == '\0')
|
||||
--p;
|
||||
else
|
||||
{
|
||||
where = 0;
|
||||
p = wherechar(p, &where);
|
||||
protochar(c, where,
|
||||
#if EDITOR
|
||||
(proto == editproto));
|
||||
#else
|
||||
0);
|
||||
#endif
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mp == message)
|
||||
return ("");
|
||||
return (message);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a message suitable for printing by the "=" command.
|
||||
*/
|
||||
public char * eq_message(void)
|
||||
{
|
||||
return (pr_expand(eqproto));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a prompt.
|
||||
* This depends on the prompt type (SHORT, MEDIUM, LONG), etc.
|
||||
* If we can't come up with an appropriate prompt, return NULL
|
||||
* and the caller will prompt with a colon.
|
||||
*/
|
||||
public char * pr_string(void)
|
||||
{
|
||||
char *prompt;
|
||||
int type;
|
||||
|
||||
type = (!less_is_more) ? pr_type : pr_type ? 0 : 1;
|
||||
prompt = pr_expand((ch_getflags() & CH_HELPFILE) ?
|
||||
hproto : prproto[type]);
|
||||
new_file = 0;
|
||||
return (prompt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a message suitable for printing while waiting in the F command.
|
||||
*/
|
||||
public char * wait_message(void)
|
||||
{
|
||||
return (pr_expand(wproto));
|
||||
}
|
34
third_party/less/regexp.h
vendored
Normal file
34
third_party/less/regexp.h
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Definitions etc. for regexp(3) routines.
|
||||
*
|
||||
* Caveat: this is V8 regexp(3) [actually, a reimplementation thereof],
|
||||
* not the System V one.
|
||||
*/
|
||||
|
||||
#ifndef _REGEXP
|
||||
#define _REGEXP 1
|
||||
|
||||
#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. */
|
||||
} regexp;
|
||||
|
||||
#if defined(__STDC__) || defined(__cplusplus)
|
||||
# define _ANSI_ARGS_(x) x
|
||||
#else
|
||||
# define _ANSI_ARGS_(x) ()
|
||||
#endif
|
||||
|
||||
extern regexp *regcomp _ANSI_ARGS_((char *exp));
|
||||
extern int regexec _ANSI_ARGS_((regexp *prog, char *string));
|
||||
extern int regexec2 _ANSI_ARGS_((regexp *prog, char *string, int notbol));
|
||||
extern void regsub _ANSI_ARGS_((regexp *prog, char *source, char *dest));
|
||||
extern void regerror _ANSI_ARGS_((char *msg));
|
||||
|
||||
#endif /* REGEXP */
|
3018
third_party/less/screen.c
vendored
Normal file
3018
third_party/less/screen.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
1868
third_party/less/search.c
vendored
Normal file
1868
third_party/less/search.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
261
third_party/less/signal.c
vendored
Normal file
261
third_party/less/signal.c
vendored
Normal file
|
@ -0,0 +1,261 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Routines dealing with signals.
|
||||
*
|
||||
* A signal usually merely causes a bit to be set in the "signals" word.
|
||||
* At some convenient time, the mainline code checks to see if any
|
||||
* signals need processing by calling psignal().
|
||||
* If we happen to be reading from a file [in iread()] at the time
|
||||
* the signal is received, we call intread to interrupt the iread.
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
#include <signal.h>
|
||||
|
||||
/*
|
||||
* "sigs" contains bits indicating signals which need to be processed.
|
||||
*/
|
||||
public int sigs;
|
||||
|
||||
extern int sc_width, sc_height;
|
||||
extern int screen_trashed;
|
||||
extern int lnloop;
|
||||
extern int linenums;
|
||||
extern int wscroll;
|
||||
extern int reading;
|
||||
extern int quit_on_intr;
|
||||
extern int secure;
|
||||
extern long jump_sline_fraction;
|
||||
|
||||
/*
|
||||
* Interrupt signal handler.
|
||||
*/
|
||||
#if MSDOS_COMPILER!=WIN32C
|
||||
/* ARGSUSED*/
|
||||
static RETSIGTYPE u_interrupt(int type)
|
||||
{
|
||||
bell();
|
||||
#if OS2
|
||||
LSIGNAL(SIGINT, SIG_ACK);
|
||||
#endif
|
||||
LSIGNAL(SIGINT, u_interrupt);
|
||||
sigs |= S_INTERRUPT;
|
||||
#if MSDOS_COMPILER==DJGPPC
|
||||
/*
|
||||
* If a keyboard has been hit, it must be Ctrl-C
|
||||
* (as opposed to Ctrl-Break), so consume it.
|
||||
* (Otherwise, Less will beep when it sees Ctrl-C from keyboard.)
|
||||
*/
|
||||
if (kbhit())
|
||||
getkey();
|
||||
#endif
|
||||
#if HILITE_SEARCH
|
||||
set_filter_pattern(NULL, 0);
|
||||
#endif
|
||||
if (reading)
|
||||
intread(); /* May longjmp */
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SIGTSTP
|
||||
/*
|
||||
* "Stop" (^Z) signal handler.
|
||||
*/
|
||||
/* ARGSUSED*/
|
||||
static RETSIGTYPE stop(int type)
|
||||
{
|
||||
LSIGNAL(SIGTSTP, stop);
|
||||
sigs |= S_STOP;
|
||||
if (reading)
|
||||
intread();
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef SIG_LESSWINDOW
|
||||
#ifdef SIGWINCH
|
||||
#define SIG_LESSWINDOW SIGWINCH
|
||||
#else
|
||||
#ifdef SIGWIND
|
||||
#define SIG_LESSWINDOW SIGWIND
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef SIG_LESSWINDOW
|
||||
/*
|
||||
* "Window" change handler
|
||||
*/
|
||||
/* ARGSUSED*/
|
||||
public RETSIGTYPE winch(int type)
|
||||
{
|
||||
LSIGNAL(SIG_LESSWINDOW, winch);
|
||||
sigs |= S_WINCH;
|
||||
if (reading)
|
||||
intread();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
/*
|
||||
* Handle CTRL-C and CTRL-BREAK keys.
|
||||
*/
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
/* #include <windows.h> */
|
||||
|
||||
static BOOL WINAPI wbreak_handler(DWORD dwCtrlType)
|
||||
{
|
||||
switch (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;
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
#endif
|
||||
|
||||
static RETSIGTYPE terminate(int type)
|
||||
{
|
||||
quit(15);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the signal handlers.
|
||||
*/
|
||||
public void init_signals(int on)
|
||||
{
|
||||
if (on)
|
||||
{
|
||||
/*
|
||||
* Set signal handlers.
|
||||
*/
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
SetConsoleCtrlHandler(wbreak_handler, TRUE);
|
||||
#else
|
||||
(void) LSIGNAL(SIGINT, u_interrupt);
|
||||
#endif
|
||||
#ifdef SIGTSTP
|
||||
(void) LSIGNAL(SIGTSTP, secure ? SIG_IGN : stop);
|
||||
#endif
|
||||
#ifdef SIGWINCH
|
||||
(void) LSIGNAL(SIGWINCH, winch);
|
||||
#endif
|
||||
#ifdef SIGWIND
|
||||
(void) LSIGNAL(SIGWIND, winch);
|
||||
#endif
|
||||
#ifdef SIGQUIT
|
||||
(void) LSIGNAL(SIGQUIT, SIG_IGN);
|
||||
#endif
|
||||
#ifdef SIGTERM
|
||||
(void) LSIGNAL(SIGTERM, terminate);
|
||||
#endif
|
||||
} else
|
||||
{
|
||||
/*
|
||||
* Restore signals to defaults.
|
||||
*/
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
SetConsoleCtrlHandler(wbreak_handler, FALSE);
|
||||
#else
|
||||
(void) LSIGNAL(SIGINT, SIG_DFL);
|
||||
#endif
|
||||
#ifdef SIGTSTP
|
||||
(void) LSIGNAL(SIGTSTP, SIG_DFL);
|
||||
#endif
|
||||
#ifdef SIGWINCH
|
||||
(void) LSIGNAL(SIGWINCH, SIG_IGN);
|
||||
#endif
|
||||
#ifdef SIGWIND
|
||||
(void) LSIGNAL(SIGWIND, SIG_IGN);
|
||||
#endif
|
||||
#ifdef SIGQUIT
|
||||
(void) LSIGNAL(SIGQUIT, SIG_DFL);
|
||||
#endif
|
||||
#ifdef SIGTERM
|
||||
(void) LSIGNAL(SIGTERM, SIG_DFL);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Process any signals we have received.
|
||||
* A received signal cause a bit to be set in "sigs".
|
||||
*/
|
||||
public void psignals(void)
|
||||
{
|
||||
int tsignals;
|
||||
|
||||
if ((tsignals = sigs) == 0)
|
||||
return;
|
||||
sigs = 0;
|
||||
|
||||
#ifdef SIGTSTP
|
||||
if (tsignals & S_STOP)
|
||||
{
|
||||
/*
|
||||
* Clean up the terminal.
|
||||
*/
|
||||
#ifdef SIGTTOU
|
||||
LSIGNAL(SIGTTOU, SIG_IGN);
|
||||
#endif
|
||||
clear_bot();
|
||||
deinit();
|
||||
flush();
|
||||
raw_mode(0);
|
||||
#ifdef SIGTTOU
|
||||
LSIGNAL(SIGTTOU, SIG_DFL);
|
||||
#endif
|
||||
LSIGNAL(SIGTSTP, SIG_DFL);
|
||||
kill(getpid(), SIGTSTP);
|
||||
/*
|
||||
* ... Bye bye. ...
|
||||
* Hopefully we'll be back later and resume here...
|
||||
* Reset the terminal and arrange to repaint the
|
||||
* screen when we get back to the main command loop.
|
||||
*/
|
||||
LSIGNAL(SIGTSTP, stop);
|
||||
raw_mode(1);
|
||||
init();
|
||||
screen_trashed = 1;
|
||||
tsignals |= S_WINCH;
|
||||
}
|
||||
#endif
|
||||
#ifdef S_WINCH
|
||||
if (tsignals & S_WINCH)
|
||||
{
|
||||
int old_width, old_height;
|
||||
/*
|
||||
* Re-execute scrsize() to read the new window size.
|
||||
*/
|
||||
old_width = sc_width;
|
||||
old_height = sc_height;
|
||||
get_term();
|
||||
if (sc_width != old_width || sc_height != old_height)
|
||||
{
|
||||
wscroll = (sc_height + 1) / 2;
|
||||
calc_jump_sline();
|
||||
calc_shift_count();
|
||||
}
|
||||
screen_trashed = 1;
|
||||
}
|
||||
#endif
|
||||
if (tsignals & S_INTERRUPT)
|
||||
{
|
||||
if (quit_on_intr)
|
||||
quit(QUIT_INTERRUPT);
|
||||
}
|
||||
}
|
758
third_party/less/tags.c
vendored
Normal file
758
third_party/less/tags.c
vendored
Normal file
|
@ -0,0 +1,758 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
#include "less.h"
|
||||
|
||||
#define WHITESP(c) ((c)==' ' || (c)=='\t')
|
||||
|
||||
#if TAGS
|
||||
|
||||
public char ztags[] = "tags";
|
||||
public char *tags = ztags;
|
||||
|
||||
static int total;
|
||||
static int curseq;
|
||||
|
||||
extern int linenums;
|
||||
extern int sigs;
|
||||
extern int ctldisp;
|
||||
|
||||
enum tag_result {
|
||||
TAG_FOUND,
|
||||
TAG_NOFILE,
|
||||
TAG_NOTAG,
|
||||
TAG_NOTYPE,
|
||||
TAG_INTR
|
||||
};
|
||||
|
||||
/*
|
||||
* 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) */
|
||||
};
|
||||
|
||||
static enum tag_result findctag(char *tag);
|
||||
static enum tag_result findgtag(char *tag, int type);
|
||||
static char *nextgtag(void);
|
||||
static char *prevgtag(void);
|
||||
static POSITION ctagsearch(void);
|
||||
static POSITION gtagsearch(void);
|
||||
static int getentry(char *buf, char **tag, char **file, char **line);
|
||||
|
||||
/*
|
||||
* The list of tags generated by the last findgtag() call.
|
||||
*
|
||||
* Use either pattern or line number.
|
||||
* findgtag() always uses line number, so pattern is always NULL.
|
||||
* findctag() uses either pattern (in which case line number is 0),
|
||||
* or line number (in which case pattern is NULL).
|
||||
*/
|
||||
struct taglist {
|
||||
struct tag *tl_first;
|
||||
struct tag *tl_last;
|
||||
};
|
||||
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 '$' */
|
||||
};
|
||||
#define TAG_END ((struct tag *) &taglist)
|
||||
static struct taglist taglist = { TAG_END, TAG_END };
|
||||
static struct tag *curtag;
|
||||
|
||||
#define TAG_INS(tp) \
|
||||
(tp)->next = TAG_END; \
|
||||
(tp)->prev = taglist.tl_last; \
|
||||
taglist.tl_last->next = (tp); \
|
||||
taglist.tl_last = (tp);
|
||||
|
||||
#define TAG_RM(tp) \
|
||||
(tp)->next->prev = (tp)->prev; \
|
||||
(tp)->prev->next = (tp)->next;
|
||||
|
||||
/*
|
||||
* Delete tag structures.
|
||||
*/
|
||||
public void cleantags(void)
|
||||
{
|
||||
struct tag *tp;
|
||||
|
||||
/*
|
||||
* Delete any existing tag list.
|
||||
* {{ Ideally, we wouldn't do this until after we know that we
|
||||
* can load some other tag information. }}
|
||||
*/
|
||||
while ((tp = taglist.tl_first) != TAG_END)
|
||||
{
|
||||
TAG_RM(tp);
|
||||
free(tp->tag_file);
|
||||
free(tp->tag_pattern);
|
||||
free(tp);
|
||||
}
|
||||
curtag = NULL;
|
||||
total = curseq = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new tag entry.
|
||||
*/
|
||||
static struct tag * maketagent(char *name, char *file, LINENUM linenum, char *pattern, int endline)
|
||||
{
|
||||
struct tag *tp;
|
||||
|
||||
tp = (struct tag *) ecalloc(sizeof(struct tag), 1);
|
||||
tp->tag_file = (char *) ecalloc(strlen(file) + 1, sizeof(char));
|
||||
strcpy(tp->tag_file, file);
|
||||
tp->tag_linenum = linenum;
|
||||
tp->tag_endline = endline;
|
||||
if (pattern == NULL)
|
||||
tp->tag_pattern = NULL;
|
||||
else
|
||||
{
|
||||
tp->tag_pattern = (char *) ecalloc(strlen(pattern) + 1, sizeof(char));
|
||||
strcpy(tp->tag_pattern, pattern);
|
||||
}
|
||||
return (tp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get tag mode.
|
||||
*/
|
||||
public int gettagtype(void)
|
||||
{
|
||||
int f;
|
||||
|
||||
if (strcmp(tags, "GTAGS") == 0)
|
||||
return T_GTAGS;
|
||||
if (strcmp(tags, "GRTAGS") == 0)
|
||||
return T_GRTAGS;
|
||||
if (strcmp(tags, "GSYMS") == 0)
|
||||
return T_GSYMS;
|
||||
if (strcmp(tags, "GPATH") == 0)
|
||||
return T_GPATH;
|
||||
if (strcmp(tags, "-") == 0)
|
||||
return T_CTAGS_X;
|
||||
f = open(tags, OPEN_READ);
|
||||
if (f >= 0)
|
||||
{
|
||||
close(f);
|
||||
return T_CTAGS;
|
||||
}
|
||||
return T_GTAGS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find tags in tag file.
|
||||
* Find a tag in the "tags" file.
|
||||
* Sets "tag_file" to the name of the file containing the tag,
|
||||
* and "tagpattern" to the search pattern which should be used
|
||||
* to find the tag.
|
||||
*/
|
||||
public void findtag(char *tag)
|
||||
{
|
||||
int type = gettagtype();
|
||||
enum tag_result result;
|
||||
|
||||
if (type == T_CTAGS)
|
||||
result = findctag(tag);
|
||||
else
|
||||
result = findgtag(tag, type);
|
||||
switch (result)
|
||||
{
|
||||
case TAG_FOUND:
|
||||
case TAG_INTR:
|
||||
break;
|
||||
case TAG_NOFILE:
|
||||
error("No tags file", NULL_PARG);
|
||||
break;
|
||||
case TAG_NOTAG:
|
||||
error("No such tag in tags file", NULL_PARG);
|
||||
break;
|
||||
case TAG_NOTYPE:
|
||||
error("unknown tag type", NULL_PARG);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Search for a tag.
|
||||
*/
|
||||
public POSITION tagsearch(void)
|
||||
{
|
||||
if (curtag == NULL)
|
||||
return (NULL_POSITION); /* No gtags loaded! */
|
||||
if (curtag->tag_linenum != 0)
|
||||
return gtagsearch();
|
||||
else
|
||||
return ctagsearch();
|
||||
}
|
||||
|
||||
/*
|
||||
* Go to the next tag.
|
||||
*/
|
||||
public char * nexttag(int n)
|
||||
{
|
||||
char *tagfile = (char *) NULL;
|
||||
|
||||
while (n-- > 0)
|
||||
tagfile = nextgtag();
|
||||
return tagfile;
|
||||
}
|
||||
|
||||
/*
|
||||
* Go to the previous tag.
|
||||
*/
|
||||
public char * prevtag(int n)
|
||||
{
|
||||
char *tagfile = (char *) NULL;
|
||||
|
||||
while (n-- > 0)
|
||||
tagfile = prevgtag();
|
||||
return tagfile;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the total number of tags.
|
||||
*/
|
||||
public int ntags(void)
|
||||
{
|
||||
return total;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the sequence number of current tag.
|
||||
*/
|
||||
public int curr_tag(void)
|
||||
{
|
||||
return curseq;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* ctags
|
||||
*/
|
||||
|
||||
/*
|
||||
* Find tags in the "tags" file.
|
||||
* Sets curtag to the first tag entry.
|
||||
*/
|
||||
static enum tag_result findctag(char *tag)
|
||||
{
|
||||
char *p;
|
||||
char *q;
|
||||
FILE *f;
|
||||
int taglen;
|
||||
LINENUM taglinenum;
|
||||
char *tagfile;
|
||||
char *tagpattern;
|
||||
int tagendline;
|
||||
int search_char;
|
||||
int err;
|
||||
char tline[TAGLINE_SIZE];
|
||||
struct tag *tp;
|
||||
|
||||
p = shell_unquote(tags);
|
||||
f = fopen(p, "r");
|
||||
free(p);
|
||||
if (f == NULL)
|
||||
return TAG_NOFILE;
|
||||
|
||||
cleantags();
|
||||
total = 0;
|
||||
taglen = (int) strlen(tag);
|
||||
|
||||
/*
|
||||
* Search the tags file for the desired tag.
|
||||
*/
|
||||
while (fgets(tline, sizeof(tline), f) != NULL)
|
||||
{
|
||||
if (tline[0] == '!')
|
||||
/* Skip header of extended format. */
|
||||
continue;
|
||||
if (strncmp(tag, tline, taglen) != 0 || !WHITESP(tline[taglen]))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Found it.
|
||||
* The line contains the tag, the filename and the
|
||||
* location in the file, separated by white space.
|
||||
* The location is either a decimal line number,
|
||||
* or a search pattern surrounded by a pair of delimiters.
|
||||
* Parse the line and extract these parts.
|
||||
*/
|
||||
tagpattern = NULL;
|
||||
|
||||
/*
|
||||
* Skip over the whitespace after the tag name.
|
||||
*/
|
||||
p = skipsp(tline+taglen);
|
||||
if (*p == '\0')
|
||||
/* File name is missing! */
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Save the file name.
|
||||
* Skip over the whitespace after the file name.
|
||||
*/
|
||||
tagfile = p;
|
||||
while (!WHITESP(*p) && *p != '\0')
|
||||
p++;
|
||||
*p++ = '\0';
|
||||
p = skipsp(p);
|
||||
if (*p == '\0')
|
||||
/* Pattern is missing! */
|
||||
continue;
|
||||
|
||||
/*
|
||||
* First see if it is a line number.
|
||||
*/
|
||||
tagendline = 0;
|
||||
taglinenum = getnum(&p, 0, &err);
|
||||
if (err)
|
||||
{
|
||||
/*
|
||||
* No, it must be a pattern.
|
||||
* Delete the initial "^" (if present) and
|
||||
* the final "$" from the pattern.
|
||||
* Delete any backslash in the pattern.
|
||||
*/
|
||||
taglinenum = 0;
|
||||
search_char = *p++;
|
||||
if (*p == '^')
|
||||
p++;
|
||||
tagpattern = q = p;
|
||||
while (*p != search_char && *p != '\0')
|
||||
{
|
||||
if (*p == '\\')
|
||||
p++;
|
||||
if (q != p)
|
||||
{
|
||||
*q++ = *p++;
|
||||
} else
|
||||
{
|
||||
q++;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
tagendline = (q[-1] == '$');
|
||||
if (tagendline)
|
||||
q--;
|
||||
*q = '\0';
|
||||
}
|
||||
tp = maketagent(tag, tagfile, taglinenum, tagpattern, tagendline);
|
||||
TAG_INS(tp);
|
||||
total++;
|
||||
}
|
||||
fclose(f);
|
||||
if (total == 0)
|
||||
return TAG_NOTAG;
|
||||
curtag = taglist.tl_first;
|
||||
curseq = 1;
|
||||
return TAG_FOUND;
|
||||
}
|
||||
|
||||
/*
|
||||
* Edit current tagged file.
|
||||
*/
|
||||
public int edit_tagfile(void)
|
||||
{
|
||||
if (curtag == NULL)
|
||||
return (1);
|
||||
return (edit(curtag->tag_file));
|
||||
}
|
||||
|
||||
static int curtag_match(char constant *line, POSITION linepos)
|
||||
{
|
||||
/*
|
||||
* Test the line to see if we have a match.
|
||||
* Use strncmp because the pattern may be
|
||||
* truncated (in the tags file) if it is too long.
|
||||
* If tagendline is set, make sure we match all
|
||||
* the way to end of line (no extra chars after the match).
|
||||
*/
|
||||
int len = (int) strlen(curtag->tag_pattern);
|
||||
if (strncmp(curtag->tag_pattern, line, len) == 0 &&
|
||||
(!curtag->tag_endline || line[len] == '\0' || line[len] == '\r'))
|
||||
{
|
||||
curtag->tag_linenum = find_linenum(linepos);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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).
|
||||
*/
|
||||
static POSITION ctagsearch(void)
|
||||
{
|
||||
POSITION pos, linepos;
|
||||
LINENUM linenum;
|
||||
int line_len;
|
||||
char *line;
|
||||
int found;
|
||||
|
||||
pos = ch_zero();
|
||||
linenum = find_linenum(pos);
|
||||
|
||||
for (found = 0; !found;)
|
||||
{
|
||||
/*
|
||||
* Get lines until we find a matching one or
|
||||
* until we hit end-of-file.
|
||||
*/
|
||||
if (ABORT_SIGS())
|
||||
return (NULL_POSITION);
|
||||
|
||||
/*
|
||||
* Read the next line, and save the
|
||||
* starting position of that line in linepos.
|
||||
*/
|
||||
linepos = pos;
|
||||
pos = forw_raw_line(pos, &line, &line_len);
|
||||
if (linenum != 0)
|
||||
linenum++;
|
||||
|
||||
if (pos == NULL_POSITION)
|
||||
{
|
||||
/*
|
||||
* We hit EOF without a match.
|
||||
*/
|
||||
error("Tag not found", NULL_PARG);
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're using line numbers, we might as well
|
||||
* remember the information we have now (the position
|
||||
* and line number of the current line).
|
||||
*/
|
||||
if (linenums)
|
||||
add_lnum(linenum, pos);
|
||||
|
||||
if (ctldisp != OPT_ONPLUS)
|
||||
{
|
||||
if (curtag_match(line, linepos))
|
||||
found = 1;
|
||||
} else
|
||||
{
|
||||
int cvt_ops = CVT_ANSI;
|
||||
int cvt_len = cvt_length(line_len, cvt_ops);
|
||||
int *chpos = cvt_alloc_chpos(cvt_len);
|
||||
char *cline = (char *) ecalloc(1, cvt_len);
|
||||
cvt_text(cline, line, chpos, &line_len, cvt_ops);
|
||||
if (curtag_match(cline, linepos))
|
||||
found = 1;
|
||||
free(chpos);
|
||||
free(cline);
|
||||
}
|
||||
}
|
||||
|
||||
return (linepos);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* gtags
|
||||
*/
|
||||
|
||||
/*
|
||||
* Find tags in the GLOBAL's tag file.
|
||||
* The findgtag() will try and load information about the requested tag.
|
||||
* It does this by calling "global -x tag" and storing the parsed output
|
||||
* for future use by gtagsearch().
|
||||
* Sets curtag to the first tag entry.
|
||||
*/
|
||||
static enum tag_result findgtag(char *tag, int type)
|
||||
{
|
||||
char buf[1024];
|
||||
FILE *fp;
|
||||
struct tag *tp;
|
||||
|
||||
if (type != T_CTAGS_X && tag == NULL)
|
||||
return TAG_NOFILE;
|
||||
|
||||
cleantags();
|
||||
total = 0;
|
||||
|
||||
/*
|
||||
* If type == T_CTAGS_X then read ctags's -x format from stdin
|
||||
* else execute global(1) and read from it.
|
||||
*/
|
||||
if (type == T_CTAGS_X)
|
||||
{
|
||||
fp = stdin;
|
||||
/* Set tag default because we cannot read stdin again. */
|
||||
tags = ztags;
|
||||
} else
|
||||
{
|
||||
#if !HAVE_POPEN
|
||||
return TAG_NOFILE;
|
||||
#else
|
||||
char *command;
|
||||
char *flag;
|
||||
char *qtag;
|
||||
char *cmd = lgetenv("LESSGLOBALTAGS");
|
||||
|
||||
if (isnullenv(cmd))
|
||||
return TAG_NOFILE;
|
||||
/* Get suitable flag value for global(1). */
|
||||
switch (type)
|
||||
{
|
||||
case T_GTAGS:
|
||||
flag = "" ;
|
||||
break;
|
||||
case T_GRTAGS:
|
||||
flag = "r";
|
||||
break;
|
||||
case T_GSYMS:
|
||||
flag = "s";
|
||||
break;
|
||||
case T_GPATH:
|
||||
flag = "P";
|
||||
break;
|
||||
default:
|
||||
return TAG_NOTYPE;
|
||||
}
|
||||
|
||||
/* Get our data from global(1). */
|
||||
qtag = shell_quote(tag);
|
||||
if (qtag == NULL)
|
||||
qtag = tag;
|
||||
command = (char *) ecalloc(strlen(cmd) + strlen(flag) +
|
||||
strlen(qtag) + 5, sizeof(char));
|
||||
sprintf(command, "%s -x%s %s", cmd, flag, qtag);
|
||||
if (qtag != tag)
|
||||
free(qtag);
|
||||
fp = popen(command, "r");
|
||||
free(command);
|
||||
#endif
|
||||
}
|
||||
if (fp != NULL)
|
||||
{
|
||||
while (fgets(buf, sizeof(buf), fp))
|
||||
{
|
||||
char *name, *file, *line;
|
||||
int len;
|
||||
|
||||
if (sigs)
|
||||
{
|
||||
#if HAVE_POPEN
|
||||
if (fp != stdin)
|
||||
pclose(fp);
|
||||
#endif
|
||||
return TAG_INTR;
|
||||
}
|
||||
len = (int) strlen(buf);
|
||||
if (len > 0 && buf[len-1] == '\n')
|
||||
buf[len-1] = '\0';
|
||||
else
|
||||
{
|
||||
int c;
|
||||
do {
|
||||
c = fgetc(fp);
|
||||
} while (c != '\n' && c != EOF);
|
||||
}
|
||||
|
||||
if (getentry(buf, &name, &file, &line))
|
||||
{
|
||||
/*
|
||||
* Couldn't parse this line for some reason.
|
||||
* We'll just pretend it never happened.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
/* Make new entry and add to list. */
|
||||
tp = maketagent(name, file, (LINENUM) atoi(line), NULL, 0);
|
||||
TAG_INS(tp);
|
||||
total++;
|
||||
}
|
||||
if (fp != stdin)
|
||||
{
|
||||
if (pclose(fp))
|
||||
{
|
||||
curtag = NULL;
|
||||
total = curseq = 0;
|
||||
return TAG_NOFILE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check to see if we found anything. */
|
||||
tp = taglist.tl_first;
|
||||
if (tp == TAG_END)
|
||||
return TAG_NOTAG;
|
||||
curtag = tp;
|
||||
curseq = 1;
|
||||
return TAG_FOUND;
|
||||
}
|
||||
|
||||
static int circular = 0; /* 1: circular tag structure */
|
||||
|
||||
/*
|
||||
* Return the filename required for the next gtag in the queue that was setup
|
||||
* by findgtag(). The next call to gtagsearch() will try to position at the
|
||||
* appropriate tag.
|
||||
*/
|
||||
static char * nextgtag(void)
|
||||
{
|
||||
struct tag *tp;
|
||||
|
||||
if (curtag == NULL)
|
||||
/* No tag loaded */
|
||||
return NULL;
|
||||
|
||||
tp = curtag->next;
|
||||
if (tp == TAG_END)
|
||||
{
|
||||
if (!circular)
|
||||
return NULL;
|
||||
/* Wrapped around to the head of the queue */
|
||||
curtag = taglist.tl_first;
|
||||
curseq = 1;
|
||||
} else
|
||||
{
|
||||
curtag = tp;
|
||||
curseq++;
|
||||
}
|
||||
return (curtag->tag_file);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the filename required for the previous gtag in the queue that was
|
||||
* setup by findgtat(). The next call to gtagsearch() will try to position
|
||||
* at the appropriate tag.
|
||||
*/
|
||||
static char * prevgtag(void)
|
||||
{
|
||||
struct tag *tp;
|
||||
|
||||
if (curtag == NULL)
|
||||
/* No tag loaded */
|
||||
return NULL;
|
||||
|
||||
tp = curtag->prev;
|
||||
if (tp == TAG_END)
|
||||
{
|
||||
if (!circular)
|
||||
return NULL;
|
||||
/* Wrapped around to the tail of the queue */
|
||||
curtag = taglist.tl_last;
|
||||
curseq = total;
|
||||
} else
|
||||
{
|
||||
curtag = tp;
|
||||
curseq--;
|
||||
}
|
||||
return (curtag->tag_file);
|
||||
}
|
||||
|
||||
/*
|
||||
* Position the current file at at what is hopefully the tag that was chosen
|
||||
* using either findtag() or one of nextgtag() and prevgtag(). Returns -1
|
||||
* if it was unable to position at the tag, 0 if successful.
|
||||
*/
|
||||
static POSITION gtagsearch(void)
|
||||
{
|
||||
if (curtag == NULL)
|
||||
return (NULL_POSITION); /* No gtags loaded! */
|
||||
return (find_pos(curtag->tag_linenum));
|
||||
}
|
||||
|
||||
/*
|
||||
* The getentry() parses both standard and extended ctags -x format.
|
||||
*
|
||||
* [standard format]
|
||||
* <tag> <lineno> <file> <image>
|
||||
* +------------------------------------------------
|
||||
* |main 30 main.c main(argc, argv)
|
||||
* |func 21 subr.c func(arg)
|
||||
*
|
||||
* The following commands write this format.
|
||||
* o Traditinal Ctags with -x option
|
||||
* o Global with -x option
|
||||
* See <http://www.gnu.org/software/global/global.html>
|
||||
*
|
||||
* [extended format]
|
||||
* <tag> <type> <lineno> <file> <image>
|
||||
* +----------------------------------------------------------
|
||||
* |main function 30 main.c main(argc, argv)
|
||||
* |func function 21 subr.c func(arg)
|
||||
*
|
||||
* The following commands write this format.
|
||||
* o Exuberant Ctags with -x option
|
||||
* See <http://ctags.sourceforge.net>
|
||||
*
|
||||
* Returns 0 on success, -1 on error.
|
||||
* The tag, file, and line will each be NUL-terminated pointers
|
||||
* into buf.
|
||||
*/
|
||||
static int getentry(char *buf, char **tag, char **file, char **line)
|
||||
{
|
||||
char *p = buf;
|
||||
|
||||
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) */
|
||||
;
|
||||
if (*p == 0)
|
||||
return (-1);
|
||||
/*
|
||||
* If the second part begin with other than digit,
|
||||
* it is assumed tag type. Skip it.
|
||||
*/
|
||||
if (!IS_DIGIT(*p))
|
||||
{
|
||||
for ( ; *p && !IS_SPACE(*p); p++) /* (skip tag type) */
|
||||
;
|
||||
for (; *p && IS_SPACE(*p); p++) /* (skip blanks) */
|
||||
;
|
||||
}
|
||||
if (!IS_DIGIT(*p))
|
||||
return (-1);
|
||||
*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) */
|
||||
;
|
||||
if (*p == 0)
|
||||
return (-1);
|
||||
*file = p; /* file name */
|
||||
for (*file = p; *p && !IS_SPACE(*p); p++)
|
||||
;
|
||||
if (*p == 0)
|
||||
return (-1);
|
||||
*p = 0;
|
||||
|
||||
/* value check */
|
||||
if (strlen(*tag) && strlen(*line) && strlen(*file) && atoi(*line) > 0)
|
||||
return (0);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#endif
|
251
third_party/less/ttyin.c
vendored
Normal file
251
third_party/less/ttyin.c
vendored
Normal file
|
@ -0,0 +1,251 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Routines dealing with getting input from the keyboard (i.e. from the user).
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
#if OS2
|
||||
#include "cmd.h"
|
||||
#include "pckeys.h"
|
||||
#endif
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x400
|
||||
#endif
|
||||
/* #include <windows.h> */
|
||||
public DWORD console_mode;
|
||||
public HANDLE tty;
|
||||
#else
|
||||
public int tty;
|
||||
#endif
|
||||
#if LESSTEST
|
||||
public char *ttyin_name = NULL;
|
||||
#endif /*LESSTEST*/
|
||||
extern int sigs;
|
||||
extern int utf_mode;
|
||||
extern int wheel_lines;
|
||||
|
||||
#if !MSDOS_COMPILER
|
||||
static int open_tty_device(constant char* dev)
|
||||
{
|
||||
#if OS2
|
||||
/* The __open() system call translates "/dev/tty" to "con". */
|
||||
return __open(dev, OPEN_READ);
|
||||
#else
|
||||
return open(dev, OPEN_READ);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Open the tty device.
|
||||
* Try ttyname(), then try /dev/tty, then use file descriptor 2.
|
||||
* In Unix, file descriptor 2 is usually attached to the screen,
|
||||
* but also usually lets you read from the keyboard.
|
||||
*/
|
||||
public int open_tty(void)
|
||||
{
|
||||
int fd = -1;
|
||||
#if LESSTEST
|
||||
if (ttyin_name != NULL)
|
||||
fd = open_tty_device(ttyin_name);
|
||||
#endif /*LESSTEST*/
|
||||
#if HAVE_TTYNAME
|
||||
if (fd < 0)
|
||||
{
|
||||
constant char *dev = ttyname(2);
|
||||
if (dev != NULL)
|
||||
fd = open_tty_device(dev);
|
||||
}
|
||||
#endif
|
||||
if (fd < 0)
|
||||
fd = open_tty_device("/dev/tty");
|
||||
if (fd < 0)
|
||||
fd = 2;
|
||||
return fd;
|
||||
}
|
||||
#endif /* MSDOS_COMPILER */
|
||||
|
||||
/*
|
||||
* Open keyboard for input.
|
||||
*/
|
||||
public void open_getchr(void)
|
||||
{
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
/* Need this to let child processes inherit our console handle */
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
|
||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
sa.bInheritHandle = TRUE;
|
||||
tty = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ, &sa,
|
||||
OPEN_EXISTING, 0L, NULL);
|
||||
GetConsoleMode(tty, &console_mode);
|
||||
/* Make sure we get Ctrl+C events. */
|
||||
SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT);
|
||||
#else
|
||||
#if MSDOS_COMPILER
|
||||
extern int fd0;
|
||||
/*
|
||||
* Open a new handle to CON: in binary mode
|
||||
* for unbuffered keyboard read.
|
||||
*/
|
||||
fd0 = dup(0);
|
||||
close(0);
|
||||
tty = open("CON", OPEN_READ);
|
||||
#if MSDOS_COMPILER==DJGPPC
|
||||
/*
|
||||
* Setting stdin to binary causes Ctrl-C to not
|
||||
* raise SIGINT. We must undo that side-effect.
|
||||
*/
|
||||
(void) __djgpp_set_ctrl_c(1);
|
||||
#endif
|
||||
#else
|
||||
tty = open_tty();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Close the keyboard.
|
||||
*/
|
||||
public void close_getchr(void)
|
||||
{
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
SetConsoleMode(tty, console_mode);
|
||||
CloseHandle(tty);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
/*
|
||||
* Close the pipe, restoring the keyboard (CMD resets it, losing the mouse).
|
||||
*/
|
||||
public int pclose(FILE *f)
|
||||
{
|
||||
int result;
|
||||
|
||||
result = _pclose(f);
|
||||
SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Get the number of lines to scroll when mouse wheel is moved.
|
||||
*/
|
||||
public int default_wheel_lines(void)
|
||||
{
|
||||
int lines = 1;
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
if (SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &lines, 0))
|
||||
{
|
||||
if (lines == WHEEL_PAGESCROLL)
|
||||
lines = 3;
|
||||
}
|
||||
#endif
|
||||
return lines;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a character from the keyboard.
|
||||
*/
|
||||
public int getchr(void)
|
||||
{
|
||||
char c;
|
||||
int result;
|
||||
|
||||
do
|
||||
{
|
||||
flush();
|
||||
#if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
|
||||
/*
|
||||
* In raw read, we don't see ^C so look here for it.
|
||||
*/
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
if (ABORT_SIGS())
|
||||
return (READ_INTR);
|
||||
c = WIN32getch();
|
||||
#else
|
||||
c = getch();
|
||||
#endif
|
||||
result = 1;
|
||||
if (c == '\003')
|
||||
return (READ_INTR);
|
||||
#else
|
||||
{
|
||||
unsigned char uc;
|
||||
result = iread(tty, &uc, sizeof(char));
|
||||
c = (char) uc;
|
||||
}
|
||||
if (result == READ_INTR)
|
||||
return (READ_INTR);
|
||||
if (result < 0)
|
||||
{
|
||||
/*
|
||||
* Don't call error() here,
|
||||
* because error calls getchr!
|
||||
*/
|
||||
quit(QUIT_ERROR);
|
||||
}
|
||||
#endif
|
||||
#if LESSTEST
|
||||
if (c == LESS_DUMP_CHAR)
|
||||
{
|
||||
dump_screen();
|
||||
result = 0;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#if 0 /* allow entering arbitrary hex chars for testing */
|
||||
/* ctrl-A followed by two hex chars makes a byte */
|
||||
{
|
||||
static int hex_in = 0;
|
||||
static int hex_value = 0;
|
||||
if (c == CONTROL('A'))
|
||||
{
|
||||
hex_in = 2;
|
||||
result = 0;
|
||||
continue;
|
||||
}
|
||||
if (hex_in > 0)
|
||||
{
|
||||
int v;
|
||||
if (c >= '0' && c <= '9')
|
||||
v = c - '0';
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
v = c - 'a' + 10;
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
v = c - 'A' + 10;
|
||||
else
|
||||
v = 0;
|
||||
hex_value = (hex_value << 4) | v;
|
||||
if (--hex_in > 0)
|
||||
{
|
||||
result = 0;
|
||||
continue;
|
||||
}
|
||||
c = hex_value;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Various parts of the program cannot handle
|
||||
* an input character of '\0'.
|
||||
* If a '\0' was actually typed, convert it to '\340' here.
|
||||
*/
|
||||
if (c == '\0')
|
||||
c = '\340';
|
||||
} while (result != 1);
|
||||
|
||||
return (c & 0xFF);
|
||||
}
|
11
third_party/less/ubin.inc
vendored
Normal file
11
third_party/less/ubin.inc
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
/* Generated by "./mkutable -f2 Cc Cs Co Zl Zp -- unicode/UnicodeData.txt" on Mon Nov 14 18:19:24 PST 2022 */
|
||||
{ 0x0000, 0x0007 }, /* Cc */
|
||||
{ 0x000b, 0x000b }, /* Cc */
|
||||
{ 0x000e, 0x001f }, /* Cc */
|
||||
{ 0x007f, 0x009f }, /* Cc */
|
||||
{ 0x2028, 0x2028 }, /* Zl */
|
||||
{ 0x2029, 0x2029 }, /* Zp */
|
||||
{ 0xd800, 0xdfff }, /* Cs */
|
||||
{ 0xe000, 0xf8ff }, /* Co */
|
||||
{ 0xf0000, 0xffffd }, /* Co */
|
||||
{ 0x100000, 0x10fffd }, /* Co */
|
998
third_party/less/version.c
vendored
Normal file
998
third_party/less/version.c
vendored
Normal file
|
@ -0,0 +1,998 @@
|
|||
/*
|
||||
* Copyright (C) 1984-2023 Mark Nudelman
|
||||
*
|
||||
* You may distribute under the terms of either the GNU General Public
|
||||
* License or the Less License, as specified in the README file.
|
||||
*
|
||||
* For more information, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
----------------------- CHANGE HISTORY --------------------------
|
||||
|
||||
1/29/84 Allowed use on standard input
|
||||
2/1/84 Added E, N, P commands
|
||||
4/17/84 Added '=' command, 'stop' signal handling
|
||||
4/20/84 Added line folding
|
||||
v2 4/27/84 Fixed '=' command to use BOTTOM_PLUS_ONE,
|
||||
instead of TOP, added 'p' & 'v' commands
|
||||
v3 5/3/84 Added -m and -t options, '-' command
|
||||
v4 5/3/84 Added LESS environment variable
|
||||
v5 5/3/84 New comments, fixed '-' command slightly
|
||||
v6 5/15/84 Added -Q, visual bell
|
||||
v7 5/24/84 Fixed jump_back(n) bug: n should count real
|
||||
lines, not folded lines. Also allow number on G command.
|
||||
v8 5/30/84 Re-do -q and -Q commands
|
||||
v9 9/25/84 Added "+<cmd>" argument
|
||||
v10 10/10/84 Fixed bug in -b<n> argument processing
|
||||
v11 10/18/84 Made error() ring bell if \n not entered.
|
||||
-----------------------------------------------------------------
|
||||
v12 2/13/85 Reorganized signal handling and made portable to 4.2bsd.
|
||||
v13 2/16/85 Reword error message for '-' command.
|
||||
v14 2/22/85 Added -bf and -bp variants of -b.
|
||||
v15 2/25/85 Miscellaneous changes.
|
||||
v16 3/13/85 Added -u flag for backspace processing.
|
||||
v17 4/13/85 Added j and k commands, changed -t default.
|
||||
v18 4/20/85 Rewrote signal handling code.
|
||||
v19 5/2/85 Got rid of "verbose" eq_message().
|
||||
Made search() scroll in some cases.
|
||||
v20 5/21/85 Fixed screen.c ioctls for System V.
|
||||
v21 5/23/85 Fixed some first_cmd bugs.
|
||||
v22 5/24/85 Added support for no RECOMP nor REGCMP.
|
||||
v23 5/25/85 Miscellanous changes and prettying up.
|
||||
Posted to USENET.
|
||||
-----------------------------------------------------------------
|
||||
v24 6/3/85 Added ti,te terminal init & de-init.
|
||||
(Thanks to Mike Kersenbrock)
|
||||
v25 6/8/85 Added -U flag, standout mode underlining.
|
||||
v26 6/9/85 Added -M flag.
|
||||
Use underline termcap (us) if it exists.
|
||||
v27 6/15/85 Renamed some variables to make unique in
|
||||
6 chars. Minor fix to -m.
|
||||
v28 6/28/85 Fixed right margin bug.
|
||||
v29 6/28/85 Incorporated M.Rose's changes to signal.c
|
||||
v30 6/29/85 Fixed stupid bug in argument processing.
|
||||
v31 7/15/85 Added -p flag, changed repaint algorithm.
|
||||
Added kludge for magic cookie terminals.
|
||||
v32 7/16/85 Added cat_file if output not a tty.
|
||||
v33 7/23/85 Added -e flag and EDITOR.
|
||||
v34 7/26/85 Added -s flag.
|
||||
v35 7/27/85 Rewrote option handling; added option.c.
|
||||
v36 7/29/85 Fixed -e flag to work if not last file.
|
||||
v37 8/10/85 Added -x flag.
|
||||
v38 8/19/85 Changed prompting; created prompt.c.
|
||||
v39 8/24/85 (Not -p) does not initially clear screen.
|
||||
v40 8/26/85 Added "skipping" indicator in forw().
|
||||
Posted to USENET.
|
||||
-----------------------------------------------------------------
|
||||
v41 9/17/85 ONLY_RETURN, control char commands,
|
||||
faster search, other minor fixes.
|
||||
v42 9/25/85 Added ++ command line syntax;
|
||||
ch_fsize for pipes.
|
||||
v43 10/15/85 Added -h flag, changed prim.c algorithms.
|
||||
v44 10/16/85 Made END print in all cases of eof;
|
||||
ignore SIGTTOU after receiv ing SIGTSTP.
|
||||
v45 10/16/85 Never print backspaces unless -u.
|
||||
v46 10/24/85 Backwards scroll in jump_loc.
|
||||
v47 10/30/85 Fixed bug in edit(): *first_cmd==0
|
||||
v48 11/16/85 Use TIOCSETN instead of TIOCSETP.
|
||||
Added marks (m and ' commands).
|
||||
Posted to USENET.
|
||||
-----------------------------------------------------------------
|
||||
v49 1/9/86 Fixed bug: signal didn't clear mcc.
|
||||
v50 1/15/86 Added ' (quote) to gomark.
|
||||
v51 1/16/86 Added + cmd, fixed problem if first_cmd
|
||||
fails, made g cmd sort of "work" on pipes
|
||||
ev en if bof is no longer buffered.
|
||||
v52 1/17/86 Made short files work better.
|
||||
v53 1/20/86 Added -P option.
|
||||
v54 1/20/86 Changed help to use HELPFILE.
|
||||
v55 1/23/86 Messages work better if not tty output.
|
||||
v56 1/24/86 Added -l option.
|
||||
v57 1/31/86 Fixed -l to get confirmation before
|
||||
ov erwriting an existing file.
|
||||
v58 8/28/86 Added filename globbing.
|
||||
v59 9/15/86 Fixed some bugs with very long filenames.
|
||||
v60 9/26/86 Incorporated changes from Leith (Casey)
|
||||
Leedom for boldface and -z option.
|
||||
v61 9/26/86 Got rid of annoying repaints after ! cmd.
|
||||
Posted to USENET.
|
||||
-----------------------------------------------------------------
|
||||
v62 12/23/86 Added is_directory(); change -z default to
|
||||
-1 instead of 24; cat-and-exit if -e and
|
||||
file is less than a screenful.
|
||||
v63 1/8/87 Fixed bug in cat-and-exit if > 1 file.
|
||||
v64 1/12/87 Changed puts/putstr, putc/putchr,
|
||||
getc/getchr to av oid name conflict with
|
||||
stdio functions.
|
||||
v65 1/26/87 Allowed '-' command to change NUMBER
|
||||
v alued options (thanks to Gary Puckering)
|
||||
v66 2/13/87 Fixed bug: prepaint should use force=1.
|
||||
v67 2/24/87 Added !! and % expansion to ! command.
|
||||
v68 2/25/87 Added SIGWINCH and TIOCGWINSZ support;
|
||||
changed is_directory to bad_file.
|
||||
(thanks to J. Robert Ward)
|
||||
v69 2/25/87 Added SIGWIND and WIOCGETD (for Unix PC).
|
||||
v70 3/13/87 Changed help cmd from 'h' to 'H'; better
|
||||
error msgs in bad_file, errno_message.
|
||||
v71 5/11/87 Changed -p to -c, made triple -c/-C
|
||||
for clear-eol like more's -c.
|
||||
v72 6/26/87 Added -E, -L, use $SHELL in lsystem().
|
||||
(thanks to Stev e Spearman)
|
||||
v73 6/26/87 Allow Examine "#" for previous file.
|
||||
Posted to USENET 8/25/87.
|
||||
-----------------------------------------------------------------
|
||||
v74 9/18/87 Fix conflict in EOF symbol with stdio.h,
|
||||
Make os.c more portable to BSD.
|
||||
v75 9/23/87 Fix problems in get_term (thanks to
|
||||
Paul Eggert); new backwards scrolling in
|
||||
jump_loc (thanks to Marion Hakanson).
|
||||
v76 9/23/87 Added -i flag; allow single "!" to
|
||||
inv oke a shell (thanks to Franco Barber).
|
||||
v77 9/24/87 Added -n flag and line number support.
|
||||
v78 9/25/87 Fixed problem with prompts longer than
|
||||
the screen width.
|
||||
v79 9/29/87 Added the _ command.
|
||||
v80 10/6/87 Allow signal to break out of linenum scan.
|
||||
v81 10/6/87 Allow -b to be changed from within less.
|
||||
v82 10/7/87 Add cmd_decode to use a table for key
|
||||
binding (thanks to Dav id Nason).
|
||||
v83 10/9/87 Allow .less file for user-defined keys.
|
||||
v84 10/11/87 Fix -e/-E problems (thanks to Felix Lee).
|
||||
v85 10/15/87 Search now keeps track of line numbers.
|
||||
v86 10/20/87 Added -B option and autobuf; fixed
|
||||
"pipe error" bug.
|
||||
v87 3/1/88 Fix bug re BSD signals while reading file.
|
||||
v88 3/12/88 Use new format for -P option (thanks to
|
||||
der Mouse), allow "+-c" without message,
|
||||
fix bug re BSD hangup.
|
||||
v89 3/18/88 Turn off line numbers if linenum scan
|
||||
is interrupted.
|
||||
v90 3/30/88 Allow -P from within less.
|
||||
v91 3/30/88 Added tags file support (new -t option)
|
||||
(thanks to Brian Campbell).
|
||||
v92 4/4/88 Added -+option syntax.
|
||||
v93 4/11/88 Add support for slow input (thanks to
|
||||
Joe Orost & apologies for taking almost
|
||||
3 years to get this in!)
|
||||
v94 4/11/88 Redo reading/signal stuff.
|
||||
v95 4/20/88 Repaint screen better after signal.
|
||||
v96 4/21/88 Add /! and ?! commands.
|
||||
v97 5/17/88 Allow -l/-L from within less.
|
||||
Eliminate some static arrays (use calloc).
|
||||
Posted to USENET.
|
||||
-----------------------------------------------------------------
|
||||
v98 10/14/88 Fix incorrect calloc call; uninitialized
|
||||
var in exec_mca; core dump on unknown TERM.
|
||||
Make v cmd work if past last line of file.
|
||||
Fix some signal bugs.
|
||||
v99 10/29/88 Allow space between -X and string,
|
||||
when X is a string-valued option.
|
||||
v100 1/5/89 Fix globbing bug when $SHELL not set;
|
||||
allow spaces after -t command.
|
||||
v101 1/6/89 Fix problem with long (truncated) lines
|
||||
in tags file (thanks to Neil Dixon).
|
||||
v102 1/6/89 Fix bug with E# when no prev file;
|
||||
allow spaces after -l command.
|
||||
v103 3/14/89 Add -N, -f and -? options. Add z and w
|
||||
commands. Add %L for prompt strings.
|
||||
v104 3/16/89 Added EDITPROTO.
|
||||
v105 3/20/89 Fix bug in find_linenum which cached
|
||||
incorrectly on long lines.
|
||||
v106 3/31/89 Added -k option and multiple lesskey
|
||||
files.
|
||||
v107 4/27/89 Add 8-bit char support and -g option.
|
||||
Split option code into 3 files.
|
||||
v108 5/5/89 Allocate position table dynamically
|
||||
(thanks to Paul Eggert); change % command
|
||||
from "percent" to vi-style brace finder.
|
||||
v109 5/10/89 Added ESC-% command, split prim.c.
|
||||
v110 5/24/89 Fixed bug in + option; fixed repaint bug
|
||||
under Sun windows (thanks to Paul Eggert).
|
||||
v111 5/25/89 Generalized # and % expansion; use
|
||||
calloc for some error messages.
|
||||
v112 5/30/89 Get rid of ESC-%, add {}()[] commands.
|
||||
v113 5/31/89 Optimize lseeks (thanks to Paul Eggert).
|
||||
v114 7/25/89 Added ESC-/ and ESC-/! commands.
|
||||
v115 7/26/89 Added ESC-n command.
|
||||
v116 7/31/89 Added find_pos to optimize g command.
|
||||
v117 8/1/89 Change -f option to -r.
|
||||
v118 8/2/89 Save positions for all previous files,
|
||||
not just the immediately previous one.
|
||||
v119 8/7/89 Save marks across file boundaries.
|
||||
Add file handle stuff.
|
||||
v120 8/11/89 Add :ta command.
|
||||
v121 8/16/89 Add -f option.
|
||||
v122 8/30/89 Fix performance with many buffers.
|
||||
v123 8/31/89 Verbose prompts for string options.
|
||||
Posted beta to USENET.
|
||||
-----------------------------------------------------------------
|
||||
v124 9/18/89 Reorganize search commands,
|
||||
N = rev, ESC-n = span, add ESC-N.
|
||||
v125 9/18/89 Fix tab bug (thanks to Alex Liu).
|
||||
Fix EOF bug when both -w and -c.
|
||||
v126 10/25/89 Add -j option.
|
||||
v127 10/27/89 Fix problems with blank lines before BOF.
|
||||
v128 10/27/89 Add %bj, etc. to prompt strings.
|
||||
v129 11/3/89 Add -+,-- commands; add set-option and
|
||||
unset-option to lesskey.
|
||||
v130 11/6/89 Generalize A_EXTRA to string, remove
|
||||
set-option, unset-option from lesskey.
|
||||
v131 11/7/89 Changed name of EDITPROTO to LESSEDIT.
|
||||
v132 11/8/89 Allow editing of command prefix.
|
||||
v133 11/16/89 Add -y option (thanks to Jeff Sullivan).
|
||||
v134 12/1/89 Glob filenames in the -l command.
|
||||
v135 12/5/89 Combined {}()[] commands into one, and
|
||||
added ESC-^F and ESC-^B commands.
|
||||
v136 1/20/90 Added -S, -R flags. Added | command.
|
||||
Added warning for binary files. (thanks
|
||||
to Richard Brittain and J. Sullivan).
|
||||
v137 1/21/90 Rewrote horrible pappend code.
|
||||
Added * notation for hi-bit chars.
|
||||
v138 1/24/90 Fix magic cookie terminal handling.
|
||||
Get rid of "cleanup" loop in ch_get.
|
||||
v139 1/27/90 Added MSDOS support. (many thanks
|
||||
to Richard Brittain).
|
||||
v140 2/7/90 Editing a new file adds it to the
|
||||
command line list.
|
||||
v141 2/8/90 Add edit_list for editing >1 file.
|
||||
v142 2/10/90 Add :x command.
|
||||
v143 2/11/90 Add * and @ modifies to search cmds.
|
||||
Change ESC-/ cmd from /@* to / *.
|
||||
v144 3/1/90 Messed around with ch_zero;
|
||||
no real change.
|
||||
v145 3/2/90 Added -R and -v/-V for MSDOS;
|
||||
renamed FILENAME to avoid conflict.
|
||||
v146 3/5/90 Pull cmdbuf functions out of command.c
|
||||
v147 3/7/90 Implement ?@; fix multi-file edit bugs.
|
||||
v148 3/29/90 Fixed bug in :e<file> then :e#.
|
||||
v149 4/3/90 Change error,ierror,query to use PARG.
|
||||
v150 4/6/90 Add LESS_CHARSET, LESS_CHARDEF.
|
||||
v151 4/13/90 Remove -g option; clean up ispipe.
|
||||
v152 4/14/90 lsystem() closes input file, for
|
||||
editors which require exclusive open.
|
||||
v153 4/18/90 Fix bug if SHELL unset;
|
||||
fix bug in overstrike control char.
|
||||
v154 4/25/90 Output to fd 2 via buffer.
|
||||
v155 4/30/90 Ignore -i if uppercase in pattern
|
||||
(thanks to Michael Rendell.)
|
||||
v156 5/3/90 Remove scroll limits in forw() & back();
|
||||
causes problems with -c.
|
||||
v157 5/4/90 Forward search starts at next real line
|
||||
(not screen line) after jump target.
|
||||
v158 6/14/90 Added F command.
|
||||
v159 7/29/90 Fix bug in exiting: output not flushed.
|
||||
v160 7/29/90 Clear screen before initial output w/ -c.
|
||||
v161 7/29/90 Add -T flag.
|
||||
v162 8/14/90 Fix bug with +F on command line.
|
||||
v163 8/21/90 Added LESSBINFMT variable.
|
||||
v164 9/5/90 Added -p, LINES, COLUMNS and
|
||||
unset mark ' == BOF, for 1003.2 D5.
|
||||
v165 9/6/90 At EOF with -c set, don't display empty
|
||||
screen when try to page forward.
|
||||
v166 9/6/90 Fix G when final line in file wraps.
|
||||
v167 9/11/90 Translate CR/LF -> LF for 1003.2.
|
||||
v168 9/13/90 Return to curr file if "tag not found".
|
||||
v169 12/12/90 G goes to EOF even if file has grown.
|
||||
v170 1/17/91 Add optimization for BSD _setjmp;
|
||||
fix #include ioctl.h TERMIO problem.
|
||||
(thanks to Paul Eggert)
|
||||
Posted to USENET.
|
||||
-----------------------------------------------------------------
|
||||
v171 3/6/91 Fix -? bug in get_filename.
|
||||
v172 3/15/91 Fix G bug in empty file.
|
||||
Fix bug with ?\n and -i and uppercase
|
||||
pattern at EOF!
|
||||
(thanks to Paul Eggert)
|
||||
v173 3/17/91 Change N cmd to not permanently change
|
||||
direction. (thanks to Brian Matthews)
|
||||
v174 3/18/91 Fix bug with namelogfile not getting
|
||||
cleared when change files.
|
||||
v175 3/18/91 Fix bug with ++cmd on command line.
|
||||
(thanks to Jim Meyering)
|
||||
v176 4/2/91 Change | to not force current screen,
|
||||
include marked line, start/end from
|
||||
top of screen. Improve search speed.
|
||||
(thanks to Don Mears)
|
||||
v177 4/2/91 Add LESSHELP variable.
|
||||
Fix bug with F command with -e.
|
||||
Try /dev/tty for input before using fd 2.
|
||||
Patches posted to USENET 4/2/91.
|
||||
-----------------------------------------------------------------
|
||||
v178 4/8/91 Fixed bug in globbing logfile name.
|
||||
(thanks to Jim Meyering)
|
||||
v179 4/9/91 Allow negative -z for screen-relative.
|
||||
v180 4/9/91 Clear to eos rather than eol if "db";
|
||||
don't use "sr" if "da".
|
||||
(thanks to Tor Lillqvist)
|
||||
v181 4/18/91 Fixed bug with "negative" chars 80 - FF.
|
||||
(thanks to Benny Sander Hofmann)
|
||||
v182 5/16/91 Fixed bug with attribute at EOL.
|
||||
(thanks to Brian Matthews)
|
||||
v183 6/1/91 Rewrite linstall to do smart config.
|
||||
v184 7/11/91 Process \b in searches based on -u
|
||||
rather than -i.
|
||||
v185 7/11/91 -Pxxx sets short prompt; assume SIGWINCH
|
||||
after a SIGSTOP. (thanks to Ken Laprade)
|
||||
-----------------------------------------------------------------
|
||||
v186 4/20/92 Port to MS-DOS (Microsoft C).
|
||||
v187 4/23/92 Added -D option & TAB_COMPLETE_FILENAME.
|
||||
v188 4/28/92 Added command line editing features.
|
||||
v189 12/8/92 Fix mem overrun in anscreen.c:init;
|
||||
fix edit_list to recover from bin file.
|
||||
v190 2/13/93 Make TAB enter one filename at a time;
|
||||
create ^L with old TAB functionality.
|
||||
v191 3/10/93 Defer creating "flash" page for MS-DOS.
|
||||
v192 9/6/93 Add BACK-TAB.
|
||||
v193 9/17/93 Simplify binary_file handling.
|
||||
v194 1/4/94 Add rudiments of alt_filename handling.
|
||||
v195 1/11/94 Port back to Unix; support keypad.
|
||||
-----------------------------------------------------------------
|
||||
v196 6/7/94 Fix bug with bad filename; fix IFILE
|
||||
type problem. (thanks to David MacKenzie)
|
||||
v197 6/7/94 Fix bug with .less tables inserted wrong.
|
||||
v198 6/23/94 Use autoconf installation technology.
|
||||
(thanks to David MacKenzie)
|
||||
v199 6/29/94 Fix MS-DOS build (thanks to Tim Wiegman).
|
||||
v200 7/25/94 Clean up copyright, minor fixes.
|
||||
Posted to prep.ai.mit.edu
|
||||
-----------------------------------------------------------------
|
||||
v201 7/27/94 Check for no memcpy; add casts to calloc;
|
||||
look for regcmp in libgen.a.
|
||||
(thanks to Kaveh Ghazi).
|
||||
v202 7/28/94 Fix bug in edit_next/edit_prev with
|
||||
non-existent files.
|
||||
v203 8/2/94 Fix a variety of configuration bugs on
|
||||
various systems. (thanks to Sakai
|
||||
Kiyotaka, Harald Koenig, Bjorn Brox,
|
||||
Teemu Rantanen, and Thorsten Lockert)
|
||||
v204 8/3/94 Use strerror if available.
|
||||
(thanks to J.T. Conklin)
|
||||
v205 8/5/94 Fix bug in finding "me" termcap entry.
|
||||
(thanks to Andreas Stolcke)
|
||||
8/10/94 v205+: Change BUFSIZ to LBUFSIZE to avoid name
|
||||
conflict with stdio.h.
|
||||
Posted to prep.ai.mit.edu
|
||||
-----------------------------------------------------------------
|
||||
v206 8/10/94 Use initial_scrpos for -t to avoid
|
||||
displaying first page before init().
|
||||
(thanks to Dominique Petitpierre)
|
||||
v207 8/12/94 Fix bug if stdout is not tty.
|
||||
v208 8/16/94 Fix bug in close_altfile if goto err1
|
||||
in edit_ifile. (Thanks to M.J. Hewitt)
|
||||
v209 8/16/94 Change scroll to wscroll to avoid
|
||||
conflict with library function.
|
||||
v210 8/16/94 Fix bug with bold on 8 bit chars.
|
||||
(thanks to Vitor Duarte)
|
||||
v211 8/16/94 Don't quit on EOI in jump_loc / forw.
|
||||
v212 8/18/94 Use time_t if available.
|
||||
v213 8/20/94 Allow ospeed to be defined in termcap.h.
|
||||
v214 8/20/94 Added HILITE_SEARCH, -F, ESC-u cmd.
|
||||
(thanks to Paul Lew and Bob Byrnes)
|
||||
v215 8/23/94 Fix -i toggle behavior.
|
||||
v216 8/23/94 Process BS in all searches, not only -u.
|
||||
v217 8/24/94 Added -X flag.
|
||||
v218 8/24/94 Reimplement undo_search.
|
||||
v219 8/24/94 Find tags marked with line number
|
||||
instead of pattern.
|
||||
v220 8/24/94 Stay at same position after SIG_WINCH.
|
||||
v221 8/24/94 Fix bug in file percentage in big file.
|
||||
v222 8/25/94 Do better if can't reopen current file.
|
||||
v223 8/27/94 Support setlocale.
|
||||
(thanks to Robert Joop)
|
||||
v224 8/29/94 Revert v216: process BS in search
|
||||
only if -u.
|
||||
v225 9/6/94 Rewrite undo_search again: toggle.
|
||||
v226 9/15/94 Configuration fixes.
|
||||
(thanks to David MacKenzie)
|
||||
v227 9/19/94 Fixed strerror config problem.
|
||||
Posted to prep.ai.mit.edu
|
||||
-----------------------------------------------------------------
|
||||
v228 9/21/94 Fix bug in signals: repeated calls to
|
||||
get_editkeys overflowed st_edittable.
|
||||
v229 9/21/94 Fix "Nothing to search" error if -a
|
||||
and SRCH_PAST_EOF.
|
||||
v230 9/21/94 Don't print extra error msg in search
|
||||
after regerror().
|
||||
v231 9/22/94 Fix hilite bug if search matches 0 chars.
|
||||
(thanks to John Polstra)
|
||||
v232 9/23/94 Deal with weird systems that have
|
||||
termios.h but not tcgetattr().
|
||||
Posted to prep.ai.mit.edu
|
||||
-----------------------------------------------------------------
|
||||
v233 9/26/94 Use get_term() instead of pos_init() in
|
||||
psignals to re-get lower_left termcap.
|
||||
(Thanks to John Malecki)
|
||||
v234 9/26/94 Make MIDDLE closer to middle of screen.
|
||||
v235 9/27/94 Use local strchr if system doesn't have.
|
||||
v236 9/28/94 Don't use libucb; use libterm if
|
||||
libtermcap & libcurses doesn't work.
|
||||
(Fix for Solaris; thanks to Frank Kaefer)
|
||||
v237 9/30/94 Use system isupper() etc if provided.
|
||||
Posted to prep.ai.mit.edu
|
||||
-----------------------------------------------------------------
|
||||
v238 10/6/94 Make binary non-blinking if LESSBINFMT
|
||||
is set to a string without a *.
|
||||
v239 10/7/94 Don't let delimit_word run back past
|
||||
beginning of cmdbuf.
|
||||
v240 10/10/94 Don't write into termcap buffer.
|
||||
(Thanks to Benoit Speckel)
|
||||
v241 10/13/94 New lesskey file format.
|
||||
Don't expand filenames in search command.
|
||||
v242 10/14/94 Allow lesskey specification of "literal".
|
||||
v243 10/14/94 Add #stop command to lesskey.
|
||||
v244 10/16/94 Add -f flag to lesskey.
|
||||
v245 10/25/94 Allow TAB_COMPLETE_FILENAME to be undefd.
|
||||
v246 10/27/94 Move help file to /usr/local/share.
|
||||
v247 10/27/94 Add -V option.
|
||||
v248 11/5/94 Add -V option to lesskey.
|
||||
v249 11/5/94 Remove -f flag from lesskey; default
|
||||
input file is ~/.lesskey.in, not stdin.
|
||||
v250 11/7/94 Lesskey input file "-" means stdin.
|
||||
v251 11/9/94 Convert cfgetospeed result to ospeed.
|
||||
(Thanks to Andrew Chernov)
|
||||
v252 11/16/94 Change default lesskey input file from
|
||||
.lesskey.in to .lesskey.
|
||||
Posted to prep.ai.mit.edu
|
||||
-----------------------------------------------------------------
|
||||
v253 11/21/94 Fix bug when tags file has a backslash.
|
||||
v254 12/6/94 Fix -k option.
|
||||
v255 12/8/94 Add #define EXAMINE to disable :e etc.
|
||||
v256 12/10/94 Change highlighting: only highlite search
|
||||
results (but now it is reliable).
|
||||
v257 12/10/94 Add goto_line and repaint_highlight
|
||||
to optimize highlight repaints.
|
||||
v258 12/12/94 Fixup in hilite_line if BS_SPECIAL.
|
||||
v259 12/12/94 Convert to autoconf 2.0.
|
||||
v260 12/13/94 Add SECURE define.
|
||||
v261 12/14/94 Use system WERASE char as EC_W_BACKSPACE.
|
||||
v262 12/16/94 Add -g/-G flag and screen_hilite.
|
||||
v263 12/20/94 Reimplement/optimize -G flag behavior.
|
||||
v264 12/23/94 Allow EXTRA string after line-edit cmd
|
||||
in lesskey file.
|
||||
v265 12/24/94 Add LESSOPEN=|cmd syntax.
|
||||
v266 12/26/94 Add -I flag.
|
||||
v267 12/28/94 Formalize the four-byte header emitted
|
||||
by a LESSOPEN pipe.
|
||||
v268 12/28/94 Get rid of four-byte header.
|
||||
v269 1/2/95 Close alt file before open new one.
|
||||
Avoids multiple popen().
|
||||
v270 1/3/95 Use VISUAL; use S_ISDIR/S_ISREG; fix
|
||||
config problem with Solaris POSIX regcomp.
|
||||
v271 1/4/95 Don't quit on read error.
|
||||
v272 1/5/95 Get rid of -L.
|
||||
v273 1/6/95 Fix ch_ungetchar bug; don't call
|
||||
LESSOPEN on a pipe.
|
||||
v274 1/6/95 Ported to OS/2 (thanks to Kai Uwe Rommel)
|
||||
v275 1/18/95 Fix bug if toggle -G at EOF.
|
||||
v276 1/30/95 Fix OS/2 version.
|
||||
v277 1/31/95 Add "next" charset; don't display ^X
|
||||
for X > 128.
|
||||
v278 2/14/95 Change default for -G.
|
||||
Posted to prep.ai.mit.edu
|
||||
-----------------------------------------------------------------
|
||||
v279 2/22/95 Add GNU options --help, --version.
|
||||
Minor config fixes.
|
||||
v280 2/24/95 Clean up calls to glob(); don't set #
|
||||
if we can't open the new file.
|
||||
v281 2/24/95 Repeat search should turn on hilites.
|
||||
v282 3/2/95 Minor fixes.
|
||||
v283 3/2/95 Fix homefile; make OS2 look in $HOME.
|
||||
v284 3/2/95 Error if "v" on LESSOPENed file;
|
||||
"%" figures out file size on pipe.
|
||||
v285 3/7/95 Don't set # in lsystem;
|
||||
lesskey try $HOME first.
|
||||
v286 3/7/95 Reformat change history (too much free time?).
|
||||
v287 3/8/95 Fix hilite bug if overstrike multiple chars.
|
||||
v288 3/8/95 Allow lesskey to override get_editkey keys.
|
||||
v289 3/9/95 Fix adj_hilite bug when line gets processed by
|
||||
hilite_line more than once.
|
||||
v290 3/9/95 Make configure automatically. Fix Sequent problem
|
||||
with incompatible sigsetmask().
|
||||
Posted to prep.ai.mit.edu
|
||||
-----------------------------------------------------------------
|
||||
v291 3/21/95 Add #env to lesskey. Fix MS-DOS build.
|
||||
Posted to simtel.
|
||||
-----------------------------------------------------------------
|
||||
v292 4/24/95 Add MS-DOS support for Borland C.
|
||||
Fix arrow keys in MS-DOS versions.
|
||||
v293 4/28/95 Add auto-versioning stuff to make dist.
|
||||
v294 5/12/95 Fix Borland build.
|
||||
v295 1/20/96 Fix search on squished file; add /@@.
|
||||
v296 1/23/96 Allow cmdbuf larger than screen width.
|
||||
v297 1/24/96 Don't call termcap if tgetent fails;
|
||||
add #defines for buffers.
|
||||
v298 1/24/96 Change @@ to ^K.
|
||||
Add alternate search modifiers ^N, ^F, ^E.
|
||||
v299 1/25/96 Fix percent overflow in jump_percent (thanks to Brent Wiese);
|
||||
don't send "ti" after shell command till RETURN pressed.
|
||||
v300 1/25/96 Change -U to print tabs as ^I.
|
||||
v301 1/30/96 Make hilites work in cmd F output.
|
||||
v302 1/31/96 Fix cmd F to notice window-change signals.
|
||||
v303 1/31/96 Add ESC-SPACE command.
|
||||
v304 2/1/96 Add ^R search modifier; add LESSSECURE.
|
||||
v305 2/2/96 Workaround Linux /proc kernel bug; add LESSKEY.
|
||||
v306 3/16/96 Minor fixes.
|
||||
v307 3/25/96 Allow cmd line arg "--"; fix DOS & OS/2 defines.h.
|
||||
v308 4/4/96 Port to OS-9 (thanks to Boisy Pitre); fix -d.
|
||||
v309 4/9/96 Fix OS-9 version; fix tags bug with "$".
|
||||
v310 4/10/96 Get rid of HELPFILE.
|
||||
v311 4/22/96 Add Windows32 support; merge doscreen.c into screen.c.
|
||||
v312 4/24/96 Don't quit after "cannot reopen" error.
|
||||
v313 4/25/96 Added horizontal scrolling.
|
||||
v314 4/26/96 Modified -e to quit on reaching end of a squished file.
|
||||
v315 4/26/96 Fix "!;TAB" bug.
|
||||
v316 5/2/96 Make "|a" when (a < curr screen) go to end of curr screen.
|
||||
v317 5/14/96 Various fixes for the MS-DOS and OS/2 builds.
|
||||
Added ## and %% handling for filenames
|
||||
v318 5/29/96 Port to OS-9 Microware compiler; minor fixes
|
||||
(thanks to Martin Gregorie).
|
||||
v319 7/8/96 Fix Windows port (thanks to Jeff Paquette).
|
||||
v320 7/11/96 Final fixes for Windows port.
|
||||
v321 7/18/96 Minor fixes.
|
||||
Posted to Web page.
|
||||
-----------------------------------------------------------------
|
||||
v322 8/13/96 Fix bug in shell escape from help file; add support for
|
||||
Microsoft Visual C under Windows; numerous small fixes.
|
||||
v323 8/19/96 Fixes for Windows version (thanks to Simon Munton);
|
||||
fix for Linux library weirdness (thanks to Jim Diamond);
|
||||
port to DJGPP (thanks to Eli Zaretskii).
|
||||
v324 8/21/96 Add support for spaces in filenames (thanks to Simon Munton).
|
||||
v325 8/21/96 Add lessecho, for spaces in filenames under Unix.
|
||||
v326 8/27/96 Fix DJGPP version.
|
||||
v327 9/1/96 Reorganize lglob, make spaces in filenames work better in Unix.
|
||||
v328 10/7/96 Append / to directory name in filename completion.
|
||||
Fix MS-DOS and OS-9 versions.
|
||||
v329 10/11/96 Fix more MS-DOS bugs; add LESSSEPARATOR; add -" option.
|
||||
Add LESSMETACHARS, LESSMETAESCAPE.
|
||||
v330 10/21/96 Minor fixes.
|
||||
Posted to Web page.
|
||||
-----------------------------------------------------------------
|
||||
v331 4/22/97 Various Windows fixes (thanks to Gurusamy Sarathy).
|
||||
v332 4/22/97 Enter filenames from cmd line into edit history.
|
||||
Posted to Web page.
|
||||
-----------------------------------------------------------------
|
||||
v333 3/4/99 Changed -w to highlite new line after forward movement.
|
||||
v334 3/9/99 Avoid overflowing prompt buffer; add %d and %D.
|
||||
v335 3/20/99 Add EBCDIC support (thanks to Thomas Dorner).
|
||||
Use HOMEDRIVE/HOMEPATH on Windows (thanks to Preston Bannister).
|
||||
Posted to Web page.
|
||||
-----------------------------------------------------------------
|
||||
v336 4/8/99 Fix installation bugs.
|
||||
v337 4/9/99 Fix another installation bug.
|
||||
Posted to Web page.
|
||||
-----------------------------------------------------------------
|
||||
v338 4/13/99 Add support for long option names.
|
||||
v339 4/18/99 Add \k, long option names to lesskey. Add -^P. Add :d.
|
||||
v340 4/21/99 Add regexec2. Fix Windows build.
|
||||
Posted to Web page.
|
||||
-----------------------------------------------------------------
|
||||
v341 5/6/99 Add -F option; %c & ?c prompt escapes.
|
||||
(Thanks to Michele Maltoni)
|
||||
v342 7/22/99 Add system-wide lesskey file; allow GPL or Less License.
|
||||
v343 9/23/99 Support UTF-8 (Thanks to Robert Brady).
|
||||
Add %P and ?P in prompts.
|
||||
v344 10/27/99 -w highlights target line of g and p commands.
|
||||
v345 10/29/99 Make -R pass thru ESC but not other control chars.
|
||||
Posted to Web page.
|
||||
-----------------------------------------------------------------
|
||||
v346 11/4/99 Fix bugs in long option processing; R cmd should clear hilites.
|
||||
Posted to Web page.
|
||||
-----------------------------------------------------------------
|
||||
v347 12/13/99 Fixes for DJGPP version (thanks to Eli Zaretskii).
|
||||
v348 12/28/99 Fix deleting file with marks (thanks to Dimitar Jekov).
|
||||
Fix color problem in DJGPP version (thanks to Eli Zaretskii).
|
||||
v349 1/24/00 Fix minor DJGPP bugs; check environment vars for UTF-8;
|
||||
add --with-editor (thanks to Eli, Markus Kuhn, Thomas Schoepf).
|
||||
v350 3/1/00 Fix clear-while-standout bug.
|
||||
v351 3/5/00 Change -M and = prompts to show top & bottom line number.
|
||||
Posted to Web page.
|
||||
-----------------------------------------------------------------
|
||||
v352 3/8/00 Fix scan_option NULL dereference.
|
||||
-----------------------------------------------------------------
|
||||
v353 3/20/00 Fix SECURE compile bug, allow space after numeric option.
|
||||
v354 3/23/00 Add support for PCRE; add --with-regex configure option.
|
||||
-----------------------------------------------------------------
|
||||
v355 6/28/00 Add -# option (thanks to Andy Levinson).
|
||||
v356 7/5/00 Add -J option.
|
||||
v357 7/6/00 Support sigprocmask.
|
||||
-----------------------------------------------------------------
|
||||
v358 7/8/00 Fix problems with #stop in lesskey file.
|
||||
Posted to Web page.
|
||||
-----------------------------------------------------------------
|
||||
v359 9/10/00 Fixes for Win32 display problems (thanks to Maurizio Vairani).
|
||||
v360 1/17/01 Move sysless to etc.
|
||||
v361 12/4/01 Add IBM-1047 charset & EBCDIC fixes (thanks to Thomas Dorner).
|
||||
Fix 32 bit dependencies (thanks to Paul Eggert).
|
||||
Fix UTF-8 overstriking (thanks to Robert Brady).
|
||||
v362 12/4/01 Make status column show search targets.
|
||||
v363 12/6/01 Add --no-keypad option.
|
||||
Add variable width tabstops (thanks to Peter Samuelson).
|
||||
v364 12/10/01 Better handling of very long lines in input;
|
||||
Fix horizontal shifting of colored text.
|
||||
v365 12/11/01 Fix overstriking of tabs;
|
||||
Add support for global(1) and multiple tag matches
|
||||
(thanks to Shigio Yamaguchi and Tim Vanderhoek).
|
||||
v366 12/11/01 Fixes for OS/2 (thanks to Kyosuke Tokoro).
|
||||
v367 12/13/01 Allow -D and -x options to terminate without dollar sign;
|
||||
Right/left arrow when entering N are shift cmds, not line edit.
|
||||
v368 12/18/01 Update lesskey commands.
|
||||
v370 12/23/01 Fix tags error messages.
|
||||
Posted to Web page.
|
||||
-----------------------------------------------------------------
|
||||
v371 12/26/01 Fix new_file bug; use popen in Windows version;
|
||||
fix some compiler warnings.
|
||||
v372 12/29/01 Make -b be in units of 1K.
|
||||
v373 1/14/02 Improve handling of filenames containing shell metachars.
|
||||
v374 2/7/02 Fix memory leak; fix bug in -x argument parsing.
|
||||
v375 4/7/02 Fix searching for SGR sequences; fix SECURE build;
|
||||
add SGR support to DJGPP version (thanks to Eli Zaretskii).
|
||||
v376 6/10/02 Fix bug in overstriking mulitbyte UTF-8 characters
|
||||
(thanks to Jungshik Shin).
|
||||
Posted to Web page.
|
||||
-----------------------------------------------------------------
|
||||
v377 9/10/02 Fix bug in Windows version when file contains CR;
|
||||
fix bug in search highlights with -R;
|
||||
make initial buffer limit really be 64K not unlimited.
|
||||
v378 9/30/02 Misc bug fixes and compiler warning cleanup.
|
||||
Posted to Web page.
|
||||
-----------------------------------------------------------------
|
||||
v379 11/23/02 Add -L option; fix bug with ctrl-K in lesskey files;
|
||||
improve UTF-8 overstriking and underscore overstriking;
|
||||
fix minor man page problems; change to autoconf 2.54.
|
||||
v380 11/24/02 Make LINENUM same as POSITION.
|
||||
v381 11/28/02 Make -N use 7 columns for line number if possible.
|
||||
-----------------------------------------------------------------
|
||||
v382 2/3/04 Remove copyrighted code.
|
||||
-----------------------------------------------------------------
|
||||
v383 2/16/04 Add history file; add -K option; improve UTF-8 handling;
|
||||
fix some signed char bugs (thanks to Christian Biere);
|
||||
fix some upper/lower case bugs (thanks to Bjoern Jacke);
|
||||
add erase2 char (thanks to David Lawrence);
|
||||
add windows charset (thanks to Dimitar Zhekov).
|
||||
v384 2/20/04 Improvements in UTF-8 handling.
|
||||
v385 2/23/04 Fix UTF-8 output bug.
|
||||
-----------------------------------------------------------------
|
||||
v386 9/13/05 Improvements to UTF-8 shift & color (thanks to Charles Levert);
|
||||
protect against invalid LESSOPEN and LESSCLOSE values.
|
||||
v387 9/14/05 Update Charles Levert's UTF-8 patch.
|
||||
v388 9/14/05 Change history behavior; change most sprintf calls to snprintf.
|
||||
v389 9/14/05 Fix copy & paste with long lines; improve performance of
|
||||
expand_linebuf; fix crash in init_mlist;
|
||||
v390 9/15/05 Show search matches in status column even if -G is set.
|
||||
-----------------------------------------------------------------
|
||||
v391 9/17/05 Fix bugs.
|
||||
v392 10/14/05 Fix line wrapping bug.
|
||||
v393 10/19/05 Allow multiple attributes per char; fix bold+underline bug
|
||||
(thanks again to Charles Levert).
|
||||
v394 11/8/05 Fix prompt bug; fix compile problem in Windows build.
|
||||
-----------------------------------------------------------------
|
||||
v395 1/12/07 Update Unicode tables (thanks to Charles Levert);
|
||||
don't chmod if LESSHISTFILE = /dev/null;
|
||||
make -f work for directories; support DESTDIR in Makefile;
|
||||
fix sigset_t detection in configure;
|
||||
make "t" cmd traverse tags in correct order
|
||||
v396 1/13/07 Add compatibility with POSIX more.
|
||||
v397 3/21/07 Allow decimal point in number for % command;
|
||||
Allow decimal point in number for -j option;
|
||||
Allow n command to fetch last search pattern from history
|
||||
(thanks to arno).
|
||||
v398 3/22/07 Don't rewrite history file if not necessary;
|
||||
fix bug when filenames contain "$".
|
||||
v399 3/22/07 Don't move to bottom of screen at startup;
|
||||
don't output extraneous newlines.
|
||||
v400 3/23/07 Allow search to find pattern after null byte (PCRE and no-regex)
|
||||
(thanks to Michael Constant).
|
||||
-----------------------------------------------------------------
|
||||
v401 3/24/07 Minor documentation fixes.
|
||||
v402 3/30/07 Fix autoconf bug when memcpy etc are inline;
|
||||
fix bug in terminating number following -j option.
|
||||
v403 5/25/07 Fix Windows build.
|
||||
v404 6/5/07 Fix display bug with F command and long lines.
|
||||
v405 6/17/07 Fix display bug when using -w option.
|
||||
v406 6/17/07 Fix secure build.
|
||||
v407 8/16/07 Fix bugs; support CSI chars.
|
||||
v408 10/1/07 Fix bug in -i with non-ASCII chars.
|
||||
v409 10/12/07 Fix crash when viewing text with invalid UTF-8 sequences.
|
||||
v411 11/6/07 Fix case-insensitive searching with non-ASCII text.
|
||||
v412 11/6/07 Use symbolic SEEK constants.
|
||||
v413 11/6/07 Fix search highlight bug with non-ASCII text.
|
||||
v414 11/6/07 Fix display bug with no-wrap terminals.
|
||||
v415 11/14/07 Add --follow-name option.
|
||||
v416 11/22/07 Fix crash when searching text with invalid UTF-8 sequences.
|
||||
v417 12/31/07 Don't support single-char CSI in UTF-8 mode;
|
||||
fix bug with -R and invalid CSI sequences;
|
||||
fix bug searching text with SGR sequences with -r;
|
||||
emulate SGR sequences in WIN32 build.
|
||||
v418 12/31/07 Clean up.
|
||||
-----------------------------------------------------------------
|
||||
v419 1/16/08 Make CSI char 0x9B work in UTF-8 mode (thanks to Colin Watson).
|
||||
v420 2/24/08 Add & command; fix -F option; fix '' after G.
|
||||
v421 2/24/08 Ignore filtered lines when searching.
|
||||
v422 3/2/08 Output CR at startup.
|
||||
v423 5/27/08 Clean up.
|
||||
v424 6/16/08 Fix compile bug with pcre; don't filter help file.
|
||||
v425 7/14/08 Fix non-ANSI code in list handling in ch.c.
|
||||
v426 10/27/08 Fix ignaw terminal handling (thanks to Per Hedeland);
|
||||
fix binary file detection in UTF-8 mode.
|
||||
v427 3/16/09 A few Win32 fixes (thanks to Jason Hood).
|
||||
v428 3/30/09 Add "|-" syntax to LESSOPEN.
|
||||
v429 4/10/09 Fix search highlighting bug with underlined text.
|
||||
-----------------------------------------------------------------
|
||||
v430 4/22/09 Don't pass "-" to non-pipe LESSOPEN unless it starts with "-".
|
||||
v431 4/29/09 Fix highlight bug when match is at end of line.
|
||||
v432 6/27/09 Better fix for highlight bugs;
|
||||
fix new problems with ignaw terminals.
|
||||
v433 6/28/09 Cleanup search code.
|
||||
v434 6/29/09 More cleanup.
|
||||
v435 7/04/09 Fix bugs with non-regex filtering.
|
||||
v436 7/05/09 Fix memory leak.
|
||||
-----------------------------------------------------------------
|
||||
v437 7/14/09 Fix bug in handling some long option names;
|
||||
make percentage calculation more accurate.
|
||||
v438 12/29/10 Fix bugs with -i/-I and & filtering;
|
||||
exit with status 2 on ctrl-C with -K.
|
||||
v439 12/31/10 Add -A option.
|
||||
v440 1/5/11 Fix bug displaying prompt after = command.
|
||||
v441 1/21/11 Fix semi-infinite loop if no newlines in file;
|
||||
make new -A behavior the default.
|
||||
-----------------------------------------------------------------
|
||||
v442 3/2/11 Fix search bug.
|
||||
Add ctrl-G line edit command.
|
||||
v443 4/9/11 Fix Windows build.
|
||||
v444 6/8/11 Fix ungetc bug; remove vestiges of obsolete -l option.
|
||||
-----------------------------------------------------------------
|
||||
v445 10/19/11 Fix hilite bug in backwards scroll with -J.
|
||||
Fix hilite bug with backspaces.
|
||||
Fix bugs handling SGR sequences in Win32 (thanks to Eric Lee).
|
||||
Add support for GNU regex (thanks to Reuben Thomas).
|
||||
v446 5/15/12 Up/down arrows in cmd editing search for matching cmd.
|
||||
v447 5/21/12 Add ESC-F command, two-pipe LESSOPEN syntax.
|
||||
v448 6/15/12 Print name of regex library in version message.
|
||||
v449 6/23/12 Allow config option --with-regex=none.
|
||||
v450 7/4/12 Fix EOF bug with ESC-F.
|
||||
v451 7/20/12 Fix typo.
|
||||
-----------------------------------------------------------------
|
||||
v452 10/19/12 Fix --with-regex=none, fix "stty 0", fix Win32.
|
||||
Don't quit if errors in cmd line options.
|
||||
v453 10/27/12 Increase buffer sizes.
|
||||
v454 11/5/12 Fix typo.
|
||||
v455 11/5/12 Fix typo.
|
||||
v456 11/8/12 Fix option string incompatibility.
|
||||
v457 12/8/12 Use new option string syntax only after --use-backslash.
|
||||
v458 4/4/13 Fix display bug in using up/down in cmd buffer.
|
||||
-----------------------------------------------------------------
|
||||
v459 5/6/13 Fix ++ bug.
|
||||
v460 6/19/13 Automate construction of Unicode tables.
|
||||
v461 6/21/13 Collapse multiple CRs before LF.
|
||||
v462 11/26/13 Don't overwrite history file, just append to it.
|
||||
v463 7/13/14 Misc. fixes.
|
||||
v464 7/19/14 Fix bugs & improve performance in & filtering
|
||||
(thanks to John Sullivan).
|
||||
v465 8/9/14 More fixes from John Sullivan.
|
||||
v466 8/23/14 Add colon to LESSANSIMIDCHARS.
|
||||
v467 9/18/14 Misc. fixes.
|
||||
v468 9/18/14 Fix typo
|
||||
v469 10/2/14 Allow extra string in command to append to a multichar
|
||||
cmd without executing it; fix bug using GNU regex.
|
||||
v470 10/5/14 Fix some compiler warnings.
|
||||
v471 12/14/14 Fix unget issues with prompt. Allow disabling history
|
||||
when compiled value of LESSHISTFILE = "-".
|
||||
v473 12/19/14 Fix prompt bug with stdin and -^P in lesskey extra string.
|
||||
v474 1/30/15 Fix bug in backwards search with match on bottom line.
|
||||
Make follow mode reopen file if file shrinks.
|
||||
v475 3/2/15 Fix possible buffer overrun with invalid UTF-8;
|
||||
fix bug when compiled with no regex; fix non-match search.
|
||||
v476 5/3/15 Update man pages.
|
||||
v477 5/19/15 Fix off-by-one in jump_forw_buffered;
|
||||
don't add FAKE_* files to cmd history.
|
||||
v478 5/21/15 Fix nonportable pointer usage in hilite tree.
|
||||
v479 7/6/15 Allow %% escapes in LESSOPEN variable.
|
||||
v480 7/24/15 Fix bug in no-regex searches; support MSVC v1900.
|
||||
v481 8/20/15 Fix broken -g option.
|
||||
-----------------------------------------------------------------
|
||||
v482 2/25/16 Update Unicode database to "2015-06-16, 20:24:00 GMT [KW]".
|
||||
v483 2/27/16 Regenerate hilite when change search caselessness.
|
||||
(Thanks to Jason Hood)
|
||||
Fix bug when terminal has no "cm". (Thanks to Noel Cragg)
|
||||
v484 9/20/16 Update to Unicode 9.0.0 database.
|
||||
v485 10/21/16 Fix "nothing to search" bug when top/bottom line is empty;
|
||||
Display line numbers in bold. (thanks to Jason Hood);
|
||||
Fix incorrect display when entering double-width chars in
|
||||
search string.
|
||||
v486 10/22/16 New commands ESC-{ and ESC-} to shift to start/end of
|
||||
displayed lines; new option -Da in Windows version to
|
||||
enable SGR mode (thanks to Jason Hood).
|
||||
v487 10/23/16 configure --help formatting.
|
||||
-----------------------------------------------------------------
|
||||
v488 2/23/17 Fix memory leaks in search (thanks to John Brooks).
|
||||
v489 3/30/17 Make -F not do init/deinit if file fits on one screen
|
||||
(thanks to Jindrich Novy).
|
||||
v490 4/5/17 Switch to ANSI prototypes in funcs.h; remove "register".
|
||||
v491 4/7/17 Fix signed char bug.
|
||||
v492 4/21/17 Handle SIGTERM.
|
||||
v493 6/22/17 Fix bug initializing charset in MSDOS build.
|
||||
v494 6/26/17 Update Unicode tables; make Cf chars composing not binary.
|
||||
v495 7/3/17 Improve binary file detection (thanks to Bela Lubkin);
|
||||
do -R filter when matching tags (thanks to Matthew Malcomson).
|
||||
v496 7/5/17 Add LESSRSCROLL marker.
|
||||
v497 7/5/17 Sync.
|
||||
v498 7/7/17 Fix early truncation of text if last char is double-width.
|
||||
v499 7/10/17 Misc fixes.
|
||||
v500 7/11/17 Fix bug where certain env variables couldn't be set in lesskey.
|
||||
v501 7/12/17 Make sure rscroll char is standout by default.
|
||||
v502 7/13/17 Control rscroll char via command line option not env variable.
|
||||
v503 7/13/17 Switch to git.
|
||||
v504 7/13/17 Call opt_rscroll at startup; change mkhelp.c to mkhelp.pl.
|
||||
v505 7/17/17 Add M and ESC-M commands;
|
||||
fix buffer handling with stdin and LESSOPEN.
|
||||
v506 7/17/17 On Windows, convert UTF-8 to multibyte if console is not UTF-8;
|
||||
handle extended chars on input (thanks to Jason Hood).
|
||||
v507 7/18/17 Fix some bugs handling filenames containing shell metachars.
|
||||
v508 7/19/17 Fix bugs when using LESSOPEN to read stdin.
|
||||
v509 7/19/17 Fix another stdin bug.
|
||||
v510 7/20/17 Fix bug in determining when to reopen a file.
|
||||
v511 7/25/17 Fix bugs in recent MSDOS changes (thanks to Jason Hood).
|
||||
v512 7/26/17 Fix MSDOS build.
|
||||
v513 7/26/17 Fix switch to normal attr at end of line with -R and rscroll.
|
||||
v514 7/27/17 Fix bug in fcomplete when pattern does not match a file.
|
||||
v515 7/28/17 Allow 'u' in -D option on Windows.
|
||||
v516 7/29/17 Fix bug using LESSOPEN with filename containing metachars.
|
||||
v517 7/30/17 Status column shows matches even if hiliting is disabled via -G.
|
||||
v518 8/1/17 Use underline in sgr mode in MSDOS (thanks to Jason Hood).
|
||||
v519 8/10/17 Fix rscroll bug when last char of line starts coloration.
|
||||
v520 9/3/17 Fix compiler warning.
|
||||
v521 10/20/17 Fix binary file warning in UTF-8 files with SGI sequences.
|
||||
v522 10/20/17 Handle keypad ENTER key properly.
|
||||
v523 10/23/17 Cleanup.
|
||||
v524 10/24/17 Fix getcc bug.
|
||||
v525 10/24/17 Change M command to mark last displayed line.
|
||||
v526 10/25/17 Fix search hilite bug introduced in v517.
|
||||
v527 10/30/17 Fix search hilite bug on last page with -a.
|
||||
v528 11/3/17 Make second ESC-u clear status column.
|
||||
v529 11/12/17 Display Unicode formatting chars in hex if -U is set.
|
||||
v530 12/2/17 Minor doc change and add missing VOID_PARAM.
|
||||
-----------------------------------------------------------------
|
||||
v531 5/13/18 Fix bug with v on empty file; fix bug with v on file with
|
||||
metachars in name; add --nohistdups option.
|
||||
v532 7/27/18 Redraw screen on SIGWINCH even if screen size doesn't change.
|
||||
v533 8/1/18 Shell escape filenames in history; use PCRE_UTF8 flag;
|
||||
use wide-chars for Windows console title (thanks to Jason Hood).
|
||||
v534 8/9/18 Support PCRE2.
|
||||
v535 8/16/18 Don't count lines of initial screen if using -X with -F
|
||||
(thanks to Linus Torvalds).
|
||||
v536 8/31/18 Use descriptive error messages for PCRE2.
|
||||
v537 8/31/18 Support mingw build system (thanks to Mike Soyka).
|
||||
v538 9/3/18 Clean up some WIN32 code.
|
||||
v539 9/13/18 Fix spurious input on Windows with CAPSLOCK.
|
||||
v540 10/29/18 Add --mouse option.
|
||||
v541 10/30/18 Add --MOUSE option.
|
||||
v542 11/6/18 Add mouse support for WIN32; add --wheel-lines option.
|
||||
(thanks to Jason Hood).
|
||||
v543 11/12/18 Code cleanup.
|
||||
v544 11/16/18 Don't init/deinit keyboard/mouse if quit due to -F.
|
||||
v545 11/22/18 Fix Windows build, memory leaks.
|
||||
v546 11/29/18 Add --save-marks option.
|
||||
v547 11/30/18 Fix some bugs with saved marks.
|
||||
v548 12/14/18 Ignore mouse input when line editing.
|
||||
v549 2/10/19 Support X11 mouse extension 1006;
|
||||
Win32 fixes (thanks to Jason Hood).
|
||||
v550 2/16/19 Fix Win32 build; don't enable mouse unless --mouse is set.
|
||||
v551 6/10/19 Doc changes.
|
||||
-----------------------------------------------------------------
|
||||
v552 7/8/19 Update Unicode tables.
|
||||
v553 10/17/19 Support tinfow; handle zero-width Hangul chars.
|
||||
v554 1/19/20 Remove erroneous free().
|
||||
v555 3/15/20 Display error msg immediately when toggle -o without stdin.
|
||||
v556 3/15/20 Update copyright.
|
||||
v557 3/21/20 Fix memory corruption with libtermcap.
|
||||
v558 4/17/20 Don't init terminal if -F and file fits on one screen (WIN32).
|
||||
v559 4/19/20 Handle deinit correctly on WIN32.
|
||||
v560 5/3/20 Fix regression when command results in no movement;
|
||||
fix some less.nro issues (thanks to Bjarni I. Gislason).
|
||||
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.
|
||||
v582 4/21/21 Less now reads lesskey source file rather than binary;
|
||||
fix bug in finding tags with backslashes.
|
||||
v583 4/21/21 Use XDG_CONFIG_HOME and XDG_DATA_HOME to find files.
|
||||
v584 4/30/21 Add --file-size option.
|
||||
v585 5/2/21 Allow color desc W per man page.
|
||||
v586 5/7/21 Doc changes.
|
||||
v587 5/27/21 Fix --with-secure; fix --file-size message on Windows;
|
||||
fix colored search hilite in colored text; don't exit
|
||||
if -F and screen is resized; fix memcpy usage.
|
||||
v588 5/27/21 Fix release.
|
||||
v589 5/29/21 Copyright & build changes.
|
||||
v590 6/3/21 Fix non-autoconf Makefiles.
|
||||
v591 8/8/21 Use \kB for backspace key in lesskey; add more \k codes;
|
||||
handle multibyte chars in prompt.
|
||||
v592 8/24/21 Add --status-line option; limit use of /proc kludge; add --header.
|
||||
v593 8/30/21 Add header columns, --no-number-headers.
|
||||
v594 10/1/21 Let regex library handle caseless; add --redraw-on-quit option;
|
||||
add #version to lesskey.
|
||||
v595 10/12/21 Add H color type; add += to lesskey var section;
|
||||
add --search-options.
|
||||
v596 11/8/21 Look for lesskey in $HOME/.config.
|
||||
v597 11/16/21 Fix bugs in --header.
|
||||
v598 12/6/21 Look for lesshst in $XDG_STATE_HOME and $HOME/.local/state.
|
||||
v599 12/28/21 Defer moving to lower left in some cases;
|
||||
suppress TAB expansion in some cases.
|
||||
v600 1/7/22 Use /dev/tty if cannot open ttyname().
|
||||
v601 1/31/22 Add --exit-follow-on-close option.
|
||||
v602 3/1/22 Doc changes.
|
||||
v603 3/14/22 Fix --header.
|
||||
v604 5/14/22 Fix termlib detection; fix non-ASCII input on Windows.
|
||||
v605 6/14/22 Update version number.
|
||||
v606 7/17/22 Fix bug with multibyte chars and --incsearch;
|
||||
escape filenames in LESSCLOSE; fix bin_file overrun.
|
||||
v607 7/19/22 Update Unicode tables.
|
||||
v608 7/22/22 Fix highlighting on colored text boundaries.
|
||||
v609 11/10/22 Add LESSUTFCHARDEF; fix overstrike color bug;
|
||||
fix procfs bug; fix signal race.
|
||||
v610 11/14/22 Update Unicode tables; fix again-search after filter;
|
||||
improve ^X to interrupt F command.
|
||||
v611 11/16/22 Fix EOF bug related to ^X change.
|
||||
v612 11/18/22 Fix more bugs related to ^X change.
|
||||
v613 11/28/22 Even more ^X issues.
|
||||
v614 11/28/22 Add ^X to wait message.
|
||||
v615 11/30/22 Add --no-vbell option.
|
||||
v616 12/9/22 Don't open tty as input file without -f.
|
||||
v617 12/10/22 Support poll on newer versions of MacOS.
|
||||
v618 12/29/22 Add --no-search-headers option; use C89 function definitions.
|
||||
v619 12/30/22 Fix bug using 'n' before '/'.
|
||||
v620 1/12/23 Add --modelines option; add --intr option;
|
||||
add subpattern coloring.
|
||||
v621 1/15/23 Add --wordwrap option; add LESS_LINES & LESS_COLUMNS.
|
||||
v622 1/27/23 Add --show-preproc-errors option.
|
||||
v623 2/2/23 Add # command; add ^S search modifier.
|
||||
v624 2/11/23 Add --proc-backspace, --proc-tab and --proc-return options.
|
||||
v625 2/16/23 Minor fixes.
|
||||
v626 2/19/23 Fix rare crash in add_attr_normal.
|
||||
v627 2/19/23 Doc.
|
||||
v628 2/20/23 Don't require newline after +&...
|
||||
v629 2/26/23 Delay "waiting for data" message for 500 ms.
|
||||
v630 3/18/23 Add LESS_DATA_DELAY.
|
||||
v631 3/26/23 Fix input of dead keys on Windows.
|
||||
v632 4/6/23 Make lesstest work on MacOS; minor fixes.
|
||||
v633 5/3/23 Fix build on systems with ncurses/termcap.h or ncursesw/termcap.h.
|
||||
v634 5/29/23 Allow program piping into less to access tty;
|
||||
fix search modifier ^E after ^W.
|
||||
v635 6/2/23 Fix crash with ! search modifier.
|
||||
v636 6/18/23 Fix -D in MS-DOS build; fix mouse wheel in MS-DOS build.
|
||||
v637 6/28/23 Fix early EOF when SIGWINCH is received.
|
||||
v638 6/29/23 Fix compile error with ECHONL.
|
||||
v639 6/29/23 Fix SIGWINCH while reading tty.
|
||||
v640 7/10/23 Add lesstest to release.
|
||||
v641 7/10/23 Fix release.
|
||||
v642 7/10/23 Fix release.
|
||||
v643 7/20/23 Fix crash on Windows with -o.
|
||||
*/
|
||||
|
||||
char version[] = "643";
|
123
third_party/less/wide.inc
vendored
Normal file
123
third_party/less/wide.inc
vendored
Normal file
|
@ -0,0 +1,123 @@
|
|||
/* Generated by "./mkutable -f1 W F -- unicode/EastAsianWidth.txt" on Mon Nov 14 18:19:24 PST 2022 */
|
||||
{ 0x1100, 0x115f }, /* W */
|
||||
{ 0x231a, 0x231b }, /* W */
|
||||
{ 0x2329, 0x232a }, /* W */
|
||||
{ 0x23e9, 0x23ec }, /* W */
|
||||
{ 0x23f0, 0x23f0 }, /* W */
|
||||
{ 0x23f3, 0x23f3 }, /* W */
|
||||
{ 0x25fd, 0x25fe }, /* W */
|
||||
{ 0x2614, 0x2615 }, /* W */
|
||||
{ 0x2648, 0x2653 }, /* W */
|
||||
{ 0x267f, 0x267f }, /* W */
|
||||
{ 0x2693, 0x2693 }, /* W */
|
||||
{ 0x26a1, 0x26a1 }, /* W */
|
||||
{ 0x26aa, 0x26ab }, /* W */
|
||||
{ 0x26bd, 0x26be }, /* W */
|
||||
{ 0x26c4, 0x26c5 }, /* W */
|
||||
{ 0x26ce, 0x26ce }, /* W */
|
||||
{ 0x26d4, 0x26d4 }, /* W */
|
||||
{ 0x26ea, 0x26ea }, /* W */
|
||||
{ 0x26f2, 0x26f3 }, /* W */
|
||||
{ 0x26f5, 0x26f5 }, /* W */
|
||||
{ 0x26fa, 0x26fa }, /* W */
|
||||
{ 0x26fd, 0x26fd }, /* W */
|
||||
{ 0x2705, 0x2705 }, /* W */
|
||||
{ 0x270a, 0x270b }, /* W */
|
||||
{ 0x2728, 0x2728 }, /* W */
|
||||
{ 0x274c, 0x274c }, /* W */
|
||||
{ 0x274e, 0x274e }, /* W */
|
||||
{ 0x2753, 0x2755 }, /* W */
|
||||
{ 0x2757, 0x2757 }, /* W */
|
||||
{ 0x2795, 0x2797 }, /* W */
|
||||
{ 0x27b0, 0x27b0 }, /* W */
|
||||
{ 0x27bf, 0x27bf }, /* W */
|
||||
{ 0x2b1b, 0x2b1c }, /* W */
|
||||
{ 0x2b50, 0x2b50 }, /* W */
|
||||
{ 0x2b55, 0x2b55 }, /* W */
|
||||
{ 0x2e80, 0x2e99 }, /* W */
|
||||
{ 0x2e9b, 0x2ef3 }, /* W */
|
||||
{ 0x2f00, 0x2fd5 }, /* W */
|
||||
{ 0x2ff0, 0x2ffb }, /* W */
|
||||
{ 0x3000, 0x3000 }, /* F */
|
||||
{ 0x3001, 0x303e }, /* W */
|
||||
{ 0x3041, 0x3096 }, /* W */
|
||||
{ 0x3099, 0x30ff }, /* W */
|
||||
{ 0x3105, 0x312f }, /* W */
|
||||
{ 0x3131, 0x318e }, /* W */
|
||||
{ 0x3190, 0x31e3 }, /* W */
|
||||
{ 0x31f0, 0x321e }, /* W */
|
||||
{ 0x3220, 0x3247 }, /* W */
|
||||
{ 0x3250, 0x4dbf }, /* W */
|
||||
{ 0x4e00, 0xa48c }, /* W */
|
||||
{ 0xa490, 0xa4c6 }, /* W */
|
||||
{ 0xa960, 0xa97c }, /* W */
|
||||
{ 0xac00, 0xd7a3 }, /* W */
|
||||
{ 0xf900, 0xfaff }, /* W */
|
||||
{ 0xfe10, 0xfe19 }, /* W */
|
||||
{ 0xfe30, 0xfe52 }, /* W */
|
||||
{ 0xfe54, 0xfe66 }, /* W */
|
||||
{ 0xfe68, 0xfe6b }, /* W */
|
||||
{ 0xff01, 0xff60 }, /* F */
|
||||
{ 0xffe0, 0xffe6 }, /* F */
|
||||
{ 0x16fe0, 0x16fe4 }, /* W */
|
||||
{ 0x16ff0, 0x16ff1 }, /* W */
|
||||
{ 0x17000, 0x187f7 }, /* W */
|
||||
{ 0x18800, 0x18cd5 }, /* W */
|
||||
{ 0x18d00, 0x18d08 }, /* W */
|
||||
{ 0x1aff0, 0x1aff3 }, /* W */
|
||||
{ 0x1aff5, 0x1affb }, /* W */
|
||||
{ 0x1affd, 0x1affe }, /* W */
|
||||
{ 0x1b000, 0x1b122 }, /* W */
|
||||
{ 0x1b132, 0x1b132 }, /* W */
|
||||
{ 0x1b150, 0x1b152 }, /* W */
|
||||
{ 0x1b155, 0x1b155 }, /* W */
|
||||
{ 0x1b164, 0x1b167 }, /* W */
|
||||
{ 0x1b170, 0x1b2fb }, /* W */
|
||||
{ 0x1f004, 0x1f004 }, /* W */
|
||||
{ 0x1f0cf, 0x1f0cf }, /* W */
|
||||
{ 0x1f18e, 0x1f18e }, /* W */
|
||||
{ 0x1f191, 0x1f19a }, /* W */
|
||||
{ 0x1f200, 0x1f202 }, /* W */
|
||||
{ 0x1f210, 0x1f23b }, /* W */
|
||||
{ 0x1f240, 0x1f248 }, /* W */
|
||||
{ 0x1f250, 0x1f251 }, /* W */
|
||||
{ 0x1f260, 0x1f265 }, /* W */
|
||||
{ 0x1f300, 0x1f320 }, /* W */
|
||||
{ 0x1f32d, 0x1f335 }, /* W */
|
||||
{ 0x1f337, 0x1f37c }, /* W */
|
||||
{ 0x1f37e, 0x1f393 }, /* W */
|
||||
{ 0x1f3a0, 0x1f3ca }, /* W */
|
||||
{ 0x1f3cf, 0x1f3d3 }, /* W */
|
||||
{ 0x1f3e0, 0x1f3f0 }, /* W */
|
||||
{ 0x1f3f4, 0x1f3f4 }, /* W */
|
||||
{ 0x1f3f8, 0x1f43e }, /* W */
|
||||
{ 0x1f440, 0x1f440 }, /* W */
|
||||
{ 0x1f442, 0x1f4fc }, /* W */
|
||||
{ 0x1f4ff, 0x1f53d }, /* W */
|
||||
{ 0x1f54b, 0x1f54e }, /* W */
|
||||
{ 0x1f550, 0x1f567 }, /* W */
|
||||
{ 0x1f57a, 0x1f57a }, /* W */
|
||||
{ 0x1f595, 0x1f596 }, /* W */
|
||||
{ 0x1f5a4, 0x1f5a4 }, /* W */
|
||||
{ 0x1f5fb, 0x1f64f }, /* W */
|
||||
{ 0x1f680, 0x1f6c5 }, /* W */
|
||||
{ 0x1f6cc, 0x1f6cc }, /* W */
|
||||
{ 0x1f6d0, 0x1f6d2 }, /* W */
|
||||
{ 0x1f6d5, 0x1f6d7 }, /* W */
|
||||
{ 0x1f6dc, 0x1f6df }, /* W */
|
||||
{ 0x1f6eb, 0x1f6ec }, /* W */
|
||||
{ 0x1f6f4, 0x1f6fc }, /* W */
|
||||
{ 0x1f7e0, 0x1f7eb }, /* W */
|
||||
{ 0x1f7f0, 0x1f7f0 }, /* W */
|
||||
{ 0x1f90c, 0x1f93a }, /* W */
|
||||
{ 0x1f93c, 0x1f945 }, /* W */
|
||||
{ 0x1f947, 0x1f9ff }, /* W */
|
||||
{ 0x1fa70, 0x1fa7c }, /* W */
|
||||
{ 0x1fa80, 0x1fa88 }, /* W */
|
||||
{ 0x1fa90, 0x1fabd }, /* W */
|
||||
{ 0x1fabf, 0x1fac5 }, /* W */
|
||||
{ 0x1face, 0x1fadb }, /* W */
|
||||
{ 0x1fae0, 0x1fae8 }, /* W */
|
||||
{ 0x1faf0, 0x1faf8 }, /* W */
|
||||
{ 0x20000, 0x2fffd }, /* W */
|
||||
{ 0x30000, 0x3fffd }, /* W */
|
163
third_party/less/xbuf.c
vendored
Normal file
163
third_party/less/xbuf.c
vendored
Normal file
|
@ -0,0 +1,163 @@
|
|||
#include "less.h"
|
||||
#include "xbuf.h"
|
||||
|
||||
/*
|
||||
* Initialize an expandable text buffer.
|
||||
*/
|
||||
public void xbuf_init(struct xbuffer *xbuf)
|
||||
{
|
||||
xbuf->data = NULL;
|
||||
xbuf->size = xbuf->end = 0;
|
||||
}
|
||||
|
||||
public void xbuf_deinit(struct xbuffer *xbuf)
|
||||
{
|
||||
if (xbuf->data != NULL)
|
||||
free(xbuf->data);
|
||||
xbuf_init(xbuf);
|
||||
}
|
||||
|
||||
public void xbuf_reset(struct xbuffer *xbuf)
|
||||
{
|
||||
xbuf->end = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a byte to an expandable text buffer.
|
||||
*/
|
||||
public void xbuf_add_byte(struct xbuffer *xbuf, unsigned char b)
|
||||
{
|
||||
if (xbuf->end >= xbuf->size)
|
||||
{
|
||||
unsigned char *data;
|
||||
if (ckd_add(&xbuf->size, xbuf->size, xbuf->size ? xbuf->size : 16))
|
||||
out_of_memory();
|
||||
data = (unsigned char *) ecalloc(xbuf->size, sizeof(unsigned char));
|
||||
if (xbuf->data != NULL)
|
||||
{
|
||||
memcpy(data, xbuf->data, xbuf->end);
|
||||
free(xbuf->data);
|
||||
}
|
||||
xbuf->data = data;
|
||||
}
|
||||
xbuf->data[xbuf->end++] = (unsigned char) b;
|
||||
}
|
||||
|
||||
public void xbuf_add_data(struct xbuffer *xbuf, unsigned char *data, int len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < len; i++)
|
||||
xbuf_add_byte(xbuf, data[i]);
|
||||
}
|
||||
|
||||
public int xbuf_pop(struct xbuffer *buf)
|
||||
{
|
||||
if (buf->end == 0)
|
||||
return -1;
|
||||
return (int) buf->data[--(buf->end)];
|
||||
}
|
||||
|
||||
public void xbuf_set(struct xbuffer *dst, struct xbuffer *src)
|
||||
{
|
||||
xbuf_reset(dst);
|
||||
xbuf_add_data(dst, src->data, src->end);
|
||||
}
|
||||
|
||||
public char * xbuf_char_data(struct xbuffer *xbuf)
|
||||
{
|
||||
return (char *)(xbuf->data);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Helper functions for the ckd_add and ckd_mul macro substitutes.
|
||||
* These helper functions do not set *R on overflow, and assume that
|
||||
* arguments are nonnegative, that INTMAX_MAX <= UINTMAX_MAX, and that
|
||||
* sizeof is a reliable way to distinguish integer representations.
|
||||
* Despite these limitations they are good enough for 'less' on all
|
||||
* known practical platforms. For more-complicated substitutes
|
||||
* without most of these limitations, see Gnulib's stdckdint module.
|
||||
*/
|
||||
#if !HAVE_STDCKDINT_H
|
||||
/*
|
||||
* If the integer *R can represent VAL, store the value and return FALSE.
|
||||
* Otherwise, possibly set *R to an indeterminate value and return TRUE.
|
||||
* R has size RSIZE, and is signed if and only if RSIGNED is nonzero.
|
||||
*/
|
||||
static int help_fixup(void *r, uintmax val, int rsize, int rsigned)
|
||||
{
|
||||
if (rsigned)
|
||||
{
|
||||
if (rsize == sizeof (int))
|
||||
{
|
||||
int *pr = r;
|
||||
if (INT_MAX < val)
|
||||
return TRUE;
|
||||
*pr = (int) val;
|
||||
#ifdef LLONG_MAX
|
||||
} else if (rsize == sizeof (long long))
|
||||
{
|
||||
long long *pr = r;
|
||||
if (LLONG_MAX < val)
|
||||
return TRUE;
|
||||
*pr = val;
|
||||
#endif
|
||||
#ifdef INTMAX_MAX
|
||||
} else if (rsize == sizeof (intmax_t)) {
|
||||
intmax_t *pr = r;
|
||||
if (INTMAX_MAX < val)
|
||||
return TRUE;
|
||||
*pr = val;
|
||||
#endif
|
||||
} else /* rsize == sizeof (long) */
|
||||
{
|
||||
long *pr = r;
|
||||
if (LONG_MAX < val)
|
||||
return TRUE;
|
||||
*pr = (long) val;
|
||||
}
|
||||
} else {
|
||||
if (rsize == sizeof (unsigned)) {
|
||||
unsigned *pr = r;
|
||||
if (UINT_MAX < val)
|
||||
return TRUE;
|
||||
*pr = (unsigned) val;
|
||||
} else if (rsize == sizeof (unsigned long)) {
|
||||
unsigned long *pr = r;
|
||||
if (ULONG_MAX < val)
|
||||
return TRUE;
|
||||
*pr = (unsigned long) val;
|
||||
#ifdef ULLONG_MAX
|
||||
} else if (rsize == sizeof (unsigned long long)) {
|
||||
long long *pr = r;
|
||||
if (ULLONG_MAX < val)
|
||||
return TRUE;
|
||||
*pr = val;
|
||||
#endif
|
||||
} else /* rsize == sizeof (uintmax) */
|
||||
{
|
||||
uintmax *pr = r;
|
||||
*pr = val;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
/*
|
||||
* If *R can represent the mathematical sum of A and B, store the sum
|
||||
* and return FALSE. Otherwise, possibly set *R to an indeterminate
|
||||
* value and return TRUE. R has size RSIZE, and is signed if and only
|
||||
* if RSIGNED is nonzero.
|
||||
*/
|
||||
public int help_ckd_add(void *r, uintmax a, uintmax b, int rsize, int rsigned)
|
||||
{
|
||||
uintmax sum = a + b;
|
||||
return sum < a || help_fixup(r, sum, rsize, rsigned);
|
||||
}
|
||||
/* Likewise, but for the product of A and B. */
|
||||
public int help_ckd_mul(void *r, uintmax a, uintmax b, int rsize, int rsigned)
|
||||
{
|
||||
uintmax product = a * b;
|
||||
return ((b != 0 && a != product / b)
|
||||
|| help_fixup(r, product, rsize, rsigned));
|
||||
}
|
||||
#endif
|
19
third_party/less/xbuf.h
vendored
Normal file
19
third_party/less/xbuf.h
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
#ifndef XBUF_H_
|
||||
#define XBUF_H_
|
||||
|
||||
struct xbuffer
|
||||
{
|
||||
unsigned char *data;
|
||||
int end;
|
||||
int size;
|
||||
};
|
||||
|
||||
void xbuf_init(struct xbuffer *xbuf);
|
||||
void xbuf_deinit(struct xbuffer *xbuf);
|
||||
void xbuf_reset(struct xbuffer *xbuf);
|
||||
void xbuf_add_byte(struct xbuffer *xbuf, unsigned char b);
|
||||
void xbuf_add_data(struct xbuffer *xbuf, unsigned char *data, int len);
|
||||
int xbuf_pop(struct xbuffer *xbuf);
|
||||
char *xbuf_char_data(struct xbuffer *xbuf);
|
||||
|
||||
#endif
|
2853
third_party/ncurses/read_entry.c
vendored
2853
third_party/ncurses/read_entry.c
vendored
File diff suppressed because it is too large
Load diff
2853
third_party/ncurses/read_termcap.c
vendored
2853
third_party/ncurses/read_termcap.c
vendored
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue