[alt.sources] elvis 1.3 - a clone of vi/ex, part 2 of 6

kirkenda@eecs.cs.pdx.edu (Steve Kirkendall) (08/25/90)

Archive-name: elvis1.3/part2
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	Elvis.lnk
#	Elvis.mak
#	Elvis.prj
#	Makefile.bsd
#	Makefile.s5
#	Makefile.st
#	Makefile.pc
#	Makefile.tos
#	blk.c
#	cmd1.c
#	cmd2.c
#	config.h
# This archive created: Fri Aug 24 10:29:54 1990
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'Elvis.lnk'
then
	echo shar: "will not over-write existing file 'Elvis.lnk'"
else
cat << \SHAR_EOF > 'Elvis.lnk'
blk.obj cmd1.obj cmd2.obj curses.obj cut.obj +
ex.obj input.obj main.obj misc.obj modify.obj +
move1.obj move2.obj move3.obj move4.obj move5.obj +
opts.obj recycle.obj redraw.obj regexp.obj +
regsub.obj system.obj tio.obj tmp.obj vars.obj +
vcmd.obj vi.obj pc.obj sysdos.obj fgetlr.obj +
tgetent.obj tgetnum.obj tgoto.obj isdigit.obj +
tgetflag.obj tgetstr.obj tputs.obj /co /noi /map +
/pac /far /stack:0x2000 
elvis.exe; 
SHAR_EOF
fi
if test -f 'Elvis.mak'
then
	echo shar: "will not over-write existing file 'Elvis.mak'"
else
cat << \SHAR_EOF > 'Elvis.mak'
# Makefile for MSC - if you don't have NDmake, use this one,
# but don't expect to be happy.
# And don't expect to do anything but making the executables, either.

OBJS=	blk.obj cmd1.obj cmd2.obj curses.obj cut.obj ex.obj input.obj \
	main.obj misc.obj modify.obj move1.obj move2.obj move3.obj move4.obj \
	move5.obj opts.obj recycle.obj redraw.obj regexp.obj regsub.obj \
	system.obj tio.obj tmp.obj vars.obj vcmd.obj vi.obj \
	pc.obj sysdos.obj tinytcap.obj

CC=	cl
	
blk.obj:	blk.c
	$(CC) -AL -c blk.c

cmd1.obj:	cmd1.c
	$(CC) -AL -c cmd1.c

cmd2.obj:	cmd2.c
	$(CC) -AL -c cmd2.c

curses.obj:	curses.c
	$(CC) -AL -c curses.c

cut.obj:	cut.c
	$(CC) -AL -c cut.c

ex.obj:		ex.c
	$(CC) -AL -c ex.c

input.obj:	input.c
	$(CC) -AL -c input.c

main.obj:	main.c
	$(CC) -AL -c main.c

misc.obj:	misc.c
	$(CC) -AL -c misc.c

modify.obj:	modify.c
	$(CC) -AL -c modify.c

move1.obj:	move1.c
	$(CC) -AL -c move1.c

move2.obj:	move2.c
	$(CC) -AL -c move2.c

move3.obj:	move3.c
	$(CC) -AL -c move3.c

move4.obj:	move4.c
	$(CC) -AL -c move4.c

move5.obj:	move5.c
	$(CC) -AL -c move5.c

opts.obj:	opts.c
	$(CC) -AL -c opts.c

recycle.obj:	recycle.c
	$(CC) -AL -c recycle.c

redraw.obj:	redraw.c
	$(CC) -AL -c redraw.c

regexp.obj:	regexp.c
	$(CC) -AL -c regexp.c

regsub.obj:	regsub.c
	$(CC) -AL -c regsub.c

system.obj:	system.c
	$(CC) -AL -c system.c

tio.obj:	tio.c
	$(CC) -AL -c tio.c

tmp.obj:	tmp.c
	$(CC) -AL -c tmp.c

vars.obj:	vars.c
	$(CC) -AL -c vars.c

vcmd.obj:	vcmd.c
	$(CC) -AL -c vcmd.c

vi.obj:		vi.c
	$(CC) -AL -c vi.c

pc.obj:		pc.c
	$(CC) -AL -c pc.c

sysdos.obj:	sysdos.c
	$(CC) -AL -c sysdos.c

tinytcap.obj:	tinytcap.c
	$(CC) -AL -c tinytcap.c

elvis.exe: $(OBJS)
	link @elvis.lnk

ctags.exe: ctags.c wildcard.c
	$(CC) -AL ctags.c -o ctags.exe

ref.exe: ref.c
	$(CC) -AL ref.c -o ref.exe

virec.exe: virec.c wildcard.c
	$(CC) -AL virec.c -o virec.exe

wildcard.exe: wildcard.c
	$(CC) -AL wildcard.c -o wildcard.exe
SHAR_EOF
fi
if test -f 'Elvis.prj'
then
	echo shar: "will not over-write existing file 'Elvis.prj'"
else
cat << \SHAR_EOF > 'Elvis.prj'
blk
cmd1
cmd2
curses
cut
ex
input
main
misc
modify
move1
move2
move3
move4
move5
opts
pc
recycle
redraw
regexp
regsub
sysdos
system
tio
tmp
vars
vcmd
vi
termcap\fgetlr
termcap\isdigit
termcap\tgetent
termcap\tgetflag
termcap\tgetnum
termcap\tgetstr
termcap\tgoto
termcap\tputs
SHAR_EOF
fi
if test -f 'Makefile.bsd'
then
	echo shar: "will not over-write existing file 'Makefile.bsd'"
else
cat << \SHAR_EOF > 'Makefile.bsd'
# BSD UNIX Makefile for ELVIS - a clone of `vi`
#
# Use `make` to compile all programs
# Use `make install` to copy the programs to the BIN directory
# Use `make clean` to remove all object files
# Use `make clobber` to remove everything except source & documentation
# Use `make tags` to build new "tags" and "refs" files
# Use `make uue` to produce uuencoded compressed tar archives of the source
# Use `make sh` to produce shar archives of the source

PROGS=	elvis ctags ref virec
#PROGS=	elvis.exe ctags.exe ref.exe virec.exe wildcard.exe
BIN=	/usr/local/bin
OBJS=	blk.o cmd1.o cmd2.o curses.o cut.o ex.o input.o main.o misc.o\
	modify.o move1.o move2.o move3.o move4.o move5.o opts.o recycle.o\
	redraw.o regexp.o regsub.o system.o tio.o tmp.o vars.o vcmd.o vi.o
#	pc.o sysdos.o tinytcap.o
#	atari.o
SRC1=	elvis.man
SRC2=	Elvis.lnk Elvis.mak Elvis.prj Makefile.bsd Makefile.s5 Makefile.st\
	Makefile.pc Makefile.tos blk.c cmd1.c cmd2.c config.h
SRC3=	atari.c curses.c curses.h cut.c elvis.ndx ex.c input.c main.c misc.c
SRC4=	modify.c move1.c move2.c move3.c move4.c move5.c nomagic.c opts.c pc.c\
	recycle.c redraw.c
SRC5=	regexp.c regexp.h regsub.c sysdos.c system.c tinytcap.c tio.c tmp.c
SRC6=	vars.c vcmd.c vi.c vi.h ctags.c ref.c virec.c wildcard.c shell.c
EXTRA=
CFLAGS=	-O
LIBS=	-ltermcap

all: $(PROGS)

elvis: $(OBJS) $(EXTRA)
	$(CC) -o elvis $(OBJS) $(EXTRA) $(LIBS)

ctags: ctags.c
	$(CC) $(CFLAGS) -DSORT ctags.c -o ctags

ref: ref.c
	$(CC) $(CFLAGS) ref.c -o ref

virec: virec.c
	$(CC) $(CFLAGS) virec.c -o virec

# The file cmd1.c is compiled with the extra flag -DDATE="today's date".
# This date is reported when elvis is run and the :version command is given.
# If you have trouble defining the date in this way, then just comment out
# these two lines so cmd1.c is compiled normally.  The :version command
# won't report the compilation date, but that's really no big deal.
cmd1.o: cmd1.c vi.h
	eval $(CC) -c $(CFLAGS) -DDATE=\'\"`date`\"\' cmd1.c

# This just says that a change to nomagic.c is effectively a change to regexp.c
regexp.o: nomagic.c

##############################################################################
install: $(PROGS)
	cp $(PROGS) $(BIN)
	(cd $(BIN); chown bin $(PROGS))
	(cd $(BIN); chmod 755 $(PROGS))

clean:
	rm -f *.o *.uue core

clobber: clean
	rm -f tags refs $(PROGS)

which:
	@echo 'BSD Unix'

tags refs: ctags
	./ctags -r *.[ch]

uue: elvis1.uue elvis2.uue elvis3.uue elvis4.uue elvis5.uue elvis6.uue

elvis1.uue: $(SRC1)
	tar cf elvis1.tar $(SRC1)
	compress -b13 elvis1.tar
	uuencode elvis1.tar.Z <elvis1.tar.Z >elvis1.uue
	rm elvis1.tar*

elvis2.uue: $(SRC2)
	tar cf elvis2.tar $(SRC2)
	compress -b13 elvis2.tar
	uuencode elvis2.tar.Z <elvis2.tar.Z >elvis2.uue
	rm elvis2.tar*

elvis3.uue: $(SRC3)
	tar cf elvis3.tar $(SRC3)
	compress -b13 elvis3.tar
	uuencode elvis3.tar.Z <elvis3.tar.Z >elvis3.uue
	rm elvis3.tar*

elvis4.uue: $(SRC4)
	tar cf elvis4.tar $(SRC4)
	compress -b13 elvis4.tar
	uuencode elvis4.tar.Z <elvis4.tar.Z >elvis4.uue
	rm elvis4.tar*

elvis5.uue: $(SRC5)
	tar cf elvis5.tar $(SRC5)
	compress -b13 elvis5.tar
	uuencode elvis5.tar.Z <elvis5.tar.Z >elvis5.uue
	rm elvis5.tar*

elvis6.uue: $(SRC6)
	tar cf elvis6.tar $(SRC6)
	compress -b13 elvis6.tar
	uuencode elvis6.tar.Z <elvis6.tar.Z >elvis6.uue
	rm elvis6.tar*

sh: elvis1.sh elvis2.sh elvis3.sh elvis4.sh elvis5.sh elvis6.sh

elvis1.sh: $(SRC1)
	shar $(SRC1) >elvis1.sh

elvis2.sh: $(SRC2)
	shar $(SRC2) >elvis2.sh

elvis3.sh: $(SRC3)
	shar $(SRC3) >elvis3.sh

elvis4.sh: $(SRC4)
	shar $(SRC4) >elvis4.sh

elvis5.sh: $(SRC5)
	shar $(SRC5) >elvis5.sh

elvis6.sh: $(SRC6)
	shar $(SRC6) >elvis6.sh

SHAR_EOF
fi
if test -f 'Makefile.s5'
then
	echo shar: "will not over-write existing file 'Makefile.s5'"
else
cat << \SHAR_EOF > 'Makefile.s5'
# UNIX SysV Makefile for ELVIS - a clone of `vi`
#
# This Makefile is pretty close to what you would want for SysV UNIX.
# You may wish to change the LIBS line to look like this:
#
#	LIBS=	-lterminfo
#
# Also, for SCO Xenix, you should add the following line:
#
#	CC=	cc -M2 -i
#
# Use `make` to compile all programs
# Use `make install` to copy the programs to the BIN directory
# Use `make clean` to remove all object files
# Use `make clobber` to remove everything except source & documentation
# Use `make tags` to build new "tags" and "refs" files
# Use `make uue` to produce uuencoded compressed tar archives of the source
# Use `make sh` to produce shar archives of the source

PROGS=	elvis ctags ref virec
#PROGS=	elvis.exe ctags.exe ref.exe virec.exe wildcard.exe
BIN=	/usr/local/bin
OBJS=	blk.o cmd1.o cmd2.o curses.o cut.o ex.o input.o main.o misc.o\
	modify.o move1.o move2.o move3.o move4.o move5.o opts.o recycle.o\
	redraw.o regexp.o regsub.o system.o tio.o tmp.o vars.o vcmd.o vi.o
#	pc.o sysdos.o tinytcap.o
#	atari.o
SRC1=	elvis.man
SRC2=	Elvis.lnk Elvis.mak Elvis.prj Makefile.bsd Makefile.s5 Makefile.st\
	Makefile.pc Makefile.tos blk.c cmd1.c cmd2.c config.h
SRC3=	atari.c curses.c curses.h cut.c elvis.ndx ex.c input.c main.c misc.c
SRC4=	modify.c move1.c move2.c move3.c move4.c move5.c nomagic.c opts.c pc.c\
	recycle.c redraw.c
SRC5=	regexp.c regexp.h regsub.c sysdos.c system.c tinytcap.c tio.c tmp.c
SRC6=	vars.c vcmd.c vi.c vi.h ctags.c ref.c virec.c wildcard.c shell.c
EXTRA=
CFLAGS=	-O -DM_SYSV
LIBS=	-ltermcap

all: $(PROGS)

elvis: $(OBJS) $(EXTRA)
	$(CC) -o elvis $(OBJS) $(EXTRA) $(LIBS)

ctags: ctags.c
	$(CC) $(CFLAGS) -DSORT ctags.c -o ctags

ref: ref.c
	$(CC) $(CFLAGS) ref.c -o ref

virec: virec.c
	$(CC) $(CFLAGS) virec.c -o virec

# The file cmd1.c is compiled with the extra flag -DDATE="today's date".
# This date is reported when elvis is run and the :version command is given.
# If you have trouble defining the date in this way, then just comment out
# these two lines so cmd1.c is compiled normally.  The :version command
# won't report the compilation date, but that's really no big deal.
cmd1.o: cmd1.c vi.h
	eval $(CC) -c $(CFLAGS) -DDATE=\'\"`date`\"\' cmd1.c

# This just says that a change to nomagic.c is effectively a change to regexp.c
regexp.o: nomagic.c

##############################################################################
install: $(PROGS)
	cp $(PROGS) $(BIN)
	(cd $(BIN); chown bin $(PROGS))
	(cd $(BIN); chmod 755 $(PROGS))

clean:
	rm -f *.o *.uue core

clobber: clean
	rm -f tags refs $(PROGS)

which:
	@echo 'System-V UNIX, $$(CC) = $(CC)'

tags refs: ctags
	./ctags -r *.[ch]

uue: elvis1.uue elvis2.uue elvis3.uue elvis4.uue elvis5.uue elvis6.uue

elvis1.uue: $(SRC1)
	tar cf elvis1.tar $(SRC1)
	compress -b13 elvis1.tar
	uuencode elvis1.tar.Z <elvis1.tar.Z >elvis1.uue
	rm elvis1.tar*

elvis2.uue: $(SRC2)
	tar cf elvis2.tar $(SRC2)
	compress -b13 elvis2.tar
	uuencode elvis2.tar.Z <elvis2.tar.Z >elvis2.uue
	rm elvis2.tar*

elvis3.uue: $(SRC3)
	tar cf elvis3.tar $(SRC3)
	compress -b13 elvis3.tar
	uuencode elvis3.tar.Z <elvis3.tar.Z >elvis3.uue
	rm elvis3.tar*

elvis4.uue: $(SRC4)
	tar cf elvis4.tar $(SRC4)
	compress -b13 elvis4.tar
	uuencode elvis4.tar.Z <elvis4.tar.Z >elvis4.uue
	rm elvis4.tar*

elvis5.uue: $(SRC5)
	tar cf elvis5.tar $(SRC5)
	compress -b13 elvis5.tar
	uuencode elvis5.tar.Z <elvis5.tar.Z >elvis5.uue
	rm elvis5.tar*

elvis6.uue: $(SRC6)
	tar cf elvis6.tar $(SRC6)
	compress -b13 elvis6.tar
	uuencode elvis6.tar.Z <elvis6.tar.Z >elvis6.uue
	rm elvis6.tar*

sh: elvis1.sh elvis2.sh elvis3.sh elvis4.sh elvis5.sh elvis6.sh

elvis1.sh: $(SRC1)
	shar $(SRC1) >elvis1.sh

elvis2.sh: $(SRC2)
	shar $(SRC2) >elvis2.sh

elvis3.sh: $(SRC3)
	shar $(SRC3) >elvis3.sh

elvis4.sh: $(SRC4)
	shar $(SRC4) >elvis4.sh

elvis5.sh: $(SRC5)
	shar $(SRC5) >elvis5.sh

elvis6.sh: $(SRC6)
	shar $(SRC6) >elvis6.sh

SHAR_EOF
fi
if test -f 'Makefile.st'
then
	echo shar: "will not over-write existing file 'Makefile.st'"
else
cat << \SHAR_EOF > 'Makefile.st'
# Minix-ST Makefile for ELVIS - a clone of `vi`
#
# Use `make` to compile all programs
# Use `make install` to copy the programs to the BIN directory
# Use `make clean` to remove all object files
# Use `make clobber` to remove everything except source & documentation
# Use `make tags` to build new "tags" and "refs" files
# Use `make uue` to produce uuencoded compressed tar archives of the source
# Use `make sh` to produce shar archives of the source

PROGS=	elvis ctags ref virec
#PROGS=	elvis.exe ctags.exe ref.exe virec.exe wildcard.exe
BIN=	/usr/bin
OBJS=	blk.o cmd1.o cmd2.o curses.o cut.o ex.o input.o main.o misc.o\
	modify.o move1.o move2.o move3.o move4.o move5.o opts.o recycle.o\
	redraw.o regexp.o regsub.o system.o tio.o tmp.o vars.o vcmd.o vi.o
#	pc.o sysdos.o tinytcap.o
#	atari.o
SRC1=	elvis.man
SRC2=	Elvis.lnk Elvis.mak Elvis.prj Makefile.bsd Makefile.s5 Makefile.st\
	Makefile.pc Makefile.tos blk.c cmd1.c cmd2.c config.h
SRC3=	atari.c curses.c curses.h cut.c elvis.ndx ex.c input.c main.c misc.c
SRC4=	modify.c move1.c move2.c move3.c move4.c move5.c nomagic.c opts.c pc.c\
	recycle.c redraw.c
SRC5=	regexp.c regexp.h regsub.c sysdos.c system.c tinytcap.c tio.c tmp.c
SRC6=	vars.c vcmd.c vi.c vi.h ctags.c ref.c virec.c wildcard.c shell.c
EXTRA=
CFLAGS=	-O
LIBS=

all: $(PROGS)

elvis: $(OBJS) $(EXTRA)
	$(CC) -o elvis $(OBJS) $(EXTRA) $(LIBS)

ctags: ctags.c
	$(CC) $(CFLAGS) ctags.c -o ctags

ref: ref.c
	$(CC) $(CFLAGS) ref.c -o ref

virec: virec.c
	$(CC) $(CFLAGS) virec.c -o virec

# The file cmd1.c is compiled with the extra flag -DDATE="today's date".
# This date is reported when elvis is run and the :version command is given.
# If you have trouble defining the date in this way, then just comment out
# these two lines so cmd1.c is compiled normally.  The :version command
# won't report the compilation date, but that's really no big deal.
cmd1.o: cmd1.c vi.h
	eval $(CC) -c $(CFLAGS) -DDATE=\'\"`date`\"\' cmd1.c

# This just says that a change to nomagic.c is effectively a change to regexp.c
regexp.o: nomagic.c

##############################################################################
install: $(PROGS)
	cp $(PROGS) $(BIN)
	(cd $(BIN); chown bin $(PROGS))
	(cd $(BIN); chmod 755 $(PROGS))
	rm -f $(BIN)/ex $(BIN)/view $(BIN)/vi
	ln $(BIN)/elvis $(BIN)/ex
	ln $(BIN)/elvis $(BIN)/view
	ln $(BIN)/elvis $(BIN)/vi

clean:
	rm -f *.o *.uue core

clobber: clean
	rm -f tags refs $(PROGS)

which:
	@echo 'Minix-ST'

tags refs: ctags
	./ctags -r *.[ch]

uue: elvis1.uue elvis2.uue elvis3.uue elvis4.uue elvis5.uue elvis6.uue

elvis1.uue: $(SRC1)
	tar cf elvis1.tar $(SRC1)
	compress -b13 elvis1.tar
	uuencode elvis1.tar.Z <elvis1.tar.Z >elvis1.uue
	rm elvis1.tar*

elvis2.uue: $(SRC2)
	tar cf elvis2.tar $(SRC2)
	compress -b13 elvis2.tar
	uuencode elvis2.tar.Z <elvis2.tar.Z >elvis2.uue
	rm elvis2.tar*

elvis3.uue: $(SRC3)
	tar cf elvis3.tar $(SRC3)
	compress -b13 elvis3.tar
	uuencode elvis3.tar.Z <elvis3.tar.Z >elvis3.uue
	rm elvis3.tar*

elvis4.uue: $(SRC4)
	tar cf elvis4.tar $(SRC4)
	compress -b13 elvis4.tar
	uuencode elvis4.tar.Z <elvis4.tar.Z >elvis4.uue
	rm elvis4.tar*

elvis5.uue: $(SRC5)
	tar cf elvis5.tar $(SRC5)
	compress -b13 elvis5.tar
	uuencode elvis5.tar.Z <elvis5.tar.Z >elvis5.uue
	rm elvis5.tar*

elvis6.uue: $(SRC6)
	tar cf elvis6.tar $(SRC6)
	compress -b13 elvis6.tar
	uuencode elvis6.tar.Z <elvis6.tar.Z >elvis6.uue
	rm elvis6.tar*

sh: elvis1.sh elvis2.sh elvis3.sh elvis4.sh elvis5.sh elvis6.sh

elvis1.sh: $(SRC1)
	shar $(SRC1) >elvis1.sh

elvis2.sh: $(SRC2)
	shar $(SRC2) >elvis2.sh

elvis3.sh: $(SRC3)
	shar $(SRC3) >elvis3.sh

elvis4.sh: $(SRC4)
	shar $(SRC4) >elvis4.sh

elvis5.sh: $(SRC5)
	shar $(SRC5) >elvis5.sh

elvis6.sh: $(SRC6)
	shar $(SRC6) >elvis6.sh

SHAR_EOF
fi
if test -f 'Makefile.pc'
then
	echo shar: "will not over-write existing file 'Makefile.pc'"
else
cat << \SHAR_EOF > 'Makefile.pc'
# Minix-PC Makefile for ELVIS - a clone of `vi`
#
# Use `make` to compile all programs
# Use `make install` to copy the programs to the BIN directory
# Use `make clean` to remove all object files
# Use `make clobber` to remove everything except source & documentation
# Use `make tags` to build new "tags" and "refs" files
# Use `make uue` to produce uuencoded compressed tar archives of the source
# Use `make sh` to produce shar archives of the source

PROGS=	elvis ctags ref virec
#PROGS=	elvis.exe ctags.exe ref.exe virec.exe wildcard.exe
BIN=	/usr/bin
OBJS=	blk.s cmd1.s cmd2.s curses.s cut.s ex.s input.s main.s misc.s\
	modify.s move1.s move2.s move3.s move4.s move5.s opts.s recycle.s\
	redraw.s regexp.s regsub.s system.s tio.s tmp.s vars.s vcmd.s vi.s
#	pc.s sysdos.s tinytcap.s
#	atari.s
SRC1=	elvis.man
SRC2=	Elvis.lnk Elvis.mak Elvis.prj Makefile.bsd Makefile.s5 Makefile.st\
	Makefile.pc Makefile.tos blk.c cmd1.c cmd2.c config.h
SRC3=	atari.c curses.c curses.h cut.c elvis.ndx ex.c input.c main.c misc.c
SRC4=	modify.c move1.c move2.c move3.c move4.c move5.c nomagic.c opts.c pc.c\
	recycle.c redraw.c
SRC5=	regexp.c regexp.h regsub.c sysdos.c system.c tinytcap.c tio.c tmp.c
SRC6=	vars.c vcmd.c vi.c vi.h ctags.c ref.c virec.c wildcard.c shell.c
EXTRA=
CC=	cc -i
CFLAGS=	-O -DNO_EXTENSIONS -DNO_CHARATTR -DNO_CURSORSHAPE -DNO_SHOWMODE \
	-DNO_DIGRAPH -DNO_MAGIC
LIBS=

all: $(PROGS)

elvis: $(OBJS) $(EXTRA)
	$(CC) -o elvis $(OBJS) $(EXTRA) $(LIBS)

ctags: ctags.c
	$(CC) $(CFLAGS) ctags.c -o ctags

ref: ref.c
	$(CC) $(CFLAGS) ref.c -o ref

virec: virec.c
	$(CC) $(CFLAGS) virec.c -o virec

# The file cmd1.c is compiled with the extra flag -DDATE="today's date".
# This date is reported when elvis is run and the :version command is given.
# If you have trouble defining the date in this way, then just comment out
# these two lines so cmd1.c is compiled normally.  The :version command
# won't report the compilation date, but that's really no big deal.
cmd1.s: cmd1.c vi.h
	eval $(CC) -c $(CFLAGS) -DDATE=\'\"`date`\"\' cmd1.c

# This just says that a change to nomagic.c is effectively a change to regexp.c
regexp.s: nomagic.c

##############################################################################
install: $(PROGS)
	cp $(PROGS) $(BIN)
	(cd $(BIN); chown bin $(PROGS))
	(cd $(BIN); chmod 755 $(PROGS))
	rm -f $(BIN)/ex $(BIN)/view $(BIN)/vi
	ln $(BIN)/elvis $(BIN)/ex
	ln $(BIN)/elvis $(BIN)/view
	ln $(BIN)/elvis $(BIN)/vi

clean:
	rm -f *.s *.uue core

clobber: clean
	rm -f tags refs $(PROGS)

which:
	@echo 'Minix-PC'

tags refs: ctags
	./ctags -r *.[ch]

uue: elvis1.uue elvis2.uue elvis3.uue elvis4.uue elvis5.uue elvis6.uue

elvis1.uue: $(SRC1)
	tar cf elvis1.tar $(SRC1)
	compress -b13 elvis1.tar
	uuencode elvis1.tar.Z <elvis1.tar.Z >elvis1.uue
	rm elvis1.tar*

elvis2.uue: $(SRC2)
	tar cf elvis2.tar $(SRC2)
	compress -b13 elvis2.tar
	uuencode elvis2.tar.Z <elvis2.tar.Z >elvis2.uue
	rm elvis2.tar*

elvis3.uue: $(SRC3)
	tar cf elvis3.tar $(SRC3)
	compress -b13 elvis3.tar
	uuencode elvis3.tar.Z <elvis3.tar.Z >elvis3.uue
	rm elvis3.tar*

elvis4.uue: $(SRC4)
	tar cf elvis4.tar $(SRC4)
	compress -b13 elvis4.tar
	uuencode elvis4.tar.Z <elvis4.tar.Z >elvis4.uue
	rm elvis4.tar*

elvis5.uue: $(SRC5)
	tar cf elvis5.tar $(SRC5)
	compress -b13 elvis5.tar
	uuencode elvis5.tar.Z <elvis5.tar.Z >elvis5.uue
	rm elvis5.tar*

elvis6.uue: $(SRC6)
	tar cf elvis6.tar $(SRC6)
	compress -b13 elvis6.tar
	uuencode elvis6.tar.Z <elvis6.tar.Z >elvis6.uue
	rm elvis6.tar*

sh: elvis1.sh elvis2.sh elvis3.sh elvis4.sh elvis5.sh elvis6.sh

elvis1.sh: $(SRC1)
	shar $(SRC1) >elvis1.sh

elvis2.sh: $(SRC2)
	shar $(SRC2) >elvis2.sh

elvis3.sh: $(SRC3)
	shar $(SRC3) >elvis3.sh

elvis4.sh: $(SRC4)
	shar $(SRC4) >elvis4.sh

elvis5.sh: $(SRC5)
	shar $(SRC5) >elvis5.sh

elvis6.sh: $(SRC6)
	shar $(SRC6) >elvis6.sh

SHAR_EOF
fi
if test -f 'Makefile.tos'
then
	echo shar: "will not over-write existing file 'Makefile.tos'"
else
cat << \SHAR_EOF > 'Makefile.tos'
# Atari TOS / MWC  Makefile for Elvis -- a clone of vi
#
# Use `make` to compile all programs
# Use `make clean` to remove all object files
# Use `make clobber` to remove everything except source & documentation
# Use `make tags` to build new "tags" and "refs" files

#PROGS=	elvis ctags ref virec
PROGS=	elvis.ttp ctags.ttp ref.ttp virec.ttp wildcard.ttp shell.ttp
BIN=	a:/
OBJS=	blk.o cmd1.o cmd2.o curses.o cut.o ex.o input.o main.o misc.o\
	modify.o move1.o move2.o move3.o move4.o move5.o opts.o recycle.o\
	redraw.o regexp.o regsub.o system.o tio.o tmp.o vars.o vcmd.o vi.o\
	atari.o sysdos.o tinytcap.o
#	pc.o
EXTRA=
CFLAGS=
LIBS=
CC=	cc -VPEEP

all:	$(PROGS)
	@echo '*** all done! ***'

elvis.ttp: $(OBJS) $(EXTRA)
	$(CC) -o elvis.ttp $(OBJS) $(EXTRA) $(LIBS)

ctags.ttp: ctags.c
	$(CC) $(CFLAGS) ctags.c -o ctags.ttp

ref.ttp: ref.c
	$(CC) $(CFLAGS) ref.c -o ref.ttp

virec.ttp: virec.c
	$(CC) $(CFLAGS) virec.c -o virec.ttp

wildcard.ttp: wildcard.c
	$(CC) $(CFLAGS) wildcard.c -o wildcard.ttp

shell.ttp: shell.c
	$(CC) $(CFLAGS) shell.c -o shell.ttp

# The file cmd1.c is compiled with the extra flag -DDATE="today's date".
# This date is reported when elvis is run and the :version command is given.
# If you have trouble defining the date in this way, then just comment out
# these two lines so cmd1.c is compiled normally.  The :version command
# won't report the compilation date, but that's really no big deal.
#cmd1.o: cmd1.c vi.h
#	eval $(CC) -c $(CFLAGS) -DDATE=\'\"`date`\"\' cmd1.c

# This just says that a change to nomagic.c is effectively a change to regexp.c
regexp.o: nomagic.c

##############################################################################
clean:
	rm -f *.o *.uue core

clobber: clean
	rm -f tags refs $(PROGS)

which:
	@echo 'Atari TOS with MWC'

tags refs: ctags
	./ctags -r *.[ch]
SHAR_EOF
fi
if test -f 'blk.c'
then
	echo shar: "will not over-write existing file 'blk.c'"
else
cat << \SHAR_EOF > 'blk.c'
/* blk.c */

/* Author:
 *	Steve Kirkendall
 *	16820 SW Tallac Way
 *	Beaverton, OR 97006
 *	kirkenda@jove.cs.pdx.edu, or ...uunet!tektronix!psueea!jove!kirkenda
 */


/* 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

extern long lseek();

/*------------------------------------------------------------------------*/

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 */
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 */
{
	register struct _blkbuf	*this;	/* used to step through blk[] */
	register 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, 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 */
blkflush(this)
	register 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, 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 */
blkdirty(bp)
	BLK	*bp;	/* buffer returned by blkget() */
{
	register int 	i, j;
	register char	*scan;
	register 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 */
{
	register 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 */
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.
 */
beforedo(undo)
	int		undo;	/* boolean: is this for an undo? */
{
	register int	i;
	register 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, BLKSIZE) != BLKSIZE)
	{
		msg("Trouble writing header to tmp file ");
	}

	/* set the file's "dirty" flag */
	setflag(file, MODIFIED);

	/* copy or swap oldnlines <--> nlines, oldlnum <--> lnum */
	if (undo)
	{
		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 */
afterdo()
{
	if (--b4cnt)
	{
		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 */
}

/* This function cuts short the current set of changes.  It is called after
 * a SIGINT.
 */
abortdo()
{
	/* if we aren't in the middle of a change, do nothing */
	if (!b4cnt)
	{
		return;
	}

	/* reset the b4cnt counter */
	b4cnt = 0;

	/* 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() */
undo()
{
	BLK		oldhdr;

	/* if beforedo() has never been run, fail */
	if (!tstflag(file, MODIFIED))
	{
		msg("You haven't modified this file yet.");
		return;
	}

	/* read the old header form the tmp file */
	lseek(tmpfd, 0L, 0);
	if (read(tmpfd, oldhdr.c, 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 */
	changes++;
}
SHAR_EOF
fi
if test -f 'cmd1.c'
then
	echo shar: "will not over-write existing file 'cmd1.c'"
else
cat << \SHAR_EOF > 'cmd1.c'
/* cmd1.c */

/* Author:
 *	Steve Kirkendall
 *	16820 SW Tallac Way
 *	Beaverton, OR 97006
 *	kirkenda@jove.cs.pdx.edu, or ...uunet!tektronix!psueea!jove!kirkenda
 */


/* This file contains some of the EX commands - mostly ones that deal with
 * files, options, etc. -- anything except text.
 */

#include "config.h"
#include <ctype.h>
#include "vi.h"
#include "regexp.h"

#if	MSDOS
#define	DATE __DATE__
#endif

#ifdef DEBUG
/* print the selected lines with info on the blocks */
/*ARGSUSED*/
void cmd_debug(frommark, tomark, cmd, bang, extra)
	MARK	frommark;
	MARK	tomark;
	CMD	cmd;
	int	bang;
	char	*extra;
{
	register char	*scan;
	register long	l;
	register int	i;
	int		len;

	/* scan lnum[] to determine which block its in */
	l = markline(frommark);
	for (i = 1; l > lnum[i]; i++)
	{
	}

	do
	{
		/* fetch text of the block containing that line */
		scan = blkget(i)->c;

		/* calculate its length */
		if (scan[BLKSIZE - 1])
		{
			len = BLKSIZE;
		}
		else
		{
			len = strlen(scan);
		}

		/* print block stats */
		msg("##### hdr[%d]=%d, lnum[%d-1]=%ld, lnum[%d]=%ld (%ld lines)",
			i, hdr.n[i], i, lnum[i-1], i, lnum[i], lnum[i] - lnum[i - 1]);
		msg("##### len=%d, buf=0x%lx, %sdirty",
			len, scan, ((int *)scan)[MAXBLKS + 1] ? "" : "not ");
		if (bang)
		{
			while (--len >= 0)
			{
				addch(*scan);
				scan++;
			}
		}
		exrefresh();

		/* next block */
		i++;
	} while (i < MAXBLKS && lnum[i] && lnum[i - 1] < markline(tomark));
}


/* This function checks a lot of conditions to make sure they aren't screwy */
/*ARGSUSED*/
void cmd_validate(frommark, tomark, cmd, bang, extra)
	MARK	frommark;
	MARK	tomark;
	CMD	cmd;
	int	bang;
	char	*extra;
{
	char	*scan;
	int	i;
	int	nlcnt;	/* used to count newlines */
	int	len;	/* counts non-NUL characters */

	/* check lnum[0] */
	if (lnum[0] != 0L)
	{
		msg("lnum[0] = %ld", lnum[0]);
	}

	/* check each block */
	for (i = 1; lnum[i] <= nlines; i++)
	{
		scan = blkget(i)->c;
		if (scan[BLKSIZE - 1])
		{
			msg("block %d has no NUL at the end", i);
		}
		else
		{
			for (nlcnt = len = 0; *scan; scan++, len++)
			{
				if (*scan == '\n')
				{
					nlcnt++;
				}
			}
			if (scan[-1] != '\n')
			{
				msg("block %d doesn't end with '\\n' (length %d)", i, len);
			}
			if (bang || nlcnt != lnum[i] - lnum[i - 1])
			{
				msg("block %d (line %ld?) has %d lines, but should have %ld",
					i, lnum[i - 1] + 1L, nlcnt, lnum[i] - lnum[i - 1]);
			}
		}
		exrefresh();
	}

	/* check lnum again */
	if (lnum[i] != INFINITY)
	{
		msg("hdr.n[%d] = %d, but lnum[%d] = %ld",
			i, hdr.n[i], i, lnum[i]);
	}

	msg("# = \"%s\", %% = \"%s\"", prevorig, origname);
}
#endif /* DEBUG */


/*ARGSUSED*/
void cmd_mark(frommark, tomark, cmd, bang, extra)
	MARK	frommark;
	MARK	tomark;
	CMD	cmd;
	int	bang;
	char	*extra;
{
	/* validate the name of the mark */
	if (!extra || *extra < 'a' || *extra > 'z' || extra[1])
	{
		msg("Invalid mark name");
		return;
	}

	mark[*extra - 'a'] = tomark;
}

/*ARGSUSED*/
void cmd_write(frommark, tomark, cmd, bang, extra)
	MARK	frommark;
	MARK	tomark;
	CMD	cmd;
	int	bang;
	char	*extra;
{
	int		fd;
	int		append;	/* boolean: write in "append" mode? */
	register long	l;
	register char	*scan;
	register int	i;

	/* if all lines are to be written, use tmpsave() */
	if (frommark == MARK_FIRST && tomark == MARK_LAST)
	{
		tmpsave(extra, bang);
		return;
	}

	/* see if we're going to do this in append mode or not */
	append = FALSE;
	if (extra[0] == '>' && extra[1] == '>')
	{
		extra += 2;
		append = TRUE;
	}

	/* either the file must not exist, or we must have a ! or be appending */
	if (access(extra, 0) == 0 && !bang && !append)
	{
		msg("File already exists - Use :w! to overwrite");
		return;
	}

	/* else do it line-by-line, like cmd_print() */
	if (append)
	{
#ifdef O_APPEND
		fd = open(extra, O_WRONLY|O_APPEND);
#else
		fd = open(extra, O_WRONLY);
		if (fd >= 0)
		{
			lseek(fd, 0L, 2);
		}
#endif
	}
	else
	{
		fd = creat(extra, 0666);
	}

	if (fd < 0)
	{
		fd = creat(extra, 0644);
		if (fd < 0)
		{
			msg("Can't write to \"%s\"", extra);
			return;
		}
	}
	for (l = markline(frommark); l <= markline(tomark); l++)
	{
		/* get the next line */
		scan = fetchline(l);
		i = strlen(scan);
		scan[i++] = '\n';

		/* print the line */
		twrite(fd, scan, i);
	}
	close(fd);
}	


/*ARGSUSED*/
void cmd_shell(frommark, tomark, cmd, bang, extra)
	MARK	frommark, tomark;
	CMD	cmd;
	int	bang;
	char	*extra;
{
	static char	prevextra[80];

	/* special case: ":sh" means ":!sh" */
	if (cmd == CMD_SHELL)
	{
		extra = o_shell;
		frommark = tomark = 0L;
	}

	/* if extra is "!", substute previous command */
	if (*extra == '!')
	{
		if (!*prevextra)
		{
			msg("No previous shell command to substitute for '!'");
			return;
		}
		extra = prevextra;
	}
	else
	{
		strcpy(prevextra, extra);
	}

	/* if no lines were specified, just run the command */
	suspend_curses();
	if (frommark == 0L)
	{
		system(extra);
	}
	else /* pipe lines from the file through the command */
	{
		filter(frommark, tomark, extra);
	}

	/* resume curses quietly for MODE_EX, but noisily otherwise */
	resume_curses(mode == MODE_EX);
}


/*ARGSUSED*/
void cmd_global(frommark, tomark, cmd, bang, extra)
	MARK	frommark, tomark;
	CMD	cmd;
	int	bang;
	char	*extra;	/* rest of the command line */
{
	char	*cmdptr;	/* the command from the command line */
	char	cmdln[100];	/* copy of the command from the command line */
	char	*line;		/* a line from the file */
	long	l;		/* used as a counter to move through lines */
	long	lqty;		/* quantity of lines to be scanned */
	regexp	*re;		/* the compiled search expression */

	/* ":g! ..." is the same as ":v ..." */
	if (bang)
	{
		cmd = CMD_VGLOBAL;
	}

	/* make sure we got a search pattern */
	if (*extra != '/' && *extra != '?')
	{
		msg("Usage: %c /regular expression/ command", cmd == CMD_GLOBAL ? 'g' : 'v');
		return;
	}

	/* parse & compile the search pattern */
	cmdptr = parseptrn(extra);
	if (!extra[1])
	{
		msg("Can't use empty regular expression with '%c' command", cmd == CMD_GLOBAL ? 'g' : 'v');
		return;
	}
	re = regcomp(extra + 1);
	if (!re)
	{
		/* regcomp found & described an error */
		return;
	}

	/* for each line in the range */
	ChangeText
	{
		/* NOTE: we have to go through the lines in a forward order,
		 * otherwise "g/re/p" would look funny.  *BUT* for "g/re/d"
		 * to work, simply adding 1 to the line# on each loop won't
		 * work.  The solution: count lines relative to the end of
		 * the file.  Think about it.
		 */
		for (l = nlines - markline(frommark), lqty = markline(tomark) - markline(frommark) + 1L;
		     lqty > 0 && nlines - l >= 0;
		     l--, lqty--)
		{
			/* fetch the line */
			line = fetchline(nlines - l);

			/* if it contains the search pattern... */
			if ((!regexec(re, line, 1)) == (cmd != CMD_GLOBAL))
			{
				/* move the cursor to that line */
				cursor = MARK_AT_LINE(nlines - l);

				/* do the ex command (without mucking up
				 * the original copy of the command line)
				 */
				strcpy(cmdln, cmdptr);
				doexcmd(cmdln);
			}
		}
	}

	/* free the regexp */
	free(re);
}


/*ARGSUSED*/
void cmd_file(frommark, tomark, cmd, bang, extra)
	MARK	frommark, tomark;
	CMD	cmd;
	int	bang;
	char	*extra;
{
	if (frommark == tomark)
	{
		msg( "\"%s\" %s%s %ld lines, this is line %ld  [%ld%%]",
			*origname ? origname : "[NO FILE]",
			tstflag(file, MODIFIED) ? "[MODIFIED]" : "",
			tstflag(file, READONLY) ? "[READONLY]" : "",
			nlines,
			markline(frommark),
			markline(frommark) * 100 / nlines);
	}
	else
	{
		msg( "\"%s\" %s%s %ld lines, range  %ld,%ld  contains %ld lines",
			*origname ? origname : "[NO FILE]",
			tstflag(file, MODIFIED) ? "[MODIFIED]" : "",
			tstflag(file, READONLY) ? "[READONLY]" : "",
			nlines,
			markline(frommark), markline(tomark),
			markline(tomark) - markline(frommark) + 1L);
	}
}


/*ARGSUSED*/
void cmd_edit(frommark, tomark, cmd, bang, extra)
	MARK	frommark, tomark;
	CMD	cmd;
	int	bang;
	char	*extra;
{
	long	line = 1L;	/* might be set to prevline */

	if (!strcmp(extra, prevorig))
	{
		line = prevline;
	}

	/* switch files */
	if (tmpabort(bang))
	{
		tmpstart(extra);
		if (line <= nlines && line >= 1L)
		{
			cursor = MARK_AT_LINE(line);
		}
	}
	else
	{
		msg("Use edit! to abort changes, or w to save changes");

		/* so we can say ":e!" with no filename next time... */
		strcpy(prevorig, extra);
		prevline = 1L;
	}
}

/* This code is also used for rewind -- GB */

/*ARGSUSED*/
void cmd_next(frommark, tomark, cmd, bang, extra)
	MARK	frommark, tomark;
	CMD	cmd;
	int	bang;
	char	*extra;
{
	int	i, j;
	char	*scan;
	char	*build;

	/* if extra stuff given, use ":args" to define a new args list */
	if (cmd == CMD_NEXT && extra && *extra)
	{
		cmd_args(frommark, tomark, cmd, bang, extra);
	}

	/* move to the next arg */
	if (cmd == CMD_NEXT)
	{
		i = argno + 1;
	}
	else if (cmd == CMD_PREVIOUS)
	{
		i = argno - 1;
	}
	else /* cmd == CMD_REWIND */
	{
		i = 0;
	}	
	if (i < 0 || i >= nargs)
	{
		msg("No %sfiles to edit", cmd == CMD_REWIND ? "" : "more ");
		return;
	}

	/* find & isolate the name of the file to edit */
	for (j = i, scan = args; j > 0; j--)
	{
		while(!isascii(*scan) || !isspace(*scan))
		{
			scan++;
		}
		while (isascii(*scan) && isspace(*scan))
		{
			scan++;
		}
	}
	for (build = tmpblk.c; *scan && (!isascii(*scan) || !isspace(*scan)); )
	{
		*build++ = *scan++;
	}
	*build = '\0';

	/* switch to the next file */
	if (tmpabort(bang))
	{
		tmpstart(tmpblk.c);
		argno = i;
	}
	else
	{
		msg("Use :%s! to abort changes, or w to save changes",
			cmd == CMD_NEXT ? "next" :
			cmd == CMD_PREVIOUS ? "previous" :
					"rewind");
	}
}

/* also called from :wq -- always writes back in this case */

/*ARGSUSED*/
void cmd_xit(frommark, tomark, cmd, bang, extra)
	MARK	frommark, tomark;
	CMD	cmd;
	int	bang;
	char	*extra;
{
	static long	whenwarned;	/* when the user was last warned of extra files */
	int		oldflag;

	/* if there are more files to edit, then warn user */
	if (argno + 1 < nargs && whenwarned != changes)
	{
		msg("More files to edit -- Use \":n\" to go to next file");
		whenwarned = changes;
		return;
	}

	/* else try to save this file */
	oldflag = tstflag(file, MODIFIED);
	if (cmd == CMD_WQUIT)
		setflag(file, MODIFIED);
	if (tmpend(bang))
	{
		mode = MODE_QUIT;
	}
	else
	{
		msg("Could not save file -- use quit! to abort changes, or w filename");
	}
	if (!oldflag)
		clrflag(file, MODIFIED);
}


void cmd_args(frommark, tomark, cmd, bang, extra)
	MARK	frommark, tomark;
	CMD	cmd;
	int	bang;
	char	*extra;
{
	char	*scan;
	char	*eow;
	int	col;
	int	arg;
	int	addcols;
	int	scrolled = 0;

	/* if no extra names given, or just current name, then report the args
	 * we have now.
	 */
	if (!extra || !*extra)
	{
		for (scan = args, col=arg=0; *scan; )
		{
			while (*scan && isascii(*scan) && isspace(*scan))
				scan++;
			eow = scan;
			while (*eow && (!isascii(*++eow) || !isspace(*eow)))
				;
			if (arg == argno)
				addcols = 2;
			else
				addcols = 0;	
			if (col+addcols+(int)(eow-scan)+1>=COLS)
			{
				addch('\n');
				scrolled=1;
				col=0;
			}
			else if (arg)
			{	qaddch(' ');
				col++;
			}
			if (arg == argno)
				qaddch('[');
			while (scan < eow)
			{	qaddch(*scan++);
				col++;
			}
			if (arg == argno)
				qaddch(']');	
			arg++;	
			col+=addcols;
		}
		/* write a trailing newline */
		if ((mode == MODE_EX || mode == MODE_COLON || scrolled) && col)
			addch('\n');
		exrefresh();	
	}
	else /* new args list given */
	{
		strcpy(args, extra);
		argno = -1; /* before the first, so :next will go to first */

		/* count the names */
		for (nargs = 0, scan = args; *scan; nargs++)
		{
			while (*scan && (!isascii(*scan) || !isspace(*scan)))
			{
				scan++;
			}
			while (isascii(*scan) && isspace(*scan))
			{
				scan++;
			}
		}
		msg("%d files to edit", nargs);
	}
}


/*ARGSUSED*/
void cmd_cd(frommark, tomark, cmd, bang, extra)
	MARK	frommark, tomark;
	CMD	cmd;
	int	bang;
	char	*extra;
{
	char	*getenv();

	/* default directory name is $HOME */
	if (!*extra)
	{
		extra = getenv("HOME");
		if (!extra)
		{
			msg("environment variable $HOME not set");
			return;
		}
	}

	/* go to the directory */
	if (chdir(extra) < 0)
	{
		perror(extra);
	}
}


/*ARGSUSED*/
void cmd_map(frommark, tomark, cmd, bang, extra)
	MARK	frommark, tomark;
	CMD	cmd;
	int	bang;
	char	*extra;
{
	char	*mapto;

	/* "map" with no extra will dump the map table contents */
	if (!*extra)
	{
		dumpkey(bang ? WHEN_VIINP|WHEN_VIREP : WHEN_VICMD);
	}
	else
	{
		/* "extra" is key to map, followed my what it maps to */
		for (mapto = extra; *mapto && *mapto != ' ' && *mapto!= '\t'; mapto++)
		{
		}
		while (*mapto == ' ' || *mapto == '\t')
		{
			*mapto++ = '\0';
		}

		mapkey(extra, mapto, bang ? WHEN_VIINP|WHEN_VIREP : WHEN_VICMD, (char *)0);
	}
}


/*ARGSUSED*/
void cmd_set(frommark, tomark, cmd, bang, extra)
	MARK	frommark, tomark;
	CMD	cmd;
	int	bang;
	char	*extra;
{
	if (!*extra)
	{
		dumpopts(FALSE);/* "FALSE" means "don't dump all" - only set */
	}
	else if (!strcmp(extra, "all"))
	{
		dumpopts(TRUE);	/* "TRUE" means "dump all" - even unset vars */
	}
	else
	{
		setopts(extra);

		/* That option may have affected the appearence of text */
		changes++;
	}
}

/*ARGSUSED*/
void cmd_tag(frommark, tomark, cmd, bang, extra)
	MARK	frommark, tomark;
	CMD	cmd;
	int	bang;
	char	*extra;
{
	char	*scan;	/* used to scan through the tmpblk.c */
	char	*cmp;	/* char of tag name we're comparing, or NULL */
	char	*end;	/* marks the end of chars in tmpblk.c */
	int	fd;	/* file descriptor used to read the file */
#ifndef NO_MAGIC
	char	wasmagic; /* preserves the original state of o_magic */
#endif
	static char prevtag[30];

	/* if no tag is given, use the previous tag */
	if (!extra || !*extra)
	{
		if (!*prevtag)
		{
			msg("No previous tag");
			return;
		}
		extra = prevtag;
	}
	else
	{
		strncpy(prevtag, extra, sizeof prevtag);
	}

	/* open the tags file */
	fd = open(TAGS, O_RDONLY);
	if (fd < 0)
	{
		msg("No tags file");
		return;
	}

	/* Hmmm... this would have been a lot easier with <stdio.h> */

	/* find the line with our tag in it */
	for(scan = end = tmpblk.c, cmp = extra; ; scan++)
	{
		/* read a block, if necessary */
		if (scan >= end)
		{
			end = tmpblk.c + tread(fd, tmpblk.c, BLKSIZE);
			scan = tmpblk.c;
			if (scan >= end)
			{
				msg("tag \"%s\" not found", extra);
				close(fd);
				return;
			}
		}

		/* if we're comparing, compare... */
		if (cmp)
		{
			/* matched??? wow! */
			if (!*cmp && *scan == '\t')
			{
				break;
			}
			if (*cmp++ != *scan)
			{
				/* failed! skip to newline */
				cmp = (char *)0;
			}
		}

		/* if we're skipping to newline, do it fast! */
		if (!cmp)
		{
			while (scan < end && *scan != '\n')
			{
				scan++;
			}
			if (scan < end)
			{
				cmp = extra;
			}
		}
	}

	/* found it! get the rest of the line into memory */
	for (cmp = tmpblk.c, scan++; scan < end && *scan != '\n'; )
	{
		*cmp++ = *scan++;
	}
	if (scan == end)
	{
		tread(fd, cmp, BLKSIZE - (cmp - tmpblk.c));
	}

	/* we can close the tags file now */
	close(fd);

	/* extract the filename from the line, and edit the file */
	for (cmp = tmpblk.c; *cmp != '\t'; cmp++)
	{
	}
	*cmp++ = '\0';
	if (strcmp(origname, tmpblk.c) != 0)
	{
		if (!tmpabort(bang))
		{
			msg("Use :tag! to abort changes, or :w to save changes");
			return;
		}
		tmpstart(tmpblk.c);
	}

	/* move to the desired line (or to line 1 if that fails) */
#ifndef NO_MAGIC
	wasmagic = *o_magic;
	*o_magic = FALSE;
#endif
	cursor = MARK_FIRST;
	linespec(cmp, &cursor);
	if (cursor == MARK_UNSET)
	{
		cursor = MARK_FIRST;
	}
#ifndef NO_MAGIC
	*o_magic = wasmagic;
#endif
}


/*ARGSUSED*/
void cmd_visual(frommark, tomark, cmd, bang, extra)
	MARK	frommark, tomark;
	CMD	cmd;
	int	bang;
	char	*extra;
{
	mode = MODE_VI;
}

/*ARGSUSED*/
void cmd_quit(frommark, tomark, cmd, bang, extra)
	MARK	frommark, tomark;
	CMD	cmd;
	int	bang;
	char	*extra;
{
	if (tmpabort(bang))
	{
		mode = MODE_QUIT;
	}
	else
	{
		msg("Use q! to abort changes, or wq to save changes");
	}
}



/* describe this version of the program */
/*ARGSUSED*/
void cmd_version(frommark, tomark, cmd, bang, extra)
	MARK	frommark;
	MARK	tomark;
	CMD	cmd;
	int	bang;
	char	*extra;
{
#ifndef DATE
	msg("%s", VERSION);
#else
	msg("%s  (%s)", VERSION, DATE);
#endif
#ifdef COMPILED_BY
	msg("Compiled by %s", COMPILED_BY);
#endif
#ifdef CREDIT
	msg("%s", CREDIT);
#endif
#ifdef COPYING
	msg("%s", COPYING);
#endif
}


#ifndef NO_EXTENSIONS
/* make a .exrc file which describes the current configuration */
/*ARGSUSED*/
void cmd_mkexrc(frommark, tomark, cmd, bang, extra)
	MARK	frommark;
	MARK	tomark;
	CMD	cmd;
	int	bang;
	char	*extra;
{
	int	fd;

	/* create the .exrc file */
	fd = creat(EXRC, 0666);
	if (fd < 0)
	{
		msg("Couldn't create a new \"%s\" file", EXRC);
		return;
	}

	/* save stuff */
	savekeys(fd);
	saveopts(fd);
#ifndef NO_DIGRAPH
	savedigs(fd);
#endif

	/* close the file */
	close(fd);
	msg("Created a new \"%s\" file", EXRC);
}
#endif

#ifndef NO_DIGRAPH
/*ARGSUSED*/
void cmd_digraph(frommark, tomark, cmd, bang, extra)
	MARK	frommark;
	MARK	tomark;
	CMD	cmd;
	int	bang;
	char	*extra;
{
	do_digraph(bang, extra);
}
#endif
SHAR_EOF
fi
if test -f 'cmd2.c'
then
	echo shar: "will not over-write existing file 'cmd2.c'"
else
cat << \SHAR_EOF > 'cmd2.c'
/* cmd2.c */

/* Author:
 *	Steve Kirkendall
 *	16820 SW Tallac Way
 *	Beaverton, OR 97006
 *	kirkenda@jove.cs.pdx.edu, or ...uunet!tektronix!psueea!jove!kirkenda
 */


/* This file contains some of the commands - mostly ones that change text */

#include "config.h"
#include "vi.h"
#include "regexp.h"


/*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 */
	int	optp;	/* boolean option: print when done? */
	int	optg;	/* boolean option: substitute globally in line? */
	long	l;	/* a line number */
	char	*s, *d;	/* used during subtitutions */
	long	chline;	/* # of lines changed */
	long	chsub;	/* # of substitutions made */


	/* 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);
	if (!re)
	{
		return;
	}

	/* parse the substitution string & find the option string */
	for (opt = subst; *opt && (*opt != *extra || opt[-1] == '\\'); opt++)
	{
	}
	if (*opt)
	{
		*opt++ = '\0';
	}

	/* analyse the option string */
	optp = optg = 0;
	while (*opt)
	{
		switch (*opt++)
		{
		  case 'p':	optp = 1;	break;
		  case 'g':	optg = 1;	break;
		  case ' ':
		  case '\t':			break;
		  default:
			msg("Subst options are p and g -- not %c", opt[-1]);
			return;
		}
	}

	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
				{
					/* increment the substitution change counter */
					chsub++;

					/* this may be the first line to redraw */
					redrawrange(l, l + 1L, l + 1L);

					/* copy stuff from before the match */
					while (s < re->startp[0])
					{
						*d++ = *s++;
					}
	
					/* subtitute for the matched part */
					regsub(re, subst, d);
					s = re->endp[0];
					d += strlen(d);

				} while (optg && regexec(re, s, FALSE));

				/* copy stuff from after the match */
				while (*d++ = *s++)	/* yes, ASSIGNMENT! */
				{
				}

				/* replace the old version of the line with the new */
				changeline(l, tmpblk.c);

				/* if supposed to print it, do so */
				if (optp)
				{
					addstr(tmpblk.c);
					addch('\n');
					exrefresh();
				}
			}
		}
	}

	/* report what happened */
	if (chsub == 0)
	{
		msg("Substitution failed");
	}

	/* tweak for redrawing */
	if (chline > 1 || redrawafter && redrawafter != markline(cursor))
	{
		mustredraw = TRUE;
	}

	/* free the regexp */
	free(re);

	/* Reporting */
	if (chline >= *o_report)
	{
		msg("%ld substitutions on %ld lines", chsub, chline);
	}
	rptlines = 0;
}




/*ARGSUSED*/
void cmd_delete(frommark, tomark, cmd, bang, extra)
	MARK	frommark;
	MARK	tomark;
	CMD	cmd;
	int	bang;
	char	*extra;
{
	MARK	curs2;	/* al 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 */

	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;
			}

			addline(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, !bang, 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 = m_down(tomark, 1L);
	}

	/* 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 + 1 > BLKSIZE)
		{
			msg("Can't join -- the resulting line would be too long");
			return;
		}

		/* catenate it, with a space in between */
		tmpblk.c[len++] = ' ';
		strcpy(tmpblk.c + len, scan);
		len += strlen(scan);
	}

	/* make the change */
	ChangeText
	{
		frommark &= ~(BLKSIZE - 1);
		tomark &= ~(BLKSIZE - 1);
		tomark += BLKSIZE;
		delete(frommark, tomark);
		addline(markline(frommark), tmpblk.c);
	}
}



/*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 */

	/* figure out how much of the screen we must redraw (for vi mode) */
	if (markline(frommark) != markline(tomark))
	{
		mustredraw = TRUE;
		redrawrange(markline(frommark), markline(tomark) + 1L, markline(tomark) + 1L);
	}

	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;
			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;
{
	long	l;	/* line number counter - where new lines go */
	int	fd, rc;	/* used while reading from the file */
	char	*scan;	/* used for finding newlines */
	char	*line;	/* points to the start of a line */
	int	prevrc;	/* used to detect abnormal EOF */

	/* special case: if ":r !cmd" then let the filter() function do it */
	if (bang || extra[0] == '!')
	{
		if (extra[0] == '!')
		{
			extra++;
		}
		frommark = (frommark & ~(BLKSIZE - 1)) + BLKSIZE;
		filter(frommark, MARK_UNSET, extra);
		return;
	}

	/* first line goes after the selected line */
	l = markline(frommark) + 1;

	/* open the file */
	fd = open(extra, O_RDONLY);
	if (fd < 0)
	{
		msg("Can't open \"%s\"", extra);
		return;
	}

	/* get blocks from the file, and add each line in the block */
	ChangeText
	{
		/* NOTE!  lint worries needlessly about the order of evaluation
		 * of the 'rc' expressions in the test clause of this for(;;){}
		 */
		for (prevrc = rc = 0;
		     (rc = rc + tread(fd, tmpblk.c + rc, BLKSIZE - rc)) > 0;
		     prevrc = rc)
		{
			/* if we couldn't read anything, we damn well better have \n */
			if (prevrc == rc)
			{
				if (rc == BLKSIZE)
				{
					rc--;
				}
				if (tmpblk.c[rc - 1] != '\n' || rc <= 0)
				{
					tmpblk.c[rc++] = '\n';
				}
			}

			/* for each complete line in this block, add it */
			for (line = scan = tmpblk.c; rc > 0; rc--, scan++)
			{
				if (*scan == '\n')
				{
					*scan = '\0';
					addline(l, line);
					l++;
					line = scan + 1;
				}
				else if (!*scan)
				{
					/* protect against NUL chars in file */
					*scan = 0x80;
				}
			}

			/* any extra chars are shifted to the start of the buffer */
			rc = scan - line;
			for (scan = tmpblk.c; scan < tmpblk.c + rc; )
			{
				*scan++ = *line++;
			}
		}
	}

	/* close the file */
	close(fd);

	/* Reporting... */
	rptlines = l - markline(frommark) - 1L;
	rptlabel = "read";
}


/*ARGSUSED*/
void cmd_list(frommark, tomark, cmd, bang, extra)
	MARK	frommark;
	MARK	tomark;
	CMD	cmd;
	int	bang;
	char	*extra;
{
	long		l;	/* line number counter */
	register char	*scan;	/* used for moving through the line */

	for (l = markline(frommark); l <= markline(tomark); l++)
	{
		/* list the line */
		scan = fetchline(l);

		while (*scan)
		{
			/* if the char is non-printable, write it as \000 */
			if (*scan < ' ' || *scan > '~')
			{
				/* build the \000 form & write it */
				addch('\\');
				addch('0' + ((*scan >> 6) & 3));
				addch('0' + ((*scan >> 3) & 7));
				addch('0' + (*scan & 7));
			}
			else
			{
				addch(*scan);
			}
			scan++;
		}

		/* write a $ and a \n */
		addstr("$\n");
		exrefresh();
	}
}


/*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;
{
	register char	*scan;
	register long	l;
	register int	col;

	for (l = markline(frommark); l <= markline(tomark); l++)
	{
		/* get the next line & display it */
		for (col = 0, scan = fetchline(l); *scan; scan++)
		{
			/* expand tabs to the proper width */
			if (*scan == '\t')
			{
				do
				{
					qaddch(' ');
					col++;
				} while (col % *o_tabstop != 0);
			}
			else
			{
				qaddch(*scan);
			}

			/* wrap at the edge of the screen */
			if (!has_AM && col >= COLS)
			{
				addch('\n');
				col = 0;
			}
		}
		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);
}
SHAR_EOF
fi
if test -f 'config.h'
then
	echo shar: "will not over-write existing file 'config.h'"
else
cat << \SHAR_EOF > 'config.h'
/*
 * vi configuration file
 * We try to automatically configure to various compilers and operating
 * systems. Extend the autoconf section as needed.
 */

/*************************** autoconf section ************************/

/* standard unix V (?) */
#ifdef	M_SYSV
# define UNIXV		1
#endif

/* xelos system, University of Ulm */
#ifdef	xelos
# define UNIXV		1
#endif

/* Microsoft C: sorry, Watcom does the same thing */
#ifdef	M_I86
# ifndef M_SYSV
#  define MSDOS		1
#  define MICROSOFT	1
#  define COMPILED_BY	"Microsoft C 5.10"
# endif
#endif

/* Borlands Turbo C */
#ifdef	__TURBOC__
# define MSDOS		1
# define TURBOC		1
# define COMPILED_BY	"Turbo C 2.00"
#endif

/* Tos Mark-Williams */
#ifdef	M68000
# define TOS 1
# define COMPILED_BY	"Mark Williams C"
#endif

/* OS-9 requires an explicit "-DOS9" in CFLAGS */

/* TOS requires an explicit "-DTOS" in CFLAGS */

/*************************** 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 OS9
# define OS9	0		/* OS-9 / 68k */
#endif

				/* Minix has no predefines */
#if !BSD && !UNIXV && !UNIX7 && !MSDOS && !TOS && !AMIGA && !OS9
# define MINIX	1
#else
# define MINIX	0
#endif

				/* generic combination of Unices */
#if UNIXV || UNIX7 || BSD || MINIX
# define ANY_UNIX 1
#else
# define ANY_UNIX 0
#endif

/*************************** compilers **************************************/
 
#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"
#endif

#if TOS
# define CREDIT "Ported to Atari/TOS by Guntram Blohm & Martin Patzel"
#endif

/*************************** functions depending on OS *********************/

/* Only MSDOS and TOS need a special function for reading from the keyboard.
 * All others just read from file descriptor 0.
 */
#if !MSDOS && !TOS
# define ttyread(buf, len)	read(0, buf, len)	/* raw read */
#endif
#if !TOS
# define ttywrite(buf, len)	write(1, buf, 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 || MINIX
# define strchr	index
#endif

/* BSD uses bcopy() instead of memcpy() */
#if BSD
#define memcpy(dest, src, siz)	bcopy(src, dest, siz)
#endif

/* text versa binary mode for read/write */
#if !TOS
#define	tread	read
#define twrite  write
#endif

/**************************** Compiler quirks *********************************/

/* The Microsoft Xenix cross compiler for DOS doesn't support "volatile" */
#if MICROSOFT
# define volatile
#endif

/* the UNIX version 7, OS-9, and (some) TOS compilers, don't allow "void" */
#if UNIX7 || TOS || OS9
# define void int
#endif

/* In OS9, argv[0] never changes */
#if OS9
# define NO_ARGV0
#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)
#else
# define UCHAR(c)	((unsigned char)(c))
#endif

/* Some compilers prefer to have malloc declared as returning a (void *) */
#if BSD
extern void *malloc();
#else
extern char *malloc();
#endif

/******************* Names of files and environment vars **********************/

#if ANY_UNIX
# define TMPDIR		"/usr/tmp"	/* directory where temp files live */
# define TMPNAME	"%s/elvt%04x%03x" /* temp file */
# define CUTNAME	"%s/elvc%04x%03x" /* cut buffer's temp file */
# define EXRC		".exrc"		/* init file in current directory */
# define KEYWORDPRG	"/usr/bin/ref"	/* keyword "help" program */
# define SCRATCHOUT	"%s/soXXXXXX"	/* temp file used as input to filter */
# define SLASH		'/'
# define EXINIT		"EXINIT"
#endif

#if MSDOS || TOS
/* do not change TMPNAME, CUTNAME and SCRATCH*: they MUST begin with '%s\\'! */
# define TMPDIR		"C:\\tmp"	/* directory where temp files live */
# define TMPNAME	"%s\\elvt%04x.%03x" /* temp file */
# define CUTNAME	"%s\\elvc%04x.%03x" /* cut buffer's temp file */
# define EXRC		"elvis.rc"	/* init file in current directory */
# if TOS
# define KEYWORDPRG	"ref.ttp"	/* keyword "help" program */
# else
# define KEYWORDPRG	"ref.exe"	/* keyword "help" program */
# endif
# define SCRATCHIN	"%s\\siXXXXXX"	/* DOS ONLY - output of filter program */
# define SCRATCHOUT	"%s\\soXXXXXX"	/* temp file used as input to filter */
# define SLASH		'\\'
#endif

#if OS9
# define TMPDIR		"/dd/tmp"	/* directory where temp files live */
# define TMPNAME	"%s/elvt%04x%03x" /* temp file */
# define CUTNAME	"%s/elvc%04x%03x" /* cut buffer's temp file */
# define EXRC		".exrc"		/* init file in current directory */
# define KEYWORDPRG	"/dd/cmds/ref"	/* keyword "help" program */
# define SCRATCHOUT	"%s/soXXXXXX"	/* temp file used as input to filter */
# define SLASH		'/'
# define EXINIT		"EXINIT"
#endif

#ifndef	TAGS
# define TAGS		"tags"		/* tags file */
#endif

#ifndef TMPNAME
# define TMPNAME	"%s/elvt%04x.%03x"	/* temp file */
#endif

#ifndef CUTNAME
# define CUTNAME	"%s/elvc%04x.%03x"	/* cut buffer's temp file */
#endif

#ifndef	EXRC
# define EXRC		"elvis.rc"
#endif

#ifndef HMEXRC
# if !MSDOS && !TOS
#  define HMEXRC	EXRC
# endif
#endif

#ifndef	KEYWORDPRG
# define KEYWORDPRG	"ref"
#endif

#ifndef	SCRATCHOUT
# define SCRATCHIN	"%s/SIXXXXXX"
# define SCRATCHOUT	"%s/SOXXXXXX"
#endif

#ifndef	SLASH
# define SLASH		'/'
#endif
SHAR_EOF
fi
exit 0
#	End of shell archive
-------------------------------------------------------------------------------
Steve Kirkendall    kirkenda@cs.pdx.edu    uunet!tektronix!psueea!eecs!kirkenda