commands: less is more.
This commit is contained in:
@@ -15,7 +15,7 @@ SUBDIR= aal add_route adduser advent arp ash at autil awk \
|
||||
fsck1 ftp101 ftpd200 getty grep gomoku head host \
|
||||
hostaddr id ifconfig ifdef indent install \
|
||||
intr ipcrm ipcs irdpd isoread join kill last leave \
|
||||
lex life loadkeys loadramdisk logger login look lp \
|
||||
less lex life loadkeys loadramdisk logger login look lp \
|
||||
lpd ls lspci M m4 mail make MAKEDEV man \
|
||||
mdb mesg mined mkdep mkdir mkdist mkfifo mkfs mknod \
|
||||
mkproto modem mount mt netconf newroot nice nm nohup \
|
||||
|
||||
5
commands/less/Makefile
Normal file
5
commands/less/Makefile
Normal file
@@ -0,0 +1,5 @@
|
||||
# $NetBSD: Makefile,v 1.2 1999/03/24 09:15:20 mrg Exp $
|
||||
|
||||
SUBDIR=less lesskey lessecho
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
7
commands/less/Makefile.inc
Normal file
7
commands/less/Makefile.inc
Normal file
@@ -0,0 +1,7 @@
|
||||
# $NetBSD: Makefile.inc,v 1.3 2001/07/26 14:20:47 mrg Exp $
|
||||
|
||||
.if exists(${.CURDIR}/../../Makefile.inc)
|
||||
.include "${.CURDIR}/../../Makefile.inc"
|
||||
.endif
|
||||
|
||||
CWARNFLAGS+= -Wno-strict-prototypes -Wno-missing-prototypes
|
||||
186
commands/less/less/INSTALL
Normal file
186
commands/less/less/INSTALL
Normal file
@@ -0,0 +1,186 @@
|
||||
This file describes how to build and install less using
|
||||
the "configure" script. This only works on Unix systems.
|
||||
To install on other systems, read the README file.
|
||||
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
These are generic installation instructions.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a `Makefile' in each directory of the package.
|
||||
It may also create one or more `.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script `config.status' that
|
||||
you can run in the future to recreate the current configuration, a file
|
||||
`config.cache' that saves the results of its tests to speed up
|
||||
reconfiguring, and a file `config.log' containing compiler output
|
||||
(useful mainly for debugging `configure').
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the `README' so they can
|
||||
be considered for the next release. If at some point `config.cache'
|
||||
contains results you don't want to keep, you may remove or edit it.
|
||||
|
||||
The file `configure.in' is used to create `configure' by a program
|
||||
called `autoconf'. You only need `configure.in' if you want to change
|
||||
it or regenerate `configure' using a newer version of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system. If you're
|
||||
using `csh' on an old version of System V, you might need to type
|
||||
`sh ./configure' instead to prevent `csh' from trying to execute
|
||||
`configure' itself.
|
||||
|
||||
Running `configure' takes awhile. While running, it prints some
|
||||
messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
|
||||
3. Optionally, type `make check' to run any self-tests that come with
|
||||
the package.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation.
|
||||
|
||||
5. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'. There is
|
||||
also a `make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that
|
||||
the `configure' script does not know about. You can give `configure'
|
||||
initial values for variables by setting them in the environment. Using
|
||||
a Bourne-compatible shell, you can do that on the command line like
|
||||
this:
|
||||
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
|
||||
|
||||
Or on systems that have the `env' program, you can do it like this:
|
||||
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
|
||||
|
||||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you must use a version of `make' that
|
||||
supports the `VPATH' variable, such as GNU `make'. `cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'.
|
||||
|
||||
If you have to use a `make' that does not supports the `VPATH'
|
||||
variable, you have to compile the package for one architecture at a time
|
||||
in the source code directory. After you have installed the package for
|
||||
one architecture, use `make distclean' before reconfiguring for another
|
||||
architecture.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' will install the package's files in
|
||||
`/usr/local/bin', `/usr/local/man', etc. You can specify an
|
||||
installation prefix other than `/usr/local' by giving `configure' the
|
||||
option `--prefix=PATH'.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
give `configure' the option `--exec-prefix=PATH', the package will use
|
||||
PATH as the prefix for installing programs and libraries.
|
||||
Documentation and other data files will still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=PATH' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them.
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
`README' should mention any `--enable-' and `--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, `configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' can not figure out
|
||||
automatically, but needs to determine by the type of host the package
|
||||
will run on. Usually `configure' can figure that out, but if it prints
|
||||
a message saying it can not guess the host type, give it the
|
||||
`--host=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name with three fields:
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the host type.
|
||||
|
||||
If you are building compiler tools for cross-compiling, you can also
|
||||
use the `--target=TYPE' option to select the type of system they will
|
||||
produce code for and the `--build=TYPE' option to select the type of
|
||||
system on which you are compiling the package.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share,
|
||||
you can create a site shell script called `config.site' that gives
|
||||
default values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all `configure' scripts look for a site script.
|
||||
|
||||
Operation Controls
|
||||
==================
|
||||
|
||||
`configure' recognizes the following options to control how it
|
||||
operates.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Use and save the results of the tests in FILE instead of
|
||||
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
|
||||
debugging `configure'.
|
||||
|
||||
`--help'
|
||||
Print a summary of the options to `configure', and exit.
|
||||
|
||||
`--quiet'
|
||||
`--silent'
|
||||
`-q'
|
||||
Do not print messages saying which checks are being made.
|
||||
|
||||
`--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
|
||||
`--version'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options.
|
||||
|
||||
27
commands/less/less/LICENSE
Normal file
27
commands/less/less/LICENSE
Normal file
@@ -0,0 +1,27 @@
|
||||
Less License
|
||||
------------
|
||||
|
||||
Less
|
||||
Copyright (C) 1984-2005 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.
|
||||
|
||||
20
commands/less/less/Makefile
Normal file
20
commands/less/less/Makefile
Normal file
@@ -0,0 +1,20 @@
|
||||
# $NetBSD: Makefile,v 1.11 2006/11/20 22:06:26 dsl Exp $
|
||||
# from: @(#)Makefile 5.6 (Berkeley) 3/12/91
|
||||
|
||||
.ifdef SMALLPROG
|
||||
CPPFLAGS+=-DSMALL
|
||||
.endif
|
||||
|
||||
PROG= less
|
||||
CPPFLAGS+=-I${.CURDIR} -I${.CURDIR}/../lesskey -DSYSDIR=\"/etc\"
|
||||
SRCS= brac.c ch.c charset.c cmdbuf.c command.c decode.c edit.c \
|
||||
filename.c forwback.c help.c ifile.c input.c jump.c line.c \
|
||||
linenum.c lsystem.c main.c mark.c optfunc.c option.c opttbl.c \
|
||||
os.c output.c position.c prompt.c screen.c search.c signal.c \
|
||||
tags.c ttyin.c version.c
|
||||
#LDADD+= -ltermcap
|
||||
DPADD+= ${LIBTERM}
|
||||
MLINKS= less.1 more.1 less.1 page.1
|
||||
LINKS= ${BINDIR}/less ${BINDIR}/more ${BINDIR}/less ${BINDIR}/page
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
634
commands/less/less/NEWS
Normal file
634
commands/less/less/NEWS
Normal file
@@ -0,0 +1,634 @@
|
||||
|
||||
NEWS about less
|
||||
|
||||
======================================================================
|
||||
|
||||
For the latest news about less, see the "less" Web page:
|
||||
http://www.greenwoodsoftware.com/less
|
||||
You can also download the latest version of less from there.
|
||||
|
||||
To report bugs, suggestions or comments, send email to bug-less@gnu.org.
|
||||
|
||||
======================================================================
|
||||
|
||||
|
||||
Major changes between "less" versions 382 and 394
|
||||
|
||||
* Add history file to save search and shell command history between
|
||||
invocations of less.
|
||||
|
||||
* Improve behavior of history list for search and shell commands.
|
||||
|
||||
* Add -K (or --quit-on-intr) option to make less exit immediately on ctrl-C.
|
||||
|
||||
* Improve handling of UTF-8 files and commands, including better
|
||||
line wrapping and handling double-width chars.
|
||||
|
||||
* Added LESSUTFBINFMT environment variable to control display of
|
||||
non-printable characters in a UTF-8 file.
|
||||
|
||||
* Add --with-secure option to configure, to make it easier to
|
||||
build a secure version of less.
|
||||
|
||||
* Show search matches in the status column even if search highlights
|
||||
are disabled via the -G option or the ESC-u command.
|
||||
|
||||
* Improve performance when the file contains very long lines.
|
||||
|
||||
* Add "windows" charset.
|
||||
|
||||
* Add man page for lessecho.
|
||||
|
||||
* Add support for erase2 character, treated same as erase.
|
||||
|
||||
* Use ASCII lowercase/uppercase logic when operating on the command line.
|
||||
|
||||
* Update makefile for Borland C++ 5.5.1.
|
||||
|
||||
* Fix bug in calculating number of pages for %D prompt.
|
||||
|
||||
* Fix bug in handling tag file error.
|
||||
|
||||
* Fix obscure bug if input file is deleted while viewing help.
|
||||
|
||||
* Fix bug handling filenames which include square brackets.
|
||||
|
||||
* Fix possible buffer overflow in "global" tag search.
|
||||
|
||||
* Fix possible buffer overflow in usage of LESSOPEN and LESSCLOSE.
|
||||
|
||||
* Fix buffer overflow in reverse search.
|
||||
|
||||
======================================================================
|
||||
|
||||
Major changes between "less" versions 381 and 382
|
||||
|
||||
* Removed some old copyrighted code.
|
||||
This probably breaks OS/9 support.
|
||||
|
||||
======================================================================
|
||||
|
||||
Major changes between "less" versions 378 and 381
|
||||
|
||||
* New -L option to disable LESSOPEN processing.
|
||||
|
||||
* Further support for large (64 bit) file addressing.
|
||||
Large file support is now set up by the configure script.
|
||||
|
||||
* Use autoconf 2.54.
|
||||
Replace configure.in, acconfig.h, defines.h.top with configure.ac.
|
||||
|
||||
* Overstriking underscore with underscore is now bold or underlined
|
||||
depending on context.
|
||||
|
||||
* Use only 7 spaces for line numbers in -N mode, if possible.
|
||||
|
||||
* Fix some bugs in handling overstriking in UTF-8 files.
|
||||
|
||||
* Fix some nroff issues in the man page.
|
||||
|
||||
======================================================================
|
||||
|
||||
Major changes between "less" versions 376 and 378
|
||||
|
||||
* Bug fixes:
|
||||
Default buffer space is now 64K as documented.
|
||||
Search highlighting works properly when used with -R.
|
||||
Windows version works properly when input file contains carriage returns.
|
||||
Clean up some compiler warnings.
|
||||
|
||||
======================================================================
|
||||
|
||||
Major changes between "less" versions 358 and 376
|
||||
|
||||
* -x option can now specify multiple variable-width tab stops.
|
||||
|
||||
* -X option no longer disables keypad initialization.
|
||||
New option --no-keypad disables keypad initialization.
|
||||
|
||||
* New commands t and T step through multiple tag matches.
|
||||
Added support for "global(1)" tags
|
||||
(see http://www.gnu.org/software/global/global.html).
|
||||
|
||||
* New prompt style set by option -Pw defines the message printed
|
||||
while waiting for data in the F command.
|
||||
|
||||
* System-wide lesskey file now defaults to sysless in etc directory
|
||||
instead of .sysless in bin directory.
|
||||
Use "configure --sysconfdir=..." to change it.
|
||||
(For backwards compatibility, .sysless in bin is still recognized.)
|
||||
|
||||
* Pressing RightArrow or LeftArrow while entering a number now shifts
|
||||
the display N columns rather than editing the number itself.
|
||||
|
||||
* Status column (enabled with -J) now shows search results.
|
||||
|
||||
* Windows version sets window title.
|
||||
|
||||
* Default LESSCHARSET for MS-DOS versions is now "dos".
|
||||
|
||||
* Searching works better with ANSI (SGR) escape sequences.
|
||||
ANSI color escape sequences are now supported in the MS-DOS (DJGPP) version.
|
||||
|
||||
* Improved performance in reading very large pipes.
|
||||
|
||||
* Eliminated some dependencies on file offets being 32 bits.
|
||||
|
||||
* Fixed problems when viewing files with very long lines.
|
||||
|
||||
* Fixed overstriking in UTF-8 mode, and overstriking tabs.
|
||||
|
||||
* Improved horizontal shifting of text using -R option with ANSI color.
|
||||
|
||||
* Improved handling of filenames containing shell metacharacters.
|
||||
|
||||
* Some fixes for EBCDIC systems.
|
||||
|
||||
* Some fixes for OS/2 systems.
|
||||
|
||||
======================================================================
|
||||
|
||||
Major changes between "less" versions 354 and 358
|
||||
|
||||
* Add -J (--status-column) option to display a status column.
|
||||
|
||||
* Add -# (--shift) option to set default horizontal shift distance.
|
||||
Default horizontal shift distance is now one-half screen width.
|
||||
|
||||
* Horizontal shifting does not shift line numbers if -N is in effect.
|
||||
|
||||
* Horizontal shifting acts as though -S were set, to avoid confusion.
|
||||
|
||||
======================================================================
|
||||
|
||||
|
||||
Major changes between "less" versions 352 and 354
|
||||
|
||||
* Allow space after numeric-valued command line options.
|
||||
|
||||
* Fix problem with configuring terminal libraries on some systems.
|
||||
|
||||
* Add support for PCRE regular expression library.
|
||||
|
||||
* Add --with-regex option to configure to allow manually selecting
|
||||
a regular expression library.
|
||||
|
||||
* Fix bug compiling with SECURE = 1.
|
||||
|
||||
======================================================================
|
||||
|
||||
|
||||
Major changes between "less" versions 346 and 352
|
||||
|
||||
* Enable UTF-8 if "UTF-8" appears in locale-related environment variables.
|
||||
|
||||
* Add --with-editor option to configure script.
|
||||
|
||||
* The -M prompt and = message now show the top and bottom line number.
|
||||
|
||||
* Fix bug in running the editor on a file whose name contains quotes, etc.
|
||||
|
||||
* Fix bug in horizontal scrolling of long lines.
|
||||
|
||||
* Fix bug in doing :d on a file which contains marks.
|
||||
|
||||
* Fix bug causing cleared lines to sometimes be filled with standout,
|
||||
bold, underline, etc. on certain terminals.
|
||||
|
||||
* Fixes for MS-DOS (DJGPP) version.
|
||||
|
||||
======================================================================
|
||||
|
||||
|
||||
Major changes between "less" versions 340 and 346
|
||||
|
||||
* The UTF-8 character set is now supported.
|
||||
|
||||
* The default character set is now latin1 rather than ascii.
|
||||
|
||||
* New option -R (--RAW-CONTROL-CHARS) is like -r but handles
|
||||
long (wrapped) lines correctly, as long as the input contains only
|
||||
normal text and ANSI color escape sequences.
|
||||
|
||||
* New option -F (--quit-if-one-screen) quits if the text fits on
|
||||
the first screen.
|
||||
|
||||
* The -w option now highlights the target line of a g or p command.
|
||||
|
||||
* A system-wide lesskey file is supported (LESSKEY_SYSTEM).
|
||||
|
||||
* New escape for prompt strings: %c is replaced by column number.
|
||||
|
||||
* New escape for prompt strings: %P is replaced by percentage into
|
||||
file, based on line number rather than byte offset.
|
||||
|
||||
* HOME and END keys now jump to beginning of file or end of file.
|
||||
|
||||
======================================================================
|
||||
|
||||
|
||||
Major changes between "less" versions 337 and 340
|
||||
|
||||
* Command line options for less may now be given in either the old
|
||||
single-letter form, or a new long name form (--option-name).
|
||||
See the less man page or "less --help" for the list of long option names.
|
||||
|
||||
* Command line options for lesskey may now be given in a new long name
|
||||
form. See the lesskey man page for the list of long option names.
|
||||
|
||||
* New command -- toggles an option using the long option name.
|
||||
|
||||
* New command __ queries an option using the long option name.
|
||||
|
||||
* The old -- command is renamed as -!.
|
||||
|
||||
* If a ^P is entered between the dash and the option letter of the -
|
||||
command, the message describing the new setting is suppressed.
|
||||
|
||||
* Lesskey files may now contain \k escape sequences to represent the
|
||||
"special" keys (arrows, PAGE-UP/PAGE-DOWN, HOME, END, INSERT, DELETE).
|
||||
|
||||
* New command :d removes the current file from the list of files.
|
||||
|
||||
* New option -~ (like -w before version 335)
|
||||
suppresses tildes after end-of-file.
|
||||
|
||||
* Less is now released under the GNU General Public License.
|
||||
|
||||
======================================================================
|
||||
|
||||
|
||||
Major changes between "less" versions 335 and 337
|
||||
|
||||
* Fixed bugs in "make install".
|
||||
|
||||
======================================================================
|
||||
|
||||
|
||||
Major changes between "less" versions 332 and 335
|
||||
|
||||
* The old -w flag (suppress tildes after end-of-file) has been removed.
|
||||
|
||||
* New -w flag highlights the first new line after a forward-screen.
|
||||
|
||||
* New -W flag highlights the first new line after any forward movement.
|
||||
|
||||
* Window resize works even if LINES and/or COLUMNS environment
|
||||
variables are incorrect.
|
||||
|
||||
* New percent escapes for prompt strings:
|
||||
%d is replaced by the page number, and
|
||||
%D is replaced by the number of pages in the file.
|
||||
|
||||
* Added charsets "iso8859" and "ebcdic".
|
||||
|
||||
* In Windows version, uses HOMEDRIVE and HOMEPATH if HOME is not defined.
|
||||
|
||||
* Fixed some bugs causing incorrect display on DOS/Windows.
|
||||
|
||||
======================================================================
|
||||
|
||||
|
||||
Major changes between "less" versions 330 and 332
|
||||
|
||||
* Filenames from the command line are entered into the command history,
|
||||
so UPARROW/DOWNARROW can be used to retrieve them from the :e command.
|
||||
|
||||
* Now works correctly on Windows when using a scrolling terminal
|
||||
window (buffer larger than display window).
|
||||
|
||||
* On Windows, now restores the console screen on exit.
|
||||
Use -X to get the old behavior.
|
||||
|
||||
* Fixed bug on Windows when CAPS-LOCK or NUM-LOCK is pressed.
|
||||
|
||||
* Fixed bug on Windows when piping output of an interactive program.
|
||||
|
||||
* Fixed bug in tags file processing when tags file has DOS-style
|
||||
line terminators (CR/LF).
|
||||
|
||||
* Fixed compilation problem on OS/2.
|
||||
|
||||
======================================================================
|
||||
|
||||
|
||||
Major changes between "less" versions 321 and 330
|
||||
|
||||
* Now supports filenames containing spaces (in double quotes).
|
||||
New option -" can be used to change the quoting characters.
|
||||
|
||||
* In filename completion, a slash is appended to a directory name.
|
||||
If the environment variable LESSSEPARATOR is set, the value of
|
||||
that variable, rather than a slash, is appended.
|
||||
|
||||
* LeftArrow and RightArrow are same as ESC-[ and ESC-].
|
||||
|
||||
* Added commands ESC-( and ESC-), same as ESC-[ and ESC-].
|
||||
|
||||
* A "quit" command defined in a lesskey file may now have an "extra"
|
||||
string, which is used to return an exit code from less when it quits.
|
||||
|
||||
* New environment variables LESSMETACHARS and LESSMETAESCAPE provide
|
||||
more control over how less interfaces to the shell.
|
||||
|
||||
* Ported to Microsoft Visual C compiler for Windows.
|
||||
|
||||
* Ported to DJGPP compiler for MS-DOS.
|
||||
|
||||
* Bug fixes.
|
||||
|
||||
======================================================================
|
||||
|
||||
|
||||
Major changes between "less" versions 291 and 321
|
||||
|
||||
* Command line at bottom of screen now scrolls, so it can be longer
|
||||
than the screen width.
|
||||
|
||||
* New commands ESC-] and ESC-[ scroll the display horizontally.
|
||||
|
||||
* New command ESC-SPACE scrolls forward a full screen, even if it
|
||||
hits end-of-file.
|
||||
|
||||
* Alternate modifiers for search commands: ^N is same as !,
|
||||
^F is same as @, and ^E is same as *.
|
||||
|
||||
* New modifier for search commands: ^K means highlight the matches
|
||||
currently on-screen, but don't move to the first match.
|
||||
|
||||
* New modifier for search commands: ^R means don't use regular
|
||||
expressions in the search.
|
||||
|
||||
* Environment variable LESSKEY gives name of default lesskey file.
|
||||
|
||||
* Environment variable LESSSECURE will force less to run in
|
||||
"secure" mode.
|
||||
|
||||
* Command line argument "--" signals that the rest of the arguments
|
||||
are files (not option flags).
|
||||
|
||||
* Help file (less.hlp) is no longer installed. Help text is now
|
||||
embedded in the less executable itself.
|
||||
|
||||
* Added -Ph to change the prompt for the help text.
|
||||
Added -Ps to change the default short prompt (same as plain -P).
|
||||
|
||||
* Ported to the Borland C compiler for MS-DOS.
|
||||
|
||||
* Ported to Windows 95 & Windows NT.
|
||||
|
||||
* Ported to OS-9.
|
||||
|
||||
* Ported to GNU Hurd.
|
||||
|
||||
======================================================================
|
||||
|
||||
|
||||
Major changes between "less" versions 290 and 291
|
||||
|
||||
* Less environment variables can be specified in lesskey files.
|
||||
|
||||
* Fixed MS-DOS build.
|
||||
|
||||
======================================================================
|
||||
|
||||
|
||||
Major changes between "less" versions 278 and 290
|
||||
|
||||
* Accepts GNU-style options "--help" and "--version".
|
||||
|
||||
* OS/2 version looks for less.ini in $HOME before $INIT and $PATH.
|
||||
|
||||
* Bug fixes
|
||||
|
||||
======================================================================
|
||||
|
||||
|
||||
Major changes between "less" versions 252 and 278
|
||||
|
||||
* A LESSOPEN preprocessor may now pipe the converted file data to less,
|
||||
rather than writing it to a temporary file.
|
||||
|
||||
* Search pattern highlighting has been fixed. It now highlights
|
||||
reliably, even if a string is split across two screen lines,
|
||||
contains TABs, etc.
|
||||
|
||||
* The -F flag (which suppress search highlighting) has been changed
|
||||
to -G. A new flag, -g, changes search highlighting to highlight
|
||||
only the string found by the last search command, instead of all
|
||||
strings which match the last search command.
|
||||
|
||||
* New flag -I acts like -i, but ignores case even if the search
|
||||
pattern contains uppercase letters.
|
||||
|
||||
* Less now checks for the environment variable VISUAL before EDITOR.
|
||||
|
||||
* Ported to OS/2.
|
||||
|
||||
======================================================================
|
||||
|
||||
|
||||
Major changes between "less" versions 237 and 252
|
||||
|
||||
* Changes in line-editing keys:
|
||||
The literal key is now ^V or ^A rather than \ (backslash).
|
||||
Filename completion commands (TAB and ^L) are disabled
|
||||
when typing a search pattern.
|
||||
|
||||
* Line-editing command keys can be redefined using lesskey.
|
||||
|
||||
* Lesskey with no input file defaults to $HOME/.lesskey
|
||||
rather than standard input.
|
||||
|
||||
* New option -V displays version number of less.
|
||||
|
||||
* New option -V displays version number of lesskey.
|
||||
|
||||
* Help file less.hlp is now installed by default in /usr/local/share
|
||||
rather than /usr/local/lib.
|
||||
|
||||
|
||||
======================================================================
|
||||
|
||||
|
||||
Major changes between "less" versions 170 and 237
|
||||
|
||||
* By popular demand, text which matches the current search pattern
|
||||
is highlighted. New -F flag disables this feature.
|
||||
|
||||
* Henry Spencer's regexp.c is now included, for systems which do not
|
||||
have a regular expression library.
|
||||
regexp.c is Copyright (c) 1986 by University of Toronto.
|
||||
|
||||
* New line-editing keys, including command history (arrow keys) and
|
||||
filename completion (TAB).
|
||||
|
||||
* Input preprocessor allows modification of input files (e.g. uncompress)
|
||||
via LESSOPEN/LESSCLOSE environment variables.
|
||||
|
||||
* New -X flag disables sending termcap "ti" and "te" (initialize and
|
||||
deinitialize) strings to the terminal.
|
||||
|
||||
* Changing -i from within less now correctly affects a subsequent
|
||||
repeated search.
|
||||
|
||||
* Searching for underlined or overstruck text now works when the -u
|
||||
flag is in effect, rather than the -i flag.
|
||||
|
||||
* Use setlocale (LANG and LC_CTYPE environment variables) to determine
|
||||
the character set if LESSCHARSET/LESSCHARDEF are not set.
|
||||
|
||||
* The default format for displaying binary characters is now standout
|
||||
(reverse video) rather than blinking. This can still be changed by
|
||||
setting the LESSBINFMT environment variable.
|
||||
|
||||
* Use autoconf installation technology.
|
||||
|
||||
* Ported to MS-DOS.
|
||||
|
||||
********************************
|
||||
Things that may surprise you
|
||||
********************************
|
||||
|
||||
* When you enter text at the bottom of the screen (search string,
|
||||
filename, etc.), some keys act different than previously.
|
||||
Specifically, \ (backslash), ESC, TAB, BACKTAB, and control-L
|
||||
now have line editing functions.
|
||||
|
||||
* Some previous unofficial versions of less were able to display
|
||||
compressed files. The new LESSOPEN/LESSCLOSE feature now provides
|
||||
this functionality in a different way.
|
||||
|
||||
* Some previous unofficial versions of less provided a -Z flag to
|
||||
set the number of lines of text to retain between full screen scrolls.
|
||||
The -z-n flag (that is, -z with a negative number) provides this
|
||||
functionality.
|
||||
|
||||
|
||||
======================================================================
|
||||
|
||||
|
||||
Major changes between "less" versions 123 and 170
|
||||
|
||||
* New option -j allows target lines to be positioned anywhere on screen.
|
||||
|
||||
* New option -S truncates displayed line at the screen width,
|
||||
rather than wrapping onto the next line.
|
||||
|
||||
* New option -y limits amount of forward scroll.
|
||||
|
||||
* New option -T specifies a "tags" file.
|
||||
|
||||
* Non-printable, non-control characters are displayed in octal.
|
||||
Such characters, as well as control characters, are displayed
|
||||
in blinking mode.
|
||||
|
||||
* New command -+ sets an option to its default.
|
||||
* New command -- sets an option to the opposite of its default.
|
||||
|
||||
* Lesskey file may have a string appended to a key's action,
|
||||
which acts as though typed in after the command.
|
||||
|
||||
* New commands ESC-^F and ESC-^B match arbitrary types of brackets.
|
||||
|
||||
* New command F monitors a growing file (like "tail -f").
|
||||
|
||||
* New command | pipes a section of the input file into a shell command.
|
||||
|
||||
* New command :x directly jumps to a file in the command line list.
|
||||
|
||||
* Search commands have been enhanced and reorganized:
|
||||
n Repeat search, same direction.
|
||||
N Repeat search, opposite direction.
|
||||
ESC-/ Search forward thru file boundaries
|
||||
ESC-? Search backward thru file boundaries
|
||||
ESC-n Repeat search thru file boundaries, same direction.
|
||||
ESC-N Repeat search thru file boundaries, opposite direction.
|
||||
Special character * causes search to search thru file boundaries.
|
||||
Special character @ causes search to begin at start/end of file list.
|
||||
|
||||
* Examining a new file adds it to the command line list.
|
||||
A list of files, or an expression which matches more than one file,
|
||||
may be examined; all of them are added to the command line list.
|
||||
|
||||
* Environment variables LESSCHARSET and LESSCHARDEF can define
|
||||
a non-ASCII character set.
|
||||
|
||||
* Partial support for MSDOS, including options -R for repainting screen
|
||||
on quit, -v/-V to select video mode, and -W to change window size.
|
||||
|
||||
|
||||
======================================================================
|
||||
|
||||
|
||||
Major changes between "less" versions 97 and 123
|
||||
|
||||
* New option (-N) causes line numbers to be displayed in the
|
||||
text of the file (like vi "set nu").
|
||||
|
||||
* New option (-?) prints help message immediately.
|
||||
|
||||
* New option (-r) displays "raw" control characters, without
|
||||
mapping them to ^X notation.
|
||||
|
||||
* New option (-f) forces less to open non-regular files
|
||||
(directories, etc).
|
||||
|
||||
* New option (-k) can be used to specify lesskey files by name.
|
||||
|
||||
* New option (-y) can be used to set a forward scroll limit
|
||||
(like -h sets a backward scroll limit).
|
||||
|
||||
* File marks (set by the m command) are now preserved when a new
|
||||
file is edited. The ' command can thus be used to switch files.
|
||||
|
||||
* New command ESC-/ searches all files (on the command line)
|
||||
for a pattern.
|
||||
|
||||
* New command ESC-n repeats previous search, spanning files.
|
||||
|
||||
* The N command has been changed to repeat the previous search
|
||||
in the reverse direction. The old N command is still available
|
||||
via :n.
|
||||
|
||||
* New command ESC-N repeats previous search in the reverse
|
||||
direction and spanning files.
|
||||
|
||||
* 8 bit characters are now supported. A new option (-g) can be
|
||||
used to strip off the eighth bit (the previous behavior).
|
||||
|
||||
* Options which take a following string (like -t) may now
|
||||
optionally have a space between the option letter and the string.
|
||||
|
||||
* Six new commands { } ( ) [ and ] can be used to match
|
||||
brackets of specific types, similar to vi % command.
|
||||
|
||||
* New commands z and w move forward/backward one window and
|
||||
simultaneously set the window size.
|
||||
|
||||
* Prompt string expansion now has %L for line number of the last
|
||||
line in the file, and %E for the name of the editor.
|
||||
Also, % escapes which refer to a line (b=bottom, t=top, etc.)
|
||||
can use j for the jump target line.
|
||||
|
||||
* New environment variable LESSEDIT can be used to tailor the
|
||||
command string passed to the editor by the v command.
|
||||
|
||||
* Examining a file which was previously examined will return
|
||||
to the same position in the file.
|
||||
|
||||
* A "%" is expanded to the current filename and a "#" to the
|
||||
previous filename, in both shell commands and the E command.
|
||||
(Previously % worked only in shell commands and # worked
|
||||
only in the E command.)
|
||||
|
||||
* New command ":ta" is equivalent to "-t".
|
||||
|
||||
* New command "s" is equivalent to "-l".
|
||||
|
||||
* The - command may be followed by "+X" to revert to the default
|
||||
for option X, or "-X" to get the opposite of the default.
|
||||
|
||||
* Lesskey files may now include characters after the action as
|
||||
extra input to be parsed after the action; for example:
|
||||
"toggle-option X" to toggle a specific option X.
|
||||
236
commands/less/less/README
Normal file
236
commands/less/less/README
Normal file
@@ -0,0 +1,236 @@
|
||||
|
||||
Less, version 394
|
||||
|
||||
This is the distribution of less, version 394, released 03 Dec 2005.
|
||||
This program is part of the GNU project (http://www.gnu.org).
|
||||
|
||||
This program is free software. You may redistribute it and/or
|
||||
modify it under the terms of either:
|
||||
|
||||
1. The GNU General Public License, as published by the Free
|
||||
Software Foundation; either version 2, or (at your option) any
|
||||
later version. A copy of this license is in the file COPYING.
|
||||
or
|
||||
2. The Less License, in the file LICENSE.
|
||||
|
||||
Please report any problems to bug-less@gnu.org or markn@greenwoodsoftware.com.
|
||||
See http://www.greenwoodsoftware.com/less for the latest info.
|
||||
You may also contact the author at:
|
||||
Mark Nudelman
|
||||
Greenwood Software
|
||||
PO Box 2402
|
||||
El Granada, CA 94018
|
||||
USA
|
||||
|
||||
=========================================================================
|
||||
|
||||
This is the distribution of "less", a paginator similar to "more" or "pg".
|
||||
|
||||
The formatted manual page is in less.man.
|
||||
The manual page nroff source is in less.nro.
|
||||
Major changes made since the last posted version are in NEWS.
|
||||
|
||||
=======================================================================
|
||||
INSTALLATION (Unix systems only):
|
||||
|
||||
1. Move the distributed source to its own directory and unpack it,
|
||||
if you have not already done so.
|
||||
|
||||
2. Type "sh configure".
|
||||
This will generate a Makefile and a defines.h.
|
||||
Warning: if you have a GNU sed, make sure it is version 2.05 or later.
|
||||
|
||||
The file INSTALL describes the usage of the configure program in
|
||||
general. In addition, these options to configure are supported:
|
||||
|
||||
--with-editor=program
|
||||
Specifies the default editor program used by the "v" command.
|
||||
The default is "vi".
|
||||
--with-regex=lib
|
||||
Specifies the regular expression library used by less for pattern
|
||||
matching. The default is "auto", which means the configure program
|
||||
finds a regular expression library automatically. Other values are:
|
||||
posix Use the POSIX-compatible regcomp.
|
||||
pcre Use the PCRE library.
|
||||
regcmp Use the regcmp library.
|
||||
re_comp Use the re_comp library.
|
||||
regcomp Use the V8-compatible regcomp.
|
||||
regcomp-local Use Henry Spencer's V8-compatible regcomp
|
||||
(source is supplied with less).
|
||||
--with-secure
|
||||
Builds a "secure" version of less, with some features disabled
|
||||
to prevent users from viewing other files, accessing shell
|
||||
commands, etc.
|
||||
|
||||
3. It is a good idea to look over the generated Makefile and defines.h
|
||||
and make sure they look ok. If you know of any peculiarities of
|
||||
your system that configure might not have detected, you may fix the
|
||||
Makefile now. Take particular notice of the list of "terminal"
|
||||
libraries in the LIBS definition in the Makefile; these may need
|
||||
to be edited. The terminal libraries will be some subset of
|
||||
-lncurses -lcurses -ltermcap -ltermlib
|
||||
|
||||
If you wish, you may edit defines.h to remove some optional features.
|
||||
If you choose not to include some features in your version, you may
|
||||
wish to edit the manual page "less.nro" and the help page "less.hlp"
|
||||
to remove the descriptions of the features which you are removing.
|
||||
If you edit less.hlp, you should run "make -f Makefile.aut help.c".
|
||||
|
||||
4. Type "make" and watch the fun.
|
||||
|
||||
5. If the make succeeds, it will generate the programs "less",
|
||||
"lesskey" and "lessecho" in your current directory. Test the
|
||||
generated programs.
|
||||
|
||||
6. When satisfied that it works, if you wish to install it
|
||||
in a public place, type "make install".
|
||||
|
||||
The default install destinations are:
|
||||
Executables (less, lesskey, lessecho) in /usr/local/bin
|
||||
Documentation (less.nro, lesskey.nro) in /usr/local/man/man1
|
||||
If you want to install any of these files elsewhere, define
|
||||
bindir and/or mandir to the appropriate directories.
|
||||
|
||||
If you have any problems building or running "less", suggestions,
|
||||
complaints, etc., you may mail to the author at markn@greenwoodsoftware.com.
|
||||
|
||||
Note to hackers: comments noting possible improvements are enclosed
|
||||
in double curly brackets {{ like this }}.
|
||||
|
||||
|
||||
|
||||
=======================================================================
|
||||
INSTALLATION (MS-DOS systems only,
|
||||
with Microsoft C, Borland C, or DJGPP)
|
||||
|
||||
1. Move the distributed source to its own directory.
|
||||
Depending on your compiler, you may need to convert the source
|
||||
to have CR-LF rather than LF as line terminators.
|
||||
|
||||
2. If you are using Microsoft C, rename MAKEFILE.DSU to MAKEFILE.
|
||||
If you are using Borland C, rename MAKEFILE.DSB to MAKEFILE.
|
||||
If you are using DJGPP, rename MAKEFILE.DSG to MAKEFILE.
|
||||
|
||||
3. Look at MAKEFILE to make sure that the definitions for CC and LIBDIR
|
||||
are correct. CC should be the name of your C compiler and
|
||||
LIBDIR should be the directory where the C libraries reside (for
|
||||
Microsoft C only). If these definitions need to be changed, you can
|
||||
either modify the definitions directly in MAKEFILE, or set your
|
||||
environment variables CC and/or LIBDIR to override the definitions
|
||||
in MAKEFILE.
|
||||
|
||||
4. If you wish, you may edit DEFINES.DS to remove some optional features.
|
||||
If you choose not to include some features in your version, you may
|
||||
wish to edit the manual page LESS.MAN and the help page HELP.C
|
||||
to remove the descriptions of the features which you are removing.
|
||||
|
||||
5. Run your "make" program and watch the fun.
|
||||
If your "make" requires a flag to import environment variables,
|
||||
you should use that flag.
|
||||
If your compiler runs out of memory, try running "make -n >cmds.bat"
|
||||
and then run cmds.bat.
|
||||
|
||||
6. If the make succeeds, it will generate the programs "LESS.EXE" and
|
||||
"LESSKEY.EXE" in your current directory. Test the generated programs.
|
||||
|
||||
7. When satisfied that it works, you may wish to install LESS.EXE and
|
||||
LESSKEY.EXE in a directory which is included in your PATH.
|
||||
|
||||
|
||||
|
||||
=======================================================================
|
||||
INSTALLATION (Windows-95, Windows-98 and Windows-NT systems only,
|
||||
with Borland C or Microsoft Visual C++)
|
||||
|
||||
1. Move the distributed source to its own directory.
|
||||
|
||||
2. If you are using Borland C, rename Makefile.wnb to Makefile.
|
||||
If you are using Microsoft Visual C++, rename Makefile.wnm to Makefile.
|
||||
|
||||
3. Check the Makefile to make sure the definitions look ok.
|
||||
|
||||
4. If you wish, you may edit defines.wn to remove some optional features.
|
||||
If you choose not to include some features in your version, you may
|
||||
wish to edit the manual page less.man and the help page help.c
|
||||
to remove the descriptions of the features which you are removing.
|
||||
|
||||
5. Type "make" and watch the fun.
|
||||
|
||||
6. If the make succeeds, it will generate the programs "less.exe" and
|
||||
"lesskey.exe" in your current directory. Test the generated programs.
|
||||
|
||||
7. When satisfied that it works, if you wish to install it
|
||||
in a public place, type "make install".
|
||||
See step 6 of the Unix installation instructions for details
|
||||
on how to change the default installation directories.
|
||||
|
||||
|
||||
|
||||
=======================================================================
|
||||
INSTALLATION (OS/2 systems only,
|
||||
with EMX C)
|
||||
|
||||
1. Move the distributed source to its own directory.
|
||||
|
||||
2. Rename Makefile.o2e to Makefile.
|
||||
|
||||
3. Check the Makefile to make sure the definitions look ok.
|
||||
|
||||
4. If you wish, you may edit defines.o2 to remove some optional features.
|
||||
If you choose not to include some features in your version, you may
|
||||
wish to edit the manual page less.man and the help page help.c
|
||||
to remove the descriptions of the features which you are removing.
|
||||
|
||||
5. Type "make" and watch the fun.
|
||||
|
||||
6. If the make succeeds, it will generate the programs "less.exe" and
|
||||
"lesskey.exe" in your current directory. Test the generated programs.
|
||||
|
||||
7. Make sure you have the emx runtime installed. You need the emx DLLs
|
||||
emx.dll and emxlibcs.dll and also the termcap database, termcap.dat.
|
||||
Make sure you have termcap.dat either in the default location or
|
||||
somewhere in a directory listed in the PATH or INIT environment
|
||||
variables.
|
||||
|
||||
8. When satisfied that it works, you may wish to install less.exe,
|
||||
lesskey.exe and scrsize.exe in a directory which is included in
|
||||
your PATH. scrsize.exe is required only if you use a terminal
|
||||
emulator such as xterm or rxvt.
|
||||
|
||||
|
||||
|
||||
=======================================================================
|
||||
INSTALLATION (OS-9 systems only,
|
||||
with Microware C or Ultra C)
|
||||
|
||||
1. Move the distributed source to its own directory.
|
||||
|
||||
2. If you are using Microware C, rename Makefile.o9c to Makefile.
|
||||
If you are using Ultra C, rename Makefile.o9u to Makefile.
|
||||
|
||||
3. Check the Makefile to make sure the definitions look ok.
|
||||
|
||||
4. If you wish, you may edit defines.o9 to remove some optional features.
|
||||
If you choose not to include some features in your version, you may
|
||||
wish to edit the manual page less.man and the help page help.c
|
||||
to remove the descriptions of the features which you are removing.
|
||||
|
||||
5. Type "dmake" and watch the fun.
|
||||
The standard OS-9 "make" will probably not work. If you don't
|
||||
have dmake, you can get a copy from os9archive.rtsi.com.
|
||||
|
||||
6. If the make succeeds, it will generate the programs "less" and
|
||||
"lesskey" in your current directory. Test the generated programs.
|
||||
|
||||
7. When satisfied that it works, if you wish to install it
|
||||
in a public place, type "dmake install".
|
||||
See step 6 of the Unix installation instructions for details
|
||||
on how to change the default installation directories.
|
||||
|
||||
=======================================================================
|
||||
ACKNOWLEDGMENTS:
|
||||
Some versions of the less distribution are packaged using
|
||||
Info-ZIP's compression utility.
|
||||
Info-ZIP's software is free and can be obtained as source
|
||||
code or executables from various anonymous-ftp sites,
|
||||
including ftp.uu.net:/pub/archiving/zip.
|
||||
101
commands/less/less/brac.c
Normal file
101
commands/less/less/brac.c
Normal file
@@ -0,0 +1,101 @@
|
||||
/* $NetBSD: brac.c,v 1.6 2006/10/26 01:33:08 mrg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1984-2004 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 about less, or for information on how to
|
||||
* contact the author, 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(obrac, cbrac, forwdir, n)
|
||||
register int obrac;
|
||||
register int cbrac;
|
||||
int forwdir;
|
||||
int n;
|
||||
{
|
||||
register int c;
|
||||
register int nest;
|
||||
POSITION pos;
|
||||
int (*chget) __P((void));
|
||||
|
||||
/*
|
||||
* 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)
|
||||
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);
|
||||
}
|
||||
845
commands/less/less/ch.c
Normal file
845
commands/less/less/ch.c
Normal file
@@ -0,0 +1,845 @@
|
||||
/* $NetBSD: ch.c,v 1.8 2006/10/26 01:33:08 mrg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1984-2004 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 about less, or for information on how to
|
||||
* contact the author, 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
|
||||
|
||||
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".
|
||||
*/
|
||||
#define LBUFSIZE 8192
|
||||
struct buf {
|
||||
struct buf *next, *prev;
|
||||
struct buf *hnext, *hprev;
|
||||
BLOCKNUM block;
|
||||
unsigned int datasize;
|
||||
unsigned char data[LBUFSIZE];
|
||||
};
|
||||
|
||||
struct buflist {
|
||||
/* -- Following members must match struct buf */
|
||||
struct buf *buf_next, *buf_prev;
|
||||
struct buf *buf_hnext, *buf_hprev;
|
||||
};
|
||||
|
||||
/*
|
||||
* The file state is maintained in a filestate structure.
|
||||
* A pointer to the filestate is kept in the ifile structure.
|
||||
*/
|
||||
#define BUFHASH_SIZE 64
|
||||
struct filestate {
|
||||
struct buf *buf_next, *buf_prev;
|
||||
struct buflist hashtbl[BUFHASH_SIZE];
|
||||
int file;
|
||||
int flags;
|
||||
POSITION fpos;
|
||||
int nbufs;
|
||||
BLOCKNUM block;
|
||||
unsigned int offset;
|
||||
POSITION fsize;
|
||||
};
|
||||
|
||||
#define ch_bufhead thisfile->buf_next
|
||||
#define ch_buftail thisfile->buf_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 ((struct buf *)&thisfile->buf_next)
|
||||
#define END_OF_HCHAIN(h) ((struct buf *)&thisfile->hashtbl[h])
|
||||
#define BUFHASH(blk) ((blk) & (BUFHASH_SIZE-1))
|
||||
|
||||
#define FOR_BUFS_IN_CHAIN(h,bp) \
|
||||
for (bp = thisfile->hashtbl[h].buf_hnext; \
|
||||
bp != END_OF_HCHAIN(h); bp = bp->hnext)
|
||||
|
||||
#define HASH_RM(bp) \
|
||||
(bp)->hnext->hprev = (bp)->hprev; \
|
||||
(bp)->hprev->hnext = (bp)->hnext;
|
||||
|
||||
#define HASH_INS(bp,h) \
|
||||
(bp)->hnext = thisfile->hashtbl[h].buf_hnext; \
|
||||
(bp)->hprev = END_OF_HCHAIN(h); \
|
||||
thisfile->hashtbl[h].buf_hnext->hprev = (bp); \
|
||||
thisfile->hashtbl[h].buf_hnext = (bp);
|
||||
|
||||
static struct filestate *thisfile;
|
||||
static int ch_ungotchar = -1;
|
||||
static int maxbufs = -1;
|
||||
|
||||
extern int autobuf;
|
||||
extern int sigs;
|
||||
extern int secure;
|
||||
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 __P((void));
|
||||
static int buffered __P((BLOCKNUM));
|
||||
static void ch_delbufs __P((void));
|
||||
|
||||
|
||||
/*
|
||||
* Get the character pointed to by the read pointer.
|
||||
* ch_get() is a macro which is more efficient to call
|
||||
* than fch_get (the function), in the usual case
|
||||
* that the block desired is at the head of the chain.
|
||||
*/
|
||||
#define ch_get() ((ch_block == ch_bufhead->block && \
|
||||
ch_offset < ch_bufhead->datasize) ? \
|
||||
ch_bufhead->data[ch_offset] : fch_get())
|
||||
int
|
||||
fch_get()
|
||||
{
|
||||
register struct buf *bp;
|
||||
register int n;
|
||||
register int slept;
|
||||
register int h;
|
||||
POSITION pos;
|
||||
POSITION len;
|
||||
|
||||
slept = FALSE;
|
||||
|
||||
/*
|
||||
* Look for a buffer holding the desired block.
|
||||
*/
|
||||
h = BUFHASH(ch_block);
|
||||
FOR_BUFS_IN_CHAIN(h, bp)
|
||||
{
|
||||
if (bp->block == ch_block)
|
||||
{
|
||||
if (ch_offset >= bp->datasize)
|
||||
/*
|
||||
* Need more data in this buffer.
|
||||
*/
|
||||
goto read_more;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 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 || 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;
|
||||
}
|
||||
bp = ch_buftail;
|
||||
HASH_RM(bp); /* Remove from old hash chain. */
|
||||
bp->block = ch_block;
|
||||
bp->datasize = 0;
|
||||
HASH_INS(bp, h); /* Insert into new hash chain. */
|
||||
|
||||
read_more:
|
||||
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, 0) == 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));
|
||||
}
|
||||
|
||||
if (n == READ_INTR)
|
||||
return (EOI);
|
||||
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 we have read to end of file, set ch_fsize to indicate
|
||||
* the position of the end of file.
|
||||
*/
|
||||
if (n == 0)
|
||||
{
|
||||
ch_fsize = pos;
|
||||
if (ignore_eoi)
|
||||
{
|
||||
/*
|
||||
* We are ignoring EOF.
|
||||
* Wait a while, then try again.
|
||||
*/
|
||||
if (!slept)
|
||||
{
|
||||
PARG parg;
|
||||
parg.p_string = wait_message();
|
||||
ierror("%s", &parg);
|
||||
}
|
||||
#if !MSDOS_COMPILER
|
||||
sleep(1);
|
||||
#else
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
Sleep(1000);
|
||||
#endif
|
||||
#endif
|
||||
slept = TRUE;
|
||||
}
|
||||
if (sigs)
|
||||
return (EOI);
|
||||
}
|
||||
|
||||
found:
|
||||
if (ch_bufhead != bp)
|
||||
{
|
||||
/*
|
||||
* Move the buffer to the head of the buffer chain.
|
||||
* This orders the buffer chain, most- to least-recently used.
|
||||
*/
|
||||
bp->next->prev = bp->prev;
|
||||
bp->prev->next = bp->next;
|
||||
bp->next = ch_bufhead;
|
||||
bp->prev = END_OF_CHAIN;
|
||||
ch_bufhead->prev = bp;
|
||||
ch_bufhead = bp;
|
||||
|
||||
/*
|
||||
* Move to head of hash chain too.
|
||||
*/
|
||||
HASH_RM(bp);
|
||||
HASH_INS(bp, h);
|
||||
}
|
||||
|
||||
if (ch_offset >= bp->datasize)
|
||||
/*
|
||||
* After all that, we still don't have enough data.
|
||||
* Go back and try again.
|
||||
*/
|
||||
goto read_more;
|
||||
|
||||
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(c)
|
||||
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()
|
||||
{
|
||||
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;
|
||||
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()
|
||||
{
|
||||
register struct buf *bp;
|
||||
int warned = FALSE;
|
||||
BLOCKNUM block;
|
||||
BLOCKNUM nblocks;
|
||||
|
||||
nblocks = (ch_fpos + LBUFSIZE - 1) / LBUFSIZE;
|
||||
for (block = 0; block < nblocks; block++)
|
||||
{
|
||||
for (bp = ch_bufhead; ; bp = bp->next)
|
||||
{
|
||||
if (bp == END_OF_CHAIN)
|
||||
{
|
||||
if (!warned)
|
||||
{
|
||||
error("Warning: log file is incomplete",
|
||||
NULL_PARG);
|
||||
warned = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (bp->block == block)
|
||||
{
|
||||
write(logfile, (char *) bp->data, bp->datasize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Determine if a specific block is currently in one of the buffers.
|
||||
*/
|
||||
static int
|
||||
buffered(block)
|
||||
BLOCKNUM block;
|
||||
{
|
||||
register struct buf *bp;
|
||||
register int h;
|
||||
|
||||
h = BUFHASH(block);
|
||||
FOR_BUFS_IN_CHAIN(h, bp)
|
||||
{
|
||||
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(pos)
|
||||
register POSITION pos;
|
||||
{
|
||||
BLOCKNUM new_block;
|
||||
POSITION len;
|
||||
|
||||
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()
|
||||
{
|
||||
POSITION len;
|
||||
|
||||
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 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()
|
||||
{
|
||||
register struct buf *bp, *firstbp;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
firstbp = bp = ch_bufhead;
|
||||
if (bp == END_OF_CHAIN)
|
||||
return (1);
|
||||
while ((bp = bp->next) != END_OF_CHAIN)
|
||||
if (bp->block < firstbp->block)
|
||||
firstbp = bp;
|
||||
ch_block = firstbp->block;
|
||||
ch_offset = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the length of the file, if known.
|
||||
*/
|
||||
public POSITION
|
||||
ch_length()
|
||||
{
|
||||
if (ignore_eoi)
|
||||
return (NULL_POSITION);
|
||||
if (ch_flags & CH_HELPFILE)
|
||||
return (size_helpdata);
|
||||
return (ch_fsize);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the current position in the file.
|
||||
*/
|
||||
public POSITION
|
||||
ch_tell()
|
||||
{
|
||||
return (ch_block * LBUFSIZE) + ch_offset;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current char and post-increment the read pointer.
|
||||
*/
|
||||
public int
|
||||
ch_forw_get()
|
||||
{
|
||||
register int c;
|
||||
|
||||
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()
|
||||
{
|
||||
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(bufspace)
|
||||
int bufspace;
|
||||
{
|
||||
if (bufspace < 0)
|
||||
maxbufs = -1;
|
||||
else
|
||||
{
|
||||
maxbufs = ((bufspace * 1024) + LBUFSIZE-1) / LBUFSIZE;
|
||||
if (maxbufs < 1)
|
||||
maxbufs = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush (discard) any saved file state, including buffer contents.
|
||||
*/
|
||||
public void
|
||||
ch_flush()
|
||||
{
|
||||
register struct buf *bp;
|
||||
|
||||
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 (bp = ch_bufhead; bp != END_OF_CHAIN; bp = bp->next)
|
||||
bp->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 1
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
ch_fsize = NULL_POSITION;
|
||||
ch_flags &= ~CH_CANSEEK;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (lseek(ch_file, (off_t)0, 0) == 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()
|
||||
{
|
||||
register struct buf *bp;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
bp->next = END_OF_CHAIN;
|
||||
bp->prev = ch_buftail;
|
||||
ch_buftail->next = bp;
|
||||
ch_buftail = bp;
|
||||
HASH_INS(bp, 0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static void
|
||||
init_hashtbl()
|
||||
{
|
||||
register int h;
|
||||
|
||||
for (h = 0; h < BUFHASH_SIZE; h++)
|
||||
{
|
||||
thisfile->hashtbl[h].buf_hnext = END_OF_HCHAIN(h);
|
||||
thisfile->hashtbl[h].buf_hprev = END_OF_HCHAIN(h);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete all buffers for this file.
|
||||
*/
|
||||
static void
|
||||
ch_delbufs()
|
||||
{
|
||||
register struct buf *bp;
|
||||
|
||||
while (ch_bufhead != END_OF_CHAIN)
|
||||
{
|
||||
bp = ch_bufhead;
|
||||
bp->next->prev = bp->prev;
|
||||
bp->prev->next = bp->next;
|
||||
free(bp);
|
||||
}
|
||||
ch_nbufs = 0;
|
||||
init_hashtbl();
|
||||
}
|
||||
|
||||
/*
|
||||
* Is it possible to seek on a file descriptor?
|
||||
*/
|
||||
public int
|
||||
seekable(f)
|
||||
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, 0) != BAD_LSEEK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize file state for a new file.
|
||||
*/
|
||||
public void
|
||||
ch_init(f, flags)
|
||||
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 *)
|
||||
calloc(1, sizeof(struct filestate));
|
||||
thisfile->buf_next = thisfile->buf_prev = END_OF_CHAIN;
|
||||
thisfile->nbufs = 0;
|
||||
thisfile->flags = 0;
|
||||
thisfile->fpos = 0;
|
||||
thisfile->block = 0;
|
||||
thisfile->offset = 0;
|
||||
thisfile->file = -1;
|
||||
thisfile->fsize = NULL_POSITION;
|
||||
ch_flags = flags;
|
||||
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()
|
||||
{
|
||||
int keepstate = FALSE;
|
||||
|
||||
if (ch_flags & (CH_CANSEEK|CH_POPENED|CH_HELPFILE))
|
||||
{
|
||||
/*
|
||||
* 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()
|
||||
{
|
||||
return (ch_flags);
|
||||
}
|
||||
|
||||
#if 0
|
||||
public void
|
||||
ch_dump(struct filestate *fs)
|
||||
{
|
||||
struct buf *bp;
|
||||
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 (bp = fs->buf_next; bp != (struct buf *)fs; bp = bp->next)
|
||||
{
|
||||
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
|
||||
1042
commands/less/less/charset.c
Normal file
1042
commands/less/less/charset.c
Normal file
File diff suppressed because it is too large
Load Diff
19
commands/less/less/charset.h
Normal file
19
commands/less/less/charset.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2005 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 about less, or for information on how to
|
||||
* contact the author, 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))
|
||||
131
commands/less/less/cmd.h
Normal file
131
commands/less/less/cmd.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (C) 1984-2004 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 about less, or for information on how to
|
||||
* contact the author, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
#define MAX_USERCMD 500
|
||||
#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_PREFIX 22
|
||||
#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_INVALID 100
|
||||
#define A_NOACTION 101
|
||||
#define A_UINVALID 102
|
||||
#define A_END_LIST 103
|
||||
#define A_SPECIAL_KEY 104
|
||||
|
||||
#define A_SKIP 127
|
||||
|
||||
#define A_EXTRA 0200
|
||||
|
||||
|
||||
/* Line editting 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_NOACTION 101
|
||||
#define EC_UINVALID 102
|
||||
|
||||
/* Flags for editchar() */
|
||||
#define EC_PEEK 01
|
||||
#define EC_NOHISTORY 02
|
||||
#define EC_NOCOMPLETE 04
|
||||
#define EC_NORIGHTLEFT 010
|
||||
|
||||
/* 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_CONTROL_K 40
|
||||
1470
commands/less/less/cmdbuf.c
Normal file
1470
commands/less/less/cmdbuf.c
Normal file
File diff suppressed because it is too large
Load Diff
1661
commands/less/less/command.c
Normal file
1661
commands/less/less/command.c
Normal file
File diff suppressed because it is too large
Load Diff
845
commands/less/less/decode.c
Normal file
845
commands/less/less/decode.c
Normal file
@@ -0,0 +1,845 @@
|
||||
/* $NetBSD: decode.c,v 1.8 2006/10/26 01:33:08 mrg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1984-2004 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 about less, or for information on how to
|
||||
* contact the author, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Routines to decode user commands.
|
||||
*
|
||||
* This is all table driven.
|
||||
* A command table is a sequence of command descriptors.
|
||||
* Each command descriptor is a sequence of bytes with the following format:
|
||||
* <c1><c2>...<cN><0><action>
|
||||
* The characters c1,c2,...,cN are the command string; that is,
|
||||
* the characters which the user must type.
|
||||
* It is terminated by a null <0> byte.
|
||||
* The byte after the null byte is the action code associated
|
||||
* with the command string.
|
||||
* If an action byte is OR-ed with A_EXTRA, this indicates
|
||||
* that the option byte is followed by an extra string.
|
||||
*
|
||||
* There may be many command tables.
|
||||
* The first (default) table is built-in.
|
||||
* Other tables are read in from "lesskey" files.
|
||||
* All the tables are linked together and are searched in order.
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
#include "cmd.h"
|
||||
#include "lesskey.h"
|
||||
|
||||
extern int erase_char, erase2_char, kill_char;
|
||||
extern int secure;
|
||||
|
||||
#define SK(k) \
|
||||
SK_SPECIAL_KEY, (k), 6, 1, 1, 1
|
||||
/*
|
||||
* Command table is ordered roughly according to expected
|
||||
* frequency of use, so the common commands are near the beginning.
|
||||
*/
|
||||
|
||||
static unsigned char cmdtable[] =
|
||||
{
|
||||
'\r',0, A_F_LINE,
|
||||
'\n',0, A_F_LINE,
|
||||
'e',0, A_F_LINE,
|
||||
'j',0, A_F_LINE,
|
||||
SK(SK_DOWN_ARROW),0, A_F_LINE,
|
||||
CONTROL('E'),0, A_F_LINE,
|
||||
CONTROL('N'),0, A_F_LINE,
|
||||
'k',0, A_B_LINE,
|
||||
'y',0, A_B_LINE,
|
||||
CONTROL('Y'),0, A_B_LINE,
|
||||
SK(SK_CONTROL_K),0, A_B_LINE,
|
||||
CONTROL('P'),0, A_B_LINE,
|
||||
SK(SK_UP_ARROW),0, A_B_LINE,
|
||||
'J',0, A_FF_LINE,
|
||||
'K',0, A_BF_LINE,
|
||||
'Y',0, A_BF_LINE,
|
||||
'd',0, A_F_SCROLL,
|
||||
CONTROL('D'),0, A_F_SCROLL,
|
||||
'u',0, A_B_SCROLL,
|
||||
CONTROL('U'),0, A_B_SCROLL,
|
||||
' ',0, A_F_SCREEN,
|
||||
'f',0, A_F_SCREEN,
|
||||
CONTROL('F'),0, A_F_SCREEN,
|
||||
CONTROL('V'),0, A_F_SCREEN,
|
||||
SK(SK_PAGE_DOWN),0, A_F_SCREEN,
|
||||
'b',0, A_B_SCREEN,
|
||||
CONTROL('B'),0, A_B_SCREEN,
|
||||
ESC,'v',0, A_B_SCREEN,
|
||||
SK(SK_PAGE_UP),0, A_B_SCREEN,
|
||||
'z',0, A_F_WINDOW,
|
||||
'w',0, A_B_WINDOW,
|
||||
ESC,' ',0, A_FF_SCREEN,
|
||||
'F',0, A_F_FOREVER,
|
||||
'R',0, A_FREPAINT,
|
||||
'r',0, A_REPAINT,
|
||||
CONTROL('R'),0, A_REPAINT,
|
||||
CONTROL('L'),0, A_REPAINT,
|
||||
ESC,'u',0, A_UNDO_SEARCH,
|
||||
'g',0, A_GOLINE,
|
||||
SK(SK_HOME),0, A_GOLINE,
|
||||
'<',0, A_GOLINE,
|
||||
ESC,'<',0, A_GOLINE,
|
||||
'p',0, A_PERCENT,
|
||||
'%',0, A_PERCENT,
|
||||
ESC,'[',0, A_LSHIFT,
|
||||
ESC,']',0, A_RSHIFT,
|
||||
ESC,'(',0, A_LSHIFT,
|
||||
ESC,')',0, A_RSHIFT,
|
||||
SK(SK_RIGHT_ARROW),0, A_RSHIFT,
|
||||
SK(SK_LEFT_ARROW),0, A_LSHIFT,
|
||||
'{',0, A_F_BRACKET|A_EXTRA, '{','}',0,
|
||||
'}',0, A_B_BRACKET|A_EXTRA, '{','}',0,
|
||||
'(',0, A_F_BRACKET|A_EXTRA, '(',')',0,
|
||||
')',0, A_B_BRACKET|A_EXTRA, '(',')',0,
|
||||
'[',0, A_F_BRACKET|A_EXTRA, '[',']',0,
|
||||
']',0, A_B_BRACKET|A_EXTRA, '[',']',0,
|
||||
ESC,CONTROL('F'),0, A_F_BRACKET,
|
||||
ESC,CONTROL('B'),0, A_B_BRACKET,
|
||||
'G',0, A_GOEND,
|
||||
ESC,'>',0, A_GOEND,
|
||||
'>',0, A_GOEND,
|
||||
SK(SK_END),0, A_GOEND,
|
||||
'P',0, A_GOPOS,
|
||||
|
||||
'0',0, A_DIGIT,
|
||||
'1',0, A_DIGIT,
|
||||
'2',0, A_DIGIT,
|
||||
'3',0, A_DIGIT,
|
||||
'4',0, A_DIGIT,
|
||||
'5',0, A_DIGIT,
|
||||
'6',0, A_DIGIT,
|
||||
'7',0, A_DIGIT,
|
||||
'8',0, A_DIGIT,
|
||||
'9',0, A_DIGIT,
|
||||
|
||||
'=',0, A_STAT,
|
||||
CONTROL('G'),0, A_STAT,
|
||||
':','f',0, A_STAT,
|
||||
'/',0, A_F_SEARCH,
|
||||
'?',0, A_B_SEARCH,
|
||||
ESC,'/',0, A_F_SEARCH|A_EXTRA, '*',0,
|
||||
ESC,'?',0, A_B_SEARCH|A_EXTRA, '*',0,
|
||||
'n',0, A_AGAIN_SEARCH,
|
||||
ESC,'n',0, A_T_AGAIN_SEARCH,
|
||||
'N',0, A_REVERSE_SEARCH,
|
||||
ESC,'N',0, A_T_REVERSE_SEARCH,
|
||||
'm',0, A_SETMARK,
|
||||
'\'',0, A_GOMARK,
|
||||
CONTROL('X'),CONTROL('X'),0, A_GOMARK,
|
||||
'E',0, A_EXAMINE,
|
||||
':','e',0, A_EXAMINE,
|
||||
CONTROL('X'),CONTROL('V'),0, A_EXAMINE,
|
||||
':','n',0, A_NEXT_FILE,
|
||||
':','p',0, A_PREV_FILE,
|
||||
't',0, A_NEXT_TAG,
|
||||
'T',0, A_PREV_TAG,
|
||||
':','x',0, A_INDEX_FILE,
|
||||
':','d',0, A_REMOVE_FILE,
|
||||
'-',0, A_OPT_TOGGLE,
|
||||
':','t',0, A_OPT_TOGGLE|A_EXTRA, 't',0,
|
||||
's',0, A_OPT_TOGGLE|A_EXTRA, 'o',0,
|
||||
'_',0, A_DISP_OPTION,
|
||||
'|',0, A_PIPE,
|
||||
'v',0, A_VISUAL,
|
||||
'!',0, A_SHELL,
|
||||
'+',0, A_FIRSTCMD,
|
||||
|
||||
'H',0, A_HELP,
|
||||
'h',0, A_HELP,
|
||||
SK(SK_F1),0, A_HELP,
|
||||
'V',0, A_VERSION,
|
||||
'q',0, A_QUIT,
|
||||
'Q',0, A_QUIT,
|
||||
':','q',0, A_QUIT,
|
||||
':','Q',0, A_QUIT,
|
||||
'Z','Z',0, A_QUIT
|
||||
};
|
||||
|
||||
static unsigned char edittable[] =
|
||||
{
|
||||
'\t',0, EC_F_COMPLETE, /* TAB */
|
||||
'\17',0, EC_B_COMPLETE, /* BACKTAB */
|
||||
SK(SK_BACKTAB),0, EC_B_COMPLETE, /* BACKTAB */
|
||||
ESC,'\t',0, EC_B_COMPLETE, /* ESC TAB */
|
||||
CONTROL('L'),0, EC_EXPAND, /* CTRL-L */
|
||||
CONTROL('V'),0, EC_LITERAL, /* BACKSLASH */
|
||||
CONTROL('A'),0, EC_LITERAL, /* BACKSLASH */
|
||||
ESC,'l',0, EC_RIGHT, /* ESC l */
|
||||
SK(SK_RIGHT_ARROW),0, EC_RIGHT, /* RIGHTARROW */
|
||||
ESC,'h',0, EC_LEFT, /* ESC h */
|
||||
SK(SK_LEFT_ARROW),0, EC_LEFT, /* LEFTARROW */
|
||||
ESC,'b',0, EC_W_LEFT, /* ESC b */
|
||||
ESC,SK(SK_LEFT_ARROW),0, EC_W_LEFT, /* ESC LEFTARROW */
|
||||
SK(SK_CTL_LEFT_ARROW),0, EC_W_LEFT, /* CTRL-LEFTARROW */
|
||||
ESC,'w',0, EC_W_RIGHT, /* ESC w */
|
||||
ESC,SK(SK_RIGHT_ARROW),0, EC_W_RIGHT, /* ESC RIGHTARROW */
|
||||
SK(SK_CTL_RIGHT_ARROW),0, EC_W_RIGHT, /* CTRL-RIGHTARROW */
|
||||
ESC,'i',0, EC_INSERT, /* ESC i */
|
||||
SK(SK_INSERT),0, EC_INSERT, /* INSERT */
|
||||
ESC,'x',0, EC_DELETE, /* ESC x */
|
||||
SK(SK_DELETE),0, EC_DELETE, /* DELETE */
|
||||
ESC,'X',0, EC_W_DELETE, /* ESC X */
|
||||
ESC,SK(SK_DELETE),0, EC_W_DELETE, /* ESC DELETE */
|
||||
SK(SK_CTL_DELETE),0, EC_W_DELETE, /* CTRL-DELETE */
|
||||
SK(SK_CTL_BACKSPACE),0, EC_W_BACKSPACE, /* CTRL-BACKSPACE */
|
||||
ESC,'\b',0, EC_W_BACKSPACE, /* ESC BACKSPACE */
|
||||
ESC,'0',0, EC_HOME, /* ESC 0 */
|
||||
SK(SK_HOME),0, EC_HOME, /* HOME */
|
||||
ESC,'$',0, EC_END, /* ESC $ */
|
||||
SK(SK_END),0, EC_END, /* END */
|
||||
ESC,'k',0, EC_UP, /* ESC k */
|
||||
SK(SK_UP_ARROW),0, EC_UP, /* UPARROW */
|
||||
ESC,'j',0, EC_DOWN, /* ESC j */
|
||||
SK(SK_DOWN_ARROW),0, EC_DOWN, /* DOWNARROW */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure to support a list of command tables.
|
||||
*/
|
||||
struct tablelist
|
||||
{
|
||||
struct tablelist *t_next;
|
||||
char *t_start;
|
||||
char *t_end;
|
||||
};
|
||||
|
||||
/*
|
||||
* List of command tables and list of line-edit tables.
|
||||
*/
|
||||
static struct tablelist *list_fcmd_tables = NULL;
|
||||
static struct tablelist *list_ecmd_tables = NULL;
|
||||
static struct tablelist *list_var_tables = NULL;
|
||||
static struct tablelist *list_sysvar_tables = NULL;
|
||||
|
||||
static int add_cmd_table __P((struct tablelist **, char *, int));
|
||||
static int cmd_decode __P((struct tablelist *, char *, char **));
|
||||
static int gint __P((char **));
|
||||
static int old_lesskey __P((char *, int));
|
||||
static int new_lesskey __P((char *, int, int));
|
||||
|
||||
/*
|
||||
* Expand special key abbreviations in a command table.
|
||||
*/
|
||||
static void
|
||||
expand_special_keys(table, len)
|
||||
char *table;
|
||||
int len;
|
||||
{
|
||||
register char *fm;
|
||||
register char *to;
|
||||
register int a;
|
||||
char *repl;
|
||||
int klen;
|
||||
|
||||
for (fm = table; fm < table + len; )
|
||||
{
|
||||
/*
|
||||
* Rewrite each command in the table with any
|
||||
* special key abbreviations expanded.
|
||||
*/
|
||||
for (to = fm; *fm != '\0'; )
|
||||
{
|
||||
if (*fm != SK_SPECIAL_KEY)
|
||||
{
|
||||
*to++ = *fm++;
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* After SK_SPECIAL_KEY, next byte is the type
|
||||
* of special key (one of the SK_* contants),
|
||||
* and the byte after that is the number of bytes,
|
||||
* N, reserved by the abbreviation (including the
|
||||
* SK_SPECIAL_KEY and key type bytes).
|
||||
* Replace all N bytes with the actual bytes
|
||||
* output by the special key on this terminal.
|
||||
*/
|
||||
repl = special_key_str(fm[1]);
|
||||
klen = fm[2] & 0377;
|
||||
fm += klen;
|
||||
if (repl == NULL || (int) strlen(repl) > klen)
|
||||
repl = "\377";
|
||||
while (*repl != '\0')
|
||||
*to++ = *repl++;
|
||||
}
|
||||
*to++ = '\0';
|
||||
/*
|
||||
* Fill any unused bytes between end of command and
|
||||
* the action byte with A_SKIP.
|
||||
*/
|
||||
while (to <= fm)
|
||||
*to++ = A_SKIP;
|
||||
fm++;
|
||||
a = *fm++ & 0377;
|
||||
if (a & A_EXTRA)
|
||||
{
|
||||
while (*fm++ != '\0')
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the command lists.
|
||||
*/
|
||||
public void
|
||||
init_cmds()
|
||||
{
|
||||
/*
|
||||
* Add the default command tables.
|
||||
*/
|
||||
add_fcmd_table((char*)cmdtable, sizeof(cmdtable));
|
||||
add_ecmd_table((char*)edittable, sizeof(edittable));
|
||||
#if USERFILE
|
||||
/*
|
||||
* For backwards compatibility,
|
||||
* try to add tables in the OLD system lesskey file.
|
||||
*/
|
||||
#ifdef BINDIR
|
||||
add_hometable(NULL, BINDIR "/.sysless", 1);
|
||||
#endif
|
||||
/*
|
||||
* Try to add the tables in the system lesskey file.
|
||||
*/
|
||||
add_hometable("LESSKEY_SYSTEM", LESSKEYFILE_SYS, 1);
|
||||
/*
|
||||
* Try to add the tables in the standard lesskey file "$HOME/.less".
|
||||
*/
|
||||
add_hometable("LESSKEY", LESSKEYFILE, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a command table.
|
||||
*/
|
||||
static int
|
||||
add_cmd_table(tlist, buf, len)
|
||||
struct tablelist **tlist;
|
||||
char *buf;
|
||||
int len;
|
||||
{
|
||||
register struct tablelist *t;
|
||||
|
||||
if (len == 0)
|
||||
return (0);
|
||||
/*
|
||||
* Allocate a tablelist structure, initialize it,
|
||||
* and link it into the list of tables.
|
||||
*/
|
||||
if ((t = (struct tablelist *)
|
||||
calloc(1, sizeof(struct tablelist))) == NULL)
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
expand_special_keys(buf, len);
|
||||
t->t_start = buf;
|
||||
t->t_end = buf + len;
|
||||
t->t_next = *tlist;
|
||||
*tlist = t;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a command table.
|
||||
*/
|
||||
public void
|
||||
add_fcmd_table(buf, len)
|
||||
char *buf;
|
||||
int len;
|
||||
{
|
||||
if (add_cmd_table(&list_fcmd_tables, buf, len) < 0)
|
||||
error("Warning: some commands disabled", NULL_PARG);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an editing command table.
|
||||
*/
|
||||
public void
|
||||
add_ecmd_table(buf, len)
|
||||
char *buf;
|
||||
int len;
|
||||
{
|
||||
if (add_cmd_table(&list_ecmd_tables, buf, len) < 0)
|
||||
error("Warning: some edit commands disabled", NULL_PARG);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an environment variable table.
|
||||
*/
|
||||
static void
|
||||
add_var_table(tlist, buf, len)
|
||||
struct tablelist **tlist;
|
||||
char *buf;
|
||||
int len;
|
||||
{
|
||||
if (add_cmd_table(tlist, buf, len) < 0)
|
||||
error("Warning: environment variables from lesskey file unavailable", NULL_PARG);
|
||||
}
|
||||
|
||||
/*
|
||||
* Search a single command table for the command string in cmd.
|
||||
*/
|
||||
static int
|
||||
cmd_search(cmd, table, endtable, sp)
|
||||
char *cmd;
|
||||
char *table;
|
||||
char *endtable;
|
||||
char **sp;
|
||||
{
|
||||
register char *p;
|
||||
register char *q;
|
||||
register int a;
|
||||
|
||||
*sp = NULL;
|
||||
for (p = table, q = cmd; p < endtable; p++, q++)
|
||||
{
|
||||
if (*p == *q)
|
||||
{
|
||||
/*
|
||||
* Current characters match.
|
||||
* If we're at the end of the string, we've found it.
|
||||
* Return the action code, which is the character
|
||||
* after the null at the end of the string
|
||||
* in the command table.
|
||||
*/
|
||||
if (*p == '\0')
|
||||
{
|
||||
a = *++p & 0377;
|
||||
while (a == A_SKIP)
|
||||
a = *++p & 0377;
|
||||
if (a == A_END_LIST)
|
||||
{
|
||||
/*
|
||||
* We get here only if the original
|
||||
* cmd string passed in was empty ("").
|
||||
* I don't think that can happen,
|
||||
* but just in case ...
|
||||
*/
|
||||
return (A_UINVALID);
|
||||
}
|
||||
/*
|
||||
* Check for an "extra" string.
|
||||
*/
|
||||
if (a & A_EXTRA)
|
||||
{
|
||||
*sp = ++p;
|
||||
a &= ~A_EXTRA;
|
||||
}
|
||||
return (a);
|
||||
}
|
||||
} else if (*q == '\0')
|
||||
{
|
||||
/*
|
||||
* Hit the end of the user's command,
|
||||
* but not the end of the string in the command table.
|
||||
* The user's command is incomplete.
|
||||
*/
|
||||
return (A_PREFIX);
|
||||
} else
|
||||
{
|
||||
/*
|
||||
* Not a match.
|
||||
* Skip ahead to the next command in the
|
||||
* command table, and reset the pointer
|
||||
* to the beginning of the user's command.
|
||||
*/
|
||||
if (*p == '\0' && p[1] == A_END_LIST)
|
||||
{
|
||||
/*
|
||||
* A_END_LIST is a special marker that tells
|
||||
* us to abort the cmd search.
|
||||
*/
|
||||
return (A_UINVALID);
|
||||
}
|
||||
while (*p++ != '\0')
|
||||
continue;
|
||||
while (*p == A_SKIP)
|
||||
p++;
|
||||
if (*p & A_EXTRA)
|
||||
while (*++p != '\0')
|
||||
continue;
|
||||
q = cmd-1;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* No match found in the entire command table.
|
||||
*/
|
||||
return (A_INVALID);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode a command character and return the associated action.
|
||||
* The "extra" string, if any, is returned in sp.
|
||||
*/
|
||||
static int
|
||||
cmd_decode(tlist, cmd, sp)
|
||||
struct tablelist *tlist;
|
||||
char *cmd;
|
||||
char **sp;
|
||||
{
|
||||
register struct tablelist *t;
|
||||
register int action = A_INVALID;
|
||||
|
||||
/*
|
||||
* Search thru all the command tables.
|
||||
* Stop when we find an action which is not A_INVALID.
|
||||
*/
|
||||
for (t = tlist; t != NULL; t = t->t_next)
|
||||
{
|
||||
action = cmd_search(cmd, t->t_start, t->t_end, sp);
|
||||
if (action != A_INVALID)
|
||||
break;
|
||||
}
|
||||
if (action == A_UINVALID)
|
||||
action = A_INVALID;
|
||||
return (action);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode a command from the cmdtables list.
|
||||
*/
|
||||
public int
|
||||
fcmd_decode(cmd, sp)
|
||||
char *cmd;
|
||||
char **sp;
|
||||
{
|
||||
return (cmd_decode(list_fcmd_tables, cmd, sp));
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode a command from the edittables list.
|
||||
*/
|
||||
public int
|
||||
ecmd_decode(cmd, sp)
|
||||
char *cmd;
|
||||
char **sp;
|
||||
{
|
||||
return (cmd_decode(list_ecmd_tables, cmd, sp));
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the value of an environment variable.
|
||||
* Looks first in the lesskey file, then in the real environment.
|
||||
*/
|
||||
public char *
|
||||
lgetenv(var)
|
||||
char *var;
|
||||
{
|
||||
int a;
|
||||
char *s;
|
||||
|
||||
a = cmd_decode(list_var_tables, var, &s);
|
||||
if (a == EV_OK)
|
||||
return (s);
|
||||
s = getenv(var);
|
||||
if (s != NULL && *s != '\0')
|
||||
return (s);
|
||||
a = cmd_decode(list_sysvar_tables, var, &s);
|
||||
if (a == EV_OK)
|
||||
return (s);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
#if USERFILE
|
||||
/*
|
||||
* Get an "integer" from a lesskey file.
|
||||
* Integers are stored in a funny format:
|
||||
* two bytes, low order first, in radix KRADIX.
|
||||
*/
|
||||
static int
|
||||
gint(sp)
|
||||
char **sp;
|
||||
{
|
||||
int n;
|
||||
|
||||
n = *(*sp)++;
|
||||
n += *(*sp)++ * KRADIX;
|
||||
return (n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process an old (pre-v241) lesskey file.
|
||||
*/
|
||||
static int
|
||||
old_lesskey(buf, len)
|
||||
char *buf;
|
||||
int len;
|
||||
{
|
||||
/*
|
||||
* Old-style lesskey file.
|
||||
* The file must end with either
|
||||
* ...,cmd,0,action
|
||||
* or ...,cmd,0,action|A_EXTRA,string,0
|
||||
* So the last byte or the second to last byte must be zero.
|
||||
*/
|
||||
if (buf[len-1] != '\0' && buf[len-2] != '\0')
|
||||
return (-1);
|
||||
add_fcmd_table(buf, len);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a new (post-v241) lesskey file.
|
||||
*/
|
||||
static int
|
||||
new_lesskey(buf, len, sysvar)
|
||||
char *buf;
|
||||
int len;
|
||||
int sysvar;
|
||||
{
|
||||
char *p;
|
||||
register int c;
|
||||
register int n;
|
||||
|
||||
/*
|
||||
* New-style lesskey file.
|
||||
* Extract the pieces.
|
||||
*/
|
||||
if (buf[len-3] != C0_END_LESSKEY_MAGIC ||
|
||||
buf[len-2] != C1_END_LESSKEY_MAGIC ||
|
||||
buf[len-1] != C2_END_LESSKEY_MAGIC)
|
||||
return (-1);
|
||||
p = buf + 4;
|
||||
for (;;)
|
||||
{
|
||||
c = *p++;
|
||||
switch (c)
|
||||
{
|
||||
case CMD_SECTION:
|
||||
n = gint(&p);
|
||||
add_fcmd_table(p, n);
|
||||
p += n;
|
||||
break;
|
||||
case EDIT_SECTION:
|
||||
n = gint(&p);
|
||||
add_ecmd_table(p, n);
|
||||
p += n;
|
||||
break;
|
||||
case VAR_SECTION:
|
||||
n = gint(&p);
|
||||
add_var_table((sysvar) ?
|
||||
&list_sysvar_tables : &list_var_tables, p, n);
|
||||
p += n;
|
||||
break;
|
||||
case END_SECTION:
|
||||
return (0);
|
||||
default:
|
||||
/*
|
||||
* Unrecognized section type.
|
||||
*/
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up a user command table, based on a "lesskey" file.
|
||||
*/
|
||||
public int
|
||||
lesskey(filename, sysvar)
|
||||
char *filename;
|
||||
int sysvar;
|
||||
{
|
||||
register char *buf;
|
||||
register POSITION len;
|
||||
register long n;
|
||||
register int f;
|
||||
|
||||
if (secure)
|
||||
return (1);
|
||||
/*
|
||||
* Try to open the lesskey file.
|
||||
*/
|
||||
filename = shell_unquote(filename);
|
||||
f = open(filename, OPEN_READ);
|
||||
free(filename);
|
||||
if (f < 0)
|
||||
return (1);
|
||||
|
||||
/*
|
||||
* Read the file into a buffer.
|
||||
* We first figure out the size of the file and allocate space for it.
|
||||
* {{ Minimal error checking is done here.
|
||||
* A garbage .less file will produce strange results.
|
||||
* To avoid a large amount of error checking code here, we
|
||||
* rely on the lesskey program to generate a good .less file. }}
|
||||
*/
|
||||
len = filesize(f);
|
||||
if (len == NULL_POSITION || len < 3)
|
||||
{
|
||||
/*
|
||||
* Bad file (valid file must have at least 3 chars).
|
||||
*/
|
||||
close(f);
|
||||
return (-1);
|
||||
}
|
||||
if ((buf = (char *) calloc((int)len, sizeof(char))) == NULL)
|
||||
{
|
||||
close(f);
|
||||
return (-1);
|
||||
}
|
||||
if (lseek(f, (off_t)0, 0) == BAD_LSEEK)
|
||||
{
|
||||
free(buf);
|
||||
close(f);
|
||||
return (-1);
|
||||
}
|
||||
n = read(f, buf, (unsigned int) len);
|
||||
close(f);
|
||||
if (n != len)
|
||||
{
|
||||
free(buf);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Figure out if this is an old-style (before version 241)
|
||||
* or new-style lesskey file format.
|
||||
*/
|
||||
if (buf[0] != C0_LESSKEY_MAGIC || buf[1] != C1_LESSKEY_MAGIC ||
|
||||
buf[2] != C2_LESSKEY_MAGIC || buf[3] != C3_LESSKEY_MAGIC)
|
||||
return (old_lesskey(buf, (int)len));
|
||||
return (new_lesskey(buf, (int)len, sysvar));
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the standard lesskey file "$HOME/.less"
|
||||
*/
|
||||
public void
|
||||
add_hometable(envname, def_filename, sysvar)
|
||||
char *envname;
|
||||
char *def_filename;
|
||||
int sysvar;
|
||||
{
|
||||
char *filename;
|
||||
PARG parg;
|
||||
|
||||
if (envname != NULL && (filename = lgetenv(envname)) != NULL)
|
||||
filename = save(filename);
|
||||
else if (sysvar)
|
||||
filename = save(def_filename);
|
||||
else
|
||||
filename = homefile(def_filename);
|
||||
if (filename == NULL)
|
||||
return;
|
||||
if (lesskey(filename, sysvar) < 0)
|
||||
{
|
||||
parg.p_string = filename;
|
||||
error("Cannot use lesskey file \"%s\"", &parg);
|
||||
}
|
||||
free(filename);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* See if a char is a special line-editing command.
|
||||
*/
|
||||
public int
|
||||
editchar(c, flags)
|
||||
int c;
|
||||
int flags;
|
||||
{
|
||||
int action;
|
||||
int nch;
|
||||
char *s = NULL; /* XXX: GCC */
|
||||
char usercmd[MAX_CMDLEN+1];
|
||||
|
||||
/*
|
||||
* An editing character could actually be a sequence of characters;
|
||||
* for example, an escape sequence sent by pressing the uparrow key.
|
||||
* To match the editing string, we use the command decoder
|
||||
* but give it the edit-commands command table
|
||||
* This table is constructed to match the user's keyboard.
|
||||
*/
|
||||
if (c == erase_char || c == erase2_char)
|
||||
return (EC_BACKSPACE);
|
||||
if (c == kill_char)
|
||||
return (EC_LINEKILL);
|
||||
|
||||
/*
|
||||
* Collect characters in a buffer.
|
||||
* Start with the one we have, and get more if we need them.
|
||||
*/
|
||||
nch = 0;
|
||||
do {
|
||||
if (nch > 0)
|
||||
c = getcc();
|
||||
usercmd[nch] = c;
|
||||
usercmd[nch+1] = '\0';
|
||||
nch++;
|
||||
action = ecmd_decode(usercmd, &s);
|
||||
} while (action == A_PREFIX);
|
||||
|
||||
if (flags & EC_NORIGHTLEFT)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case EC_RIGHT:
|
||||
case EC_LEFT:
|
||||
action = A_INVALID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if CMD_HISTORY
|
||||
if (flags & EC_NOHISTORY)
|
||||
{
|
||||
/*
|
||||
* The caller says there is no history list.
|
||||
* Reject any history-manipulation action.
|
||||
*/
|
||||
switch (action)
|
||||
{
|
||||
case EC_UP:
|
||||
case EC_DOWN:
|
||||
action = A_INVALID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if TAB_COMPLETE_FILENAME
|
||||
if (flags & EC_NOCOMPLETE)
|
||||
{
|
||||
/*
|
||||
* The caller says we don't want any filename completion cmds.
|
||||
* Reject them.
|
||||
*/
|
||||
switch (action)
|
||||
{
|
||||
case EC_F_COMPLETE:
|
||||
case EC_B_COMPLETE:
|
||||
case EC_EXPAND:
|
||||
action = A_INVALID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if ((flags & EC_PEEK) || action == A_INVALID)
|
||||
{
|
||||
/*
|
||||
* We're just peeking, or we didn't understand the command.
|
||||
* Unget all the characters we read in the loop above.
|
||||
* This does NOT include the original character that was
|
||||
* passed in as a parameter.
|
||||
*/
|
||||
while (nch > 1)
|
||||
{
|
||||
ungetcc(usercmd[--nch]);
|
||||
}
|
||||
} else
|
||||
{
|
||||
if (s != NULL)
|
||||
ungetsc(s);
|
||||
}
|
||||
return action;
|
||||
}
|
||||
|
||||
411
commands/less/less/defines.h
Normal file
411
commands/less/less/defines.h
Normal file
@@ -0,0 +1,411 @@
|
||||
/* $NetBSD: defines.h,v 1.7 2006/10/26 01:33:08 mrg Exp $ */
|
||||
|
||||
/* defines.h. Generated 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)
|
||||
|
||||
/*
|
||||
* LOGFILE is 1 if you wish to allow the -l 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 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 "/"
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
/*
|
||||
* Sizes of various buffers.
|
||||
*/
|
||||
#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 */
|
||||
|
||||
/* 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
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the `gen' library (-lgen). */
|
||||
/* #undef HAVE_LIBGEN */
|
||||
|
||||
/* Define to 1 if you have the `intl' library (-lintl). */
|
||||
/* #undef HAVE_LIBINTL */
|
||||
|
||||
/* Define to 1 if you have the `PW' library (-lPW). */
|
||||
/* #undef HAVE_LIBPW */
|
||||
|
||||
/* Define to 1 if you have the <limits.h> header file. */
|
||||
#define HAVE_LIMITS_H 1
|
||||
|
||||
/* Define HAVE_LOCALE if you have locale.h and setlocale. */
|
||||
#define HAVE_LOCALE 0
|
||||
|
||||
/* Define to 1 if you have the `memcpy' function. */
|
||||
#define HAVE_MEMCPY 1
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define HAVE_OSPEED if your termcap library has the ospeed variable. */
|
||||
#define HAVE_OSPEED 0
|
||||
|
||||
/* PCRE (Perl-compatible regular expression) library */
|
||||
/* #undef HAVE_PCRE */
|
||||
|
||||
/* Define to 1 if you have the `popen' function. */
|
||||
#define HAVE_POPEN 1
|
||||
|
||||
/* POSIX regcomp() and regex.h */
|
||||
#define HAVE_POSIX_REGCOMP 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. */
|
||||
#define HAVE_SIGSETMASK 1
|
||||
|
||||
/* Define HAVE_SIGSET_T you have the sigset_t type. */
|
||||
#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 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 to 1 if you have the `strchr' function. */
|
||||
#define HAVE_STRCHR 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 `strstr' function. */
|
||||
#define HAVE_STRSTR 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/ptem.h> header file. */
|
||||
/* #undef HAVE_SYS_PTEM_H */
|
||||
|
||||
/* 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 <termcap.h> header file. */
|
||||
#define HAVE_TERMCAP_H 1
|
||||
|
||||
/* 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 <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
|
||||
|
||||
/* 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 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. */
|
||||
/* #undef MUST_DEFINE_OSPEED */
|
||||
|
||||
/* 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 version of this package. */
|
||||
#define PACKAGE_VERSION "1"
|
||||
|
||||
/* Define as the return type of signal handlers (`int' or `void'). */
|
||||
#define RETSIGTYPE void
|
||||
|
||||
/* 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 you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
||||
#define TIME_WITH_SYS_TIME 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' if <sys/types.h> does not define. */
|
||||
/* #undef off_t */
|
||||
|
||||
/* Define to `unsigned' if <sys/types.h> does not define. */
|
||||
/* #undef size_t */
|
||||
795
commands/less/less/edit.c
Normal file
795
commands/less/less/edit.c
Normal file
@@ -0,0 +1,795 @@
|
||||
/* $NetBSD: edit.c,v 1.9 2008/02/16 07:20:54 matt Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1984-2005 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 about less, or for information on how to
|
||||
* contact the author, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
#include "less.h"
|
||||
|
||||
public int fd0 = 0;
|
||||
|
||||
extern int new_file;
|
||||
extern int errmsgs;
|
||||
extern int cbufs;
|
||||
extern char *every_first_cmd;
|
||||
extern int any_display;
|
||||
extern int force_open;
|
||||
extern int is_tty;
|
||||
extern int sigs;
|
||||
extern IFILE curr_ifile;
|
||||
extern IFILE old_ifile;
|
||||
extern struct scrpos initial_scrpos;
|
||||
extern void *constant ml_examine;
|
||||
#if SPACES_IN_FILENAMES
|
||||
extern char openquote;
|
||||
extern char closequote;
|
||||
#endif
|
||||
|
||||
#if LOGFILE
|
||||
extern int logfile;
|
||||
extern int force_logfile;
|
||||
extern char *namelogfile;
|
||||
#endif
|
||||
|
||||
char *curr_altfilename = NULL;
|
||||
static void *curr_altpipe;
|
||||
|
||||
|
||||
static void close_file __P((void));
|
||||
static int edit_istep __P((IFILE, int, int));
|
||||
static int edit_inext __P((IFILE, int));
|
||||
static int edit_iprev __P((IFILE, int));
|
||||
|
||||
/*
|
||||
* Textlist functions deal with a list of words separated by spaces.
|
||||
* init_textlist sets up a textlist structure.
|
||||
* forw_textlist uses that structure to iterate thru the list of
|
||||
* words, returning each one as a standard null-terminated string.
|
||||
* back_textlist does the same, but runs thru the list backwards.
|
||||
*/
|
||||
public void
|
||||
init_textlist(tlist, str)
|
||||
struct textlist *tlist;
|
||||
char *str;
|
||||
{
|
||||
char *s;
|
||||
#if SPACES_IN_FILENAMES
|
||||
int meta_quoted = 0;
|
||||
int delim_quoted = 0;
|
||||
char *esc = get_meta_escape();
|
||||
int esclen = strlen(esc);
|
||||
#endif
|
||||
|
||||
tlist->string = skipsp(str);
|
||||
tlist->endstring = tlist->string + strlen(tlist->string);
|
||||
for (s = str; s < tlist->endstring; s++)
|
||||
{
|
||||
#if SPACES_IN_FILENAMES
|
||||
if (meta_quoted)
|
||||
{
|
||||
meta_quoted = 0;
|
||||
} else if (esclen > 0 && s + esclen < tlist->endstring &&
|
||||
strncmp(s, esc, esclen) == 0)
|
||||
{
|
||||
meta_quoted = 1;
|
||||
s += esclen - 1;
|
||||
} else if (delim_quoted)
|
||||
{
|
||||
if (*s == closequote)
|
||||
delim_quoted = 0;
|
||||
} else /* (!delim_quoted) */
|
||||
{
|
||||
if (*s == openquote)
|
||||
delim_quoted = 1;
|
||||
else if (*s == ' ')
|
||||
*s = '\0';
|
||||
}
|
||||
#else
|
||||
if (*s == ' ')
|
||||
*s = '\0';
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public char *
|
||||
forw_textlist(tlist, prev)
|
||||
struct textlist *tlist;
|
||||
char *prev;
|
||||
{
|
||||
char *s;
|
||||
|
||||
/*
|
||||
* prev == NULL means return the first word in the list.
|
||||
* Otherwise, return the word after "prev".
|
||||
*/
|
||||
if (prev == NULL)
|
||||
s = tlist->string;
|
||||
else
|
||||
s = prev + strlen(prev);
|
||||
if (s >= tlist->endstring)
|
||||
return (NULL);
|
||||
while (*s == '\0')
|
||||
s++;
|
||||
if (s >= tlist->endstring)
|
||||
return (NULL);
|
||||
return (s);
|
||||
}
|
||||
|
||||
public char *
|
||||
back_textlist(tlist, prev)
|
||||
struct textlist *tlist;
|
||||
char *prev;
|
||||
{
|
||||
char *s;
|
||||
|
||||
/*
|
||||
* prev == NULL means return the last word in the list.
|
||||
* Otherwise, return the word before "prev".
|
||||
*/
|
||||
if (prev == NULL)
|
||||
s = tlist->endstring;
|
||||
else if (prev <= tlist->string)
|
||||
return (NULL);
|
||||
else
|
||||
s = prev - 1;
|
||||
while (*s == '\0')
|
||||
s--;
|
||||
if (s <= tlist->string)
|
||||
return (NULL);
|
||||
while (s[-1] != '\0' && s > tlist->string)
|
||||
s--;
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Close the current input file.
|
||||
*/
|
||||
static void
|
||||
close_file()
|
||||
{
|
||||
struct scrpos scrpos;
|
||||
|
||||
if (curr_ifile == NULL_IFILE)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Save the current position so that we can return to
|
||||
* the same position if we edit this file again.
|
||||
*/
|
||||
get_scrpos(&scrpos);
|
||||
if (scrpos.pos != NULL_POSITION)
|
||||
{
|
||||
store_pos(curr_ifile, &scrpos);
|
||||
lastmark();
|
||||
}
|
||||
/*
|
||||
* Close the file descriptor, unless it is a pipe.
|
||||
*/
|
||||
ch_close();
|
||||
/*
|
||||
* If we opened a file using an alternate name,
|
||||
* do special stuff to close it.
|
||||
*/
|
||||
if (curr_altfilename != NULL)
|
||||
{
|
||||
close_altfile(curr_altfilename, get_filename(curr_ifile),
|
||||
curr_altpipe);
|
||||
free(curr_altfilename);
|
||||
curr_altfilename = NULL;
|
||||
}
|
||||
curr_ifile = NULL_IFILE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Edit a new file (given its name).
|
||||
* Filename == "-" means standard input.
|
||||
* Filename == NULL means just close the current file.
|
||||
*/
|
||||
public int
|
||||
edit(filename)
|
||||
char *filename;
|
||||
{
|
||||
if (filename == NULL)
|
||||
return (edit_ifile(NULL_IFILE));
|
||||
return (edit_ifile(get_ifile(filename, curr_ifile)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Edit a new file (given its IFILE).
|
||||
* ifile == NULL means just close the current file.
|
||||
*/
|
||||
public int
|
||||
edit_ifile(ifile)
|
||||
IFILE ifile;
|
||||
{
|
||||
int f;
|
||||
int answer;
|
||||
int no_display;
|
||||
int chflags;
|
||||
char *filename;
|
||||
char *open_filename;
|
||||
char *qopen_filename;
|
||||
char *alt_filename;
|
||||
void *alt_pipe;
|
||||
IFILE was_curr_ifile;
|
||||
PARG parg;
|
||||
|
||||
if (ifile == curr_ifile)
|
||||
{
|
||||
/*
|
||||
* Already have the correct file open.
|
||||
*/
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* We must close the currently open file now.
|
||||
* This is necessary to make the open_altfile/close_altfile pairs
|
||||
* nest properly (or rather to avoid nesting at all).
|
||||
* {{ Some stupid implementations of popen() mess up if you do:
|
||||
* fA = popen("A"); fB = popen("B"); pclose(fA); pclose(fB); }}
|
||||
*/
|
||||
#if LOGFILE
|
||||
end_logfile();
|
||||
#endif
|
||||
was_curr_ifile = save_curr_ifile();
|
||||
if (curr_ifile != NULL_IFILE)
|
||||
{
|
||||
chflags = ch_getflags();
|
||||
close_file();
|
||||
if ((chflags & CH_HELPFILE) && held_ifile(was_curr_ifile) <= 1)
|
||||
{
|
||||
/*
|
||||
* Don't keep the help file in the ifile list.
|
||||
*/
|
||||
del_ifile(was_curr_ifile);
|
||||
was_curr_ifile = old_ifile;
|
||||
}
|
||||
}
|
||||
|
||||
if (ifile == NULL_IFILE)
|
||||
{
|
||||
/*
|
||||
* No new file to open.
|
||||
* (Don't set old_ifile, because if you call edit_ifile(NULL),
|
||||
* you're supposed to have saved curr_ifile yourself,
|
||||
* and you'll restore it if necessary.)
|
||||
*/
|
||||
unsave_ifile(was_curr_ifile);
|
||||
return (0);
|
||||
}
|
||||
|
||||
filename = save(get_filename(ifile));
|
||||
/*
|
||||
* See if LESSOPEN specifies an "alternate" file to open.
|
||||
*/
|
||||
alt_pipe = NULL;
|
||||
alt_filename = open_altfile(filename, &f, &alt_pipe);
|
||||
open_filename = (alt_filename != NULL) ? alt_filename : filename;
|
||||
qopen_filename = shell_unquote(open_filename);
|
||||
|
||||
chflags = 0;
|
||||
if (alt_pipe != NULL)
|
||||
{
|
||||
/*
|
||||
* The alternate "file" is actually a pipe.
|
||||
* f has already been set to the file descriptor of the pipe
|
||||
* in the call to open_altfile above.
|
||||
* Keep the file descriptor open because it was opened
|
||||
* via popen(), and pclose() wants to close it.
|
||||
*/
|
||||
chflags |= CH_POPENED;
|
||||
} else if (strcmp(open_filename, "-") == 0)
|
||||
{
|
||||
/*
|
||||
* Use standard input.
|
||||
* Keep the file descriptor open because we can't reopen it.
|
||||
*/
|
||||
f = fd0;
|
||||
chflags |= CH_KEEPOPEN;
|
||||
/*
|
||||
* Must switch stdin to BINARY mode.
|
||||
*/
|
||||
SET_BINARY(f);
|
||||
#if MSDOS_COMPILER==DJGPPC
|
||||
/*
|
||||
* Setting stdin to binary by default causes
|
||||
* Ctrl-C to not raise SIGINT. We must undo
|
||||
* that side-effect.
|
||||
*/
|
||||
__djgpp_set_ctrl_c(1);
|
||||
#endif
|
||||
} else if (strcmp(open_filename, FAKE_HELPFILE) == 0)
|
||||
{
|
||||
f = -1;
|
||||
chflags |= CH_HELPFILE;
|
||||
} else if ((parg.p_string = bad_file(open_filename)) != NULL)
|
||||
{
|
||||
/*
|
||||
* It looks like a bad file. Don't try to open it.
|
||||
*/
|
||||
error("%s", &parg);
|
||||
free((void *)parg.p_string);
|
||||
err1:
|
||||
if (alt_filename != NULL)
|
||||
{
|
||||
close_altfile(alt_filename, filename, alt_pipe);
|
||||
free(alt_filename);
|
||||
}
|
||||
del_ifile(ifile);
|
||||
free(qopen_filename);
|
||||
free(filename);
|
||||
/*
|
||||
* Re-open the current file.
|
||||
*/
|
||||
if (was_curr_ifile == ifile)
|
||||
{
|
||||
/*
|
||||
* Whoops. The "current" ifile is the one we just deleted.
|
||||
* Just give up.
|
||||
*/
|
||||
quit(QUIT_ERROR);
|
||||
}
|
||||
reedit_ifile(was_curr_ifile);
|
||||
return (1);
|
||||
} else if ((f = open(qopen_filename, OPEN_READ)) < 0)
|
||||
{
|
||||
/*
|
||||
* Got an error trying to open it.
|
||||
*/
|
||||
parg.p_string = errno_message(filename);
|
||||
error("%s", &parg);
|
||||
free((void *)parg.p_string);
|
||||
goto err1;
|
||||
} else
|
||||
{
|
||||
chflags |= CH_CANSEEK;
|
||||
if (!force_open && !opened(ifile) && bin_file(f))
|
||||
{
|
||||
/*
|
||||
* Looks like a binary file.
|
||||
* Ask user if we should proceed.
|
||||
*/
|
||||
parg.p_string = filename;
|
||||
answer = query("\"%s\" may be a binary file. See it anyway? ",
|
||||
&parg);
|
||||
if (answer != 'y' && answer != 'Y')
|
||||
{
|
||||
close(f);
|
||||
goto err1;
|
||||
}
|
||||
}
|
||||
}
|
||||
free(qopen_filename);
|
||||
|
||||
/*
|
||||
* Get the new ifile.
|
||||
* Get the saved position for the file.
|
||||
*/
|
||||
if (was_curr_ifile != NULL_IFILE)
|
||||
{
|
||||
old_ifile = was_curr_ifile;
|
||||
unsave_ifile(was_curr_ifile);
|
||||
}
|
||||
curr_ifile = ifile;
|
||||
curr_altfilename = alt_filename;
|
||||
curr_altpipe = alt_pipe;
|
||||
set_open(curr_ifile); /* File has been opened */
|
||||
get_pos(curr_ifile, &initial_scrpos);
|
||||
new_file = TRUE;
|
||||
ch_init(f, chflags);
|
||||
|
||||
if (!(chflags & CH_HELPFILE))
|
||||
{
|
||||
#if LOGFILE
|
||||
if (namelogfile != NULL && is_tty)
|
||||
use_logfile(namelogfile);
|
||||
#endif
|
||||
if (every_first_cmd != NULL)
|
||||
ungetsc(every_first_cmd);
|
||||
}
|
||||
|
||||
no_display = !any_display;
|
||||
flush();
|
||||
any_display = TRUE;
|
||||
|
||||
if (is_tty)
|
||||
{
|
||||
/*
|
||||
* Output is to a real tty.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Indicate there is nothing displayed yet.
|
||||
*/
|
||||
pos_clear();
|
||||
clr_linenum();
|
||||
#if HILITE_SEARCH
|
||||
clr_hilite();
|
||||
#endif
|
||||
cmd_addhist(ml_examine, filename);
|
||||
if (no_display && errmsgs > 0)
|
||||
{
|
||||
/*
|
||||
* We displayed some messages on error output
|
||||
* (file descriptor 2; see error() function).
|
||||
* Before erasing the screen contents,
|
||||
* display the file name and wait for a keystroke.
|
||||
*/
|
||||
parg.p_string = filename;
|
||||
error("%s", &parg);
|
||||
}
|
||||
}
|
||||
free(filename);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Edit a space-separated list of files.
|
||||
* For each filename in the list, enter it into the ifile list.
|
||||
* Then edit the first one.
|
||||
*/
|
||||
public int
|
||||
edit_list(filelist)
|
||||
char *filelist;
|
||||
{
|
||||
IFILE save_ifile;
|
||||
char *good_filename;
|
||||
char *filename;
|
||||
char *gfilelist;
|
||||
char *gfilename;
|
||||
struct textlist tl_files;
|
||||
struct textlist tl_gfiles;
|
||||
|
||||
save_ifile = save_curr_ifile();
|
||||
good_filename = NULL;
|
||||
|
||||
/*
|
||||
* Run thru each filename in the list.
|
||||
* Try to glob the filename.
|
||||
* If it doesn't expand, just try to open the filename.
|
||||
* If it does expand, try to open each name in that list.
|
||||
*/
|
||||
init_textlist(&tl_files, filelist);
|
||||
filename = NULL;
|
||||
while ((filename = forw_textlist(&tl_files, filename)) != NULL)
|
||||
{
|
||||
gfilelist = lglob(filename);
|
||||
init_textlist(&tl_gfiles, gfilelist);
|
||||
gfilename = NULL;
|
||||
while ((gfilename = forw_textlist(&tl_gfiles, gfilename)) != NULL)
|
||||
{
|
||||
if (edit(gfilename) == 0 && good_filename == NULL)
|
||||
good_filename = get_filename(curr_ifile);
|
||||
}
|
||||
free(gfilelist);
|
||||
}
|
||||
/*
|
||||
* Edit the first valid filename in the list.
|
||||
*/
|
||||
if (good_filename == NULL)
|
||||
{
|
||||
unsave_ifile(save_ifile);
|
||||
return (1);
|
||||
}
|
||||
if (get_ifile(good_filename, curr_ifile) == curr_ifile)
|
||||
{
|
||||
/*
|
||||
* Trying to edit the current file; don't reopen it.
|
||||
*/
|
||||
unsave_ifile(save_ifile);
|
||||
return (0);
|
||||
}
|
||||
reedit_ifile(save_ifile);
|
||||
return (edit(good_filename));
|
||||
}
|
||||
|
||||
/*
|
||||
* Edit the first file in the command line (ifile) list.
|
||||
*/
|
||||
public int
|
||||
edit_first()
|
||||
{
|
||||
curr_ifile = NULL_IFILE;
|
||||
return (edit_next(1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Edit the last file in the command line (ifile) list.
|
||||
*/
|
||||
public int
|
||||
edit_last()
|
||||
{
|
||||
curr_ifile = NULL_IFILE;
|
||||
return (edit_prev(1));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Edit the n-th next or previous file in the command line (ifile) list.
|
||||
*/
|
||||
static int
|
||||
edit_istep(h, n, dir)
|
||||
IFILE h;
|
||||
int n;
|
||||
int dir;
|
||||
{
|
||||
IFILE next;
|
||||
|
||||
/*
|
||||
* Skip n filenames, then try to edit each filename.
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
next = (dir > 0) ? next_ifile(h) : prev_ifile(h);
|
||||
if (--n < 0)
|
||||
{
|
||||
if (edit_ifile(h) == 0)
|
||||
break;
|
||||
}
|
||||
if (next == NULL_IFILE)
|
||||
{
|
||||
/*
|
||||
* Reached end of the ifile list.
|
||||
*/
|
||||
return (1);
|
||||
}
|
||||
if (ABORT_SIGS())
|
||||
{
|
||||
/*
|
||||
* Interrupt breaks out, if we're in a long
|
||||
* list of files that can't be opened.
|
||||
*/
|
||||
return (1);
|
||||
}
|
||||
h = next;
|
||||
}
|
||||
/*
|
||||
* Found a file that we can edit.
|
||||
*/
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
edit_inext(h, n)
|
||||
IFILE h;
|
||||
int n;
|
||||
{
|
||||
return (edit_istep(h, n, +1));
|
||||
}
|
||||
|
||||
public int
|
||||
edit_next(n)
|
||||
int n;
|
||||
{
|
||||
return edit_istep(curr_ifile, n, +1);
|
||||
}
|
||||
|
||||
static int
|
||||
edit_iprev(h, n)
|
||||
IFILE h;
|
||||
int n;
|
||||
{
|
||||
return (edit_istep(h, n, -1));
|
||||
}
|
||||
|
||||
public int
|
||||
edit_prev(n)
|
||||
int n;
|
||||
{
|
||||
return edit_istep(curr_ifile, n, -1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Edit a specific file in the command line (ifile) list.
|
||||
*/
|
||||
public int
|
||||
edit_index(n)
|
||||
int n;
|
||||
{
|
||||
IFILE h;
|
||||
|
||||
h = NULL_IFILE;
|
||||
do
|
||||
{
|
||||
if ((h = next_ifile(h)) == NULL_IFILE)
|
||||
{
|
||||
/*
|
||||
* Reached end of the list without finding it.
|
||||
*/
|
||||
return (1);
|
||||
}
|
||||
} while (get_index(h) != n);
|
||||
|
||||
return (edit_ifile(h));
|
||||
}
|
||||
|
||||
public IFILE
|
||||
save_curr_ifile()
|
||||
{
|
||||
if (curr_ifile != NULL_IFILE)
|
||||
hold_ifile(curr_ifile, 1);
|
||||
return (curr_ifile);
|
||||
}
|
||||
|
||||
public void
|
||||
unsave_ifile(save_ifile)
|
||||
IFILE save_ifile;
|
||||
{
|
||||
if (save_ifile != NULL_IFILE)
|
||||
hold_ifile(save_ifile, -1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reedit the ifile which was previously open.
|
||||
*/
|
||||
public void
|
||||
reedit_ifile(save_ifile)
|
||||
IFILE save_ifile;
|
||||
{
|
||||
IFILE next;
|
||||
IFILE prev;
|
||||
|
||||
/*
|
||||
* Try to reopen the ifile.
|
||||
* Note that opening it may fail (maybe the file was removed),
|
||||
* in which case the ifile will be deleted from the list.
|
||||
* So save the next and prev ifiles first.
|
||||
*/
|
||||
unsave_ifile(save_ifile);
|
||||
next = next_ifile(save_ifile);
|
||||
prev = prev_ifile(save_ifile);
|
||||
if (edit_ifile(save_ifile) == 0)
|
||||
return;
|
||||
/*
|
||||
* If can't reopen it, open the next input file in the list.
|
||||
*/
|
||||
if (next != NULL_IFILE && edit_inext(next, 0) == 0)
|
||||
return;
|
||||
/*
|
||||
* If can't open THAT one, open the previous input file in the list.
|
||||
*/
|
||||
if (prev != NULL_IFILE && edit_iprev(prev, 0) == 0)
|
||||
return;
|
||||
/*
|
||||
* If can't even open that, we're stuck. Just quit.
|
||||
*/
|
||||
quit(QUIT_ERROR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Edit standard input.
|
||||
*/
|
||||
public int
|
||||
edit_stdin()
|
||||
{
|
||||
if (isatty(fd0))
|
||||
{
|
||||
error("Missing filename (\"less --help\" for help)", NULL_PARG);
|
||||
quit(QUIT_OK);
|
||||
}
|
||||
return (edit("-"));
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy a file directly to standard output.
|
||||
* Used if standard output is not a tty.
|
||||
*/
|
||||
public void
|
||||
cat_file()
|
||||
{
|
||||
register int c;
|
||||
|
||||
while ((c = ch_forw_get()) != EOI)
|
||||
putchr(c);
|
||||
flush();
|
||||
}
|
||||
|
||||
#if LOGFILE
|
||||
|
||||
/*
|
||||
* If the user asked for a log file and our input file
|
||||
* is standard input, create the log file.
|
||||
* We take care not to blindly overwrite an existing file.
|
||||
*/
|
||||
public void
|
||||
use_logfile(filename)
|
||||
char *filename;
|
||||
{
|
||||
register int exists;
|
||||
register int answer;
|
||||
PARG parg;
|
||||
|
||||
if (ch_getflags() & CH_CANSEEK)
|
||||
/*
|
||||
* Can't currently use a log file on a file that can seek.
|
||||
*/
|
||||
return;
|
||||
|
||||
/*
|
||||
* {{ We could use access() here. }}
|
||||
*/
|
||||
filename = shell_unquote(filename);
|
||||
exists = open(filename, OPEN_READ);
|
||||
if (exists >= 0)
|
||||
close(exists);
|
||||
exists = (exists >= 0);
|
||||
|
||||
/*
|
||||
* Decide whether to overwrite the log file or append to it.
|
||||
* If it doesn't exist we "overwrite" it.
|
||||
*/
|
||||
if (!exists || force_logfile)
|
||||
{
|
||||
/*
|
||||
* Overwrite (or create) the log file.
|
||||
*/
|
||||
answer = 'O';
|
||||
} else
|
||||
{
|
||||
/*
|
||||
* Ask user what to do.
|
||||
*/
|
||||
parg.p_string = filename;
|
||||
answer = query("Warning: \"%s\" exists; Overwrite, Append or Don't log? ", &parg);
|
||||
}
|
||||
|
||||
loop:
|
||||
switch (answer)
|
||||
{
|
||||
case 'O': case 'o':
|
||||
/*
|
||||
* Overwrite: create the file.
|
||||
*/
|
||||
logfile = creat(filename, 0644);
|
||||
break;
|
||||
case 'A': case 'a':
|
||||
/*
|
||||
* Append: open the file and seek to the end.
|
||||
*/
|
||||
logfile = open(filename, OPEN_APPEND);
|
||||
if (lseek(logfile, (off_t)0, 2) == BAD_LSEEK)
|
||||
{
|
||||
close(logfile);
|
||||
logfile = -1;
|
||||
}
|
||||
break;
|
||||
case 'D': case 'd':
|
||||
/*
|
||||
* Don't do anything.
|
||||
*/
|
||||
free(filename);
|
||||
return;
|
||||
case 'q':
|
||||
quit(QUIT_OK);
|
||||
/*NOTREACHED*/
|
||||
default:
|
||||
/*
|
||||
* Eh?
|
||||
*/
|
||||
answer = query("Overwrite, Append, or Don't log? (Type \"O\", \"A\", \"D\" or \"q\") ", NULL_PARG);
|
||||
goto loop;
|
||||
}
|
||||
|
||||
if (logfile < 0)
|
||||
{
|
||||
/*
|
||||
* Error in opening logfile.
|
||||
*/
|
||||
parg.p_string = filename;
|
||||
error("Cannot write to \"%s\"", &parg);
|
||||
free(filename);
|
||||
return;
|
||||
}
|
||||
free(filename);
|
||||
SET_BINARY(logfile);
|
||||
}
|
||||
|
||||
#endif
|
||||
1043
commands/less/less/filename.c
Normal file
1043
commands/less/less/filename.c
Normal file
File diff suppressed because it is too large
Load Diff
417
commands/less/less/forwback.c
Normal file
417
commands/less/less/forwback.c
Normal file
@@ -0,0 +1,417 @@
|
||||
/* $NetBSD: forwback.c,v 1.10 2006/10/26 01:33:08 mrg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1984-2005 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 about less, or for information on how to
|
||||
* contact the author, 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 hit_eof; /* Keeps track of how many times we hit end of file */
|
||||
public int screen_trashed;
|
||||
public int squished;
|
||||
public int no_back_scroll = 0;
|
||||
|
||||
extern int sigs;
|
||||
extern int top_scroll;
|
||||
extern int quiet;
|
||||
extern int sc_width, sc_height;
|
||||
extern int quit_at_eof;
|
||||
extern int more_mode;
|
||||
extern int plusoption;
|
||||
extern int forw_scroll;
|
||||
extern int back_scroll;
|
||||
extern int ignore_eoi;
|
||||
extern int clear_bg;
|
||||
extern int final_attr;
|
||||
#if TAGS
|
||||
extern char *tagoption;
|
||||
#endif
|
||||
|
||||
static void eof_bell __P((void));
|
||||
static void eof_check __P((void));
|
||||
static void squish_check __P((void));
|
||||
|
||||
/*
|
||||
* Sound the bell to indicate user is trying to move past end of file.
|
||||
*/
|
||||
static void
|
||||
eof_bell()
|
||||
{
|
||||
if (quiet == NOT_QUIET)
|
||||
bell();
|
||||
else
|
||||
vbell();
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if the end of file is currently "displayed".
|
||||
*/
|
||||
static void
|
||||
eof_check()
|
||||
{
|
||||
POSITION pos;
|
||||
|
||||
if (ignore_eoi)
|
||||
return;
|
||||
if (ABORT_SIGS())
|
||||
return;
|
||||
/*
|
||||
* 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);
|
||||
if (pos == NULL_POSITION || pos == ch_length())
|
||||
hit_eof++;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
static void
|
||||
squish_check()
|
||||
{
|
||||
if (!squished)
|
||||
return;
|
||||
squished = 0;
|
||||
repaint();
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(n, pos, force, only_last, nblank)
|
||||
register int n;
|
||||
POSITION pos;
|
||||
int force;
|
||||
int only_last;
|
||||
int nblank;
|
||||
{
|
||||
int eof = 0;
|
||||
int nlines = 0;
|
||||
int do_repaint;
|
||||
static int first_time = 1;
|
||||
|
||||
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 (!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;
|
||||
if (more_mode == 0)
|
||||
{
|
||||
if (top_scroll == OPT_ONPLUS ||
|
||||
(first_time && top_scroll != OPT_ON))
|
||||
clear();
|
||||
home();
|
||||
}
|
||||
} else
|
||||
{
|
||||
clear_bot();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (top_scroll == OPT_ONPLUS)
|
||||
clear();
|
||||
home();
|
||||
} else if (!first_time)
|
||||
{
|
||||
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 (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.
|
||||
*/
|
||||
eof = 1;
|
||||
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 || more_mode) &&
|
||||
pos == NULL_POSITION && !top_scroll &&
|
||||
#if TAGS
|
||||
tagoption == NULL &&
|
||||
#endif
|
||||
!plusoption)
|
||||
{
|
||||
squished = 1;
|
||||
continue;
|
||||
}
|
||||
if (top_scroll == OPT_ON)
|
||||
clear_eol();
|
||||
put_line();
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
if (ignore_eoi)
|
||||
hit_eof = 0;
|
||||
else if (eof && !ABORT_SIGS())
|
||||
hit_eof++;
|
||||
else
|
||||
eof_check();
|
||||
if (nlines == 0)
|
||||
eof_bell();
|
||||
else if (do_repaint)
|
||||
repaint();
|
||||
first_time = 0;
|
||||
(void) currline(BOTTOM);
|
||||
}
|
||||
|
||||
/*
|
||||
* Display n lines, scrolling backward.
|
||||
*/
|
||||
public void
|
||||
back(n, pos, force, only_last)
|
||||
register 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));
|
||||
hit_eof = 0;
|
||||
while (--n >= 0)
|
||||
{
|
||||
/*
|
||||
* Get the previous line of input.
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
eof_check();
|
||||
if (nlines == 0)
|
||||
eof_bell();
|
||||
else if (do_repaint)
|
||||
repaint();
|
||||
(void) currline(BOTTOM);
|
||||
}
|
||||
|
||||
/*
|
||||
* Display n more lines, forward.
|
||||
* Start just after the line currently displayed at the bottom of the screen.
|
||||
*/
|
||||
public void
|
||||
forward(n, force, only_last)
|
||||
int n;
|
||||
int force;
|
||||
int only_last;
|
||||
{
|
||||
POSITION pos;
|
||||
|
||||
if (quit_at_eof && hit_eof && !(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);
|
||||
}
|
||||
} else
|
||||
{
|
||||
eof_bell();
|
||||
hit_eof++;
|
||||
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(n, force, only_last)
|
||||
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()
|
||||
{
|
||||
if (no_back_scroll)
|
||||
return (0);
|
||||
if (back_scroll >= 0)
|
||||
return (back_scroll);
|
||||
if (top_scroll)
|
||||
return (sc_height - 2);
|
||||
return (10000); /* infinity */
|
||||
}
|
||||
263
commands/less/less/funcs.h
Normal file
263
commands/less/less/funcs.h
Normal file
@@ -0,0 +1,263 @@
|
||||
/* $NetBSD: funcs.h,v 1.9 2006/10/26 01:33:08 mrg Exp $ */
|
||||
|
||||
public char * save ();
|
||||
public VOID_POINTER ecalloc ();
|
||||
public char * skipsp ();
|
||||
public int sprefix ();
|
||||
public void quit () __attribute__((__noreturn__));
|
||||
public void raw_mode ();
|
||||
public void scrsize ();
|
||||
public char * special_key_str ();
|
||||
public void get_term ();
|
||||
public void init ();
|
||||
public void deinit ();
|
||||
public void home ();
|
||||
public void add_line ();
|
||||
public void remove_top ();
|
||||
public void win32_scroll_up ();
|
||||
public void lower_left ();
|
||||
public void check_winch ();
|
||||
public void goto_line ();
|
||||
public void vbell ();
|
||||
public void bell ();
|
||||
public void clear ();
|
||||
public void clear_eol ();
|
||||
public void clear_bot ();
|
||||
public void at_enter ();
|
||||
public void at_exit ();
|
||||
public void at_switch ();
|
||||
public int is_at_equiv ();
|
||||
public int apply_at_specials ();
|
||||
public void backspace ();
|
||||
public void putbs ();
|
||||
public char WIN32getch ();
|
||||
public void match_brac ();
|
||||
public void ch_ungetchar ();
|
||||
public void end_logfile ();
|
||||
public void sync_logfile ();
|
||||
public int ch_seek ();
|
||||
public int ch_end_seek ();
|
||||
public int ch_beg_seek ();
|
||||
public POSITION ch_length ();
|
||||
public POSITION ch_tell ();
|
||||
public int ch_forw_get ();
|
||||
public int ch_back_get ();
|
||||
public void ch_setbufspace ();
|
||||
public void ch_flush ();
|
||||
public int seekable ();
|
||||
public void ch_init ();
|
||||
public void ch_close ();
|
||||
public int ch_getflags ();
|
||||
public void ch_dump ();
|
||||
public void init_charset ();
|
||||
public int binary_char ();
|
||||
public int control_char ();
|
||||
public char * prchar ();
|
||||
public char * prutfchar ();
|
||||
public int utf_len ();
|
||||
public int is_utf8_well_formed ();
|
||||
public LWCHAR get_wchar ();
|
||||
public LWCHAR step_char ();
|
||||
public int is_composing_char ();
|
||||
public int is_ubin_char ();
|
||||
public int is_wide_char ();
|
||||
public int is_combining_char ();
|
||||
public void cmd_reset ();
|
||||
public void clear_cmd ();
|
||||
public void cmd_putstr ();
|
||||
public int len_cmdbuf ();
|
||||
public void set_mlist ();
|
||||
public void cmd_addhist ();
|
||||
public void cmd_accept ();
|
||||
public int cmd_char ();
|
||||
public LINENUM cmd_int ();
|
||||
public char * get_cmdbuf ();
|
||||
public void init_cmdhist ();
|
||||
public void save_cmdhist ();
|
||||
public int in_mca ();
|
||||
public void dispversion ();
|
||||
public int getcc ();
|
||||
public void ungetcc ();
|
||||
public void ungetsc ();
|
||||
public void commands ();
|
||||
public void init_cmds ();
|
||||
public void add_fcmd_table ();
|
||||
public void add_ecmd_table ();
|
||||
public int fcmd_decode ();
|
||||
public int ecmd_decode ();
|
||||
public char * lgetenv ();
|
||||
public int lesskey ();
|
||||
public void add_hometable ();
|
||||
public int editchar ();
|
||||
public void init_textlist ();
|
||||
public char * forw_textlist ();
|
||||
public char * back_textlist ();
|
||||
public int edit ();
|
||||
public int edit_ifile ();
|
||||
public int edit_list ();
|
||||
public int edit_first ();
|
||||
public int edit_last ();
|
||||
public int edit_next ();
|
||||
public int edit_prev ();
|
||||
public int edit_index ();
|
||||
public IFILE save_curr_ifile ();
|
||||
public void unsave_ifile ();
|
||||
public void reedit_ifile ();
|
||||
public int edit_stdin ();
|
||||
public void cat_file ();
|
||||
public void use_logfile ();
|
||||
public char * shell_unquote ();
|
||||
public char * get_meta_escape ();
|
||||
public char * shell_quote ();
|
||||
public char * homefile ();
|
||||
public char * fexpand ();
|
||||
public char * fcomplete ();
|
||||
public int bin_file ();
|
||||
public char * lglob ();
|
||||
public char * open_altfile ();
|
||||
public void close_altfile ();
|
||||
public int is_dir ();
|
||||
public char * bad_file ();
|
||||
public POSITION filesize ();
|
||||
public char * shell_coption ();
|
||||
public void forw ();
|
||||
public void back ();
|
||||
public void forward ();
|
||||
public void backward ();
|
||||
public int get_back_scroll ();
|
||||
public void del_ifile ();
|
||||
public IFILE next_ifile ();
|
||||
public IFILE prev_ifile ();
|
||||
public IFILE getoff_ifile ();
|
||||
public int nifile ();
|
||||
public IFILE get_ifile ();
|
||||
public char * get_filename ();
|
||||
public int get_index ();
|
||||
public void store_pos ();
|
||||
public void get_pos ();
|
||||
public void set_open ();
|
||||
public int opened ();
|
||||
public void hold_ifile ();
|
||||
public int held_ifile ();
|
||||
public void * get_filestate ();
|
||||
public void set_filestate ();
|
||||
public void if_dump ();
|
||||
public POSITION forw_line ();
|
||||
public POSITION back_line ();
|
||||
public void set_attnpos ();
|
||||
public void jump_forw ();
|
||||
public void jump_back ();
|
||||
public void repaint ();
|
||||
public void jump_percent ();
|
||||
public void jump_line_loc ();
|
||||
public void jump_loc ();
|
||||
public void init_line ();
|
||||
public int is_ascii_char ();
|
||||
public void prewind ();
|
||||
public void plinenum ();
|
||||
public void pshift_all ();
|
||||
public int is_ansi_end ();
|
||||
public int is_ansi_middle ();
|
||||
public int pappend ();
|
||||
public int pflushmbc ();
|
||||
public void pdone ();
|
||||
public int gline ();
|
||||
public void null_line ();
|
||||
public POSITION forw_raw_line ();
|
||||
public POSITION back_raw_line ();
|
||||
public void clr_linenum ();
|
||||
public void add_lnum ();
|
||||
public LINENUM find_linenum ();
|
||||
public POSITION find_pos ();
|
||||
public LINENUM currline ();
|
||||
public void lsystem ();
|
||||
public int pipe_mark ();
|
||||
public int pipe_data ();
|
||||
public void init_mark ();
|
||||
public int badmark ();
|
||||
public void setmark ();
|
||||
public void lastmark ();
|
||||
public void gomark ();
|
||||
public POSITION markpos ();
|
||||
public void unmark ();
|
||||
public void opt_o ();
|
||||
public void opt__O ();
|
||||
public void opt_l ();
|
||||
public void opt_k ();
|
||||
public void opt_t ();
|
||||
public void opt__T ();
|
||||
public void opt_p ();
|
||||
public void opt__P ();
|
||||
public void opt_b ();
|
||||
public void opt_i ();
|
||||
public void opt__V ();
|
||||
public void opt_D ();
|
||||
public void opt_x ();
|
||||
public void opt_quote ();
|
||||
public void opt_query ();
|
||||
public int get_swindow ();
|
||||
public void scan_option ();
|
||||
public void toggle_option ();
|
||||
public int single_char_option ();
|
||||
public char * opt_prompt ();
|
||||
public int isoptpending ();
|
||||
public void nopendopt ();
|
||||
public int getnum ();
|
||||
public void init_option ();
|
||||
public struct loption * findopt ();
|
||||
public struct loption * findopt_name ();
|
||||
public int iread ();
|
||||
public void intread ();
|
||||
public long get_time ();
|
||||
public char * errno_message ();
|
||||
public int percentage ();
|
||||
public POSITION percent_pos ();
|
||||
public int os9_signal ();
|
||||
public void put_line ();
|
||||
public void flush ();
|
||||
public int putchr ();
|
||||
public void putstr ();
|
||||
public void get_return ();
|
||||
public void error ();
|
||||
public void ierror ();
|
||||
public int query ();
|
||||
public POSITION position ();
|
||||
public void add_forw_pos ();
|
||||
public void add_back_pos ();
|
||||
public void pos_clear ();
|
||||
public void pos_init ();
|
||||
public int onscreen ();
|
||||
public int empty_screen ();
|
||||
public int empty_lines ();
|
||||
public void get_scrpos ();
|
||||
public int adjsline ();
|
||||
public void init_prompt ();
|
||||
public char * pr_expand ();
|
||||
public char * eq_message ();
|
||||
public char * pr_string ();
|
||||
public char * wait_message ();
|
||||
public void repaint_hilite ();
|
||||
public void clear_attn ();
|
||||
public void undo_search ();
|
||||
public void clr_hilite ();
|
||||
public int is_hilited ();
|
||||
public void chg_caseless ();
|
||||
public void chg_hilite ();
|
||||
public int search ();
|
||||
public void prep_hilite ();
|
||||
public RETSIGTYPE winch ();
|
||||
public RETSIGTYPE winch ();
|
||||
public void init_signals ();
|
||||
public void psignals ();
|
||||
public void cleantags ();
|
||||
public int gettagtype ();
|
||||
public void findtag ();
|
||||
public POSITION tagsearch ();
|
||||
public char * nexttag ();
|
||||
public char * prevtag ();
|
||||
public int ntags ();
|
||||
public int curr_tag ();
|
||||
public int edit_tagfile ();
|
||||
public void open_getchr ();
|
||||
public void close_getchr ();
|
||||
public int getchr ();
|
||||
232
commands/less/less/help.c
Normal file
232
commands/less/less/help.c
Normal file
@@ -0,0 +1,232 @@
|
||||
/* $NetBSD: help.c,v 1.6 2006/11/20 22:06:26 dsl Exp $ */
|
||||
|
||||
/* This file was generated by mkhelp from less.hlp */
|
||||
#include "less.h"
|
||||
#ifdef SMALL
|
||||
constant char helpdata[] = "\nNo help available\n";
|
||||
#else
|
||||
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',
|
||||
'\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',' ','*',' ',' ','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','-','(',' ',' ','L','e','f','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',
|
||||
' ',' ','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',
|
||||
' ',' ','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',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ','S','e','a','r','c','h',' ','p','a','t','t','e','r','n','s',' ','m','a','y',' ','b','e',' ','m','o','d','i','f','i','e','d',' ','b','y',' ','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',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ','*',' ','a','n','d',' ','@',' ','m','o','d','i','f','i','e','r','s',' ','a','r','e',' ','r','e','c','o','g','n','i','z','e','d',' ','i','n',' ','l','e','s','s',' ','m','o','d','e',' ','o','n','l','y','.','\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',' ','p','o','s','i','t','i','o','n',' ','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',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\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',
|
||||
' ',' ','|','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',
|
||||
' ',' ','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','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',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','F','o','r','w','a','r','d',' ','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',
|
||||
' ',' ','-','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',' ',' ','.','.','.','.',' ',' ','-','-','c','l','e','a','r','-','s','c','r','e','e','n',' ',' ','-','-','C','L','E','A','R','-','S','C','R','E','E','N','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','R','e','p','a','i','n','t',' ','b','y',' ','s','c','r','o','l','l','i','n','g','/','c','l','e','a','r','i','n','g','.','\n',
|
||||
' ',' ','-','d',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','d','u','m','b','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','u','m','b',' ','t','e','r','m','i','n','a','l','.','\n',
|
||||
' ',' ','-','D',' ','[','_','\b','x','_','\b','n','_','\b','.','_','\b','n',']',' ',' ','.',' ',' ','-','-','c','o','l','o','r','=','_','\b','x','_','\b','n','_','\b','.','_','\b','n','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','t',' ','s','c','r','e','e','n',' ','c','o','l','o','r','s','.',' ','(','M','S','-','D','O','S',' ','o','n','l','y',')','\n',
|
||||
' ',' ','-','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',
|
||||
' ',' ','-','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',' ',' ','-','N',' ',' ','.','.','.','.',' ',' ','-','-','l','i','n','e','-','n','u','m','b','e','r','s',' ',' ','-','-','L','I','N','E','-','N','U','M','B','E','R','S','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','U','s','e',' ','l','i','n','e',' ','n','u','m','b','e','r','s','.','\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',' ','l','o','n','g',' ','l','i','n','e','s','.','\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','.','\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',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','n','o','-','k','e','y','p','a','d','\n',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','o','n','\'','t',' ','u','s','e',' ','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',
|
||||
' ',' ','-','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',
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','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',
|
||||
'\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','N','T','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','N','T','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','N','T','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','N','T','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','N','T','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','N','T','L','-','L',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','C','o','m','p','l','e','t','e',' ','f','i','l','e','n','a','m','e',',',' ','l','i','s','t',' ','a','l','l','.','\n',
|
||||
'\n',
|
||||
0 };
|
||||
#endif
|
||||
constant int size_helpdata = sizeof(helpdata) - 1;
|
||||
354
commands/less/less/ifile.c
Normal file
354
commands/less/less/ifile.c
Normal file
@@ -0,0 +1,354 @@
|
||||
/* $NetBSD: ifile.c,v 1.6 2006/10/26 01:33:08 mrg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1984-2004 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 about less, or for information on how to
|
||||
* contact the author, 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 */
|
||||
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 */
|
||||
};
|
||||
|
||||
/*
|
||||
* 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, 0, 0, '\0',
|
||||
{ NULL_POSITION, 0 } };
|
||||
static int ifiles = 0;
|
||||
|
||||
static void incr_index __P((struct ifile *, int));
|
||||
static void link_ifile __P((struct ifile *, struct ifile *));
|
||||
static void unlink_ifile __P((struct ifile *));
|
||||
static struct ifile *new_ifile __P((char *, struct ifile *));
|
||||
static struct ifile *find_ifile __P((char *));
|
||||
|
||||
static void
|
||||
incr_index(p, incr)
|
||||
register 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(p, prev)
|
||||
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(p)
|
||||
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(filename, prev)
|
||||
char *filename;
|
||||
struct ifile *prev;
|
||||
{
|
||||
register struct ifile *p;
|
||||
|
||||
/*
|
||||
* Allocate and initialize structure.
|
||||
*/
|
||||
p = (struct ifile *) ecalloc(1, sizeof(struct ifile));
|
||||
p->h_filename = save(filename);
|
||||
p->h_scrpos.pos = NULL_POSITION;
|
||||
p->h_opened = 0;
|
||||
p->h_hold = 0;
|
||||
p->h_filestate = NULL;
|
||||
link_ifile(p, prev);
|
||||
return (p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete an existing ifile structure.
|
||||
*/
|
||||
public void
|
||||
del_ifile(h)
|
||||
IFILE h;
|
||||
{
|
||||
register 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_filename);
|
||||
free(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the ifile after a given one in the list.
|
||||
*/
|
||||
public IFILE
|
||||
next_ifile(h)
|
||||
IFILE h;
|
||||
{
|
||||
register 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(h)
|
||||
IFILE h;
|
||||
{
|
||||
register 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;
|
||||
{
|
||||
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()
|
||||
{
|
||||
return (ifiles);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find an ifile structure, given a filename.
|
||||
*/
|
||||
static struct ifile *
|
||||
find_ifile(filename)
|
||||
char *filename;
|
||||
{
|
||||
register struct ifile *p;
|
||||
|
||||
for (p = anchor.h_next; p != &anchor; p = p->h_next)
|
||||
if (strcmp(filename, p->h_filename) == 0)
|
||||
return (p);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(filename, prev)
|
||||
char *filename;
|
||||
IFILE prev;
|
||||
{
|
||||
register struct ifile *p;
|
||||
|
||||
if ((p = find_ifile(filename)) == NULL)
|
||||
p = new_ifile(filename, int_ifile(prev));
|
||||
return (ext_ifile(p));
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the filename associated with a ifile.
|
||||
*/
|
||||
public char *
|
||||
get_filename(ifile)
|
||||
IFILE ifile;
|
||||
{
|
||||
if (ifile == NULL)
|
||||
return (NULL);
|
||||
return (int_ifile(ifile)->h_filename);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the index of the file associated with a ifile.
|
||||
*/
|
||||
public int
|
||||
get_index(ifile)
|
||||
IFILE ifile;
|
||||
{
|
||||
return (int_ifile(ifile)->h_index);
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the file position to be associated with a given file.
|
||||
*/
|
||||
public void
|
||||
store_pos(ifile, scrpos)
|
||||
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, scrpos)
|
||||
IFILE ifile;
|
||||
struct scrpos *scrpos;
|
||||
{
|
||||
*scrpos = int_ifile(ifile)->h_scrpos;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark the ifile as "opened".
|
||||
*/
|
||||
public void
|
||||
set_open(ifile)
|
||||
IFILE ifile;
|
||||
{
|
||||
int_ifile(ifile)->h_opened = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return whether the ifile has been opened previously.
|
||||
*/
|
||||
public int
|
||||
opened(ifile)
|
||||
IFILE ifile;
|
||||
{
|
||||
return (int_ifile(ifile)->h_opened);
|
||||
}
|
||||
|
||||
public void
|
||||
hold_ifile(ifile, incr)
|
||||
IFILE ifile;
|
||||
int incr;
|
||||
{
|
||||
int_ifile(ifile)->h_hold += incr;
|
||||
}
|
||||
|
||||
public int
|
||||
held_ifile(ifile)
|
||||
IFILE ifile;
|
||||
{
|
||||
return (int_ifile(ifile)->h_hold);
|
||||
}
|
||||
|
||||
public void *
|
||||
get_filestate(ifile)
|
||||
IFILE ifile;
|
||||
{
|
||||
return (int_ifile(ifile)->h_filestate);
|
||||
}
|
||||
|
||||
public void
|
||||
set_filestate(ifile, filestate)
|
||||
IFILE ifile;
|
||||
void *filestate;
|
||||
{
|
||||
int_ifile(ifile)->h_filestate = filestate;
|
||||
}
|
||||
|
||||
#if 0
|
||||
public void
|
||||
if_dump()
|
||||
{
|
||||
register 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
|
||||
406
commands/less/less/input.c
Normal file
406
commands/less/less/input.c
Normal file
@@ -0,0 +1,406 @@
|
||||
/*
|
||||
* Copyright (C) 1984-2005 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 about less, or for information on how to
|
||||
* contact the author, 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 chopline;
|
||||
extern int hshift;
|
||||
extern int quit_if_one_screen;
|
||||
extern int sigs;
|
||||
extern int ignore_eoi;
|
||||
extern int status_col;
|
||||
extern POSITION start_attnpos;
|
||||
extern POSITION end_attnpos;
|
||||
#if HILITE_SEARCH
|
||||
extern int hilite_search;
|
||||
extern int size_linebuf;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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(curr_pos)
|
||||
POSITION curr_pos;
|
||||
{
|
||||
POSITION base_pos;
|
||||
POSITION new_pos;
|
||||
register int c;
|
||||
int blankline;
|
||||
int endline;
|
||||
int backchars;
|
||||
|
||||
if (curr_pos == NULL_POSITION)
|
||||
{
|
||||
null_line();
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
#if HILITE_SEARCH
|
||||
if (hilite_search == OPT_ONPLUS || 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);
|
||||
#endif
|
||||
if (ch_seek(curr_pos))
|
||||
{
|
||||
null_line();
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
prewind();
|
||||
plinenum(base_pos);
|
||||
(void) ch_seek(base_pos);
|
||||
while (base_pos < curr_pos)
|
||||
{
|
||||
if (ABORT_SIGS())
|
||||
{
|
||||
null_line();
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
c = ch_forw_get();
|
||||
backchars = pappend(c, base_pos);
|
||||
base_pos++;
|
||||
if (backchars > 0)
|
||||
{
|
||||
pshift_all();
|
||||
base_pos -= backchars;
|
||||
while (--backchars >= 0)
|
||||
(void) ch_back_get();
|
||||
}
|
||||
}
|
||||
(void) pflushmbc();
|
||||
pshift_all();
|
||||
|
||||
c = ch_forw_get();
|
||||
if (c == EOI)
|
||||
{
|
||||
null_line();
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
blankline = (c == '\n' || c == '\r');
|
||||
|
||||
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 && !chopline && hshift == 0)
|
||||
{
|
||||
new_pos -= backchars + 1;
|
||||
endline = FALSE;
|
||||
} else
|
||||
endline = TRUE;
|
||||
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 (chopline || hshift > 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
c = ch_forw_get();
|
||||
} while (c != '\n' && c != EOI);
|
||||
new_pos = ch_tell();
|
||||
endline = TRUE;
|
||||
quit_if_one_screen = FALSE;
|
||||
} else
|
||||
{
|
||||
new_pos = ch_tell() - backchars;
|
||||
endline = FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
c = ch_forw_get();
|
||||
}
|
||||
pdone(endline);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(curr_pos)
|
||||
POSITION curr_pos;
|
||||
{
|
||||
POSITION new_pos, begin_new_pos;
|
||||
int c;
|
||||
int endline;
|
||||
int backchars;
|
||||
|
||||
if (curr_pos == NULL_POSITION || curr_pos <= ch_zero())
|
||||
{
|
||||
null_line();
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
#if HILITE_SEARCH
|
||||
if (hilite_search == OPT_ONPLUS || 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.
|
||||
*/
|
||||
new_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.
|
||||
*/
|
||||
new_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. }}
|
||||
*/
|
||||
if (ch_seek(new_pos))
|
||||
{
|
||||
null_line();
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
endline = FALSE;
|
||||
prewind();
|
||||
plinenum(new_pos);
|
||||
loop:
|
||||
begin_new_pos = new_pos;
|
||||
(void) ch_seek(new_pos);
|
||||
|
||||
do
|
||||
{
|
||||
c = ch_forw_get();
|
||||
if (c == EOI || ABORT_SIGS())
|
||||
{
|
||||
null_line();
|
||||
return (NULL_POSITION);
|
||||
}
|
||||
new_pos++;
|
||||
if (c == '\n')
|
||||
{
|
||||
backchars = pflushmbc();
|
||||
if (backchars > 0 && !chopline && hshift == 0)
|
||||
{
|
||||
backchars++;
|
||||
goto shift;
|
||||
}
|
||||
endline = TRUE;
|
||||
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 (chopline || hshift > 0)
|
||||
{
|
||||
endline = TRUE;
|
||||
quit_if_one_screen = FALSE;
|
||||
break;
|
||||
}
|
||||
shift:
|
||||
pshift_all();
|
||||
while (backchars-- > 0)
|
||||
{
|
||||
(void) ch_back_get();
|
||||
new_pos--;
|
||||
}
|
||||
goto loop;
|
||||
}
|
||||
} while (new_pos < curr_pos);
|
||||
|
||||
pdone(endline);
|
||||
|
||||
return (begin_new_pos);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set attnpos.
|
||||
*/
|
||||
public void
|
||||
set_attnpos(pos)
|
||||
POSITION pos;
|
||||
{
|
||||
int c;
|
||||
|
||||
if (pos != NULL_POSITION)
|
||||
{
|
||||
if (ch_seek(pos))
|
||||
return;
|
||||
for (;;)
|
||||
{
|
||||
c = ch_forw_get();
|
||||
if (c == EOI)
|
||||
return;
|
||||
if (c != '\n' && c != '\r')
|
||||
break;
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
start_attnpos = pos;
|
||||
for (;;)
|
||||
{
|
||||
c = ch_forw_get();
|
||||
pos++;
|
||||
if (c == EOI || c == '\n' || c == '\r')
|
||||
break;
|
||||
}
|
||||
end_attnpos = pos;
|
||||
}
|
||||
291
commands/less/less/jump.c
Normal file
291
commands/less/less/jump.c
Normal file
@@ -0,0 +1,291 @@
|
||||
/*
|
||||
* Copyright (C) 1984-2005 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 about less, or for information on how to
|
||||
* contact the author, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Routines which jump to a new location in the file.
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
#include "position.h"
|
||||
|
||||
extern int hit_eof;
|
||||
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()
|
||||
{
|
||||
POSITION pos;
|
||||
|
||||
if (ch_end_seek())
|
||||
{
|
||||
error("Cannot seek to end of file", NULL_PARG);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* 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 = back_line(ch_tell());
|
||||
if (pos == NULL_POSITION)
|
||||
jump_loc((POSITION)0, sc_height-1);
|
||||
else
|
||||
jump_loc(pos, sc_height-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Jump to line n in the file.
|
||||
*/
|
||||
public void
|
||||
jump_back(linenum)
|
||||
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()
|
||||
{
|
||||
struct scrpos scrpos;
|
||||
/*
|
||||
* Start at the line currently at the top of the screen
|
||||
* and redisplay the screen.
|
||||
*/
|
||||
get_scrpos(&scrpos);
|
||||
pos_clear();
|
||||
jump_loc(scrpos.pos, scrpos.ln);
|
||||
}
|
||||
|
||||
/*
|
||||
* Jump to a specified percentage into the file.
|
||||
*/
|
||||
public void
|
||||
jump_percent(percent)
|
||||
int percent;
|
||||
{
|
||||
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);
|
||||
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(pos, sline)
|
||||
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(pos, sline)
|
||||
POSITION pos;
|
||||
int sline;
|
||||
{
|
||||
register int nline;
|
||||
POSITION tpos;
|
||||
POSITION bpos;
|
||||
|
||||
/*
|
||||
* Normalize sline.
|
||||
*/
|
||||
sline = adjsline(sline);
|
||||
|
||||
if ((nline = onscreen(pos)) >= 0)
|
||||
{
|
||||
/*
|
||||
* The line is currently displayed.
|
||||
* Just scroll there.
|
||||
*/
|
||||
nline -= sline;
|
||||
if (nline > 0)
|
||||
forw(nline, position(BOTTOM_PLUS_ONE), 1, 0, 0);
|
||||
else
|
||||
back(-nline, position(TOP), 1, 0);
|
||||
if (show_attn)
|
||||
repaint_hilite(1);
|
||||
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 < sline; 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-sline+nline-1, bpos, 1, 0, 0);
|
||||
if (show_attn)
|
||||
repaint_hilite(1);
|
||||
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();
|
||||
hit_eof = 0;
|
||||
squished = 0;
|
||||
screen_trashed = 0;
|
||||
forw(sc_height-1, pos, 1, 0, sline-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
|
||||
* sline-th line on the screen.
|
||||
*/
|
||||
for (nline = sline; 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 (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 (show_attn)
|
||||
repaint_hilite(1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
lastmark();
|
||||
if (top_scroll != OPT_ON)
|
||||
clear();
|
||||
else
|
||||
home();
|
||||
screen_trashed = 0;
|
||||
add_back_pos(pos);
|
||||
back(sc_height-1, pos, 1, 0);
|
||||
}
|
||||
}
|
||||
1663
commands/less/less/less.1
Normal file
1663
commands/less/less/less.1
Normal file
File diff suppressed because it is too large
Load Diff
469
commands/less/less/less.h
Normal file
469
commands/less/less/less.h
Normal file
@@ -0,0 +1,469 @@
|
||||
/* $NetBSD: less.h,v 1.9 2008/02/16 07:20:54 matt Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1984-2005 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 about less, or for information on how to
|
||||
* contact the author, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* 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_VOID
|
||||
#define VOID_POINTER void *
|
||||
#else
|
||||
#define VOID_POINTER char *
|
||||
#define void int
|
||||
#endif
|
||||
#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_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#if HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#if HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#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_POINTER 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_UPPER_LOWER
|
||||
#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)
|
||||
#else
|
||||
#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))
|
||||
#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
|
||||
|
||||
#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 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 /* Min printing width of a line number */
|
||||
#define MAX_UTF_CHAR_LEN 6 /* Max bytes in one UTF-8 char */
|
||||
|
||||
#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
|
||||
|
||||
/*
|
||||
* 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_POINTER
|
||||
#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
|
||||
{
|
||||
constant char *p_string;
|
||||
int p_int;
|
||||
LINENUM p_linenum;
|
||||
} PARG;
|
||||
|
||||
#define NULL_PARG ((PARG *)NULL)
|
||||
|
||||
struct textlist
|
||||
{
|
||||
char *string;
|
||||
char *endstring;
|
||||
};
|
||||
|
||||
#define EOI (-1)
|
||||
|
||||
#define READ_INTR (-2)
|
||||
|
||||
/* 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_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_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) */
|
||||
|
||||
#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('[')
|
||||
|
||||
#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))
|
||||
|
||||
#define QUIT_OK 0
|
||||
#define QUIT_ERROR 1
|
||||
#define QUIT_SAVED_STATUS (-1)
|
||||
|
||||
/* filestate flags */
|
||||
#define CH_CANSEEK 001
|
||||
#define CH_KEEPOPEN 002
|
||||
#define CH_POPENED 004
|
||||
#define CH_HELPFILE 010
|
||||
|
||||
#define ch_zero() ((POSITION)0)
|
||||
|
||||
#define FAKE_HELPFILE "@/\\less/\\help/\\file/\\@"
|
||||
|
||||
#include "funcs.h"
|
||||
|
||||
/* Functions not included in funcs.h */
|
||||
void postoa();
|
||||
void linenumtoa();
|
||||
void inttoa();
|
||||
40
commands/less/less/lesskey.h
Normal file
40
commands/less/less/lesskey.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 1984-2004 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 about less, or for information on how to
|
||||
* contact the author, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* 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
|
||||
95
commands/less/less/lglob.h
Normal file
95
commands/less/less/lglob.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (C) 1984-2004 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 about less, or for information on how to
|
||||
* contact the author, 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; size_t 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)
|
||||
|
||||
#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]; \
|
||||
long 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
|
||||
1207
commands/less/less/line.c
Normal file
1207
commands/less/less/line.c
Normal file
File diff suppressed because it is too large
Load Diff
458
commands/less/less/linenum.c
Normal file
458
commands/less/less/linenum.c
Normal file
@@ -0,0 +1,458 @@
|
||||
/* $NetBSD: linenum.c,v 1.8 2006/10/26 01:33:08 mrg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1984-2004 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 about less, or for information on how to
|
||||
* contact the author, 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 50 /* Size of line number pool */
|
||||
|
||||
#define LONGTIME (2) /* In seconds */
|
||||
|
||||
public int lnloop = 0; /* Are we in the line num loop? */
|
||||
|
||||
static struct linenum_info anchor; /* Anchor of the list */
|
||||
static struct linenum_info *freelist; /* Anchor of the unused entries */
|
||||
static struct linenum_info pool[NPOOL]; /* The pool itself */
|
||||
static struct linenum_info *spare; /* We always keep one spare entry */
|
||||
|
||||
extern int linenums;
|
||||
extern int sigs;
|
||||
extern int sc_height;
|
||||
|
||||
static void calcgap __P((struct linenum_info *));
|
||||
static void longloopmessage __P((void));
|
||||
static void longish __P((void));
|
||||
|
||||
/*
|
||||
* Initialize the line number structures.
|
||||
*/
|
||||
public void
|
||||
clr_linenum()
|
||||
{
|
||||
register 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(p)
|
||||
register 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, pos)
|
||||
LINENUM linenum;
|
||||
POSITION pos;
|
||||
{
|
||||
register struct linenum_info *p;
|
||||
register struct linenum_info *new;
|
||||
register struct linenum_info *nextp;
|
||||
register struct linenum_info *prevp;
|
||||
register 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()
|
||||
{
|
||||
ierror("Calculating line numbers", NULL_PARG);
|
||||
/*
|
||||
* Set the lnloop flag here, so if the user interrupts while
|
||||
* we are calculating line numbers, the signal handler will
|
||||
* turn off line numbers (linenums=0).
|
||||
*/
|
||||
lnloop = 1;
|
||||
}
|
||||
|
||||
static int loopcount;
|
||||
#if HAVE_TIME
|
||||
static long startime;
|
||||
#endif
|
||||
|
||||
static void
|
||||
longish()
|
||||
{
|
||||
#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
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the line number associated with a given position.
|
||||
* Return 0 if we can't figure it out.
|
||||
*/
|
||||
public LINENUM
|
||||
find_linenum(pos)
|
||||
POSITION pos;
|
||||
{
|
||||
register struct linenum_info *p;
|
||||
register 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
|
||||
if (p == &anchor || pos - p->prev->pos < p->pos - pos)
|
||||
{
|
||||
/*
|
||||
* Go forward.
|
||||
*/
|
||||
p = p->prev;
|
||||
if (ch_seek(p->pos))
|
||||
return (0);
|
||||
loopcount = 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);
|
||||
if (ABORT_SIGS() || cpos == NULL_POSITION)
|
||||
return (0);
|
||||
longish();
|
||||
}
|
||||
lnloop = 0;
|
||||
/*
|
||||
* 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);
|
||||
loopcount = 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);
|
||||
if (ABORT_SIGS() || cpos == NULL_POSITION)
|
||||
return (0);
|
||||
longish();
|
||||
}
|
||||
lnloop = 0;
|
||||
/*
|
||||
* We might as well cache it.
|
||||
*/
|
||||
add_lnum(linenum, cpos);
|
||||
}
|
||||
|
||||
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 linenum;
|
||||
{
|
||||
register 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);
|
||||
if (ABORT_SIGS() || 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);
|
||||
if (ABORT_SIGS() || 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(where)
|
||||
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);
|
||||
}
|
||||
370
commands/less/less/lsystem.c
Normal file
370
commands/less/less/lsystem.c
Normal file
@@ -0,0 +1,370 @@
|
||||
/* $NetBSD: lsystem.c,v 1.8 2006/10/26 01:33:08 mrg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1984-2005 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 about less, or for information on how to
|
||||
* contact the author, 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>
|
||||
#ifdef _MSC_VER
|
||||
#include <direct.h>
|
||||
#define setdisk(n) _chdrive((n)+1)
|
||||
#else
|
||||
#include <dir.h>
|
||||
#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(cmd, donemsg)
|
||||
char *cmd;
|
||||
char *donemsg;
|
||||
{
|
||||
register int inp;
|
||||
#if HAVE_SHELL
|
||||
register char *shell;
|
||||
register char *p;
|
||||
#endif
|
||||
IFILE save_ifile;
|
||||
#if MSDOS_COMPILER
|
||||
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
|
||||
/*
|
||||
* 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
|
||||
|
||||
/*
|
||||
* 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 OS2
|
||||
/* The __open() system call translates "/dev/tty" to "con". */
|
||||
if (__open("/dev/tty", OPEN_READ) < 0)
|
||||
#else
|
||||
if (open("/dev/tty", OPEN_READ) < 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 = 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
|
||||
/*
|
||||
* 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(c, cmd)
|
||||
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(cmd, spos, epos)
|
||||
char *cmd;
|
||||
POSITION spos;
|
||||
POSITION epos;
|
||||
{
|
||||
register FILE *f;
|
||||
register 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
|
||||
407
commands/less/less/main.c
Normal file
407
commands/less/less/main.c
Normal file
@@ -0,0 +1,407 @@
|
||||
/* $NetBSD: main.c,v 1.14 2008/08/28 07:20:20 mrg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1984-2004 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 about less, or for information on how to
|
||||
* contact the author, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Entry point, initialization, miscellaneous routines.
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
#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 int any_display = FALSE;
|
||||
public POSITION start_attnpos = NULL_POSITION;
|
||||
public POSITION end_attnpos = NULL_POSITION;
|
||||
public int wscroll;
|
||||
public char * progname;
|
||||
public int quitting;
|
||||
public int secure;
|
||||
public int dohelp;
|
||||
public int more_mode = 0;
|
||||
|
||||
#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
|
||||
|
||||
extern int missing_cap;
|
||||
extern int know_dumb;
|
||||
|
||||
|
||||
/*
|
||||
* Entry point.
|
||||
*/
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
IFILE ifile;
|
||||
char *s;
|
||||
|
||||
#ifdef __EMX__
|
||||
_response(&argc, &argv);
|
||||
_wildcard(&argc, &argv);
|
||||
#endif
|
||||
|
||||
progname = *argv++;
|
||||
argc--;
|
||||
|
||||
secure = 0;
|
||||
s = lgetenv("LESSSECURE");
|
||||
if (s != NULL && *s != '\0')
|
||||
secure = 1;
|
||||
|
||||
#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.
|
||||
*/
|
||||
if (strcmp(getprogname(), "more") == 0)
|
||||
more_mode = 1;
|
||||
|
||||
is_tty = isatty(1);
|
||||
get_term();
|
||||
init_cmds();
|
||||
init_prompt();
|
||||
init_charset();
|
||||
init_line();
|
||||
init_cmdhist();
|
||||
init_option();
|
||||
|
||||
if (more_mode) {
|
||||
scan_option("-E");
|
||||
scan_option("-m");
|
||||
scan_option("-G");
|
||||
scan_option("-f");
|
||||
s = lgetenv("MORE");
|
||||
} else
|
||||
s = lgetenv("LESS");
|
||||
if (s != NULL)
|
||||
scan_option(save(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);
|
||||
}
|
||||
|
||||
#if EDITOR
|
||||
editor = lgetenv("VISUAL");
|
||||
if (editor == NULL || *editor == '\0')
|
||||
{
|
||||
editor = lgetenv("EDITOR");
|
||||
if (editor == NULL || *editor == '\0')
|
||||
editor = EDIT_PGM;
|
||||
}
|
||||
editproto = lgetenv("LESSEDIT");
|
||||
if (editproto == NULL || *editproto == '\0')
|
||||
editproto = "%E ?lm+%lm. %f";
|
||||
#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)
|
||||
{
|
||||
char *filename;
|
||||
#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 *gfilename;
|
||||
|
||||
gfilename = lglob(*argv++);
|
||||
init_textlist(&tlist, gfilename);
|
||||
filename = NULL;
|
||||
while ((filename = forw_textlist(&tlist, filename)) != NULL)
|
||||
{
|
||||
(void) get_ifile(filename, ifile);
|
||||
ifile = prev_ifile(NULL_IFILE);
|
||||
}
|
||||
free(gfilename);
|
||||
#else
|
||||
filename = shell_quote(*argv);
|
||||
if (filename == NULL)
|
||||
filename = *argv;
|
||||
argv++;
|
||||
(void) get_ifile(filename, 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_BINARY(1);
|
||||
if (nifile() == 0)
|
||||
{
|
||||
if (edit_stdin() == 0)
|
||||
cat_file();
|
||||
} else if (edit_first() == 0)
|
||||
{
|
||||
do {
|
||||
cat_file();
|
||||
} while (edit_next(1) == 0);
|
||||
}
|
||||
quit(QUIT_OK);
|
||||
}
|
||||
|
||||
if (missing_cap && !know_dumb && !more_mode)
|
||||
error("WARNING: terminal is not fully functional", NULL_PARG);
|
||||
init_mark();
|
||||
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 (nifile() == 0)
|
||||
{
|
||||
if (edit_stdin()) /* Edit standard input */
|
||||
quit(QUIT_ERROR);
|
||||
} else
|
||||
{
|
||||
if (edit_first()) /* Edit first valid file in cmd line */
|
||||
quit(QUIT_ERROR);
|
||||
}
|
||||
|
||||
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(s)
|
||||
char *s;
|
||||
{
|
||||
register char *p;
|
||||
|
||||
p = (char *) ecalloc(strlen(s)+1, sizeof(char));
|
||||
strcpy(p, s);
|
||||
return (p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate memory.
|
||||
* Like calloc(), but never returns an error (NULL).
|
||||
*/
|
||||
public VOID_POINTER
|
||||
ecalloc(count, size)
|
||||
int count;
|
||||
unsigned int size;
|
||||
{
|
||||
register VOID_POINTER p;
|
||||
|
||||
p = (VOID_POINTER) calloc(count, size);
|
||||
if (p != NULL)
|
||||
return (p);
|
||||
error("Cannot allocate memory", NULL_PARG);
|
||||
quit(QUIT_ERROR);
|
||||
/*NOTREACHED*/
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip leading spaces in a string.
|
||||
*/
|
||||
public char *
|
||||
skipsp(s)
|
||||
register 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(ps, s, uppercase)
|
||||
char *ps;
|
||||
char *s;
|
||||
int uppercase;
|
||||
{
|
||||
register int c;
|
||||
register int sc;
|
||||
register 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(status)
|
||||
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;
|
||||
edit((char*)NULL);
|
||||
save_cmdhist();
|
||||
if (any_display && is_tty)
|
||||
clear_bot();
|
||||
deinit();
|
||||
flush();
|
||||
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
|
||||
#if WIN32
|
||||
SetConsoleTitle(consoleTitle);
|
||||
#endif
|
||||
close_getchr();
|
||||
exit(status);
|
||||
}
|
||||
260
commands/less/less/mark.c
Normal file
260
commands/less/less/mark.c
Normal file
@@ -0,0 +1,260 @@
|
||||
/* $NetBSD: mark.c,v 1.6 2006/10/26 01:33:08 mrg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1984-2004 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 about less, or for information on how to
|
||||
* contact the author, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
#include "less.h"
|
||||
|
||||
extern IFILE curr_ifile;
|
||||
extern int sc_height;
|
||||
extern int jump_sline;
|
||||
|
||||
/*
|
||||
* A mark is an ifile (input file) plus a position within the file.
|
||||
*/
|
||||
struct mark {
|
||||
IFILE m_ifile;
|
||||
struct scrpos m_scrpos;
|
||||
};
|
||||
|
||||
/*
|
||||
* 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)+1) /* a-z, A-Z, lastmark */
|
||||
#define LASTMARK (NMARKS-1)
|
||||
static struct mark marks[NMARKS];
|
||||
|
||||
/*
|
||||
* Initialize the mark table to show no marks are set.
|
||||
*/
|
||||
public void
|
||||
init_mark()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NMARKS; i++)
|
||||
marks[i].m_scrpos.pos = NULL_POSITION;
|
||||
}
|
||||
|
||||
/*
|
||||
* See if a mark letter is valid (between a and z).
|
||||
*/
|
||||
static struct mark *
|
||||
getumark(c)
|
||||
int c;
|
||||
{
|
||||
if (c >= 'a' && c <= 'z')
|
||||
return (&marks[c-'a']);
|
||||
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
return (&marks[c-'A'+26]);
|
||||
|
||||
error("Invalid mark letter", NULL_PARG);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the mark structure identified by a character.
|
||||
* The mark struct may come either from the mark table
|
||||
* or may be constructed on the fly for certain characters like ^, $.
|
||||
*/
|
||||
static struct mark *
|
||||
getmark(c)
|
||||
int c;
|
||||
{
|
||||
register struct mark *m;
|
||||
static struct mark sm;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '^':
|
||||
/*
|
||||
* Beginning of the current file.
|
||||
*/
|
||||
m = &sm;
|
||||
m->m_scrpos.pos = ch_zero();
|
||||
m->m_scrpos.ln = 0;
|
||||
m->m_ifile = curr_ifile;
|
||||
break;
|
||||
case '$':
|
||||
/*
|
||||
* End of the current file.
|
||||
*/
|
||||
if (ch_end_seek())
|
||||
{
|
||||
error("Cannot seek to end of file", NULL_PARG);
|
||||
return (NULL);
|
||||
}
|
||||
m = &sm;
|
||||
m->m_scrpos.pos = ch_tell();
|
||||
m->m_scrpos.ln = sc_height-1;
|
||||
m->m_ifile = curr_ifile;
|
||||
break;
|
||||
case '.':
|
||||
/*
|
||||
* Current position in the current file.
|
||||
*/
|
||||
m = &sm;
|
||||
get_scrpos(&m->m_scrpos);
|
||||
m->m_ifile = curr_ifile;
|
||||
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 is invalid?
|
||||
*/
|
||||
public int
|
||||
badmark(c)
|
||||
int c;
|
||||
{
|
||||
return (getmark(c) == NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a user-defined mark.
|
||||
*/
|
||||
public void
|
||||
setmark(c)
|
||||
int c;
|
||||
{
|
||||
register struct mark *m;
|
||||
struct scrpos scrpos;
|
||||
|
||||
m = getumark(c);
|
||||
if (m == NULL)
|
||||
return;
|
||||
get_scrpos(&scrpos);
|
||||
m->m_scrpos = scrpos;
|
||||
m->m_ifile = curr_ifile;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set lmark (the mark named by the apostrophe).
|
||||
*/
|
||||
public void
|
||||
lastmark()
|
||||
{
|
||||
struct scrpos scrpos;
|
||||
|
||||
if (ch_getflags() & CH_HELPFILE)
|
||||
return;
|
||||
get_scrpos(&scrpos);
|
||||
if (scrpos.pos == NULL_POSITION)
|
||||
return;
|
||||
marks[LASTMARK].m_scrpos = scrpos;
|
||||
marks[LASTMARK].m_ifile = curr_ifile;
|
||||
}
|
||||
|
||||
/*
|
||||
* Go to a mark.
|
||||
*/
|
||||
public void
|
||||
gomark(c)
|
||||
int c;
|
||||
{
|
||||
register 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.
|
||||
*/
|
||||
if (m == &marks[LASTMARK] && m->m_scrpos.pos == NULL_POSITION)
|
||||
{
|
||||
m->m_ifile = curr_ifile;
|
||||
m->m_scrpos.pos = ch_zero();
|
||||
m->m_scrpos.ln = jump_sline;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're using lmark, we must save the screen position now,
|
||||
* because if we call edit_ifile() below, lmark will change.
|
||||
* (We save the screen position even if we're not using lmark.)
|
||||
*/
|
||||
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(c)
|
||||
int c;
|
||||
{
|
||||
register 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);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear the marks associated with a specified ifile.
|
||||
*/
|
||||
public void
|
||||
unmark(ifile)
|
||||
IFILE ifile;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NMARKS; i++)
|
||||
if (marks[i].m_ifile == ifile)
|
||||
marks[i].m_scrpos.pos = NULL_POSITION;
|
||||
}
|
||||
602
commands/less/less/optfunc.c
Normal file
602
commands/less/less/optfunc.c
Normal file
@@ -0,0 +1,602 @@
|
||||
/*
|
||||
* Copyright (C) 1984-2005 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 about less, or for information on how to
|
||||
* contact the author, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Handling functions for command line options.
|
||||
*
|
||||
* Most options are handled by the generic code in option.c.
|
||||
* But all string options, and a few non-string options, require
|
||||
* special handling specific to the particular option.
|
||||
* This special processing is done by the "handling functions" in this file.
|
||||
*
|
||||
* Each handling function is passed a "type" and, if it is a string
|
||||
* option, the string which should be "assigned" to the option.
|
||||
* The type may be one of:
|
||||
* INIT The option is being initialized from the command line.
|
||||
* TOGGLE The option is being changed from within the program.
|
||||
* QUERY The setting of the option is merely being queried.
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
#include "option.h"
|
||||
|
||||
extern int nbufs;
|
||||
extern int bufspace;
|
||||
extern int pr_type;
|
||||
extern int plusoption;
|
||||
extern int swindow;
|
||||
extern int sc_height;
|
||||
extern int secure;
|
||||
extern int dohelp;
|
||||
extern int any_display;
|
||||
extern int less_is_more;
|
||||
extern char openquote;
|
||||
extern char closequote;
|
||||
extern char constant *prproto[];
|
||||
extern char constant *eqproto;
|
||||
extern char constant *hproto;
|
||||
extern char constant *wproto;
|
||||
extern IFILE curr_ifile;
|
||||
extern char version[];
|
||||
#if LOGFILE
|
||||
extern char *namelogfile;
|
||||
extern int force_logfile;
|
||||
extern int logfile;
|
||||
#endif
|
||||
#if TAGS
|
||||
public char *tagoption = NULL;
|
||||
extern char *tags;
|
||||
extern int jump_sline;
|
||||
#endif
|
||||
#if MSDOS_COMPILER
|
||||
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;
|
||||
#endif
|
||||
|
||||
|
||||
#if LOGFILE
|
||||
/*
|
||||
* Handler for -o option.
|
||||
*/
|
||||
public void
|
||||
opt_o(type, s)
|
||||
int type;
|
||||
char *s;
|
||||
{
|
||||
PARG parg;
|
||||
|
||||
if (secure)
|
||||
{
|
||||
error("log file support is not available", NULL_PARG);
|
||||
return;
|
||||
}
|
||||
switch (type)
|
||||
{
|
||||
case INIT:
|
||||
namelogfile = s;
|
||||
break;
|
||||
case TOGGLE:
|
||||
if (ch_getflags() & CH_CANSEEK)
|
||||
{
|
||||
error("Input is not a pipe", NULL_PARG);
|
||||
return;
|
||||
}
|
||||
if (logfile >= 0)
|
||||
{
|
||||
error("Log file is already in use", NULL_PARG);
|
||||
return;
|
||||
}
|
||||
s = skipsp(s);
|
||||
namelogfile = lglob(s);
|
||||
use_logfile(namelogfile);
|
||||
sync_logfile();
|
||||
break;
|
||||
case QUERY:
|
||||
if (logfile < 0)
|
||||
error("No log file", NULL_PARG);
|
||||
else
|
||||
{
|
||||
parg.p_string = namelogfile;
|
||||
error("Log file \"%s\"", &parg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handler for -O option.
|
||||
*/
|
||||
public void
|
||||
opt__O(type, s)
|
||||
int type;
|
||||
char *s;
|
||||
{
|
||||
force_logfile = TRUE;
|
||||
opt_o(type, s);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Handlers for -l option.
|
||||
*/
|
||||
public void
|
||||
opt_l(type, s)
|
||||
int type;
|
||||
char *s;
|
||||
{
|
||||
int err;
|
||||
int n;
|
||||
char *t;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case INIT:
|
||||
t = s;
|
||||
n = getnum(&t, "l", &err);
|
||||
if (err || n <= 0)
|
||||
{
|
||||
error("Line number is required after -l", NULL_PARG);
|
||||
return;
|
||||
}
|
||||
plusoption = TRUE;
|
||||
ungetsc(s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if USERFILE
|
||||
public void
|
||||
opt_k(type, s)
|
||||
int type;
|
||||
char *s;
|
||||
{
|
||||
PARG parg;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case INIT:
|
||||
if (lesskey(s, 0))
|
||||
{
|
||||
parg.p_string = s;
|
||||
error("Cannot use lesskey file \"%s\"", &parg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TAGS
|
||||
/*
|
||||
* Handler for -t option.
|
||||
*/
|
||||
public void
|
||||
opt_t(type, s)
|
||||
int type;
|
||||
char *s;
|
||||
{
|
||||
IFILE save_ifile;
|
||||
POSITION pos;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case INIT:
|
||||
tagoption = s;
|
||||
/* Do the rest in main() */
|
||||
break;
|
||||
case TOGGLE:
|
||||
if (secure)
|
||||
{
|
||||
error("tags support is not available", NULL_PARG);
|
||||
break;
|
||||
}
|
||||
findtag(skipsp(s));
|
||||
save_ifile = save_curr_ifile();
|
||||
/*
|
||||
* Try to open the file containing the tag
|
||||
* and search for the tag in that file.
|
||||
*/
|
||||
if (edit_tagfile() || (pos = tagsearch()) == NULL_POSITION)
|
||||
{
|
||||
/* Failed: reopen the old file. */
|
||||
reedit_ifile(save_ifile);
|
||||
break;
|
||||
}
|
||||
unsave_ifile(save_ifile);
|
||||
jump_loc(pos, jump_sline);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handler for -T option.
|
||||
*/
|
||||
public void
|
||||
opt__T(type, s)
|
||||
int type;
|
||||
char *s;
|
||||
{
|
||||
PARG parg;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case INIT:
|
||||
tags = s;
|
||||
break;
|
||||
case TOGGLE:
|
||||
s = skipsp(s);
|
||||
tags = lglob(s);
|
||||
break;
|
||||
case QUERY:
|
||||
parg.p_string = tags;
|
||||
error("Tags file \"%s\"", &parg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Handler for -p option.
|
||||
*/
|
||||
public void
|
||||
opt_p(type, s)
|
||||
int type;
|
||||
register char *s;
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case INIT:
|
||||
/*
|
||||
* Unget a search command for the specified string.
|
||||
* {{ This won't work if the "/" command is
|
||||
* changed or invalidated by a .lesskey file. }}
|
||||
*/
|
||||
plusoption = TRUE;
|
||||
ungetsc(s);
|
||||
/*
|
||||
* In "more" mode, the -p argument is a command,
|
||||
* not a search string, so we don't need a slash.
|
||||
*/
|
||||
if (!less_is_more);
|
||||
ungetsc("/");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handler for -P option.
|
||||
*/
|
||||
public void
|
||||
opt__P(type, s)
|
||||
int type;
|
||||
register char *s;
|
||||
{
|
||||
register constant char **proto;
|
||||
PARG parg;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case INIT:
|
||||
case TOGGLE:
|
||||
/*
|
||||
* Figure out which prototype string should be changed.
|
||||
*/
|
||||
switch (*s)
|
||||
{
|
||||
case 's': proto = &prproto[PR_SHORT]; s++; break;
|
||||
case 'm': proto = &prproto[PR_MEDIUM]; s++; break;
|
||||
case 'M': proto = &prproto[PR_LONG]; s++; break;
|
||||
case '=': proto = &eqproto; s++; break;
|
||||
case 'h': proto = &hproto; s++; break;
|
||||
case 'w': proto = &wproto; s++; break;
|
||||
default: proto = &prproto[PR_SHORT]; break;
|
||||
}
|
||||
free((void *)*proto);
|
||||
*proto = save(s);
|
||||
break;
|
||||
case QUERY:
|
||||
parg.p_string = prproto[pr_type];
|
||||
error("%s", &parg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handler for the -b option.
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
public void
|
||||
opt_b(type, s)
|
||||
int type;
|
||||
char *s;
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case INIT:
|
||||
case TOGGLE:
|
||||
/*
|
||||
* Set the new number of buffers.
|
||||
*/
|
||||
ch_setbufspace(bufspace);
|
||||
break;
|
||||
case QUERY:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handler for the -i option.
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
public void
|
||||
opt_i(type, s)
|
||||
int type;
|
||||
char *s;
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case TOGGLE:
|
||||
chg_caseless();
|
||||
break;
|
||||
case QUERY:
|
||||
case INIT:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handler for the -V option.
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
public void
|
||||
opt__V(type, s)
|
||||
int type;
|
||||
char *s;
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case TOGGLE:
|
||||
case QUERY:
|
||||
dispversion();
|
||||
break;
|
||||
case INIT:
|
||||
/*
|
||||
* Force output to stdout per GNU standard for --version output.
|
||||
*/
|
||||
any_display = 1;
|
||||
putstr("less ");
|
||||
putstr(version);
|
||||
putstr("\nCopyright (C) 1984-2005 Mark Nudelman\n\n");
|
||||
putstr("less comes with NO WARRANTY, to the extent permitted by law.\n");
|
||||
putstr("For information about the terms of redistribution,\n");
|
||||
putstr("see the file named README in the less distribution.\n");
|
||||
putstr("Homepage: http://www.greenwoodsoftware.com/less\n");
|
||||
quit(QUIT_OK);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if MSDOS_COMPILER
|
||||
/*
|
||||
* Parse an MSDOS color descriptor.
|
||||
*/
|
||||
static void
|
||||
colordesc(s, fg_color, bg_color)
|
||||
char *s;
|
||||
int *fg_color;
|
||||
int *bg_color;
|
||||
{
|
||||
int fg, bg;
|
||||
int err;
|
||||
|
||||
fg = getnum(&s, "D", &err);
|
||||
if (err)
|
||||
{
|
||||
error("Missing fg color in -D", NULL_PARG);
|
||||
return;
|
||||
}
|
||||
if (*s != '.')
|
||||
bg = 0;
|
||||
else
|
||||
{
|
||||
s++;
|
||||
bg = getnum(&s, "D", &err);
|
||||
if (err)
|
||||
{
|
||||
error("Missing fg color in -D", NULL_PARG);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (*s != '\0')
|
||||
error("Extra characters at end of -D option", NULL_PARG);
|
||||
*fg_color = fg;
|
||||
*bg_color = bg;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handler for the -D option.
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
public void
|
||||
opt_D(type, s)
|
||||
int type;
|
||||
char *s;
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case INIT:
|
||||
case TOGGLE:
|
||||
switch (*s++)
|
||||
{
|
||||
case 'n':
|
||||
colordesc(s, &nm_fg_color, &nm_bg_color);
|
||||
break;
|
||||
case 'd':
|
||||
colordesc(s, &bo_fg_color, &bo_bg_color);
|
||||
break;
|
||||
case 'u':
|
||||
colordesc(s, &ul_fg_color, &ul_bg_color);
|
||||
break;
|
||||
case 'k':
|
||||
colordesc(s, &bl_fg_color, &bl_bg_color);
|
||||
break;
|
||||
case 's':
|
||||
colordesc(s, &so_fg_color, &so_bg_color);
|
||||
break;
|
||||
default:
|
||||
error("-D must be followed by n, d, u, k or s", NULL_PARG);
|
||||
break;
|
||||
}
|
||||
if (type == TOGGLE)
|
||||
{
|
||||
at_enter(AT_STANDOUT);
|
||||
at_exit();
|
||||
}
|
||||
break;
|
||||
case QUERY:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Handler for the -x option.
|
||||
*/
|
||||
public void
|
||||
opt_x(type, s)
|
||||
int type;
|
||||
register char *s;
|
||||
{
|
||||
extern int tabstops[];
|
||||
extern int ntabstops;
|
||||
extern int tabdefault;
|
||||
char msg[60+(4*TABSTOP_MAX)];
|
||||
int i;
|
||||
PARG p;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case INIT:
|
||||
case TOGGLE:
|
||||
/* Start at 1 because tabstops[0] is always zero. */
|
||||
for (i = 1; i < TABSTOP_MAX; )
|
||||
{
|
||||
int n = 0;
|
||||
s = skipsp(s);
|
||||
while (*s >= '0' && *s <= '9')
|
||||
n = (10 * n) + (*s++ - '0');
|
||||
if (n > tabstops[i-1])
|
||||
tabstops[i++] = n;
|
||||
s = skipsp(s);
|
||||
if (*s++ != ',')
|
||||
break;
|
||||
}
|
||||
if (i < 2)
|
||||
return;
|
||||
ntabstops = i;
|
||||
tabdefault = tabstops[ntabstops-1] - tabstops[ntabstops-2];
|
||||
break;
|
||||
case QUERY:
|
||||
strcpy(msg, "Tab stops ");
|
||||
if (ntabstops > 2)
|
||||
{
|
||||
for (i = 1; i < ntabstops; i++)
|
||||
{
|
||||
if (i > 1)
|
||||
strcat(msg, ",");
|
||||
sprintf(msg+strlen(msg), "%d", tabstops[i]);
|
||||
}
|
||||
sprintf(msg+strlen(msg), " and then ");
|
||||
}
|
||||
sprintf(msg+strlen(msg), "every %d spaces",
|
||||
tabdefault);
|
||||
p.p_string = msg;
|
||||
error("%s", &p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Handler for the -" option.
|
||||
*/
|
||||
public void
|
||||
opt_quote(type, s)
|
||||
int type;
|
||||
register char *s;
|
||||
{
|
||||
char buf[3];
|
||||
PARG parg;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case INIT:
|
||||
case TOGGLE:
|
||||
if (s[0] == '\0')
|
||||
{
|
||||
openquote = closequote = '\0';
|
||||
break;
|
||||
}
|
||||
if (s[1] != '\0' && s[2] != '\0')
|
||||
{
|
||||
error("-\" must be followed by 1 or 2 chars", NULL_PARG);
|
||||
return;
|
||||
}
|
||||
openquote = s[0];
|
||||
if (s[1] == '\0')
|
||||
closequote = openquote;
|
||||
else
|
||||
closequote = s[1];
|
||||
break;
|
||||
case QUERY:
|
||||
buf[0] = openquote;
|
||||
buf[1] = closequote;
|
||||
buf[2] = '\0';
|
||||
parg.p_string = buf;
|
||||
error("quotes %s", &parg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* "-?" means display a help message.
|
||||
* If from the command line, exit immediately.
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
public void
|
||||
opt_query(type, s)
|
||||
int type;
|
||||
char *s;
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case QUERY:
|
||||
case TOGGLE:
|
||||
error("Use \"h\" for help", NULL_PARG);
|
||||
break;
|
||||
case INIT:
|
||||
dohelp = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the "screen window" size.
|
||||
*/
|
||||
public int
|
||||
get_swindow()
|
||||
{
|
||||
if (swindow > 0)
|
||||
return (swindow);
|
||||
return (sc_height + swindow);
|
||||
}
|
||||
|
||||
638
commands/less/less/option.c
Normal file
638
commands/less/less/option.c
Normal file
@@ -0,0 +1,638 @@
|
||||
/* $NetBSD: option.c,v 1.8 2006/10/26 01:33:08 mrg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1984-2004 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 about less, or for information on how to
|
||||
* contact the author, 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 int flip_triple __P((int, int));
|
||||
static char *propt __P((int));
|
||||
static void nostring __P((char *));
|
||||
static char *optstring __P((char *, char **, char *, char *));
|
||||
|
||||
extern int screen_trashed;
|
||||
extern char *every_first_cmd;
|
||||
|
||||
/*
|
||||
* Scan an argument (either from the command line or from the
|
||||
* LESS environment variable) and process it.
|
||||
*/
|
||||
public void
|
||||
scan_option(s)
|
||||
char *s;
|
||||
{
|
||||
register struct loption *o;
|
||||
register 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 = propt(pendopt->oletter);
|
||||
*(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 (*str == '+')
|
||||
every_first_cmd = save(++str);
|
||||
else
|
||||
ungetsc(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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
quit(QUIT_ERROR);
|
||||
}
|
||||
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);
|
||||
quit(QUIT_ERROR);
|
||||
}
|
||||
|
||||
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]);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(c, s, how_toggle)
|
||||
int c;
|
||||
char *s;
|
||||
int how_toggle;
|
||||
{
|
||||
register struct loption *o;
|
||||
register int num;
|
||||
int no_prompt;
|
||||
int err;
|
||||
PARG parg;
|
||||
|
||||
no_prompt = (how_toggle & OPT_NO_PROMPT);
|
||||
how_toggle &= ~OPT_NO_PROMPT;
|
||||
|
||||
/*
|
||||
* Look up the option letter in the option table.
|
||||
*/
|
||||
o = findopt(c);
|
||||
if (o == NULL)
|
||||
{
|
||||
parg.p_string = propt(c);
|
||||
error("There is no %s option", &parg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (how_toggle == OPT_TOGGLE && (o->otype & NO_TOGGLE))
|
||||
{
|
||||
parg.p_string = propt(c);
|
||||
error("Cannot change the %s option", &parg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (how_toggle == OPT_NO_TOGGLE && (o->otype & NO_QUERY))
|
||||
{
|
||||
parg.p_string = propt(c);
|
||||
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),
|
||||
ASCII_IS_LOWER(c));
|
||||
break;
|
||||
case OPT_UNSET:
|
||||
*(o->ovar) = o->odefault;
|
||||
break;
|
||||
case OPT_SET:
|
||||
*(o->ovar) = flip_triple(o->odefault,
|
||||
ASCII_IS_LOWER(c));
|
||||
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:
|
||||
if (*(o->ovar) < 0)
|
||||
error("Negative option is invalid", NULL_PARG);
|
||||
/*
|
||||
* 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(val, lc)
|
||||
int val;
|
||||
int lc;
|
||||
{
|
||||
if (lc)
|
||||
return ((val == OPT_ON) ? OPT_OFF : OPT_ON);
|
||||
else
|
||||
return ((val == OPT_ONPLUS) ? OPT_OFF : OPT_ONPLUS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a string suitable for printing as the "name" of an option.
|
||||
* For example, if the option letter is 'x', just return "-x".
|
||||
*/
|
||||
static char *
|
||||
propt(c)
|
||||
int c;
|
||||
{
|
||||
static char buf[8];
|
||||
|
||||
sprintf(buf, "-%s", prchar(c));
|
||||
return (buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if an option is a single character option (BOOL or TRIPLE),
|
||||
* or if it a multi-character option (NUMBER).
|
||||
*/
|
||||
public int
|
||||
single_char_option(c)
|
||||
int c;
|
||||
{
|
||||
register struct loption *o;
|
||||
|
||||
o = findopt(c);
|
||||
if (o == NULL)
|
||||
return (TRUE);
|
||||
return ((o->otype & (BOOL|TRIPLE|NOVAR|NO_TOGGLE)) != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the prompt to be used for a given option letter.
|
||||
* Only string and number valued options have prompts.
|
||||
*/
|
||||
public char *
|
||||
opt_prompt(c)
|
||||
int c;
|
||||
{
|
||||
register struct loption *o;
|
||||
|
||||
o = findopt(c);
|
||||
if (o == NULL || (o->otype & (STRING|NUMBER)) == 0)
|
||||
return (NULL);
|
||||
return (o->odesc[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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()
|
||||
{
|
||||
return (pendopt != NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print error message about missing string.
|
||||
*/
|
||||
static void
|
||||
nostring(printopt)
|
||||
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()
|
||||
{
|
||||
nostring(propt(pendopt->oletter));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(s, p_str, printopt, validchars)
|
||||
char *s;
|
||||
char **p_str;
|
||||
char *printopt;
|
||||
char *validchars;
|
||||
{
|
||||
register char *p;
|
||||
|
||||
if (*s == '\0')
|
||||
{
|
||||
nostring(printopt);
|
||||
quit(QUIT_ERROR);
|
||||
}
|
||||
*p_str = s;
|
||||
for (p = s; *p != '\0'; p++)
|
||||
{
|
||||
if (*p == END_OPTION_STRING ||
|
||||
(validchars != NULL && strchr(validchars, *p) == NULL))
|
||||
{
|
||||
switch (*p)
|
||||
{
|
||||
case END_OPTION_STRING:
|
||||
case ' ': case '\t': case '-':
|
||||
/* Replace the char with a null to terminate string. */
|
||||
*p++ = '\0';
|
||||
break;
|
||||
default:
|
||||
/* Cannot replace char; make a copy of the string. */
|
||||
*p_str = (char *) ecalloc(p-s+1, sizeof(char));
|
||||
strncpy(*p_str, s, p-s);
|
||||
(*p_str)[p-s] = '\0';
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (p);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(sp, printopt, errp)
|
||||
char **sp;
|
||||
char *printopt;
|
||||
int *errp;
|
||||
{
|
||||
register char *s;
|
||||
register int n;
|
||||
register int neg;
|
||||
PARG parg;
|
||||
|
||||
s = skipsp(*sp);
|
||||
neg = FALSE;
|
||||
if (*s == '-')
|
||||
{
|
||||
neg = TRUE;
|
||||
s++;
|
||||
}
|
||||
if (*s < '0' || *s > '9')
|
||||
{
|
||||
if (errp != NULL)
|
||||
{
|
||||
*errp = TRUE;
|
||||
return (-1);
|
||||
}
|
||||
if (printopt != NULL)
|
||||
{
|
||||
parg.p_string = printopt;
|
||||
error("Number is required after %s", &parg);
|
||||
}
|
||||
quit(QUIT_ERROR);
|
||||
}
|
||||
|
||||
n = 0;
|
||||
while (*s >= '0' && *s <= '9')
|
||||
n = 10 * n + *s++ - '0';
|
||||
*sp = s;
|
||||
if (errp != NULL)
|
||||
*errp = FALSE;
|
||||
if (neg)
|
||||
n = -n;
|
||||
return (n);
|
||||
}
|
||||
66
commands/less/less/option.h
Normal file
66
commands/less/less/option.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/* $NetBSD: option.h,v 1.7 2006/10/26 01:33:08 mrg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1984-2004 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 about less, or for information on how to
|
||||
* contact the author, 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)
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
};
|
||||
|
||||
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) /* Pointer to special handling function */
|
||||
__P((int, char *));
|
||||
char *odesc[3]; /* Description of each value */
|
||||
};
|
||||
|
||||
592
commands/less/less/opttbl.c
Normal file
592
commands/less/less/opttbl.c
Normal file
@@ -0,0 +1,592 @@
|
||||
/* $NetBSD: opttbl.c,v 1.12 2006/10/26 01:33:08 mrg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1984-2004 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 about less, or for information on how to
|
||||
* contact the author, 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 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 be_helpful; /* more(1) style -d */
|
||||
public int squeeze; /* Squeeze multiple blank lines into one */
|
||||
public int tabstop; /* Tab settings */
|
||||
public int back_scroll; /* Repaint screen on backwards movement */
|
||||
public int forw_scroll; /* Repaint screen on forward movement */
|
||||
public int caseless; /* Do "caseless" searches */
|
||||
public int linenums; /* Use line numbers */
|
||||
public int autobuf; /* Automatically allocate buffers as needed */
|
||||
public int bufspace; /* Max buffer space per file (K) */
|
||||
public int ctldisp; /* Send control chars to screen untranslated */
|
||||
public int force_open; /* Open the file even if not regular file */
|
||||
public int swindow; /* Size of scrolling window */
|
||||
public int jump_sline; /* Screen line of "jump target" */
|
||||
public int chopline; /* Truncate displayed lines at screen width */
|
||||
public int no_init; /* Disable sending ti/te termcap strings */
|
||||
public int no_keypad; /* Disable sending ks/ke termcap strings */
|
||||
public int twiddle; /* Show tildes after EOF */
|
||||
public int show_attn; /* Hilite first unread line */
|
||||
public int shift_count; /* Number of positions to shift horizontally */
|
||||
public int status_col; /* Display a status column */
|
||||
public int use_lessopen; /* Use the LESSOPEN filter */
|
||||
public int quit_on_intr; /* Quit on interrupt */
|
||||
#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 };
|
||||
#if MSDOS_COMPILER
|
||||
static struct optname D__optname = { "color", NULL };
|
||||
#endif
|
||||
static struct optname e_optname = { "quit-at-eof", NULL };
|
||||
static struct optname f_optname = { "force", NULL };
|
||||
static struct optname F__optname = { "quit-if-one-screen", NULL };
|
||||
#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 };
|
||||
#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 };
|
||||
|
||||
|
||||
/*
|
||||
* 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,
|
||||
BOOL, OPT_OFF, &how_search, NULL,
|
||||
{
|
||||
"Search includes displayed screen",
|
||||
"Search skips displayed screen",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
|
||||
{ '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 clearing each line",
|
||||
"Repaint by painting from top of screen"
|
||||
}
|
||||
},
|
||||
#if 1
|
||||
{ 'd', &d_optname,
|
||||
BOOL, OPT_OFF, &be_helpful, NULL,
|
||||
{ "Be less helpful in prompts",
|
||||
"Be helpful in prompts",
|
||||
NULL }
|
||||
},
|
||||
#endif
|
||||
{ -1, &d_optname,
|
||||
BOOL|NO_TOGGLE, OPT_OFF, &know_dumb, NULL,
|
||||
{
|
||||
"Assume intelligent terminal",
|
||||
"Assume dumb terminal",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
#if MSDOS_COMPILER
|
||||
{ 'D', &D__optname,
|
||||
STRING|REPAINT|NO_QUERY, 0, NULL, opt_D,
|
||||
{
|
||||
"color desc: ",
|
||||
"Ddknsu0123456789.",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
#endif
|
||||
{ '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,
|
||||
NUMBER, 1, &jump_sline, NULL,
|
||||
{
|
||||
"Target line: ",
|
||||
"Position target at screen line %d",
|
||||
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 }
|
||||
},
|
||||
#endif
|
||||
{ 'K', &K__optname,
|
||||
BOOL, OPT_OFF, &quit_on_intr, NULL,
|
||||
{
|
||||
"Interrupt (ctrl-C) returns to prompt",
|
||||
"Interrupt (ctrl-C) exits less",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ 'l', NULL,
|
||||
STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_l,
|
||||
{ NULL, NULL, 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",
|
||||
"Display control characters directly, processing ANSI sequences"
|
||||
}
|
||||
},
|
||||
{ '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, 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,
|
||||
NUMBER, 0, &shift_count, NULL,
|
||||
{
|
||||
"Horizontal shift: ",
|
||||
"Horizontal shift %d positions",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ '.', &keypad_optname,
|
||||
BOOL|NO_TOGGLE, OPT_OFF, &no_keypad, NULL,
|
||||
{
|
||||
"Use keypad mode",
|
||||
"Don't use keypad mode",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ '\0', NULL, NOVAR, 0, NULL, NULL, { NULL, NULL, NULL } }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Initialize each option to its default value.
|
||||
*/
|
||||
public void
|
||||
init_option()
|
||||
{
|
||||
register struct loption *o;
|
||||
char *p;
|
||||
|
||||
p = lgetenv("LESS_IS_MORE");
|
||||
if (p != NULL && *p != '\0')
|
||||
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(c)
|
||||
int c;
|
||||
{
|
||||
register 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(c)
|
||||
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(p_optname, p_oname, p_err)
|
||||
char **p_optname;
|
||||
char **p_oname;
|
||||
int *p_err;
|
||||
{
|
||||
char *optname = *p_optname;
|
||||
register struct loption *o;
|
||||
register struct optname *oname;
|
||||
register 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);
|
||||
}
|
||||
335
commands/less/less/os.c
Normal file
335
commands/less/less/os.c
Normal file
@@ -0,0 +1,335 @@
|
||||
/* $NetBSD: os.c,v 1.9 2006/10/26 01:33:08 mrg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1984-2005 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 about less, or for information on how to
|
||||
* contact the author, 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 HAVE_TIME_H
|
||||
#include <time.h>
|
||||
#endif
|
||||
#if HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#if HAVE_VALUES_H
|
||||
#include <values.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_TIME_T
|
||||
#define time_type time_t
|
||||
#else
|
||||
#define time_type long
|
||||
#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;
|
||||
|
||||
static jmp_buf read_label;
|
||||
|
||||
extern int sigs;
|
||||
|
||||
#if !HAVE_STRERROR
|
||||
static char *strerror __P((int));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Like read() system call, but is deliberately interruptible.
|
||||
* A call to intread() from a signal handler will interrupt
|
||||
* any pending iread().
|
||||
*/
|
||||
public int
|
||||
iread(fd, buf, len)
|
||||
int fd;
|
||||
char *buf;
|
||||
unsigned int len;
|
||||
{
|
||||
register int n;
|
||||
|
||||
#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 (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
|
||||
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.
|
||||
*/
|
||||
fd_set readfds;
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(fd, &readfds);
|
||||
if (select(fd+1, &readfds, 0, 0, 0) == -1)
|
||||
return (-1);
|
||||
}
|
||||
#endif
|
||||
n = read(fd, buf, len);
|
||||
#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.
|
||||
*/
|
||||
{
|
||||
extern int ignore_eoi;
|
||||
if (!ignore_eoi)
|
||||
{
|
||||
static int consecutive_nulls = 0;
|
||||
if (n == 0)
|
||||
consecutive_nulls++;
|
||||
else
|
||||
consecutive_nulls = 0;
|
||||
if (consecutive_nulls > 20)
|
||||
quit(QUIT_ERROR);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
reading = 0;
|
||||
if (n < 0)
|
||||
return (-1);
|
||||
return (n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt a pending iread().
|
||||
*/
|
||||
public void
|
||||
intread()
|
||||
{
|
||||
LONG_JUMP(read_label, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the current time.
|
||||
*/
|
||||
#if HAVE_TIME
|
||||
public long
|
||||
get_time()
|
||||
{
|
||||
time_type t;
|
||||
|
||||
time(&t);
|
||||
return (t);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if !HAVE_STRERROR
|
||||
/*
|
||||
* Local version of strerror, if not available from the system.
|
||||
*/
|
||||
static char *
|
||||
strerror(err)
|
||||
int err;
|
||||
{
|
||||
#if HAVE_SYS_ERRLIST
|
||||
static char buf[16];
|
||||
extern char *sys_errlist[];
|
||||
extern int sys_nerr;
|
||||
|
||||
if (err < sys_nerr)
|
||||
return sys_errlist[err];
|
||||
sprintf(buf, "Error %d", err);
|
||||
return buf;
|
||||
#else
|
||||
return ("cannot open");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* errno_message: Return an error message based on the value of "errno".
|
||||
*/
|
||||
public char *
|
||||
errno_message(filename)
|
||||
char *filename;
|
||||
{
|
||||
register const char *p;
|
||||
register char *m;
|
||||
int len;
|
||||
#if HAVE_ERRNO
|
||||
#if MUST_DEFINE_ERRNO
|
||||
extern int errno;
|
||||
#endif
|
||||
p = strerror(errno);
|
||||
#else
|
||||
p = "cannot open";
|
||||
#endif
|
||||
len = strlen(filename) + strlen(p) + 3;
|
||||
m = (char *) ecalloc(len, sizeof(char));
|
||||
SNPRINTF2(m, len, "%s: %s", filename, p);
|
||||
return (m);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the ratio of two POSITIONS, as a percentage.
|
||||
* {{ Assumes a POSITION is a long int. }}
|
||||
*/
|
||||
public int
|
||||
percentage(num, den)
|
||||
POSITION num, den;
|
||||
{
|
||||
POSITION num100 = num * 100;
|
||||
|
||||
if (num100 / 100 == num)
|
||||
return (num100 / den);
|
||||
else
|
||||
return (num / (den / 100));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the specified percentage of a POSITION.
|
||||
*/
|
||||
public POSITION
|
||||
percent_pos(pos, percent)
|
||||
POSITION pos;
|
||||
int percent;
|
||||
{
|
||||
POSITION result100;
|
||||
|
||||
if (percent == 0)
|
||||
return (0);
|
||||
else if ((result100 = pos * percent) / percent == pos)
|
||||
return (result100 / 100);
|
||||
else
|
||||
return (percent * (pos / 100));
|
||||
}
|
||||
|
||||
#if !HAVE_STRCHR
|
||||
/*
|
||||
* strchr is used by regexp.c.
|
||||
*/
|
||||
char *
|
||||
strchr(s, c)
|
||||
char *s;
|
||||
int c;
|
||||
{
|
||||
for ( ; *s != '\0'; s++)
|
||||
if (*s == c)
|
||||
return (s);
|
||||
if (c == '\0')
|
||||
return (s);
|
||||
return (NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !HAVE_MEMCPY
|
||||
VOID_POINTER
|
||||
memcpy(dst, src, len)
|
||||
VOID_POINTER dst;
|
||||
VOID_POINTER 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(type, handler)
|
||||
int type;
|
||||
RETSIGTYPE (*handler)();
|
||||
{
|
||||
intercept(handler);
|
||||
}
|
||||
|
||||
#include <sgstat.h>
|
||||
|
||||
int
|
||||
isatty(f)
|
||||
int f;
|
||||
{
|
||||
struct sgbuf sgbuf;
|
||||
|
||||
if (_gs_opt(f, &sgbuf) < 0)
|
||||
return -1;
|
||||
return (sgbuf.sg_class == 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
612
commands/less/less/output.c
Normal file
612
commands/less/less/output.c
Normal file
@@ -0,0 +1,612 @@
|
||||
/* $NetBSD: output.c,v 1.10 2008/02/16 07:20:54 matt Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1984-2005 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 about less, or for information on how to
|
||||
* contact the author, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* High level routines dealing with the output to the screen.
|
||||
*/
|
||||
|
||||
#include "less.h"
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
#include "windows.h"
|
||||
#endif
|
||||
|
||||
public int errmsgs; /* Count of messages displayed by error() */
|
||||
public int need_clr;
|
||||
public int final_attr;
|
||||
|
||||
extern int sigs;
|
||||
extern int sc_width;
|
||||
extern int so_s_width, so_e_width;
|
||||
extern int screen_trashed;
|
||||
extern int any_display;
|
||||
extern int is_tty;
|
||||
|
||||
#if 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;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Display the line which is in the line buffer.
|
||||
*/
|
||||
public void
|
||||
put_line()
|
||||
{
|
||||
register int c;
|
||||
register 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;
|
||||
|
||||
/*
|
||||
* 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()
|
||||
{
|
||||
register int n;
|
||||
register int fd;
|
||||
|
||||
n = ob - obuf;
|
||||
if (n == 0)
|
||||
return;
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
if (is_tty && any_display)
|
||||
{
|
||||
char *op;
|
||||
DWORD nwritten = 0;
|
||||
CONSOLE_SCREEN_BUFFER_INFO scr;
|
||||
int row;
|
||||
int col;
|
||||
int olen;
|
||||
extern HANDLE con_out;
|
||||
|
||||
olen = ob - obuf;
|
||||
/*
|
||||
* There is a bug in Win32 WriteConsole() if we're
|
||||
* writing in the last cell with a different color.
|
||||
* To avoid color problems in the bottom line,
|
||||
* we scroll the screen manually, before writing.
|
||||
*/
|
||||
GetConsoleScreenBufferInfo(con_out, &scr);
|
||||
col = scr.dwCursorPosition.X;
|
||||
row = scr.dwCursorPosition.Y;
|
||||
for (op = obuf; op < obuf + olen; op++)
|
||||
{
|
||||
if (*op == '\n')
|
||||
{
|
||||
col = 0;
|
||||
row++;
|
||||
} else if (*op == '\r')
|
||||
{
|
||||
col = 0;
|
||||
} else
|
||||
{
|
||||
col++;
|
||||
if (col >= sc_width)
|
||||
{
|
||||
col = 0;
|
||||
row++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (row > scr.srWindow.Bottom)
|
||||
win32_scroll_up(row - scr.srWindow.Bottom);
|
||||
WriteConsole(con_out, obuf, olen, &nwritten, NULL);
|
||||
ob = obuf;
|
||||
return;
|
||||
}
|
||||
#else
|
||||
#if MSDOS_COMPILER==MSOFTC
|
||||
if (is_tty && any_display)
|
||||
{
|
||||
*ob = '\0';
|
||||
_outtext(obuf);
|
||||
ob = obuf;
|
||||
return;
|
||||
}
|
||||
#else
|
||||
#if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC
|
||||
if (is_tty && any_display)
|
||||
{
|
||||
*ob = '\0';
|
||||
if (ctldisp != OPT_ONPLUS)
|
||||
cputs(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;
|
||||
int buflen = ob - obuf;
|
||||
unsigned char fg, bg, norm_attr;
|
||||
/*
|
||||
* Only dark colors mentioned here, so that
|
||||
* bold has visible effect.
|
||||
*/
|
||||
static enum COLORS screen_color[] = {
|
||||
BLACK, RED, GREEN, BROWN,
|
||||
BLUE, MAGENTA, CYAN, LIGHTGRAY
|
||||
};
|
||||
|
||||
/* Normal text colors are used as baseline. */
|
||||
bg = nm_bg_color & 0xf;
|
||||
fg = nm_fg_color & 0xf;
|
||||
norm_attr = (bg << 4) | fg;
|
||||
for (anchor = p_next = obuf;
|
||||
(p_next = memchr (p_next, ESC,
|
||||
buflen - (p_next - obuf)))
|
||||
!= NULL; )
|
||||
{
|
||||
p = p_next;
|
||||
|
||||
/*
|
||||
* Handle the null escape sequence
|
||||
* (ESC-[m), which is used to restore
|
||||
* the original color.
|
||||
*/
|
||||
if (p[1] == '[' && is_ansi_end(p[2]))
|
||||
{
|
||||
textattr(norm_attr);
|
||||
p += 3;
|
||||
anchor = p_next = p;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (p[1] == '[') /* "Esc-[" sequence */
|
||||
{
|
||||
/*
|
||||
* If some chars seen since
|
||||
* the last escape sequence,
|
||||
* write it out to the screen
|
||||
* using current text attributes.
|
||||
*/
|
||||
if (p > anchor)
|
||||
{
|
||||
*p = '\0';
|
||||
cputs (anchor);
|
||||
*p = ESC;
|
||||
anchor = p;
|
||||
}
|
||||
p += 2;
|
||||
p_next = p;
|
||||
while (!is_ansi_end(*p))
|
||||
{
|
||||
char *q;
|
||||
long code = strtol(p, &q, 10);
|
||||
|
||||
if (!*q)
|
||||
{
|
||||
/*
|
||||
* Incomplete sequence.
|
||||
* Leave it unprocessed
|
||||
* in the buffer.
|
||||
*/
|
||||
int slop = q - anchor;
|
||||
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++;
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case 1: /* bold on */
|
||||
fg = bo_fg_color;
|
||||
bg = bo_bg_color;
|
||||
break;
|
||||
case 3: /* italic on */
|
||||
fg = so_fg_color;
|
||||
bg = so_bg_color;
|
||||
break;
|
||||
case 4: /* underline on */
|
||||
fg = ul_fg_color;
|
||||
bg = ul_bg_color;
|
||||
break;
|
||||
case 8: /* concealed on */
|
||||
fg = (bg & 7) | 8;
|
||||
break;
|
||||
case 0: /* all attrs off */
|
||||
case 22:/* bold off */
|
||||
case 23:/* italic off */
|
||||
case 24:/* underline off */
|
||||
fg = nm_fg_color;
|
||||
bg = nm_bg_color;
|
||||
break;
|
||||
case 30: case 31: case 32:
|
||||
case 33: case 34: case 35:
|
||||
case 36: case 37:
|
||||
fg = (fg & 8) | (screen_color[code - 30]);
|
||||
break;
|
||||
case 39: /* default fg */
|
||||
fg = nm_fg_color;
|
||||
break;
|
||||
case 40: case 41: case 42:
|
||||
case 43: case 44: case 45:
|
||||
case 46: case 47:
|
||||
bg = (bg & 8) | (screen_color[code - 40]);
|
||||
break;
|
||||
case 49: /* default fg */
|
||||
bg = nm_bg_color;
|
||||
break;
|
||||
}
|
||||
p = q;
|
||||
}
|
||||
if (is_ansi_end(*p) && p > p_next)
|
||||
{
|
||||
bg &= 15;
|
||||
fg &= 15;
|
||||
textattr ((bg << 4)| fg);
|
||||
p_next = anchor = p + 1;
|
||||
} else
|
||||
break;
|
||||
} else
|
||||
p_next++;
|
||||
}
|
||||
|
||||
/* Output what's left in the buffer. */
|
||||
cputs (anchor);
|
||||
}
|
||||
ob = obuf;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
fd = (any_display) ? 1 : 2;
|
||||
if (write(fd, obuf, n) != n)
|
||||
screen_trashed = 1;
|
||||
ob = obuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Output a character.
|
||||
*/
|
||||
public int
|
||||
putchr(c)
|
||||
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
|
||||
if (need_clr)
|
||||
{
|
||||
need_clr = 0;
|
||||
clear_bot();
|
||||
}
|
||||
#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;
|
||||
return (c);
|
||||
}
|
||||
|
||||
/*
|
||||
* Output a string.
|
||||
*/
|
||||
public void
|
||||
putstr(s)
|
||||
register char *s;
|
||||
{
|
||||
while (*s != '\0')
|
||||
putchr(*s++);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert an integral type to a string.
|
||||
*/
|
||||
#define TYPE_TO_A_FUNC(funcname, type) \
|
||||
void funcname(num, buf) \
|
||||
type num; \
|
||||
char *buf; \
|
||||
{ \
|
||||
int neg = (num < 0); \
|
||||
char tbuf[INT_STRLEN_BOUND(num)+2]; \
|
||||
register char *s = tbuf + sizeof(tbuf); \
|
||||
if (neg) num = -num; \
|
||||
*--s = '\0'; \
|
||||
do { \
|
||||
*--s = (num % 10) + '0'; \
|
||||
} while ((num /= 10) != 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)
|
||||
|
||||
/*
|
||||
* Output an integer in a given radix.
|
||||
*/
|
||||
static int
|
||||
iprint_int(num)
|
||||
int num;
|
||||
{
|
||||
char buf[INT_STRLEN_BOUND(num)];
|
||||
|
||||
inttoa(num, buf);
|
||||
putstr(buf);
|
||||
return (strlen(buf));
|
||||
}
|
||||
|
||||
/*
|
||||
* Output a line number in a given radix.
|
||||
*/
|
||||
static int
|
||||
iprint_linenum(num)
|
||||
LINENUM num;
|
||||
{
|
||||
char buf[INT_STRLEN_BOUND(num)];
|
||||
|
||||
linenumtoa(num, buf);
|
||||
putstr(buf);
|
||||
return (strlen(buf));
|
||||
}
|
||||
|
||||
/*
|
||||
* This function implements printf-like functionality
|
||||
* using a more portable argument list mechanism than printf's.
|
||||
*/
|
||||
static int
|
||||
less_printf(fmt, parg)
|
||||
register char *fmt;
|
||||
PARG *parg;
|
||||
{
|
||||
register constant char *s;
|
||||
register 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);
|
||||
parg++;
|
||||
break;
|
||||
case 'n':
|
||||
col += iprint_linenum(parg->p_linenum);
|
||||
parg++;
|
||||
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()
|
||||
{
|
||||
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(fmt, parg)
|
||||
char *fmt;
|
||||
PARG *parg;
|
||||
{
|
||||
int col = 0;
|
||||
static char return_to_continue[] = " (press RETURN)";
|
||||
|
||||
errmsgs++;
|
||||
|
||||
if (any_display && is_tty)
|
||||
{
|
||||
at_exit();
|
||||
clear_bot();
|
||||
at_enter(AT_STANDOUT);
|
||||
col += so_s_width;
|
||||
}
|
||||
|
||||
col += less_printf(fmt, parg);
|
||||
|
||||
if (!(any_display && is_tty))
|
||||
{
|
||||
putchr('\n');
|
||||
return;
|
||||
}
|
||||
|
||||
putstr(return_to_continue);
|
||||
at_exit();
|
||||
col += sizeof(return_to_continue) + so_e_width;
|
||||
|
||||
get_return();
|
||||
lower_left();
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
static char intr_to_abort[] = "... (interrupt to abort)";
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
public void
|
||||
ierror(fmt, parg)
|
||||
char *fmt;
|
||||
PARG *parg;
|
||||
{
|
||||
at_exit();
|
||||
clear_bot();
|
||||
at_enter(AT_STANDOUT);
|
||||
(void) less_printf(fmt, parg);
|
||||
putstr(intr_to_abort);
|
||||
at_exit();
|
||||
flush();
|
||||
need_clr = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Output a message in the lower left corner of the screen
|
||||
* and return a single-character response.
|
||||
*/
|
||||
public int
|
||||
query(fmt, parg)
|
||||
char *fmt;
|
||||
PARG *parg;
|
||||
{
|
||||
register int c;
|
||||
int col = 0;
|
||||
|
||||
if (any_display && is_tty)
|
||||
clear_bot();
|
||||
|
||||
(void) less_printf(fmt, parg);
|
||||
c = getchr();
|
||||
|
||||
if (!(any_display && is_tty))
|
||||
{
|
||||
putchr('\n');
|
||||
return (c);
|
||||
}
|
||||
|
||||
lower_left();
|
||||
if (col >= sc_width)
|
||||
screen_trashed = 1;
|
||||
flush();
|
||||
|
||||
return (c);
|
||||
}
|
||||
34
commands/less/less/pckeys.h
Normal file
34
commands/less/less/pckeys.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 1984-2004 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 about less, or for information on how to
|
||||
* contact the author, 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'
|
||||
233
commands/less/less/position.c
Normal file
233
commands/less/less/position.c
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* Copyright (C) 1984-2004 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 about less, or for information on how to
|
||||
* contact the author, 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;
|
||||
|
||||
extern int sc_width, sc_height;
|
||||
|
||||
/*
|
||||
* Return the starting file position of a line displayed on the screen.
|
||||
* The line may be specified as a line number relative to the top
|
||||
* of the screen, but is usually one of these special cases:
|
||||
* the top (first) line on the screen
|
||||
* the second line on the screen
|
||||
* the bottom line on the screen
|
||||
* the line after the bottom line on the screen
|
||||
*/
|
||||
public POSITION
|
||||
position(where)
|
||||
int where;
|
||||
{
|
||||
switch (where)
|
||||
{
|
||||
case BOTTOM:
|
||||
where = sc_height - 2;
|
||||
break;
|
||||
case BOTTOM_PLUS_ONE:
|
||||
where = sc_height - 1;
|
||||
break;
|
||||
case MIDDLE:
|
||||
where = (sc_height - 1) / 2;
|
||||
}
|
||||
return (table[where]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a new file position to the bottom of the position table.
|
||||
*/
|
||||
public void
|
||||
add_forw_pos(pos)
|
||||
POSITION pos;
|
||||
{
|
||||
register 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(pos)
|
||||
POSITION pos;
|
||||
{
|
||||
register 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()
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = 0; i < sc_height; i++)
|
||||
table[i] = NULL_POSITION;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate or reallocate the position table.
|
||||
*/
|
||||
public void
|
||||
pos_init()
|
||||
{
|
||||
struct scrpos scrpos;
|
||||
scrpos.pos = scrpos.ln = 0; /* XXX: GCC */
|
||||
|
||||
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);
|
||||
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(pos)
|
||||
POSITION pos;
|
||||
{
|
||||
register 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()
|
||||
{
|
||||
return (empty_lines(0, sc_height-1));
|
||||
}
|
||||
|
||||
public int
|
||||
empty_lines(s, e)
|
||||
int s;
|
||||
int e;
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = s; i <= e; i++)
|
||||
if (table[i] != NULL_POSITION)
|
||||
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(scrpos)
|
||||
struct scrpos *scrpos;
|
||||
{
|
||||
register int i;
|
||||
|
||||
/*
|
||||
* Find the first line on the screen which has something on it,
|
||||
* and return the screen line number and the file position.
|
||||
*/
|
||||
for (i = 0; i < sc_height; i++)
|
||||
if (table[i] != NULL_POSITION)
|
||||
{
|
||||
scrpos->ln = i+1;
|
||||
scrpos->pos = table[i];
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* 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
|
||||
adjsline(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-1.
|
||||
*/
|
||||
if (sline <= 0)
|
||||
sline = 1;
|
||||
if (sline >= sc_height)
|
||||
sline = sc_height - 1;
|
||||
/*
|
||||
* Return zero-based line number, not one-based.
|
||||
*/
|
||||
return (sline-1);
|
||||
}
|
||||
19
commands/less/less/position.h
Normal file
19
commands/less/less/position.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 1984-2004 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 about less, or for information on how to
|
||||
* contact the author, 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)
|
||||
593
commands/less/less/prompt.c
Normal file
593
commands/less/less/prompt.c
Normal file
@@ -0,0 +1,593 @@
|
||||
/* $NetBSD: prompt.c,v 1.13 2008/02/16 07:20:54 matt Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1984-2004 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 about less, or for information on how to
|
||||
* contact the author, 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 hit_eof;
|
||||
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 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";
|
||||
|
||||
public char constant *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;
|
||||
|
||||
static void ap_pos __P((POSITION));
|
||||
static void ap_int __P((int));
|
||||
static void ap_str __P((char *));
|
||||
static void ap_char __P((int));
|
||||
static void ap_quest __P((void));
|
||||
static POSITION curr_byte __P((int));
|
||||
static int cond __P((int, int));
|
||||
static void protochar __P((int, int, int));
|
||||
static char *skipcond __P((char *));
|
||||
static char *wherechar __P((char *, int *));
|
||||
|
||||
/*
|
||||
* Initialize the prompt prototype strings.
|
||||
*/
|
||||
public void
|
||||
init_prompt()
|
||||
{
|
||||
prproto[0] = save(s_proto);
|
||||
prproto[1] = save(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(s)
|
||||
char *s;
|
||||
{
|
||||
int len;
|
||||
|
||||
len = strlen(s);
|
||||
if (mp + len >= message + PROMPT_SIZE)
|
||||
len = 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(i)
|
||||
int i;
|
||||
{
|
||||
char buf[2];
|
||||
char c = (char)i;
|
||||
|
||||
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(pos)
|
||||
POSITION pos;
|
||||
{
|
||||
char buf[INT_STRLEN_BOUND(pos) + 2];
|
||||
|
||||
postoa(pos, buf);
|
||||
ap_str(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Append a line number to the end of the message.
|
||||
*/
|
||||
static void
|
||||
ap_linenum(linenum)
|
||||
LINENUM linenum;
|
||||
{
|
||||
char buf[INT_STRLEN_BOUND(linenum) + 2];
|
||||
|
||||
linenumtoa(linenum, buf);
|
||||
ap_str(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Append an integer to the end of the message.
|
||||
*/
|
||||
static void
|
||||
ap_int(num)
|
||||
int num;
|
||||
{
|
||||
char buf[INT_STRLEN_BOUND(num) + 2];
|
||||
|
||||
inttoa(num, buf);
|
||||
ap_str(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Append a question mark to the end of the message.
|
||||
*/
|
||||
static void
|
||||
ap_quest()
|
||||
{
|
||||
ap_str("?");
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the "current" byte offset in the file.
|
||||
*/
|
||||
static POSITION
|
||||
curr_byte(where)
|
||||
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(c, where)
|
||||
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 (hit_eof);
|
||||
case 'f': /* Filename known? */
|
||||
return (strcmp(get_filename(curr_ifile), "-") != 0);
|
||||
case 'l': /* Line number known? */
|
||||
case 'd': /* Same as l */
|
||||
return (linenums);
|
||||
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(c, where, iseditproto)
|
||||
int c;
|
||||
int where;
|
||||
int iseditproto;
|
||||
{
|
||||
POSITION pos;
|
||||
POSITION len;
|
||||
int n;
|
||||
LINENUM linenum;
|
||||
LINENUM last_linenum;
|
||||
IFILE h;
|
||||
|
||||
#undef PAGE_NUM
|
||||
#define PAGE_NUM(linenum) ((((linenum) - 1) / (sc_height - 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 > 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 '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(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(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--;
|
||||
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 char *
|
||||
skipcond(p)
|
||||
register char *p;
|
||||
{
|
||||
register 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.
|
||||
*/
|
||||
++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 char *
|
||||
wherechar(p, wp)
|
||||
char *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 = adjsline(jump_sline); break;
|
||||
default: *wp = TOP; p--; break;
|
||||
}
|
||||
}
|
||||
return (p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct a message based on a prototype string.
|
||||
*/
|
||||
public char *
|
||||
pr_expand(proto, maxwidth)
|
||||
char *proto;
|
||||
int maxwidth;
|
||||
{
|
||||
register char *p;
|
||||
register 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 */
|
||||
p++;
|
||||
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 ("");
|
||||
if (maxwidth > 0 && mp >= message + maxwidth)
|
||||
{
|
||||
/*
|
||||
* Message is too long.
|
||||
* Return just the final portion of it.
|
||||
*/
|
||||
return (mp - maxwidth);
|
||||
}
|
||||
return (message);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a message suitable for printing by the "=" command.
|
||||
*/
|
||||
public char *
|
||||
eq_message()
|
||||
{
|
||||
return (pr_expand(eqproto, 0));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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()
|
||||
{
|
||||
char *prompt;
|
||||
|
||||
prompt = pr_expand((ch_getflags() & CH_HELPFILE) ?
|
||||
hproto : prproto[pr_type],
|
||||
sc_width-so_s_width-so_e_width-2);
|
||||
new_file = 0;
|
||||
return (prompt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a message suitable for printing while waiting in the F command.
|
||||
*/
|
||||
public char *
|
||||
wait_message()
|
||||
{
|
||||
return (pr_expand(wproto, sc_width-so_s_width-so_e_width-2));
|
||||
}
|
||||
2424
commands/less/less/screen.c
Normal file
2424
commands/less/less/screen.c
Normal file
File diff suppressed because it is too large
Load Diff
1452
commands/less/less/search.c
Normal file
1452
commands/less/less/search.c
Normal file
File diff suppressed because it is too large
Load Diff
281
commands/less/less/signal.c
Normal file
281
commands/less/less/signal.c
Normal file
@@ -0,0 +1,281 @@
|
||||
/* $NetBSD: signal.c,v 1.6 2006/10/26 01:33:08 mrg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1984-2004 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 about less, or for information on how to
|
||||
* contact the author, 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;
|
||||
|
||||
static RETSIGTYPE u_interrupt __P((int));
|
||||
static RETSIGTYPE stop __P((int));
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
static BOOL WINAPI wbreak_handler __P((DWORD));
|
||||
#endif
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
* Interrupt signal handler.
|
||||
*/
|
||||
/* ARGSUSED*/
|
||||
static RETSIGTYPE
|
||||
u_interrupt(type)
|
||||
int type;
|
||||
{
|
||||
#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 (reading)
|
||||
intread();
|
||||
}
|
||||
|
||||
#ifdef SIGTSTP
|
||||
/*
|
||||
* "Stop" (^Z) signal handler.
|
||||
*/
|
||||
/* ARGSUSED*/
|
||||
static RETSIGTYPE
|
||||
stop(type)
|
||||
int type;
|
||||
{
|
||||
LSIGNAL(SIGTSTP, stop);
|
||||
sigs |= S_STOP;
|
||||
if (reading)
|
||||
intread();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SIGWINCH
|
||||
/*
|
||||
* "Window" change handler
|
||||
*/
|
||||
/* ARGSUSED*/
|
||||
public RETSIGTYPE
|
||||
winch(type)
|
||||
int type;
|
||||
{
|
||||
LSIGNAL(SIGWINCH, winch);
|
||||
sigs |= S_WINCH;
|
||||
if (reading)
|
||||
intread();
|
||||
}
|
||||
#else
|
||||
#ifdef SIGWIND
|
||||
/*
|
||||
* "Window" change handler
|
||||
*/
|
||||
/* ARGSUSED*/
|
||||
public RETSIGTYPE
|
||||
winch(type)
|
||||
int type;
|
||||
{
|
||||
LSIGNAL(SIGWIND, winch);
|
||||
sigs |= S_WINCH;
|
||||
if (reading)
|
||||
intread();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
/*
|
||||
* Handle CTRL-C and CTRL-BREAK keys.
|
||||
*/
|
||||
#include "windows.h"
|
||||
|
||||
static BOOL WINAPI
|
||||
wbreak_handler(dwCtrlType)
|
||||
DWORD dwCtrlType;
|
||||
{
|
||||
switch (dwCtrlType)
|
||||
{
|
||||
case CTRL_C_EVENT:
|
||||
case CTRL_BREAK_EVENT:
|
||||
sigs |= S_INTERRUPT;
|
||||
return (TRUE);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set up the signal handlers.
|
||||
*/
|
||||
public void
|
||||
init_signals(on)
|
||||
int on;
|
||||
{
|
||||
if (on)
|
||||
{
|
||||
/*
|
||||
* Set signal handlers.
|
||||
*/
|
||||
(void) LSIGNAL(SIGINT, u_interrupt);
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
SetConsoleCtrlHandler(wbreak_handler, TRUE);
|
||||
#endif
|
||||
#ifdef SIGTSTP
|
||||
(void) LSIGNAL(SIGTSTP, stop);
|
||||
#endif
|
||||
#ifdef SIGWINCH
|
||||
(void) LSIGNAL(SIGWINCH, winch);
|
||||
#else
|
||||
#ifdef SIGWIND
|
||||
(void) LSIGNAL(SIGWIND, winch);
|
||||
#endif
|
||||
#ifdef SIGQUIT
|
||||
(void) LSIGNAL(SIGQUIT, SIG_IGN);
|
||||
#endif
|
||||
#endif
|
||||
} else
|
||||
{
|
||||
/*
|
||||
* Restore signals to defaults.
|
||||
*/
|
||||
(void) LSIGNAL(SIGINT, SIG_DFL);
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
SetConsoleCtrlHandler(wbreak_handler, FALSE);
|
||||
#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
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Process any signals we have received.
|
||||
* A received signal cause a bit to be set in "sigs".
|
||||
*/
|
||||
public void
|
||||
psignals()
|
||||
{
|
||||
register 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;
|
||||
screen_trashed = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (tsignals & S_INTERRUPT)
|
||||
{
|
||||
if (quit_on_intr)
|
||||
quit(QUIT_OK);
|
||||
bell();
|
||||
/*
|
||||
* {{ You may wish to replace the bell() with
|
||||
* error("Interrupt", NULL_PARG); }}
|
||||
*/
|
||||
|
||||
/*
|
||||
* If we were interrupted while in the "calculating
|
||||
* line numbers" loop, turn off line numbers.
|
||||
*/
|
||||
if (lnloop)
|
||||
{
|
||||
lnloop = 0;
|
||||
if (linenums == 2)
|
||||
screen_trashed = 1;
|
||||
linenums = 0;
|
||||
error("Line numbers turned off", NULL_PARG);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
759
commands/less/less/tags.c
Normal file
759
commands/less/less/tags.c
Normal file
@@ -0,0 +1,759 @@
|
||||
/* $NetBSD: tags.c,v 1.8 2006/10/26 01:33:08 mrg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1984-2004 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 about less, or for information on how to
|
||||
* contact the author, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
#include "less.h"
|
||||
|
||||
#define WHITESP(c) ((c)==' ' || (c)=='\t')
|
||||
|
||||
#if TAGS
|
||||
|
||||
public char *tags = "tags";
|
||||
|
||||
static int total;
|
||||
static int curseq;
|
||||
|
||||
extern int linenums;
|
||||
extern int sigs;
|
||||
|
||||
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 defenition (global) */
|
||||
T_GRTAGS, /* 'GRTAGS': function reference (global) */
|
||||
T_GSYMS, /* 'GSYMS': other symbols (global) */
|
||||
T_GPATH /* 'GPATH': path name (global) */
|
||||
};
|
||||
|
||||
static enum tag_result findctag();
|
||||
static enum tag_result findgtag();
|
||||
static char *nextgtag();
|
||||
static char *prevgtag();
|
||||
static POSITION ctagsearch();
|
||||
static POSITION gtagsearch();
|
||||
static int getentry();
|
||||
|
||||
/*
|
||||
* 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() usually either pattern (in which case line number is 0),
|
||||
* or line number (in which case pattern is NULL).
|
||||
*/
|
||||
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 '$' */
|
||||
};
|
||||
struct taglist {
|
||||
struct tag *tl_first;
|
||||
struct tag *tl_last;
|
||||
};
|
||||
#define TAG_END ((struct tag *) &taglist)
|
||||
static struct taglist taglist = { TAG_END, TAG_END };
|
||||
static struct tag *curtag;
|
||||
|
||||
#define TAG_INS(tp) \
|
||||
(tp)->next = taglist.tl_first; \
|
||||
(tp)->prev = TAG_END; \
|
||||
taglist.tl_first->prev = (tp); \
|
||||
taglist.tl_first = (tp);
|
||||
|
||||
#define TAG_RM(tp) \
|
||||
(tp)->next->prev = (tp)->prev; \
|
||||
(tp)->prev->next = (tp)->next;
|
||||
|
||||
/*
|
||||
* Delete tag structures.
|
||||
*/
|
||||
public void
|
||||
cleantags()
|
||||
{
|
||||
register 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);
|
||||
}
|
||||
curtag = NULL;
|
||||
total = curseq = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new tag entry.
|
||||
*/
|
||||
static struct tag *
|
||||
maketagent(name, file, linenum, pattern, endline)
|
||||
char *name;
|
||||
char *file;
|
||||
LINENUM linenum;
|
||||
char *pattern;
|
||||
int endline;
|
||||
{
|
||||
register 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()
|
||||
{
|
||||
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(tag)
|
||||
register 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()
|
||||
{
|
||||
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(n)
|
||||
int n;
|
||||
{
|
||||
char *tagfile = (char *) NULL;
|
||||
|
||||
while (n-- > 0)
|
||||
tagfile = nextgtag();
|
||||
return tagfile;
|
||||
}
|
||||
|
||||
/*
|
||||
* Go to the previous tag.
|
||||
*/
|
||||
public char *
|
||||
prevtag(n)
|
||||
int n;
|
||||
{
|
||||
char *tagfile = (char *) NULL;
|
||||
|
||||
while (n-- > 0)
|
||||
tagfile = prevgtag();
|
||||
return tagfile;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the total number of tags.
|
||||
*/
|
||||
public int
|
||||
ntags()
|
||||
{
|
||||
return total;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the sequence number of current tag.
|
||||
*/
|
||||
public int
|
||||
curr_tag()
|
||||
{
|
||||
return curseq;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* ctags
|
||||
*/
|
||||
|
||||
/*
|
||||
* Find tags in the "tags" file.
|
||||
* Sets curtag to the first tag entry.
|
||||
*/
|
||||
static enum tag_result
|
||||
findctag(tag)
|
||||
register char *tag;
|
||||
{
|
||||
char *p;
|
||||
register FILE *f;
|
||||
register 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 = 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 = p;
|
||||
while (*p != search_char && *p != '\0')
|
||||
{
|
||||
if (*p == '\\')
|
||||
p++;
|
||||
p++;
|
||||
}
|
||||
tagendline = (p[-1] == '$');
|
||||
if (tagendline)
|
||||
p--;
|
||||
*p = '\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()
|
||||
{
|
||||
if (curtag == NULL)
|
||||
return (1);
|
||||
return (edit(curtag->tag_file));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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()
|
||||
{
|
||||
POSITION pos, linepos;
|
||||
LINENUM linenum;
|
||||
int len;
|
||||
char *line;
|
||||
|
||||
pos = ch_zero();
|
||||
linenum = find_linenum(pos);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/*
|
||||
* 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);
|
||||
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);
|
||||
|
||||
/*
|
||||
* 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).
|
||||
*/
|
||||
len = 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);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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(tag, type)
|
||||
char *tag; /* tag to load */
|
||||
int type; /* tags type */
|
||||
{
|
||||
char buf[256];
|
||||
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 = "tags";
|
||||
} else
|
||||
{
|
||||
#if !HAVE_POPEN
|
||||
return TAG_NOFILE;
|
||||
#else
|
||||
char *command;
|
||||
char *flag;
|
||||
char *qtag;
|
||||
char *cmd = lgetenv("LESSGLOBALTAGS");
|
||||
|
||||
if (cmd == NULL || *cmd == '\0')
|
||||
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;
|
||||
size_t len;
|
||||
|
||||
if (sigs)
|
||||
{
|
||||
#if HAVE_POPEN
|
||||
if (fp != stdin)
|
||||
pclose(fp);
|
||||
#endif
|
||||
return TAG_INTR;
|
||||
}
|
||||
len = 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()
|
||||
{
|
||||
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()
|
||||
{
|
||||
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()
|
||||
{
|
||||
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(buf, tag, file, line)
|
||||
char *buf; /* standard or extended ctags -x format data */
|
||||
char **tag; /* name of the tag we actually found */
|
||||
char **file; /* file in which to find this tag */
|
||||
char **line; /* line number of file where this tag is found */
|
||||
{
|
||||
char *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
|
||||
178
commands/less/less/ttyin.c
Normal file
178
commands/less/less/ttyin.c
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (C) 1984-2004 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 about less, or for information on how to
|
||||
* contact the author, 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
|
||||
#include "windows.h"
|
||||
extern char WIN32getch();
|
||||
static DWORD console_mode;
|
||||
#endif
|
||||
|
||||
public int tty;
|
||||
extern int sigs;
|
||||
extern int utf_mode;
|
||||
|
||||
/*
|
||||
* Open keyboard for input.
|
||||
*/
|
||||
public void
|
||||
open_getchr()
|
||||
{
|
||||
#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 = (int) CreateFile("CONIN$", GENERIC_READ,
|
||||
FILE_SHARE_READ, &sa,
|
||||
OPEN_EXISTING, 0L, NULL);
|
||||
GetConsoleMode((HANDLE)tty, &console_mode);
|
||||
/* Make sure we get Ctrl+C events. */
|
||||
SetConsoleMode((HANDLE)tty, ENABLE_PROCESSED_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
|
||||
/*
|
||||
* Try /dev/tty.
|
||||
* If that doesn't work, use file descriptor 2,
|
||||
* which in Unix is usually attached to the screen,
|
||||
* but also usually lets you read from the keyboard.
|
||||
*/
|
||||
#if OS2
|
||||
/* The __open() system call translates "/dev/tty" to "con". */
|
||||
tty = __open("/dev/tty", OPEN_READ);
|
||||
#else
|
||||
tty = open("/dev/tty", OPEN_READ);
|
||||
#endif
|
||||
if (tty < 0)
|
||||
tty = 2;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Close the keyboard.
|
||||
*/
|
||||
public void
|
||||
close_getchr()
|
||||
{
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
SetConsoleMode((HANDLE)tty, console_mode);
|
||||
CloseHandle((HANDLE)tty);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a character from the keyboard.
|
||||
*/
|
||||
public int
|
||||
getchr()
|
||||
{
|
||||
char c;
|
||||
int result;
|
||||
#if 0
|
||||
int hex_in = 0;
|
||||
int hex_value = 0;
|
||||
#endif
|
||||
|
||||
do
|
||||
{
|
||||
#if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
|
||||
/*
|
||||
* In raw read, we don't see ^C so look here for it.
|
||||
*/
|
||||
flush();
|
||||
#if MSDOS_COMPILER==WIN32C
|
||||
if (ABORT_SIGS())
|
||||
return (READ_INTR);
|
||||
c = WIN32getch(tty);
|
||||
#else
|
||||
c = getch();
|
||||
#endif
|
||||
result = 1;
|
||||
if (c == '\003')
|
||||
return (READ_INTR);
|
||||
#else
|
||||
result = iread(tty, &c, sizeof(char));
|
||||
if (result == READ_INTR)
|
||||
return (READ_INTR);
|
||||
if (result < 0)
|
||||
{
|
||||
/*
|
||||
* Don't call error() here,
|
||||
* because error calls getchr!
|
||||
*/
|
||||
quit(QUIT_ERROR);
|
||||
}
|
||||
#endif
|
||||
#if 0 /* allow entering arbitrary hex chars for testing */
|
||||
/* ctrl-A followed by two hex chars makes a byte */
|
||||
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
|
||||
hex_in = 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);
|
||||
}
|
||||
675
commands/less/less/version.c
Normal file
675
commands/less/less/version.c
Normal file
@@ -0,0 +1,675 @@
|
||||
/* $NetBSD: version.c,v 1.6 2006/10/26 01:33:08 mrg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1984-2005 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 about less, or for information on how to
|
||||
* contact the author, 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.
|
||||
*/
|
||||
|
||||
char version[] = "394";
|
||||
100
commands/less/less2netbsd
Executable file
100
commands/less/less2netbsd
Executable file
@@ -0,0 +1,100 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# $NetBSD: less2netbsd,v 1.8 2008/05/29 14:51:27 mrg Exp $
|
||||
#
|
||||
# Copyright (c) 1996, 2003 Matthew R. Green
|
||||
# All rights reserved.
|
||||
#
|
||||
# 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, this list of conditions and the following disclaimer 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.
|
||||
|
||||
# less2netbsd: convert a less source tree into a netbsd less source
|
||||
# tree, under src/usr.bin/less ready for importing. note that you need
|
||||
# to run ./configure to generate defines.h (a bug in less 381's configure
|
||||
# wrongly does not find sigset_t on NetBSD; correct this in defines.h.)
|
||||
|
||||
if [ $# -ne 2 ]; then echo "less2netbsd src dest"; exit 1; fi
|
||||
|
||||
r=$1
|
||||
d=$2/less
|
||||
|
||||
case "$d" in
|
||||
/*)
|
||||
;;
|
||||
*)
|
||||
d=`/bin/pwd`/$d
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$r" in
|
||||
/*)
|
||||
;;
|
||||
*)
|
||||
r=`/bin/pwd`/$r
|
||||
;;
|
||||
esac
|
||||
|
||||
echo preparing directory $d
|
||||
rm -rf $d
|
||||
mkdir -p $d; cd $d
|
||||
mkdir -p src/usr.bin/less/less src/usr.bin/less/lesskey src/usr.bin/less/lessecho
|
||||
|
||||
### start less ###############################
|
||||
cd $r
|
||||
echo less:
|
||||
src="main.c screen.c brac.c ch.c charset.c cmdbuf.c command.c decode.c edit.c filename.c forwback.c help.c ifile.c input.c jump.c line.c linenum.c lsystem.c mark.c optfunc.c option.c opttbl.c os.c output.c position.c prompt.c search.c signal.c tags.c ttyin.c version.c"
|
||||
src="$src charset.h cmd.h defines.h funcs.h less.h lesskey.h lglob.h option.h pckeys.h position.h regexp.h"
|
||||
src="$src INSTALL LICENSE NEWS README less.nro"
|
||||
|
||||
pax -rvw $src $d/src/usr.bin/less/less
|
||||
|
||||
cd $d/src/usr.bin/less/less
|
||||
mv less.nro less.1
|
||||
|
||||
### end less ###############################
|
||||
|
||||
### start lesskey ###############################
|
||||
cd $r
|
||||
echo lesskey:
|
||||
src='lesskey.c lesskey.h lesskey.nro'
|
||||
|
||||
pax -rvw $src $d/src/usr.bin/less/lesskey
|
||||
|
||||
cd $d/src/usr.bin/less/lesskey
|
||||
mv lesskey.nro lesskey.1
|
||||
|
||||
### end lesskey ###############################
|
||||
|
||||
### start lessecho ###############################
|
||||
cd $r
|
||||
echo lessecho:
|
||||
src='lessecho.c'
|
||||
|
||||
pax -rvw $src $d/src/usr.bin/less/lessecho
|
||||
|
||||
### end lesskey ###############################
|
||||
|
||||
find $d -name '*.[ch]' -print | while read c; do
|
||||
chmod u+w $c
|
||||
done
|
||||
|
||||
echo done
|
||||
exit 0
|
||||
10
commands/less/lessecho/Makefile
Normal file
10
commands/less/lessecho/Makefile
Normal file
@@ -0,0 +1,10 @@
|
||||
# $NetBSD: Makefile,v 1.3 2002/09/18 14:00:38 lukem Exp $
|
||||
|
||||
NOMAN= # defined
|
||||
|
||||
PROG= lessecho
|
||||
SRCS= lessecho.c version.c
|
||||
CPPFLAGS+=-I${.CURDIR}/../less
|
||||
.PATH: ${.CURDIR}/../less
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
279
commands/less/lessecho/lessecho.c
Normal file
279
commands/less/lessecho/lessecho.c
Normal file
@@ -0,0 +1,279 @@
|
||||
/* $NetBSD: lessecho.c,v 1.6 2006/10/26 01:33:08 mrg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1984-2004 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 about less, or for information on how to
|
||||
* contact the author, 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.6 $";
|
||||
|
||||
static int quote_all = 0;
|
||||
static char openquote = '"';
|
||||
static char closequote = '"';
|
||||
static char *meta_escape = "\\";
|
||||
static char meta_escape_buf[2];
|
||||
static char metachars[64] = "";
|
||||
static int num_metachars = 0;
|
||||
|
||||
static void pr_usage __P((void));
|
||||
static void pr_version __P((void));
|
||||
static void pr_error __P((char *));
|
||||
static long lstrtol __P((char *, int, char **));
|
||||
|
||||
static void
|
||||
pr_usage()
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: lessecho [-ox] [-cx] [-pn] [-dn] [-mx] [-nn] [-ex] [-fn] [-a] file ...\n");
|
||||
}
|
||||
|
||||
static void
|
||||
pr_version()
|
||||
{
|
||||
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(s)
|
||||
char *s;
|
||||
{
|
||||
fprintf(stderr, "%s\n", s);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static long
|
||||
lstrtol(s, radix, pend)
|
||||
char *s;
|
||||
int radix;
|
||||
char **pend;
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
#if !HAVE_STRCHR
|
||||
char *
|
||||
strchr(s, c)
|
||||
char *s;
|
||||
int c;
|
||||
{
|
||||
for ( ; *s != '\0'; s++)
|
||||
if (*s == c)
|
||||
return (s);
|
||||
if (c == '\0')
|
||||
return (s);
|
||||
return (NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
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, 0, &s);
|
||||
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, 0, &s);
|
||||
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, 0, &s);
|
||||
if (s == arg)
|
||||
pr_error("Missing number after -p");
|
||||
break;
|
||||
case 'm':
|
||||
metachars[num_metachars++] = *++arg;
|
||||
metachars[num_metachars] = '\0';
|
||||
break;
|
||||
case 'n':
|
||||
metachars[num_metachars++] = lstrtol(++arg, 0, &s);
|
||||
if (s == arg)
|
||||
pr_error("Missing number after -n");
|
||||
metachars[num_metachars] = '\0';
|
||||
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 (strchr(metachars, *s) != NULL)
|
||||
{
|
||||
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 (strchr(metachars, *s) != NULL)
|
||||
printf("%s", meta_escape);
|
||||
printf("%c", *s);
|
||||
}
|
||||
}
|
||||
if (argc > 0)
|
||||
printf(" ");
|
||||
else
|
||||
printf("\n");
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
9
commands/less/lesskey/Makefile
Normal file
9
commands/less/lesskey/Makefile
Normal file
@@ -0,0 +1,9 @@
|
||||
# $NetBSD: Makefile,v 1.5 1997/10/24 09:00:39 lukem Exp $
|
||||
|
||||
PROG= lesskey
|
||||
SRCS= lesskey.c version.c
|
||||
CPPFLAGS+=-I${.CURDIR}/../less
|
||||
|
||||
.PATH: ${.CURDIR}/../less
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
386
commands/less/lesskey/lesskey.1
Normal file
386
commands/less/lesskey/lesskey.1
Normal file
@@ -0,0 +1,386 @@
|
||||
.\" $NetBSD: lesskey.1,v 1.9 2006/10/26 01:33:08 mrg Exp $
|
||||
.\"
|
||||
.TH LESSKEY 1 "Version 394: 03 Dec 2005"
|
||||
.SH NAME
|
||||
lesskey \- specify key bindings for less
|
||||
.SH SYNOPSIS
|
||||
.B "lesskey [-o output] [--] [input]"
|
||||
.br
|
||||
.B "lesskey [--output=output] [--] [input]"
|
||||
.br
|
||||
.B "lesskey -V"
|
||||
.br
|
||||
.B "lesskey --version"
|
||||
.SH DESCRIPTION
|
||||
.I Lesskey
|
||||
is used to specify a set of key bindings to be used by
|
||||
.I less.
|
||||
The input file is a text file which describes the key bindings,
|
||||
If the input file is "-", standard input is read.
|
||||
If no input file is specified, a standard filename is used
|
||||
as the name of the input file, which depends on the system being used:
|
||||
On Unix systems, $HOME/.lesskey is used;
|
||||
on MS-DOS systems, $HOME/_lesskey is used;
|
||||
and on OS/2 systems $HOME/lesskey.ini is used,
|
||||
or $INIT/lesskey.ini if $HOME is undefined.
|
||||
The output file is a binary file which is used by
|
||||
.I less.
|
||||
If no output file is specified,
|
||||
and the environment variable LESSKEY is set,
|
||||
the value of LESSKEY is used as the name of the output file.
|
||||
Otherwise, a standard filename is used as the name of the output file,
|
||||
which depends on the system being used:
|
||||
On Unix and OS-9 systems, $HOME/.less is used;
|
||||
on MS-DOS systems, $HOME/_less is used;
|
||||
and on OS/2 systems, $HOME/less.ini is used,
|
||||
or $INIT/less.ini if $HOME is undefined.
|
||||
If the output file already exists,
|
||||
.I lesskey
|
||||
will overwrite it.
|
||||
.PP
|
||||
The -V or --version option causes
|
||||
.I lesskey
|
||||
to print its version number and immediately exit.
|
||||
If -V or --version is present, other options and arguments are ignored.
|
||||
.PP
|
||||
The input file consists of one or more
|
||||
.I sections.
|
||||
Each section starts with a line that identifies the type of section.
|
||||
Possible sections are:
|
||||
.IP #command
|
||||
Defines new command keys.
|
||||
.IP #line-edit
|
||||
Defines new line-editing keys.
|
||||
.IP #env
|
||||
Defines environment variables.
|
||||
.PP
|
||||
Blank lines and lines which start with a pound sign (#) are ignored,
|
||||
except for the special section header lines.
|
||||
|
||||
.SH "COMMAND SECTION"
|
||||
The command section begins with the line
|
||||
.sp
|
||||
#command
|
||||
.sp
|
||||
If the command section is the first section in the file,
|
||||
this line may be omitted.
|
||||
The command section consists of lines of the form:
|
||||
.sp
|
||||
\fIstring\fP \*[Lt]whitespace\*[Gt] \fIaction\fP [extra-string] \*[Lt]newline\*[Gt]
|
||||
.sp
|
||||
Whitespace is any sequence of one or more spaces and/or tabs.
|
||||
The \fIstring\fP is the command key(s) which invoke the action.
|
||||
The \fIstring\fP may be a single command key, or a sequence of up to 15 keys.
|
||||
The \fIaction\fP is the name of the less action, from the list below.
|
||||
The characters in the \fIstring\fP may appear literally, or be
|
||||
prefixed by a caret to indicate a control key.
|
||||
A backslash followed by one to three octal digits may be used to
|
||||
specify a character by its octal value.
|
||||
A backslash followed by certain characters specifies input
|
||||
characters as follows:
|
||||
.IP \eb
|
||||
BACKSPACE
|
||||
.IP \ee
|
||||
ESCAPE
|
||||
.IP \en
|
||||
NEWLINE
|
||||
.IP \er
|
||||
RETURN
|
||||
.IP \et
|
||||
TAB
|
||||
.IP \eku
|
||||
UP ARROW
|
||||
.IP \ekd
|
||||
DOWN ARROW
|
||||
.IP \ekr
|
||||
RIGHT ARROW
|
||||
.IP \ekl
|
||||
LEFT ARROW
|
||||
.IP \ekU
|
||||
PAGE UP
|
||||
.IP \ekD
|
||||
PAGE DOWN
|
||||
.IP \ekh
|
||||
HOME
|
||||
.IP \eke
|
||||
END
|
||||
.IP \ekx
|
||||
DELETE
|
||||
.PP
|
||||
A backslash followed by any other character indicates that character is
|
||||
to be taken literally.
|
||||
Characters which must be preceded by backslash include
|
||||
caret, space, tab and the backslash itself.
|
||||
.PP
|
||||
An action may be followed by an "extra" string.
|
||||
When such a command is entered while running
|
||||
.I less,
|
||||
the action is performed, and then the extra
|
||||
string is parsed, just as if it were typed in to
|
||||
.I less.
|
||||
This feature can be used in certain cases to extend
|
||||
the functionality of a command.
|
||||
For example, see the "{" and ":t" commands in the example below.
|
||||
The extra string has a special meaning for the "quit" action:
|
||||
when
|
||||
.I less
|
||||
quits, first character of the extra string is used as its exit status.
|
||||
|
||||
.SH EXAMPLE
|
||||
The following input file describes the set of
|
||||
default command keys used by less:
|
||||
.sp
|
||||
.nf
|
||||
#command
|
||||
\er forw-line
|
||||
\en forw-line
|
||||
e forw-line
|
||||
j forw-line
|
||||
\ekd forw-line
|
||||
^E forw-line
|
||||
^N forw-line
|
||||
k back-line
|
||||
y back-line
|
||||
^Y back-line
|
||||
^K back-line
|
||||
^P back-line
|
||||
J forw-line-force
|
||||
K back-line-force
|
||||
Y back-line-force
|
||||
d forw-scroll
|
||||
^D forw-scroll
|
||||
u back-scroll
|
||||
^U back-scroll
|
||||
\e40 forw-screen
|
||||
f forw-screen
|
||||
^F forw-screen
|
||||
^V forw-screen
|
||||
\ekD forw-screen
|
||||
b back-screen
|
||||
^B back-screen
|
||||
\eev back-screen
|
||||
\ekU back-screen
|
||||
z forw-window
|
||||
w back-window
|
||||
\ee\e40 forw-screen-force
|
||||
F forw-forever
|
||||
R repaint-flush
|
||||
r repaint
|
||||
^R repaint
|
||||
^L repaint
|
||||
\eeu undo-hilite
|
||||
g goto-line
|
||||
\ekh goto-line
|
||||
\*[Lt] goto-line
|
||||
\ee\*[Lt] goto-line
|
||||
p percent
|
||||
% percent
|
||||
\ee[ left-scroll
|
||||
\ee] right-scroll
|
||||
\ee( left-scroll
|
||||
\ee) right-scroll
|
||||
{ forw-bracket {}
|
||||
} back-bracket {}
|
||||
( forw-bracket ()
|
||||
) back-bracket ()
|
||||
[ forw-bracket []
|
||||
] back-bracket []
|
||||
\ee^F forw-bracket
|
||||
\ee^B back-bracket
|
||||
G goto-end
|
||||
\ee\*[Gt] goto-end
|
||||
\*[Gt] goto-end
|
||||
\eke goto-end
|
||||
= status
|
||||
^G status
|
||||
:f status
|
||||
/ forw-search
|
||||
? back-search
|
||||
\ee/ forw-search *
|
||||
\ee? back-search *
|
||||
n repeat-search
|
||||
\een repeat-search-all
|
||||
N reverse-search
|
||||
\eeN reverse-search-all
|
||||
m set-mark
|
||||
' goto-mark
|
||||
^X^X goto-mark
|
||||
E examine
|
||||
:e examine
|
||||
^X^V examine
|
||||
:n next-file
|
||||
:p prev-file
|
||||
t next-tag
|
||||
T prev-tag
|
||||
:x index-file
|
||||
:d remove-file
|
||||
- toggle-option
|
||||
:t toggle-option t
|
||||
s toggle-option o
|
||||
_ display-option
|
||||
| pipe
|
||||
v visual
|
||||
! shell
|
||||
+ firstcmd
|
||||
H help
|
||||
h help
|
||||
V version
|
||||
0 digit
|
||||
1 digit
|
||||
2 digit
|
||||
3 digit
|
||||
4 digit
|
||||
5 digit
|
||||
6 digit
|
||||
7 digit
|
||||
8 digit
|
||||
9 digit
|
||||
q quit
|
||||
Q quit
|
||||
:q quit
|
||||
:Q quit
|
||||
ZZ quit
|
||||
.fi
|
||||
.sp
|
||||
.SH PRECEDENCE
|
||||
Commands specified by
|
||||
.I lesskey
|
||||
take precedence over the default commands.
|
||||
A default command key may be disabled by including it in the
|
||||
input file with the action "invalid".
|
||||
Alternatively, a key may be defined
|
||||
to do nothing by using the action "noaction".
|
||||
"noaction" is similar to "invalid", but
|
||||
.I less
|
||||
will give an error beep for an "invalid" command,
|
||||
but not for a "noaction" command.
|
||||
In addition, ALL default commands may be disabled by
|
||||
adding this control line to the input file:
|
||||
.sp
|
||||
#stop
|
||||
.sp
|
||||
This will cause all default commands to be ignored.
|
||||
The #stop line should be the last line in that section of the file.
|
||||
.PP
|
||||
Be aware that #stop can be dangerous.
|
||||
Since all default commands are disabled,
|
||||
you must provide sufficient commands before the #stop line
|
||||
to enable all necessary actions.
|
||||
For example, failure to provide a "quit" command can lead to frustration.
|
||||
|
||||
.SH "LINE EDITING SECTION"
|
||||
The line-editing section begins with the line:
|
||||
.sp
|
||||
#line-edit
|
||||
.sp
|
||||
This section specifies new key bindings for the line editing commands,
|
||||
in a manner similar to the way key bindings for
|
||||
ordinary commands are specified in the #command section.
|
||||
The line-editing section consists of a list of keys and actions,
|
||||
one per line as in the example below.
|
||||
|
||||
.SH EXAMPLE
|
||||
The following input file describes the set of
|
||||
default line-editing keys used by less:
|
||||
.sp
|
||||
.nf
|
||||
#line-edit
|
||||
\et forw-complete
|
||||
\e17 back-complete
|
||||
\ee\et back-complete
|
||||
^L expand
|
||||
^V literal
|
||||
^A literal
|
||||
\eel right
|
||||
\ekr right
|
||||
\eeh left
|
||||
\ekl left
|
||||
\eeb word-left
|
||||
\ee\ekl word-left
|
||||
\eew word-right
|
||||
\ee\ekr word-right
|
||||
\eei insert
|
||||
\eex delete
|
||||
\ekx delete
|
||||
\eeX word-delete
|
||||
\eekx word-delete
|
||||
\ee\eb word-backspace
|
||||
\ee0 home
|
||||
\ekh home
|
||||
\ee$ end
|
||||
\eke end
|
||||
\eek up
|
||||
\eku up
|
||||
\eej down
|
||||
.fi
|
||||
.sp
|
||||
|
||||
.SH "LESS ENVIRONMENT VARIABLES"
|
||||
The environment variable section begins with the line
|
||||
.sp
|
||||
#env
|
||||
.sp
|
||||
Following this line is a list of environment variable assignments.
|
||||
Each line consists of an environment variable name, an equals sign (=)
|
||||
and the value to be assigned to the environment variable.
|
||||
White space before and after the equals sign is ignored.
|
||||
Variables assigned in this way are visible only to
|
||||
.I less.
|
||||
If a variable is specified in the system environment and also in a
|
||||
lesskey file, the value in the lesskey file takes precedence.
|
||||
Although the lesskey file can be used to override variables set in the
|
||||
environment, the main purpose of assigning variables in the lesskey file
|
||||
is simply to have all
|
||||
.I less
|
||||
configuration information stored in one file.
|
||||
|
||||
.SH EXAMPLE
|
||||
The following input file sets the -i option whenever
|
||||
.I less
|
||||
is run, and specifies the character set to be "latin1":
|
||||
.sp
|
||||
.nf
|
||||
#env
|
||||
LESS = -i
|
||||
LESSCHARSET = latin1
|
||||
.fi
|
||||
.sp
|
||||
|
||||
.SH "SEE ALSO"
|
||||
less(1)
|
||||
|
||||
.SH WARNINGS
|
||||
It is not possible to specify special keys, such as uparrow,
|
||||
in a keyboard-independent manner.
|
||||
The only way to specify such keys is to specify the escape sequence
|
||||
which a particular keyboard sends when such a key is pressed.
|
||||
.PP
|
||||
On MS-DOS and OS/2 systems, certain keys send a sequence of characters
|
||||
which start with a NUL character (0).
|
||||
This NUL character should be represented as \e340 in a lesskey file.
|
||||
|
||||
.SH COPYRIGHT
|
||||
Copyright (C) 2004 Mark Nudelman
|
||||
.PP
|
||||
lesskey is part of the GNU project and is free software;
|
||||
you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation;
|
||||
either version 2, or (at your option) any later version.
|
||||
.PP
|
||||
lesskey is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
.PP
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with lesskey; see the file COPYING.
|
||||
If not, write to the Free Software Foundation, 59 Temple Place,
|
||||
Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
.SH AUTHOR
|
||||
.PP
|
||||
Mark Nudelman \*[Lt]markn@greenwoodsoftware.com\*[Gt]
|
||||
.br
|
||||
Send bug reports or comments to the above address or to bug-less@gnu.org.
|
||||
|
||||
875
commands/less/lesskey/lesskey.c
Normal file
875
commands/less/lesskey/lesskey.c
Normal file
@@ -0,0 +1,875 @@
|
||||
/* $NetBSD: lesskey.c,v 1.9 2006/10/26 01:33:08 mrg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1984-2004 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 about less, or for information on how to
|
||||
* contact the author, 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 "less.h"
|
||||
#include "lesskey.h"
|
||||
#include "cmd.h"
|
||||
|
||||
struct cmdname
|
||||
{
|
||||
char *cn_name;
|
||||
int cn_action;
|
||||
};
|
||||
|
||||
struct cmdname cmdnames[] =
|
||||
{
|
||||
{ "back-bracket", A_B_BRACKET },
|
||||
{ "back-line", A_B_LINE },
|
||||
{ "back-line-force", A_BF_LINE },
|
||||
{ "back-screen", A_B_SCREEN },
|
||||
{ "back-scroll", A_B_SCROLL },
|
||||
{ "back-search", A_B_SEARCH },
|
||||
{ "back-window", A_B_WINDOW },
|
||||
{ "debug", A_DEBUG },
|
||||
{ "digit", A_DIGIT },
|
||||
{ "display-flag", A_DISP_OPTION },
|
||||
{ "display-option", A_DISP_OPTION },
|
||||
{ "end", A_GOEND },
|
||||
{ "examine", A_EXAMINE },
|
||||
{ "first-cmd", A_FIRSTCMD },
|
||||
{ "firstcmd", A_FIRSTCMD },
|
||||
{ "flush-repaint", A_FREPAINT },
|
||||
{ "forw-bracket", A_F_BRACKET },
|
||||
{ "forw-forever", A_F_FOREVER },
|
||||
{ "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-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 },
|
||||
{ "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 },
|
||||
{ "shell", A_SHELL },
|
||||
{ "status", A_STAT },
|
||||
{ "toggle-flag", A_OPT_TOGGLE },
|
||||
{ "toggle-option", A_OPT_TOGGLE },
|
||||
{ "undo-hilite", A_UNDO_SEARCH },
|
||||
{ "version", A_VERSION },
|
||||
{ "visual", A_VISUAL },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
struct cmdname editnames[] =
|
||||
{
|
||||
{ "back-complete", EC_B_COMPLETE },
|
||||
{ "backspace", EC_BACKSPACE },
|
||||
{ "delete", EC_DELETE },
|
||||
{ "down", EC_DOWN },
|
||||
{ "end", EC_END },
|
||||
{ "expand", EC_EXPAND },
|
||||
{ "forw-complete", EC_F_COMPLETE },
|
||||
{ "home", EC_HOME },
|
||||
{ "insert", EC_INSERT },
|
||||
{ "invalid", EC_UINVALID },
|
||||
{ "kill-line", EC_LINEKILL },
|
||||
{ "left", EC_LEFT },
|
||||
{ "literal", EC_LITERAL },
|
||||
{ "right", EC_RIGHT },
|
||||
{ "up", EC_UP },
|
||||
{ "word-backspace", EC_W_BACKSPACE },
|
||||
{ "word-delete", EC_W_DELETE },
|
||||
{ "word-left", EC_W_LEFT },
|
||||
{ "word-right", EC_W_RIGHT },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
struct table
|
||||
{
|
||||
struct cmdname *names;
|
||||
char *pbuffer;
|
||||
char buffer[MAX_USERCMD];
|
||||
};
|
||||
|
||||
struct table cmdtable;
|
||||
struct table edittable;
|
||||
struct table vartable;
|
||||
struct table *currtable = &cmdtable;
|
||||
|
||||
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 ;
|
||||
|
||||
int linenum;
|
||||
int errors;
|
||||
|
||||
void terror(char *);
|
||||
|
||||
extern char version[];
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
fprintf(stderr, "usage: lesskey [-o output] [input]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *
|
||||
mkpathname(dirname, filename)
|
||||
char *dirname;
|
||||
char *filename;
|
||||
{
|
||||
char *pathname;
|
||||
|
||||
pathname = calloc(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(filename)
|
||||
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.
|
||||
*/
|
||||
void
|
||||
parse_args(argc, argv)
|
||||
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;
|
||||
else
|
||||
infile = homefile(DEF_LESSKEYINFILE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize data structures.
|
||||
*/
|
||||
void
|
||||
init_tables()
|
||||
{
|
||||
cmdtable.names = cmdnames;
|
||||
cmdtable.pbuffer = cmdtable.buffer;
|
||||
|
||||
edittable.names = editnames;
|
||||
edittable.pbuffer = edittable.buffer;
|
||||
|
||||
vartable.names = NULL;
|
||||
vartable.pbuffer = vartable.buffer;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse one character of a string.
|
||||
*/
|
||||
char *
|
||||
tstr(pp, xlate)
|
||||
char **pp;
|
||||
int xlate;
|
||||
{
|
||||
register char *p;
|
||||
register char ch;
|
||||
register int i;
|
||||
static char buf[10];
|
||||
static char tstr_control_k[] =
|
||||
{ SK_SPECIAL_KEY, SK_CONTROL_K, 6, 1, 1, 1, '\0' };
|
||||
|
||||
p = *pp;
|
||||
switch (*p)
|
||||
{
|
||||
case '\\':
|
||||
++p;
|
||||
switch (*p)
|
||||
{
|
||||
case '0': case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
/*
|
||||
* Parse an octal number.
|
||||
*/
|
||||
ch = 0;
|
||||
i = 0;
|
||||
do
|
||||
ch = 8*ch + (*p - '0');
|
||||
while (*++p >= '0' && *p <= '7' && ++i < 3);
|
||||
*pp = p;
|
||||
if (xlate && ch == CONTROL('K'))
|
||||
return tstr_control_k;
|
||||
buf[0] = ch;
|
||||
buf[1] = '\0';
|
||||
return (buf);
|
||||
case 'b':
|
||||
*pp = p+1;
|
||||
return ("\b");
|
||||
case 'e':
|
||||
*pp = p+1;
|
||||
buf[0] = ESC;
|
||||
buf[1] = '\0';
|
||||
return (buf);
|
||||
case 'n':
|
||||
*pp = p+1;
|
||||
return ("\n");
|
||||
case 'r':
|
||||
*pp = p+1;
|
||||
return ("\r");
|
||||
case 't':
|
||||
*pp = p+1;
|
||||
return ("\t");
|
||||
case 'k':
|
||||
if (xlate)
|
||||
{
|
||||
switch (*++p)
|
||||
{
|
||||
case 'u': ch = SK_UP_ARROW; break;
|
||||
case 'd': ch = SK_DOWN_ARROW; break;
|
||||
case 'r': ch = SK_RIGHT_ARROW; break;
|
||||
case 'l': ch = SK_LEFT_ARROW; break;
|
||||
case 'U': ch = SK_PAGE_UP; break;
|
||||
case 'D': ch = SK_PAGE_DOWN; break;
|
||||
case 'h': ch = SK_HOME; break;
|
||||
case 'e': ch = SK_END; break;
|
||||
case 'x': ch = SK_DELETE; break;
|
||||
default:
|
||||
terror("illegal char after \\k");
|
||||
*pp = p+1;
|
||||
return ("");
|
||||
}
|
||||
*pp = p+1;
|
||||
buf[0] = SK_SPECIAL_KEY;
|
||||
buf[1] = ch;
|
||||
buf[2] = 6;
|
||||
buf[3] = 1;
|
||||
buf[4] = 1;
|
||||
buf[5] = 1;
|
||||
buf[6] = '\0';
|
||||
return (buf);
|
||||
}
|
||||
/* FALLTHRU */
|
||||
default:
|
||||
/*
|
||||
* Backslash followed by any other char
|
||||
* just means that char.
|
||||
*/
|
||||
*pp = p+1;
|
||||
buf[0] = *p;
|
||||
buf[1] = '\0';
|
||||
if (xlate && buf[0] == CONTROL('K'))
|
||||
return tstr_control_k;
|
||||
return (buf);
|
||||
}
|
||||
case '^':
|
||||
/*
|
||||
* Carat means CONTROL.
|
||||
*/
|
||||
*pp = p+2;
|
||||
buf[0] = CONTROL(p[1]);
|
||||
buf[1] = '\0';
|
||||
if (buf[0] == CONTROL('K'))
|
||||
return tstr_control_k;
|
||||
return (buf);
|
||||
}
|
||||
*pp = p+1;
|
||||
buf[0] = *p;
|
||||
buf[1] = '\0';
|
||||
if (xlate && buf[0] == CONTROL('K'))
|
||||
return tstr_control_k;
|
||||
return (buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip leading spaces in a string.
|
||||
*/
|
||||
public char *
|
||||
skipsp(s)
|
||||
register char *s;
|
||||
{
|
||||
while (*s == ' ' || *s == '\t')
|
||||
s++;
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip non-space characters in a string.
|
||||
*/
|
||||
public char *
|
||||
skipnsp(s)
|
||||
register char *s;
|
||||
{
|
||||
while (*s != '\0' && *s != ' ' && *s != '\t')
|
||||
s++;
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up an input line:
|
||||
* strip off the trailing newline & any trailing # comment.
|
||||
*/
|
||||
char *
|
||||
clean_line(s)
|
||||
char *s;
|
||||
{
|
||||
register int i;
|
||||
|
||||
s = skipsp(s);
|
||||
for (i = 0; s[i] != '\n' && s[i] != '\r' && s[i] != '\0'; i++)
|
||||
if (s[i] == '#' && (i == 0 || s[i-1] != '\\'))
|
||||
break;
|
||||
s[i] = '\0';
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a byte to the output command table.
|
||||
*/
|
||||
void
|
||||
add_cmd_char(c)
|
||||
int c;
|
||||
{
|
||||
if (currtable->pbuffer >= currtable->buffer + MAX_USERCMD)
|
||||
{
|
||||
terror("too many commands");
|
||||
exit(1);
|
||||
}
|
||||
*(currtable->pbuffer)++ = c;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a string to the output command table.
|
||||
*/
|
||||
void
|
||||
add_cmd_str(s)
|
||||
char *s;
|
||||
{
|
||||
for ( ; *s != '\0'; s++)
|
||||
add_cmd_char(*s);
|
||||
}
|
||||
|
||||
/*
|
||||
* See if we have a special "control" line.
|
||||
*/
|
||||
int
|
||||
control_line(s)
|
||||
char *s;
|
||||
{
|
||||
#define PREFIX(str,pat) (strncmp(str,pat,strlen(pat)-1) == 0)
|
||||
|
||||
if (PREFIX(s, "#line-edit"))
|
||||
{
|
||||
currtable = &edittable;
|
||||
return (1);
|
||||
}
|
||||
if (PREFIX(s, "#command"))
|
||||
{
|
||||
currtable = &cmdtable;
|
||||
return (1);
|
||||
}
|
||||
if (PREFIX(s, "#env"))
|
||||
{
|
||||
currtable = &vartable;
|
||||
return (1);
|
||||
}
|
||||
if (PREFIX(s, "#stop"))
|
||||
{
|
||||
add_cmd_char('\0');
|
||||
add_cmd_char(A_END_LIST);
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Output some bytes.
|
||||
*/
|
||||
void
|
||||
fputbytes(fd, buf, len)
|
||||
FILE *fd;
|
||||
char *buf;
|
||||
int len;
|
||||
{
|
||||
while (len-- > 0)
|
||||
{
|
||||
fwrite(buf, sizeof(char), 1, fd);
|
||||
buf++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Output an integer, in special KRADIX form.
|
||||
*/
|
||||
void
|
||||
fputint(fd, val)
|
||||
FILE *fd;
|
||||
unsigned int val;
|
||||
{
|
||||
char c;
|
||||
|
||||
if (val >= KRADIX*KRADIX)
|
||||
{
|
||||
fprintf(stderr, "error: integer too big (%d > %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);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find an action, given the name of the action.
|
||||
*/
|
||||
int
|
||||
findaction(actname)
|
||||
char *actname;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; currtable->names[i].cn_name != NULL; i++)
|
||||
if (strcmp(currtable->names[i].cn_name, actname) == 0)
|
||||
return (currtable->names[i].cn_action);
|
||||
terror("unknown action");
|
||||
return (A_INVALID);
|
||||
}
|
||||
|
||||
void
|
||||
terror(s)
|
||||
char *s;
|
||||
{
|
||||
fprintf(stderr, "line %d: %s\n", linenum, s);
|
||||
errors++;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
parse_cmdline(p)
|
||||
char *p;
|
||||
{
|
||||
int cmdlen;
|
||||
char *actname;
|
||||
int action;
|
||||
char *s;
|
||||
char c;
|
||||
|
||||
/*
|
||||
* Parse the command string and store it in the current table.
|
||||
*/
|
||||
cmdlen = 0;
|
||||
do
|
||||
{
|
||||
s = tstr(&p, 1);
|
||||
cmdlen += strlen(s);
|
||||
if (cmdlen > MAX_CMDLEN)
|
||||
terror("command too long");
|
||||
else
|
||||
add_cmd_str(s);
|
||||
} while (*p != ' ' && *p != '\t' && *p != '\0');
|
||||
/*
|
||||
* Terminate the command string with a null byte.
|
||||
*/
|
||||
add_cmd_char('\0');
|
||||
|
||||
/*
|
||||
* Skip white space between the command string
|
||||
* and the action name.
|
||||
* Terminate the action name with a null byte.
|
||||
*/
|
||||
p = skipsp(p);
|
||||
if (*p == '\0')
|
||||
{
|
||||
terror("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);
|
||||
|
||||
/*
|
||||
* See if an extra string follows the action name.
|
||||
*/
|
||||
*p = c;
|
||||
p = skipsp(p);
|
||||
if (*p == '\0')
|
||||
{
|
||||
add_cmd_char(action);
|
||||
} else
|
||||
{
|
||||
/*
|
||||
* OR the special value A_EXTRA into the action byte.
|
||||
* Put the extra string after the action byte.
|
||||
*/
|
||||
add_cmd_char(action | A_EXTRA);
|
||||
while (*p != '\0')
|
||||
add_cmd_str(tstr(&p, 0));
|
||||
add_cmd_char('\0');
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
parse_varline(p)
|
||||
char *p;
|
||||
{
|
||||
char *s;
|
||||
|
||||
do
|
||||
{
|
||||
s = tstr(&p, 0);
|
||||
add_cmd_str(s);
|
||||
} while (*p != ' ' && *p != '\t' && *p != '=' && *p != '\0');
|
||||
/*
|
||||
* Terminate the variable name with a null byte.
|
||||
*/
|
||||
add_cmd_char('\0');
|
||||
|
||||
p = skipsp(p);
|
||||
if (*p++ != '=')
|
||||
{
|
||||
terror("missing =");
|
||||
return;
|
||||
}
|
||||
|
||||
add_cmd_char(EV_OK|A_EXTRA);
|
||||
|
||||
p = skipsp(p);
|
||||
while (*p != '\0')
|
||||
{
|
||||
s = tstr(&p, 0);
|
||||
add_cmd_str(s);
|
||||
}
|
||||
add_cmd_char('\0');
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a line from the lesskey file.
|
||||
*/
|
||||
void
|
||||
parse_line(line)
|
||||
char *line;
|
||||
{
|
||||
char *p;
|
||||
|
||||
/*
|
||||
* See if it is a control line.
|
||||
*/
|
||||
if (control_line(line))
|
||||
return;
|
||||
/*
|
||||
* Skip leading white space.
|
||||
* Replace the final newline with a null byte.
|
||||
* Ignore blank lines and comments.
|
||||
*/
|
||||
p = clean_line(line);
|
||||
if (*p == '\0')
|
||||
return;
|
||||
|
||||
if (currtable == &vartable)
|
||||
parse_varline(p);
|
||||
else
|
||||
parse_cmdline(p);
|
||||
}
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
FILE *desc;
|
||||
FILE *out;
|
||||
char line[1024];
|
||||
|
||||
#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 *) calloc(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);
|
||||
init_tables();
|
||||
|
||||
/*
|
||||
* Open the input file.
|
||||
*/
|
||||
if (strcmp(infile, "-") == 0)
|
||||
desc = stdin;
|
||||
else if ((desc = fopen(infile, "r")) == NULL)
|
||||
{
|
||||
#if HAVE_PERROR
|
||||
perror(infile);
|
||||
#else
|
||||
fprintf(stderr, "Cannot open %s\n", infile);
|
||||
#endif
|
||||
usage();
|
||||
}
|
||||
|
||||
/*
|
||||
* Read and parse the input file, one line at a time.
|
||||
*/
|
||||
errors = 0;
|
||||
linenum = 0;
|
||||
while (fgets(line, sizeof(line), desc) != NULL)
|
||||
{
|
||||
++linenum;
|
||||
parse_line(line);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the output file.
|
||||
* If no output file was specified, use "$HOME/.less"
|
||||
*/
|
||||
if (errors > 0)
|
||||
{
|
||||
fprintf(stderr, "%d errors; no output produced\n", errors);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (outfile == NULL)
|
||||
outfile = getenv("LESSKEY");
|
||||
if (outfile == NULL)
|
||||
outfile = homefile(LESSKEYFILE);
|
||||
if ((out = fopen(outfile, "wb")) == NULL)
|
||||
{
|
||||
#if HAVE_PERROR
|
||||
perror(outfile);
|
||||
#else
|
||||
fprintf(stderr, "Cannot open %s\n", outfile);
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* File header */
|
||||
fputbytes(out, fileheader, sizeof(fileheader));
|
||||
|
||||
/* Command key section */
|
||||
fputbytes(out, cmdsection, sizeof(cmdsection));
|
||||
fputint(out, cmdtable.pbuffer - cmdtable.buffer);
|
||||
fputbytes(out, (char *)cmdtable.buffer, cmdtable.pbuffer-cmdtable.buffer);
|
||||
/* Edit key section */
|
||||
fputbytes(out, editsection, sizeof(editsection));
|
||||
fputint(out, edittable.pbuffer - edittable.buffer);
|
||||
fputbytes(out, (char *)edittable.buffer, edittable.pbuffer-edittable.buffer);
|
||||
|
||||
/* Environment variable section */
|
||||
fputbytes(out, varsection, sizeof(varsection));
|
||||
fputint(out, vartable.pbuffer - vartable.buffer);
|
||||
fputbytes(out, (char *)vartable.buffer, vartable.pbuffer-vartable.buffer);
|
||||
|
||||
/* File trailer */
|
||||
fputbytes(out, endsection, sizeof(endsection));
|
||||
fputbytes(out, filetrailer, sizeof(filetrailer));
|
||||
return (0);
|
||||
}
|
||||
40
commands/less/lesskey/lesskey.h
Normal file
40
commands/less/lesskey/lesskey.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 1984-2004 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 about less, or for information on how to
|
||||
* contact the author, see the README file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* 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
|
||||
Reference in New Issue
Block a user