Termcap update, replacing elvis by nvi.
Removing elvis, importing nvi, ctags, updating libedit. Change-Id: I881eb04d2dc64cf112facd992de1114e1a59107f
This commit is contained in:
parent
f9f6c9251a
commit
3e1db26a5a
491 changed files with 192709 additions and 28905 deletions
|
@ -8,7 +8,7 @@ SUBDIR= add_route arp ash at backup banner basename btrace cal \
|
|||
comm compress cp crc cron crontab cut \
|
||||
dd decomp16 DESCRIBE devmand devsize df dhcpd \
|
||||
dhrystone diff dirname diskctl dumpcore \
|
||||
eject elvis env expand factor fbdctl \
|
||||
eject env expand factor fbdctl \
|
||||
find finger fingerd fix fold format fortune fsck.mfs \
|
||||
ftp101 gcore gcov-pull getty grep head hexdump host \
|
||||
hostaddr id ifconfig ifdef \
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
Lightweight vi
|
File diff suppressed because it is too large
Load diff
|
@ -1,68 +0,0 @@
|
|||
The following options are missing:
|
||||
[no]optimize - affects screen redrawing method
|
||||
[no]redraw - simulate character insertion by redrawing line
|
||||
[no]slowopen - don't use character insertion
|
||||
tags="tags" - list of tags, used as TAGPATH
|
||||
|
||||
I'd like to improve the versatility of the options whose value is a command:
|
||||
cc, make, kp, and ep. I'd like to add some notation that allows you to say
|
||||
where to insert the current filename or current word.
|
||||
-------------------------------------------------------------------------------
|
||||
Currently, elvis is configured to look for | only in .exrc files. It doesn't
|
||||
look for | in any interactively entered command lines, yet.
|
||||
-------------------------------------------------------------------------------
|
||||
The 'p', '#', and 'l' flags aren't supported. Also, ex commands don't accept
|
||||
counts; e.g., ":c5" can't be used to change five lines.
|
||||
-------------------------------------------------------------------------------
|
||||
The following have been reported, but have not been verified. If you have
|
||||
experienced any of the following, and haven't reported it yet, then please
|
||||
report it now! I need more information about these bugs.
|
||||
|
||||
[Bugs that are not in this list should also be reported, of course.]
|
||||
|
||||
- Under VMS on an 80-column screen, after scolling sideways to approximately
|
||||
column 110, a ^L will not redraw the part of the line after the cursor.
|
||||
- On an Atari ST running under TOS: some ASCII keys seem to send '#' plus
|
||||
another key. (This is normal for non-ASCII keys like <F1> or <Help>, but
|
||||
ASCII keys should always send a single ASCII character.)
|
||||
-------------------------------------------------------------------------------
|
||||
BIG JOBS:
|
||||
Desirable extension: merge input mode and visual command mode.
|
||||
Display long lines by wrapping, like the real vi (if ":set sidescroll=0")
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
- In the ":w >>filename" command, elvis doesn't allow any whitespace between
|
||||
the ">>" and "filename".
|
||||
|
||||
- Elvis doesn't allow "backslash newline" inside a single EX command.
|
||||
|
||||
- VMS intercepts the control-T character, which is normally used to increase
|
||||
indentation. The <Tab> key works, but it doesn't do quite the same thing.
|
||||
(":map! ^I ^T" helps.)
|
||||
|
||||
- Under VMS, file I/O is very slow. Looking over the vmsio.c file, I get the
|
||||
impression that it is rather over-done for elvis. Its speed could
|
||||
probably be inproved.
|
||||
|
||||
- The errlist feature doesn't seem to work with the Borland compilers. Perhaps
|
||||
they write to stderr instead of stdout? This will probably be easy to solve
|
||||
once I modify the "cc" and "make" options, as described earlier.
|
||||
|
||||
- The command ":0" should move the cursor to line 1. Currently, it doesn't
|
||||
move the cursor at all.
|
||||
|
||||
- File preservation is still flakey. On DOS/TOS/VMS systems, it is also more
|
||||
complex that it should be.
|
||||
|
||||
- The act of appending to a cut buffer (as in "Ayy) sets file modification
|
||||
flag. It shouldn't!
|
||||
|
||||
- The .exrc file is limited to BLKSIZE bytes -- 2048 on most systems, but
|
||||
1024 on Minicx-PC, Coherent, and MS-DOS.
|
||||
|
||||
- I *still* haven't quite perfected the screen update code. If you suspect
|
||||
that the screen doesn't accurately reflect the contents of the edit buffer,
|
||||
then you should try doing a control-L.
|
||||
|
||||
I'll be overhauling the screen update code soon to make it wrap long lines
|
||||
like the real vi. I expect to fix this bug then.
|
|
@ -1,87 +0,0 @@
|
|||
# This is the Makefile for Elvis' "doc" directory. It makes use of a
|
||||
# troff-like formatter called mroff. Since you probably don't have mroff,
|
||||
# you'll need to edit this Makefile before you can fully use it. It can
|
||||
# also use nroff, though, so you should be able to get something out of it.
|
||||
#
|
||||
# make Use nroff to create an ASCII version of the manual.
|
||||
# make foo.doc Use nroff to create an ASCII version of foo.man or foo.ms
|
||||
# make manual Use MROFF to print a typeset manual on a laser printer
|
||||
# make foo.1200 Use MROFF to print a typeset version of foo.man or foo.ms
|
||||
# make foo.100 Use MROFF to print a draft-quality version of foo.man or foo.ms
|
||||
# make foo.more Use MROFF to preview foo.man or foo.more on your terminal
|
||||
#
|
||||
|
||||
###############################################################################
|
||||
# Definitions...
|
||||
|
||||
MAN= ctags.man elvis.man elvprsv.man elvrec.man fmt.man ref.man
|
||||
MS= title.ms index.ms intro.ms visual.ms ex.ms regexp.ms options.ms\
|
||||
cutbufs.ms differ.ms internal.ms cflags.ms termcap.ms environ.ms\
|
||||
versions.ms question.ms
|
||||
ASC= title.doc index.doc intro.doc visual.doc ex.doc regexp.doc options.doc\
|
||||
cutbufs.doc differ.doc internal.doc cflags.doc termcap.doc environ.doc\
|
||||
versions.doc question.doc\
|
||||
ctags.doc elvis.doc elvprsv.doc elvrec.doc fmt.doc ref.doc
|
||||
MANUAL= title.1200 index.1200 intro.1200 visual.1200 ex.1200 regexp.1200 options.1200\
|
||||
cutbufs.1200 differ.1200 internal.1200 cflags.1200 termcap.1200 environ.1200\
|
||||
versions.1200\
|
||||
ctags.1200 elvis.1200 elvprsv.1200 elvrec.1200 fmt.1200 ref.1200
|
||||
VER= ver.ms
|
||||
TROFF= mroff
|
||||
NROFF= nroff
|
||||
|
||||
###############################################################################
|
||||
# Rules...
|
||||
|
||||
.SUFFIXES: .tmp .100 .1200 .more .doc .man .ms .vga .vgas
|
||||
|
||||
.ms.tmp:
|
||||
$(TROFF) -ms $(VER) $< >tmp
|
||||
|
||||
.man.tmp:
|
||||
$(TROFF) -man $< >tmp
|
||||
|
||||
.ms.more:
|
||||
$(TROFF) -ms $(VER) $< | draft | more
|
||||
|
||||
.man.more:
|
||||
$(TROFF) -man $< | draft | more
|
||||
|
||||
.ms.1200:
|
||||
$(TROFF) -ms $(VER) $< | hp2 1200 | lp -og $(PRINTER)
|
||||
|
||||
.man.1200:
|
||||
$(TROFF) -man $< | hp2 1200 | lp -og $(PRINTER)
|
||||
|
||||
.ms.100:
|
||||
$(TROFF) -ms $(VER) $< | hp2 100 | lp -og $(PRINTER)
|
||||
|
||||
.man.100:
|
||||
$(TROFF) -man $< | hp2 100 | lp -og $(PRINTER)
|
||||
|
||||
.ms.doc:
|
||||
$(NROFF) -ms $(VER) $< >$@
|
||||
|
||||
.man.doc:
|
||||
$(NROFF) -man $< >$@
|
||||
|
||||
.ms.vga:
|
||||
$(TROFF) -ms $(VER) $< >/tmp/foo
|
||||
-vga /tmp/foo
|
||||
rm /tmp/foo
|
||||
|
||||
.ms.vgas:
|
||||
$(TROFF) -ms $(VER) $< >/tmp/foo
|
||||
-vgas /tmp/foo
|
||||
rm /tmp/foo
|
||||
|
||||
#############################################################################
|
||||
# Targets...
|
||||
|
||||
asc: $(ASC)
|
||||
cat $(ASC) >asc
|
||||
|
||||
manual: $(MANUAL)
|
||||
|
||||
clean:
|
||||
rm -f *.doc *.sh
|
|
@ -1,50 +0,0 @@
|
|||
# Makefile for elvis
|
||||
#
|
||||
# Several groups of Makefile settings are included below. Choose *ONE* group
|
||||
# of settings for your particular system, and leave the others commented out.
|
||||
# The meanings of these settings are:
|
||||
# EXTRA version-specific object files used in elvis
|
||||
# CC the C compiler command, possibly with "memory model" flags
|
||||
# CFLAGS compiler flags used to select compile-time options
|
||||
# PROGS the list of all programs
|
||||
# SORT if the "tags" file must be sorted, then SORT=-DSORT
|
||||
|
||||
PROGS= elvis ctags ref elvrec fmt elvprsv
|
||||
CPPFLAGS+= -w -DCRUNCH \
|
||||
-DNO_MKEXRC -DNO_CURSORSHAPE -DNO_CHARATTR -DNO_SHOWMODE \
|
||||
-DNO_MODELINE -DNO_OPTCOLS -DNO_DIGRAPH -DNO_EXTENSIONS \
|
||||
-DNO_ERRLIST -DNO_FKEY -DNO_VISIBLE -DNO_COLOR -DNO_POPUP
|
||||
|
||||
# LSC Force usage of local getline, this is required here as long as
|
||||
# we do not fix elvis.
|
||||
CPPFLAGS+= -D__NBSD_LIBC
|
||||
|
||||
###########################################################################
|
||||
### The rest of this Makefile contains no user-serviceable parts ###
|
||||
###########################################################################
|
||||
|
||||
SRCS.elvis= blk.c cmd1.c cmd2.c ctype.c curses.c cut.c ex.c input.c \
|
||||
main.c misc.c modify.c move1.c move2.c move3.c move4.c move5.c \
|
||||
opts.c recycle.c redraw.c regexp.c regsub.c system.c tio.c tmp.c \
|
||||
unix.c vars.c vcmd.c vi.c
|
||||
|
||||
BINDIR= /usr/bin
|
||||
|
||||
# Do not overwrite vi and ex if they already exist, only install the links
|
||||
# as a default fallback in their absence
|
||||
.if !exists(${DESTDIR}/${BINDIR}/vi)
|
||||
LINKS+= ${BINDIR}/elvis ${BINDIR}/vi
|
||||
.endif
|
||||
|
||||
.if !exists(${DESTDIR}/${BINDIR}/ex)
|
||||
LINKS+= ${BINDIR}/elvis ${BINDIR}/ex
|
||||
.endif
|
||||
|
||||
MAN.elvis=
|
||||
MAN.ctags=
|
||||
MAN.ref=
|
||||
MAN.elvrec=
|
||||
MAN.fmt=
|
||||
MAN.elvprsv=
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -1,414 +0,0 @@
|
|||
echo x - ctags.man
|
||||
sed '/^X/s///' > ctags.man << '/'
|
||||
X.TH CTAGS 1
|
||||
X.SH NAME
|
||||
Xctags - Generates "tags" and (optionally) "refs" files
|
||||
X.SH SYNOPSIS
|
||||
X\fBctags\fP [\fB-stvra\fP] \fIfilesnames\fP...
|
||||
X.SH DESCRIPTION
|
||||
X\fIctags\fP generates the "tags" and "refs" files
|
||||
Xfrom a group of C source files.
|
||||
XThe "tags" file is used by Elvis' ":tag" command,
|
||||
Xcontrol-] command,
|
||||
Xand -t option.
|
||||
XThe "refs" file is sometimes used by the \fIref(1)\fP program.
|
||||
X.PP
|
||||
XEach C source file is scanned for #define statements and
|
||||
Xglobal function definitions.
|
||||
XThe name of the macro or function becomes the name of a tag.
|
||||
XFor each tag, a line is added to the "tags" file which contains:
|
||||
X.RS
|
||||
X.nf
|
||||
X - the name of the tag
|
||||
X - a tab character
|
||||
X - the name of the file containing the tag
|
||||
X - a tab character
|
||||
X - a way to find the particular line within the file.
|
||||
X.RE
|
||||
X.fi
|
||||
X.PP
|
||||
XThe filenames list will typically be the names of all C source
|
||||
Xfiles in the current directory, like this:
|
||||
X.RS
|
||||
X.nf
|
||||
X$ ctags -stv *.[ch]
|
||||
X.RE
|
||||
X.fi
|
||||
X.SH OPTIONS
|
||||
X.IP \fB-t\fR
|
||||
XInclude typedefs.
|
||||
XA tag will be generated for each user-defined type.
|
||||
XAlso tags will be generated for struct and enum names.
|
||||
XTypes are considered to be global if they are defined in a header file,
|
||||
Xand static if they are defined in a C source file.
|
||||
X.IP \fB-v\fR
|
||||
XInclude variable declarations.
|
||||
XA tag will be generated for each variable, except for those that are declared
|
||||
Xinside the body of a function.
|
||||
X.IP \fB-s\fR
|
||||
XInclude static tags.
|
||||
X\fICtags\fR will normally put global tags in the "tags" file, and silently ignore
|
||||
Xthe static tags.
|
||||
XThis flag causes both global and static tags to be added.
|
||||
XThe name of a static tag is generated by prefixing the name of the declared
|
||||
Xitem with the name of the file where it is defined, with a colon in between.
|
||||
XFor example, "static foo(){}" in "bar.c" results in a tag named "bar.c:foo".
|
||||
X.IP \fB-r\fP
|
||||
XThis causes \fIctags\fP to generate both "tags" and "refs".
|
||||
XWithout \fB-r\fP, it would only generate "tags".
|
||||
X.IP \fB-a\fR
|
||||
XAppend to "tags", and maybe "refs".
|
||||
XNormally, \fIctags\fR overwrites these files each time it is invoked.
|
||||
XThis flag is useful when you have to many files in the current directory
|
||||
Xfor you to list them on a single command-line;
|
||||
Xit allows you to split the arguments among several invocations.
|
||||
X.SH FILES
|
||||
X.IP tags
|
||||
XA cross-reference that lists each tag name, the name of the source file that
|
||||
Xcontains it, and a way to locate a particular line in the source file.
|
||||
X.IP refs
|
||||
XThe "refs" file contains the definitions for each tag in the "tags" file,
|
||||
Xand very little else.
|
||||
XThis file can be useful, for example, when licensing restrictions prevent
|
||||
Xyou from making the source code to the standard C library readable by everybody,
|
||||
Xbut you still everybody to know what arguments the library functions need.
|
||||
X.SH BUGS
|
||||
X.PP
|
||||
X\fIctags\fR is sensitive to indenting and line breaks.
|
||||
XConsequently, it might not discover all of the tags in a file that
|
||||
Xis formatted in an unusual way.
|
||||
X.SH "SEE ALSO"
|
||||
Xelvis(1), refs(1)
|
||||
X.SH AUTHOR
|
||||
X.nf
|
||||
XSteve Kirkendall
|
||||
Xkirkenda@cs.pdx.edu
|
||||
X.fi
|
||||
/
|
||||
echo x - elvis.man
|
||||
sed '/^X/s///' > elvis.man << '/'
|
||||
X.TH ELVIS 1
|
||||
X.SH NAME
|
||||
Xelvis, ex, vi, view, input - The editor
|
||||
X.SH SYNOPSIS
|
||||
X\fBelvis\fP [\fIflags\fP] [\fB+\fP\fIcmd\fP] [\fIfiles\fP...]
|
||||
X.SH DESCRIPTION
|
||||
X\fIElvis\fP is a text editor which emulates \fIvi\fP/\fIex\fP.
|
||||
X.PP
|
||||
XOn systems which pass the program name as an argument, such as Unix and Minix,
|
||||
Xyou may also install \fIelvis\fP under the names "ex", "vi", "view", and "input".
|
||||
XThese extra names would normally be links to elvis;
|
||||
Xsee the "ln" shell command.
|
||||
X.PP
|
||||
XWhen \fIelvis\fP is invoked as "vi",
|
||||
Xit behaves exactly as though it was invoked as "elvis".
|
||||
XHowever, if you invoke \fIelvis\fP as "view",
|
||||
Xthen the readonly option is set as though you had given it the "-R" flag.
|
||||
XIf you invoke \fIelvis\fP as "ex",
|
||||
Xthen \fIelvis\fP will start up in the colon command mode
|
||||
Xinstead of the visual command mode,
|
||||
Xas though you had given it the "-e" flag.
|
||||
XIf you invoke \fIelvis\fP as "input" or "edit",
|
||||
Xthen \fIelvis\fP will start up in input mode,
|
||||
Xas though the "-i" flag was given.
|
||||
X.SH OPTIONS
|
||||
X.IP \fB-r\fP
|
||||
XTo the real vi, this flag means that a previous edit should be recovered.
|
||||
X\fIElvis\fP, though, has a separate program, called \fIelvrec(1)\fP, for recovering
|
||||
Xfiles.
|
||||
XWhen you invoke \fIelvis\fP with -r, \fIelvis\fP will tell you to run \fIelvrec\fP.
|
||||
X.IP \fB-R\fP
|
||||
XThis sets the "readonly" option,
|
||||
Xso you won't accidentally overwrite a file.
|
||||
X.IP "\fB-t\fP \fItag\fP"
|
||||
XThis causes \fIelvis\fP to start editing at the given tag.
|
||||
X.IP "\fB-m\fP [\fIfile\fP]"
|
||||
X\fIElvis\fP will search through \fIfile\fP for something that looks like
|
||||
Xan error message from a compiler.
|
||||
XIt will then begin editing the source file that caused the error,
|
||||
Xwith the cursor sitting on the line where the error was detected.
|
||||
XIf you don't explicitly name a \fIfile\fP, then "errlist" is assumed.
|
||||
X.IP \fB-e\fP
|
||||
X\fIElvis\fP will start up in colon command mode.
|
||||
X.IP \fB-v\fP
|
||||
X\fIElvis\fP will start up in visual command mode.
|
||||
X.IP \fB-i\fP
|
||||
X\fIElvis\fP will start up in input mode.
|
||||
X.IP "\fB-w\fR \fIwinsize\fR"
|
||||
XSets the "window" option's value to \fIwinsize\fR.
|
||||
X.IP "\fB+\fP\fIcommand\fP or \fB-c\fP \fIcommand\fP"
|
||||
XIf you use the +\fIcommand\fP parameter,
|
||||
Xthen after the first file is loaded
|
||||
X\fIcommand\fP is executed as an EX command.
|
||||
XA typical example would be "elvis +237 foo",
|
||||
Xwhich would cause \fIelvis\fP to start editing foo and
|
||||
Xthen move directly to line 237.
|
||||
XThe "-c \fIcommand\fP" variant was added for UNIX SysV compatibility.
|
||||
X.SH FILES
|
||||
X.IP /tmp/elv*
|
||||
XDuring editing,
|
||||
X\fIelvis\fP stores text in a temporary file.
|
||||
XFor UNIX, this file will usually be stored in the /tmp directory,
|
||||
Xand the first three characters will be "elv".
|
||||
XFor other systems, the temporary files may be stored someplace else;
|
||||
Xsee the version-specific section of the documentation.
|
||||
X.IP tags
|
||||
XThis is the database used by the \fI:tags\fP command and the \fB-t\fP option.
|
||||
XIt is usually created by the \fIctags(1)\fP program.
|
||||
X.IP ".exrc or elvis.rc"
|
||||
XOn UNIX-like systems, a file called ".exrc" in your home directory
|
||||
Xis executed as a series of \fIex\fR commands.
|
||||
XA file by the same name may be executed in the current directory, too.
|
||||
XOn non-UNIX systems, ".exrc" is usually an invalid file name;
|
||||
Xthere, the initialization file is called "elvis.rc" instead.
|
||||
X.SH "SEE ALSO"
|
||||
Xctags(1), ref(1), virec(1)
|
||||
X.PP
|
||||
X\fIElvis - A Clone of Vi/Ex\fP, the complete \fIelvis\fP documentation.
|
||||
X.SH BUGS
|
||||
XThere is no LISP support.
|
||||
XCertain other features are missing, too.
|
||||
X.PP
|
||||
XAuto-indent mode is not quite compatible with the real vi.
|
||||
XAmong other things, 0^D and ^^D don't do what you might expect.
|
||||
X.PP
|
||||
XLong lines are displayed differently.
|
||||
XThe real vi wraps long lines onto multiple rows of the screen,
|
||||
Xbut \fIelvis\fP scrolls sideways.
|
||||
X.SH AUTHOR
|
||||
X.nf
|
||||
XSteve Kirkendall
|
||||
Xkirkenda@cs.pdx.edu
|
||||
X.fi
|
||||
X.PP
|
||||
XMany other people have worked to port \fIelvis\fP to various operating systems.
|
||||
XTo see who deserves credit, run the \fI:version\fP command from within \fIelvis\fP,
|
||||
Xor look in the system-specific section of the complete documentation.
|
||||
/
|
||||
echo x - elvprsv.man
|
||||
sed '/^X/s///' > elvprsv.man << '/'
|
||||
X.TH ELVPRSV 1
|
||||
X.SH NAME
|
||||
Xelvprsv - Preserve the the modified version of a file after a crash.
|
||||
X.SH SYNOPSIS
|
||||
X.nf
|
||||
X\fB\fBelvprsv\fP ["-\fIwhy elvis died\fP"] /tmp/\fIfilename\fP...
|
||||
X\fB\fBelvprsv\fP -R /tmp/\fIfilename\fP...
|
||||
X.fi
|
||||
X.SH DESCRIPTION
|
||||
X.PP
|
||||
X\fIelvprsv\fP preserves your edited text after \fIelvis\fP dies.
|
||||
XThe text can be recovered later, via the \fIelvprsv\fP program.
|
||||
X.PP
|
||||
XFor UNIX-like systems,
|
||||
Xyou should never need to run this program from the command line.
|
||||
XIt is run automatically when \fIelvis\fP is about to die,
|
||||
Xand it should be run (via /etc/rc) when the computer is booted.
|
||||
XTHAT'S ALL!
|
||||
X.PP
|
||||
XFor non-UNIX systems such as MS-DOS, you can either use \fIelvprsv\fP
|
||||
Xthe same way as under UNIX systems (by running it from your AUTOEXEC.BAT file),
|
||||
Xor you can run it separately with the "-R" flag to recover the files
|
||||
Xin one step.
|
||||
X.PP
|
||||
XIf you're editing a file when \fIelvis\fP dies
|
||||
X(due to a bug, system crash, power failure, etc.)
|
||||
Xthen \fIelvprsv\fP will preserve the most recent version of your text.
|
||||
XThe preserved text is stored in a special directory; it does NOT overwrite
|
||||
Xyour text file automatically.
|
||||
X.PP
|
||||
X\fIelvprsv\fP will send mail to any user whose work it preserves,
|
||||
Xif your operating system normally supports mail.
|
||||
X.SH FILES
|
||||
X.IP /tmp/elv*
|
||||
XThe temporary file that \fIelvis\fP was using when it died.
|
||||
X.IP /usr/preserve/p*
|
||||
XThe text that is preserved by \fIelvprsv\fP.
|
||||
X.IP /usr/preserve/Index
|
||||
XA text file which lists the names of all preserved files, and the names
|
||||
Xof the /usr/preserve/p* files which contain their preserved text.
|
||||
X.SH BUGS
|
||||
X.PP
|
||||
XDue to the permissions on the /usr/preserve directory, on UNIX systems
|
||||
X\fIelvprsv\fP must be run as superuser.
|
||||
XThis is accomplished by making the \fIelvprsv\fP executable be owned by "root"
|
||||
Xand turning on its "set user id" bit.
|
||||
X.PP
|
||||
XIf you're editing a nameless buffer when \fIelvis\fP dies, then \fIelvprsv\fP will pretend
|
||||
Xthat the file was named "foo".
|
||||
X.SH AUTHOR
|
||||
X.nf
|
||||
XSteve Kirkendall
|
||||
Xkirkenda@cs.pdx.edu
|
||||
X.fi
|
||||
/
|
||||
echo x - elvrec.man
|
||||
sed '/^X/s///' > elvrec.man << '/'
|
||||
X.TH ELVREC 1
|
||||
X.SH NAME
|
||||
Xelvrec - Recover the modified version of a file after a crash
|
||||
X.SH SYNOPSIS
|
||||
X.nf
|
||||
X\fBelvrec\fP [\fIpreservedfile\fP [\fInewfile\fR]]
|
||||
X.fi
|
||||
X.SH DESCRIPTION
|
||||
X.PP
|
||||
XIf you're editing a file when \fIelvis\fP dies, the system crashes, or power fails,
|
||||
Xthe most recent version of your text will be preserved.
|
||||
XThe preserved text is stored in a special directory; it does NOT overwrite
|
||||
Xyour text file automatically.
|
||||
X.PP
|
||||
XThe \fIelvrec\fP program locates the preserved version of a given file,
|
||||
Xand writes it over the top of your text file -- or to a new file, if you prefer.
|
||||
XThe recovered file will have nearly all of your changes.
|
||||
X.PP
|
||||
XTo see a list of all recoverable files, run \fIelvrec\fP with no arguments.
|
||||
X.SH FILES
|
||||
X.IP /usr/preserve/p*
|
||||
XThe text that was preserved when \fIelvis\fP died.
|
||||
X.IP /usr/preserve/Index
|
||||
XA text file which lists the names of all preserved files, and the names
|
||||
Xof the /usr/preserve/p* files which contain their preserved text.
|
||||
X.SH BUGS
|
||||
X.PP
|
||||
X\fIelvrec\fP is very picky about filenames.
|
||||
XYou must tell it to recover the file using exactly the same pathname as
|
||||
Xwhen you were editing it.
|
||||
XThe simplest way to do this is to go into the same directory that you were
|
||||
Xediting, and invoke \fIelvrec\fP with the same filename as \fIelvis\fP.
|
||||
XIf that doesn't work, then try running \fIelvrec\fP with no arguments,
|
||||
Xto see exactly which pathname it is using for the desired file.
|
||||
X.PP
|
||||
XDue to the permissions on the /usr/preserve directory, on UNIX systems
|
||||
X\fIelvrec\fP must be run as superuser.
|
||||
XThis is accomplished by making the \fIelvrec\fP executable be owned by "root"
|
||||
Xand setting its "set user id" bit.
|
||||
X.PP
|
||||
XIf you're editing a nameless buffer when \fIelvis\fP dies, then \fIelvrec\fP
|
||||
Xwill pretend that the file was named "foo".
|
||||
X.SH AUTHOR
|
||||
X.nf
|
||||
XSteve Kirkendall
|
||||
Xkirkenda@cs.pdx.edu
|
||||
X.fi
|
||||
/
|
||||
echo x - fmt.man
|
||||
sed '/^X/s///' > fmt.man << '/'
|
||||
X.TH FMT 1
|
||||
X.SH NAME
|
||||
Xfmt - adjust line-length for paragraphs of text
|
||||
X.SH SYNOPSIS
|
||||
X\fBfmt\fP [\-\fIwidth\fP] [\fIfiles\fP]...
|
||||
X.SH DESCRIPTION
|
||||
X\fIfmt\fR is a simple text formatter.
|
||||
XIt inserts or deletes newlines, as necessary, to make all lines in a
|
||||
Xparagraph be approximately the same width.
|
||||
XIt preserves indentation and word spacing.
|
||||
X.PP
|
||||
XThe default line width is 72 characters.
|
||||
XYou can override this with the \-\fIwidth\fR flag.
|
||||
XIf you don't name any files on the command line,
|
||||
Xthen \fIfmt\fR will read from stdin.
|
||||
X.PP
|
||||
XIt is typically used from within \fIvi\fR to adjust the line breaks
|
||||
Xin a single paragraph.
|
||||
XTo do this, move the cursor to the top of the paragraph,
|
||||
Xtype "!}fmt", and
|
||||
Xhit <Return>.
|
||||
X.SH AUTHOR
|
||||
X.nf
|
||||
XSteve Kirkendall
|
||||
Xkirkenda@cs.pdx.edu
|
||||
X.fi
|
||||
/
|
||||
echo x - ref.man
|
||||
sed '/^X/s///' > ref.man << '/'
|
||||
X.TH REF 1
|
||||
X.SH NAME
|
||||
Xref - Display a C function header
|
||||
X.SH SYNOPSIS
|
||||
X\fBref\fR [-t] [-c \fIclass\fR]... [-f \fIfile\fR]... \fItag\fR
|
||||
X.SH DESCRIPTION
|
||||
X\fIref\fP quickly locates and displays the header of a function.
|
||||
XTo do this, \fIref\fR
|
||||
Xlooks in the "tags" file for the line that describes the function, and then
|
||||
Xscans the source file for the function.
|
||||
XWhen it locates the function, it displays an introductory comment
|
||||
X(if there is one), the function's declaration, and the declarations of all
|
||||
Xarguments.
|
||||
X.SH "SEARCH METHOD"
|
||||
X.PP
|
||||
X\fIref\fR uses a fairly sophisticated tag look-up algorithm.
|
||||
XIf you supply a filename via \fB-f\fR \fIfile\fR, then elvis first scans
|
||||
Xthe tags file for a static tag from that file.
|
||||
XThis search is limited to the tags file in the current directory.
|
||||
X.PP
|
||||
XIf you supply a classname via \fB-c\fR \fIclass\fR, then elvis searches
|
||||
Xfor a tag from that class.
|
||||
XThis search is not limited to the current directory;
|
||||
XYou can supply a list of directories in the environment variable \fITAGPATH\fR,
|
||||
Xand \fIref\fR will search through the "tags" file in each directory until it finds
|
||||
Xa tag in the desired class.
|
||||
X.PP
|
||||
XIf that fails, \fIref\fR will then try to look up an ordinary global tag.
|
||||
XThis search checks all of the directories listed in \fITAGPATH\fR, too.
|
||||
X.PP
|
||||
XIf you've given the \fB-t\fR flag, then \fIref\fR will simply output the tag line that
|
||||
Xit found, and then exit.
|
||||
XWithout \fB-t\fR, though, \fIref\fR will search for the tag line.
|
||||
XIt will try to open the source file, which should be in the same directory
|
||||
Xas the tags file where the tag was discovered.
|
||||
XIf the source file doesn't exist, or is unreadable, then \fIref\fR will try to open
|
||||
Xa file called "\fIrefs\fR" in that directory.
|
||||
XEither way, \fIref\fR will try to locate the tag, and display whatever it finds.
|
||||
X.SH "INTERACTION WITH ELVIS"
|
||||
X.PP
|
||||
X\fIref\fP is used by \fIelvis\fR' shift-K command.
|
||||
XIf the cursor is located on a word such as "splat", in the file "foo.c",
|
||||
Xthen \fIelvis\fR will invoke \fIref\fR with the command "ref -f foo.c splat".
|
||||
X.PP
|
||||
XIf \fIelvis\fR has been compiled with the -DEXTERNAL_TAGS flag, then \fIelvis\fR will
|
||||
Xuse \fIref\fR \fB\fRto scan the tags files.
|
||||
XThis is slower than the built-in tag searching, but it allows \fIelvis\fR to access
|
||||
Xthe more sophisticated tag lookup provided by \fIref\fR.
|
||||
XOther than that, external tags should act exactly like internal tags.
|
||||
X.SH OPTIONS
|
||||
X.IP \fB-t\fR
|
||||
XOutput tag info, instead of the function header.
|
||||
X.IP "\fB-f\fR \fIfile\fR"
|
||||
XThe tag might be a static function in \fIfile\fR.
|
||||
XYou can use several -f flags to have \fIref\fR consider static tags from more than one file.
|
||||
X.IP "\fB-c\fR \fIclass\fR"
|
||||
XThe tag might be a member of class \fIclass\fR.
|
||||
XYou can use several -c flags to have \fIref\fR consider tags from more than one class.
|
||||
X.SH FILES
|
||||
X.IP \fBtags\fR
|
||||
XList of function names and their locations, generated by \fIctags\fR.
|
||||
X.IP \fBrefs\fR
|
||||
XFunction headers extracted from source files (optional).
|
||||
X.SH ENVIRONMENT
|
||||
X.IP \fBTAGPATH\fR
|
||||
XList of directories to be searched.
|
||||
XThe elements in the list are separated by either
|
||||
Xsemicolons (for MS-DOS, Atari TOS, and AmigaDos), or
|
||||
Xby colons (every other operating system).
|
||||
XFor each operating system, \fIref\fR has a built-in default which is probably
|
||||
Xadequate.
|
||||
X.SH NOTES
|
||||
X.PP
|
||||
XYou might want to generate a "tags" file the directory that contains the
|
||||
Xsource code for standard C library on your system.
|
||||
XIf licensing restrictions prevent you from making the library source readable
|
||||
Xby everybody, then you can have \fIctags\fR generate a "refs" file,
|
||||
Xand make "refs" readable by everybody.
|
||||
X.PP
|
||||
XIf your system doesn't come with the library source code, then perhaps you
|
||||
Xcan produce something workable from the \fIlint\fR libraries.
|
||||
X.SH "SEE ALSO"
|
||||
Xelvis(1), ctags(1)
|
||||
X.SH AUTHOR
|
||||
X.nf
|
||||
XSteve Kirkendall
|
||||
Xkirkenda@cs.pdx.edu
|
||||
X.fi
|
||||
/
|
|
@ -1,31 +0,0 @@
|
|||
Elvis is a clone of vi/ex, the standard UNIX editor. Elvis supports
|
||||
nearly all of the vi/ex commands, in both visual mode and colon mode.
|
||||
|
||||
Elvis runs under BSD UNIX, AT&T SysV UNIX, SCO Xenix, Minix, MS-DOS
|
||||
(Turbo-C or MSC 5.1), Atari TOS, OS9/68000, Coherent, VMS, and AmigaDos.
|
||||
Ports to other operating systems are in progress; contact me before you
|
||||
start porting it to some other OS, because somebody else may have
|
||||
already done it for you.
|
||||
|
||||
Elvis is freely redistributable, in either source form or executable
|
||||
form. There are no restrictions on how you may use it.
|
||||
|
||||
The file "elvisman.txt" contains the manual for elvis. It is a plain
|
||||
ASCII file with nothing more exotic than a newline character. It is
|
||||
formatted for 66-line, 80-column pages. There may also be an archive of
|
||||
"*.ms" and "*.man" files, which contain the TROFF source text used to
|
||||
generate that manual.
|
||||
|
||||
The file named "Makefile.mix" is used to compile elvis for all systems
|
||||
except VMS and possibly MS-DOS. You should copy "Makefile.mix" to
|
||||
"Makefile", and then edit "Makefile" to select the appropriate group of
|
||||
settings for your system.
|
||||
|
||||
|
||||
Author: Steve Kirkendall
|
||||
14407 SW Teal Blvd. #C
|
||||
Beaverton, OR 97005
|
||||
|
||||
E-mail: kirkenda@cs.pdx.edu
|
||||
|
||||
Phone: (503) 643-6980
|
|
@ -1,469 +0,0 @@
|
|||
/* blk.c */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* 14407 SW Teal Blvd. #C
|
||||
* Beaverton, OR 97005
|
||||
* kirkenda@cs.pdx.edu
|
||||
*/
|
||||
|
||||
|
||||
/* This file contains the functions that get/put blocks from the temp file.
|
||||
* It also contains the "do" and "undo" functions.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "vi.h"
|
||||
|
||||
#ifndef NBUFS
|
||||
# define NBUFS 5 /* must be at least 3 -- more is better */
|
||||
#endif
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
BLK hdr; /* buffer for the header block */
|
||||
|
||||
static int b4cnt; /* used to count context of beforedo/afterdo */
|
||||
static struct _blkbuf
|
||||
{
|
||||
BLK buf; /* contents of a text block */
|
||||
unsigned short logical; /* logical block number */
|
||||
int dirty; /* must the buffer be rewritten? */
|
||||
}
|
||||
blk[NBUFS], /* buffers for text[?] blocks */
|
||||
*toonew, /* buffer which shouldn't be recycled yet */
|
||||
*newtoo, /* another buffer which should be recycled */
|
||||
*recycle = blk; /* next block to be recycled */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* This function wipes out all buffers */
|
||||
void blkinit()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NBUFS; i++)
|
||||
{
|
||||
blk[i].logical = 0;
|
||||
blk[i].dirty = FALSE;
|
||||
}
|
||||
for (i = 0; i < MAXBLKS; i++)
|
||||
{
|
||||
hdr.n[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* This function allocates a buffer and fills it with a given block's text */
|
||||
BLK *blkget(logical)
|
||||
int logical; /* logical block number to fetch */
|
||||
{
|
||||
REG struct _blkbuf *this; /* used to step through blk[] */
|
||||
REG int i;
|
||||
|
||||
/* if logical is 0, just return the hdr buffer */
|
||||
if (logical == 0)
|
||||
{
|
||||
return &hdr;
|
||||
}
|
||||
|
||||
/* see if we have that block in mem already */
|
||||
for (this = blk; this < &blk[NBUFS]; this++)
|
||||
{
|
||||
if (this->logical == logical)
|
||||
{
|
||||
newtoo = toonew;
|
||||
toonew = this;
|
||||
return &this->buf;
|
||||
}
|
||||
}
|
||||
|
||||
/* choose a block to be recycled */
|
||||
do
|
||||
{
|
||||
this = recycle++;
|
||||
if (recycle == &blk[NBUFS])
|
||||
{
|
||||
recycle = blk;
|
||||
}
|
||||
} while (this == toonew || this == newtoo);
|
||||
|
||||
/* if it contains a block, flush that block */
|
||||
blkflush(this);
|
||||
|
||||
/* fill this buffer with the desired block */
|
||||
this->logical = logical;
|
||||
if (hdr.n[logical])
|
||||
{
|
||||
/* it has been used before - fill it from tmp file */
|
||||
lseek(tmpfd, (long)hdr.n[logical] * (long)BLKSIZE, 0);
|
||||
if (read(tmpfd, this->buf.c, (unsigned)BLKSIZE) != BLKSIZE)
|
||||
{
|
||||
msg("Error reading back from tmp file!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* it is new - zero it */
|
||||
for (i = 0; i < BLKSIZE; i++)
|
||||
{
|
||||
this->buf.c[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* This isn't really a change, but it does potentially invalidate
|
||||
* the kinds of shortcuts that the "changes" variable is supposed
|
||||
* to protect us from... so count it as a change.
|
||||
*/
|
||||
changes++;
|
||||
|
||||
/* mark it as being "not dirty" */
|
||||
this->dirty = 0;
|
||||
|
||||
/* return it */
|
||||
newtoo = toonew;
|
||||
toonew = this;
|
||||
return &this->buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* This function writes a block out to the temporary file */
|
||||
void blkflush(this)
|
||||
REG struct _blkbuf *this; /* the buffer to flush */
|
||||
{
|
||||
long seekpos; /* seek position of the new block */
|
||||
unsigned short physical; /* physical block number */
|
||||
|
||||
/* if its empty (an orphan blkadd() maybe?) then make it dirty */
|
||||
if (this->logical && !*this->buf.c)
|
||||
{
|
||||
blkdirty(&this->buf);
|
||||
}
|
||||
|
||||
/* if it's an empty buffer or a clean version is on disk, quit */
|
||||
if (!this->logical || hdr.n[this->logical] && !this->dirty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* find a free place in the file */
|
||||
#ifndef NO_RECYCLE
|
||||
seekpos = allocate();
|
||||
lseek(tmpfd, seekpos, 0);
|
||||
#else
|
||||
seekpos = lseek(tmpfd, 0L, 2);
|
||||
#endif
|
||||
physical = seekpos / BLKSIZE;
|
||||
|
||||
/* put the block there */
|
||||
if (write(tmpfd, this->buf.c, (unsigned)BLKSIZE) != BLKSIZE)
|
||||
{
|
||||
msg("Trouble writing to tmp file");
|
||||
}
|
||||
this->dirty = FALSE;
|
||||
|
||||
/* update the header so it knows we put it there */
|
||||
hdr.n[this->logical] = physical;
|
||||
}
|
||||
|
||||
|
||||
/* This function sets a block's "dirty" flag or deletes empty blocks */
|
||||
void blkdirty(bp)
|
||||
BLK *bp; /* buffer returned by blkget() */
|
||||
{
|
||||
REG int i, j;
|
||||
REG char *scan;
|
||||
REG int k;
|
||||
|
||||
/* find the buffer */
|
||||
for (i = 0; i < NBUFS && bp != &blk[i].buf; i++)
|
||||
{
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (i >= NBUFS)
|
||||
{
|
||||
msg("blkdirty() called with unknown buffer at 0x%lx", bp);
|
||||
return;
|
||||
}
|
||||
if (blk[i].logical == 0)
|
||||
{
|
||||
msg("blkdirty called with freed buffer");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* if this block ends with line# INFINITY, then it must have been
|
||||
* allocated unnecessarily during tmpstart(). Forget it.
|
||||
*/
|
||||
if (lnum[blk[i].logical] == INFINITY)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (blk[i].buf.c[0])
|
||||
{
|
||||
msg("bkldirty called with non-empty extra BLK");
|
||||
}
|
||||
#endif
|
||||
blk[i].logical = 0;
|
||||
blk[i].dirty = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* count lines in this block */
|
||||
for (j = 0, scan = bp->c; *scan && scan < bp->c + BLKSIZE; scan++)
|
||||
{
|
||||
if (*scan == '\n')
|
||||
{
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
/* adjust lnum, if necessary */
|
||||
k = blk[i].logical;
|
||||
j += (lnum[k - 1] - lnum[k]);
|
||||
if (j != 0)
|
||||
{
|
||||
nlines += j;
|
||||
while (k < MAXBLKS && lnum[k] != INFINITY)
|
||||
{
|
||||
lnum[k++] += j;
|
||||
}
|
||||
}
|
||||
|
||||
/* if it still has text, mark it as dirty */
|
||||
if (*bp->c)
|
||||
{
|
||||
blk[i].dirty = TRUE;
|
||||
}
|
||||
else /* empty block, so delete it */
|
||||
{
|
||||
/* adjust the cache */
|
||||
k = blk[i].logical;
|
||||
for (j = 0; j < NBUFS; j++)
|
||||
{
|
||||
if (blk[j].logical >= k)
|
||||
{
|
||||
blk[j].logical--;
|
||||
}
|
||||
}
|
||||
|
||||
/* delete it from hdr.n[] and lnum[] */
|
||||
blk[i].logical = 0;
|
||||
blk[i].dirty = FALSE;
|
||||
while (k < MAXBLKS - 1)
|
||||
{
|
||||
hdr.n[k] = hdr.n[k + 1];
|
||||
lnum[k] = lnum[k + 1];
|
||||
k++;
|
||||
}
|
||||
hdr.n[MAXBLKS - 1] = 0;
|
||||
lnum[MAXBLKS - 1] = INFINITY;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* insert a new block into hdr, and adjust the cache */
|
||||
BLK *blkadd(logical)
|
||||
int logical; /* where to insert the new block */
|
||||
{
|
||||
REG int i;
|
||||
|
||||
/* adjust hdr and lnum[] */
|
||||
for (i = MAXBLKS - 1; i > logical; i--)
|
||||
{
|
||||
hdr.n[i] = hdr.n[i - 1];
|
||||
lnum[i] = lnum[i - 1];
|
||||
}
|
||||
hdr.n[logical] = 0;
|
||||
lnum[logical] = lnum[logical - 1];
|
||||
|
||||
/* adjust the cache */
|
||||
for (i = 0; i < NBUFS; i++)
|
||||
{
|
||||
if (blk[i].logical >= logical)
|
||||
{
|
||||
blk[i].logical++;
|
||||
}
|
||||
}
|
||||
|
||||
/* return the new block, via blkget() */
|
||||
return blkget(logical);
|
||||
}
|
||||
|
||||
|
||||
/* This function forces all dirty blocks out to disk */
|
||||
void blksync()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NBUFS; i++)
|
||||
{
|
||||
/* blk[i].dirty = TRUE; */
|
||||
blkflush(&blk[i]);
|
||||
}
|
||||
if (*o_sync)
|
||||
{
|
||||
sync();
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
static MARK undocurs; /* where the cursor should go if undone */
|
||||
static long oldnlines;
|
||||
static long oldlnum[MAXBLKS];
|
||||
|
||||
|
||||
/* This function should be called before each command that changes the text.
|
||||
* It defines the state that undo() will reset the file to.
|
||||
*/
|
||||
void beforedo(forundo)
|
||||
int forundo; /* boolean: is this for an undo? */
|
||||
{
|
||||
REG int i;
|
||||
REG long l;
|
||||
|
||||
/* if this is a nested call to beforedo, quit! Use larger context */
|
||||
if (b4cnt++ > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* force all block buffers to disk */
|
||||
blksync();
|
||||
|
||||
#ifndef NO_RECYCLE
|
||||
/* perform garbage collection on blocks from tmp file */
|
||||
garbage();
|
||||
#endif
|
||||
|
||||
/* force the header out to disk */
|
||||
lseek(tmpfd, 0L, 0);
|
||||
if (write(tmpfd, hdr.c, (unsigned)BLKSIZE) != BLKSIZE)
|
||||
{
|
||||
msg("Trouble writing header to tmp file ");
|
||||
}
|
||||
|
||||
/* copy or swap oldnlines <--> nlines, oldlnum <--> lnum */
|
||||
if (forundo)
|
||||
{
|
||||
for (i = 0; i < MAXBLKS; i++)
|
||||
{
|
||||
l = lnum[i];
|
||||
lnum[i] = oldlnum[i];
|
||||
oldlnum[i] = l;
|
||||
}
|
||||
l = nlines;
|
||||
nlines = oldnlines;
|
||||
oldnlines = l;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < MAXBLKS; i++)
|
||||
{
|
||||
oldlnum[i] = lnum[i];
|
||||
}
|
||||
oldnlines = nlines;
|
||||
}
|
||||
|
||||
/* save the cursor position */
|
||||
undocurs = cursor;
|
||||
|
||||
/* upon return, the calling function continues and makes changes... */
|
||||
}
|
||||
|
||||
/* This function marks the end of a (nested?) change to the file */
|
||||
void afterdo()
|
||||
{
|
||||
if (--b4cnt)
|
||||
{
|
||||
/* after abortdo(), b4cnt may decribe nested beforedo/afterdo
|
||||
* pairs incorrectly. If it is decremented to often, then
|
||||
* keep b4cnt sane but don't do anything else.
|
||||
*/
|
||||
if (b4cnt < 0)
|
||||
b4cnt = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* make sure the cursor wasn't left stranded in deleted text */
|
||||
if (markline(cursor) > nlines)
|
||||
{
|
||||
cursor = MARK_LAST;
|
||||
}
|
||||
/* NOTE: it is still possible that markidx(cursor) is after the
|
||||
* end of a line, so the Vi mode will have to take care of that
|
||||
* itself */
|
||||
|
||||
/* if a significant change has been made to this file, then set the
|
||||
* MODIFIED flag.
|
||||
*/
|
||||
if (significant)
|
||||
{
|
||||
setflag(file, MODIFIED);
|
||||
setflag(file, UNDOABLE);
|
||||
}
|
||||
}
|
||||
|
||||
/* This function cuts short the current set of changes. It is called after
|
||||
* a SIGINT.
|
||||
*/
|
||||
void abortdo()
|
||||
{
|
||||
/* finish the operation immediately. */
|
||||
if (b4cnt > 0)
|
||||
{
|
||||
b4cnt = 1;
|
||||
afterdo();
|
||||
}
|
||||
|
||||
/* in visual mode, the screen is probably screwed up */
|
||||
if (mode == MODE_COLON)
|
||||
{
|
||||
mode = MODE_VI;
|
||||
}
|
||||
if (mode == MODE_VI)
|
||||
{
|
||||
redraw(MARK_UNSET, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/* This function discards all changes made since the last call to beforedo() */
|
||||
int undo()
|
||||
{
|
||||
BLK oldhdr;
|
||||
|
||||
/* if beforedo() has never been run, fail */
|
||||
if (!tstflag(file, UNDOABLE))
|
||||
{
|
||||
msg("You haven't modified this file yet.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* read the old header form the tmp file */
|
||||
lseek(tmpfd, 0L, 0);
|
||||
if (read(tmpfd, oldhdr.c, (unsigned)BLKSIZE) != BLKSIZE)
|
||||
{
|
||||
msg("Trouble rereading the old header from tmp file");
|
||||
}
|
||||
|
||||
/* "do" the changed version, so we can undo the "undo" */
|
||||
cursor = undocurs;
|
||||
beforedo(TRUE);
|
||||
afterdo();
|
||||
|
||||
/* wipe out the block buffers - we can't assume they're correct */
|
||||
blkinit();
|
||||
|
||||
/* use the old header -- and therefore the old text blocks */
|
||||
hdr = oldhdr;
|
||||
|
||||
/* This is a change */
|
||||
significant = TRUE;
|
||||
changes++;
|
||||
|
||||
return TRUE;
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,942 +0,0 @@
|
|||
/* cmd2.c */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* 14407 SW Teal Blvd. #C
|
||||
* Beaverton, OR 97005
|
||||
* kirkenda@cs.pdx.edu
|
||||
*/
|
||||
|
||||
|
||||
/* This file contains some of the commands - mostly ones that change text */
|
||||
|
||||
#include "config.h"
|
||||
#include "ctype.h"
|
||||
#include "vi.h"
|
||||
#include "regexp.h"
|
||||
#if TOS
|
||||
# include <stat.h>
|
||||
#else
|
||||
# if OSK
|
||||
# include "osk.h"
|
||||
# else
|
||||
# if AMIGA
|
||||
# include "amistat.h"
|
||||
# else
|
||||
# include <sys/stat.h>
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/*ARGSUSED*/
|
||||
void cmd_substitute(frommark, tomark, cmd, bang, extra)
|
||||
MARK frommark;
|
||||
MARK tomark;
|
||||
CMD cmd;
|
||||
int bang;
|
||||
char *extra; /* rest of the command line */
|
||||
{
|
||||
char *line; /* a line from the file */
|
||||
regexp *re; /* the compiled search expression */
|
||||
char *subst; /* the substitution string */
|
||||
char *opt; /* substitution options */
|
||||
long l; /* a line number */
|
||||
char *s, *d; /* used during subtitutions */
|
||||
char *conf; /* used during confirmation */
|
||||
long chline; /* # of lines changed */
|
||||
long chsub; /* # of substitutions made */
|
||||
static optp; /* boolean option: print when done? */
|
||||
static optg; /* boolean option: substitute globally in line? */
|
||||
static optc; /* boolean option: confirm before subst? */
|
||||
#ifndef CRUNCH
|
||||
long oldnlines;
|
||||
#endif
|
||||
|
||||
|
||||
/* for now, assume this will fail */
|
||||
rptlines = -1L;
|
||||
|
||||
if (cmd == CMD_SUBAGAIN)
|
||||
{
|
||||
#ifndef NO_MAGIC
|
||||
if (*o_magic)
|
||||
subst = "~";
|
||||
else
|
||||
#endif
|
||||
subst = "\\~";
|
||||
re = regcomp("");
|
||||
|
||||
/* if visual "&", then turn off the "p" and "c" options */
|
||||
if (bang)
|
||||
{
|
||||
optp = optc = FALSE;
|
||||
}
|
||||
}
|
||||
else /* CMD_SUBSTITUTE */
|
||||
{
|
||||
/* make sure we got a search pattern */
|
||||
if (*extra != '/' && *extra != '?')
|
||||
{
|
||||
msg("Usage: s/regular expression/new text/");
|
||||
return;
|
||||
}
|
||||
|
||||
/* parse & compile the search pattern */
|
||||
subst = parseptrn(extra);
|
||||
re = regcomp(extra + 1);
|
||||
}
|
||||
|
||||
/* abort if RE error -- error message already given by regcomp() */
|
||||
if (!re)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (cmd == CMD_SUBSTITUTE)
|
||||
{
|
||||
/* parse the substitution string & find the option string */
|
||||
for (opt = subst; *opt && *opt != *extra; opt++)
|
||||
{
|
||||
if (*opt == '\\' && opt[1])
|
||||
{
|
||||
opt++;
|
||||
}
|
||||
}
|
||||
if (*opt)
|
||||
{
|
||||
*opt++ = '\0';
|
||||
}
|
||||
|
||||
/* analyse the option string */
|
||||
if (!*o_edcompatible)
|
||||
{
|
||||
optp = optg = optc = FALSE;
|
||||
}
|
||||
while (*opt)
|
||||
{
|
||||
switch (*opt++)
|
||||
{
|
||||
case 'p': optp = !optp; break;
|
||||
case 'g': optg = !optg; break;
|
||||
case 'c': optc = !optc; break;
|
||||
case ' ':
|
||||
case '\t': break;
|
||||
default:
|
||||
msg("Subst options are p, c, and g -- not %c", opt[-1]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if "c" or "p" flag was given, and we're in visual mode, then NEWLINE */
|
||||
if ((optc || optp) && mode == MODE_VI)
|
||||
{
|
||||
addch('\n');
|
||||
exrefresh();
|
||||
}
|
||||
|
||||
ChangeText
|
||||
{
|
||||
/* reset the change counters */
|
||||
chline = chsub = 0L;
|
||||
|
||||
/* for each selected line */
|
||||
for (l = markline(frommark); l <= markline(tomark); l++)
|
||||
{
|
||||
/* fetch the line */
|
||||
line = fetchline(l);
|
||||
|
||||
/* if it contains the search pattern... */
|
||||
if (regexec(re, line, TRUE))
|
||||
{
|
||||
/* increment the line change counter */
|
||||
chline++;
|
||||
|
||||
/* initialize the pointers */
|
||||
s = line;
|
||||
d = tmpblk.c;
|
||||
|
||||
/* do once or globally ... */
|
||||
do
|
||||
{
|
||||
#ifndef CRUNCH
|
||||
/* confirm, if necessary */
|
||||
if (optc)
|
||||
{
|
||||
for (conf = line; conf < re->startp[0]; conf++)
|
||||
addch(*conf);
|
||||
standout();
|
||||
for ( ; conf < re->endp[0]; conf++)
|
||||
addch(*conf);
|
||||
standend();
|
||||
for (; *conf; conf++)
|
||||
addch(*conf);
|
||||
addch('\n');
|
||||
exrefresh();
|
||||
if (getkey(0) != 'y')
|
||||
{
|
||||
/* copy accross the original chars */
|
||||
while (s < re->endp[0])
|
||||
*d++ = *s++;
|
||||
|
||||
/* skip to next match on this line, if any */
|
||||
goto Continue;
|
||||
}
|
||||
}
|
||||
#endif /* not CRUNCH */
|
||||
|
||||
/* increment the substitution change counter */
|
||||
chsub++;
|
||||
|
||||
/* copy stuff from before the match */
|
||||
while (s < re->startp[0])
|
||||
{
|
||||
*d++ = *s++;
|
||||
}
|
||||
|
||||
/* substitute for the matched part */
|
||||
regsub(re, subst, d);
|
||||
s = re->endp[0];
|
||||
d += strlen(d);
|
||||
|
||||
Continue:
|
||||
/* if this regexp could conceivably match
|
||||
* a zero-length string, then require at
|
||||
* least 1 unmatched character between
|
||||
* matches.
|
||||
*/
|
||||
if (re->minlen == 0)
|
||||
{
|
||||
if (!*s)
|
||||
break;
|
||||
*d++ = *s++;
|
||||
}
|
||||
|
||||
} while (optg && regexec(re, s, FALSE));
|
||||
|
||||
/* copy stuff from after the match */
|
||||
while (*d++ = *s++) /* yes, ASSIGNMENT! */
|
||||
{
|
||||
}
|
||||
|
||||
#ifndef CRUNCH
|
||||
/* NOTE: since the substitution text is allowed to have ^Ms which are
|
||||
* translated into newlines, it is possible that the number of lines
|
||||
* in the file will increase after each line has been substituted.
|
||||
* we need to adjust for this.
|
||||
*/
|
||||
oldnlines = nlines;
|
||||
#endif
|
||||
|
||||
/* replace the old version of the line with the new */
|
||||
d[-1] = '\n';
|
||||
d[0] = '\0';
|
||||
change(MARK_AT_LINE(l), MARK_AT_LINE(l + 1), tmpblk.c);
|
||||
|
||||
#ifndef CRUNCH
|
||||
l += nlines - oldnlines;
|
||||
tomark += MARK_AT_LINE(nlines - oldnlines);
|
||||
#endif
|
||||
|
||||
/* if supposed to print it, do so */
|
||||
if (optp)
|
||||
{
|
||||
addstr(tmpblk.c);
|
||||
exrefresh();
|
||||
}
|
||||
|
||||
/* move the cursor to that line */
|
||||
cursor = MARK_AT_LINE(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* free the regexp */
|
||||
free(re);
|
||||
|
||||
/* if done from within a ":g" command, then finish silently */
|
||||
if (doingglobal)
|
||||
{
|
||||
rptlines = chline;
|
||||
rptlabel = "changed";
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reporting */
|
||||
if (chsub == 0)
|
||||
{
|
||||
msg("Substitution failed");
|
||||
}
|
||||
else if (chline >= *o_report)
|
||||
{
|
||||
msg("%ld substitutions on %ld lines", chsub, chline);
|
||||
}
|
||||
rptlines = 0L;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*ARGSUSED*/
|
||||
void cmd_delete(frommark, tomark, cmd, bang, extra)
|
||||
MARK frommark;
|
||||
MARK tomark;
|
||||
CMD cmd;
|
||||
int bang;
|
||||
char *extra;
|
||||
{
|
||||
MARK curs2; /* an altered form of the cursor */
|
||||
|
||||
/* choose your cut buffer */
|
||||
if (*extra == '"')
|
||||
{
|
||||
extra++;
|
||||
}
|
||||
if (*extra)
|
||||
{
|
||||
cutname(*extra);
|
||||
}
|
||||
|
||||
/* make sure we're talking about whole lines here */
|
||||
frommark = frommark & ~(BLKSIZE - 1);
|
||||
tomark = (tomark & ~(BLKSIZE - 1)) + BLKSIZE;
|
||||
|
||||
/* yank the lines */
|
||||
cut(frommark, tomark);
|
||||
|
||||
/* if CMD_DELETE then delete the lines */
|
||||
if (cmd != CMD_YANK)
|
||||
{
|
||||
curs2 = cursor;
|
||||
ChangeText
|
||||
{
|
||||
/* delete the lines */
|
||||
delete(frommark, tomark);
|
||||
}
|
||||
if (curs2 > tomark)
|
||||
{
|
||||
cursor = curs2 - tomark + frommark;
|
||||
}
|
||||
else if (curs2 > frommark)
|
||||
{
|
||||
cursor = frommark;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*ARGSUSED*/
|
||||
void cmd_append(frommark, tomark, cmd, bang, extra)
|
||||
MARK frommark;
|
||||
MARK tomark;
|
||||
CMD cmd;
|
||||
int bang;
|
||||
char *extra;
|
||||
{
|
||||
long l; /* line counter */
|
||||
|
||||
#ifndef CRUNCH
|
||||
/* if '!' then toggle auto-indent */
|
||||
if (bang)
|
||||
{
|
||||
*o_autoindent = !*o_autoindent;
|
||||
}
|
||||
#endif
|
||||
|
||||
ChangeText
|
||||
{
|
||||
/* if we're doing a change, delete the old version */
|
||||
if (cmd == CMD_CHANGE)
|
||||
{
|
||||
/* delete 'em */
|
||||
cmd_delete(frommark, tomark, cmd, bang, extra);
|
||||
}
|
||||
|
||||
/* new lines start at the frommark line, or after it */
|
||||
l = markline(frommark);
|
||||
if (cmd == CMD_APPEND)
|
||||
{
|
||||
l++;
|
||||
}
|
||||
|
||||
/* get lines until no more lines, or "." line, and insert them */
|
||||
while (vgets('\0', tmpblk.c, BLKSIZE) >= 0)
|
||||
{
|
||||
addch('\n');
|
||||
if (!strcmp(tmpblk.c, "."))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
strcat(tmpblk.c, "\n");
|
||||
add(MARK_AT_LINE(l), tmpblk.c);
|
||||
l++;
|
||||
}
|
||||
}
|
||||
|
||||
/* on the odd chance that we're calling this from vi mode ... */
|
||||
redraw(MARK_UNSET, FALSE);
|
||||
}
|
||||
|
||||
|
||||
/*ARGSUSED*/
|
||||
void cmd_put(frommark, tomark, cmd, bang, extra)
|
||||
MARK frommark;
|
||||
MARK tomark;
|
||||
CMD cmd;
|
||||
int bang;
|
||||
char *extra;
|
||||
{
|
||||
/* choose your cut buffer */
|
||||
if (*extra == '"')
|
||||
{
|
||||
extra++;
|
||||
}
|
||||
if (*extra)
|
||||
{
|
||||
cutname(*extra);
|
||||
}
|
||||
|
||||
/* paste it */
|
||||
ChangeText
|
||||
{
|
||||
cursor = paste(frommark, TRUE, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*ARGSUSED*/
|
||||
void cmd_join(frommark, tomark, cmd, bang, extra)
|
||||
MARK frommark;
|
||||
MARK tomark;
|
||||
CMD cmd;
|
||||
int bang;
|
||||
char *extra;
|
||||
{
|
||||
long l;
|
||||
char *scan;
|
||||
int len; /* length of the new line */
|
||||
|
||||
/* if only one line is specified, assume the following one joins too */
|
||||
if (markline(frommark) == nlines)
|
||||
{
|
||||
msg("Nothing to join with this line");
|
||||
return;
|
||||
}
|
||||
if (markline(frommark) == markline(tomark))
|
||||
{
|
||||
tomark += BLKSIZE;
|
||||
}
|
||||
|
||||
/* get the first line */
|
||||
l = markline(frommark);
|
||||
strcpy(tmpblk.c, fetchline(l));
|
||||
len = strlen(tmpblk.c);
|
||||
|
||||
/* build the longer line */
|
||||
while (++l <= markline(tomark))
|
||||
{
|
||||
/* get the next line */
|
||||
scan = fetchline(l);
|
||||
|
||||
/* remove any leading whitespace */
|
||||
while (*scan == '\t' || *scan == ' ')
|
||||
{
|
||||
scan++;
|
||||
}
|
||||
|
||||
/* see if the line will fit */
|
||||
if (strlen(scan) + len + 3 > BLKSIZE)
|
||||
{
|
||||
msg("Can't join -- the resulting line would be too long");
|
||||
return;
|
||||
}
|
||||
|
||||
/* catenate it, with a space (or two) in between */
|
||||
if (!bang)
|
||||
{
|
||||
if (len >= 1)
|
||||
{
|
||||
if (tmpblk.c[len - 1] == '.'
|
||||
|| tmpblk.c[len - 1] == '?'
|
||||
|| tmpblk.c[len - 1] == '!')
|
||||
{
|
||||
tmpblk.c[len++] = ' ';
|
||||
}
|
||||
tmpblk.c[len++] = ' ';
|
||||
}
|
||||
}
|
||||
strcpy(tmpblk.c + len, scan);
|
||||
len += strlen(scan);
|
||||
}
|
||||
tmpblk.c[len++] = '\n';
|
||||
tmpblk.c[len] = '\0';
|
||||
|
||||
/* make the change */
|
||||
ChangeText
|
||||
{
|
||||
frommark &= ~(BLKSIZE - 1);
|
||||
tomark &= ~(BLKSIZE - 1);
|
||||
tomark += BLKSIZE;
|
||||
change(frommark, tomark, tmpblk.c);
|
||||
}
|
||||
|
||||
/* Reporting... */
|
||||
rptlines = markline(tomark) - markline(frommark) - 1L;
|
||||
rptlabel = "joined";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*ARGSUSED*/
|
||||
void cmd_shift(frommark, tomark, cmd, bang, extra)
|
||||
MARK frommark;
|
||||
MARK tomark;
|
||||
CMD cmd;
|
||||
int bang;
|
||||
char *extra;
|
||||
{
|
||||
long l; /* line number counter */
|
||||
int oldidx; /* number of chars previously used for indent */
|
||||
int newidx; /* number of chars in the new indent string */
|
||||
int oldcol; /* previous indent amount */
|
||||
int newcol; /* new indent amount */
|
||||
char *text; /* pointer to the old line's text */
|
||||
|
||||
ChangeText
|
||||
{
|
||||
/* for each line to shift... */
|
||||
for (l = markline(frommark); l <= markline(tomark); l++)
|
||||
{
|
||||
/* get the line - ignore empty lines unless ! mode */
|
||||
text = fetchline(l);
|
||||
if (!*text && !bang)
|
||||
continue;
|
||||
|
||||
/* calc oldidx and oldcol */
|
||||
for (oldidx = 0, oldcol = 0;
|
||||
text[oldidx] == ' ' || text[oldidx] == '\t';
|
||||
oldidx++)
|
||||
{
|
||||
if (text[oldidx] == ' ')
|
||||
{
|
||||
oldcol += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
oldcol += *o_tabstop - (oldcol % *o_tabstop);
|
||||
}
|
||||
}
|
||||
|
||||
/* calc newcol */
|
||||
if (cmd == CMD_SHIFTR)
|
||||
{
|
||||
newcol = oldcol + (*o_shiftwidth & 0xff);
|
||||
}
|
||||
else
|
||||
{
|
||||
newcol = oldcol - (*o_shiftwidth & 0xff);
|
||||
if (newcol < 0)
|
||||
newcol = 0;
|
||||
}
|
||||
|
||||
/* if no change, then skip to next line */
|
||||
if (oldcol == newcol)
|
||||
continue;
|
||||
|
||||
/* build a new indent string */
|
||||
newidx = 0;
|
||||
if (*o_autotab)
|
||||
{
|
||||
while (newcol >= *o_tabstop)
|
||||
{
|
||||
tmpblk.c[newidx++] = '\t';
|
||||
newcol -= *o_tabstop;
|
||||
}
|
||||
}
|
||||
while (newcol > 0)
|
||||
{
|
||||
tmpblk.c[newidx++] = ' ';
|
||||
newcol--;
|
||||
}
|
||||
tmpblk.c[newidx] = '\0';
|
||||
|
||||
/* change the old indent string into the new */
|
||||
change(MARK_AT_LINE(l), MARK_AT_LINE(l) + oldidx, tmpblk.c);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reporting... */
|
||||
rptlines = markline(tomark) - markline(frommark) + 1L;
|
||||
if (cmd == CMD_SHIFTR)
|
||||
{
|
||||
rptlabel = ">ed";
|
||||
}
|
||||
else
|
||||
{
|
||||
rptlabel = "<ed";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*ARGSUSED*/
|
||||
void cmd_read(frommark, tomark, cmd, bang, extra)
|
||||
MARK frommark;
|
||||
MARK tomark;
|
||||
CMD cmd;
|
||||
int bang;
|
||||
char *extra;
|
||||
{
|
||||
int fd, rc; /* used while reading from the file */
|
||||
char *scan; /* used for finding NUL characters */
|
||||
int hadnul; /* boolean: any NULs found? */
|
||||
int addnl; /* boolean: forced to add newlines? */
|
||||
int len; /* number of chars in current line */
|
||||
long lines; /* number of lines in current block */
|
||||
struct stat statb;
|
||||
|
||||
/* special case: if ":r !cmd" then let the filter() function do it */
|
||||
if (extra[0] == '!')
|
||||
{
|
||||
filter(frommark, MARK_UNSET, extra + 1, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* open the file */
|
||||
fd = open(extra, O_RDONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
msg("Can't open \"%s\"", extra);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef CRUNCH
|
||||
if (stat(extra, &statb) < 0)
|
||||
{
|
||||
msg("Can't stat \"%s\"", extra);
|
||||
}
|
||||
# if TOS
|
||||
if (statb.st_mode & S_IJDIR)
|
||||
# else
|
||||
# if OSK
|
||||
if (statb.st_mode & S_IFDIR)
|
||||
# else
|
||||
if ((statb.st_mode & S_IFMT) != S_IFREG)
|
||||
# endif
|
||||
# endif
|
||||
{
|
||||
msg("\"%s\" is not a regular file", extra);
|
||||
return;
|
||||
}
|
||||
#endif /* not CRUNCH */
|
||||
|
||||
/* get blocks from the file, and add them */
|
||||
ChangeText
|
||||
{
|
||||
/* insertion starts at the line following frommark */
|
||||
tomark = frommark = (frommark | (BLKSIZE - 1L)) + 1L;
|
||||
len = 0;
|
||||
hadnul = addnl = FALSE;
|
||||
|
||||
/* add an extra newline, so partial lines at the end of
|
||||
* the file don't trip us up
|
||||
*/
|
||||
add(tomark, "\n");
|
||||
|
||||
/* for each chunk of text... */
|
||||
while ((rc = tread(fd, tmpblk.c, BLKSIZE - 1)) > 0)
|
||||
{
|
||||
/* count newlines, convert NULs, etc. ... */
|
||||
for (lines = 0, scan = tmpblk.c; rc > 0; rc--, scan++)
|
||||
{
|
||||
/* break up long lines */
|
||||
if (*scan != '\n' && len + 2 > BLKSIZE)
|
||||
{
|
||||
*scan = '\n';
|
||||
addnl = TRUE;
|
||||
}
|
||||
|
||||
/* protect against NUL chars in file */
|
||||
if (!*scan)
|
||||
{
|
||||
*scan = 0x80;
|
||||
hadnul = TRUE;
|
||||
}
|
||||
|
||||
/* starting a new line? */
|
||||
if (*scan == '\n')
|
||||
{
|
||||
/* reset length at newline */
|
||||
len = 0;
|
||||
lines++;
|
||||
}
|
||||
else
|
||||
{
|
||||
len++;
|
||||
}
|
||||
}
|
||||
|
||||
/* add the text */
|
||||
*scan = '\0';
|
||||
add(tomark, tmpblk.c);
|
||||
tomark += MARK_AT_LINE(lines) + len - markidx(tomark);
|
||||
}
|
||||
|
||||
/* if partial last line, then retain that first newline */
|
||||
if (len > 0)
|
||||
{
|
||||
msg("Last line had no newline");
|
||||
tomark += BLKSIZE; /* <- for the rptlines calc */
|
||||
}
|
||||
else /* delete that first newline */
|
||||
{
|
||||
delete(tomark, (tomark | (BLKSIZE - 1L)) + 1L);
|
||||
}
|
||||
}
|
||||
|
||||
/* close the file */
|
||||
close(fd);
|
||||
|
||||
/* Reporting... */
|
||||
rptlines = markline(tomark) - markline(frommark);
|
||||
rptlabel = "read";
|
||||
if (mode == MODE_EX)
|
||||
{
|
||||
cursor = (tomark & ~BLKSIZE) - BLKSIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
cursor = frommark;
|
||||
}
|
||||
|
||||
if (addnl)
|
||||
msg("Newlines were added to break up long lines");
|
||||
if (hadnul)
|
||||
msg("NULs were converted to 0x80");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*ARGSUSED*/
|
||||
void cmd_undo(frommark, tomark, cmd, bang, extra)
|
||||
MARK frommark;
|
||||
MARK tomark;
|
||||
CMD cmd;
|
||||
int bang;
|
||||
char *extra;
|
||||
{
|
||||
undo();
|
||||
}
|
||||
|
||||
|
||||
/* print the selected lines */
|
||||
/*ARGSUSED*/
|
||||
void cmd_print(frommark, tomark, cmd, bang, extra)
|
||||
MARK frommark;
|
||||
MARK tomark;
|
||||
CMD cmd;
|
||||
int bang;
|
||||
char *extra;
|
||||
{
|
||||
REG char *scan;
|
||||
REG long l;
|
||||
REG int col;
|
||||
|
||||
for (l = markline(frommark); l <= markline(tomark); l++)
|
||||
{
|
||||
/* display a line number, if CMD_NUMBER */
|
||||
if (cmd == CMD_NUMBER)
|
||||
{
|
||||
sprintf(tmpblk.c, "%6ld ", l);
|
||||
qaddstr(tmpblk.c);
|
||||
col = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
col = 0;
|
||||
}
|
||||
|
||||
/* get the next line & display it */
|
||||
for (scan = fetchline(l); *scan; scan++)
|
||||
{
|
||||
/* expand tabs to the proper width */
|
||||
if (*scan == '\t' && cmd != CMD_LIST)
|
||||
{
|
||||
do
|
||||
{
|
||||
qaddch(' ');
|
||||
col++;
|
||||
} while (col % *o_tabstop != 0);
|
||||
}
|
||||
else if (*scan > 0 && *scan < ' ' || *scan == '\177')
|
||||
{
|
||||
qaddch('^');
|
||||
qaddch(*scan ^ 0x40);
|
||||
col += 2;
|
||||
}
|
||||
else if ((*scan & 0x80) && cmd == CMD_LIST)
|
||||
{
|
||||
sprintf(tmpblk.c, "\\%03o", UCHAR(*scan));
|
||||
qaddstr(tmpblk.c);
|
||||
col += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
qaddch(*scan);
|
||||
col++;
|
||||
}
|
||||
|
||||
/* wrap at the edge of the screen */
|
||||
if (!has_AM && col >= COLS)
|
||||
{
|
||||
addch('\n');
|
||||
col -= COLS;
|
||||
}
|
||||
}
|
||||
if (cmd == CMD_LIST)
|
||||
{
|
||||
qaddch('$');
|
||||
}
|
||||
addch('\n');
|
||||
exrefresh();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* move or copy selected lines */
|
||||
/*ARGSUSED*/
|
||||
void cmd_move(frommark, tomark, cmd, bang, extra)
|
||||
MARK frommark;
|
||||
MARK tomark;
|
||||
CMD cmd;
|
||||
int bang;
|
||||
char *extra;
|
||||
{
|
||||
MARK destmark;
|
||||
|
||||
/* parse the destination linespec. No defaults. Line 0 is okay */
|
||||
destmark = cursor;
|
||||
if (!strcmp(extra, "0"))
|
||||
{
|
||||
destmark = 0L;
|
||||
}
|
||||
else if (linespec(extra, &destmark) == extra || !destmark)
|
||||
{
|
||||
msg("invalid destination address");
|
||||
return;
|
||||
}
|
||||
|
||||
/* flesh the marks out to encompass whole lines */
|
||||
frommark &= ~(BLKSIZE - 1);
|
||||
tomark = (tomark & ~(BLKSIZE - 1)) + BLKSIZE;
|
||||
destmark = (destmark & ~(BLKSIZE - 1)) + BLKSIZE;
|
||||
|
||||
/* make sure the destination is valid */
|
||||
if (cmd == CMD_MOVE && destmark >= frommark && destmark < tomark)
|
||||
{
|
||||
msg("invalid destination address");
|
||||
}
|
||||
|
||||
/* Do it */
|
||||
ChangeText
|
||||
{
|
||||
/* save the text to a cut buffer */
|
||||
cutname('\0');
|
||||
cut(frommark, tomark);
|
||||
|
||||
/* if we're not copying, delete the old text & adjust destmark */
|
||||
if (cmd != CMD_COPY)
|
||||
{
|
||||
delete(frommark, tomark);
|
||||
if (destmark >= frommark)
|
||||
{
|
||||
destmark -= (tomark - frommark);
|
||||
}
|
||||
}
|
||||
|
||||
/* add the new text */
|
||||
paste(destmark, FALSE, FALSE);
|
||||
}
|
||||
|
||||
/* move the cursor to the last line of the moved text */
|
||||
cursor = destmark + (tomark - frommark) - BLKSIZE;
|
||||
if (cursor < MARK_FIRST || cursor >= MARK_LAST + BLKSIZE)
|
||||
{
|
||||
cursor = MARK_LAST;
|
||||
}
|
||||
|
||||
/* Reporting... */
|
||||
rptlabel = ( (cmd == CMD_COPY) ? "copied" : "moved" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* execute EX commands from a file */
|
||||
/*ARGSUSED*/
|
||||
void cmd_source(frommark, tomark, cmd, bang, extra)
|
||||
MARK frommark;
|
||||
MARK tomark;
|
||||
CMD cmd;
|
||||
int bang;
|
||||
char *extra;
|
||||
{
|
||||
/* must have a filename */
|
||||
if (!*extra)
|
||||
{
|
||||
msg("\"source\" requires a filename");
|
||||
return;
|
||||
}
|
||||
|
||||
doexrc(extra);
|
||||
}
|
||||
|
||||
|
||||
#ifndef NO_AT
|
||||
/*ARGSUSED*/
|
||||
void cmd_at(frommark, tomark, cmd, bang, extra)
|
||||
MARK frommark;
|
||||
MARK tomark;
|
||||
CMD cmd;
|
||||
int bang;
|
||||
char *extra;
|
||||
{
|
||||
static nest = FALSE;
|
||||
int result;
|
||||
char buf[MAXRCLEN];
|
||||
|
||||
/* don't allow nested macros */
|
||||
if (nest)
|
||||
{
|
||||
msg("@ macros can't be nested");
|
||||
return;
|
||||
}
|
||||
nest = TRUE;
|
||||
|
||||
/* require a buffer name */
|
||||
if (*extra == '"')
|
||||
extra++;
|
||||
if (!*extra || !isascii(*extra) ||!islower(*extra))
|
||||
{
|
||||
msg("@ requires a cut buffer name (a-z)");
|
||||
}
|
||||
|
||||
/* get the contents of the buffer */
|
||||
result = cb2str(*extra, buf, (unsigned)(sizeof buf));
|
||||
if (result <= 0)
|
||||
{
|
||||
msg("buffer \"%c is empty", *extra);
|
||||
}
|
||||
else if (result >= sizeof buf)
|
||||
{
|
||||
msg("buffer \"%c is too large to execute", *extra);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* execute the contents of the buffer as ex commands */
|
||||
exstring(buf, result, '\\');
|
||||
}
|
||||
|
||||
nest = FALSE;
|
||||
}
|
||||
#endif
|
|
@ -1,526 +0,0 @@
|
|||
/*
|
||||
* vi configuration file
|
||||
* We try to automatically configure to various compilers and operating
|
||||
* systems. Extend the autoconf section as needed.
|
||||
*/
|
||||
|
||||
#ifndef _CONFIG_H
|
||||
# define _CONFIG_H
|
||||
|
||||
/*************************** autoconf section ************************/
|
||||
|
||||
/* Commodore-Amiga */
|
||||
#ifdef amiga
|
||||
# define AMIGA 1
|
||||
# define COMPILED_BY "Manx Aztec C 5.2b"
|
||||
#endif
|
||||
|
||||
/* standard unix V (?) */
|
||||
#ifdef M_SYSV
|
||||
# define UNIXV 1
|
||||
#endif
|
||||
|
||||
/* xelos system, University of Ulm */
|
||||
#ifdef xelos
|
||||
# define UNIXV 1
|
||||
#endif
|
||||
|
||||
/* BSD UNIX? */
|
||||
#ifdef bsd
|
||||
# define BSD 1
|
||||
#else
|
||||
# ifdef sun
|
||||
# define BSD 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Microsoft C: sorry, Watcom does the same thing */
|
||||
#ifdef M_I86
|
||||
# ifndef M_SYSV
|
||||
# define MSDOS 1
|
||||
# ifdef IBMC2
|
||||
# define COMPILED_BY "IBM C/2 1.00"
|
||||
# else
|
||||
# define MICROSOFT 1
|
||||
# define COMPILED_BY "Microsoft C 5.10"
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Borland's Turbo C */
|
||||
#ifdef __TURBOC__
|
||||
# define MSDOS 1
|
||||
# define TURBOC 1
|
||||
# ifdef __BORLANDC__
|
||||
# define COMPILED_BY "Borland C 2.00"
|
||||
# else
|
||||
# define COMPILED_BY (__TURBOC__ >= 661 ? "Turbo C++ 1.00" : "Turbo C 2.00")
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Tos Mark-Williams */
|
||||
#ifdef M68000
|
||||
# define TOS 1
|
||||
# define COMPILED_BY "Mark Williams C"
|
||||
#endif
|
||||
|
||||
/* Tos GNU-C */
|
||||
#if defined(__atarist__) && defined(__gem__)
|
||||
# define TOS 1
|
||||
# define COMPILED_BY "GNU-C " __VERSION__
|
||||
#endif
|
||||
|
||||
/* OS9/68000 */
|
||||
#ifdef OSK
|
||||
# define COMPILED_BY "Microware C V2.3 Edition 40"
|
||||
#endif
|
||||
|
||||
/* DEC Rainbow, running MS-DOS (handled by earlier MS-DOS tests) */
|
||||
/* (would need -DRAINBOW in CFLAGS to compile a Rainbow-compatible .EXE) */
|
||||
|
||||
#ifdef VMS
|
||||
# define COMPILED_BY "VAX/VMS VAXC compiler"
|
||||
# undef VMS
|
||||
# define VMS 1
|
||||
#endif
|
||||
|
||||
/*************************** end of autoconf section ************************/
|
||||
|
||||
/* All undefined symbols are defined to zero here, to allow for older */
|
||||
/* compilers which dont understand #if defined() or #if UNDEFINED_SYMBOL */
|
||||
|
||||
/*************************** operating systems *****************************/
|
||||
|
||||
#ifndef BSD
|
||||
# define BSD 0 /* UNIX - Berkeley 4.x */
|
||||
#endif
|
||||
|
||||
#ifndef UNIXV
|
||||
# define UNIXV 0 /* UNIX - AT&T SYSV */
|
||||
#endif
|
||||
|
||||
#ifndef UNIX7
|
||||
# define UNIX7 0 /* UNIX - version 7 */
|
||||
#endif
|
||||
|
||||
#ifndef MSDOS
|
||||
# define MSDOS 0 /* PC */
|
||||
#endif
|
||||
|
||||
#ifndef TOS
|
||||
# define TOS 0 /* Atari ST */
|
||||
#endif
|
||||
|
||||
#ifndef AMIGA
|
||||
# define AMIGA 0 /* Commodore Amiga */
|
||||
#endif
|
||||
|
||||
#ifndef OSK
|
||||
# define OSK 0 /* OS-9 / 68k */
|
||||
#endif
|
||||
|
||||
#ifndef COHERENT
|
||||
# define COHERENT 0 /* Coherent */
|
||||
#endif
|
||||
|
||||
#ifndef RAINBOW /* DEC Rainbow support, under MS-DOS */
|
||||
# define RAINBOW 0
|
||||
#endif
|
||||
|
||||
#ifndef VMS
|
||||
# define VMS 0 /* VAX/VMS */
|
||||
#endif
|
||||
/* Minix has no predefines */
|
||||
#if !BSD && !UNIXV && !UNIX7 && !MSDOS && !TOS && !AMIGA && !OSK && !COHERENT && !VMS
|
||||
# define MINIX 1
|
||||
#else
|
||||
# define MINIX 0
|
||||
#endif
|
||||
|
||||
/* generic combination of Unices */
|
||||
#if UNIXV || UNIX7 || BSD || MINIX || COHERENT
|
||||
# define ANY_UNIX 1
|
||||
#else
|
||||
# define ANY_UNIX 0
|
||||
#endif
|
||||
|
||||
/*************************** compilers **************************************/
|
||||
|
||||
#ifndef AZTEC_C
|
||||
# define AZTEC_C 0
|
||||
#endif
|
||||
|
||||
#ifndef MICROSOFT
|
||||
# define MICROSOFT 0
|
||||
#endif
|
||||
|
||||
#ifndef TURBOC
|
||||
# define TURBOC 0
|
||||
#endif
|
||||
|
||||
/******************************* Credit ************************************/
|
||||
|
||||
#if MSDOS
|
||||
# define CREDIT "Ported to MS-DOS by Guntram Blohm & Martin Patzel"
|
||||
# if RAINBOW
|
||||
# define CREDIT2 "Rainbow support added by Willett Kempton"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if AMIGA
|
||||
# define CREDIT "Ported to AmigaDOS 2.04 by Mike Rieser & Dale Rahn"
|
||||
#endif
|
||||
|
||||
#if TOS
|
||||
# define CREDIT "Ported to Atari/TOS by Guntram Blohm & Martin Patzel"
|
||||
#endif
|
||||
|
||||
#if OSK
|
||||
# define CREDIT "Ported to Microware OS9/68k by Peter Reinig"
|
||||
#endif
|
||||
|
||||
#if COHERENT
|
||||
# define CREDIT "Ported to Coherent by Esa Ahola"
|
||||
#endif
|
||||
|
||||
#if VMS
|
||||
# define CREDIT "Ported to VAX/VMS by John Campbell"
|
||||
#endif
|
||||
/*************************** functions depending on OS *********************/
|
||||
|
||||
/* There are two terminal-related functions that we need: ttyread() and
|
||||
* ttywrite(). The ttyread() function implements read-with-timeout and is
|
||||
* a true function on all systems. The ttywrite() function is almost always
|
||||
* just a macro...
|
||||
*/
|
||||
#if !TOS && !AMIGA
|
||||
# define ttywrite(buf, len) write(1, buf, (unsigned)(len)) /* raw write */
|
||||
#endif
|
||||
|
||||
/* The strchr() function is an official standard now, so everybody has it
|
||||
* except Unix version 7 (which is old) and BSD Unix (which is academic).
|
||||
* Those guys use something called index() to do the same thing.
|
||||
*/
|
||||
#if BSD || UNIX7 || OSK
|
||||
# define strchr index
|
||||
#endif
|
||||
extern char *strchr();
|
||||
|
||||
/* BSD uses bcopy() instead of memcpy() */
|
||||
#if BSD
|
||||
# define memcpy(dest, src, siz) bcopy(src, dest, siz)
|
||||
#endif
|
||||
|
||||
/* BSD uses getwd() instead of getcwd(). The arguments are a little different,
|
||||
* but we'll ignore that and hope for the best; adding arguments to the macro
|
||||
* would mess up an "extern" declaration of the function.
|
||||
*/
|
||||
#if BSD || COHERENT
|
||||
# define getcwd getwd
|
||||
#endif
|
||||
extern char *getcwd();
|
||||
|
||||
/* text versa binary mode for read/write */
|
||||
#if !TOS
|
||||
#define tread(fd,buf,n) read(fd,buf,(unsigned)(n))
|
||||
#define twrite(fd,buf,n) write(fd,buf,(unsigned)(n))
|
||||
#endif
|
||||
|
||||
/**************************** Compiler quirks *********************************/
|
||||
|
||||
/* the UNIX version 7 and (some) TOS compilers, don't allow "void" */
|
||||
#if UNIX7 || TOS
|
||||
# define void int
|
||||
#endif
|
||||
|
||||
/* as far as I know, all compilers except version 7 support unsigned char */
|
||||
/* NEWFLASH: the Minix-ST compiler has subtle problems with unsigned char */
|
||||
#if UNIX7 || MINIX
|
||||
# define UCHAR(c) ((c) & 0xff)
|
||||
# define uchar char
|
||||
#else
|
||||
# define UCHAR(c) ((unsigned char)(c))
|
||||
# define uchar unsigned char
|
||||
#endif
|
||||
|
||||
/* Some compilers prefer to have malloc declared as returning a (void *) */
|
||||
#if BSD || AMIGA
|
||||
extern void *malloc();
|
||||
#else
|
||||
extern char *malloc();
|
||||
#endif
|
||||
|
||||
/* everybody but Amiga wants lseek declared here */
|
||||
/* LSC: MINIX Does not want it either! */
|
||||
#if !AMIGA && !defined(__minix)
|
||||
extern long lseek();
|
||||
#endif
|
||||
|
||||
/******************* Names of files and environment vars **********************/
|
||||
|
||||
#if ANY_UNIX
|
||||
# ifndef TMPDIR
|
||||
# if MINIX
|
||||
# define TMPDIR "/tmp"
|
||||
# endif
|
||||
# endif
|
||||
# ifndef PRSVDIR
|
||||
# define PRSVDIR "/usr/preserve" /* directory where preserved file live */
|
||||
# endif
|
||||
# ifndef PRSVINDEX
|
||||
# define PRSVINDEX "/usr/preserve/Index" /* index of files in PRSVDIR */
|
||||
# endif
|
||||
# ifndef EXRC
|
||||
# define EXRC ".exrc" /* init file in current directory */
|
||||
# endif
|
||||
# define SCRATCHOUT "%s/soXXXXXX" /* temp file used as input to filter */
|
||||
# ifndef SHELL
|
||||
# define SHELL "/bin/sh" /* default shell */
|
||||
# endif
|
||||
# if COHERENT
|
||||
# ifndef REDIRECT
|
||||
# define REDIRECT ">" /* Coherent CC writes errors to stdout */
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if AMIGA /* Specify AMIGA environment */
|
||||
# ifndef CC_COMMAND
|
||||
# define CC_COMMAND "cc" /* generic C compiler */
|
||||
# endif
|
||||
# ifndef COLON
|
||||
# define COLON ':' /* Amiga files can also end in `:' */
|
||||
# endif
|
||||
# ifndef SYSEXRC
|
||||
# define SYSEXRC "S:" EXRC /* name of ".exrc" file in system dir */
|
||||
# endif
|
||||
# ifndef MAXRCLEN
|
||||
# define MAXRCLEN 2048 /* max size of a .exrc file */
|
||||
# endif
|
||||
# ifndef NBUFS
|
||||
# define NBUFS 10 /* must be at least 3 -- more is better */
|
||||
# endif
|
||||
# ifndef NEEDSYNC
|
||||
# define NEEDSYNC TRUE /* assume ":se sync" by default */
|
||||
# endif
|
||||
# ifndef PRSVDIR
|
||||
# define PRSVDIR "Elvis:" /* directory where preserved file live */
|
||||
# endif
|
||||
# ifndef PRSVINDEX
|
||||
# define PRSVINDEX "Elvis:Index" /* index of files in PRSVDIR */
|
||||
# endif
|
||||
# ifndef REDIRECT
|
||||
# define REDIRECT ">" /* Amiga writes errors to stdout */
|
||||
# endif
|
||||
# ifndef SCRATCHIN
|
||||
# define SCRATCHIN "%sSIXXXXXX"
|
||||
# endif
|
||||
# ifndef SCRATCHOUT
|
||||
# define SCRATCHOUT "%sSOXXXXXX"
|
||||
# endif
|
||||
# ifndef SHELL
|
||||
# define SHELL "newshell" /* default shell */
|
||||
# endif
|
||||
# ifndef TERMTYPE
|
||||
# define TERMTYPE "amiga" /* default termtype */
|
||||
# endif
|
||||
# ifndef TMPDIR /* for AMIGA should end in `:' or `/' */
|
||||
# define TMPDIR "T:" /* directory where temp files live */
|
||||
# endif
|
||||
# ifndef TMPNAME
|
||||
# define TMPNAME "%selv_%x.%x" /* format of names for temp files */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if MSDOS || TOS
|
||||
/* do not change TMPNAME and SCRATCH*: they MUST begin with '%s\\'! */
|
||||
# ifndef TMPDIR
|
||||
# define TMPDIR "C:\\tmp" /* directory where temp files live */
|
||||
# endif
|
||||
# ifndef PRSVDIR
|
||||
# define PRSVDIR "C:\\preserve" /* directory where preserved file live */
|
||||
# endif
|
||||
# ifndef PRSVINDEX
|
||||
# define PRSVINDEX "C:\\preserve\\Index" /* index of files in PRSVDIR */
|
||||
# endif
|
||||
# define TMPNAME "%s\\elv_%x.%x" /* temp file */
|
||||
# if MSDOS
|
||||
# if MICROSOFT
|
||||
# define CC_COMMAND "cl -c" /* C compiler */
|
||||
# else
|
||||
# if __BORLANDC__ /* Borland C */
|
||||
# define CC_COMMAND "bcc" /* C compiler */
|
||||
# else
|
||||
# if TURBOC /* Turbo C */
|
||||
# define CC_COMMAND "tcc" /* C compiler */
|
||||
# endif /* TURBOC */
|
||||
# endif /* BORLANDC */
|
||||
# endif /* MICROSOFT */
|
||||
# endif /* MSDOS */
|
||||
# define SCRATCHIN "%s\\siXXXXXX" /* DOS ONLY - output of filter program */
|
||||
# define SCRATCHOUT "%s\\soXXXXXX" /* temp file used as input to filter */
|
||||
# define SLASH '\\'
|
||||
# ifndef SHELL
|
||||
# if TOS
|
||||
# define SHELL "shell.ttp" /* default shell */
|
||||
# else
|
||||
# define SHELL "command.com" /* default shell */
|
||||
# endif
|
||||
# endif
|
||||
# define NEEDSYNC TRUE /* assume ":se sync" by default */
|
||||
# if TOS && __GNUC__ /* probably on other systems, too */
|
||||
# define REDIRECT "2>" /* GNUC reports on 2, others on 1 */
|
||||
# define CC_COMMAND "gcc -c"
|
||||
# else
|
||||
# define REDIRECT ">" /* shell's redirection of stderr */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if VMS
|
||||
/* do not change TMPNAME, and SCRATCH*: they MUST begin with '%s\\'! */
|
||||
# ifndef TMPDIR
|
||||
# define TMPDIR "sys$scratch:" /* directory where temp files live */
|
||||
# endif
|
||||
# define TMPNAME "%selv_%x.%x;1" /* temp file */
|
||||
# define SCRATCHIN "%ssiXXXXXX" /* DOS ONLY - output of filter program */
|
||||
# define SCRATCHOUT "%ssoXXXXXX" /* temp file used as input to filter */
|
||||
# define SLASH '\:' /* Worry point... jdc */
|
||||
# ifndef SHELL
|
||||
# define SHELL "" /* default shell */
|
||||
# endif
|
||||
# define REDIRECT ">" /* shell's redirection of stderr */
|
||||
# define tread(fd,buf,n) vms_read(fd,buf,(unsigned)(n))
|
||||
# define close vms_close
|
||||
# define lseek vms_lseek
|
||||
# define unlink vms_delete
|
||||
# define delete __delete /* local routine conflicts w/VMS rtl routine. */
|
||||
# define rpipe vms_rpipe
|
||||
# define rpclose vms_rpclose
|
||||
# define ttyread vms_ttyread
|
||||
/* There is no sync() on vms */
|
||||
# define sync()
|
||||
/* jdc -- seems VMS external symbols are case insensitive */
|
||||
# define m_fWord m_fw_ord
|
||||
# define m_bWord m_bw_ord
|
||||
# define m_eWord m_ew_ord
|
||||
# define m_Nsrch m_n_srch
|
||||
# define m_Fch m_f_ch
|
||||
# define m_Tch m_t_ch
|
||||
# define v_Xchar v_x_char
|
||||
/* jdc -- also, braindead vms curses always found by linker. */
|
||||
# define LINES elvis_LINES
|
||||
# define COLS elvis_COLS
|
||||
# define curscr elvis_curscr
|
||||
# define stdscr elvis_stdscr
|
||||
# define initscr elvis_initscr
|
||||
# define endwin elvis_endwin
|
||||
# define wrefresh elvis_wrefresh
|
||||
#endif
|
||||
|
||||
#if OSK
|
||||
# ifndef TMPDIR
|
||||
# define TMPDIR "/dd/tmp" /* directory where temp files live */
|
||||
# endif
|
||||
# ifndef PRSVDIR
|
||||
# define PRSVDIR "/dd/usr/preserve" /* directory where preserved file live */
|
||||
# endif
|
||||
# ifndef PRSVINDEX
|
||||
# define PRSVINDEX "/dd/usr/preserve/Index" /* index of files in PRSVDIR */
|
||||
# endif
|
||||
# ifndef CC_COMMAND
|
||||
# define CC_COMMAND "cc -r" /* name of the compiler */
|
||||
# endif
|
||||
# ifndef EXRC
|
||||
# define EXRC ".exrc" /* init file in current directory */
|
||||
# endif
|
||||
# define SCRATCHOUT "%s/soXXXXXX" /* temp file used as input to filter */
|
||||
# ifndef SHELL
|
||||
# define SHELL "shell" /* default shell */
|
||||
# endif
|
||||
# define FILEPERMS (S_IREAD|S_IWRITE) /* file permissions used for creat() */
|
||||
# define REDIRECT ">>-" /* shell's redirection of stderr */
|
||||
# define sync() /* OS9 doesn't need a sync() */
|
||||
#endif
|
||||
|
||||
#ifndef TAGS
|
||||
# define TAGS "tags" /* name of the tags file */
|
||||
#endif
|
||||
|
||||
#ifndef TMPNAME
|
||||
# define TMPNAME "%s/elv_%x.%x" /* format of names for temp files */
|
||||
#endif
|
||||
|
||||
#ifndef EXINIT
|
||||
# define EXINIT "EXINIT" /* name of EXINIT environment variable */
|
||||
#endif
|
||||
|
||||
#ifndef EXRC
|
||||
# define EXRC "elvis.rc" /* name of ".exrc" file in current dir */
|
||||
#endif
|
||||
|
||||
#ifndef HMEXRC
|
||||
# define HMEXRC EXRC /* name of ".exrc" file in home dir */
|
||||
#endif
|
||||
|
||||
#ifndef KEYWORDPRG
|
||||
# define KEYWORDPRG "ref"
|
||||
#endif
|
||||
|
||||
#ifndef SCRATCHOUT
|
||||
# define SCRATCHIN "%s/SIXXXXXX"
|
||||
# define SCRATCHOUT "%s/SOXXXXXX"
|
||||
#endif
|
||||
|
||||
#ifndef ERRLIST
|
||||
# define ERRLIST "errlist"
|
||||
#endif
|
||||
|
||||
#ifndef SLASH
|
||||
# define SLASH '/'
|
||||
#endif
|
||||
|
||||
#ifndef SHELL
|
||||
# define SHELL "shell"
|
||||
#endif
|
||||
|
||||
#ifndef REG
|
||||
# define REG register
|
||||
#endif
|
||||
|
||||
#ifndef NEEDSYNC
|
||||
# define NEEDSYNC FALSE
|
||||
#endif
|
||||
|
||||
#ifndef FILEPERMS
|
||||
# define FILEPERMS 0666
|
||||
#endif
|
||||
|
||||
#ifndef PRESERVE
|
||||
# define PRESERVE "elvprsv" /* name of the "preserve" program */
|
||||
#endif
|
||||
|
||||
#ifndef CC_COMMAND
|
||||
# define CC_COMMAND "cc -c"
|
||||
#endif
|
||||
|
||||
#ifndef MAKE_COMMAND
|
||||
# define MAKE_COMMAND "make"
|
||||
#endif
|
||||
|
||||
#ifndef REDIRECT
|
||||
# define REDIRECT "2>"
|
||||
#endif
|
||||
|
||||
#ifndef BLKSIZE
|
||||
# ifdef CRUNCH
|
||||
# define BLKSIZE 1024
|
||||
# else
|
||||
# define BLKSIZE 2048
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef KEYBUFSIZE
|
||||
# define KEYBUFSIZE 1000
|
||||
#endif
|
||||
|
||||
#endif /* ndef _CONFIG_H */
|
|
@ -1,819 +0,0 @@
|
|||
/* ctags.c */
|
||||
|
||||
/* This is a reimplementation of the ctags(1) program. It supports ANSI C,
|
||||
* and has heaps o' flags. It is meant to be distributed with elvis.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "config.h"
|
||||
#ifndef FALSE
|
||||
# define FALSE 0
|
||||
# define TRUE 1
|
||||
#endif
|
||||
#ifndef TAGS
|
||||
# define TAGS "tags"
|
||||
#endif
|
||||
#ifndef REFS
|
||||
# define REFS "refs"
|
||||
#endif
|
||||
#ifndef BLKSIZE
|
||||
# define BLKSIZE 1024
|
||||
#endif
|
||||
|
||||
#include "ctype.c" /* yes, that really is the .c file, not the .h one. */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Some global variables */
|
||||
|
||||
/* The following boolean variables are set according to command line flags */
|
||||
int incl_static; /* -s include static tags */
|
||||
int incl_types; /* -t include typedefs and structs */
|
||||
int incl_vars; /* -v include variables */
|
||||
int make_refs; /* -r generate a "refs" file */
|
||||
int append_files; /* -a append to "tags" [and "refs"] files */
|
||||
|
||||
/* The following are used for outputting to the "tags" and "refs" files */
|
||||
FILE *tags; /* used for writing to the "tags" file */
|
||||
FILE *refs; /* used for writing to the "refs" file */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* These are used for reading a source file. It keeps track of line numbers */
|
||||
char *file_name; /* name of the current file */
|
||||
FILE *file_fp; /* stream used for reading the file */
|
||||
long file_lnum; /* line number in the current file */
|
||||
long file_seek; /* fseek() offset to the start of current line */
|
||||
int file_afternl; /* boolean: was previous character a newline? */
|
||||
int file_prevch; /* a single character that was ungotten */
|
||||
int file_header; /* boolean: is the current file a header file? */
|
||||
|
||||
/* This function opens a file, and resets the line counter. If it fails, it
|
||||
* it will display an error message and leave the file_fp set to NULL.
|
||||
*/
|
||||
void file_open(name)
|
||||
char *name; /* name of file to be opened */
|
||||
{
|
||||
/* if another file was already open, then close it */
|
||||
if (file_fp)
|
||||
{
|
||||
fclose(file_fp);
|
||||
}
|
||||
|
||||
/* try to open the file for reading. The file must be opened in
|
||||
* "binary" mode because otherwise fseek() would misbehave under DOS.
|
||||
*/
|
||||
#if MSDOS || TOS
|
||||
file_fp = fopen(name, "rb");
|
||||
#else
|
||||
file_fp = fopen(name, "r");
|
||||
#endif
|
||||
if (!file_fp)
|
||||
{
|
||||
perror(name);
|
||||
}
|
||||
|
||||
/* reset the name & line number */
|
||||
file_name = name;
|
||||
file_lnum = 0L;
|
||||
file_seek = 0L;
|
||||
file_afternl = TRUE;
|
||||
|
||||
/* determine whether this is a header file */
|
||||
file_header = FALSE;
|
||||
name += strlen(name) - 2;
|
||||
if (name >= file_name && name[0] == '.' && (name[1] == 'h' || name[1] == 'H'))
|
||||
{
|
||||
file_header = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* This function reads a single character from the stream. If the *previous*
|
||||
* character was a newline, then it also increments file_lnum and sets
|
||||
* file_offset.
|
||||
*/
|
||||
int file_getc()
|
||||
{
|
||||
int ch;
|
||||
|
||||
/* if there is an ungotten character, then return it. Don't do any
|
||||
* other processing on it, though, because we already did that the
|
||||
* first time it was read.
|
||||
*/
|
||||
if (file_prevch)
|
||||
{
|
||||
ch = file_prevch;
|
||||
file_prevch = 0;
|
||||
return ch;
|
||||
}
|
||||
|
||||
/* if previous character was a newline, then we're starting a line */
|
||||
if (file_afternl)
|
||||
{
|
||||
file_afternl = FALSE;
|
||||
file_seek = ftell(file_fp);
|
||||
file_lnum++;
|
||||
}
|
||||
|
||||
/* Get a character. If no file is open, then return EOF */
|
||||
ch = (file_fp ? getc(file_fp) : EOF);
|
||||
|
||||
/* if it is a newline, then remember that fact */
|
||||
if (ch == '\n')
|
||||
{
|
||||
file_afternl = TRUE;
|
||||
}
|
||||
|
||||
/* return the character */
|
||||
return ch;
|
||||
}
|
||||
|
||||
/* This function ungets a character from the current source file */
|
||||
void file_ungetc(ch)
|
||||
int ch; /* character to be ungotten */
|
||||
{
|
||||
file_prevch = ch;
|
||||
}
|
||||
|
||||
/* This function copies the current line out some other fp. It has no effect
|
||||
* on the file_getc() function. During copying, any '\' characters are doubled
|
||||
* and a leading '^' or trailing '$' is also quoted. The newline character is
|
||||
* not copied.
|
||||
*
|
||||
* This is meant to be used when generating a tag line.
|
||||
*/
|
||||
void file_copyline(seek, fp)
|
||||
long seek; /* where the lines starts in the source file */
|
||||
FILE *fp; /* the output stream to copy it to */
|
||||
{
|
||||
long oldseek;/* where the file's pointer was before we messed it up */
|
||||
char ch; /* a single character from the file */
|
||||
char next; /* the next character from this file */
|
||||
|
||||
/* go to the start of the line */
|
||||
oldseek = ftell(file_fp);
|
||||
fseek(file_fp, seek, 0);
|
||||
|
||||
/* if first character is '^', then emit \^ */
|
||||
ch = getc(file_fp);
|
||||
if (ch == '^')
|
||||
{
|
||||
putc('\\', fp);
|
||||
putc('^', fp);
|
||||
ch = getc(file_fp);
|
||||
}
|
||||
|
||||
/* write everything up to, but not including, the newline */
|
||||
while (ch != '\n')
|
||||
{
|
||||
/* preread the next character from this file */
|
||||
next = getc(file_fp);
|
||||
|
||||
/* if character is '\', or a terminal '$', then quote it */
|
||||
if (ch == '\\' || (ch == '$' && next == '\n'))
|
||||
{
|
||||
putc('\\', fp);
|
||||
}
|
||||
putc(ch, fp);
|
||||
|
||||
/* next character... */
|
||||
ch = next;
|
||||
}
|
||||
|
||||
/* seek back to the old position */
|
||||
fseek(file_fp, oldseek, 0);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* This section handles preprocessor directives. It strips out all of the
|
||||
* directives, and may emit a tag for #define directives.
|
||||
*/
|
||||
|
||||
int cpp_afternl; /* boolean: look for '#' character? */
|
||||
int cpp_prevch; /* an ungotten character, if any */
|
||||
int cpp_refsok; /* boolean: can we echo characters out to "refs"? */
|
||||
|
||||
/* This function opens the file & resets variables */
|
||||
void cpp_open(name)
|
||||
char *name; /* name of source file to be opened */
|
||||
{
|
||||
/* use the lower-level file_open function to open the file */
|
||||
file_open(name);
|
||||
|
||||
/* reset variables */
|
||||
cpp_afternl = TRUE;
|
||||
cpp_refsok = TRUE;
|
||||
}
|
||||
|
||||
/* This function copies a character from the source file to the "refs" file */
|
||||
void cpp_echo(ch)
|
||||
int ch; /* the character to copy */
|
||||
{
|
||||
static wasnl;
|
||||
|
||||
/* echo non-EOF chars, unless not making "ref", or echo turned off */
|
||||
if (ch != EOF && make_refs && cpp_refsok && !file_header)
|
||||
{
|
||||
/* try to avoid blank lines */
|
||||
if (ch == '\n')
|
||||
{
|
||||
if (wasnl)
|
||||
{
|
||||
return;
|
||||
}
|
||||
wasnl = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
wasnl = FALSE;
|
||||
}
|
||||
|
||||
/* add the character */
|
||||
putc(ch, refs);
|
||||
}
|
||||
}
|
||||
|
||||
/* This function returns the next character which isn't part of a directive */
|
||||
int cpp_getc()
|
||||
{
|
||||
static
|
||||
int ch; /* the next input character */
|
||||
char *scan;
|
||||
|
||||
/* if we have an ungotten character, then return it */
|
||||
if (cpp_prevch)
|
||||
{
|
||||
ch = cpp_prevch;
|
||||
cpp_prevch = 0;
|
||||
return ch;
|
||||
}
|
||||
|
||||
/* Get a character from the file. Return it if not special '#' */
|
||||
ch = file_getc();
|
||||
if (ch == '\n')
|
||||
{
|
||||
cpp_afternl = TRUE;
|
||||
cpp_echo(ch);
|
||||
return ch;
|
||||
}
|
||||
else if (ch != '#' || !cpp_afternl)
|
||||
{
|
||||
/* normal character. Any non-whitespace should turn off afternl */
|
||||
if (ch != ' ' && ch != '\t')
|
||||
{
|
||||
cpp_afternl = FALSE;
|
||||
}
|
||||
cpp_echo(ch);
|
||||
return ch;
|
||||
}
|
||||
|
||||
/* Yikes! We found a directive */
|
||||
|
||||
/* see whether this is a #define line */
|
||||
scan = " define ";
|
||||
while (*scan)
|
||||
{
|
||||
if (*scan == ' ')
|
||||
{
|
||||
/* space character matches any whitespace */
|
||||
do
|
||||
{
|
||||
ch = file_getc();
|
||||
} while (ch == ' ' || ch == '\t');
|
||||
file_ungetc(ch);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* other characters should match exactly */
|
||||
ch = file_getc();
|
||||
if (ch != *scan)
|
||||
{
|
||||
file_ungetc(ch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
scan++;
|
||||
}
|
||||
|
||||
/* is this a #define line? and should we generate a tag for it? */
|
||||
if (!*scan && (file_header || incl_static))
|
||||
{
|
||||
/* if not a header, then this will be a static tag */
|
||||
if (!file_header)
|
||||
{
|
||||
fputs(file_name, tags);
|
||||
putc(':', tags);
|
||||
}
|
||||
|
||||
/* output the tag name */
|
||||
for (ch = file_getc(); isalnum(ch) || ch == '_'; ch = file_getc())
|
||||
{
|
||||
putc(ch, tags);
|
||||
}
|
||||
|
||||
/* output a tab, the filename, another tab, and the line number */
|
||||
fprintf(tags, "\t%s\t%ld\n", file_name, file_lnum);
|
||||
}
|
||||
|
||||
/* skip to the end of the directive -- a newline that isn't preceded
|
||||
* by a '\' character.
|
||||
*/
|
||||
while (ch != EOF && ch != '\n')
|
||||
{
|
||||
if (ch == '\\')
|
||||
{
|
||||
ch = file_getc();
|
||||
}
|
||||
ch = file_getc();
|
||||
}
|
||||
|
||||
/* return the newline that we found at the end of the directive */
|
||||
cpp_echo(ch);
|
||||
return ch;
|
||||
}
|
||||
|
||||
/* This puts a character back into the input queue for the source file */
|
||||
cpp_ungetc(ch)
|
||||
int ch; /* a character to be ungotten */
|
||||
{
|
||||
cpp_prevch = ch;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* This is the lexical analyser. It gets characters from the preprocessor,
|
||||
* and gives tokens to the parser. Some special codes are...
|
||||
* (deleted) / *...* / (comments)
|
||||
* (deleted) //...\n (comments)
|
||||
* (deleted) (* (parens used in complex declaration)
|
||||
* (deleted) [...] (array subscript, when ... contains no ])
|
||||
* (deleted) struct (intro to structure declaration)
|
||||
* BODY {...} ('{' can occur anywhere, '}' only at BOW if ... has '{')
|
||||
* ARGS (...{ (args of function, not extern or forward)
|
||||
* ARGS (...); (args of an extern/forward function declaration)
|
||||
* COMMA , (separate declarations that have same scope)
|
||||
* SEMICOLON ; (separate declarations that have different scope)
|
||||
* SEMICOLON =...; (initializer)
|
||||
* TYPEDEF typedef (the "typedef" keyword)
|
||||
* STATIC static (the "static" keyword)
|
||||
* STATIC private (the "static" keyword)
|
||||
* STATIC PRIVATE (the "static" keyword)
|
||||
* NAME [a-z]+ (really any valid name that isn't reserved word)
|
||||
*/
|
||||
|
||||
/* #define EOF -1 */
|
||||
#define DELETED 0
|
||||
#define BODY 1
|
||||
#define ARGS 2
|
||||
#define COMMA 3
|
||||
#define SEMICOLON 4
|
||||
#define TYPEDEF 5
|
||||
#define STATIC 6
|
||||
#define EXTERN 7
|
||||
#define NAME 8
|
||||
|
||||
char lex_name[BLKSIZE]; /* the name of a "NAME" token */
|
||||
long lex_seek; /* start of line that contains lex_name */
|
||||
|
||||
lex_gettoken()
|
||||
{
|
||||
int ch; /* a character from the preprocessor */
|
||||
int next; /* the next character */
|
||||
int token; /* the token that we'll return */
|
||||
int i;
|
||||
|
||||
/* loop until we get a token that isn't "DELETED" */
|
||||
do
|
||||
{
|
||||
/* get the next character */
|
||||
ch = cpp_getc();
|
||||
|
||||
/* process the character */
|
||||
switch (ch)
|
||||
{
|
||||
case ',':
|
||||
token = COMMA;
|
||||
break;
|
||||
|
||||
case ';':
|
||||
token = SEMICOLON;
|
||||
break;
|
||||
|
||||
case '/':
|
||||
/* get the next character */
|
||||
ch = cpp_getc();
|
||||
switch (ch)
|
||||
{
|
||||
case '*': /* start of C comment */
|
||||
ch = cpp_getc();
|
||||
next = cpp_getc();
|
||||
while (next != EOF && (ch != '*' || next != '/'))
|
||||
{
|
||||
ch = next;
|
||||
next = cpp_getc();
|
||||
}
|
||||
break;
|
||||
|
||||
case '/': /* start of a C++ comment */
|
||||
do
|
||||
{
|
||||
ch = cpp_getc();
|
||||
} while (ch != '\n' && ch != EOF);
|
||||
break;
|
||||
|
||||
default: /* some other slash */
|
||||
cpp_ungetc(ch);
|
||||
}
|
||||
token = DELETED;
|
||||
break;
|
||||
|
||||
case '(':
|
||||
ch = cpp_getc();
|
||||
if (ch == '*')
|
||||
{
|
||||
token = DELETED;
|
||||
}
|
||||
else
|
||||
{
|
||||
next = cpp_getc();
|
||||
while (ch != '{' && ch != EOF && (ch != ')' || next != ';'))/*}*/
|
||||
{
|
||||
ch = next;
|
||||
next = cpp_getc();
|
||||
}
|
||||
if (ch == '{')/*}*/
|
||||
{
|
||||
cpp_ungetc(ch);
|
||||
}
|
||||
else if (next == ';')
|
||||
{
|
||||
cpp_ungetc(next);
|
||||
}
|
||||
token = ARGS;
|
||||
}
|
||||
break;
|
||||
|
||||
case '{':/*}*/
|
||||
/* don't send the next characters to "refs" */
|
||||
cpp_refsok = FALSE;
|
||||
|
||||
/* skip ahead to closing '}', or to embedded '{' */
|
||||
do
|
||||
{
|
||||
ch = cpp_getc();
|
||||
} while (ch != '{' && ch != '}' && ch != EOF);
|
||||
|
||||
/* if has embedded '{', then skip to '}' in column 1 */
|
||||
if (ch == '{') /*}*/
|
||||
{
|
||||
ch = cpp_getc();
|
||||
next = cpp_getc();
|
||||
while (ch != EOF && (ch != '\n' || next != '}'))/*{*/
|
||||
{
|
||||
ch = next;
|
||||
next = cpp_getc();
|
||||
}
|
||||
}
|
||||
|
||||
/* resume "refs" processing */
|
||||
cpp_refsok = TRUE;
|
||||
cpp_echo('}');
|
||||
|
||||
token = BODY;
|
||||
break;
|
||||
|
||||
case '[':
|
||||
/* skip to matching ']' */
|
||||
do
|
||||
{
|
||||
ch = cpp_getc();
|
||||
} while (ch != ']' && ch != EOF);
|
||||
token = DELETED;
|
||||
break;
|
||||
|
||||
case '=':
|
||||
/* skip to next ';' */
|
||||
do
|
||||
{
|
||||
ch = cpp_getc();
|
||||
|
||||
/* leave array initializers out of "refs" */
|
||||
if (ch == '{')
|
||||
{
|
||||
cpp_refsok = FALSE;
|
||||
}
|
||||
} while (ch != ';' && ch != EOF);
|
||||
|
||||
/* resume echoing to "refs" */
|
||||
if (!cpp_refsok)
|
||||
{
|
||||
cpp_refsok = TRUE;
|
||||
cpp_echo('}');
|
||||
cpp_echo(';');
|
||||
}
|
||||
token = SEMICOLON;
|
||||
break;
|
||||
|
||||
case EOF:
|
||||
token = EOF;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* is this the start of a name/keyword? */
|
||||
if (isalpha(ch) || ch == '_')
|
||||
{
|
||||
/* collect the whole word */
|
||||
lex_name[0] = ch;
|
||||
for (i = 1, ch = cpp_getc();
|
||||
i < BLKSIZE - 1 && (isalnum(ch) || ch == '_');
|
||||
i++, ch = cpp_getc())
|
||||
{
|
||||
lex_name[i] = ch;
|
||||
}
|
||||
lex_name[i] = '\0';
|
||||
cpp_ungetc(ch);
|
||||
|
||||
/* is it a reserved word? */
|
||||
if (!strcmp(lex_name, "typedef"))
|
||||
{
|
||||
token = TYPEDEF;
|
||||
lex_seek = -1L;
|
||||
}
|
||||
else if (!strcmp(lex_name, "static")
|
||||
|| !strcmp(lex_name, "private")
|
||||
|| !strcmp(lex_name, "PRIVATE"))
|
||||
{
|
||||
token = STATIC;
|
||||
lex_seek = -1L;
|
||||
}
|
||||
else if (!strcmp(lex_name, "extern")
|
||||
|| !strcmp(lex_name, "EXTERN")
|
||||
|| !strcmp(lex_name, "FORWARD"))
|
||||
{
|
||||
token = EXTERN;
|
||||
lex_seek = -1L;
|
||||
}
|
||||
else
|
||||
{
|
||||
token = NAME;
|
||||
lex_seek = file_seek;
|
||||
}
|
||||
}
|
||||
else /* not part of a name/keyword */
|
||||
{
|
||||
token = DELETED;
|
||||
}
|
||||
|
||||
} /* end switch(ch) */
|
||||
|
||||
} while (token == DELETED);
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* This is the parser. It locates tag candidates, and then decides whether to
|
||||
* generate a tag for them.
|
||||
*/
|
||||
|
||||
/* This function generates a tag for the object in lex_name, whose tag line is
|
||||
* located at a given seek offset.
|
||||
*/
|
||||
void maketag(scope, seek)
|
||||
int scope; /* 0 if global, or STATIC if static */
|
||||
long seek; /* the seek offset of the line */
|
||||
{
|
||||
/* output the tagname and filename fields */
|
||||
if (scope == EXTERN)
|
||||
{
|
||||
/* whoa! we should *never* output a tag for "extern" decl */
|
||||
return;
|
||||
}
|
||||
else if (scope == STATIC)
|
||||
{
|
||||
fprintf(tags, "%s:%s\t%s\t", file_name, lex_name, file_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(tags, "%s\t%s\t", lex_name, file_name);
|
||||
}
|
||||
|
||||
/* output the target line */
|
||||
putc('/', tags);
|
||||
putc('^', tags);
|
||||
file_copyline(seek, tags);
|
||||
putc('$', tags);
|
||||
putc('/', tags);
|
||||
putc('\n', tags);
|
||||
}
|
||||
|
||||
|
||||
/* This function parses a source file, adding any tags that it finds */
|
||||
void ctags(name)
|
||||
char *name; /* the name of a source file to be checked */
|
||||
{
|
||||
int prev; /* the previous token from the source file */
|
||||
int token; /* the current token from the source file */
|
||||
int scope; /* normally 0, but could be a TYPEDEF or STATIC token */
|
||||
int gotname;/* boolean: does lex_name contain a tag candidate? */
|
||||
long tagseek;/* start of line that contains lex_name */
|
||||
|
||||
/* open the file */
|
||||
cpp_open(name);
|
||||
|
||||
/* reset */
|
||||
scope = 0;
|
||||
gotname = FALSE;
|
||||
token = SEMICOLON;
|
||||
|
||||
/* parse until the end of the file */
|
||||
while (prev = token, (token = lex_gettoken()) != EOF)
|
||||
{
|
||||
/* scope keyword? */
|
||||
if (token == TYPEDEF || token == STATIC || token == EXTERN)
|
||||
{
|
||||
scope = token;
|
||||
gotname = FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* name of a possible tag candidate? */
|
||||
if (token == NAME)
|
||||
{
|
||||
tagseek = file_seek;
|
||||
gotname = TRUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* if NAME BODY, without ARGS, then NAME is a struct tag */
|
||||
if (gotname && token == BODY && prev != ARGS)
|
||||
{
|
||||
gotname = FALSE;
|
||||
|
||||
/* ignore if in typedef -- better name is coming soon */
|
||||
if (scope == TYPEDEF)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* generate a tag, if -t and maybe -s */
|
||||
if (incl_types && (file_header || incl_static))
|
||||
{
|
||||
maketag(file_header ? 0 : STATIC, tagseek);
|
||||
}
|
||||
}
|
||||
|
||||
/* If NAME ARGS BODY, then NAME is a function */
|
||||
if (gotname && prev == ARGS && token == BODY)
|
||||
{
|
||||
gotname = FALSE;
|
||||
|
||||
/* generate a tag, maybe checking -s */
|
||||
if (scope != STATIC || incl_static)
|
||||
{
|
||||
maketag(scope, tagseek);
|
||||
}
|
||||
}
|
||||
|
||||
/* If NAME SEMICOLON or NAME COMMA, then NAME is var/typedef */
|
||||
if (gotname && (token == SEMICOLON || token == COMMA))
|
||||
{
|
||||
gotname = FALSE;
|
||||
|
||||
/* generate a tag, if -v/-t and maybe -s */
|
||||
if (scope == TYPEDEF && incl_types && (file_header || incl_static)
|
||||
|| scope == STATIC && incl_vars && incl_static
|
||||
|| incl_vars)
|
||||
{
|
||||
/* a TYPEDEF outside of a header is STATIC */
|
||||
if (scope == TYPEDEF && !file_header)
|
||||
{
|
||||
maketag(STATIC, tagseek);
|
||||
}
|
||||
else /* use whatever scope was declared */
|
||||
{
|
||||
maketag(scope, tagseek);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* reset after a semicolon or ARGS BODY pair */
|
||||
if (token == SEMICOLON || (prev == ARGS && token == BODY))
|
||||
{
|
||||
scope = 0;
|
||||
gotname = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* The source file will be automatically closed */
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void usage()
|
||||
{
|
||||
fprintf(stderr, "usage: ctags [flags] filenames...\n");
|
||||
fprintf(stderr, "\t-s include static functions\n");
|
||||
fprintf(stderr, "\t-t include typedefs\n");
|
||||
fprintf(stderr, "\t-v include variable declarations\n");
|
||||
fprintf(stderr, "\t-r generate a \"refs\" file, too\n");
|
||||
fprintf(stderr, "\t-a append to \"tags\", instead of overwriting\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if AMIGA
|
||||
# include "amiwild.c"
|
||||
#endif
|
||||
|
||||
#if VMS
|
||||
# include "vmswild.c"
|
||||
#endif
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int i, j;
|
||||
|
||||
#if MSDOS || TOS
|
||||
char **wildexpand();
|
||||
argv = wildexpand(&argc, argv);
|
||||
#endif
|
||||
|
||||
/* build the tables used by the ctype macros */
|
||||
_ct_init("");
|
||||
|
||||
/* parse the option flags */
|
||||
for (i = 1; i < argc && argv[i][0] == '-'; i++)
|
||||
{
|
||||
for (j = 1; argv[i][j]; j++)
|
||||
{
|
||||
switch (argv[i][j])
|
||||
{
|
||||
case 's': incl_static = TRUE; break;
|
||||
case 't': incl_types = TRUE; break;
|
||||
case 'v': incl_vars = TRUE; break;
|
||||
case 'r': make_refs = TRUE; break;
|
||||
case 'a': append_files = TRUE; break;
|
||||
default: usage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* There should always be at least one source file named in args */
|
||||
if (i == argc)
|
||||
{
|
||||
usage();
|
||||
}
|
||||
|
||||
/* open the "tags" and maybe "refs" files */
|
||||
tags = fopen(TAGS, append_files ? "a" : "w");
|
||||
if (!tags)
|
||||
{
|
||||
perror(TAGS);
|
||||
exit(3);
|
||||
}
|
||||
if (make_refs)
|
||||
{
|
||||
refs = fopen(REFS, append_files ? "a" : "w");
|
||||
if (!refs)
|
||||
{
|
||||
perror(REFS);
|
||||
exit(4);
|
||||
}
|
||||
}
|
||||
|
||||
/* parse each source file */
|
||||
for (; i < argc; i++)
|
||||
{
|
||||
ctags(argv[i]);
|
||||
}
|
||||
|
||||
/* close "tags" and maybe "refs" */
|
||||
fclose(tags);
|
||||
if (make_refs)
|
||||
{
|
||||
fclose(refs);
|
||||
}
|
||||
|
||||
#ifdef SORT
|
||||
/* This is a hack which will sort the tags list. It should
|
||||
* on UNIX and OS-9. You may have trouble with csh. Note
|
||||
* that the tags list only has to be sorted if you intend to
|
||||
* use it with the real vi; elvis permits unsorted tags.
|
||||
*/
|
||||
# if OSK
|
||||
system("qsort tags >-_tags; -nx; del tags; rename _tags tags");
|
||||
# else
|
||||
system("sort tags >_tags$$; mv _tags$$ tags");
|
||||
# endif
|
||||
#endif
|
||||
|
||||
exit(0);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
#if MSDOS || TOS
|
||||
# define WILDCARD_NO_MAIN
|
||||
# include "wildcard.c"
|
||||
#endif
|
|
@ -1,74 +0,0 @@
|
|||
/* ctype.c */
|
||||
|
||||
/* This file contains the tables and initialization function for elvis'
|
||||
* version of <ctype.h>. It should be portable.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "ctype.h"
|
||||
|
||||
uchar _ct_toupper[256];
|
||||
uchar _ct_tolower[256];
|
||||
uchar _ct_ctypes[256];
|
||||
|
||||
/* This function initializes the tables used by the ctype macros. It should
|
||||
* be called at the start of the program. It can be called again anytime you
|
||||
* wish to change the non-standard "flipcase" list. The "flipcase" list is
|
||||
* a string of characters which are taken to be lowercase/uppercase pairs.
|
||||
* If you don't want to use any special flipcase characters, then pass an
|
||||
* empty string.
|
||||
*/
|
||||
void _ct_init(flipcase)
|
||||
uchar *flipcase; /* list of non-standard lower/upper letter pairs */
|
||||
{
|
||||
int i;
|
||||
uchar *scan;
|
||||
|
||||
/* reset all of the tables */
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
_ct_toupper[i] = _ct_tolower[i] = i;
|
||||
_ct_ctypes[i] = 0;
|
||||
}
|
||||
|
||||
/* add the digits */
|
||||
for (scan = (uchar *)"0123456789"; *scan; scan++)
|
||||
{
|
||||
_ct_ctypes[*scan] |= _CT_DIGIT | _CT_ALNUM;
|
||||
}
|
||||
|
||||
/* add the whitespace */
|
||||
for (scan = (uchar *)" \t\n\r\f"; *scan; scan++)
|
||||
{
|
||||
_ct_ctypes[*scan] |= _CT_SPACE;
|
||||
}
|
||||
|
||||
/* add the standard ASCII letters */
|
||||
for (scan = (uchar *)"aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ"; *scan; scan += 2)
|
||||
{
|
||||
_ct_ctypes[scan[0]] |= _CT_LOWER | _CT_ALNUM;
|
||||
_ct_ctypes[scan[1]] |= _CT_UPPER | _CT_ALNUM;
|
||||
_ct_toupper[scan[0]] = scan[1];
|
||||
_ct_tolower[scan[1]] = scan[0];
|
||||
}
|
||||
|
||||
/* add the flipcase letters */
|
||||
for (scan = flipcase; scan[0] && scan[1]; scan += 2)
|
||||
{
|
||||
_ct_ctypes[scan[0]] |= _CT_LOWER | _CT_ALNUM;
|
||||
_ct_ctypes[scan[1]] |= _CT_UPPER | _CT_ALNUM;
|
||||
_ct_toupper[scan[0]] = scan[1];
|
||||
_ct_tolower[scan[1]] = scan[0];
|
||||
}
|
||||
|
||||
/* include '_' in the isalnum() list */
|
||||
_ct_ctypes[UCHAR('_')] |= _CT_ALNUM;
|
||||
|
||||
/* !!! find the control characters in an ASCII-dependent way */
|
||||
for (i = 0; i < ' '; i++)
|
||||
{
|
||||
_ct_ctypes[i] |= _CT_CNTRL;
|
||||
}
|
||||
_ct_ctypes[127] |= _CT_CNTRL;
|
||||
_ct_ctypes[255] |= _CT_CNTRL;
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/* ctype.h */
|
||||
|
||||
/* This file contains macros definitions and extern declarations for a
|
||||
* version of <ctype.h> which is aware of the o_flipcase letters used in
|
||||
* elvis.
|
||||
*
|
||||
* This file uses the "uchar" data type and "UCHAR" conversion macro which
|
||||
* are defined in "config.h". Consequently, any file that includes this
|
||||
* header must include config.h first.
|
||||
*/
|
||||
|
||||
#ifndef _CT_UPPER
|
||||
|
||||
#define _CT_UPPER 0x01
|
||||
#define _CT_LOWER 0x02
|
||||
#define _CT_SPACE 0x04
|
||||
#define _CT_DIGIT 0x08
|
||||
#define _CT_ALNUM 0x10
|
||||
#define _CT_CNTRL 0x20
|
||||
|
||||
#define isalnum(c) (_ct_ctypes[UCHAR(c)] & _CT_ALNUM)
|
||||
#define isalpha(c) (_ct_ctypes[UCHAR(c)] & (_CT_LOWER|_CT_UPPER))
|
||||
#define isdigit(c) (_ct_ctypes[UCHAR(c)] & _CT_DIGIT)
|
||||
#define islower(c) (_ct_ctypes[UCHAR(c)] & _CT_LOWER)
|
||||
#define isspace(c) (_ct_ctypes[UCHAR(c)] & _CT_SPACE)
|
||||
#define isupper(c) (_ct_ctypes[UCHAR(c)] & _CT_UPPER)
|
||||
#define iscntrl(c) (_ct_ctypes[UCHAR(c)] & _CT_CNTRL)
|
||||
#define ispunct(c) (!_ct_ctypes[UCHAR(c)]) /* punct = "none of the above" */
|
||||
|
||||
#define isascii(c) (!((c) & 0x80))
|
||||
|
||||
#define toupper(c) _ct_toupper[UCHAR(c)]
|
||||
#define tolower(c) _ct_tolower[UCHAR(c)]
|
||||
|
||||
extern uchar _ct_toupper[];
|
||||
extern uchar _ct_tolower[];
|
||||
extern uchar _ct_ctypes[];
|
||||
extern void _ct_init(/* char *flipcase */);
|
||||
|
||||
#endif /* ndef _CT_UPPER */
|
|
@ -1,925 +0,0 @@
|
|||
/* curses.c */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* 14407 SW Teal Blvd. #C
|
||||
* Beaverton, OR 97005
|
||||
* kirkenda@cs.pdx.edu
|
||||
*/
|
||||
|
||||
|
||||
/* This file contains the functions & variables needed for a tiny subset of
|
||||
* curses. The principle advantage of this version of curses is its
|
||||
* extreme speed. Disadvantages are potentially larger code, few supported
|
||||
* functions, limited compatibility with full curses, and only stdscr.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "vi.h"
|
||||
|
||||
#if ANY_UNIX
|
||||
/* The termios/termio/sgtty #ifdefs were a mess, so I removed all but termios.
|
||||
* (KJB)
|
||||
*/
|
||||
# include <termios.h>
|
||||
# if MINIX
|
||||
# include <sys/ioctl.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if TOS
|
||||
# include <osbind.h>
|
||||
#endif
|
||||
|
||||
#if OSK
|
||||
# include <sgstat.h>
|
||||
#endif
|
||||
|
||||
#if VMS
|
||||
extern int VMS_read_raw; /* Set in initscr() */
|
||||
#endif
|
||||
|
||||
|
||||
extern char *getenv();
|
||||
static void starttcap();
|
||||
|
||||
/* variables, publicly available & used in the macros */
|
||||
char *termtype; /* name of terminal entry */
|
||||
short ospeed; /* speed of the tty, eg B2400 */
|
||||
#if OSK
|
||||
char PC_; /* Pad char */
|
||||
char *BC; /* backspace character string */
|
||||
#else
|
||||
char PC; /* Pad char */
|
||||
#endif
|
||||
WINDOW *stdscr; /* pointer into kbuf[] */
|
||||
WINDOW kbuf[KBSIZ]; /* a very large output buffer */
|
||||
int LINES; /* :li#: number of rows */
|
||||
int COLS; /* :co#: number of columns */
|
||||
int AM; /* :am: boolean: auto margins? */
|
||||
int PT; /* :pt: boolean: physical tabs? */
|
||||
char *VB; /* :vb=: visible bell */
|
||||
char *UP; /* :up=: move cursor up */
|
||||
char *SO = ""; /* :so=: standout start */
|
||||
char *SE = ""; /* :se=: standout end */
|
||||
char *US = ""; /* :us=: underline start */
|
||||
char *UE = ""; /* :ue=: underline end */
|
||||
char *MD = ""; /* :md=: bold start */
|
||||
char *ME = ""; /* :me=: bold end */
|
||||
char *AS = ""; /* :as=: alternate (italic) start */
|
||||
char *AE = ""; /* :ae=: alternate (italic) end */
|
||||
#ifndef NO_VISIBLE
|
||||
char *MV; /* :mv=: "visible" selection start */
|
||||
#endif
|
||||
char *CM; /* :cm=: cursor movement */
|
||||
char *CE; /* :ce=: clear to end of line */
|
||||
char *CD; /* :cd=: clear to end of screen */
|
||||
char *AL; /* :al=: add a line */
|
||||
char *DL; /* :dl=: delete a line */
|
||||
#if OSK
|
||||
char *SR_; /* :sr=: scroll reverse */
|
||||
#else
|
||||
char *SR; /* :sr=: scroll reverse */
|
||||
#endif
|
||||
char *KS = ""; /* :ks=: init string for cursor */
|
||||
char *KE = ""; /* :ke=: restore string for cursor */
|
||||
char *KU; /* :ku=: key sequence sent by up arrow */
|
||||
char *KD; /* :kd=: key sequence sent by down arrow */
|
||||
char *KL; /* :kl=: key sequence sent by left arrow */
|
||||
char *KR; /* :kr=: key sequence sent by right arrow */
|
||||
char *HM; /* :HM=: key sequence sent by the <Home> key */
|
||||
char *EN; /* :EN=: key sequence sent by the <End> key */
|
||||
char *PU; /* :PU=: key sequence sent by the <PgUp> key */
|
||||
char *PD; /* :PD=: key sequence sent by the <PgDn> key */
|
||||
char *KI; /* :kI=: key sequence sent by the <Insert> key */
|
||||
#ifndef NO_FKEY
|
||||
char *FKEY[NFKEYS]; /* :k0=: ... :k9=: sequences sent by function keys */
|
||||
#endif
|
||||
char *IM = ""; /* :im=: insert mode start */
|
||||
char *IC = ""; /* :ic=: insert the following character */
|
||||
char *EI = ""; /* :ei=: insert mode end */
|
||||
char *DC; /* :dc=: delete a character */
|
||||
char *TI = ""; /* :ti=: terminal init */ /* GB */
|
||||
char *TE = ""; /* :te=: terminal exit */ /* GB */
|
||||
#ifndef NO_CURSORSHAPE
|
||||
#if 1
|
||||
char *CQ = (char *)0;/* :cQ=: normal cursor */
|
||||
char *CX = (char *)1;/* :cX=: cursor used for EX command/entry */
|
||||
char *CV = (char *)2;/* :cV=: cursor used for VI command mode */
|
||||
char *CI = (char *)3;/* :cI=: cursor used for VI input mode */
|
||||
char *CR = (char *)4;/* :cR=: cursor used for VI replace mode */
|
||||
#else
|
||||
char *CQ = ""; /* :cQ=: normal cursor */
|
||||
char *CX = ""; /* :cX=: cursor used for EX command/entry */
|
||||
char *CV = ""; /* :cV=: cursor used for VI command mode */
|
||||
char *CI = ""; /* :cI=: cursor used for VI input mode */
|
||||
char *CR = ""; /* :cR=: cursor used for VI replace mode */
|
||||
#endif
|
||||
#endif
|
||||
char *aend = ""; /* end an attribute -- either UE or ME */
|
||||
char ERASEKEY; /* backspace key taken from ioctl structure */
|
||||
#ifndef NO_COLOR
|
||||
char normalcolor[16];
|
||||
char SOcolor[16];
|
||||
char SEcolor[16];
|
||||
char UScolor[16];
|
||||
char UEcolor[16];
|
||||
char MDcolor[16];
|
||||
char MEcolor[16];
|
||||
char AScolor[16];
|
||||
char AEcolor[16];
|
||||
# ifndef NO_POPUP
|
||||
char POPUPcolor[16];
|
||||
# endif
|
||||
# ifndef NO_VISIBLE
|
||||
char VISIBLEcolor[16];
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if ANY_UNIX
|
||||
static struct termios oldtermio; /* original tty mode */
|
||||
static struct termios newtermio; /* cbreak/noecho tty mode */
|
||||
#endif
|
||||
|
||||
#if OSK
|
||||
static struct sgbuf oldsgttyb; /* orginal tty mode */
|
||||
static struct sgbuf newsgttyb; /* noecho tty mode */
|
||||
#endif
|
||||
|
||||
static char *capbuf; /* capability string buffer */
|
||||
|
||||
|
||||
/* Initialize the Curses package. */
|
||||
void initscr()
|
||||
{
|
||||
/* make sure TERM variable is set */
|
||||
termtype = getenv("TERM");
|
||||
|
||||
#if VMS
|
||||
/* VMS getenv() handles TERM as a environment setting. Foreign
|
||||
* terminal support can be implemented by setting the ELVIS_TERM
|
||||
* logical or symbol to match a tinytcap entry.
|
||||
*/
|
||||
if (!strcmp(termtype,"unknown"))
|
||||
termtype = getenv("ELVIS_TERM");
|
||||
#endif
|
||||
#if MSDOS
|
||||
/* For MS-DOS, if TERM is unset we can default to "pcbios", or
|
||||
* maybe "rainbow".
|
||||
*/
|
||||
if (!termtype)
|
||||
{
|
||||
#ifdef RAINBOW
|
||||
if (*(unsigned char far*)(0xffff000eL) == 6 /* Rainbow 100a */
|
||||
|| *(unsigned char far*)(0xffff000eL) == 148)/* Rainbow 100b */
|
||||
{
|
||||
termtype = "rainbow";
|
||||
}
|
||||
else
|
||||
#endif
|
||||
termtype = "pcbios";
|
||||
}
|
||||
if (!strcmp(termtype, "pcbios"))
|
||||
#else
|
||||
if (!termtype)
|
||||
#endif
|
||||
{
|
||||
#if ANY_UNIX
|
||||
write(2, "Environment variable TERM must be set\n", (unsigned)38);
|
||||
exit(1);
|
||||
#endif
|
||||
#if OSK
|
||||
writeln(2, "Environment variable TERM must be set\n", (unsigned)38);
|
||||
exit(1);
|
||||
#endif
|
||||
#if AMIGA
|
||||
termtype = TERMTYPE;
|
||||
starttcap(termtype);
|
||||
#endif
|
||||
#if MSDOS
|
||||
starttcap("pcbios");
|
||||
#endif
|
||||
#if TOS
|
||||
termtype = "vt52";
|
||||
starttcap(termtype);
|
||||
#endif
|
||||
#if VMS
|
||||
write(2, "UNKNOWN terminal: define ELVIS_TERM\n", (unsigned)36);
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if MSDOS
|
||||
*o_pcbios = 0;
|
||||
#endif
|
||||
/* start termcap stuff */
|
||||
starttcap(termtype);
|
||||
}
|
||||
|
||||
/* create stdscr and curscr */
|
||||
stdscr = kbuf;
|
||||
|
||||
/* change the terminal mode to cbreak/noecho */
|
||||
#if ANY_UNIX
|
||||
tcgetattr(2, &oldtermio);
|
||||
#endif
|
||||
|
||||
#if OSK
|
||||
_gs_opt(0, &oldsgttyb);
|
||||
#endif
|
||||
|
||||
#if VMS
|
||||
VMS_read_raw = 1; /* cbreak/noecho */
|
||||
vms_open_tty();
|
||||
#endif
|
||||
resume_curses(TRUE);
|
||||
}
|
||||
|
||||
/* Shut down the Curses package. */
|
||||
void endwin()
|
||||
{
|
||||
/* change the terminal mode back the way it was */
|
||||
suspend_curses();
|
||||
#if AMIGA
|
||||
amiclosewin();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static int curses_active = FALSE;
|
||||
|
||||
/* Send any required termination strings. Turn off "raw" mode. */
|
||||
void suspend_curses()
|
||||
{
|
||||
#ifndef NO_CURSORSHAPE
|
||||
if (has_CQ)
|
||||
{
|
||||
do_CQ();
|
||||
}
|
||||
#endif
|
||||
if (has_TE) /* GB */
|
||||
{
|
||||
do_TE();
|
||||
}
|
||||
if (has_KE)
|
||||
{
|
||||
do_KE();
|
||||
}
|
||||
#ifndef NO_COLOR
|
||||
quitcolor();
|
||||
#endif
|
||||
refresh();
|
||||
|
||||
/* change the terminal mode back the way it was */
|
||||
#if ANY_UNIX
|
||||
tcsetattr(2, TCSADRAIN, &oldtermio);
|
||||
#endif
|
||||
#if OSK
|
||||
_ss_opt(0, &oldsgttyb);
|
||||
#endif
|
||||
#if AMIGA
|
||||
ttyshutdown();
|
||||
#endif
|
||||
#if MSDOS
|
||||
raw_set_stdio(FALSE);
|
||||
#endif
|
||||
|
||||
#if VMS
|
||||
VMS_read_raw = 0;
|
||||
#endif
|
||||
curses_active = FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* put the terminal in RAW mode. If "quietly" is FALSE, then ask the user
|
||||
* to hit a key, and wait for keystroke before returning.
|
||||
*/
|
||||
void resume_curses(quietly)
|
||||
int quietly;
|
||||
{
|
||||
if (!curses_active)
|
||||
{
|
||||
/* change the terminal mode to cbreak/noecho */
|
||||
#if ANY_UNIX
|
||||
ospeed = cfgetospeed(&oldtermio);
|
||||
ERASEKEY = oldtermio.c_cc[VERASE];
|
||||
newtermio = oldtermio;
|
||||
newtermio.c_iflag &= (IXON|IXOFF|IXANY|ISTRIP|IGNBRK);
|
||||
newtermio.c_oflag &= ~OPOST;
|
||||
newtermio.c_lflag &= ISIG;
|
||||
newtermio.c_cc[VINTR] = ctrl('C'); /* always use ^C for interrupts */
|
||||
newtermio.c_cc[VMIN] = 1;
|
||||
newtermio.c_cc[VTIME] = 0;
|
||||
newtermio.c_cc[VSUSP] = 0;
|
||||
tcsetattr(2, TCSADRAIN, &newtermio);
|
||||
#endif
|
||||
#if OSK
|
||||
newsgttyb = oldsgttyb;
|
||||
newsgttyb.sg_echo = 0;
|
||||
newsgttyb.sg_eofch = 0;
|
||||
newsgttyb.sg_kbach = 0;
|
||||
newsgttyb.sg_kbich = ctrl('C');
|
||||
_ss_opt(0, &newsgttyb);
|
||||
ospeed = oldsgttyb.sg_baud;
|
||||
ERASEKEY = oldsgttyb.sg_bspch;
|
||||
#endif
|
||||
#if AMIGA
|
||||
/* turn on window resize and RAW */
|
||||
ttysetup();
|
||||
#endif
|
||||
#if MSDOS
|
||||
raw_set_stdio(TRUE);
|
||||
#endif
|
||||
|
||||
#if VMS
|
||||
VMS_read_raw = 1;
|
||||
{ int c;
|
||||
read(0,&c,0); /* Flush the tty buffer. */
|
||||
}
|
||||
ERASEKEY = '\177'; /* Accept <DEL> as <^H> for VMS */
|
||||
#endif
|
||||
|
||||
if (has_TI) /* GB */
|
||||
{
|
||||
do_TI();
|
||||
}
|
||||
if (has_KS)
|
||||
{
|
||||
do_KS();
|
||||
}
|
||||
|
||||
curses_active = TRUE;
|
||||
}
|
||||
|
||||
/* If we're supposed to quit quietly, then we're done */
|
||||
if (quietly)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
signal(SIGINT, SIG_IGN);
|
||||
|
||||
move(LINES - 1, 0);
|
||||
do_SO();
|
||||
#if VMS
|
||||
qaddstr("\n[Press <RETURN> to continue]");
|
||||
#else
|
||||
qaddstr("[Press <RETURN> to continue]");
|
||||
#endif
|
||||
do_SE();
|
||||
refresh();
|
||||
ttyread(kbuf, 20, 0); /* in RAW mode, so <20 is very likely */
|
||||
if (kbuf[0] == ':')
|
||||
{
|
||||
mode = MODE_COLON;
|
||||
addch('\n');
|
||||
refresh();
|
||||
}
|
||||
else
|
||||
{
|
||||
mode = MODE_VI;
|
||||
redraw(MARK_UNSET, FALSE);
|
||||
}
|
||||
exwrote = FALSE;
|
||||
|
||||
signal(SIGINT, (void(*)()) trapint);
|
||||
}
|
||||
|
||||
/* This function fetches an optional string from termcap */
|
||||
static void mayhave(T, s)
|
||||
char **T; /* where to store the returned pointer */
|
||||
char *s; /* name of the capability */
|
||||
{
|
||||
char *val;
|
||||
|
||||
val = tgetstr(s, &capbuf);
|
||||
if (val)
|
||||
{
|
||||
*T = val;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* This function fetches a required string from termcap */
|
||||
static void musthave(T, s)
|
||||
char **T; /* where to store the returned pointer */
|
||||
char *s; /* name of the capability */
|
||||
{
|
||||
mayhave(T, s);
|
||||
if (!*T)
|
||||
{
|
||||
write(2, "This termcap entry lacks the :", (unsigned)30);
|
||||
write(2, s, (unsigned)2);
|
||||
write(2, "=: capability\n", (unsigned)14);
|
||||
#if OSK
|
||||
write(2, "\l", 1);
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* This function fetches a pair of strings from termcap. If one of them is
|
||||
* missing, then the other one is ignored.
|
||||
*/
|
||||
static void pair(T, U, sT, sU)
|
||||
char **T; /* where to store the first pointer */
|
||||
char **U; /* where to store the second pointer */
|
||||
char *sT; /* name of the first capability */
|
||||
char *sU; /* name of the second capability */
|
||||
{
|
||||
mayhave(T, sT);
|
||||
mayhave(U, sU);
|
||||
if (!**T || !**U)
|
||||
{
|
||||
*T = *U = "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void getsize(int signo);
|
||||
|
||||
/* Read everything from termcap */
|
||||
static void starttcap(term)
|
||||
char *term;
|
||||
{
|
||||
static char cbmem[800];
|
||||
|
||||
/* allocate memory for capbuf */
|
||||
capbuf = cbmem;
|
||||
|
||||
/* get the termcap entry */
|
||||
switch (tgetent(kbuf, term))
|
||||
{
|
||||
case -1:
|
||||
write(2, "Can't read /etc/termcap\n", (unsigned)24);
|
||||
#if OSK
|
||||
write(2, "\l", 1);
|
||||
#endif
|
||||
exit(2);
|
||||
|
||||
case 0:
|
||||
write(2, "Unrecognized TERM type\n", (unsigned)23);
|
||||
#if OSK
|
||||
write(2, "\l", 1);
|
||||
#endif
|
||||
exit(3);
|
||||
}
|
||||
|
||||
/* get strings */
|
||||
musthave(&UP, "up");
|
||||
mayhave(&VB, "vb");
|
||||
musthave(&CM, "cm");
|
||||
pair(&SO, &SE, "so", "se");
|
||||
mayhave(&TI, "ti");
|
||||
mayhave(&TE, "te");
|
||||
if (tgetnum("ug") <= 0)
|
||||
{
|
||||
pair(&US, &UE, "us", "ue");
|
||||
pair(&MD, &ME, "md", "me");
|
||||
|
||||
/* get italics, or have it default to underline */
|
||||
pair(&AS, &AE, "as", "ae");
|
||||
if (!*AS)
|
||||
{
|
||||
AS = US;
|
||||
AE = UE;
|
||||
}
|
||||
}
|
||||
#ifndef NO_VISIBLE
|
||||
MV = SO; /* by default */
|
||||
mayhave(&MV, "mv");
|
||||
#endif
|
||||
mayhave(&AL, "al");
|
||||
mayhave(&DL, "dl");
|
||||
musthave(&CE, "ce");
|
||||
mayhave(&CD, "cd");
|
||||
#if OSK
|
||||
mayhave(&SR_, "sr");
|
||||
#else
|
||||
mayhave(&SR, "sr");
|
||||
#endif
|
||||
pair(&IM, &EI, "im", "ei");
|
||||
mayhave(&IC, "ic");
|
||||
mayhave(&DC, "dc");
|
||||
|
||||
/* other termcap stuff */
|
||||
AM = (tgetflag("am") && !tgetflag("xn"));
|
||||
PT = tgetflag("pt");
|
||||
#if AMIGA
|
||||
amiopenwin(termtype); /* Must run this before ttysetup(); */
|
||||
ttysetup(); /* Must run this before getsize(0); */
|
||||
#endif
|
||||
getsize(0);
|
||||
|
||||
/* Key sequences */
|
||||
pair(&KS, &KE, "ks", "ke");
|
||||
mayhave(&KU, "ku"); /* up */
|
||||
mayhave(&KD, "kd"); /* down */
|
||||
mayhave(&KL, "kl"); /* left */
|
||||
mayhave(&KR, "kr"); /* right */
|
||||
mayhave(&PU, "kP"); /* PgUp */
|
||||
mayhave(&PD, "kN"); /* PgDn */
|
||||
mayhave(&HM, "kh"); /* Home */
|
||||
mayhave(&EN, "kH"); /* End */
|
||||
mayhave(&KI, "kI"); /* Insert */
|
||||
#ifndef CRUNCH
|
||||
if (!PU) mayhave(&PU, "K2"); /* "3x3 pad" names for PgUp, etc. */
|
||||
if (!PD) mayhave(&PD, "K5");
|
||||
if (!HM) mayhave(&HM, "K1");
|
||||
if (!EN) mayhave(&EN, "K4");
|
||||
|
||||
mayhave(&PU, "PU"); /* old XENIX names for PgUp, etc. */
|
||||
mayhave(&PD, "PD"); /* (overrides others, if used.) */
|
||||
mayhave(&HM, "HM");
|
||||
mayhave(&EN, "EN");
|
||||
#endif
|
||||
#ifndef NO_FKEY
|
||||
mayhave(&FKEY[0], "k0"); /* function key codes */
|
||||
mayhave(&FKEY[1], "k1");
|
||||
mayhave(&FKEY[2], "k2");
|
||||
mayhave(&FKEY[3], "k3");
|
||||
mayhave(&FKEY[4], "k4");
|
||||
mayhave(&FKEY[5], "k5");
|
||||
mayhave(&FKEY[6], "k6");
|
||||
mayhave(&FKEY[7], "k7");
|
||||
mayhave(&FKEY[8], "k8");
|
||||
mayhave(&FKEY[9], "k9");
|
||||
# ifndef NO_SHIFT_FKEY
|
||||
mayhave(&FKEY[10], "s0"); /* shift function key codes */
|
||||
mayhave(&FKEY[11], "s1");
|
||||
mayhave(&FKEY[12], "s2");
|
||||
mayhave(&FKEY[13], "s3");
|
||||
mayhave(&FKEY[14], "s4");
|
||||
mayhave(&FKEY[15], "s5");
|
||||
mayhave(&FKEY[16], "s6");
|
||||
mayhave(&FKEY[17], "s7");
|
||||
mayhave(&FKEY[18], "s8");
|
||||
mayhave(&FKEY[19], "s9");
|
||||
# ifndef NO_CTRL_FKEY
|
||||
mayhave(&FKEY[20], "c0"); /* control function key codes */
|
||||
mayhave(&FKEY[21], "c1");
|
||||
mayhave(&FKEY[22], "c2");
|
||||
mayhave(&FKEY[23], "c3");
|
||||
mayhave(&FKEY[24], "c4");
|
||||
mayhave(&FKEY[25], "c5");
|
||||
mayhave(&FKEY[26], "c6");
|
||||
mayhave(&FKEY[27], "c7");
|
||||
mayhave(&FKEY[28], "c8");
|
||||
mayhave(&FKEY[29], "c9");
|
||||
# ifndef NO_ALT_FKEY
|
||||
mayhave(&FKEY[30], "a0"); /* alt function key codes */
|
||||
mayhave(&FKEY[31], "a1");
|
||||
mayhave(&FKEY[32], "a2");
|
||||
mayhave(&FKEY[33], "a3");
|
||||
mayhave(&FKEY[34], "a4");
|
||||
mayhave(&FKEY[35], "a5");
|
||||
mayhave(&FKEY[36], "a6");
|
||||
mayhave(&FKEY[37], "a7");
|
||||
mayhave(&FKEY[38], "a8");
|
||||
mayhave(&FKEY[39], "a9");
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef NO_CURSORSHAPE
|
||||
/* cursor shapes */
|
||||
CQ = tgetstr("cQ", &capbuf);
|
||||
if (has_CQ)
|
||||
{
|
||||
CX = tgetstr("cX", &capbuf);
|
||||
if (!CX) CX = CQ;
|
||||
CV = tgetstr("cV", &capbuf);
|
||||
if (!CV) CV = CQ;
|
||||
CI = tgetstr("cI", &capbuf);
|
||||
if (!CI) CI = CQ;
|
||||
CR = tgetstr("cR", &capbuf);
|
||||
if (!CR) CR = CQ;
|
||||
}
|
||||
# ifndef CRUNCH
|
||||
else
|
||||
{
|
||||
CQ = CV = "";
|
||||
pair(&CQ, &CV, "ve", "vs");
|
||||
CX = CI = CR = CQ;
|
||||
}
|
||||
# endif /* !CRUNCH */
|
||||
#endif /* !NO_CURSORSHAPE */
|
||||
|
||||
#ifndef NO_COLOR
|
||||
strcpy(SOcolor, SO);
|
||||
strcpy(SEcolor, SE);
|
||||
strcpy(AScolor, AS);
|
||||
strcpy(AEcolor, AE);
|
||||
strcpy(MDcolor, MD);
|
||||
strcpy(MEcolor, ME);
|
||||
strcpy(UScolor, US);
|
||||
strcpy(UEcolor, UE);
|
||||
# ifndef NO_POPUP
|
||||
strcpy(POPUPcolor, SO);
|
||||
# endif
|
||||
# ifndef NO_VISIBLE
|
||||
strcpy(VISIBLEcolor, MV);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* This function gets the window size. It uses the TIOCGWINSZ ioctl call if
|
||||
* your system has it, or tgetnum("li") and tgetnum("co") if it doesn't.
|
||||
* This function is called once during initialization, and thereafter it is
|
||||
* called whenever the SIGWINCH signal is sent to this process.
|
||||
*/
|
||||
void getsize(signo)
|
||||
int signo;
|
||||
{
|
||||
int lines;
|
||||
int cols;
|
||||
#ifdef TIOCGWINSZ
|
||||
struct winsize size;
|
||||
#endif
|
||||
|
||||
#ifdef SIGWINCH
|
||||
/* reset the signal vector */
|
||||
signal(SIGWINCH, getsize);
|
||||
#endif
|
||||
|
||||
/* get the window size, one way or another. */
|
||||
lines = cols = 0;
|
||||
#ifdef TIOCGWINSZ
|
||||
if (ioctl(2, TIOCGWINSZ, &size) >= 0)
|
||||
{
|
||||
lines = size.ws_row;
|
||||
cols = size.ws_col;
|
||||
}
|
||||
#endif
|
||||
#if AMIGA
|
||||
/* Amiga gets window size by asking the console.device */
|
||||
if (!strcmp(TERMTYPE, termtype))
|
||||
{
|
||||
auto long len;
|
||||
auto char buf[30];
|
||||
|
||||
Write(Output(), "\2330 q", 4); /* Ask the console.device */
|
||||
len = Read(Input(), buf, 29);
|
||||
buf[len] = '\000';
|
||||
sscanf(&buf[5], "%d;%d", &lines, &cols);
|
||||
}
|
||||
#endif
|
||||
if ((lines == 0 || cols == 0) && signo == 0)
|
||||
{
|
||||
LINES = tgetnum("li");
|
||||
COLS = tgetnum("co");
|
||||
}
|
||||
#if MSDOS
|
||||
# ifdef RAINBOW
|
||||
if (!strcmp(termtype, "rainbow"))
|
||||
{
|
||||
/* Determine whether Rainbow is in 80-column or 132-column mode */
|
||||
cols = *(unsigned char far *)0xee000f57L;
|
||||
}
|
||||
else
|
||||
# endif
|
||||
{
|
||||
lines = v_rows();
|
||||
cols = v_cols();
|
||||
}
|
||||
#endif
|
||||
if (lines >= 2)
|
||||
{
|
||||
LINES = lines;
|
||||
}
|
||||
|
||||
if (cols >= 30)
|
||||
{
|
||||
COLS = cols;
|
||||
}
|
||||
|
||||
/* Make sure we got values that we can live with */
|
||||
if (LINES < 2 || COLS < 30)
|
||||
{
|
||||
write(2, "Screen too small\n", (unsigned)17);
|
||||
#if OSK
|
||||
write(2, "\l", 1);
|
||||
#endif
|
||||
endwin();
|
||||
exit(2);
|
||||
}
|
||||
|
||||
#if AMIGA
|
||||
if (*o_lines != LINES || *o_columns != COLS)
|
||||
{
|
||||
*o_lines = LINES;
|
||||
*o_columns = COLS;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* This is a function version of addch() -- it is used by tputs() */
|
||||
int faddch(ch)
|
||||
int ch;
|
||||
{
|
||||
addch(ch);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function quickly adds a string to the output queue. It does *NOT*
|
||||
* convert \n into <CR><LF>.
|
||||
*/
|
||||
void qaddstr(str)
|
||||
char *str;
|
||||
{
|
||||
REG char *s_, *d_;
|
||||
|
||||
#if MSDOS
|
||||
if (o_pcbios[0])
|
||||
{
|
||||
while (*str)
|
||||
qaddch(*str++);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
for (s_=(str), d_=stdscr; *d_++ = *s_++; )
|
||||
{
|
||||
}
|
||||
stdscr = d_ - 1;
|
||||
}
|
||||
|
||||
/* Output the ESC sequence needed to go into any video mode, if supported */
|
||||
void attrset(a)
|
||||
int a;
|
||||
{
|
||||
do_aend();
|
||||
if (a == A_BOLD)
|
||||
{
|
||||
do_MD();
|
||||
aend = ME;
|
||||
}
|
||||
else if (a == A_UNDERLINE)
|
||||
{
|
||||
do_US();
|
||||
aend = UE;
|
||||
}
|
||||
else if (a == A_ALTCHARSET)
|
||||
{
|
||||
do_AS();
|
||||
aend = AE;
|
||||
}
|
||||
else
|
||||
{
|
||||
aend = "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Insert a single character into the display */
|
||||
void insch(ch)
|
||||
int ch;
|
||||
{
|
||||
if (has_IM)
|
||||
do_IM();
|
||||
do_IC();
|
||||
qaddch(ch);
|
||||
if (has_EI)
|
||||
do_EI();
|
||||
}
|
||||
|
||||
void wrefresh()
|
||||
{
|
||||
if (stdscr != kbuf)
|
||||
{
|
||||
VOIDBIOS(;,ttywrite(kbuf, (unsigned)(stdscr - kbuf)));
|
||||
stdscr = kbuf;
|
||||
}
|
||||
}
|
||||
|
||||
void wqrefresh()
|
||||
{
|
||||
if (stdscr - kbuf > 2000)
|
||||
{
|
||||
VOIDBIOS(stdscr = kbuf,
|
||||
{
|
||||
ttywrite(kbuf, (unsigned)(stdscr - kbuf));
|
||||
stdscr = kbuf;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NO_COLOR
|
||||
/* This function is called during termination. It resets color modes */
|
||||
int ansiquit()
|
||||
{
|
||||
/* if ANSI color terminal, then reset the colors */
|
||||
if (!strcmp(UP, "\033[A"))
|
||||
{
|
||||
tputs("\033[37;40m\033[m", 1, faddch);
|
||||
clrtoeol();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This sets the color strings that work for ANSI terminals. If the TERMCAP
|
||||
* doesn't look like an ANSI terminal, then it returns FALSE. If the colors
|
||||
* aren't understood, it also returns FALSE. If all goes well, it returns TRUE
|
||||
*/
|
||||
int ansicolor(cmode, attrbyte)
|
||||
int cmode; /* mode to set, e.g. A_NORMAL */
|
||||
int attrbyte; /* IBM PC attribute byte */
|
||||
{
|
||||
char temp[16]; /* hold the new mode string */
|
||||
|
||||
/* if not ANSI-ish, then fail */
|
||||
if (strcmp(UP, "\033[A") && strcmp(UP, "\033OA"))
|
||||
{
|
||||
msg("Don't know how to set colors for this terminal");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* construct the color string */
|
||||
sprintf(temp, "\033[m\033[3%c;4%c%s%sm",
|
||||
"04261537"[attrbyte & 0x07],
|
||||
"04261537"[(attrbyte >> 4) & 0x07],
|
||||
(attrbyte & 0x08) ? ";1" : "",
|
||||
(attrbyte & 0x80) ? ";5" : "");
|
||||
|
||||
/* stick it in the right place */
|
||||
switch (cmode)
|
||||
{
|
||||
case A_NORMAL:
|
||||
if (!strcmp(MEcolor, normalcolor))
|
||||
strcpy(MEcolor, temp);
|
||||
if (!strcmp(UEcolor, normalcolor))
|
||||
strcpy(UEcolor, temp);
|
||||
if (!strcmp(AEcolor, normalcolor))
|
||||
strcpy(AEcolor, temp);
|
||||
if (!strcmp(SEcolor, normalcolor))
|
||||
strcpy(SEcolor, temp);
|
||||
|
||||
strcpy(normalcolor, temp);
|
||||
tputs(normalcolor, 1, faddch);
|
||||
break;
|
||||
|
||||
case A_BOLD:
|
||||
strcpy(MDcolor, temp);
|
||||
strcpy(MEcolor, normalcolor);
|
||||
break;
|
||||
|
||||
case A_UNDERLINE:
|
||||
strcpy(UScolor, temp);
|
||||
strcpy(UEcolor, normalcolor);
|
||||
break;
|
||||
|
||||
case A_ALTCHARSET:
|
||||
strcpy(AScolor, temp);
|
||||
strcpy(AEcolor, normalcolor);
|
||||
break;
|
||||
|
||||
case A_STANDOUT:
|
||||
strcpy(SOcolor, temp);
|
||||
strcpy(SEcolor, normalcolor);
|
||||
break;
|
||||
|
||||
#ifndef NO_POPUP
|
||||
case A_POPUP:
|
||||
strcpy(POPUPcolor, temp);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifndef NO_VISIBLE
|
||||
case A_VISIBLE:
|
||||
strcpy(VISIBLEcolor, temp);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* This function outputs the ESC sequence needed to switch the screen back
|
||||
* to "normal" mode. On color terminals which haven't had their color set
|
||||
* yet, this is one of the termcap strings; for color terminals that really
|
||||
* have had colors defined, we just the "normal color" escape sequence.
|
||||
*/
|
||||
endcolor()
|
||||
{
|
||||
if (aend == ME)
|
||||
tputs(MEcolor, 1, faddch);
|
||||
else if (aend == UE)
|
||||
tputs(UEcolor, 1, faddch);
|
||||
else if (aend == AE)
|
||||
tputs(AEcolor, 1, faddch);
|
||||
else if (aend == SE)
|
||||
tputs(SEcolor, 1, faddch);
|
||||
aend = "";
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif /* !NO_COLOR */
|
|
@ -1,319 +0,0 @@
|
|||
/* curses.h */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* 14407 SW Teal Blvd. #C
|
||||
* Beaverton, OR 97005
|
||||
* kirkenda@cs.pdx.edu
|
||||
*/
|
||||
|
||||
|
||||
/* This is the header file for a small, fast, fake curses package */
|
||||
|
||||
/* termcap stuff */
|
||||
extern char *tgoto();
|
||||
extern char *tgetstr();
|
||||
extern void tputs();
|
||||
|
||||
#if MSDOS
|
||||
/* BIOS interface used instead of termcap for MS-DOS */
|
||||
extern int vmode;
|
||||
extern void v_up();
|
||||
extern void v_cb();
|
||||
extern void v_cs();
|
||||
extern void v_ce();
|
||||
extern void v_cl();
|
||||
extern void v_cd();
|
||||
extern void v_al();
|
||||
extern void v_dl();
|
||||
extern void v_sr();
|
||||
extern void v_move();
|
||||
#endif
|
||||
|
||||
/* faddch() is a function. a pointer to it is passed to tputs() */
|
||||
extern int faddch();
|
||||
|
||||
/* data types */
|
||||
#define WINDOW char
|
||||
|
||||
/* CONSTANTS & SYMBOLS */
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define A_NORMAL 0
|
||||
#define A_STANDOUT 1
|
||||
#define A_BOLD 2
|
||||
#define A_UNDERLINE 3
|
||||
#define A_ALTCHARSET 4
|
||||
#define A_POPUP 5
|
||||
#define A_VISIBLE 6
|
||||
#define KBSIZ 4096
|
||||
|
||||
/* figure out how many function keys we need to allow. */
|
||||
#ifndef NO_FKEY
|
||||
# ifdef NO_SHIFT_FKEY
|
||||
# define NFKEYS 10
|
||||
# else
|
||||
# ifdef NO_CTRL_FKEY
|
||||
# define NFKEYS 20
|
||||
# else
|
||||
# ifdef NO_ALT_FKEY
|
||||
# define NFKEYS 30
|
||||
# else
|
||||
# define NFKEYS 40
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
extern char *FKEY[NFKEYS]; /* :k0=:...:k9=: codes sent by function keys */
|
||||
#endif
|
||||
|
||||
/* extern variables, defined in curses.c */
|
||||
extern char *termtype; /* name of terminal entry */
|
||||
extern short ospeed; /* tty speed, eg B2400 */
|
||||
#if OSK
|
||||
extern char PC_; /* Pad char */
|
||||
extern char *BC; /* Backspace char string */
|
||||
#else
|
||||
extern char PC; /* Pad char */
|
||||
#endif
|
||||
extern WINDOW *stdscr; /* pointer into kbuf[] */
|
||||
extern WINDOW kbuf[KBSIZ]; /* a very large output buffer */
|
||||
extern int LINES; /* :li#: number of rows */
|
||||
extern int COLS; /* :co#: number of columns */
|
||||
extern int AM; /* :am: boolean: auto margins? */
|
||||
extern int PT; /* :pt: boolean: physical tabs? */
|
||||
extern char *VB; /* :vb=: visible bell */
|
||||
extern char *UP; /* :up=: move cursor up */
|
||||
extern char *SO; /* :so=: standout start */
|
||||
extern char *SE; /* :se=: standout end */
|
||||
extern char *US; /* :us=: underline start */
|
||||
extern char *UE; /* :ue=: underline end */
|
||||
extern char *MD; /* :md=: bold start */
|
||||
extern char *ME; /* :me=: bold end */
|
||||
extern char *AS; /* :as=: alternate (italic) start */
|
||||
extern char *AE; /* :ae=: alternate (italic) end */
|
||||
#ifndef NO_VISIBLE
|
||||
extern char *MV; /* :mv=: "visible" selection start */
|
||||
#endif
|
||||
extern char *CM; /* :cm=: cursor movement */
|
||||
extern char *CE; /* :ce=: clear to end of line */
|
||||
extern char *CD; /* :cd=: clear to end of screen */
|
||||
extern char *AL; /* :al=: add a line */
|
||||
extern char *DL; /* :dl=: delete a line */
|
||||
#if OSK
|
||||
extern char *SR_; /* :sr=: scroll reverse */
|
||||
#else
|
||||
extern char *SR; /* :sr=: scroll reverse */
|
||||
#endif
|
||||
extern char *KS; /* :ks=: init string for cursor */
|
||||
extern char *KE; /* :ke=: restore string for cursor */
|
||||
extern char *KU; /* :ku=: sequence sent by up key */
|
||||
extern char *KD; /* :kd=: sequence sent by down key */
|
||||
extern char *KL; /* :kl=: sequence sent by left key */
|
||||
extern char *KR; /* :kr=: sequence sent by right key */
|
||||
extern char *PU; /* :PU=: key sequence sent by PgUp key */
|
||||
extern char *PD; /* :PD=: key sequence sent by PgDn key */
|
||||
extern char *HM; /* :HM=: key sequence sent by Home key */
|
||||
extern char *EN; /* :EN=: key sequence sent by End key */
|
||||
extern char *KI; /* :kI=: key sequence sent by Insert key */
|
||||
extern char *IM; /* :im=: insert mode start */
|
||||
extern char *IC; /* :ic=: insert following char */
|
||||
extern char *EI; /* :ei=: insert mode end */
|
||||
extern char *DC; /* :dc=: delete a character */
|
||||
extern char *TI; /* :ti=: terminal init */ /* GB */
|
||||
extern char *TE; /* :te=: terminal exit */ /* GB */
|
||||
#ifndef NO_CURSORSHAPE
|
||||
extern char *CQ; /* :cQ=: normal cursor */
|
||||
extern char *CX; /* :cX=: cursor used for EX command/entry */
|
||||
extern char *CV; /* :cV=: cursor used for VI command mode */
|
||||
extern char *CI; /* :cI=: cursor used for VI input mode */
|
||||
extern char *CR; /* :cR=: cursor used for VI replace mode */
|
||||
#endif
|
||||
extern char *aend; /* end an attribute -- either UE or ME */
|
||||
extern char ERASEKEY; /* taken from the ioctl structure */
|
||||
#ifndef NO_COLOR
|
||||
extern char SOcolor[];
|
||||
extern char SEcolor[];
|
||||
extern char UScolor[];
|
||||
extern char UEcolor[];
|
||||
extern char MDcolor[];
|
||||
extern char MEcolor[];
|
||||
extern char AScolor[];
|
||||
extern char AEcolor[];
|
||||
# ifndef NO_POPUP
|
||||
extern char POPUPcolor[];
|
||||
# endif
|
||||
# ifndef NO_VISIBLE
|
||||
extern char VISIBLEcolor[];
|
||||
# endif
|
||||
extern char normalcolor[];
|
||||
#endif /* undef NO_COLOR */
|
||||
|
||||
/* Msdos-versions may use bios; others always termcap.
|
||||
* Will emit some 'code has no effect' warnings in unix.
|
||||
*/
|
||||
|
||||
#if MSDOS
|
||||
extern char o_pcbios[1]; /* BAH! */
|
||||
#define CHECKBIOS(x,y) (*o_pcbios ? (x) : (y))
|
||||
#define VOIDBIOS(x,y) {if (*o_pcbios) {x;} else {y;}}
|
||||
#else
|
||||
#define CHECKBIOS(x,y) (y)
|
||||
#define VOIDBIOS(x,y) {y;}
|
||||
#endif
|
||||
|
||||
#ifndef NO_COLOR
|
||||
# define setcolor(m,a) CHECKBIOS(bioscolor(m,a), ansicolor(m,a))
|
||||
# define fixcolor() VOIDBIOS(;, tputs(normalcolor, 1, faddch))
|
||||
# define quitcolor() CHECKBIOS(biosquit(), ansiquit())
|
||||
# define do_SO() VOIDBIOS((vmode=A_STANDOUT), tputs(SOcolor, 1, faddch))
|
||||
# define do_SE() VOIDBIOS((vmode=A_NORMAL), tputs(SEcolor, 1, faddch))
|
||||
# define do_US() VOIDBIOS((vmode=A_UNDERLINE), tputs(UScolor, 1, faddch))
|
||||
# define do_UE() VOIDBIOS((vmode=A_NORMAL), tputs(UEcolor, 1, faddch))
|
||||
# define do_MD() VOIDBIOS((vmode=A_BOLD), tputs(MDcolor, 1, faddch))
|
||||
# define do_ME() VOIDBIOS((vmode=A_NORMAL), tputs(MEcolor, 1, faddch))
|
||||
# define do_AS() VOIDBIOS((vmode=A_ALTCHARSET), tputs(AScolor, 1, faddch))
|
||||
# define do_AE() VOIDBIOS((vmode=A_NORMAL), tputs(AEcolor, 1, faddch))
|
||||
# define do_POPUP() VOIDBIOS((vmode=A_POPUP), tputs(POPUPcolor, 1, faddch))
|
||||
# define do_VISIBLE() VOIDBIOS((vmode=A_VISIBLE), tputs(VISIBLEcolor, 1, faddch))
|
||||
#else
|
||||
# define do_SO() VOIDBIOS((vmode=A_STANDOUT), tputs(SO, 1, faddch))
|
||||
# define do_SE() VOIDBIOS((vmode=A_NORMAL), tputs(SE, 1, faddch))
|
||||
# define do_US() VOIDBIOS((vmode=A_UNDERLINE), tputs(US, 1, faddch))
|
||||
# define do_UE() VOIDBIOS((vmode=A_NORMAL), tputs(UE, 1, faddch))
|
||||
# define do_MD() VOIDBIOS((vmode=A_BOLD), tputs(MD, 1, faddch))
|
||||
# define do_ME() VOIDBIOS((vmode=A_NORMAL), tputs(ME, 1, faddch))
|
||||
# define do_AS() VOIDBIOS((vmode=A_ALTCHARSET), tputs(AS, 1, faddch))
|
||||
# define do_AE() VOIDBIOS((vmode=A_NORMAL), tputs(AE, 1, faddch))
|
||||
# define do_POPUP() VOIDBIOS((vmode=A_POPUP), tputs(SO, 1, faddch))
|
||||
# define do_VISIBLE() VOIDBIOS((vmode=A_VISIBLE), tputs(MV, 1, faddch))
|
||||
#endif
|
||||
|
||||
#define do_VB() VOIDBIOS(;, tputs(VB, 1, faddch))
|
||||
#define do_UP() VOIDBIOS(v_up(), tputs(UP, 1, faddch))
|
||||
#undef do_CM /* move */
|
||||
#define do_CE() VOIDBIOS(v_ce(), tputs(CE, 1, faddch))
|
||||
#define do_CD() VOIDBIOS(v_cd(), tputs(CD, 1, faddch))
|
||||
#define do_AL() VOIDBIOS(v_al(), tputs(AL, LINES, faddch))
|
||||
#define do_DL() VOIDBIOS(v_dl(), tputs(DL, LINES, faddch))
|
||||
#if OSK
|
||||
#define do_SR() VOIDBIOS(v_sr(), tputs(SR_, 1, faddch))
|
||||
#else
|
||||
#define do_SR() VOIDBIOS(v_sr(), tputs(SR, 1, faddch))
|
||||
#endif
|
||||
#define do_KS() VOIDBIOS(1, tputs(KS, 1, faddch))
|
||||
#define do_KE() VOIDBIOS(1, tputs(KE, 1, faddch))
|
||||
#define do_IM() VOIDBIOS(;, tputs(IM, 1, faddch))
|
||||
#define do_IC() VOIDBIOS(;, tputs(IC, 1, faddch))
|
||||
#define do_EI() VOIDBIOS(;, tputs(EI, 1, faddch))
|
||||
#define do_DC() VOIDBIOS(;, tputs(DC, COLS, faddch))
|
||||
#define do_TI() VOIDBIOS(;, (void)ttywrite(TI, (unsigned)strlen(TI)))
|
||||
#define do_TE() VOIDBIOS(;, (void)ttywrite(TE, (unsigned)strlen(TE)))
|
||||
#ifndef NO_CURSORSHAPE
|
||||
# define do_CQ() VOIDBIOS(v_cs(), tputs(CQ, 1, faddch))
|
||||
# define do_CX() VOIDBIOS(v_cs(), tputs(CX, 1, faddch))
|
||||
# define do_CV() VOIDBIOS(v_cs(), tputs(CV, 1, faddch))
|
||||
# define do_CI() VOIDBIOS(v_cb(), tputs(CI, 1, faddch))
|
||||
# define do_CR() VOIDBIOS(v_cb(), tputs(CR, 1, faddch))
|
||||
#endif
|
||||
#ifndef NO_COLOR
|
||||
# define do_aend() VOIDBIOS((vmode=A_NORMAL), endcolor())
|
||||
#else
|
||||
# define do_aend() VOIDBIOS((vmode=A_NORMAL), tputs(aend, 1, faddch))
|
||||
#endif
|
||||
|
||||
#define has_AM CHECKBIOS(1, AM)
|
||||
#define has_PT CHECKBIOS(0, PT)
|
||||
#define has_VB CHECKBIOS((char *)0, VB)
|
||||
#define has_UP CHECKBIOS((char *)1, UP)
|
||||
#define has_SO CHECKBIOS((char)1, (*SO))
|
||||
#define has_SE CHECKBIOS((char)1, (*SE))
|
||||
#define has_US CHECKBIOS((char)1, (*US))
|
||||
#define has_UE CHECKBIOS((char)1, (*UE))
|
||||
#define has_MD CHECKBIOS((char)1, (*MD))
|
||||
#define has_ME CHECKBIOS((char)1, (*ME))
|
||||
#define has_AS CHECKBIOS((char)1, (*AS))
|
||||
#define has_AE CHECKBIOS((char)1, (*AE))
|
||||
#undef has_CM /* cursor move: don't need */
|
||||
#define has_CB CHECKBIOS(1, 0)
|
||||
#define has_CS CHECKBIOS(1, 0)
|
||||
#define has_CE CHECKBIOS((char *)1, CE)
|
||||
#define has_CD CHECKBIOS((char *)1, CD)
|
||||
#define has_AL CHECKBIOS((char *)1, AL)
|
||||
#define has_DL CHECKBIOS((char *)1, DL)
|
||||
#if OSK
|
||||
#define has_SR CHECKBIOS((char *)1, SR_)
|
||||
#else
|
||||
#define has_SR CHECKBIOS((char *)1, SR)
|
||||
#endif
|
||||
#define has_KS CHECKBIOS((char)1, (*KS))
|
||||
#define has_KE CHECKBIOS((char)1, (*KE))
|
||||
#define has_KU KU
|
||||
#define has_KD KD
|
||||
#define has_KL KL
|
||||
#define has_KR KR
|
||||
#define has_HM HM
|
||||
#define has_EN EN
|
||||
#define has_PU PU
|
||||
#define has_PD PD
|
||||
#define has_KI KI
|
||||
#define has_IM CHECKBIOS((char)0, (*IM))
|
||||
#define has_IC CHECKBIOS((char)0, (*IC))
|
||||
#define has_EI CHECKBIOS((char)0, (*EI))
|
||||
#define has_DC CHECKBIOS((char *)0, DC)
|
||||
#define has_TI CHECKBIOS((char)0, (*TI))
|
||||
#define has_TE CHECKBIOS((char)0, (*TE))
|
||||
#ifndef NO_CURSORSHAPE
|
||||
#define has_CQ CHECKBIOS((char *)1, CQ)
|
||||
#endif
|
||||
|
||||
/* (pseudo)-Curses-functions */
|
||||
|
||||
#ifdef lint
|
||||
# define _addCR VOIDBIOS(;, (stdscr[-1] == '\n' ? qaddch('\r') : (stdscr[-1] = '\n')))
|
||||
#else
|
||||
# if OSK
|
||||
# define _addCR VOIDBIOS(;, (stdscr[-1] == '\n' ? qaddch('\l') : (stdscr[-1] = stdscr[-1])))
|
||||
# else
|
||||
# define _addCR VOIDBIOS(;, (stdscr[-1] == '\n' ? qaddch('\r') : 0))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef AZTEC_C
|
||||
# define qaddch(ch) CHECKBIOS(v_put(ch), (*stdscr = (ch), *stdscr++))
|
||||
#else
|
||||
#define qaddch(ch) CHECKBIOS(v_put(ch), (*stdscr++ = (ch)))
|
||||
#endif
|
||||
|
||||
#if OSK
|
||||
#define addch(ch) if (qaddch(ch) == '\n') qaddch('\l'); else
|
||||
#else
|
||||
#define addch(ch) if (qaddch(ch) == '\n') qaddch('\r'); else
|
||||
#endif
|
||||
|
||||
extern void initscr();
|
||||
extern void endwin();
|
||||
extern void suspend_curses();
|
||||
extern void resume_curses();
|
||||
extern void attrset();
|
||||
extern void insch();
|
||||
extern void qaddstr();
|
||||
extern void wrefresh();
|
||||
extern void wqrefresh();
|
||||
#define addstr(str) {qaddstr(str); _addCR;}
|
||||
#define move(y,x) VOIDBIOS(v_move(x,y), tputs(tgoto(CM, x, y), 1, faddch))
|
||||
#define mvaddch(y,x,ch) {move(y,x); addch(ch);}
|
||||
#define refresh() VOIDBIOS(;, wrefresh())
|
||||
#define standout() do_SO()
|
||||
#define standend() do_SE()
|
||||
#define clrtoeol() do_CE()
|
||||
#define clrtobot() do_CD()
|
||||
#define insertln() do_AL()
|
||||
#define deleteln() do_DL()
|
||||
#define delch() do_DC()
|
||||
#define scrollok(w,b)
|
||||
#define raw()
|
||||
#define echo()
|
||||
#define cbreak()
|
||||
#define noraw()
|
||||
#define noecho()
|
||||
#define nocbreak()
|
|
@ -1,700 +0,0 @@
|
|||
/* cut.c */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* 14407 SW Teal Blvd. #C
|
||||
* Beaverton, OR 97005
|
||||
* kirkenda@cs.pdx.edu
|
||||
*/
|
||||
|
||||
|
||||
/* This file contains function which manipulate the cut buffers. */
|
||||
|
||||
#include "config.h"
|
||||
#include "vi.h"
|
||||
#if TURBOC
|
||||
#include <process.h> /* needed for getpid */
|
||||
#endif
|
||||
#if TOS
|
||||
#include <osbind.h>
|
||||
#define rename(a,b) Frename(0,a,b)
|
||||
#endif
|
||||
|
||||
# define NANONS 9 /* number of anonymous buffers */
|
||||
|
||||
static struct cutbuf
|
||||
{
|
||||
short *phys; /* pointer to an array of #s of BLKs containing text */
|
||||
int nblks; /* number of blocks in phys[] array */
|
||||
int start; /* offset into first block of start of cut */
|
||||
int end; /* offset into last block of end of cut */
|
||||
int tmpnum; /* ID number of the temp file */
|
||||
char lnmode; /* boolean: line-mode cut? (as opposed to char-mode) */
|
||||
}
|
||||
named[27], /* cut buffers "a through "z and ". */
|
||||
anon[NANONS]; /* anonymous cut buffers */
|
||||
|
||||
static char cbname; /* name chosen for next cut/paste operation */
|
||||
static char dotcb; /* cut buffer to use if "doingdot" is set */
|
||||
|
||||
|
||||
#ifndef NO_RECYCLE
|
||||
/* This function builds a list of all blocks needed in the current tmp file
|
||||
* for the contents of cut buffers.
|
||||
* !!! WARNING: if you have more than ~450000 bytes of text in all of the
|
||||
* cut buffers, then this will fail disastrously, because buffer overflow
|
||||
* is *not* allowed for.
|
||||
*/
|
||||
int cutneeds(need)
|
||||
BLK *need; /* this is where we deposit the list */
|
||||
{
|
||||
struct cutbuf *cb; /* used to count through cut buffers */
|
||||
int i; /* used to count through blocks of a cut buffer */
|
||||
int n; /* total number of blocks in list */
|
||||
|
||||
n = 0;
|
||||
|
||||
/* first the named buffers... */
|
||||
for (cb = named; cb < &named[27]; cb++)
|
||||
{
|
||||
if (cb->tmpnum != tmpnum)
|
||||
continue;
|
||||
|
||||
for (i = cb->nblks; i-- > 0; )
|
||||
{
|
||||
need->n[n++] = cb->phys[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* then the anonymous buffers */
|
||||
for (cb = anon; cb < &anon[NANONS]; cb++)
|
||||
{
|
||||
if (cb->tmpnum != tmpnum)
|
||||
continue;
|
||||
|
||||
for (i = cb->nblks; i-- > 0; )
|
||||
{
|
||||
need->n[n++] = cb->phys[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* return the length of the list */
|
||||
return n;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void maybezap(num)
|
||||
int num; /* the tmpnum of the temporary file to [maybe] delete */
|
||||
{
|
||||
char cutfname[80];
|
||||
int i;
|
||||
|
||||
/* if this is the current tmp file, then we'd better keep it! */
|
||||
if (tmpfd >= 0 && num == tmpnum)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* see if anybody else needs this tmp file */
|
||||
for (i = 27; --i >= 0; )
|
||||
{
|
||||
if (named[i].nblks > 0 && named[i].tmpnum == num)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < 0)
|
||||
{
|
||||
for (i = NANONS; --i >= 0 ; )
|
||||
{
|
||||
if (anon[i].nblks > 0 && anon[i].tmpnum == num)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if nobody else needs it, then discard the tmp file */
|
||||
if (i < 0)
|
||||
{
|
||||
#if MSDOS || TOS
|
||||
strcpy(cutfname, o_directory);
|
||||
if ((i = strlen(cutfname)) && !strchr(":/\\", cutfname[i - 1]))
|
||||
cutfname[i++] = SLASH;
|
||||
sprintf(cutfname + i, TMPNAME + 3, getpid(), num);
|
||||
#else
|
||||
sprintf(cutfname, TMPNAME, o_directory, getpid(), num);
|
||||
#endif
|
||||
unlink(cutfname);
|
||||
}
|
||||
}
|
||||
|
||||
/* This function frees a cut buffer. If it was the last cut buffer that
|
||||
* refered to an old temp file, then it will delete the temp file. */
|
||||
static void cutfree(buf)
|
||||
struct cutbuf *buf;
|
||||
{
|
||||
int num;
|
||||
|
||||
/* return immediately if the buffer is already empty */
|
||||
if (buf->nblks <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* else free up stuff */
|
||||
num = buf->tmpnum;
|
||||
buf->nblks = 0;
|
||||
#ifdef DEBUG
|
||||
if (!buf->phys)
|
||||
msg("cutfree() tried to free a NULL buf->phys pointer.");
|
||||
else
|
||||
#endif
|
||||
free((char *)buf->phys);
|
||||
|
||||
/* maybe delete the temp file */
|
||||
maybezap(num);
|
||||
}
|
||||
|
||||
/* This function is called when we are about to abort a tmp file.
|
||||
*
|
||||
* To minimize the number of extra files lying around, only named cut buffers
|
||||
* are preserved in a file switch; the anonymous buffers just go away.
|
||||
*/
|
||||
void cutswitch()
|
||||
{
|
||||
int i;
|
||||
|
||||
/* mark the current temp file as being "obsolete", and close it. */
|
||||
storename((char *)0);
|
||||
close(tmpfd);
|
||||
tmpfd = -1;
|
||||
|
||||
/* discard all anonymous cut buffers */
|
||||
for (i = 0; i < NANONS; i++)
|
||||
{
|
||||
cutfree(&anon[i]);
|
||||
}
|
||||
|
||||
/* delete the temp file, if we don't really need it */
|
||||
maybezap(tmpnum);
|
||||
}
|
||||
|
||||
/* This function should be called just before termination of vi */
|
||||
void cutend()
|
||||
{
|
||||
int i;
|
||||
|
||||
/* free the anonymous buffers, if they aren't already free */
|
||||
cutswitch();
|
||||
|
||||
/* free all named cut buffers, since they might be forcing an older
|
||||
* tmp file to be retained.
|
||||
*/
|
||||
for (i = 0; i < 27; i++)
|
||||
{
|
||||
cutfree(&named[i]);
|
||||
}
|
||||
|
||||
/* delete the temp file */
|
||||
maybezap(tmpnum);
|
||||
}
|
||||
|
||||
|
||||
/* This function is used to select the cut buffer to be used next */
|
||||
void cutname(name)
|
||||
int name; /* a single character */
|
||||
{
|
||||
cbname = name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* This function copies a selected segment of text to a cut buffer */
|
||||
void cut(from, to)
|
||||
MARK from; /* start of text to cut */
|
||||
MARK to; /* end of text to cut */
|
||||
{
|
||||
int first; /* logical number of first block in cut */
|
||||
int last; /* logical number of last block used in cut */
|
||||
long line; /* a line number */
|
||||
int lnmode; /* boolean: will this be a line-mode cut? */
|
||||
MARK delthru;/* end of text temporarily inserted for apnd */
|
||||
REG struct cutbuf *cb;
|
||||
REG long l;
|
||||
REG int i;
|
||||
REG char *scan;
|
||||
char *blkc;
|
||||
|
||||
/* detect whether this must be a line-mode cut or char-mode cut */
|
||||
if (markidx(from) == 0 && markidx(to) == 0)
|
||||
lnmode = TRUE;
|
||||
else
|
||||
lnmode = FALSE;
|
||||
|
||||
/* by default, we don't "delthru" anything */
|
||||
delthru = MARK_UNSET;
|
||||
|
||||
/* handle the "doingdot" quirks */
|
||||
if (doingdot)
|
||||
{
|
||||
if (!cbname)
|
||||
{
|
||||
cbname = dotcb;
|
||||
}
|
||||
}
|
||||
else if (cbname != '.')
|
||||
{
|
||||
dotcb = cbname;
|
||||
}
|
||||
|
||||
/* decide which cut buffer to use */
|
||||
if (!cbname)
|
||||
{
|
||||
/* free up the last anonymous cut buffer */
|
||||
cutfree(&anon[NANONS - 1]);
|
||||
|
||||
/* shift the anonymous cut buffers */
|
||||
for (i = NANONS - 1; i > 0; i--)
|
||||
{
|
||||
anon[i] = anon[i - 1];
|
||||
}
|
||||
|
||||
/* use the first anonymous cut buffer */
|
||||
cb = anon;
|
||||
cb->nblks = 0;
|
||||
}
|
||||
else if (cbname >= 'a' && cbname <= 'z')
|
||||
{
|
||||
cb = &named[cbname - 'a'];
|
||||
cutfree(cb);
|
||||
}
|
||||
#ifndef CRUNCH
|
||||
else if (cbname >= 'A' && cbname <= 'Z')
|
||||
{
|
||||
cb = &named[cbname - 'A'];
|
||||
if (cb->nblks > 0)
|
||||
{
|
||||
/* resolve linemode/charmode differences */
|
||||
if (!lnmode && cb->lnmode)
|
||||
{
|
||||
from &= ~(BLKSIZE - 1);
|
||||
if (markidx(to) != 0 || to == from)
|
||||
{
|
||||
to = to + BLKSIZE - markidx(to);
|
||||
}
|
||||
lnmode = TRUE;
|
||||
}
|
||||
|
||||
/* insert the old cut-buffer before the new text */
|
||||
mark[28] = to;
|
||||
delthru = paste(from, FALSE, TRUE);
|
||||
if (delthru == MARK_UNSET)
|
||||
{
|
||||
return;
|
||||
}
|
||||
delthru++;
|
||||
to = mark[28];
|
||||
}
|
||||
cutfree(cb);
|
||||
}
|
||||
#endif /* not CRUNCH */
|
||||
else if (cbname == '.')
|
||||
{
|
||||
cb = &named[26];
|
||||
cutfree(cb);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg("Invalid cut buffer name: \"%c", cbname);
|
||||
dotcb = cbname = '\0';
|
||||
return;
|
||||
}
|
||||
cbname = '\0';
|
||||
cb->tmpnum = tmpnum;
|
||||
|
||||
/* detect whether we're doing a line mode cut */
|
||||
cb->lnmode = lnmode;
|
||||
|
||||
/* ---------- */
|
||||
|
||||
/* Reporting... */
|
||||
if (markidx(from) == 0 && markidx(to) == 0)
|
||||
{
|
||||
rptlines = markline(to) - markline(from);
|
||||
rptlabel = "yanked";
|
||||
}
|
||||
|
||||
/* ---------- */
|
||||
|
||||
/* make sure each block has a physical disk address */
|
||||
blksync();
|
||||
|
||||
/* find the first block in the cut */
|
||||
line = markline(from);
|
||||
for (first = 1; line > lnum[first]; first++)
|
||||
{
|
||||
}
|
||||
|
||||
/* fetch text of the block containing that line */
|
||||
blkc = scan = blkget(first)->c;
|
||||
|
||||
/* find the mark in the block */
|
||||
for (l = lnum[first - 1]; ++l < line; )
|
||||
{
|
||||
while (*scan++ != '\n')
|
||||
{
|
||||
}
|
||||
}
|
||||
scan += markidx(from);
|
||||
|
||||
/* remember the offset of the start */
|
||||
cb->start = scan - blkc;
|
||||
|
||||
/* ---------- */
|
||||
|
||||
/* find the last block in the cut */
|
||||
line = markline(to);
|
||||
for (last = first; line > lnum[last]; last++)
|
||||
{
|
||||
}
|
||||
|
||||
/* fetch text of the block containing that line */
|
||||
if (last != first)
|
||||
{
|
||||
blkc = scan = blkget(last)->c;
|
||||
}
|
||||
else
|
||||
{
|
||||
scan = blkc;
|
||||
}
|
||||
|
||||
/* find the mark in the block */
|
||||
for (l = lnum[last - 1]; ++l < line; )
|
||||
{
|
||||
while (*scan++ != '\n')
|
||||
{
|
||||
}
|
||||
}
|
||||
if (markline(to) <= nlines)
|
||||
{
|
||||
scan += markidx(to);
|
||||
}
|
||||
|
||||
/* remember the offset of the end */
|
||||
cb->end = scan - blkc;
|
||||
|
||||
/* ------- */
|
||||
|
||||
/* remember the physical block numbers of all included blocks */
|
||||
cb->nblks = last - first;
|
||||
if (cb->end > 0)
|
||||
{
|
||||
cb->nblks++;
|
||||
}
|
||||
#ifdef lint
|
||||
cb->phys = (short *)0;
|
||||
#else
|
||||
cb->phys = (short *)malloc((unsigned)(cb->nblks * sizeof(short)));
|
||||
#endif
|
||||
for (i = 0; i < cb->nblks; i++)
|
||||
{
|
||||
cb->phys[i] = hdr.n[first++];
|
||||
}
|
||||
|
||||
#ifndef CRUNCH
|
||||
/* if we temporarily inserted text for appending, then delete that
|
||||
* text now -- before the user sees it.
|
||||
*/
|
||||
if (delthru)
|
||||
{
|
||||
line = rptlines;
|
||||
delete(from, delthru);
|
||||
rptlines = line;
|
||||
rptlabel = "yanked";
|
||||
}
|
||||
#endif /* not CRUNCH */
|
||||
}
|
||||
|
||||
|
||||
static void readcutblk(cb, blkno)
|
||||
struct cutbuf *cb;
|
||||
int blkno;
|
||||
{
|
||||
char cutfname[50];/* name of an old temp file */
|
||||
int fd; /* either tmpfd or the result of open() */
|
||||
#if MSDOS || TOS
|
||||
int i;
|
||||
#endif
|
||||
|
||||
/* decide which fd to use */
|
||||
if (cb->tmpnum == tmpnum)
|
||||
{
|
||||
fd = tmpfd;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if MSDOS || TOS
|
||||
strcpy(cutfname, o_directory);
|
||||
if ((i = strlen(cutfname)) && !strchr(":/\\", cutfname[i-1]))
|
||||
cutfname[i++]=SLASH;
|
||||
sprintf(cutfname+i, TMPNAME+3, getpid(), cb->tmpnum);
|
||||
#else
|
||||
sprintf(cutfname, TMPNAME, o_directory, getpid(), cb->tmpnum);
|
||||
#endif
|
||||
fd = open(cutfname, O_RDONLY);
|
||||
}
|
||||
|
||||
/* get the block */
|
||||
lseek(fd, (long)cb->phys[blkno] * (long)BLKSIZE, 0);
|
||||
if (read(fd, tmpblk.c, (unsigned)BLKSIZE) != BLKSIZE)
|
||||
{
|
||||
msg("Error reading back from tmp file for pasting!");
|
||||
}
|
||||
|
||||
/* close the fd, if it isn't tmpfd */
|
||||
if (fd != tmpfd)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* This function inserts text from a cut buffer, and returns the MARK where
|
||||
* insertion ended. Return MARK_UNSET on errors.
|
||||
*/
|
||||
MARK paste(at, after, retend)
|
||||
MARK at; /* where to insert the text */
|
||||
int after; /* boolean: insert after mark? (rather than before) */
|
||||
int retend; /* boolean: return end of text? (rather than start) */
|
||||
{
|
||||
REG struct cutbuf *cb;
|
||||
REG int i;
|
||||
|
||||
/* handle the "doingdot" quirks */
|
||||
if (doingdot)
|
||||
{
|
||||
if (!cbname)
|
||||
{
|
||||
if (dotcb >= '1' && dotcb < '1' + NANONS - 1)
|
||||
{
|
||||
dotcb++;
|
||||
}
|
||||
cbname = dotcb;
|
||||
}
|
||||
}
|
||||
else if (cbname != '.')
|
||||
{
|
||||
dotcb = cbname;
|
||||
}
|
||||
|
||||
/* decide which cut buffer to use */
|
||||
if (cbname >= 'A' && cbname <= 'Z')
|
||||
{
|
||||
cb = &named[cbname - 'A'];
|
||||
}
|
||||
else if (cbname >= 'a' && cbname <= 'z')
|
||||
{
|
||||
cb = &named[cbname - 'a'];
|
||||
}
|
||||
else if (cbname >= '1' && cbname <= '9')
|
||||
{
|
||||
cb = &anon[cbname - '1'];
|
||||
}
|
||||
else if (cbname == '.')
|
||||
{
|
||||
cb = &named[26];
|
||||
}
|
||||
else if (!cbname)
|
||||
{
|
||||
cb = anon;
|
||||
}
|
||||
else
|
||||
{
|
||||
msg("Invalid cut buffer name: \"%c", cbname);
|
||||
cbname = '\0';
|
||||
return MARK_UNSET;
|
||||
}
|
||||
|
||||
/* make sure it isn't empty */
|
||||
if (cb->nblks == 0)
|
||||
{
|
||||
if (cbname)
|
||||
msg("Cut buffer \"%c is empty", cbname);
|
||||
else
|
||||
msg("Cut buffer is empty");
|
||||
cbname = '\0';
|
||||
return MARK_UNSET;
|
||||
}
|
||||
cbname = '\0';
|
||||
|
||||
/* adjust the insertion MARK for "after" and line-mode cuts */
|
||||
if (cb->lnmode)
|
||||
{
|
||||
at &= ~(BLKSIZE - 1);
|
||||
if (after)
|
||||
{
|
||||
at += BLKSIZE;
|
||||
}
|
||||
}
|
||||
else if (after)
|
||||
{
|
||||
/* careful! if markidx(at) == 0 we might be pasting into an
|
||||
* empty line -- so we can't blindly increment "at".
|
||||
*/
|
||||
if (markidx(at) == 0)
|
||||
{
|
||||
pfetch(markline(at));
|
||||
if (plen != 0)
|
||||
{
|
||||
at++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
at++;
|
||||
}
|
||||
}
|
||||
|
||||
/* put a copy of the "at" mark in the mark[] array, so it stays in
|
||||
* sync with changes made via add().
|
||||
*/
|
||||
mark[27] = at;
|
||||
|
||||
/* simple one-block paste? */
|
||||
if (cb->nblks == 1)
|
||||
{
|
||||
/* get the block */
|
||||
readcutblk(cb, 0);
|
||||
|
||||
/* isolate the text we need within it */
|
||||
if (cb->end)
|
||||
{
|
||||
tmpblk.c[cb->end] = '\0';
|
||||
}
|
||||
|
||||
/* insert it */
|
||||
ChangeText
|
||||
{
|
||||
add(at, &tmpblk.c[cb->start]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* multi-block paste */
|
||||
|
||||
ChangeText
|
||||
{
|
||||
i = cb->nblks - 1;
|
||||
|
||||
/* add text from the last block first */
|
||||
if (cb->end > 0)
|
||||
{
|
||||
readcutblk(cb, i);
|
||||
tmpblk.c[cb->end] = '\0';
|
||||
add(at, tmpblk.c);
|
||||
i--;
|
||||
}
|
||||
|
||||
/* add intervening blocks */
|
||||
while (i > 0)
|
||||
{
|
||||
readcutblk(cb, i);
|
||||
add(at, tmpblk.c);
|
||||
i--;
|
||||
}
|
||||
|
||||
/* add text from the first cut block */
|
||||
readcutblk(cb, 0);
|
||||
add(at, &tmpblk.c[cb->start]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reporting... */
|
||||
rptlines = markline(mark[27]) - markline(at);
|
||||
rptlabel = "pasted";
|
||||
|
||||
/* return the mark at the beginning/end of inserted text */
|
||||
if (retend)
|
||||
{
|
||||
return mark[27] - 1L;
|
||||
}
|
||||
return at;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef NO_AT
|
||||
|
||||
/* This function copies characters from a cut buffer into a string.
|
||||
* It returns the number of characters in the cut buffer. If the cut
|
||||
* buffer is too large to fit in the string (i.e. if cb2str() returns
|
||||
* a number >= size) then the characters will not have been copied.
|
||||
* It returns 0 if the cut buffer is empty, and -1 for invalid cut buffers.
|
||||
*/
|
||||
int cb2str(name, buf, size)
|
||||
int name; /* the name of a cut-buffer to get: a-z only! */
|
||||
char *buf; /* where to put the string */
|
||||
unsigned size; /* size of buf */
|
||||
{
|
||||
REG struct cutbuf *cb;
|
||||
REG char *src;
|
||||
REG char *dest;
|
||||
|
||||
/* decide which cut buffer to use */
|
||||
if (name >= 'a' && name <= 'z')
|
||||
{
|
||||
cb = &named[name - 'a'];
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* if the buffer is empty, return 0 */
|
||||
if (cb->nblks == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* !!! if not a single-block cut, then fail */
|
||||
if (cb->nblks != 1)
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
/* if too big, return the size now, without doing anything */
|
||||
if (cb->end - cb->start >= size)
|
||||
{
|
||||
return cb->end - cb->start;
|
||||
}
|
||||
|
||||
/* get the block */
|
||||
readcutblk(cb, 0);
|
||||
|
||||
/* isolate the string within that blk */
|
||||
if (cb->start == 0)
|
||||
{
|
||||
tmpblk.c[cb->end] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
for (dest = tmpblk.c, src = dest + cb->start; src < tmpblk.c + cb->end; )
|
||||
{
|
||||
*dest++ = *src++;
|
||||
}
|
||||
*dest = '\0';
|
||||
}
|
||||
|
||||
/* copy the string into the buffer */
|
||||
if (buf != tmpblk.c)
|
||||
{
|
||||
strcpy(buf, tmpblk.c);
|
||||
}
|
||||
|
||||
/* return the length */
|
||||
return cb->end - cb->start;
|
||||
}
|
||||
#endif
|
|
@ -1,287 +0,0 @@
|
|||
/* elvprsv.c */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* 14407 SW Teal Blvd. #C
|
||||
* Beaverton, OR 97005
|
||||
* kirkenda@cs.pdx.edu
|
||||
*/
|
||||
|
||||
|
||||
/* This file contains the portable sources for the "elvprsv" program.
|
||||
* "Elvprsv" is run by Elvis when Elvis is about to die. It is also
|
||||
* run when the computer boots up. It is not intended to be run directly
|
||||
* by the user, ever.
|
||||
*
|
||||
* Basically, this program does the following four things:
|
||||
* - It extracts the text from the temporary file, and places the text in
|
||||
* a file in the /usr/preserve directory.
|
||||
* - It adds a line to the /usr/preserve/Index file, describing the file
|
||||
* that it just preserved.
|
||||
* - It removes the temporary file.
|
||||
* - It sends mail to the owner of the file, saying that the file was
|
||||
* preserved, and how it can be recovered.
|
||||
*
|
||||
* The /usr/preserve/Index file is a log file that contains one line for each
|
||||
* file that has ever been preserved. Each line of this file describes one
|
||||
* preserved file. The first word on the line is the name of the file that
|
||||
* contains the preserved text. The second word is the full pathname of the
|
||||
* file that was being edited; for anonymous buffers, this is the directory
|
||||
* name plus "/foo".
|
||||
*
|
||||
* If elvprsv's first argument (after the command name) starts with a hyphen,
|
||||
* then the characters after the hyphen are used as a description of when
|
||||
* the editor went away. This is optional.
|
||||
*
|
||||
* The remaining arguments are all the names of temporary files that are
|
||||
* to be preserved. For example, on a UNIX system, the /etc/rc file might
|
||||
* invoke it this way:
|
||||
*
|
||||
* elvprsv "-the system went down" /tmp/elv_*.*
|
||||
*
|
||||
* This file contains only the portable parts of the preserve program.
|
||||
* It must #include a system-specific file. The system-specific file is
|
||||
* expected to define the following functions:
|
||||
*
|
||||
* char *ownername(char *filename) - returns name of person who owns file
|
||||
*
|
||||
* void mail(char *user, char *name, char *when)
|
||||
* - tell user that file was preserved
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "config.h"
|
||||
#include "vi.h"
|
||||
|
||||
#if AMIGA
|
||||
BLK tmpblk;
|
||||
#error AMIGA here DEBUG
|
||||
# include "amiwild.c"
|
||||
# include "amiprsv.c"
|
||||
#endif
|
||||
|
||||
#if OSK
|
||||
# undef sprintf
|
||||
#endif
|
||||
|
||||
#if ANY_UNIX || OSK
|
||||
# include "prsvunix.c"
|
||||
#endif
|
||||
|
||||
#if MSDOS || TOS
|
||||
# include "prsvdos.c"
|
||||
# define WILDCARD_NO_MAIN
|
||||
# include "wildcard.c"
|
||||
#endif
|
||||
|
||||
|
||||
BLK buf;
|
||||
BLK hdr;
|
||||
BLK name;
|
||||
int rewrite_now; /* boolean: should we send text directly to orig file? */
|
||||
|
||||
|
||||
|
||||
/* This function preserves a single file, and announces its success/failure
|
||||
* via an e-mail message.
|
||||
*/
|
||||
void preserve(tname, when)
|
||||
char *tname; /* name of a temp file to be preserved */
|
||||
char *when; /* description of when the editor died */
|
||||
{
|
||||
int infd; /* fd used for reading from the temp file */
|
||||
FILE *outfp; /* fp used for writing to the recovery file */
|
||||
FILE *index; /* fp used for appending to index file */
|
||||
char outname[100]; /* the name of the recovery file */
|
||||
char *user; /* name of the owner of the temp file */
|
||||
#if AMIGA
|
||||
char *prsvdir;
|
||||
#endif
|
||||
int i;
|
||||
|
||||
/* open the temp file */
|
||||
infd = open(tname, O_RDONLY|O_BINARY);
|
||||
if (infd < 0)
|
||||
{
|
||||
/* if we can't open the file, then we should assume that
|
||||
* the filename contains wildcard characters that weren't
|
||||
* expanded... and also assume that they weren't expanded
|
||||
* because there are no files that need to be preserved.
|
||||
* THEREFORE... we should silently ignore it.
|
||||
* (Or loudly ignore it if the user was using -R)
|
||||
*/
|
||||
if (rewrite_now)
|
||||
{
|
||||
perror(tname);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* read the header and name from the file */
|
||||
if (read(infd, hdr.c, BLKSIZE) != BLKSIZE
|
||||
|| read(infd, name.c, BLKSIZE) != BLKSIZE)
|
||||
{
|
||||
/* something wrong with the file - sorry */
|
||||
fprintf(stderr, "%s: trucated header blocks\n", tname);
|
||||
close(infd);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the filename block contains an empty string, then Elvis was
|
||||
* only keeping the temp file around because it contained some text
|
||||
* that was needed for a named cut buffer. The user doesn't care
|
||||
* about that kind of temp file, so we should silently delete it.
|
||||
*/
|
||||
if (name.c[0] == '\0' && name.c[1] == '\177')
|
||||
{
|
||||
close(infd);
|
||||
unlink(tname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (rewrite_now)
|
||||
{
|
||||
/* we don't need to open the index file */
|
||||
index = (FILE *)0;
|
||||
|
||||
/* make sure we can read every block! */
|
||||
for (i = 1; i < MAXBLKS && hdr.n[i]; i++)
|
||||
{
|
||||
lseek(infd, (long)hdr.n[i] * (long)BLKSIZE, 0);
|
||||
if (read(infd, buf.c, BLKSIZE) != BLKSIZE)
|
||||
{
|
||||
/* messed up header */
|
||||
fprintf(stderr, "%s: unrecoverable -- header trashed\n", name.c);
|
||||
close(infd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* open the user's file for writing */
|
||||
outfp = fopen(name.c, "w");
|
||||
if (!outfp)
|
||||
{
|
||||
perror(name.c);
|
||||
close(infd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* open/create the index file */
|
||||
index = fopen(PRSVINDEX, "a");
|
||||
if (!index)
|
||||
{
|
||||
perror(PRSVINDEX);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* create the recovery file in the PRESVDIR directory */
|
||||
#if AMIGA
|
||||
prsvdir = &PRSVDIR[strlen(PRSVDIR) - 1];
|
||||
if (*prsvdir == '/' || *prsvdir == ':')
|
||||
{
|
||||
sprintf(outname, "%sp%ld", PRSVDIR, ftell(index));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
sprintf(outname, "%s%cp%ld", PRSVDIR, SLASH, ftell(index));
|
||||
outfp = fopen(outname, "w");
|
||||
if (!outfp)
|
||||
{
|
||||
perror(outname);
|
||||
close(infd);
|
||||
fclose(index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* write the text of the file out to the recovery file */
|
||||
for (i = 1; i < MAXBLKS && hdr.n[i]; i++)
|
||||
{
|
||||
lseek(infd, (long)hdr.n[i] * (long)BLKSIZE, 0);
|
||||
if (read(infd, buf.c, BLKSIZE) != BLKSIZE)
|
||||
{
|
||||
/* messed up header */
|
||||
fprintf(stderr, "%s: unrecoverable -- header trashed\n", name.c);
|
||||
fclose(outfp);
|
||||
close(infd);
|
||||
if (index)
|
||||
{
|
||||
fclose(index);
|
||||
}
|
||||
unlink(outname);
|
||||
return;
|
||||
}
|
||||
fputs(buf.c, outfp);
|
||||
}
|
||||
|
||||
/* add a line to the index file */
|
||||
if (index)
|
||||
{
|
||||
fprintf(index, "%s %s\n", outname, name.c);
|
||||
}
|
||||
|
||||
/* close everything */
|
||||
close(infd);
|
||||
fclose(outfp);
|
||||
if (index)
|
||||
{
|
||||
fclose(index);
|
||||
}
|
||||
|
||||
/* Are we doing this due to something more frightening than just
|
||||
* a ":preserve" command?
|
||||
*/
|
||||
if (*when)
|
||||
{
|
||||
/* send a mail message */
|
||||
mail(ownername(tname), name.c, when);
|
||||
|
||||
/* remove the temp file -- the editor has died already */
|
||||
unlink(tname);
|
||||
}
|
||||
}
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int i;
|
||||
char *when = "the editor went away";
|
||||
|
||||
#if MSDOS || TOS
|
||||
/* expand any wildcards in the command line */
|
||||
argv = wildexpand(&argc, argv);
|
||||
#endif
|
||||
|
||||
/* do we have a "when" argument? */
|
||||
i = 1;
|
||||
if (argc >= i + 1 && !strcmp(argv[i], "-R"))
|
||||
{
|
||||
rewrite_now = 1;
|
||||
when = "";
|
||||
i++;
|
||||
#if ANY_UNIX
|
||||
setuid(geteuid());
|
||||
#endif
|
||||
}
|
||||
#if OSK
|
||||
else
|
||||
{
|
||||
setuid(0);
|
||||
}
|
||||
#endif
|
||||
if (argc >= i + 1 && argv[i][0] == '-')
|
||||
{
|
||||
when = argv[i] + 1;
|
||||
i++;
|
||||
}
|
||||
|
||||
/* preserve everything we're supposed to */
|
||||
while (i < argc)
|
||||
{
|
||||
preserve(argv[i], when);
|
||||
i++;
|
||||
}
|
||||
}
|
|
@ -1,199 +0,0 @@
|
|||
/* elvrec.c */
|
||||
|
||||
/* This file contains the file recovery program */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* 14407 SW Teal Blvd. #C
|
||||
* Beaverton, OR 97005
|
||||
* kirkenda@cs.pdx.edu
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "config.h"
|
||||
#include "vi.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
void recover(basename, outname)
|
||||
char *basename; /* the name of the file to recover */
|
||||
char *outname; /* the name of the file to write to */
|
||||
{
|
||||
char pathname[500]; /* full pathname of the file to recover */
|
||||
char line[600]; /* a line from the /usr/preserve/Index file */
|
||||
int ch; /* a character from the text being recovered */
|
||||
FILE *from; /* the /usr/preserve file, or /usr/preserve/Index */
|
||||
FILE *to; /* the user's text file */
|
||||
char *ptr;
|
||||
struct stat st;
|
||||
#if OSK
|
||||
int uid;
|
||||
#endif
|
||||
|
||||
/* convert basename to a full pathname */
|
||||
if (basename)
|
||||
{
|
||||
#ifndef CRUNCH
|
||||
# if MSDOS || TOS
|
||||
if (!basename[0] || basename[1] != ':')
|
||||
# else
|
||||
if (basename[0] != SLASH)
|
||||
# endif
|
||||
{
|
||||
ptr = getcwd(pathname, sizeof pathname);
|
||||
if (ptr != pathname)
|
||||
{
|
||||
strcpy(pathname, ptr);
|
||||
}
|
||||
ptr = pathname + strlen(pathname);
|
||||
*ptr++ = SLASH;
|
||||
strcpy(ptr, basename);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
strcpy(pathname, basename);
|
||||
}
|
||||
}
|
||||
|
||||
#if OSK
|
||||
uid = getuid();
|
||||
if(setuid(0))
|
||||
exit(_errmsg(errno, "Can't set uid\n"));
|
||||
#endif
|
||||
/* scan the /usr/preserve/Index file, for the *oldest* unrecovered
|
||||
* version of this file.
|
||||
*/
|
||||
from = fopen(PRSVINDEX, "r");
|
||||
while (from && fgets(line, sizeof line, from))
|
||||
{
|
||||
/* strip off the newline from the end of the string */
|
||||
line[strlen(line) - 1] = '\0';
|
||||
|
||||
/* parse the line into a "preserve" name and a "text" name */
|
||||
for (ptr = line; *ptr != ' '; ptr++)
|
||||
{
|
||||
}
|
||||
*ptr++ = '\0';
|
||||
|
||||
/* If the "preserve" file is missing, then ignore this line
|
||||
* because it describes a file that has already been recovered.
|
||||
*/
|
||||
if (stat(line, &st) < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* are we looking for a specific file? */
|
||||
if (basename)
|
||||
{
|
||||
/* quit if we found it */
|
||||
if (!strcmp(ptr, pathname))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* list this file as "available for recovery" */
|
||||
puts(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
/* file not found? */
|
||||
if (!basename || !from || feof(from))
|
||||
{
|
||||
if (from != NULL) fclose(from);
|
||||
if (basename)
|
||||
{
|
||||
fprintf(stderr, "%s: no recovered file has that exact name\n", pathname);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (from != NULL) fclose(from);
|
||||
|
||||
/* copy the recovered text back into the user's file... */
|
||||
|
||||
/* open the /usr/preserve file for reading */
|
||||
from = fopen(line, "r");
|
||||
if (!from)
|
||||
{
|
||||
perror(line);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
#if ANY_UNIX
|
||||
/* Be careful about user-id. We want to be running under the user's
|
||||
* real id when we open/create the user's text file... but we want
|
||||
* to be superuser when we delete the /usr/preserve file. For UNIX,
|
||||
* we accomplish this by deleting the /usr/preserve file *now*,
|
||||
* when it is open but before we've read it. Then we revert to the
|
||||
* user's real id.
|
||||
*/
|
||||
unlink(line);
|
||||
setuid(getuid());
|
||||
#endif
|
||||
#if OSK
|
||||
setuid(uid);
|
||||
#endif
|
||||
|
||||
if (outname == NULL) return;
|
||||
|
||||
/* open the user's file for writing */
|
||||
to = fopen(outname, "w");
|
||||
if (!to)
|
||||
{
|
||||
perror(ptr);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
/* copy the text */
|
||||
while ((ch = getc(from)) != EOF)
|
||||
{
|
||||
putc(ch, to);
|
||||
}
|
||||
|
||||
#if !ANY_UNIX
|
||||
#if OSK
|
||||
fclose(from);
|
||||
setuid(0);
|
||||
#endif
|
||||
/* delete the /usr/preserve file */
|
||||
unlink(line);
|
||||
#if OSK
|
||||
setuid(uid);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
/* check arguments */
|
||||
if (argc > 3)
|
||||
{
|
||||
fprintf(stderr, "usage: %s [preserved_file [recovery_file]]\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* recover the requested file, or list recoverable files */
|
||||
if (argc == 3)
|
||||
{
|
||||
/* recover the file, but write it to a different filename */
|
||||
recover (argv[1], argv[2]);
|
||||
}
|
||||
else if (argc == 2)
|
||||
{
|
||||
/* recover the file */
|
||||
recover(argv[1], argv[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* list the recoverable files */
|
||||
recover((char *)0, (char *)0);
|
||||
}
|
||||
|
||||
/* success! */
|
||||
exit(0);
|
||||
}
|
|
@ -1,722 +0,0 @@
|
|||
/* ex.c */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* 14407 SW Teal Blvd. #C
|
||||
* Beaverton, OR 97005
|
||||
* kirkenda@cs.pdx.edu
|
||||
*/
|
||||
|
||||
|
||||
/* This file contains the code for reading ex commands. */
|
||||
|
||||
#include "config.h"
|
||||
#include "ctype.h"
|
||||
#include "vi.h"
|
||||
|
||||
/* This data type is used to describe the possible argument combinations */
|
||||
typedef short ARGT;
|
||||
#define FROM 1 /* allow a linespec */
|
||||
#define TO 2 /* allow a second linespec */
|
||||
#define BANG 4 /* allow a ! after the command name */
|
||||
#define EXTRA 8 /* allow extra args after command name */
|
||||
#define XFILE 16 /* expand wildcards in extra part */
|
||||
#define NOSPC 32 /* no spaces allowed in the extra part */
|
||||
#define DFLALL 64 /* default file range is 1,$ */
|
||||
#define DFLNONE 128 /* no default file range */
|
||||
#define NODFL 256 /* do not default to the current file name */
|
||||
#define EXRCOK 512 /* can be in a .exrc file */
|
||||
#define NL 1024 /* if mode!=MODE_EX, then write a newline first */
|
||||
#define PLUS 2048 /* allow a line number, as in ":e +32 foo" */
|
||||
#define ZERO 4096 /* allow 0 to be given as a line number */
|
||||
#define NOBAR 8192 /* treat following '|' chars as normal */
|
||||
#define FILES (XFILE + EXTRA) /* multiple extra files allowed */
|
||||
#define WORD1 (EXTRA + NOSPC) /* one extra word allowed */
|
||||
#define FILE1 (FILES + NOSPC) /* 1 file allowed, defaults to current file */
|
||||
#define NAMEDF (FILE1 + NODFL) /* 1 file allowed, defaults to "" */
|
||||
#define NAMEDFS (FILES + NODFL) /* multiple files allowed, default is "" */
|
||||
#define RANGE (FROM + TO) /* range of linespecs allowed */
|
||||
#define NONE 0 /* no args allowed at all */
|
||||
|
||||
/* This array maps ex command names to command codes. The order in which
|
||||
* command names are listed below is significant -- ambiguous abbreviations
|
||||
* are always resolved to be the first possible match. (e.g. "r" is taken
|
||||
* to mean "read", not "rewind", because "read" comes before "rewind")
|
||||
*/
|
||||
static struct
|
||||
{
|
||||
char *name; /* name of the command */
|
||||
CMD code; /* enum code of the command */
|
||||
void (*fn)();/* function which executes the command */
|
||||
ARGT argt; /* command line arguments permitted/needed/used */
|
||||
}
|
||||
cmdnames[] =
|
||||
{ /* cmd name cmd code function arguments */
|
||||
{"append", CMD_APPEND, cmd_append, FROM+ZERO+BANG },
|
||||
#ifdef DEBUG
|
||||
{"bug", CMD_DEBUG, cmd_debug, RANGE+BANG+EXTRA+NL},
|
||||
#endif
|
||||
{"change", CMD_CHANGE, cmd_append, RANGE+BANG },
|
||||
{"delete", CMD_DELETE, cmd_delete, RANGE+WORD1 },
|
||||
{"edit", CMD_EDIT, cmd_edit, BANG+FILE1+PLUS },
|
||||
{"file", CMD_FILE, cmd_file, NAMEDF },
|
||||
{"global", CMD_GLOBAL, cmd_global, RANGE+BANG+EXTRA+DFLALL+NOBAR},
|
||||
{"insert", CMD_INSERT, cmd_append, FROM+BANG },
|
||||
{"join", CMD_INSERT, cmd_join, RANGE+BANG },
|
||||
{"k", CMD_MARK, cmd_mark, FROM+WORD1 },
|
||||
{"list", CMD_LIST, cmd_print, RANGE+NL },
|
||||
{"move", CMD_MOVE, cmd_move, RANGE+EXTRA },
|
||||
{"next", CMD_NEXT, cmd_next, BANG+NAMEDFS },
|
||||
{"Next", CMD_PREVIOUS, cmd_next, BANG },
|
||||
{"print", CMD_PRINT, cmd_print, RANGE+NL },
|
||||
{"quit", CMD_QUIT, cmd_xit, BANG },
|
||||
{"read", CMD_READ, cmd_read, FROM+ZERO+NAMEDF},
|
||||
{"substitute", CMD_SUBSTITUTE, cmd_substitute, RANGE+EXTRA },
|
||||
{"to", CMD_COPY, cmd_move, RANGE+EXTRA },
|
||||
{"undo", CMD_UNDO, cmd_undo, NONE },
|
||||
{"vglobal", CMD_VGLOBAL, cmd_global, RANGE+EXTRA+DFLALL+NOBAR},
|
||||
{"write", CMD_WRITE, cmd_write, RANGE+BANG+FILE1+DFLALL},
|
||||
{"xit", CMD_XIT, cmd_xit, BANG+NL },
|
||||
{"yank", CMD_YANK, cmd_delete, RANGE+WORD1 },
|
||||
|
||||
{"!", CMD_BANG, cmd_shell, EXRCOK+RANGE+NAMEDFS+DFLNONE+NL+NOBAR},
|
||||
{"#", CMD_NUMBER, cmd_print, RANGE+NL },
|
||||
{"<", CMD_SHIFTL, cmd_shift, RANGE },
|
||||
{">", CMD_SHIFTR, cmd_shift, RANGE },
|
||||
{"=", CMD_EQUAL, cmd_file, RANGE },
|
||||
{"&", CMD_SUBAGAIN, cmd_substitute, RANGE },
|
||||
#ifndef NO_AT
|
||||
{"@", CMD_AT, cmd_at, EXTRA },
|
||||
#endif
|
||||
|
||||
#ifndef NO_ABBR
|
||||
{"abbreviate", CMD_ABBR, cmd_map, EXRCOK+BANG+EXTRA},
|
||||
#endif
|
||||
{"args", CMD_ARGS, cmd_args, EXRCOK+NAMEDFS },
|
||||
#ifndef NO_ERRLIST
|
||||
{"cc", CMD_CC, cmd_make, BANG+FILES },
|
||||
#endif
|
||||
{"cd", CMD_CD, cmd_cd, EXRCOK+BANG+NAMEDF},
|
||||
{"copy", CMD_COPY, cmd_move, RANGE+EXTRA },
|
||||
#ifndef NO_DIGRAPH
|
||||
{"digraph", CMD_DIGRAPH, cmd_digraph, EXRCOK+BANG+EXTRA},
|
||||
#endif
|
||||
#ifndef NO_ERRLIST
|
||||
{"errlist", CMD_ERRLIST, cmd_errlist, BANG+NAMEDF },
|
||||
#endif
|
||||
{"ex", CMD_EDIT, cmd_edit, BANG+FILE1 },
|
||||
{"mark", CMD_MARK, cmd_mark, FROM+WORD1 },
|
||||
#ifndef NO_MKEXRC
|
||||
{"mkexrc", CMD_MKEXRC, cmd_mkexrc, NAMEDF },
|
||||
#endif
|
||||
{"number", CMD_NUMBER, cmd_print, RANGE+NL },
|
||||
{"put", CMD_PUT, cmd_put, FROM+ZERO+WORD1 },
|
||||
{"set", CMD_SET, cmd_set, EXRCOK+EXTRA },
|
||||
{"shell", CMD_SHELL, cmd_shell, NL },
|
||||
{"source", CMD_SOURCE, cmd_source, EXRCOK+NAMEDF },
|
||||
#ifdef SIGTSTP
|
||||
{"stop", CMD_STOP, cmd_suspend, NONE },
|
||||
#endif
|
||||
{"tag", CMD_TAG, cmd_tag, BANG+WORD1 },
|
||||
{"version", CMD_VERSION, cmd_version, EXRCOK+NONE },
|
||||
{"visual", CMD_VISUAL, cmd_edit, BANG+NAMEDF },
|
||||
{"wq", CMD_WQUIT, cmd_xit, NL },
|
||||
|
||||
#ifdef DEBUG
|
||||
{"debug", CMD_DEBUG, cmd_debug, RANGE+BANG+EXTRA+NL},
|
||||
{"validate", CMD_VALIDATE, cmd_validate, BANG+NL },
|
||||
#endif
|
||||
{"chdir", CMD_CD, cmd_cd, EXRCOK+BANG+NAMEDF},
|
||||
#ifndef NO_COLOR
|
||||
{"color", CMD_COLOR, cmd_color, EXRCOK+EXTRA },
|
||||
#endif
|
||||
#ifndef NO_ERRLIST
|
||||
{"make", CMD_MAKE, cmd_make, BANG+NAMEDFS },
|
||||
#endif
|
||||
{"map", CMD_MAP, cmd_map, EXRCOK+BANG+EXTRA},
|
||||
{"previous", CMD_PREVIOUS, cmd_next, BANG },
|
||||
{"rewind", CMD_REWIND, cmd_next, BANG },
|
||||
#ifdef SIGTSTP
|
||||
{"suspend", CMD_SUSPEND, cmd_suspend, NONE },
|
||||
#endif
|
||||
{"unmap", CMD_UNMAP, cmd_map, EXRCOK+BANG+EXTRA},
|
||||
#ifndef NO_ABBR
|
||||
{"unabbreviate",CMD_UNABBR, cmd_map, EXRCOK+WORD1 },
|
||||
#endif
|
||||
|
||||
{(char *)0}
|
||||
};
|
||||
|
||||
|
||||
/* This function parses a search pattern - given a pointer to a / or ?,
|
||||
* it replaces the ending / or ? with a \0, and returns a pointer to the
|
||||
* stuff that came after the pattern.
|
||||
*/
|
||||
char *parseptrn(ptrn)
|
||||
REG char *ptrn;
|
||||
{
|
||||
REG char *scan;
|
||||
|
||||
for (scan = ptrn + 1;
|
||||
*scan && *scan != *ptrn;
|
||||
scan++)
|
||||
{
|
||||
/* allow backslashed versions of / and ? in the pattern */
|
||||
if (*scan == '\\' && scan[1] != '\0')
|
||||
{
|
||||
scan++;
|
||||
}
|
||||
}
|
||||
if (*scan)
|
||||
{
|
||||
*scan++ = '\0';
|
||||
}
|
||||
|
||||
return scan;
|
||||
}
|
||||
|
||||
|
||||
/* This function parses a line specifier for ex commands */
|
||||
char *linespec(s, markptr)
|
||||
REG char *s; /* start of the line specifier */
|
||||
MARK *markptr; /* where to store the mark's value */
|
||||
{
|
||||
long num;
|
||||
REG char *t;
|
||||
|
||||
/* parse each ;-delimited clause of this linespec */
|
||||
do
|
||||
{
|
||||
/* skip an initial ';', if any */
|
||||
if (*s == ';')
|
||||
{
|
||||
s++;
|
||||
}
|
||||
|
||||
/* skip leading spaces */
|
||||
while (isspace(*s))
|
||||
{
|
||||
s++;
|
||||
}
|
||||
|
||||
/* dot means current position */
|
||||
if (*s == '.')
|
||||
{
|
||||
s++;
|
||||
*markptr = cursor;
|
||||
}
|
||||
/* '$' means the last line */
|
||||
else if (*s == '$')
|
||||
{
|
||||
s++;
|
||||
*markptr = MARK_LAST;
|
||||
}
|
||||
/* digit means an absolute line number */
|
||||
else if (isdigit(*s))
|
||||
{
|
||||
for (num = 0; isdigit(*s); s++)
|
||||
{
|
||||
num = num * 10 + *s - '0';
|
||||
}
|
||||
*markptr = MARK_AT_LINE(num);
|
||||
}
|
||||
/* appostrophe means go to a set mark */
|
||||
else if (*s == '\'')
|
||||
{
|
||||
s++;
|
||||
*markptr = m_tomark(cursor, 1L, (int)*s);
|
||||
s++;
|
||||
}
|
||||
/* slash means do a search */
|
||||
else if (*s == '/' || *s == '?')
|
||||
{
|
||||
/* put a '\0' at the end of the search pattern */
|
||||
t = parseptrn(s);
|
||||
|
||||
/* search for the pattern */
|
||||
*markptr &= ~(BLKSIZE - 1);
|
||||
if (*s == '/')
|
||||
{
|
||||
pfetch(markline(*markptr));
|
||||
if (plen > 0)
|
||||
*markptr += plen - 1;
|
||||
*markptr = m_fsrch(*markptr, s);
|
||||
}
|
||||
else
|
||||
{
|
||||
*markptr = m_bsrch(*markptr, s);
|
||||
}
|
||||
|
||||
/* adjust command string pointer */
|
||||
s = t;
|
||||
}
|
||||
|
||||
/* if linespec was faulty, quit now */
|
||||
if (!*markptr)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
/* maybe add an offset */
|
||||
t = s;
|
||||
if (*t == '-' || *t == '+')
|
||||
{
|
||||
s++;
|
||||
for (num = 0; isdigit(*s); s++)
|
||||
{
|
||||
num = num * 10 + *s - '0';
|
||||
}
|
||||
if (num == 0)
|
||||
{
|
||||
num = 1;
|
||||
}
|
||||
*markptr = m_updnto(*markptr, num, *t);
|
||||
}
|
||||
} while (*s == ';' || *s == '+' || *s == '-');
|
||||
|
||||
/* protect against invalid line numbers */
|
||||
num = markline(*markptr);
|
||||
if (num < 1L || num > nlines)
|
||||
{
|
||||
msg("Invalid line number -- must be from 1 to %ld", nlines);
|
||||
*markptr = MARK_UNSET;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* This function reads an ex command and executes it. */
|
||||
void ex()
|
||||
{
|
||||
char cmdbuf[150];
|
||||
REG int cmdlen;
|
||||
static long oldline;
|
||||
|
||||
significant = FALSE;
|
||||
oldline = markline(cursor);
|
||||
|
||||
while (mode == MODE_EX)
|
||||
{
|
||||
/* read a line */
|
||||
#ifdef CRUNCH
|
||||
cmdlen = vgets(':', cmdbuf, sizeof(cmdbuf));
|
||||
#else
|
||||
cmdlen = vgets(*o_prompt ? ':' : '\0', cmdbuf, sizeof(cmdbuf));
|
||||
#endif
|
||||
if (cmdlen < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* if empty line, assume ".+1" */
|
||||
if (cmdlen == 0)
|
||||
{
|
||||
strcpy(cmdbuf, ".+1");
|
||||
qaddch('\r');
|
||||
clrtoeol();
|
||||
}
|
||||
else
|
||||
{
|
||||
addch('\n');
|
||||
}
|
||||
refresh();
|
||||
|
||||
/* parse & execute the command */
|
||||
doexcmd(cmdbuf);
|
||||
|
||||
/* handle autoprint */
|
||||
if (significant || markline(cursor) != oldline)
|
||||
{
|
||||
significant = FALSE;
|
||||
oldline = markline(cursor);
|
||||
if (*o_autoprint && mode == MODE_EX)
|
||||
{
|
||||
cmd_print(cursor, cursor, CMD_PRINT, FALSE, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void doexcmd(cmdbuf)
|
||||
char *cmdbuf; /* string containing an ex command */
|
||||
{
|
||||
REG char *scan; /* used to scan thru cmdbuf */
|
||||
MARK frommark; /* first linespec */
|
||||
MARK tomark; /* second linespec */
|
||||
REG int cmdlen; /* length of the command name given */
|
||||
CMD cmd; /* what command is this? */
|
||||
ARGT argt; /* argument types for this command */
|
||||
short forceit; /* bang version of a command? */
|
||||
REG int cmdidx; /* index of command */
|
||||
REG char *build; /* used while copying filenames */
|
||||
int iswild; /* boolean: filenames use wildcards? */
|
||||
int isdfl; /* using default line ranges? */
|
||||
int didsub; /* did we substitute file names for % or # */
|
||||
|
||||
/* ex commands can't be undone via the shift-U command */
|
||||
U_line = 0L;
|
||||
|
||||
/* permit extra colons at the start of the line */
|
||||
for (; *cmdbuf == ':'; cmdbuf++)
|
||||
{
|
||||
}
|
||||
|
||||
/* ignore command lines that start with a double-quote */
|
||||
if (*cmdbuf == '"')
|
||||
{
|
||||
return;
|
||||
}
|
||||
scan = cmdbuf;
|
||||
|
||||
/* parse the line specifier */
|
||||
if (nlines < 1)
|
||||
{
|
||||
/* no file, so don't allow addresses */
|
||||
}
|
||||
else if (*scan == '%')
|
||||
{
|
||||
/* '%' means all lines */
|
||||
frommark = MARK_FIRST;
|
||||
tomark = MARK_LAST;
|
||||
scan++;
|
||||
}
|
||||
else if (*scan == '0')
|
||||
{
|
||||
frommark = tomark = MARK_UNSET;
|
||||
scan++;
|
||||
}
|
||||
else
|
||||
{
|
||||
frommark = cursor;
|
||||
scan = linespec(scan, &frommark);
|
||||
tomark = frommark;
|
||||
if (frommark && *scan == ',')
|
||||
{
|
||||
scan++;
|
||||
scan = linespec(scan, &tomark);
|
||||
}
|
||||
if (!tomark)
|
||||
{
|
||||
/* faulty line spec -- fault already described */
|
||||
return;
|
||||
}
|
||||
if (frommark > tomark)
|
||||
{
|
||||
msg("first address exceeds the second");
|
||||
return;
|
||||
}
|
||||
}
|
||||
isdfl = (scan == cmdbuf);
|
||||
|
||||
/* skip whitespace */
|
||||
while (isspace(*scan))
|
||||
{
|
||||
scan++;
|
||||
}
|
||||
|
||||
/* if no command, then just move the cursor to the mark */
|
||||
if (!*scan)
|
||||
{
|
||||
if (tomark != MARK_UNSET)
|
||||
cursor = tomark;
|
||||
return;
|
||||
}
|
||||
|
||||
/* figure out how long the command name is */
|
||||
if (!isalpha(*scan))
|
||||
{
|
||||
cmdlen = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (cmdlen = 1;
|
||||
isalpha(scan[cmdlen]);
|
||||
cmdlen++)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/* lookup the command code */
|
||||
for (cmdidx = 0;
|
||||
cmdnames[cmdidx].name && strncmp(scan, cmdnames[cmdidx].name, cmdlen);
|
||||
cmdidx++)
|
||||
{
|
||||
}
|
||||
argt = cmdnames[cmdidx].argt;
|
||||
cmd = cmdnames[cmdidx].code;
|
||||
if (cmd == CMD_NULL)
|
||||
{
|
||||
msg("Unknown command \"%.*s\"", cmdlen, scan);
|
||||
return;
|
||||
}
|
||||
|
||||
/* !!! if the command doesn't have NOBAR set, then replace | with \0 */
|
||||
|
||||
/* if the command ended with a bang, set the forceit flag */
|
||||
scan += cmdlen;
|
||||
if ((argt & BANG) && *scan == '!')
|
||||
{
|
||||
scan++;
|
||||
forceit = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
forceit = 0;
|
||||
}
|
||||
|
||||
/* skip any more whitespace, to leave scan pointing to arguments */
|
||||
while (isspace(*scan))
|
||||
{
|
||||
scan++;
|
||||
}
|
||||
|
||||
/* a couple of special cases for filenames */
|
||||
if (argt & XFILE)
|
||||
{
|
||||
/* if names were given, process them */
|
||||
if (*scan)
|
||||
{
|
||||
for (build = tmpblk.c, iswild = didsub = FALSE; *scan; scan++)
|
||||
{
|
||||
switch (*scan)
|
||||
{
|
||||
case '\\':
|
||||
if (scan[1] == '\\' || scan[1] == '%' || scan[1] == '#')
|
||||
{
|
||||
*build++ = *++scan;
|
||||
}
|
||||
else
|
||||
{
|
||||
*build++ = '\\';
|
||||
}
|
||||
break;
|
||||
|
||||
case '%':
|
||||
if (!*origname)
|
||||
{
|
||||
msg("No filename to substitute for %%");
|
||||
return;
|
||||
}
|
||||
strcpy(build, origname);
|
||||
while (*build)
|
||||
{
|
||||
build++;
|
||||
}
|
||||
didsub = TRUE;
|
||||
break;
|
||||
|
||||
case '#':
|
||||
if (!*prevorig)
|
||||
{
|
||||
msg("No filename to substitute for #");
|
||||
return;
|
||||
}
|
||||
strcpy(build, prevorig);
|
||||
while (*build)
|
||||
{
|
||||
build++;
|
||||
}
|
||||
didsub = TRUE;
|
||||
break;
|
||||
|
||||
case '*':
|
||||
case '?':
|
||||
#if !(MSDOS || TOS)
|
||||
case '[':
|
||||
case '`':
|
||||
case '{': /* } */
|
||||
case '$':
|
||||
case '~':
|
||||
#endif
|
||||
*build++ = *scan;
|
||||
iswild = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
*build++ = *scan;
|
||||
}
|
||||
}
|
||||
*build = '\0';
|
||||
|
||||
if (cmd == CMD_BANG
|
||||
|| cmd == CMD_READ && tmpblk.c[0] == '!'
|
||||
|| cmd == CMD_WRITE && tmpblk.c[0] == '!')
|
||||
{
|
||||
if (didsub)
|
||||
{
|
||||
if (mode != MODE_EX)
|
||||
{
|
||||
addch('\n');
|
||||
}
|
||||
addstr(tmpblk.c);
|
||||
addch('\n');
|
||||
exrefresh();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (iswild && tmpblk.c[0] != '>')
|
||||
{
|
||||
scan = wildcard(tmpblk.c);
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* no names given, maybe assume origname */
|
||||
{
|
||||
if (!(argt & NODFL))
|
||||
{
|
||||
strcpy(tmpblk.c, origname);
|
||||
}
|
||||
else
|
||||
{
|
||||
*tmpblk.c = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
scan = tmpblk.c;
|
||||
}
|
||||
|
||||
/* bad arguments? */
|
||||
if (!(argt & EXRCOK) && nlines < 1L)
|
||||
{
|
||||
msg("Can't use the \"%s\" command in a %s file", cmdnames[cmdidx].name, EXRC);
|
||||
return;
|
||||
}
|
||||
if (!(argt & (ZERO | EXRCOK)) && frommark == MARK_UNSET)
|
||||
{
|
||||
msg("Can't use address 0 with \"%s\" command.", cmdnames[cmdidx].name);
|
||||
return;
|
||||
}
|
||||
if (!(argt & FROM) && frommark != cursor && nlines >= 1L)
|
||||
{
|
||||
msg("Can't use address with \"%s\" command.", cmdnames[cmdidx].name);
|
||||
return;
|
||||
}
|
||||
if (!(argt & TO) && tomark != frommark && nlines >= 1L)
|
||||
{
|
||||
msg("Can't use a range with \"%s\" command.", cmdnames[cmdidx].name);
|
||||
return;
|
||||
}
|
||||
if (!(argt & EXTRA) && *scan)
|
||||
{
|
||||
msg("Extra characters after \"%s\" command.", cmdnames[cmdidx].name);
|
||||
return;
|
||||
}
|
||||
if ((argt & NOSPC) && !(cmd == CMD_READ && (forceit || *scan == '!')))
|
||||
{
|
||||
build = scan;
|
||||
#ifndef CRUNCH
|
||||
if ((argt & PLUS) && *build == '+')
|
||||
{
|
||||
while (*build && !isspace(*build))
|
||||
{
|
||||
build++;
|
||||
}
|
||||
while (*build && isspace(*build))
|
||||
{
|
||||
build++;
|
||||
}
|
||||
}
|
||||
#endif /* not CRUNCH */
|
||||
for (; *build; build++)
|
||||
{
|
||||
if (isspace(*build))
|
||||
{
|
||||
msg("Too many %s to \"%s\" command.",
|
||||
(argt & XFILE) ? "filenames" : "arguments",
|
||||
cmdnames[cmdidx].name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* some commands have special default ranges */
|
||||
if (isdfl && (argt & DFLALL))
|
||||
{
|
||||
frommark = MARK_FIRST;
|
||||
tomark = MARK_LAST;
|
||||
}
|
||||
else if (isdfl && (argt & DFLNONE))
|
||||
{
|
||||
frommark = tomark = 0L;
|
||||
}
|
||||
|
||||
/* write a newline if called from visual mode */
|
||||
if ((argt & NL) && mode != MODE_EX && !exwrote)
|
||||
{
|
||||
addch('\n');
|
||||
exrefresh();
|
||||
}
|
||||
|
||||
/* act on the command */
|
||||
(*cmdnames[cmdidx].fn)(frommark, tomark, cmd, forceit, scan);
|
||||
}
|
||||
|
||||
|
||||
/* This function executes EX commands from a file. It returns 1 normally, or
|
||||
* 0 if the file could not be opened for reading.
|
||||
*/
|
||||
int doexrc(filename)
|
||||
char *filename; /* name of a ".exrc" file */
|
||||
{
|
||||
int fd; /* file descriptor */
|
||||
int len; /* length of the ".exrc" file */
|
||||
|
||||
/* !!! kludge: we use U_text as the buffer. This has the side-effect
|
||||
* of interfering with the shift-U visual command. Disable shift-U.
|
||||
*/
|
||||
U_line = 0L;
|
||||
|
||||
/* open the file, read it, and close */
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
len = tread(fd, U_text, BLKSIZE);
|
||||
close(fd);
|
||||
|
||||
/* execute the string */
|
||||
exstring(U_text, len, ctrl('V'));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This function executes EX commands from a string. The commands may be
|
||||
* separated by newlines or by | characters. It also handles quoting.
|
||||
* Each individual command is limited to 132 bytes, but the total string
|
||||
* may be longer.
|
||||
*/
|
||||
void exstring(buf, len, qchar)
|
||||
char *buf; /* the commands to execute */
|
||||
int len; /* the length of the string */
|
||||
int qchar; /* the quote character -- ^V for file, or \ for kbd */
|
||||
{
|
||||
char single[133]; /* a single command */
|
||||
char *src, *dest;
|
||||
int i;
|
||||
|
||||
/* find & do each command */
|
||||
for (src = buf; src < &buf[len]; src++)
|
||||
{
|
||||
/* Copy a single command into single[]. Convert any quoted |
|
||||
* into a normal |, and stop at a newline or unquoted |.
|
||||
*/
|
||||
for (dest = single, i = 0;
|
||||
i < 132 && src < &buf[len] && *src != '\n' && *src != '|';
|
||||
src++, i++)
|
||||
{
|
||||
if (src[0] == qchar && src[1] == '|')
|
||||
{
|
||||
src++;
|
||||
}
|
||||
*dest++ = *src;
|
||||
}
|
||||
*dest = '\0';
|
||||
|
||||
/* do it */
|
||||
doexcmd(single);
|
||||
}
|
||||
}
|
|
@ -1,266 +0,0 @@
|
|||
/* fmt.c */
|
||||
|
||||
/* usage: fmt [-width] [files]...
|
||||
*
|
||||
* Fmt rearrages text in order to make each line have roughly the
|
||||
* same width. Indentation and word spacing is preserved.
|
||||
*
|
||||
* The default width is 72 characters, but you can override that via -width.
|
||||
* If no files are given on the command line, then it reads stdin.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef TRUE
|
||||
# define TRUE 1
|
||||
# define FALSE 0
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
int width = 72; /* the desired line width */
|
||||
int isblank; /* is the current output line blank? */
|
||||
int indent; /* width of the indentation */
|
||||
char ind[512]; /* indentation text */
|
||||
char word[1024]; /* word buffer */
|
||||
|
||||
/* This function displays a usage message and quits */
|
||||
void usage()
|
||||
{
|
||||
fprintf(stderr, "usage: fmt [-width] [files]...\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* This function outputs a single word. It takes care of spacing and the
|
||||
* newlines within a paragraph.
|
||||
*/
|
||||
void putword()
|
||||
{
|
||||
int i; /* index into word[], or whatever */
|
||||
int ww; /* width of the word */
|
||||
int sw; /* width of spacing after word */
|
||||
static int psw; /* space width of previous word */
|
||||
static int tab; /* the width of text already written */
|
||||
|
||||
|
||||
/* separate the word and its spacing */
|
||||
for (ww = 0; word[ww] && word[ww] != ' '; ww++)
|
||||
{
|
||||
}
|
||||
sw = strlen(word) - ww;
|
||||
word[ww] = '\0';
|
||||
|
||||
/* if no spacing (that is, the word was at the end of the line) then
|
||||
* assume 1 space unless the last char of the word was punctuation
|
||||
*/
|
||||
if (sw == 0)
|
||||
{
|
||||
sw = 1;
|
||||
if (word[ww - 1] == '.' || word[ww - 1] == '?' || word[ww - 1] == '!')
|
||||
sw = 2;
|
||||
}
|
||||
|
||||
/* if this is the first word on the line... */
|
||||
if (isblank)
|
||||
{
|
||||
/* output the indentation first */
|
||||
fputs(ind, stdout);
|
||||
tab = indent;
|
||||
}
|
||||
else /* text has already been written to this output line */
|
||||
{
|
||||
/* will the word fit on this line? */
|
||||
if (psw + ww + tab <= width)
|
||||
{
|
||||
/* yes - so write the previous word's spacing */
|
||||
for (i = 0; i < psw; i++)
|
||||
{
|
||||
putchar(' ');
|
||||
}
|
||||
tab += psw;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no, so write a newline and the indentation */
|
||||
putchar('\n');
|
||||
fputs(ind, stdout);
|
||||
tab = indent;
|
||||
}
|
||||
}
|
||||
|
||||
/* write the word itself */
|
||||
fputs(word, stdout);
|
||||
tab += ww;
|
||||
|
||||
/* remember this word's spacing */
|
||||
psw = sw;
|
||||
|
||||
/* this output line isn't blank anymore. */
|
||||
isblank = FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* This function reformats text. */
|
||||
void fmt(in)
|
||||
FILE *in; /* the name of the input stream */
|
||||
{
|
||||
int ch; /* character from input stream */
|
||||
int prevch; /* the previous character in the loop */
|
||||
int i; /* index into ind[] or word[] */
|
||||
int inword; /* boolean: are we between indent & newline? */
|
||||
|
||||
|
||||
/* for each character in the stream... */
|
||||
for (indent = -1, isblank = TRUE, inword = FALSE, i = 0, prevch = '\n';
|
||||
(ch = getc(in)) != EOF;
|
||||
prevch = ch)
|
||||
{
|
||||
/* is this the end of a line? */
|
||||
if (ch == '\n')
|
||||
{
|
||||
/* if end of last word in the input line */
|
||||
if (inword)
|
||||
{
|
||||
/* if it really is a word */
|
||||
if (i > 0)
|
||||
{
|
||||
/* output it */
|
||||
word[i] = '\0';
|
||||
putword();
|
||||
}
|
||||
}
|
||||
else /* blank line in input */
|
||||
{
|
||||
/* finish the previous paragraph */
|
||||
if (!isblank)
|
||||
{
|
||||
putchar('\n');
|
||||
isblank = TRUE;
|
||||
}
|
||||
|
||||
/* output a blank line */
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
/* continue with next input line... */
|
||||
indent = -1;
|
||||
i = 0;
|
||||
inword = FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* if we're expecting indentation now... */
|
||||
if (indent < 0)
|
||||
{
|
||||
/* if this is part of the indentation... */
|
||||
if (ch == ' ' || ch == '\t')
|
||||
{
|
||||
/* remember it */
|
||||
ind[i++] = ch;
|
||||
}
|
||||
else /* end of indentation */
|
||||
{
|
||||
/* mark the end of the indentation string */
|
||||
ind[i] = '\0';
|
||||
|
||||
/* calculate the width of the indentation */
|
||||
for (i = indent = 0; ind[i]; i++)
|
||||
{
|
||||
if (ind[i] == '\t')
|
||||
indent = (indent | 7) + 1;
|
||||
else
|
||||
indent++;
|
||||
}
|
||||
|
||||
/* reset the word index */
|
||||
i = 0;
|
||||
|
||||
/* reprocess that last character */
|
||||
ungetc(ch, in);
|
||||
}
|
||||
|
||||
/* continue in the for-loop */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* if we get here, we're either in a word or in the space
|
||||
* after a word.
|
||||
*/
|
||||
inword = TRUE;
|
||||
|
||||
/* is this the start of a new word? */
|
||||
if (ch != ' ' && prevch == ' ')
|
||||
{
|
||||
/* yes! output the previous word */
|
||||
word[i] = '\0';
|
||||
putword();
|
||||
|
||||
/* reset `i' to the start of the word[] buffer */
|
||||
i = 0;
|
||||
}
|
||||
word[i++] = ch;
|
||||
}
|
||||
|
||||
/* if necessary, write a final newline */
|
||||
if (!isblank)
|
||||
{
|
||||
putchar('\n');
|
||||
isblank = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
FILE *in; /* an input stream */
|
||||
int error; /* if non-zero, then an error occurred */
|
||||
int i;
|
||||
|
||||
|
||||
/* handle the -width flag, if given */
|
||||
if (argc > 1 && argv[1][0] == '-')
|
||||
{
|
||||
width = atoi(argv[1] + 1);
|
||||
if (width <= 0)
|
||||
{
|
||||
usage();
|
||||
}
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
/* if no filenames given, then process stdin */
|
||||
if (argc == 1)
|
||||
{
|
||||
fmt(stdin);
|
||||
}
|
||||
else /* one or more filenames given */
|
||||
{
|
||||
for (error = 0, i = 1; i < argc; i++)
|
||||
{
|
||||
in = fopen(argv[i], "r");
|
||||
if (!in)
|
||||
{
|
||||
perror(argv[i]);
|
||||
error = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt(in);
|
||||
fclose(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* exit, possibly indicating an error */
|
||||
exit(error);
|
||||
/*NOTREACHED*/
|
||||
}
|
|
@ -1,852 +0,0 @@
|
|||
/* input.c */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* 14407 SW Teal Blvd. #C
|
||||
* Beaverton, OR 97005
|
||||
* kirkenda@cs.pdx.edu
|
||||
*/
|
||||
|
||||
|
||||
/* This file contains the input() function, which implements vi's INPUT mode.
|
||||
* It also contains the code that supports digraphs.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "ctype.h"
|
||||
#include "vi.h"
|
||||
|
||||
|
||||
#ifndef NO_DIGRAPH
|
||||
static struct _DIG
|
||||
{
|
||||
struct _DIG *next;
|
||||
char key1;
|
||||
char key2;
|
||||
char dig;
|
||||
char save;
|
||||
} *digs;
|
||||
|
||||
char digraph(key1, key2)
|
||||
char key1; /* the underlying character */
|
||||
char key2; /* the second character */
|
||||
{
|
||||
int newkey;
|
||||
REG struct _DIG *dp;
|
||||
|
||||
/* if digraphs are disabled, then just return the new char */
|
||||
if (!*o_digraph)
|
||||
{
|
||||
return key2;
|
||||
}
|
||||
|
||||
/* remember the new key, so we can return it if this isn't a digraph */
|
||||
newkey = key2;
|
||||
|
||||
/* sort key1 and key2, so that their original order won't matter */
|
||||
if (key1 > key2)
|
||||
{
|
||||
key2 = key1;
|
||||
key1 = newkey;
|
||||
}
|
||||
|
||||
/* scan through the digraph chart */
|
||||
for (dp = digs;
|
||||
dp && (dp->key1 != key1 || dp->key2 != key2);
|
||||
dp = dp->next)
|
||||
{
|
||||
}
|
||||
|
||||
/* if this combination isn't in there, just use the new key */
|
||||
if (!dp)
|
||||
{
|
||||
return newkey;
|
||||
}
|
||||
|
||||
/* else use the digraph key */
|
||||
return dp->dig;
|
||||
}
|
||||
|
||||
/* this function lists or defines digraphs */
|
||||
void do_digraph(bang, extra)
|
||||
int bang;
|
||||
char extra[];
|
||||
{
|
||||
int dig;
|
||||
REG struct _DIG *dp;
|
||||
struct _DIG *prev;
|
||||
static int user_defined = FALSE; /* boolean: are all later digraphs user-defined? */
|
||||
char listbuf[8];
|
||||
|
||||
/* if "extra" is NULL, then we've reached the end of the built-ins */
|
||||
if (!extra)
|
||||
{
|
||||
user_defined = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* if no args, then display the existing digraphs */
|
||||
if (*extra < ' ')
|
||||
{
|
||||
listbuf[0] = listbuf[1] = listbuf[2] = listbuf[5] = ' ';
|
||||
listbuf[7] = '\0';
|
||||
for (dig = 0, dp = digs; dp; dp = dp->next)
|
||||
{
|
||||
if (dp->save || bang)
|
||||
{
|
||||
dig += 7;
|
||||
if (dig >= COLS)
|
||||
{
|
||||
addch('\n');
|
||||
exrefresh();
|
||||
dig = 7;
|
||||
}
|
||||
listbuf[3] = dp->key1;
|
||||
listbuf[4] = dp->key2;
|
||||
listbuf[6] = dp->dig;
|
||||
qaddstr(listbuf);
|
||||
}
|
||||
}
|
||||
addch('\n');
|
||||
exrefresh();
|
||||
return;
|
||||
}
|
||||
|
||||
/* make sure we have at least two characters */
|
||||
if (!extra[1])
|
||||
{
|
||||
msg("Digraphs must be composed of two characters");
|
||||
return;
|
||||
}
|
||||
|
||||
/* sort key1 and key2, so that their original order won't matter */
|
||||
if (extra[0] > extra[1])
|
||||
{
|
||||
dig = extra[0];
|
||||
extra[0] = extra[1];
|
||||
extra[1] = dig;
|
||||
}
|
||||
|
||||
/* locate the new digraph character */
|
||||
for (dig = 2; extra[dig] == ' ' || extra[dig] == '\t'; dig++)
|
||||
{
|
||||
}
|
||||
dig = extra[dig];
|
||||
if (!bang && dig)
|
||||
{
|
||||
dig |= 0x80;
|
||||
}
|
||||
|
||||
/* search for the digraph */
|
||||
for (prev = (struct _DIG *)0, dp = digs;
|
||||
dp && (dp->key1 != extra[0] || dp->key2 != extra[1]);
|
||||
prev = dp, dp = dp->next)
|
||||
{
|
||||
}
|
||||
|
||||
/* deleting the digraph? */
|
||||
if (!dig)
|
||||
{
|
||||
if (!dp)
|
||||
{
|
||||
#ifndef CRUNCH
|
||||
msg("%c%c not a digraph", extra[0], extra[1]);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
if (prev)
|
||||
prev->next = dp->next;
|
||||
else
|
||||
digs = dp->next;
|
||||
free(dp);
|
||||
return;
|
||||
}
|
||||
|
||||
/* if necessary, create a new digraph struct for the new digraph */
|
||||
if (dig && !dp)
|
||||
{
|
||||
dp = (struct _DIG *)malloc(sizeof *dp);
|
||||
if (!dp)
|
||||
{
|
||||
msg("Out of space in the digraph table");
|
||||
return;
|
||||
}
|
||||
if (prev)
|
||||
prev->next = dp;
|
||||
else
|
||||
digs = dp;
|
||||
dp->next = (struct _DIG *)0;
|
||||
}
|
||||
|
||||
/* assign it the new digraph value */
|
||||
dp->key1 = extra[0];
|
||||
dp->key2 = extra[1];
|
||||
dp->dig = dig;
|
||||
dp->save = user_defined;
|
||||
}
|
||||
|
||||
# ifndef NO_MKEXRC
|
||||
void savedigs(fd)
|
||||
int fd;
|
||||
{
|
||||
static char buf[] = "digraph! XX Y\n";
|
||||
REG struct _DIG *dp;
|
||||
|
||||
for (dp = digs; dp; dp = dp->next)
|
||||
{
|
||||
if (dp->save)
|
||||
{
|
||||
buf[9] = dp->key1;
|
||||
buf[10] = dp->key2;
|
||||
buf[12] = dp->dig;
|
||||
write(fd, buf, (unsigned)14);
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* This function allows the user to replace an existing (possibly zero-length)
|
||||
* chunk of text with typed-in text. It returns the MARK of the last character
|
||||
* that the user typed in.
|
||||
*/
|
||||
MARK input(from, to, when, above)
|
||||
MARK from; /* where to start inserting text */
|
||||
MARK to; /* extent of text to delete */
|
||||
int when; /* either WHEN_VIINP or WHEN_VIREP */
|
||||
int above; /* boolean: take indentation from lower line? */
|
||||
{
|
||||
char key[2]; /* key char followed by '\0' char */
|
||||
char *build; /* used in building a newline+indent string */
|
||||
char *scan; /* used while looking at the indent chars of a line */
|
||||
MARK m; /* some place in the text */
|
||||
#ifndef NO_EXTENSIONS
|
||||
int quit = FALSE; /* boolean: are we exiting after this? */
|
||||
int inchg; /* boolean: have we done a "beforedo()" yet? */
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
/* if "from" and "to" are reversed, complain */
|
||||
if (from > to)
|
||||
{
|
||||
msg("ERROR: input(%ld:%d, %ld:%d)",
|
||||
markline(from), markidx(from),
|
||||
markline(to), markidx(to));
|
||||
return MARK_UNSET;
|
||||
}
|
||||
#endif
|
||||
|
||||
key[1] = 0;
|
||||
|
||||
/* if we're replacing text with new text, save the old stuff */
|
||||
/* (Alas, there is no easy way to save text for replace mode) */
|
||||
if (from != to)
|
||||
{
|
||||
cut(from, to);
|
||||
}
|
||||
|
||||
/* if doing a dot command, then reuse the previous text */
|
||||
if (doingdot)
|
||||
{
|
||||
ChangeText
|
||||
{
|
||||
/* delete the text that's there now */
|
||||
if (from != to)
|
||||
{
|
||||
delete(from, to);
|
||||
}
|
||||
|
||||
/* insert the previous text */
|
||||
cutname('.');
|
||||
cursor = paste(from, FALSE, TRUE) + 1L;
|
||||
}
|
||||
}
|
||||
else /* interactive version */
|
||||
{
|
||||
/* assume that whoever called this already did a beforedo() */
|
||||
#ifndef NO_EXTENSIONS
|
||||
inchg = TRUE;
|
||||
#endif
|
||||
|
||||
/* if doing a change within the line... */
|
||||
if (from != to && markline(from) == markline(to))
|
||||
{
|
||||
/* mark the end of the text with a "$" */
|
||||
change(to - 1, to, "$");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* delete the old text right off */
|
||||
if (from != to)
|
||||
{
|
||||
delete(from, to);
|
||||
}
|
||||
to = from;
|
||||
}
|
||||
|
||||
/* handle autoindent of the first line, maybe */
|
||||
cursor = from;
|
||||
m = (above ? (cursor + BLKSIZE) : (cursor - BLKSIZE));
|
||||
if (*o_autoindent && markidx(m) == 0
|
||||
&& markline(m) >= 1L && markline(m) <= nlines)
|
||||
{
|
||||
/* Only autoindent blank lines. */
|
||||
pfetch(markline(cursor));
|
||||
if (plen == 0)
|
||||
{
|
||||
/* Okay, we really want to autoindent */
|
||||
pfetch(markline(m));
|
||||
for (scan = ptext, build = tmpblk.c;
|
||||
*scan == ' ' || *scan == '\t';
|
||||
)
|
||||
{
|
||||
*build++ = *scan++;
|
||||
}
|
||||
if (build > tmpblk.c)
|
||||
{
|
||||
*build = '\0';
|
||||
add(cursor, tmpblk.c);
|
||||
cursor += (build - tmpblk.c);
|
||||
if (cursor > to)
|
||||
to = cursor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* repeatedly add characters from the user */
|
||||
for (;;)
|
||||
{
|
||||
/* Get a character */
|
||||
redraw(cursor, TRUE);
|
||||
#ifdef DEBUG2
|
||||
msg("cursor=%ld.%d, to=%ld.%d",
|
||||
markline(cursor), markidx(cursor),
|
||||
markline(to), markidx(to));
|
||||
#endif
|
||||
#ifndef NO_ABBR
|
||||
pfetch(markline(cursor));
|
||||
build = ptext;
|
||||
if (pline == markline(from))
|
||||
build += markidx(from);
|
||||
for (scan = ptext + markidx(cursor); --scan >= build && isalnum(*scan); )
|
||||
{
|
||||
}
|
||||
scan++;
|
||||
key[0] = getabkey(when, scan, (int)(ptext + markidx(cursor) - scan));
|
||||
#else
|
||||
key[0] = getkey(when);
|
||||
#endif
|
||||
#ifndef NO_VISIBLE
|
||||
if (key[0] != '\0' && V_from != MARK_UNSET)
|
||||
{
|
||||
msg("Can't modify text during a selection");
|
||||
beep();
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NO_EXTENSIONS
|
||||
if (key[0] == ctrl('O'))
|
||||
{
|
||||
if (inchg)
|
||||
{
|
||||
if (cursor < to)
|
||||
{
|
||||
delete(cursor, to);
|
||||
redraw(cursor, TRUE);
|
||||
}
|
||||
afterdo();
|
||||
inchg = FALSE;
|
||||
}
|
||||
}
|
||||
else if (key[0] != ctrl('['))
|
||||
{
|
||||
if (!inchg)
|
||||
{
|
||||
beforedo(FALSE);
|
||||
inchg = TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CRUNCH
|
||||
/* if wrapmargin is set & we're past the
|
||||
* warpmargin, then change the last whitespace
|
||||
* characters on line into a newline
|
||||
*/
|
||||
if (*o_wrapmargin != 0)
|
||||
{
|
||||
pfetch(markline(cursor));
|
||||
if (idx2col(cursor, ptext, TRUE) > COLS - (*o_wrapmargin & 0xff))
|
||||
{
|
||||
build = tmpblk.c;
|
||||
*build++ = '\n';
|
||||
if (*o_autoindent)
|
||||
{
|
||||
/* figure out indent for next line */
|
||||
for (scan = ptext; *scan == ' ' || *scan == '\t'; )
|
||||
{
|
||||
*build++ = *scan++;
|
||||
}
|
||||
}
|
||||
*build = '\0';
|
||||
|
||||
scan = ptext + plen;
|
||||
m = cursor & ~(BLKSIZE - 1);
|
||||
while (ptext < scan)
|
||||
{
|
||||
scan--;
|
||||
if (*scan != ' ' && *scan != '\t')
|
||||
continue;
|
||||
|
||||
/*break up line, and we do autoindent if needed*/
|
||||
change(m + (scan - ptext), m + (scan - ptext) + 1, tmpblk.c);
|
||||
cursor = (cursor & ~(BLKSIZE - 1))
|
||||
+ BLKSIZE
|
||||
+ strlen(tmpblk.c) - 1
|
||||
+ plen - (scan - ptext) - 1;
|
||||
|
||||
/*remove trailing spaces on previous line*/
|
||||
pfetch(markline(m));
|
||||
scan = ptext + plen;
|
||||
while (ptext < scan)
|
||||
{
|
||||
scan--;
|
||||
if (*scan != ' ' && *scan != '\t')
|
||||
break;
|
||||
}
|
||||
delete(m + (scan-ptext) + 1, m + plen);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* !CRUNCH */
|
||||
|
||||
/* process it */
|
||||
switch (*key)
|
||||
{
|
||||
#ifndef NO_EXTENSIONS
|
||||
case ctrl('O'): /* special movement mapped keys */
|
||||
*key = getkey(0);
|
||||
switch (*key)
|
||||
{
|
||||
case 'h': m = m_left(cursor, 0L); break;
|
||||
case 'j':
|
||||
case 'k': m = m_updnto(cursor, 0L, *key); break;
|
||||
case 'l': m = cursor + 1; break;
|
||||
case 'B':
|
||||
case 'b': m = m_bword(cursor, 0L, *key); break;
|
||||
case 'W':
|
||||
case 'w': m = m_fword(cursor, 0L, *key, '\0'); break;
|
||||
case '^': m = m_front(cursor, 0L); break;
|
||||
case '$': m = m_rear(cursor, 0L); break;
|
||||
case ctrl('B'):
|
||||
case ctrl('F'):
|
||||
m = m_scroll(cursor, 0L, *key); break;
|
||||
case 'x':
|
||||
#ifndef NO_VISIBLE
|
||||
if (V_from)
|
||||
beep();
|
||||
else
|
||||
#endif
|
||||
ChangeText
|
||||
{
|
||||
m = v_xchar(cursor, 0L, 'x');
|
||||
}
|
||||
break;
|
||||
case 'i': m = to = from = cursor;
|
||||
when = WHEN_VIINP + WHEN_VIREP - when;
|
||||
break;
|
||||
case 'K':
|
||||
pfetch(markline(cursor));
|
||||
changes++; /* <- after this, we can alter ptext */
|
||||
ptext[markidx(cursor)] = 0;
|
||||
for (scan = ptext + markidx(cursor) - 1;
|
||||
scan >= ptext && isalnum(*scan);
|
||||
scan--)
|
||||
{
|
||||
}
|
||||
scan++;
|
||||
m = (*scan ? v_keyword(scan, cursor, 0L) : cursor);
|
||||
break;
|
||||
|
||||
# ifndef NO_VISIBLE
|
||||
case 'v':
|
||||
case 'V':
|
||||
if (V_from)
|
||||
V_from = MARK_UNSET;
|
||||
else
|
||||
V_from = cursor;
|
||||
m = from = to = cursor;
|
||||
V_linemd = (*key == 'V');
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'y':
|
||||
case '\\':
|
||||
/* do nothing if unmarked */
|
||||
if (!V_from)
|
||||
{
|
||||
msg("You must mark the text first");
|
||||
beep();
|
||||
break;
|
||||
}
|
||||
|
||||
/* "from" must come before "to" */
|
||||
if (V_from < cursor)
|
||||
{
|
||||
from = V_from;
|
||||
to = cursor;
|
||||
}
|
||||
else
|
||||
{
|
||||
from = cursor;
|
||||
to = V_from;
|
||||
}
|
||||
|
||||
/* we don't need V_from anymore */
|
||||
V_from = MARK_UNSET;
|
||||
|
||||
if (V_linemd)
|
||||
{
|
||||
/* adjust for line mode */
|
||||
from &= ~(BLKSIZE - 1);
|
||||
to |= (BLKSIZE - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* in character mode, we must
|
||||
* worry about deleting the newline
|
||||
* at the end of the last line
|
||||
*/
|
||||
pfetch(markline(to));
|
||||
if (markidx(to) == plen)
|
||||
to |= (BLKSIZE - 1);
|
||||
}
|
||||
to++;
|
||||
|
||||
switch (*key)
|
||||
{
|
||||
case 'y':
|
||||
cut(from, to);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
ChangeText
|
||||
{
|
||||
cut(from, to);
|
||||
delete(from, to);
|
||||
}
|
||||
cursor = from;
|
||||
break;
|
||||
|
||||
#ifndef NO_POPUP
|
||||
case '\\':
|
||||
ChangeText
|
||||
{
|
||||
cursor = v_popup(from, to);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
m = from = to = cursor;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
case 'P':
|
||||
V_from = MARK_UNSET;
|
||||
ChangeText
|
||||
{
|
||||
m = from = to = cursor = paste(cursor, (*key == 'p'), FALSE);
|
||||
}
|
||||
break;
|
||||
# endif /* !NO_VISIBLE */
|
||||
default: m = MARK_UNSET;
|
||||
}
|
||||
|
||||
/* adjust the moved cursor */
|
||||
if (m != cursor)
|
||||
{
|
||||
m = adjmove(cursor, m, (*key == 'j' || *key == 'k' ? 0x20 : 0));
|
||||
if (*key == '$' || (*key == 'l' && m <= cursor))
|
||||
{
|
||||
m++;
|
||||
}
|
||||
}
|
||||
|
||||
/* if the cursor is reasonable, use it */
|
||||
if (m == MARK_UNSET)
|
||||
{
|
||||
beep();
|
||||
}
|
||||
else
|
||||
{
|
||||
from = to = cursor = m;
|
||||
}
|
||||
break;
|
||||
|
||||
case ctrl('Z'):
|
||||
if (getkey(0) == ctrl('Z'))
|
||||
{
|
||||
quit = TRUE;
|
||||
goto BreakBreak;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case ctrl('['):
|
||||
/* if last line contains only whitespace, then remove whitespace */
|
||||
if (*o_autoindent)
|
||||
{
|
||||
pfetch(markline(cursor));
|
||||
for (scan = ptext; isspace(*scan); scan++)
|
||||
{
|
||||
}
|
||||
if (scan > ptext && !*scan)
|
||||
{
|
||||
cursor &= ~(BLKSIZE - 1L);
|
||||
if (to < cursor + plen)
|
||||
{
|
||||
to = cursor + plen;
|
||||
}
|
||||
}
|
||||
}
|
||||
goto BreakBreak;
|
||||
|
||||
case ctrl('U'):
|
||||
if (markline(cursor) == markline(from))
|
||||
{
|
||||
cursor = from;
|
||||
}
|
||||
else
|
||||
{
|
||||
cursor &= ~(BLKSIZE - 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case ctrl('D'):
|
||||
case ctrl('T'):
|
||||
if (to > cursor)
|
||||
{
|
||||
delete(cursor, to);
|
||||
}
|
||||
mark[27] = cursor;
|
||||
cmd_shift(cursor, cursor, *key == ctrl('D') ? CMD_SHIFTL : CMD_SHIFTR, TRUE, "");
|
||||
if (mark[27])
|
||||
{
|
||||
cursor = mark[27];
|
||||
}
|
||||
else
|
||||
{
|
||||
cursor = m_front(cursor, 0L);
|
||||
}
|
||||
to = cursor;
|
||||
break;
|
||||
|
||||
case '\b':
|
||||
if (cursor <= from)
|
||||
{
|
||||
beep();
|
||||
}
|
||||
else if (markidx(cursor) == 0)
|
||||
{
|
||||
cursor -= BLKSIZE;
|
||||
pfetch(markline(cursor));
|
||||
cursor += plen;
|
||||
}
|
||||
else
|
||||
{
|
||||
cursor--;
|
||||
}
|
||||
break;
|
||||
|
||||
case ctrl('W'):
|
||||
m = m_bword(cursor, 1L, 'b');
|
||||
if (markline(m) == markline(cursor) && m >= from)
|
||||
{
|
||||
cursor = m;
|
||||
if (from > cursor)
|
||||
{
|
||||
from = cursor;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
beep();
|
||||
}
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
#if OSK
|
||||
case '\l':
|
||||
#else
|
||||
case '\r':
|
||||
#endif
|
||||
build = tmpblk.c;
|
||||
*build++ = '\n';
|
||||
if (*o_autoindent)
|
||||
{
|
||||
/* figure out indent for next line */
|
||||
pfetch(markline(cursor));
|
||||
for (scan = ptext; *scan == ' ' || *scan == '\t'; )
|
||||
{
|
||||
*build++ = *scan++;
|
||||
}
|
||||
|
||||
/* remove indent from this line, if blank */
|
||||
if ((scan - ptext) >= markidx(cursor) && plen > 0)
|
||||
{
|
||||
to = cursor &= ~(BLKSIZE - 1);
|
||||
delete(cursor, cursor + plen);
|
||||
}
|
||||
}
|
||||
*build = 0;
|
||||
if (cursor >= to && when != WHEN_VIREP)
|
||||
{
|
||||
add(cursor, tmpblk.c);
|
||||
}
|
||||
else
|
||||
{
|
||||
change(cursor, to, tmpblk.c);
|
||||
}
|
||||
redraw(cursor, TRUE);
|
||||
to = cursor = (cursor & ~(BLKSIZE - 1))
|
||||
+ BLKSIZE
|
||||
+ (int)(build - tmpblk.c) - 1;
|
||||
break;
|
||||
|
||||
case ctrl('A'):
|
||||
case ctrl('P'):
|
||||
if (cursor < to)
|
||||
{
|
||||
delete(cursor, to);
|
||||
}
|
||||
if (*key == ctrl('A'))
|
||||
{
|
||||
cutname('.');
|
||||
}
|
||||
to = cursor = paste(cursor, FALSE, TRUE) + 1L;
|
||||
break;
|
||||
|
||||
case ctrl('V'):
|
||||
if (cursor >= to && when != WHEN_VIREP)
|
||||
{
|
||||
add(cursor, "^");
|
||||
}
|
||||
else
|
||||
{
|
||||
change(cursor, to, "^");
|
||||
to = cursor + 1;
|
||||
}
|
||||
redraw(cursor, TRUE);
|
||||
*key = getkey(0);
|
||||
if (*key == '\n')
|
||||
{
|
||||
/* '\n' too hard to handle */
|
||||
#if OSK
|
||||
*key = '\l';
|
||||
#else
|
||||
*key = '\r';
|
||||
#endif
|
||||
}
|
||||
change(cursor, cursor + 1, key);
|
||||
cursor++;
|
||||
if (cursor > to)
|
||||
{
|
||||
to = cursor;
|
||||
}
|
||||
break;
|
||||
|
||||
case ctrl('L'):
|
||||
case ctrl('R'):
|
||||
redraw(MARK_UNSET, FALSE);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (cursor >= to && when != WHEN_VIREP)
|
||||
{
|
||||
add(cursor, key);
|
||||
cursor++;
|
||||
to = cursor;
|
||||
}
|
||||
else
|
||||
{
|
||||
pfetch(markline(cursor));
|
||||
if (markidx(cursor) == plen)
|
||||
{
|
||||
add(cursor, key);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef NO_DIGRAPH
|
||||
*key = digraph(ptext[markidx(cursor)], *key);
|
||||
#endif
|
||||
change(cursor, cursor + 1, key);
|
||||
}
|
||||
cursor++;
|
||||
}
|
||||
#ifndef NO_SHOWMATCH
|
||||
/* show matching "({[" if necessary */
|
||||
if (*o_showmatch && strchr(")}]", *key))
|
||||
{
|
||||
redraw(cursor, TRUE);
|
||||
m = m_match(cursor - 1, 0L);
|
||||
if (markline(m) >= topline
|
||||
&& markline(m) <= botline)
|
||||
{
|
||||
redraw(m, TRUE);
|
||||
refresh();
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} /* end switch(*key) */
|
||||
} /* end for(;;) */
|
||||
BreakBreak:;
|
||||
/* delete any excess characters */
|
||||
if (cursor < to)
|
||||
{
|
||||
#ifndef NO_EXTENSIONS
|
||||
/* if we aren't in the middle of a change, start one! */
|
||||
if (!inchg)
|
||||
{
|
||||
beforedo(FALSE);
|
||||
inchg = TRUE;
|
||||
}
|
||||
#endif
|
||||
delete(cursor, to);
|
||||
}
|
||||
|
||||
} /* end if doingdot else */
|
||||
|
||||
/* put the new text into a cut buffer for possible reuse */
|
||||
if (!doingdot)
|
||||
{
|
||||
blksync();
|
||||
cutname('.');
|
||||
cut(from, cursor);
|
||||
}
|
||||
|
||||
/* move to last char that we inputted, unless it was newline */
|
||||
if (markidx(cursor) != 0)
|
||||
{
|
||||
cursor--;
|
||||
}
|
||||
redraw(cursor, FALSE);
|
||||
|
||||
#ifndef NO_EXTENSIONS
|
||||
if (quit)
|
||||
{
|
||||
/* if this is a nested "do", then cut it short */
|
||||
abortdo();
|
||||
|
||||
/* exit, unless we can't write out the file */
|
||||
cursor = v_xit(cursor, 0L, 'Z');
|
||||
}
|
||||
#endif
|
||||
|
||||
rptlines = 0L;
|
||||
return cursor;
|
||||
}
|
|
@ -1,512 +0,0 @@
|
|||
/* main.c */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* 14407 SW Teal Blvd. #C
|
||||
* Beaverton, OR 97005
|
||||
* kirkenda@cs.pdx.edu
|
||||
*/
|
||||
|
||||
|
||||
/* This file contains the main() function of vi */
|
||||
|
||||
/* HACK! bcc needs to disable use of precompiled headers for this file,
|
||||
or else command line args will not be passed to elvis */
|
||||
#if __BORLANDC__
|
||||
#include "borland.h"
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
#include <setjmp.h>
|
||||
#include "vi.h"
|
||||
|
||||
extern trapint(); /* defined below */
|
||||
extern char *getenv();
|
||||
jmp_buf jmpenv;
|
||||
|
||||
#ifndef NO_DIGRAPH
|
||||
static init_digraphs();
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
|
||||
#if AMIGA
|
||||
# include "amiwild.c"
|
||||
main (argc, argv)
|
||||
#else
|
||||
# if VMS
|
||||
# include "vmswild.c"
|
||||
main (argc, argv)
|
||||
# else
|
||||
int main(argc, argv)
|
||||
# endif
|
||||
#endif
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int i;
|
||||
char *cmd = (char *)0;
|
||||
char *err = (char *)0;
|
||||
char *str;
|
||||
char *tag = (char *)0;
|
||||
|
||||
/* set mode to MODE_VI or MODE_EX depending on program name */
|
||||
switch (argv[0][strlen(argv[0]) - 1])
|
||||
{
|
||||
case 'x': /* "ex" */
|
||||
mode = MODE_EX;
|
||||
break;
|
||||
|
||||
case 'w': /* "view" */
|
||||
mode = MODE_VI;
|
||||
*o_readonly = TRUE;
|
||||
break;
|
||||
#ifndef NO_EXTENSIONS
|
||||
case 't': /* "edit" or "input" */
|
||||
mode = MODE_VI;
|
||||
*o_inputmode = TRUE;
|
||||
break;
|
||||
#endif
|
||||
default: /* "vi" or "elvis" */
|
||||
mode = MODE_VI;
|
||||
}
|
||||
|
||||
#ifndef DEBUG
|
||||
# ifdef SIGQUIT
|
||||
/* normally, we ignore SIGQUIT. SIGINT is trapped later */
|
||||
signal(SIGQUIT, SIG_IGN);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* temporarily ignore SIGINT */
|
||||
signal(SIGINT, SIG_IGN);
|
||||
|
||||
/* start curses */
|
||||
initscr();
|
||||
cbreak();
|
||||
noecho();
|
||||
scrollok(stdscr, TRUE);
|
||||
|
||||
/* arrange for deadly signals to be caught */
|
||||
# ifdef SIGHUP
|
||||
signal(SIGHUP, (void(*)()) deathtrap);
|
||||
# endif
|
||||
# ifndef DEBUG
|
||||
# ifdef SIGILL
|
||||
signal(SIGILL, (void(*)()) deathtrap);
|
||||
# endif
|
||||
# ifdef SIGBUS
|
||||
signal(SIGBUS, (void(*)()) deathtrap);
|
||||
# endif
|
||||
# ifdef SIGSEGV
|
||||
signal(SIGSEGV, (void(*)()) deathtrap);
|
||||
# endif
|
||||
# ifdef SIGSYS
|
||||
signal(SIGSYS, (void(*)()) deathtrap);
|
||||
# endif
|
||||
# endif /* !DEBUG */
|
||||
# ifdef SIGPIPE
|
||||
signal(SIGPIPE, (void(*)()) deathtrap);
|
||||
# endif
|
||||
# ifdef SIGTERM
|
||||
signal(SIGTERM, (void(*)()) deathtrap);
|
||||
# endif
|
||||
# ifdef SIGUSR1
|
||||
signal(SIGUSR1, (void(*)()) deathtrap);
|
||||
# endif
|
||||
# ifdef SIGUSR2
|
||||
signal(SIGUSR2, (void(*)()) deathtrap);
|
||||
# endif
|
||||
|
||||
/* initialize the options - must be done after initscr(), so that
|
||||
* we can alter LINES and COLS if necessary.
|
||||
*/
|
||||
initopts();
|
||||
|
||||
/* map the arrow keys. The KU,KD,KL,and KR variables correspond to
|
||||
* the :ku=: (etc.) termcap capabilities. The variables are defined
|
||||
* as part of the curses package.
|
||||
*/
|
||||
if (has_KU) mapkey(has_KU, "k", WHEN_VICMD|WHEN_INMV, "<Up>");
|
||||
if (has_KD) mapkey(has_KD, "j", WHEN_VICMD|WHEN_INMV, "<Down>");
|
||||
if (has_KL) mapkey(has_KL, "h", WHEN_VICMD|WHEN_INMV, "<Left>");
|
||||
if (has_KR) mapkey(has_KR, "l", WHEN_VICMD|WHEN_INMV, "<Right>");
|
||||
if (has_HM) mapkey(has_HM, "^", WHEN_VICMD|WHEN_INMV, "<Home>");
|
||||
if (has_EN) mapkey(has_EN, "$", WHEN_VICMD|WHEN_INMV, "<End>");
|
||||
if (has_PU) mapkey(has_PU, "\002", WHEN_VICMD|WHEN_INMV, "<PageUp>");
|
||||
if (has_PD) mapkey(has_PD, "\006", WHEN_VICMD|WHEN_INMV, "<PageDn>");
|
||||
if (has_KI) mapkey(has_KI, "i", WHEN_VICMD|WHEN_INMV, "<Insert>");
|
||||
#if MSDOS
|
||||
# if RAINBOW
|
||||
if (!strcmp("rainbow", o_term))
|
||||
{
|
||||
mapkey("\033[1~", "/", WHEN_VICMD, "<Find>");
|
||||
mapkey("\033[3~", "x", WHEN_VICMD|WHEN_INMV, "<Remove>");
|
||||
mapkey("\033[4~", "v", WHEN_VICMD|WHEN_INMV, "<Select>");
|
||||
mapkey("\033[17~", ":sh\n", WHEN_VICMD, "<Intrpt>");
|
||||
mapkey("\033[19~", ":q\n", WHEN_VICMD, "<Cancel>");
|
||||
mapkey("\033[21~", "ZZ", WHEN_VICMD, "<Exit>");
|
||||
mapkey("\033[26~", "V", WHEN_VICMD|WHEN_INMV, "<AddlOp>");
|
||||
mapkey("\033[28~", "\\", WHEN_VICMD|WHEN_INMV, "<Help>");
|
||||
mapkey("\033[29~", "K", WHEN_VICMD|WHEN_INMV, "<Do>");
|
||||
}
|
||||
else
|
||||
# endif /* RAINBOW */
|
||||
{
|
||||
mapkey("#S", "x", WHEN_VICMD|WHEN_INMV, "<Delete>");
|
||||
mapkey("#s", "B", WHEN_VICMD|WHEN_INMV, "^<Left>");
|
||||
mapkey("#t", "W", WHEN_VICMD|WHEN_INMV, "^<Right>");
|
||||
}
|
||||
#else /* not MSDOS */
|
||||
# if COHERENT
|
||||
mapkey("\033[P", "x", WHEN_VICMD|WHEN_INMV, "<Del>");
|
||||
# else
|
||||
#if AMIGA
|
||||
mapkey("\233?~", "\\", WHEN_VICMD|WHEN_INMV, "<Help>");
|
||||
#endif
|
||||
|
||||
if (ERASEKEY != '\177')
|
||||
{
|
||||
mapkey("\177", "x", WHEN_VICMD|WHEN_INMV, "<Del>");
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef NO_DIGRAPH
|
||||
init_digraphs();
|
||||
#endif /* NO_DIGRAPH */
|
||||
|
||||
/* process any flags */
|
||||
for (i = 1; i < argc && *argv[i] == '-'; i++)
|
||||
{
|
||||
switch (argv[i][1])
|
||||
{
|
||||
case 'R': /* readonly */
|
||||
*o_readonly = TRUE;
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
case 'r': /* recover */
|
||||
msg("Use the `elvrec` program to recover lost files");
|
||||
endmsgs();
|
||||
refresh();
|
||||
endwin();
|
||||
exit(0);
|
||||
break;
|
||||
|
||||
case 't': /* tag */
|
||||
if (argv[i][2])
|
||||
{
|
||||
tag = argv[i] + 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
tag = argv[++i];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'v': /* vi mode */
|
||||
mode = MODE_VI;
|
||||
break;
|
||||
|
||||
case 'e': /* ex mode */
|
||||
mode = MODE_EX;
|
||||
break;
|
||||
#ifndef NO_EXTENSIONS
|
||||
case 'i': /* input mode */
|
||||
*o_inputmode = TRUE;
|
||||
break;
|
||||
#endif
|
||||
#ifndef NO_ERRLIST
|
||||
case 'm': /* use "errlist" as the errlist */
|
||||
if (argv[i][2])
|
||||
{
|
||||
err = argv[i] + 2;
|
||||
}
|
||||
else if (i + 1 < argc)
|
||||
{
|
||||
err = argv[++i];
|
||||
}
|
||||
else
|
||||
{
|
||||
err = "";
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifndef CRUNCH
|
||||
case 'c': /* run the following command, later */
|
||||
if (argv[i][2])
|
||||
{
|
||||
cmd = argv[i] + 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd = argv[++i];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'w': /* set the window size */
|
||||
if (argv[i][2])
|
||||
{
|
||||
*o_window = atoi(argv[i] + 2);
|
||||
wset = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*o_window = atoi(argv[++i]);
|
||||
wset = TRUE;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
msg("Ignoring unknown flag \"%s\"", argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* if we were given an initial ex command, save it... */
|
||||
if (i < argc && *argv[i] == '+')
|
||||
{
|
||||
if (argv[i][1])
|
||||
{
|
||||
cmd = argv[i++] + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd = "$"; /* "vi + file" means start at EOF */
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/* the remaining args are file names. */
|
||||
if (i < argc)
|
||||
{
|
||||
strcpy(args, argv[i]);
|
||||
while (++i < argc && strlen(args) + 1 + strlen(argv[i]) < sizeof args)
|
||||
{
|
||||
strcat(args, " ");
|
||||
strcat(args, argv[i]);
|
||||
}
|
||||
#if MSDOS || TOS
|
||||
/* expand wildcard characters, if necessary */
|
||||
if (strchr(args, '*') || strchr(args, '?'))
|
||||
{
|
||||
strcpy(args, wildcard(args));
|
||||
}
|
||||
#endif
|
||||
strcpy(tmpblk.c, args);
|
||||
cmd_args(MARK_UNSET, MARK_UNSET, CMD_ARGS, TRUE, tmpblk.c);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* empty args list */
|
||||
args[0] = '\0';
|
||||
nargs = 1;
|
||||
argno = -1;
|
||||
}
|
||||
|
||||
/* perform the .exrc files and EXINIT environment variable */
|
||||
#ifdef SYSEXRC
|
||||
doexrc(SYSEXRC);
|
||||
#endif
|
||||
#ifdef HMEXRC
|
||||
str = getenv("HOME");
|
||||
if (str && *str)
|
||||
{
|
||||
strcpy(tmpblk.c, str);
|
||||
str = tmpblk.c + strlen(tmpblk.c);
|
||||
#if !VMS
|
||||
# if AMIGA /* Don't SLASH a device. "Elvis:.exrc" */
|
||||
if (str[-1] != COLON && str[-1] != SLASH)
|
||||
# else
|
||||
if (str[-1] != SLASH)
|
||||
# endif
|
||||
{
|
||||
*str++ = SLASH;
|
||||
}
|
||||
#endif
|
||||
strcpy(str, HMEXRC);
|
||||
doexrc(tmpblk.c);
|
||||
}
|
||||
#endif
|
||||
#ifndef CRUNCH
|
||||
if (*o_exrc)
|
||||
#endif
|
||||
{
|
||||
doexrc(EXRC);
|
||||
}
|
||||
#ifdef EXINIT
|
||||
str = getenv(EXINIT);
|
||||
if (str)
|
||||
{
|
||||
exstring(str, strlen(str), ctrl('V'));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* search for a tag (or an error) now, if desired */
|
||||
blkinit();
|
||||
if (tag)
|
||||
{
|
||||
cmd_tag(MARK_FIRST, MARK_FIRST, CMD_TAG, 0, tag);
|
||||
}
|
||||
#ifndef NO_ERRLIST
|
||||
else if (err)
|
||||
{
|
||||
cmd_errlist(MARK_FIRST, MARK_FIRST, CMD_ERRLIST, 0, err);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* if no tag/err, or tag failed, then start with first arg */
|
||||
if (tmpfd < 0)
|
||||
{
|
||||
/* start with first arg */
|
||||
cmd_next(MARK_UNSET, MARK_UNSET, CMD_NEXT, FALSE, "");
|
||||
|
||||
/* pretend to do something, just to force a recoverable
|
||||
* version of the file out to disk
|
||||
*/
|
||||
ChangeText
|
||||
{
|
||||
}
|
||||
clrflag(file, MODIFIED);
|
||||
}
|
||||
|
||||
/* now we do the immediate ex command that we noticed before */
|
||||
if (cmd)
|
||||
{
|
||||
doexcmd(cmd);
|
||||
}
|
||||
|
||||
/* repeatedly call ex() or vi() (depending on the mode) until the
|
||||
* mode is set to MODE_QUIT
|
||||
*/
|
||||
while (mode != MODE_QUIT)
|
||||
{
|
||||
if (setjmp(jmpenv))
|
||||
{
|
||||
/* Maybe we just aborted a change? */
|
||||
abortdo();
|
||||
}
|
||||
signal(SIGINT, (void(*)()) trapint);
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case MODE_VI:
|
||||
vi();
|
||||
break;
|
||||
|
||||
case MODE_EX:
|
||||
ex();
|
||||
break;
|
||||
#ifdef DEBUG
|
||||
default:
|
||||
msg("mode = %d?", mode);
|
||||
mode = MODE_QUIT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* free up the cut buffers */
|
||||
cutend();
|
||||
|
||||
/* end curses */
|
||||
#ifndef NO_CURSORSHAPE
|
||||
if (has_CQ)
|
||||
do_CQ();
|
||||
#endif
|
||||
endmsgs();
|
||||
move(LINES - 1, 0);
|
||||
clrtoeol();
|
||||
refresh();
|
||||
endwin();
|
||||
|
||||
exit(0);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
|
||||
/*ARGSUSED*/
|
||||
int trapint(signo)
|
||||
int signo;
|
||||
{
|
||||
beep();
|
||||
resume_curses(FALSE);
|
||||
abortdo();
|
||||
#if OSK
|
||||
sigmask(-1);
|
||||
#endif
|
||||
signal(signo, (void (*)())trapint);
|
||||
doingglobal = FALSE;
|
||||
|
||||
longjmp(jmpenv, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef NO_DIGRAPH
|
||||
|
||||
/* This stuff us used to build the default digraphs table. */
|
||||
static char digtable[][4] =
|
||||
{
|
||||
# ifdef CS_IBMPC
|
||||
"C,\200", "u\"\1", "e'\2", "a^\3",
|
||||
"a\"\4", "a`\5", "a@\6", "c,\7",
|
||||
"e^\10", "e\"\211", "e`\12", "i\"\13",
|
||||
"i^\14", "i`\15", "A\"\16", "A@\17",
|
||||
"E'\20", "ae\21", "AE\22", "o^\23",
|
||||
"o\"\24", "o`\25", "u^\26", "u`\27",
|
||||
"y\"\30", "O\"\31", "U\"\32", "a'\240",
|
||||
"i'!", "o'\"", "u'#", "n~$",
|
||||
"N~%", "a-&", "o-'", "~?(",
|
||||
"~!-", "\"<.", "\">/",
|
||||
# ifdef CS_SPECIAL
|
||||
"2/+", "4/,", "^+;", "^q<",
|
||||
"^c=", "^r>", "^t?", "pp]",
|
||||
"^^^", "oo_", "*a`", "*ba",
|
||||
"*pc", "*Sd", "*se", "*uf",
|
||||
"*tg", "*Ph", "*Ti", "*Oj",
|
||||
"*dk", "*Hl", "*hm", "*En",
|
||||
"*No", "eqp", "pmq", "ger",
|
||||
"les", "*It", "*iu", "*/v",
|
||||
"*=w", "sq{", "^n|", "^2}",
|
||||
"^3~", "^_\377",
|
||||
# endif /* CS_SPECIAL */
|
||||
# endif /* CS_IBMPC */
|
||||
# ifdef CS_LATIN1
|
||||
"~!!", "a-*", "\">+", "o-:",
|
||||
"\"<>", "~??",
|
||||
|
||||
"A`@", "A'A", "A^B", "A~C",
|
||||
"A\"D", "A@E", "AEF", "C,G",
|
||||
"E`H", "E'I", "E^J", "E\"K",
|
||||
"I`L", "I'M", "I^N", "I\"O",
|
||||
"-DP", "N~Q", "O`R", "O'S",
|
||||
"O^T", "O~U", "O\"V", "O/X",
|
||||
"U`Y", "U'Z", "U^[", "U\"\\",
|
||||
"Y'_",
|
||||
|
||||
"a``", "a'a", "a^b", "a~c",
|
||||
"a\"d", "a@e", "aef", "c,g",
|
||||
"e`h", "e'i", "e^j", "e\"k",
|
||||
"i`l", "i'm", "i^n", "i\"o",
|
||||
"-dp", "n~q", "o`r", "o's",
|
||||
"o^t", "o~u", "o\"v", "o/x",
|
||||
"u`y", "u'z", "u^{", "u\"|",
|
||||
"y'~",
|
||||
# endif /* CS_LATIN1 */
|
||||
""
|
||||
};
|
||||
|
||||
static init_digraphs()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; *digtable[i]; i++)
|
||||
{
|
||||
do_digraph(FALSE, digtable[i]);
|
||||
}
|
||||
do_digraph(FALSE, (char *)0);
|
||||
return 0;
|
||||
}
|
||||
#endif /* NO_DIGRAPH */
|
|
@ -1,103 +0,0 @@
|
|||
/* misc.c */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* 14407 SW Teal Blvd. #C
|
||||
* Beaverton, OR 97005
|
||||
* kirkenda@cs.pdx.edu
|
||||
*/
|
||||
|
||||
|
||||
/* This file contains functions which didn't seem happy anywhere else */
|
||||
|
||||
#include "config.h"
|
||||
#include "vi.h"
|
||||
|
||||
|
||||
/* find a particular line & return a pointer to a copy of its text */
|
||||
char *fetchline(line)
|
||||
long line; /* line number of the line to fetch */
|
||||
{
|
||||
int i;
|
||||
REG char *scan; /* used to search for the line in a BLK */
|
||||
long l; /* line number counter */
|
||||
static BLK buf; /* holds ONLY the selected line (as string) */
|
||||
REG char *cpy; /* used while copying the line */
|
||||
static long nextline; /* } These four variables are used */
|
||||
static long chglevel; /* } to implement a shortcut when */
|
||||
static char *nextscan; /* } consecutive lines are fetched */
|
||||
static long nextlnum; /* } */
|
||||
|
||||
/* can we do a shortcut? */
|
||||
if (changes == chglevel && line == nextline)
|
||||
{
|
||||
scan = nextscan;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* scan lnum[] to determine which block its in */
|
||||
for (i = 1; line > lnum[i]; i++)
|
||||
{
|
||||
}
|
||||
nextlnum = lnum[i];
|
||||
|
||||
/* fetch text of the block containing that line */
|
||||
scan = blkget(i)->c;
|
||||
|
||||
/* find the line in the block */
|
||||
for (l = lnum[i - 1]; ++l < line; )
|
||||
{
|
||||
while (*scan++ != '\n')
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* copy it into a block by itself, with no newline */
|
||||
for (cpy = buf.c; *scan != '\n'; )
|
||||
{
|
||||
*cpy++ = *scan++;
|
||||
}
|
||||
*cpy = '\0';
|
||||
|
||||
/* maybe speed up the next call to fetchline() ? */
|
||||
if (line < nextlnum)
|
||||
{
|
||||
nextline = line + 1;
|
||||
chglevel = changes;
|
||||
nextscan = scan + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextline = 0;
|
||||
}
|
||||
|
||||
/* Calls to fetchline() interfere with calls to pfetch(). Make sure
|
||||
* that pfetch() resets itself on its next invocation.
|
||||
*/
|
||||
pchgs = 0L;
|
||||
|
||||
/* Return a pointer to the line's text */
|
||||
return buf.c;
|
||||
}
|
||||
|
||||
|
||||
/* error message from the regexp code */
|
||||
void regerror(txt)
|
||||
char *txt; /* an error message */
|
||||
{
|
||||
msg("RE error: %s", txt);
|
||||
}
|
||||
|
||||
/* This function is equivelent to the pfetch() macro */
|
||||
void pfetch(l)
|
||||
long l; /* line number of line to fetch */
|
||||
{
|
||||
if(l != pline || changes != pchgs)
|
||||
{
|
||||
pline = (l);
|
||||
ptext = fetchline(pline);
|
||||
plen = strlen(ptext);
|
||||
pchgs = changes;
|
||||
}
|
||||
}
|
|
@ -1,474 +0,0 @@
|
|||
/* modify.c */
|
||||
|
||||
/* This file contains the low-level file modification functions:
|
||||
* delete(frommark, tomark) - removes line or portions of lines
|
||||
* add(frommark, text) - inserts new text
|
||||
* change(frommark, tomark, text) - delete, then add
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "vi.h"
|
||||
|
||||
#ifdef DEBUG2
|
||||
# include <stdio.h>
|
||||
static FILE *dbg;
|
||||
|
||||
/*VARARGS1*/
|
||||
debout(msg, arg1, arg2, arg3, arg4, arg5)
|
||||
char *msg, *arg1, *arg2, *arg3, *arg4, *arg5;
|
||||
{
|
||||
if (!dbg)
|
||||
{
|
||||
dbg = fopen("debug.out", "w");
|
||||
if (!dbg)
|
||||
return;
|
||||
setbuf(dbg, (FILE *)0);
|
||||
}
|
||||
fprintf(dbg, msg, arg1, arg2, arg3, arg4, arg5);
|
||||
}
|
||||
#endif /* DEBUG2 */
|
||||
|
||||
/* delete a range of text from the file */
|
||||
void delete(frommark, tomark)
|
||||
MARK frommark; /* first char to be deleted */
|
||||
MARK tomark; /* AFTER last char to be deleted */
|
||||
{
|
||||
int i; /* used to move thru logical blocks */
|
||||
REG char *scan; /* used to scan thru text of the blk */
|
||||
REG char *cpy; /* used when copying chars */
|
||||
BLK *blk; /* a text block */
|
||||
long l; /* a line number */
|
||||
MARK m; /* a traveling version of frommark */
|
||||
|
||||
#ifdef DEBUG2
|
||||
debout("delete(%ld.%d, %ld.%d)\n", markline(frommark), markidx(frommark), markline(tomark), markidx(tomark));
|
||||
#endif
|
||||
|
||||
/* if not deleting anything, quit now */
|
||||
if (frommark == tomark)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* This is a change */
|
||||
changes++;
|
||||
significant = TRUE;
|
||||
|
||||
/* supply clues to the redraw module */
|
||||
redrawrange(markline(frommark), markline(tomark), markline(frommark));
|
||||
|
||||
/* adjust marks 'a through 'z and '' as needed */
|
||||
l = markline(tomark);
|
||||
for (i = 0; i < NMARKS; i++)
|
||||
{
|
||||
if (mark[i] < frommark)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (mark[i] < tomark)
|
||||
{
|
||||
mark[i] = MARK_UNSET;
|
||||
}
|
||||
else if (markline(mark[i]) == l)
|
||||
{
|
||||
if (markline(frommark) == l)
|
||||
{
|
||||
mark[i] -= markidx(tomark) - markidx(frommark);
|
||||
}
|
||||
else
|
||||
{
|
||||
mark[i] -= markidx(tomark);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mark[i] -= MARK_AT_LINE(l - markline(frommark));
|
||||
}
|
||||
}
|
||||
|
||||
/* Reporting... */
|
||||
if (markidx(frommark) == 0 && markidx(tomark) == 0)
|
||||
{
|
||||
rptlines = markline(tomark) - markline(frommark);
|
||||
rptlabel = "deleted";
|
||||
}
|
||||
|
||||
/* find the block containing frommark */
|
||||
l = markline(frommark);
|
||||
for (i = 1; lnum[i] < l; i++)
|
||||
{
|
||||
}
|
||||
|
||||
/* process each affected block... */
|
||||
for (m = frommark;
|
||||
m < tomark && lnum[i] < INFINITY;
|
||||
m = MARK_AT_LINE(lnum[i - 1] + 1))
|
||||
{
|
||||
/* fetch the block */
|
||||
blk = blkget(i);
|
||||
|
||||
/* find the mark in the block */
|
||||
scan = blk->c;
|
||||
for (l = markline(m) - lnum[i - 1] - 1; l > 0; l--)
|
||||
{
|
||||
while (*scan++ != '\n')
|
||||
{
|
||||
}
|
||||
}
|
||||
scan += markidx(m);
|
||||
|
||||
/* figure out where the changes to this block end */
|
||||
if (markline(tomark) > lnum[i])
|
||||
{
|
||||
cpy = blk->c + BLKSIZE;
|
||||
}
|
||||
else if (markline(tomark) == markline(m))
|
||||
{
|
||||
cpy = scan - markidx(m) + markidx(tomark);
|
||||
}
|
||||
else
|
||||
{
|
||||
cpy = scan;
|
||||
for (l = markline(tomark) - markline(m);
|
||||
l > 0;
|
||||
l--)
|
||||
{
|
||||
while (*cpy++ != '\n')
|
||||
{
|
||||
}
|
||||
}
|
||||
cpy += markidx(tomark);
|
||||
}
|
||||
|
||||
/* delete the stuff by moving chars within this block */
|
||||
while (cpy < blk->c + BLKSIZE)
|
||||
{
|
||||
*scan++ = *cpy++;
|
||||
}
|
||||
while (scan < blk->c + BLKSIZE)
|
||||
{
|
||||
*scan++ = '\0';
|
||||
}
|
||||
|
||||
/* adjust tomark to allow for lines deleted from this block */
|
||||
tomark -= MARK_AT_LINE(lnum[i] + 1 - markline(m));
|
||||
|
||||
/* if this block isn't empty now, then advance i */
|
||||
if (*blk->c)
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
/* the buffer has changed. Update hdr and lnum. */
|
||||
blkdirty(blk);
|
||||
}
|
||||
|
||||
/* must have at least 1 line */
|
||||
if (nlines == 0)
|
||||
{
|
||||
blk = blkadd(1);
|
||||
blk->c[0] = '\n';
|
||||
blkdirty(blk);
|
||||
cursor = MARK_FIRST;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* add some text at a specific place in the file */
|
||||
void add(atmark, newtext)
|
||||
MARK atmark; /* where to insert the new text */
|
||||
char *newtext; /* NUL-terminated string to insert */
|
||||
{
|
||||
REG char *scan; /* used to move through string */
|
||||
REG char *build; /* used while copying chars */
|
||||
int addlines; /* number of lines we're adding */
|
||||
int lastpart; /* size of last partial line */
|
||||
BLK *blk; /* the block to be modified */
|
||||
int blkno; /* the logical block# of (*blk) */
|
||||
REG char *newptr; /* where new text starts in blk */
|
||||
BLK buf; /* holds chars from orig blk */
|
||||
BLK linebuf; /* holds part of line that didn't fit */
|
||||
BLK *following; /* the BLK following the last BLK */
|
||||
int i;
|
||||
long l;
|
||||
|
||||
#ifdef DEBUG2
|
||||
debout("add(%ld.%d, \"%s\")\n", markline(atmark), markidx(atmark), newtext);
|
||||
#endif
|
||||
#ifdef lint
|
||||
buf.c[0] = 0;
|
||||
#endif
|
||||
/* if not adding anything, return now */
|
||||
if (!*newtext)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* This is a change */
|
||||
changes++;
|
||||
significant = TRUE;
|
||||
|
||||
/* count the number of lines in the new text */
|
||||
for (scan = newtext, lastpart = addlines = 0; *scan; )
|
||||
{
|
||||
if (*scan++ == '\n')
|
||||
{
|
||||
addlines++;
|
||||
lastpart = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastpart++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reporting... */
|
||||
if (lastpart == 0 && markidx(atmark) == 0)
|
||||
{
|
||||
rptlines = addlines;
|
||||
rptlabel = "added";
|
||||
}
|
||||
|
||||
/* extract the line# from atmark */
|
||||
l = markline(atmark);
|
||||
|
||||
/* supply clues to the redraw module */
|
||||
if ((markidx(atmark) == 0 && lastpart == 0) || addlines == 0)
|
||||
{
|
||||
redrawrange(l, l, l + addlines);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* make sure the last line gets redrawn -- it was
|
||||
* split, so its appearance has changed
|
||||
*/
|
||||
redrawrange(l, l + 1L, l + addlines + 1L);
|
||||
}
|
||||
|
||||
/* adjust marks 'a through 'z and '' as needed */
|
||||
for (i = 0; i < NMARKS; i++)
|
||||
{
|
||||
if (mark[i] < atmark)
|
||||
{
|
||||
/* earlier line, or earlier in same line: no change */
|
||||
continue;
|
||||
}
|
||||
else if (markline(mark[i]) > l)
|
||||
{
|
||||
/* later line: move down a whole number of lines */
|
||||
mark[i] += MARK_AT_LINE(addlines);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* later in same line */
|
||||
if (addlines > 0)
|
||||
{
|
||||
/* multi-line add, which split this line:
|
||||
* move down, and possibly left or right,
|
||||
* depending on where the split was and how
|
||||
* much text was inserted after the last \n
|
||||
*/
|
||||
mark[i] += MARK_AT_LINE(addlines) + lastpart - markidx(atmark);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* totally within this line: move right */
|
||||
mark[i] += lastpart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* get the block to be modified */
|
||||
for (blkno = 1; lnum[blkno] < l && lnum[blkno + 1] < INFINITY; blkno++)
|
||||
{
|
||||
}
|
||||
blk = blkget(blkno);
|
||||
buf = *blk;
|
||||
|
||||
/* figure out where the new text starts */
|
||||
for (newptr = buf.c, l = markline(atmark) - lnum[blkno - 1] - 1;
|
||||
l > 0;
|
||||
l--)
|
||||
{
|
||||
while (*newptr++ != '\n')
|
||||
{
|
||||
}
|
||||
}
|
||||
newptr += markidx(atmark);
|
||||
|
||||
/* keep start of old block */
|
||||
build = blk->c + (int)(newptr - buf.c);
|
||||
|
||||
/* fill this block (or blocks) from the newtext string */
|
||||
while (*newtext)
|
||||
{
|
||||
while (*newtext && build < blk->c + BLKSIZE - 1)
|
||||
{
|
||||
*build++ = *newtext++;
|
||||
}
|
||||
if (*newtext)
|
||||
{
|
||||
/* save the excess */
|
||||
for (scan = linebuf.c + BLKSIZE;
|
||||
build > blk->c && build[-1] != '\n';
|
||||
)
|
||||
{
|
||||
*--scan = *--build;
|
||||
}
|
||||
|
||||
/* write the block */
|
||||
while (build < blk->c + BLKSIZE)
|
||||
{
|
||||
*build++ = '\0';
|
||||
}
|
||||
blkdirty(blk);
|
||||
|
||||
/* add another block */
|
||||
blkno++;
|
||||
blk = blkadd(blkno);
|
||||
|
||||
/* copy in the excess from last time */
|
||||
for (build = blk->c; scan < linebuf.c + BLKSIZE; )
|
||||
{
|
||||
*build++ = *scan++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* fill this block(s) from remainder of orig block */
|
||||
while (newptr < buf.c + BLKSIZE && *newptr)
|
||||
{
|
||||
while (newptr < buf.c + BLKSIZE
|
||||
&& *newptr
|
||||
&& build < blk->c + BLKSIZE - 1)
|
||||
{
|
||||
*build++ = *newptr++;
|
||||
}
|
||||
if (newptr < buf.c + BLKSIZE && *newptr)
|
||||
{
|
||||
/* save the excess */
|
||||
for (scan = linebuf.c + BLKSIZE;
|
||||
build > blk->c && build[-1] != '\n';
|
||||
)
|
||||
{
|
||||
*--scan = *--build;
|
||||
}
|
||||
|
||||
/* write the block */
|
||||
while (build < blk->c + BLKSIZE)
|
||||
{
|
||||
*build++ = '\0';
|
||||
}
|
||||
blkdirty(blk);
|
||||
|
||||
/* add another block */
|
||||
blkno++;
|
||||
blk = blkadd(blkno);
|
||||
|
||||
/* copy in the excess from last time */
|
||||
for (build = blk->c; scan < linebuf.c + BLKSIZE; )
|
||||
{
|
||||
*build++ = *scan++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* see if we can combine our last block with the following block */
|
||||
if (lnum[blkno] < nlines && lnum[blkno + 1] - lnum[blkno] < (BLKSIZE >> 6))
|
||||
{
|
||||
/* hey, we probably can! Get the following block & see... */
|
||||
following = blkget(blkno + 1);
|
||||
if (strlen(following->c) + (build - blk->c) < BLKSIZE - 1)
|
||||
{
|
||||
/* we can! Copy text from following to blk */
|
||||
for (scan = following->c; *scan; )
|
||||
{
|
||||
*build++ = *scan++;
|
||||
}
|
||||
while (build < blk->c + BLKSIZE)
|
||||
{
|
||||
*build++ = '\0';
|
||||
}
|
||||
blkdirty(blk);
|
||||
|
||||
/* pretend the following was the last blk */
|
||||
blk = following;
|
||||
build = blk->c;
|
||||
}
|
||||
}
|
||||
|
||||
/* that last block is dirty by now */
|
||||
while (build < blk->c + BLKSIZE)
|
||||
{
|
||||
*build++ = '\0';
|
||||
}
|
||||
blkdirty(blk);
|
||||
}
|
||||
|
||||
|
||||
/* change the text of a file */
|
||||
void change(frommark, tomark, newtext)
|
||||
MARK frommark, tomark;
|
||||
char *newtext;
|
||||
{
|
||||
int i;
|
||||
long l;
|
||||
char *text;
|
||||
BLK *blk;
|
||||
|
||||
#ifdef DEBUG2
|
||||
debout("change(%ld.%d, %ld.%d, \"%s\")\n", markline(frommark), markidx(frommark), markline(tomark), markidx(tomark), newtext);
|
||||
#endif
|
||||
|
||||
/* optimize for single-character replacement */
|
||||
if (frommark + 1 == tomark && newtext[0] && !newtext[1] && newtext[0] != '\n')
|
||||
{
|
||||
/* find the block containing frommark */
|
||||
l = markline(frommark);
|
||||
for (i = 1; lnum[i] < l; i++)
|
||||
{
|
||||
}
|
||||
|
||||
/* get the block */
|
||||
blk = blkget(i);
|
||||
|
||||
/* find the line within the block */
|
||||
for (text = blk->c, i = l - lnum[i - 1] - 1; i > 0; text++)
|
||||
{
|
||||
if (*text == '\n')
|
||||
{
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
/* replace the char */
|
||||
text += markidx(frommark);
|
||||
if (*text == newtext[0])
|
||||
{
|
||||
/* no change was needed - same char */
|
||||
return;
|
||||
}
|
||||
else if (*text != '\n')
|
||||
{
|
||||
/* This is a change */
|
||||
changes++;
|
||||
significant = TRUE;
|
||||
ChangeText
|
||||
{
|
||||
*text = newtext[0];
|
||||
blkdirty(blk);
|
||||
}
|
||||
redrawrange(markline(frommark), markline(tomark), markline(frommark));
|
||||
return;
|
||||
}
|
||||
/* else it is a complex change involving newline... */
|
||||
}
|
||||
|
||||
/* couldn't optimize, so do delete & add */
|
||||
ChangeText
|
||||
{
|
||||
delete(frommark, tomark);
|
||||
add(frommark, newtext);
|
||||
rptlabel = "changed";
|
||||
}
|
||||
}
|
|
@ -1,585 +0,0 @@
|
|||
/* move1.c */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* 14407 SW Teal Blvd. #C
|
||||
* Beaverton, OR 97005
|
||||
* kirkenda@cs.pdx.edu
|
||||
*/
|
||||
|
||||
|
||||
/* This file contains most movement functions */
|
||||
|
||||
#include "config.h"
|
||||
#include "vi.h"
|
||||
#include "ctype.h"
|
||||
|
||||
MARK m_updnto(m, cnt, cmd)
|
||||
MARK m; /* movement is relative to this mark */
|
||||
long cnt; /* a numeric argument */
|
||||
char cmd; /* the command character */
|
||||
{
|
||||
DEFAULT(cmd == 'G' ? nlines : 1L);
|
||||
|
||||
/* move up or down 'cnt' lines */
|
||||
switch (cmd)
|
||||
{
|
||||
case ctrl('P'):
|
||||
case '-':
|
||||
case 'k':
|
||||
m -= MARK_AT_LINE(cnt);
|
||||
break;
|
||||
|
||||
case 'G':
|
||||
if (cnt < 1L || cnt > nlines)
|
||||
{
|
||||
msg("Only %ld lines", nlines);
|
||||
return MARK_UNSET;
|
||||
}
|
||||
m = MARK_AT_LINE(cnt);
|
||||
break;
|
||||
|
||||
case '_':
|
||||
cnt--;
|
||||
/* fall through... */
|
||||
|
||||
default:
|
||||
m += MARK_AT_LINE(cnt);
|
||||
}
|
||||
|
||||
/* if that left us screwed up, then fail */
|
||||
if (m < MARK_FIRST || markline(m) > nlines)
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
MARK m_right(m, cnt, key, prevkey)
|
||||
MARK m; /* movement is relative to this mark */
|
||||
long cnt; /* a numeric argument */
|
||||
int key; /* movement keystroke */
|
||||
int prevkey;/* operator keystroke, or 0 if none */
|
||||
{
|
||||
int idx; /* index of the new cursor position */
|
||||
|
||||
DEFAULT(1);
|
||||
|
||||
/* If used with an operator, then move 1 less character, since the 'l'
|
||||
* command includes the character that it moves onto.
|
||||
*/
|
||||
if (prevkey != '\0')
|
||||
{
|
||||
cnt--;
|
||||
}
|
||||
|
||||
/* move to right, if that's OK */
|
||||
pfetch(markline(m));
|
||||
idx = markidx(m) + cnt;
|
||||
if (idx < plen)
|
||||
{
|
||||
m += cnt;
|
||||
}
|
||||
else
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
MARK m_left(m, cnt)
|
||||
MARK m; /* movement is relative to this mark */
|
||||
long cnt; /* a numeric argument */
|
||||
{
|
||||
DEFAULT(1);
|
||||
|
||||
/* move to the left, if that's OK */
|
||||
if (markidx(m) >= cnt)
|
||||
{
|
||||
m -= cnt;
|
||||
}
|
||||
else
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
MARK m_tocol(m, cnt, cmd)
|
||||
MARK m; /* movement is relative to this mark */
|
||||
long cnt; /* a numeric argument */
|
||||
int cmd; /* either ctrl('X') or '|' */
|
||||
{
|
||||
char *text; /* text of the line */
|
||||
int col; /* column number */
|
||||
int idx; /* index into the line */
|
||||
|
||||
|
||||
/* if doing ^X, then adjust for sideways scrolling */
|
||||
if (cmd == ctrl('X'))
|
||||
{
|
||||
DEFAULT(*o_columns & 0xff);
|
||||
cnt += leftcol;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEFAULT(1);
|
||||
}
|
||||
|
||||
/* internally, columns are numbered 0..COLS-1, not 1..COLS */
|
||||
cnt--;
|
||||
|
||||
/* if 0, that's easy */
|
||||
if (cnt == 0)
|
||||
{
|
||||
m &= ~(BLKSIZE - 1);
|
||||
return m;
|
||||
}
|
||||
|
||||
/* find that column within the line */
|
||||
pfetch(markline(m));
|
||||
text = ptext;
|
||||
for (col = idx = 0; col < cnt && *text; text++, idx++)
|
||||
{
|
||||
if (*text == '\t' && !*o_list)
|
||||
{
|
||||
col += *o_tabstop;
|
||||
col -= col % *o_tabstop;
|
||||
}
|
||||
else if (UCHAR(*text) < ' ' || *text == '\177')
|
||||
{
|
||||
col += 2;
|
||||
}
|
||||
#ifndef NO_CHARATTR
|
||||
else if (text[0] == '\\' && text[1] == 'f' && text[2] && *o_charattr)
|
||||
{
|
||||
text += 2; /* plus one more as part of for loop */
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
col++;
|
||||
}
|
||||
}
|
||||
if (!*text)
|
||||
{
|
||||
/* the desired column was past the end of the line, so
|
||||
* act like the user pressed "$" instead.
|
||||
*/
|
||||
return m | (BLKSIZE - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
m = (m & ~(BLKSIZE - 1)) + idx;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
MARK m_front(m, cnt)
|
||||
MARK m; /* movement is relative to this mark */
|
||||
long cnt; /* a numeric argument (ignored) */
|
||||
{
|
||||
char *scan;
|
||||
|
||||
/* move to the first non-whitespace character */
|
||||
pfetch(markline(m));
|
||||
scan = ptext;
|
||||
m &= ~(BLKSIZE - 1);
|
||||
while (*scan == ' ' || *scan == '\t')
|
||||
{
|
||||
scan++;
|
||||
m++;
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
MARK m_rear(m, cnt)
|
||||
MARK m; /* movement is relative to this mark */
|
||||
long cnt; /* a numeric argument (ignored) */
|
||||
{
|
||||
/* Try to move *EXTREMELY* far to the right. It is fervently hoped
|
||||
* that other code will convert this to a more reasonable MARK before
|
||||
* anything tries to actually use it. (See adjmove() in vi.c)
|
||||
*/
|
||||
return m | (BLKSIZE - 1);
|
||||
}
|
||||
|
||||
#ifndef NO_SENTENCE
|
||||
static int isperiod(ptr)
|
||||
char *ptr; /* pointer to possible sentence-ender */
|
||||
{
|
||||
/* if not '.', '?', or '!', then it isn't a sentence ender */
|
||||
if (*ptr != '.' && *ptr != '?' && *ptr != '!')
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* skip any intervening ')', ']', or '"' characters */
|
||||
do
|
||||
{
|
||||
ptr++;
|
||||
} while (*ptr == ')' || *ptr == ']' || *ptr == '"');
|
||||
|
||||
/* do we have two spaces or EOL? */
|
||||
if (!*ptr || ptr[0] == ' ' && ptr[1] == ' ')
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
MARK m_sentence(m, cnt, cmd)
|
||||
MARK m; /* movement is relative to this mark */
|
||||
long cnt; /* a numeric argument */
|
||||
int cmd; /* either '(' or ')' */
|
||||
{
|
||||
REG char *text;
|
||||
REG long l;
|
||||
|
||||
DEFAULT(1);
|
||||
|
||||
/* If '(' command, then move back one word, so that if we hit '(' at
|
||||
* the start of a sentence we don't simply stop at the end of the
|
||||
* previous sentence and bounce back to the start of this one again.
|
||||
*/
|
||||
if (cmd == '(')
|
||||
{
|
||||
m = m_bword(m, 1L, 'b');
|
||||
if (!m)
|
||||
{
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
||||
/* get the current line */
|
||||
l = markline(m);
|
||||
pfetch(l);
|
||||
text = ptext + markidx(m);
|
||||
|
||||
/* for each requested sentence... */
|
||||
while (cnt-- > 0)
|
||||
{
|
||||
/* search forward for one of [.?!] followed by spaces or EOL */
|
||||
do
|
||||
{
|
||||
if (cmd == ')')
|
||||
{
|
||||
/* move forward, wrap at end of line */
|
||||
if (!text[0])
|
||||
{
|
||||
if (l >= nlines)
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
l++;
|
||||
pfetch(l);
|
||||
text = ptext;
|
||||
}
|
||||
else
|
||||
{
|
||||
text++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* move backward, wrap at beginning of line */
|
||||
if (text == ptext)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (l <= 1)
|
||||
{
|
||||
return MARK_FIRST;
|
||||
}
|
||||
l--;
|
||||
pfetch(l);
|
||||
} while (!*ptext);
|
||||
text = ptext + plen - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
text--;
|
||||
}
|
||||
}
|
||||
} while (!isperiod(text));
|
||||
}
|
||||
|
||||
/* construct a mark for this location */
|
||||
m = buildmark(text);
|
||||
|
||||
/* move forward to the first word of the next sentence */
|
||||
m = m_fword(m, 1L, 'w', '\0');
|
||||
|
||||
return m;
|
||||
}
|
||||
#endif
|
||||
|
||||
MARK m_paragraph(m, cnt, cmd)
|
||||
MARK m; /* movement is relative to this mark */
|
||||
long cnt; /* a numeric argument */
|
||||
int cmd; /* either '{' or '}' */
|
||||
{
|
||||
char *text; /* text of the current line */
|
||||
char *pscn; /* used to scan thru value of "paragraphs" option */
|
||||
long l, ol; /* current line number, original line number */
|
||||
int dir; /* -1 if we're moving up, or 1 if down */
|
||||
char col0; /* character to expect in column 0 */
|
||||
#ifndef NO_SENTENCE
|
||||
# define SENTENCE(x) (x)
|
||||
char *list; /* either o_sections or o_paragraph */
|
||||
#else
|
||||
# define SENTENCE(x)
|
||||
#endif
|
||||
|
||||
DEFAULT(1);
|
||||
|
||||
/* set the direction, based on the command */
|
||||
switch (cmd)
|
||||
{
|
||||
case '{':
|
||||
dir = -1;
|
||||
col0 = '\0';
|
||||
SENTENCE(list = o_paragraphs);
|
||||
break;
|
||||
|
||||
case '}':
|
||||
dir = 1;
|
||||
col0 = '\0';
|
||||
SENTENCE(list = o_paragraphs);
|
||||
break;
|
||||
|
||||
case '[':
|
||||
if (getkey(0) != '[')
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
dir = -1;
|
||||
col0 = '{';
|
||||
SENTENCE(list = o_sections);
|
||||
break;
|
||||
|
||||
case ']':
|
||||
if (getkey(0) != ']')
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
dir = 1;
|
||||
col0 = '{';
|
||||
SENTENCE(list = o_sections);
|
||||
break;
|
||||
}
|
||||
ol = l = markline(m);
|
||||
|
||||
/* for each paragraph that we want to travel through... */
|
||||
while (l > 0 && l <= nlines && cnt-- > 0)
|
||||
{
|
||||
/* skip blank lines between paragraphs */
|
||||
while (l > 0 && l <= nlines && col0 == *(text = fetchline(l)))
|
||||
{
|
||||
l += dir;
|
||||
}
|
||||
|
||||
/* skip non-blank lines that aren't paragraph separators
|
||||
*/
|
||||
do
|
||||
{
|
||||
#ifndef NO_SENTENCE
|
||||
if (*text == '.' && l != ol)
|
||||
{
|
||||
for (pscn = list; pscn[0] && pscn[1]; pscn += 2)
|
||||
{
|
||||
if (pscn[0] == text[1] && pscn[1] == text[2])
|
||||
{
|
||||
pscn = (char *)0;
|
||||
goto BreakBreak;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
l += dir;
|
||||
} while (l > 0 && l <= nlines && col0 != *(text = fetchline(l)));
|
||||
BreakBreak: ;
|
||||
}
|
||||
|
||||
if (l > nlines)
|
||||
{
|
||||
m = MARK_LAST;
|
||||
}
|
||||
else if (l <= 0)
|
||||
{
|
||||
m = MARK_FIRST;
|
||||
}
|
||||
else
|
||||
{
|
||||
m = MARK_AT_LINE(l);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/*ARGSUSED*/
|
||||
MARK m_match(m, cnt)
|
||||
MARK m; /* movement is relative to this mark */
|
||||
long cnt; /* a numeric argument (normally 0) */
|
||||
{
|
||||
long l;
|
||||
REG char *text;
|
||||
REG char match;
|
||||
REG char nest;
|
||||
REG int count;
|
||||
|
||||
#ifndef NO_EXTENSIONS
|
||||
/* if we're given a number, then treat it as a percentage of the file */
|
||||
if (cnt > 0)
|
||||
{
|
||||
/* make sure it is a reasonable number */
|
||||
if (cnt > 100)
|
||||
{
|
||||
msg("can only be from 1%% to 100%%");
|
||||
return MARK_UNSET;
|
||||
}
|
||||
|
||||
/* return the appropriate line number */
|
||||
l = (nlines - 1L) * cnt / 100L + 1L;
|
||||
return MARK_AT_LINE(l);
|
||||
}
|
||||
#endif /* undef NO_EXTENSIONS */
|
||||
|
||||
/* get the current line */
|
||||
l = markline(m);
|
||||
pfetch(l);
|
||||
text = ptext + markidx(m);
|
||||
|
||||
/* search forward within line for one of "[](){}" */
|
||||
for (match = '\0'; !match && *text; text++)
|
||||
{
|
||||
/* tricky way to recognize 'em in ASCII */
|
||||
nest = *text;
|
||||
if ((nest & 0xdf) == ']' || (nest & 0xdf) == '[')
|
||||
{
|
||||
match = nest ^ ('[' ^ ']');
|
||||
}
|
||||
else if ((nest & 0xfe) == '(')
|
||||
{
|
||||
match = nest ^ ('(' ^ ')');
|
||||
}
|
||||
else
|
||||
{
|
||||
match = 0;
|
||||
}
|
||||
}
|
||||
if (!match)
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
text--;
|
||||
|
||||
/* search forward or backward for match */
|
||||
if (match == '(' || match == '[' || match == '{')
|
||||
{
|
||||
/* search backward */
|
||||
for (count = 1; count > 0; )
|
||||
{
|
||||
/* wrap at beginning of line */
|
||||
if (text == ptext)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (l <= 1L)
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
l--;
|
||||
pfetch(l);
|
||||
} while (!*ptext);
|
||||
text = ptext + plen - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
text--;
|
||||
}
|
||||
|
||||
/* check the char */
|
||||
if (*text == match)
|
||||
count--;
|
||||
else if (*text == nest)
|
||||
count++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* search forward */
|
||||
for (count = 1; count > 0; )
|
||||
{
|
||||
/* wrap at end of line */
|
||||
if (!*text)
|
||||
{
|
||||
if (l >= nlines)
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
l++;
|
||||
pfetch(l);
|
||||
text = ptext;
|
||||
}
|
||||
else
|
||||
{
|
||||
text++;
|
||||
}
|
||||
|
||||
/* check the char */
|
||||
if (*text == match)
|
||||
count--;
|
||||
else if (*text == nest)
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* construct a mark for this place */
|
||||
m = buildmark(text);
|
||||
return m;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
MARK m_tomark(m, cnt, key)
|
||||
MARK m; /* movement is relative to this mark */
|
||||
long cnt; /* (ignored) */
|
||||
int key; /* keystroke - the mark to move to */
|
||||
{
|
||||
/* mark '' is a special case */
|
||||
if (key == '\'' || key == '`')
|
||||
{
|
||||
if (mark[26] == MARK_UNSET)
|
||||
{
|
||||
return MARK_FIRST;
|
||||
}
|
||||
else
|
||||
{
|
||||
return mark[26];
|
||||
}
|
||||
}
|
||||
|
||||
/* if not a valid mark number, don't move */
|
||||
if (key < 'a' || key > 'z')
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
|
||||
/* return the selected mark -- may be MARK_UNSET */
|
||||
if (!mark[key - 'a'])
|
||||
{
|
||||
msg("mark '%c is unset", key);
|
||||
}
|
||||
return mark[key - 'a'];
|
||||
}
|
||||
|
|
@ -1,291 +0,0 @@
|
|||
/* move2.c */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* 14407 SW Teal Blvd. #C
|
||||
* Beaverton, OR 97005
|
||||
* kirkenda@cs.pdx.edu
|
||||
*/
|
||||
|
||||
|
||||
/* This function contains the movement functions that perform RE searching */
|
||||
|
||||
#include "config.h"
|
||||
#include "vi.h"
|
||||
#include "regexp.h"
|
||||
|
||||
extern long atol();
|
||||
|
||||
static regexp *re; /* compiled version of the pattern to search for */
|
||||
static prevsf; /* boolean: previous search direction was forward? */
|
||||
|
||||
#ifndef NO_EXTENSIONS
|
||||
/*ARGSUSED*/
|
||||
MARK m_wsrch(word, m, cnt)
|
||||
char *word; /* the word to search for */
|
||||
MARK m; /* the starting point */
|
||||
int cnt; /* ignored */
|
||||
{
|
||||
char buffer[30];
|
||||
|
||||
/* wrap \< and \> around the word */
|
||||
strcpy(buffer, "/\\<");
|
||||
strcat(buffer, word);
|
||||
strcat(buffer, "\\>");
|
||||
|
||||
/* show the searched-for word on the bottom line */
|
||||
move(LINES - 1, 0);
|
||||
qaddstr(buffer);
|
||||
clrtoeol();
|
||||
refresh();
|
||||
|
||||
/* search for the word */
|
||||
return m_fsrch(m, buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
MARK m_nsrch(m)
|
||||
MARK m; /* where to start searching */
|
||||
{
|
||||
if (prevsf)
|
||||
{
|
||||
m = m_fsrch(m, (char *)0);
|
||||
prevsf = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
m = m_bsrch(m, (char *)0);
|
||||
prevsf = FALSE;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
MARK m_Nsrch(m)
|
||||
MARK m; /* where to start searching */
|
||||
{
|
||||
if (prevsf)
|
||||
{
|
||||
m = m_bsrch(m, (char *)0);
|
||||
prevsf = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
m = m_fsrch(m, (char *)0);
|
||||
prevsf = FALSE;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
MARK m_fsrch(m, ptrn)
|
||||
MARK m; /* where to start searching */
|
||||
char *ptrn; /* pattern to search for */
|
||||
{
|
||||
long l; /* line# of line to be searched */
|
||||
char *line; /* text of line to be searched */
|
||||
int wrapped;/* boolean: has our search wrapped yet? */
|
||||
int pos; /* where we are in the line */
|
||||
#ifndef CRUNCH
|
||||
long delta = INFINITY;/* line offset, for things like "/foo/+1" */
|
||||
#endif
|
||||
|
||||
/* remember: "previous search was forward" */
|
||||
prevsf = TRUE;
|
||||
|
||||
if (ptrn && *ptrn)
|
||||
{
|
||||
/* locate the closing '/', if any */
|
||||
line = parseptrn(ptrn);
|
||||
#ifndef CRUNCH
|
||||
if (*line)
|
||||
{
|
||||
delta = atol(line);
|
||||
}
|
||||
#endif
|
||||
ptrn++;
|
||||
|
||||
/* free the previous pattern */
|
||||
if (re) free(re);
|
||||
|
||||
/* compile the pattern */
|
||||
re = regcomp(ptrn);
|
||||
if (!re)
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
}
|
||||
else if (!re)
|
||||
{
|
||||
msg("No previous expression");
|
||||
return MARK_UNSET;
|
||||
}
|
||||
|
||||
/* search forward for the pattern */
|
||||
pos = markidx(m) + 1;
|
||||
pfetch(markline(m));
|
||||
if (pos >= plen)
|
||||
{
|
||||
pos = 0;
|
||||
m = (m | (BLKSIZE - 1)) + 1;
|
||||
}
|
||||
wrapped = FALSE;
|
||||
for (l = markline(m); l != markline(m) + 1 || !wrapped; l++)
|
||||
{
|
||||
/* wrap search */
|
||||
if (l > nlines)
|
||||
{
|
||||
/* if we wrapped once already, then the search failed */
|
||||
if (wrapped)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* else maybe we should wrap now? */
|
||||
if (*o_wrapscan)
|
||||
{
|
||||
l = 0;
|
||||
wrapped = TRUE;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* get this line */
|
||||
line = fetchline(l);
|
||||
|
||||
/* check this line */
|
||||
if (regexec(re, &line[pos], (pos == 0)))
|
||||
{
|
||||
/* match! */
|
||||
if (wrapped && *o_warn)
|
||||
msg("(wrapped)");
|
||||
#ifndef CRUNCH
|
||||
if (delta != INFINITY)
|
||||
{
|
||||
l += delta;
|
||||
if (l < 1 || l > nlines)
|
||||
{
|
||||
msg("search offset too big");
|
||||
return MARK_UNSET;
|
||||
}
|
||||
force_flags = LNMD|INCL;
|
||||
return MARK_AT_LINE(l);
|
||||
}
|
||||
#endif
|
||||
return MARK_AT_LINE(l) + (int)(re->startp[0] - line);
|
||||
}
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
/* not found */
|
||||
msg(*o_wrapscan ? "Not found" : "Hit bottom without finding RE");
|
||||
return MARK_UNSET;
|
||||
}
|
||||
|
||||
MARK m_bsrch(m, ptrn)
|
||||
MARK m; /* where to start searching */
|
||||
char *ptrn; /* pattern to search for */
|
||||
{
|
||||
long l; /* line# of line to be searched */
|
||||
char *line; /* text of line to be searched */
|
||||
int wrapped;/* boolean: has our search wrapped yet? */
|
||||
int pos; /* last acceptable idx for a match on this line */
|
||||
int last; /* remembered idx of the last acceptable match on this line */
|
||||
int try; /* an idx at which we strat searching for another match */
|
||||
#ifndef CRUNCH
|
||||
long delta = INFINITY;/* line offset, for things like "/foo/+1" */
|
||||
#endif
|
||||
|
||||
/* remember: "previous search was not forward" */
|
||||
prevsf = FALSE;
|
||||
|
||||
if (ptrn && *ptrn)
|
||||
{
|
||||
/* locate the closing '?', if any */
|
||||
line = parseptrn(ptrn);
|
||||
#ifndef CRUNCH
|
||||
if (*line)
|
||||
{
|
||||
delta = atol(line);
|
||||
}
|
||||
#endif
|
||||
ptrn++;
|
||||
|
||||
/* free the previous pattern, if any */
|
||||
if (re) free(re);
|
||||
|
||||
/* compile the pattern */
|
||||
re = regcomp(ptrn);
|
||||
if (!re)
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
}
|
||||
else if (!re)
|
||||
{
|
||||
msg("No previous expression");
|
||||
return MARK_UNSET;
|
||||
}
|
||||
|
||||
/* search backward for the pattern */
|
||||
pos = markidx(m);
|
||||
wrapped = FALSE;
|
||||
for (l = markline(m); l != markline(m) - 1 || !wrapped; l--)
|
||||
{
|
||||
/* wrap search */
|
||||
if (l < 1)
|
||||
{
|
||||
if (*o_wrapscan)
|
||||
{
|
||||
l = nlines + 1;
|
||||
wrapped = TRUE;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* get this line */
|
||||
line = fetchline(l);
|
||||
|
||||
/* check this line */
|
||||
if (regexec(re, line, 1) && (int)(re->startp[0] - line) < pos)
|
||||
{
|
||||
/* match! now find the last acceptable one in this line */
|
||||
do
|
||||
{
|
||||
last = (int)(re->startp[0] - line);
|
||||
try = (int)(re->endp[0] - line);
|
||||
} while (try > 0
|
||||
&& regexec(re, &line[try], FALSE)
|
||||
&& (int)(re->startp[0] - line) < pos);
|
||||
|
||||
if (wrapped && *o_warn)
|
||||
msg("(wrapped)");
|
||||
#ifndef CRUNCH
|
||||
if (delta != INFINITY)
|
||||
{
|
||||
l += delta;
|
||||
if (l < 1 || l > nlines)
|
||||
{
|
||||
msg("search offset too big");
|
||||
return MARK_UNSET;
|
||||
}
|
||||
force_flags = LNMD|INCL;
|
||||
return MARK_AT_LINE(l);
|
||||
}
|
||||
#endif
|
||||
return MARK_AT_LINE(l) + last;
|
||||
}
|
||||
pos = BLKSIZE;
|
||||
}
|
||||
|
||||
/* not found */
|
||||
msg(*o_wrapscan ? "Not found" : "Hit top without finding RE");
|
||||
return MARK_UNSET;
|
||||
}
|
||||
|
|
@ -1,163 +0,0 @@
|
|||
/* move3.c */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* 14407 SW Teal Blvd. #C
|
||||
* Beaverton, OR 97005
|
||||
* kirkenda@cs.pdx.edu
|
||||
*/
|
||||
|
||||
|
||||
/* This file contains movement functions that perform character searches */
|
||||
|
||||
#include "config.h"
|
||||
#include "vi.h"
|
||||
|
||||
#ifndef NO_CHARSEARCH
|
||||
static MARK (*prevfwdfn)(); /* function to search in same direction */
|
||||
static MARK (*prevrevfn)(); /* function to search in opposite direction */
|
||||
static char prev_key; /* sought cvhar from previous [fFtT] */
|
||||
|
||||
MARK m__ch(m, cnt, cmd)
|
||||
MARK m; /* current position */
|
||||
long cnt;
|
||||
char cmd; /* command: either ',' or ';' */
|
||||
{
|
||||
MARK (*tmp)();
|
||||
|
||||
if (!prevfwdfn)
|
||||
{
|
||||
msg("No previous f, F, t, or T command");
|
||||
return MARK_UNSET;
|
||||
}
|
||||
|
||||
if (cmd == ',')
|
||||
{
|
||||
m = (*prevrevfn)(m, cnt, prev_key);
|
||||
|
||||
/* Oops! we didn't want to change the prev*fn vars! */
|
||||
tmp = prevfwdfn;
|
||||
prevfwdfn = prevrevfn;
|
||||
prevrevfn = tmp;
|
||||
|
||||
return m;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (*prevfwdfn)(m, cnt, prev_key);
|
||||
}
|
||||
}
|
||||
|
||||
/* move forward within this line to next occurrence of key */
|
||||
MARK m_fch(m, cnt, key)
|
||||
MARK m; /* where to search from */
|
||||
long cnt;
|
||||
char key; /* what to search for */
|
||||
{
|
||||
REG char *text;
|
||||
|
||||
DEFAULT(1);
|
||||
|
||||
prevfwdfn = m_fch;
|
||||
prevrevfn = m_Fch;
|
||||
prev_key = key;
|
||||
|
||||
pfetch(markline(m));
|
||||
text = ptext + markidx(m);
|
||||
while (cnt-- > 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
m++;
|
||||
text++;
|
||||
} while (*text && *text != key);
|
||||
}
|
||||
if (!*text)
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/* move backward within this line to previous occurrence of key */
|
||||
MARK m_Fch(m, cnt, key)
|
||||
MARK m; /* where to search from */
|
||||
long cnt;
|
||||
char key; /* what to search for */
|
||||
{
|
||||
REG char *text;
|
||||
|
||||
DEFAULT(1);
|
||||
|
||||
prevfwdfn = m_Fch;
|
||||
prevrevfn = m_fch;
|
||||
prev_key = key;
|
||||
|
||||
pfetch(markline(m));
|
||||
text = ptext + markidx(m);
|
||||
while (cnt-- > 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
m--;
|
||||
text--;
|
||||
} while (text >= ptext && *text != key);
|
||||
}
|
||||
if (text < ptext)
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/* move forward within this line almost to next occurrence of key */
|
||||
MARK m_tch(m, cnt, key)
|
||||
MARK m; /* where to search from */
|
||||
long cnt;
|
||||
char key; /* what to search for */
|
||||
{
|
||||
/* skip the adjacent char */
|
||||
pfetch(markline(m));
|
||||
if (plen <= markidx(m))
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
m++;
|
||||
|
||||
m = m_fch(m, cnt, key);
|
||||
if (m == MARK_UNSET)
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
|
||||
prevfwdfn = m_tch;
|
||||
prevrevfn = m_Tch;
|
||||
|
||||
return m - 1;
|
||||
}
|
||||
|
||||
/* move backward within this line almost to previous occurrence of key */
|
||||
MARK m_Tch(m, cnt, key)
|
||||
MARK m; /* where to search from */
|
||||
long cnt;
|
||||
char key; /* what to search for */
|
||||
{
|
||||
/* skip the adjacent char */
|
||||
if (markidx(m) == 0)
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
m--;
|
||||
|
||||
m = m_Fch(m, cnt, key);
|
||||
if (m == MARK_UNSET)
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
|
||||
prevfwdfn = m_Tch;
|
||||
prevrevfn = m_tch;
|
||||
|
||||
return m + 1;
|
||||
}
|
||||
#endif
|
|
@ -1,211 +0,0 @@
|
|||
/* move4.c */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* 14407 SW Teal Blvd. #C
|
||||
* Beaverton, OR 97005
|
||||
* kirkenda@cs.pdx.edu
|
||||
*/
|
||||
|
||||
|
||||
/* This file contains movement functions which are screen-relative */
|
||||
|
||||
#include "config.h"
|
||||
#include "vi.h"
|
||||
|
||||
/* This moves the cursor to a particular row on the screen */
|
||||
/*ARGSUSED*/
|
||||
MARK m_row(m, cnt, key)
|
||||
MARK m; /* the cursor position */
|
||||
long cnt; /* the row we'll move to */
|
||||
int key; /* the keystroke of this move - H/L/M */
|
||||
{
|
||||
DEFAULT(1);
|
||||
|
||||
/* calculate destination line based on key */
|
||||
cnt--;
|
||||
switch (key)
|
||||
{
|
||||
case 'H':
|
||||
cnt = topline + cnt;
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
cnt = topline + (LINES - 1) / 2;
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
cnt = botline - cnt;
|
||||
break;
|
||||
}
|
||||
|
||||
/* return the mark of the destination line */
|
||||
return MARK_AT_LINE(cnt);
|
||||
}
|
||||
|
||||
|
||||
/* This function repositions the current line to show on a given row */
|
||||
MARK m_z(m, cnt, key)
|
||||
MARK m; /* the cursor */
|
||||
long cnt; /* the line number we're repositioning */
|
||||
int key; /* key struck after the z */
|
||||
{
|
||||
long newtop;
|
||||
int i;
|
||||
|
||||
/* Which line are we talking about? */
|
||||
if (cnt < 0 || cnt > nlines)
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
if (cnt)
|
||||
{
|
||||
m = MARK_AT_LINE(cnt);
|
||||
newtop = cnt;
|
||||
}
|
||||
else
|
||||
{
|
||||
newtop = markline(m);
|
||||
}
|
||||
|
||||
/* allow a "window size" number to be entered */
|
||||
for (i = 0; key >= '0' && key <= '9'; key = getkey(0))
|
||||
{
|
||||
i = i * 10 + key - '0';
|
||||
}
|
||||
#ifndef CRUNCH
|
||||
if (i > 0 && i <= LINES - 1)
|
||||
{
|
||||
*o_window = i;
|
||||
wset = TRUE;
|
||||
}
|
||||
#else
|
||||
/* the number is ignored if -DCRUNCH */
|
||||
#endif
|
||||
|
||||
/* figure out which line will have to be at the top of the screen */
|
||||
switch (key)
|
||||
{
|
||||
case '\n':
|
||||
#if OSK
|
||||
case '\l':
|
||||
#else
|
||||
case '\r':
|
||||
#endif
|
||||
case '+':
|
||||
break;
|
||||
|
||||
case '.':
|
||||
case 'z':
|
||||
newtop -= LINES / 2;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
newtop -= LINES - 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
return MARK_UNSET;
|
||||
}
|
||||
|
||||
/* make the new topline take effect */
|
||||
redraw(MARK_UNSET, FALSE);
|
||||
if (newtop >= 1)
|
||||
{
|
||||
topline = newtop;
|
||||
}
|
||||
else
|
||||
{
|
||||
topline = 1L;
|
||||
}
|
||||
redrawrange(0L, INFINITY, INFINITY);
|
||||
|
||||
/* The cursor doesn't move */
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/* This function scrolls the screen. It does this by calling redraw() with
|
||||
* an off-screen line as the argument. It will move the cursor if necessary
|
||||
* so that the cursor is on the new screen.
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
MARK m_scroll(m, cnt, key)
|
||||
MARK m; /* the cursor position */
|
||||
long cnt; /* for some keys: the number of lines to scroll */
|
||||
int key; /* keystroke that causes this movement */
|
||||
{
|
||||
MARK tmp; /* a temporary mark, used as arg to redraw() */
|
||||
|
||||
/* adjust cnt, and maybe *o_scroll, depending of key */
|
||||
switch (key)
|
||||
{
|
||||
case ctrl('F'):
|
||||
case ctrl('B'):
|
||||
DEFAULT(1);
|
||||
redrawrange(0L, INFINITY, INFINITY); /* force complete redraw */
|
||||
cnt = cnt * (LINES - 1) - 2; /* keeps two old lines on screen */
|
||||
break;
|
||||
|
||||
case ctrl('E'):
|
||||
case ctrl('Y'):
|
||||
DEFAULT(1);
|
||||
break;
|
||||
|
||||
case ctrl('U'):
|
||||
case ctrl('D'):
|
||||
if (cnt == 0) /* default */
|
||||
{
|
||||
cnt = *o_scroll;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cnt > LINES - 1)
|
||||
{
|
||||
cnt = LINES - 1;
|
||||
}
|
||||
*o_scroll = cnt;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* scroll up or down, depending on key */
|
||||
switch (key)
|
||||
{
|
||||
case ctrl('B'):
|
||||
case ctrl('Y'):
|
||||
case ctrl('U'):
|
||||
cnt = topline - cnt;
|
||||
if (cnt < 1L)
|
||||
{
|
||||
cnt = 1L;
|
||||
m = MARK_FIRST;
|
||||
}
|
||||
tmp = MARK_AT_LINE(cnt) + markidx(m);
|
||||
redraw(tmp, FALSE);
|
||||
if (markline(m) > botline)
|
||||
{
|
||||
m = MARK_AT_LINE(botline);
|
||||
}
|
||||
break;
|
||||
|
||||
case ctrl('F'):
|
||||
case ctrl('E'):
|
||||
case ctrl('D'):
|
||||
cnt = botline + cnt;
|
||||
if (cnt > nlines)
|
||||
{
|
||||
cnt = nlines;
|
||||
m = MARK_LAST;
|
||||
}
|
||||
tmp = MARK_AT_LINE(cnt) + markidx(m);
|
||||
redraw(tmp, FALSE);
|
||||
if (markline(m) < topline)
|
||||
{
|
||||
m = MARK_AT_LINE(topline);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
|
@ -1,256 +0,0 @@
|
|||
/* move5.c */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* 14407 SW Teal Blvd. #C
|
||||
* Beaverton, OR 97005
|
||||
* kirkenda@cs.pdx.edu
|
||||
*/
|
||||
|
||||
|
||||
/* This file contains the word-oriented movement functions */
|
||||
|
||||
#include "config.h"
|
||||
#include "ctype.h"
|
||||
#include "vi.h"
|
||||
|
||||
MARK m_fword(m, cnt, cmd, prevkey)
|
||||
MARK m; /* movement is relative to this mark */
|
||||
long cnt; /* a numeric argument */
|
||||
int cmd; /* either 'w' or 'W' */
|
||||
int prevkey;/* previous command... if 'c' then exclude whitespace */
|
||||
{
|
||||
REG long l;
|
||||
REG char *text;
|
||||
REG int i;
|
||||
|
||||
DEFAULT(1);
|
||||
|
||||
l = markline(m);
|
||||
pfetch(l);
|
||||
text = ptext + markidx(m);
|
||||
|
||||
#ifndef CRUNCH
|
||||
/* As a special case, "cw" or "cW" on whitespace without a count
|
||||
* treats the single whitespace character under the cursor as a word.
|
||||
*/
|
||||
if (cnt == 1L && prevkey == 'c' && isspace(*text))
|
||||
{
|
||||
return m + 1L;
|
||||
}
|
||||
#endif
|
||||
|
||||
while (cnt-- > 0) /* yes, ASSIGNMENT! */
|
||||
{
|
||||
i = *text++;
|
||||
|
||||
if (cmd == 'W')
|
||||
{
|
||||
/* include any non-whitespace */
|
||||
while (i && !isspace(i))
|
||||
{
|
||||
i = *text++;
|
||||
}
|
||||
}
|
||||
else if (isalnum(i) || i == '_')
|
||||
{
|
||||
/* include an alphanumeric word */
|
||||
while (i && isalnum(i))
|
||||
{
|
||||
i = *text++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* include contiguous punctuation */
|
||||
while (i && !isalnum(i) && !isspace(i))
|
||||
{
|
||||
i = *text++;
|
||||
}
|
||||
}
|
||||
|
||||
/* if not part of "cw" or "cW" command... */
|
||||
if (prevkey != 'c' || cnt > 0)
|
||||
{
|
||||
/* include trailing whitespace */
|
||||
while (!i || isspace(i))
|
||||
{
|
||||
/* did we hit the end of this line? */
|
||||
if (!i)
|
||||
{
|
||||
/* "dw" shouldn't delete newline after word */
|
||||
if (prevkey && cnt == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* move to next line, if there is one */
|
||||
l++;
|
||||
if (l > nlines)
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
pfetch(l);
|
||||
text = ptext;
|
||||
}
|
||||
|
||||
i = *text++;
|
||||
}
|
||||
}
|
||||
text--;
|
||||
}
|
||||
|
||||
/* if argument to operator, then back off 1 char since "w" and "W"
|
||||
* include the last char in the affected text.
|
||||
*/
|
||||
if (prevkey)
|
||||
{
|
||||
text--;
|
||||
}
|
||||
|
||||
/* construct a MARK for this place */
|
||||
m = buildmark(text);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
MARK m_bword(m, cnt, cmd)
|
||||
MARK m; /* movement is relative to this mark */
|
||||
long cnt; /* a numeric argument */
|
||||
int cmd; /* either 'b' or 'B' */
|
||||
{
|
||||
REG long l;
|
||||
REG char *text;
|
||||
|
||||
DEFAULT(1);
|
||||
|
||||
l = markline(m);
|
||||
pfetch(l);
|
||||
text = ptext + markidx(m);
|
||||
while (cnt-- > 0) /* yes, ASSIGNMENT! */
|
||||
{
|
||||
text--;
|
||||
|
||||
/* include preceding whitespace */
|
||||
while (text < ptext || isspace(*text))
|
||||
{
|
||||
/* did we hit the end of this line? */
|
||||
if (text < ptext)
|
||||
{
|
||||
/* move to preceding line, if there is one */
|
||||
l--;
|
||||
if (l <= 0)
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
pfetch(l);
|
||||
text = ptext + plen - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
text--;
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd == 'B')
|
||||
{
|
||||
/* include any non-whitespace */
|
||||
while (text >= ptext && !isspace(*text))
|
||||
{
|
||||
text--;
|
||||
}
|
||||
}
|
||||
else if (isalnum(*text) || *text == '_')
|
||||
{
|
||||
/* include an alphanumeric word */
|
||||
while (text >= ptext && isalnum(*text))
|
||||
{
|
||||
text--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* include contiguous punctuation */
|
||||
while (text >= ptext && !isalnum(*text) && !isspace(*text))
|
||||
{
|
||||
text--;
|
||||
}
|
||||
}
|
||||
text++;
|
||||
}
|
||||
|
||||
/* construct a MARK for this place */
|
||||
m = buildmark(text);
|
||||
return m;
|
||||
}
|
||||
|
||||
MARK m_eword(m, cnt, cmd)
|
||||
MARK m; /* movement is relative to this mark */
|
||||
long cnt; /* a numeric argument */
|
||||
int cmd; /* either 'e' or 'E' */
|
||||
{
|
||||
REG long l;
|
||||
REG char *text;
|
||||
REG int i;
|
||||
|
||||
DEFAULT(1);
|
||||
|
||||
l = markline(m);
|
||||
pfetch(l);
|
||||
text = ptext + markidx(m);
|
||||
while (cnt-- > 0) /* yes, ASSIGNMENT! */
|
||||
{
|
||||
if (*text)
|
||||
text++;
|
||||
i = *text++;
|
||||
|
||||
/* include preceding whitespace */
|
||||
while (!i || isspace(i))
|
||||
{
|
||||
/* did we hit the end of this line? */
|
||||
if (!i)
|
||||
{
|
||||
/* move to next line, if there is one */
|
||||
l++;
|
||||
if (l > nlines)
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
pfetch(l);
|
||||
text = ptext;
|
||||
}
|
||||
|
||||
i = *text++;
|
||||
}
|
||||
|
||||
if (cmd == 'E')
|
||||
{
|
||||
/* include any non-whitespace */
|
||||
while (i && !isspace(i))
|
||||
{
|
||||
i = *text++;
|
||||
}
|
||||
}
|
||||
else if (isalnum(i) || i == '_')
|
||||
{
|
||||
/* include an alphanumeric word */
|
||||
while (i && isalnum(i))
|
||||
{
|
||||
i = *text++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* include contiguous punctuation */
|
||||
while (i && !isalnum(i) && !isspace(i))
|
||||
{
|
||||
i = *text++;
|
||||
}
|
||||
}
|
||||
text -= 2;
|
||||
}
|
||||
|
||||
/* construct a MARK for this place */
|
||||
m = buildmark(text);
|
||||
return m;
|
||||
}
|
|
@ -1,795 +0,0 @@
|
|||
/* opts.c */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* 14407 SW Teal Blvd. #C
|
||||
* Beaverton, OR 97005
|
||||
* kirkenda@cs.pdx.edu
|
||||
*/
|
||||
|
||||
|
||||
/* This file contains the code that manages the run-time options -- The
|
||||
* values that can be modified via the "set" command.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "vi.h"
|
||||
#include "ctype.h"
|
||||
#include <sys/null.h>
|
||||
extern char *getenv();
|
||||
|
||||
/* maximum width to permit for strings, including ="" */
|
||||
#define MAXWIDTH 20
|
||||
|
||||
/* These are the default values of all options */
|
||||
char o_autoindent[1] = {FALSE};
|
||||
char o_autoprint[1] = {TRUE};
|
||||
char o_autotab[1] = {TRUE};
|
||||
char o_autowrite[1] = {FALSE};
|
||||
char o_columns[3] = {80, 32, 255};
|
||||
char o_directory[30] = TMPDIR;
|
||||
char o_edcompatible[1] = {FALSE};
|
||||
char o_equalprg[80] = {"fmt"};
|
||||
char o_errorbells[1] = {TRUE};
|
||||
char o_exrefresh[1] = {TRUE};
|
||||
char o_ignorecase[1] = {FALSE};
|
||||
char o_keytime[3] = {1, 0, 50};
|
||||
char o_keywordprg[80] = {KEYWORDPRG};
|
||||
char o_lines[3] = {25, 2, 96};
|
||||
char o_list[1] = {FALSE};
|
||||
char o_number[1] = {FALSE};
|
||||
char o_readonly[1] = {FALSE};
|
||||
char o_remap[1] = {TRUE};
|
||||
char o_report[3] = {5, 1, 127};
|
||||
char o_scroll[3] = {12, 1, 127};
|
||||
char o_shell[60] = SHELL;
|
||||
char o_shiftwidth[3] = {8, 1, 255};
|
||||
char o_sidescroll[3] = {8, 1, 40};
|
||||
char o_sync[1] = {NEEDSYNC};
|
||||
char o_tabstop[3] = {8, 1, 40};
|
||||
char o_term[30] = "?";
|
||||
char o_flash[1] = {TRUE};
|
||||
char o_warn[1] = {TRUE};
|
||||
char o_wrapscan[1] = {TRUE};
|
||||
|
||||
#ifndef CRUNCH
|
||||
char o_beautify[1] = {FALSE};
|
||||
char o_exrc[1] = {FALSE};
|
||||
char o_mesg[1] = {TRUE};
|
||||
char o_more[1] = {TRUE};
|
||||
char o_novice[1] = {FALSE};
|
||||
char o_prompt[1] = {TRUE};
|
||||
char o_taglength[3] = {0, 0, 30};
|
||||
char o_terse[1] = {FALSE};
|
||||
char o_window[3] = {0, 1, 24};
|
||||
char o_wrapmargin[3] = {0, 0, 255};
|
||||
char o_writeany[1] = {FALSE};
|
||||
#endif
|
||||
|
||||
#ifndef NO_ERRLIST
|
||||
char o_cc[30] = {CC_COMMAND};
|
||||
char o_make[30] = {MAKE_COMMAND};
|
||||
#endif
|
||||
|
||||
#ifndef NO_CHARATTR
|
||||
char o_charattr[1] = {FALSE};
|
||||
#endif
|
||||
|
||||
#ifndef NO_DIGRAPH
|
||||
char o_digraph[1] = {FALSE};
|
||||
char o_flipcase[80]
|
||||
# ifdef CS_IBMPC
|
||||
= {"\207\200\201\232\202\220\204\216\206\217\221\222\224\231\244\245"}
|
||||
# endif
|
||||
# ifdef CS_LATIN1
|
||||
/* initialized by initopts() */
|
||||
# endif
|
||||
;
|
||||
#endif
|
||||
|
||||
#ifndef NO_SENTENCE
|
||||
char o_hideformat[1] = {FALSE};
|
||||
#endif
|
||||
|
||||
#ifndef NO_EXTENSIONS
|
||||
char o_inputmode[1] = {FALSE};
|
||||
char o_ruler[1] = {FALSE};
|
||||
#endif
|
||||
|
||||
#ifndef NO_MAGIC
|
||||
char o_magic[1] = {TRUE};
|
||||
#endif
|
||||
|
||||
#ifndef NO_MODELINES
|
||||
char o_modelines[1] = {FALSE};
|
||||
#endif
|
||||
|
||||
#ifndef NO_SENTENCE
|
||||
char o_paragraphs[30] = "PPppIPLPQP";
|
||||
char o_sections[30] = "NHSHSSSEse";
|
||||
#endif
|
||||
|
||||
#if MSDOS
|
||||
char o_pcbios[1] = {TRUE};
|
||||
#endif
|
||||
|
||||
#ifndef NO_SHOWMATCH
|
||||
char o_showmatch[1] = {FALSE};
|
||||
#endif
|
||||
|
||||
#ifndef NO_SHOWMODE
|
||||
char o_smd[1] = {FALSE};
|
||||
#endif
|
||||
|
||||
|
||||
/* The following describes the names & types of all options */
|
||||
#define BOOL 0
|
||||
#define NUM 1
|
||||
#define STR 2
|
||||
#define SET 0x01 /* this option has had its value altered */
|
||||
#define CANSET 0x02 /* this option can be set at any time */
|
||||
#define RCSET 0x06 /* this option can be set in a .exrc file only */
|
||||
#define NOSAVE 0x0a /* this option should never be saved by mkexrc */
|
||||
#define WSET 0x20 /* is this the "window" size option? */
|
||||
#define MR 0x40 /* does this option affect the way text is displayed? */
|
||||
struct
|
||||
{
|
||||
char *name; /* name of an option */
|
||||
char *nm; /* short name of an option */
|
||||
char type; /* type of an option */
|
||||
char flags; /* boolean: has this option been set? */
|
||||
char *value; /* value */
|
||||
}
|
||||
opts[] =
|
||||
{
|
||||
/* name type flags value */
|
||||
{ "autoindent", "ai", BOOL, CANSET, o_autoindent },
|
||||
{ "autoprint", "ap", BOOL, CANSET, o_autoprint },
|
||||
{ "autotab", "at", BOOL, CANSET, o_autotab },
|
||||
{ "autowrite", "aw", BOOL, CANSET, o_autowrite },
|
||||
#ifndef CRUNCH
|
||||
{ "beautify", "bf", BOOL, CANSET, o_beautify },
|
||||
#endif
|
||||
#ifndef NO_ERRLIST
|
||||
{ "cc", "cc", STR, CANSET, o_cc },
|
||||
#endif
|
||||
#ifndef NO_CHARATTR
|
||||
{ "charattr", "ca", BOOL, CANSET|MR, o_charattr },
|
||||
#endif
|
||||
{ "columns", "co", NUM, SET|NOSAVE|MR, o_columns },
|
||||
#ifndef NO_DIGRAPH
|
||||
{ "digraph", "dig", BOOL, CANSET, o_digraph },
|
||||
#endif
|
||||
{ "directory", "dir", STR, RCSET, o_directory },
|
||||
{ "edcompatible","ed", BOOL, CANSET, o_edcompatible },
|
||||
{ "equalprg", "ep", STR, CANSET, o_equalprg },
|
||||
{ "errorbells", "eb", BOOL, CANSET, o_errorbells },
|
||||
#ifndef CRUNCH
|
||||
{ "exrc", "exrc", BOOL, CANSET, o_exrc },
|
||||
#endif
|
||||
{ "exrefresh", "er", BOOL, CANSET, o_exrefresh },
|
||||
{ "flash", "vbell",BOOL, CANSET, o_flash },
|
||||
#ifndef NO_DIGRAPH
|
||||
{ "flipcase", "fc", STR, CANSET, o_flipcase },
|
||||
#endif
|
||||
#ifndef NO_SENTENCE
|
||||
{ "hideformat", "hf", BOOL, CANSET|MR, o_hideformat },
|
||||
#endif
|
||||
{ "ignorecase", "ic", BOOL, CANSET, o_ignorecase },
|
||||
#ifndef NO_EXTENSIONS
|
||||
{ "inputmode", "im", BOOL, CANSET, o_inputmode },
|
||||
#endif
|
||||
{ "keytime", "kt", NUM, CANSET, o_keytime },
|
||||
{ "keywordprg", "kp", STR, CANSET, o_keywordprg },
|
||||
{ "lines", "ls", NUM, SET|NOSAVE|MR, o_lines },
|
||||
{ "list", "li", BOOL, CANSET|MR, o_list },
|
||||
#ifndef NO_MAGIC
|
||||
{ "magic", "ma", BOOL, CANSET, o_magic },
|
||||
#endif
|
||||
#ifndef NO_ERRLIST
|
||||
{ "make", "mk", STR, CANSET, o_make },
|
||||
#endif
|
||||
#ifndef CRUNCH
|
||||
{ "mesg", "me", BOOL, CANSET, o_mesg },
|
||||
#endif
|
||||
#ifndef NO_MODELINES
|
||||
{ "modelines", "ml", BOOL, CANSET, o_modelines },
|
||||
#endif
|
||||
#ifndef CRUNCH
|
||||
{ "more", "mo", BOOL, CANSET, o_more },
|
||||
{ "novice", "nov", BOOL, CANSET, o_novice },
|
||||
#endif
|
||||
{ "number", "nu", BOOL, CANSET|MR, o_number },
|
||||
#ifndef NO_SENTENCE
|
||||
{ "paragraphs", "para", STR, CANSET, o_paragraphs },
|
||||
#endif
|
||||
#if MSDOS
|
||||
{ "pcbios", "pc", BOOL, SET|NOSAVE, o_pcbios },
|
||||
#endif
|
||||
#ifndef CRUNCH
|
||||
{ "prompt", "pr", BOOL, CANSET, o_prompt },
|
||||
#endif
|
||||
{ "readonly", "ro", BOOL, CANSET, o_readonly },
|
||||
{ "remap", "remap",BOOL, CANSET, o_remap },
|
||||
{ "report", "re", NUM, CANSET, o_report },
|
||||
#ifndef NO_EXTENSIONS
|
||||
{ "ruler", "ru", BOOL, CANSET, o_ruler },
|
||||
#endif
|
||||
{ "scroll", "sc", NUM, CANSET, o_scroll },
|
||||
#ifndef NO_SENTENCE
|
||||
{ "sections", "sect", STR, CANSET, o_sections },
|
||||
#endif
|
||||
{ "shell", "sh", STR, CANSET, o_shell },
|
||||
#ifndef NO_SHOWMATCH
|
||||
{ "showmatch", "sm", BOOL, CANSET, o_showmatch },
|
||||
#endif
|
||||
#ifndef NO_SHOWMODE
|
||||
{ "showmode", "smd", BOOL, CANSET, o_smd },
|
||||
#endif
|
||||
{ "shiftwidth", "sw", NUM, CANSET, o_shiftwidth },
|
||||
{ "sidescroll", "ss", NUM, CANSET, o_sidescroll },
|
||||
{ "sync", "sy", BOOL, CANSET, o_sync },
|
||||
{ "tabstop", "ts", NUM, CANSET|MR, o_tabstop },
|
||||
#ifndef CRUNCH
|
||||
{ "taglength", "tl", NUM, CANSET, o_taglength },
|
||||
#endif
|
||||
{ "term", "te", STR, SET, o_term },
|
||||
#ifndef CRUNCH
|
||||
{ "terse", "tr", BOOL, CANSET, o_terse },
|
||||
{ "timeout", "to", BOOL, CANSET, o_keytime },
|
||||
#endif
|
||||
#ifndef CRUNCH
|
||||
{ "window", "wi", NUM, CANSET|MR|WSET, o_window },
|
||||
{ "wrapmargin", "wm", NUM, CANSET, o_wrapmargin },
|
||||
#endif
|
||||
{ "wrapscan", "ws", BOOL, CANSET, o_wrapscan },
|
||||
#ifndef CRUNCH
|
||||
{ "writeany", "wr", BOOL, CANSET, o_writeany },
|
||||
#endif
|
||||
{ NULL, NULL, 0, CANSET, NULL }
|
||||
};
|
||||
|
||||
|
||||
/* This function initializes certain options from environment variables, etc. */
|
||||
void initopts()
|
||||
{
|
||||
char *val;
|
||||
int i;
|
||||
|
||||
/* set some stuff from environment variables */
|
||||
#if MSDOS
|
||||
if (val = getenv("COMSPEC")) /* yes, ASSIGNMENT! */
|
||||
#else
|
||||
if (val = getenv("SHELL")) /* yes, ASSIGNMENT! */
|
||||
#endif
|
||||
{
|
||||
strcpy(o_shell, val);
|
||||
}
|
||||
|
||||
strcpy(o_term, termtype);
|
||||
#if MSDOS
|
||||
if (strcmp(termtype, "pcbios"))
|
||||
{
|
||||
o_pcbios[0] = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
o_pcbios[0] = TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if AMIGA || MSDOS || TOS
|
||||
if ((val = getenv("TMP")) /* yes, ASSIGNMENT! */
|
||||
|| (val = getenv("TEMP")))
|
||||
strcpy(o_directory, val);
|
||||
#endif
|
||||
|
||||
#ifndef CRUNCH
|
||||
if ((val = getenv("LINES")) && atoi(val) > 4) /* yes, ASSIGNMENT! */
|
||||
{
|
||||
LINES = atoi(val);
|
||||
}
|
||||
if ((val = getenv("COLUMNS")) && atoi(val) > 30) /* yes, ASSIGNMENT! */
|
||||
{
|
||||
COLS = atoi(val);
|
||||
}
|
||||
#endif
|
||||
*o_lines = LINES;
|
||||
*o_columns = COLS;
|
||||
*o_scroll = LINES / 2 - 1;
|
||||
#ifndef CRUNCH
|
||||
if (o_window[0] == 0)
|
||||
{
|
||||
o_window[0] = o_window[2] = *o_lines;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* disable the flash option if we don't know how to do a flash */
|
||||
if (!has_VB)
|
||||
{
|
||||
for (i = 0; opts[i].value != o_flash; i++)
|
||||
{
|
||||
}
|
||||
opts[i].flags &= ~CANSET;
|
||||
*o_flash = FALSE;
|
||||
}
|
||||
|
||||
#ifndef NO_DIGRAPH
|
||||
# ifdef CS_LATIN1
|
||||
for (i = 0, val = o_flipcase; i < 32; i++)
|
||||
{
|
||||
/* leave out the multiply/divide symbols */
|
||||
if (i == 23)
|
||||
continue;
|
||||
|
||||
/* add lower/uppercase pair */
|
||||
*val++ = i + 0xe0;
|
||||
*val++ = i + 0xc0;
|
||||
}
|
||||
*val = '\0';
|
||||
# endif /* CS_LATIN1 */
|
||||
|
||||
/* initialize the ctype package */
|
||||
_ct_init(o_flipcase);
|
||||
#else
|
||||
_ct_init("");
|
||||
#endif /* not NO_DIGRAPH */
|
||||
}
|
||||
|
||||
/* This function lists the current values of all options */
|
||||
void dumpopts(all)
|
||||
int all; /* boolean: dump all options, or just set ones? */
|
||||
{
|
||||
#ifndef NO_OPTCOLS
|
||||
int i, j, k;
|
||||
char nbuf[4]; /* used for converting numbers to ASCII */
|
||||
int widths[5]; /* width of each column, including gap */
|
||||
int ncols; /* number of columns */
|
||||
int nrows; /* number of options per column */
|
||||
int nset; /* number of options to be output */
|
||||
int width; /* width of a particular option */
|
||||
int todump[60]; /* indicies of options to be dumped */
|
||||
|
||||
/* step 1: count the number of set options */
|
||||
for (nset = i = 0; opts[i].name; i++)
|
||||
{
|
||||
if (all || (opts[i].flags & SET))
|
||||
{
|
||||
todump[nset++] = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* step two: try to use as many columns as possible */
|
||||
for (ncols = (nset > 5 ? 5 : nset); ncols > 1; ncols--)
|
||||
{
|
||||
/* how many would go in this column? */
|
||||
nrows = (nset + ncols - 1) / ncols;
|
||||
|
||||
/* figure out the width of each column */
|
||||
for (i = 0; i < ncols; i++)
|
||||
{
|
||||
widths[i] = 0;
|
||||
for (j = 0, k = nrows * i; j < nrows && k < nset; j++, k++)
|
||||
{
|
||||
/* figure out the width of a particular option */
|
||||
switch (opts[todump[k]].type)
|
||||
{
|
||||
case BOOL:
|
||||
if (!*opts[todump[k]].value)
|
||||
width = 2;
|
||||
else
|
||||
width = 0;
|
||||
break;
|
||||
|
||||
case STR:
|
||||
width = 3 + strlen(opts[todump[k]].value);
|
||||
if (width > MAXWIDTH)
|
||||
width = MAXWIDTH;
|
||||
break;
|
||||
|
||||
case NUM:
|
||||
width = 4;
|
||||
break;
|
||||
}
|
||||
width += strlen(opts[todump[k]].name);
|
||||
|
||||
/* if this is the widest so far, widen col */
|
||||
if (width > widths[i])
|
||||
{
|
||||
widths[i] = width;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* if the total width is narrow enough, then use it */
|
||||
for (width = -2, i = 0; i < ncols; i++)
|
||||
{
|
||||
width += widths[i] + 2;
|
||||
}
|
||||
if (width < COLS - 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* step 3: output the columns */
|
||||
nrows = (nset + ncols - 1) / ncols;
|
||||
for (i = 0; i < nrows; i++)
|
||||
{
|
||||
for (j = 0; j < ncols; j++)
|
||||
{
|
||||
/* if we hit the end of the options, quit */
|
||||
k = i + j * nrows;
|
||||
if (k >= nset)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* output this option's value */
|
||||
width = 0;
|
||||
switch (opts[todump[k]].type)
|
||||
{
|
||||
case BOOL:
|
||||
if (!*opts[todump[k]].value)
|
||||
{
|
||||
qaddch('n');
|
||||
qaddch('o');
|
||||
width = 2;
|
||||
}
|
||||
qaddstr(opts[todump[k]].name);
|
||||
width += strlen(opts[todump[k]].name);
|
||||
break;
|
||||
|
||||
case NUM:
|
||||
sprintf(nbuf, "%-3d", UCHAR(*opts[todump[k]].value));
|
||||
qaddstr(opts[todump[k]].name);
|
||||
qaddch('=');
|
||||
qaddstr(nbuf);
|
||||
width = 4 + strlen(opts[todump[k]].name);
|
||||
break;
|
||||
|
||||
case STR:
|
||||
qaddstr(opts[todump[k]].name);
|
||||
qaddch('=');
|
||||
qaddch('"');
|
||||
strcpy(tmpblk.c, opts[todump[k]].value);
|
||||
width = 3 + strlen(tmpblk.c);
|
||||
if (width > MAXWIDTH)
|
||||
{
|
||||
width = MAXWIDTH;
|
||||
strcpy(tmpblk.c + MAXWIDTH - 6, "...");
|
||||
}
|
||||
qaddstr(tmpblk.c);
|
||||
qaddch('"');
|
||||
width += strlen(opts[todump[k]].name);
|
||||
break;
|
||||
}
|
||||
|
||||
/* pad the field to the correct size */
|
||||
if (k + nrows <= nset)
|
||||
{
|
||||
while (width < widths[j] + 2)
|
||||
{
|
||||
qaddch(' ');
|
||||
width++;
|
||||
}
|
||||
}
|
||||
}
|
||||
addch('\n');
|
||||
exrefresh();
|
||||
}
|
||||
#else
|
||||
int i;
|
||||
int col;
|
||||
char nbuf[4];
|
||||
|
||||
for (i = col = 0; opts[i].name; i++)
|
||||
{
|
||||
/* if not set and not all, ignore this option */
|
||||
if (!all && !(opts[i].flags & SET))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* align this option in one of the columns */
|
||||
if (col > 52)
|
||||
{
|
||||
addch('\n');
|
||||
col = 0;
|
||||
}
|
||||
else if (col > 26)
|
||||
{
|
||||
while (col < 52)
|
||||
{
|
||||
qaddch(' ');
|
||||
col++;
|
||||
}
|
||||
}
|
||||
else if (col > 0)
|
||||
{
|
||||
while (col < 26)
|
||||
{
|
||||
qaddch(' ');
|
||||
col++;
|
||||
}
|
||||
}
|
||||
|
||||
switch (opts[i].type)
|
||||
{
|
||||
case BOOL:
|
||||
if (!*opts[i].value)
|
||||
{
|
||||
qaddch('n');
|
||||
qaddch('o');
|
||||
col += 2;
|
||||
}
|
||||
qaddstr(opts[i].name);
|
||||
col += strlen(opts[i].name);
|
||||
break;
|
||||
|
||||
case NUM:
|
||||
sprintf(nbuf, "%-3d", UCHAR(*opts[i].value));
|
||||
qaddstr(opts[i].name);
|
||||
qaddch('=');
|
||||
qaddstr(nbuf);
|
||||
col += 4 + strlen(opts[i].name);
|
||||
break;
|
||||
|
||||
case STR:
|
||||
qaddstr(opts[i].name);
|
||||
qaddch('=');
|
||||
qaddch('"');
|
||||
qaddstr(opts[i].value);
|
||||
qaddch('"');
|
||||
col += 3 + strlen(opts[i].name) + strlen(opts[i].value);
|
||||
break;
|
||||
}
|
||||
exrefresh();
|
||||
}
|
||||
if (col > 0)
|
||||
{
|
||||
addch('\n');
|
||||
exrefresh();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NO_MKEXRC
|
||||
/* This function saves the current configuration of options to a file */
|
||||
void saveopts(fd)
|
||||
int fd; /* file descriptor to write to */
|
||||
{
|
||||
int i;
|
||||
char buf[256], *pos;
|
||||
|
||||
/* write each set options */
|
||||
for (i = 0; opts[i].name; i++)
|
||||
{
|
||||
/* if unset or unsettable, ignore this option */
|
||||
if ((opts[i].flags & (SET|CANSET|NOSAVE)) != (SET|CANSET))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
strcpy(buf, "set ");
|
||||
pos = &buf[4];
|
||||
switch (opts[i].type)
|
||||
{
|
||||
case BOOL:
|
||||
if (!*opts[i].value)
|
||||
{
|
||||
*pos++='n';
|
||||
*pos++='o';
|
||||
}
|
||||
strcpy(pos, opts[i].name);
|
||||
strcat(pos, "\n");
|
||||
break;
|
||||
|
||||
case NUM:
|
||||
sprintf(pos, "%s=%-3d\n", opts[i].name, *opts[i].value & 0xff);
|
||||
break;
|
||||
|
||||
case STR:
|
||||
sprintf(pos, "%s=\"%s\"\n", opts[i].name, opts[i].value);
|
||||
break;
|
||||
}
|
||||
twrite(fd, buf, (unsigned)strlen(buf));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* This function changes the values of one or more options. */
|
||||
void setopts(assignments)
|
||||
char *assignments; /* a string containing option assignments */
|
||||
{
|
||||
char *name; /* name of variable in assignments */
|
||||
char *value; /* value of the variable */
|
||||
char *scan; /* used for moving through strings */
|
||||
char *build; /* used for copying chars from "scan" */
|
||||
char *prefix; /* pointer to "neg" or "no" at front of a boolean */
|
||||
int quote; /* boolean: inside '"' quotes? */
|
||||
int i, j;
|
||||
|
||||
#ifndef CRUNCH
|
||||
/* reset the upper limit of "window" option to lines-1 */
|
||||
*o_window = *o_lines - 1;
|
||||
#endif
|
||||
|
||||
/* for each assignment... */
|
||||
for (name = assignments; *name; )
|
||||
{
|
||||
/* skip whitespace */
|
||||
if (*name == ' ' || *name == '\t')
|
||||
{
|
||||
name++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* after the name, find the value (if any) */
|
||||
for (scan = name; isalnum(*scan); scan++)
|
||||
{
|
||||
}
|
||||
if (*scan == '=')
|
||||
{
|
||||
*scan++ = '\0';
|
||||
value = build = scan;
|
||||
for (quote = FALSE; *scan && (quote || !isspace(*scan)); scan++)
|
||||
{
|
||||
if (*scan == '"')
|
||||
{
|
||||
quote = !quote;
|
||||
}
|
||||
else if (*scan == '\\' && scan[1])
|
||||
{
|
||||
*build++ = *++scan;
|
||||
}
|
||||
else
|
||||
{
|
||||
*build++ = *scan;
|
||||
}
|
||||
}
|
||||
if (*scan)
|
||||
scan++;
|
||||
*build = '\0';
|
||||
}
|
||||
else /* no "=" so it is probably boolean... */
|
||||
{
|
||||
if (*scan)
|
||||
{
|
||||
*scan++ = '\0';
|
||||
}
|
||||
value = NULL;
|
||||
prefix = name;
|
||||
#ifndef CRUNCH
|
||||
if (!strcmp(name, "novice"))
|
||||
/* don't check for a "no" prefix */;
|
||||
else
|
||||
#endif
|
||||
if (prefix[0] == 'n' && prefix[1] == 'o')
|
||||
name += 2;
|
||||
else if (prefix[0] == 'n' && prefix[1] == 'e' && prefix[2] == 'g')
|
||||
name += 3;
|
||||
}
|
||||
|
||||
/* find the variable */
|
||||
for (i = 0;
|
||||
opts[i].name && strcmp(opts[i].name, name) && strcmp(opts[i].nm, name);
|
||||
i++)
|
||||
{
|
||||
}
|
||||
|
||||
/* change the variable */
|
||||
if (!opts[i].name)
|
||||
{
|
||||
msg("invalid option name \"%s\"", name);
|
||||
}
|
||||
else if ((opts[i].flags & CANSET) != CANSET)
|
||||
{
|
||||
msg("option \"%s\" can't be altered", name);
|
||||
}
|
||||
else if ((opts[i].flags & RCSET) != CANSET && nlines >= 1L)
|
||||
{
|
||||
msg("option \"%s\" can only be set in a %s file", name, EXRC);
|
||||
}
|
||||
else if (value)
|
||||
{
|
||||
switch (opts[i].type)
|
||||
{
|
||||
case BOOL:
|
||||
msg("option \"[no]%s\" is boolean", name);
|
||||
break;
|
||||
|
||||
case NUM:
|
||||
j = atoi(value);
|
||||
if (j == 0 && *value != '0')
|
||||
{
|
||||
msg("option \"%s\" must have a numeric value", name);
|
||||
}
|
||||
else if (j < opts[i].value[1] || j > (opts[i].value[2] & 0xff))
|
||||
{
|
||||
msg("option \"%s\" must have a value between %d and %d",
|
||||
name, opts[i].value[1], opts[i].value[2] & 0xff);
|
||||
}
|
||||
else
|
||||
{
|
||||
*opts[i].value = atoi(value);
|
||||
opts[i].flags |= SET;
|
||||
}
|
||||
break;
|
||||
|
||||
case STR:
|
||||
strcpy(opts[i].value, value);
|
||||
opts[i].flags |= SET;
|
||||
break;
|
||||
}
|
||||
if (opts[i].flags & MR)
|
||||
{
|
||||
redraw(MARK_UNSET, FALSE);
|
||||
}
|
||||
#ifndef CRUNCH
|
||||
if (opts[i].flags & WSET)
|
||||
{
|
||||
wset = TRUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else /* valid option, no value */
|
||||
{
|
||||
if (opts[i].type == BOOL)
|
||||
{
|
||||
if (prefix == name)
|
||||
*opts[i].value = TRUE;
|
||||
else if (prefix[1] == 'o')
|
||||
*opts[i].value = FALSE;
|
||||
else
|
||||
*opts[i].value = !*opts[i].value;
|
||||
|
||||
opts[i].flags |= SET;
|
||||
if (opts[i].flags & MR)
|
||||
{
|
||||
redraw(MARK_UNSET, FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
msg("option \"%s\" must be given a value", name);
|
||||
}
|
||||
}
|
||||
|
||||
/* move on to the next option */
|
||||
name = scan;
|
||||
}
|
||||
|
||||
/* special processing ... */
|
||||
|
||||
#ifndef CRUNCH
|
||||
/* if "novice" is set, then ":set report=1 showmode nomagic" */
|
||||
if (*o_novice)
|
||||
{
|
||||
*o_report = 1;
|
||||
# ifndef NO_SHOWMODE
|
||||
*o_smd = TRUE;
|
||||
# endif
|
||||
# ifndef NO_MAGIC
|
||||
*o_magic = FALSE;
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* if "readonly" then set the READONLY flag for this file */
|
||||
if (*o_readonly)
|
||||
{
|
||||
setflag(file, READONLY);
|
||||
}
|
||||
|
||||
#ifndef NO_DIGRAPH
|
||||
/* re-initialize the ctype package */
|
||||
_ct_init(o_flipcase);
|
||||
#endif /* not NO_DIGRAPH */
|
||||
|
||||
/* copy o_lines and o_columns into LINES and COLS */
|
||||
LINES = (*o_lines & 255);
|
||||
COLS = (*o_columns & 255);
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
/* prsvunix.c */
|
||||
|
||||
/* This file contains the UNIX-specific parts of the "elvprsv" program. */
|
||||
|
||||
#if OSK
|
||||
#define ELVPRSV
|
||||
#include "osk.c"
|
||||
#else
|
||||
#include <sys/stat.h>
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
|
||||
/* This variable is used to add extra error messages for mail sent to root */
|
||||
char *ps;
|
||||
|
||||
/* This function returns the login name of the owner of a file */
|
||||
char *ownername(filename)
|
||||
char *filename; /* name of a file */
|
||||
{
|
||||
struct stat st;
|
||||
struct passwd *pw;
|
||||
|
||||
/* stat the file, to get its uid */
|
||||
if (stat(filename, &st) < 0)
|
||||
{
|
||||
ps = "stat() failed";
|
||||
return "root";
|
||||
}
|
||||
|
||||
/* get the /etc/passwd entry for that user */
|
||||
pw = getpwuid(st.st_uid);
|
||||
if (!pw)
|
||||
{
|
||||
ps = "uid not found in password file";
|
||||
return "root";
|
||||
}
|
||||
|
||||
/* return the user's name */
|
||||
return pw->pw_name;
|
||||
}
|
||||
|
||||
|
||||
/* This function sends a mail message to a given user, saying that a file
|
||||
* has been preserved.
|
||||
*/
|
||||
void mail(user, file, when)
|
||||
char *user; /* name of user who should receive the mail */
|
||||
char *file; /* name of original text file that was preserved */
|
||||
char *when; /* description of why the file was preserved */
|
||||
{
|
||||
char cmd[80];/* buffer used for constructing a "mail" command */
|
||||
FILE *m, *popen(); /* stream used for giving text to the "mail" program */
|
||||
char *base; /* basename of the file */
|
||||
|
||||
/* separate the directory name from the basename. */
|
||||
for (base = file + strlen(file); --base > file && *base != SLASH; )
|
||||
{
|
||||
}
|
||||
if (*base == SLASH)
|
||||
{
|
||||
*base++ = '\0';
|
||||
}
|
||||
|
||||
/* for anonymous buffers, pretend the name was "foo" */
|
||||
if (!strcmp(base, "*"))
|
||||
{
|
||||
base = "foo";
|
||||
}
|
||||
|
||||
/* open a pipe to the "mail" program */
|
||||
#if OSK
|
||||
sprintf(cmd, "mail \"-s=%s preserved!\" %s", base, user);
|
||||
#else /* ANY_UNIX */
|
||||
sprintf(cmd, "mail %s >/dev/null 2>/dev/null", user);
|
||||
#endif
|
||||
m = popen(cmd, "w");
|
||||
if (!m)
|
||||
{
|
||||
/* Can't send mail! Hope the user figures it out. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Tell the user that the file was preserved */
|
||||
fprintf(m, "A version of your file \"%s%c%s\"\n", file, SLASH, base);
|
||||
fprintf(m, "was preserved when %s.\n", when);
|
||||
fprintf(m, "To recover this file, do the following:\n");
|
||||
fprintf(m, "\n");
|
||||
#if OSK
|
||||
fprintf(m, " chd %s\n", file);
|
||||
#else /* ANY_UNIX */
|
||||
fprintf(m, " cd %s\n", file);
|
||||
#endif
|
||||
fprintf(m, " elvrec %s\n", base);
|
||||
fprintf(m, "\n");
|
||||
fprintf(m, "With fond wishes for a speedy recovery,\n");
|
||||
fprintf(m, " Elvis\n");
|
||||
if (ps)
|
||||
{
|
||||
fprintf(m, "\nP.S. %s\n", ps);
|
||||
ps = (char *)0;
|
||||
}
|
||||
|
||||
/* close the stream */
|
||||
pclose(m);
|
||||
}
|
|
@ -1,183 +0,0 @@
|
|||
/* recycle.c */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* 14407 SW Teal Blvd. #C
|
||||
* Beaverton, OR 97005
|
||||
* kirkenda@cs.pdx.edu
|
||||
*/
|
||||
|
||||
|
||||
/* This file contains the functions perform garbage collection and allocate
|
||||
* reusable blocks.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "vi.h"
|
||||
|
||||
#ifndef NO_RECYCLE
|
||||
/* this whole file would have be skipped if NO_RECYCLE is defined */
|
||||
|
||||
|
||||
#define BTST(bitno, byte) ((byte) & (1 << (bitno)))
|
||||
#define BSET(bitno, byte) ((byte) |= (1 << (bitno)))
|
||||
#define BCLR(bitno, byte) ((byte) &= ~(1 << (bitno)))
|
||||
|
||||
#define TST(blkno) ((blkno) < MAXBIT ? BTST((blkno) & 7, bitmap[(blkno) >> 3]) : 1)
|
||||
#define SET(blkno) if ((blkno) < MAXBIT) BSET((blkno) & 7, bitmap[(blkno) >> 3])
|
||||
#define CLR(blkno) if ((blkno) < MAXBIT) BCLR((blkno) & 7, bitmap[(blkno) >> 3])
|
||||
|
||||
/* bitmap of free blocks in first 4096k of tmp file */
|
||||
static unsigned char bitmap[512];
|
||||
#define MAXBIT (sizeof bitmap << 3)
|
||||
|
||||
/* this function locates all free blocks in the current tmp file */
|
||||
void garbage()
|
||||
{
|
||||
int i;
|
||||
BLK oldhdr;
|
||||
|
||||
/* start by assuming every block is free */
|
||||
for (i = 0; i < sizeof bitmap; i++)
|
||||
{
|
||||
bitmap[i] = 255;
|
||||
}
|
||||
|
||||
/* header blocks aren't free */
|
||||
#ifndef lint
|
||||
CLR(0);
|
||||
CLR(1);
|
||||
#endif
|
||||
|
||||
/* blocks needed for current hdr aren't free */
|
||||
for (i = 1; i < MAXBLKS; i++)
|
||||
{
|
||||
CLR(hdr.n[i]);
|
||||
}
|
||||
|
||||
/* blocks needed for undo version aren't free */
|
||||
lseek(tmpfd, 0L, 0);
|
||||
if (read(tmpfd, &oldhdr, (unsigned)sizeof oldhdr) != sizeof oldhdr)
|
||||
{
|
||||
msg("garbage() failed to read oldhdr??");
|
||||
for (i = 0; i < sizeof bitmap; i++)
|
||||
{
|
||||
bitmap[i] = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (i = 1; i < MAXBLKS; i++)
|
||||
{
|
||||
CLR(oldhdr.n[i]);
|
||||
}
|
||||
|
||||
/* blocks needed for cut buffers aren't free */
|
||||
for (i = cutneeds(&oldhdr) - 1; i >= 0; i--)
|
||||
{
|
||||
CLR(oldhdr.n[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* This function allocates the first available block in the tmp file */
|
||||
long allocate()
|
||||
{
|
||||
int i;
|
||||
long offset;
|
||||
|
||||
/* search for the first byte with a free bit set */
|
||||
for (i = 0; i < sizeof bitmap && bitmap[i] == 0; i++)
|
||||
{
|
||||
}
|
||||
|
||||
/* if we hit the end of the bitmap, return the end of the file */
|
||||
if (i == sizeof bitmap)
|
||||
{
|
||||
offset = lseek(tmpfd, 0L, 2);
|
||||
}
|
||||
else /* compute the offset for the free block */
|
||||
{
|
||||
for (i <<= 3; TST(i) == 0; i++)
|
||||
{
|
||||
}
|
||||
offset = (long)i * (long)BLKSIZE;
|
||||
|
||||
/* mark the block as "allocated" */
|
||||
CLR(i);
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
# include <stdio.h>
|
||||
# undef malloc
|
||||
# undef free
|
||||
# define MEMMAGIC 0x19f72cc0L
|
||||
# define MAXALLOC 800
|
||||
static char *allocated[MAXALLOC];
|
||||
static char *fromfile[MAXALLOC];
|
||||
static int fromline[MAXALLOC];
|
||||
static int sizes[MAXALLOC];
|
||||
|
||||
char *dbmalloc(size, file, line)
|
||||
int size;
|
||||
char *file;
|
||||
int line;
|
||||
{
|
||||
char *ret;
|
||||
int i;
|
||||
|
||||
size = size + sizeof(long) - (size % sizeof(long));
|
||||
ret = (char *)malloc(size + 2 * sizeof(long)) + sizeof(long);
|
||||
for (i = 0; i < MAXALLOC && allocated[i]; i++)
|
||||
{
|
||||
}
|
||||
if (i == MAXALLOC)
|
||||
{
|
||||
endwin();
|
||||
fprintf(stderr, "\r\n%s(%d): Too many malloc calls!\n", file, line);
|
||||
abort();
|
||||
}
|
||||
sizes[i] = size/sizeof(long);
|
||||
allocated[i] = ret;
|
||||
fromfile[i] = file;
|
||||
fromline[i] = line;
|
||||
((long *)ret)[-1] = MEMMAGIC;
|
||||
((long *)ret)[sizes[i]] = MEMMAGIC;
|
||||
return ret;
|
||||
}
|
||||
|
||||
dbfree(ptr, file, line)
|
||||
char *ptr;
|
||||
char *file;
|
||||
int line;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAXALLOC && allocated[i] != ptr; i++)
|
||||
{
|
||||
}
|
||||
if (i == MAXALLOC)
|
||||
{
|
||||
endwin();
|
||||
fprintf(stderr, "\r\n%s(%d): attempt to free mem that wasn't allocated\n", file, line);
|
||||
abort();
|
||||
}
|
||||
allocated[i] = (char *)0;
|
||||
if (((long *)ptr)[-1] != MEMMAGIC)
|
||||
{
|
||||
endwin();
|
||||
fprintf(stderr, "\r\n%s(%d): underflowed malloc space, allocated at %s(%d)\n", file, line, fromfile[i], fromline[i]);
|
||||
abort();
|
||||
}
|
||||
if (((long *)ptr)[sizes[i]] != MEMMAGIC)
|
||||
{
|
||||
endwin();
|
||||
fprintf(stderr, "\r\n%s(%d): overflowed malloc space, allocated at %s(%d)\n", file, line, fromfile[i], fromline[i]);
|
||||
abort();
|
||||
}
|
||||
free(ptr - sizeof(long));
|
||||
}
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -1,525 +0,0 @@
|
|||
/* ref2.c */
|
||||
|
||||
/* This is a totally rewritten version of ref. This version looks for the
|
||||
* desired function name in the "tags" file, and then reads the header out
|
||||
* from the source file. There is no longer any need for a "refs" file.
|
||||
*
|
||||
* Usage: ref [-a] [-t] [-f file] [-c class] tag
|
||||
* Options: -t output tag info, not the description
|
||||
* -f file default filename for static functions
|
||||
* -c class default class names for class functions
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "config.h"
|
||||
extern char *getenv();
|
||||
extern char *fgets();
|
||||
|
||||
|
||||
/* This is the default path that is searched for tags */
|
||||
#if OSK
|
||||
# define DEFTAGPATH ".:/dd/defs:/dd/defs/sys:/dd/usr/src/lib:../lib:/dd/usr/lib"
|
||||
#else
|
||||
# if ANY_UNIX
|
||||
# define DEFTAGPATH ".:/usr/include:/usr/include/sys:/usr/src/lib:../lib:/usr/local/lib"
|
||||
# else
|
||||
# if MSDOS || TOS
|
||||
# define DEFTAGPATH ".;C:\\include;C:\\include\\sys;C:\\lib;..\\lib"
|
||||
# define SEP ';'
|
||||
# else
|
||||
# if AMIGA
|
||||
# define DEFTAGPATH ".;Include:;Include:sys"
|
||||
# define SEP ';'
|
||||
# else /* any other OS */
|
||||
# define DEFTAGPATH "."
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef SEP
|
||||
# define SEP ':'
|
||||
#endif
|
||||
|
||||
|
||||
/* These variables reflect the command-line options given by the user. */
|
||||
int taginfo; /* boolean: give only the tag info? (not header?) */
|
||||
char *def_file; /* default filename for static functions */
|
||||
char *def_class; /* default classname for class members */
|
||||
int colons; /* #colons in tag: 0=normal, 1=static, 2=member */
|
||||
|
||||
/* This function checks for a tag in the "tags" file of given directory.
|
||||
* If the tag is found, then it returns a pointer to a static buffer which
|
||||
* contains the filename, a tab character, and a linespec for finding the
|
||||
* the tag. If the tag is not found in the "tags" file, or if the "tags"
|
||||
* file cannot be opened or doesn't exist, then this function returns NULL.
|
||||
*/
|
||||
char *cktagdir(tag, dir)
|
||||
char *tag; /* name of the tag to look for */
|
||||
char *dir; /* name of the directory to check */
|
||||
{
|
||||
char buf[BLKSIZE];
|
||||
static char found[BLKSIZE];
|
||||
FILE *tfile;
|
||||
int len;
|
||||
|
||||
#if AMIGA
|
||||
if (dir[strlen(dir) - 1] == COLON)
|
||||
sprintf(buf, "%s%s", dir, TAGS); /* no slash after colon. */
|
||||
else
|
||||
#endif
|
||||
/* construct the name of the "tags" file in this directory */
|
||||
sprintf(buf, "%s%c%s", dir, SLASH, TAGS);
|
||||
|
||||
/* Try to open the tags file. Return NULL if can't open */
|
||||
#if AMIGA
|
||||
if (buf[0] == '.' && buf[1] == SLASH)
|
||||
tfile = fopen(&buf[2], "r");
|
||||
else
|
||||
#endif
|
||||
tfile = fopen(buf, "r");
|
||||
if (!tfile)
|
||||
{
|
||||
return (char *)0;
|
||||
}
|
||||
|
||||
/* compute the length of the tagname once */
|
||||
len = strlen(tag);
|
||||
|
||||
/* read lines until we get the one for this tag */
|
||||
found[0] = '\0';
|
||||
while (fgets(buf, sizeof buf, tfile))
|
||||
{
|
||||
/* is this the one we want? */
|
||||
if (!strncmp(buf, tag, len) && buf[len] == '\t')
|
||||
{
|
||||
/* we've found a match -- remember it */
|
||||
strcpy(found, buf);
|
||||
|
||||
/* if there is no default file, or this match is in
|
||||
* the default file, then we've definitely found the
|
||||
* one we want. Break out of the loop now.
|
||||
*/
|
||||
if (!def_file || !strncmp(&buf[len + 1], def_file, strlen(def_file)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* we're through reading */
|
||||
fclose(tfile);
|
||||
|
||||
/* if there's anything in found[], use it */
|
||||
if (found[0])
|
||||
{
|
||||
return &found[len + 1];
|
||||
}
|
||||
|
||||
/* else we didn't find it */
|
||||
return (char *)0;
|
||||
}
|
||||
|
||||
/* This function reads a single textline from a binary file. It returns
|
||||
* the number of bytes read, or 0 at EOF.
|
||||
*/
|
||||
#ifdef __NBSD_LIBC
|
||||
/* Avoid name pollution with stdio's getline. */
|
||||
#define getline ref_getline
|
||||
#endif
|
||||
int getline(buf, limit, fp)
|
||||
char *buf; /* buffer to read into */
|
||||
int limit; /* maximum characters to read */
|
||||
FILE *fp; /* binary stream to read from */
|
||||
{
|
||||
int bytes; /* number of bytes read so far */
|
||||
int ch; /* single character from file */
|
||||
|
||||
for (bytes = 0, ch = 0; ch != '\n' && --limit > 0 && (ch = getc(fp)) != EOF; bytes++)
|
||||
{
|
||||
#if MSDOS || TOS
|
||||
/* since this is a binary file, we'll need to manually strip CR's */
|
||||
if (ch == '\r')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
*buf++ = ch;
|
||||
}
|
||||
*buf = '\0';
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
/* This function reads a source file, looking for a given tag. If it finds
|
||||
* the tag, then it displays it and returns TRUE. Otherwise it returns FALSE.
|
||||
* To display the tag, it attempts to output any introductory comment, the
|
||||
* tag line itself, and any arguments. Arguments are assumed to immediately
|
||||
* follow the tag line, and start with whitespace. Comments are assumed to
|
||||
* start with lines that begin with "/ *", "//", "(*", or "--", and end at the
|
||||
* tag line or at a blank line.
|
||||
*/
|
||||
int lookup(dir, entry)
|
||||
char *dir; /* name of the directory that contains the source */
|
||||
char *entry; /* source filename, <Tab>, linespec */
|
||||
{
|
||||
char buf[BLKSIZE]; /* pathname of sourcefile */
|
||||
long lnum; /* line number */
|
||||
long here; /* seek position where current line began */
|
||||
long comment; /* seek position of introductory comment, or -1L */
|
||||
FILE *sfile; /* used for reading the source file */
|
||||
int len; /* length of string */
|
||||
char *ptr;
|
||||
|
||||
|
||||
/* construct the pathname of the source file */
|
||||
strcpy(buf, dir);
|
||||
ptr = buf + strlen(buf);
|
||||
#if AMIGA
|
||||
if (ptr[-1] != COLON)
|
||||
#endif
|
||||
*ptr++ = SLASH;
|
||||
while (*entry != '\t')
|
||||
{
|
||||
*ptr++ = *entry++;
|
||||
}
|
||||
*ptr = '\0';
|
||||
entry++;
|
||||
|
||||
/* searching for string or number? */
|
||||
if (*entry >= '0' && *entry <= '9')
|
||||
{
|
||||
/* given a specific line number */
|
||||
lnum = atol(entry);
|
||||
entry = (char *)0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* given a string -- strip off "/^" and "$/\n" */
|
||||
entry += 2;
|
||||
len = strlen(entry) - 2;
|
||||
if (entry[len - 1] == '$')
|
||||
{
|
||||
entry[len - 1] = '\n';
|
||||
}
|
||||
lnum = 0L;
|
||||
}
|
||||
|
||||
/* Open the file. Note that we open the file in binary mode even
|
||||
* though we know it is a text file, because ftell() and fseek()
|
||||
* don't work on text files.
|
||||
*/
|
||||
#if MSDOS || TOS
|
||||
sfile = fopen(buf, "rb");
|
||||
#else
|
||||
# if AMIGA
|
||||
if (buf[0] == '.' && buf[1] == SLASH)
|
||||
sfile = fopen(&buf[2], "r");
|
||||
else
|
||||
# endif
|
||||
sfile = fopen(buf, "r");
|
||||
#endif
|
||||
if (!sfile)
|
||||
{
|
||||
/* can't open the real source file. Try "refs" instead */
|
||||
#if AMIGA
|
||||
if (dir[strlen(dir) - 1] == COLON)
|
||||
sprintf(buf, "%srefs", dir);
|
||||
else
|
||||
#endif
|
||||
sprintf(buf, "%s%crefs", dir, SLASH);
|
||||
#if MSDOS || TOS
|
||||
sfile = fopen(buf, "rb");
|
||||
#else
|
||||
# if AMIGA
|
||||
if (buf[0] == '.' && buf[1] == SLASH)
|
||||
sfile = fopen(&buf[2], "r");
|
||||
else
|
||||
# endif
|
||||
sfile = fopen(buf, "r");
|
||||
#endif
|
||||
if (!sfile)
|
||||
{
|
||||
/* failed! */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* search the file */
|
||||
for (comment = -1L; here = ftell(sfile), getline(buf, BLKSIZE, sfile) > 0; )
|
||||
{
|
||||
/* Is this the start/end of a comment? */
|
||||
if (comment == -1L)
|
||||
{
|
||||
/* starting a comment? */
|
||||
if (buf[0] == '/' && buf[1] == '*'
|
||||
|| buf[0] == '/' && buf[1] == '/'
|
||||
|| buf[0] == '(' && buf[1] == '*'
|
||||
|| buf[0] == '-' && buf[1] == '-')
|
||||
{
|
||||
comment = here;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ending a comment? */
|
||||
if (buf[0] == '\n' || buf[0] == '#')
|
||||
{
|
||||
comment = -1L;
|
||||
}
|
||||
}
|
||||
|
||||
/* is this the tag line? */
|
||||
if (--lnum == 0L || (entry && !strncmp(buf, entry, len)))
|
||||
{
|
||||
/* if there were introductory comments, show them */
|
||||
if (comment != -1L)
|
||||
{
|
||||
fseek(sfile, comment, 0);
|
||||
while (comment != here)
|
||||
{
|
||||
getline(buf, BLKSIZE, sfile);
|
||||
fputs(buf, stdout);
|
||||
comment = ftell(sfile);
|
||||
}
|
||||
|
||||
/* re-fetch the tag line */
|
||||
fgets(buf, BLKSIZE, sfile);
|
||||
}
|
||||
|
||||
/* show the tag line */
|
||||
fputs(buf, stdout);
|
||||
|
||||
/* show any argument lines */
|
||||
while (getline(buf, BLKSIZE, sfile) > 0
|
||||
&& buf[0] != '#'
|
||||
&& strchr(buf, '{') == (char *)0)
|
||||
{
|
||||
fputs(buf, stdout);
|
||||
}
|
||||
|
||||
/* Done! Close the file, and return TRUE */
|
||||
fclose(sfile);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* not found -- return FALSE */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function searches through the entire search path for a given tag.
|
||||
* If it finds the tag, then it displays the info and returns TRUE;
|
||||
* otherwise it returns FALSE.
|
||||
*/
|
||||
int find(tag)
|
||||
char *tag; /* the tag to look up */
|
||||
{
|
||||
char *tagpath;
|
||||
char dir[80];
|
||||
char *ptr;
|
||||
int len;
|
||||
|
||||
if (colons == 1)
|
||||
{
|
||||
/* looking for static function -- only look in current dir */
|
||||
tagpath = ".";
|
||||
}
|
||||
else
|
||||
{
|
||||
/* get the tagpath from the environment. Default to DEFTAGPATH */
|
||||
tagpath = getenv("TAGPATH");
|
||||
if (!tagpath)
|
||||
{
|
||||
tagpath = DEFTAGPATH;
|
||||
}
|
||||
}
|
||||
|
||||
/* for each entry in the path... */
|
||||
while (*tagpath)
|
||||
{
|
||||
/* Copy the entry into the dir[] buffer */
|
||||
for (ptr = dir; *tagpath && *tagpath != SEP; tagpath++)
|
||||
{
|
||||
*ptr++ = *tagpath;
|
||||
}
|
||||
if (*tagpath == SEP)
|
||||
{
|
||||
tagpath++;
|
||||
}
|
||||
|
||||
/* if the entry ended with "/tags", then strip that off */
|
||||
len = strlen(TAGS);
|
||||
if (&dir[len] < ptr && ptr[-len - 1] == SLASH && !strncmp(&ptr[-len], TAGS, len))
|
||||
{
|
||||
ptr -= len + 1;
|
||||
}
|
||||
|
||||
/* if the entry is now an empty string, then assume "." */
|
||||
if (ptr == dir)
|
||||
{
|
||||
*ptr++ = '.';
|
||||
}
|
||||
*ptr = '\0';
|
||||
|
||||
/* look for the tag in this path. If found, then display it
|
||||
* and exit.
|
||||
*/
|
||||
ptr = cktagdir(tag, dir);
|
||||
if (ptr)
|
||||
{
|
||||
/* just supposed to display tag info? */
|
||||
if (taginfo)
|
||||
{
|
||||
/* then do only that! */
|
||||
if (strcmp(dir, "."))
|
||||
{
|
||||
printf("%s%c%s", dir, SLASH, ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* avoid leading "./" if possible */
|
||||
fputs(ptr, stdout);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* else look up the declaration of the thing */
|
||||
return lookup(dir, ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if we get here, then the tag wasn't found anywhere */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usage()
|
||||
{
|
||||
fputs("usage: ref [-a] [-t] [-c class] [-f file] tag\n", stderr);
|
||||
fputs(" -a function's args may be flush against left margin\n", stderr);
|
||||
fputs(" -t output tag info, instead of the function header\n", stderr);
|
||||
fputs(" -f File tag might be a static function in File\n", stderr);
|
||||
fputs(" -c Class tag might be a member of class Class\n", stderr);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
|
||||
int countcolons(str)
|
||||
char *str;
|
||||
{
|
||||
while (*str != ':' && *str)
|
||||
{
|
||||
str++;
|
||||
}
|
||||
if (str[0] != ':')
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (str[1] != ':')
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
int main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char def_tag[100]; /* used to build tag name with default file/class */
|
||||
int i;
|
||||
|
||||
/* parse flags */
|
||||
for (i = 1; i < argc && argv[i][0] == '-'; i++)
|
||||
{
|
||||
switch (argv[i][1])
|
||||
{
|
||||
case 't':
|
||||
taginfo = 1;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
if (argv[i][2])
|
||||
{
|
||||
def_file = &argv[i][2];
|
||||
}
|
||||
else if (++i < argc)
|
||||
{
|
||||
def_file = argv[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
usage();
|
||||
}
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
if (argv[i][2])
|
||||
{
|
||||
def_class = &argv[i][2];
|
||||
}
|
||||
else if (++i < argc)
|
||||
{
|
||||
def_class = argv[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
usage();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
/* if no tag was given, complain */
|
||||
if (i + 1 != argc)
|
||||
{
|
||||
usage();
|
||||
}
|
||||
|
||||
/* does the tag have an explicit class or file? */
|
||||
colons = countcolons(argv[i]);
|
||||
|
||||
/* if not, then maybe try some defaults */
|
||||
if (colons == 0)
|
||||
{
|
||||
/* try a static function in the file first */
|
||||
if (def_file)
|
||||
{
|
||||
sprintf(def_tag, "%s:%s", def_file, argv[i]);
|
||||
colons = 1;
|
||||
if (find(def_tag))
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* try a member function for a class */
|
||||
if (def_class)
|
||||
{
|
||||
sprintf(def_tag, "%s::%s", def_class, argv[i]);
|
||||
colons = 2;
|
||||
if (find(def_tag))
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* oh, well */
|
||||
colons = 0;
|
||||
}
|
||||
|
||||
/* find the tag */
|
||||
if (find(argv[i]))
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
|
||||
exit(1);
|
||||
/*NOTREACHED*/
|
||||
}
|
|
@ -1,934 +0,0 @@
|
|||
/* regexp.c */
|
||||
|
||||
/* This file contains the code that compiles regular expressions and executes
|
||||
* them. It supports the same syntax and features as vi's regular expression
|
||||
* code. Specifically, the meta characters are:
|
||||
* ^ matches the beginning of a line
|
||||
* $ matches the end of a line
|
||||
* \< matches the beginning of a word
|
||||
* \> matches the end of a word
|
||||
* . matches any single character
|
||||
* [] matches any character in a character class
|
||||
* \( delimits the start of a subexpression
|
||||
* \) delimits the end of a subexpression
|
||||
* * repeats the preceding 0 or more times
|
||||
* NOTE: You cannot follow a \) with a *.
|
||||
*
|
||||
* The physical structure of a compiled RE is as follows:
|
||||
* - First, there is a one-byte value that says how many character classes
|
||||
* are used in this regular expression
|
||||
* - Next, each character class is stored as a bitmap that is 256 bits
|
||||
* (32 bytes) long.
|
||||
* - A mixture of literal characters and compiled meta characters follows.
|
||||
* This begins with M_BEGIN(0) and ends with M_END(0). All meta chars
|
||||
* are stored as a \n followed by a one-byte code, so they take up two
|
||||
* bytes apiece. Literal characters take up one byte apiece. \n can't
|
||||
* be used as a literal character.
|
||||
*
|
||||
* If NO_MAGIC is defined, then a different set of functions is used instead.
|
||||
* That right, this file contains TWO versions of the code.
|
||||
*/
|
||||
|
||||
#include <setjmp.h>
|
||||
#include "config.h"
|
||||
#include "ctype.h"
|
||||
#include "vi.h"
|
||||
#include "regexp.h"
|
||||
|
||||
|
||||
|
||||
static char *previous; /* the previous regexp, used when null regexp is given */
|
||||
|
||||
|
||||
#ifndef NO_MAGIC
|
||||
/* THE REAL REGEXP PACKAGE IS USED UNLESS "NO_MAGIC" IS DEFINED */
|
||||
|
||||
/* These are used to classify or recognize meta-characters */
|
||||
#define META '\0'
|
||||
#define BASE_META(m) ((m) - 256)
|
||||
#define INT_META(c) ((c) + 256)
|
||||
#define IS_META(m) ((m) >= 256)
|
||||
#define IS_CLASS(m) ((m) >= M_CLASS(0) && (m) <= M_CLASS(9))
|
||||
#define IS_START(m) ((m) >= M_START(0) && (m) <= M_START(9))
|
||||
#define IS_END(m) ((m) >= M_END(0) && (m) <= M_END(9))
|
||||
#define IS_CLOSURE(m) ((m) >= M_SPLAT && (m) <= M_RANGE)
|
||||
#define ADD_META(s,m) (*(s)++ = META, *(s)++ = BASE_META(m))
|
||||
#define GET_META(s) (*(s) == META ? INT_META(*++(s)) : *s)
|
||||
|
||||
/* These are the internal codes used for each type of meta-character */
|
||||
#define M_BEGLINE 256 /* internal code for ^ */
|
||||
#define M_ENDLINE 257 /* internal code for $ */
|
||||
#define M_BEGWORD 258 /* internal code for \< */
|
||||
#define M_ENDWORD 259 /* internal code for \> */
|
||||
#define M_ANY 260 /* internal code for . */
|
||||
#define M_SPLAT 261 /* internal code for * */
|
||||
#define M_PLUS 262 /* internal code for \+ */
|
||||
#define M_QMARK 263 /* internal code for \? */
|
||||
#define M_RANGE 264 /* internal code for \{ */
|
||||
#define M_CLASS(n) (265+(n)) /* internal code for [] */
|
||||
#define M_START(n) (275+(n)) /* internal code for \( */
|
||||
#define M_END(n) (285+(n)) /* internal code for \) */
|
||||
|
||||
/* These are used during compilation */
|
||||
static int class_cnt; /* used to assign class IDs */
|
||||
static int start_cnt; /* used to assign start IDs */
|
||||
static int end_stk[NSUBEXP];/* used to assign end IDs */
|
||||
static int end_sp;
|
||||
static char *retext; /* points to the text being compiled */
|
||||
|
||||
/* error-handling stuff */
|
||||
jmp_buf errorhandler;
|
||||
#define FAIL(why) regerror(why); longjmp(errorhandler, 1)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* This function builds a bitmap for a particular class */
|
||||
static char *makeclass(text, bmap)
|
||||
REG char *text; /* start of the class */
|
||||
REG char *bmap; /* the bitmap */
|
||||
{
|
||||
REG int i;
|
||||
int complement = 0;
|
||||
|
||||
|
||||
/* zero the bitmap */
|
||||
for (i = 0; bmap && i < 32; i++)
|
||||
{
|
||||
bmap[i] = 0;
|
||||
}
|
||||
|
||||
/* see if we're going to complement this class */
|
||||
if (*text == '^')
|
||||
{
|
||||
text++;
|
||||
complement = 1;
|
||||
}
|
||||
|
||||
/* add in the characters */
|
||||
while (*text && *text != ']')
|
||||
{
|
||||
/* is this a span of characters? */
|
||||
if (text[1] == '-' && text[2])
|
||||
{
|
||||
/* spans can't be backwards */
|
||||
if (text[0] > text[2])
|
||||
{
|
||||
FAIL("Backwards span in []");
|
||||
}
|
||||
|
||||
/* add each character in the span to the bitmap */
|
||||
for (i = text[0]; bmap && i <= text[2]; i++)
|
||||
{
|
||||
bmap[i >> 3] |= (1 << (i & 7));
|
||||
}
|
||||
|
||||
/* move past this span */
|
||||
text += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* add this single character to the span */
|
||||
i = *text++;
|
||||
if (bmap)
|
||||
{
|
||||
bmap[i >> 3] |= (1 << (i & 7));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* make sure the closing ] is missing */
|
||||
if (*text++ != ']')
|
||||
{
|
||||
FAIL("] missing");
|
||||
}
|
||||
|
||||
/* if we're supposed to complement this class, then do so */
|
||||
if (complement && bmap)
|
||||
{
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
bmap[i] = ~bmap[i];
|
||||
}
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* This function gets the next character or meta character from a string.
|
||||
* The pointer is incremented by 1, or by 2 for \-quoted characters. For [],
|
||||
* a bitmap is generated via makeclass() (if re is given), and the
|
||||
* character-class text is skipped.
|
||||
*/
|
||||
static int gettoken(sptr, re)
|
||||
char **sptr;
|
||||
regexp *re;
|
||||
{
|
||||
int c;
|
||||
|
||||
c = **sptr;
|
||||
++*sptr;
|
||||
if (c == '\\')
|
||||
{
|
||||
c = **sptr;
|
||||
++*sptr;
|
||||
switch (c)
|
||||
{
|
||||
case '<':
|
||||
return M_BEGWORD;
|
||||
|
||||
case '>':
|
||||
return M_ENDWORD;
|
||||
|
||||
case '(':
|
||||
if (start_cnt >= NSUBEXP)
|
||||
{
|
||||
FAIL("Too many \\(s");
|
||||
}
|
||||
end_stk[end_sp++] = start_cnt;
|
||||
return M_START(start_cnt++);
|
||||
|
||||
case ')':
|
||||
if (end_sp <= 0)
|
||||
{
|
||||
FAIL("Mismatched \\)");
|
||||
}
|
||||
return M_END(end_stk[--end_sp]);
|
||||
|
||||
case '*':
|
||||
return (*o_magic ? c : M_SPLAT);
|
||||
|
||||
case '.':
|
||||
return (*o_magic ? c : M_ANY);
|
||||
|
||||
case '+':
|
||||
return M_PLUS;
|
||||
|
||||
case '?':
|
||||
return M_QMARK;
|
||||
#ifndef CRUNCH
|
||||
case '{':
|
||||
return M_RANGE;
|
||||
#endif
|
||||
default:
|
||||
return c;
|
||||
}
|
||||
}
|
||||
else if (*o_magic)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '^':
|
||||
if (*sptr == retext + 1)
|
||||
{
|
||||
return M_BEGLINE;
|
||||
}
|
||||
return c;
|
||||
|
||||
case '$':
|
||||
if (!**sptr)
|
||||
{
|
||||
return M_ENDLINE;
|
||||
}
|
||||
return c;
|
||||
|
||||
case '.':
|
||||
return M_ANY;
|
||||
|
||||
case '*':
|
||||
return M_SPLAT;
|
||||
|
||||
case '[':
|
||||
/* make sure we don't have too many classes */
|
||||
if (class_cnt >= 10)
|
||||
{
|
||||
FAIL("Too many []s");
|
||||
}
|
||||
|
||||
/* process the character list for this class */
|
||||
if (re)
|
||||
{
|
||||
/* generate the bitmap for this class */
|
||||
*sptr = makeclass(*sptr, re->program + 1 + 32 * class_cnt);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* skip to end of the class */
|
||||
*sptr = makeclass(*sptr, (char *)0);
|
||||
}
|
||||
return M_CLASS(class_cnt++);
|
||||
|
||||
default:
|
||||
return c;
|
||||
}
|
||||
}
|
||||
else /* unquoted nomagic */
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '^':
|
||||
if (*sptr == retext + 1)
|
||||
{
|
||||
return M_BEGLINE;
|
||||
}
|
||||
return c;
|
||||
|
||||
case '$':
|
||||
if (!**sptr)
|
||||
{
|
||||
return M_ENDLINE;
|
||||
}
|
||||
return c;
|
||||
|
||||
default:
|
||||
return c;
|
||||
}
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* This function calculates the number of bytes that will be needed for a
|
||||
* compiled RE. Its argument is the uncompiled version. It is not clever
|
||||
* about catching syntax errors; that is done in a later pass.
|
||||
*/
|
||||
static unsigned calcsize(text)
|
||||
char *text;
|
||||
{
|
||||
unsigned size;
|
||||
int token;
|
||||
|
||||
retext = text;
|
||||
class_cnt = 0;
|
||||
start_cnt = 1;
|
||||
end_sp = 0;
|
||||
size = 5;
|
||||
while ((token = gettoken(&text, (regexp *)0)) != 0)
|
||||
{
|
||||
if (IS_CLASS(token))
|
||||
{
|
||||
size += 34;
|
||||
}
|
||||
#ifndef CRUNCH
|
||||
else if (token == M_RANGE)
|
||||
{
|
||||
size += 4;
|
||||
while ((token = gettoken(&text, (regexp *)0)) != 0
|
||||
&& token != '}')
|
||||
{
|
||||
}
|
||||
if (!token)
|
||||
{
|
||||
return size;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if (IS_META(token))
|
||||
{
|
||||
size += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
size++;
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* This function compiles a regexp. */
|
||||
regexp *regcomp(exp)
|
||||
char *exp;
|
||||
{
|
||||
int needfirst;
|
||||
unsigned size;
|
||||
int token;
|
||||
int peek;
|
||||
char *build;
|
||||
regexp *re;
|
||||
#ifndef CRUNCH
|
||||
int from;
|
||||
int to;
|
||||
int digit;
|
||||
#endif
|
||||
|
||||
|
||||
/* prepare for error handling */
|
||||
re = (regexp *)0;
|
||||
if (setjmp(errorhandler))
|
||||
{
|
||||
if (re)
|
||||
{
|
||||
free(re);
|
||||
}
|
||||
return (regexp *)0;
|
||||
}
|
||||
|
||||
/* if an empty regexp string was given, use the previous one */
|
||||
if (*exp == 0)
|
||||
{
|
||||
if (!previous)
|
||||
{
|
||||
FAIL("No previous RE");
|
||||
}
|
||||
exp = previous;
|
||||
}
|
||||
else /* non-empty regexp given, so remember it */
|
||||
{
|
||||
if (previous)
|
||||
free(previous);
|
||||
previous = (char *)malloc((unsigned)(strlen(exp) + 1));
|
||||
if (previous)
|
||||
strcpy(previous, exp);
|
||||
}
|
||||
|
||||
/* allocate memory */
|
||||
class_cnt = 0;
|
||||
start_cnt = 1;
|
||||
end_sp = 0;
|
||||
retext = exp;
|
||||
size = calcsize(exp) + sizeof(regexp) + 10; /* !!! 10 bytes for slop */
|
||||
#ifdef lint
|
||||
re = ((regexp *)0) + size;
|
||||
#else
|
||||
re = (regexp *)malloc((unsigned)size);
|
||||
#endif
|
||||
if (!re)
|
||||
{
|
||||
FAIL("Not enough memory for this RE");
|
||||
}
|
||||
|
||||
/* compile it */
|
||||
build = &re->program[1 + 32 * class_cnt];
|
||||
re->program[0] = class_cnt;
|
||||
for (token = 0; token < NSUBEXP; token++)
|
||||
{
|
||||
re->startp[token] = re->endp[token] = (char *)0;
|
||||
}
|
||||
re->first = 0;
|
||||
re->bol = 0;
|
||||
re->minlen = 0;
|
||||
needfirst = 1;
|
||||
class_cnt = 0;
|
||||
start_cnt = 1;
|
||||
end_sp = 0;
|
||||
retext = exp;
|
||||
for (token = M_START(0), peek = gettoken(&exp, re);
|
||||
token;
|
||||
token = peek, peek = gettoken(&exp, re))
|
||||
{
|
||||
/* special processing for the closure operator */
|
||||
if (IS_CLOSURE(peek))
|
||||
{
|
||||
/* detect misuse of closure operator */
|
||||
if (IS_START(token))
|
||||
{
|
||||
FAIL("Closure operator follows nothing");
|
||||
}
|
||||
else if (IS_META(token) && token != M_ANY && !IS_CLASS(token))
|
||||
{
|
||||
FAIL("Closure operators can only follow a normal character or . or []");
|
||||
}
|
||||
|
||||
#ifndef CRUNCH
|
||||
/* if \{ \} then read the range */
|
||||
if (peek == M_RANGE)
|
||||
{
|
||||
from = 0;
|
||||
for (digit = gettoken(&exp, re);
|
||||
!IS_META(digit) && isdigit(digit);
|
||||
digit = gettoken(&exp, re))
|
||||
{
|
||||
from = from * 10 + digit - '0';
|
||||
}
|
||||
if (digit == '}')
|
||||
{
|
||||
to = from;
|
||||
}
|
||||
else if (digit == ',')
|
||||
{
|
||||
to = 0;
|
||||
for (digit = gettoken(&exp, re);
|
||||
!IS_META(digit) && isdigit(digit);
|
||||
digit = gettoken(&exp, re))
|
||||
{
|
||||
to = to * 10 + digit - '0';
|
||||
}
|
||||
if (to == 0)
|
||||
{
|
||||
to = 255;
|
||||
}
|
||||
}
|
||||
if (digit != '}')
|
||||
{
|
||||
FAIL("Bad characters after \\{");
|
||||
}
|
||||
else if (to < from || to == 0 || from >= 255)
|
||||
{
|
||||
FAIL("Invalid range for \\{ \\}");
|
||||
}
|
||||
re->minlen += from;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (peek != M_SPLAT)
|
||||
{
|
||||
re->minlen++;
|
||||
}
|
||||
|
||||
/* it is okay -- make it prefix instead of postfix */
|
||||
ADD_META(build, peek);
|
||||
#ifndef CRUNCH
|
||||
if (peek == M_RANGE)
|
||||
{
|
||||
*build++ = from;
|
||||
*build++ = (to < 255 ? to : 255);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* take care of "needfirst" - is this the first char? */
|
||||
if (needfirst && peek == M_PLUS && !IS_META(token))
|
||||
{
|
||||
re->first = token;
|
||||
}
|
||||
needfirst = 0;
|
||||
|
||||
/* we used "peek" -- need to refill it */
|
||||
peek = gettoken(&exp, re);
|
||||
if (IS_CLOSURE(peek))
|
||||
{
|
||||
FAIL("* or \\+ or \\? doubled up");
|
||||
}
|
||||
}
|
||||
else if (!IS_META(token))
|
||||
{
|
||||
/* normal char is NOT argument of closure */
|
||||
if (needfirst)
|
||||
{
|
||||
re->first = token;
|
||||
needfirst = 0;
|
||||
}
|
||||
re->minlen++;
|
||||
}
|
||||
else if (token == M_ANY || IS_CLASS(token))
|
||||
{
|
||||
/* . or [] is NOT argument of closure */
|
||||
needfirst = 0;
|
||||
re->minlen++;
|
||||
}
|
||||
|
||||
/* the "token" character is not closure -- process it normally */
|
||||
if (token == M_BEGLINE)
|
||||
{
|
||||
/* set the BOL flag instead of storing M_BEGLINE */
|
||||
re->bol = 1;
|
||||
}
|
||||
else if (IS_META(token))
|
||||
{
|
||||
ADD_META(build, token);
|
||||
}
|
||||
else
|
||||
{
|
||||
*build++ = token;
|
||||
}
|
||||
}
|
||||
|
||||
/* end it with a \) which MUST MATCH the opening \( */
|
||||
ADD_META(build, M_END(0));
|
||||
if (end_sp > 0)
|
||||
{
|
||||
FAIL("Not enough \\)s");
|
||||
}
|
||||
|
||||
return re;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/* This function checks for a match between a character and a token which is
|
||||
* known to represent a single character. It returns 0 if they match, or
|
||||
* 1 if they don't.
|
||||
*/
|
||||
int match1(re, ch, token)
|
||||
regexp *re;
|
||||
REG char ch;
|
||||
REG int token;
|
||||
{
|
||||
if (!ch)
|
||||
{
|
||||
/* the end of a line can't match any RE of width 1 */
|
||||
return 1;
|
||||
}
|
||||
if (token == M_ANY)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (IS_CLASS(token))
|
||||
{
|
||||
if (re->program[1 + 32 * (token - M_CLASS(0)) + (ch >> 3)] & (1 << (ch & 7)))
|
||||
return 0;
|
||||
}
|
||||
else if (ch == token || *o_ignorecase && tolower(ch) == tolower(token))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* This function checks characters up to and including the next closure, at
|
||||
* which point it does a recursive call to check the rest of it. This function
|
||||
* returns 0 if everything matches, or 1 if something doesn't match.
|
||||
*/
|
||||
int match(re, str, prog, here)
|
||||
regexp *re; /* the regular expression */
|
||||
char *str; /* the string */
|
||||
REG char *prog; /* a portion of re->program, an compiled RE */
|
||||
REG char *here; /* a portion of str, the string to compare it to */
|
||||
{
|
||||
REG int token; /* the roken pointed to by prog */
|
||||
REG int nmatched;/* counter, used during closure matching */
|
||||
REG int closure;/* the token denoting the type of closure */
|
||||
int from; /* minimum number of matches in closure */
|
||||
int to; /* maximum number of matches in closure */
|
||||
|
||||
for (token = GET_META(prog); !IS_CLOSURE(token); prog++, token = GET_META(prog))
|
||||
{
|
||||
switch (token)
|
||||
{
|
||||
/*case M_BEGLINE: can't happen; re->bol is used instead */
|
||||
case M_ENDLINE:
|
||||
if (*here)
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case M_BEGWORD:
|
||||
if (here != str &&
|
||||
(here[-1] == '_' || isalnum(here[-1])))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case M_ENDWORD:
|
||||
if (here[0] == '_' || isalnum(here[0]))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case M_START(0):
|
||||
case M_START(1):
|
||||
case M_START(2):
|
||||
case M_START(3):
|
||||
case M_START(4):
|
||||
case M_START(5):
|
||||
case M_START(6):
|
||||
case M_START(7):
|
||||
case M_START(8):
|
||||
case M_START(9):
|
||||
re->startp[token - M_START(0)] = (char *)here;
|
||||
break;
|
||||
|
||||
case M_END(0):
|
||||
case M_END(1):
|
||||
case M_END(2):
|
||||
case M_END(3):
|
||||
case M_END(4):
|
||||
case M_END(5):
|
||||
case M_END(6):
|
||||
case M_END(7):
|
||||
case M_END(8):
|
||||
case M_END(9):
|
||||
re->endp[token - M_END(0)] = (char *)here;
|
||||
if (token == M_END(0))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default: /* literal, M_CLASS(n), or M_ANY */
|
||||
if (match1(re, *here, token) != 0)
|
||||
return 1;
|
||||
here++;
|
||||
}
|
||||
}
|
||||
|
||||
/* C L O S U R E */
|
||||
|
||||
/* step 1: see what we have to match against, and move "prog" to point
|
||||
* to the remainder of the compiled RE.
|
||||
*/
|
||||
closure = token;
|
||||
prog++;
|
||||
switch (closure)
|
||||
{
|
||||
case M_SPLAT:
|
||||
from = 0;
|
||||
to = strlen(str); /* infinity */
|
||||
break;
|
||||
|
||||
case M_PLUS:
|
||||
from = 1;
|
||||
to = strlen(str); /* infinity */
|
||||
break;
|
||||
|
||||
case M_QMARK:
|
||||
from = 0;
|
||||
to = 1;
|
||||
break;
|
||||
|
||||
#ifndef CRUNCH
|
||||
case M_RANGE:
|
||||
from = UCHAR(*prog++);
|
||||
to = UCHAR(*prog++);
|
||||
if (to == 255)
|
||||
{
|
||||
to = strlen(str); /* infinity */
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
token = GET_META(prog);
|
||||
prog++;
|
||||
|
||||
/* step 2: see how many times we can match that token against the string */
|
||||
for (nmatched = 0;
|
||||
nmatched < to && *here && match1(re, *here, token) == 0;
|
||||
nmatched++, here++)
|
||||
{
|
||||
}
|
||||
|
||||
/* step 3: try to match the remainder, and back off if it doesn't */
|
||||
while (nmatched >= from && match(re, str, prog, here) != 0)
|
||||
{
|
||||
nmatched--;
|
||||
here--;
|
||||
}
|
||||
|
||||
/* so how did it work out? */
|
||||
if (nmatched >= from)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* This function searches through a string for text that matches an RE. */
|
||||
int regexec(re, str, bol)
|
||||
regexp *re; /* the compiled regexp to search for */
|
||||
char *str; /* the string to search through */
|
||||
int bol; /* boolean: does str start at the beginning of a line? */
|
||||
{
|
||||
char *prog; /* the entry point of re->program */
|
||||
int len; /* length of the string */
|
||||
REG char *here;
|
||||
|
||||
/* if must start at the beginning of a line, and this isn't, then fail */
|
||||
if (re->bol && !bol)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = strlen(str);
|
||||
prog = re->program + 1 + 32 * re->program[0];
|
||||
|
||||
/* search for the RE in the string */
|
||||
if (re->bol)
|
||||
{
|
||||
/* must occur at BOL */
|
||||
if ((re->first
|
||||
&& match1(re, *(char *)str, re->first))/* wrong first letter? */
|
||||
|| len < re->minlen /* not long enough? */
|
||||
|| match(re, (char *)str, prog, str)) /* doesn't match? */
|
||||
return 0; /* THEN FAIL! */
|
||||
}
|
||||
#ifndef CRUNCH
|
||||
else if (!*o_ignorecase)
|
||||
{
|
||||
/* can occur anywhere in the line, noignorecase */
|
||||
for (here = (char *)str;
|
||||
(re->first && re->first != *here)
|
||||
|| match(re, (char *)str, prog, here);
|
||||
here++, len--)
|
||||
{
|
||||
if (len < re->minlen)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
/* can occur anywhere in the line, ignorecase */
|
||||
for (here = (char *)str;
|
||||
(re->first && match1(re, *here, (int)re->first))
|
||||
|| match(re, (char *)str, prog, here);
|
||||
here++, len--)
|
||||
{
|
||||
if (len < re->minlen)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* if we didn't fail, then we must have succeeded */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*============================================================================*/
|
||||
#else /* NO_MAGIC */
|
||||
|
||||
regexp *regcomp(exp)
|
||||
char *exp;
|
||||
{
|
||||
char *src;
|
||||
char *dest;
|
||||
regexp *re;
|
||||
int i;
|
||||
|
||||
/* allocate a big enough regexp structure */
|
||||
#ifdef lint
|
||||
re = (regexp *)0;
|
||||
#else
|
||||
re = (regexp *)malloc((unsigned)(strlen(exp) + 1 + sizeof(struct regexp)));
|
||||
#endif
|
||||
if (!re)
|
||||
{
|
||||
regerror("Could not malloc a regexp structure");
|
||||
return (regexp *)0;
|
||||
}
|
||||
|
||||
/* initialize all fields of the structure */
|
||||
for (i = 0; i < NSUBEXP; i++)
|
||||
{
|
||||
re->startp[i] = re->endp[i] = (char *)0;
|
||||
}
|
||||
re->minlen = 0;
|
||||
re->first = 0;
|
||||
re->bol = 0;
|
||||
|
||||
/* copy the string into it, translating ^ and $ as needed */
|
||||
for (src = exp, dest = re->program + 1; *src; src++)
|
||||
{
|
||||
switch (*src)
|
||||
{
|
||||
case '^':
|
||||
if (src == exp)
|
||||
{
|
||||
re->bol += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*dest++ = '^';
|
||||
re->minlen++;
|
||||
}
|
||||
break;
|
||||
|
||||
case '$':
|
||||
if (!src[1])
|
||||
{
|
||||
re->bol += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*dest++ = '$';
|
||||
re->minlen++;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
if (src[1])
|
||||
{
|
||||
*dest++ = *++src;
|
||||
re->minlen++;
|
||||
}
|
||||
else
|
||||
{
|
||||
regerror("extra \\ at end of regular expression");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
*dest++ = *src;
|
||||
re->minlen++;
|
||||
}
|
||||
}
|
||||
*dest = '\0';
|
||||
|
||||
return re;
|
||||
}
|
||||
|
||||
|
||||
/* This "helper" function checks for a match at a given location. It returns
|
||||
* 1 if it matches, 0 if it doesn't match here but might match later on in the
|
||||
* string, or -1 if it could not possibly match
|
||||
*/
|
||||
static int reghelp(prog, string, bolflag)
|
||||
struct regexp *prog;
|
||||
char *string;
|
||||
int bolflag;
|
||||
{
|
||||
char *scan;
|
||||
char *str;
|
||||
|
||||
/* if ^, then require bolflag */
|
||||
if ((prog->bol & 1) && !bolflag)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* if it matches, then it will start here */
|
||||
prog->startp[0] = string;
|
||||
|
||||
/* compare, possibly ignoring case */
|
||||
if (*o_ignorecase)
|
||||
{
|
||||
for (scan = &prog->program[1]; *scan; scan++, string++)
|
||||
if (tolower(*scan) != tolower(*string))
|
||||
return *string ? 0 : -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (scan = &prog->program[1]; *scan; scan++, string++)
|
||||
if (*scan != *string)
|
||||
return *string ? 0 : -1;
|
||||
}
|
||||
|
||||
/* if $, then require string to end here, too */
|
||||
if ((prog->bol & 2) && *string)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if we get to here, it matches */
|
||||
prog->endp[0] = string;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int regexec(prog, string, bolflag)
|
||||
struct regexp *prog;
|
||||
char *string;
|
||||
int bolflag;
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* keep trying to match it */
|
||||
for (rc = reghelp(prog, string, bolflag); rc == 0; rc = reghelp(prog, string, 0))
|
||||
{
|
||||
string++;
|
||||
}
|
||||
|
||||
/* did we match? */
|
||||
return rc == 1;
|
||||
}
|
||||
#endif
|
|
@ -1,21 +0,0 @@
|
|||
/*
|
||||
* Definitions etc. for regexp(3) routines.
|
||||
*
|
||||
* Caveat: this is V8 regexp(3) [actually, a reimplementation thereof],
|
||||
* not the System V one.
|
||||
*/
|
||||
#define NSUBEXP 10
|
||||
|
||||
typedef struct regexp {
|
||||
char *startp[NSUBEXP];
|
||||
char *endp[NSUBEXP];
|
||||
int minlen; /* length of shortest possible match */
|
||||
char first; /* first character, if known; else \0 */
|
||||
char bol; /* boolean: must start at beginning of line? */
|
||||
char program[1]; /* Unwarranted chumminess with compiler. */
|
||||
} regexp;
|
||||
|
||||
extern regexp *regcomp();
|
||||
extern int regexec();
|
||||
extern void regsub();
|
||||
extern void regerror();
|
|
@ -1,243 +0,0 @@
|
|||
/* regsub.c */
|
||||
|
||||
/* This file contains the regsub() function, which performs substitutions
|
||||
* after a regexp match has been found.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "ctype.h"
|
||||
#include "vi.h"
|
||||
#include "regexp.h"
|
||||
|
||||
|
||||
/* perform substitutions after a regexp match */
|
||||
void regsub(re, src, dst)
|
||||
regexp *re; /* the regexp with pointers into matched text */
|
||||
REG char *src; /* the replacement string */
|
||||
REG char *dst; /* where to put the result of the subst */
|
||||
{
|
||||
REG char *cpy; /* pointer to start of text to copy */
|
||||
REG char *end; /* pointer to end of text to copy */
|
||||
REG char c;
|
||||
char *start;
|
||||
#ifndef CRUNCH
|
||||
int mod = 0;/* used to track \U, \L, \u, \l, and \E */
|
||||
int len; /* used to calculate length of subst string */
|
||||
static char *prev; /* a copy of the text from the previous subst */
|
||||
|
||||
/* replace \~ (or maybe ~) by previous substitution text */
|
||||
|
||||
/* step 1: calculate the length of the new substitution text */
|
||||
for (len = strlen(src), c = '\0', cpy = src; *cpy; cpy++)
|
||||
{
|
||||
# ifdef NO_MAGIC
|
||||
if (c == '\\' && *cpy == '~')
|
||||
# else
|
||||
if (c == (*o_magic ? '\0' : '\\') && *cpy == '~')
|
||||
# endif
|
||||
{
|
||||
if (!prev)
|
||||
{
|
||||
regerror("No prev text to substitute for ~");
|
||||
return;
|
||||
}
|
||||
len += strlen(prev) - 1;
|
||||
# ifndef NO_MAGIC
|
||||
if (!*o_magic)
|
||||
# endif
|
||||
len -= 1; /* because we lose the \ too */
|
||||
}
|
||||
|
||||
/* watch backslash quoting */
|
||||
if (c != '\\' && *cpy == '\\')
|
||||
c = '\\';
|
||||
else
|
||||
c = '\0';
|
||||
}
|
||||
|
||||
/* allocate memory for the ~ed version of src */
|
||||
start = cpy = (char *)malloc((unsigned)(len + 1));
|
||||
if (!cpy)
|
||||
{
|
||||
regerror("Not enough memory for ~ expansion");
|
||||
return;
|
||||
}
|
||||
|
||||
/* copy src into start, replacing the ~s by the previous text */
|
||||
while (*src)
|
||||
{
|
||||
# ifndef NO_MAGIC
|
||||
if (*o_magic && *src == '~')
|
||||
{
|
||||
strcpy(cpy, prev);
|
||||
cpy += strlen(prev);
|
||||
src++;
|
||||
}
|
||||
else if (!*o_magic && *src == '\\' && *(src + 1) == '~')
|
||||
# else /* NO_MAGIC */
|
||||
if (*src == '\\' && *(src + 1) == '~')
|
||||
# endif /* NO_MAGIC */
|
||||
{
|
||||
strcpy(cpy, prev);
|
||||
cpy += strlen(prev);
|
||||
src += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*cpy++ = *src++;
|
||||
}
|
||||
}
|
||||
*cpy = '\0';
|
||||
#ifdef DEBUG
|
||||
if ((int)(cpy - start) != len)
|
||||
{
|
||||
msg("Bug in regsub.c! Predicted length = %d, Actual length = %d", len, (int)(cpy - start));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* remember this as the "previous" for next time */
|
||||
if (prev)
|
||||
free(prev);
|
||||
prev = src = start;
|
||||
|
||||
#endif /* undef CRUNCH */
|
||||
|
||||
start = src;
|
||||
while ((c = *src++) != '\0')
|
||||
{
|
||||
#ifndef NO_MAGIC
|
||||
/* recognize any meta characters */
|
||||
if (c == '&' && *o_magic)
|
||||
{
|
||||
cpy = re->startp[0];
|
||||
end = re->endp[0];
|
||||
}
|
||||
else
|
||||
#endif /* not NO_MAGIC */
|
||||
if (c == '\\')
|
||||
{
|
||||
c = *src++;
|
||||
switch (c)
|
||||
{
|
||||
#ifndef NO_MAGIC
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
/* \0 thru \9 mean "copy subexpression" */
|
||||
c -= '0';
|
||||
cpy = re->startp[c];
|
||||
end = re->endp[c];
|
||||
break;
|
||||
# ifndef CRUNCH
|
||||
case 'U':
|
||||
case 'u':
|
||||
case 'L':
|
||||
case 'l':
|
||||
/* \U and \L mean "convert to upper/lowercase" */
|
||||
mod = c;
|
||||
continue;
|
||||
|
||||
case 'E':
|
||||
case 'e':
|
||||
/* \E ends the \U or \L */
|
||||
mod = 0;
|
||||
continue;
|
||||
# endif /* not CRUNCH */
|
||||
case '&':
|
||||
/* "\&" means "original text" */
|
||||
if (*o_magic)
|
||||
{
|
||||
*dst++ = c;
|
||||
continue;
|
||||
}
|
||||
cpy = re->startp[0];
|
||||
end = re->endp[0];
|
||||
break;
|
||||
|
||||
#else /* NO_MAGIC */
|
||||
case '&':
|
||||
/* "\&" means "original text" */
|
||||
cpy = re->startp[0];
|
||||
end = re->endp[0];
|
||||
break;
|
||||
#endif /* NO_MAGIC */
|
||||
default:
|
||||
/* ordinary char preceded by backslash */
|
||||
*dst++ = c;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#ifndef CRUNCH
|
||||
# if OSK
|
||||
else if (c == '\l')
|
||||
# else
|
||||
else if (c == '\r')
|
||||
# endif
|
||||
{
|
||||
/* transliterate ^M into newline */
|
||||
*dst++ = '\n';
|
||||
continue;
|
||||
}
|
||||
#endif /* !CRUNCH */
|
||||
else
|
||||
{
|
||||
/* ordinary character, so just copy it */
|
||||
*dst++ = c;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Note: to reach this point in the code, we must have evaded
|
||||
* all "continue" statements. To do that, we must have hit
|
||||
* a metacharacter that involves copying.
|
||||
*/
|
||||
|
||||
/* if there is nothing to copy, loop */
|
||||
if (!cpy)
|
||||
continue;
|
||||
|
||||
/* copy over a portion of the original */
|
||||
while (cpy < end)
|
||||
{
|
||||
#ifndef NO_MAGIC
|
||||
# ifndef CRUNCH
|
||||
switch (mod)
|
||||
{
|
||||
case 'U':
|
||||
case 'u':
|
||||
/* convert to uppercase */
|
||||
*dst++ = toupper(*cpy++);
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
case 'l':
|
||||
/* convert to lowercase */
|
||||
*dst++ = tolower(*cpy++);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* copy without any conversion */
|
||||
*dst++ = *cpy++;
|
||||
}
|
||||
|
||||
/* \u and \l end automatically after the first char */
|
||||
if (mod && (mod == 'u' || mod == 'l'))
|
||||
{
|
||||
mod = 0;
|
||||
}
|
||||
# else /* CRUNCH */
|
||||
*dst++ = *cpy++;
|
||||
# endif /* CRUNCH */
|
||||
#else /* NO_MAGIC */
|
||||
*dst++ = *cpy++;
|
||||
#endif /* NO_MAGIC */
|
||||
}
|
||||
}
|
||||
*dst = '\0';
|
||||
}
|
|
@ -1,415 +0,0 @@
|
|||
/* system.c -- UNIX version */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* 14407 SW Teal Blvd. #C
|
||||
* Beaverton, OR 97005
|
||||
* kirkenda@cs.pdx.edu
|
||||
*/
|
||||
|
||||
|
||||
/* This file contains a new version of the system() function and related stuff.
|
||||
*
|
||||
* Entry points are:
|
||||
* system(cmd) - run a single shell command
|
||||
* wildcard(names) - expand wildcard characters in filanames
|
||||
* filter(m,n,cmd,back) - run text lines through a filter program
|
||||
*
|
||||
* This is probably the single least portable file in the program. The code
|
||||
* shown here should work correctly if it links at all; it will work on UNIX
|
||||
* and any O.S./Compiler combination which adheres to UNIX forking conventions.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "vi.h"
|
||||
extern char **environ;
|
||||
|
||||
#if ANY_UNIX
|
||||
|
||||
/* This is a new version of the system() function. The only difference
|
||||
* between this one and the library one is: this one uses the o_shell option.
|
||||
*/
|
||||
int system(cmd)
|
||||
char *cmd; /* a command to run */
|
||||
{
|
||||
int pid; /* process ID of child */
|
||||
int died;
|
||||
int status; /* exit status of the command */
|
||||
|
||||
|
||||
signal(SIGINT, SIG_IGN);
|
||||
pid = fork();
|
||||
switch (pid)
|
||||
{
|
||||
case -1: /* error */
|
||||
msg("fork() failed");
|
||||
status = -1;
|
||||
break;
|
||||
|
||||
case 0: /* child */
|
||||
/* for the child, close all files except stdin/out/err */
|
||||
for (status = 3; status < 60 && (close(status), errno != EINVAL); status++)
|
||||
{
|
||||
}
|
||||
|
||||
signal(SIGINT, SIG_DFL);
|
||||
if (cmd == o_shell)
|
||||
{
|
||||
execle(o_shell, o_shell, (char *)0, environ);
|
||||
}
|
||||
else
|
||||
{
|
||||
execle(o_shell, o_shell, "-c", cmd, (char *)0, environ);
|
||||
}
|
||||
msg("execle(\"%s\", ...) failed", o_shell);
|
||||
exit(1); /* if we get here, the exec failed */
|
||||
|
||||
default: /* parent */
|
||||
do
|
||||
{
|
||||
died = wait(&status);
|
||||
} while (died >= 0 && died != pid);
|
||||
if (died < 0)
|
||||
{
|
||||
status = -1;
|
||||
}
|
||||
signal(SIGINT, (void (*)()) trapint);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* This private function opens a pipe from a filter. It is similar to the
|
||||
* system() function above, and to popen(cmd, "r").
|
||||
*/
|
||||
int rpipe(cmd, in)
|
||||
char *cmd; /* the filter command to use */
|
||||
int in; /* the fd to use for stdin */
|
||||
{
|
||||
int r0w1[2];/* the pipe fd's */
|
||||
|
||||
/* make the pipe */
|
||||
if (pipe(r0w1) < 0)
|
||||
{
|
||||
return -1; /* pipe failed */
|
||||
}
|
||||
|
||||
/* The parent process (elvis) ignores signals while the filter runs.
|
||||
* The child (the filter program) will reset this, so that it can
|
||||
* catch the signal.
|
||||
*/
|
||||
signal(SIGINT, SIG_IGN);
|
||||
|
||||
switch (fork())
|
||||
{
|
||||
case -1: /* error */
|
||||
return -1;
|
||||
|
||||
case 0: /* child */
|
||||
/* close the "read" end of the pipe */
|
||||
close(r0w1[0]);
|
||||
|
||||
/* redirect stdout to go to the "write" end of the pipe */
|
||||
close(1);
|
||||
dup(r0w1[1]);
|
||||
close(2);
|
||||
dup(r0w1[1]);
|
||||
close(r0w1[1]);
|
||||
|
||||
/* redirect stdin */
|
||||
if (in != 0)
|
||||
{
|
||||
close(0);
|
||||
dup(in);
|
||||
close(in);
|
||||
}
|
||||
|
||||
/* the filter should accept SIGINT signals */
|
||||
signal(SIGINT, SIG_DFL);
|
||||
|
||||
/* exec the shell to run the command */
|
||||
execle(o_shell, o_shell, "-c", cmd, (char *)0, environ);
|
||||
exit(1); /* if we get here, exec failed */
|
||||
|
||||
default: /* parent */
|
||||
/* close the "write" end of the pipe */
|
||||
close(r0w1[1]);
|
||||
|
||||
return r0w1[0];
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* non-DOS */
|
||||
|
||||
#if OSK
|
||||
|
||||
/* This private function opens a pipe from a filter. It is similar to the
|
||||
* system() function above, and to popen(cmd, "r").
|
||||
*/
|
||||
int rpipe(cmd, in)
|
||||
char *cmd; /* the filter command to use */
|
||||
int in; /* the fd to use for stdin */
|
||||
{
|
||||
return osk_popen(cmd, "r", in, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ANY_UNIX || OSK
|
||||
|
||||
/* This function closes the pipe opened by rpipe(), and returns 0 for success */
|
||||
int rpclose(fd)
|
||||
int fd;
|
||||
{
|
||||
int status;
|
||||
|
||||
close(fd);
|
||||
wait(&status);
|
||||
signal(SIGINT, (void (*)()) trapint);
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif /* non-DOS */
|
||||
|
||||
/* This function expands wildcards in a filename or filenames. It does this
|
||||
* by running the "echo" command on the filenames via the shell; it is assumed
|
||||
* that the shell will expand the names for you. If for any reason it can't
|
||||
* run echo, then it returns the names unmodified.
|
||||
*/
|
||||
|
||||
#if MSDOS || TOS
|
||||
#define PROG "wildcard "
|
||||
#define PROGLEN 9
|
||||
#include <string.h>
|
||||
#else
|
||||
#define PROG "echo "
|
||||
#define PROGLEN 5
|
||||
#endif
|
||||
|
||||
#if !AMIGA
|
||||
char *wildcard(names)
|
||||
char *names;
|
||||
{
|
||||
|
||||
# if VMS
|
||||
/*
|
||||
We could use expand() [vmswild.c], but what's the point on VMS?
|
||||
Anyway, echo is the wrong thing to do, it takes too long to build
|
||||
a subprocess on VMS and any "echo" program would have to be supplied
|
||||
by elvis. More importantly, many VMS utilities expand names
|
||||
themselves (the shell doesn't do any expansion) so the concept is
|
||||
non-native. jdc
|
||||
*/
|
||||
return names;
|
||||
# else
|
||||
|
||||
int i, j, fd;
|
||||
REG char *s, *d;
|
||||
|
||||
|
||||
/* build the echo command */
|
||||
if (names != tmpblk.c)
|
||||
{
|
||||
/* the names aren't in tmpblk.c, so we can do it the easy way */
|
||||
strcpy(tmpblk.c, PROG);
|
||||
strcat(tmpblk.c, names);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* the names are already in tmpblk.c, so shift them to make
|
||||
* room for the word "echo "
|
||||
*/
|
||||
for (s = names + strlen(names) + 1, d = s + PROGLEN; s > names; )
|
||||
{
|
||||
*--d = *--s;
|
||||
}
|
||||
strncpy(names, PROG, PROGLEN);
|
||||
}
|
||||
|
||||
/* run the command & read the resulting names */
|
||||
fd = rpipe(tmpblk.c, 0);
|
||||
if (fd < 0) return names;
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
j = tread(fd, tmpblk.c + i, BLKSIZE - i);
|
||||
i += j;
|
||||
} while (j > 0);
|
||||
|
||||
/* successful? */
|
||||
if (rpclose(fd) == 0 && j == 0 && i < BLKSIZE && i > 0)
|
||||
{
|
||||
tmpblk.c[i-1] = '\0'; /* "i-1" so we clip off the newline */
|
||||
return tmpblk.c;
|
||||
}
|
||||
else
|
||||
{
|
||||
return names;
|
||||
}
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This function runs a range of lines through a filter program, and replaces
|
||||
* the original text with the filtered version. As a special case, if "to"
|
||||
* is MARK_UNSET, then it runs the filter program with stdin coming from
|
||||
* /dev/null, and inserts any output lines.
|
||||
*/
|
||||
int filter(from, to, cmd, back)
|
||||
MARK from, to; /* the range of lines to filter */
|
||||
char *cmd; /* the filter command */
|
||||
int back; /* boolean: will we read lines back? */
|
||||
{
|
||||
int scratch; /* fd of the scratch file */
|
||||
int fd; /* fd of the pipe from the filter */
|
||||
char scrout[50]; /* name of the scratch out file */
|
||||
MARK new; /* place where new text should go */
|
||||
long sent, rcvd; /* number of lines sent/received */
|
||||
int i, j;
|
||||
|
||||
/* write the lines (if specified) to a temp file */
|
||||
if (to)
|
||||
{
|
||||
/* we have lines */
|
||||
#if MSDOS || TOS
|
||||
strcpy(scrout, o_directory);
|
||||
if ((i=strlen(scrout)) && !strchr("\\/:", scrout[i-1]))
|
||||
scrout[i++]=SLASH;
|
||||
strcpy(scrout+i, SCRATCHOUT+3);
|
||||
#else
|
||||
sprintf(scrout, SCRATCHOUT, o_directory);
|
||||
#endif
|
||||
mktemp(scrout);
|
||||
cmd_write(from, to, CMD_BANG, FALSE, scrout);
|
||||
sent = markline(to) - markline(from) + 1L;
|
||||
|
||||
/* use those lines as stdin */
|
||||
scratch = open(scrout, O_RDONLY);
|
||||
if (scratch < 0)
|
||||
{
|
||||
unlink(scrout);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
scratch = 0;
|
||||
sent = 0L;
|
||||
}
|
||||
|
||||
/* start the filter program */
|
||||
#if VMS
|
||||
/*
|
||||
VMS doesn't know a thing about file descriptor 0. The rpipe
|
||||
concept is non-portable. Hence we need a file name argument.
|
||||
*/
|
||||
fd = rpipe(cmd, scratch, scrout);
|
||||
#else
|
||||
fd = rpipe(cmd, scratch);
|
||||
#endif
|
||||
if (fd < 0)
|
||||
{
|
||||
if (to)
|
||||
{
|
||||
close(scratch);
|
||||
unlink(scrout);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (back)
|
||||
{
|
||||
ChangeText
|
||||
{
|
||||
/* adjust MARKs for whole lines, and set "new" */
|
||||
from &= ~(BLKSIZE - 1);
|
||||
if (to)
|
||||
{
|
||||
to &= ~(BLKSIZE - 1);
|
||||
to += BLKSIZE;
|
||||
new = to;
|
||||
}
|
||||
else
|
||||
{
|
||||
new = from + BLKSIZE;
|
||||
}
|
||||
|
||||
#if VMS
|
||||
/* Reading from a VMS mailbox (pipe) is record oriented... */
|
||||
# define tread vms_pread
|
||||
#endif
|
||||
|
||||
/* repeatedly read in new text and add it */
|
||||
rcvd = 0L;
|
||||
while ((i = tread(fd, tmpblk.c, BLKSIZE - 1)) > 0)
|
||||
{
|
||||
tmpblk.c[i] = '\0';
|
||||
add(new, tmpblk.c);
|
||||
#if VMS
|
||||
/* What! An advantage to record oriented reads? */
|
||||
new += (i - 1);
|
||||
new = (new & ~(BLKSIZE - 1)) + BLKSIZE;
|
||||
rcvd++;
|
||||
#else
|
||||
for (i = 0; tmpblk.c[i]; i++)
|
||||
{
|
||||
if (tmpblk.c[i] == '\n')
|
||||
{
|
||||
new = (new & ~(BLKSIZE - 1)) + BLKSIZE;
|
||||
rcvd++;
|
||||
}
|
||||
else
|
||||
{
|
||||
new++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* delete old text, if any */
|
||||
if (to)
|
||||
{
|
||||
cut(from, to);
|
||||
delete(from, to);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* read the command's output, and copy it to the screen */
|
||||
while ((i = tread(fd, tmpblk.c, BLKSIZE - 1)) > 0)
|
||||
{
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
addch(tmpblk.c[j]);
|
||||
}
|
||||
}
|
||||
rcvd = 0;
|
||||
}
|
||||
|
||||
/* Reporting... */
|
||||
if (sent >= *o_report || rcvd >= *o_report)
|
||||
{
|
||||
if (sent > 0L && rcvd > 0L)
|
||||
{
|
||||
msg("%ld lines out, %ld lines back", sent, rcvd);
|
||||
}
|
||||
else if (sent > 0)
|
||||
{
|
||||
msg("%ld lines written to filter", sent);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg("%ld lines read from filter", rcvd);
|
||||
}
|
||||
}
|
||||
rptlines = 0L;
|
||||
|
||||
/* cleanup */
|
||||
rpclose(fd);
|
||||
if (to)
|
||||
{
|
||||
close(scratch);
|
||||
unlink(scrout);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,230 +0,0 @@
|
|||
/* tinyprnt.c */
|
||||
|
||||
#if OSK
|
||||
#define sprintf Sprintf
|
||||
#endif
|
||||
|
||||
/* This is a limited version of sprintf(). It is useful for Minix-PC and
|
||||
* Coherent-286 because those systems are both limited to 64k+64k and the
|
||||
* standard sprintf() is just too damn big.
|
||||
*
|
||||
* It should also be useful for OS-9 because OS-9's sprintf() doesn't
|
||||
* understand the true meaning of asterisks in a format string. This one
|
||||
* does.
|
||||
*/
|
||||
|
||||
/* Place-holders in format strings look like "%<pad><clip><type>".
|
||||
*
|
||||
* The <pad> adds space to the front (or, if negative, to the back) of the
|
||||
* output value, to pad it to a given width. If <pad> is absent, then 0 is
|
||||
* assumed. If <pad> is an asterisk, then the next argument is assumed to
|
||||
* be an (int) which used as the pad width.
|
||||
*
|
||||
* The <clip> string can be absent, in which case no clipping is done.
|
||||
* However, if it is present, then it should be either a "." followed by
|
||||
* a number, or a "." followed by an asterisk. The asterisk means that the
|
||||
* next argument is an (int) which should be used as the pad width. Clipping
|
||||
* only affects strings; for other data types it is ignored.
|
||||
*
|
||||
* The <type> is one of "s" for strings, "c" for characters (really ints that
|
||||
* are assumed to be legal char values), "d" for ints, "ld" for long ints, or
|
||||
* "%" to output a percent sign.
|
||||
*/
|
||||
|
||||
/* NOTE: Variable argument lists are handled by direct stack-twiddling. Sorry! */
|
||||
|
||||
static void cvtnum(buf, num, base)
|
||||
char *buf; /* where to store the number */
|
||||
unsigned long num; /* the number to convert */
|
||||
int base; /* either 8, 10, or 16 */
|
||||
{
|
||||
static char digits[] = "0123456789abcdef";
|
||||
unsigned long tmp;
|
||||
|
||||
/* if the number is 0, then just stuff a "0" into the buffer */
|
||||
if (num == 0L)
|
||||
{
|
||||
buf[0] = '0';
|
||||
buf[1] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
/* use tmp to figure out how many digits we'll need */
|
||||
for (tmp = num; tmp > 0; tmp /= base)
|
||||
{
|
||||
buf++;
|
||||
}
|
||||
|
||||
/* mark the spot that will be the end of the string */
|
||||
*buf = '\0';
|
||||
|
||||
/* generate all digits, as needed */
|
||||
for (tmp = num; tmp > 0; tmp /= base)
|
||||
{
|
||||
*--buf = digits[tmp % base];
|
||||
}
|
||||
}
|
||||
|
||||
int sprintf(buf, fmt, argref)
|
||||
char *buf; /* where to deposit the formatted output */
|
||||
char *fmt; /* the format string */
|
||||
int argref; /* the first argument is located at &argref */
|
||||
{
|
||||
char *argptr;/* pointer to next argument on the stack */
|
||||
int pad; /* value of the pad string */
|
||||
int clip; /* value of the clip string */
|
||||
long num; /* a binary number being converted to ASCII digits */
|
||||
long digit; /* used during conversion */
|
||||
char *src, *dst;
|
||||
|
||||
/* make argptr point to the first argument after the format string */
|
||||
argptr = (char *)&argref;
|
||||
|
||||
/* loop through the whole format string */
|
||||
while (*fmt)
|
||||
{
|
||||
/* if not part of a place-holder, then copy it literally */
|
||||
if (*fmt != '%')
|
||||
{
|
||||
*buf++ = *fmt++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* found a place-holder! Get <pad> value */
|
||||
fmt++;
|
||||
if ('*' == *fmt)
|
||||
{
|
||||
pad = *((int *)argptr)++;
|
||||
fmt++;
|
||||
}
|
||||
else if (*fmt == '-' || (*fmt >= '0' && *fmt <= '9'))
|
||||
{
|
||||
pad = atol(fmt);
|
||||
do
|
||||
{
|
||||
fmt++;
|
||||
} while (*fmt >= '0' && *fmt <= '9');
|
||||
}
|
||||
else
|
||||
{
|
||||
pad = 0;
|
||||
}
|
||||
|
||||
/* get a <clip> value */
|
||||
if (*fmt == '.')
|
||||
{
|
||||
fmt++;
|
||||
if ('*' == *fmt)
|
||||
{
|
||||
clip = *((int *)argptr)++;
|
||||
fmt++;
|
||||
}
|
||||
else if (*fmt >= '0' && *fmt <= '9')
|
||||
{
|
||||
clip = atol(fmt);
|
||||
do
|
||||
{
|
||||
fmt++;
|
||||
} while (*fmt >= '0' && *fmt <= '9');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
clip = 0;
|
||||
}
|
||||
|
||||
/* handle <type>, possibly noticing <clip> */
|
||||
switch (*fmt++)
|
||||
{
|
||||
case 'c':
|
||||
buf[0] = *((int *)argptr)++;
|
||||
buf[1] = '\0';
|
||||
break;
|
||||
|
||||
case 's':
|
||||
src = *((char **)argptr)++;
|
||||
if (!src)
|
||||
{
|
||||
src = "(null)";
|
||||
}
|
||||
if (clip)
|
||||
{
|
||||
strncpy(buf, src, clip);
|
||||
buf[clip] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(buf, src);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
fmt++; /* to skip the "d" in "%ld" */
|
||||
num = *((long *)argptr)++;
|
||||
dst = buf;
|
||||
if (num < 0)
|
||||
{
|
||||
*dst++ = '-';
|
||||
num = -num;
|
||||
}
|
||||
cvtnum(dst, num, 10);
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
num = *((int *)argptr)++;
|
||||
cvtnum(buf, num, 16);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
num = *((int *)argptr)++;
|
||||
dst = buf;
|
||||
if (num < 0)
|
||||
{
|
||||
*dst++ = '-';
|
||||
num = -num;
|
||||
}
|
||||
cvtnum(dst, num, 10);
|
||||
break;
|
||||
|
||||
default:
|
||||
buf[0] = fmt[-1];
|
||||
buf[1] = '\0';
|
||||
}
|
||||
|
||||
/* now fix the padding, if the value is too short */
|
||||
clip = strlen(buf);
|
||||
if (pad < 0)
|
||||
{
|
||||
/* add spaces after the value */
|
||||
pad = -pad - clip;
|
||||
for (buf += clip; pad > 0; pad--)
|
||||
{
|
||||
*buf++ = ' ';
|
||||
}
|
||||
*buf = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
/* add spaces before the value */
|
||||
pad -= clip;
|
||||
if (pad > 0)
|
||||
{
|
||||
src = buf + clip;
|
||||
dst = src + pad;
|
||||
*dst = '\0';
|
||||
while (src > buf)
|
||||
{
|
||||
*--dst = *--src;
|
||||
}
|
||||
while (dst > buf)
|
||||
{
|
||||
*--dst = ' ';
|
||||
}
|
||||
}
|
||||
buf += strlen(buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* mark the end of the output string */
|
||||
*buf = '\0';
|
||||
}
|
|
@ -1,388 +0,0 @@
|
|||
/* tinytcap.c */
|
||||
|
||||
/* This file contains functions which simulate the termcap functions.
|
||||
*
|
||||
* It doesn't access a "termcap" file. Instead, it uses an initialized array
|
||||
* of strings to store the entries. Any string that doesn't start with a ':'
|
||||
* is taken to be the name of a type of terminal. Any string that does start
|
||||
* with a ':' is interpretted as the list of fields describing all of the
|
||||
* terminal types that precede it.
|
||||
*
|
||||
* Note: since these are C strings, you can't use special sequences like
|
||||
* ^M or \E in the fields; your C compiler won't understand them. Also,
|
||||
* at run time there is no way to tell the difference between ':' and '\072'
|
||||
* so I sure hope your terminal definition doesn't require a ':' character.
|
||||
*
|
||||
* getenv(TERM) on VMS checks the SET TERM device setting. To implement
|
||||
* non-standard terminals set the logical ELVIS_TERM in VMS. (jdc)
|
||||
*
|
||||
* Other possible terminal types are...
|
||||
* TERM_WYSE925 - "wyse925", a Wyse 50 terminal emulating Televideo 925
|
||||
* ... or you could set $TERMCAP to the terminal's description string, which
|
||||
* $TERM set up to match it.
|
||||
*
|
||||
* Note that you can include several terminal types at the same time. Elvis
|
||||
* chooses which entry to use at runtime, based primarily on the value of $TERM.
|
||||
*/
|
||||
|
||||
|
||||
#include "config.h"
|
||||
extern char *getenv();
|
||||
|
||||
/* decide which terminal descriptions should *always* be included. */
|
||||
#if MSDOS
|
||||
# define TERM_NANSI
|
||||
# define TERM_DOSANSI
|
||||
# if RAINBOW
|
||||
# define TERM_RAINBOW
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if VMS
|
||||
# define TERM_VT100
|
||||
# define TERM_VT100W
|
||||
# define TERM_VT52
|
||||
#endif
|
||||
|
||||
#if AMIGA
|
||||
# define TERM_AMIGA /* Internal Amiga termcap entry */
|
||||
/* # define TERM_VT52 /* The rest of these are here for those */
|
||||
# define TERM_VT100 /* people who want to use elvis over an */
|
||||
/* # define TERM_NANSI /* AUX: port (serial.device). */
|
||||
/* # define TERM_DOSANSI /* Take out all but AMIGA to save memory. */
|
||||
/* # define TERM_MINIX /* Vanilla ANSI? */
|
||||
/* # define TERM_925 /* Hang a terminal off your Amiga */
|
||||
#endif
|
||||
|
||||
#if MINIX || UNIXV
|
||||
# define TERM_MINIX
|
||||
#endif
|
||||
|
||||
#if COHERENT
|
||||
# define TERM_COHERENT
|
||||
#endif
|
||||
|
||||
#if TOS
|
||||
# define TERM_ATARI
|
||||
#endif
|
||||
|
||||
static char *termcap[] =
|
||||
{
|
||||
#ifdef TERM_AMIGA
|
||||
"AA",
|
||||
"amiga",
|
||||
"Amiga ANSI",
|
||||
/* Amiga termcap modified from version 1.3 by Kent Polk */
|
||||
":co#80:li#24:am:bs:bw:xn:\
|
||||
:AL=\233%dL:DC=\233%dP:DL=\233%dM:DO=\233%dB:\
|
||||
:LE=\233%dD:RI=\233%dC:SF=\233%dS:SR=\233%dT:UP=\233%dA:IC=\233%d@:\
|
||||
:ae=\2330m:al=\233L:as=\2333m:bl=\007:bt=\233Z:cd=\233J:\
|
||||
:ce=\233K:cl=\013:cm=\233%i%d;%dH:dc=\233P:dl=\233M:do=\233B:\
|
||||
:kb=^H:ho=\233H:ic=\233@:is=\23320l:\
|
||||
:mb=\2337;2m:md=\2331m:me=\2330m:mh=\2332m:mk=\2338m:mr=\2337m:nd=\233C:\
|
||||
:rs=\033c:se=\2330m:sf=\233S:so=\2337m:sb=\233T:sr=\233T:ue=\23323m:\
|
||||
:up=\233A:us=\2334m:vb=\007:ve=\233\040p:vi=\2330\040p:\
|
||||
:k1=\2330~:k2=\2331~:k3=\2332~:k4=\2333~:k5=\2334~:\
|
||||
:k6=\2335~:k7=\2336~:k8=\2337~:k9=\2338~:k0=\2339~:\
|
||||
:s1=\23310~:s2=\23311~:s3=\23312~:s4=\23313~:s5=\23314~:\
|
||||
:s6=\23315~:s7=\23316~:s8=\23317~:s9=\23318~:s0=\23319~:\
|
||||
:kd=\233B:kl=\233D:kn#10:kr=\233C:ku=\233A:le=\233D:\
|
||||
:kP=\233T:kN=\233S:kh=\233\040A:kH=\233\040@:",
|
||||
#endif
|
||||
|
||||
#ifdef TERM_NANSI
|
||||
"fansi",
|
||||
"nnansi",
|
||||
"nansi",
|
||||
"pcbios",
|
||||
":al=\033[L:dl=\033[M:am:bs:ce=\033[K:cl=\033[2J:\
|
||||
:cm=\033[%i%d;%dH:co#80:do=\033[B:\
|
||||
:k1=#;:k2=#<:k3=#=:k4=#>:k5=#?:k6=#@:k7=#A:k8=#B:k9=#C:k0=#D:\
|
||||
:s1=#T:s2=#U:s3=#V:s4=#W:s5=#X:s6=#Y:s7=#Z:s8=#[:s9=#\\:s0=#]:\
|
||||
:c1=#^:c2=#_:c3=#`:c4=#a:c5=#b:c6=#c:c7=#d:c8=#e:c9=#f:c0=#g:\
|
||||
:a1=#h:a2=#i:a3=#j:a4=#k:a5=#l:a6=#m:a7=#n:a8=#o:a9=#p:a0=#q:\
|
||||
:kd=#P:kh=#G:kH=#O:kI=#R:kl=#K:kN=#Q:kP=#I:kr=#M:ku=#H:\
|
||||
:li#25:md=\033[1m:me=\033[m:nd=\033[C:se=\033[m:so=\033[7m:\
|
||||
:ue=\033[m:up=\033[A:us=\033[4m:",
|
||||
#endif
|
||||
|
||||
#ifdef TERM_DOSANSI
|
||||
#if !ANY_UNIX
|
||||
"ansi",
|
||||
#endif
|
||||
"dosansi",
|
||||
":am:bs:ce=\033[K:cl=\033[2J:\
|
||||
:cm=\033[%i%d;%dH:co#80:do=\033[B:\
|
||||
:k1=#;:k2=#<:k3=#=:k4=#>:k5=#?:k6=#@:k7=#A:k8=#B:k9=#C:k0=#D:\
|
||||
:s1=#T:s2=#U:s3=#V:s4=#W:s5=#X:s6=#Y:s7=#Z:s8=#[:s9=#\\:s0=#]:\
|
||||
:c1=#^:c2=#_:c3=#`:c4=#a:c5=#b:c6=#c:c7=#d:c8=#e:c9=#f:c0=#g:\
|
||||
:a1=#h:a2=#i:a3=#j:a4=#k:a5=#l:a6=#m:a7=#n:a8=#o:a9=#p:a0=#q:\
|
||||
:kd=#P:kh=#G:kH=#O:kI=#R:kl=#K:kN=#Q:kP=#I:kr=#M:ku=#H:\
|
||||
:li#25:md=\033[1m:me=\033[m:nd=\033[C:se=\033[m:so=\033[7m:\
|
||||
:ue=\033[m:up=\033[A:us=\033[4m:",
|
||||
#endif
|
||||
|
||||
#ifdef TERM_RAINBOW
|
||||
"vt220",
|
||||
"rainbow",
|
||||
":al=\033[L:dl=\033[M:am:bs:ce=\033[K:cl=\033[2J:\
|
||||
:cm=\033[%i%d;%dH:co#80:do=\033[B:kd=\033[B:kl=\033[D:\
|
||||
:kr=\033[C:ku=\033[A:kP=\033[5~:kN=\033[6~:kI=\033[2~:\
|
||||
:li#24:md=\033[1m:me=\033[m:nd=\033[C:se=\033[m:so=\033[7m:\
|
||||
:ue=\033[m:up=\033[A:us=\033[4m:xn:",
|
||||
#endif
|
||||
|
||||
#ifdef TERM_VT100
|
||||
"vt100-80",
|
||||
"vt200-80",
|
||||
"vt300-80",
|
||||
"vt101-80",
|
||||
"vt102-80",
|
||||
":al=\033[L:am:bs:ce=\033[K:cl=\033[2J:cm=\033[%i%d;%dH:\
|
||||
:co#80:dl=\033[M:do=\033[B:k0=\033[20~:k1=\033[1~:\
|
||||
:k2=\033[2~:k3=\033[3~:k4=\033[4~:k5=\033[5~:k6=\033[6~:\
|
||||
:k7=\033[17~:k8=\033[18~:k9=\033[19~:kd=\033[B:kh=\033[H:\
|
||||
:kH=\033[Y:kI=\033[I:kl=\033[D:kN=\033[U:kP=\033[V:\
|
||||
:kr=\033[C:ku=\033[A:li#24:md=\033[1m:me=\033[m:nd=\033[C:\
|
||||
:se=\033[m:so=\033[7m:ti=\033[1;24r\033[24;1H:\
|
||||
:ue=\033[m:up=\033[A:us=\033[4m:xn:",
|
||||
#endif
|
||||
|
||||
#ifdef TERM_VT100W
|
||||
"vt100-w",
|
||||
"vt200-w",
|
||||
"vt300-w",
|
||||
"vt101-w",
|
||||
"vt102-w",
|
||||
"vt100-132",
|
||||
"vt200-132",
|
||||
"vt300-132",
|
||||
"vt101-132",
|
||||
"vt102-132",
|
||||
":al=\033[L:am:bs:ce=\033[K:cl=\033[2J:cm=\033[%i%d;%dH:\
|
||||
:co#132:dl=\033[M:do=\033[B:k0=\033[20~:k1=\033[1~:\
|
||||
:k2=\033[2~:k3=\033[3~:k4=\033[4~:k5=\033[5~:k6=\033[6~:\
|
||||
:k7=\033[17~:k8=\033[18~:k9=\033[19~:kd=\033[B:kh=\033[H:\
|
||||
:kH=\033[Y:kI=\033[I:kl=\033[D:kN=\033[U:kP=\033[V:\
|
||||
:kr=\033[C:ku=\033[A:li#24:md=\033[1m:me=\033[m:nd=\033[C:\
|
||||
:se=\033[m:so=\033[7m:ti=\033[1;24r\033[24;1H:\
|
||||
:ue=\033[m:up=\033[A:us=\033[4m:xn:",
|
||||
#endif
|
||||
|
||||
#ifdef TERM_VT52
|
||||
"vt52",
|
||||
":do=\n:le=\b:up=\033A:nd=\033C:cm=\033Y%+ %+ :ti=\033e\033v:\
|
||||
:sr=\033I:cd=\033J:ce=\033K:cl=\033H\033J:co#80:li#24:\
|
||||
:ku=\033A:kd=\033B:kr=\033C:kl=\033D:kb=\b:pt:am:xn:bs:",
|
||||
#endif
|
||||
|
||||
#ifdef TERM_MINIX
|
||||
"minix",
|
||||
"ansi",
|
||||
"AT386",
|
||||
":al=\033[L:am:bs:ce=\033[K:cl=\033[2J:cm=\033[%i%d;%dH:\
|
||||
:co#80:dl=\033[M:do=\033[B:k0=\033[20~:k1=\033[1~:\
|
||||
:k2=\033[2~:k3=\033[3~:k4=\033[4~:k5=\033[5~:k6=\033[6~:\
|
||||
:k7=\033[17~:k8=\033[18~:k9=\033[19~:kd=\033[B:kh=\033[H:\
|
||||
:kH=\033[Y:kI=\033[I:kl=\033[D:kN=\033[U:kP=\033[V:\
|
||||
:kr=\033[C:ku=\033[A:li#25:md=\033[1m:me=\033[m:nd=\033[C:\
|
||||
:se=\033[m:so=\033[7m:ue=\033[m:up=\033[A:us=\033[4m:",
|
||||
#endif /* MINIX */
|
||||
|
||||
#ifdef TERM_COHERENT
|
||||
"coherent",
|
||||
"ansipc",
|
||||
":al=\033[L:am:bs:ce=\033[K:cl=\033[2J:cm=\033[%i%d;%dH:\
|
||||
:co#80:dl=\033[M:do=\033[B:k0=\033[0x:k1=\033[1x:k2=\033[2x:\
|
||||
:k3=\033[3x:k4=\033[4x:k5=\033[5x:k6=\033[6x:\
|
||||
:k7=\033[7x:k8=\033[8x:k9=\033[9x:kd=\033[B:kh=\033[H:\
|
||||
:kH=\033[24H:kI=\033[@:kl=\033[D:kN=\033[U:kP=\033[V:\
|
||||
:kr=\033[C:ku=\033[A:li#24:md=\033[1m:me=\033[m:\
|
||||
:nd=\033[C:se=\033[m:so=\033[7m:ue=\033[m:up=\033[A:\
|
||||
:us=\033[4m:",
|
||||
#endif /* COHERENT */
|
||||
|
||||
#ifdef TERM_ATARI
|
||||
"atari-st",
|
||||
"vt52",
|
||||
":al=\033L:am:bs:ce=\033K:cl=\033E:cm=\033Y%i%+ %+ :\
|
||||
:co#80:dl=\033M:do=\033B:\
|
||||
:k1=#;:k2=#<:k3=#=:k4=#>:k5=#?:k6=#@:k7=#A:k8=#B:k9=#C:k0=#D:\
|
||||
:s1=#T:s2=#U:s3=#V:s4=#W:s5=#X:s6=#Y:s7=#Z:s8=#[:s9=#\\:s0=#]:\
|
||||
:c1=#^:c2=#_:c3=#`:c4=#a:c5=#b:c6=#c:c7=#d:c8=#e:c9=#f:c0=#g:\
|
||||
:a1=#h:a2=#i:a3=#j:a4=#k:a5=#l:a6=#m:a7=#n:a8=#o:a9=#p:a0=#q:\
|
||||
kd=#P:kh=#G:kI=#R:kl=#K:kr=#M:ku=#H:li#25:nd=\033C:se=\033q:\
|
||||
:so=\033p:te=:ti=\033e\033v:up=\033A:",
|
||||
#endif
|
||||
|
||||
#ifdef TERM_925
|
||||
"wyse925",
|
||||
":xn@:\
|
||||
:hs:am:bs:co#80:li#24:cm=\033=%+ %+ :cl=\033*:cd=\033y:\
|
||||
:ce=\033t:is=\033l\033\":\
|
||||
:al=\033E:dl=\033R:im=:ei=:ic=\033Q:dc=\033W:\
|
||||
:ho=\036:nd=\014:bt=\033I:pt:so=\033G4:se=\033G0:sg#1:us=\033G8:ue=\033G0:ug#1:\
|
||||
:up=\013:do=\026:kb=\010:ku=\013:kd=\026:kl=\010:kr=\014:\
|
||||
:kh=\036:ma=\026\012\014 :\
|
||||
:k1=\001@\r:k2=\001A\r:k3=\001B\r:k4=\001C\r:k5=\001D\r:k6=\001E\r:k7=\001F\r:\
|
||||
:k8=\001G\r:k9=\001H\r:k0=\001I\r:ko=ic,dc,al,dl,cl,ce,cd,bt:\
|
||||
:ts=\033f:fs=\033g:ds=\033h:sr=\033j:", /* was :xn: for tvi925 alone*/
|
||||
#endif
|
||||
|
||||
(char *)0
|
||||
};
|
||||
|
||||
|
||||
static char *fields;
|
||||
|
||||
|
||||
/*ARGSUSED*/
|
||||
int tgetent(bp, name)
|
||||
char *bp; /* buffer for storing the entry -- ignored */
|
||||
char *name; /* name of the entry */
|
||||
{
|
||||
int i;
|
||||
|
||||
/* if TERMCAP is defined, and seems to match, then use it */
|
||||
fields = getenv("TERMCAP");
|
||||
if (fields)
|
||||
{
|
||||
for (i = 0; fields[i] && fields[i] != ':'; i++)
|
||||
{
|
||||
if (!strncmp(fields + i, name, strlen(name)))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* locate the entry in termcap[] */
|
||||
for (i = 0; termcap[i] && strcmp(termcap[i], name); i++)
|
||||
{
|
||||
}
|
||||
if (!termcap[i])
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* search forward for fields */
|
||||
while (termcap[i][0] != ':')
|
||||
{
|
||||
i++;
|
||||
}
|
||||
fields = termcap[i];
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static char *find(id, vtype)
|
||||
char *id; /* name of a value to locate */
|
||||
int vtype; /* '=' for strings, '#' for numbers, or 0 for bools */
|
||||
{
|
||||
int i;
|
||||
|
||||
/* search for a ':' followed by the two-letter id */
|
||||
for (i = 0; fields[i]; i++)
|
||||
{
|
||||
if (fields[i] == ':'
|
||||
&& fields[i + 1] == id[0]
|
||||
&& fields[i + 2] == id[1])
|
||||
{
|
||||
/* if correct type, then return its value */
|
||||
if (fields[i + 3] == vtype)
|
||||
return &fields[i + 4];
|
||||
else
|
||||
return (char *)0;
|
||||
}
|
||||
}
|
||||
return (char *)0;
|
||||
}
|
||||
|
||||
int tgetnum(id)
|
||||
char *id;
|
||||
{
|
||||
id = find(id, '#');
|
||||
if (id)
|
||||
{
|
||||
return atoi(id);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int tgetflag(id)
|
||||
char *id;
|
||||
{
|
||||
if (find(id, ':'))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
char *tgetstr(id, bp)
|
||||
char *id;
|
||||
char **bp; /* pointer to pointer to buffer - ignored */
|
||||
{
|
||||
char *cpy;
|
||||
|
||||
/* find the string */
|
||||
id = find(id, '=');
|
||||
if (!id)
|
||||
{
|
||||
return (char *)0;
|
||||
}
|
||||
|
||||
/* copy it into the buffer, and terminate it with NUL */
|
||||
for (cpy = *bp; *id != ':'; )
|
||||
{
|
||||
if (id[0] == '\\' && id[1] == 'E')
|
||||
*cpy++ = '\033', id += 2;
|
||||
else
|
||||
*cpy++ = *id++;
|
||||
}
|
||||
*cpy++ = '\0';
|
||||
|
||||
/* update the bp pointer */
|
||||
id = *bp;
|
||||
*bp = cpy;
|
||||
|
||||
/* return a pointer to the copy of the string */
|
||||
return id;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
char *tgoto(cm, destcol, destrow)
|
||||
char *cm; /* cursor movement string -- ignored */
|
||||
int destcol;/* destination column, 0 - 79 */
|
||||
int destrow;/* destination row, 0 - 24 */
|
||||
{
|
||||
static char buf[30];
|
||||
|
||||
#ifdef CRUNCH
|
||||
# if TOS
|
||||
sprintf(buf, "\033Y%c%c", ' ' + destrow, ' ' + destcol);
|
||||
# else
|
||||
sprintf(buf, "\033[%d;%dH", destrow + 1, destcol + 1);
|
||||
# endif
|
||||
#else
|
||||
if (cm[1] == 'Y' || cm[1] == '=')
|
||||
sprintf(buf, "\033%c%c%c", cm[1], ' ' + destrow, ' ' + destcol);
|
||||
else
|
||||
sprintf(buf, "\033[%d;%dH", destrow + 1, destcol + 1);
|
||||
#endif
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
void tputs(cp, affcnt, outfn)
|
||||
char *cp; /* the string to output */
|
||||
int affcnt; /* number of affected lines -- ignored */
|
||||
int (*outfn)(); /* the output function */
|
||||
{
|
||||
while (*cp)
|
||||
{
|
||||
(*outfn)(*cp);
|
||||
cp++;
|
||||
}
|
||||
}
|
1026
commands/elvis/tio.c
1026
commands/elvis/tio.c
File diff suppressed because it is too large
Load diff
|
@ -1,762 +0,0 @@
|
|||
/* tmp.c */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* 14407 SW Teal Blvd. #C
|
||||
* Beaverton, OR 97005
|
||||
* kirkenda@cs.pdx.edu
|
||||
*/
|
||||
|
||||
|
||||
/* This file contains functions which create & readback a TMPFILE */
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include "vi.h"
|
||||
#if TOS
|
||||
# include <stat.h>
|
||||
#else
|
||||
# if OSK
|
||||
# include "osk.h"
|
||||
# else
|
||||
# if AMIGA
|
||||
# include "amistat.h"
|
||||
# else
|
||||
# include <sys/stat.h>
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
#if TURBOC
|
||||
# include <process.h>
|
||||
#endif
|
||||
|
||||
#ifndef NO_MODELINES
|
||||
static void do_modelines(l, stop)
|
||||
long l; /* line number to start at */
|
||||
long stop; /* line number to stop at */
|
||||
{
|
||||
char *str; /* used to scan through the line */
|
||||
char *start; /* points to the start of the line */
|
||||
char buf[80];
|
||||
|
||||
/* if modelines are disabled, then do nothing */
|
||||
if (!*o_modelines)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* for each line... */
|
||||
for (; l <= stop; l++)
|
||||
{
|
||||
/* for each position in the line.. */
|
||||
for (str = fetchline(l); *str; str++)
|
||||
{
|
||||
/* if it is the start of a modeline command... */
|
||||
if ((str[0] == 'e' && str[1] == 'x'
|
||||
|| str[0] == 'v' && str[1] == 'i')
|
||||
&& str[2] == ':')
|
||||
{
|
||||
start = str += 3;
|
||||
|
||||
/* find the end */
|
||||
for (str = start + strlen(start); *--str != ':'; )
|
||||
{
|
||||
}
|
||||
|
||||
/* if it is a well-formed modeline, execute it */
|
||||
if (str > start && str - start < sizeof buf)
|
||||
{
|
||||
strncpy(buf, start, (int)(str - start));
|
||||
exstring(buf, str - start, '\\');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* The FAIL() macro prints an error message and then exits. */
|
||||
#define FAIL(why,arg) mode = MODE_EX; msg(why, arg); endwin(); exit(9)
|
||||
|
||||
/* This is the name of the temp file */
|
||||
static char tmpname[80];
|
||||
|
||||
/* This function creates the temp file and copies the original file into it.
|
||||
* Returns if successful, or stops execution if it fails.
|
||||
*/
|
||||
int tmpstart(filename)
|
||||
char *filename; /* name of the original file */
|
||||
{
|
||||
int origfd; /* fd used for reading the original file */
|
||||
struct stat statb; /* stat buffer, used to examine inode */
|
||||
REG BLK *this; /* pointer to the current block buffer */
|
||||
REG BLK *next; /* pointer to the next block buffer */
|
||||
int inbuf; /* number of characters in a buffer */
|
||||
int nread; /* number of bytes read */
|
||||
REG int j, k;
|
||||
int i;
|
||||
long nbytes;
|
||||
|
||||
/* switching to a different file certainly counts as a change */
|
||||
changes++;
|
||||
redraw(MARK_UNSET, FALSE);
|
||||
|
||||
/* open the original file for reading */
|
||||
*origname = '\0';
|
||||
if (filename && *filename)
|
||||
{
|
||||
strcpy(origname, filename);
|
||||
origfd = open(origname, O_RDONLY);
|
||||
if (origfd < 0 && errno != ENOENT)
|
||||
{
|
||||
msg("Can't open \"%s\"", origname);
|
||||
return tmpstart("");
|
||||
}
|
||||
if (origfd >= 0)
|
||||
{
|
||||
if (stat(origname, &statb) < 0)
|
||||
{
|
||||
FAIL("Can't stat \"%s\"", origname);
|
||||
}
|
||||
#if TOS
|
||||
if (origfd >= 0 && (statb.st_mode & S_IJDIR))
|
||||
#else
|
||||
# if OSK
|
||||
if (origfd >= 0 && (statb.st_mode & S_IFDIR))
|
||||
# else
|
||||
if (origfd >= 0 && (statb.st_mode & S_IFMT) != S_IFREG)
|
||||
# endif
|
||||
#endif
|
||||
{
|
||||
msg("\"%s\" is not a regular file", origname);
|
||||
return tmpstart("");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stat(".", &statb);
|
||||
}
|
||||
if (origfd >= 0)
|
||||
{
|
||||
origtime = statb.st_mtime;
|
||||
#if OSK
|
||||
if (*o_readonly || !(statb.st_mode &
|
||||
((getuid() >> 16) == 0 ? S_IOWRITE | S_IWRITE :
|
||||
((statb.st_gid != (getuid() >> 16) ? S_IOWRITE : S_IWRITE)))))
|
||||
#endif
|
||||
#if AMIGA || MSDOS || (TOS && defined(__GNUC__))
|
||||
if (*o_readonly || !(statb.st_mode & S_IWRITE))
|
||||
#endif
|
||||
#if TOS && !defined(__GNUC__)
|
||||
if (*o_readonly || (statb.st_mode & S_IJRON))
|
||||
#endif
|
||||
#if ANY_UNIX
|
||||
if (*o_readonly || !(statb.st_mode &
|
||||
((geteuid() == 0) ? 0222 :
|
||||
((statb.st_uid != geteuid() ? 0022 : 0200)))))
|
||||
#endif
|
||||
#if VMS
|
||||
if (*o_readonly)
|
||||
#endif
|
||||
{
|
||||
setflag(file, READONLY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
origtime = 0L;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setflag(file, NOFILE);
|
||||
origfd = -1;
|
||||
origtime = 0L;
|
||||
stat(".", &statb);
|
||||
}
|
||||
|
||||
/* make a name for the tmp file */
|
||||
tmpnum++;
|
||||
#if MSDOS || TOS
|
||||
/* MS-Dos doesn't allow multiple slashes, but supports drives
|
||||
* with current directories.
|
||||
* This relies on TMPNAME beginning with "%s\\"!!!!
|
||||
*/
|
||||
strcpy(tmpname, o_directory);
|
||||
if ((i = strlen(tmpname)) && !strchr(":/\\", tmpname[i-1]))
|
||||
tmpname[i++]=SLASH;
|
||||
sprintf(tmpname+i, TMPNAME+3, getpid(), tmpnum);
|
||||
#else
|
||||
sprintf(tmpname, TMPNAME, o_directory, getpid(), tmpnum);
|
||||
#endif
|
||||
|
||||
/* make sure nobody else is editing the same file */
|
||||
if (access(tmpname, 0) == 0)
|
||||
{
|
||||
FAIL("Temp file \"%s\" already exists?", tmpname);
|
||||
}
|
||||
|
||||
/* create the temp file */
|
||||
#if ANY_UNIX
|
||||
close(creat(tmpname, 0600)); /* only we can read it */
|
||||
#else
|
||||
close(creat(tmpname, FILEPERMS)); /* anybody body can read it, alas */
|
||||
#endif
|
||||
tmpfd = open(tmpname, O_RDWR | O_BINARY);
|
||||
if (tmpfd < 0)
|
||||
{
|
||||
FAIL("Can't create temp file... Does directory \"%s\" exist?", o_directory);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* allocate space for the header in the file */
|
||||
write(tmpfd, hdr.c, (unsigned)BLKSIZE);
|
||||
write(tmpfd, tmpblk.c, (unsigned)BLKSIZE);
|
||||
|
||||
#ifndef NO_RECYCLE
|
||||
/* initialize the block allocator */
|
||||
/* This must already be done here, before the first attempt
|
||||
* to write to the new file! GB */
|
||||
garbage();
|
||||
#endif
|
||||
|
||||
/* initialize lnum[] */
|
||||
for (i = 1; i < MAXBLKS; i++)
|
||||
{
|
||||
lnum[i] = INFINITY;
|
||||
}
|
||||
lnum[0] = 0;
|
||||
|
||||
/* if there is no original file, then create a 1-line file */
|
||||
if (origfd < 0)
|
||||
{
|
||||
hdr.n[0] = 0; /* invalid inode# denotes new file */
|
||||
|
||||
this = blkget(1); /* get the new text block */
|
||||
strcpy(this->c, "\n"); /* put a line in it */
|
||||
|
||||
lnum[1] = 1L; /* block 1 ends with line 1 */
|
||||
nlines = 1L; /* there is 1 line in the file */
|
||||
nbytes = 1L;
|
||||
|
||||
if (*origname)
|
||||
{
|
||||
msg("\"%s\" [NEW FILE] 1 line, 1 char", origname);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg("\"[NO FILE]\" 1 line, 1 char");
|
||||
}
|
||||
}
|
||||
else /* there is an original file -- read it in */
|
||||
{
|
||||
nbytes = nlines = 0;
|
||||
|
||||
/* preallocate 1 "next" buffer */
|
||||
i = 1;
|
||||
next = blkget(i);
|
||||
inbuf = 0;
|
||||
|
||||
/* loop, moving blocks from orig to tmp */
|
||||
for (;;)
|
||||
{
|
||||
/* "next" buffer becomes "this" buffer */
|
||||
this = next;
|
||||
|
||||
/* read [more] text into this block */
|
||||
nread = tread(origfd, &this->c[inbuf], BLKSIZE - 1 - inbuf);
|
||||
if (nread < 0)
|
||||
{
|
||||
close(origfd);
|
||||
close(tmpfd);
|
||||
tmpfd = -1;
|
||||
unlink(tmpname);
|
||||
FAIL("Error reading \"%s\"", origname);
|
||||
}
|
||||
|
||||
/* convert NUL characters to something else */
|
||||
for (j = k = inbuf; k < inbuf + nread; k++)
|
||||
{
|
||||
if (!this->c[k])
|
||||
{
|
||||
setflag(file, HADNUL);
|
||||
this->c[j++] = 0x80;
|
||||
}
|
||||
#ifndef CRUNCH
|
||||
else if (*o_beautify && this->c[k] < ' ' && this->c[k] > 0)
|
||||
{
|
||||
if (this->c[k] == '\t'
|
||||
|| this->c[k] == '\n'
|
||||
|| this->c[k] == '\f')
|
||||
{
|
||||
this->c[j++] = this->c[k];
|
||||
}
|
||||
else if (this->c[k] == '\b')
|
||||
{
|
||||
/* delete '\b', but complain */
|
||||
setflag(file, HADBS);
|
||||
}
|
||||
/* else silently delete control char */
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
this->c[j++] = this->c[k];
|
||||
}
|
||||
}
|
||||
inbuf = j;
|
||||
|
||||
/* if the buffer is empty, quit */
|
||||
if (inbuf == 0)
|
||||
{
|
||||
goto FoundEOF;
|
||||
}
|
||||
|
||||
#if MSDOS || TOS
|
||||
/* BAH! MS text mode read fills inbuf, then compresses eliminating \r
|
||||
but leaving garbage at end of buf. The same is true for TURBOC. GB. */
|
||||
|
||||
memset(this->c + inbuf, '\0', BLKSIZE - inbuf);
|
||||
#endif
|
||||
|
||||
/* search backward for last newline */
|
||||
for (k = inbuf; --k >= 0 && this->c[k] != '\n';)
|
||||
{
|
||||
}
|
||||
if (k++ < 0)
|
||||
{
|
||||
if (inbuf >= BLKSIZE - 1)
|
||||
{
|
||||
k = 80;
|
||||
}
|
||||
else
|
||||
{
|
||||
k = inbuf;
|
||||
}
|
||||
}
|
||||
|
||||
/* allocate next buffer */
|
||||
next = blkget(++i);
|
||||
|
||||
/* move fragmentary last line to next buffer */
|
||||
inbuf -= k;
|
||||
for (j = 0; k < BLKSIZE; j++, k++)
|
||||
{
|
||||
next->c[j] = this->c[k];
|
||||
this->c[k] = 0;
|
||||
}
|
||||
|
||||
/* if necessary, add a newline to this buf */
|
||||
for (k = BLKSIZE - inbuf; --k >= 0 && !this->c[k]; )
|
||||
{
|
||||
}
|
||||
if (this->c[k] != '\n')
|
||||
{
|
||||
setflag(file, ADDEDNL);
|
||||
this->c[k + 1] = '\n';
|
||||
}
|
||||
|
||||
/* count the lines in this block */
|
||||
for (k = 0; k < BLKSIZE && this->c[k]; k++)
|
||||
{
|
||||
if (this->c[k] == '\n')
|
||||
{
|
||||
nlines++;
|
||||
}
|
||||
nbytes++;
|
||||
}
|
||||
if(i >= MAXBLKS) {
|
||||
FAIL("Too many blocks: %d.", i);
|
||||
}
|
||||
lnum[i - 1] = nlines;
|
||||
}
|
||||
FoundEOF:
|
||||
|
||||
/* if this is a zero-length file, add 1 line */
|
||||
if (nlines == 0)
|
||||
{
|
||||
this = blkget(1); /* get the new text block */
|
||||
strcpy(this->c, "\n"); /* put a line in it */
|
||||
|
||||
lnum[1] = 1; /* block 1 ends with line 1 */
|
||||
nlines = 1; /* there is 1 line in the file */
|
||||
nbytes = 1;
|
||||
}
|
||||
|
||||
#if MSDOS || TOS
|
||||
/* each line has an extra CR that we didn't count yet */
|
||||
nbytes += nlines;
|
||||
#endif
|
||||
|
||||
/* report the number of lines in the file */
|
||||
msg("\"%s\" %s %ld line%s, %ld char%s",
|
||||
origname,
|
||||
(tstflag(file, READONLY) ? "[READONLY]" : ""),
|
||||
nlines,
|
||||
nlines == 1 ? "" : "s",
|
||||
nbytes,
|
||||
nbytes == 1 ? "" : "s");
|
||||
}
|
||||
|
||||
/* initialize the cursor to start of line 1 */
|
||||
cursor = MARK_FIRST;
|
||||
|
||||
/* close the original file */
|
||||
close(origfd);
|
||||
|
||||
/* any other messages? */
|
||||
if (tstflag(file, HADNUL))
|
||||
{
|
||||
msg("This file contained NULs. They've been changed to \\x80 chars");
|
||||
}
|
||||
if (tstflag(file, ADDEDNL))
|
||||
{
|
||||
msg("Newline characters have been inserted to break up long lines");
|
||||
}
|
||||
#ifndef CRUNCH
|
||||
if (tstflag(file, HADBS))
|
||||
{
|
||||
msg("Backspace characters deleted due to ':set beautify'");
|
||||
}
|
||||
#endif
|
||||
|
||||
storename(origname);
|
||||
|
||||
#ifndef NO_MODELINES
|
||||
if (nlines > 10)
|
||||
{
|
||||
do_modelines(1L, 5L);
|
||||
do_modelines(nlines - 4L, nlines);
|
||||
}
|
||||
else
|
||||
{
|
||||
do_modelines(1L, nlines);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* force all blocks out onto the disk, to support file recovery */
|
||||
blksync();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* This function copies the temp file back onto an original file.
|
||||
* Returns TRUE if successful, or FALSE if the file could NOT be saved.
|
||||
*/
|
||||
int tmpsave(filename, bang)
|
||||
char *filename; /* the name to save it to */
|
||||
int bang; /* forced write? */
|
||||
{
|
||||
int fd; /* fd of the file we're writing to */
|
||||
REG int len; /* length of a text block */
|
||||
REG BLK *this; /* a text block */
|
||||
long bytes; /* byte counter */
|
||||
REG int i;
|
||||
|
||||
/* if no filename is given, assume the original file name */
|
||||
if (!filename || !*filename)
|
||||
{
|
||||
filename = origname;
|
||||
}
|
||||
|
||||
/* if still no file name, then fail */
|
||||
if (!*filename)
|
||||
{
|
||||
msg("Don't know a name for this file -- NOT WRITTEN");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* can't rewrite a READONLY file */
|
||||
#if AMIGA
|
||||
if (!strcmp(filename, origname) && tstflag(file, READONLY) && !bang)
|
||||
#else
|
||||
if (!strcmp(filename, origname) && *o_readonly && !bang)
|
||||
#endif
|
||||
{
|
||||
msg("\"%s\" [READONLY] -- NOT WRITTEN", filename);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* open the file */
|
||||
if (*filename == '>' && filename[1] == '>')
|
||||
{
|
||||
filename += 2;
|
||||
while (*filename == ' ' || *filename == '\t')
|
||||
{
|
||||
filename++;
|
||||
}
|
||||
#ifdef O_APPEND
|
||||
fd = open(filename, O_WRONLY|O_APPEND);
|
||||
#else
|
||||
fd = open(filename, O_WRONLY);
|
||||
lseek(fd, 0L, 2);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/* either the file must not exist, or it must be the original
|
||||
* file, or we must have a bang, or "writeany" must be set.
|
||||
*/
|
||||
if (strcmp(filename, origname) && access(filename, 0) == 0 && !bang
|
||||
#ifndef CRUNCH
|
||||
&& !*o_writeany
|
||||
#endif
|
||||
)
|
||||
{
|
||||
msg("File already exists - Use :w! to overwrite");
|
||||
return FALSE;
|
||||
}
|
||||
#if VMS
|
||||
/* Create a new VMS version of this file. */
|
||||
{
|
||||
char *strrchr(), *ptr = strrchr(filename,';');
|
||||
if (ptr) *ptr = '\0'; /* Snip off any ;number in the name */
|
||||
}
|
||||
#endif
|
||||
fd = creat(filename, FILEPERMS);
|
||||
}
|
||||
if (fd < 0)
|
||||
{
|
||||
msg("Can't write to \"%s\" -- NOT WRITTEN", filename);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* write each text block to the file */
|
||||
bytes = 0L;
|
||||
for (i = 1; i < MAXBLKS && (this = blkget(i)) && this->c[0]; i++)
|
||||
{
|
||||
for (len = 0; len < BLKSIZE && this->c[len]; len++)
|
||||
{
|
||||
}
|
||||
if (twrite(fd, this->c, len) < len)
|
||||
{
|
||||
msg("Trouble writing to \"%s\"", filename);
|
||||
if (!strcmp(filename, origname))
|
||||
{
|
||||
setflag(file, MODIFIED);
|
||||
}
|
||||
close(fd);
|
||||
return FALSE;
|
||||
}
|
||||
bytes += len;
|
||||
}
|
||||
|
||||
/* reset the "modified" flag, but not the "undoable" flag */
|
||||
clrflag(file, MODIFIED);
|
||||
significant = FALSE;
|
||||
|
||||
/* report lines & characters */
|
||||
#if MSDOS || TOS
|
||||
bytes += nlines; /* for the inserted carriage returns */
|
||||
#endif
|
||||
msg("Wrote \"%s\" %ld lines, %ld characters", filename, nlines, bytes);
|
||||
|
||||
/* close the file */
|
||||
close(fd);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* This function deletes the temporary file. If the file has been modified
|
||||
* and "bang" is FALSE, then it returns FALSE without doing anything; else
|
||||
* it returns TRUE.
|
||||
*
|
||||
* If the "autowrite" option is set, then instead of returning FALSE when
|
||||
* the file has been modified and "bang" is false, it will call tmpend().
|
||||
*/
|
||||
int tmpabort(bang)
|
||||
int bang;
|
||||
{
|
||||
/* if there is no file, return successfully */
|
||||
if (tmpfd < 0)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* see if we must return FALSE -- can't quit */
|
||||
if (!bang && tstflag(file, MODIFIED))
|
||||
{
|
||||
/* if "autowrite" is set, then act like tmpend() */
|
||||
if (*o_autowrite)
|
||||
return tmpend(bang);
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* delete the tmp file */
|
||||
cutswitch();
|
||||
strcpy(prevorig, origname);
|
||||
prevline = markline(cursor);
|
||||
*origname = '\0';
|
||||
origtime = 0L;
|
||||
blkinit();
|
||||
nlines = 0;
|
||||
initflags();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* This function saves the file if it has been modified, and then deletes
|
||||
* the temporary file. Returns TRUE if successful, or FALSE if the file
|
||||
* needs to be saved but can't be. When it returns FALSE, it will not have
|
||||
* deleted the tmp file, either.
|
||||
*/
|
||||
int tmpend(bang)
|
||||
int bang;
|
||||
{
|
||||
/* save the file if it has been modified */
|
||||
if (tstflag(file, MODIFIED) && !tmpsave((char *)0, FALSE) && !bang)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* delete the tmp file */
|
||||
tmpabort(TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* If the tmp file has been changed, then this function will force those
|
||||
* changes to be written to the disk, so that the tmp file will survive a
|
||||
* system crash or power failure.
|
||||
*/
|
||||
#if AMIGA || MSDOS || TOS
|
||||
sync()
|
||||
{
|
||||
/* MS-DOS and TOS don't flush their buffers until the file is closed,
|
||||
* so here we close the tmp file and then immediately reopen it.
|
||||
*/
|
||||
close(tmpfd);
|
||||
tmpfd = open(tmpname, O_RDWR | O_BINARY);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* This function stores the file's name in the second block of the temp file.
|
||||
* SLEAZE ALERT! SLEAZE ALERT! The "tmpblk" buffer is probably being used
|
||||
* to store the arguments to a command, so we can't use it here. Instead,
|
||||
* we'll borrow the buffer that is used for "shift-U".
|
||||
*/
|
||||
storename(name)
|
||||
char *name; /* the name of the file - normally origname */
|
||||
{
|
||||
#ifndef CRUNCH
|
||||
int len;
|
||||
char *ptr;
|
||||
#endif
|
||||
|
||||
/* we're going to clobber the U_text buffer, so reset U_line */
|
||||
U_line = 0L;
|
||||
|
||||
if (!name)
|
||||
{
|
||||
strncpy(U_text, "", BLKSIZE);
|
||||
U_text[1] = 127;
|
||||
}
|
||||
#ifndef CRUNCH
|
||||
else if (*name != SLASH)
|
||||
{
|
||||
/* get the directory name */
|
||||
ptr = getcwd(U_text, BLKSIZE);
|
||||
if (ptr != U_text)
|
||||
{
|
||||
strcpy(U_text, ptr);
|
||||
}
|
||||
|
||||
/* append a slash to the directory name */
|
||||
len = strlen(U_text);
|
||||
U_text[len++] = SLASH;
|
||||
|
||||
/* append the filename, padded with heaps o' NULs */
|
||||
strncpy(U_text + len, *name ? name : "foo", BLKSIZE - len);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
/* copy the filename into U_text */
|
||||
strncpy(U_text, *name ? name : "foo", BLKSIZE);
|
||||
}
|
||||
|
||||
if (tmpfd >= 0)
|
||||
{
|
||||
/* write the name out to second block of the temp file */
|
||||
lseek(tmpfd, (long)BLKSIZE, 0);
|
||||
write(tmpfd, U_text, (unsigned)BLKSIZE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* This function handles deadly signals. It restores sanity to the terminal
|
||||
* preserves the current temp file, and deletes any old temp files.
|
||||
*/
|
||||
int deathtrap(sig)
|
||||
int sig; /* the deadly signal that we caught */
|
||||
{
|
||||
char *why;
|
||||
|
||||
/* restore the terminal's sanity */
|
||||
endwin();
|
||||
|
||||
#ifdef CRUNCH
|
||||
why = "-Elvis died";
|
||||
#else
|
||||
/* give a more specific description of how Elvis died */
|
||||
switch (sig)
|
||||
{
|
||||
# ifdef SIGHUP
|
||||
case SIGHUP: why = "-the modem lost its carrier"; break;
|
||||
# endif
|
||||
# ifndef DEBUG
|
||||
# ifdef SIGILL
|
||||
case SIGILL: why = "-Elvis hit an illegal instruction"; break;
|
||||
# endif
|
||||
# ifdef SIGBUS
|
||||
case SIGBUS: why = "-Elvis had a bus error"; break;
|
||||
# endif
|
||||
# if defined(SIGSEGV) && !defined(TOS)
|
||||
case SIGSEGV: why = "-Elvis had a segmentation violation"; break;
|
||||
# endif
|
||||
# ifdef SIGSYS
|
||||
case SIGSYS: why = "-Elvis munged a system call"; break;
|
||||
# endif
|
||||
# endif /* !DEBUG */
|
||||
# ifdef SIGPIPE
|
||||
case SIGPIPE: why = "-the pipe reader died"; break;
|
||||
# endif
|
||||
# ifdef SIGTERM
|
||||
case SIGTERM: why = "-Elvis was terminated"; break;
|
||||
# endif
|
||||
# if !MINIX
|
||||
# ifdef SIGUSR1
|
||||
case SIGUSR1: why = "-Elvis was killed via SIGUSR1"; break;
|
||||
# endif
|
||||
# ifdef SIGUSR2
|
||||
case SIGUSR2: why = "-Elvis was killed via SIGUSR2"; break;
|
||||
# endif
|
||||
# endif
|
||||
default: why = "-Elvis died"; break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* if we had a temp file going, then preserve it */
|
||||
if (tmpnum > 0 && tmpfd >= 0)
|
||||
{
|
||||
close(tmpfd);
|
||||
sprintf(tmpblk.c, "%s \"%s\" %s", PRESERVE, why, tmpname);
|
||||
system(tmpblk.c);
|
||||
}
|
||||
|
||||
/* delete any old temp files */
|
||||
cutend();
|
||||
|
||||
/* exit with the proper exit status */
|
||||
exit(sig);
|
||||
}
|
|
@ -1,218 +0,0 @@
|
|||
/* unix.c */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* 14407 SW Teal Blvd. #C
|
||||
* Beaverton, OR 97005
|
||||
* kirkenda@cs.pdx.edu
|
||||
*/
|
||||
|
||||
|
||||
/* This file contains the unix-specific versions the ttyread() functions.
|
||||
* There are actually three versions of ttyread() defined here, because
|
||||
* BSD, SysV, and V7 all need quite different implementations.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#if ANY_UNIX
|
||||
# include "vi.h"
|
||||
|
||||
# if BSD
|
||||
/* For BSD, we use select() to wait for characters to become available,
|
||||
* and then do a read() to actually get the characters. We also try to
|
||||
* handle SIGWINCH -- if the signal arrives during the select() call, then
|
||||
* we adjust the o_columns and o_lines variables, and fake a control-L.
|
||||
*/
|
||||
# include <sys/types.h>
|
||||
# include <sys/time.h>
|
||||
int ttyread(buf, len, time)
|
||||
char *buf; /* where to store the gotten characters */
|
||||
int len; /* maximum number of characters to read */
|
||||
int time; /* maximum time to allow for reading */
|
||||
{
|
||||
fd_set rd; /* the file descriptors that we want to read from */
|
||||
static tty; /* 'y' if reading from tty, or 'n' if not a tty */
|
||||
int i;
|
||||
struct timeval t;
|
||||
struct timeval *tp;
|
||||
|
||||
|
||||
/* do we know whether this is a tty or not? */
|
||||
if (!tty)
|
||||
{
|
||||
tty = (isatty(0) ? 'y' : 'n');
|
||||
}
|
||||
|
||||
/* compute the timeout value */
|
||||
if (time)
|
||||
{
|
||||
t.tv_sec = time / 10;
|
||||
t.tv_usec = (time % 10) * 100000L;
|
||||
tp = &t;
|
||||
}
|
||||
else
|
||||
{
|
||||
tp = (struct timeval *)0;
|
||||
}
|
||||
|
||||
/* loop until we get characters or a definite EOF */
|
||||
for (;;)
|
||||
{
|
||||
if (tty == 'y')
|
||||
{
|
||||
/* wait until timeout or characters are available */
|
||||
FD_ZERO(&rd);
|
||||
FD_SET(0, &rd);
|
||||
i = select(1, &rd, (fd_set *)0, (fd_set *)0, tp);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if reading from a file or pipe, never timeout!
|
||||
* (This also affects the way that EOF is detected)
|
||||
*/
|
||||
i = 1;
|
||||
}
|
||||
|
||||
/* react accordingly... */
|
||||
switch (i)
|
||||
{
|
||||
case -1: /* assume we got an EINTR because of SIGWINCH */
|
||||
if (*o_lines != LINES || *o_columns != COLS)
|
||||
{
|
||||
*o_lines = LINES;
|
||||
*o_columns = COLS;
|
||||
#ifndef CRUNCH
|
||||
if (!wset)
|
||||
{
|
||||
*o_window = LINES - 1;
|
||||
}
|
||||
#endif
|
||||
if (mode != MODE_EX)
|
||||
{
|
||||
/* pretend the user hit ^L */
|
||||
*buf = ctrl('L');
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0: /* timeout */
|
||||
return 0;
|
||||
|
||||
default: /* characters available */
|
||||
return read(0, buf, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
# else
|
||||
|
||||
# if M_SYSV
|
||||
/* For System-V or Coherent, we use VMIN/VTIME to implement the timeout.
|
||||
* For no timeout, VMIN should be 1 and VTIME should be 0; for timeout,
|
||||
* VMIN should be 0 and VTIME should be the timeout value.
|
||||
*/
|
||||
# include <termio.h>
|
||||
int ttyread(buf, len, time)
|
||||
char *buf; /* where to store the gotten characters */
|
||||
int len; /* maximum number of characters to read */
|
||||
int time; /* maximum time to allow for reading */
|
||||
{
|
||||
struct termio tio;
|
||||
int bytes; /* number of bytes actually read */
|
||||
|
||||
/* arrange for timeout */
|
||||
ioctl(0, TCGETA, &tio);
|
||||
if (time)
|
||||
{
|
||||
tio.c_cc[VMIN] = 0;
|
||||
tio.c_cc[VTIME] = time;
|
||||
}
|
||||
else
|
||||
{
|
||||
tio.c_cc[VMIN] = 1;
|
||||
tio.c_cc[VTIME] = 0;
|
||||
}
|
||||
ioctl(0, TCSETA, &tio);
|
||||
|
||||
/* Perform the read. Loop if EINTR error happens */
|
||||
while ((bytes = read(0, buf, len)) < 0)
|
||||
{
|
||||
/* probably EINTR error because a SIGWINCH was received */
|
||||
if (*o_lines != LINES || *o_columns != COLS)
|
||||
{
|
||||
*o_lines = LINES;
|
||||
*o_columns = COLS;
|
||||
#ifndef CRUNCH
|
||||
if (!wset)
|
||||
{
|
||||
*o_window = LINES - 1;
|
||||
}
|
||||
#endif
|
||||
if (mode != MODE_EX)
|
||||
{
|
||||
/* pretend the user hit ^L */
|
||||
*buf = ctrl('L');
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* return the number of bytes read */
|
||||
return bytes;
|
||||
|
||||
/* NOTE: The terminal may be left in a timeout-mode after this function
|
||||
* returns. This shouldn't be a problem since Elvis *NEVER* tries to
|
||||
* read from the keyboard except through this function.
|
||||
*/
|
||||
}
|
||||
|
||||
# else /* any other version of UNIX, assume it is V7 compatible */
|
||||
|
||||
/* For V7 UNIX (including Minix) we set an alarm() before doing a blocking
|
||||
* read(), and assume that the SIGALRM signal will cause the read() function
|
||||
* to give up.
|
||||
*/
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
static jmp_buf env;
|
||||
|
||||
/*ARGSUSED*/
|
||||
int dummy(signo)
|
||||
int signo;
|
||||
{
|
||||
longjmp(env, 1);
|
||||
}
|
||||
int ttyread(buf, len, time)
|
||||
char *buf; /* where to store the gotten characters */
|
||||
int len; /* maximum number of characters to read */
|
||||
int time; /* maximum time to allow for reading */
|
||||
{
|
||||
/* arrange for timeout */
|
||||
signal(SIGALRM, (void (*)()) dummy);
|
||||
alarm(time);
|
||||
|
||||
/* perform the blocking read */
|
||||
if (setjmp(env) == 0)
|
||||
{
|
||||
len = read(0, buf, len);
|
||||
}
|
||||
else /* I guess we timed out */
|
||||
{
|
||||
len = 0;
|
||||
}
|
||||
|
||||
/* cancel the alarm */
|
||||
signal(SIGALRM, (void (*)())dummy); /* work around a bug in Minix */
|
||||
alarm(0);
|
||||
|
||||
/* return the number of bytes read */
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
return len;
|
||||
}
|
||||
|
||||
# endif /* !(M_SYSV || COHERENT) */
|
||||
# endif /* !BSD */
|
||||
|
||||
#endif /* ANY_UNIX */
|
|
@ -1,115 +0,0 @@
|
|||
/* vars.c */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* 14407 SW Teal Blvd. #C
|
||||
* Beaverton, OR 97005
|
||||
* kirkenda@cs.pdx.edu
|
||||
*/
|
||||
|
||||
|
||||
/* This file contains variables which weren't happy anyplace else */
|
||||
|
||||
#include "config.h"
|
||||
#include "vi.h"
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
/* used to remember whether the file has been modified */
|
||||
struct _viflags viflags;
|
||||
|
||||
/* used to access the tmp file */
|
||||
long lnum[MAXBLKS];
|
||||
long nlines;
|
||||
int tmpfd = -1;
|
||||
int tmpnum;
|
||||
#ifndef CRUNCH
|
||||
int wset = FALSE;
|
||||
#endif
|
||||
|
||||
/* used to keep track of the current file & alternate file */
|
||||
long origtime;
|
||||
char origname[256];
|
||||
char prevorig[256];
|
||||
long prevline = 1;
|
||||
|
||||
/* used to track various places in the text */
|
||||
MARK mark[NMARKS]; /* marks 'a through 'z, plus mark '' */
|
||||
MARK cursor; /* the cursor position within the file */
|
||||
|
||||
/* which mode of the editor we're in */
|
||||
int mode; /* vi mode? ex mode? quitting? */
|
||||
|
||||
/* used to manage the args list */
|
||||
char args[BLKSIZE]; /* list of filenames to edit */
|
||||
int argno; /* index of current file in args list */
|
||||
int nargs; /* number of filenames in args[] */
|
||||
|
||||
/* dummy var, never explicitly referenced */
|
||||
int bavar; /* used only in BeforeAfter macros */
|
||||
|
||||
/* used to detect changes that invalidate cached text/blocks */
|
||||
long changes; /* incremented when file is changed */
|
||||
int significant; /* boolean: was a *REAL* change made? */
|
||||
|
||||
/* used to support the pfetch() macro */
|
||||
int plen; /* length of the line */
|
||||
long pline; /* line number that len refers to */
|
||||
long pchgs; /* "changes" level that len refers to */
|
||||
char *ptext; /* text of previous line, if valid */
|
||||
|
||||
/* misc temporary storage - mostly for strings */
|
||||
BLK tmpblk; /* a block used to accumulate changes */
|
||||
|
||||
/* screen oriented stuff */
|
||||
long topline; /* file line number of top line */
|
||||
int leftcol; /* column number of left col */
|
||||
int physcol; /* physical column number that cursor is on */
|
||||
int physrow; /* physical row number that cursor is on */
|
||||
|
||||
/* used to help minimize that "[Hit a key to continue]" message */
|
||||
int exwrote; /* Boolean: was the last ex command wordy? */
|
||||
|
||||
/* This variable affects the behaviour of certain functions -- most importantly
|
||||
* the input function.
|
||||
*/
|
||||
int doingdot; /* boolean: are we doing the "." command? */
|
||||
|
||||
/* This variable affects the behaviour of the ":s" command, and it is also
|
||||
* used to detect & prohibit nesting of ":g" commands
|
||||
*/
|
||||
int doingglobal; /* boolean: are doing a ":g" command? */
|
||||
|
||||
/* This variable is zeroed before a command executes, and later ORed with the
|
||||
* command's flags after the command has been executed. It is used to force
|
||||
* certain flags to be TRUE for *some* invocations of a particular command.
|
||||
* For example, "/regexp/+offset" forces the LNMD flag, and sometimes a "p"
|
||||
* or "P" command will force FRNT.
|
||||
*/
|
||||
int force_flags;
|
||||
|
||||
/* These are used for reporting multi-line changes to the user */
|
||||
long rptlines; /* number of lines affected by a command */
|
||||
char *rptlabel; /* description of how lines were affected */
|
||||
|
||||
/* These store info that pertains to the shift-U command */
|
||||
long U_line; /* line# of the undoable line, or 0l for none */
|
||||
char U_text[BLKSIZE]; /* contents of the undoable line */
|
||||
|
||||
|
||||
#ifndef NO_VISIBLE
|
||||
/* These are used to implement the 'v' and 'V' commands */
|
||||
MARK V_from; /* starting point for v or V */
|
||||
int V_linemd; /* boolean: doing line-mode version? (V, not v) */
|
||||
#endif
|
||||
|
||||
/* Bigger stack req'ed for TOS and TURBOC */
|
||||
|
||||
#if TOS
|
||||
long _stksize = 16384;
|
||||
#endif
|
||||
|
||||
#if TURBOC
|
||||
#include <dos.h>
|
||||
extern unsigned _stklen = 16384U;
|
||||
#endif
|
|
@ -1,975 +0,0 @@
|
|||
/* vcmd.c */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* 14407 SW Teal Blvd. #C
|
||||
* Beaverton, OR 97005
|
||||
* kirkenda@cs.pdx.edu
|
||||
*/
|
||||
|
||||
|
||||
/* This file contains the functions that handle VI commands */
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include "ctype.h"
|
||||
#include "vi.h"
|
||||
#if MSDOS
|
||||
# include <process.h>
|
||||
# include <string.h>
|
||||
#endif
|
||||
#if TOS
|
||||
# include <osbind.h>
|
||||
# include <string.h>
|
||||
#endif
|
||||
#if OSK
|
||||
# include <stdio.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* This function puts the editor in EX mode */
|
||||
MARK v_quit()
|
||||
{
|
||||
move(LINES - 1, 0);
|
||||
mode = MODE_EX;
|
||||
return cursor;
|
||||
}
|
||||
|
||||
/* This function causes the screen to be redrawn */
|
||||
MARK v_redraw()
|
||||
{
|
||||
redraw(MARK_UNSET, FALSE);
|
||||
return cursor;
|
||||
}
|
||||
|
||||
/* This function executes a string of EX commands, and waits for a user keystroke
|
||||
* before returning to the VI screen. If that keystroke is another ':', then
|
||||
* another EX command is read and executed.
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
MARK v_1ex(m, text)
|
||||
MARK m; /* the current line */
|
||||
char *text; /* the first command to execute */
|
||||
{
|
||||
/* run the command. be careful about modes & output */
|
||||
exwrote = (mode == MODE_COLON);
|
||||
doexcmd(text);
|
||||
exrefresh();
|
||||
|
||||
/* if mode is no longer MODE_VI, then we should quit right away! */
|
||||
if (mode != MODE_VI && mode != MODE_COLON)
|
||||
return cursor;
|
||||
|
||||
/* The command did some output. Wait for a keystoke. */
|
||||
if (exwrote)
|
||||
{
|
||||
mode = MODE_VI;
|
||||
msg("[Hit <RETURN> to continue]");
|
||||
if (getkey(0) == ':')
|
||||
{ mode = MODE_COLON;
|
||||
addch('\n');
|
||||
}
|
||||
else
|
||||
redraw(MARK_UNSET, FALSE);
|
||||
}
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
/* This function undoes the last change */
|
||||
/*ARGSUSED*/
|
||||
MARK v_undo(m)
|
||||
MARK m; /* (ignored) */
|
||||
{
|
||||
if (undo())
|
||||
{
|
||||
redraw(MARK_UNSET, FALSE);
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
|
||||
/* This function deletes the character(s) that the cursor is on */
|
||||
MARK v_xchar(m, cnt, cmd)
|
||||
MARK m; /* where to start deletions */
|
||||
long cnt; /* number of chars to delete */
|
||||
int cmd; /* either 'x' or 'X' */
|
||||
{
|
||||
DEFAULT(1);
|
||||
|
||||
/* for 'X', adjust so chars are deleted *BEFORE* cursor */
|
||||
if (cmd == 'X')
|
||||
{
|
||||
if (markidx(m) < cnt)
|
||||
return MARK_UNSET;
|
||||
m -= cnt;
|
||||
}
|
||||
|
||||
/* make sure we don't try to delete more thars than there are */
|
||||
pfetch(markline(m));
|
||||
if (markidx(m + cnt) > plen)
|
||||
{
|
||||
cnt = plen - markidx(m);
|
||||
}
|
||||
if (cnt == 0L)
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
|
||||
/* do it */
|
||||
ChangeText
|
||||
{
|
||||
cut(m, m + cnt);
|
||||
delete(m, m + cnt);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/* This function defines a mark */
|
||||
/*ARGSUSED*/
|
||||
MARK v_mark(m, count, key)
|
||||
MARK m; /* where the mark will be */
|
||||
long count; /* (ignored) */
|
||||
int key; /* the ASCII label of the mark */
|
||||
{
|
||||
if (key < 'a' || key > 'z')
|
||||
{
|
||||
msg("Marks must be from a to z");
|
||||
}
|
||||
else
|
||||
{
|
||||
mark[key - 'a'] = m;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/* This function toggles upper & lower case letters */
|
||||
MARK v_ulcase(m, cnt)
|
||||
MARK m; /* where to make the change */
|
||||
long cnt; /* number of chars to flip */
|
||||
{
|
||||
REG char *pos;
|
||||
REG int j;
|
||||
|
||||
DEFAULT(1);
|
||||
|
||||
/* fetch the current version of the line */
|
||||
pfetch(markline(m));
|
||||
|
||||
/* for each position in the line */
|
||||
for (j = 0, pos = &ptext[markidx(m)]; j < cnt && *pos; j++, pos++)
|
||||
{
|
||||
if (isupper(*pos))
|
||||
{
|
||||
tmpblk.c[j] = tolower(*pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpblk.c[j] = toupper(*pos);
|
||||
}
|
||||
}
|
||||
|
||||
/* if the new text is different from the old, then change it */
|
||||
if (strncmp(tmpblk.c, &ptext[markidx(m)], j))
|
||||
{
|
||||
ChangeText
|
||||
{
|
||||
tmpblk.c[j] = '\0';
|
||||
change(m, m + j, tmpblk.c);
|
||||
}
|
||||
}
|
||||
|
||||
return m + j;
|
||||
}
|
||||
|
||||
|
||||
MARK v_replace(m, cnt, key)
|
||||
MARK m; /* first char to be replaced */
|
||||
long cnt; /* number of chars to replace */
|
||||
int key; /* what to replace them with */
|
||||
{
|
||||
REG char *text;
|
||||
REG int i;
|
||||
|
||||
DEFAULT(1);
|
||||
|
||||
/* map ^M to '\n' */
|
||||
if (key == '\r')
|
||||
{
|
||||
key = '\n';
|
||||
}
|
||||
|
||||
/* make sure the resulting line isn't too long */
|
||||
if (cnt > BLKSIZE - 2 - markidx(m))
|
||||
{
|
||||
cnt = BLKSIZE - 2 - markidx(m);
|
||||
}
|
||||
|
||||
/* build a string of the desired character with the desired length */
|
||||
for (text = tmpblk.c, i = cnt; i > 0; i--)
|
||||
{
|
||||
*text++ = key;
|
||||
}
|
||||
*text = '\0';
|
||||
|
||||
/* make sure cnt doesn't extend past EOL */
|
||||
pfetch(markline(m));
|
||||
key = markidx(m);
|
||||
if (key + cnt > plen)
|
||||
{
|
||||
cnt = plen - key;
|
||||
}
|
||||
|
||||
/* do the replacement */
|
||||
ChangeText
|
||||
{
|
||||
change(m, m + cnt, tmpblk.c);
|
||||
}
|
||||
|
||||
if (*tmpblk.c == '\n')
|
||||
{
|
||||
return (m & ~(BLKSIZE - 1)) + cnt * BLKSIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return m + cnt - 1;
|
||||
}
|
||||
}
|
||||
|
||||
MARK v_overtype(m)
|
||||
MARK m; /* where to start overtyping */
|
||||
{
|
||||
MARK end; /* end of a substitution */
|
||||
static long width; /* width of a single-line replace */
|
||||
|
||||
/* the "doingdot" version of replace is really a substitution */
|
||||
if (doingdot)
|
||||
{
|
||||
/* was the last one really repeatable? */
|
||||
if (width < 0)
|
||||
{
|
||||
msg("Can't repeat a multi-line overtype command");
|
||||
return MARK_UNSET;
|
||||
}
|
||||
|
||||
/* replacing nothing by nothing? Don't bother */
|
||||
if (width == 0)
|
||||
{
|
||||
return m;
|
||||
}
|
||||
|
||||
/* replace some chars by repeated text */
|
||||
return v_subst(m, width);
|
||||
}
|
||||
|
||||
/* Normally, we input starting here, in replace mode */
|
||||
ChangeText
|
||||
{
|
||||
end = input(m, m, WHEN_VIREP, FALSE);
|
||||
}
|
||||
|
||||
/* if we ended on the same line we started on, then this
|
||||
* overtype is repeatable via the dot key.
|
||||
*/
|
||||
if (markline(end) == markline(m) && end >= m - 1L)
|
||||
{
|
||||
width = end - m + 1L;
|
||||
}
|
||||
else /* it isn't repeatable */
|
||||
{
|
||||
width = -1L;
|
||||
}
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
|
||||
/* This function selects which cut buffer to use */
|
||||
/*ARGSUSED*/
|
||||
MARK v_selcut(m, cnt, key)
|
||||
MARK m;
|
||||
long cnt;
|
||||
int key;
|
||||
{
|
||||
cutname(key);
|
||||
return m;
|
||||
}
|
||||
|
||||
/* This function pastes text from a cut buffer */
|
||||
/*ARGSUSED*/
|
||||
MARK v_paste(m, cnt, cmd)
|
||||
MARK m; /* where to paste the text */
|
||||
long cnt; /* (ignored) */
|
||||
int cmd; /* either 'p' or 'P' */
|
||||
{
|
||||
MARK dest;
|
||||
|
||||
ChangeText
|
||||
{
|
||||
/* paste the text, and find out where it ends */
|
||||
dest = paste(m, cmd == 'p', TRUE);
|
||||
|
||||
/* was that a line-mode paste? */
|
||||
if (dest && markline(dest) != markline(m))
|
||||
{
|
||||
/* line-mode pastes leave the cursor at the front
|
||||
* of the first pasted line.
|
||||
*/
|
||||
dest = m;
|
||||
if (cmd == 'p')
|
||||
{
|
||||
dest += BLKSIZE;
|
||||
}
|
||||
force_flags |= FRNT;
|
||||
}
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* This function yanks text into a cut buffer */
|
||||
MARK v_yank(m, n)
|
||||
MARK m, n; /* range of text to yank */
|
||||
{
|
||||
cut(m, n);
|
||||
return m;
|
||||
}
|
||||
|
||||
/* This function deletes a range of text */
|
||||
MARK v_delete(m, n)
|
||||
MARK m, n; /* range of text to delete */
|
||||
{
|
||||
/* illegal to try and delete nothing */
|
||||
if (n <= m)
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
|
||||
/* Do it */
|
||||
ChangeText
|
||||
{
|
||||
cut(m, n);
|
||||
delete(m, n);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/* This starts input mode without deleting anything */
|
||||
MARK v_insert(m, cnt, key)
|
||||
MARK m; /* where to start (sort of) */
|
||||
long cnt; /* repeat how many times? */
|
||||
int key; /* what command is this for? {a,A,i,I,o,O} */
|
||||
{
|
||||
int wasdot;
|
||||
long reps;
|
||||
int above; /* boolean: new line going above old line? */
|
||||
|
||||
DEFAULT(1);
|
||||
|
||||
ChangeText
|
||||
{
|
||||
/* tweak the insertion point, based on command key */
|
||||
above = FALSE;
|
||||
switch (key)
|
||||
{
|
||||
case 'i':
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
pfetch(markline(m));
|
||||
if (plen > 0)
|
||||
{
|
||||
m++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
m = m_front(m, 1L);
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
pfetch(markline(m));
|
||||
m = (m & ~(BLKSIZE - 1)) + plen;
|
||||
break;
|
||||
|
||||
case 'O':
|
||||
m &= ~(BLKSIZE - 1);
|
||||
add(m, "\n");
|
||||
above = TRUE;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
m = (m & ~(BLKSIZE - 1)) + BLKSIZE;
|
||||
add(m, "\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* insert the same text once or more */
|
||||
for (reps = cnt, wasdot = doingdot; reps > 0; reps--, doingdot = TRUE)
|
||||
{
|
||||
m = input(m, m, WHEN_VIINP, above) + 1;
|
||||
}
|
||||
if (markidx(m) > 0)
|
||||
{
|
||||
m--;
|
||||
}
|
||||
|
||||
doingdot = wasdot;
|
||||
}
|
||||
|
||||
#ifndef CRUNCH
|
||||
# ifndef NO_EXTENSIONS
|
||||
if (key == 'i' && *o_inputmode && mode == MODE_VI)
|
||||
{
|
||||
msg("Now in command mode! To return to input mode, hit <i>");
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/* This starts input mode with some text deleted */
|
||||
MARK v_change(m, n)
|
||||
MARK m, n; /* the range of text to change */
|
||||
{
|
||||
int lnmode; /* is this a line-mode change? */
|
||||
|
||||
/* swap them if they're in reverse order */
|
||||
if (m > n)
|
||||
{
|
||||
MARK tmp;
|
||||
tmp = m;
|
||||
m = n;
|
||||
n = tmp;
|
||||
}
|
||||
|
||||
/* for line mode, retain the last newline char */
|
||||
lnmode = (markidx(m) == 0 && markidx(n) == 0 && m != n);
|
||||
if (lnmode)
|
||||
{
|
||||
n -= BLKSIZE;
|
||||
pfetch(markline(n));
|
||||
n = (n & ~(BLKSIZE - 1)) + plen;
|
||||
}
|
||||
|
||||
ChangeText
|
||||
{
|
||||
cut(m, n);
|
||||
m = input(m, n, WHEN_VIINP, FALSE);
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/* This function replaces a given number of characters with input */
|
||||
MARK v_subst(m, cnt)
|
||||
MARK m; /* where substitutions start */
|
||||
long cnt; /* number of chars to replace */
|
||||
{
|
||||
DEFAULT(1);
|
||||
|
||||
/* make sure we don't try replacing past EOL */
|
||||
pfetch(markline(m));
|
||||
if (markidx(m) + cnt > plen)
|
||||
{
|
||||
cnt = plen - markidx(m);
|
||||
}
|
||||
|
||||
/* Go for it! */
|
||||
ChangeText
|
||||
{
|
||||
cut(m, m + cnt);
|
||||
m = input(m, m + cnt, WHEN_VIINP, FALSE);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/* This calls the ex "join" command to join some lines together */
|
||||
MARK v_join(m, cnt)
|
||||
MARK m; /* the first line to be joined */
|
||||
long cnt; /* number of other lines to join */
|
||||
{
|
||||
MARK joint; /* where the lines were joined */
|
||||
|
||||
DEFAULT(1);
|
||||
|
||||
/* figure out where the joint will be */
|
||||
pfetch(markline(m));
|
||||
joint = (m & ~(BLKSIZE - 1)) + plen;
|
||||
|
||||
/* join the lines */
|
||||
cmd_join(m, m + MARK_AT_LINE(cnt), CMD_JOIN, 0, "");
|
||||
|
||||
/* the cursor should be left at the joint */
|
||||
return joint;
|
||||
}
|
||||
|
||||
|
||||
/* This calls the ex "<" command to shift some lines left */
|
||||
MARK v_lshift(m, n)
|
||||
MARK m, n; /* range of lines to shift */
|
||||
{
|
||||
/* adjust for inclusive endmarks in ex */
|
||||
n -= BLKSIZE;
|
||||
|
||||
cmd_shift(m, n, CMD_SHIFTL, FALSE, (char *)0);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/* This calls the ex ">" command to shift some lines right */
|
||||
MARK v_rshift(m, n)
|
||||
MARK m, n; /* range of lines to shift */
|
||||
{
|
||||
/* adjust for inclusive endmarks in ex */
|
||||
n -= BLKSIZE;
|
||||
|
||||
cmd_shift(m, n, CMD_SHIFTR, FALSE, (char *)0);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/* This filters some lines through a preset program, to reformat them */
|
||||
MARK v_reformat(m, n)
|
||||
MARK m, n; /* range of lines to shift */
|
||||
{
|
||||
/* adjust for inclusive endmarks in ex */
|
||||
n -= BLKSIZE;
|
||||
|
||||
/* run the filter command */
|
||||
filter(m, n, o_equalprg, TRUE);
|
||||
|
||||
redraw(MARK_UNSET, FALSE);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/* This runs some lines through a filter program */
|
||||
MARK v_filter(m, n)
|
||||
MARK m, n; /* range of lines to shift */
|
||||
{
|
||||
char cmdln[150]; /* a shell command line */
|
||||
|
||||
/* adjust for inclusive endmarks in ex */
|
||||
n -= BLKSIZE;
|
||||
|
||||
if (vgets('!', cmdln, sizeof(cmdln)) > 0)
|
||||
{
|
||||
filter(m, n, cmdln, TRUE);
|
||||
}
|
||||
|
||||
redraw(MARK_UNSET, FALSE);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/* This function runs the ex "file" command to show the file's status */
|
||||
MARK v_status()
|
||||
{
|
||||
cmd_file(cursor, cursor, CMD_FILE, 0, "");
|
||||
return cursor;
|
||||
}
|
||||
|
||||
|
||||
/* This function runs the ":&" command to repeat the previous :s// */
|
||||
MARK v_again(m, n)
|
||||
MARK m, n;
|
||||
{
|
||||
cmd_substitute(m, n - BLKSIZE, CMD_SUBAGAIN, TRUE, "");
|
||||
return cursor;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* This function switches to the previous file, if possible */
|
||||
MARK v_switch()
|
||||
{
|
||||
if (!*prevorig)
|
||||
msg("No previous file");
|
||||
else
|
||||
{ strcpy(tmpblk.c, prevorig);
|
||||
cmd_edit(cursor, cursor, CMD_EDIT, 0, tmpblk.c);
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
|
||||
/* This function does a tag search on a keyword */
|
||||
/*ARGSUSED*/
|
||||
MARK v_tag(keyword, m, cnt)
|
||||
char *keyword;
|
||||
MARK m;
|
||||
long cnt;
|
||||
{
|
||||
/* move the cursor to the start of the tag name, where m is */
|
||||
cursor = m;
|
||||
|
||||
/* perform the tag search */
|
||||
cmd_tag(cursor, cursor, CMD_TAG, 0, keyword);
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
#ifndef NO_EXTENSIONS
|
||||
/* This function looks up a keyword by calling the helpprog program */
|
||||
/*ARGSUSED*/
|
||||
MARK v_keyword(keyword, m, cnt)
|
||||
char *keyword;
|
||||
MARK m;
|
||||
long cnt;
|
||||
{
|
||||
int waswarn;
|
||||
char cmdline[130];
|
||||
|
||||
move(LINES - 1, 0);
|
||||
addstr("---------------------------------------------------------\n");
|
||||
clrtoeol();
|
||||
refresh();
|
||||
sprintf(cmdline, "%s %s", o_keywordprg, keyword);
|
||||
waswarn = *o_warn;
|
||||
*o_warn = FALSE;
|
||||
suspend_curses();
|
||||
if (system(cmdline))
|
||||
{
|
||||
addstr("<<< failed >>>\n");
|
||||
}
|
||||
resume_curses(FALSE);
|
||||
mode = MODE_VI;
|
||||
redraw(MARK_UNSET, FALSE);
|
||||
*o_warn = waswarn;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
|
||||
MARK v_increment(keyword, m, cnt)
|
||||
char *keyword;
|
||||
MARK m;
|
||||
long cnt;
|
||||
{
|
||||
static sign;
|
||||
char newval[12];
|
||||
long atol();
|
||||
|
||||
DEFAULT(1);
|
||||
|
||||
/* get one more keystroke, unless doingdot */
|
||||
if (!doingdot)
|
||||
{
|
||||
sign = getkey(0);
|
||||
}
|
||||
|
||||
/* adjust the number, based on that second keystroke */
|
||||
switch (sign)
|
||||
{
|
||||
case '+':
|
||||
case '#':
|
||||
cnt = atol(keyword) + cnt;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
cnt = atol(keyword) - cnt;
|
||||
break;
|
||||
|
||||
case '=':
|
||||
break;
|
||||
|
||||
default:
|
||||
return MARK_UNSET;
|
||||
}
|
||||
sprintf(newval, "%ld", cnt);
|
||||
|
||||
ChangeText
|
||||
{
|
||||
change(m, m + strlen(keyword), newval);
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* This function acts like the EX command "xit" */
|
||||
/*ARGSUSED*/
|
||||
MARK v_xit(m, cnt, key)
|
||||
MARK m; /* ignored */
|
||||
long cnt; /* ignored */
|
||||
int key; /* must be a second 'Z' */
|
||||
{
|
||||
/* if second char wasn't 'Z', fail */
|
||||
if (key != 'Z')
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
|
||||
/* move the cursor to the bottom of the screen */
|
||||
move(LINES - 1, 0);
|
||||
clrtoeol();
|
||||
|
||||
/* do the xit command */
|
||||
cmd_xit(m, m, CMD_XIT, FALSE, "");
|
||||
|
||||
/* return the cursor */
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/* This function undoes changes to a single line, if possible */
|
||||
MARK v_undoline(m)
|
||||
MARK m; /* where we hope to undo the change */
|
||||
{
|
||||
/* make sure we have the right line in the buffer */
|
||||
if (markline(m) != U_line)
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
|
||||
/* fix it */
|
||||
ChangeText
|
||||
{
|
||||
strcat(U_text, "\n");
|
||||
change(MARK_AT_LINE(U_line), MARK_AT_LINE(U_line + 1), U_text);
|
||||
}
|
||||
|
||||
/* nothing in the buffer anymore */
|
||||
U_line = -1L;
|
||||
|
||||
/* return, with the cursor at the front of the line */
|
||||
return m & ~(BLKSIZE - 1);
|
||||
}
|
||||
|
||||
|
||||
#ifndef NO_ERRLIST
|
||||
MARK v_errlist(m)
|
||||
MARK m;
|
||||
{
|
||||
cmd_errlist(m, m, CMD_ERRLIST, FALSE, "");
|
||||
return cursor;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef NO_AT
|
||||
/*ARGSUSED*/
|
||||
MARK v_at(m, cnt, key)
|
||||
MARK m;
|
||||
long cnt;
|
||||
int key;
|
||||
{
|
||||
int size;
|
||||
|
||||
size = cb2str(key, tmpblk.c, BLKSIZE);
|
||||
if (size <= 0 || size == BLKSIZE)
|
||||
{
|
||||
return MARK_UNSET;
|
||||
}
|
||||
|
||||
execmap(0, tmpblk.c, FALSE);
|
||||
return cursor;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef SIGTSTP
|
||||
MARK v_suspend()
|
||||
{
|
||||
cmd_suspend(MARK_UNSET, MARK_UNSET, CMD_SUSPEND, FALSE, "");
|
||||
return MARK_UNSET;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef NO_VISIBLE
|
||||
/*ARGSUSED*/
|
||||
MARK v_start(m, cnt, cmd)
|
||||
MARK m; /* starting point for a v or V command */
|
||||
long cnt; /* ignored */
|
||||
int cmd; /* either 'v' or 'V' */
|
||||
{
|
||||
if (V_from)
|
||||
{
|
||||
V_from = MARK_UNSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
V_from = m;
|
||||
V_linemd = isupper(cmd);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NO_POPUP
|
||||
# define MENU_HEIGHT 11
|
||||
# define MENU_WIDTH 23
|
||||
MARK v_popup(m, n)
|
||||
MARK m, n; /* the range of text to change */
|
||||
{
|
||||
int i;
|
||||
int y, x; /* position where the window will pop up at */
|
||||
int key; /* keystroke from the user */
|
||||
int sel; /* index of the selected operation */
|
||||
static int dfltsel;/* default value of sel */
|
||||
static char *labels[11] =
|
||||
{
|
||||
"ESC cancel! ",
|
||||
" d delete (cut) ",
|
||||
" y yank (copy) ",
|
||||
" p paste after ",
|
||||
" P paste before ",
|
||||
" > more indented ",
|
||||
" < less indented ",
|
||||
" = reformat ",
|
||||
" ! external filter ",
|
||||
" ZZ save & exit ",
|
||||
" u undo previous "
|
||||
};
|
||||
|
||||
/* try to position the menu near the cursor */
|
||||
x = physcol - (MENU_WIDTH / 2);
|
||||
if (x < 0)
|
||||
x = 0;
|
||||
else if (x + MENU_WIDTH + 2 > COLS)
|
||||
x = COLS - MENU_WIDTH - 2;
|
||||
if (markline(cursor) < topline || markline(cursor) > botline)
|
||||
y = 0;
|
||||
else if (markline(cursor) + 1L + MENU_HEIGHT > botline)
|
||||
y = (int)(markline(cursor) - topline) - MENU_HEIGHT;
|
||||
else
|
||||
y = (int)(markline(cursor) - topline) + 1L;
|
||||
|
||||
/* draw the menu */
|
||||
for (sel = 0; sel < MENU_HEIGHT; sel++)
|
||||
{
|
||||
move(y + sel, x);
|
||||
do_POPUP();
|
||||
if (sel == dfltsel)
|
||||
qaddstr("-->");
|
||||
else
|
||||
qaddstr(" ");
|
||||
qaddstr(labels[sel]);
|
||||
do_SE();
|
||||
}
|
||||
|
||||
/* get a selection */
|
||||
move(y + dfltsel, x + 4);
|
||||
for (sel = dfltsel; (key = getkey(WHEN_POPUP)) != '\\' && key != '\r'; )
|
||||
{
|
||||
/* erase the selection arrow */
|
||||
move(y + sel, x);
|
||||
do_POPUP();
|
||||
qaddstr(" ");
|
||||
qaddstr(labels[sel]);
|
||||
do_SE();
|
||||
|
||||
/* process the user's keystroke */
|
||||
if (key == 'j' && sel < MENU_HEIGHT - 1)
|
||||
{
|
||||
sel++;
|
||||
}
|
||||
else if (key == 'k' && sel > 0)
|
||||
{
|
||||
sel--;
|
||||
}
|
||||
else if (key == '\033')
|
||||
{
|
||||
sel = 0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 1; i < MENU_HEIGHT && labels[i][1] != key; i++)
|
||||
{
|
||||
}
|
||||
if (i < MENU_HEIGHT)
|
||||
{
|
||||
sel = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* redraw the arrow, possibly in a new place */
|
||||
move(y + sel, x);
|
||||
do_POPUP();
|
||||
qaddstr("-->");
|
||||
qaddstr(labels[sel]);
|
||||
do_SE();
|
||||
move(y + sel, x + 4);
|
||||
}
|
||||
|
||||
/* in most cases, the default selection is "paste after" */
|
||||
dfltsel = 3;
|
||||
|
||||
/* perform the appropriate action */
|
||||
switch (sel)
|
||||
{
|
||||
case 0:
|
||||
m = cursor;
|
||||
dfltsel = 0;
|
||||
break;
|
||||
|
||||
case 1: /* delete (cut) */
|
||||
m = v_delete(m, n);
|
||||
break;
|
||||
|
||||
case 2: /* yank (copy) */
|
||||
m = v_yank(m, n);
|
||||
break;
|
||||
|
||||
case 3: /* paste after */
|
||||
m = v_paste(n, 1L, 'P');
|
||||
break;
|
||||
|
||||
case 4: /* paste before */
|
||||
m = v_paste(m, 1L, 'P');
|
||||
dfltsel = 4;
|
||||
break;
|
||||
|
||||
case 5: /* more indented */
|
||||
m = v_rshift(m, n);
|
||||
dfltsel = 5;
|
||||
break;
|
||||
|
||||
case 6: /* less indented */
|
||||
m = v_lshift(m, n);
|
||||
dfltsel = 6;
|
||||
break;
|
||||
|
||||
case 7: /* reformat */
|
||||
m = v_reformat(m, n);
|
||||
dfltsel = 7;
|
||||
break;
|
||||
|
||||
case 8: /* external filter */
|
||||
m = v_filter(m, n);
|
||||
dfltsel = 0;
|
||||
break;
|
||||
|
||||
case 9: /* save & exit */
|
||||
/* get confirmation first */
|
||||
do
|
||||
{
|
||||
key = getkey(0);
|
||||
} while (key != '\\' && key != 'Z' && key != '\r' /* good */
|
||||
&& key != '\033'); /* bad */
|
||||
if (key != '\033')
|
||||
{
|
||||
m = v_xit(m, 0L, 'Z');
|
||||
}
|
||||
break;
|
||||
|
||||
case 10: /* undo previous */
|
||||
m = v_undo(m);
|
||||
dfltsel = 9;
|
||||
break;
|
||||
}
|
||||
|
||||
/* arrange for the menu to be erased (except that "chg from kbd"
|
||||
* already erased it, and "save & exit" doesn't care)
|
||||
*/
|
||||
if (sel != 5 && sel != 9)
|
||||
redraw(MARK_UNSET, FALSE);
|
||||
|
||||
return m;
|
||||
}
|
||||
#endif /* undef NO_POPUP */
|
|
@ -1,815 +0,0 @@
|
|||
/* vi.c */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* Beaverton, OR 97005
|
||||
* kirkenda@cs.pdx.edu
|
||||
*/
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include "ctype.h"
|
||||
#include "vi.h"
|
||||
|
||||
|
||||
|
||||
/* This array describes what each key does */
|
||||
#define NO_FUNC (MARK (*)())0
|
||||
|
||||
#define NO_ARGS 0
|
||||
#define CURSOR 1
|
||||
#define CURSOR_CNT_KEY 2
|
||||
#define CURSOR_MOVED 3
|
||||
#define CURSOR_EOL 4
|
||||
#define ZERO 5
|
||||
#define DIGIT 6
|
||||
#define CURSOR_TEXT 7
|
||||
#define KEYWORD 8
|
||||
#define ARGSMASK 0x0f
|
||||
#define C_C_K_REP1 (CURSOR_CNT_KEY | 0x10)
|
||||
#define C_C_K_CUT (CURSOR_CNT_KEY | 0x20)
|
||||
#define C_C_K_MARK (CURSOR_CNT_KEY | 0x30)
|
||||
#define C_C_K_CHAR (CURSOR_CNT_KEY | 0x40)
|
||||
#ifndef NO_SHOWMODE
|
||||
static int keymodes[] = {0, WHEN_REP1, WHEN_CUT, WHEN_MARK, WHEN_CHAR};
|
||||
# define KEYMODE(args) (keymodes[(args) >> 4])
|
||||
#else
|
||||
# define KEYMODE(args) 0
|
||||
#endif
|
||||
|
||||
static struct keystru
|
||||
{
|
||||
MARK (*func)(); /* the function to run */
|
||||
uchar args; /* description of the args needed */
|
||||
#ifndef NO_VISIBLE
|
||||
short flags;
|
||||
#else
|
||||
uchar flags; /* other stuff */
|
||||
#endif
|
||||
}
|
||||
vikeys[] =
|
||||
{
|
||||
/* NUL not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
#ifndef NO_EXTENSIONS
|
||||
/* ^A find cursor word */ {m_wsrch, KEYWORD, MVMT|NREL|VIZ},
|
||||
#else
|
||||
/* ^A not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
#endif
|
||||
/* ^B page backward */ {m_scroll, CURSOR, FRNT|VIZ},
|
||||
/* ^C not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
/* ^D scroll dn 1/2page*/ {m_scroll, CURSOR, NCOL|VIZ},
|
||||
/* ^E scroll up */ {m_scroll, CURSOR, NCOL|VIZ},
|
||||
/* ^F page forward */ {m_scroll, CURSOR, FRNT|VIZ},
|
||||
/* ^G show file status */ {v_status, NO_ARGS, NO_FLAGS},
|
||||
/* ^H move left, like h*/ {m_left, CURSOR, MVMT|VIZ},
|
||||
/* ^I not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
/* ^J move down */ {m_updnto, CURSOR, MVMT|LNMD|VIZ|INCL},
|
||||
/* ^K not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
/* ^L redraw screen */ {v_redraw, NO_ARGS, NO_FLAGS|VIZ},
|
||||
/* ^M mv front next ln */ {m_updnto, CURSOR, MVMT|FRNT|LNMD|VIZ|INCL},
|
||||
/* ^N move down */ {m_updnto, CURSOR, MVMT|LNMD|VIZ|INCL|NCOL},
|
||||
/* ^O not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
/* ^P move up */ {m_updnto, CURSOR, MVMT|LNMD|VIZ|INCL|NCOL},
|
||||
/* ^Q not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
/* ^R redraw screen */ {v_redraw, NO_ARGS, NO_FLAGS|VIZ},
|
||||
/* ^S not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
/* ^T not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
/* ^U scroll up 1/2page*/ {m_scroll, CURSOR, NCOL|VIZ},
|
||||
/* ^V not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
/* ^W not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
/* ^X move to phys col */ {m_tocol, CURSOR, MVMT|NREL|VIZ},
|
||||
/* ^Y scroll down */ {m_scroll, CURSOR, NCOL|VIZ},
|
||||
#ifdef SIGTSTP
|
||||
/* ^Z suspend elvis */ {v_suspend, NO_ARGS, NO_FLAGS},
|
||||
#else
|
||||
/* ^Z not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
#endif
|
||||
/* ESC not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
/* ^\ not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
/* ^] keyword is tag */ {v_tag, KEYWORD, NO_FLAGS},
|
||||
/* ^^ previous file */ {v_switch, CURSOR, NO_FLAGS},
|
||||
/* ^_ not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
/* SPC move right,like l*/ {m_right, CURSOR, MVMT|INCL|VIZ},
|
||||
/* ! run thru filter */ {v_filter, CURSOR_MOVED, FRNT|LNMD|INCL|VIZ},
|
||||
/* " select cut buffer*/ {v_selcut, C_C_K_CUT, PTMV|VIZ},
|
||||
#ifndef NO_EXTENSIONS
|
||||
/* # increment number */ {v_increment, KEYWORD, SDOT},
|
||||
#else
|
||||
/* # not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
#endif
|
||||
/* $ move to rear */ {m_rear, CURSOR, MVMT|INCL|VIZ},
|
||||
/* % move to match */ {m_match, CURSOR, MVMT|INCL|VIZ},
|
||||
/* & repeat subst */ {v_again, CURSOR_MOVED, SDOT|NCOL|LNMD|INCL},
|
||||
/* ' move to a mark */ {m_tomark, C_C_K_MARK, MVMT|FRNT|NREL|LNMD|INCL|VIZ},
|
||||
#ifndef NO_SENTENCE
|
||||
/* ( mv back sentence */ {m_sentence, CURSOR, MVMT|VIZ},
|
||||
/* ) mv fwd sentence */ {m_sentence, CURSOR, MVMT|VIZ},
|
||||
#else
|
||||
/* ( not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
/* ) not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
#endif
|
||||
#ifndef NO_ERRLIST
|
||||
/* * errlist */ {v_errlist, CURSOR, FRNT|NREL},
|
||||
#else
|
||||
/* * not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
#endif
|
||||
/* + mv front next ln */ {m_updnto, CURSOR, MVMT|FRNT|LNMD|VIZ|INCL},
|
||||
#ifndef NO_CHARSEARCH
|
||||
/* , reverse [fFtT] cmd*/ {m__ch, CURSOR, MVMT|INCL|VIZ},
|
||||
#else
|
||||
/* , not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
#endif
|
||||
/* - mv front prev ln */ {m_updnto, CURSOR, MVMT|FRNT|LNMD|VIZ|INCL},
|
||||
/* . special... */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
/* / forward search */ {m_fsrch, CURSOR_TEXT, MVMT|NREL|VIZ},
|
||||
/* 0 part of count? */ {NO_FUNC, ZERO, MVMT|PTMV|VIZ},
|
||||
/* 1 part of count */ {NO_FUNC, DIGIT, PTMV|VIZ},
|
||||
/* 2 part of count */ {NO_FUNC, DIGIT, PTMV|VIZ},
|
||||
/* 3 part of count */ {NO_FUNC, DIGIT, PTMV|VIZ},
|
||||
/* 4 part of count */ {NO_FUNC, DIGIT, PTMV|VIZ},
|
||||
/* 5 part of count */ {NO_FUNC, DIGIT, PTMV|VIZ},
|
||||
/* 6 part of count */ {NO_FUNC, DIGIT, PTMV|VIZ},
|
||||
/* 7 part of count */ {NO_FUNC, DIGIT, PTMV|VIZ},
|
||||
/* 8 part of count */ {NO_FUNC, DIGIT, PTMV|VIZ},
|
||||
/* 9 part of count */ {NO_FUNC, DIGIT, PTMV|VIZ},
|
||||
/* : run single EX cmd*/ {v_1ex, CURSOR_TEXT, NO_FLAGS},
|
||||
#ifndef NO_CHARSEARCH
|
||||
/* ; repeat [fFtT] cmd*/ {m__ch, CURSOR, MVMT|INCL|VIZ},
|
||||
#else
|
||||
/* ; not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS|VIZ},
|
||||
#endif
|
||||
/* < shift text left */ {v_lshift, CURSOR_MOVED, SDOT|FRNT|LNMD|INCL|VIZ},
|
||||
/* = preset filter */ {v_reformat, CURSOR_MOVED, SDOT|FRNT|LNMD|INCL|VIZ},
|
||||
/* > shift text right */ {v_rshift, CURSOR_MOVED, SDOT|FRNT|LNMD|INCL|VIZ},
|
||||
/* ? backward search */ {m_bsrch, CURSOR_TEXT, MVMT|NREL|VIZ},
|
||||
#ifndef NO_AT
|
||||
/* @ execute a cutbuf */ {v_at, C_C_K_CUT, NO_FLAGS},
|
||||
#else
|
||||
/* @ not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
#endif
|
||||
/* A append at EOL */ {v_insert, CURSOR, SDOT},
|
||||
/* B move back Word */ {m_bword, CURSOR, MVMT|VIZ},
|
||||
/* C change to EOL */ {v_change, CURSOR_EOL, SDOT},
|
||||
/* D delete to EOL */ {v_delete, CURSOR_EOL, SDOT},
|
||||
/* E move end of Word */ {m_eword, CURSOR, MVMT|INCL|VIZ},
|
||||
#ifndef NO_CHARSEARCH
|
||||
/* F move bk to char */ {m_Fch, C_C_K_CHAR, MVMT|INCL|VIZ},
|
||||
#else
|
||||
/* F not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
#endif
|
||||
/* G move to line # */ {m_updnto, CURSOR, MVMT|NREL|LNMD|FRNT|INCL|VIZ},
|
||||
/* H move to row */ {m_row, CURSOR, MVMT|LNMD|FRNT|VIZ|INCL},
|
||||
/* I insert at front */ {v_insert, CURSOR, SDOT},
|
||||
/* J join lines */ {v_join, CURSOR, SDOT},
|
||||
#ifndef NO_EXTENSIONS
|
||||
/* K look up keyword */ {v_keyword, KEYWORD, NO_FLAGS},
|
||||
#else
|
||||
/* K not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
#endif
|
||||
/* L move to last row */ {m_row, CURSOR, MVMT|LNMD|FRNT|VIZ|INCL},
|
||||
/* M move to mid row */ {m_row, CURSOR, MVMT|LNMD|FRNT|VIZ|INCL},
|
||||
/* N reverse prev srch*/ {m_Nsrch, CURSOR, MVMT|NREL|VIZ},
|
||||
/* O insert above line*/ {v_insert, CURSOR, SDOT},
|
||||
/* P paste before */ {v_paste, CURSOR, SDOT},
|
||||
/* Q quit to EX mode */ {v_quit, NO_ARGS, NO_FLAGS},
|
||||
/* R overtype */ {v_overtype, CURSOR, SDOT},
|
||||
/* S change line */ {v_change, CURSOR_MOVED, SDOT},
|
||||
#ifndef NO_CHARSEARCH
|
||||
/* T move bk to char */ {m_Tch, C_C_K_CHAR, MVMT|INCL|VIZ},
|
||||
#else
|
||||
/* T not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
#endif
|
||||
/* U undo whole line */ {v_undoline, CURSOR, FRNT},
|
||||
#ifndef NO_VISIBLE
|
||||
/* V start visible */ {v_start, CURSOR, INCL|LNMD|VIZ},
|
||||
#else
|
||||
/* V not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
#endif
|
||||
/* W move forward Word*/ {m_fword, CURSOR, MVMT|INCL|VIZ},
|
||||
/* X delete to left */ {v_xchar, CURSOR, SDOT},
|
||||
/* Y yank text */ {v_yank, CURSOR_MOVED, NCOL},
|
||||
/* Z save file & exit */ {v_xit, CURSOR_CNT_KEY, NO_FLAGS},
|
||||
/* [ move back section*/ {m_paragraph, CURSOR, MVMT|LNMD|NREL|VIZ},
|
||||
#ifndef NO_POPUP
|
||||
/* \ pop-up menu */ {v_popup, CURSOR_MOVED, VIZ},
|
||||
#else
|
||||
/* \ not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
#endif
|
||||
/* ] move fwd section */ {m_paragraph, CURSOR, MVMT|LNMD|NREL|VIZ},
|
||||
/* ^ move to front */ {m_front, CURSOR, MVMT|VIZ},
|
||||
/* _ current line */ {m_updnto, CURSOR, MVMT|LNMD|FRNT|INCL},
|
||||
/* ` move to mark */ {m_tomark, C_C_K_MARK, MVMT|NREL|VIZ},
|
||||
/* a append at cursor */ {v_insert, CURSOR, SDOT},
|
||||
/* b move back word */ {m_bword, CURSOR, MVMT|VIZ},
|
||||
/* c change text */ {v_change, CURSOR_MOVED, SDOT|VIZ},
|
||||
/* d delete op */ {v_delete, CURSOR_MOVED, SDOT|VIZ},
|
||||
/* e move end word */ {m_eword, CURSOR, MVMT|INCL|VIZ},
|
||||
#ifndef NO_CHARSEARCH
|
||||
/* f move fwd for char*/ {m_fch, C_C_K_CHAR, MVMT|INCL|VIZ},
|
||||
#else
|
||||
/* f not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
#endif
|
||||
/* g not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
/* h move left */ {m_left, CURSOR, MVMT|VIZ},
|
||||
/* i insert at cursor */ {v_insert, CURSOR, SDOT},
|
||||
/* j move down */ {m_updnto, CURSOR, MVMT|NCOL|LNMD|VIZ|INCL},
|
||||
/* k move up */ {m_updnto, CURSOR, MVMT|NCOL|LNMD|VIZ|INCL},
|
||||
/* l move right */ {m_right, CURSOR, MVMT|INCL|VIZ},
|
||||
/* m define a mark */ {v_mark, C_C_K_MARK, NO_FLAGS},
|
||||
/* n repeat prev srch */ {m_nsrch, CURSOR, MVMT|NREL|VIZ},
|
||||
/* o insert below line*/ {v_insert, CURSOR, SDOT},
|
||||
/* p paste after */ {v_paste, CURSOR, SDOT},
|
||||
/* q not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
/* r replace chars */ {v_replace, C_C_K_REP1, SDOT},
|
||||
/* s subst N chars */ {v_subst, CURSOR, SDOT},
|
||||
#ifndef NO_CHARSEARCH
|
||||
/* t move fwd to char */ {m_tch, C_C_K_CHAR, MVMT|INCL|VIZ},
|
||||
#else
|
||||
/* t not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
#endif
|
||||
/* u undo */ {v_undo, CURSOR, NO_FLAGS},
|
||||
#ifndef NO_VISIBLE
|
||||
/* v start visible */ {v_start, CURSOR, INCL|VIZ},
|
||||
#else
|
||||
/* v not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
|
||||
#endif
|
||||
/* w move fwd word */ {m_fword, CURSOR, MVMT|INCL|VIZ},
|
||||
/* x delete character */ {v_xchar, CURSOR, SDOT},
|
||||
/* y yank text */ {v_yank, CURSOR_MOVED, NCOL|VIZ},
|
||||
/* z adjust scrn row */ {m_z, CURSOR_CNT_KEY, NCOL|VIZ},
|
||||
/* { back paragraph */ {m_paragraph, CURSOR, MVMT|LNMD|VIZ},
|
||||
/* | move to column */ {m_tocol, CURSOR, MVMT|NREL|VIZ},
|
||||
/* } fwd paragraph */ {m_paragraph, CURSOR, MVMT|LNMD|VIZ},
|
||||
/* ~ upper/lowercase */ {v_ulcase, CURSOR, SDOT},
|
||||
/* DEL not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS}
|
||||
};
|
||||
|
||||
|
||||
|
||||
void vi()
|
||||
{
|
||||
REG int key; /* keystroke from user */
|
||||
long count; /* numeric argument to some functions */
|
||||
REG struct keystru *keyptr;/* pointer to vikeys[] element */
|
||||
MARK tcurs; /* temporary cursor */
|
||||
int prevkey;/* previous key, if d/c/y/</>/! */
|
||||
MARK range; /* start of range for d/c/y/</>/! */
|
||||
char text[132];
|
||||
int dotkey; /* last "key" of a change */
|
||||
int dotpkey;/* last "prevkey" of a change */
|
||||
int dotkey2;/* last extra "getkey()" of a change */
|
||||
int dotcnt; /* last "count" of a change */
|
||||
int firstkey;
|
||||
REG int i;
|
||||
|
||||
/* tell the redraw() function to start from scratch */
|
||||
redraw(MARK_UNSET, FALSE);
|
||||
|
||||
#ifdef lint
|
||||
/* lint says that "range" might be used before it is set. This
|
||||
* can't really happen due to the way "range" and "prevkey" are used,
|
||||
* but lint doesn't know that. This line is here ONLY to keep lint
|
||||
* happy.
|
||||
*/
|
||||
range = 0L;
|
||||
#endif
|
||||
|
||||
/* safeguard against '.' with no previous command */
|
||||
dotkey = dotpkey = dotkey2 = dotcnt = 0;
|
||||
|
||||
/* go immediately into insert mode, if ":set inputmode" */
|
||||
firstkey = 0;
|
||||
#ifndef NO_EXTENSIONS
|
||||
if (*o_inputmode)
|
||||
{
|
||||
firstkey = 'i';
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Repeatedly handle VI commands */
|
||||
for (count = 0, prevkey = '\0'; mode == MODE_VI; )
|
||||
{
|
||||
/* if we've moved off the undoable line, then we can't undo it at all */
|
||||
if (markline(cursor) != U_line)
|
||||
{
|
||||
U_line = 0L;
|
||||
}
|
||||
|
||||
/* report any changes from the previous command */
|
||||
if (rptlines >= *o_report)
|
||||
{
|
||||
redraw(cursor, FALSE);
|
||||
msg("%ld line%s %s", rptlines, (rptlines==1?"":"s"), rptlabel);
|
||||
}
|
||||
rptlines = 0L;
|
||||
|
||||
/* get the next command key. It must be ASCII */
|
||||
if (firstkey)
|
||||
{
|
||||
key = firstkey;
|
||||
firstkey = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
key = getkey(WHEN_VICMD);
|
||||
} while (key < 0 || key > 127);
|
||||
}
|
||||
|
||||
/* Convert a doubled-up operator such as "dd" into "d_" */
|
||||
if (prevkey && key == prevkey)
|
||||
{
|
||||
key = '_';
|
||||
}
|
||||
|
||||
/* look up the structure describing this command */
|
||||
keyptr = &vikeys[key];
|
||||
|
||||
/* '&' and uppercase operators always act like doubled */
|
||||
if (!prevkey && keyptr->args == CURSOR_MOVED
|
||||
&& (key == '&' || isupper(key)))
|
||||
{
|
||||
range = cursor;
|
||||
prevkey = key;
|
||||
key = '_';
|
||||
keyptr = &vikeys[key];
|
||||
}
|
||||
|
||||
#ifndef NO_VISIBLE
|
||||
/* if we're in the middle of a v/V command, reject commands
|
||||
* that aren't operators or movement commands
|
||||
*/
|
||||
if (V_from && !(keyptr->flags & VIZ))
|
||||
{
|
||||
beep();
|
||||
prevkey = 0;
|
||||
count = 0;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* if we're in the middle of a d/c/y/</>/! command, reject
|
||||
* anything but movement.
|
||||
*/
|
||||
if (prevkey && !(keyptr->flags & (MVMT|PTMV)))
|
||||
{
|
||||
beep();
|
||||
prevkey = 0;
|
||||
count = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* set the "dot" variables, if we're supposed to */
|
||||
if (((keyptr->flags & SDOT)
|
||||
|| (prevkey && vikeys[prevkey].flags & SDOT))
|
||||
#ifndef NO_VISIBLE
|
||||
&& !V_from
|
||||
#endif
|
||||
)
|
||||
{
|
||||
dotkey = key;
|
||||
dotpkey = prevkey;
|
||||
dotkey2 = '\0';
|
||||
dotcnt = count;
|
||||
|
||||
/* remember the line before any changes are made */
|
||||
if (U_line != markline(cursor))
|
||||
{
|
||||
U_line = markline(cursor);
|
||||
strcpy(U_text, fetchline(U_line));
|
||||
}
|
||||
}
|
||||
|
||||
/* if this is "." then set other vars from the "dot" vars */
|
||||
if (key == '.')
|
||||
{
|
||||
key = dotkey;
|
||||
keyptr = &vikeys[key];
|
||||
prevkey = dotpkey;
|
||||
if (prevkey)
|
||||
{
|
||||
range = cursor;
|
||||
}
|
||||
if (count == 0)
|
||||
{
|
||||
count = dotcnt;
|
||||
}
|
||||
doingdot = TRUE;
|
||||
|
||||
/* remember the line before any changes are made */
|
||||
if (U_line != markline(cursor))
|
||||
{
|
||||
U_line = markline(cursor);
|
||||
strcpy(U_text, fetchline(U_line));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
doingdot = FALSE;
|
||||
}
|
||||
|
||||
/* process the key as a command */
|
||||
tcurs = cursor;
|
||||
force_flags = NO_FLAGS;
|
||||
switch (keyptr->args & ARGSMASK)
|
||||
{
|
||||
case ZERO:
|
||||
if (count == 0)
|
||||
{
|
||||
tcurs = cursor & ~(BLKSIZE - 1);
|
||||
break;
|
||||
}
|
||||
/* else fall through & treat like other digits... */
|
||||
|
||||
case DIGIT:
|
||||
count = count * 10 + key - '0';
|
||||
break;
|
||||
|
||||
case KEYWORD:
|
||||
/* if not on a keyword, fail */
|
||||
pfetch(markline(cursor));
|
||||
key = markidx(cursor);
|
||||
if (!isalnum(ptext[key]))
|
||||
{
|
||||
tcurs = MARK_UNSET;
|
||||
break;
|
||||
}
|
||||
|
||||
/* find the start of the keyword */
|
||||
while (key > 0 && isalnum(ptext[key - 1]))
|
||||
{
|
||||
key--;
|
||||
}
|
||||
tcurs = (cursor & ~(BLKSIZE - 1)) + key;
|
||||
|
||||
/* copy it into a buffer, and NUL-terminate it */
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
text[i++] = ptext[key++];
|
||||
} while (isalnum(ptext[key]));
|
||||
text[i] = '\0';
|
||||
|
||||
/* call the function */
|
||||
tcurs = (*keyptr->func)(text, tcurs, count);
|
||||
count = 0L;
|
||||
break;
|
||||
|
||||
case NO_ARGS:
|
||||
if (keyptr->func)
|
||||
{
|
||||
(*keyptr->func)();
|
||||
}
|
||||
else
|
||||
{
|
||||
beep();
|
||||
}
|
||||
count = 0L;
|
||||
break;
|
||||
|
||||
case CURSOR:
|
||||
tcurs = (*keyptr->func)(cursor, count, key, prevkey);
|
||||
count = 0L;
|
||||
break;
|
||||
|
||||
case CURSOR_CNT_KEY:
|
||||
if (doingdot)
|
||||
{
|
||||
tcurs = (*keyptr->func)(cursor, count, dotkey2);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* get a key */
|
||||
i = getkey(KEYMODE(keyptr->args));
|
||||
if (i == '\033') /* ESC */
|
||||
{
|
||||
count = 0;
|
||||
tcurs = MARK_UNSET;
|
||||
break; /* exit from "case CURSOR_CNT_KEY" */
|
||||
}
|
||||
else if (i == ctrl('V'))
|
||||
{
|
||||
i = getkey(0);
|
||||
}
|
||||
|
||||
/* if part of an SDOT command, remember it */
|
||||
if (keyptr->flags & SDOT
|
||||
|| (prevkey && vikeys[prevkey].flags & SDOT))
|
||||
{
|
||||
dotkey2 = i;
|
||||
}
|
||||
|
||||
/* do it */
|
||||
tcurs = (*keyptr->func)(cursor, count, i);
|
||||
}
|
||||
count = 0L;
|
||||
break;
|
||||
|
||||
case CURSOR_MOVED:
|
||||
#ifndef NO_VISIBLE
|
||||
if (V_from)
|
||||
{
|
||||
range = cursor;
|
||||
tcurs = V_from;
|
||||
count = 0L;
|
||||
prevkey = key;
|
||||
key = (V_linemd ? 'V' : 'v');
|
||||
keyptr = &vikeys[key];
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
prevkey = key;
|
||||
range = cursor;
|
||||
force_flags = LNMD|INCL;
|
||||
}
|
||||
break;
|
||||
|
||||
case CURSOR_EOL:
|
||||
prevkey = key;
|
||||
/* a zero-length line needs special treatment */
|
||||
pfetch(markline(cursor));
|
||||
if (plen == 0)
|
||||
{
|
||||
/* act on a zero-length section of text */
|
||||
range = tcurs = cursor;
|
||||
key = '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
/* act like CURSOR_MOVED with '$' movement */
|
||||
range = cursor;
|
||||
tcurs = m_rear(cursor, 1L);
|
||||
key = '$';
|
||||
}
|
||||
count = 0L;
|
||||
keyptr = &vikeys[key];
|
||||
break;
|
||||
|
||||
case CURSOR_TEXT:
|
||||
do
|
||||
{
|
||||
text[0] = key;
|
||||
if (vgets(key, text + 1, sizeof text - 1) >= 0)
|
||||
{
|
||||
/* reassure user that <CR> was hit */
|
||||
qaddch('\r');
|
||||
refresh();
|
||||
|
||||
/* call the function with the text */
|
||||
tcurs = (*keyptr->func)(cursor, text);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (exwrote || mode == MODE_COLON)
|
||||
{
|
||||
redraw(MARK_UNSET, FALSE);
|
||||
}
|
||||
mode = MODE_VI;
|
||||
}
|
||||
} while (mode == MODE_COLON);
|
||||
count = 0L;
|
||||
break;
|
||||
}
|
||||
|
||||
/* if that command took us out of vi mode, then exit the loop
|
||||
* NOW, without tweaking the cursor or anything. This is very
|
||||
* important when mode == MODE_QUIT.
|
||||
*/
|
||||
if (mode != MODE_VI)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* now move the cursor, as appropriate */
|
||||
if (keyptr->args == CURSOR_MOVED)
|
||||
{
|
||||
/* the < and > keys have FRNT,
|
||||
* but it shouldn't be applied yet
|
||||
*/
|
||||
tcurs = adjmove(cursor, tcurs, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
tcurs = adjmove(cursor, tcurs, (int)keyptr->flags | force_flags);
|
||||
}
|
||||
|
||||
/* was that the end of a d/c/y/</>/! command? */
|
||||
if (prevkey && ((keyptr->flags & MVMT)
|
||||
#ifndef NO_VISIBLE
|
||||
|| V_from
|
||||
#endif
|
||||
) && count == 0L)
|
||||
{
|
||||
#ifndef NO_VISIBLE
|
||||
/* turn off the hilight */
|
||||
V_from = 0L;
|
||||
#endif
|
||||
|
||||
/* if the movement command failed, cancel operation */
|
||||
if (tcurs == MARK_UNSET)
|
||||
{
|
||||
prevkey = 0;
|
||||
count = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* make sure range=front and tcurs=rear. Either way,
|
||||
* leave cursor=range since that's where we started.
|
||||
*/
|
||||
cursor = range;
|
||||
if (tcurs < range)
|
||||
{
|
||||
range = tcurs;
|
||||
tcurs = cursor;
|
||||
}
|
||||
|
||||
/* The 'w' and 'W' destinations should never take us
|
||||
* to the front of a line. Instead, they should take
|
||||
* us only to the end of the preceding line.
|
||||
*/
|
||||
if ((keyptr->flags & (MVMT|NREL|LNMD|FRNT|INCL)) == MVMT
|
||||
&& markline(range) < markline(tcurs)
|
||||
&& (markline(tcurs) > nlines || tcurs == m_front(tcurs, 0L)))
|
||||
{
|
||||
tcurs = (tcurs & ~(BLKSIZE - 1)) - BLKSIZE;
|
||||
pfetch(markline(tcurs));
|
||||
tcurs += plen;
|
||||
}
|
||||
|
||||
/* adjust for line mode & inclusion of last char/line */
|
||||
i = (keyptr->flags | vikeys[prevkey].flags);
|
||||
switch ((i | force_flags) & (INCL|LNMD))
|
||||
{
|
||||
case INCL:
|
||||
tcurs++;
|
||||
break;
|
||||
|
||||
case INCL|LNMD:
|
||||
tcurs += BLKSIZE;
|
||||
/* fall through... */
|
||||
|
||||
case LNMD:
|
||||
range &= ~(BLKSIZE - 1);
|
||||
tcurs &= ~(BLKSIZE - 1);
|
||||
break;
|
||||
}
|
||||
|
||||
/* run the function */
|
||||
tcurs = (*vikeys[prevkey].func)(range, tcurs);
|
||||
if (mode == MODE_VI)
|
||||
{
|
||||
(void)adjmove(cursor, cursor, 0);
|
||||
cursor = adjmove(cursor, tcurs, (int)vikeys[prevkey].flags);
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
prevkey = 0;
|
||||
}
|
||||
else if (!prevkey)
|
||||
{
|
||||
if (tcurs != MARK_UNSET)
|
||||
cursor = tcurs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This function adjusts the MARK value that they return; here we make sure
|
||||
* it isn't past the end of the line, and that the column hasn't been
|
||||
* *accidentally* changed.
|
||||
*/
|
||||
MARK adjmove(old, new, flags)
|
||||
MARK old; /* the cursor position before the command */
|
||||
REG MARK new; /* the cursor position after the command */
|
||||
int flags; /* various flags regarding cursor mvmt */
|
||||
{
|
||||
static int colno; /* the column number that we want */
|
||||
REG char *text; /* used to scan through the line's text */
|
||||
REG int i;
|
||||
|
||||
#ifdef DEBUG
|
||||
watch();
|
||||
#endif
|
||||
|
||||
/* if the command failed, bag it! */
|
||||
if (new == MARK_UNSET)
|
||||
{
|
||||
beep();
|
||||
return old;
|
||||
}
|
||||
|
||||
/* if this is a non-relative movement, set the '' mark */
|
||||
if (flags & NREL)
|
||||
{
|
||||
mark[26] = old;
|
||||
}
|
||||
|
||||
/* make sure it isn't past the end of the file */
|
||||
if (markline(new) < 1)
|
||||
{
|
||||
new = MARK_FIRST;
|
||||
}
|
||||
else if (markline(new) > nlines)
|
||||
{
|
||||
new = MARK_LAST;
|
||||
}
|
||||
|
||||
/* fetch the new line */
|
||||
pfetch(markline(new));
|
||||
|
||||
/* move to the front, if we're supposed to */
|
||||
if (flags & FRNT)
|
||||
{
|
||||
new = m_front(new, 1L);
|
||||
}
|
||||
|
||||
/* change the column#, or change the mark to suit the column# */
|
||||
if (!(flags & NCOL))
|
||||
{
|
||||
/* change the column# */
|
||||
i = markidx(new);
|
||||
if (i == BLKSIZE - 1)
|
||||
{
|
||||
new &= ~(BLKSIZE - 1);
|
||||
if (plen > 0)
|
||||
{
|
||||
new += plen - 1;
|
||||
}
|
||||
colno = BLKSIZE * 8; /* one heck of a big colno */
|
||||
}
|
||||
else if (plen > 0)
|
||||
{
|
||||
if (i >= plen)
|
||||
{
|
||||
new = (new & ~(BLKSIZE - 1)) + plen - 1;
|
||||
}
|
||||
colno = idx2col(new, ptext, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
new &= ~(BLKSIZE - 1);
|
||||
colno = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* adjust the mark to get as close as possible to column# */
|
||||
for (i = 0, text = ptext; i <= colno && *text; text++)
|
||||
{
|
||||
if (*text == '\t' && !*o_list)
|
||||
{
|
||||
i += *o_tabstop - (i % *o_tabstop);
|
||||
}
|
||||
else if (UCHAR(*text) < ' ' || *text == 127)
|
||||
{
|
||||
i += 2;
|
||||
}
|
||||
#ifndef NO_CHARATTR
|
||||
else if (*o_charattr && text[0] == '\\' && text[1] == 'f' && text[2])
|
||||
{
|
||||
text += 2; /* plus one more in "for()" stmt */
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (text > ptext)
|
||||
{
|
||||
text--;
|
||||
}
|
||||
new = (new & ~(BLKSIZE - 1)) + (int)(text - ptext);
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
watch()
|
||||
{
|
||||
static wasset;
|
||||
|
||||
if (*origname)
|
||||
{
|
||||
wasset = TRUE;
|
||||
}
|
||||
else if (wasset)
|
||||
{
|
||||
mode = MODE_EX;
|
||||
msg("origname was clobbered");
|
||||
endwin();
|
||||
abort();
|
||||
}
|
||||
|
||||
if (wasset && nlines == 0)
|
||||
{
|
||||
mode = MODE_EX;
|
||||
msg("nlines=0");
|
||||
endwin();
|
||||
abort();
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,596 +0,0 @@
|
|||
/* vi.h */
|
||||
|
||||
/* Author:
|
||||
* Steve Kirkendall
|
||||
* 14407 SW Teal Blvd. #C
|
||||
* Beaverton, OR 97005
|
||||
* kirkenda@cs.pdx.edu
|
||||
*/
|
||||
|
||||
#define VERSION "ELVIS 1.5, by Steve Kirkendall (23 March 1992)"
|
||||
#define COPYING "This version of ELVIS is freely redistributable."
|
||||
|
||||
#include <errno.h>
|
||||
extern int errno;
|
||||
#if TOS && !defined(__GNUC__)
|
||||
#define ENOENT (-AEFILNF)
|
||||
#endif
|
||||
|
||||
#if TOS || VMS
|
||||
# include <types.h>
|
||||
# define O_RDONLY 0
|
||||
# define O_WRONLY 1
|
||||
# define O_RDWR 2
|
||||
# ifdef __GNUC__
|
||||
# define S_IJDIR S_IFDIR
|
||||
# endif
|
||||
#else
|
||||
# if OSK
|
||||
# include <modes.h>
|
||||
# define O_RDONLY S_IREAD
|
||||
# define O_WRONLY S_IWRITE
|
||||
# define O_RDWR (S_IREAD | S_IWRITE)
|
||||
# define ENOENT E_PNNF
|
||||
# define sprintf Sprintf
|
||||
# else
|
||||
# include <sys/types.h>
|
||||
# if COHERENT
|
||||
# include <sys/fcntl.h>
|
||||
# else
|
||||
# include <fcntl.h>
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef O_BINARY
|
||||
# define O_BINARY 0
|
||||
#endif
|
||||
|
||||
#include "curses.h"
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Miscellaneous constants. */
|
||||
|
||||
#define INFINITY 2000000001L /* a very large integer */
|
||||
#define LONGKEY 10 /* longest possible raw :map key */
|
||||
#ifndef MAXRCLEN
|
||||
# define MAXRCLEN 1000 /* longest possible :@ command */
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* These describe how temporary files are divided into blocks */
|
||||
|
||||
#define MAXBLKS (BLKSIZE / sizeof(unsigned short))
|
||||
typedef union
|
||||
{
|
||||
char c[BLKSIZE]; /* for text blocks */
|
||||
unsigned short n[MAXBLKS]; /* for the header block */
|
||||
}
|
||||
BLK;
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* These are used manipulate BLK buffers. */
|
||||
|
||||
extern BLK hdr; /* buffer for the header block */
|
||||
extern BLK *blkget(); /* given index into hdr.c[], reads block */
|
||||
extern BLK *blkadd(); /* inserts a new block into hdr.c[] */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* These are used to keep track of various flags */
|
||||
extern struct _viflags
|
||||
{
|
||||
short file; /* file flags */
|
||||
}
|
||||
viflags;
|
||||
|
||||
/* file flags */
|
||||
#define NEWFILE 0x0001 /* the file was just created */
|
||||
#define READONLY 0x0002 /* the file is read-only */
|
||||
#define HADNUL 0x0004 /* the file contained NUL characters */
|
||||
#define MODIFIED 0x0008 /* the file has been modified, but not saved */
|
||||
#define NOFILE 0x0010 /* no name is known for the current text */
|
||||
#define ADDEDNL 0x0020 /* newlines were added to the file */
|
||||
#define HADBS 0x0040 /* backspace chars were lost from the file */
|
||||
#define UNDOABLE 0x0080 /* file has been modified */
|
||||
#define NOTEDITED 0x0100 /* the :file command has been used */
|
||||
|
||||
/* macros used to set/clear/test flags */
|
||||
#define setflag(x,y) viflags.x |= y
|
||||
#define clrflag(x,y) viflags.x &= ~y
|
||||
#define tstflag(x,y) (viflags.x & y)
|
||||
#define initflags() viflags.file = 0;
|
||||
|
||||
/* The options */
|
||||
extern char o_autoindent[1];
|
||||
extern char o_autoprint[1];
|
||||
extern char o_autotab[1];
|
||||
extern char o_autowrite[1];
|
||||
extern char o_columns[3];
|
||||
extern char o_directory[30];
|
||||
extern char o_edcompatible[1];
|
||||
extern char o_equalprg[80];
|
||||
extern char o_errorbells[1];
|
||||
extern char o_exrefresh[1];
|
||||
extern char o_ignorecase[1];
|
||||
extern char o_keytime[3];
|
||||
extern char o_keywordprg[80];
|
||||
extern char o_lines[3];
|
||||
extern char o_list[1];
|
||||
extern char o_number[1];
|
||||
extern char o_readonly[1];
|
||||
extern char o_remap[1];
|
||||
extern char o_report[3];
|
||||
extern char o_scroll[3];
|
||||
extern char o_shell[60];
|
||||
extern char o_shiftwidth[3];
|
||||
extern char o_sidescroll[3];
|
||||
extern char o_sync[1];
|
||||
extern char o_tabstop[3];
|
||||
extern char o_term[30];
|
||||
extern char o_flash[1];
|
||||
extern char o_warn[1];
|
||||
extern char o_wrapscan[1];
|
||||
|
||||
#ifndef CRUNCH
|
||||
extern char o_beautify[1];
|
||||
extern char o_exrc[1];
|
||||
extern char o_mesg[1];
|
||||
extern char o_more[1];
|
||||
extern char o_novice[1];
|
||||
extern char o_prompt[1];
|
||||
extern char o_taglength[3];
|
||||
extern char o_terse[1];
|
||||
extern char o_window[3];
|
||||
extern char o_wrapmargin[3];
|
||||
extern char o_writeany[1];
|
||||
#endif
|
||||
|
||||
#ifndef NO_ERRLIST
|
||||
extern char o_cc[30];
|
||||
extern char o_make[30];
|
||||
#endif
|
||||
|
||||
#ifndef NO_CHARATTR
|
||||
extern char o_charattr[1];
|
||||
#endif
|
||||
|
||||
#ifndef NO_DIGRAPH
|
||||
extern char o_digraph[1];
|
||||
extern char o_flipcase[80];
|
||||
#endif
|
||||
|
||||
#ifndef NO_SENTENCE
|
||||
extern char o_hideformat[1];
|
||||
#endif
|
||||
|
||||
#ifndef NO_EXTENSIONS
|
||||
extern char o_inputmode[1];
|
||||
extern char o_ruler[1];
|
||||
#endif
|
||||
|
||||
#ifndef NO_MAGIC
|
||||
extern char o_magic[1];
|
||||
#endif
|
||||
|
||||
#ifndef NO_MODELINES
|
||||
extern char o_modelines[1];
|
||||
#endif
|
||||
|
||||
#ifndef NO_SENTENCE
|
||||
extern char o_paragraphs[30];
|
||||
extern char o_sections[30];
|
||||
#endif
|
||||
|
||||
#if MSDOS
|
||||
extern char o_pcbios[1];
|
||||
#endif
|
||||
|
||||
#ifndef NO_SHOWMATCH
|
||||
extern char o_showmatch[1];
|
||||
#endif
|
||||
|
||||
#ifndef NO_SHOWMODE
|
||||
extern char o_smd[1];
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* These help support the single-line multi-change "undo" -- shift-U */
|
||||
|
||||
extern char U_text[BLKSIZE];
|
||||
extern long U_line;
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* These are used to refer to places in the text */
|
||||
|
||||
typedef long MARK;
|
||||
#define markline(x) (long)((x) / BLKSIZE)
|
||||
#define markidx(x) (int)((x) & (BLKSIZE - 1))
|
||||
#define MARK_UNSET ((MARK)0)
|
||||
#define MARK_FIRST ((MARK)BLKSIZE)
|
||||
#define MARK_LAST ((MARK)(nlines * BLKSIZE))
|
||||
#define MARK_AT_LINE(x) ((MARK)(x) * BLKSIZE)
|
||||
|
||||
#define NMARKS 29
|
||||
extern MARK mark[NMARKS]; /* marks a-z, plus mark ' and two temps */
|
||||
extern MARK cursor; /* mark where line is */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* These are used to keep track of the current & previous files. */
|
||||
|
||||
extern long origtime; /* modification date&time of the current file */
|
||||
extern char origname[256]; /* name of the current file */
|
||||
extern char prevorig[256]; /* name of the preceding file */
|
||||
extern long prevline; /* line number from preceding file */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* misc housekeeping variables & functions */
|
||||
|
||||
extern int tmpfd; /* fd used to access the tmp file */
|
||||
extern int tmpnum; /* counter used to generate unique filenames */
|
||||
extern long lnum[MAXBLKS]; /* last line# of each block */
|
||||
extern long nlines; /* number of lines in the file */
|
||||
extern char args[BLKSIZE]; /* file names given on the command line */
|
||||
extern int argno; /* the current element of args[] */
|
||||
extern int nargs; /* number of filenames in args */
|
||||
extern long changes; /* counts changes, to prohibit short-cuts */
|
||||
extern int significant; /* boolean: was a *REAL* change made? */
|
||||
extern BLK tmpblk; /* a block used to accumulate changes */
|
||||
extern long topline; /* file line number of top line */
|
||||
extern int leftcol; /* column number of left col */
|
||||
#define botline (topline + LINES - 2)
|
||||
#define rightcol (leftcol + COLS - (*o_number ? 9 : 1))
|
||||
extern int physcol; /* physical column number that cursor is on */
|
||||
extern int physrow; /* physical row number that cursor is on */
|
||||
extern int exwrote; /* used to detect verbose ex commands */
|
||||
extern int doingdot; /* boolean: are we doing the "." command? */
|
||||
extern int doingglobal; /* boolean: are doing a ":g" command? */
|
||||
extern long rptlines; /* number of lines affected by a command */
|
||||
extern char *rptlabel; /* description of how lines were affected */
|
||||
extern char *fetchline(); /* read a given line from tmp file */
|
||||
extern char *parseptrn(); /* isolate a regexp in a line */
|
||||
extern MARK paste(); /* paste from cut buffer to a given point */
|
||||
extern char *wildcard(); /* expand wildcards in filenames */
|
||||
extern MARK input(); /* inserts characters from keyboard */
|
||||
extern char *linespec(); /* finds the end of a /regexp/ string */
|
||||
#define ctrl(ch) ((ch)&037)
|
||||
#ifndef NO_RECYCLE
|
||||
extern long allocate(); /* allocate a free block of the tmp file */
|
||||
#endif
|
||||
extern int trapint(); /* trap handler for SIGINT */
|
||||
extern int deathtrap(); /* trap handler for deadly signals */
|
||||
extern void blkdirty(); /* marks a block as being "dirty" */
|
||||
extern void blkflush(); /* writes a single dirty block to the disk */
|
||||
extern void blksync(); /* forces all "dirty" blocks to disk */
|
||||
extern void blkinit(); /* resets the block cache to "empty" state */
|
||||
extern void beep(); /* rings the terminal's bell */
|
||||
extern void exrefresh(); /* writes text to the screen */
|
||||
extern void msg(); /* writes a printf-style message to the screen */
|
||||
extern void endmsgs(); /* if "manymsgs" is set, then scroll up 1 line */
|
||||
extern void garbage(); /* reclaims any garbage blocks */
|
||||
extern void redraw(); /* updates the screen after a change */
|
||||
extern void resume_curses();/* puts the terminal in "cbreak" mode */
|
||||
extern void beforedo(); /* saves current revision before a new change */
|
||||
extern void afterdo(); /* marks end of a beforedo() change */
|
||||
extern void abortdo(); /* like "afterdo()" followed by "undo()" */
|
||||
extern int undo(); /* restores file to previous undo() */
|
||||
extern void dumpkey(); /* lists key mappings to the screen */
|
||||
extern void mapkey(); /* defines a new key mapping */
|
||||
extern void savekeys(); /* lists key mappings to a file */
|
||||
extern void redrawrange(); /* records clues from modify.c */
|
||||
extern void cut(); /* saves text in a cut buffer */
|
||||
extern void delete(); /* deletes text */
|
||||
extern void add(); /* adds text */
|
||||
extern void change(); /* deletes text, and then adds other text */
|
||||
extern void cutswitch(); /* updates cut buffers when we switch files */
|
||||
extern void do_abbr(); /* defines or lists abbreviations */
|
||||
extern void do_digraph(); /* defines or lists digraphs */
|
||||
extern void exstring(); /* execute a string as EX commands */
|
||||
extern void dumpopts();
|
||||
extern void setopts();
|
||||
extern void saveopts();
|
||||
extern void savedigs();
|
||||
extern void saveabbr();
|
||||
extern void savecolor();
|
||||
extern void cutname();
|
||||
extern void cutname();
|
||||
extern void initopts();
|
||||
extern void cutend();
|
||||
#ifndef CRUNCH
|
||||
extern int wset; /* boolean: has the "window" size been set? */
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* macros that are used as control structures */
|
||||
|
||||
#define BeforeAfter(before, after) for((before),bavar=1;bavar;(after),bavar=0)
|
||||
#define ChangeText BeforeAfter(beforedo(FALSE),afterdo())
|
||||
|
||||
extern int bavar; /* used only in BeforeAfter macros */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* These are the movement commands. Each accepts a mark for the starting */
|
||||
/* location & number and returns a mark for the destination. */
|
||||
|
||||
extern MARK m_updnto(); /* k j G */
|
||||
extern MARK m_right(); /* h */
|
||||
extern MARK m_left(); /* l */
|
||||
extern MARK m_tocol(); /* | */
|
||||
extern MARK m_front(); /* ^ */
|
||||
extern MARK m_rear(); /* $ */
|
||||
extern MARK m_fword(); /* w */
|
||||
extern MARK m_bword(); /* b */
|
||||
extern MARK m_eword(); /* e */
|
||||
extern MARK m_paragraph(); /* { } [[ ]] */
|
||||
extern MARK m_match(); /* % */
|
||||
#ifndef NO_SENTENCE
|
||||
extern MARK m_sentence(); /* ( ) */
|
||||
#endif
|
||||
extern MARK m_tomark(); /* 'm */
|
||||
#ifndef NO_EXTENSIONS
|
||||
extern MARK m_wsrch(); /* ^A */
|
||||
#endif
|
||||
extern MARK m_nsrch(); /* n */
|
||||
extern MARK m_Nsrch(); /* N */
|
||||
extern MARK m_fsrch(); /* /regexp */
|
||||
extern MARK m_bsrch(); /* ?regexp */
|
||||
#ifndef NO_CHARSEARCH
|
||||
extern MARK m__ch(); /* ; , */
|
||||
extern MARK m_fch(); /* f */
|
||||
extern MARK m_tch(); /* t */
|
||||
extern MARK m_Fch(); /* F */
|
||||
extern MARK m_Tch(); /* T */
|
||||
#endif
|
||||
extern MARK m_row(); /* H L M */
|
||||
extern MARK m_z(); /* z */
|
||||
extern MARK m_scroll(); /* ^B ^F ^E ^Y ^U ^D */
|
||||
|
||||
/* Some stuff that is used by movement functions... */
|
||||
|
||||
extern MARK adjmove(); /* a helper fn, used by move fns */
|
||||
|
||||
/* This macro is used to set the default value of cnt */
|
||||
#define DEFAULT(val) if (cnt < 1) cnt = (val)
|
||||
|
||||
/* These are used to minimize calls to fetchline() */
|
||||
extern int plen; /* length of the line */
|
||||
extern long pline; /* line number that len refers to */
|
||||
extern long pchgs; /* "changes" level that len refers to */
|
||||
extern char *ptext; /* text of previous line, if valid */
|
||||
extern void pfetch();
|
||||
extern char digraph();
|
||||
|
||||
/* This is used to build a MARK that corresponds to a specific point in the
|
||||
* line that was most recently pfetch'ed.
|
||||
*/
|
||||
#define buildmark(text) (MARK)(BLKSIZE * pline + (int)((text) - ptext))
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* These are used to handle EX commands. */
|
||||
|
||||
#define CMD_NULL 0 /* NOT A VALID COMMAND */
|
||||
#define CMD_ABBR 1 /* "define an abbreviation" */
|
||||
#define CMD_ARGS 2 /* "show me the args" */
|
||||
#define CMD_APPEND 3 /* "insert lines after this line" */
|
||||
#define CMD_AT 4 /* "execute a cut buffer's contents via EX" */
|
||||
#define CMD_BANG 5 /* "run a single shell command" */
|
||||
#define CMD_CC 6 /* "run `cc` and then do CMD_ERRLIST" */
|
||||
#define CMD_CD 7 /* "change directories" */
|
||||
#define CMD_CHANGE 8 /* "change some lines" */
|
||||
#define CMD_COLOR 9 /* "change the default colors" */
|
||||
#define CMD_COPY 10 /* "copy the selected text to a given place" */
|
||||
#define CMD_DELETE 11 /* "delete the selected text" */
|
||||
#define CMD_DIGRAPH 12 /* "add a digraph, or display them all" */
|
||||
#define CMD_EDIT 13 /* "switch to a different file" */
|
||||
#define CMD_EQUAL 14 /* "display a line number" */
|
||||
#define CMD_ERRLIST 15 /* "locate the next error in a list" */
|
||||
#define CMD_FILE 16 /* "show the file's status" */
|
||||
#define CMD_GLOBAL 17 /* "globally search & do a command" */
|
||||
#define CMD_INSERT 18 /* "insert lines before the current line" */
|
||||
#define CMD_JOIN 19 /* "join the selected line & the one after" */
|
||||
#define CMD_LIST 20 /* "print lines, making control chars visible" */
|
||||
#define CMD_MAKE 21 /* "run `make` and then do CMD_ERRLIST" */
|
||||
#define CMD_MAP 22 /* "adjust the keyboard map" */
|
||||
#define CMD_MARK 23 /* "mark this line" */
|
||||
#define CMD_MKEXRC 24 /* "make a .exrc file" */
|
||||
#define CMD_MOVE 25 /* "move the selected text to a given place" */
|
||||
#define CMD_NEXT 26 /* "switch to next file in args" */
|
||||
#define CMD_NUMBER 27 /* "print lines from the file w/ line numbers" */
|
||||
#define CMD_PRESERVE 28 /* "act as though vi crashed" */
|
||||
#define CMD_PREVIOUS 29 /* "switch to the previous file in args" */
|
||||
#define CMD_PRINT 30 /* "print the selected text" */
|
||||
#define CMD_PUT 31 /* "insert any cut lines before this line" */
|
||||
#define CMD_QUIT 32 /* "quit without writing the file" */
|
||||
#define CMD_READ 33 /* "append the given file after this line */
|
||||
#define CMD_RECOVER 34 /* "recover file after vi crashes" - USE -r FLAG */
|
||||
#define CMD_REWIND 35 /* "rewind to first file" */
|
||||
#define CMD_SET 36 /* "set a variable's value" */
|
||||
#define CMD_SHELL 37 /* "run some lines through a command" */
|
||||
#define CMD_SHIFTL 38 /* "shift lines left" */
|
||||
#define CMD_SHIFTR 39 /* "shift lines right" */
|
||||
#define CMD_SOURCE 40 /* "interpret a file's contents as ex commands" */
|
||||
#define CMD_STOP 41 /* same as CMD_SUSPEND */
|
||||
#define CMD_SUBAGAIN 42 /* "repeat the previous substitution" */
|
||||
#define CMD_SUBSTITUTE 43 /* "substitute text in this line" */
|
||||
#define CMD_SUSPEND 44 /* "suspend the vi session" */
|
||||
#define CMD_TR 45 /* "transliterate chars in the selected lines" */
|
||||
#define CMD_TAG 46 /* "go to a particular tag" */
|
||||
#define CMD_UNABBR 47 /* "remove an abbreviation definition" */
|
||||
#define CMD_UNDO 48 /* "undo the previous command" */
|
||||
#define CMD_UNMAP 49 /* "remove a key sequence map */
|
||||
#define CMD_VERSION 50 /* "describe which version this is" */
|
||||
#define CMD_VGLOBAL 51 /* "apply a cmd to lines NOT containing an RE" */
|
||||
#define CMD_VISUAL 52 /* "go into visual mode" */
|
||||
#define CMD_WQUIT 53 /* "write this file out (any case) & quit" */
|
||||
#define CMD_WRITE 54 /* "write the selected(?) text to a given file" */
|
||||
#define CMD_XIT 55 /* "write this file out (if modified) & quit" */
|
||||
#define CMD_YANK 56 /* "copy the selected text into the cut buffer" */
|
||||
#ifdef DEBUG
|
||||
# define CMD_DEBUG 57 /* access to internal data structures */
|
||||
# define CMD_VALIDATE 58 /* check for internal consistency */
|
||||
#endif
|
||||
typedef int CMD;
|
||||
|
||||
extern void ex();
|
||||
extern void vi();
|
||||
extern void doexcmd();
|
||||
|
||||
extern void cmd_append();
|
||||
extern void cmd_args();
|
||||
#ifndef NO_AT
|
||||
extern void cmd_at();
|
||||
#endif
|
||||
extern void cmd_cd();
|
||||
#ifndef NO_COLOR
|
||||
extern void cmd_color();
|
||||
#endif
|
||||
extern void cmd_delete();
|
||||
#ifndef NO_DIGRAPH
|
||||
extern void cmd_digraph();
|
||||
#endif
|
||||
extern void cmd_edit();
|
||||
#ifndef NO_ERRLIST
|
||||
extern void cmd_errlist();
|
||||
#endif
|
||||
extern void cmd_file();
|
||||
extern void cmd_global();
|
||||
extern void cmd_join();
|
||||
extern void cmd_mark();
|
||||
#ifndef NO_ERRLIST
|
||||
extern void cmd_make();
|
||||
#endif
|
||||
extern void cmd_map();
|
||||
#ifndef NO_MKEXRC
|
||||
extern void cmd_mkexrc();
|
||||
#endif
|
||||
extern void cmd_next();
|
||||
extern void cmd_print();
|
||||
extern void cmd_put();
|
||||
extern void cmd_read();
|
||||
extern void cmd_set();
|
||||
extern void cmd_shell();
|
||||
extern void cmd_shift();
|
||||
extern void cmd_source();
|
||||
extern void cmd_substitute();
|
||||
extern void cmd_tag();
|
||||
extern void cmd_undo();
|
||||
extern void cmd_version();
|
||||
extern void cmd_write();
|
||||
extern void cmd_xit();
|
||||
extern void cmd_move();
|
||||
#ifdef DEBUG
|
||||
extern void cmd_debug();
|
||||
extern void cmd_validate();
|
||||
#endif
|
||||
#ifdef SIGTSTP
|
||||
extern void cmd_suspend();
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* These are used to handle VI commands */
|
||||
|
||||
extern MARK v_1ex(); /* : */
|
||||
extern MARK v_mark(); /* m */
|
||||
extern MARK v_quit(); /* Q */
|
||||
extern MARK v_redraw(); /* ^L ^R */
|
||||
extern MARK v_ulcase(); /* ~ */
|
||||
extern MARK v_undo(); /* u */
|
||||
extern MARK v_xchar(); /* x X */
|
||||
extern MARK v_replace(); /* r */
|
||||
extern MARK v_overtype(); /* R */
|
||||
extern MARK v_selcut(); /* " */
|
||||
extern MARK v_paste(); /* p P */
|
||||
extern MARK v_yank(); /* y Y */
|
||||
extern MARK v_delete(); /* d D */
|
||||
extern MARK v_join(); /* J */
|
||||
extern MARK v_insert(); /* a A i I o O */
|
||||
extern MARK v_change(); /* c C */
|
||||
extern MARK v_subst(); /* s */
|
||||
extern MARK v_lshift(); /* < */
|
||||
extern MARK v_rshift(); /* > */
|
||||
extern MARK v_reformat(); /* = */
|
||||
extern MARK v_filter(); /* ! */
|
||||
extern MARK v_status(); /* ^G */
|
||||
extern MARK v_switch(); /* ^^ */
|
||||
extern MARK v_tag(); /* ^] */
|
||||
extern MARK v_xit(); /* ZZ */
|
||||
extern MARK v_undoline(); /* U */
|
||||
extern MARK v_again(); /* & */
|
||||
#ifndef NO_EXTENSIONS
|
||||
extern MARK v_keyword(); /* K */
|
||||
extern MARK v_increment(); /* * */
|
||||
#endif
|
||||
#ifndef NO_ERRLIST
|
||||
extern MARK v_errlist(); /* * */
|
||||
#endif
|
||||
#ifndef NO_AT
|
||||
extern MARK v_at(); /* @ */
|
||||
#endif
|
||||
#ifdef SIGTSTP
|
||||
extern MARK v_suspend(); /* ^Z */
|
||||
#endif
|
||||
#ifndef NO_POPUP
|
||||
extern MARK v_popup(); /* \ */
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* These flags describe the quirks of the individual visual commands */
|
||||
#define NO_FLAGS 0x00
|
||||
#define MVMT 0x01 /* this is a movement command */
|
||||
#define PTMV 0x02 /* this can be *part* of a movement command */
|
||||
#define FRNT 0x04 /* after move, go to front of line */
|
||||
#define INCL 0x08 /* include last char when used with c/d/y */
|
||||
#define LNMD 0x10 /* use line mode of c/d/y */
|
||||
#define NCOL 0x20 /* this command can't change the column# */
|
||||
#define NREL 0x40 /* this is "non-relative" -- set the '' mark */
|
||||
#define SDOT 0x80 /* set the "dot" variables, for the "." cmd */
|
||||
#ifndef NO_VISIBLE
|
||||
# define VIZ 0x100 /* commands which can be used with 'v' */
|
||||
#else
|
||||
# define VIZ 0
|
||||
#endif
|
||||
|
||||
/* This variable is zeroed before a command executes, and later ORed with the
|
||||
* command's flags after the command has been executed. It is used to force
|
||||
* certain flags to be TRUE for *some* invocations of a particular command.
|
||||
* For example, "/regexp/+offset" forces the LNMD flag, and sometimes a "p"
|
||||
* or "P" command will force FRNT.
|
||||
*/
|
||||
extern int force_flags;
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* These describe what mode we're in */
|
||||
|
||||
#define MODE_EX 1 /* executing ex commands */
|
||||
#define MODE_VI 2 /* executing vi commands */
|
||||
#define MODE_COLON 3 /* executing an ex command from vi mode */
|
||||
#define MODE_QUIT 4
|
||||
extern int mode;
|
||||
|
||||
#define WHEN_VICMD 1 /* getkey: we're reading a VI command */
|
||||
#define WHEN_VIINP 2 /* getkey: we're in VI's INPUT mode */
|
||||
#define WHEN_VIREP 4 /* getkey: we're in VI's REPLACE mode */
|
||||
#define WHEN_EX 8 /* getkey: we're in EX mode */
|
||||
#define WHEN_MSG 16 /* getkey: we're at a "more" prompt */
|
||||
#define WHEN_POPUP 32 /* getkey: we're in the pop-up menu */
|
||||
#define WHEN_REP1 64 /* getkey: we're getting a single char for 'r' */
|
||||
#define WHEN_CUT 128 /* getkey: we're getting a cut buffer name */
|
||||
#define WHEN_MARK 256 /* getkey: we're getting a mark name */
|
||||
#define WHEN_CHAR 512 /* getkey: we're getting a destination for f/F/t/T */
|
||||
#define WHEN_INMV 4096 /* in input mode, interpret the key in VICMD mode */
|
||||
#define WHEN_FREE 8192 /* free the keymap after doing it once */
|
||||
#define WHENMASK (WHEN_VICMD|WHEN_VIINP|WHEN_VIREP|WHEN_REP1|WHEN_CUT|WHEN_MARK|WHEN_CHAR)
|
||||
|
||||
#ifndef NO_VISIBLE
|
||||
extern MARK V_from;
|
||||
extern int V_linemd;
|
||||
extern MARK v_start();
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
# define malloc(size) dbmalloc(size, __FILE__, __LINE__)
|
||||
# define free(ptr) dbfree(ptr, __FILE__, __LINE__)
|
||||
extern char *dbmalloc();
|
||||
#endif
|
34
dist/nvi/Changes
vendored
Normal file
34
dist/nvi/Changes
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
Changes since 1.81.5
|
||||
* various compilation fixes
|
||||
* support for newer DBs
|
||||
* tcl support compiles again
|
||||
Changes since 1.81.4
|
||||
* add Changes document
|
||||
* the preserve command overwrote the edited file; the problem
|
||||
is really in DB; a bandaid was added
|
||||
* configure changes
|
||||
- -rpath now on by default
|
||||
- check for iconv
|
||||
* handle incomplete/invalid input
|
||||
* upgrade libtool and automake
|
||||
* Motif front-end was getting out of sync; fixed
|
||||
* ^T works in presence of wide chars
|
||||
* fix use of OPT_GLOBAL (YAMAMOTO Takashi <takashi.yamamoto@bigfoot.com>)
|
||||
* missing fallback function added
|
||||
* fix use of both leftright and number
|
||||
(problem reported by Dima Dorfman <dima@unixfreak.org>)
|
||||
* install everything 1.79 installed
|
||||
* fix count argument for commands
|
||||
(problem reported by Arfst Ludwig <Arfst.Ludwig@LHSystems.COM>)
|
||||
* perl changes
|
||||
- map no longer assumes its argument is the name of a perl function
|
||||
- EXISTS for marks
|
||||
* documentation changes
|
||||
- vi.ref converted to texinfo
|
||||
- vsplit documented
|
||||
Changes since 1.81.3
|
||||
* support for newer ncurses
|
||||
* various other wide character related changes
|
||||
* eliminate spurious cursor movements on split screens
|
||||
* use of gtk-1.2 allowed again
|
||||
* small fix to Motif front-end
|
39
dist/nvi/LICENSE
vendored
Normal file
39
dist/nvi/LICENSE
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*-
|
||||
* Id: LICENSE,v 8.17 2000/08/18 14:58:41 bostic Exp (Sleepycat) Date: 2000/08/18 14:58:41
|
||||
*/
|
||||
|
||||
The following are the copyrights and redistribution conditions that apply
|
||||
to this copy of the Vi software.
|
||||
|
||||
/*
|
||||
* Copyright (c) 1991, 1992, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
|
||||
* Keith Bostic. All rights reserved.
|
||||
* Copyright (c) 1999, 2000
|
||||
* Sven Verdoolaege. 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.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
*/
|
104
dist/nvi/README
vendored
Normal file
104
dist/nvi/README
vendored
Normal file
|
@ -0,0 +1,104 @@
|
|||
# Id: README,v 8.153 2001/04/30 09:31:12 skimo Exp (Berkeley) Date: 2001/04/30 09:31:12
|
||||
|
||||
This is version 1.81.6 (2007-11-18) of nex/nvi, a reimplementation of the ex/vi
|
||||
text editors originally distributed as part of the Fourth Berkeley
|
||||
Software Distribution (4BSD), by the University of California, Berkeley.
|
||||
|
||||
The directory layout is as follows:
|
||||
|
||||
LICENSE ....... Copyright, use and redistribution information.
|
||||
README ........ This file.
|
||||
build.unix .... UNIX build directory.
|
||||
catalog ....... Message catalogs; see catalog/README.
|
||||
cl ............ Vi interface to the curses(3) library.
|
||||
clib .......... C library replacement source code.
|
||||
common ........ Code shared by ex and vi.
|
||||
db ............ A stripped-down, replacement db(3) library.
|
||||
dist .......... Various files used to build the vi distribution.
|
||||
docs .......... Ex/vi documentation, both current and historic.
|
||||
docs/README ... Documentation overview.
|
||||
docs/edit ..... Edit: A tutorial.
|
||||
docs/exref .... Ex Reference Manual -- Version 3.7.
|
||||
docs/vi.man ... UNIX manual page for nex/nvi.
|
||||
docs/vi.ref ... Nex/nvi reference manual.
|
||||
docs/vitut .... An Introduction to Display Editing with Vi.
|
||||
ex ............ Ex source code.
|
||||
gtk ........... Vi gtk application.
|
||||
include ....... Replacement include files.
|
||||
ip ............ Library interface to vi: vi side.
|
||||
ipc ........... Library interface to vi: application side.
|
||||
motif ......... Vi motif application.
|
||||
motif_l ....... Motif library interface to vi.
|
||||
perl_api ...... Perl scripting language support.
|
||||
perl_scripts .. Perl scripts.
|
||||
regex ......... POSIX 1003.2 regular expression library.
|
||||
tcl_api ....... Tcl scripting language support.
|
||||
tcl_scripts ... Tcl scripts.
|
||||
vi ............ Vi source code.
|
||||
|
||||
To build DB for a UNIX platform:
|
||||
|
||||
cd build.unix
|
||||
../dist/configure
|
||||
make
|
||||
|
||||
To build multiple UNIX versions of DB in the same source tree, create
|
||||
a new directory then configure and build.
|
||||
|
||||
mkdir build.bsdos3.0
|
||||
cd build.bsdos3.0
|
||||
../dist/configure
|
||||
make
|
||||
|
||||
For additional information about building DB for UNIX platforms, the
|
||||
description of possible configuration options and other information
|
||||
on DB configuration and build issues, see the file build.unix/README.
|
||||
|
||||
Bug fixes and updated versions of this software will periodically be made
|
||||
available. For more information, as well as a list of Frequently Asked
|
||||
Questions, see:
|
||||
|
||||
http://www.bostic.com/vi
|
||||
|
||||
To ask questions about vi, report vi problems, request notification of
|
||||
future releases and/or bug fixes, or to contact the authors for any
|
||||
reason, please send email to:
|
||||
|
||||
bostic@bostic.com
|
||||
|
||||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
o This software is several years old and is the product of many folks' work.
|
||||
|
||||
This software was originally derived from software contributed to
|
||||
the University of California, Berkeley by Steve Kirkendall, the
|
||||
author of the vi clone elvis. Without his work, this work would
|
||||
have been far more difficult.
|
||||
|
||||
IEEE POSIX 1003.2 style regular expression support is courtesy of
|
||||
Henry Spencer, for which I am *very* grateful.
|
||||
|
||||
Elan Amir did the original 4BSD curses work that made it possible
|
||||
to support a full-screen editor using curses.
|
||||
|
||||
George Neville-Neil added the Tcl interpreter, and the initial
|
||||
interpreter design was his.
|
||||
|
||||
Sven Verdoolaege added the Perl interpreter.
|
||||
|
||||
Rob Mayoff provided the original Cscope support.
|
||||
|
||||
o Many, many people suggested enhancements, and provided bug reports and
|
||||
testing, far too many to individually thank.
|
||||
|
||||
o From the original vi acknowledgements, by William Joy and Mark Horton:
|
||||
|
||||
Bruce Englar encouraged the early development of this display
|
||||
editor. Peter Kessler helped bring sanity to version 2's
|
||||
command layout. Bill Joy wrote versions 1 and 2.0 through 2.7,
|
||||
and created the framework that users see in the present editor.
|
||||
Mark Horton added macros and other features and made the editor
|
||||
work on a large number of terminals and Unix systems.
|
||||
|
||||
o And...
|
||||
The financial support of UUNET Communications Services is gratefully
|
||||
acknowledged.
|
17
dist/nvi/README.1st
vendored
Normal file
17
dist/nvi/README.1st
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
This is a development version of nvi.
|
||||
Use at your own risk.
|
||||
|
||||
Please do not contact the original authors about bugs you
|
||||
find in this version. Contact skimo-vi@kotnet.org instead.
|
||||
|
||||
There is no guarantee that anything in this version will be
|
||||
available in upcoming stable releases.
|
||||
|
||||
New versions will be made available on
|
||||
http://www.kotnet.org/~skimo/nvi
|
||||
|
||||
As always this software comes with absolutely NO WARRANTY.
|
||||
|
||||
Now read the original README file.
|
||||
|
||||
Sven Verdoolaege
|
22
dist/nvi/README.DB3
vendored
Normal file
22
dist/nvi/README.DB3
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
This version of vi requires DB3.1 or better, which can be found
|
||||
on http://www.sleepycat.com/ .
|
||||
|
||||
Note that there is a small problem with DB 3.2 in that it will
|
||||
not let nvi read in a final line that doesn't end in a newline.
|
||||
This should be fixed in DB 3.3
|
||||
|
||||
If your system library (such as glibc prior to version 2.2) uses a
|
||||
previous version of db (e.g. DB2) internally, you must configure with
|
||||
--enable-dynamic-loading to avoid symbols in the internally used db from
|
||||
being resolved against the newer db.
|
||||
|
||||
If, on top of that, the vi binary is explicitly linked against that
|
||||
previous version of db (such as might happen if you enable the perl
|
||||
embedding), you should compile the 3.x version with all symbols internally
|
||||
resolved. In case you use the Gnu linker (ld), this can be accomplished
|
||||
by passing it the -Bsymbolic option. You can do this by setting CC
|
||||
to e.g. "gcc -Wl,-Bsymbolic" prior to configuring db.
|
||||
See docs/ref/build_unix/flags.html in the db distribution for more
|
||||
information.
|
||||
|
||||
skimo@kotnet.org
|
123
dist/nvi/TODO
vendored
Normal file
123
dist/nvi/TODO
vendored
Normal file
|
@ -0,0 +1,123 @@
|
|||
# Id: TODO,v 8.2 1997/04/12 15:53:31 bostic Exp (Berkeley) Date: 1997/04/12 15:53:31
|
||||
|
||||
========================================================================
|
||||
GENERAL
|
||||
========================================================================
|
||||
2.0: Open mode is not yet implemented.
|
||||
|
||||
|
||||
========================================================================
|
||||
DB
|
||||
========================================================================
|
||||
1.N When nvi edits files that don't have trailing newlines, it appends
|
||||
one, regardless. This is required, by default, from POSIX.2.
|
||||
|
||||
1.N: If you run out of space in the recovery directory, the recovery
|
||||
file is left in place.
|
||||
|
||||
2.0: It's known that it's possible to sync the backing files in the
|
||||
wrong manner, leaving backup files that aren't recoverable. This
|
||||
is going to be left alone until we have a logging version of DB,
|
||||
which will hopefully fix this (or at least make it possible to
|
||||
easily do so).
|
||||
|
||||
========================================================================
|
||||
VI
|
||||
========================================================================
|
||||
1.N: Make the search pattern and command history (what the '.' command
|
||||
executes) remembered between windows, or configurable so that it
|
||||
is.
|
||||
|
||||
1.N: Change the screen scrolling to not eat user characters... i.e.
|
||||
g/pattern/foo should not eat already entered chars.
|
||||
|
||||
1.N: The vi main command loop should use the general-purpose overflow
|
||||
and underflow routines. In addition, the vi command loop uses
|
||||
unsigned longs -- should probably be fixed as a 32-bit unsigned
|
||||
type, and then check to make sure it's never used as as variable
|
||||
type again.
|
||||
|
||||
1.N: Should "view" set a lock on the file?
|
||||
|
||||
1.N: Should "view" copy the file (or even open a recovery file)?
|
||||
|
||||
1.N: The strings found by searches should be highlighted until the next
|
||||
character is entered.
|
||||
|
||||
1.N: Display a split vi screen for the :help command.
|
||||
|
||||
1.N: When getting a key for a continue screen, we should always read from
|
||||
the terminal, not from a mapped key.
|
||||
|
||||
1.N: The sentence, paragraph and section movement commands don't match
|
||||
historic practice in some boundary cases. This should be left
|
||||
alone until POSIX 1003.2 makes up its mind.
|
||||
|
||||
1.N: The vs_sm_fill routine should scroll if possible, not always redraw.
|
||||
|
||||
1.N: Think about setting a dirty/inuse bits on the lines of the SMAP
|
||||
structure. That way the message routines could steal lines and
|
||||
refresh would continue to work, because it would know not to touch
|
||||
the lines that were in use.
|
||||
|
||||
========================================================================
|
||||
EX
|
||||
========================================================================
|
||||
2.0: ^C isn't passed to the shell in the script windows as an interrupt
|
||||
character.
|
||||
|
||||
2.0: It would be nice to inverse video the replaced text during
|
||||
interactive substitute.
|
||||
|
||||
2.0: The :args command should put the current file name out in reverse
|
||||
video. This isn't going to be easy, currently only full lines can
|
||||
be in reverse video, not just parts.
|
||||
|
||||
========================================================================
|
||||
CURSES
|
||||
========================================================================
|
||||
1.N In single-line screens, have to press 'q' twice when quitting out
|
||||
of a ":set all" display.
|
||||
|
||||
========================================================================
|
||||
MOTIF/IPC
|
||||
========================================================================
|
||||
1.N: We currently permit the user to change the lines, columns and term
|
||||
edit options. Shouldn't that be illegal in a window interface?
|
||||
|
||||
========================================================================
|
||||
REDESIGN
|
||||
========================================================================
|
||||
2.0: There's a serious problem with error returns -- we need to separate
|
||||
command failure from fatal error, consistently, over the entire source
|
||||
tree. We need to rework all of vi to have three return values:
|
||||
0: success
|
||||
1: vi error, continue
|
||||
2: fatal error, die
|
||||
Right now we don't recognize fatal errors for what they are.
|
||||
|
||||
2.0: The complete list of POSIX.1 calls that can return EINTR are:
|
||||
wait, waitpid, sleep, dup2, close, read, write,
|
||||
fcntl(SETLCKW) tcsetattr, tcdrain
|
||||
The problem is that technically, any system/library call can
|
||||
return EINTR, so, while nvi blocks (most of?) the obvious ones,
|
||||
someone may have to do a complete pass and block signals
|
||||
everywhere.
|
||||
|
||||
2.0: The options hardtabs, lisp, optimize, redraw, and slowopen
|
||||
are recognized, but not implemented.
|
||||
|
||||
|
||||
2.0: Field editing shouldn't be hard to add to nvi:
|
||||
|
||||
Field editing file template:
|
||||
version #
|
||||
field # row/column start row/column stop
|
||||
label field # Label string
|
||||
re field # Matching re string.
|
||||
field # row/column start row/column stop
|
||||
label field # Label string
|
||||
re field # Matching re string.
|
||||
|
||||
<tab> moves to the next field
|
||||
<bs> in column 0 moves to the previous field
|
362
dist/nvi/build.unix/README
vendored
Normal file
362
dist/nvi/build.unix/README
vendored
Normal file
|
@ -0,0 +1,362 @@
|
|||
# Id: README,v 8.29 2001/05/13 20:52:36 skimo Exp (Berkeley) Date: 2001/05/13 20:52:36
|
||||
|
||||
Nvi uses the GNU autoconf program for configuration and compilation. You
|
||||
should enter:
|
||||
|
||||
../dist/configure
|
||||
make
|
||||
|
||||
and nvi will configure the system and build one or two binaries: nvi and
|
||||
tknvi. You can use any path to the configure script, e.g., to build for
|
||||
an x86 architecture, I suggest that you do:
|
||||
|
||||
mkdir build.x86
|
||||
cd build.x86
|
||||
../dist/configure
|
||||
make
|
||||
|
||||
There are options that you can specify to the configure command. See
|
||||
the next section for a description of these options.
|
||||
|
||||
If you want to rebuild or reconfigure nvi, for example, because you change
|
||||
your mind as to the curses library that you want to use, create a new
|
||||
directory and reconfigure it using "configure" and whatever options you
|
||||
choose, don't try to selectively edit the files.
|
||||
|
||||
By default, nvi is installed as "vi", with hard links to "ex" and "view".
|
||||
To install them using different names, use the configure program options.
|
||||
For example, to install them as "nvi", "nex" and "nview", use:
|
||||
|
||||
configure --program-prefix=n
|
||||
|
||||
See the section below on installation for details.
|
||||
|
||||
Note, if you're building nvi on a LynxOS system, you should read the
|
||||
README.LynxOS file in this directory for additional build instructions
|
||||
that are specific to that operating system.
|
||||
|
||||
If you have trouble with this procedure, send email to the addresses
|
||||
listed in ../README. In that email, please provide a complete script
|
||||
of the output for all of the above commands that you entered.
|
||||
|
||||
=-=-=-=-=-=-=
|
||||
NVI'S OPTIONS TO THE CONFIGURE PROGRAM
|
||||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
There are many options that you can enter to the configuration program.
|
||||
To see a complete list of the options, enter "configure --help". Only
|
||||
a few of them are nvi specific. These options are as follows:
|
||||
|
||||
--disable-re DON'T use the nvi-provided RE routines.
|
||||
--enable-debug Build a debugging version.
|
||||
--enable-perlinterp Include a Perl interpreter in vi.
|
||||
--enable-tclinterp Include a Tk/Tcl interpreter in vi.
|
||||
--enable-gtk Build a gtk front-end.
|
||||
--enable-motif Build a motif front-end.
|
||||
--enable-threads Turn on thread support.
|
||||
--enable-widechar Build a wide character aware vi (experimental).
|
||||
--with-curses=DIR Path to curses installation.
|
||||
--with-db3=db3prefix Path to db3 installation.
|
||||
--enable-dynamic-loading Load DB 3 dynamically.
|
||||
|
||||
disable-re:
|
||||
By default, nvi loads its own versions of the POSIX 1003.2 Regular
|
||||
Expression routines (which are Henry Spencer's implementation).
|
||||
If your C library contains an implementation of the POSIX 1003.2
|
||||
RE routines (note, this is NOT the same as the historic UNIX RE
|
||||
routines), and you want to use them instead, enter:
|
||||
|
||||
--disable-re
|
||||
|
||||
as an argument to configure, and the RE routines will be taken
|
||||
from whatever libraries you load. Please ensure that your RE
|
||||
routines implement Henry Spencer's extensions for doing vi-style
|
||||
"word" searches.
|
||||
|
||||
enable-debug:
|
||||
If you want to build nvi with no optimization (i.e. without -O
|
||||
as a compiler flag), with -g as a compiler flag, and with DEBUG
|
||||
defined during compilation, enter:
|
||||
|
||||
--enable-debug
|
||||
|
||||
as an argument to configure.
|
||||
|
||||
enable-perlinterp:
|
||||
If you have the Perl 5 libraries and you want to compile in the
|
||||
Perl interpreter, enter:
|
||||
|
||||
--enable-perlinterp
|
||||
|
||||
as an argument to configure. (Note: this is NOT possible with
|
||||
Perl 4, or even with Perl 5 versions earlier than 5.002.)
|
||||
|
||||
enable-tclinterp:
|
||||
If you have the Tk/Tcl libraries and you want to compile in the
|
||||
Tcl/Tk interpreter, enter:
|
||||
|
||||
--enable-tclinterp
|
||||
|
||||
as an argument to configure. If your Tk/Tcl include files and
|
||||
libraries aren't in the standard library and include locations,
|
||||
see the next section of this README file for more information.
|
||||
|
||||
enable-gtk:
|
||||
If you have the Gtk libraries and you want to build the Gtk
|
||||
nvi front-end, enter:
|
||||
|
||||
--enable-gtk
|
||||
|
||||
as an argument to configure. If your Gtk include files and
|
||||
libraries aren't in the standard library and include locations,
|
||||
see the next section of this README file for more information.
|
||||
See also the enable-threads option.
|
||||
|
||||
enable-motif:
|
||||
If you have the Motif libraries and you want to build the Motif
|
||||
nvi front-end, enter:
|
||||
|
||||
--enable-motif
|
||||
|
||||
as an argument to configure. If your Motif include files and
|
||||
libraries aren't in the standard library and include locations,
|
||||
see the next section of this README file for more information.
|
||||
|
||||
enable-threads:
|
||||
If you want to be able to use multiple windows in the Gtk
|
||||
front-end, you should specify this option.
|
||||
|
||||
with-curses:
|
||||
Specifies the path where curses is installed.
|
||||
|
||||
with-db3:
|
||||
Specifies the path where DB3 is installed.
|
||||
See README.DB3 for more information about DB3.
|
||||
|
||||
enable-dynamic-loading:
|
||||
Dynamically load DB3 library.
|
||||
See README.DB3 for more information about DB3.
|
||||
|
||||
enable-widechar:
|
||||
Enables support for wide characters.
|
||||
Note that this is still rather experimental.
|
||||
|
||||
If you try this out on Solaris, you will want to point nvi
|
||||
to the curses in /usr/xpg4/ which is CSI compliant.
|
||||
|
||||
=-=-=-=-=-=-=
|
||||
ADDING OR CHANGING COMPILERS, OR COMPILE OR LOAD LINE FLAGS
|
||||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
If you want to use a specific compiler, specify the CC environment
|
||||
variable before running configure. For example:
|
||||
|
||||
env CC=gcc configure
|
||||
|
||||
Using anything other than the native compiler will almost certainly
|
||||
mean that you'll want to check the compile and load line flags, too.
|
||||
|
||||
If you want to specify additional load line flags, specify the ADDLDFLAGS
|
||||
environment variable before running configure. For example:
|
||||
|
||||
env ADDLDFLAGS="-Q" configure
|
||||
|
||||
would specify the -Q flag in the load line when the nvi programs are
|
||||
loaded.
|
||||
|
||||
If you don't want configure to use the default load line flags for the
|
||||
system, specify the LDFLAGS environment variable before running configure.
|
||||
For example:
|
||||
|
||||
env LDFLAGS="-32" configure
|
||||
|
||||
will cause configure to set the load line flags to "-32", and not set
|
||||
them based on the current system.
|
||||
|
||||
If you want to specify additional compile line flags, specify the
|
||||
ADDCPPFLAGS environment variable before running configure. For example:
|
||||
|
||||
env ADDCPPFLAGS="-I../foo" configure
|
||||
|
||||
would cause the compiler to be passed the -I../foo flag when compiling
|
||||
test programs during configuration as well as when building nvi object
|
||||
files.
|
||||
|
||||
If you don't want configure to use the default compile line flags for the
|
||||
system, specify the CPPFLAGS environment variable before running configure.
|
||||
For example:
|
||||
|
||||
env CPPFLAGS="-I.." configure
|
||||
|
||||
will cause configure to use "-I.." as the compile line flags instead of
|
||||
the default values.
|
||||
|
||||
=-=-=-=-=-=-=
|
||||
ADDING LIBRARIES AND INCLUDE FILES
|
||||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
If the Tk/Tcl or any other include files or libraries are in non-standard
|
||||
places on your system, you will need to specify the directory path where
|
||||
they can be found.
|
||||
|
||||
If you want to specify additional library paths, set the ADDLIBS environment
|
||||
variable before running configure. For example:
|
||||
|
||||
env ADDLIBS="-L/a/b -L/e/f -ldb" configure
|
||||
|
||||
would specify two additional directories to search for libraries, /a/b
|
||||
and /e/f, and one additional library to load, "db".
|
||||
|
||||
If you want to specify additional include paths, specify the ADDCPPFLAGS
|
||||
environment variable before running configure. For example:
|
||||
|
||||
env ADDCPPFLAGS="-I/usr/local/include" LIBS="-ldb" configure
|
||||
|
||||
would search /usr/local/include for include files, as well as load the db
|
||||
library as described above.
|
||||
|
||||
As a final example, let's say that you've downloaded ncurses from the net
|
||||
and you've built it in a directory named ncurses which is at the same
|
||||
level in the filesystem hierarchy as nvi. You would enter something like:
|
||||
|
||||
env ADDCPPFLAGS="-I../../ncurses/include" \
|
||||
ADDLIBS="-L../../ncurses/libraries" configure
|
||||
|
||||
to cause nvi to look for the curses include files and the curses library
|
||||
in the ncurses environment.
|
||||
|
||||
Notes:
|
||||
Make sure that you prepend -L to any library directory names, and
|
||||
that you prepend -I to any include file directory names! Also,
|
||||
make sure that you quote the paths as shown above, i.e. with
|
||||
single or double quotes around the values you're specifying for
|
||||
ADDCPPFLAGS and ADDLIBS.
|
||||
|
||||
=-=-=-=-=-=
|
||||
You should NOT need to add any libraries or include files to load
|
||||
the Perl5 interpreter. The configure script will obtain that
|
||||
information directly from the Perl5 program. This means that the
|
||||
configure script must be able to find perl in its path. It looks
|
||||
for "perl5" first, and then "perl". If you're building a Perl
|
||||
interpreter and neither is found, it's a fatal error.
|
||||
|
||||
=-=-=-=-=-=
|
||||
You do not need to specify additional libraries to load Tk/Tcl,
|
||||
Perl or curses, as the nvi configuration script adds the
|
||||
appropriate libraries to the load line whenever you specify
|
||||
--enable-tknvi or other Perl or Tk/Tcl related option, or build
|
||||
the Tk/Tcl or curses version of nvi. The library names that are
|
||||
automatically loaded are as follows:
|
||||
|
||||
for Perl: -lperl
|
||||
for Tk/Tcl: -ltk -ltcl -lm
|
||||
for curses: -lcurses
|
||||
|
||||
In addition, the configure script loads:
|
||||
|
||||
... the X libraries when loading the Tk/Tcl libraries,
|
||||
if they exist.
|
||||
|
||||
... the -ltermcap or -ltermlib libraries when loading
|
||||
any curses library, if they exist.
|
||||
|
||||
=-=-=-=-=-=
|
||||
The env command is available on most systems, and simply sets one
|
||||
or more environment variables before running a command. If the
|
||||
env command is not available to you, you can set the environment
|
||||
variables in your shell before running configure. For example,
|
||||
in sh or ksh, you could do:
|
||||
|
||||
ADDLIBS="-L/a/b -L/e/f -ldb" configure
|
||||
|
||||
and in csh or tcsh, you could do:
|
||||
|
||||
setenv ADDLIBS "-L/a/b -L/e/f -ldb"
|
||||
configure
|
||||
|
||||
See your shell manual page for further information.
|
||||
|
||||
=-=-=-=-=-=-=
|
||||
INSTALLING NVI
|
||||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
Nvi installs the following files into the following locations, with
|
||||
the following default values:
|
||||
|
||||
Variables: Default value:
|
||||
prefix /usr/local
|
||||
exec_prefix $(prefix)
|
||||
bindir $(prefix)/bin
|
||||
datadir $(prefix)/share
|
||||
mandir $(prefix)/man
|
||||
|
||||
File(s): Default location
|
||||
----------------------------------------
|
||||
vi $(bindir)/vi
|
||||
vi.1 $(mandir)/man1/vi.1
|
||||
vi.0 $(mandir)/cat1/vi.0
|
||||
Perl scripts $(datadir)/vi/perl/
|
||||
Tcl scripts $(datadir)/vi/tcl/
|
||||
Message Catalogs $(datadir)/vi/catalog/
|
||||
|
||||
Notes:
|
||||
There are two hard links to the vi program, named ex and view.
|
||||
Similarly, there are two hard links to the unformatted vi manual
|
||||
page, named ex.1 and view.1, and two hard links to the formatted
|
||||
manual page, named ex.0 and view.0. These links are created when
|
||||
the program and man pages are installed.
|
||||
|
||||
If you want to install vi, ex, view and the man pages as nvi, nex,
|
||||
nview, use the configure option --program-prefix=n. Other, more
|
||||
complex transformations are possible -- use configure --help to
|
||||
see more options.
|
||||
|
||||
To move the entire installation tree somewhere besides /usr/local,
|
||||
change the value of both "exec_prefix" and "prefix". To move the
|
||||
binaries to a different place, change the value of "bindir".
|
||||
Similarly, to put the datafiles (the message catalogs, Perl and
|
||||
Tcl scripts) or the man pages in a different place, change the
|
||||
value of "datadir" or "mandir". These values can be changed as
|
||||
part of configuration:
|
||||
|
||||
configure --exec_prefix=/usr/contrib --prefix=/usr/share
|
||||
|
||||
or when doing the install itself:
|
||||
|
||||
make exec_prefix=/usr/contrib prefix=/usr/contrib install
|
||||
|
||||
The datafile directory (e.g., /usr/local/share/vi by default) is
|
||||
completely removed and then recreated as part of the installation
|
||||
process.
|
||||
|
||||
=-=-=-=-=-=-=
|
||||
NVI AND THE CURSES LIBRARY
|
||||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
The major portability problem for nvi is selecting a curses library.
|
||||
Unfortunately, it is common to find broken versions of curses -- the
|
||||
original System V curses was broken, resulting in all vendors whose
|
||||
implementations are derived from System V having broken implementations
|
||||
in turn.
|
||||
|
||||
If you use the vendor's or other curses library, and you see any of the
|
||||
following symptoms:
|
||||
|
||||
+ Core dumps in curses routines.
|
||||
+ Missing routines when compiling.
|
||||
+ Repainting the wrong characters on the screen.
|
||||
+ Displaying inverse video in the wrong places.
|
||||
+ Failure to reset your terminal to the correct modes on exit.
|
||||
|
||||
you have a broken curses implementation, and you should reconfigure nvi
|
||||
to use another curses library.
|
||||
|
||||
An alternative for your vendor's curses is ncurses, available from
|
||||
ftp://ftp.gnu.org/pub/gnu/ncurses/
|
||||
|
||||
One final note. If you see the following symptoms:
|
||||
|
||||
+ Line-by-line screen repainting instead of scrolling.
|
||||
|
||||
it usually means that your termcap or terminfo information is insufficient
|
||||
for the terminal.
|
320
dist/nvi/build.unix/README.LynxOS
vendored
Normal file
320
dist/nvi/build.unix/README.LynxOS
vendored
Normal file
|
@ -0,0 +1,320 @@
|
|||
README.LynxOS
|
||||
=============
|
||||
|
||||
Written by Ronald F. Guilmette <rfg@monkeys.com>
|
||||
|
||||
Last modified Wed Aug 14 23:10:07 PDT 1996
|
||||
------------------------------------------
|
||||
|
||||
0. Introduction
|
||||
---------------
|
||||
|
||||
This file describes how to build and install the Berkeley nvi editor for
|
||||
the LynxOS 2.4.0 operating system.
|
||||
|
||||
LynxOS 2.4.0 is available for a variety of different hardware platforms, in
|
||||
particular, x86, m680x0, Sparc, and PowerPC. I have successfully built nvi
|
||||
on all four of these flavors of LynxOS by following the procedures given in
|
||||
this file.
|
||||
|
||||
Note that these procedures may not work on versions of LynxOS prior to 2.4.0.
|
||||
(As I understand it, a good deal of work went into making the 2.4.0 release
|
||||
more POSIX-compliant, and I have no idea what build glitches, if any, you
|
||||
might encounter if you try to build nvi on a pre-2.4.0 version of LynxOS.)
|
||||
|
||||
There are basically four steps to configuring, building, and installing nvi
|
||||
on LynxOS, namely:
|
||||
|
||||
1. Get setup to use the proper C compiler.
|
||||
2. Replace your installed `tr' program.
|
||||
3. Fix your system include files.
|
||||
4. Do a normal configure, build, and install of nvi.
|
||||
|
||||
These steps are described in separate sections below.
|
||||
|
||||
1. Get Setup to Use the Proper C Compiler
|
||||
------------------------------------------
|
||||
|
||||
The first step when building nvi on LynxOS is to set your $PATH environment
|
||||
variable properly so that the gcc 2.x compiler appears first on your path,
|
||||
prior to the older (and less robust) gcc 1.xx compiler (typically installed
|
||||
as /bin/gcc) and/or the old Lynx proprietary C compiler (typically installed
|
||||
as /bin/cc), both of which may also be present on your system.
|
||||
|
||||
Note that for most operating systems, the configure script for nvi tries
|
||||
to use whatever compiler you have installed (and in your $PATH) as "cc",
|
||||
however in the special case of LynxOS, the configure script will auto-
|
||||
matically try to find a "gcc" program on your $PATH in preference to a
|
||||
compiler called "cc". If the nvi configure script only find a compiler
|
||||
called "cc", that's OK. It will still try to see if that is really just
|
||||
the GNU C compiler installed under the name "cc".
|
||||
|
||||
Regardless of the name however (be it "gcc" or "cc") the first C compiler
|
||||
in your $PATH should be some _recent_ (i.e. 2.0 or later) version of the
|
||||
GNU C compiler... and the nvi configure script now checks that this is the
|
||||
case, and fails if it isn't.
|
||||
|
||||
Oddly enough, LynxOS 2.4.0 (and some prior versions) shipped with as many
|
||||
as three different C compilers installed, so it is important to set your
|
||||
$PATH environment variable carfully in order to get the proper C compiler
|
||||
to appear first in your $PATH. You want to avoid having either the /bin/gcc
|
||||
compiler or the /bin/cc compiler be the first C compiler in your $PATH.
|
||||
|
||||
To make sure that the GNU C version 2.x compiler which was shipped with your
|
||||
LynxOS system appears first on your path, you will need to either set your
|
||||
$PATH variable (for sh/bash/ksh users) or your $path variable (for csh/tcsh
|
||||
users). You can, of course, just do this at the shell command prompt, but
|
||||
it is probably better to actually edit this change into your .profile file
|
||||
(for sh/bash/ksh users) or into your .cshrc file (for csh/tcsh users).
|
||||
|
||||
The pathname of the directory that contains the GNU C version 2.x compiler
|
||||
is (unfortunately) dependent upon the exact type of LynxOS system you have.
|
||||
|
||||
For LynxOS 2.4.0 on x86 systems, gcc 2.x is located in:
|
||||
|
||||
/cygnus/94q4-lynxos-x86/bin
|
||||
|
||||
For LynxOS 2.4.0 on m680x0 systems, gcc 2.x is located in:
|
||||
|
||||
/cygnus/94q4-lynxos-68k/bin
|
||||
|
||||
For LynxOS 2.4.0 on Sparc systems, gcc 2.x is located in:
|
||||
|
||||
/cygnus/94q4-lynxos-usparc/bin
|
||||
|
||||
For LynxOS 2.4.0 on PowerPC systems, gcc 2.x is located in:
|
||||
|
||||
/cygnus/95q2-lynxos-ppc/bin
|
||||
|
||||
(Note also that these locations may change in LynxOS 2.5.x and beyond.)
|
||||
|
||||
Anyway, it is imperative that you setup your $PATH environment variable
|
||||
(*before* you do the configure step for nvi) so that the GNU C version 2.x
|
||||
compiler appears in your $PATH before either the /bin/cc or /bin/gcc
|
||||
compilers (if present). If you fail to do this, the configure step for
|
||||
nvi will fail, because the compiler script actually checks (now) that the
|
||||
compiler you are using (if your are on a LynxOS system) is gcc 2.0 or
|
||||
later.
|
||||
|
||||
To make absolutely sure that you will be configuring and building nvi with
|
||||
the proper C compiler (i.e. the GNU C version 2.x compiler on your system)
|
||||
you should add the directory name listed above for your specific system type
|
||||
to your $PATH setting in your $HOME/.profile file. (For csh/tcsh users, you
|
||||
will instead want to add the relevant directory name to the setting of your
|
||||
$path variable in your ~/.cshrc file.) Once you have added the proper direc-
|
||||
tory name (from the list given above) to your $HOME/.profile file (or to your
|
||||
~/.cshrc file, if you are using csh or tcsh) you should log out completely
|
||||
and then log back into the system just to make sure your new $PATH/$path
|
||||
setting takes effect properly.
|
||||
|
||||
When you finish making this adjustment to your $PATH (or $path), the most
|
||||
up-to-date version of gcc on your system should be available to you as the
|
||||
first `gcc' program on your $PATH. You should verify that this is indeed the
|
||||
case simply by typing `gcc -v' and then checking the version number reported
|
||||
by the compiler. It should say either "2.6-94q4" or (on PowerPC systems) it
|
||||
should say "2.6-95q2". If you don't get these results, try again to set your
|
||||
$PATH (or $path) until you do. You won't be able to build nvi until you are
|
||||
properly setup to use gcc version 2.0 or later.
|
||||
|
||||
Performing the steps shown above will insure that your subsequent configura-
|
||||
tion and build steps for nvi will make use of the most up-to-date version of
|
||||
gcc that was shipped with your Lynx operating system. (Note that the versions
|
||||
of gcc which are currently shipping with LynxOS 2.4.0 are also somewhat out-
|
||||
of-date themselves, but they are still quite a bit newer and more bug-free
|
||||
and ANSI conformant that those other two C compilers, /bin/cc and /bin/gcc,
|
||||
which also ship with LynxOS 2.4.0.)
|
||||
|
||||
(Note: At present, LynxOS version 2.4.0 is the latest officially released
|
||||
version of LynxOS, and all of the above information is accurate and correct
|
||||
for LynxOS 2.4.0 as of the time of this writing. However it is rumored that
|
||||
future releases of LynxOS may provide a still newer version of gcc, and that
|
||||
it may be located in the /usr/bin directory. Thus, if you are building nvi
|
||||
for some LynxOS version later than 2.4.0, you may wish to check and see if
|
||||
your system has a program called /usr/bin/gcc, and use that version of gcc,
|
||||
if available, rather than the one suggested above.)
|
||||
|
||||
2. Replace Your Installed `tr' Program
|
||||
---------------------------------------
|
||||
|
||||
The `tr' program which comes bundled with LynxOS 2.4.0 (as /bin/tr) has a
|
||||
somewhat obscure bug which just happens to be tickled by almost all GNU
|
||||
`autoconf' generated `configure' scripts (including the one that nowadays
|
||||
comes bundled with nvi). Using the stock /bin/tr program on LynxOS when
|
||||
executing such `configure' scripts _will_ cause these scripts to malfunction
|
||||
in various ways. It is therefore imperative that you replace your LynxOS
|
||||
/bin/tr program with a properly working version of the `tr' command _before_
|
||||
you even try to configure nvi. (You can tell if your `tr' program has the
|
||||
bug by executng the command "echo ab- | tr ab- ABC". If this yields the
|
||||
string "Ab-" then you have the bug. If it yields "ABC" then you don't.)
|
||||
|
||||
You can obtain sources for a working version of the `tr' command as part of
|
||||
the GNU `textutils' package (the latest version of which, at the time of this
|
||||
writing, is 1.19). The GNU textutils package is available for downloading
|
||||
from prep.ai.mit.edu in the pub/gnu directory. Look for the file named
|
||||
textutils-1.19.tar.gz, or an even more recent version of textutils, if one
|
||||
is available. Fetch it, gunzip it, untar it, and follow the directions in
|
||||
the INSTALL file included in the tar file to build and install the entire
|
||||
textutils set of utility programs (which includes a working `tr' program).
|
||||
Then just make sure that the GNU version of `tr' appears on your $PATH
|
||||
_before_ the LynxOS version of `tr' (i.e. /bin/tr). Be sure to do this
|
||||
step _before_ you start to configure nvi.
|
||||
|
||||
When building the textutils set of programs, I suggest that you use the most
|
||||
up-to-date C compiler available on your system (as described above). Also,
|
||||
note that it will be important for you to AVOID using the -O (optimize)
|
||||
compiler option when building the GNU textutils package, even if you are
|
||||
using the most up-to-date version of gcc which shipped with your system.
|
||||
If you try to use -O when building the textutils package on an x86 with
|
||||
the Cygnus 94q4 C compiler, you will end up with a `tr' program which will
|
||||
malfunction even worse than the one you are trying to replace! If you use
|
||||
-O when building the textutils package on LynxOS on the PowerPC (using the
|
||||
Cygnus 95q2 C compiler) you will just get yourself a compiler crash. So
|
||||
just don't use -O when building textutils. You can avoid using -O by in-
|
||||
voking make in the textutils directory as follows:
|
||||
|
||||
make CFLAGS="-g"
|
||||
|
||||
(Note: At present, LynxOS version 2.4.0 is the latest officially released
|
||||
version of LynxOS, and all of the above information is accurate and correct
|
||||
for LynxOS 2.4.0 as of the time of this writing. However it is rumored that
|
||||
the bug in the /bin/tr program will be fixed in future releases of LynxOS,
|
||||
so if you have a version of LynxOS later than 2.4.0, you may wish to check
|
||||
and see if your /bin/tr program even has the problematic bug before bothering
|
||||
with all of this.)
|
||||
|
||||
|
||||
3. Fix Your System Include Files
|
||||
---------------------------------
|
||||
|
||||
If you are building nvi on a PowerPC system, it is also important that you
|
||||
apply the patches given at the end of this file to your /usr/include files.
|
||||
(Note that you will have to be root in order to do this.) Two of the patches
|
||||
included below fix a pair of serious bugs in the /usr/include/stdarg.h file
|
||||
on the PowerPC, and you really _do_ want to have these bugs fixed anyway,
|
||||
because without these fixes, anything that you compile which uses <stdarg.h>
|
||||
will very likely malfunction at run-time.
|
||||
|
||||
Regardless of which LynxOS platform you are using (i.e. x86, PowerPC, Sparc,
|
||||
or m680x0) you may want to apply all of the system include files patches that
|
||||
are included below anyway. Doing so will clean up a few minor problems with
|
||||
the relevant system include files (i.e. <stdarg.h>, <ioctl.h>, and <wait.h>)
|
||||
and this step will also prevent a few warnings which you would otherwise get
|
||||
during the build of nvi.
|
||||
|
||||
You can apply all of the patches given at the end of this file simply by
|
||||
doing the following:
|
||||
|
||||
su root
|
||||
cd /usr/include
|
||||
/bin/patch < this-file
|
||||
|
||||
Where `this-file' is the actual full pathname of the file you are now reading,
|
||||
wherever it may reside on your own system.
|
||||
|
||||
(Note: At present, LynxOS version 2.4.0 is the latest officially released
|
||||
version of LynxOS, and all of the above information is accurate and correct
|
||||
for LynxOS 2.4.0 as of the time of this writing. However it is rumored that
|
||||
future releases of LynxOS may incorporate some or all of the important system
|
||||
include file fixes provided below. Thus, if you are building nvi for some
|
||||
LynxOS version later than 2.4.0, you should probably go ahead and try to
|
||||
apply the patches given below to your system include files, and then just
|
||||
don't worry about it if these patches seem to have already been applied.)
|
||||
|
||||
|
||||
4. A Brief Note about Sendmail
|
||||
-------------------------------
|
||||
|
||||
I should mention also that LynxOS does not normally ship with the `sendmail'
|
||||
mail transfer program installed, either under /usr/lib/ or anywhere else for
|
||||
that matter. This isn't really a big problem, but nvi normally wants and
|
||||
expects to have a sendmail program available so that it can send users notifi-
|
||||
cations (by mail) whenever a partially edited file is preserved by the editor
|
||||
in response to a sudden system crash, a sudden system shutdown, or an unexpect-
|
||||
ed serial-line hangup. You can configure and build nvi without any sendmail
|
||||
program installed on your system, but you will get warnings about its absence
|
||||
when you are doing the initial configure step prior to actually building nvi.
|
||||
If you want to have a fully-functional nvi which does send out notification
|
||||
messages (by mail) whenever partially edited files are preserved during a
|
||||
serial line hangup or system crash, then you should get the BSD sendmail
|
||||
sources (via ftp from ftp.cs.berkeley.edu), build and install sendmail, and
|
||||
then reconfigure, rebuild, and reinstall nvi.
|
||||
|
||||
Please contact me at the E-mail address below if you experience any problems in
|
||||
building or using nvi on LynxOS. I make no guarrantees, but I may be willing
|
||||
to try to help.
|
||||
|
||||
Ron Guilmette
|
||||
Roseville, California
|
||||
<rfg@monkeys.com>
|
||||
August 14, 1996
|
||||
|
||||
|
||||
cut here for LynxOS 2.4.0 system include files patches
|
||||
-----------------------------------------------------------------------------
|
||||
*** wait.h Fri Apr 26 10:02:45 1996
|
||||
--- wait.h Sun May 19 05:36:50 1996
|
||||
***************
|
||||
*** 94,104 ****
|
||||
/* Function prototypes */
|
||||
#ifndef __LYNXOS
|
||||
- #ifdef _POSIX_SOURCE
|
||||
extern pid_t wait _AP((int *));
|
||||
extern pid_t waitpid _AP((pid_t, int *, int));
|
||||
! #else
|
||||
! extern int wait _AP((union wait *));
|
||||
! extern int waitpid _AP((int, union wait *, int));
|
||||
! extern int wait3 _AP((union wait *, int, struct rusage *));
|
||||
#endif
|
||||
#endif /* !__LYNXOS */
|
||||
--- 94,101 ----
|
||||
/* Function prototypes */
|
||||
#ifndef __LYNXOS
|
||||
extern pid_t wait _AP((int *));
|
||||
extern pid_t waitpid _AP((pid_t, int *, int));
|
||||
! #ifndef _POSIX_SOURCE
|
||||
! extern int wait3 _AP((int *, int, struct rusage *));
|
||||
#endif
|
||||
#endif /* !__LYNXOS */
|
||||
*** ioctl.h Fri Apr 26 16:50:51 1996
|
||||
--- ioctl.h Sat May 18 17:55:16 1996
|
||||
***************
|
||||
*** 572,576 ****
|
||||
|
||||
#ifndef __LYNXOS
|
||||
! extern int ioctl _AP((int, int, char *));
|
||||
#endif
|
||||
|
||||
--- 572,576 ----
|
||||
|
||||
#ifndef __LYNXOS
|
||||
! extern int ioctl _AP((int, int, ...));
|
||||
#endif
|
||||
|
||||
*** stdarg.h Fri Apr 26 16:51:02 1996
|
||||
--- stdarg.h Sat May 18 19:34:13 1996
|
||||
***************
|
||||
*** 88,92 ****
|
||||
(((sizeof(TYPE) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
|
||||
|
||||
! #define va_start(AP, LASTARG) (AP = ((char *) __builtin_next_arg ()))
|
||||
|
||||
void va_end(va_list); /* Defined in libgcc.a */
|
||||
--- 88,92 ----
|
||||
(((sizeof(TYPE) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
|
||||
|
||||
! #define va_start(AP, LASTARG) (AP = ((char *) __builtin_next_arg (LASTARG)))
|
||||
|
||||
void va_end(va_list); /* Defined in libgcc.a */
|
||||
***************
|
||||
*** 162,166 ****
|
||||
(((sizeof(TYPE) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
|
||||
|
||||
! #define va_start(AP, LASTARG) (AP = ((char *) __builtin_next_arg ()))
|
||||
|
||||
void va_end(va_list); /* Defined in libgcc.a */
|
||||
--- 162,166 ----
|
||||
(((sizeof(TYPE) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
|
||||
|
||||
! #define va_start(AP, LASTARG) (AP = ((char *) __builtin_next_arg (LASTARG)))
|
||||
|
||||
void va_end(va_list); /* Defined in libgcc.a */
|
10
dist/nvi/build.unix/README.Solaris
vendored
Normal file
10
dist/nvi/build.unix/README.Solaris
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
There are some known problems with Solaris curses.
|
||||
Please give ncurses a try when you encounter a screen output problem.
|
||||
|
||||
Apparently, the more recent Solaris compilers invoke the incremental linker,
|
||||
`ild', when the "-g" option is used and one or more "xxx.o" files are
|
||||
specified on the command line during the link phase. Unfortunately, the
|
||||
executable produced is up to 3-4 times as big as an executable generated
|
||||
by the standard linker `ld'.
|
||||
You can bypass this by adding "-xildoff" to LDFLAGS or by
|
||||
setting CFLAGS (to something that does not contain "-g").
|
84
dist/nvi/catalog/Makefile
vendored
Normal file
84
dist/nvi/catalog/Makefile
vendored
Normal file
|
@ -0,0 +1,84 @@
|
|||
# Id: Makefile,v 8.30 1996/11/27 11:59:09 bostic Exp (Berkeley) Date: 1996/11/27 11:59:09
|
||||
|
||||
CAT= dutch english french german ru_RU.KOI8-R spanish swedish
|
||||
FILES= ../cl/*.c ../common/*.c ../ex/*.c ../vi/*.c
|
||||
|
||||
all: dump ${CAT}
|
||||
|
||||
${CAT}: english.base
|
||||
@echo "... $@"; \
|
||||
rm -f $@; \
|
||||
sort -u $@.base | \
|
||||
awk '{ \
|
||||
if ($$1 == 1) { \
|
||||
print "\nMESSAGE NUMBER 1 IS NOT LEGAL"; \
|
||||
exit 1; \
|
||||
} \
|
||||
if (++nline > $$1) { \
|
||||
print "DUPLICATE MESSAGE NUMBER " $$1; \
|
||||
exit 1; \
|
||||
} \
|
||||
for (; nline < $$1; ++nline) \
|
||||
print ""; \
|
||||
print $0; \
|
||||
}' | \
|
||||
sed -e '1s/^/VI_MESSAGE_CATALOG/' \
|
||||
-e '/"/s/^[^"]*"//' \
|
||||
-e '1!s/"$$/X/' > $@; \
|
||||
chmod 444 $@; \
|
||||
if grep DUPLICATE $@ > /dev/null; then \
|
||||
grep DUPLICATE $@; \
|
||||
fi; \
|
||||
if grep 'NOT LEGAL' $@ > /dev/null; then \
|
||||
grep 'NOT LEGAL' $@; \
|
||||
fi
|
||||
|
||||
CHK= dutch.check english.check french.check german.check \
|
||||
ru_RU.KOI8-R.check spanish.check swedish.check
|
||||
check: ${CHK}
|
||||
${CHK}: ${CAT}
|
||||
@echo "... $@"; \
|
||||
f=`basename $@ .check`; \
|
||||
(echo "Unused message id's (this is okay):"; \
|
||||
awk '{ \
|
||||
while (++nline < $$1) \
|
||||
printf "%03d\n", nline; \
|
||||
}' < $$f.base; \
|
||||
echo =========================; \
|
||||
echo "MISSING ERROR MESSAGES (Please add!):"; \
|
||||
awk '{print $$1}' < $$f.base | sort -u > __ck1; \
|
||||
awk '{print $$1}' < english.base | sort -u > __ck2; \
|
||||
comm -13 __ck1 __ck2; \
|
||||
echo =========================; \
|
||||
echo "Extra error messages (just delete them):"; \
|
||||
comm -23 __ck1 __ck2; \
|
||||
echo =========================; \
|
||||
echo "MESSAGES WITH THE SAME MESSAGE ID's (FIX!):"; \
|
||||
for j in \
|
||||
`sed '/^$$/d' < $$f.base | sort -u | \
|
||||
awk '{print $$1}' | uniq -d`; do \
|
||||
egrep $$j $$f.base; \
|
||||
done; \
|
||||
echo =========================; \
|
||||
echo "Duplicate messages, both id and message (this is okay):"; \
|
||||
sed '/^$$/d' < $$f.base | sort | uniq -c | \
|
||||
awk '$$1 != 1 { print $$0 }' | sort -n; \
|
||||
echo =========================; \
|
||||
echo "Duplicate messages, just message (this is okay):"; \
|
||||
sed '/^$$/d' < $$f | sort | uniq -c | \
|
||||
awk '$$1 != 1 { print $$0 }' | sort -n; \
|
||||
echo =========================) > $@
|
||||
|
||||
english.base: dump ${FILES} #Makefile
|
||||
./dump ${FILES} |\
|
||||
sed -e '/|/!d' \
|
||||
-e 's/|/ "/' \
|
||||
-e 's/^"//' \
|
||||
-e 's/\\"/"/g' |\
|
||||
sort -n > $@
|
||||
|
||||
dump: dump.c
|
||||
${CC} -O -o dump dump.c
|
||||
|
||||
clean:
|
||||
rm -f dump dump.o ${CAT} english.base *.check __ck1 __ck2
|
166
dist/nvi/catalog/README
vendored
Normal file
166
dist/nvi/catalog/README
vendored
Normal file
|
@ -0,0 +1,166 @@
|
|||
# Id: README,v 8.4 1994/11/22 09:52:04 bostic Exp (Berkeley) Date: 1994/11/22 09:52:04
|
||||
|
||||
Generally, all non-system error and informational messages in nvi are
|
||||
catalog messages, i.e. they can be tailored to a specific langauge.
|
||||
Command strings, usage strings, system errors and other "known text"
|
||||
are not. It would certainly be possible to internationalize all the
|
||||
text strings in nvi, but it's unclear that it's the right thing to do.
|
||||
|
||||
First, there's no portable way to do message catalogs. The System V
|
||||
scheme is a reasonable choice, but none of the 4BSD derived systems
|
||||
support it. So, catalogs are completely implemented within nvi, and
|
||||
don't require any library support.
|
||||
|
||||
Message catalogs in nvi are fairly simple. Every catalog message
|
||||
consists of two parts -- an initial number followed by a pipe (`|')
|
||||
character, followed by the English text for the message. For example:
|
||||
|
||||
msgq(sp, M_ERR, "001|This is an error message");
|
||||
|
||||
would be a typical message.
|
||||
|
||||
When the msgq() routine is called, if the user has specified a message
|
||||
catalog and the format string (the third argument) has a leading number,
|
||||
then it is converted to a record number, and that record is retrieved
|
||||
from the message catalog and used as a replacement format string. If
|
||||
the record can't be retrieved for any reason, the English text is displayed
|
||||
instead.
|
||||
|
||||
Each message format string MUST map into the English format string, i.e.
|
||||
it can't display more or different arguments than the English one.
|
||||
|
||||
For example:
|
||||
|
||||
msgq(sp, M_ERR, "002|Error: %d %x", arg1, arg2);
|
||||
|
||||
is a format string that displays two arguments. It is possible, however,
|
||||
to reorder the arguments or to not display all of them. The convention
|
||||
nvi uses is the System V printf(3) convention, i.e. "%[0-9]*$" is the name
|
||||
of a specific, numbered argument. For example:
|
||||
|
||||
msgq(sp, M_ERR, "002|Error: %2$d %1$x", arg1, arg2);
|
||||
|
||||
displays the arguments in reverse order.
|
||||
|
||||
If the system supports this convention in its library printf routines
|
||||
(as specified by the test #define NL_ARGMAX), nvi uses those routines.
|
||||
Otherwise, there is some serious magic going on in common/msg.c to make
|
||||
this all work.
|
||||
|
||||
Arguments to the msgq function are required to contain ONLY printable
|
||||
characters. No further translation is done by the msgq routine before
|
||||
displaying the message on the screen. For example, in the msgq call:
|
||||
|
||||
msgq(sp, M_ERR, "003|File: %s", file_name);
|
||||
|
||||
"file_name" must contain only printable characters. The routine
|
||||
msg_print() returns a printable version of a string in allocated
|
||||
memory. For example:
|
||||
|
||||
char *p;
|
||||
|
||||
p = msg_print(sp, file_name);
|
||||
msgq(sp, M_ERR, M("003", "File: %s"), p);
|
||||
FREE_SPACE(sp, p, 0);
|
||||
|
||||
makes sure that "file_name" is printable before calling the msgq
|
||||
routine.
|
||||
|
||||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
The message catalogs themselves are maintained in two files. The first
|
||||
is the "base file" which contains two fields, a record number and the
|
||||
message itself. All base files are named using the convention
|
||||
"vi_<language>.base", e.g. the English one is "vi_english.base". For
|
||||
example:
|
||||
|
||||
002 "Unable to create temporary file"
|
||||
003 "Warning: %s is not a regular file"
|
||||
004 "%s already locked, session is read-only"
|
||||
005 "%s: remove"
|
||||
006 "%s: close"
|
||||
007 "%s: remove"
|
||||
008 "%s: remove"
|
||||
009 "Read-only file, not written; use ! to override"
|
||||
010 "Read-only file, not written"
|
||||
|
||||
are the first few lines of the current vi_english.base file. Note that
|
||||
message #1 is missing -- the first message of each catalog is a special
|
||||
one, so that nvi can recognize message catalog files. It's added by the
|
||||
Makefile script that creates the second version of the message catalog.
|
||||
|
||||
The second file is the file used by nvi to access messages, and is a list
|
||||
of the messages, one per line:
|
||||
|
||||
VI_MESSAGE_CATALOG
|
||||
Unable to create temporary fileX
|
||||
Warning: %s is not a regular fileX
|
||||
%s already locked, session is read-onlyX
|
||||
%s: removeX
|
||||
%s: closeX
|
||||
%s: removeX
|
||||
%s: removeX
|
||||
Read-only file, not written; use ! to overrideX
|
||||
Read-only file, not writtenX
|
||||
|
||||
Note that all messages have had a trailing 'X' character appended. This
|
||||
is to provide nvi a place to store a trailing nul for the message so that
|
||||
C library routines that expect one won't be disappointed.
|
||||
|
||||
These files are named for their language, e.g. "vi_english". The second
|
||||
files are automatically created from the first files.
|
||||
|
||||
To create a new catalog for nvi:
|
||||
|
||||
Copy the file vi_english.base to a file that you can modify , e.g. "cp
|
||||
vi_english.base vi_german.base". For each of the messages in the file,
|
||||
replace the message with the string that you want to use. To find out
|
||||
what the arguments to a message are, I'm afraid you'll have to search
|
||||
the source code for the message number. You can find them fairly quickly
|
||||
by doing:
|
||||
|
||||
cd ..; egrep '123\|' */*.[chys]
|
||||
|
||||
I'm sorry that there's not an easier way, but I couldn't think of
|
||||
anything that wasn't a lot of work.
|
||||
|
||||
If, for some reason, you don't have the file vi_english.base, or you
|
||||
have new sources for which you want to create a new base catalog, you
|
||||
can create it by running the command "make english" in the catalog
|
||||
directory.
|
||||
|
||||
Once you've translated all of the strings, then add your catalog to the
|
||||
"CAT=" line of the Makefile, and run the command "make catalog". This
|
||||
will create the second (and corresponding) file for each file named
|
||||
<language>.base.
|
||||
|
||||
Don't worry about missing line numbers, i.e. base files that look like:
|
||||
|
||||
005 Message number 5.
|
||||
007 Message number 7.
|
||||
|
||||
This simply means that a message was deleted during the course of nvi's
|
||||
development. It will be taken care of automatically when you create
|
||||
the second form of the file.
|
||||
|
||||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
If you add new messages to the nvi sources, you can check your work by
|
||||
doing "make english; make check". The "make check" target lists unused
|
||||
message numbers, duplicate message numbers, and duplicate messages.
|
||||
Unused message numbers are only useful if you are condensing messages.
|
||||
Duplicate message numbers are a serious problem and have to be fixed.
|
||||
Duplicate messages are only interesting if a message appears often enough
|
||||
that it's worth creating a routine so that the string is only need in
|
||||
a single place.
|
||||
|
||||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
To select a catalog when running nvi, set the "msgcat" option. If the
|
||||
value of this option ends with a '/', it is treated as the name of a
|
||||
directory that contains a message catalog "vi_XXXX", where XXXX is the
|
||||
value of the LANG environmental variable, if it's set, or the value of
|
||||
the LC_MESSAGES environmental variable if it's not. If neither of those
|
||||
environmental variables are set, or if the option doesn't end in a '/',
|
||||
the option is treated as the full path name of the message catalog to use.
|
||||
|
||||
If any messages are missing from the catalog, the backup text (English)
|
||||
is used instead.
|
91
dist/nvi/catalog/dump.c
vendored
Normal file
91
dist/nvi/catalog/dump.c
vendored
Normal file
|
@ -0,0 +1,91 @@
|
|||
/* $NetBSD: dump.c,v 1.2 2008/06/11 21:30:52 aymeric Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* %sccs.include.redist.c%
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"%Z% Copyright (c) 1992, 1993, 1994\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "Id: dump.c,v 8.1 1994/08/31 13:27:37 bostic Exp (Berkeley) Date: 1994/08/31 13:27:37";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static void
|
||||
parse(fp)
|
||||
FILE *fp;
|
||||
{
|
||||
int ch, s1, s2, s3;
|
||||
|
||||
#define TESTD(s) { \
|
||||
if ((s = getc(fp)) == EOF) \
|
||||
return; \
|
||||
if (!isdigit(s)) \
|
||||
continue; \
|
||||
}
|
||||
#define TESTP { \
|
||||
if ((ch = getc(fp)) == EOF) \
|
||||
return; \
|
||||
if (ch != '|') \
|
||||
continue; \
|
||||
}
|
||||
#define MOVEC(t) { \
|
||||
do { \
|
||||
if ((ch = getc(fp)) == EOF) \
|
||||
return; \
|
||||
} while (ch != (t)); \
|
||||
}
|
||||
for (;;) {
|
||||
MOVEC('"');
|
||||
TESTD(s1);
|
||||
TESTD(s2);
|
||||
TESTD(s3);
|
||||
TESTP;
|
||||
putchar('"');
|
||||
putchar(s1);
|
||||
putchar(s2);
|
||||
putchar(s3);
|
||||
putchar('|');
|
||||
for (;;) { /* dump to end quote. */
|
||||
if ((ch = getc(fp)) == EOF)
|
||||
return;
|
||||
putchar(ch);
|
||||
if (ch == '"')
|
||||
break;
|
||||
if (ch == '\\') {
|
||||
if ((ch = getc(fp)) == EOF)
|
||||
return;
|
||||
putchar(ch);
|
||||
}
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
for (; *argv != NULL; ++argv) {
|
||||
if ((fp = fopen(*argv, "r")) == NULL) {
|
||||
perror(*argv);
|
||||
exit (1);
|
||||
}
|
||||
parse(fp);
|
||||
(void)fclose(fp);
|
||||
}
|
||||
exit (0);
|
||||
}
|
306
dist/nvi/catalog/dutch.base
vendored
Normal file
306
dist/nvi/catalog/dutch.base
vendored
Normal file
|
@ -0,0 +1,306 @@
|
|||
002 "regel te lang"
|
||||
003 "kan regel %lu niet verwijderen"
|
||||
004 "kan niet toevoegen aan regel %lu"
|
||||
005 "kan niet invoegen vooraan regel %lu"
|
||||
006 "kan regel %lu niet opslaan"
|
||||
007 "kan laatste regel niet lezen"
|
||||
008 "Fout: kan regel %lu niet vinden"
|
||||
009 "log bestand"
|
||||
010 "Er vindt geen logging plaats, kan wijzigingen niet ongedaan maken"
|
||||
011 "geen wijzigingen om ongedaan te maken"
|
||||
012 "Er vindt geen logging plaats, kan wijzigingen niet ongedaan maken"
|
||||
013 "Er vindt geen logging plaats, herhaling niet mogelijk"
|
||||
014 "geen wijzigingen om te herhalen"
|
||||
015 "%s/%d: schrijven naar log mislukt"
|
||||
016 "Vi's standaard invoer en uitvoer moeten aan een terminal gekoppeld zijn"
|
||||
017 "Merk %s: niet gezet"
|
||||
018 "Merk %s: de regel is verwijderd"
|
||||
019 "Merk %s: de cursor positie bestaat niet meer"
|
||||
020 "Fout: "
|
||||
021 "nieuw bestand"
|
||||
022 "naam veranderd"
|
||||
023 "gewijzigd"
|
||||
024 "ongewijzigd"
|
||||
025 "NIET BEVEILIGD"
|
||||
026 "niet schrijfbaar"
|
||||
027 "regel %lu uit %lu [%ld%%]"
|
||||
028 "leeg bestand"
|
||||
029 "regel %lu"
|
||||
030 "Het bestand %s is geen message catalog"
|
||||
031 "Niet in staat om de standaard %s optie in te stellen"
|
||||
032 "Gebruik: %s"
|
||||
033 "set: optie %s onbekend: 'set all' laat alle opties zien"
|
||||
034 "set: [no]%s optie kan geen waarde hebben"
|
||||
035 "set: %s optie moet een waarde hebben"
|
||||
036 "set: %s optie: %s"
|
||||
037 "set: %s optie: %s: getal is te groot"
|
||||
038 "set: %s optie: %s is een ongeldige waarde"
|
||||
039 "set: %s optie moet een waarde hebben"
|
||||
040 "Te weinig kolommen op het scherm, minder dan %d"
|
||||
041 "Aantal kolommen te groot, meer dan %d"
|
||||
042 "Te weinig regels op het scherm, minder dan %d"
|
||||
043 "Aantal regels te groot, meer dan %d"
|
||||
044 "De lisp optie is niet ondersteund"
|
||||
045 "messages niet uitgeschakeld: %s"
|
||||
046 "messages niet geactiveerd: %s"
|
||||
047 "set: de %s optie moet karakter paren bevatten"
|
||||
053 "De standaard buffer is leeg"
|
||||
054 "Buffer %s is leeg"
|
||||
055 "Bestanden met newlines in de naam kunnen niet hersteld worden"
|
||||
056 "Wijzigingen kunnen niet ongedaan gemaakt worden als deze sessie mislukt"
|
||||
057 "Bestand wordt gecopieerd voor herstel..."
|
||||
058 "Herstel mechanisme werkt niet: %s"
|
||||
059 "Wijzigingen kunnen niet ongedaan gemaakt worden als deze sessie mislukt"
|
||||
060 "Kon bestand niet veilig stellen: %s"
|
||||
061 "Bestand wordt gecopieerd voor herstel..."
|
||||
062 "Informatie met betrekking tot gebruiker nummer %u niet gevonden"
|
||||
063 "Kan herstel bestand niet beveiligen"
|
||||
064 "herstel buffer overgelopen"
|
||||
065 "herstel bestand"
|
||||
066 "%s: verminkt herstel bestand"
|
||||
067 "%s: verminkt herstel bestand"
|
||||
068 "U heeft geen bestand genaamd %s te herstellen"
|
||||
069 "U kan eerdere versies van dit bestand herstellen"
|
||||
070 "U kan nog meer bestanden herstellen"
|
||||
071 "kan geen email versturen: %s"
|
||||
072 "Bestand leeg; niets om te doorzoeken"
|
||||
073 "Einde van het bestand bereikt zonder dat het patroon gevonden is"
|
||||
074 "Geen vorig zoek patroon"
|
||||
075 "Patroon niet gevonden"
|
||||
076 "Begin van het bestand bereikt zonder dat het patroon gevonden is"
|
||||
077 "Zoek-operatie omgeslagen"
|
||||
078 "Bezig met zoeken..."
|
||||
079 "Geen niet-printbaar karakter gevonden"
|
||||
080 "Onbekend commando"
|
||||
082 "Commando niet beschikbaar in ex mode"
|
||||
083 "Aantal mag niet nul zijn"
|
||||
084 "%s: ongeldige regel aanduiding"
|
||||
085 "Interne fout in syntax tabel (%s: %s)"
|
||||
086 "Gebruik: %s"
|
||||
087 "%s: tijdelijke buffer niet vrijgegeven"
|
||||
088 "Vlag offset voor regel 1"
|
||||
089 "Vlag offset voorbij bestands einde"
|
||||
090 "bestand/scherm veranderd tijdens uitvoeren van @ in een blok"
|
||||
091 "bestand/scherm veranderd tijdens uitvoeren van globaal/v commando"
|
||||
092 "Ex commando mislukt: rest van commando(s) genegeerd"
|
||||
093 "Ex commando mislukt: gemappede toetsen genegeerd"
|
||||
094 "Het tweede adres is kleiner dan het eerste"
|
||||
095 "Geen merk naam opgegeven"
|
||||
096 "\\ niet gevolgd door / of ?"
|
||||
097 "Referentie aan een regel nummer kleiner dan 0"
|
||||
098 "Het %s commando is onbekend"
|
||||
099 "Adres waarde te groot"
|
||||
100 "Adres waarde te klein"
|
||||
101 "Ongeldige adres combinatie"
|
||||
102 "Ongeldig adres: slechts %lu regels in het bestand aanwezig"
|
||||
103 "Ongeldig adres: het bestand is leeg"
|
||||
104 "Het %s commando staat het adres 0 niet toe"
|
||||
105 "Geen afkortingen om weer te geven"
|
||||
106 "Afkortingen moeten eindigen met een "woord" letter"
|
||||
107 "Afkortingen mogen geen tabulaties of spaties bevatten"
|
||||
108 "Afkortingen mogen geen woord/niet-woord karakters mengen, behalve aan het einde"
|
||||
109 ""%s" is geen afkorting"
|
||||
110 "Vi commando mislukt: gemappede toetsen genegeerd"
|
||||
111 "Dit is het laatste bestand"
|
||||
112 "Dit is het eerste bestand"
|
||||
113 "Dit is het eerste bestand"
|
||||
114 "lijst met bestanden is leeg"
|
||||
115 "Geen voorgaand commando om "!" te vervangen"
|
||||
116 "Geen bestandsnaam voor %%"
|
||||
117 "Geen bestandsnaam voor #"
|
||||
118 "Fout: execl: %s"
|
||||
119 "I/O fout: %s"
|
||||
120 "Bestand gewijzigd sinds laatste schrijfactie; schrijf het weg of gebruik ! om het te forceren"
|
||||
121 "Kan uw home directory niet vinden"
|
||||
122 "Nieuwe huidige directory: %s"
|
||||
123 "Geen cut buffers aanwezig"
|
||||
124 "Het %s commando kan niet gebruikt worden in een globaal of v commando"
|
||||
125 "%s/%s: niet gelezen: noch U noch root is de eigenaar"
|
||||
126 "%s/%s: niet gelezen: U bent niet de eigenaar"
|
||||
127 "%s/%s: niet gelezen: kan gewijzigd worden door andere gebruikers"
|
||||
128 "%s: niet gelezen: noch U noch root is de eigenaar""
|
||||
129 "%s: niet gelezen: U bent niet de eigenaar"
|
||||
130 "%s: niet gelezen: kan gewijzigd worden door andere gebruikers"
|
||||
131 "Geen volgende regel om samen te voegen"
|
||||
132 "Geen input map entries"
|
||||
133 "Geen command map entries"
|
||||
134 "Het %s karakter kan niet ge-remapped worden"
|
||||
135 ""%s" is niet gemapped"
|
||||
136 "Merk naam moet een enkel karakter zijn"
|
||||
137 "%s bestaat al, niet weggeschreven; gebruik ! om het te forceren"
|
||||
138 "Nieuw .exrc bestand: %s. "
|
||||
139 "doel regel ligt in het blok"
|
||||
140 "Het open commando vereist dat de open optie actief is"
|
||||
141 "Het open commando is nog niet ondersteund"
|
||||
142 "Kan dit bestand niet veilig stellen"
|
||||
143 "Bestand veilig gesteld"
|
||||
144 "%s resulteert in te veel bestandsnamen"
|
||||
145 "Alleen echte bestanden en named pipes kunnen gelezen worden"
|
||||
146 "%s: lees beveiliging niet beschikbaar"
|
||||
147 "Bezig met lezen..."
|
||||
148 "%s: %lu regels, %lu karakters"
|
||||
149 "Geen achtergrond schermen aanwezig"
|
||||
150 "Het script commando is alleen beschikbaar in vi mode"
|
||||
151 "Geen comando om uit te voeren"
|
||||
152 "shiftwidth optie op 0 gezet"
|
||||
153 "Count te groot"
|
||||
154 "Count te klein"
|
||||
155 "Reguliere expressie opgegeven; r vlag heeft geen betekenis"
|
||||
156 "De #, l en p vlaggen kunnen niet gecombineerd worden met de c vlag in vi mode"
|
||||
157 "Geen match gevonden"
|
||||
158 "Geen voorafgaande tag aanwezig"
|
||||
159 "Minder dan %s elementen op de tags stapel; gebruik :display t[ags]"
|
||||
160 "Geen bestand genaamd %s op de tags stapel; gebruik :display t[ags]"
|
||||
161 "Kies Enter om door te gaan: "
|
||||
162 "%s: tag niet gevonden"
|
||||
163 "%s: verminkte tag in %s"
|
||||
164 "%s: Het regel nummer van deze tag is voorbij het einde van het bestand"
|
||||
165 "De tags stapel is leeg"
|
||||
166 "%s: zoek patroon niet gevonden"
|
||||
167 "%d andere bestanden te wijzigen"
|
||||
168 "Buffer %s is leeg"
|
||||
169 "Bevestig wijziging? [n]"
|
||||
170 "Onderbroken"
|
||||
171 "Geen voorafgaande buffer om uit te voeren"
|
||||
172 "Geen vorige reguliere expressie"
|
||||
173 "Het %s commando vereist dat er een bestand geladen is"
|
||||
174 "Gebruik: %s"
|
||||
175 "Het visual commando vereist dat de open optie actief is"
|
||||
177 "Leeg bestand"
|
||||
178 "Geen voorafgaand F, f, T of t zoek commando"
|
||||
179 "%s niet gevonden"
|
||||
180 "Geen voorafgaand bestand te bewerken"
|
||||
181 "Cursor niet op een getal"
|
||||
182 "Getal wordt te groot"
|
||||
183 "Getal wordt te klein"
|
||||
184 "Geen overeenkomstig karakter op deze regel"
|
||||
185 "Overeenkomstig karakter niet gevonden"
|
||||
186 "Geen karakters te vervangen"
|
||||
187 "Geen ander scherm aanwezig"
|
||||
188 "Karakters achter het zoek patroon, de regel offset, en/of het z commando"
|
||||
189 "Geen voorafgaand zoek patroon"
|
||||
190 "Zoekopdracht na omslag teruggekeerd op originele positie"
|
||||
191 "Afkorting overschrijdt expansie limiet: karakters genegeerd"
|
||||
192 "Ongeldig karakter; quote to enter"
|
||||
193 "Reeds aan het begin van de invoer"
|
||||
194 "Niet meer karakters te verwijderen"
|
||||
195 "Verplaatsing voorbij het einde van het bestand"
|
||||
196 "Verplaatsing voorbij het einde van de regel"
|
||||
197 "Cursor niet verplaatst"
|
||||
198 "Reeds aan het begin van het bestand"
|
||||
199 "Verplaatsing voorbij het begin van het bestand"
|
||||
200 "Reeds in de eerste kolom"
|
||||
201 "Buffers moeten voor het commando opgegeven worden"
|
||||
202 "Reeds bij het einde van het bestand"
|
||||
203 "Reeds bij het einde van de regel"
|
||||
204 "%s is geen vi commando"
|
||||
205 "Gebruik: %s"
|
||||
206 "Geen karakters te verwijderen"
|
||||
207 "Het Q commando vereist de ex terminal interface"
|
||||
208 "Geen commando om te herhalen"
|
||||
209 "Het bestand is leeg"
|
||||
210 "%s mag niet gebruikt worden als een verplaatsings commando"
|
||||
211 "Al in commando mode"
|
||||
212 "Cursor niet in een woord"
|
||||
214 "Windows optie waarde is te groot, maximum is %u"
|
||||
215 "Toevoegen"
|
||||
216 "Veranderen"
|
||||
217 "Commando"
|
||||
218 "Invoegen"
|
||||
219 "Vervangen"
|
||||
220 "Verplaatsing voorbij het eind van het scherm"
|
||||
221 "Verplaatsing voorbij het begin van het scherm"
|
||||
222 "Scherm moet meer dan %d regels hebben om het te kunnen splitsen"
|
||||
223 "Er zijn geen achtergrond schermen"
|
||||
224 "Er is geen achtergrond scherm waarin U bestand %s aan het bewerken bent"
|
||||
225 "U kan uw enige scherm niet in de achtergrond zetten"
|
||||
226 "Het scherm kan slechts verkleind worden tot %d regels"
|
||||
227 "Het scherm kan niet kleiner"
|
||||
228 "Het scherm kan niet groter"
|
||||
230 "Dit scherm kan niet gesuspend worden"
|
||||
231 "Onderbroken: gemappede toetsen genegeerd"
|
||||
232 "vi: tijdelijke buffer niet vrijgegeven"
|
||||
233 "Deze terminal heeft geen %s toets"
|
||||
234 "Er kan slechts een buffer opgegeven worden"
|
||||
235 "Getal groter dan %lu"
|
||||
236 "Onderbroken"
|
||||
237 "Aanmaken van tijdelijk bestand is mislukt"
|
||||
238 "Waarschuwing: %s is geen regulier bestand"
|
||||
239 "%s is al geopend, bestand is in deze sessie niet schrijfbaar"
|
||||
240 "%s: verwijdering mislukt"
|
||||
241 "%s: sluiting mislukt"
|
||||
242 "%s: verwijdering mislukt"
|
||||
243 "%s: verwijdering mislukt"
|
||||
244 "Bestand niet schrijfbaar, niet weggeschreven; gebruik ! om het te forceren"
|
||||
245 "Bestand niet schrijfbaar, niet weggeschreven"
|
||||
246 "%s bestaat al, niet weggeschreven; gebruik ! om het te forceren"
|
||||
247 "%s bestaat al, niet weggeschreven"
|
||||
248 "Gebruik ! om een incompleet bestand weg te schrijven"
|
||||
249 "Bestand incompleet, niet weggeschreven"
|
||||
250 "%s: bestand op disk nieuwer dan deze versie; gebruik ! om het te forceren"
|
||||
251 "%s: bestand op disk nieuwer dan deze versie"
|
||||
252 "%s: schrijf beveiliging niet beschikbaar"
|
||||
253 "Bezig met schrijven..."
|
||||
254 "%s: WAARSCHUWING: BESTAND INCOMPLEET"
|
||||
255 "Reeds op de eerste tag van deze groep"
|
||||
256 "%s: nieuw bestand: %lu regels, %lu karakters"
|
||||
257 "%s: %lu regels, %lu karakters"
|
||||
258 "%s resulteert in te veel bestandsnamen"
|
||||
259 "%s: geen normaal bestand"
|
||||
260 "%s: U bent niet de eigenaar"
|
||||
261 "%s: kan gewijzigd worden door andere gebruikers"
|
||||
262 "Bestand gewijzigd sinds laatste schrijfactie; schrijf het weg of gebruik ! om het te forceren"
|
||||
263 "Bestand gewijzigd sinds laatste schrijfactie; schrijf het weg of gebruik :edit! om het te forceren"
|
||||
264 "Bestand gewijzigd sinds laatste schrijfactie; schrijf het weg of gebruik ! om het te forceren"
|
||||
265 "Tijdelijk bestand; exit negeert wijzigingen"
|
||||
266 "Bestand niet schrijfbaar, wijzigingen niet automatisch weggeschreven"
|
||||
267 "log opnieuw gestart"
|
||||
268 "Bevestig? [ynq]"
|
||||
269 "Druk op een toets om door te gaan: "
|
||||
270 "Druk op een toets om door te gaan [: voor meer ex commandos]: "
|
||||
271 "Druk op een toets om door te gaan [q om te stoppen]: "
|
||||
272 "Deze vorm van %s vereist de ex terminal interface"
|
||||
273 "Entering ex input mode."
|
||||
274 "Commando mislukt, nog geen bestand geladen."
|
||||
275 " doorgaan?"
|
||||
276 "Onverwacht character event"
|
||||
277 "Onverwacht end-of-file event"
|
||||
278 "Geen match gevonden voor dit patroon"
|
||||
279 "Onverwacht interrupt event"
|
||||
280 "Onverwacht quit event"
|
||||
281 "Onverwacht repaint event"
|
||||
282 "Reeds op de laatste tag van deze groep"
|
||||
283 "Het %s command vereist de ex terminal interface"
|
||||
284 "Deze vorm van %s is niet ondersteund als de secure edit optie actief is"
|
||||
285 "Onverwacht string event"
|
||||
286 "Onverwacht timeout event"
|
||||
287 "Onverwacht write event"
|
||||
289 "Shell expansies zijn niet ondersteund als de secure edit optie actief is"
|
||||
290 "Het %s commando is niet ondersteund als de secure edit optie actief is"
|
||||
291 "set: %s mag niet uitgezet worden"
|
||||
292 "Scherm te klein."
|
||||
293 "toegevoegd"
|
||||
294 "gewijzigd"
|
||||
295 "verwijderd"
|
||||
296 "samengevoegd"
|
||||
297 "verplaatst"
|
||||
298 "verschoven"
|
||||
299 "gebufferd"
|
||||
300 "regel"
|
||||
301 "regels"
|
||||
302 "Vi was niet geladen met een Tcl interpreter"
|
||||
303 "Bestand gewijzigd sinds het de laatste keer weg is geschreven."
|
||||
304 "Shell expansie mislukt"
|
||||
305 "Geen %s edit optie opgegeven"
|
||||
306 "Vi was niet geladen met een Perl interpreter"
|
||||
307 "Geen ex commando om uit te voeren"
|
||||
308 "Kies <CR> om commando uit te voeren, :q om te stoppen"
|
||||
309 "Gebruik "cscope help" voor uitleg"
|
||||
310 "Nog geen cscope connectie aanwezig"
|
||||
311 "%s: onbekend zoek type: gebruik een van %s"
|
||||
312 "%d: onbekende cscope sessie"
|
||||
313 "set: de %s optie mag nooit aangezet worden"
|
||||
314 "set: de %s optie mag nooit op 0 gezet worden"
|
||||
315 "%s: toegevoegd: %lu regels, %lu karakters"
|
||||
316 "Onverwacht resize event"
|
||||
317 "%d bestanden te wijzigen"
|
1
dist/nvi/catalog/dutch.owner
vendored
Normal file
1
dist/nvi/catalog/dutch.owner
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
J.G. Vons <Gert-Jan.Vons@ocegr.fr>
|
1
dist/nvi/catalog/english.owner
vendored
Normal file
1
dist/nvi/catalog/english.owner
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
Keith Bostic <bostic@cs.berkeley.edu>
|
308
dist/nvi/catalog/french.base
vendored
Normal file
308
dist/nvi/catalog/french.base
vendored
Normal file
|
@ -0,0 +1,308 @@
|
|||
002 "Dépassement de longueur de ligne"
|
||||
003 "impossible de supprimer la ligne %lu"
|
||||
004 "impossible d'ajouter à la ligne %lu"
|
||||
005 "impossible d'insérer devant la ligne %lu"
|
||||
006 "impossible de stocker la ligne %lu"
|
||||
007 "impossible d'obtenir la dernière ligne"
|
||||
008 "Erreur : impossible de récupérer la ligne %lu"
|
||||
009 "Fichier journal"
|
||||
010 "Aucune journalisation n'étant effectuée, impossible d'annuler"
|
||||
011 "Aucune action à annuler"
|
||||
012 "Aucune journalisation n'étant effectuée, impossible d'annuler"
|
||||
013 "Aucune journalisation n'étant effectuée, reprise actualisée impossible"
|
||||
014 "Aucune action à refaire"
|
||||
015 "%s/%d : Erreur d'écriture de journal"
|
||||
016 "L'entrée et la sortie Vi standards doivent être un terminal"
|
||||
017 "Marque %s : non définie"
|
||||
018 "Marque %s : la ligne a été supprimée"
|
||||
019 "Marque %s : la position du curseur n'existe plus"
|
||||
020 "Erreur : "
|
||||
021 "nouveau fichier"
|
||||
022 "le nom a changé"
|
||||
023 "modifié"
|
||||
024 "non modifié"
|
||||
025 "DÉVERROUILLÉ"
|
||||
026 "lecture seule"
|
||||
027 "ligne %lu de %lu [%ld%%]"
|
||||
028 "fichier vide"
|
||||
029 "ligne %lu"
|
||||
030 "Ce fichier %s n'est pas un catalogue de messages"
|
||||
031 "Impossible de configurer option %s par défaut"
|
||||
032 "Utilisation : %s"
|
||||
033 "Définition : pas d'option %s : 'set all' donne toutes les valeurs optionnelles"
|
||||
034 "Définition : option [no]%s ne prend pas de valeur"
|
||||
035 "Définition : l'option %s n'est pas booléenne"
|
||||
036 "Définition : option %s : %s"
|
||||
037 "Définition : option %s : %s : Dépassement de valeur"
|
||||
038 "Définition : option %s : %s n'est pas un nombre valide"
|
||||
039 "Définition : l'option %s n'est pas booléenne"
|
||||
040 "Les colonnes de l'écran sont trop petites, inférieures à %d"
|
||||
041 "Les colonnes de l'écran sont trop grandes, supérieures à %d"
|
||||
042 "Les lignes de l'écran sont trop courtes, inférieures à %d"
|
||||
043 "Les lignes de l'écran sont trop longues, supérieures à %d"
|
||||
044 "L'option lisp n'est pas implémentée"
|
||||
045 "Les messages ne sont pas désactivés : %s"
|
||||
046 "Les messages ne sont pas activés : %s"
|
||||
047 "D‚finition : l'option de %s doit ˆtre en groupe de deux caractŠres"
|
||||
053 "Le tampon par défaut est vide"
|
||||
054 "Le tampon %s est vide"
|
||||
055 "Les fichiers dont le nom contient des caractères de saut de ligne sont irrécupérables"
|
||||
056 "Impossible de récupérer les modifications si la session échoue"
|
||||
057 "Copie en cours du fichier pour récupération..."
|
||||
058 "La préservation a échoué : %s"
|
||||
059 "Impossible de récupérer les modifications si la session échoue"
|
||||
060 "La sauvegarde du fichier a échoué : %s"
|
||||
061 "Copie en cours du fichier pour récupération..."
|
||||
062 "Les renseignements sur l'identité %u de l'utilisateur sont introuvables"
|
||||
063 "Impossible de verrouiller le fichier de récupération"
|
||||
064 "Débordement de tampon du fichier de récupération"
|
||||
065 "Fichier de récupération"
|
||||
066 "%s : Fichier de récupération malformé"
|
||||
067 "%s : Fichier de récupération malformé"
|
||||
068 "Aucun fichier nommé %s à récupérer, que vous puissiez lire"
|
||||
069 "Il existe des versions récupérables antérieures à ce fichier"
|
||||
070 "Vous avez d'autres fichiers à récupérer"
|
||||
071 "pas d'envoi d'email : %s"
|
||||
072 "Fichier vide, rien à rechercher"
|
||||
073 "Fin de fichier atteinte sans trouver le motif"
|
||||
074 "Pas de motif de recherche précédent"
|
||||
075 "Motif introuvable"
|
||||
076 "Début du fichier atteint sans trouver le motif"
|
||||
077 "La recherche est revenue à son point de départ"
|
||||
078 "Recherche en cours..."
|
||||
079 "Caractère non-imprimable introuvable"
|
||||
080 "Nom de commande inconnu"
|
||||
082 "%s : Commande non disponible en ex mode"
|
||||
083 "Le compteur ne peut être zéro"
|
||||
084 "%s : mauvaise spécification de ligne"
|
||||
085 "Erreur de tableau de syntaxe interne (%s: %s)"
|
||||
086 "Utilisation : %s"
|
||||
087 "%s : tampon temporaire non libéré"
|
||||
088 "Décalage de drapeau hors de la ligne 1"
|
||||
089 "Décalage de drapeau hors de la fin du fichier"
|
||||
090 "@ avec plage, en cours d'exécution quand le fichier/l'écran a changé"
|
||||
091 "Commande Global/v en cours d'exécution quand le fichier/l'écran a changé"
|
||||
092 "La commande ex a échoué : commandes en attente abandonnées"
|
||||
093 "La commande ex a échoué : les touches affectées sont abandonnées"
|
||||
094 "La deuxième adresse est plus petite que la première"
|
||||
095 "Aucun nom de marque fourni"
|
||||
096 "\\ non suivi par / ou ?"
|
||||
097 "Référence à un numéro de ligne inférieure à 0"
|
||||
098 "La commande %s est inconnue"
|
||||
099 "Dépassement de la valeur adresse"
|
||||
100 "Dépassement négatif de la valeur adresse"
|
||||
101 "Combinaison d'adresse non valide"
|
||||
102 "Adresse non valide : il n'y a que %lu lignes dans ce fichier"
|
||||
103 "Adresse non valide : le fichier est vide"
|
||||
104 "La commande %s ne permet pas une adresse de 0"
|
||||
105 "Pas d'abréviations à afficher"
|
||||
106 "Les abréviations doivent finir par un caractère"mot"
|
||||
107 "Les abréviations ne peuvent pas contenir de tabulations ni d'espaces"
|
||||
108 "Les abréviations ne peuvent pas contenir un mélange de caractères mot/non-mot, sauf à la fin"
|
||||
109 ""%s" n'est pas une abréviation"
|
||||
110 "La commande Vi a échoué : Les touches affectées ont été abandonnées"
|
||||
111 "Plus de fichiers à éditer"
|
||||
112 "Pas de fichiers précédents à éditer"
|
||||
113 "Pas de fichiers précédents à rembobiner"
|
||||
114 "Pas de liste de fichiers à afficher"
|
||||
115 "Pas de commande précédente à remplacer"!""
|
||||
116 "Pas de nom de fichier à substituer à %%"
|
||||
117 "Pas de nom de fichier à substituer à #"
|
||||
118 "Erreur : execl : %s"
|
||||
119 "Erreur E/S : %s"
|
||||
120 "Fichier modifié depuis la dernière écriture complète ; écrire ou utiliser ! pour outrepasser"
|
||||
121 "Impossible de trouver l'emplacement du répertoire d'origine"
|
||||
122 "Nouveau répertoire en cours : %s"
|
||||
123 "Pas de tampon de coupure à afficher"
|
||||
124 "La commande %s ne peut pas être utilisée à l'intérieur d'une commande globale ou commande v"
|
||||
125 "%s/%s : échec de source : ni vous ni le super-utilisateur n'êtes les propriétaires "
|
||||
126 "%s/%s : échec de source : vous n'êtes pas le propriétaire"
|
||||
127 "%s/%s : échec de source : peut être écrit par un utilisateur autre que le propriétaire"
|
||||
128 "%s : échec de source : ni vous ni le super-utilisateur n'êtes les propriétaires"
|
||||
129 "%s : échec de source : vous n'êtes pas le propriétaire"
|
||||
130 "%s : échec de source : peut être écrit par un utilisateur autre que le propriétaire"
|
||||
131 "Pas de lignes suivantes à joindre"
|
||||
132 "Pas d'entrées de mappage d'entrée"
|
||||
133 "Pas d'entrées de mappage de commandes"
|
||||
134 "Le caractère %s ne peut pas être remappé"
|
||||
135 ""%s" n'est pas actuellement mappé"
|
||||
136 "Les noms de marque ne doivent avoir qu'un caractère"
|
||||
137 "%s existe, non enregistré; utiliser ! pour outrepasser"
|
||||
138 "Nouveau fichier exrc : %s"
|
||||
139 "La ligne de destination est à l'intérieur de la plage à déplacer"
|
||||
140 "La commande ouverte nécessite que l'option ouverte soit définie"
|
||||
141 "La commande ouverte n'est pas encore implémentée"
|
||||
142 "La préservation de ce fichier est impossible"
|
||||
143 "Fichier préservé"
|
||||
144 "%s: étendu dans trop de noms de fichiers"
|
||||
145 "Vous ne pouvez lire que les fichiers standards et les canaux de transmission nommés"
|
||||
146 "%s: Interdiction de lecture non disponible"
|
||||
147 "Lecture en cours..."
|
||||
148 "%s: %lu lignes, %lu caractères"
|
||||
149 "Pas d'écrans d'arrière-plan à afficher"
|
||||
150 "La commande script n'est disponible qu'en mode vi"
|
||||
151 "Pas de commande à exécuter"
|
||||
152 "Option de largeur de décalage définie sur 0"
|
||||
153 "Compter dépassement"
|
||||
154 "Compter dépassement négatif"
|
||||
155 "Expression standard spécifiée; drapeau r superflu"
|
||||
156 "Vous ne pouvez pas en mode vi, combiner les drapeaux #, l et p avec le drapeau c"
|
||||
157 "Aucune correspondance trouvée"
|
||||
158 "Aucune marque précédente entrée"
|
||||
159 "Moins de %s entrées dans la pile de marques ; utilisez t[ags]"
|
||||
160 "Pas de fichier %s vers lequel retourner dans la pile de marques ; utiliser : affichage t[ags]"
|
||||
161 "Appuyez sur Entrée pour continuer :"
|
||||
162 "%s : marque introuvable"
|
||||
163 "%s : marque corrompue en %s"
|
||||
164 "%s : le numéro de ligne de la marque dépasse la fin du fichier"
|
||||
165 "La pile de marques est vide"
|
||||
166 "%s : motif de recherche introuvable"
|
||||
167 "%d fichiers supplémentaires à éditer"
|
||||
168 "Le tampon %s est vide
|
||||
169 "Confirmer les changements ? [n]"
|
||||
170 "Interrompu"
|
||||
171 "Pas de tampon précédent à exécuter"
|
||||
172 "Pas d'expression standard précédente"
|
||||
173 "La commande %s nécessite qu'un fichier ait déjà été lu en mémoire"
|
||||
174 "Utilisation : %s"
|
||||
175 "La commande visual nécessite que l'option open soit définie"
|
||||
177 "Fichier vide"
|
||||
178 "Pas de recherche précédente F, f, T ou t"
|
||||
179 "%s introuvable"
|
||||
180 "Pas de fichier précédent à éditer"
|
||||
181 "Le curseur n'est pas dans un nombre"
|
||||
182 "Le nombre obtenu est trop grand"
|
||||
183 "Le nombre obtenu est trop petit"
|
||||
184 "Pas de correspondance de caractère sur cette ligne"
|
||||
185 "Caractère correspondant introuvable"
|
||||
186 "Pas de caractères à remplacer"
|
||||
187 "Pas d'autre écran vers lequel basculer"
|
||||
188 "Caractères après la chaîne de recherche, décalage de ligne et/ou commande z"
|
||||
189 "Pas de motif de recherche précédent"
|
||||
190 "La recherche est revenue à son point de départ"
|
||||
191 "L'abréviation a dépassé la limite de l'expansion : caractères abandonnés"
|
||||
192 "Caractère non valide ; guillemet pour saisir"
|
||||
193 "Déjà au début de l'insertion"
|
||||
194 "Plus de caractères à effacer"
|
||||
195 "Déplacement hors de fin de fichier"
|
||||
196 "Déplacement hors de fin de ligne"
|
||||
197 "Aucun mouvement de curseur n'a été effectué"
|
||||
198 "Déjà au début du fichier"
|
||||
199 "Déplacement hors du début du fichier"
|
||||
200 "Déjà dans la première colonne"
|
||||
201 "Les tampons doivent être spécifiés avant la commande"
|
||||
202 "Déjà à la fin du fichier"
|
||||
203 "Déjà à la fin de la ligne"
|
||||
204 "%s n'est pas une commande vi"
|
||||
205 "Utilisation : %s"
|
||||
206 "Pas de caractères à supprimer"
|
||||
207 "La commande Q nécessite une interface terminal ex"
|
||||
208 "Pas de commande à répéter"
|
||||
209 "Le fichier est vide"
|
||||
209 "Le fichier est vide"
|
||||
210 "Vous ne pouvez pas utiliser %s comme commande de déplacement"
|
||||
211 "Déjà en mode commande"
|
||||
212 "Le curseur n'est pas dans un mot"
|
||||
214 "Valeur optionnelle de fenêtre trop grande, maximum est %u"
|
||||
215 "Ajouter"
|
||||
216 "Changer"
|
||||
217 "Commande"
|
||||
218 "Insérer"
|
||||
219 "Remplacer"
|
||||
220 "Déplacement hors de la fin d'écran"
|
||||
221 "Déplacement hors du début d'écran"
|
||||
222 "L'écran doit être supérieur à %d lignes pour se fractionner"
|
||||
223 "Il n'y a pas d'écran d'arrière-plan"
|
||||
224 "Il n'y a pas d'écran d'arrière-plan qui édite un fichier nommé %s"
|
||||
225 "Vous ne pouvez pas mettre à l'arrière-plan votre seul écran affiché"
|
||||
226 "L'écran ne peut être réduit qu'à %d rangs"
|
||||
227 "L'écran n'est pas auto-réductible"
|
||||
228 "L'écran n'est pas auto-extensible"
|
||||
230 "Vous ne pouvez pas mettre cet écran en attente"
|
||||
231 "Interrompu : les touches affectées ont été abandonnées"
|
||||
232 "vi : le tampon temporaire n' a pas été libéré"
|
||||
233 "Ce terminal n'a pas de touche %s"
|
||||
234 "Vous ne pouvez spécifier qu'un seul tampon"
|
||||
235 "Nombre supérieur à %lu"
|
||||
236 "Interrompu"
|
||||
237 "Impossible de créer un fichier temporaire"
|
||||
238 "Avertissement : %s n'est pas un fichier standard"
|
||||
239 "%s déjà verrouillé, session en lecture seule"
|
||||
240 "%s: supprimer"
|
||||
241 "%s: fermer"
|
||||
242 "%s: supprimer"
|
||||
243 "%s: supprimer"
|
||||
244 "Fichier en lecture seule, non écrit, utiliser ! pour outrepasser"
|
||||
245 "Fichier en lecture seule, non écrit"
|
||||
246 "%s existe, non écrit; utiliser ! pour outrepasser"
|
||||
247 "%s existe, non écrit"
|
||||
248 "Fichier partiel, non écrit; utiliser ! pour outrepasser"
|
||||
249 "Fichier partiel, non écrit"
|
||||
250 "%s: fichier modifié plus récemment que cet exemplaire; utiliser ! pour outrepasser"
|
||||
251 "%s: fichier modifié plus récemment que cet exemplaire"
|
||||
252 "%s: interdiction d'écriture non disponible"
|
||||
253 "Ecriture en cours..."
|
||||
254 "%s: AVERTISSEMENT : FICHIER TRONQUÉ"
|
||||
255 "Première marque de ce groupe déjà atteinte"
|
||||
256 "%s: nouveau fichier : %lu lignes, %lu caractères"
|
||||
257 "%s: %lu lignes, %lu caractères"
|
||||
258 "%s étendue à trop de noms de fichiers"
|
||||
259 "%s: pas un fichier standard"
|
||||
260 "%s: ne vous appartient pas"
|
||||
261 "%s: accessible par un utilisateur autre que son propriétaire"
|
||||
262 "Fichier modifé depuis la dernière écriture complète ; écrire ou utiliser ! pour outrepasser "
|
||||
263 "Fichier modifé depuis la dernière écriture complète ; écrire ou utiliser :edit! pour outrepasser"
|
||||
264 "Fichier modifé depuis la dernière écriture complète ; écrire ou utiliser ! pour outrepasser"
|
||||
265 "Fichier temporaire ; quitter annulera les modifications"
|
||||
266 "Fichier en lecture seule ; les modifications ne sont pas écrites automatiquement"
|
||||
267 "Journal redémarré"
|
||||
268 "confirmer ? [ynq]"
|
||||
269 "Appuyez sur n'importe quelle touche pour continuer : "
|
||||
270 "Appuyez sur n'importe quelle touche pour continuer [: pour entrer plus de commandes ex] : "
|
||||
271 "Appuyez sur n'importe quelle touche pour continuer [q pour Quitter]: "
|
||||
272 "Cette forme de %s nécessite l'interface de terminal ex"
|
||||
273 "Entrée de mode entrée ex."
|
||||
274 "La commande a échoué, aucun fichier n'a encore été lu."
|
||||
275 "cont?"
|
||||
276 "Evénement imprévu de caractère"
|
||||
277 "Evénement imprévu de fin-de-fichier"
|
||||
278 "Pas de correspondances pour cette requête"
|
||||
279 "Evénement imprévu d'interruption"
|
||||
280 "Evénement quitter imprévu"
|
||||
281 "Evénement imprévu de rafraîchissement"
|
||||
282 "La dernière marque de ce groupe a déjà été atteinte"
|
||||
283 "La commande %s nécessite l'interface de terminal ex"
|
||||
284 "Cette forme de %s n'est pas reconnue quand l'option d'édition protégée est activée"
|
||||
285 "Evénement imprévu de chaîne"
|
||||
286 "Evénement imprévu de délai imparti"
|
||||
287 "Evénement d'écriture imprévu"
|
||||
289 "Les expansions du shell ne sont pas reconnues quand l'option d'édition protégée est activée"
|
||||
290 "La commande %s n'est pas reconnue quand l'option d'édition protégée est activée"
|
||||
291 "Définition : l'option %s ne peut pas être désactivée"
|
||||
292 "Affichage trop petit."
|
||||
293 "ajouté"
|
||||
294 "changé"
|
||||
295 "supprimé"
|
||||
296 "joint"
|
||||
297 "déplacé"
|
||||
298 "décalé"
|
||||
299 "coupé"
|
||||
300 "ligne"
|
||||
301 "lignes"
|
||||
302 "Vi n'a pas été chargé avec un interprétateur Tcl"
|
||||
303 "Ficher modifié depuis le dernier enregistrement."
|
||||
304 "L'expansion du shell a échoué"
|
||||
304 "L'expansion du shell a échoué"
|
||||
305 "Pas d'option d'édition %s spécifiée"
|
||||
306 "Vi n'a pas été chargé avec un interprétateur Perl"
|
||||
307 "Pas de commande ex à exécuter"
|
||||
308 "Entrez <CR> pour exécuter une commande, :q pour quitter"
|
||||
309 "Utiliser "cscope help" pour obtenir de l'aide"
|
||||
310 "Aucune connexion cscope n'est lancée"
|
||||
311 "%s : type de recherche inconnu : utiliser un des %s"
|
||||
312 "%d : Il n'existe pas de telle session cscope"
|
||||
313 "Définition : l'option %s ne peut jamais être activée"
|
||||
314 "Définition : l'option %s ne peut jamais être définie sur 0"
|
||||
315 "%s: joints : %lu lignes, %lu caractères"
|
||||
316 "événement imprévu de redimensionnement"
|
||||
317 "%d fichiers à éditer"
|
306
dist/nvi/catalog/german.base
vendored
Normal file
306
dist/nvi/catalog/german.base
vendored
Normal file
|
@ -0,0 +1,306 @@
|
|||
002 "Zeilenlängen-Überlauf"
|
||||
003 "kann Zeile %lu nicht löschen"
|
||||
004 "kann an Zeile %lu nicht anfügen"
|
||||
005 "kann in Zeile %lu nicht einfügen"
|
||||
006 "kann Zeile %lu nicht speichern"
|
||||
007 "kann letzte Zeile nicht lesen"
|
||||
008 "Fehler: kann Zeile %lu nicht wiederherstellen"
|
||||
009 "Protokolldatei"
|
||||
010 "Keine Protokollierung aktiv, Rückgängigmachen nicht möglich"
|
||||
011 "Keine Änderungen rückgängig zu machen"
|
||||
012 "Keine Protokollierung aktiv, Rückgängigmachen nicht möglich"
|
||||
013 "Keine Protokollierung aktiv, Wiederholung von Änderungen nicht möglich"
|
||||
014 "Keine Änderungen zu wiederholen"
|
||||
015 "%s/%d: Protokollschreibfehler"
|
||||
016 "Vi's Standardein- und -ausgabe muß ein Terminal sein"
|
||||
017 "Marke %s: nicht gesetzt"
|
||||
018 "Marke %s: die Zeile wurde gelöscht"
|
||||
019 "Marke %s: Cursorposition existiert nicht mehr"
|
||||
020 "Fehler: "
|
||||
021 "neue Datei"
|
||||
022 "Name geändert"
|
||||
023 "geändert"
|
||||
024 "nicht geändert"
|
||||
025 "NICHT GELOCKT"
|
||||
026 "nur zum Lesen"
|
||||
027 "Zeile %lu von %lu [%ld%%]"
|
||||
028 "leere Datei"
|
||||
029 "Zeile %lu"
|
||||
030 "Die Datei %s ist kein Meldungskatalog"
|
||||
031 "Setzen der Voreinstellung für %s Option nicht möglich"
|
||||
032 "Benutzung: %s"
|
||||
033 "set: keine %s Option: 'set all' zeigt alle Optionen mit Werten an"
|
||||
034 "set: der [no]%s Option kann kein Wert zugewiesen werden"
|
||||
035 "set: %s ist keine Boolsche Option"
|
||||
036 "set: %s Option: %s"
|
||||
037 "set: %s Option: %s: Werte-Überlauf"
|
||||
038 "set: %s Option: %s ist eine ungültige Zahl"
|
||||
039 "set: %s ist keine Boolsche Option"
|
||||
040 "Bildschirm hat zu wenig Spalten, weniger als %d"
|
||||
041 "Bildschirm hat zu viele Spalten, mehr als %d"
|
||||
042 "Bildschirm hat zu wenig Zeilen, weniger als %d"
|
||||
043 "Bildschirm hat zu viele Zeilen, mehr als %d"
|
||||
044 "Die lisp-Option ist nicht implementiert"
|
||||
045 "Meldungen nicht abgeschaltet: %s"
|
||||
046 "Meldungen nicht eingeschaltet: %s"
|
||||
047 "set: Die %s Option muss Gruppen zu zwei Zeichen enthalten"
|
||||
053 "Der Standardpuffer ist leer"
|
||||
054 "Puffer %s ist leer"
|
||||
055 "Dateien mit newlines im Namen sind nicht wiederherstellbar"
|
||||
056 "Änderungen nicht wiederherstellbar, falls die Editorsitzung schiefgeht"
|
||||
057 "kopiere Datei für Wiederherstellung ..."
|
||||
058 "Rettungsmechanismus funktioniert nicht: %s"
|
||||
059 "Änderungen nicht wiederherstellbar, falls die Editorsitzung schiefgeht"
|
||||
060 "Sicherung der Datei gescheitert: %s"
|
||||
061 "kopiere Datei für Wiederherstellung ..."
|
||||
062 "Informationen über den Benutzer mit id %u nicht gefunden"
|
||||
063 "Wiederherstellungsdatei kann nicht gelockt werden"
|
||||
064 "Puffer der Wiederherstellungsdatei übergelaufen"
|
||||
065 "Wiederherstellungsdatei"
|
||||
066 "%s: Wiederherstellungsdatei hat falsches Format"
|
||||
067 "%s: Wiederherstellungsdatei hat falsches Format"
|
||||
068 "Keine von Ihnen lesbaren Dateien mit Namen %s zum Wiederherstellen"
|
||||
069 "Es gibt ältere Versionen dieser Datei von Ihnen zum Wiederherstellen"
|
||||
070 "Sie haben noch andere Dateien zum Wiederherstellen"
|
||||
071 "schicke keine email: %s"
|
||||
072 "Datei leer; nichts zu suchen"
|
||||
073 "Dateiende erreicht, ohne das Suchmuster zu finden"
|
||||
074 "Kein altes Suchmuster"
|
||||
075 "Suchmuster nicht gefunden"
|
||||
076 "Dateianfang erreicht, ohne das Suchmuster zu finden"
|
||||
077 "Suche beginnt von vorn"
|
||||
078 "suche ..."
|
||||
079 "Keine nichtdruckbaren Zeichen gefunden"
|
||||
080 "Unbekannter Kommandoname"
|
||||
082 "%s: Kommando im ex-Modus nicht verfügbar"
|
||||
083 "Anzahl darf nicht Null sein"
|
||||
084 "%s: falsche Zeilenangabe"
|
||||
085 "Interner Syntaxtabellenfehler (%s: %s)"
|
||||
086 "Benutzung: %s"
|
||||
087 "%s: temporärer Puffer nicht freigegeben"
|
||||
088 "Flagoffset vor Zeile 1"
|
||||
089 "Flagoffset hinter dem Dateiende"
|
||||
090 "@ mit Bereich lief, als Datei/Anzeige geändert wurde"
|
||||
091 "globales oder v-Kommando lief, als Datei/Anzeige geändert wurde"
|
||||
092 "Ex-Kommando mißlungen: restliche Kommandoeingabe ignoriert"
|
||||
093 "Ex-Kommando mißlungen: umdefinierte Tasten ungültig"
|
||||
094 "Die zweite Adresse ist kleiner als die erste"
|
||||
095 "Kein Markenname angegeben"
|
||||
096 "\\ ohne folgenden / oder ?"
|
||||
097 "Referenz auf eine negative Zeilennummer"
|
||||
098 "Das Kommando %s ist unbekannt"
|
||||
099 "Adreßwert zu groß"
|
||||
100 "Adreßwert zu klein"
|
||||
101 "Ungültige Adreßkombination"
|
||||
102 "Ungültige Adresse: nur %lu Zeilen in der Datei"
|
||||
103 "Ungültige Adresse: die Datei ist leer"
|
||||
104 "Das Kommando %s erlaubt keine Adresse 0"
|
||||
105 "Keine Abkürzungen zum Anzeigen"
|
||||
106 "Abkürzungen müssen mit einem "Wort"-Zeichen enden"
|
||||
107 "Abkürzungen dürfen keine Tabulator- oder Leerzeichen enthalten"
|
||||
108 "In Abkürzungen dürfen außer am Ende Wort- und Nicht-Wort-Zeichen nicht gemischt werden"
|
||||
109 ""%s" ist keine Abkürzung"
|
||||
110 "Vi Kommando mißlungen: umdefinierte Tasten ungültig"
|
||||
111 "Keine weiteren Dateien zu editieren"
|
||||
112 "Keine vorhergehenden Dateien zu editieren"
|
||||
113 "Keine vorhergehenden Dateien für rewind"
|
||||
114 "Keine Dateiliste zum Anzeigen"
|
||||
115 "Kein vorhergehendes Kommando, um "!" zu ersetzen"
|
||||
116 "Kein Dateiname für %%"
|
||||
117 "Kein Dateiname für #"
|
||||
118 "Fehler: execl: %s"
|
||||
119 "E/A-Fehler: %s"
|
||||
120 "Datei wurde seit dem letzten vollständigen Schreiben geändert; schreibe oder verwende ! zum ignorieren"
|
||||
121 "Kann Homedirectory nicht bestimmen"
|
||||
122 "Neues aktuelles Directory: %s"
|
||||
123 "Keine Puffer anzuzeigen"
|
||||
124 "Das Kommando %s kann nicht als Teil eines global oder v Kommandos verwendet werden"
|
||||
125 "%s/%s: nicht gelesen: gehört weder Ihnen noch root"
|
||||
126 "%s/%s: nicht gelesen: gehört nicht Ihnen"
|
||||
127 "%s/%s: nicht gelesen: anderer Benutzer als Eigentümer hat Schreibrecht"
|
||||
128 "%s: nicht gelesen: gehört weder Ihnen noch root"
|
||||
129 "%s: nicht gelesen: gehört nicht Ihnen"
|
||||
130 "%s: nicht gelesen: anderer Benutzer als Eigentümer hat Schreibrecht"
|
||||
131 "Keine folgenden Zeilen zum Verbinden"
|
||||
132 "Kein input-Map Eintrag"
|
||||
133 "Kein command-Map Eintrag"
|
||||
134 "Das %s Zeichen kann nicht umgemappt werden"
|
||||
135 ""%s" ist momentan nicht gemappt"
|
||||
136 "Markennamen müssen einzelne Buchstaben sein"
|
||||
137 "%s existiert, nicht geschrieben; verwende ! zum Überschreiben"
|
||||
138 "Neue .exrc Datei: %s. "
|
||||
139 "Zielzeile ist innerhalb des Verschiebebereichs"
|
||||
140 "Das open Kommando verlangt, daß die open Option gesetzt ist"
|
||||
141 "Das open Kommando ist nocht nicht implementiert"
|
||||
142 "Rettung dieser Datei nicht möglich"
|
||||
143 "Datei gerettet"
|
||||
144 "%s wurde in zu viele Dateinamen expandiert"
|
||||
145 "Nur reguläre Dateien und named pipes können gelesen werden"
|
||||
146 "%s: Locken zum Lesen war nicht möglich"
|
||||
147 "lese ..."
|
||||
148 "%s: %lu Zeilen, %lu Zeichen"
|
||||
149 "Keine Hintergrundanzeigen vorhanden"
|
||||
150 "Das script Kommando ist nur im vi Modus verfügbar"
|
||||
151 "Kein Kommando auszuführen"
|
||||
152 "shiftwidth Option auf 0 gesetzt"
|
||||
153 "Anzahl-Überlauf"
|
||||
154 "Anzahl-Unterlauf"
|
||||
155 "Regulärer Ausdruck angegeben; r Flag bedeutungslos"
|
||||
156 "Die #, l und p Flags können im vi Modus nicht mit dem c Flag kombiniert werden"
|
||||
157 "Keine Übereinstimmung gefunden"
|
||||
158 "Kein vorhergehender 'tag' angegeben"
|
||||
159 "Weniger als %s Einträge auf dem 'tag'-Stack; verwende :display t[ags]"
|
||||
160 "Keine Datei namens %s auf dem 'tag'-Stack; verwende :display t[ags]"
|
||||
161 "Drücke Enter um fortzufahren: "
|
||||
162 "%s: 'tag' nicht gefunden"
|
||||
163 "%s: kaputter 'tag' in %s"
|
||||
164 "%s: die Zeilennummer des 'tag' ist hinter dem Dateiende"
|
||||
165 "Der 'tag' Stack ist leer"
|
||||
166 "%s: Suchmuster nicht gefunden"
|
||||
167 "%d weitere Dateien zu editieren"
|
||||
168 "Puffer %s ist leer"
|
||||
169 "Bestätige Änderung [n]"
|
||||
170 "Unterbrochen."
|
||||
171 "Kein vorhergehender Puffer zum Ausführen"
|
||||
172 "Kein vorhergehender regulärer Ausdruck"
|
||||
173 "Das Kommando %s verlangt, daß bereits eine Datei eingelesen wurde"
|
||||
174 "Benutzung: %s"
|
||||
175 "Das visual Kommando verlangt daß die open Option gesetzt ist"
|
||||
177 "Leere Datei"
|
||||
178 "Keine vorhergehende F, f, T oder t Suche"
|
||||
179 "%s nicht gefunden"
|
||||
180 "Keine vorhergehende Datei zu editieren"
|
||||
181 "Cursor nicht auf einer Zahl"
|
||||
182 "Sich ergebende Zahl ist zu groß"
|
||||
183 "Sich ergebende Zahl ist zu klein"
|
||||
184 "Kein korrespondierendes Zeichen in dieser Zeile"
|
||||
185 "Korrespondierendes Zeichen nicht gefunden"
|
||||
186 "Keine Zeichen zu ersetzen"
|
||||
187 "Keine andere Anzeige zum Hinschalten"
|
||||
188 "Zeichen nach Suchmuster, Zeilenoffset und/oder z Kommando"
|
||||
189 "Kein altes Suchmuster"
|
||||
190 "Suche zur ursprünglichen Position zurückgekehrt"
|
||||
191 "Abkürzung überschreitet Expansionsgrenze: Zeichen weggelassen"
|
||||
192 "Nicht erlaubtes Zeichen; maskiere zum Eingeben"
|
||||
193 "Bereits am Anfang der Eingabe"
|
||||
194 "Keine weiteren Zeichen zu löschen"
|
||||
195 "Bewegung hinter das Dateiende"
|
||||
196 "Bewegung hinter das Zeilenende"
|
||||
197 "Keine Cursorbewegung gemacht"
|
||||
198 "Bereits am Dateianfang"
|
||||
199 "Bewegung vor den Dateianfang"
|
||||
200 "Bereits in der ersten Spalte"
|
||||
201 "Puffer sollen vor dem Kommando angegeben werden"
|
||||
202 "Bereits am Dateiende"
|
||||
203 "Bereits am Zeilenende"
|
||||
204 "%s ist kein vi Kommando"
|
||||
205 "Benutzung: %s"
|
||||
206 "Keine Zeichen zu löschen"
|
||||
207 "Das Q Kommando benötigt das ex Terminal Interface"
|
||||
208 "Kein Kommando zu wiederholen"
|
||||
209 "Die Datei ist leer"
|
||||
210 "%s kann nicht als Bewegungskommando verwendet werden"
|
||||
211 "Bereits im Kommando-Modus"
|
||||
212 " Cursor nicht auf einem Wort"
|
||||
214 "Wert der Window Option ist zu groß, max ist %u"
|
||||
215 "Anhängen"
|
||||
216 "Ändern"
|
||||
217 "Kommando"
|
||||
218 "Einfügen"
|
||||
219 "Ersetzen"
|
||||
220 "Bewegung hinter das Anzeigenende"
|
||||
221 "Bewegung vor den Anzeigenanfang"
|
||||
222 "Anzeige muß für Bildschirmteilung größer als %d sein"
|
||||
223 "Keine Hintergrundanzeigen vorhanden"
|
||||
224 "Es gibt keine Hintergrundanzeige, die eine Datei namens %s editiert"
|
||||
225 "Die einzige dargestellte Anzeige kann nicht in den Hintergrund gebracht werden"
|
||||
226 "Die Anzeige kann nur auf %d Zeilen verkleinert werden"
|
||||
227 "Die Anzeige kann nicht verkleinert werden"
|
||||
228 "Die Anzeige kann nicht vergrößert werden"
|
||||
230 "Diese Anzeige kann nicht gestopt werden"
|
||||
231 "Unterbrochen: umdefinierte Tasten ungültig"
|
||||
232 "vi: temporärer Puffer nicht freigegeben"
|
||||
233 "Dieses Terminal hat keine %s Taste"
|
||||
234 "es kann nur ein Puffer angegeben werden"
|
||||
235 "Zahl größer als %lu"
|
||||
236 "Unterbrochen"
|
||||
237 "Nicht möglich, temporäre Datei anzulegen"
|
||||
238 "Warnung: %s ist keine reguläre Datei"
|
||||
239 "%s ist bereits gelockt, Editorsitzung schreibgeschützt"
|
||||
240 "%s: löschen"
|
||||
241 "%s: schließen"
|
||||
242 "%s: löschen"
|
||||
243 "%s: löschen"
|
||||
244 "Datei nicht schreibbar, nicht geschrieben; verwende ! zum Überschreiben"
|
||||
245 "Datei nicht schreibbar, nicht geschrieben"
|
||||
246 "%s existiert, nicht geschrieben; verwende ! zum Überschreiben"
|
||||
247 "%s existiert, nicht geschrieben"
|
||||
248 "Teil der Datei, nicht geschrieben; verwende ! zum Überschreiben"
|
||||
249 "Teil der Datei, nicht geschrieben"
|
||||
250 "%s: Datei wurde später als diese Kopie verändert; verwende ! zum Überschreiben"
|
||||
251 "%s: Datei wurde später als diese Kopie verändert"
|
||||
252 "%s: Locken zum Schreiben war nicht möglich"
|
||||
253 "schreibe ..."
|
||||
254 "%s: WARNUNG: DATEI ABGESCHNITTEN"
|
||||
255 "Bereits am ersten 'tag' dieser Gruppe"
|
||||
256 "%s: neue Datei: %lu Zeilen, %lu Zeichen"
|
||||
257 "%s: %lu Zeilen, %lu Zeichen"
|
||||
258 "%s wurde in zu viele Dateinamen expandiert"
|
||||
259 "%s: keine reguläre Datei"
|
||||
260 "%s: gehört nicht Ihnen"
|
||||
261 "%s: anderer Benutzer als Eigentümer hat Zugriff"
|
||||
262 "Datei wurde seit dem letzten vollständigen Schreiben geändert; schreibe oder verwende ! zum ignorieren"
|
||||
263 "Datei wurde seit dem letzten vollständigen Schreiben geändert; schreibe oder verwende :edit! zum ignorieren"
|
||||
264 "Datei wurde seit dem letzten vollständigen Schreiben geändert; schreibe oder verwende ! zum ignorieren"
|
||||
265 "Datei ist temporär; beim Verlassen gehen die Änderungen verloren"
|
||||
266 "Datei ist schreibgeschützt, Änderungen werden nicht automatisch geschrieben"
|
||||
267 "Portokollierung neu begonnen"
|
||||
268 "bestätigen [ynq]"
|
||||
269 "Drücke beliebige Taste um fortzufahren"
|
||||
270 "Drücke beliebige Taste um fortzufahren [: um weitere Kommandos einzugeben]: "
|
||||
271 "Drücke beliebige Taste um fortzufahren [q zum Verlassen]: "
|
||||
272 "Diese Form von %s benötigt das ex Terminal-Interface"
|
||||
273 "Gehe in ex Eingabe-Modus.\n"
|
||||
274 "Kommando schiefgelaufen, noch keine Datei eingelesen"
|
||||
275 " weiter?"
|
||||
276 "unerwartetes Zeichen - Ereignis"
|
||||
277 "unerwartetes Dateiende - Ereignis"
|
||||
278 "Keine Position zum Anspringen gefunden"
|
||||
279 "unerwartetes Unterbrechungs - Ereignis"
|
||||
280 "unerwartetes Verlassen - Ereignis"
|
||||
281 "unerwartetes Wiederherstellungs - Ereignis"
|
||||
282 "Bereits am letzten 'tag' dieser Gruppe"
|
||||
283 "Das %s Kommando benötigt das ex Terminal-Interface"
|
||||
284 "Diese Form von %s wird nicht unterstützt wenn die 'secure edit' - Option gesetzt ist"
|
||||
285 "unerwartetes Zeichenketten - Ereignis"
|
||||
286 "unerwartetes timeout - Ereignis"
|
||||
287 "unerwartetes Schreibe - Ereignis"
|
||||
289 "Shell Expandierungen nicht unterstützt wenn die 'secure edit' - Option gesetzt ist"
|
||||
290 "Das %s Kommando wird nicht unterstützt wenn die 'secure edit' - Option gesetzt ist"
|
||||
291 "set: %s kann nicht ausgeschaltet werden"
|
||||
292 "Anzeige zu klein."
|
||||
293 "angefügt"
|
||||
294 "geändert"
|
||||
295 "gelöscht"
|
||||
296 "verbunden"
|
||||
297 "verschoben"
|
||||
298 "geschoben"
|
||||
299 "in Puffer geschrieben"
|
||||
300 "Zeile"
|
||||
301 "Zeilen"
|
||||
302 "Vi wurde nicht mit dem Tcl Interpreter gelinkt"
|
||||
303 "Datei wurde seit dem letzten Schreiben verändert."
|
||||
304 "Shell Expansion hat nicht geklappt"
|
||||
305 "Es ist keine %s Editieroption angegeben"
|
||||
306 "Vi wurde nicht mit einem Perl Interpreter geladen"
|
||||
307 "Kein ex Kommando auszuführen"
|
||||
308 "Drücke <CR> um ein Kommando auszuführen, :q zum verlassen"
|
||||
309 "Verwende "cscope help" für Hilestellung"
|
||||
310 "Keine cscope Verbindung aktiv"
|
||||
311 "%s: unbekannter Suchtyp: verwende einen aus %s"
|
||||
312 "%d: keine solche cscope Verbindung"
|
||||
313 "set: die %s Option kann nicht eingeschaltet werden"
|
||||
314 "set: die %s Option kann nicht auf 0 gesetzt werden"
|
||||
315 "%s: angefügt: %lu Zeilen, %lu Zeichen"
|
||||
316 "unerwartetes Größenveränderungs - Ereignis"
|
||||
317 "%d Dateien zu edieren"
|
2
dist/nvi/catalog/german.owner
vendored
Normal file
2
dist/nvi/catalog/german.owner
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
Bernhard Daeubler <daeb@physik.uni-ulm.de>
|
||||
Joerg Wunsch <joerg_wunsch@uriah.heep.sax.de>
|
214
dist/nvi/catalog/ru_RU.KOI8-R.base
vendored
Normal file
214
dist/nvi/catalog/ru_RU.KOI8-R.base
vendored
Normal file
|
@ -0,0 +1,214 @@
|
|||
002 "Переполнение значения длины строки"
|
||||
003 "невозможно удалить строку %lu"
|
||||
004 "невозможно добавить к строке %lu"
|
||||
005 "невозможно вставить в строку %lu"
|
||||
006 "невозможно сохранить строку %lu"
|
||||
007 "невозможно достать последнюю строку"
|
||||
009 "Файл записей"
|
||||
010 "Записи не велись, невозможно отменить последнюю команду"
|
||||
011 "Нет изменений для отмены"
|
||||
012 "Записи не велись, невозможно отменить последнюю команду"
|
||||
013 "Записи не велись, невозможно просмотреть вперед"
|
||||
014 "Нет изменений для переделки"
|
||||
015 "%s/%d: ошибка при записи протокола"
|
||||
016 "Стандартный ввод/вывод для VI должен быть терминал"
|
||||
017 "Отметка %s: не установлена"
|
||||
018 "Отметка %s: строка была удалена"
|
||||
019 "Отметка %s: позиции курсора больше не существует"
|
||||
020 "Ошибка: "
|
||||
030 "Файл %s не является каталогом сообщений"
|
||||
031 "Невозможно установить опцию %s по умолчанию"
|
||||
032 "Использование: %s"
|
||||
033 "Опции %s нет: 'set all' показывает все возможные опции"
|
||||
034 "set: [no]%s не принимает такого значения"
|
||||
035 "set: %s опция не является логической"
|
||||
038 "set: неправильное значение %s"
|
||||
039 "set: %s опция не является логической"
|
||||
040 "Количество колонок экрана слишком мало, меньше чем %d"
|
||||
041 "Количество колонок экрана слишком велико, больше чем %d"
|
||||
042 "Количество строк экрана слишком мало, меньше чем %d"
|
||||
043 "Количество строк экрана слишком велико, больше чем %d"
|
||||
044 "Опция lisp отсутствует"
|
||||
045 "Сообщения не выключены: %s"
|
||||
046 "Сообщения не включены: %s"
|
||||
048 "Опция paragraph должна состоять из групп с двумя символами"
|
||||
049 "Опция section должна состоять из групп с двумя символами"
|
||||
053 "Стартовый буфер пуст"
|
||||
054 "Буфер %s пуст"
|
||||
055 "Файлы с символами перевода строки в имени не могут быть восстановлены"
|
||||
056 "Изменения не сохранены при крахе сессии"
|
||||
058 "Сохранение не удалось: %s"
|
||||
059 "Изменения не сохраняются при обрыве сессии"
|
||||
060 "Сохранение копии файла не удалось: %s"
|
||||
062 "Информации на пользователя %u не найдено"
|
||||
063 "Невозможно защитить спасенный файл"
|
||||
064 "Буфер восстановленного файла переполнен"
|
||||
065 "Восстановленный файл"
|
||||
066 "%s: не до конца восстановленный файл"
|
||||
067 "%s: не до конца восстановленный файл"
|
||||
068 "Файлов с именем %s, которые Вы можете читать, не существует"
|
||||
069 "Есть старые версии файла, которые можно восстановить"
|
||||
070 "Существуют другие файлы, которые можно восстановить"
|
||||
071 "е-mail не послан: %s"
|
||||
072 "Файл пуст - искать нечего"
|
||||
073 "Достигнут конец файла без нахождения образца поиска"
|
||||
074 "Не задан образец поиска"
|
||||
075 "Образец поиска не найден"
|
||||
076 "Доступно начало файла без нахождения образца поиска"
|
||||
077 "Поиск зациклен"
|
||||
079 "Непечатных символов не найдено"
|
||||
080 "Неизвестная команда"
|
||||
082 "%s: команда не доступна в режиме ex"
|
||||
083 "Счетчик не может быть нулем"
|
||||
084 "%s: неправильное указание строки"
|
||||
085 "Внутренняя ошибка в синтаксисе (%s: %s)"
|
||||
086 "Использование: %s"
|
||||
087 "%s: временный буфер не использован"
|
||||
088 "Метка поставлена перед строкой 1"
|
||||
089 "Метка поставлена после конца файла"
|
||||
092 "Команда ex не удалась: последующие команды забыты"
|
||||
094 "Второй адрес меньше чем первый"
|
||||
095 "Не указано название отметки"
|
||||
096 "\\ не завершается / или ?"
|
||||
097 "Ссылка к строке с номером меньше 0"
|
||||
098 "Команда %s неизвестна"
|
||||
099 "Переполнение значения адреса"
|
||||
100 "Недобор значения адреса"
|
||||
101 "Недопустимая комбинация в адресе"
|
||||
102 "Неправильный адрес: всего %lu строк в файле"
|
||||
103 "Неправильный адрес: файл пуст"
|
||||
104 "Комманда %s не может использовать адрес 0"
|
||||
105 "Аббревиатуры отсутствуют"
|
||||
106 "Аббревиатуры должны заканчиваться символом "word""
|
||||
107 "Аббревиатуры не могут содержать символоы табляции или пробелы"
|
||||
108 "Аббревиатуры не могут сочетаться с символами слов/не-слов, за исключением конца строки"
|
||||
109 ""%s" не является аббревиатурой"
|
||||
111 "Файлов для редактирования больше нет"
|
||||
112 "Отсутствие предыдущего файла для редактирования"
|
||||
113 "Отсутствие предыдущего файла для просмотра назад"
|
||||
114 "Нет файлов"
|
||||
115 "Отсутствие предыдущей команды для замены "!""
|
||||
116 "Отсутствие замены для %%"
|
||||
117 "Отсутствие замены для #"
|
||||
118 "Ошибка: execl: %s"
|
||||
119 "Ошибка ввода/вывода: %s"
|
||||
120 "Файл изменен с момента последней полной записи: используйте ! для обхода"
|
||||
121 "Невозможно найти домашний каталог"
|
||||
122 "Новый каталог: %s"
|
||||
123 "Нет вырезаных буферов"
|
||||
124 "Команда %s не может быть использована внутри глобальной или v команды"
|
||||
125 "%s/%s: не открыт: не принадлежит Вам или root-у"
|
||||
126 "%s/%s: не открыт: не принадлежит Вам"
|
||||
127 "%s/%s: не открыт: возможность записи у пользователя, не являющегося владельцем"
|
||||
128 "%s: не считан: не принадлежит Вам или root-у"
|
||||
129 "%s: не считан: не принадлежит Вам"
|
||||
130 "%s: не считан: возможность записи у пользователя, не являющегося владельцем"
|
||||
131 "Последующие строки отсутствуют"
|
||||
132 "Отсутствие параметров ввода"
|
||||
133 "Отсутствие параметров команды"
|
||||
134 "Символ %s не может быть переназначен"
|
||||
135 ""%s" на данный момент не назначен"
|
||||
136 "Имя метки должно быть одним символом"
|
||||
137 "%s существует, не записан; используйте ! для обхода"
|
||||
138 "Новый файл exrc: %s"
|
||||
139 "Строка переноса находится внутри параметров переноса"
|
||||
140 "Команда open подразумевает установку опции open"
|
||||
141 "Команда open не реализована"
|
||||
142 "Защита файла невозможна"
|
||||
143 "Файл защищен"
|
||||
144 "%s расширился в слишком большое количество имен файлов"
|
||||
146 "%s: защита на чтение была недоступна"
|
||||
148 "%s: %lu строк, %lu символов"
|
||||
149 "Нет теневых окон"
|
||||
150 "Команда script используется только в режиме vi"
|
||||
151 "Нет команды для исполнения"
|
||||
152 "Опция shiftwidth установлена на 0"
|
||||
153 "Переполнение счетчика"
|
||||
154 "Цикл выполнен не до конца"
|
||||
155 "Указано регулярное выражение: флаг r не нужен"
|
||||
156 "Флаги #, l и p не могут быть объединены с флагом c в режиме vi"
|
||||
157 "Совпадений нет"
|
||||
158 "Метка отсутствует"
|
||||
159 "В стеке меток записей меньше, чем %s, используйте :display t[ags]"
|
||||
160 "Файла с именем %s в стеке меток нет; используйте :display t[ags]"
|
||||
162 "%s: метка не найдена"
|
||||
163 "%s: плохая метка в %s"
|
||||
165 "Стек меток пуст"
|
||||
166 "%s: образец поиска не найден"
|
||||
168 "Буфер %s пуст"
|
||||
170 "Прервано"
|
||||
171 "Отсутствие буфера для использования"
|
||||
172 "Нет предидущего регулярного выражения"
|
||||
173 "Команда %s подразумевает наличие прочтенного файла"
|
||||
174 "Использование: %s"
|
||||
175 "Команда visual подразумевает обязательную установку опции open"
|
||||
177 "Пустой файл"
|
||||
178 "Нет предыдущего поиска F, f, T, или t"
|
||||
179 "%s не найдено"
|
||||
180 "Нет предыдущего файла для редактирования"
|
||||
181 "Курсор стоит не на цифре"
|
||||
182 "Полученное число слишком велико"
|
||||
183 "Полученное число слишком мало"
|
||||
184 "Подходящего символа нет на этой строке"
|
||||
185 "Подходящий символ не найден"
|
||||
186 "Нет символов для удаления"
|
||||
187 "Другого экрана не существует"
|
||||
188 "Символы после строки для поиска, смещения строки и/или команды z"
|
||||
189 "Прошлый образец поиска отсутствует"
|
||||
190 "Поиск завершился на начальной позиции"
|
||||
192 "Символ неправилен; квотируйте для ввода"
|
||||
193 "Уже на начале вставки"
|
||||
194 "Нет символов для удаления"
|
||||
195 "Передвижение за конец файла"
|
||||
196 "Передвижение за конец строки"
|
||||
197 "Движение строки не сделано"
|
||||
198 "Уже на начале файла"
|
||||
199 "Движение курсора за начало файла"
|
||||
200 "Уже в первой колонке"
|
||||
201 "Буферы должны быть указаны до выполнения команды"
|
||||
202 "Уже на конце файла"
|
||||
203 "Уже на конце строки"
|
||||
204 "%s не является командой VI"
|
||||
205 "Использование: %s"
|
||||
206 "Нет символов для удаления"
|
||||
208 "Нет команды для повтора"
|
||||
210 "Команда %s не может быть использована как команда перемещения"
|
||||
211 "Уже в командном режиме"
|
||||
214 "Значение опции windows слишком велико, максимальное значение = %u"
|
||||
220 "Движение курсора за конец экрана"
|
||||
221 "Движение курсора за начало экрана"
|
||||
223 "Теневых окон нет"
|
||||
224 "Не существует теневого окна с редактированием файла %s"
|
||||
225 "Вы не можете сделать единственное окно теневым"
|
||||
226 "Экран может быть сжат"
|
||||
227 "Экран не может быть сжат только до %d строк"
|
||||
228 "Экран не может быть расширен"
|
||||
233 "Данный тип терминала не имеет клавиши %s"
|
||||
237 "Невозможно создать временный файл"
|
||||
238 "Внимание: %s специальный файл"
|
||||
239 "%s уже заблокирован, доступен только на чтение"
|
||||
240 "%s: удален"
|
||||
241 "%s: закрыт"
|
||||
242 "%s: удален"
|
||||
243 "%s: удален"
|
||||
244 "Файл только для чтения, не записан: Используйте ! для обхода"
|
||||
245 "Файл только для чтения, не записан"
|
||||
246 "%s существует, не записан; используйте ! для обхода"
|
||||
247 "%s существует, не записан"
|
||||
248 "Используйте ! для частичной записи файла"
|
||||
249 "Часть файла, файл не записан"
|
||||
250 "%s: Файл изменялся позднее, чем данная копия: используйте ! для обхода"
|
||||
251 "%s: Файл изменялся позднее, чем данная копия"
|
||||
252 "%s: защита на запись была недоступна"
|
||||
254 "%s: ВНИМАНИЕ: ФАЙЛ УСЕЧЕН"
|
||||
256 "%s: новый файл: %lu строк, %lu символов"
|
||||
257 "%s: %lu строк, %lu символов"
|
||||
258 "%s расширился в слишком большое количество имен файлов"
|
||||
259 "%s: специальный файл"
|
||||
260 "%s: не принадлежит Вам"
|
||||
261 "%s: доступен не только Вам"
|
||||
262 "Файл изменен со времени последней записи: сохраните или используйте ! для обхода"
|
||||
263 "Файл изменен со времени последней записи: сохраните или используйте :edit для обхода"
|
||||
264 "Файл изменен со времени последней записи: сохраните или используйте ! для обхода"
|
||||
265 "Файл временный: выход сотрет любые изменения"
|
||||
267 "Записи начаты заново"
|
2
dist/nvi/catalog/ru_RU.KOI8-R.owner
vendored
Normal file
2
dist/nvi/catalog/ru_RU.KOI8-R.owner
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
Andrey A. Chernov <ache@nagual.ru>
|
||||
Dima Ruban <dima@rdy.com>
|
308
dist/nvi/catalog/spanish.base
vendored
Normal file
308
dist/nvi/catalog/spanish.base
vendored
Normal file
|
@ -0,0 +1,308 @@
|
|||
002 "Desbordamiento de longitud de l¡nea"
|
||||
003 "no se puede borrar la l¡nea %lu"
|
||||
004 "no se puede a¤adir la l¡nea %lu"
|
||||
005 "no se puede insertar en la l¡nea %lu"
|
||||
006 "no se puede guardar la l¡nea %lu"
|
||||
007 "no se puede obtener la £ltima l¡nea"
|
||||
008 "Error: no se puede recuperar la l¡nea %lu"
|
||||
009 "Archivo de log"
|
||||
010 "No se realiza log, no se puede deshacer"
|
||||
011 "No hay cambios para deshacer"
|
||||
012 "No se realiza log, no se puede deshacer"
|
||||
013 "No se realiza log, no se puede remontar hacia adelante"
|
||||
014 "No hay cambios para rehacer"
|
||||
015 "%s/%d: error de log"
|
||||
016 "La entrada y salida est ndar de Vi debe ser una terminal"
|
||||
017 "Marcar %s: no determinado"
|
||||
018 "Marcar %s: se borr¢ la l¡nea"
|
||||
019 "Marcar %s: la posici¢n del cursor ya no existe"
|
||||
020 "Error: "
|
||||
021 "nuevo archivo"
|
||||
022 "nombre cambiado"
|
||||
023 "modificado"
|
||||
024 "no modificado"
|
||||
025 "DESTRABADO"
|
||||
026 "lectura solamente"
|
||||
027 "l¡nea %lu de %lu [%ld%%]"
|
||||
028 "archivo vac¡o"
|
||||
029 "l¡nea %lu"
|
||||
030 "El archivo %s no es un cat logo de mensajes"
|
||||
031 "No se puede determinar la opci¢n por omisi¢n %s"
|
||||
032 "Uso: %s"
|
||||
033 "determinar: no hay opci¢n %s: 'determinar todo' establece todos los valores de opci¢n"
|
||||
034 "determinar: [no] hay opci¢n %s no tiene valor"
|
||||
035 "determinar: opci¢n %s no es booleano"
|
||||
036 "determinar: opci¢n %s: %s"
|
||||
037 "determinar: opci¢n %s: %s: desbordamiento de valores"
|
||||
038 "determinar: opci¢n %s: %s es un n£mero ilegal"
|
||||
039 "determinar: opci¢n %s no es booleano"
|
||||
040 "Las columnas en pantalla son demasiado peque¤as, menos de %d"
|
||||
041 "Las columnas en pantalla son demasiado grandes, m s de %d"
|
||||
042 "Las l¡neas en pantalla son demasiado peque¤as, menos de %d"
|
||||
043 "Las l¡neas en pantalla son demasiado grandes, m s de %d"
|
||||
044 "La opci¢n lisp no est implementada"
|
||||
045 "mensajes no desconectados: %s"
|
||||
046 "mensajes no conectados: %s"
|
||||
047 "determinar: La opci¢n de %s debe estar en dos grupos de caracteres"
|
||||
053 "El buffer por omisi¢n est vac¡o"
|
||||
054 "El buffer %s est vac¡o"
|
||||
055 "Los archivos con nuevas l¡neas en el nombre son irrecuperables"
|
||||
056 "Las modificaciones no pueden recuperarse si la sesi¢n falla"
|
||||
057 "Copiando archivo para recuperaci¢n..."
|
||||
058 "Preservaci¢n fracasada: %s"
|
||||
059 "Las modificaciones no pueden recuperarse si la sesi¢n falla"
|
||||
060 "Archivo de respaldo fracasado: %s"
|
||||
061 "Copiando archivo para recuperaci¢n..."
|
||||
062 "Informaci¢n sobre identificaci¢n del usuario %u no encontrada"
|
||||
063 "No se puede trabar archivo de recuperaci¢n"
|
||||
064 "Desbordamiento de buffer de archivo de recuperaci¢n"
|
||||
065 "Archivo de recuperaci¢n"
|
||||
066 "%s: archivo de recuperaci¢n defectuoso"
|
||||
067 "%s: archivo de recuperaci¢n defectuoso"
|
||||
068 "No hay archivos denominados %s, que usted pueda leer, para recuperar"
|
||||
069 "Existen versiones m s antiguas de este archivo que usted puede recuperar"
|
||||
070 "Existen otros archivos que usted puede recuperar"
|
||||
071 "no env¡a email: %s"
|
||||
072 "Archivo vac¡o; no hay nada para buscar"
|
||||
073 "Se alcanz¢ el final del archivo sin encontrar el patr¢n"
|
||||
074 "No hay patr¢n anterior de b£squeda"
|
||||
075 "No se encontr¢ el patr¢n"
|
||||
076 " Se alcanz¢ el principio del archivo sin encontrar el patr¢n"
|
||||
077 "B£squeda reiniciada"
|
||||
078 "Buscando..."
|
||||
079 "No se encontr¢ ning£n car cter no imprimible"
|
||||
080 "Nombre de comando desconocido"
|
||||
082 "%s: comando no disponible en modalidad ex"
|
||||
083 "La cuenta no puede ser cero"
|
||||
084 "%s: mala especificaci¢n de l¡nea"
|
||||
085 "Error interno de tabla de sintaxis (%s: %s)"
|
||||
086 "Uso: %s"
|
||||
087 "%s: buffer temporario no liberado"
|
||||
088 "Desplazamiento de marcador a antes de la l¡nea 1"
|
||||
089 "Desplazamiento de marcador m s all del final del archivo"
|
||||
090 "@ con rango que corre cuando se cambia el archivo/la pantalla"
|
||||
091 "Comando global/v que corre cuando se cambia el archivo/la pantalla"
|
||||
092 "Comando Ex fracasado: comandos pendientes descartados"
|
||||
093 "Comando Ex fracasado: teclas mapeadas descartadas"
|
||||
094 "La segunda direcci¢n es m s peque¤a que la primera"
|
||||
095 "No se suministra nombre de marca"
|
||||
096 "\\ no es seguido por / o ?"
|
||||
097 "Referencia a un n£mero de l¡nea menor que 0"
|
||||
098 "El comando %s es desconocido"
|
||||
099 "Desbordamiento de valor de direcci¢n"
|
||||
100 "Subdesbordamiento de valor de direcci¢n"
|
||||
101 "Combinaci¢n de direcci¢n ilegal"
|
||||
102 "Direcci¢n ilegal: s¢lo %lu l¡neas en el archivo"
|
||||
103 "Direcci¢n ilegal: el archivo est vac¡o"
|
||||
104 "El comando %s no permite una direcci¢n de 0"
|
||||
105 "No hay abreviaturas para visualizar"
|
||||
106 "Las abreviaturas deben terminar con un car cter de \"palabra\" "
|
||||
107 "Las abreviaturas no pueden contener tabs o espacios"
|
||||
108 "Las abreviaturas no pueden mezclar caracteres palabra/no-palabra, salvo al final"
|
||||
109 "\"%s\" no es una abreviatura"
|
||||
110 "Comando Vi fracasado: teclas mapeadas descartadas"
|
||||
111 "No hay m s archivos para editar"
|
||||
112 "No hay archivos anteriores para editar"
|
||||
113 "No hay archivos anteriores para rebobinar"
|
||||
114 "No hay lista de archivos para visualizar"
|
||||
115 "No hay un comando anterior para reemplazar a \"!\""
|
||||
116 "No hay nombre de archivo para sustituir por %%"
|
||||
117 "No hay nombre de archivo para sustituir por #"
|
||||
118 "Error: execl: %s"
|
||||
119 "Error de E/S: %s"
|
||||
120 "Archivo modificado desde la £ltima escritura completa; escribir o usar ! para alterar"
|
||||
121 "No se puede encontrar la ubicaci¢n del directorio inicial"
|
||||
122 "Nuevo directorio actual: %s"
|
||||
123 "No hay buffers sueltos para visualizar"
|
||||
124 "El comando %s no puede usarse como parte de un comando global o v"
|
||||
125 "%s/%s: sin fuente: no le pertenece a usted o a ra¡z"
|
||||
126 "%s/%s: sin fuente: no le pertenece a usted"
|
||||
127 "%s/%s: sin fuente: puede ser escrito por un usuario que no sea el propietario"
|
||||
128 "%s: sin fuente: no le pertenece a usted o a ra¡z"
|
||||
129 "%s: sin fuente: no le pertenece a usted"
|
||||
130 "%s: sin fuente: puede ser escrito por un usuario que no sea el propietario"
|
||||
131 "No hay l¡neas siguientes para unir"
|
||||
132 "No hay anotaciones de mapa de entrada"
|
||||
133 "No hay anotaciones de mapa de comando"
|
||||
134 "El car cter %s no puede remapearse"
|
||||
135 "\"%s\" no est mapeado actualmente"
|
||||
136 "Marca de nombres debe ser un s¢lo car cter"
|
||||
137 "%s existe, no est escrito; usar ! para alterar"
|
||||
138 "Nuevo archivo exrc: %s"
|
||||
139 "La l¡nea de destino se encuentra dentro del rango de movimiento"
|
||||
140 "El comando abierto requiere que se determine la opci¢n abierta"
|
||||
141 "El comando abierto no se ha implementado a£n"
|
||||
142 "No es posible preservar este archivo"
|
||||
143 "Archivo preservado"
|
||||
144 "%s: expandido a demasiados nombres de archivo"
|
||||
145 "S¢lo pueden leerse los archivos regulares y los conductos nombrados"
|
||||
146 "%s: traba de lectura no disponible"
|
||||
147 "Leyendo..."
|
||||
148 "%s: %lu l¡neas, %lu caracteres"
|
||||
149 "No hay pantallas de fondo para mostrar"
|
||||
150 "El comando de script s¢lo est disponible en modalidad vi"
|
||||
151 "No hay comando para ejecutar"
|
||||
152 "opci¢n de ancho de desplazamiento en 0"
|
||||
153 "Desbordamiento de cuenta"
|
||||
154 "Subdesbordamiento de cuenta"
|
||||
155 "Expresi¢n regular especificada; marcador r no tiene significado"
|
||||
156 "Los marcadores #, l y p no pueden combinarse con el marcador c en la modalidad vi"
|
||||
157 "No se encontr¢ coincidencia"
|
||||
158 "No se ingres¢ un identificador anterior"
|
||||
159 "Se encontraron menos de %s anotaciones en la pila de identificadores; usar :visualizar i[dentificadores]"
|
||||
160 "No hay archivo %s en la pila de identificadores al que se pueda volver; usar :visualizar i[dentificadores]"
|
||||
161 "Presionar Intro para continuar: "
|
||||
162 "%s: no se encontr¢ el identificador"
|
||||
163 "%s: identificador corrompido en %s"
|
||||
164 "%s: el n£mero de l¡nea del identificador es posterior al final del archivo"
|
||||
165 "La pila de identificadores est vac¡a"
|
||||
166 "%s: patr¢n de b£squeda no encontrado"
|
||||
167 "%d archivos m s para editar"
|
||||
168 "El buffer %s est vac¡o"
|
||||
169 "¨Confirmar cambio? [n]"
|
||||
170 "Interrumpido"
|
||||
171 "No hay buffer anterior para ejecutar"
|
||||
172 "No hay expresi¢n regular anterior"
|
||||
173 "El comando %s requiere que se haya le¡do un archivo"
|
||||
174 "Uso: %s"
|
||||
175 "El comando visual requiere que se determine la opci¢n abierta"
|
||||
177 "Archivo vac¡o"
|
||||
178 "No hay b£squeda F, f, T o t anterior"
|
||||
179 "%s no se encontr¢"
|
||||
180 "No hay archivo anterior para editar"
|
||||
181 "El cursor no est en un n£mero"
|
||||
182 "El n£mero resultante es demasiado grande"
|
||||
183 " El n£mero resultante es demasiado peque¤o"
|
||||
184 "No hay car cter coincidente en esta l¡nea"
|
||||
185 "No se encontr¢ un car cter coincidente"
|
||||
186 "No hay caracteres para reemplazar"
|
||||
187 "No hay otra pantalla a la que se pueda pasar"
|
||||
188 "Caracteres despu‚s de cadena de b£squeda, desplazamiento de l¡nea y/o comando z"
|
||||
189 "No hay patr¢n anterior de b£squeda"
|
||||
190 "B£squeda vuelve a la posici¢n inicial"
|
||||
191 "Se super¢ el l¡mite de expansi¢n de abreviatura: se descartaron caracteres"
|
||||
192 "Car cter ilegal; mencionar para entrar"
|
||||
193 "Ya se encuentra al principio de la inserci¢n"
|
||||
194 "No hay m s caracteres para borrar"
|
||||
195 "Movimiento m s all del final del archivo"
|
||||
196 "Movimiento m s all del final de la l¡nea"
|
||||
197 "No hay movimiento del cursor"
|
||||
198 "Ya se encuentra al principio del archivo"
|
||||
199 "Movimiento m s all del principio del archivo"
|
||||
200 "Ya se encuentra en la primera columna"
|
||||
201 "Los buffers deben especificarse antes del comando"
|
||||
202 "Ya se encuentra al final del archivo"
|
||||
203 "Ya se encuentra al final de la l¡nea"
|
||||
204 "%s no es un comando vi"
|
||||
205 "Uso: %s"
|
||||
206 "No hay caracteres para borrar"
|
||||
207 "El comando Q requiere la interfase de terminal ex"
|
||||
208 "No hay comando para repetir"
|
||||
209 "El archivo est vac¡o"
|
||||
209 "El archivo est vac¡o"
|
||||
210 "%s no puede usarse como comando de movimiento"
|
||||
211 "Ya se encuentra en modalidad de comando"
|
||||
212 "El cursor no se encuentra en una palabra"
|
||||
214 "El valor de opci¢n de Windows es demasiado grande, el m x. es %u"
|
||||
215 "A¤adir"
|
||||
216 "Cambiar"
|
||||
217 "Comando"
|
||||
218 "Insertar"
|
||||
219 "Reemplazar"
|
||||
220 "El movimiento va m s all del final de la pantalla"
|
||||
221 "El movimiento va m s all del principio de la pantalla"
|
||||
222 "La pantalla debe tener m s de %d l¡neas para dividirse"
|
||||
223 "No hay pantallas de fondo"
|
||||
224 "No hay pantalla de fondo editando un archivo denominado %s"
|
||||
225 "No se puede poner fondo a la £nica pantalla que se visualiza"
|
||||
226 "La pantalla s¢lo puede reducirse a %d hileras"
|
||||
227 "La pantalla no puede reducirse"
|
||||
228 "La pantalla no puede aumentarse"
|
||||
230 "Esta pantalla no puede suspenderse"
|
||||
231 "Interrumpido: teclas mapeadas descartadas"
|
||||
232 "vi: buffer temporario no liberado"
|
||||
233 "Esta terminal no tiene tecla %s"
|
||||
234 "S¢lo un buffer puede especificarse"
|
||||
235 "N£mero mayor que %lu"
|
||||
236 "Interrumpido"
|
||||
237 "No se puede crear archivo temporario"
|
||||
238 "Advertencia: %s no es un archivo regular"
|
||||
239 "%s ya se encuentra trabado, la sesi¢n es de lectura solamente"
|
||||
240 "%s: eliminar"
|
||||
241 "%s: cerrar"
|
||||
242 "%s: eliminar"
|
||||
243 "%s: eliminar"
|
||||
244 "Archivo de lectura solamente, no escrito; usar ! para alterar"
|
||||
245 " Archivo de lectura solamente, no escrito"
|
||||
246 "%s existe, no escrito; usar ! para alterar"
|
||||
247 "%s existe, no escrito"
|
||||
248 "Archivo parcial, no escrito; usar ! para alterar"
|
||||
249 "Archivo parcial, no escrito"
|
||||
250 "%s: archivo modificado m s recientemente que esta copia; usar ! para alterar"
|
||||
251 "%s: archivo modificado m s recientemente que esta copia"
|
||||
252 "%s: la traba de escritura no estaba disponible"
|
||||
253 "Escribiendo..."
|
||||
254 "%s: ADVERTENCIA: ARCHIVO TRUNCADO"
|
||||
255 "Ya se encuentra en el primer identificador de este grupo"
|
||||
256 "%s: nuevo archivo: %lu l¡neas, %lu caracteres"
|
||||
257 "%s: %lu l¡neas, %lu caracteres"
|
||||
258 "%s expandido a demasiados nombres de archivos"
|
||||
259 "%s: no es un archivo regular"
|
||||
260 "%s: no le pertenece"
|
||||
261 "%s: accesible por un usuario que no sea el propietario"
|
||||
262 "Archivo modificado desde la £ltima escritura completa; escribir o usar ! para alterar"
|
||||
263 "Archivo modificado desde la £ltima escritura completa; escribir o usar :editar! para alterar"
|
||||
264 "Archivo modificado desde la £ltima escritura completa; escribir o usar ! para alterar"
|
||||
265 "El archivo es temporario; al salir se descartar n las modificaciones"
|
||||
266 "Archivo de lectura solamente, las modificaciones no se autoescriben"
|
||||
267 "Se reinici¢ el log"
|
||||
268 "confirmar? [snq]"
|
||||
269 "Presionar cualquier tecla para continuar: "
|
||||
270 "Presionar cualquier tecla para continuar [: para ingresar m s comandos ex]: "
|
||||
271 "Presionar cualquier tecla para continuar [q para salir]: "
|
||||
272 "Esta forma de %s requiere la interfase terminal ex"
|
||||
273 "Ingresando en la modalidad de entrada ex."
|
||||
274 "Comando fracasado, no hay archivo le¡do aun."
|
||||
275 " cont?"
|
||||
276 "Evento inesperado de car cter"
|
||||
277 "Evento inesperado de final de archivo"
|
||||
278 "No hay coincidencias para consulta"
|
||||
279 "Evento inesperado de interrupci¢n"
|
||||
280 "Evento inesperado de salida"
|
||||
281 "Evento inesperado de repintura"
|
||||
282 "Ya se encuentra en el £ltimo identificador de este grupo"
|
||||
283 "El comando %s requiere la interfase terminal ex"
|
||||
284 "Esta forma de %s no se encuentra soportada cuando se determina la opci¢n de edici¢n segura"
|
||||
285 "Evento inesperado de cadena"
|
||||
286 "Evento inesperado de tiempo excedido"
|
||||
287 "Evento inesperado de escritura"
|
||||
289 "Las expansiones de shell no se encuentran soportadas cuando se determina la opci¢n de edici¢n segura"
|
||||
290 "El comando %s no se encuentra soportado cuando se determina la opci¢n de edici¢n segura"
|
||||
291 "determinar: la opci¢n %s puede no estar desconectada"
|
||||
292 "El monitor es demasiado peque¤o."
|
||||
293 "agregado"
|
||||
294 "cambiado"
|
||||
295 "borrado"
|
||||
296 "unido"
|
||||
297 "movido"
|
||||
298 "desplazado"
|
||||
299 "arrancado"
|
||||
300 "l¡nea"
|
||||
301 "l¡neas"
|
||||
302 "Vi no se carg¢ con un int‚rprete Tcl"
|
||||
303 "Archivo modificado desde la £ltima escritura."
|
||||
304 "Expansi¢n de shell fracasada"
|
||||
304 "Expansi¢n de shell fracasada"
|
||||
305 "No hay opci¢n de edici¢n %s especificada"
|
||||
306 "Vi no se carg¢ con un int‚rprete Perl"
|
||||
307 "No hay comando ex para ejecutar"
|
||||
308 "Ingresar <CR> para ejecutar un comando, :q para salir"
|
||||
309 "Usar \"cscope ayuda\" para obtener ayuda"
|
||||
310 "No hay conexiones cscope corriendo"
|
||||
311 "%s: tipo de b£squeda desconocido: usar uno de %s"
|
||||
312 "%d: no existe esta sesi¢n cscope"
|
||||
313 "determinar: la opci¢n %s no puede conectarse nunca"
|
||||
314 "determinar: la opci¢n %s no puede determinarse nunca en 0"
|
||||
315 "%s: a¤adido: %lu l¡neas, %lu caracteres"
|
||||
316 "Evento inesperado de modificaci¢n de tama¤o"
|
||||
317 "%d archivos para editar"
|
19
dist/nvi/catalog/spell.ok
vendored
Normal file
19
dist/nvi/catalog/spell.ok
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
ARGMAX
|
||||
LC
|
||||
NL
|
||||
XXXX
|
||||
arg1
|
||||
arg2
|
||||
chys
|
||||
english
|
||||
english.base
|
||||
german.base
|
||||
langauge
|
||||
msg
|
||||
msg.c
|
||||
msgcat
|
||||
msgq
|
||||
nvi
|
||||
nvi's
|
||||
pathname
|
||||
sp
|
306
dist/nvi/catalog/swedish.base
vendored
Normal file
306
dist/nvi/catalog/swedish.base
vendored
Normal file
|
@ -0,0 +1,306 @@
|
|||
002 "För långa rader"
|
||||
003 "kan inte ta bort rad %lu"
|
||||
004 "kan inte lägga till på rad %lu"
|
||||
005 "kan inte sätta in på rad %lu"
|
||||
006 "kan inte lagra rad %lu"
|
||||
007 "kan inte hämta sista raden"
|
||||
008 "Fel: kan inte hämta rad %lu"
|
||||
009 "Loggningsfil"
|
||||
010 "Loggning utförs inte, ångra är inte möjligt"
|
||||
011 "Inga ändringar att ångra"
|
||||
012 "Loggning utförs inte, ångra är inte möjligt"
|
||||
013 "Loggning utförs inte, ångra ångra är inte möjligt"
|
||||
014 "Inga ändringar att återgöra"
|
||||
015 "%s/%d: fel vid loggning"
|
||||
016 "Vi:s standard in och ut måste gå till en terminal"
|
||||
017 "Markering %s: inte satt"
|
||||
018 "Markering %s: raden har tagits bort"
|
||||
019 "Markering %s: markörpositionen finns inte längre"
|
||||
020 "Fel: "
|
||||
021 "ny fil"
|
||||
022 "namnet ändrades"
|
||||
023 "ändrad"
|
||||
024 "oförändrad"
|
||||
025 "OLÅST"
|
||||
026 "inte skrivbar"
|
||||
027 "rad %lu av %lu [%ld%%]"
|
||||
028 "tom fil"
|
||||
029 "rad %lu"
|
||||
030 "Filen %s är ingen meddelandekatalog"
|
||||
031 "Kan inte sätta standardvärde för %s flaggan"
|
||||
032 "Användning: %s"
|
||||
033 "set: %s är en okänd flagga: "set all" visar alla flaggor"
|
||||
034 "set: [no]%s flaggan kan inte ges ett värde"
|
||||
035 "set: %s flaggan är inte boleansk"
|
||||
036 "set: %s flaggan: %s"
|
||||
037 "set: %s flaggan: %s: för stort värde"
|
||||
038 "set: %s flaggan: %s är ett otillåtet tal"
|
||||
039 "set: %s flaggan är inte boleansk"
|
||||
040 "Fönsterkolumnerna är för få, mindre än %d"
|
||||
041 "Fönsterkolumnerna är för många, fler än %d"
|
||||
042 "Fönsterraderna är för få, mindre än %d"
|
||||
043 "Fönsterraderna är för många, fler än %d"
|
||||
044 "Lisp flaggan är inte implementerad"
|
||||
045 "meddelanden är inte avslagna: %s"
|
||||
046 "meddelanden är inte påslagna: %s"
|
||||
047 "set: %s flaggan måste ges i teckengrupper om två"
|
||||
053 "Standardbufferten är tom"
|
||||
054 "Buffer %s är tom"
|
||||
055 "Filer med radmatning i namnet kan inte återskapas"
|
||||
056 "Ändringar kan inte återskapas om programmet kraschar"
|
||||
057 "Kopierar filen för återskapning..."
|
||||
058 "Säkerhetskopiering misslyckades: %s"
|
||||
059 "Ändringar kan inte återskapas om programmet kraschar"
|
||||
060 "Misslyckades att säkerhetskopiera filen: %s"
|
||||
061 "Kopierar filen för återskapning..."
|
||||
062 "Kan inte hitta information om användaridentitet %u"
|
||||
063 "Kan inte låsa återskapningsfilen"
|
||||
064 "Återskapningsfilens buffer överskriven"
|
||||
065 "Återskapningsfil"
|
||||
066 "%s: Återskapningsfilen är korrupt"
|
||||
067 "%s: Återskapningsfilen är korrupt"
|
||||
068 "Det finns ingen fil %s, läsbar av dig, att återskapa"
|
||||
069 "Det finns äldre versioner av denna fil som du kan återskapa"
|
||||
070 "Det finns andra filer du kan återskapa"
|
||||
071 "skickar inte email: %s"
|
||||
072 "Filen är tom; inget att söka i"
|
||||
073 "Kom till slutet på filen utan att hitta söksträngen"
|
||||
074 "Ingen tidigare söksträng"
|
||||
075 "Hittar inte söksträngen"
|
||||
076 "Kom till början av filen utan att hitta söksträngen"
|
||||
077 "Sökningen slog runt"
|
||||
078 "Söker..."
|
||||
079 "Inga icke skrivbara tecken funna"
|
||||
080 "Okänt kommandonamn"
|
||||
082 "%s: kommandot är inte tillgängligt i "ex" läge"
|
||||
083 "Talet får inte vara noll"
|
||||
084 "%s: Ogiltig radspecifikation"
|
||||
085 "Fel i intern syntaxtabell (%s: %s)"
|
||||
086 "Användning: %s"
|
||||
087 "%s: temporärbuffert inte frisläppt"
|
||||
088 "Offset är före rad 1"
|
||||
089 "Offset är efter slutet på filen"
|
||||
090 "@ med intervall exekverades när filen/fönstret ändrades"
|
||||
091 "Global/v kommando exekverades när filen/fönstret ändrades"
|
||||
092 "Ex kommando misslyckades: efterföljande kommandon ignorerade"
|
||||
093 "Ex kommando misslyckades: omdefinierade tangenter ignorerade"
|
||||
094 "Den andra adressen är mindre än den första"
|
||||
095 "Inget namn på markering givet"
|
||||
096 "\\ följs inte av / eller ?"
|
||||
097 "Referens till ett radnummer mindre än 0"
|
||||
098 "%s kommandot är inte känt"
|
||||
099 "Värdet på adressen är för stort"
|
||||
100 "Värdet på adressen är för litet"
|
||||
101 "Otillåten adresskombination"
|
||||
102 "Otillåten adress: bara %lu rader finns i filen"
|
||||
103 "Otillåten adress: filen är tom"
|
||||
104 "%s kommandot tillåter inte en adress som är 0"
|
||||
105 "Inga förkortningar att visa"
|
||||
106 "Förkortningar måste sluta med ett "ord" tecken"
|
||||
107 "Förkortningar kan inte innehålla mellanslag eller tab"
|
||||
108 "Förkortningar kan inte blanda "ord"/"icke ord" tecken, utom i slutet"
|
||||
109 ""%s" är ingen förkortning"
|
||||
110 "Vi kommando misslyckades: omdefinierade tangenter ignorerade"
|
||||
111 "Inga fler filer att editera"
|
||||
112 "Inga tidigare filer att editera"
|
||||
113 "Inga tidigare filer att spela tillbaka"
|
||||
114 "Ingen fillista att visa"
|
||||
115 "Inget tidigare kommando att ersätta "!" med"
|
||||
116 "Inget filnamn att ersätta %% med"
|
||||
117 "Inget filnamn att ersätta # med"
|
||||
118 "Fel: execl: %s"
|
||||
119 "I/O fel: %s"
|
||||
120 "Filen ändrad efter sista skrivning; spara eller använd !"
|
||||
121 "Kan inte hitta hemkatalog"
|
||||
122 "Ny nuvarande katalog: %s"
|
||||
123 "Inga "cut buffers" att visa"
|
||||
124 "%s kommandot kan inte används som del i ett "global" eller v kommando"
|
||||
125 "%s/%s: inte läst: varken du eller root är ägare"
|
||||
126 "%s/%s: inte läst: du är inte ägare"
|
||||
127 "%s/%s: inte läst: skrivbar av annan än ägaren"
|
||||
128 "%s: inte läst: varken du eller root är ägare"
|
||||
129 "%s: inte läst: du är inte ägare"
|
||||
130 "%s: inte läst: skrivbar av annan än ägaren"
|
||||
131 "Ingen nästa rad att sätta ihop med"
|
||||
132 "Det finns inget i inmatningsmappningen"
|
||||
133 "Det finns inget i kommandomappningen"
|
||||
134 "%s tecknet kan inte mappas om"
|
||||
135 ""%s" är inte ommappat just nu"
|
||||
136 "Namn på markeringar måste vara ett tecken långa"
|
||||
137 "%s finns, inget sparat; använd ! för att spara"
|
||||
138 "Ny exrc fil: %s"
|
||||
139 "Målraden ligger inne i området som ska flyttas"
|
||||
140 "Open kommandot kräver att open flaggan är satt"
|
||||
141 "Open kommandot är inte implementerat ännu"
|
||||
142 "Säkerhetskopiering av filen är inte möjligt"
|
||||
143 "Filen säkerhetskopierad"
|
||||
144 "%s expanderade till för många filnamn"
|
||||
145 "Endast vanliga filer och namngivna rör kan läsas"
|
||||
146 "%s: läslåset är otillgängligt"
|
||||
147 "Läser..."
|
||||
148 "%s: %lu rader, %lu tecken"
|
||||
149 "Inga bakgrundsfönster att visa"
|
||||
150 "Script kommandot finns bara i "vi" läge"
|
||||
151 "Inget kommando att exekvera"
|
||||
152 "shiftwidth flaggan satt till 0"
|
||||
153 "Talet har för stort värde"
|
||||
154 "Talet har för litet värde"
|
||||
155 "Reguljärt uttryck är givet; r flaggan är meningslös"
|
||||
156 "#, l och p flaggorna kan inte kombineras med c flaggan i "vi" läge"
|
||||
157 "Ingen matchande text funnen"
|
||||
158 "Inget tidigare märke har givits"
|
||||
159 "Det är färre än %s märken i stacken; använd :display t[ags]"
|
||||
160 "Det finns ingen fil %s i märkesstacken; använd :display t[ags]"
|
||||
161 "Tryck Enter för att fortsätta: "
|
||||
162 "%s: märke inte funnet"
|
||||
163 "%s: korrupt märke i %s"
|
||||
164 "%s: märkets radnummer är bortom filslutet"
|
||||
165 "Märkesstacken är tom"
|
||||
166 "%s: söksträngen inte funnen"
|
||||
167 "%d filer till att editera"
|
||||
168 "Buffert %s är tom"
|
||||
169 "Bekräfta ändring? [n]"
|
||||
170 "Avbruten"
|
||||
171 "Ingen tidigare buffert att exekvera"
|
||||
172 "Inget tidigare reguljärt uttryck"
|
||||
173 "%s kommandot kräver att en fil redan lästs in"
|
||||
174 "Användning: %s"
|
||||
175 "Visual kommandot kräver att open flaggan är satt"
|
||||
177 "Tom fil"
|
||||
178 "Ingen tidigare F, f, T eller t sökning"
|
||||
179 "%s inte funnen"
|
||||
180 "Ingen tidigare fil att editera"
|
||||
181 "Markören är inte i ett tal"
|
||||
182 "Det resulterande talet är för stort"
|
||||
183 "Det resulterande talet är för litet"
|
||||
184 "Inget matchande tecken på denna rad"
|
||||
185 "Matchande tecken inte funnet"
|
||||
186 "Det finns inga tecken att ersätta"
|
||||
187 "Det finns inget fönster att byta till"
|
||||
188 "Tecken efter söksträng, radoffset och/eller z kommandot"
|
||||
189 "Ingen tidigare söksträng"
|
||||
190 "Sökningen slog runt till ursprungliga positionen"
|
||||
191 "Förkortning överskred expanderingsgränsen: tecken har tagits bort"
|
||||
192 "Ogiltigt tecken; använd "quote" för att sätta in"
|
||||
193 "Redan i början på insättningen"
|
||||
194 "Inga fler tecken att ta bort"
|
||||
195 "Försök att gå bortom slutet på filen"
|
||||
196 "Försök att gå bortom slutet på raden"
|
||||
197 "Ingen förflyttning gjord"
|
||||
198 "Redan i början på filen"
|
||||
199 "Försök att gå före början på filen"
|
||||
200 "Redan i första kolumnen"
|
||||
201 "Buffertar måste anges före kommandot"
|
||||
202 "Redan i slutet av filen"
|
||||
203 "Redan på slutet av raden"
|
||||
204 "%s är inte ett "vi" kommando"
|
||||
205 "Användning: %s"
|
||||
206 "Inga tecken att ta bort"
|
||||
207 "Q kommandot kräver "ex" i terminalläge"
|
||||
208 "Inget kommando att repetera"
|
||||
209 "Filen är tom"
|
||||
210 "%s kan inte användas som ett förflyttningskommando"
|
||||
211 "Redan i kommando läge"
|
||||
212 "Markören är inte i ett ord"
|
||||
214 "Windows flaggans värde är för stor, största värde är %u"
|
||||
215 "Lägg till"
|
||||
216 "Ändra"
|
||||
217 "Kommando"
|
||||
218 "Sätt in"
|
||||
219 "Ersätt"
|
||||
220 "Förflyttning bortom fönsterslut"
|
||||
221 "Förflyttning till före fönstrets början"
|
||||
222 "Fönstret måste vara större än %d rader för delning"
|
||||
223 "Det finns inga fönster i bakgrunden"
|
||||
224 "Det finns inget fönster i bakgrunden som editerar filen %s"
|
||||
225 "Du får inte sätta ditt enda synliga fönster i bakgrunden"
|
||||
226 "Fönstret kan bara krympa till %d rader"
|
||||
227 "Fönstret kan inte krympa"
|
||||
228 "Fönstret kan inte växa"
|
||||
230 "Detta fönster kan inte pausas"
|
||||
231 "Avbrutet: omdefinierade tangenter ignorerade"
|
||||
232 "vi: temporärbuffertar inte frisläppta"
|
||||
233 "Denna terminal har ingen %s tangent"
|
||||
234 "Endast en buffert kan anges"
|
||||
235 "Talet är större än %lu"
|
||||
236 "Avbrutet"
|
||||
237 "Kan inte skapa temporär fil"
|
||||
238 "Warning: %s är inte en normal fil"
|
||||
239 "%s är redan låst, detta blir en icke skrivbar session"
|
||||
240 "%s: ta bort"
|
||||
241 "%s: stäng"
|
||||
242 "%s: ta bort"
|
||||
243 "%s: ta bort"
|
||||
244 "Ej skrivbar fil, filen inte sparad; använd ! för att skriva över"
|
||||
245 "Ej skrivbar fil, filen inte sparad"
|
||||
246 "%s finns, ej sparad; använd ! för att utföra operationen"
|
||||
247 "%s finns, filen inte sparad"
|
||||
248 "Ofullständig fil, filen inte sparad, använd ! för att skriva över"
|
||||
249 "Ofullständig fil, filen inte sparad"
|
||||
250 "%s: filen ändrad efter denna kopia togs; använd ! för att utföra operationen"
|
||||
251 "%s: filen ändrad efter denna kopia togs"
|
||||
252 "%s: skrivlåset är otillgängligt"
|
||||
253 "Skriver..."
|
||||
254 "%s: VARNING: FILEN TRUNKERAD"
|
||||
255 "Redan vid första märket i denna grupp"
|
||||
256 "%s: ny fil: %lu rader, %lu tecken"
|
||||
257 "%s: %lu rader, %lu tecken"
|
||||
258 "%s expanderade till för många filnamn"
|
||||
259 "%s är inte en normal fil"
|
||||
260 "%s ägs inte av dig"
|
||||
261 "%s är åtkomstbar av andra än ägaren"
|
||||
262 "Filen har ändrats efter den sparats; spara eller använd !"
|
||||
263 "Filen har ändrats efter den sparats; spara eller använd :edit!"
|
||||
264 "Filen har ändrats efter den sparats; spara eller använd !"
|
||||
265 "Filen är temporär; exit kastar bort ändringarna"
|
||||
266 "Ej skrivbar fil, ändringar har inte automatsparats"
|
||||
267 "Loggningen startar om"
|
||||
268 "bekräfta? [ynq]"
|
||||
269 "Tryck på en tangent för att fortsätta: "
|
||||
270 "Tryck på en tangent för att fortsätta [: för att ge fler kommandon]: "
|
||||
271 "Tryck på en tangent för att fortsätta [q för att avsluta]: "
|
||||
272 "Den formen av %s kräver "ex" i terminalläge"
|
||||
273 "Går till "ex" inmatningsläge."
|
||||
274 "Kommandot misslyckades, ingen fil inläst ännu."
|
||||
275 " forts?"
|
||||
276 "Oväntad teckenhändelse"
|
||||
277 "Oväntad filslutshändelse"
|
||||
278 "Sökningen hittade ingenting"
|
||||
279 "Oväntad avbrottshändelse"
|
||||
280 "Oväntad avslutningshändelse"
|
||||
281 "Oväntad omritningshändelse"
|
||||
282 "Redan vid sista märket i denna grupp"
|
||||
283 "%s kommandot kräver "ex" i terminalläge"
|
||||
284 "Den formen av %s är inte tillgänglig när secure edit flaggan är satt"
|
||||
285 "Oväntad stränghändelse"
|
||||
286 "Oväntad tidshändelse"
|
||||
287 "Oväntad skrivhändelse"
|
||||
289 "Skalexpansion är inte tillgänglig när secure edit flaggan är satt"
|
||||
290 "%s kommandot är inte tillgänglig när secure edit flaggan är satt"
|
||||
291 "set: %s kan inte slås av"
|
||||
292 "Fönstret för litet."
|
||||
293 "tillagda"
|
||||
294 "ändrade"
|
||||
295 "borttagna"
|
||||
296 "ihopsatta"
|
||||
297 "flyttade"
|
||||
298 "flyttade"
|
||||
299 "inklistrade"
|
||||
300 "rad"
|
||||
301 "rader"
|
||||
302 "Vi har inte länkats med en Tcl tolk"
|
||||
303 "Filen har ändrats efter den sparats."
|
||||
304 "Skalexpansion misslyckades"
|
||||
305 "Ingen %s edit flagga given"
|
||||
306 "Vi har inte länkats med en Perl tolk"
|
||||
307 "Inga "ex" kommandon att exekvera"
|
||||
308 "Tryck <CR> för att exekvera kommando, :q för att avsluta"
|
||||
309 "Gör "cscope help" för hjälp"
|
||||
310 "Inga cscope kopplingar körs"
|
||||
311 "%s: okänd söktyp: använd en av %s"
|
||||
312 "%d: ingen sådan cscope session"
|
||||
313 "set: %s flaggan får aldrig slås på"
|
||||
314 "set: %s flaggan får aldrig sättas till 0"
|
||||
315 "%s: tillagt: %lu rader, %lu tecken"
|
||||
316 "Oväntad storleksändring"
|
||||
317 "%d filer att editera"
|
1
dist/nvi/catalog/swedish.owner
vendored
Normal file
1
dist/nvi/catalog/swedish.owner
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
Jan Djarv <jan.djarv@mbox200.swipnet.se>
|
174
dist/nvi/cl/README.signal
vendored
Normal file
174
dist/nvi/cl/README.signal
vendored
Normal file
|
@ -0,0 +1,174 @@
|
|||
# Id: README.signal,v 10.1 1995/06/23 10:28:17 bostic Exp (Berkeley) Date: 1995/06/23 10:28:17
|
||||
|
||||
There are six (normally) asynchronous actions about which vi cares:
|
||||
SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGTSTP and SIGWINCH.
|
||||
|
||||
The assumptions:
|
||||
1: The DB routines are not reentrant.
|
||||
2: The curses routines may not be reentrant.
|
||||
3: Neither DB nor curses will restart system calls.
|
||||
|
||||
XXX
|
||||
Note, most C library functions don't restart system calls. So, we should
|
||||
*probably* start blocking around any imported function that we don't know
|
||||
doesn't make a system call. This is going to be a genuine annoyance...
|
||||
|
||||
SIGHUP, SIGTERM
|
||||
Used for file recovery. The DB routines can't be reentered, nor
|
||||
can they handle interrupted system calls, so the vi routines that
|
||||
call DB block signals. This means that DB routines could be
|
||||
called at interrupt time, if necessary.
|
||||
|
||||
SIGQUIT
|
||||
Disabled by the signal initialization routines. Historically, ^\
|
||||
switched vi into ex mode, and we continue that practice.
|
||||
|
||||
SIGWINCH:
|
||||
The interrupt routine sets a global bit which is checked by the
|
||||
key-read routine, so there are no reentrancy issues. This means
|
||||
that the screen will not resize until vi runs out of keys, but
|
||||
that doesn't seem like a problem.
|
||||
|
||||
SIGINT and SIGTSTP are a much more difficult issue to resolve. Vi has
|
||||
to permit the user to interrupt long-running operations. Generally, a
|
||||
search, substitution or read/write is done on a large file, or, the user
|
||||
creates a key mapping with an infinite loop. This problem will become
|
||||
worse as more complex semantics are added to vi, especially things like
|
||||
making it a pure text widget. There are four major solutions on the table,
|
||||
each of which have minor permutations.
|
||||
|
||||
1: Run in raw mode.
|
||||
|
||||
The up side is that there's no asynchronous behavior to worry about,
|
||||
and obviously no reentrancy problems. The down side is that it's easy
|
||||
to misinterpret characters (e.g. :w big_file^Mi^V^C is going to look
|
||||
like an interrupt) and it's easy to get into places where we won't see
|
||||
interrupt characters (e.g. ":map a ixx^[hxxaXXX" infinitely loops in
|
||||
historic implementations of vi). Periodically reading the terminal
|
||||
input buffer might solve the latter problem, but it's not going to be
|
||||
pretty.
|
||||
|
||||
Also, we're going to be checking for ^C's and ^Z's both, all over
|
||||
the place -- I hate to litter the source code with that. For example,
|
||||
the historic version of vi didn't permit you to suspend the screen if
|
||||
you were on the colon command line. This isn't right. ^Z isn't a vi
|
||||
command, it's a terminal event. (Dammit.)
|
||||
|
||||
2: Run in cbreak mode. There are two problems in this area. First, the
|
||||
current curses implementations (both System V and Berkeley) don't give
|
||||
you clean cbreak modes. For example, the IEXTEN bit is left on, turning
|
||||
on DISCARD and LNEXT. To clarify, what vi WANTS is 8-bit clean, with
|
||||
the exception that flow control and signals are turned on, and curses
|
||||
cbreak mode doesn't give you this.
|
||||
|
||||
We can either set raw mode and twiddle the tty, or cbreak mode and
|
||||
twiddle the tty. I chose to use raw mode, on the grounds that raw
|
||||
mode is better defined and I'm less likely to be surprised by a curses
|
||||
implementation down the road. The twiddling consists of setting ISIG,
|
||||
IXON/IXOFF, and disabling some of the interrupt characters (see the
|
||||
comments in cl_init.c). This is all found in historic System V (SVID
|
||||
3) and POSIX 1003.1-1992, so it should be fairly portable.
|
||||
|
||||
The second problem is that vi permits you to enter literal signal
|
||||
characters, e.g. ^V^C. There are two possible solutions. First, you
|
||||
can turn off signals when you get a ^V, but that means that a network
|
||||
packet containing ^V and ^C will lose, since the ^C may take effect
|
||||
before vi reads the ^V. (This is particularly problematic if you're
|
||||
talking over a protocol that recognizes signals locally and sends OOB
|
||||
packets when it sees them.) Second, you can turn the ^C into a literal
|
||||
character in vi, but that means that there's a race between entering
|
||||
^V<character>^C, i.e. the sequence may end up being ^V^C<character>.
|
||||
Also, the second solution doesn't work for flow control characters, as
|
||||
they aren't delivered to the program as signals.
|
||||
|
||||
Generally, this is what historic vi did. (It didn't have the curses
|
||||
problems because it didn't use curses.) It entered signals following
|
||||
^V characters into the input stream, (which is why there's no way to
|
||||
enter a literal flow control character).
|
||||
|
||||
3: Run in mostly raw mode; turn signals on when doing an operation the
|
||||
user might want to interrupt, but leave them off most of the time.
|
||||
|
||||
This works well for things like file reads and writes. This doesn't
|
||||
work well for trying to detect infinite maps. The problem is that
|
||||
you can write the code so that you don't have to turn on interrupts
|
||||
per keystroke, but the code isn't pretty and it's hard to make sure
|
||||
that an optimization doesn't cover up an infinite loop. This also
|
||||
requires interaction or state between the vi parser and the key
|
||||
reading routines, as an infinite loop may still be returning keys
|
||||
to the parser.
|
||||
|
||||
Also, if the user inserts an interrupt into the tty queue while the
|
||||
interrupts are turned off, the key won't be treated as an interrupt,
|
||||
and requiring the user to pound the keyboard to catch an interrupt
|
||||
window is nasty.
|
||||
|
||||
4: Run in mostly raw mode, leaving signals on all of the time. Done
|
||||
by setting raw mode, and twiddling the tty's termios ISIG bit.
|
||||
|
||||
This works well for the interrupt cases, because the code only has
|
||||
to check to see if the interrupt flag has been set, and can otherwise
|
||||
ignore signals. It's also less likely that we'll miss a case, and we
|
||||
don't have to worry about synchronizing between the vi parser and the
|
||||
key read routines.
|
||||
|
||||
The down side is that we have to turn signals off if the user wants
|
||||
to enter a literal character (e.g. ^V^C). If the user enters the
|
||||
combination fast enough, or as part of a single network packet,
|
||||
the text input routines will treat it as a signal instead of as a
|
||||
literal character. To some extent, we have this problem already,
|
||||
since we turn off flow control so that the user can enter literal
|
||||
XON/XOFF characters.
|
||||
|
||||
This is probably the easiest to code, and provides the smoothest
|
||||
programming interface.
|
||||
|
||||
There are a couple of other problems to consider.
|
||||
|
||||
First, System V's curses doesn't handle SIGTSTP correctly. If you use the
|
||||
newterm() interface, the TSTP signal will leave you in raw mode, and the
|
||||
final endwin() will leave you in the correct shell mode. If you use the
|
||||
initscr() interface, the TSTP signal will return you to the correct shell
|
||||
mode, but the final endwin() will leave you in raw mode. There you have
|
||||
it: proof that drug testing is not making any significant headway in the
|
||||
computer industry. The 4BSD curses is deficient in that it does not have
|
||||
an interface to the terminal keypad. So, regardless, we have to do our
|
||||
own SIGTSTP handling.
|
||||
|
||||
The problem with this is that if we do our own SIGTSTP handling, in either
|
||||
models #3 or #4, we're going to have to call curses routines at interrupt
|
||||
time, which means that we might be reentering curses, which is something we
|
||||
don't want to do.
|
||||
|
||||
Second, SIGTSTP has its own little problems. It's broadcast to the entire
|
||||
process group, not sent to a single process. The scenario goes something
|
||||
like this: the shell execs the mail program, which execs vi. The user hits
|
||||
^Z, and all three programs get the signal, in some random order. The mail
|
||||
program goes to sleep immediately (since it probably didn't have a SIGTSTP
|
||||
handler in place). The shell gets a SIGCHLD, does a wait, and finds out
|
||||
that the only child in its foreground process group (of which it's aware)
|
||||
is asleep. It then optionally resets the terminal (because the modes aren't
|
||||
how it left them), and starts prompting the user for input. The problem is
|
||||
that somewhere in the middle of all of this, vi is resetting the terminal,
|
||||
and getting ready to send a SIGTSTP to the process group in order to put
|
||||
itself to sleep. There's a solution to all of this: when vi starts, it puts
|
||||
itself into its own process group, and then only it (and possible child
|
||||
processes) receive the SIGTSTP. This permits it to clean up the terminal
|
||||
and switch back to the original process group, where it sends that process
|
||||
group a SIGTSTP, putting everyone to sleep and waking the shell.
|
||||
|
||||
Third, handing SIGTSTP asynchronously is further complicated by the child
|
||||
processes vi may fork off. If vi calls ex, ex resets the terminal and
|
||||
starts running some filter, and SIGTSTP stops them both, vi has to know
|
||||
when it restarts that it can't repaint the screen until ex's child has
|
||||
finished running. This is solveable, but it's annoying.
|
||||
|
||||
Well, somebody had to make a decision, and this is the way it's going to be
|
||||
(unless I get talked out of it). SIGINT is handled asynchronously, so
|
||||
that we can pretty much guarantee that the user can interrupt any operation
|
||||
at any time. SIGTSTP is handled synchronously, so that we don't have to
|
||||
reenter curses and so that we don't have to play the process group games.
|
||||
^Z is recognized in the standard text input and command modes. (^Z should
|
||||
also be recognized during operations that may potentially take a long time.
|
||||
The simplest solution is probably to twiddle the tty, install a handler for
|
||||
SIGTSTP, and then restore normal tty modes when the operation is complete.)
|
120
dist/nvi/cl/cl.h
vendored
Normal file
120
dist/nvi/cl/cl.h
vendored
Normal file
|
@ -0,0 +1,120 @@
|
|||
/* $NetBSD: cl.h,v 1.2 2010/02/03 15:34:37 roy Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* Copyright (c) 1993, 1994, 1995, 1996
|
||||
* Keith Bostic. All rights reserved.
|
||||
*
|
||||
* See the LICENSE file for redistribution information.
|
||||
*
|
||||
* Id: cl.h,v 10.32 2001/08/28 11:33:40 skimo Exp (Berkeley) Date: 2001/08/28 11:33:40
|
||||
*/
|
||||
|
||||
/* Avoid clash on OSF1 */
|
||||
#undef DB
|
||||
|
||||
#ifdef USE_SLANG_CURSES
|
||||
#include <slcurses.h>
|
||||
#else
|
||||
#ifdef HAVE_NCURSESW_NCURSES_H /* { */
|
||||
#include <ncursesw/ncurses.h>
|
||||
#else /* } { */
|
||||
#ifdef HAVE_NCURSES_H /* { */
|
||||
#include <ncurses.h>
|
||||
#else /* } { */
|
||||
#include <curses.h>
|
||||
#include <term.h>
|
||||
#include <termcap.h>
|
||||
#endif /* } */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef struct _cl_private {
|
||||
char ibuf[256]; /* Input keys. */
|
||||
|
||||
size_t skip; /* Remaining keys. */
|
||||
|
||||
CONVWIN cw; /* Conversion buffer. */
|
||||
|
||||
int eof_count; /* EOF count. */
|
||||
|
||||
struct termios orig; /* Original terminal values. */
|
||||
struct termios ex_enter;/* Terminal values to enter ex. */
|
||||
struct termios vi_enter;/* Terminal values to enter vi. */
|
||||
|
||||
char *el; /* Clear to EOL terminal string. */
|
||||
char *cup; /* Cursor movement terminal string. */
|
||||
char *cuu1; /* Cursor up terminal string. */
|
||||
char *rmso, *smso; /* Inverse video terminal strings. */
|
||||
char *smcup, *rmcup; /* Terminal start/stop strings. */
|
||||
|
||||
char *oname; /* Original screen window name. */
|
||||
|
||||
SCR *focus; /* Screen that has the "focus". */
|
||||
|
||||
int killersig; /* Killer signal. */
|
||||
#define INDX_HUP 0
|
||||
#define INDX_INT 1
|
||||
#define INDX_TERM 2
|
||||
#define INDX_WINCH 3
|
||||
#define INDX_MAX 4 /* Original signal information. */
|
||||
struct sigaction oact[INDX_MAX];
|
||||
|
||||
enum { /* Tty group write mode. */
|
||||
TGW_UNKNOWN=0, TGW_SET, TGW_UNSET } tgw;
|
||||
|
||||
enum { /* Terminal initialization strings. */
|
||||
TE_SENT=0, TI_SENT } ti_te;
|
||||
|
||||
#define CL_IN_EX 0x0001 /* Currently running ex. */
|
||||
#define CL_LAYOUT 0x0002 /* Screen layout changed. */
|
||||
#define CL_RENAME 0x0004 /* X11 xterm icon/window renamed. */
|
||||
#define CL_RENAME_OK 0x0008 /* User wants the windows renamed. */
|
||||
#define CL_SCR_EX_INIT 0x0010 /* Ex screen initialized. */
|
||||
#define CL_SCR_VI_INIT 0x0020 /* Vi screen initialized. */
|
||||
#define CL_SIGHUP 0x0040 /* SIGHUP arrived. */
|
||||
#define CL_SIGINT 0x0080 /* SIGINT arrived. */
|
||||
#define CL_SIGTERM 0x0100 /* SIGTERM arrived. */
|
||||
#define CL_SIGWINCH 0x0200 /* SIGWINCH arrived. */
|
||||
#define CL_STDIN_TTY 0x0400 /* Talking to a terminal. */
|
||||
u_int32_t flags;
|
||||
} CL_PRIVATE;
|
||||
|
||||
#define CLP(sp) ((CL_PRIVATE *)((sp)->gp->cl_private))
|
||||
#define GCLP(gp) ((CL_PRIVATE *)gp->cl_private)
|
||||
#define CLSP(sp) ((WINDOW *)((sp)->cl_private))
|
||||
|
||||
/* Return possibilities from the keyboard read routine. */
|
||||
typedef enum { INP_OK=0, INP_EOF, INP_ERR, INP_INTR, INP_TIMEOUT } input_t;
|
||||
|
||||
/* The screen position relative to a specific window. */
|
||||
/*
|
||||
#define RCNO(sp, cno) (sp)->coff + (cno)
|
||||
#define RLNO(sp, lno) (sp)->roff + (lno)
|
||||
*/
|
||||
#define RCNO(sp, cno) (cno)
|
||||
#define RLNO(sp, lno) (lno)
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Some implementations of curses.h don't define these for us. Used for
|
||||
* compatibility only.
|
||||
*/
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
#ifdef USE_PERL_SETENV
|
||||
#include "../perl_api/extern.h"
|
||||
#define cl_setenv(sp,name,val) perl_setenv(sp,name,val)
|
||||
#define cl_unsetenv(sp,name) perl_setenv(sp,name,NULL)
|
||||
#else
|
||||
#define cl_setenv(sp,name,val) setenv(name,val,1)
|
||||
#define cl_unsetenv(sp,name) unsetenv(name)
|
||||
#endif
|
350
dist/nvi/cl/cl_bsd.c
vendored
Normal file
350
dist/nvi/cl/cl_bsd.c
vendored
Normal file
|
@ -0,0 +1,350 @@
|
|||
/* $NetBSD: cl_bsd.c,v 1.4 2010/02/03 15:34:37 roy Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1995, 1996
|
||||
* Keith Bostic. All rights reserved.
|
||||
*
|
||||
* See the LICENSE file for redistribution information.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "Id: cl_bsd.c,v 8.32 2000/12/01 13:56:17 skimo Exp (Berkeley) Date: 2000/12/01 13:56:17";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <bitstring.h>
|
||||
#include <ctype.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../common/common.h"
|
||||
#include "../vi/vi.h"
|
||||
#include "cl.h"
|
||||
|
||||
#ifndef HAVE_CURSES_SETUPTERM
|
||||
static char *ke; /* Keypad on. */
|
||||
static char *ks; /* Keypad off. */
|
||||
static char *vb; /* Visible bell string. */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* HP's support the entire System V curses package except for the tigetstr
|
||||
* and tigetnum functions. Ultrix supports the BSD curses package except
|
||||
* for the idlok function. Cthulu only knows why. Break things up into a
|
||||
* minimal set of functions.
|
||||
*/
|
||||
|
||||
#ifndef HAVE_CURSES_WADDNSTR
|
||||
/*
|
||||
* waddnstr --
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_CURSES_WADDNSTR
|
||||
* PUBLIC: int waddnstr __P((WINDOW*, char *, int));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
int
|
||||
waddnstr(w, s, n)
|
||||
WINDOW *w;
|
||||
char *s;
|
||||
int n;
|
||||
{
|
||||
int ch;
|
||||
|
||||
while (n-- && (ch = *s++))
|
||||
waddch(w, ch);
|
||||
return (OK);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_CURSES_BEEP
|
||||
/*
|
||||
* beep --
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_CURSES_BEEP
|
||||
* PUBLIC: void beep __P((void));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
void
|
||||
beep()
|
||||
{
|
||||
(void)write(1, "\007", 1); /* '\a' */
|
||||
}
|
||||
#endif /* !HAVE_CURSES_BEEP */
|
||||
|
||||
#ifndef HAVE_CURSES_FLASH
|
||||
/*
|
||||
* flash --
|
||||
* Flash the screen.
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_CURSES_FLASH
|
||||
* PUBLIC: void flash __P((void));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
void
|
||||
flash()
|
||||
{
|
||||
if (vb != NULL) {
|
||||
(void)tputs(vb, 1, cl_putchar);
|
||||
(void)fflush(stdout);
|
||||
} else
|
||||
beep();
|
||||
}
|
||||
#endif /* !HAVE_CURSES_FLASH */
|
||||
|
||||
#ifndef HAVE_CURSES_IDLOK
|
||||
/*
|
||||
* idlok --
|
||||
* Turn on/off hardware line insert/delete.
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_CURSES_IDLOK
|
||||
* PUBLIC: void idlok __P((WINDOW *, int));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
void
|
||||
idlok(win, bf)
|
||||
WINDOW *win;
|
||||
int bf;
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif /* !HAVE_CURSES_IDLOK */
|
||||
|
||||
#ifndef HAVE_CURSES_KEYPAD
|
||||
/*
|
||||
* keypad --
|
||||
* Put the keypad/cursor arrows into or out of application mode.
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_CURSES_KEYPAD
|
||||
* PUBLIC: int keypad __P((void *, int));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
int
|
||||
keypad(a, on)
|
||||
void *a;
|
||||
int on;
|
||||
{
|
||||
char *p;
|
||||
|
||||
if ((p = tigetstr(on ? "smkx" : "rmkx")) != (char *)-1) {
|
||||
(void)tputs(p, 0, cl_putchar);
|
||||
(void)fflush(stdout);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif /* !HAVE_CURSES_KEYPAD */
|
||||
|
||||
#ifndef HAVE_CURSES_NEWTERM
|
||||
/*
|
||||
* newterm --
|
||||
* Create a new curses screen.
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_CURSES_NEWTERM
|
||||
* PUBLIC: void *newterm __P((const char *, FILE *, FILE *));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
void *
|
||||
newterm(a, b, c)
|
||||
const char *a;
|
||||
FILE *b, *c;
|
||||
{
|
||||
return (initscr());
|
||||
}
|
||||
#endif /* !HAVE_CURSES_NEWTERM */
|
||||
|
||||
#ifndef HAVE_CURSES_SETUPTERM
|
||||
/*
|
||||
* setupterm --
|
||||
* Set up terminal.
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_CURSES_SETUPTERM
|
||||
* PUBLIC: void setupterm __P((char *, int, int *));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
void
|
||||
setupterm(ttype, fno, errp)
|
||||
char *ttype;
|
||||
int fno, *errp;
|
||||
{
|
||||
static char buf[2048];
|
||||
char *p;
|
||||
|
||||
if ((*errp = tgetent(buf, ttype)) > 0) {
|
||||
if (ke != NULL)
|
||||
free(ke);
|
||||
ke = ((p = tigetstr("rmkx")) == (char *)-1) ?
|
||||
NULL : strdup(p);
|
||||
if (ks != NULL)
|
||||
free(ks);
|
||||
ks = ((p = tigetstr("smkx")) == (char *)-1) ?
|
||||
NULL : strdup(p);
|
||||
if (vb != NULL)
|
||||
free(vb);
|
||||
vb = ((p = tigetstr("flash")) == (char *)-1) ?
|
||||
NULL : strdup(p);
|
||||
}
|
||||
}
|
||||
#endif /* !HAVE_CURSES_SETUPTERM */
|
||||
|
||||
#ifndef HAVE_CURSES_TIGETSTR
|
||||
/* Terminfo-to-termcap translation table. */
|
||||
typedef struct _tl {
|
||||
const char *terminfo; /* Terminfo name. */
|
||||
const char *termcap; /* Termcap name. */
|
||||
} TL;
|
||||
static const TL list[] = {
|
||||
{ "cols", "co", }, /* Terminal columns. */
|
||||
{ "cup", "cm", }, /* Cursor up. */
|
||||
{ "cuu1", "up", }, /* Cursor up. */
|
||||
{ "el", "ce", }, /* Clear to end-of-line. */
|
||||
{ "flash", "vb", }, /* Visible bell. */
|
||||
{ "kcub1", "kl", }, /* Cursor left. */
|
||||
{ "kcud1", "kd", }, /* Cursor down. */
|
||||
{ "kcuf1", "kr", }, /* Cursor right. */
|
||||
{ "kcuu1", "ku", }, /* Cursor up. */
|
||||
{ "kdch1", "kD", }, /* Delete character. */
|
||||
{ "kdl1", "kL", }, /* Delete line. */
|
||||
{ "ked", "kS", }, /* Delete to end of screen. */
|
||||
{ "kel", "kE", }, /* Delete to eol. */
|
||||
{ "kend", "@7", }, /* Go to eol. */
|
||||
{ "khome", "kh", }, /* Go to sol. */
|
||||
{ "kich1", "kI", }, /* Insert at cursor. */
|
||||
{ "kil1", "kA", }, /* Insert line. */
|
||||
{ "kind", "kF", }, /* Scroll down. */
|
||||
{ "kll", "kH", }, /* Go to eol. */
|
||||
{ "knp", "kN", }, /* Page down. */
|
||||
{ "kpp", "kP", }, /* Page up. */
|
||||
{ "kri", "kR", }, /* Scroll up. */
|
||||
{ "lines", "li", }, /* Terminal lines. */
|
||||
{ "rmcup", "te", }, /* Terminal end string. */
|
||||
{ "rmkx", "ke", }, /* Exit "keypad-transmit" mode. */
|
||||
{ "rmso", "se", }, /* Standout end. */
|
||||
{ "smcup", "ti", }, /* Terminal initialization string. */
|
||||
{ "smkx", "ks", }, /* Enter "keypad-transmit" mode. */
|
||||
{ "smso", "so", }, /* Standout begin. */
|
||||
};
|
||||
|
||||
#ifdef _AIX
|
||||
/*
|
||||
* AIX's implementation for function keys greater than 10 is different and
|
||||
* only goes as far as 36.
|
||||
*/
|
||||
static const char codes[] = {
|
||||
/* 0-10 */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ';',
|
||||
/* 11-20 */ '<', '>', '!', '@', '#', '$', '%', '^', '&', '*',
|
||||
/* 21-30 */ '(', ')', '-', '_', '+', ',', ':', '?', '[', ']',
|
||||
/* 31-36 */ '{', '}', '|', '~', '/', '='
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* Historically, the 4BSD termcap code didn't support functions keys greater
|
||||
* than 9. This was silently enforced -- asking for key k12 would return the
|
||||
* value for k1. We try and get around this by using the tables specified in
|
||||
* the terminfo(TI_ENV) man page from the 3rd Edition SVID. This assumes the
|
||||
* implementors of any System V compatibility code or an extended termcap used
|
||||
* those codes.
|
||||
*/
|
||||
static const char codes[] = {
|
||||
/* 0-10 */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ';',
|
||||
/* 11-19 */ '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
/* 20-63 */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
};
|
||||
#endif /* _AIX */
|
||||
|
||||
/*
|
||||
* lcmp --
|
||||
* list comparison routine for bsearch.
|
||||
*/
|
||||
static int
|
||||
lcmp(const void *a, const void *b)
|
||||
{
|
||||
return (strcmp(a, ((const TL *)b)->terminfo));
|
||||
}
|
||||
|
||||
/*
|
||||
* tigetstr --
|
||||
*
|
||||
* Vendors put the prototype for tigetstr into random include files, including
|
||||
* <term.h>, which we can't include because it makes other systems unhappy.
|
||||
* Try and work around the problem, since we only care about the return value.
|
||||
*
|
||||
* PUBLIC: #ifdef HAVE_CURSES_TIGETSTR
|
||||
* PUBLIC: char *tigetstr();
|
||||
* PUBLIC: #else
|
||||
* PUBLIC: char *tigetstr __P((char *));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
char *
|
||||
tigetstr(name)
|
||||
const char *name;
|
||||
{
|
||||
static char sbuf[256];
|
||||
TL *tlp;
|
||||
int n;
|
||||
char *p, mykeyname[3];
|
||||
|
||||
if ((tlp = bsearch(name,
|
||||
list, sizeof(list) / sizeof(TL), sizeof(TL), lcmp)) == NULL) {
|
||||
#ifdef _AIX
|
||||
if (name[0] == 'k' &&
|
||||
name[1] == 'f' && (n = atoi(name + 2)) <= 36) {
|
||||
mykeyname[0] = 'k';
|
||||
mykeyname[1] = codes[n];
|
||||
mykeyname[2] = '\0';
|
||||
#else
|
||||
if (name[0] == 'k' &&
|
||||
name[1] == 'f' && (n = atoi(name + 2)) <= 63) {
|
||||
mykeyname[0] = n <= 10 ? 'k' : 'F';
|
||||
mykeyname[1] = codes[n];
|
||||
mykeyname[2] = '\0';
|
||||
#endif
|
||||
name = mykeyname;
|
||||
}
|
||||
} else
|
||||
name = tlp->termcap;
|
||||
|
||||
p = sbuf;
|
||||
#ifdef _AIX
|
||||
return ((p = tgetstr(name, &p)) == NULL ? (char *)-1 : strcpy(sbuf, p));
|
||||
#else
|
||||
return (tgetstr(name, &p) == NULL ? (char *)-1 : sbuf);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* tigetnum --
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_CURSES_TIGETSTR
|
||||
* PUBLIC: int tigetnum __P((char *));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
int
|
||||
tigetnum(name)
|
||||
const char *name;
|
||||
{
|
||||
TL *tlp;
|
||||
int val;
|
||||
|
||||
if ((tlp = bsearch(name,
|
||||
list, sizeof(list) / sizeof(TL), sizeof(TL), lcmp)) != NULL) {
|
||||
name = tlp->termcap;
|
||||
}
|
||||
|
||||
return ((val = tgetnum(name)) == -1 ? -2 : val);
|
||||
}
|
||||
#endif /* !HAVE_CURSES_TIGETSTR */
|
||||
|
894
dist/nvi/cl/cl_funcs.c
vendored
Normal file
894
dist/nvi/cl/cl_funcs.c
vendored
Normal file
|
@ -0,0 +1,894 @@
|
|||
/* $NetBSD: cl_funcs.c,v 1.4 2009/11/15 18:43:28 dsl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* Copyright (c) 1993, 1994, 1995, 1996
|
||||
* Keith Bostic. All rights reserved.
|
||||
*
|
||||
* See the LICENSE file for redistribution information.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "Id: cl_funcs.c,v 10.72 2002/03/02 23:18:33 skimo Exp (Berkeley) Date: 2002/03/02 23:18:33";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <bitstring.h>
|
||||
#include <ctype.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../common/common.h"
|
||||
#include "../vi/vi.h"
|
||||
#include "cl.h"
|
||||
|
||||
static void cl_rdiv __P((SCR *));
|
||||
|
||||
static int
|
||||
addstr4(SCR *sp, const void *str, size_t len, int wide)
|
||||
{
|
||||
CL_PRIVATE *clp;
|
||||
WINDOW *win;
|
||||
size_t y, x;
|
||||
int iv;
|
||||
|
||||
clp = CLP(sp);
|
||||
win = CLSP(sp) ? CLSP(sp) : stdscr;
|
||||
|
||||
/*
|
||||
* If ex isn't in control, it's the last line of the screen and
|
||||
* it's a split screen, use inverse video.
|
||||
*/
|
||||
iv = 0;
|
||||
getyx(win, y, x);
|
||||
if (!F_ISSET(sp, SC_SCR_EXWROTE) &&
|
||||
y == RLNO(sp, LASTLINE(sp)) && IS_SPLIT(sp)) {
|
||||
iv = 1;
|
||||
(void)wstandout(win);
|
||||
}
|
||||
|
||||
#ifdef USE_WIDECHAR
|
||||
if (wide) {
|
||||
if (waddnwstr(win, str, len) == ERR)
|
||||
return (1);
|
||||
} else
|
||||
#endif
|
||||
if (waddnstr(win, str, len) == ERR)
|
||||
return (1);
|
||||
|
||||
if (iv)
|
||||
(void)wstandend(win);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_waddstr --
|
||||
* Add len bytes from the string at the cursor, advancing the cursor.
|
||||
*
|
||||
* PUBLIC: int cl_waddstr __P((SCR *, const CHAR_T *, size_t));
|
||||
*/
|
||||
int
|
||||
cl_waddstr(SCR *sp, const CHAR_T *str, size_t len)
|
||||
{
|
||||
return addstr4(sp, (const void *)str, len, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_addstr --
|
||||
* Add len bytes from the string at the cursor, advancing the cursor.
|
||||
*
|
||||
* PUBLIC: int cl_addstr __P((SCR *, const char *, size_t));
|
||||
*/
|
||||
int
|
||||
cl_addstr(SCR *sp, const char *str, size_t len)
|
||||
{
|
||||
return addstr4(sp, (const void *)str, len, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_attr --
|
||||
* Toggle a screen attribute on/off.
|
||||
*
|
||||
* PUBLIC: int cl_attr __P((SCR *, scr_attr_t, int));
|
||||
*/
|
||||
int
|
||||
cl_attr(SCR *sp, scr_attr_t attribute, int on)
|
||||
{
|
||||
CL_PRIVATE *clp;
|
||||
WINDOW *win;
|
||||
|
||||
clp = CLP(sp);
|
||||
win = CLSP(sp) ? CLSP(sp) : stdscr;
|
||||
|
||||
switch (attribute) {
|
||||
case SA_ALTERNATE:
|
||||
/*
|
||||
* !!!
|
||||
* There's a major layering violation here. The problem is that the
|
||||
* X11 xterm screen has what's known as an "alternate" screen. Some
|
||||
* xterm termcap/terminfo entries include sequences to switch to/from
|
||||
* that alternate screen as part of the ti/te (smcup/rmcup) strings.
|
||||
* Vi runs in the alternate screen, so that you are returned to the
|
||||
* same screen contents on exit from vi that you had when you entered
|
||||
* vi. Further, when you run :shell, or :!date or similar ex commands,
|
||||
* you also see the original screen contents. This wasn't deliberate
|
||||
* on vi's part, it's just that it historically sent terminal init/end
|
||||
* sequences at those times, and the addition of the alternate screen
|
||||
* sequences to the strings changed the behavior of vi. The problem
|
||||
* caused by this is that we don't want to switch back to the alternate
|
||||
* screen while getting a new command from the user, when the user is
|
||||
* continuing to enter ex commands, e.g.:
|
||||
*
|
||||
* :!date <<< switch to original screen
|
||||
* [Hit return to continue] <<< prompt user to continue
|
||||
* :command <<< get command from user
|
||||
*
|
||||
* Note that the :command input is a true vi input mode, e.g., input
|
||||
* maps and abbreviations are being done. So, we need to be able to
|
||||
* switch back into the vi screen mode, without flashing the screen.
|
||||
*
|
||||
* To make matters worse, the curses initscr() and endwin() calls will
|
||||
* do this automatically -- so, this attribute isn't as controlled by
|
||||
* the higher level screen as closely as one might like.
|
||||
*/
|
||||
if (on) {
|
||||
if (clp->ti_te != TI_SENT) {
|
||||
clp->ti_te = TI_SENT;
|
||||
if (clp->smcup == NULL)
|
||||
(void)cl_getcap(sp, "smcup", &clp->smcup);
|
||||
if (clp->smcup != NULL)
|
||||
(void)tputs(clp->smcup, 1, cl_putchar);
|
||||
}
|
||||
} else
|
||||
if (clp->ti_te != TE_SENT) {
|
||||
clp->ti_te = TE_SENT;
|
||||
if (clp->rmcup == NULL)
|
||||
(void)cl_getcap(sp, "rmcup", &clp->rmcup);
|
||||
if (clp->rmcup != NULL)
|
||||
(void)tputs(clp->rmcup, 1, cl_putchar);
|
||||
(void)fflush(stdout);
|
||||
}
|
||||
(void)fflush(stdout);
|
||||
break;
|
||||
case SA_INVERSE:
|
||||
if (F_ISSET(sp, SC_EX | SC_SCR_EXWROTE)) {
|
||||
if (clp->smso == NULL)
|
||||
return (1);
|
||||
if (on)
|
||||
(void)tputs(clp->smso, 1, cl_putchar);
|
||||
else
|
||||
(void)tputs(clp->rmso, 1, cl_putchar);
|
||||
(void)fflush(stdout);
|
||||
} else {
|
||||
if (on)
|
||||
(void)wstandout(win);
|
||||
else
|
||||
(void)wstandend(win);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_baud --
|
||||
* Return the baud rate.
|
||||
*
|
||||
* PUBLIC: int cl_baud __P((SCR *, u_long *));
|
||||
*/
|
||||
int
|
||||
cl_baud(SCR *sp, u_long *ratep)
|
||||
{
|
||||
CL_PRIVATE *clp;
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* There's no portable way to get a "baud rate" -- cfgetospeed(3)
|
||||
* returns the value associated with some #define, which we may
|
||||
* never have heard of, or which may be a purely local speed. Vi
|
||||
* only cares if it's SLOW (w300), slow (w1200) or fast (w9600).
|
||||
* Try and detect the slow ones, and default to fast.
|
||||
*/
|
||||
clp = CLP(sp);
|
||||
switch (cfgetospeed(&clp->orig)) {
|
||||
case B50:
|
||||
case B75:
|
||||
case B110:
|
||||
case B134:
|
||||
case B150:
|
||||
case B200:
|
||||
case B300:
|
||||
case B600:
|
||||
*ratep = 600;
|
||||
break;
|
||||
case B1200:
|
||||
*ratep = 1200;
|
||||
break;
|
||||
default:
|
||||
*ratep = 9600;
|
||||
break;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_bell --
|
||||
* Ring the bell/flash the screen.
|
||||
*
|
||||
* PUBLIC: int cl_bell __P((SCR *));
|
||||
*/
|
||||
int
|
||||
cl_bell(SCR *sp)
|
||||
{
|
||||
if (F_ISSET(sp, SC_EX | SC_SCR_EXWROTE | SC_SCR_EX))
|
||||
(void)write(STDOUT_FILENO, "\07", 1); /* \a */
|
||||
else {
|
||||
/*
|
||||
* Vi has an edit option which determines if the terminal
|
||||
* should be beeped or the screen flashed.
|
||||
*/
|
||||
if (O_ISSET(sp, O_FLASH))
|
||||
(void)flash();
|
||||
else
|
||||
(void)beep();
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_clrtoeol --
|
||||
* Clear from the current cursor to the end of the line.
|
||||
*
|
||||
* PUBLIC: int cl_clrtoeol __P((SCR *));
|
||||
*/
|
||||
int
|
||||
cl_clrtoeol(SCR *sp)
|
||||
{
|
||||
WINDOW *win;
|
||||
#if 0
|
||||
size_t spcnt, y, x;
|
||||
#endif
|
||||
|
||||
win = CLSP(sp) ? CLSP(sp) : stdscr;
|
||||
|
||||
#if 0
|
||||
if (IS_VSPLIT(sp)) {
|
||||
/* The cursor must be returned to its original position. */
|
||||
getyx(win, y, x);
|
||||
for (spcnt = (sp->coff + sp->cols) - x; spcnt > 0; --spcnt)
|
||||
(void)waddch(win, ' ');
|
||||
(void)wmove(win, y, x);
|
||||
return (0);
|
||||
} else
|
||||
#endif
|
||||
return (wclrtoeol(win) == ERR);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_cursor --
|
||||
* Return the current cursor position.
|
||||
*
|
||||
* PUBLIC: int cl_cursor __P((SCR *, size_t *, size_t *));
|
||||
*/
|
||||
int
|
||||
cl_cursor(SCR *sp, size_t *yp, size_t *xp)
|
||||
{
|
||||
WINDOW *win;
|
||||
win = CLSP(sp) ? CLSP(sp) : stdscr;
|
||||
/*
|
||||
* The curses screen support splits a single underlying curses screen
|
||||
* into multiple screens to support split screen semantics. For this
|
||||
* reason the returned value must be adjusted to be relative to the
|
||||
* current screen, and not absolute. Screens that implement the split
|
||||
* using physically distinct screens won't need this hack.
|
||||
*/
|
||||
getyx(win, *yp, *xp);
|
||||
/*
|
||||
*yp -= sp->roff;
|
||||
*xp -= sp->coff;
|
||||
*/
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_deleteln --
|
||||
* Delete the current line, scrolling all lines below it.
|
||||
*
|
||||
* PUBLIC: int cl_deleteln __P((SCR *));
|
||||
*/
|
||||
int
|
||||
cl_deleteln(SCR *sp)
|
||||
{
|
||||
CHAR_T ch;
|
||||
CL_PRIVATE *clp;
|
||||
WINDOW *win;
|
||||
size_t col, lno, spcnt, y, x;
|
||||
|
||||
clp = CLP(sp);
|
||||
win = CLSP(sp) ? CLSP(sp) : stdscr;
|
||||
|
||||
/*
|
||||
* This clause is required because the curses screen uses reverse
|
||||
* video to delimit split screens. If the screen does not do this,
|
||||
* this code won't be necessary.
|
||||
*
|
||||
* If the bottom line was in reverse video, rewrite it in normal
|
||||
* video before it's scrolled.
|
||||
*
|
||||
* Check for the existence of a chgat function; XSI requires it, but
|
||||
* historic implementations of System V curses don't. If it's not
|
||||
* a #define, we'll fall back to doing it by hand, which is slow but
|
||||
* acceptable.
|
||||
*
|
||||
* By hand means walking through the line, retrieving and rewriting
|
||||
* each character. Curses has no EOL marker, so track strings of
|
||||
* spaces, and copy the trailing spaces only if there's a non-space
|
||||
* character following.
|
||||
*/
|
||||
if (!F_ISSET(sp, SC_SCR_EXWROTE) && IS_SPLIT(sp)) {
|
||||
getyx(win, y, x);
|
||||
#ifdef mvchgat
|
||||
mvwchgat(win, RLNO(sp, LASTLINE(sp)), 0, -1, A_NORMAL, 0, NULL);
|
||||
#else
|
||||
for (lno = RLNO(sp, LASTLINE(sp)), col = spcnt = 0;;) {
|
||||
(void)wmove(win, lno, col);
|
||||
ch = winch(win);
|
||||
if (isblank(ch))
|
||||
++spcnt;
|
||||
else {
|
||||
(void)wmove(win, lno, col - spcnt);
|
||||
for (; spcnt > 0; --spcnt)
|
||||
(void)waddch(win, ' ');
|
||||
(void)waddch(win, ch);
|
||||
}
|
||||
if (++col >= sp->cols)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
(void)wmove(win, y, x);
|
||||
}
|
||||
|
||||
/*
|
||||
* The bottom line is expected to be blank after this operation,
|
||||
* and other screens must support that semantic.
|
||||
*/
|
||||
return (wdeleteln(win) == ERR);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_discard --
|
||||
* Discard a screen.
|
||||
*
|
||||
* PUBLIC: int cl_discard __P((SCR *, SCR **));
|
||||
*/
|
||||
int
|
||||
cl_discard(SCR *discardp, SCR **acquirep)
|
||||
{
|
||||
CL_PRIVATE *clp;
|
||||
SCR* tsp;
|
||||
|
||||
if (discardp) {
|
||||
clp = CLP(discardp);
|
||||
F_SET(clp, CL_LAYOUT);
|
||||
|
||||
if (CLSP(discardp)) {
|
||||
delwin(CLSP(discardp));
|
||||
discardp->cl_private = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* no screens got a piece; we're done */
|
||||
if (!acquirep)
|
||||
return 0;
|
||||
|
||||
for (; (tsp = *acquirep) != NULL; ++acquirep) {
|
||||
clp = CLP(tsp);
|
||||
F_SET(clp, CL_LAYOUT);
|
||||
|
||||
if (CLSP(tsp))
|
||||
delwin(CLSP(tsp));
|
||||
tsp->cl_private = subwin(stdscr, tsp->rows, tsp->cols,
|
||||
tsp->roff, tsp->coff);
|
||||
}
|
||||
|
||||
/* discardp is going away, acquirep is taking up its space. */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_ex_adjust --
|
||||
* Adjust the screen for ex. This routine is purely for standalone
|
||||
* ex programs. All special purpose, all special case.
|
||||
*
|
||||
* PUBLIC: int cl_ex_adjust __P((SCR *, exadj_t));
|
||||
*/
|
||||
int
|
||||
cl_ex_adjust(SCR *sp, exadj_t action)
|
||||
{
|
||||
CL_PRIVATE *clp;
|
||||
int cnt;
|
||||
|
||||
clp = CLP(sp);
|
||||
switch (action) {
|
||||
case EX_TERM_SCROLL:
|
||||
/* Move the cursor up one line if that's possible. */
|
||||
if (clp->cuu1 != NULL)
|
||||
(void)tputs(clp->cuu1, 1, cl_putchar);
|
||||
else if (clp->cup != NULL)
|
||||
(void)tputs(tgoto(clp->cup,
|
||||
0, LINES - 2), 1, cl_putchar);
|
||||
else
|
||||
return (0);
|
||||
/* FALLTHROUGH */
|
||||
case EX_TERM_CE:
|
||||
/* Clear the line. */
|
||||
if (clp->el != NULL) {
|
||||
(void)putchar('\r');
|
||||
(void)tputs(clp->el, 1, cl_putchar);
|
||||
} else {
|
||||
/*
|
||||
* Historically, ex didn't erase the line, so, if the
|
||||
* displayed line was only a single glyph, and <eof>
|
||||
* was more than one glyph, the output would not fully
|
||||
* overwrite the user's input. To fix this, output
|
||||
* the maxiumum character number of spaces. Note,
|
||||
* this won't help if the user entered extra prompt
|
||||
* or <blank> characters before the command character.
|
||||
* We'd have to do a lot of work to make that work, and
|
||||
* it's almost certainly not worth the effort.
|
||||
*/
|
||||
for (cnt = 0; cnt < MAX_CHARACTER_COLUMNS; ++cnt)
|
||||
(void)putchar('\b');
|
||||
for (cnt = 0; cnt < MAX_CHARACTER_COLUMNS; ++cnt)
|
||||
(void)putchar(' ');
|
||||
(void)putchar('\r');
|
||||
(void)fflush(stdout);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_insertln --
|
||||
* Push down the current line, discarding the bottom line.
|
||||
*
|
||||
* PUBLIC: int cl_insertln __P((SCR *));
|
||||
*/
|
||||
int
|
||||
cl_insertln(SCR *sp)
|
||||
{
|
||||
WINDOW *win;
|
||||
win = CLSP(sp) ? CLSP(sp) : stdscr;
|
||||
/*
|
||||
* The current line is expected to be blank after this operation,
|
||||
* and the screen must support that semantic.
|
||||
*/
|
||||
return (winsertln(win) == ERR);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_keyval --
|
||||
* Return the value for a special key.
|
||||
*
|
||||
* PUBLIC: int cl_keyval __P((SCR *, scr_keyval_t, CHAR_T *, int *));
|
||||
*/
|
||||
int
|
||||
cl_keyval(SCR *sp, scr_keyval_t val, CHAR_T *chp, int *dnep)
|
||||
{
|
||||
CL_PRIVATE *clp;
|
||||
|
||||
/*
|
||||
* VEOF, VERASE and VKILL are required by POSIX 1003.1-1990,
|
||||
* VWERASE is a 4BSD extension.
|
||||
*/
|
||||
clp = CLP(sp);
|
||||
switch (val) {
|
||||
case KEY_VEOF:
|
||||
*dnep = (*chp = clp->orig.c_cc[VEOF]) == _POSIX_VDISABLE;
|
||||
break;
|
||||
case KEY_VERASE:
|
||||
*dnep = (*chp = clp->orig.c_cc[VERASE]) == _POSIX_VDISABLE;
|
||||
break;
|
||||
case KEY_VKILL:
|
||||
*dnep = (*chp = clp->orig.c_cc[VKILL]) == _POSIX_VDISABLE;
|
||||
break;
|
||||
#ifdef VWERASE
|
||||
case KEY_VWERASE:
|
||||
*dnep = (*chp = clp->orig.c_cc[VWERASE]) == _POSIX_VDISABLE;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
*dnep = 1;
|
||||
break;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_move --
|
||||
* Move the cursor.
|
||||
*
|
||||
* PUBLIC: int cl_move __P((SCR *, size_t, size_t));
|
||||
*/
|
||||
int
|
||||
cl_move(SCR *sp, size_t lno, size_t cno)
|
||||
{
|
||||
WINDOW *win;
|
||||
win = CLSP(sp) ? CLSP(sp) : stdscr;
|
||||
/* See the comment in cl_cursor. */
|
||||
if (wmove(win, RLNO(sp, lno), RCNO(sp, cno)) == ERR) {
|
||||
msgq(sp, M_ERR, "Error: move: l(%zu + %zu) c(%zu + %zu)",
|
||||
lno, sp->roff, cno, sp->coff);
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_refresh --
|
||||
* Refresh the screen.
|
||||
*
|
||||
* PUBLIC: int cl_refresh __P((SCR *, int));
|
||||
*/
|
||||
int
|
||||
cl_refresh(SCR *sp, int repaint)
|
||||
{
|
||||
GS *gp;
|
||||
CL_PRIVATE *clp;
|
||||
WINDOW *win;
|
||||
SCR *psp, *tsp;
|
||||
size_t y, x;
|
||||
|
||||
gp = sp->gp;
|
||||
clp = CLP(sp);
|
||||
win = CLSP(sp) ? CLSP(sp) : stdscr;
|
||||
|
||||
/*
|
||||
* If we received a killer signal, we're done, there's no point
|
||||
* in refreshing the screen.
|
||||
*/
|
||||
if (clp->killersig)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* If repaint is set, the editor is telling us that we don't know
|
||||
* what's on the screen, so we have to repaint from scratch.
|
||||
*
|
||||
* If repaint set or the screen layout changed, we need to redraw
|
||||
* any lines separating vertically split screens. If the horizontal
|
||||
* offsets are the same, then the split was vertical, and need to
|
||||
* draw a dividing line.
|
||||
*/
|
||||
if (repaint || F_ISSET(clp, CL_LAYOUT)) {
|
||||
getyx(stdscr, y, x);
|
||||
for (psp = sp;
|
||||
psp != (void *)&sp->wp->scrq; psp = psp->q.cqe_next)
|
||||
for (tsp = psp->q.cqe_next;
|
||||
tsp != (void *)&sp->wp->scrq;
|
||||
tsp = tsp->q.cqe_next)
|
||||
if (psp->roff == tsp->roff) {
|
||||
if (psp->coff + psp->cols + 1 == tsp->coff)
|
||||
cl_rdiv(psp);
|
||||
else
|
||||
if (tsp->coff + tsp->cols + 1 == psp->coff)
|
||||
cl_rdiv(tsp);
|
||||
}
|
||||
(void)wmove(stdscr, y, x);
|
||||
F_CLR(clp, CL_LAYOUT);
|
||||
}
|
||||
|
||||
/*
|
||||
* In the curses library, doing wrefresh(curscr) is okay, but the
|
||||
* screen flashes when we then apply the refresh() to bring it up
|
||||
* to date. So, use clearok().
|
||||
*/
|
||||
if (repaint)
|
||||
clearok(curscr, 1);
|
||||
/*
|
||||
* Only do an actual refresh, when this is the focus window,
|
||||
* i.e. the one holding the cursor. This assumes that refresh
|
||||
* is called for that window after refreshing the others.
|
||||
* This prevents the cursor being drawn in the other windows.
|
||||
*/
|
||||
return (wnoutrefresh(stdscr) == ERR ||
|
||||
wnoutrefresh(win) == ERR ||
|
||||
(sp == clp->focus && doupdate() == ERR));
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_rdiv --
|
||||
* Draw a dividing line between two vertically split screens.
|
||||
*/
|
||||
static void
|
||||
cl_rdiv(SCR *sp)
|
||||
{
|
||||
size_t cnt;
|
||||
|
||||
for (cnt = 0; cnt < sp->rows - 1; ++cnt) {
|
||||
wmove(stdscr, sp->roff + cnt, sp->cols + sp->coff);
|
||||
waddch(stdscr, '|');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_rename --
|
||||
* Rename the file.
|
||||
*
|
||||
* PUBLIC: int cl_rename __P((SCR *, char *, int));
|
||||
*/
|
||||
int
|
||||
cl_rename(SCR *sp, char *name, int on)
|
||||
{
|
||||
CL_PRIVATE *clp;
|
||||
FILE *pfp;
|
||||
GS *gp;
|
||||
char buf[256], *p;
|
||||
|
||||
gp = sp->gp;
|
||||
clp = CLP(sp);
|
||||
|
||||
if (on) {
|
||||
clp->focus = sp;
|
||||
if (!F_ISSET(clp, CL_RENAME_OK))
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* We can only rename windows for xterm.
|
||||
*/
|
||||
if (strncmp(OG_STR(gp, GO_TERM), "xterm", sizeof("xterm") - 1))
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Try and figure out the current name of this window. There
|
||||
* are two forms of the xwininfo output I've seen:
|
||||
*
|
||||
* Window id: 0x400000d "name"
|
||||
* Window id: 0x140000d (name)
|
||||
*/
|
||||
#define COMMAND \
|
||||
"expr \"`xwininfo -id $WINDOWID | grep id:`\" : '.* [\"(]\\(.*\\)[\")]'"
|
||||
|
||||
if (clp->oname == NULL &&
|
||||
(pfp = popen(COMMAND, "r")) != NULL) {
|
||||
if (fgets(buf, sizeof(buf), pfp) != NULL &&
|
||||
(p = strchr(buf, '\n')) != NULL) {
|
||||
*p = '\0';
|
||||
clp->oname = strdup(buf);
|
||||
}
|
||||
(void)fclose(pfp);
|
||||
}
|
||||
|
||||
cl_setname(gp, name);
|
||||
|
||||
F_SET(clp, CL_RENAME);
|
||||
} else
|
||||
if (F_ISSET(clp, CL_RENAME)) {
|
||||
cl_setname(gp, clp->oname);
|
||||
|
||||
F_CLR(clp, CL_RENAME);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_setname --
|
||||
* Set a X11 icon/window name.
|
||||
*
|
||||
* PUBLIC: void cl_setname __P((GS *, char *));
|
||||
*/
|
||||
void
|
||||
cl_setname(GS *gp, char *name)
|
||||
{
|
||||
/* X11 xterm escape sequence to rename the icon/window. */
|
||||
#define XTERM_RENAME "\033]0;%s\007"
|
||||
|
||||
(void)printf(XTERM_RENAME, name == NULL ? OG_STR(gp, GO_TERM) : name);
|
||||
(void)fflush(stdout);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_split --
|
||||
* Split a screen.
|
||||
*
|
||||
* PUBLIC: int cl_split __P((SCR *, SCR *));
|
||||
*/
|
||||
int
|
||||
cl_split(SCR *origp, SCR *newp)
|
||||
{
|
||||
CL_PRIVATE *clp;
|
||||
|
||||
clp = CLP(origp);
|
||||
F_SET(clp, CL_LAYOUT);
|
||||
|
||||
if (CLSP(origp))
|
||||
delwin(CLSP(origp));
|
||||
|
||||
origp->cl_private = subwin(stdscr, origp->rows, origp->cols,
|
||||
origp->roff, origp->coff);
|
||||
newp->cl_private = subwin(stdscr, newp->rows, newp->cols,
|
||||
newp->roff, newp->coff);
|
||||
|
||||
/* origp is the original screen, giving up space to newp. */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_suspend --
|
||||
* Suspend a screen.
|
||||
*
|
||||
* PUBLIC: int cl_suspend __P((SCR *, int *));
|
||||
*/
|
||||
int
|
||||
cl_suspend(SCR *sp, int *allowedp)
|
||||
{
|
||||
struct termios t;
|
||||
CL_PRIVATE *clp;
|
||||
WINDOW *win;
|
||||
GS *gp;
|
||||
size_t y, x;
|
||||
int changed;
|
||||
|
||||
gp = sp->gp;
|
||||
clp = CLP(sp);
|
||||
win = CLSP(sp) ? CLSP(sp) : stdscr;
|
||||
*allowedp = 1;
|
||||
|
||||
/*
|
||||
* The ex implementation of this function isn't needed by screens not
|
||||
* supporting ex commands that require full terminal canonical mode
|
||||
* (e.g. :suspend).
|
||||
*
|
||||
* The vi implementation of this function isn't needed by screens not
|
||||
* supporting vi process suspension, i.e. any screen that isn't backed
|
||||
* by a UNIX shell.
|
||||
*
|
||||
* Setting allowedp to 0 will cause the editor to reject the command.
|
||||
*/
|
||||
if (F_ISSET(sp, SC_EX)) {
|
||||
/* Save the terminal settings, and restore the original ones. */
|
||||
if (F_ISSET(clp, CL_STDIN_TTY)) {
|
||||
(void)tcgetattr(STDIN_FILENO, &t);
|
||||
(void)tcsetattr(STDIN_FILENO,
|
||||
TCSASOFT | TCSADRAIN, &clp->orig);
|
||||
}
|
||||
|
||||
/* Stop the process group. */
|
||||
(void)kill(0, SIGTSTP);
|
||||
|
||||
/* Time passes ... */
|
||||
|
||||
/* Restore terminal settings. */
|
||||
if (F_ISSET(clp, CL_STDIN_TTY))
|
||||
(void)tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &t);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move to the lower left-hand corner of the screen.
|
||||
*
|
||||
* XXX
|
||||
* Not sure this is necessary in System V implementations, but it
|
||||
* shouldn't hurt.
|
||||
*/
|
||||
getyx(win, y, x);
|
||||
(void)wmove(win, LINES - 1, 0);
|
||||
(void)wrefresh(win);
|
||||
|
||||
/*
|
||||
* Temporarily end the screen. System V introduced a semantic where
|
||||
* endwin() could be restarted. We use it because restarting curses
|
||||
* from scratch often fails in System V. 4BSD curses didn't support
|
||||
* restarting after endwin(), so we have to do what clean up we can
|
||||
* without calling it.
|
||||
*/
|
||||
/* Save the terminal settings. */
|
||||
(void)tcgetattr(STDIN_FILENO, &t);
|
||||
|
||||
/* Restore the cursor keys to normal mode. */
|
||||
(void)keypad(stdscr, FALSE);
|
||||
|
||||
/* Restore the window name. */
|
||||
(void)cl_rename(sp, NULL, 0);
|
||||
|
||||
#ifdef HAVE_BSD_CURSES
|
||||
(void)cl_attr(sp, SA_ALTERNATE, 0);
|
||||
#else
|
||||
(void)endwin();
|
||||
#endif
|
||||
/*
|
||||
* XXX
|
||||
* Restore the original terminal settings. This is bad -- the
|
||||
* reset can cause character loss from the tty queue. However,
|
||||
* we can't call endwin() in BSD curses implementations, and too
|
||||
* many System V curses implementations don't get it right.
|
||||
*/
|
||||
(void)tcsetattr(STDIN_FILENO, TCSADRAIN | TCSASOFT, &clp->orig);
|
||||
|
||||
/* Stop the process group. */
|
||||
(void)kill(0, SIGTSTP);
|
||||
|
||||
/* Time passes ... */
|
||||
|
||||
/*
|
||||
* If we received a killer signal, we're done. Leave everything
|
||||
* unchanged. In addition, the terminal has already been reset
|
||||
* correctly, so leave it alone.
|
||||
*/
|
||||
if (clp->killersig) {
|
||||
F_CLR(clp, CL_SCR_EX_INIT | CL_SCR_VI_INIT);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Restore terminal settings. */
|
||||
wrefresh(win); /* Needed on SunOs/Solaris ? */
|
||||
if (F_ISSET(clp, CL_STDIN_TTY))
|
||||
(void)tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &t);
|
||||
|
||||
#ifdef HAVE_BSD_CURSES
|
||||
(void)cl_attr(sp, SA_ALTERNATE, 1);
|
||||
#endif
|
||||
|
||||
/* Set the window name. */
|
||||
(void)cl_rename(sp, sp->frp->name, 1);
|
||||
|
||||
/* Put the cursor keys into application mode. */
|
||||
(void)keypad(stdscr, TRUE);
|
||||
|
||||
/* Refresh and repaint the screen. */
|
||||
(void)wmove(win, y, x);
|
||||
(void)cl_refresh(sp, 1);
|
||||
|
||||
/* If the screen changed size, set the SIGWINCH bit. */
|
||||
if (cl_ssize(sp, 1, NULL, NULL, &changed))
|
||||
return (1);
|
||||
if (changed)
|
||||
F_SET(CLP(sp), CL_SIGWINCH);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_usage --
|
||||
* Print out the curses usage messages.
|
||||
*
|
||||
* PUBLIC: void cl_usage __P((void));
|
||||
*/
|
||||
void
|
||||
cl_usage(void)
|
||||
{
|
||||
#define USAGE "\
|
||||
usage: ex [-eFRrSsv] [-c command] [-t tag] [-w size] [file ...]\n\
|
||||
usage: vi [-eFlRrSv] [-c command] [-t tag] [-w size] [file ...]\n"
|
||||
(void)fprintf(stderr, "%s", USAGE);
|
||||
#undef USAGE
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* gdbrefresh --
|
||||
* Stub routine so can flush out curses screen changes using gdb.
|
||||
*/
|
||||
int
|
||||
gdbrefresh(void)
|
||||
{
|
||||
refresh();
|
||||
return (0); /* XXX Convince gdb to run it. */
|
||||
}
|
||||
#endif
|
440
dist/nvi/cl/cl_main.c
vendored
Normal file
440
dist/nvi/cl/cl_main.c
vendored
Normal file
|
@ -0,0 +1,440 @@
|
|||
/* $NetBSD: cl_main.c,v 1.4 2011/09/16 16:13:41 joerg Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* Copyright (c) 1993, 1994, 1995, 1996
|
||||
* Keith Bostic. All rights reserved.
|
||||
*
|
||||
* See the LICENSE file for redistribution information.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "Id: cl_main.c,v 10.54 2001/07/29 19:07:27 skimo Exp (Berkeley) Date: 2001/07/29 19:07:27";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <bitstring.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../common/common.h"
|
||||
#include "../ip/extern.h"
|
||||
#include "cl.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
GS *__global_list; /* GLOBAL: List of screens. */
|
||||
sigset_t __sigblockset; /* GLOBAL: Blocked signals. */
|
||||
|
||||
static void cl_func_std __P((WIN *));
|
||||
#ifdef notused
|
||||
static void cl_end __P((CL_PRIVATE *));
|
||||
#endif
|
||||
static CL_PRIVATE *cl_init __P((WIN *));
|
||||
__dead static void perr __P((const char *, const char *));
|
||||
static int setsig __P((int, struct sigaction *, void (*)(int)));
|
||||
static void sig_end __P((GS *));
|
||||
static void term_init __P((const char *, const char *));
|
||||
|
||||
/*
|
||||
* main --
|
||||
* This is the main loop for the standalone curses editor.
|
||||
*/
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
static int reenter;
|
||||
CL_PRIVATE *clp;
|
||||
GS *gp;
|
||||
WIN *wp;
|
||||
size_t rows, cols;
|
||||
int rval;
|
||||
char **p_av, **t_av;
|
||||
const char *ttype;
|
||||
|
||||
/* If loaded at 0 and jumping through a NULL pointer, stop. */
|
||||
if (reenter++)
|
||||
abort();
|
||||
|
||||
/* Create and initialize the global structure. */
|
||||
__global_list = gp = gs_init(argv[0]);
|
||||
|
||||
/*
|
||||
* Strip out any arguments that vi isn't going to understand. There's
|
||||
* no way to portably call getopt twice, so arguments parsed here must
|
||||
* be removed from the argument list.
|
||||
*/
|
||||
for (p_av = t_av = argv;;) {
|
||||
if (*t_av == NULL) {
|
||||
*p_av = NULL;
|
||||
break;
|
||||
}
|
||||
if (!strcmp(*t_av, "--")) {
|
||||
while ((*p_av++ = *t_av++) != NULL);
|
||||
break;
|
||||
}
|
||||
*p_av++ = *t_av++;
|
||||
}
|
||||
|
||||
/* Create new window */
|
||||
wp = gs_new_win(gp);
|
||||
|
||||
/* Create and initialize the CL_PRIVATE structure. */
|
||||
clp = cl_init(wp);
|
||||
|
||||
/*
|
||||
* Initialize the terminal information.
|
||||
*
|
||||
* We have to know what terminal it is from the start, since we may
|
||||
* have to use termcap/terminfo to find out how big the screen is.
|
||||
*/
|
||||
if ((ttype = getenv("TERM")) == NULL) {
|
||||
if (isatty(STDIN_FILENO))
|
||||
fprintf(stderr, "%s: warning: TERM is not set\n",
|
||||
gp->progname);
|
||||
ttype = "unknown";
|
||||
}
|
||||
term_init(gp->progname, ttype);
|
||||
|
||||
/* Add the terminal type to the global structure. */
|
||||
if ((OG_D_STR(gp, GO_TERM) =
|
||||
OG_STR(gp, GO_TERM) = strdup(ttype)) == NULL)
|
||||
perr(gp->progname, NULL);
|
||||
|
||||
/* Figure out how big the screen is. */
|
||||
if (cl_ssize(NULL, 0, &rows, &cols, NULL))
|
||||
exit (1);
|
||||
|
||||
/* Add the rows and columns to the global structure. */
|
||||
OG_VAL(gp, GO_LINES) = OG_D_VAL(gp, GO_LINES) = rows;
|
||||
OG_VAL(gp, GO_COLUMNS) = OG_D_VAL(gp, GO_COLUMNS) = cols;
|
||||
|
||||
/* Ex wants stdout to be buffered. */
|
||||
(void)setvbuf(stdout, NULL, _IOFBF, 0);
|
||||
|
||||
/* Start catching signals. */
|
||||
if (sig_init(gp, NULL))
|
||||
exit (1);
|
||||
|
||||
/* Run ex/vi. */
|
||||
rval = editor(wp, argc, argv);
|
||||
|
||||
/* Clean out the global structure. */
|
||||
gs_end(gp);
|
||||
|
||||
/* Clean up signals. */
|
||||
sig_end(gp);
|
||||
|
||||
/* Clean up the terminal. */
|
||||
(void)cl_quit(gp);
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Reset the O_MESG option.
|
||||
*/
|
||||
if (clp->tgw != TGW_UNKNOWN)
|
||||
(void)cl_omesg(NULL, clp, clp->tgw == TGW_SET);
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Reset the X11 xterm icon/window name.
|
||||
*/
|
||||
if (F_ISSET(clp, CL_RENAME))
|
||||
cl_setname(gp, clp->oname);
|
||||
|
||||
/* If a killer signal arrived, pretend we just got it. */
|
||||
if (clp->killersig) {
|
||||
(void)signal(clp->killersig, SIG_DFL);
|
||||
(void)kill(getpid(), clp->killersig);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* Free the global and CL private areas. */
|
||||
#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
|
||||
cl_end(clp);
|
||||
free(gp);
|
||||
#endif
|
||||
|
||||
exit (rval);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_init --
|
||||
* Create and partially initialize the CL structure.
|
||||
*/
|
||||
static CL_PRIVATE *
|
||||
cl_init(WIN *wp)
|
||||
{
|
||||
CL_PRIVATE *clp;
|
||||
int fd;
|
||||
GS *gp;
|
||||
|
||||
gp = wp->gp;
|
||||
|
||||
/* Allocate the CL private structure. */
|
||||
CALLOC_NOMSG(NULL, clp, CL_PRIVATE *, 1, sizeof(CL_PRIVATE));
|
||||
if (clp == NULL)
|
||||
perr(gp->progname, NULL);
|
||||
gp->cl_private = clp;
|
||||
|
||||
/*
|
||||
* Set the CL_STDIN_TTY flag. It's purpose is to avoid setting
|
||||
* and resetting the tty if the input isn't from there. We also
|
||||
* use the same test to determine if we're running a script or
|
||||
* not.
|
||||
*/
|
||||
if (isatty(STDIN_FILENO))
|
||||
F_SET(clp, CL_STDIN_TTY);
|
||||
else
|
||||
F_SET(gp, G_SCRIPTED);
|
||||
|
||||
/*
|
||||
* We expect that if we've lost our controlling terminal that the
|
||||
* open() (but not the tcgetattr()) will fail.
|
||||
*/
|
||||
if (F_ISSET(clp, CL_STDIN_TTY)) {
|
||||
if (tcgetattr(STDIN_FILENO, &clp->orig) == -1)
|
||||
goto tcfail;
|
||||
} else if ((fd = open(_PATH_TTY, O_RDONLY, 0)) != -1) {
|
||||
if (tcgetattr(fd, &clp->orig) == -1) {
|
||||
tcfail: perr(gp->progname, "tcgetattr");
|
||||
exit (1);
|
||||
}
|
||||
(void)close(fd);
|
||||
}
|
||||
|
||||
/* Initialize the list of curses functions. */
|
||||
cl_func_std(wp);
|
||||
|
||||
return (clp);
|
||||
}
|
||||
|
||||
#ifdef notused
|
||||
/*
|
||||
* cl_end --
|
||||
* Discard the CL structure.
|
||||
*/
|
||||
static void
|
||||
cl_end(CL_PRIVATE *clp)
|
||||
{
|
||||
if (clp->oname != NULL)
|
||||
free(clp->oname);
|
||||
free(clp);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* term_init --
|
||||
* Initialize terminal information.
|
||||
*/
|
||||
static void
|
||||
term_init(const char *name, const char *ttype)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Set up the terminal database information. */
|
||||
setupterm(__UNCONST(ttype), STDOUT_FILENO, &err);
|
||||
switch (err) {
|
||||
case -1:
|
||||
(void)fprintf(stderr,
|
||||
"%s: No terminal database found\n", name);
|
||||
exit (1);
|
||||
case 0:
|
||||
(void)fprintf(stderr,
|
||||
"%s: %s: unknown terminal type\n", name, ttype);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
#define GLOBAL_CLP \
|
||||
CL_PRIVATE *clp = GCLP(__global_list);
|
||||
static void
|
||||
h_hup(int signo)
|
||||
{
|
||||
GLOBAL_CLP;
|
||||
|
||||
F_SET(clp, CL_SIGHUP);
|
||||
clp->killersig = SIGHUP;
|
||||
}
|
||||
|
||||
static void
|
||||
h_int(int signo)
|
||||
{
|
||||
GLOBAL_CLP;
|
||||
|
||||
F_SET(clp, CL_SIGINT);
|
||||
}
|
||||
|
||||
static void
|
||||
h_term(int signo)
|
||||
{
|
||||
GLOBAL_CLP;
|
||||
|
||||
F_SET(clp, CL_SIGTERM);
|
||||
clp->killersig = SIGTERM;
|
||||
}
|
||||
|
||||
static void
|
||||
h_winch(int signo)
|
||||
{
|
||||
GLOBAL_CLP;
|
||||
|
||||
F_SET(clp, CL_SIGWINCH);
|
||||
}
|
||||
#undef GLOBAL_CLP
|
||||
|
||||
/*
|
||||
* sig_init --
|
||||
* Initialize signals.
|
||||
*
|
||||
* PUBLIC: int sig_init __P((GS *, SCR *));
|
||||
*/
|
||||
int
|
||||
sig_init(GS *gp, SCR *sp)
|
||||
{
|
||||
CL_PRIVATE *clp;
|
||||
|
||||
clp = GCLP(gp);
|
||||
|
||||
if (sp == NULL) {
|
||||
(void)sigemptyset(&__sigblockset);
|
||||
if (sigaddset(&__sigblockset, SIGHUP) ||
|
||||
setsig(SIGHUP, &clp->oact[INDX_HUP], h_hup) ||
|
||||
sigaddset(&__sigblockset, SIGINT) ||
|
||||
setsig(SIGINT, &clp->oact[INDX_INT], h_int) ||
|
||||
sigaddset(&__sigblockset, SIGTERM) ||
|
||||
setsig(SIGTERM, &clp->oact[INDX_TERM], h_term)
|
||||
#ifdef SIGWINCH
|
||||
||
|
||||
sigaddset(&__sigblockset, SIGWINCH) ||
|
||||
setsig(SIGWINCH, &clp->oact[INDX_WINCH], h_winch)
|
||||
#endif
|
||||
) {
|
||||
perr(gp->progname, NULL);
|
||||
return (1);
|
||||
}
|
||||
} else
|
||||
if (setsig(SIGHUP, NULL, h_hup) ||
|
||||
setsig(SIGINT, NULL, h_int) ||
|
||||
setsig(SIGTERM, NULL, h_term)
|
||||
#ifdef SIGWINCH
|
||||
||
|
||||
setsig(SIGWINCH, NULL, h_winch)
|
||||
#endif
|
||||
) {
|
||||
msgq(sp, M_SYSERR, "signal-reset");
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* setsig --
|
||||
* Set a signal handler.
|
||||
*/
|
||||
static int
|
||||
setsig(int signo, struct sigaction *oactp, void (*handler) (int))
|
||||
{
|
||||
struct sigaction act;
|
||||
|
||||
/*
|
||||
* Use sigaction(2), not signal(3), since we don't always want to
|
||||
* restart system calls. The example is when waiting for a command
|
||||
* mode keystroke and SIGWINCH arrives. Besides, you can't portably
|
||||
* restart system calls (thanks, POSIX!). On the other hand, you
|
||||
* can't portably NOT restart system calls (thanks, Sun!). SunOS
|
||||
* used SA_INTERRUPT as their extension to NOT restart read calls.
|
||||
* We sure hope nobody else used it for anything else. Mom told me
|
||||
* there'd be days like this. She just never told me that there'd
|
||||
* be so many.
|
||||
*/
|
||||
act.sa_handler = handler;
|
||||
sigemptyset(&act.sa_mask);
|
||||
|
||||
#ifdef SA_INTERRUPT
|
||||
act.sa_flags = SA_INTERRUPT;
|
||||
#else
|
||||
act.sa_flags = 0;
|
||||
#endif
|
||||
return (sigaction(signo, &act, oactp));
|
||||
}
|
||||
|
||||
/*
|
||||
* sig_end --
|
||||
* End signal setup.
|
||||
*/
|
||||
static void
|
||||
sig_end(GS *gp)
|
||||
{
|
||||
CL_PRIVATE *clp;
|
||||
|
||||
clp = GCLP(gp);
|
||||
(void)sigaction(SIGHUP, NULL, &clp->oact[INDX_HUP]);
|
||||
(void)sigaction(SIGINT, NULL, &clp->oact[INDX_INT]);
|
||||
(void)sigaction(SIGTERM, NULL, &clp->oact[INDX_TERM]);
|
||||
#ifdef SIGWINCH
|
||||
(void)sigaction(SIGWINCH, NULL, &clp->oact[INDX_WINCH]);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_func_std --
|
||||
* Initialize the standard curses functions.
|
||||
*/
|
||||
static void
|
||||
cl_func_std(WIN *wp)
|
||||
{
|
||||
GS *gp;
|
||||
|
||||
gp = wp->gp;
|
||||
|
||||
gp->scr_addstr = cl_addstr;
|
||||
gp->scr_waddstr = cl_waddstr;
|
||||
gp->scr_attr = cl_attr;
|
||||
gp->scr_baud = cl_baud;
|
||||
gp->scr_bell = cl_bell;
|
||||
gp->scr_busy = NULL;
|
||||
gp->scr_child = NULL;
|
||||
gp->scr_clrtoeol = cl_clrtoeol;
|
||||
gp->scr_cursor = cl_cursor;
|
||||
gp->scr_deleteln = cl_deleteln;
|
||||
gp->scr_reply = NULL;
|
||||
gp->scr_discard = cl_discard;
|
||||
gp->scr_event = cl_event;
|
||||
gp->scr_ex_adjust = cl_ex_adjust;
|
||||
gp->scr_fmap = cl_fmap;
|
||||
gp->scr_insertln = cl_insertln;
|
||||
gp->scr_keyval = cl_keyval;
|
||||
gp->scr_move = cl_move;
|
||||
wp->scr_msg = NULL;
|
||||
gp->scr_optchange = cl_optchange;
|
||||
gp->scr_refresh = cl_refresh;
|
||||
gp->scr_rename = cl_rename;
|
||||
gp->scr_screen = cl_screen;
|
||||
gp->scr_split = cl_split;
|
||||
gp->scr_suspend = cl_suspend;
|
||||
gp->scr_usage = cl_usage;
|
||||
}
|
||||
|
||||
/*
|
||||
* perr --
|
||||
* Print system error.
|
||||
*/
|
||||
static void
|
||||
perr(const char *name, const char *msg)
|
||||
{
|
||||
(void)fprintf(stderr, "%s:", name);
|
||||
if (msg != NULL)
|
||||
(void)fprintf(stderr, "%s:", msg);
|
||||
(void)fprintf(stderr, "%s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
312
dist/nvi/cl/cl_read.c
vendored
Normal file
312
dist/nvi/cl/cl_read.c
vendored
Normal file
|
@ -0,0 +1,312 @@
|
|||
/* $NetBSD: cl_read.c,v 1.2 2008/12/05 22:51:42 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* Copyright (c) 1993, 1994, 1995, 1996
|
||||
* Keith Bostic. All rights reserved.
|
||||
*
|
||||
* See the LICENSE file for redistribution information.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "Id: cl_read.c,v 10.29 2001/08/18 21:51:59 skimo Exp (Berkeley) Date: 2001/08/18 21:51:59";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/queue.h>
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <bitstring.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../common/common.h"
|
||||
#include "../ex/script.h"
|
||||
#include "cl.h"
|
||||
|
||||
/* Pollution by Solaris curses. */
|
||||
#undef columns
|
||||
#undef lines
|
||||
|
||||
static input_t cl_read __P((SCR *,
|
||||
u_int32_t, char *, size_t, int *, struct timeval *));
|
||||
static int cl_resize __P((SCR *, size_t, size_t));
|
||||
|
||||
/*
|
||||
* cl_event --
|
||||
* Return a single event.
|
||||
*
|
||||
* PUBLIC: int cl_event __P((SCR *, EVENT *, u_int32_t, int));
|
||||
*/
|
||||
int
|
||||
cl_event(SCR *sp, EVENT *evp, u_int32_t flags, int ms)
|
||||
{
|
||||
struct timeval t, *tp;
|
||||
CL_PRIVATE *clp;
|
||||
size_t lines, columns;
|
||||
int changed, nr = 0;
|
||||
const CHAR_T *wp;
|
||||
size_t wlen;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* Queue signal based events. We never clear SIGHUP or SIGTERM events,
|
||||
* so that we just keep returning them until the editor dies.
|
||||
*/
|
||||
clp = CLP(sp);
|
||||
retest: if (LF_ISSET(EC_INTERRUPT) || F_ISSET(clp, CL_SIGINT)) {
|
||||
if (F_ISSET(clp, CL_SIGINT)) {
|
||||
F_CLR(clp, CL_SIGINT);
|
||||
evp->e_event = E_INTERRUPT;
|
||||
} else
|
||||
evp->e_event = E_TIMEOUT;
|
||||
return (0);
|
||||
}
|
||||
if (F_ISSET(clp, CL_SIGHUP | CL_SIGTERM | CL_SIGWINCH)) {
|
||||
if (F_ISSET(clp, CL_SIGHUP)) {
|
||||
evp->e_event = E_SIGHUP;
|
||||
return (0);
|
||||
}
|
||||
if (F_ISSET(clp, CL_SIGTERM)) {
|
||||
evp->e_event = E_SIGTERM;
|
||||
return (0);
|
||||
}
|
||||
if (F_ISSET(clp, CL_SIGWINCH)) {
|
||||
F_CLR(clp, CL_SIGWINCH);
|
||||
if (cl_ssize(sp, 1, &lines, &columns, &changed))
|
||||
return (1);
|
||||
if (changed) {
|
||||
(void)cl_resize(sp, lines, columns);
|
||||
evp->e_event = E_WRESIZE;
|
||||
return (0);
|
||||
}
|
||||
/* No real change, ignore the signal. */
|
||||
}
|
||||
}
|
||||
|
||||
/* Set timer. */
|
||||
if (ms == 0)
|
||||
tp = NULL;
|
||||
else {
|
||||
t.tv_sec = ms / 1000;
|
||||
t.tv_usec = (ms % 1000) * 1000;
|
||||
tp = &t;
|
||||
}
|
||||
|
||||
/* Read input characters. */
|
||||
read:
|
||||
switch (cl_read(sp, LF_ISSET(EC_QUOTED | EC_RAW),
|
||||
clp->ibuf + clp->skip, SIZE(clp->ibuf) - clp->skip, &nr, tp)) {
|
||||
case INP_OK:
|
||||
rc = INPUT2INT5(sp, clp->cw, clp->ibuf, nr + clp->skip,
|
||||
wp, wlen);
|
||||
evp->e_csp = __UNCONST(wp);
|
||||
evp->e_len = wlen;
|
||||
evp->e_event = E_STRING;
|
||||
if (rc < 0) {
|
||||
int n = -rc;
|
||||
memmove(clp->ibuf, clp->ibuf + nr + clp->skip - n, n);
|
||||
clp->skip = n;
|
||||
if (wlen == 0)
|
||||
goto read;
|
||||
} else if (rc == 0)
|
||||
clp->skip = 0;
|
||||
else
|
||||
msgq(sp, M_ERR, "323|Invalid input. Truncated.");
|
||||
break;
|
||||
case INP_ERR:
|
||||
evp->e_event = E_ERR;
|
||||
break;
|
||||
case INP_EOF:
|
||||
evp->e_event = E_EOF;
|
||||
break;
|
||||
case INP_INTR:
|
||||
goto retest;
|
||||
case INP_TIMEOUT:
|
||||
evp->e_event = E_TIMEOUT;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_read --
|
||||
* Read characters from the input.
|
||||
*/
|
||||
static input_t
|
||||
cl_read(SCR *sp, u_int32_t flags, char *bp, size_t blen, int *nrp, struct timeval *tp)
|
||||
{
|
||||
struct termios term1, term2;
|
||||
struct timeval poll;
|
||||
CL_PRIVATE *clp;
|
||||
GS *gp;
|
||||
fd_set rdfd;
|
||||
input_t rval;
|
||||
int maxfd, nr, term_reset;
|
||||
|
||||
gp = sp->gp;
|
||||
clp = CLP(sp);
|
||||
term_reset = 0;
|
||||
|
||||
/*
|
||||
* 1: A read from a file or a pipe. In this case, the reads
|
||||
* never timeout regardless. This means that we can hang
|
||||
* when trying to complete a map, but we're going to hang
|
||||
* on the next read anyway.
|
||||
*/
|
||||
if (!F_ISSET(clp, CL_STDIN_TTY)) {
|
||||
switch (nr = read(STDIN_FILENO, bp, blen)) {
|
||||
case 0:
|
||||
return (INP_EOF);
|
||||
case -1:
|
||||
goto err;
|
||||
default:
|
||||
*nrp = nr;
|
||||
return (INP_OK);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/*
|
||||
* 2: A read with an associated timeout, e.g., trying to complete
|
||||
* a map sequence. If input exists, we fall into #3.
|
||||
*/
|
||||
FD_ZERO(&rdfd);
|
||||
poll.tv_sec = 0;
|
||||
poll.tv_usec = 0;
|
||||
if (tp != NULL) {
|
||||
FD_SET(STDIN_FILENO, &rdfd);
|
||||
switch (select(STDIN_FILENO + 1,
|
||||
&rdfd, NULL, NULL, tp == NULL ? &poll : tp)) {
|
||||
case 0:
|
||||
return (INP_TIMEOUT);
|
||||
case -1:
|
||||
goto err;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The user can enter a key in the editor to quote a character. If we
|
||||
* get here and the next key is supposed to be quoted, do what we can.
|
||||
* Reset the tty so that the user can enter a ^C, ^Q, ^S. There's an
|
||||
* obvious race here, when the key has already been entered, but there's
|
||||
* nothing that we can do to fix that problem.
|
||||
*
|
||||
* The editor can ask for the next literal character even thought it's
|
||||
* generally running in line-at-a-time mode. Do what we can.
|
||||
*/
|
||||
if (LF_ISSET(EC_QUOTED | EC_RAW) && !tcgetattr(STDIN_FILENO, &term1)) {
|
||||
term_reset = 1;
|
||||
if (LF_ISSET(EC_QUOTED)) {
|
||||
term2 = term1;
|
||||
term2.c_lflag &= ~ISIG;
|
||||
term2.c_iflag &= ~(IXON | IXOFF);
|
||||
(void)tcsetattr(STDIN_FILENO,
|
||||
TCSASOFT | TCSADRAIN, &term2);
|
||||
} else
|
||||
(void)tcsetattr(STDIN_FILENO,
|
||||
TCSASOFT | TCSADRAIN, &clp->vi_enter);
|
||||
}
|
||||
|
||||
/*
|
||||
* 3: Wait for input.
|
||||
*
|
||||
* Select on the command input and scripting window file descriptors.
|
||||
* It's ugly that we wait on scripting file descriptors here, but it's
|
||||
* the only way to keep from locking out scripting windows.
|
||||
*/
|
||||
if (F_ISSET(gp, G_SCRWIN)) {
|
||||
FD_ZERO(&rdfd);
|
||||
FD_SET(STDIN_FILENO, &rdfd);
|
||||
maxfd = STDIN_FILENO;
|
||||
if (sscr_check_input(sp, &rdfd, maxfd))
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* 4: Read the input.
|
||||
*
|
||||
* !!!
|
||||
* What's going on here is some scary stuff. Ex runs the terminal in
|
||||
* canonical mode. So, the <newline> character terminating a line of
|
||||
* input is returned in the buffer, but a trailing <EOF> character is
|
||||
* not similarly included. As ex uses 0<EOF> and ^<EOF> as autoindent
|
||||
* commands, it has to see the trailing <EOF> characters to determine
|
||||
* the difference between the user entering "0ab" and "0<EOF>ab". We
|
||||
* leave an extra slot in the buffer, so that we can add a trailing
|
||||
* <EOF> character if the buffer isn't terminated by a <newline>. We
|
||||
* lose if the buffer is too small for the line and exactly N characters
|
||||
* are entered followed by an <EOF> character.
|
||||
*/
|
||||
#define ONE_FOR_EOF 1
|
||||
switch (nr = read(STDIN_FILENO, bp, blen - ONE_FOR_EOF)) {
|
||||
case 0: /* EOF. */
|
||||
/*
|
||||
* ^D in canonical mode returns a read of 0, i.e. EOF. EOF is
|
||||
* a valid command, but we don't want to loop forever because
|
||||
* the terminal driver is returning EOF because the user has
|
||||
* disconnected. The editor will almost certainly try to write
|
||||
* something before this fires, which should kill us, but You
|
||||
* Never Know.
|
||||
*/
|
||||
if (++clp->eof_count < 50) {
|
||||
bp[0] = clp->orig.c_cc[VEOF];
|
||||
*nrp = 1;
|
||||
rval = INP_OK;
|
||||
|
||||
} else
|
||||
rval = INP_EOF;
|
||||
break;
|
||||
case -1: /* Error or interrupt. */
|
||||
err: if (errno == EINTR)
|
||||
rval = INP_INTR;
|
||||
else {
|
||||
rval = INP_ERR;
|
||||
msgq(sp, M_SYSERR, "input");
|
||||
}
|
||||
break;
|
||||
default: /* Input characters. */
|
||||
if (F_ISSET(sp, SC_EX) && bp[nr - 1] != '\n')
|
||||
bp[nr++] = clp->orig.c_cc[VEOF];
|
||||
*nrp = nr;
|
||||
clp->eof_count = 0;
|
||||
rval = INP_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Restore the terminal state if it was modified. */
|
||||
if (term_reset)
|
||||
(void)tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &term1);
|
||||
return (rval);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_resize --
|
||||
* Reset the options for a resize event.
|
||||
*/
|
||||
static int
|
||||
cl_resize(SCR *sp, size_t lines, size_t columns)
|
||||
{
|
||||
int rval;
|
||||
|
||||
rval = api_opts_set(sp, L("lines"), NULL, lines, 0);
|
||||
if (api_opts_set(sp, L("columns"), NULL, columns, 0))
|
||||
rval = 1;
|
||||
return (rval);
|
||||
}
|
580
dist/nvi/cl/cl_screen.c
vendored
Normal file
580
dist/nvi/cl/cl_screen.c
vendored
Normal file
|
@ -0,0 +1,580 @@
|
|||
/* $NetBSD: cl_screen.c,v 1.2 2008/12/05 22:51:42 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* Copyright (c) 1993, 1994, 1995, 1996
|
||||
* Keith Bostic. All rights reserved.
|
||||
*
|
||||
* See the LICENSE file for redistribution information.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "Id: cl_screen.c,v 10.56 2002/05/03 19:59:44 skimo Exp (Berkeley) Date: 2002/05/03 19:59:44";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <bitstring.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../common/common.h"
|
||||
#include "cl.h"
|
||||
|
||||
static int cl_ex_end __P((GS *));
|
||||
static int cl_ex_init __P((SCR *));
|
||||
static void cl_freecap __P((CL_PRIVATE *));
|
||||
static int cl_vi_end __P((GS *));
|
||||
static int cl_vi_init __P((SCR *));
|
||||
static int cl_putenv __P((SCR *, const char *, const char *, u_long));
|
||||
|
||||
/*
|
||||
* cl_screen --
|
||||
* Switch screen types.
|
||||
*
|
||||
* PUBLIC: int cl_screen __P((SCR *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
cl_screen(SCR *sp, u_int32_t flags)
|
||||
{
|
||||
CL_PRIVATE *clp;
|
||||
WINDOW *win;
|
||||
GS *gp;
|
||||
|
||||
gp = sp->gp;
|
||||
clp = CLP(sp);
|
||||
win = CLSP(sp) ? CLSP(sp) : stdscr;
|
||||
|
||||
/* See if the current information is incorrect. */
|
||||
if (F_ISSET(gp, G_SRESTART)) {
|
||||
if (CLSP(sp)) {
|
||||
delwin(CLSP(sp));
|
||||
sp->cl_private = NULL;
|
||||
}
|
||||
if (cl_quit(gp))
|
||||
return (1);
|
||||
F_CLR(gp, G_SRESTART);
|
||||
}
|
||||
|
||||
/* See if we're already in the right mode. */
|
||||
if ((LF_ISSET(SC_EX) && F_ISSET(sp, SC_SCR_EX)) ||
|
||||
(LF_ISSET(SC_VI) && F_ISSET(sp, SC_SCR_VI)))
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* Fake leaving ex mode.
|
||||
*
|
||||
* We don't actually exit ex or vi mode unless forced (e.g. by a window
|
||||
* size change). This is because many curses implementations can't be
|
||||
* called twice in a single program. Plus, it's faster. If the editor
|
||||
* "leaves" vi to enter ex, when it exits ex we'll just fall back into
|
||||
* vi.
|
||||
*/
|
||||
if (F_ISSET(sp, SC_SCR_EX))
|
||||
F_CLR(sp, SC_SCR_EX);
|
||||
|
||||
/*
|
||||
* Fake leaving vi mode.
|
||||
*
|
||||
* Clear out the rest of the screen if we're in the middle of a split
|
||||
* screen. Move to the last line in the current screen -- this makes
|
||||
* terminal scrolling happen naturally. Note: *don't* move past the
|
||||
* end of the screen, as there are ex commands (e.g., :read ! cat file)
|
||||
* that don't want to. Don't clear the info line, its contents may be
|
||||
* valid, e.g. :file|append.
|
||||
*/
|
||||
if (F_ISSET(sp, SC_SCR_VI)) {
|
||||
F_CLR(sp, SC_SCR_VI);
|
||||
|
||||
if (sp->q.cqe_next != (void *)&sp->wp->scrq) {
|
||||
(void)wmove(win, RLNO(sp, sp->rows), 0);
|
||||
wclrtobot(win);
|
||||
}
|
||||
(void)wmove(win, RLNO(sp, sp->rows) - 1, 0);
|
||||
wrefresh(win);
|
||||
}
|
||||
|
||||
/* Enter the requested mode. */
|
||||
if (LF_ISSET(SC_EX)) {
|
||||
if (cl_ex_init(sp))
|
||||
return (1);
|
||||
F_SET(clp, CL_IN_EX | CL_SCR_EX_INIT);
|
||||
|
||||
/*
|
||||
* If doing an ex screen for ex mode, move to the last line
|
||||
* on the screen.
|
||||
*/
|
||||
if (F_ISSET(sp, SC_EX) && clp->cup != NULL)
|
||||
tputs(tgoto(clp->cup,
|
||||
0, O_VAL(sp, O_LINES) - 1), 1, cl_putchar);
|
||||
} else {
|
||||
if (cl_vi_init(sp))
|
||||
return (1);
|
||||
F_CLR(clp, CL_IN_EX);
|
||||
F_SET(clp, CL_SCR_VI_INIT);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_quit --
|
||||
* Shutdown the screens.
|
||||
*
|
||||
* PUBLIC: int cl_quit __P((GS *));
|
||||
*/
|
||||
int
|
||||
cl_quit(GS *gp)
|
||||
{
|
||||
CL_PRIVATE *clp;
|
||||
int rval;
|
||||
|
||||
rval = 0;
|
||||
clp = GCLP(gp);
|
||||
|
||||
/*
|
||||
* If we weren't really running, ignore it. This happens if the
|
||||
* screen changes size before we've called curses.
|
||||
*/
|
||||
if (!F_ISSET(clp, CL_SCR_EX_INIT | CL_SCR_VI_INIT))
|
||||
return (0);
|
||||
|
||||
/* Clean up the terminal mappings. */
|
||||
if (cl_term_end(gp))
|
||||
rval = 1;
|
||||
|
||||
/* Really leave vi mode. */
|
||||
if (F_ISSET(clp, CL_STDIN_TTY) &&
|
||||
F_ISSET(clp, CL_SCR_VI_INIT) && cl_vi_end(gp))
|
||||
rval = 1;
|
||||
|
||||
/* Really leave ex mode. */
|
||||
if (F_ISSET(clp, CL_STDIN_TTY) &&
|
||||
F_ISSET(clp, CL_SCR_EX_INIT) && cl_ex_end(gp))
|
||||
rval = 1;
|
||||
|
||||
/*
|
||||
* If we were running ex when we quit, or we're using an implementation
|
||||
* of curses where endwin() doesn't get this right, restore the original
|
||||
* terminal modes.
|
||||
*
|
||||
* XXX
|
||||
* We always do this because it's too hard to figure out what curses
|
||||
* implementations get it wrong. It may discard type-ahead characters
|
||||
* from the tty queue.
|
||||
*/
|
||||
(void)tcsetattr(STDIN_FILENO, TCSADRAIN | TCSASOFT, &clp->orig);
|
||||
|
||||
F_CLR(clp, CL_SCR_EX_INIT | CL_SCR_VI_INIT);
|
||||
return (rval);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_vi_init --
|
||||
* Initialize the curses vi screen.
|
||||
*/
|
||||
static int
|
||||
cl_vi_init(SCR *sp)
|
||||
{
|
||||
CL_PRIVATE *clp;
|
||||
GS *gp;
|
||||
char *o_cols, *o_lines, *o_term;
|
||||
const char *ttype;
|
||||
|
||||
gp = sp->gp;
|
||||
clp = CLP(sp);
|
||||
|
||||
/* If already initialized, just set the terminal modes. */
|
||||
if (F_ISSET(clp, CL_SCR_VI_INIT))
|
||||
goto fast;
|
||||
|
||||
/* Curses vi always reads from (and writes to) a terminal. */
|
||||
if (!F_ISSET(clp, CL_STDIN_TTY) || !isatty(STDOUT_FILENO)) {
|
||||
msgq(sp, M_ERR,
|
||||
"016|Vi's standard input and output must be a terminal");
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* We'll need a terminal type. */
|
||||
if (opts_empty(sp, O_TERM, 0))
|
||||
return (1);
|
||||
ttype = O_STR(sp, O_TERM);
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Changing the row/column and terminal values is done by putting them
|
||||
* into the environment, which is then read by curses. What this loses
|
||||
* in ugliness, it makes up for in stupidity. We can't simply put the
|
||||
* values into the environment ourselves, because in the presence of a
|
||||
* kernel mechanism for returning the window size, entering values into
|
||||
* the environment will screw up future screen resizing events, e.g. if
|
||||
* the user enters a :shell command and then resizes their window. So,
|
||||
* if they weren't already in the environment, we make sure to delete
|
||||
* them immediately after setting them.
|
||||
*
|
||||
* XXX
|
||||
* Putting the TERM variable into the environment is necessary, even
|
||||
* though we're using newterm() here. We may be using initscr() as
|
||||
* the underlying function.
|
||||
*/
|
||||
o_term = getenv("TERM");
|
||||
cl_putenv(sp, "TERM", ttype, 0);
|
||||
o_lines = getenv("LINES");
|
||||
cl_putenv(sp, "LINES", NULL, (u_long)O_VAL(sp, O_LINES));
|
||||
o_cols = getenv("COLUMNS");
|
||||
cl_putenv(sp, "COLUMNS", NULL, (u_long)O_VAL(sp, O_COLUMNS));
|
||||
|
||||
/*
|
||||
* We don't care about the SCREEN reference returned by newterm, we
|
||||
* never have more than one SCREEN at a time.
|
||||
*
|
||||
* XXX
|
||||
* The SunOS initscr() can't be called twice. Don't even think about
|
||||
* using it. It fails in subtle ways (e.g. select(2) on fileno(stdin)
|
||||
* stops working). (The SVID notes that applications should only call
|
||||
* initscr() once.)
|
||||
*
|
||||
* XXX
|
||||
* The HP/UX newterm doesn't support the NULL first argument, so we
|
||||
* have to specify the terminal type.
|
||||
*/
|
||||
errno = 0;
|
||||
if (newterm(__UNCONST(ttype), stdout, stdin) == NULL) {
|
||||
if (errno)
|
||||
msgq(sp, M_SYSERR, "%s", ttype);
|
||||
else
|
||||
msgq(sp, M_ERR, "%s: unknown terminal type", ttype);
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (o_term == NULL)
|
||||
cl_unsetenv(sp, "TERM");
|
||||
if (o_lines == NULL)
|
||||
cl_unsetenv(sp, "LINES");
|
||||
if (o_cols == NULL)
|
||||
cl_unsetenv(sp, "COLUMNS");
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Someone got let out alone without adult supervision -- the SunOS
|
||||
* newterm resets the signal handlers. There's a race, but it's not
|
||||
* worth closing.
|
||||
*/
|
||||
(void)sig_init(sp->gp, sp);
|
||||
|
||||
/*
|
||||
* We use raw mode. What we want is 8-bit clean, however, signals
|
||||
* and flow control should continue to work. Admittedly, it sounds
|
||||
* like cbreak, but it isn't. Using cbreak() can get you additional
|
||||
* things like IEXTEN, which turns on flags like DISCARD and LNEXT.
|
||||
*
|
||||
* !!!
|
||||
* If raw isn't turning off echo and newlines, something's wrong.
|
||||
* However, it shouldn't hurt.
|
||||
*/
|
||||
noecho(); /* No character echo. */
|
||||
nonl(); /* No CR/NL translation. */
|
||||
raw(); /* 8-bit clean. */
|
||||
idlok(stdscr, 1); /* Use hardware insert/delete line. */
|
||||
|
||||
/* Put the cursor keys into application mode. */
|
||||
(void)keypad(stdscr, TRUE);
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* The screen TI sequence just got sent. See the comment in
|
||||
* cl_funcs.c:cl_attr().
|
||||
*/
|
||||
clp->ti_te = TI_SENT;
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Historic implementations of curses handled SIGTSTP signals
|
||||
* in one of three ways. They either:
|
||||
*
|
||||
* 1: Set their own handler, regardless.
|
||||
* 2: Did not set a handler if a handler was already installed.
|
||||
* 3: Set their own handler, but then called any previously set
|
||||
* handler after completing their own cleanup.
|
||||
*
|
||||
* We don't try and figure out which behavior is in place, we force
|
||||
* it to SIG_DFL after initializing the curses interface, which means
|
||||
* that curses isn't going to take the signal. Since curses isn't
|
||||
* reentrant (i.e., the whole curses SIGTSTP interface is a fantasy),
|
||||
* we're doing The Right Thing.
|
||||
*/
|
||||
(void)signal(SIGTSTP, SIG_DFL);
|
||||
|
||||
/*
|
||||
* If flow control was on, turn it back on. Turn signals on. ISIG
|
||||
* turns on VINTR, VQUIT, VDSUSP and VSUSP. The main curses code
|
||||
* already installed a handler for VINTR. We're going to disable the
|
||||
* other three.
|
||||
*
|
||||
* XXX
|
||||
* We want to use ^Y as a vi scrolling command. If the user has the
|
||||
* DSUSP character set to ^Y (common practice) clean it up. As it's
|
||||
* equally possible that the user has VDSUSP set to 'a', we disable
|
||||
* it regardless. It doesn't make much sense to suspend vi at read,
|
||||
* so I don't think anyone will care. Alternatively, we could look
|
||||
* it up in the table of legal command characters and turn it off if
|
||||
* it matches one. VDSUSP wasn't in POSIX 1003.1-1990, so we test for
|
||||
* it.
|
||||
*
|
||||
* XXX
|
||||
* We don't check to see if the user had signals enabled originally.
|
||||
* If they didn't, it's unclear what we're supposed to do here, but
|
||||
* it's also pretty unlikely.
|
||||
*/
|
||||
if (tcgetattr(STDIN_FILENO, &clp->vi_enter)) {
|
||||
msgq(sp, M_SYSERR, "tcgetattr");
|
||||
goto err;
|
||||
}
|
||||
if (clp->orig.c_iflag & IXON)
|
||||
clp->vi_enter.c_iflag |= IXON;
|
||||
if (clp->orig.c_iflag & IXOFF)
|
||||
clp->vi_enter.c_iflag |= IXOFF;
|
||||
|
||||
clp->vi_enter.c_lflag |= ISIG;
|
||||
#ifdef VDSUSP
|
||||
clp->vi_enter.c_cc[VDSUSP] = _POSIX_VDISABLE;
|
||||
#endif
|
||||
clp->vi_enter.c_cc[VQUIT] = _POSIX_VDISABLE;
|
||||
clp->vi_enter.c_cc[VSUSP] = _POSIX_VDISABLE;
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* OSF/1 doesn't turn off the <discard>, <literal-next> or <status>
|
||||
* characters when curses switches into raw mode. It should be OK
|
||||
* to do it explicitly for everyone.
|
||||
*/
|
||||
#ifdef VDISCARD
|
||||
clp->vi_enter.c_cc[VDISCARD] = _POSIX_VDISABLE;
|
||||
#endif
|
||||
#ifdef VLNEXT
|
||||
clp->vi_enter.c_cc[VLNEXT] = _POSIX_VDISABLE;
|
||||
#endif
|
||||
#ifdef VSTATUS
|
||||
clp->vi_enter.c_cc[VSTATUS] = _POSIX_VDISABLE;
|
||||
#endif
|
||||
|
||||
/* Initialize terminal based information. */
|
||||
if (cl_term_init(sp))
|
||||
goto err;
|
||||
|
||||
fast: /* Set the terminal modes. */
|
||||
if (tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &clp->vi_enter)) {
|
||||
if (errno == EINTR)
|
||||
goto fast;
|
||||
msgq(sp, M_SYSERR, "tcsetattr");
|
||||
err: (void)cl_vi_end(sp->gp);
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_vi_end --
|
||||
* Shutdown the vi screen.
|
||||
*/
|
||||
static int
|
||||
cl_vi_end(GS *gp)
|
||||
{
|
||||
CL_PRIVATE *clp;
|
||||
|
||||
clp = GCLP(gp);
|
||||
|
||||
/* Restore the cursor keys to normal mode. */
|
||||
(void)keypad(stdscr, FALSE);
|
||||
|
||||
/*
|
||||
* If we were running vi when we quit, scroll the screen up a single
|
||||
* line so we don't lose any information.
|
||||
*
|
||||
* Move to the bottom of the window (some endwin implementations don't
|
||||
* do this for you).
|
||||
*/
|
||||
if (!F_ISSET(clp, CL_IN_EX)) {
|
||||
(void)move(0, 0);
|
||||
(void)deleteln();
|
||||
(void)move(LINES - 1, 0);
|
||||
(void)refresh();
|
||||
}
|
||||
|
||||
cl_freecap(clp);
|
||||
|
||||
/* End curses window. */
|
||||
(void)endwin();
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* The screen TE sequence just got sent. See the comment in
|
||||
* cl_funcs.c:cl_attr().
|
||||
*/
|
||||
clp->ti_te = TE_SENT;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_ex_init --
|
||||
* Initialize the ex screen.
|
||||
*/
|
||||
static int
|
||||
cl_ex_init(SCR *sp)
|
||||
{
|
||||
CL_PRIVATE *clp;
|
||||
|
||||
clp = CLP(sp);
|
||||
|
||||
/* If already initialized, just set the terminal modes. */
|
||||
if (F_ISSET(clp, CL_SCR_EX_INIT))
|
||||
goto fast;
|
||||
|
||||
/* If not reading from a file, we're done. */
|
||||
if (!F_ISSET(clp, CL_STDIN_TTY))
|
||||
return (0);
|
||||
|
||||
/* Get the ex termcap/terminfo strings. */
|
||||
(void)cl_getcap(sp, "cup", &clp->cup);
|
||||
(void)cl_getcap(sp, "smso", &clp->smso);
|
||||
(void)cl_getcap(sp, "rmso", &clp->rmso);
|
||||
(void)cl_getcap(sp, "el", &clp->el);
|
||||
(void)cl_getcap(sp, "cuu1", &clp->cuu1);
|
||||
|
||||
/* Enter_standout_mode and exit_standout_mode are paired. */
|
||||
if (clp->smso == NULL || clp->rmso == NULL) {
|
||||
if (clp->smso != NULL) {
|
||||
free(clp->smso);
|
||||
clp->smso = NULL;
|
||||
}
|
||||
if (clp->rmso != NULL) {
|
||||
free(clp->rmso);
|
||||
clp->rmso = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Turn on canonical mode, with normal input and output processing.
|
||||
* Start with the original terminal settings as the user probably
|
||||
* had them (including any local extensions) set correctly for the
|
||||
* current terminal.
|
||||
*
|
||||
* !!!
|
||||
* We can't get everything that we need portably; for example, ONLCR,
|
||||
* mapping <newline> to <carriage-return> on output isn't required
|
||||
* by POSIX 1003.1b-1993. If this turns out to be a problem, then
|
||||
* we'll either have to play some games on the mapping, or we'll have
|
||||
* to make all ex printf's output \r\n instead of \n.
|
||||
*/
|
||||
clp->ex_enter = clp->orig;
|
||||
clp->ex_enter.c_lflag |= ECHO | ECHOE | ECHOK | ICANON | IEXTEN | ISIG;
|
||||
#ifdef ECHOCTL
|
||||
clp->ex_enter.c_lflag |= ECHOCTL;
|
||||
#endif
|
||||
#ifdef ECHOKE
|
||||
clp->ex_enter.c_lflag |= ECHOKE;
|
||||
#endif
|
||||
clp->ex_enter.c_iflag |= ICRNL;
|
||||
clp->ex_enter.c_oflag |= OPOST;
|
||||
#ifdef ONLCR
|
||||
clp->ex_enter.c_oflag |= ONLCR;
|
||||
#endif
|
||||
|
||||
fast: if (tcsetattr(STDIN_FILENO, TCSADRAIN | TCSASOFT, &clp->ex_enter)) {
|
||||
if (errno == EINTR)
|
||||
goto fast;
|
||||
msgq(sp, M_SYSERR, "tcsetattr");
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_ex_end --
|
||||
* Shutdown the ex screen.
|
||||
*/
|
||||
static int
|
||||
cl_ex_end(GS *gp)
|
||||
{
|
||||
CL_PRIVATE *clp;
|
||||
|
||||
clp = GCLP(gp);
|
||||
|
||||
cl_freecap(clp);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_getcap --
|
||||
* Retrieve termcap/terminfo strings.
|
||||
*
|
||||
* PUBLIC: int cl_getcap __P((SCR *, char *, char **));
|
||||
*/
|
||||
int
|
||||
cl_getcap(SCR *sp, const char *name, char **elementp)
|
||||
{
|
||||
size_t len;
|
||||
char *t;
|
||||
|
||||
if ((t = tigetstr(name)) != NULL &&
|
||||
t != (char *)-1 && (len = strlen(t)) != 0) {
|
||||
MALLOC_RET(sp, *elementp, char *, len + 1);
|
||||
memmove(*elementp, t, len + 1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_freecap --
|
||||
* Free any allocated termcap/terminfo strings.
|
||||
*/
|
||||
static void
|
||||
cl_freecap(CL_PRIVATE *clp)
|
||||
{
|
||||
if (clp->el != NULL) {
|
||||
free(clp->el);
|
||||
clp->el = NULL;
|
||||
}
|
||||
if (clp->cup != NULL) {
|
||||
free(clp->cup);
|
||||
clp->cup = NULL;
|
||||
}
|
||||
if (clp->cuu1 != NULL) {
|
||||
free(clp->cuu1);
|
||||
clp->cuu1 = NULL;
|
||||
}
|
||||
if (clp->rmso != NULL) {
|
||||
free(clp->rmso);
|
||||
clp->rmso = NULL;
|
||||
}
|
||||
if (clp->smso != NULL) {
|
||||
free(clp->smso);
|
||||
clp->smso = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_putenv --
|
||||
* Put a value into the environment.
|
||||
*/
|
||||
static int
|
||||
cl_putenv(SCR *sp, const char *name, const char *str, u_long value)
|
||||
{
|
||||
char buf[40];
|
||||
|
||||
if (str == NULL) {
|
||||
(void)snprintf(buf, sizeof(buf), "%lu", value);
|
||||
return (cl_setenv(sp, name, buf));
|
||||
} else
|
||||
return (cl_setenv(sp, name, str));
|
||||
}
|
481
dist/nvi/cl/cl_term.c
vendored
Normal file
481
dist/nvi/cl/cl_term.c
vendored
Normal file
|
@ -0,0 +1,481 @@
|
|||
/* $NetBSD: cl_term.c,v 1.4 2011/11/23 19:25:27 tnozaki Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* Copyright (c) 1993, 1994, 1995, 1996
|
||||
* Keith Bostic. All rights reserved.
|
||||
*
|
||||
* See the LICENSE file for redistribution information.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "Id: cl_term.c,v 10.31 2001/07/08 13:06:56 skimo Exp (Berkeley) Date: 2001/07/08 13:06:56";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <bitstring.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../common/common.h"
|
||||
#include "cl.h"
|
||||
|
||||
static int cl_pfmap __P((SCR *, seq_t, CHAR_T *, size_t, CHAR_T *, size_t));
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* THIS REQUIRES THAT ALL SCREENS SHARE A TERMINAL TYPE.
|
||||
*/
|
||||
typedef struct _tklist {
|
||||
const char *ts; /* Key's termcap string. */
|
||||
const char *output; /* Corresponding vi command. */
|
||||
const char *name; /* Name. */
|
||||
u_char value; /* Special value (for lookup). */
|
||||
} TKLIST;
|
||||
|
||||
#define TKINIT(a, b, c) { a, b, c, 0 }
|
||||
|
||||
static TKLIST const c_tklist[] = { /* Command mappings. */
|
||||
TKINIT("kil1", "O", "insert line"),
|
||||
TKINIT("kdch1", "x", "delete character"),
|
||||
TKINIT("kcud1", "j", "cursor down"),
|
||||
TKINIT("kel", "D", "delete to eol"),
|
||||
TKINIT("kind", "\004", "scroll down"), /* ^D */
|
||||
TKINIT("kll", "$", "go to eol"),
|
||||
TKINIT("kend", "$", "go to eol"),
|
||||
TKINIT("khome", "^", "go to sol"),
|
||||
TKINIT("kich1", "i", "insert at cursor"),
|
||||
TKINIT("kdl1", "dd", "delete line"),
|
||||
TKINIT("kcub1", "h", "cursor left"),
|
||||
TKINIT("knp", "\006", "page down"), /* ^F */
|
||||
TKINIT("kpp", "\002", "page up"), /* ^B */
|
||||
TKINIT("kri", "\025", "scroll up"), /* ^U */
|
||||
TKINIT("ked", "dG", "delete to end of screen"),
|
||||
TKINIT("kcuf1", "l", "cursor right"),
|
||||
TKINIT("kcuu1", "k", "cursor up"),
|
||||
TKINIT(NULL, NULL, NULL),
|
||||
};
|
||||
static TKLIST const m1_tklist[] = { /* Input mappings (lookup). */
|
||||
TKINIT(NULL, NULL, NULL),
|
||||
};
|
||||
static TKLIST const m2_tklist[] = { /* Input mappings (set or delete). */
|
||||
TKINIT("kcud1", "\033ja", "cursor down"), /* ^[ja */
|
||||
TKINIT("kcub1", "\033ha", "cursor left"), /* ^[ha */
|
||||
TKINIT("kcuu1", "\033ka", "cursor up"), /* ^[ka */
|
||||
TKINIT("kcuf1", "\033la", "cursor right"), /* ^[la */
|
||||
TKINIT(NULL, NULL, NULL),
|
||||
};
|
||||
|
||||
/*
|
||||
* cl_term_init --
|
||||
* Initialize the special keys defined by the termcap/terminfo entry.
|
||||
*
|
||||
* PUBLIC: int cl_term_init __P((SCR *));
|
||||
*/
|
||||
int
|
||||
cl_term_init(SCR *sp)
|
||||
{
|
||||
KEYLIST *kp;
|
||||
SEQ *qp;
|
||||
TKLIST const *tkp;
|
||||
char *t;
|
||||
CHAR_T name[60];
|
||||
CHAR_T output[5];
|
||||
CHAR_T ts[20];
|
||||
const CHAR_T *wp;
|
||||
size_t wlen;
|
||||
|
||||
/* Command mappings. */
|
||||
for (tkp = c_tklist; tkp->name != NULL; ++tkp) {
|
||||
if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1)
|
||||
continue;
|
||||
CHAR2INT(sp, tkp->name, strlen(tkp->name), wp, wlen);
|
||||
MEMCPYW(name, wp, wlen);
|
||||
CHAR2INT(sp, t, strlen(t), wp, wlen);
|
||||
MEMCPYW(ts, wp, wlen);
|
||||
CHAR2INT(sp, tkp->output, strlen(tkp->output), wp, wlen);
|
||||
MEMCPYW(output, wp, wlen);
|
||||
if (seq_set(sp, name, strlen(tkp->name), ts, strlen(t),
|
||||
output, strlen(tkp->output), SEQ_COMMAND,
|
||||
SEQ_NOOVERWRITE | SEQ_SCREEN))
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Input mappings needing to be looked up. */
|
||||
for (tkp = m1_tklist; tkp->name != NULL; ++tkp) {
|
||||
if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1)
|
||||
continue;
|
||||
for (kp = keylist;; ++kp)
|
||||
if (kp->value == tkp->value)
|
||||
break;
|
||||
if (kp == NULL)
|
||||
continue;
|
||||
CHAR2INT(sp, tkp->name, strlen(tkp->name), wp, wlen);
|
||||
MEMCPYW(name, wp, wlen);
|
||||
CHAR2INT(sp, t, strlen(t), wp, wlen);
|
||||
MEMCPYW(ts, wp, wlen);
|
||||
output[0] = (UCHAR_T)kp->ch;
|
||||
if (seq_set(sp, name, strlen(tkp->name), ts, strlen(t),
|
||||
output, 1, SEQ_INPUT, SEQ_NOOVERWRITE | SEQ_SCREEN))
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Input mappings that are already set or are text deletions. */
|
||||
for (tkp = m2_tklist; tkp->name != NULL; ++tkp) {
|
||||
if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1)
|
||||
continue;
|
||||
/*
|
||||
* !!!
|
||||
* Some terminals' <cursor_left> keys send single <backspace>
|
||||
* characters. This is okay in command mapping, but not okay
|
||||
* in input mapping. That combination is the only one we'll
|
||||
* ever see, hopefully, so kluge it here for now.
|
||||
*/
|
||||
if (!strcmp(t, "\b"))
|
||||
continue;
|
||||
if (tkp->output == NULL) {
|
||||
CHAR2INT(sp, tkp->name, strlen(tkp->name), wp, wlen);
|
||||
MEMCPYW(name, wp, wlen);
|
||||
CHAR2INT(sp, t, strlen(t), wp, wlen);
|
||||
MEMCPYW(ts, wp, wlen);
|
||||
if (seq_set(sp, name, strlen(tkp->name),
|
||||
ts, strlen(t), NULL, 0,
|
||||
SEQ_INPUT, SEQ_NOOVERWRITE | SEQ_SCREEN))
|
||||
return (1);
|
||||
} else {
|
||||
CHAR2INT(sp, tkp->name, strlen(tkp->name), wp, wlen);
|
||||
MEMCPYW(name, wp, wlen);
|
||||
CHAR2INT(sp, t, strlen(t), wp, wlen);
|
||||
MEMCPYW(ts, wp, wlen);
|
||||
CHAR2INT(sp, tkp->output, strlen(tkp->output), wp, wlen);
|
||||
MEMCPYW(output, wp, wlen);
|
||||
if (seq_set(sp, name, strlen(tkp->name),
|
||||
ts, strlen(t), output, strlen(tkp->output),
|
||||
SEQ_INPUT, SEQ_NOOVERWRITE | SEQ_SCREEN))
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Rework any function key mappings that were set before the
|
||||
* screen was initialized.
|
||||
*/
|
||||
for (qp = sp->gp->seqq.lh_first; qp != NULL; qp = qp->q.le_next)
|
||||
if (F_ISSET(qp, SEQ_FUNCMAP))
|
||||
(void)cl_pfmap(sp, qp->stype,
|
||||
qp->input, qp->ilen, qp->output, qp->olen);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_term_end --
|
||||
* End the special keys defined by the termcap/terminfo entry.
|
||||
*
|
||||
* PUBLIC: int cl_term_end __P((GS *));
|
||||
*/
|
||||
int
|
||||
cl_term_end(GS *gp)
|
||||
{
|
||||
SEQ *qp, *nqp;
|
||||
|
||||
/* Delete screen specific mappings. */
|
||||
for (qp = gp->seqq.lh_first; qp != NULL; qp = nqp) {
|
||||
nqp = qp->q.le_next;
|
||||
if (F_ISSET(qp, SEQ_SCREEN))
|
||||
(void)seq_mdel(qp);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_fmap --
|
||||
* Map a function key.
|
||||
*
|
||||
* PUBLIC: int cl_fmap __P((SCR *, seq_t, CHAR_T *, size_t, CHAR_T *, size_t));
|
||||
*/
|
||||
int
|
||||
cl_fmap(SCR *sp, seq_t stype, CHAR_T *from, size_t flen, CHAR_T *to, size_t tlen)
|
||||
{
|
||||
/* Ignore until the screen is running, do the real work then. */
|
||||
if (F_ISSET(sp, SC_VI) && !F_ISSET(sp, SC_SCR_VI))
|
||||
return (0);
|
||||
if (F_ISSET(sp, SC_EX) && !F_ISSET(sp, SC_SCR_EX))
|
||||
return (0);
|
||||
|
||||
return (cl_pfmap(sp, stype, from, flen, to, tlen));
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_pfmap --
|
||||
* Map a function key (private version).
|
||||
*/
|
||||
static int
|
||||
cl_pfmap(SCR *sp, seq_t stype, CHAR_T *from, size_t flen, CHAR_T *to, size_t tlen)
|
||||
{
|
||||
size_t nlen;
|
||||
char *p;
|
||||
char name[64];
|
||||
CHAR_T mykeyname[64];
|
||||
CHAR_T ts[20];
|
||||
const CHAR_T *wp;
|
||||
size_t wlen;
|
||||
|
||||
(void)snprintf(name, sizeof(name), "kf%d",
|
||||
(int)STRTOL(from+1,NULL,10));
|
||||
if ((p = tigetstr(name)) == NULL ||
|
||||
p == (char *)-1 || strlen(p) == 0)
|
||||
p = NULL;
|
||||
if (p == NULL) {
|
||||
msgq_wstr(sp, M_ERR, from, "233|This terminal has no %s key");
|
||||
return (1);
|
||||
}
|
||||
|
||||
nlen = SPRINTF(mykeyname,
|
||||
SIZE(mykeyname), L("function key %d"),
|
||||
(int)STRTOL(from+1,NULL,10));
|
||||
CHAR2INT(sp, p, strlen(p), wp, wlen);
|
||||
MEMCPYW(ts, wp, wlen);
|
||||
return (seq_set(sp, mykeyname, nlen,
|
||||
ts, strlen(p), to, tlen, stype, SEQ_NOOVERWRITE | SEQ_SCREEN));
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_optchange --
|
||||
* Curses screen specific "option changed" routine.
|
||||
*
|
||||
* PUBLIC: int cl_optchange __P((SCR *, int, const char *, u_long *));
|
||||
*/
|
||||
int
|
||||
cl_optchange(SCR *sp, int opt, const char *str, u_long *valp)
|
||||
{
|
||||
CL_PRIVATE *clp;
|
||||
|
||||
clp = CLP(sp);
|
||||
|
||||
switch (opt) {
|
||||
case O_COLUMNS:
|
||||
case O_LINES:
|
||||
case O_TERM:
|
||||
/*
|
||||
* Changing the columns, lines or terminal require that
|
||||
* we restart the screen.
|
||||
*/
|
||||
F_SET(sp->gp, G_SRESTART);
|
||||
F_CLR(sp, SC_SCR_EX | SC_SCR_VI);
|
||||
break;
|
||||
case O_MESG:
|
||||
(void)cl_omesg(sp, clp, *valp);
|
||||
break;
|
||||
case O_WINDOWNAME:
|
||||
if (*valp) {
|
||||
F_SET(clp, CL_RENAME_OK);
|
||||
|
||||
/*
|
||||
* If the screen is live, i.e. we're not reading the
|
||||
* .exrc file, update the window.
|
||||
*/
|
||||
if (sp->frp != NULL && sp->frp->name != NULL)
|
||||
(void)cl_rename(sp, sp->frp->name, 1);
|
||||
} else {
|
||||
F_CLR(clp, CL_RENAME_OK);
|
||||
|
||||
(void)cl_rename(sp, NULL, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_omesg --
|
||||
* Turn the tty write permission on or off.
|
||||
*
|
||||
* PUBLIC: int cl_omesg __P((SCR *, CL_PRIVATE *, int));
|
||||
*/
|
||||
int
|
||||
cl_omesg(SCR *sp, CL_PRIVATE *clp, int on)
|
||||
{
|
||||
struct stat sb;
|
||||
char *tty;
|
||||
|
||||
/* Find the tty, get the current permissions. */
|
||||
if ((tty = ttyname(STDERR_FILENO)) == NULL) {
|
||||
if (sp != NULL)
|
||||
msgq(sp, M_SYSERR, "stderr");
|
||||
return (1);
|
||||
}
|
||||
if (stat(tty, &sb) < 0) {
|
||||
if (sp != NULL)
|
||||
msgq(sp, M_SYSERR, "%s", tty);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Save the original status if it's unknown. */
|
||||
if (clp->tgw == TGW_UNKNOWN)
|
||||
clp->tgw = sb.st_mode & S_IWGRP ? TGW_SET : TGW_UNSET;
|
||||
|
||||
/* Toggle the permissions. */
|
||||
if (on) {
|
||||
if (chmod(tty, sb.st_mode | S_IWGRP) < 0) {
|
||||
if (sp != NULL)
|
||||
msgq(sp, M_SYSERR,
|
||||
"046|messages not turned on: %s", tty);
|
||||
return (1);
|
||||
}
|
||||
} else
|
||||
if (chmod(tty, sb.st_mode & ~S_IWGRP) < 0) {
|
||||
if (sp != NULL)
|
||||
msgq(sp, M_SYSERR,
|
||||
"045|messages not turned off: %s", tty);
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_ssize --
|
||||
* Return the terminal size.
|
||||
*
|
||||
* PUBLIC: int cl_ssize __P((SCR *, int, size_t *, size_t *, int *));
|
||||
*/
|
||||
int
|
||||
cl_ssize(SCR *sp, int sigwinch, size_t *rowp, size_t *colp, int *changedp)
|
||||
{
|
||||
#ifdef TIOCGWINSZ
|
||||
struct winsize win;
|
||||
#endif
|
||||
size_t col, row;
|
||||
int rval;
|
||||
char *p;
|
||||
|
||||
/* Assume it's changed. */
|
||||
if (changedp != NULL)
|
||||
*changedp = 1;
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* sp may be NULL.
|
||||
*
|
||||
* Get the screen rows and columns. If the values are wrong, it's
|
||||
* not a big deal -- as soon as the user sets them explicitly the
|
||||
* environment will be set and the screen package will use the new
|
||||
* values.
|
||||
*
|
||||
* Try TIOCGWINSZ.
|
||||
*/
|
||||
row = col = 0;
|
||||
#ifdef TIOCGWINSZ
|
||||
if (ioctl(STDERR_FILENO, TIOCGWINSZ, &win) != -1) {
|
||||
row = win.ws_row;
|
||||
col = win.ws_col;
|
||||
}
|
||||
#endif
|
||||
/* If here because of suspend or a signal, only trust TIOCGWINSZ. */
|
||||
if (sigwinch) {
|
||||
/*
|
||||
* Somebody didn't get TIOCGWINSZ right, or has suspend
|
||||
* without window resizing support. The user just lost,
|
||||
* but there's nothing we can do.
|
||||
*/
|
||||
if (row == 0 || col == 0) {
|
||||
if (changedp != NULL)
|
||||
*changedp = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* SunOS systems deliver SIGWINCH when windows are uncovered
|
||||
* as well as when they change size. In addition, we call
|
||||
* here when continuing after being suspended since the window
|
||||
* may have changed size. Since we don't want to background
|
||||
* all of the screens just because the window was uncovered,
|
||||
* ignore the signal if there's no change.
|
||||
*/
|
||||
if (sp != NULL &&
|
||||
row == O_VAL(sp, O_LINES) && col == O_VAL(sp, O_COLUMNS)) {
|
||||
if (changedp != NULL)
|
||||
*changedp = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (rowp != NULL)
|
||||
*rowp = row;
|
||||
if (colp != NULL)
|
||||
*colp = col;
|
||||
resizeterm(row, col);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* If TIOCGWINSZ failed, or had entries of 0, try termcap. This
|
||||
* routine is called before any termcap or terminal information
|
||||
* has been set up. If there's no TERM environmental variable set,
|
||||
* let it go, at least ex can run.
|
||||
*/
|
||||
if (row == 0 || col == 0) {
|
||||
if ((p = getenv("TERM")) == NULL)
|
||||
goto noterm;
|
||||
if (row == 0) {
|
||||
if ((rval = tigetnum("lines")) < 0)
|
||||
msgq(sp, M_SYSERR, "tigetnum: lines");
|
||||
else
|
||||
row = rval;
|
||||
}
|
||||
if (col == 0) {
|
||||
if ((rval = tigetnum("cols")) < 0)
|
||||
msgq(sp, M_SYSERR, "tigetnum: cols");
|
||||
else
|
||||
col = rval;
|
||||
}
|
||||
}
|
||||
|
||||
/* If nothing else, well, it's probably a VT100. */
|
||||
noterm: if (row == 0)
|
||||
row = 24;
|
||||
if (col == 0)
|
||||
col = 80;
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* POSIX 1003.2 requires the environment to override everything.
|
||||
* Often, people can get nvi to stop messing up their screen by
|
||||
* deleting the LINES and COLUMNS environment variables from their
|
||||
* dot-files.
|
||||
*/
|
||||
if ((p = getenv("LINES")) != NULL)
|
||||
row = strtol(p, NULL, 10);
|
||||
if ((p = getenv("COLUMNS")) != NULL)
|
||||
col = strtol(p, NULL, 10);
|
||||
|
||||
if (rowp != NULL)
|
||||
*rowp = row;
|
||||
if (colp != NULL)
|
||||
*colp = col;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* cl_putchar --
|
||||
* Function version of putchar, for tputs.
|
||||
*
|
||||
* PUBLIC: int cl_putchar __P((int));
|
||||
*/
|
||||
int
|
||||
cl_putchar(int ch)
|
||||
{
|
||||
return (putchar(ch));
|
||||
}
|
59
dist/nvi/cl/extern.h
vendored
Normal file
59
dist/nvi/cl/extern.h
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
/* $NetBSD: extern.h,v 1.3 2010/02/03 15:34:37 roy Exp $ */
|
||||
|
||||
/* Do not edit: automatically built by build/distrib. */
|
||||
#ifndef HAVE_CURSES_WADDNSTR
|
||||
int waddnstr __P((WINDOW*, char *, int));
|
||||
#endif
|
||||
#ifndef HAVE_CURSES_BEEP
|
||||
void beep __P((void));
|
||||
#endif
|
||||
#ifndef HAVE_CURSES_FLASH
|
||||
void flash __P((void));
|
||||
#endif
|
||||
#ifndef HAVE_CURSES_IDLOK
|
||||
void idlok __P((WINDOW *, int));
|
||||
#endif
|
||||
#ifndef HAVE_CURSES_KEYPAD
|
||||
int keypad __P((void *, int));
|
||||
#endif
|
||||
#ifndef HAVE_CURSES_NEWTERM
|
||||
void *newterm __P((const char *, FILE *, FILE *));
|
||||
#endif
|
||||
#ifndef HAVE_CURSES_SETUPTERM
|
||||
void setupterm __P((char *, int, int *));
|
||||
#endif
|
||||
#ifndef HAVE_CURSES_TIGETSTR
|
||||
char *tigetstr __P((const char *));
|
||||
int tigetnum __P((const char *));
|
||||
#endif
|
||||
int cl_waddstr __P((SCR *, const CHAR_T *, size_t));
|
||||
int cl_addstr __P((SCR *, const char *, size_t));
|
||||
int cl_attr __P((SCR *, scr_attr_t, int));
|
||||
int cl_baud __P((SCR *, u_long *));
|
||||
int cl_bell __P((SCR *));
|
||||
int cl_clrtoeol __P((SCR *));
|
||||
int cl_cursor __P((SCR *, size_t *, size_t *));
|
||||
int cl_deleteln __P((SCR *));
|
||||
int cl_discard __P((SCR *, SCR **));
|
||||
int cl_ex_adjust __P((SCR *, exadj_t));
|
||||
int cl_insertln __P((SCR *));
|
||||
int cl_keyval __P((SCR *, scr_keyval_t, CHAR_T *, int *));
|
||||
int cl_move __P((SCR *, size_t, size_t));
|
||||
int cl_refresh __P((SCR *, int));
|
||||
int cl_rename __P((SCR *, char *, int));
|
||||
void cl_setname __P((GS *, char *));
|
||||
int cl_split __P((SCR *, SCR *));
|
||||
int cl_suspend __P((SCR *, int *));
|
||||
void cl_usage __P((void));
|
||||
int sig_init __P((GS *, SCR *));
|
||||
int cl_event __P((SCR *, EVENT *, u_int32_t, int));
|
||||
int cl_screen __P((SCR *, u_int32_t));
|
||||
int cl_quit __P((GS *));
|
||||
int cl_getcap __P((SCR *, const char *, char **));
|
||||
int cl_term_init __P((SCR *));
|
||||
int cl_term_end __P((GS *));
|
||||
int cl_fmap __P((SCR *, seq_t, CHAR_T *, size_t, CHAR_T *, size_t));
|
||||
int cl_optchange __P((SCR *, int, const char *, u_long *));
|
||||
int cl_omesg __P((SCR *, CL_PRIVATE *, int));
|
||||
int cl_ssize __P((SCR *, int, size_t *, size_t *, int *));
|
||||
int cl_putchar __P((int));
|
87
dist/nvi/clib/bsearch.c
vendored
Normal file
87
dist/nvi/clib/bsearch.c
vendored
Normal file
|
@ -0,0 +1,87 @@
|
|||
/* $NetBSD: bsearch.c,v 1.1.1.2 2008/05/18 14:29:38 aymeric Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char sccsid[] = "@(#)bsearch.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "port.h"
|
||||
|
||||
/*
|
||||
* Perform a binary search.
|
||||
*
|
||||
* The code below is a bit sneaky. After a comparison fails, we
|
||||
* divide the work in half by moving either left or right. If lim
|
||||
* is odd, moving left simply involves halving lim: e.g., when lim
|
||||
* is 5 we look at item 2, so we change lim to 2 so that we will
|
||||
* look at items 0 & 1. If lim is even, the same applies. If lim
|
||||
* is odd, moving right again involes halving lim, this time moving
|
||||
* the base up one item past p: e.g., when lim is 5 we change base
|
||||
* to item 3 and make lim 2 so that we will look at items 3 and 4.
|
||||
* If lim is even, however, we have to shrink it by one before
|
||||
* halving: e.g., when lim is 4, we still looked at item 2, so we
|
||||
* have to make lim 3, then halve, obtaining 1, so that we will only
|
||||
* look at item 3.
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_BSEARCH
|
||||
* PUBLIC: void *bsearch __P((const void *, const void *, size_t,
|
||||
* PUBLIC: size_t, int (*)(const void *, const void *)));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
void *
|
||||
bsearch(register const void *key, const void *base0, size_t nmemb, register size_t size, register int (*compar) (const void *, const void *))
|
||||
{
|
||||
register const char *base = base0;
|
||||
register size_t lim;
|
||||
register int cmp;
|
||||
register const void *p;
|
||||
|
||||
for (lim = nmemb; lim != 0; lim >>= 1) {
|
||||
p = base + (lim >> 1) * size;
|
||||
cmp = (*compar)(key, p);
|
||||
if (cmp == 0)
|
||||
return ((void *)p);
|
||||
if (cmp > 0) { /* key > p: move right */
|
||||
base = (char *)p + size;
|
||||
lim--;
|
||||
} /* else move left */
|
||||
}
|
||||
return (NULL);
|
||||
}
|
160
dist/nvi/clib/env.c
vendored
Normal file
160
dist/nvi/clib/env.c
vendored
Normal file
|
@ -0,0 +1,160 @@
|
|||
/* $NetBSD: env.c,v 1.1.1.2 2008/05/18 14:29:38 aymeric Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1987, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char sccsid[] = "@(#)getenv.c 8.1 (Berkeley) 6/4/93";
|
||||
static const char sccsid[] = "@(#)setenv.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* __findenv --
|
||||
* Returns pointer to value associated with name, if any, else NULL.
|
||||
* Sets offset to be the offset of the name/value combination in the
|
||||
* environmental array, for use by setenv(3) and unsetenv(3).
|
||||
* Explicitly removes '=' in argument name.
|
||||
*
|
||||
* This routine *should* be a static; don't use it.
|
||||
*/
|
||||
static char *
|
||||
__findenv(register char *name, int *offset)
|
||||
{
|
||||
extern char **environ;
|
||||
register int len;
|
||||
register char *np;
|
||||
register char **p, *c;
|
||||
|
||||
if (name == NULL || environ == NULL)
|
||||
return (NULL);
|
||||
for (np = name; *np && *np != '='; ++np)
|
||||
continue;
|
||||
len = np - name;
|
||||
for (p = environ; (c = *p) != NULL; ++p)
|
||||
if (strncmp(c, name, len) == 0 && c[len] == '=') {
|
||||
*offset = p - environ;
|
||||
return (c + len + 1);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
#ifndef HAVE_SETENV
|
||||
/*
|
||||
* setenv --
|
||||
* Set the value of the environmental variable "name" to be
|
||||
* "value". If rewrite is set, replace any current value.
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_SETENV
|
||||
* PUBLIC: int setenv __P((const char *, const char *, int));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
setenv(name, value, rewrite)
|
||||
register char *name;
|
||||
register char *value;
|
||||
int rewrite;
|
||||
{
|
||||
extern char **environ;
|
||||
static int alloced; /* if allocated space before */
|
||||
register char *c;
|
||||
int l_value, offset;
|
||||
|
||||
if (*value == '=') /* no `=' in value */
|
||||
++value;
|
||||
l_value = strlen(value);
|
||||
if ((c = __findenv(name, &offset))) { /* find if already exists */
|
||||
if (!rewrite)
|
||||
return (0);
|
||||
if (strlen(c) >= l_value) { /* old larger; copy over */
|
||||
while (*c++ = *value++);
|
||||
return (0);
|
||||
}
|
||||
} else { /* create new slot */
|
||||
register int cnt;
|
||||
register char **p;
|
||||
|
||||
for (p = environ, cnt = 0; *p; ++p, ++cnt);
|
||||
if (alloced) { /* just increase size */
|
||||
environ = (char **)realloc((char *)environ,
|
||||
(size_t)(sizeof(char *) * (cnt + 2)));
|
||||
if (!environ)
|
||||
return (-1);
|
||||
}
|
||||
else { /* get new space */
|
||||
alloced = 1; /* copy old entries into it */
|
||||
p = malloc((size_t)(sizeof(char *) * (cnt + 2)));
|
||||
if (!p)
|
||||
return (-1);
|
||||
memmove(p, environ, cnt * sizeof(char *));
|
||||
environ = p;
|
||||
}
|
||||
environ[cnt + 1] = NULL;
|
||||
offset = cnt;
|
||||
}
|
||||
for (c = (char *)name; *c && *c != '='; ++c); /* no `=' in name */
|
||||
if (!(environ[offset] = /* name + `=' + value */
|
||||
malloc((size_t)((int)(c - name) + l_value + 2))))
|
||||
return (-1);
|
||||
for (c = environ[offset]; (*c = *name++) && *c != '='; ++c);
|
||||
for (*c++ = '='; *c++ = *value++;);
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_UNSETENV
|
||||
/*
|
||||
* unsetenv(name) --
|
||||
* Delete environmental variable "name".
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_UNSETENV
|
||||
* PUBLIC: void unsetenv __P((const char *));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
void
|
||||
unsetenv(name)
|
||||
char *name;
|
||||
{
|
||||
extern char **environ;
|
||||
register char **p;
|
||||
int offset;
|
||||
|
||||
while (__findenv(name, &offset)) /* if set multiple times */
|
||||
for (p = &environ[offset];; ++p)
|
||||
if (!(*p = *(p + 1)))
|
||||
break;
|
||||
}
|
||||
#endif
|
24
dist/nvi/clib/gethostname.c
vendored
Normal file
24
dist/nvi/clib/gethostname.c
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
/* $NetBSD: gethostname.c,v 1.1.1.2 2008/05/18 14:29:38 aymeric Exp $ */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/*
|
||||
* Solaris doesn't include the gethostname call by default.
|
||||
*/
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/systeminfo.h>
|
||||
|
||||
#include <netdb.h>
|
||||
|
||||
/*
|
||||
* PUBLIC: #ifndef HAVE_GETHOSTNAME
|
||||
* PUBLIC: int gethostname __P((char *, int));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
int
|
||||
gethostname(host, len)
|
||||
char *host;
|
||||
int len;
|
||||
{
|
||||
return (sysinfo(SI_HOSTNAME, host, len) == -1 ? -1 : 0);
|
||||
}
|
16
dist/nvi/clib/iswblank.c
vendored
Normal file
16
dist/nvi/clib/iswblank.c
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
/* $NetBSD: iswblank.c,v 1.1.1.2 2008/05/18 14:29:38 aymeric Exp $ */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char sccsid[] = "Id: iswblank.c,v 1.1 2001/10/11 19:22:29 skimo Exp";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <wchar.h>
|
||||
#include <wctype.h>
|
||||
|
||||
int
|
||||
iswblank (wint_t wc)
|
||||
{
|
||||
return iswctype(wc, wctype("blank"));
|
||||
}
|
64
dist/nvi/clib/memchr.c
vendored
Normal file
64
dist/nvi/clib/memchr.c
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
/* $NetBSD: memchr.c,v 1.1.1.2 2008/05/18 14:29:38 aymeric Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Chris Torek.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char sccsid[] = "@(#)memchr.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* PUBLIC: #ifndef HAVE_MEMCHR
|
||||
* PUBLIC: void *memchr __P((const void *, int, size_t));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
void *
|
||||
memchr(const void *s, register unsigned char c, register size_t n)
|
||||
{
|
||||
if (n != 0) {
|
||||
register const unsigned char *p = s;
|
||||
|
||||
do {
|
||||
if (*p++ == c)
|
||||
return ((void *)(p - 1));
|
||||
} while (--n != 0);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
139
dist/nvi/clib/memset.c
vendored
Normal file
139
dist/nvi/clib/memset.c
vendored
Normal file
|
@ -0,0 +1,139 @@
|
|||
/* $NetBSD: memset.c,v 1.1.1.2 2008/05/18 14:29:38 aymeric Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Mike Hibler and Chris Torek.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char sccsid[] = "@(#)memset.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* PUBLIC: #ifndef HAVE_MEMSET
|
||||
* PUBLIC: void *memset __P((void *, int, size_t));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
#define wsize sizeof(u_int)
|
||||
#define wmask (wsize - 1)
|
||||
|
||||
#ifdef BZERO
|
||||
#define RETURN return
|
||||
#define VAL 0
|
||||
#define WIDEVAL 0
|
||||
|
||||
void
|
||||
bzero(dst0, length)
|
||||
void *dst0;
|
||||
register size_t length;
|
||||
#else
|
||||
#define RETURN return (dst0)
|
||||
#define VAL c0
|
||||
#define WIDEVAL c
|
||||
|
||||
void *
|
||||
memset(void *dst0, register int c0, register size_t length)
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
{
|
||||
register size_t t;
|
||||
register u_int c;
|
||||
register u_char *dst;
|
||||
|
||||
dst = dst0;
|
||||
/*
|
||||
* If not enough words, just fill bytes. A length >= 2 words
|
||||
* guarantees that at least one of them is `complete' after
|
||||
* any necessary alignment. For instance:
|
||||
*
|
||||
* |-----------|-----------|-----------|
|
||||
* |00|01|02|03|04|05|06|07|08|09|0A|00|
|
||||
* ^---------------------^
|
||||
* dst dst+length-1
|
||||
*
|
||||
* but we use a minimum of 3 here since the overhead of the code
|
||||
* to do word writes is substantial.
|
||||
*/
|
||||
if (length < 3 * wsize) {
|
||||
while (length != 0) {
|
||||
*dst++ = VAL;
|
||||
--length;
|
||||
}
|
||||
RETURN;
|
||||
}
|
||||
|
||||
#ifndef BZERO
|
||||
if ((c = (u_char)c0) != 0) { /* Fill the word. */
|
||||
c = (c << 8) | c; /* u_int is 16 bits. */
|
||||
#if UINT_MAX > 0xffff
|
||||
c = (c << 16) | c; /* u_int is 32 bits. */
|
||||
#endif
|
||||
#if UINT_MAX > 0xffffffff
|
||||
c = (c << 32) | c; /* u_int is 64 bits. */
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
/* Align destination by filling in bytes. */
|
||||
if ((t = (int)dst & wmask) != 0) {
|
||||
t = wsize - t;
|
||||
length -= t;
|
||||
do {
|
||||
*dst++ = VAL;
|
||||
} while (--t != 0);
|
||||
}
|
||||
|
||||
/* Fill words. Length was >= 2*words so we know t >= 1 here. */
|
||||
t = length / wsize;
|
||||
do {
|
||||
*(u_int *)dst = WIDEVAL;
|
||||
dst += wsize;
|
||||
} while (--t != 0);
|
||||
|
||||
/* Mop up trailing bytes, if any. */
|
||||
t = length & wmask;
|
||||
if (t != 0)
|
||||
do {
|
||||
*dst++ = VAL;
|
||||
} while (--t != 0);
|
||||
RETURN;
|
||||
}
|
131
dist/nvi/clib/mkstemp.c
vendored
Normal file
131
dist/nvi/clib/mkstemp.c
vendored
Normal file
|
@ -0,0 +1,131 @@
|
|||
/* $NetBSD: mkstemp.c,v 1.2 2011/03/21 14:53:02 tnozaki Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1987, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static int _gettemp(char *path, register int *doopen);
|
||||
|
||||
/*
|
||||
* PUBLIC: #ifndef HAVE_MKSTEMP
|
||||
* PUBLIC: int mkstemp __P((char *));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
mkstemp(char *path)
|
||||
{
|
||||
int fd;
|
||||
|
||||
return (_gettemp(path, &fd) ? fd : -1);
|
||||
}
|
||||
|
||||
char *
|
||||
mktemp(char *path)
|
||||
{
|
||||
return(_gettemp(path, (int *)NULL) ? path : (char *)NULL);
|
||||
}
|
||||
|
||||
static
|
||||
_gettemp(char *path, register int *doopen)
|
||||
{
|
||||
extern int errno;
|
||||
register char *start, *trv;
|
||||
struct stat sbuf;
|
||||
u_int pid;
|
||||
|
||||
pid = getpid();
|
||||
for (trv = path; *trv; ++trv); /* extra X's get set to 0's */
|
||||
while (*--trv == 'X') {
|
||||
*trv = (pid % 10) + '0';
|
||||
pid /= 10;
|
||||
}
|
||||
|
||||
/*
|
||||
* check the target directory; if you have six X's and it
|
||||
* doesn't exist this runs for a *very* long time.
|
||||
*/
|
||||
for (start = trv + 1;; --trv) {
|
||||
if (trv <= path)
|
||||
break;
|
||||
if (*trv == '/') {
|
||||
*trv = '\0';
|
||||
if (stat(path, &sbuf))
|
||||
return(0);
|
||||
if (!S_ISDIR(sbuf.st_mode)) {
|
||||
errno = ENOTDIR;
|
||||
return(0);
|
||||
}
|
||||
*trv = '/';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (doopen) {
|
||||
if ((*doopen =
|
||||
open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
|
||||
return(1);
|
||||
if (errno != EEXIST)
|
||||
return(0);
|
||||
}
|
||||
else if (stat(path, &sbuf))
|
||||
return(errno == ENOENT ? 1 : 0);
|
||||
|
||||
/* tricky little algorithm for backward compatibility */
|
||||
for (trv = start;;) {
|
||||
if (!*trv)
|
||||
return(0);
|
||||
if (*trv == 'z')
|
||||
*trv++ = 'a';
|
||||
else {
|
||||
if (isdigit((unsigned char)*trv))
|
||||
*trv = 'a';
|
||||
else
|
||||
++*trv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
46
dist/nvi/clib/mmap.c
vendored
Normal file
46
dist/nvi/clib/mmap.c
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
/* $NetBSD: mmap.c,v 1.1.1.2 2008/05/18 14:29:38 aymeric Exp $ */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* This function fakes mmap() by reading `len' bytes from the file descriptor
|
||||
* `fd' and returning a pointer to that memory. The "mapped" region can later
|
||||
* be deallocated with munmap().
|
||||
*
|
||||
* Note: ONLY reading is supported and only reading of the exact size of the
|
||||
* file will work.
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_MMAP
|
||||
* PUBLIC: char *mmap __P((char *, size_t, int, int, int, off_t));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
char *
|
||||
mmap(char *addr, size_t len, int prot, int flags, int fd, off_t off)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
if ((ptr = (char *)malloc(len)) == 0)
|
||||
return ((char *)-1);
|
||||
if (read(fd, ptr, len) < 0) {
|
||||
free(ptr);
|
||||
return ((char *)-1);
|
||||
}
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
/*
|
||||
* PUBLIC: #ifndef HAVE_MMAP
|
||||
* PUBLIC: int munmap __P((char *, size_t));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
int
|
||||
munmap(char *addr, size_t len)
|
||||
{
|
||||
free(addr);
|
||||
return (0);
|
||||
}
|
47
dist/nvi/clib/snprintf.c
vendored
Normal file
47
dist/nvi/clib/snprintf.c
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
/* $NetBSD: snprintf.c,v 1.1.1.2 2008/05/18 14:29:39 aymeric Exp $ */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* PUBLIC: #ifndef HAVE_SNPRINTF
|
||||
* PUBLIC: int snprintf __P((char *, size_t, const char *, ...));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
int
|
||||
#ifdef __STDC__
|
||||
snprintf(char *str, size_t n, const char *fmt, ...)
|
||||
#else
|
||||
snprintf(str, n, fmt, va_alist)
|
||||
char *str;
|
||||
size_t n;
|
||||
const char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
int rval;
|
||||
#ifdef __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
#ifdef SPRINTF_RET_CHARPNT
|
||||
(void)vsprintf(str, fmt, ap);
|
||||
va_end(ap);
|
||||
return (strlen(str));
|
||||
#else
|
||||
rval = vsprintf(str, fmt, ap);
|
||||
va_end(ap);
|
||||
return (rval);
|
||||
#endif
|
||||
}
|
64
dist/nvi/clib/strdup.c
vendored
Normal file
64
dist/nvi/clib/strdup.c
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
/* $NetBSD: strdup.c,v 1.1.1.2 2008/05/18 14:29:39 aymeric Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char sccsid[] = "@(#)strdup.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* PUBLIC: #ifndef HAVE_STRDUP
|
||||
* PUBLIC: char *strdup __P((const char *));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
char *
|
||||
strdup(const char *str)
|
||||
{
|
||||
size_t len;
|
||||
char *copy;
|
||||
|
||||
len = strlen(str) + 1;
|
||||
if (!(copy = malloc((u_int)len)))
|
||||
return (NULL);
|
||||
memcpy(copy, str, len);
|
||||
return (copy);
|
||||
}
|
63
dist/nvi/clib/strpbrk.c
vendored
Normal file
63
dist/nvi/clib/strpbrk.c
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
/* $NetBSD: strpbrk.c,v 1.1.1.2 2008/05/18 14:29:39 aymeric Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1985, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char sccsid[] = "@(#)strpbrk.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* Find the first occurrence in s1 of a character in s2 (excluding NUL).
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_STRPBRK
|
||||
* PUBLIC: char *strpbrk __P((const char *, const char *));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
char *
|
||||
strpbrk(register const char *s1, register const char *s2)
|
||||
{
|
||||
register const char *scanp;
|
||||
register int c, sc;
|
||||
|
||||
while ((c = *s1++) != 0) {
|
||||
for (scanp = s2; (sc = *scanp++) != 0;)
|
||||
if (sc == c)
|
||||
return ((char *)(s1 - 1));
|
||||
}
|
||||
return (NULL);
|
||||
}
|
85
dist/nvi/clib/strsep.c
vendored
Normal file
85
dist/nvi/clib/strsep.c
vendored
Normal file
|
@ -0,0 +1,85 @@
|
|||
/* $NetBSD: strsep.c,v 1.1.1.2 2008/05/18 14:29:39 aymeric Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char sccsid[] = "@(#)strsep.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* Get next token from string *stringp, where tokens are possibly-empty
|
||||
* strings separated by characters from delim.
|
||||
*
|
||||
* Writes NULs into the string at *stringp to end tokens.
|
||||
* delim need not remain constant from call to call.
|
||||
* On return, *stringp points past the last NUL written (if there might
|
||||
* be further tokens), or is NULL (if there are definitely no more tokens).
|
||||
*
|
||||
* If *stringp is NULL, strsep returns NULL.
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_STRSEP
|
||||
* PUBLIC: char *strsep __P((char **, const char *));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
char *
|
||||
strsep(register char **stringp, register const char *delim)
|
||||
{
|
||||
register char *s;
|
||||
register const char *spanp;
|
||||
register int c, sc;
|
||||
char *tok;
|
||||
|
||||
if ((s = *stringp) == NULL)
|
||||
return (NULL);
|
||||
for (tok = s;;) {
|
||||
c = *s++;
|
||||
spanp = delim;
|
||||
do {
|
||||
if ((sc = *spanp++) == c) {
|
||||
if (c == 0)
|
||||
s = NULL;
|
||||
else
|
||||
s[-1] = 0;
|
||||
*stringp = s;
|
||||
return (tok);
|
||||
}
|
||||
} while (sc != 0);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
133
dist/nvi/clib/strtol.c
vendored
Normal file
133
dist/nvi/clib/strtol.c
vendored
Normal file
|
@ -0,0 +1,133 @@
|
|||
/* $NetBSD: strtol.c,v 1.1.1.2 2008/05/18 14:29:39 aymeric Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char sccsid[] = "@(#)strtol.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
* Convert a string to a long integer.
|
||||
*
|
||||
* Ignores `locale' stuff. Assumes that the upper and lower case
|
||||
* alphabets and digits are each contiguous.
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_STRTOL
|
||||
* PUBLIC: long strtol __P((const char *, char **, int));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
long
|
||||
strtol(const char *nptr, char **endptr, register int base)
|
||||
{
|
||||
register const char *s = nptr;
|
||||
register unsigned long acc;
|
||||
register int c;
|
||||
register unsigned long cutoff;
|
||||
register int neg = 0, any, cutlim;
|
||||
|
||||
/*
|
||||
* Skip white space and pick up leading +/- sign if any.
|
||||
* If base is 0, allow 0x for hex and 0 for octal, else
|
||||
* assume decimal; if base is already 16, allow 0x.
|
||||
*/
|
||||
do {
|
||||
c = *s++;
|
||||
} while (isspace(c));
|
||||
if (c == '-') {
|
||||
neg = 1;
|
||||
c = *s++;
|
||||
} else if (c == '+')
|
||||
c = *s++;
|
||||
if ((base == 0 || base == 16) &&
|
||||
c == '0' && (*s == 'x' || *s == 'X')) {
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
if (base == 0)
|
||||
base = c == '0' ? 8 : 10;
|
||||
|
||||
/*
|
||||
* Compute the cutoff value between legal numbers and illegal
|
||||
* numbers. That is the largest legal value, divided by the
|
||||
* base. An input number that is greater than this value, if
|
||||
* followed by a legal input character, is too big. One that
|
||||
* is equal to this value may be valid or not; the limit
|
||||
* between valid and invalid numbers is then based on the last
|
||||
* digit. For instance, if the range for longs is
|
||||
* [-2147483648..2147483647] and the input base is 10,
|
||||
* cutoff will be set to 214748364 and cutlim to either
|
||||
* 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
|
||||
* a value > 214748364, or equal but the next digit is > 7 (or 8),
|
||||
* the number is too big, and we will return a range error.
|
||||
*
|
||||
* Set any if any `digits' consumed; make it negative to indicate
|
||||
* overflow.
|
||||
*/
|
||||
cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
|
||||
cutlim = cutoff % (unsigned long)base;
|
||||
cutoff /= (unsigned long)base;
|
||||
for (acc = 0, any = 0;; c = *s++) {
|
||||
if (isdigit(c))
|
||||
c -= '0';
|
||||
else if (isalpha(c))
|
||||
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
|
||||
else
|
||||
break;
|
||||
if (c >= base)
|
||||
break;
|
||||
if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
|
||||
any = -1;
|
||||
else {
|
||||
any = 1;
|
||||
acc *= base;
|
||||
acc += c;
|
||||
}
|
||||
}
|
||||
if (any < 0) {
|
||||
acc = neg ? LONG_MIN : LONG_MAX;
|
||||
errno = ERANGE;
|
||||
} else if (neg)
|
||||
acc = -acc;
|
||||
if (endptr != 0)
|
||||
*endptr = (char *)(any ? s - 1 : nptr);
|
||||
return (acc);
|
||||
}
|
112
dist/nvi/clib/strtoul.c
vendored
Normal file
112
dist/nvi/clib/strtoul.c
vendored
Normal file
|
@ -0,0 +1,112 @@
|
|||
/* $NetBSD: strtoul.c,v 1.1.1.2 2008/05/18 14:29:39 aymeric Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char sccsid[] = "@(#)strtoul.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
* Convert a string to an unsigned long integer.
|
||||
*
|
||||
* Ignores `locale' stuff. Assumes that the upper and lower case
|
||||
* alphabets and digits are each contiguous.
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_STRTOUL
|
||||
* PUBLIC: unsigned long strtoul __P((const char *, char **, int));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
unsigned long
|
||||
strtoul(const char *nptr, char **endptr, register int base)
|
||||
{
|
||||
register const char *s = nptr;
|
||||
register unsigned long acc;
|
||||
register int c;
|
||||
register unsigned long cutoff;
|
||||
register int neg = 0, any, cutlim;
|
||||
|
||||
/*
|
||||
* See strtol for comments as to the logic used.
|
||||
*/
|
||||
do {
|
||||
c = *s++;
|
||||
} while (isspace(c));
|
||||
if (c == '-') {
|
||||
neg = 1;
|
||||
c = *s++;
|
||||
} else if (c == '+')
|
||||
c = *s++;
|
||||
if ((base == 0 || base == 16) &&
|
||||
c == '0' && (*s == 'x' || *s == 'X')) {
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
if (base == 0)
|
||||
base = c == '0' ? 8 : 10;
|
||||
cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
|
||||
cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
|
||||
for (acc = 0, any = 0;; c = *s++) {
|
||||
if (isdigit(c))
|
||||
c -= '0';
|
||||
else if (isalpha(c))
|
||||
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
|
||||
else
|
||||
break;
|
||||
if (c >= base)
|
||||
break;
|
||||
if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
|
||||
any = -1;
|
||||
else {
|
||||
any = 1;
|
||||
acc *= base;
|
||||
acc += c;
|
||||
}
|
||||
}
|
||||
if (any < 0) {
|
||||
acc = ULONG_MAX;
|
||||
errno = ERANGE;
|
||||
} else if (neg)
|
||||
acc = -acc;
|
||||
if (endptr != 0)
|
||||
*endptr = (char *)(any ? s - 1 : nptr);
|
||||
return (acc);
|
||||
}
|
33
dist/nvi/clib/vsnprintf.c
vendored
Normal file
33
dist/nvi/clib/vsnprintf.c
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
/* $NetBSD: vsnprintf.c,v 1.1.1.2 2008/05/18 14:29:39 aymeric Exp $ */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* PUBLIC: #ifndef HAVE_VSNPRINTF
|
||||
* PUBLIC: int vsnprintf __P((char *, size_t, const char *, ...));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
int
|
||||
vsnprintf(str, n, fmt, ap)
|
||||
char *str;
|
||||
size_t n;
|
||||
const char *fmt;
|
||||
va_list ap;
|
||||
{
|
||||
#ifdef SPRINTF_RET_CHARPNT
|
||||
(void)vsprintf(str, fmt, ap);
|
||||
return (strlen(str));
|
||||
#else
|
||||
return (vsprintf(str, fmt, ap));
|
||||
#endif
|
||||
}
|
609
dist/nvi/common/api.c
vendored
Normal file
609
dist/nvi/common/api.c
vendored
Normal file
|
@ -0,0 +1,609 @@
|
|||
/* $NetBSD: api.c,v 1.2 2008/12/05 22:51:42 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* Copyright (c) 1992, 1993, 1994, 1995, 1996
|
||||
* Keith Bostic. All rights reserved.
|
||||
* Copyright (c) 1995
|
||||
* George V. Neville-Neil. All rights reserved.
|
||||
*
|
||||
* See the LICENSE file for redistribution information.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "Id: api.c,v 8.40 2002/06/08 19:30:33 skimo Exp (Berkeley) Date: 2002/06/08 19:30:33";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <bitstring.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../common/common.h"
|
||||
#include "../ex/tag.h"
|
||||
|
||||
extern GS *__global_list; /* XXX */
|
||||
|
||||
/*
|
||||
* api_fscreen --
|
||||
* Return a pointer to the screen specified by the screen id
|
||||
* or a file name.
|
||||
*
|
||||
* PUBLIC: SCR *api_fscreen __P((int, char *));
|
||||
*/
|
||||
SCR *
|
||||
api_fscreen(int id, char *name)
|
||||
{
|
||||
GS *gp;
|
||||
SCR *tsp;
|
||||
WIN *wp;
|
||||
|
||||
gp = __global_list;
|
||||
|
||||
/* Search the displayed lists. */
|
||||
for (wp = gp->dq.cqh_first;
|
||||
wp != (void *)&gp->dq; wp = wp->q.cqe_next)
|
||||
for (tsp = wp->scrq.cqh_first;
|
||||
tsp != (void *)&wp->scrq; tsp = tsp->q.cqe_next)
|
||||
if (name == NULL) {
|
||||
if (id == tsp->id)
|
||||
return (tsp);
|
||||
} else if (!strcmp(name, tsp->frp->name))
|
||||
return (tsp);
|
||||
|
||||
/* Search the hidden list. */
|
||||
for (tsp = gp->hq.cqh_first;
|
||||
tsp != (void *)&gp->hq; tsp = tsp->q.cqe_next)
|
||||
if (name == NULL) {
|
||||
if (id == tsp->id)
|
||||
return (tsp);
|
||||
} else if (!strcmp(name, tsp->frp->name))
|
||||
return (tsp);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* api_aline --
|
||||
* Append a line.
|
||||
*
|
||||
* PUBLIC: int api_aline __P((SCR *, db_recno_t, char *, size_t));
|
||||
*/
|
||||
int
|
||||
api_aline(SCR *sp, db_recno_t lno, char *line, size_t len)
|
||||
{
|
||||
size_t wblen;
|
||||
const CHAR_T *wbp;
|
||||
|
||||
CHAR2INT(sp, line, len, wbp, wblen);
|
||||
|
||||
return (db_append(sp, 1, lno, wbp, wblen));
|
||||
}
|
||||
|
||||
/*
|
||||
* api_extend --
|
||||
* Extend file.
|
||||
*
|
||||
* PUBLIC: int api_extend __P((SCR *, db_recno_t));
|
||||
*/
|
||||
int
|
||||
api_extend(SCR *sp, db_recno_t lno)
|
||||
{
|
||||
db_recno_t lastlno;
|
||||
if (db_last(sp, &lastlno))
|
||||
return 1;
|
||||
while(lastlno < lno)
|
||||
if (db_append(sp, 1, lastlno++, NULL, 0))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* api_dline --
|
||||
* Delete a line.
|
||||
*
|
||||
* PUBLIC: int api_dline __P((SCR *, db_recno_t));
|
||||
*/
|
||||
int
|
||||
api_dline(SCR *sp, db_recno_t lno)
|
||||
{
|
||||
if (db_delete(sp, lno))
|
||||
return 1;
|
||||
/* change current line if deleted line is that one
|
||||
* or one berfore that
|
||||
*/
|
||||
if (sp->lno >= lno && sp->lno > 1)
|
||||
sp->lno--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* api_gline --
|
||||
* Get a line.
|
||||
*
|
||||
* PUBLIC: int api_gline __P((SCR *, db_recno_t, CHAR_T **, size_t *));
|
||||
*/
|
||||
int
|
||||
api_gline(SCR *sp, db_recno_t lno, CHAR_T **linepp, size_t *lenp)
|
||||
{
|
||||
int isempty;
|
||||
|
||||
if (db_eget(sp, lno, linepp, lenp, &isempty)) {
|
||||
if (isempty)
|
||||
msgq(sp, M_ERR, "209|The file is empty");
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* api_iline --
|
||||
* Insert a line.
|
||||
*
|
||||
* PUBLIC: int api_iline __P((SCR *, db_recno_t, CHAR_T *, size_t));
|
||||
*/
|
||||
int
|
||||
api_iline(SCR *sp, db_recno_t lno, CHAR_T *line, size_t len)
|
||||
{
|
||||
return (db_insert(sp, lno, line, len));
|
||||
}
|
||||
|
||||
/*
|
||||
* api_lline --
|
||||
* Return the line number of the last line in the file.
|
||||
*
|
||||
* PUBLIC: int api_lline __P((SCR *, db_recno_t *));
|
||||
*/
|
||||
int
|
||||
api_lline(SCR *sp, db_recno_t *lnop)
|
||||
{
|
||||
return (db_last(sp, lnop));
|
||||
}
|
||||
|
||||
/*
|
||||
* api_sline --
|
||||
* Set a line.
|
||||
*
|
||||
* PUBLIC: int api_sline __P((SCR *, db_recno_t, CHAR_T *, size_t));
|
||||
*/
|
||||
int
|
||||
api_sline(SCR *sp, db_recno_t lno, CHAR_T *line, size_t len)
|
||||
{
|
||||
return (db_set(sp, lno, line, len));
|
||||
}
|
||||
|
||||
/*
|
||||
* api_getmark --
|
||||
* Get the mark.
|
||||
*
|
||||
* PUBLIC: int api_getmark __P((SCR *, int, MARK *));
|
||||
*/
|
||||
int
|
||||
api_getmark(SCR *sp, int markname, MARK *mp)
|
||||
{
|
||||
return (mark_get(sp, (ARG_CHAR_T)markname, mp, M_ERR));
|
||||
}
|
||||
|
||||
/*
|
||||
* api_setmark --
|
||||
* Set the mark.
|
||||
*
|
||||
* PUBLIC: int api_setmark __P((SCR *, int, MARK *));
|
||||
*/
|
||||
int
|
||||
api_setmark(SCR *sp, int markname, MARK *mp)
|
||||
{
|
||||
return (mark_set(sp, (ARG_CHAR_T)markname, mp, 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* api_nextmark --
|
||||
* Return the first mark if next not set, otherwise return the
|
||||
* subsequent mark.
|
||||
*
|
||||
* PUBLIC: int api_nextmark __P((SCR *, int, char *));
|
||||
*/
|
||||
int
|
||||
api_nextmark(SCR *sp, int next, char *namep)
|
||||
{
|
||||
LMARK *mp;
|
||||
|
||||
mp = sp->ep->marks.lh_first;
|
||||
if (next)
|
||||
for (; mp != NULL; mp = mp->q.le_next)
|
||||
if (mp->name == *namep) {
|
||||
mp = mp->q.le_next;
|
||||
break;
|
||||
}
|
||||
if (mp == NULL)
|
||||
return (1);
|
||||
*namep = mp->name;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* api_getcursor --
|
||||
* Get the cursor.
|
||||
*
|
||||
* PUBLIC: int api_getcursor __P((SCR *, MARK *));
|
||||
*/
|
||||
int
|
||||
api_getcursor(SCR *sp, MARK *mp)
|
||||
{
|
||||
mp->lno = sp->lno;
|
||||
mp->cno = sp->cno;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* api_setcursor --
|
||||
* Set the cursor.
|
||||
*
|
||||
* PUBLIC: int api_setcursor __P((SCR *, MARK *));
|
||||
*/
|
||||
int
|
||||
api_setcursor(SCR *sp, MARK *mp)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (db_get(sp, mp->lno, DBG_FATAL, NULL, &len))
|
||||
return (1);
|
||||
if (mp->cno > len) {
|
||||
msgq(sp, M_ERR, "Cursor set to nonexistent column");
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Set the cursor. */
|
||||
sp->lno = mp->lno;
|
||||
sp->cno = mp->cno;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* api_emessage --
|
||||
* Print an error message.
|
||||
*
|
||||
* PUBLIC: void api_emessage __P((SCR *, char *));
|
||||
*/
|
||||
void
|
||||
api_emessage(SCR *sp, char *text)
|
||||
{
|
||||
msgq(sp, M_ERR, "%s", text);
|
||||
}
|
||||
|
||||
/*
|
||||
* api_imessage --
|
||||
* Print an informational message.
|
||||
*
|
||||
* PUBLIC: void api_imessage __P((SCR *, char *));
|
||||
*/
|
||||
void
|
||||
api_imessage(SCR *sp, char *text)
|
||||
{
|
||||
msgq(sp, M_INFO, "%s", text);
|
||||
}
|
||||
|
||||
/*
|
||||
* api_edit
|
||||
* Create a new screen and return its id
|
||||
* or edit a new file in the current screen.
|
||||
*
|
||||
* PUBLIC: int api_edit __P((SCR *, char *, SCR **, int));
|
||||
*/
|
||||
int
|
||||
api_edit(SCR *sp, char *file, SCR **spp, int newscreen)
|
||||
{
|
||||
EXCMD cmd;
|
||||
size_t wlen;
|
||||
const CHAR_T *wp;
|
||||
|
||||
if (file) {
|
||||
ex_cinit(sp, &cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0);
|
||||
CHAR2INT(sp, file, strlen(file) + 1, wp, wlen);
|
||||
argv_exp0(sp, &cmd, wp, wlen - 1 /* terminating 0 */);
|
||||
} else
|
||||
ex_cinit(sp, &cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0);
|
||||
if (newscreen)
|
||||
cmd.flags |= E_NEWSCREEN; /* XXX */
|
||||
if (cmd.cmd->fn(sp, &cmd))
|
||||
return (1);
|
||||
*spp = sp->nextdisp;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* api_escreen
|
||||
* End a screen.
|
||||
*
|
||||
* PUBLIC: int api_escreen __P((SCR *));
|
||||
*/
|
||||
int
|
||||
api_escreen(SCR *sp)
|
||||
{
|
||||
EXCMD cmd;
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* If the interpreter exits anything other than the current
|
||||
* screen, vi isn't going to update everything correctly.
|
||||
*/
|
||||
ex_cinit(sp, &cmd, C_QUIT, 0, OOBLNO, OOBLNO, 0);
|
||||
return (cmd.cmd->fn(sp, &cmd));
|
||||
}
|
||||
|
||||
/*
|
||||
* api_swscreen --
|
||||
* Switch to a new screen.
|
||||
*
|
||||
* PUBLIC: int api_swscreen __P((SCR *, SCR *));
|
||||
*/
|
||||
int
|
||||
api_swscreen(SCR *sp, SCR *new)
|
||||
{
|
||||
/*
|
||||
* XXX
|
||||
* If the interpreter switches from anything other than the
|
||||
* current screen, vi isn't going to update everything correctly.
|
||||
*/
|
||||
sp->nextdisp = new;
|
||||
F_SET(sp, SC_SSWITCH);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* api_map --
|
||||
* Map a key.
|
||||
*
|
||||
* PUBLIC: int api_map __P((SCR *, char *, char *, size_t));
|
||||
*/
|
||||
int
|
||||
api_map(SCR *sp, char *name, char *map, size_t len)
|
||||
{
|
||||
EXCMD cmd;
|
||||
size_t wlen;
|
||||
const CHAR_T *wp;
|
||||
|
||||
ex_cinit(sp, &cmd, C_MAP, 0, OOBLNO, OOBLNO, 0);
|
||||
CHAR2INT(sp, name, strlen(name) + 1, wp, wlen);
|
||||
argv_exp0(sp, &cmd, wp, wlen - 1);
|
||||
CHAR2INT(sp, map, len, wp, wlen);
|
||||
argv_exp0(sp, &cmd, wp, wlen);
|
||||
return (cmd.cmd->fn(sp, &cmd));
|
||||
}
|
||||
|
||||
/*
|
||||
* api_unmap --
|
||||
* Unmap a key.
|
||||
*
|
||||
* PUBLIC: int api_unmap __P((SCR *, char *));
|
||||
*/
|
||||
int
|
||||
api_unmap(SCR *sp, char *name)
|
||||
{
|
||||
EXCMD cmd;
|
||||
size_t wlen;
|
||||
const CHAR_T *wp;
|
||||
|
||||
ex_cinit(sp, &cmd, C_UNMAP, 0, OOBLNO, OOBLNO, 0);
|
||||
CHAR2INT(sp, name, strlen(name) + 1, wp, wlen);
|
||||
argv_exp0(sp, &cmd, wp, wlen - 1);
|
||||
return (cmd.cmd->fn(sp, &cmd));
|
||||
}
|
||||
|
||||
/*
|
||||
* api_opts_get --
|
||||
* Return a option value as a string, in allocated memory.
|
||||
* If the option is of type boolean, boolvalue is (un)set
|
||||
* according to the value; otherwise boolvalue is -1.
|
||||
*
|
||||
* PUBLIC: int api_opts_get __P((SCR *, CHAR_T *, char **, int *));
|
||||
*/
|
||||
int
|
||||
api_opts_get(SCR *sp, const CHAR_T *name, char **value, int *boolvalue)
|
||||
{
|
||||
OPTLIST const *op;
|
||||
int offset;
|
||||
|
||||
if ((op = opts_search(name)) == NULL) {
|
||||
opts_nomatch(sp, name);
|
||||
return (1);
|
||||
}
|
||||
|
||||
offset = op - optlist;
|
||||
if (boolvalue != NULL)
|
||||
*boolvalue = -1;
|
||||
switch (op->type) {
|
||||
case OPT_0BOOL:
|
||||
case OPT_1BOOL:
|
||||
MALLOC_RET(sp, *value, char *, STRLEN(op->name) + 2 + 1);
|
||||
(void)sprintf(*value,
|
||||
"%s"WS, O_ISSET(sp, offset) ? "" : "no", op->name);
|
||||
if (boolvalue != NULL)
|
||||
*boolvalue = O_ISSET(sp, offset);
|
||||
break;
|
||||
case OPT_NUM:
|
||||
MALLOC_RET(sp, *value, char *, 20);
|
||||
(void)sprintf(*value, "%lu", (u_long)O_VAL(sp, offset));
|
||||
break;
|
||||
case OPT_STR:
|
||||
if (O_STR(sp, offset) == NULL) {
|
||||
MALLOC_RET(sp, *value, char *, 2);
|
||||
value[0] = '\0';
|
||||
} else {
|
||||
MALLOC_RET(sp,
|
||||
*value, char *, strlen(O_STR(sp, offset)) + 1);
|
||||
(void)sprintf(*value, "%s", O_STR(sp, offset));
|
||||
}
|
||||
break;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* api_opts_set --
|
||||
* Set options.
|
||||
*
|
||||
* PUBLIC: int api_opts_set __P((SCR *, CHAR_T *, char *, u_long, int));
|
||||
*/
|
||||
int
|
||||
api_opts_set(SCR *sp, const CHAR_T *name,
|
||||
const char *str_value, u_long num_value, int bool_value)
|
||||
{
|
||||
ARGS *ap[2], a, b;
|
||||
OPTLIST const *op;
|
||||
int rval;
|
||||
size_t blen;
|
||||
CHAR_T *bp;
|
||||
|
||||
if ((op = opts_search(name)) == NULL) {
|
||||
opts_nomatch(sp, name);
|
||||
return (1);
|
||||
}
|
||||
|
||||
switch (op->type) {
|
||||
case OPT_0BOOL:
|
||||
case OPT_1BOOL:
|
||||
GET_SPACE_RETW(sp, bp, blen, 64);
|
||||
a.len = SPRINTF(bp, 64, L("%s"WS), bool_value ? "" : "no", name);
|
||||
break;
|
||||
case OPT_NUM:
|
||||
GET_SPACE_RETW(sp, bp, blen, 64);
|
||||
a.len = SPRINTF(bp, 64, L(""WS"=%lu"), name, num_value);
|
||||
break;
|
||||
case OPT_STR:
|
||||
GET_SPACE_RETW(sp, bp, blen, 1024);
|
||||
a.len = SPRINTF(bp, 1024, L(""WS"=%s"), name, str_value);
|
||||
break;
|
||||
default:
|
||||
bp = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
a.bp = bp;
|
||||
b.len = 0;
|
||||
b.bp = NULL;
|
||||
ap[0] = &a;
|
||||
ap[1] = &b;
|
||||
rval = opts_set(sp, ap, NULL);
|
||||
|
||||
FREE_SPACEW(sp, bp, blen);
|
||||
|
||||
return (rval);
|
||||
}
|
||||
|
||||
/*
|
||||
* api_run_str --
|
||||
* Execute a string as an ex command.
|
||||
*
|
||||
* PUBLIC: int api_run_str __P((SCR *, char *));
|
||||
*/
|
||||
int
|
||||
api_run_str(SCR *sp, char *cmd)
|
||||
{
|
||||
size_t wlen;
|
||||
const CHAR_T *wp;
|
||||
|
||||
CHAR2INT(sp, cmd, strlen(cmd)+1, wp, wlen);
|
||||
return (ex_run_str(sp, NULL, wp, wlen - 1, 0, 0));
|
||||
}
|
||||
|
||||
/*
|
||||
* PUBLIC: TAGQ * api_tagq_new __P((SCR*, char*));
|
||||
*/
|
||||
TAGQ *
|
||||
api_tagq_new(SCR *sp, char *tag)
|
||||
{
|
||||
TAGQ *tqp;
|
||||
size_t len;
|
||||
|
||||
/* Allocate and initialize the tag queue structure. */
|
||||
len = strlen(tag);
|
||||
CALLOC_GOTO(sp, tqp, TAGQ *, 1, sizeof(TAGQ) + len + 1);
|
||||
CIRCLEQ_INIT(&tqp->tagq);
|
||||
tqp->tag = tqp->buf;
|
||||
memcpy(tqp->tag, tag, (tqp->tlen = len) + 1);
|
||||
|
||||
return tqp;
|
||||
|
||||
alloc_err:
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* PUBLIC: void api_tagq_add __P((SCR*, TAGQ*, char*, char *, char *));
|
||||
*/
|
||||
void
|
||||
api_tagq_add(SCR *sp, TAGQ *tqp, char *filename, char *search, char *msg)
|
||||
{
|
||||
TAG *tp;
|
||||
const CHAR_T *wp;
|
||||
size_t wlen;
|
||||
size_t flen = strlen(filename);
|
||||
size_t slen = strlen(search);
|
||||
size_t mlen = strlen(msg);
|
||||
|
||||
CALLOC_GOTO(sp, tp, TAG *, 1,
|
||||
sizeof(TAG) - 1 + flen + 1 +
|
||||
(slen + 1 + mlen + 1) * sizeof(CHAR_T));
|
||||
tp->fname = (char *)tp->buf;
|
||||
memcpy(tp->fname, filename, flen + 1);
|
||||
tp->fnlen = flen;
|
||||
tp->search = (CHAR_T *)((char *)tp->fname + flen + 1);
|
||||
CHAR2INT(sp, search, slen + 1, wp, wlen);
|
||||
MEMCPYW(tp->search, wp, wlen);
|
||||
tp->slen = slen;
|
||||
tp->msg = tp->search + slen + 1;
|
||||
CHAR2INT(sp, msg, mlen + 1, wp, wlen);
|
||||
MEMCPYW(tp->msg, wp, wlen);
|
||||
tp->mlen = mlen;
|
||||
CIRCLEQ_INSERT_TAIL(&tqp->tagq, tp, q);
|
||||
|
||||
alloc_err:
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* PUBLIC: int api_tagq_push __P((SCR*, TAGQ**));
|
||||
*/
|
||||
int
|
||||
api_tagq_push(SCR *sp, TAGQ **tqpp)
|
||||
{
|
||||
TAGQ *tqp;
|
||||
|
||||
tqp = *tqpp;
|
||||
|
||||
*tqpp = 0;
|
||||
|
||||
/* Check to see if we found anything. */
|
||||
if (tqp->tagq.cqh_first == (void *)&tqp->tagq) {
|
||||
free(tqp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
tqp->current = tqp->tagq.cqh_first;
|
||||
|
||||
if (tagq_push(sp, tqp, 0, 0))
|
||||
return 1;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* PUBLIC: void api_tagq_free __P((SCR*, TAGQ*));
|
||||
*/
|
||||
void
|
||||
api_tagq_free(SCR *sp, TAGQ *tqp)
|
||||
{
|
||||
if (tqp)
|
||||
tagq_free(sp, tqp);
|
||||
}
|
31
dist/nvi/common/args.h
vendored
Normal file
31
dist/nvi/common/args.h
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
/* $NetBSD: args.h,v 1.1.1.2 2008/05/18 14:29:40 aymeric Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* Copyright (c) 1993, 1994, 1995, 1996
|
||||
* Keith Bostic. All rights reserved.
|
||||
*
|
||||
* See the LICENSE file for redistribution information.
|
||||
*
|
||||
* Id: args.h,v 10.2 1996/03/06 19:50:07 bostic Exp (Berkeley) Date: 1996/03/06 19:50:07
|
||||
*/
|
||||
|
||||
/*
|
||||
* Structure for building "argc/argv" vector of arguments.
|
||||
*
|
||||
* !!!
|
||||
* All arguments are nul terminated as well as having an associated length.
|
||||
* The argument vector is NOT necessarily NULL terminated. The proper way
|
||||
* to check the number of arguments is to use the argc value in the EXCMDARG
|
||||
* structure or to walk the array until an ARGS structure with a length of 0
|
||||
* is found.
|
||||
*/
|
||||
typedef struct _args {
|
||||
CHAR_T *bp; /* Argument. */
|
||||
size_t blen; /* Buffer length. */
|
||||
size_t len; /* Argument length. */
|
||||
|
||||
#define A_ALLOCATED 0x01 /* If allocated space. */
|
||||
u_int8_t flags;
|
||||
} ARGS;
|
112
dist/nvi/common/common.h
vendored
Normal file
112
dist/nvi/common/common.h
vendored
Normal file
|
@ -0,0 +1,112 @@
|
|||
/* $NetBSD: common.h,v 1.3 2012/01/27 16:41:22 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* Copyright (c) 1991, 1993, 1994, 1995, 1996
|
||||
* Keith Bostic. All rights reserved.
|
||||
*
|
||||
* See the LICENSE file for redistribution information.
|
||||
*
|
||||
* Id: common.h,v 10.20 2002/03/02 23:36:22 skimo Exp (Berkeley) Date: 2002/03/02 23:36:22
|
||||
*/
|
||||
|
||||
/*
|
||||
* Avoid include sys/types.h after definition of pgno_t
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/queue.h>
|
||||
#include <bitstring.h>
|
||||
/*
|
||||
* Porting information built at configuration time. Included before
|
||||
* any of nvi's include files.
|
||||
*/
|
||||
#include "port.h"
|
||||
|
||||
/*
|
||||
* Pseudo-local includes. These are files that are unlikely to exist
|
||||
* on most machines to which we're porting vi, and we want to include
|
||||
* them in a very specific order, regardless.
|
||||
*/
|
||||
#include "db.h"
|
||||
#include <regex.h>
|
||||
|
||||
/*
|
||||
* Forward structure declarations. Not pretty, but the include files
|
||||
* are far too interrelated for a clean solution.
|
||||
*/
|
||||
typedef struct _cb CB;
|
||||
typedef struct _csc CSC;
|
||||
typedef struct _conv CONV;
|
||||
typedef struct _conv_win CONVWIN;
|
||||
typedef struct _event EVENT;
|
||||
typedef struct _excmd EXCMD;
|
||||
typedef struct _exf EXF;
|
||||
typedef struct _fref FREF;
|
||||
typedef struct _gs GS;
|
||||
typedef struct _lmark LMARK;
|
||||
typedef struct _mark MARK;
|
||||
typedef struct _msg MSGS;
|
||||
typedef struct _option OPTION;
|
||||
typedef struct _optlist OPTLIST;
|
||||
typedef struct _scr SCR;
|
||||
typedef struct _script SCRIPT;
|
||||
typedef struct _seq SEQ;
|
||||
typedef struct _tag TAG;
|
||||
typedef struct _tagf TAGF;
|
||||
typedef struct _tagq TAGQ;
|
||||
typedef struct _text TEXT;
|
||||
typedef struct _win WIN;
|
||||
|
||||
/* Autoindent state. */
|
||||
typedef enum { C_NOTSET, C_CARATSET, C_NOCHANGE, C_ZEROSET } carat_t;
|
||||
|
||||
/* Busy message types. */
|
||||
typedef enum { BUSY_ON = 1, BUSY_OFF, BUSY_UPDATE } busy_t;
|
||||
|
||||
/*
|
||||
* Routines that return a confirmation return:
|
||||
*
|
||||
* CONF_NO User answered no.
|
||||
* CONF_QUIT User answered quit, eof or an error.
|
||||
* CONF_YES User answered yes.
|
||||
*/
|
||||
typedef enum { CONF_NO, CONF_QUIT, CONF_YES } conf_t;
|
||||
|
||||
/* Directions. */
|
||||
typedef enum { NOTSET, FORWARD, BACKWARD } dir_t;
|
||||
|
||||
/* Line operations. */
|
||||
typedef enum { LINE_APPEND, LINE_DELETE, LINE_INSERT, LINE_RESET } lnop_t;
|
||||
|
||||
/* Lock return values. */
|
||||
typedef enum { LOCK_FAILED, LOCK_SUCCESS, LOCK_UNAVAIL } lockr_t;
|
||||
|
||||
/* Sequence types. */
|
||||
typedef enum { SEQ_ABBREV, SEQ_COMMAND, SEQ_INPUT } seq_t;
|
||||
|
||||
#define ENTIRE_LINE ((size_t)-1)
|
||||
/*
|
||||
* Local includes.
|
||||
*/
|
||||
#include "key.h" /* Required by args.h. */
|
||||
#include "args.h" /* Required by options.h. */
|
||||
#include "options.h" /* Required by screen.h. */
|
||||
|
||||
#include "msg.h" /* Required by gs.h. */
|
||||
#include "cut.h" /* Required by gs.h. */
|
||||
#include "seq.h" /* Required by screen.h. */
|
||||
#include "util.h" /* Required by ex.h. */
|
||||
#include "mark.h" /* Required by gs.h. */
|
||||
#include "conv.h" /* Required by ex.h and screen.h */
|
||||
#include "../ex/ex.h" /* Required by gs.h. */
|
||||
#include "gs.h" /* Required by screen.h. */
|
||||
#include "log.h" /* Required by screen.h */
|
||||
#include "screen.h" /* Required by exf.h. */
|
||||
#include "exf.h"
|
||||
#include "mem.h"
|
||||
#if defined(USE_DB4_LOGGING)
|
||||
#include "vi_auto.h"
|
||||
#endif
|
||||
|
||||
#include "extern.h"
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue