[comp.sources.unix] v14i060: Jove, an emacs variant, version 4.9, Part04/21

rsalz@bbn.com (Rich Salz) (04/26/88)

Submitted-by: Jonathan Payne <jpayne@cs.rochester.edu>
Posting-number: Volume 14, Issue 60
Archive-name: jove4.9/part04

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 4 (of 21)."
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f './Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./Makefile'\"
else
echo shar: Extracting \"'./Makefile'\" \(8207 characters\)
sed "s/^X//" >'./Makefile' <<'END_OF_FILE'
X###########################################################################
X# This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE #
X# is provided to you without charge, and with no warranty.  You may give  #
X# away copies of JOVE, including sources, provided that this notice is    #
X# included in all the files.                                              #
X###########################################################################
X
X# TMPDIR is where the tmp files get stored, usually /tmp or /tmp/jove.  If
X# your system does not remove subdirectories of /tmp on reboot (lots do
X# remove them these days) then it makes sense to make TMPDIR be /tmp/jove.
X# But if you want to recover buffers on system crashes, you should create a
X# directory that doesn't get clearned upon reboot, and use that instead.
X# You would probably want to clean out that directory periodically with
X# /etc/cron.  LIBDIR is for online documentation, the PORTSRV process,
X# RECOVER, and the system-wide .joverc file.  BINDIR is where to put the
X# executables JOVE and TEACHJOVE.  MANDIR is where the manual pages go for
X# JOVE, RECOVER and TEACHJOVE.  MANEXT is the extension for the man pages,
X# e.g., jove.1 or jove.l or jove.m.
X
DESTDIR =
TMPDIR = /tmp
LIBDIR = /usr/local/lib/jove
BINDIR = /usr/local
MANDIR = /usr/man/manl
MANEXT = l
SHELL = /bin/csh
X
X# These should all just be right if the above ones are.
JOVE = $(DESTDIR)$(BINDIR)/jove
TEACHJOVE = $(DESTDIR)$(BINDIR)/teachjove
RECOVER = $(DESTDIR)$(LIBDIR)/recover
PORTSRV = $(DESTDIR)$(LIBDIR)/portsrv
JOVERC = $(DESTDIR)$(LIBDIR)/.joverc
CMDS.DOC = $(DESTDIR)$(LIBDIR)/cmds.doc
TEACH-JOVE = $(DESTDIR)$(LIBDIR)/teach-jove
JOVEM = $(DESTDIR)$(MANDIR)/jove.$(MANEXT)
TEACHJOVEM = $(DESTDIR)$(MANDIR)/teachjove.$(MANEXT)
X
X# Select the right libraries for your system.
X#	2.10BSD:LIBS = -ltermcap
X#	v7:	LIBS = -ltermcap
X#	4.1BSD:	LIBS = -ltermcap -ljobs
X#	4.2BSD:	LIBS = -ltermcap
X#	4.3BSD:	LIBS = -ltermcap
X#	SysV Rel. 2: LIBS = -lcurses
X#	SCO Xenix: LIBS = -ltermcap -lx
X
LIBS = -ltermcap
X
X# If you are not VMUNIX (vax running Berkeley Version 4), you must specify
X# the -i flags (split I/D space) and maybe the -x option (for adb to work).
X#	2.10BSD:LDFLAGS =
X#	v7:	LDFLAGS =
X#	4.1BSD:	LDFLAGS =
X#	4.2BSD:	LDFLAGS =
X#	4.3BSD:	LDFLAGS =
X#	SysV Rel. 2: LDFLAGS = -Ml
X#	SCO Xenix: LDFLAGS = -Ml -F 3000
X#
X# SEPFLAG should be:
X#	not on a PDP-11:		SEPFLAG =
X#	PDP-11 with separate I&D:	SEPFLAG = -i
X#	PDP-11 without separate I&D:	SEPFLAG = -n
X#
X
LDFLAGS = 
X
SEPFLAG =
X
X# for SCO Xenix, set
X#	MEMFLAGS = -Mle
X#	CFLAGS = -LARGE -O -F 3000 -K -Mle  (say -Mle2 for an 80286)
X
CFLAGS = -O 
X
BASESEG = funcdefs.o keymaps.o argcount.o ask.o buf.o ctype.o delete.o \
X	  disp.o insert.o io.o jove.o malloc.o marks.o misc.o re.o \
X	  screen.o table.o tune.o util.o vars.o version.o
OVLAY1 = abbrev.o rec.o paragraph.o fmt.o
OVLAY2 = c.o wind.o fp.o move.o
OVLAY3 = extend.o macros.o
OVLAY4 = iproc.o re1.o
OVLAY5 = proc.o scandir.o term.o case.o
X
OBJECTS = $(BASESEG) $(OVLAY1) $(OVLAY2) $(OVLAY3) $(OVLAY4) $(OVLAY5)
X
C_SRC = funcdefs.c abbrev.c argcount.c ask.c buf.c c.c case.c ctype.c \
X	delete.c disp.c extend.c fp.c fmt.c insert.c io.c iproc.c \
X	jove.c macros.c malloc.c marks.c misc.c move.c paragraph.c \
X	proc.c re.c re1.c rec.c scandir.c screen.c table.c term.c util.c \
X	vars.c version.c wind.c getch.c mac.c
X
SOURCES = $(C_SRC) portsrv.c recover.c setmaps.c teachjove.c
X
HEADERS = ctype.h io.h jove.h re.h rec.h table.h temp.h termcap.h \
X	tune.h externs.h mac.h
X
DOCS =	doc/cmds.doc.nr doc/example.rc doc/jove.1 doc/jove.2 doc/jove.3 \
X	doc/jove.4 doc/jove.5 doc/jove.nr doc/system.rc \
X	doc/teach-jove doc/teachjove.nr doc/README doc/jove.qref
X
MISC = Makefile Ovmakefile Makefile.dos tune.dos tune.template \
X	README Readme.dos Readme.mac iproc-pipes.c iproc-ptys.c
X
SUPPORT = teachjove.c recover.c setmaps.c portsrv.c keymaps.txt \
X	macvert.c menumaps.txt mjovers.Hqx
X
BACKUPS = $(HEADERS) $(C_SRC) $(DOCS) $(SUPPORT) $(MISC)
X
all:	sdate xjove recover teachjove portsrv macvert edate
X
sdate:
X	@echo "**** make started at `date` ****"
X
edate:
X	@echo "**** make completed at `date` ****"
X
xjove:	$(OBJECTS)
X	$(CC) $(LDFLAGS) -o xjove $(OBJECTS) $(LIBS)
X	@-size xjove
X
gjove:	$(OBJECTS)
X	ld -X /lib/gcrt0.o -o gjove $(OBJECTS) -lc $(LIBS)
X	@-size gjove
X
ovjove:	$(OBJECTS)
X	ld $(SEPFLAG) $(LDFLAGS) -X /lib/crt0.o \
X		-Z $(OVLAY1) \
X		-Z $(OVLAY2) \
X		-Z $(OVLAY3) \
X		-Z $(OVLAY4) \
X		-Z $(OVLAY5) \
X		-Y $(BASESEG) \
X		-o xjove $(LIBS) -lc; \
X	@-size xjove
X
portsrv:	portsrv.o
X	$(CC) $(LDFLAGS) -o portsrv $(SEPFLAG) portsrv.o $(LIBS)
X
recover:	recover.o tune.o rec.h temp.h
X	$(CC) $(LDFLAGS) -o recover $(SEPFLAG) recover.o tune.o $(LIBS)
X
teachjove:	teachjove.o
X	$(CC) $(LDFLAGS) -o teachjove $(SEPFLAG) teachjove.o $(LIBS)
X
setmaps:	setmaps.o funcdefs.c
X	$(CC) $(LDFLAGS) -o setmaps setmaps.o
X
teachjove.o:	teachjove.c /usr/include/sys/types.h /usr/include/sys/file.h
X	cc -c $(CFLAGS) -DTEACHJOVE=\"$(TEACH-JOVE)\" teachjove.c
X
X# don't optimize setmaps.c because it produces bad code in some places
X# for some reason
setmaps.o:	funcdefs.c keymaps.txt
X	$(CC) $(MEMFLAGS) -c setmaps.c
X
X# ignore error messages from setmaps
X# it doesn't understand ifdefs
X
keymaps.c:	setmaps keymaps.txt
X	-setmaps < keymaps.txt > keymaps.c
X
keymaps.o:	keymaps.c jove.h
X
tune.c: Makefile tune.template
X	@echo "/* Changes should be made in Makefile, not to this file! */" > tune.c
X	@echo "" >> tune.c
X	@sed -e 's;TMPDIR;$(TMPDIR);' \
X	     -e 's;LIBDIR;$(LIBDIR);' \
X	     -e 's;BINDIR;$(BINDIR);' \
X	     -e 's;SHELL;$(SHELL);' tune.template >> tune.c
X
iproc.o: iproc-ptys.c iproc-pipes.c iproc.c
X	$(CC) -c $(CFLAGS) iproc.c
X
macvert:	macvert.c
X	$(CC) $(CFLAGS) -o macvert macvert.c
X
X# install doesn't work for Xenix (no install program)
X
install: $(DESTDIR)$(LIBDIR) $(TEACH-JOVE) $(CMDS.DOC) $(JOVERC) \
X	 $(PORTSRV) $(RECOVER) $(JOVE) $(TEACHJOVE) $(JOVEM) \
X	 $(RECOVERM) $(TEACHJOVEM)
X
X$(DESTDIR)$(LIBDIR):
X	-mkdir $(DESTDIR)$(LIBDIR)
X
X$(TEACH-JOVE): doc/teach-jove
X	install -c -m 644 doc/teach-jove $(TEACH-JOVE)
X
doc/cmds.doc:	doc/cmds.doc.nr doc/jove.4 doc/jove.5
X	nroff doc/cmds.doc.nr doc/jove.4 doc/jove.5 > doc/cmds.doc
X
X$(CMDS.DOC): doc/cmds.doc
X	install -c -m 644 doc/cmds.doc $(CMDS.DOC)
X
X$(JOVERC): doc/system.rc
X	install -c -m 644 doc/system.rc $(JOVERC)
X
X$(PORTSRV): portsrv
X	install -c -s -m 755 portsrv $(PORTSRV)
X
X$(RECOVER): recover
X	install -c -s -m 755 recover $(RECOVER)
X
X$(JOVE): xjove
X	install -c -m 755 xjove $(JOVE)
X
X$(TEACHJOVE): teachjove
X	install -c -s -m 755 teachjove $(TEACHJOVE)
X
X$(JOVEM): doc/jove.nr
X	@sed -e 's;TMPDIR;$(TMPDIR);' \
X	     -e 's;LIBDIR;$(LIBDIR);' \
X	     -e 's;SHELL;$(SHELL);' doc/jove.nr > /tmp/jove.nr
X	install -m 644 /tmp/jove.nr $(JOVEM)
X
X$(TEACHJOVEM): doc/teachjove.nr
X	@sed -e 's;TMPDIR;$(TMPDIR);' \
X	     -e 's;LIBDIR;$(LIBDIR);' \
X	     -e 's;SHELL;$(SHELL);' doc/teachjove.nr > /tmp/teachjove.nr
X	install -m 644 /tmp/teachjove.nr $(TEACHJOVEM)
X
echo:
X	@echo $(C-FILES) $(HEADERS)
X
lint:
X	lint -n $(C_SRC) tune.c keymaps.c
X	@echo Done
X
tags:
X	ctags -w $(C_SRC) $(HEADERS) iproc-ptys.c
X
ciall:
X	ci $(BACKUPS)
X
coall:
X	co $(BACKUPS)
X
jove.shar:
X	shar $(BACKUPS) > jove.shar
X
backup: $(BACKUPS)
X	tar chf backup $(BACKUPS)
X
tape-backup:
X	tar c $(BACKUPS)
X
srcdownload:
X	kermit -s $(SUPPORT) $(MISC) $(HEADERS) $(C_SRC)
X
docdownload:
X	kermit -s $(DOCS)
X
touch:
X	touch $(OBJECTS)
X
clean:
X	rm -f a.out core *.o keymaps.c tune.c xjove portsrv recover setmaps \
X	teachjove macvert
X
X# This version only works under 4.3BSD
X#depend:
X#	for i in ${SOURCES} ; do \
X#		cc -M ${CFLAGS} $$i | awk ' { if ($$1 != prev) \
X#		    { if (rec != "") print rec; rec = $$0; prev = $$1; } \
X#		    else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \
X#		    else rec = rec " " $$2 } } \
X#		    END { print rec } ' >> makedep; done
X#	echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep
X#	echo '$$r makedep' >>eddep
X#	echo 'w' >>eddep
X#	cp Makefile Makefile.bak
X#	ed - Makefile < eddep
X#	rm eddep makedep
X#	echo '# DEPENDENCIES MUST END AT END OF FILE' >> Makefile
X#	echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >> Makefile
X#	echo '# see make depend above' >> Makefile
X#
X## DO NOT DELETE THIS LINE -- make depend uses it
END_OF_FILE
if test 8207 -ne `wc -c <'./Makefile'`; then
    echo shar: \"'./Makefile'\" unpacked with wrong size!
fi
# end of './Makefile'
fi
if test -f './README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./README'\"
else
echo shar: Extracting \"'./README'\" \(8923 characters\)
sed "s/^X//" >'./README' <<'END_OF_FILE'
X###########################################################################
X# This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE #
X# is provided to you without charge, and with no warranty.  You may give  #
X# away copies of JOVE, including sources, provided that this notice is    #
X# included in all the files.                                              #
X###########################################################################
X
To make JOVE edit Makefile to set the right directories for the binaries,
on line documentation, the man pages, and the TMP files and select the
appropriate load command (see SEPFLAG in Makefile).  (IMPORTANT! read the
Makefile carefully.)  "tune.c" will be created from "tune.template" by
MAKE automatically, and it will use the directories you specified in the
Makefile.  (NOTE:  You should never edit tune.c directly because your
changes will be undone by the next make.  If you want to make a change to
a part of tune.c that isn't a directory name, you should edit
tune.template.)  Next you must edit "tune.h" selecting the compile time
options you care about.  See below for a description of all the compile
time options.  You can type "make" to compile XJOVE, PORTSRV (this is
compiled but not used on 4.2+ systems), RECOVER TEACHJOVE, and
MACVERT.  NOTE:  make won't work if it fires up /bin/csh for the shell
commands.  Test them out to see if they work.  If they do, type "make
install" to install everything where it belongs.
X
Here are some things to consider for deciding where to put the tmp files.
TMPDIR is where the tmp files get stored, usually /tmp or /tmp/jove.  If
your system does not remove subdirectories of /tmp on reboot (lots do
remove them these days) then it makes sense to make TMPDIR be /tmp/jove.
But if you want to recover buffers on system crashes, you should create a
directory that doesn't get cleared upon reboot, and use that instead.
You would probably want to clean out that directory periodically with
X/etc/cron.
X
For the pdp11 version there is the Ovmakefile.  This has only been tested
on 2.9bsd.  It works pretty well, actually, and it is possible to turn on
all the compile time options with this version.
X
Bug reports:  If you find bugs in JOVE I would appreciate hearing about
them.  (My net address is at end of this message.)  So, send me the bug
reports.  If the bug isn't already fixed, I will ask you to send me the
fix.  If you haven't found the bug, I may be able to, so don't wait until
you have found it.  If you make improvements to JOVE and want them
incorporated into the official version, send me a message explaining what
the change is, and I will decide whether I want to include it.  If it is
possible for your change to be #ifdef'd in, that would be best, since I
want to avoid making JOVE huge.  For instance, if it's a new package type
thing (say, like word abbrev. mode, or something) then it would be best
if that were a compile-time option.  I will send out periodic updates to
mod.sources.  I will report all significant bug fixes there, and to
net.emacs as well.
X
Here's a list of the compile time options and what they mean:
X
ABBREV	   - Enables word-abbrev-mode which again is nice for paper writers.
X
BACKUPFILES - This enables backing up files on write.  I guess lots of
X	      people like this feature.  It enables the feature but you
X	      can still control whether files are backed up with the
X	      make-backup-files variable.
X
BIFF	   - This enables turning on and off BIFF so your screen doesn't
X	      get messed up with messages from BIFF.
X
BSD4_2     - Obviously, if you're a Berkeley 4.2 system.
X
BSD4_3	   - If you're running a Berkeley 4.3 or 2.10 system.
X	     This will automatically define BSD4_2, also.
X
CHDIR	   - This enables the directory commands; PUSHD, POPD, DIRS and
X	      CD.  These simulate the csh commands exactly, I think.  As
X	      a side-effect, absolute path names are enabled, which means
X	      JOVE parses file names for "." and ".." and all that to get
X	      at what you REALLY mean.  It's nicer when this is enabled,
X	      but not essential.
X
CMT_FMT	   - This enables code to format and indent C comments.
X
ID_CHAR	   - Enables support for Insert/Delete character on terminals
X	     that have those capabilities.  Couple of problems with this code:
X	     it's large, takes up lots of I space which is a problem for the
X	     smaller computers (pdp11).  Also, it isn't particularly smart
X	     and sometimes does really stupid things.  It sometimes uses
X	     insert/delete character when simply redrawing would have been
X	     faster.  And if you look at code you'll understand why I don't
X	     like it all that much.
X
IPROCS	   - Nice feature which lets you run interactive UNIX commands in
X	     windows.  In particular, there is a shell command built
X	     in which starts up an interactive shell in a window.  This works
X	     only on systems with JOB_CONTROL since it relies on the fancy
X	     signal mechanism.
X
JOB_CONTROL - Versions of UNIX that have the job control facility.
X	      Berkeley 2.9-10 systems, and the 4.1-3 systems I know have
X	      job stopping, so if you're one of those, define
X	      this.  The reason MENLO_JCL is defined when JOB_CONTROL
X	      is that the 2.9 signal.h file only defines all of the job
X	      stopping signals only when MENLO_JCL is defined.
X
LISP	   - Enables Lisp Mode.  This includes code to indent "properly"
X	     for Lisp code and new routines to move over s-expressions.
X	     You probably won't want (or need) this on PDP-11's.
X
MY_MALLOC  - Use the older version of malloc that is more memory efficient
X	     than the newer 4BSD version.  The 4BSD version places more
X	     importance on the speed of the allocation than the amount of
X	     memory it uses.  Make your	choice ... JOVE hardly ever calls
X	     malloc, anyway, relatively speaking, since it allocates
X	     lines in big chunks.  NOTE: This doesn't seem to work on suns
X	     and the iAPX286.
X
PIPEPROCS  - If NOT defined, JOVE will use Berkeley pseudo-ttys when
X	     doing interactive processes.  This is infinitely better,
X	     since you get job control and all that stuff on i-procs.
X	     If defined, the portsrv program will have to be made, and
X	     all communication between jove and i-procs will be done using
X	     pipes.
X
RESHAPING  - This is for BRL or Berkeley 4.3 and 2.10 systems.  When the
X	     window size of the terminal jove is running in is changed
X	     a SIGWINCH is sent to all processes in the tty group.  This
X	     define enables code in jove to catch that signal and reshape
X	     its windows.
X
SPELL	   - Enables the spell-buffer and parse-spelling-errors commands.
X	     They are nice especially if you have lots of paper writers.
X
WIRED_TERMS - Include compiled-in hard-wired code for certain terminals,
X	     like the Concept 100.  If you don't have these terminals,
X	     you probably don't need this (but no point in taking it
X	     out unless you're low on space).
X
The macros have been rewritten from scratch.  The most noteable change is
that they are no longer stored in binary files.  The write-macros-to-file
command writes a file which is suitable for use with the source command.
So you can have actual macro definitions in your .joverc if you want.  If
you have lots of macros defined in the old format, you can use the
macvert program to convert them to the new style.  You say
X	macvert old-style-macros-file > new-style-macro-file
X
X"doc/system.rc" and "doc/example.rc" are jove initialization files.
X"system.rc" is the "system" rc file here at UoR, and it gets ready every
time JOVE starts up FOR EVERYONE.  ("make install" should copy the
system-wide .joverc to the right place automatically.)  After that JOVE
reads an initialization file in the user's home directory.  "example.rc"
is my personal .joverc.
X
The files "jove.[12345]" in DOC are the official JOVE manual.  I got
permission from Richard Stallman to use his manual for the original EMACS,
modifying it where necessary for JOVE.  Lots of work was done by Brian
Harvey on this manual.
X
There are man pages for jove and teachjove.  Teachjove is for people who
have never used EMACS style editors.  It is an interactive tutorial, THE
tutorial written by Stallman for the original EMACS, only slightly
modified for JOVE in the appropriate places.  The man pages are
completely up to date, thanks to me.
X
Thanks to Jay (hack) Fenlason for writing the original pty code.
X
Thanks to Dave Curry at Purdue for putting in tons of time and effort
into getting JOVE ready.  It just wouldn't be working without his help.
X
Thanks to Jeff Mc Carrell at Berkeley for finding bugs and adding
features, in particular, the comment formatter.
X
Thanks to Karl Gegenfurtner for making the PC version.
X
X(Thanks to Brian Harvey for teaching me about linked lists ...)
X
Good luck, have fun.
X
X	Jonathan Payne (jpayne@cs.rochester.edu until '88)
END_OF_FILE
if test 8923 -ne `wc -c <'./README'`; then
    echo shar: \"'./README'\" unpacked with wrong size!
fi
# end of './README'
fi
if test -f './fmt.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./fmt.c'\"
else
echo shar: Extracting \"'./fmt.c'\" \(7964 characters\)
sed "s/^X//" >'./fmt.c' <<'END_OF_FILE'
X/***************************************************************************
X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
X * is provided to you without charge, and with no warranty.  You may give  *
X * away copies of JOVE, including sources, provided that this notice is    *
X * included in all the files.                                              *
X ***************************************************************************/
X
X#include "jove.h"
X#include "io.h"
X#include "termcap.h"
X
X#ifdef MAC
X#	include  "mac.h"
X#else
X#	include <varargs.h>
X#endif
X
X#ifdef MAC
X#	undef private
X#	define private
X#endif
X
X#ifdef	LINT_ARGS
private void
X	doformat(File *, char *, ...),
X	outld(long, int),
X	pad(int, int),
X	PPchar(int, char *),
X	putld(long, int),
X	puts(char *);
X#else
private void
X	doformat(),
X	outld(),
X	pad(),
X	PPchar(),
X	putld(),
X	puts();
X#endif	/* LINT_ARGS */
X
X#ifdef MAC
X#	undef private
X#	define private static
X#endif
X
X
char	mesgbuf[MESG_SIZE];
X
X/* VARARGS2 */
X
void
format(buf, len, fmt, ap)
char	*buf,
X	*fmt;
va_list	ap;
X{
X	File	strbuf,
X		*sp = &strbuf;
X
X 	sp->f_ptr = sp->f_base = buf;
X	sp->f_fd = -1;		/* Not legit for files */
X	sp->f_cnt = len;
X	sp->f_flags = F_STRING;
X	sp->f_bufsize = len;
X
X	doformat(sp, fmt, ap);
X	putc('\0', sp);
X}
X
X#ifdef IBMPC
int	specialmap = 0,
X	specialkey = 0;
X
X#define Empty ""
X
char *altseq[133] = {
Empty, Empty, Empty, "Ctrl-@", Empty, Empty, Empty, Empty,
Empty, Empty, Empty, Empty, Empty, Empty, Empty, "Left", 
X"Alt-Q", "Alt-W", "Alt-E", "Alt-R", "Alt-T", "Alt-Y", "Alt-U", "Alt-I",
X"Alt-O", "Alt-P", Empty, Empty, Empty, Empty, "Alt-A", "Alt-S",
X"Alt-D", "Alt-F", "Alt-G", "Alt-H", "Alt-J", "Alt-K", "Alt-L", Empty,
Empty, Empty, Empty, Empty, "Alt-Z", "Alt-X", "Alt-C", "Alt-V",
X"Alt-B", "Alt-N", "Alt-M", Empty, Empty, Empty, Empty, Empty,
Empty, Empty, Empty, "F1", "F2", "F3", "F4", "F5", 
X"F6", "F7", "F8", "F9", "F10", Empty, Empty, "Home",
X"Up", "PageUp", Empty, "Left", Empty, "Right", Empty, "End",
X"Down", "PageDown", "Ins", "Del", "Shift F1", "Shift F2", "Shift F3", "Shift F4", 
X"Shift F5", "Shift F6", "Shift F7", "Shift F8", "Shift F9", "Shift F10", "Ctrl F1", "Ctrl F2",
X"Ctrl F3", "Ctrl F4", "Ctrl F5", "Ctrl F6", "Ctrl F7", "Ctrl F8", "Ctrl F9", "Ctrl F10", 
X"Alt F1", "Alt F2", "Alt F3", "Alt F4", "Alt F5", "Alt F6", "Alt F7", "Alt F8",
X"Alt F9", "Alt F10", "Ctrl PrtSc", "Ctrl Left", "Ctrl Right", "Ctrl End", "Ctrl PageDown", "Ctrl Home",
X"Alt 1", "Alt 2", "Alt 3", "Alt 4", "Alt 5", "Alt 6", "Alt 7", "Alt 8",
X"Alt 9", "Alt 0", "Alt Minus", "Alt Equals", "Ctrl PageUp" 
X};
X#endif
X
X
private void
PPchar(c, str)
int	c;
char	*str;
X{
X	char	*cp = str;
X
X#ifdef IBMPC
X	if (specialmap || specialkey) {
X		if (c < 0 || c > 132)
X			c = 0;
X		strcpy(cp, altseq[c]);
X	} else
X#endif	
X	if (c == '\033')
X		strcpy(cp, "ESC");
X#ifdef IBMPC				/* this character is invisible */
X	else if (c == '\377') {
X			*cp = 0;
X	}
X#endif /* IBMPC */
X	else if (c < ' ')
X		sprintf(cp, "C-%c", c + '@');
X	else if (c == '\177')
X		strcpy(cp, "^?");
X	else
X		sprintf(cp, "%c", c);
X}
X
private struct fmt_state {
X	int	precision,
X		width,
X		leftadj;
X	char	padc;
X	File	*iop;
X} current_fmt;
X
private void
putld(d, base)
long	d;
X{
X	int	length = 1;
X	long	tmpd = d;
X
X	if (current_fmt.width == 0 && current_fmt.precision) {
X		current_fmt.width = current_fmt.precision;
X		current_fmt.padc = '0';
X	}
X	while (tmpd = (tmpd / base))
X		length += 1;
X	if (d < 0)
X		length += 1;
X	if (!current_fmt.leftadj)
X		pad(current_fmt.padc, current_fmt.width - length);
X	if (d < 0) {
X		putc('-', current_fmt.iop);
X		d = -d;
X	}
X	outld(d, base);
X	if (current_fmt.leftadj)
X		pad(current_fmt.padc, current_fmt.width - length);
X}
X
private void
outld(d, base)
long	d;
X{
X	register long	n;
X	static char	chars[] = {'0', '1', '2', '3', '4', '5', '6',
X				    '7', '8', '9', 'a', 'b', 'c', 'd',
X				    'e', 'f'};
X
X	if (n = (d / base))
X		outld(n, base);
X	putc((int) (chars[(int) (d % base)]), current_fmt.iop);
X}
X
private void
puts(str)
char	*str;
X{
X	int	length;
X	register char	*cp;
X
X	if (str == 0)
X#if pyr
X		str = "";
X#else
X		str = "(null)";
X#endif
X	length = strlen(str);
X	if (current_fmt.precision == 0 || length < current_fmt.precision)
X		current_fmt.precision = length;
X	else
X		length = current_fmt.precision;
X	cp = str;
X	if (!current_fmt.leftadj)
X		pad(' ', current_fmt.width - length);
X	while (--current_fmt.precision >= 0)
X		putc(*cp++, current_fmt.iop);
X	if (current_fmt.leftadj)
X		pad(' ', current_fmt.width - length);
X}
X
private void
pad(c, amount)
register int	c,
X		amount;
X{
X	while (--amount >= 0)
X		putc(c, current_fmt.iop);
X}
X
private void
doformat(sp, fmt, ap)
register File	*sp;
register char	*fmt;
va_list	ap;
X{
X	register char	c;
X	struct fmt_state	prev_fmt;
X
X	prev_fmt = current_fmt;
X	current_fmt.iop = sp;
X
X	while (c = *fmt++) {
X		if (c != '%') {
X			putc(c, current_fmt.iop);
X			continue;
X		}
X
X		current_fmt.padc = ' ';
X		current_fmt.precision = current_fmt.leftadj = current_fmt.width = 0;
X		c = *fmt++;
X		if (c == '-') {
X			current_fmt.leftadj = YES;
X			c = *fmt++;
X		}
X		if (c == '0') {
X			current_fmt.padc = '0';
X			c = *fmt++;
X		}
X		while (c >= '0' && c <= '9') {
X			current_fmt.width = current_fmt.width * 10 + (c - '0');
X			c = *fmt++;
X		}
X		if (c == '*') {
X			current_fmt.width = va_arg(ap, int);
X			c = *fmt++;
X		}
X		if (c == '.') {
X			c = *fmt++;
X			while (c >= '0' && c <= '9') {
X				current_fmt.precision = current_fmt.precision * 10 + (c - '0');
X				c = *fmt++;
X			}
X			if (c == '*') {
X				current_fmt.precision = va_arg(ap, int);
X				c = *fmt++;
X			}
X		}
X	reswitch:
X		/* At this point, fmt points at one past the format letter. */
X		switch (c) {
X		case '%':
X			putc('%', current_fmt.iop);
X			break;
X	
X		case 'O':
X		case 'D':
X		case 'X':
X			putld(va_arg(ap, long), (c == 'O') ? 8 :
X						(c == 'D') ? 10 : 16);
X			break;
X	
X		case 'b':
X		    {
X			Buffer	*b = va_arg(ap, Buffer *);
X
X			puts(b->b_name);
X			break;
X		    }
X
X		case 'c':
X			putc(va_arg(ap, int), current_fmt.iop);
X			break;
X	
X		case 'o':
X		case 'd':
X		case 'x':
X			putld((long) va_arg(ap, int), (c == 'o') ? 8 :
X						(c == 'd') ? 10 : 16);
X			break;
X	
X		case 'f':	/* current command name gets inserted here! */
X			puts(LastCmd->Name);
X			break;
X
X		case 'l':
X			c = CharUpcase(*++fmt);
X			goto reswitch;
X	
X		case 'n':
X			if (va_arg(ap, int) != 1)
X				puts("s");
X			break;
X
X		case 'p':
X		    {
X		    	char	cbuf[20];
X
X		    	PPchar(va_arg(ap, int), cbuf);
X		    	puts(cbuf);
X		    	break;
X		    }
X
X		case 's':
X			puts(va_arg(ap, char *));
X			break;
X		
X		default:
X			complain("Unknown format directive: \"%%%c\"", c);
X		}
X	}
X	current_fmt = prev_fmt;
X}
X
X/* VARARGS1 */
X
char *
sprint(fmt, va_alist)
char	*fmt;
va_dcl
X{
X	va_list	ap;
X	static char	line[100];
X
X	va_start(ap);
X	format(line, sizeof line, fmt, ap);
X	va_end(ap);
X	return line;
X}
X
X/* VARARGS1 */
X
void
printf(fmt, va_alist)
char	*fmt;
va_dcl
X{
X	va_list	ap;
X
X	va_start(ap);
X#ifndef IBMPC
X	doformat(stdout, fmt, ap);
X#else /* IBMPC */
X	write_em(sprint(fmt, ap));
X	/* doformat(stdout, fmt, ap); */
X#endif /* IBMPC */
X	va_end(ap);
X}
X
X/* VARARGS1 */
X
void
fprintf(fp, fmt, va_alist)
File	*fp;
char	*fmt;
va_dcl
X{
X	va_list	ap;
X
X	va_start(ap);
X	doformat(fp, fmt, ap);
X	va_end(ap);
X}
X
X/* VARARGS2 */
X
void
sprintf(str, fmt, va_alist)
char	*str,
X	*fmt;
va_dcl
X{
X	va_list	ap;
X
X	va_start(ap);
X	format(str, 130, fmt, ap);
X	va_end(ap);
X}
X
X/* VARARGS1 */
X
void
s_mess(fmt, va_alist)
char	*fmt;
va_dcl
X{
X	va_list	ap;
X
X	if (InJoverc)
X		return;
X	va_start(ap);
X	format(mesgbuf, sizeof mesgbuf, fmt, ap);
X	va_end(ap);
X	message(mesgbuf);
X}
X
X/* VARARGS1 */
X
void
f_mess(fmt, va_alist)
char	*fmt;
va_dcl
X{
X	va_list	ap;
X
X	va_start(ap);
X	format(mesgbuf, sizeof mesgbuf, fmt, ap);
X	va_end(ap);
X	DrawMesg(NO);
X	UpdMesg = YES;	/* still needs updating (for convenience) */
X}
X
X/* VARARGS1 */
X
void
add_mess(fmt, va_alist)
char	*fmt;
va_dcl
X{
X	int	mesg_len = strlen(mesgbuf);
X	va_list	ap;
X
X	if (InJoverc)
X		return;
X	va_start(ap);
X	format(&mesgbuf[mesg_len], (sizeof mesgbuf) - mesg_len, fmt, ap);
X	va_end(ap);
X	message(mesgbuf);
X}
END_OF_FILE
if test 7964 -ne `wc -c <'./fmt.c'`; then
    echo shar: \"'./fmt.c'\" unpacked with wrong size!
fi
# end of './fmt.c'
fi
if test -f './iproc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./iproc.c'\"
else
echo shar: Extracting \"'./iproc.c'\" \(9262 characters\)
sed "s/^X//" >'./iproc.c' <<'END_OF_FILE'
X/***************************************************************************
X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
X * is provided to you without charge, and with no warranty.  You may give  *
X * away copies of JOVE, including sources, provided that this notice is    *
X * included in all the files.                                              *
X ***************************************************************************/
X
X#include "jove.h"
X#include "re.h"
X#include <varargs.h>
X
X#ifdef IPROCS
X
int	proc_child();
X
X#ifdef PIPEPROCS
X#   include "iproc-pipes.c"
X#else
X#   include "iproc-ptys.c"
X#endif
X
char	proc_prompt[128] = "% ";
X
KillProcs()
X{
X	register Process	*p;
X	register int	killem = -1;		/* -1 means undetermined */
X	register char	*yorn;
X
X	for (p = procs; p != 0; p = p->p_next)
X		if (!isdead(p)) {
X			if (killem == -1) {
X				yorn = ask("y", "Should I kill your i-processes? ");
X				killem = (CharUpcase(*yorn) == 'Y');
X			}
X			if (killem)
X				proc_kill(p, SIGKILL);
X		}
X}
X
pbuftiedp(b)
register Buffer	*b;
X{
X	register Process	*p = b->b_process;
X
X	if (!isdead(p))
X		complain("Process %s, attached to %b, is %s.",
X			 proc_cmd(p), b, pstate(p));
X}
X
X/* Process receive: receives the characters in buf, and appends them to
X   the buffer associated with p. */
X
private
proc_rec(p, buf)
register Process	*p;
char	*buf;
X{
X	Buffer	*saveb = curbuf;
X	register Window	*w;
X	register Mark	*savepoint;
X	int	sameplace = NO,
X		do_disp = NO;
X
X	if (curwind->w_bufp == p->p_buffer)
X		w = curwind;
X	else
X		w = windbp(p->p_buffer);	/* Is this window visible? */
X	if (w != 0)
X		do_disp = (in_window(w, p->p_mark->m_line) != -1);
X	SetBuf(p->p_buffer);
X	savepoint = MakeMark(curline, curchar, M_FLOATER);
X	ToMark(p->p_mark);		/* where output last stopped */
X	if (savepoint->m_line == curline && savepoint->m_char == curchar)
X		sameplace = YES;
X
X	ins_str(buf, YES);
X	MarkSet(p->p_mark, curline, curchar);
X	if (!sameplace)
X		ToMark(savepoint);	/* back to where we were */
X	DelMark(savepoint);
X	/* redisplay now, instead of right after the ins_str, so that
X	   we don't get a bouncing effect if point is not the same as
X	   the process output position */
X	if (do_disp) {
X		w->w_line = curline;
X		w->w_char = curchar;
X		redisplay();
X	}
X	SetBuf(saveb);
X}
X
proc_kill(p, sig)
register Process	*p;
X{
X	if (isdead(p))
X		return;
X	if (killpg(p->p_pid, sig) == -1)
X		s_mess("Cannot kill %s!", proc_buf(p));
X}
X
X/* Free process CHILD.  Do all the necessary cleaning up (closing fd's,
X   etc.). */
X
free_proc(child)
Process	*child;
X{
X	register Process	*p,
X				*prev = 0;
X
X	if (!isdead(child))
X		return;	
X	for (p = procs; p != child; prev = p, p = p->p_next)
X		;
X	if (prev == 0)
X		procs = child->p_next;
X	else
X		prev->p_next = child->p_next;
X	proc_close(child);		/* if not already closed */
X	
X	/* It's possible that the buffer has been given another process
X	   between the time CHILD dies and CHILD's death is noticed (via
X	   list-processes).  So we only set it the buffer's process to
X	   0 if CHILD is still the controlling process. */
X	if (child->p_buffer->b_process == child) {
X		child->p_buffer->b_process = 0;
X		if (curbuf == child->p_buffer)
X			PopPBs();
X	}
X	{
X		Buffer	*old = curbuf;
X
X		SetBuf(child->p_buffer);
X		DelMark(child->p_mark);
X		SetBuf(old);
X	}
X	free((char *) child->p_name);
X	free((char *) child);
X}
X
ProcList()
X{
X	register Process	*p,
X				*next;
X	char	*fmt = "%-15s  %-15s  %-8s %s",
X		pidstr[16];
X
X	if (procs == 0) {
X		message("[No subprocesses]");
X		return;
X	}
X	TOstart("Process list", TRUE);
X
X	Typeout(fmt, "Buffer", "Status", "Pid ", "Command");
X	Typeout(fmt, "------", "------", "--- ", "-------");
X	for (p = procs; p != 0; p = next) {
X		next = p->p_next;
X		sprintf(pidstr, "%d", p->p_pid);
X		Typeout(fmt, proc_buf(p), pstate(p), pidstr, p->p_name);
X		if (isdead(p)) {
X			free_proc(p);
X			UpdModLine = YES;
X		}
X	}
X	TOstop();
X}
X
ProcNewline()
X{
X#ifdef ABBREV
X	MaybeAbbrevExpand();
X#endif
X	SendData(YES);
X}
X
ProcSendData()
X{
X#ifdef ABBREV
X	MaybeAbbrevExpand();
X#endif
X	SendData(NO);
X}
X
private
SendData(newlinep)
X{
X	register Process	*p = curbuf->b_process;
X	register char	*lp,
X			*gp;	/* JF fix for better prompt handling */
X
X	if (isdead(p))
X		return;
X	/* If the process mark was involved in a big deletion, because
X	   the user hit ^W or something, then let's do some magic with
X	   the process mark.  Problem is that if the user yanks back the
X	   text he deleted, the mark stays at the beginning of the region,
X	   and so the next time SendData() is called the entire region
X	   will be sent.  That's not good.  So, to deal with that we reset
X	   the mark to the last line, after skipping over the prompt, etc. */
X	if (p->p_mark->m_flags & M_BIG_DELETE) {
X		Bufpos	bp;
X
X		p->p_mark->m_flags &= ~M_BIG_DELETE;
X
X		DOTsave(&bp);
X		ToLast();
X		Bol();
X		/* While we're looking at a prompt, and while we're
X		   moving forward.  This is for people who accidently
X		   set their process-prompt to ">*" which will always
X		   match! */
X		while ((LookingAt(proc_prompt, linebuf, curchar)) &&
X 		       (REeom > curchar))
X			curchar = REeom;
X		MarkSet(p->p_mark, curline, curchar);
X		SetDot(&bp);
X	}
X
X	if (lastp(curline)) {
X		Eol();
X		if (newlinep)
X			LineInsert(1);
X		do_rtp(p->p_mark);
X		MarkSet(p->p_mark, curline, curchar);
X	} else {
X		/* Either we're looking at a prompt, or we're not, in
X		   which case we want to strip off the beginning of the
X		   line anything that looks like what the prompt at the
X		   end of the file is.  In other words, if "(dbx) stop in
X		   ProcessNewline" is the line we're on, and the last
X		   line in the buffer is "(dbx) ", then we strip off the
X		   leading "(dbx) " from this line, because we know it's
X		   part of the prompt.  But this only happens if "(dbx) "
X		   isn't one of the process prompts ... follow what I'm
X		   saying? */
X		Bol();
X		if (LookingAt(proc_prompt, linebuf, curchar)) {
X			do
X				curchar = REeom;
X			while ((LookingAt(proc_prompt, linebuf, curchar)) &&
X			       (REeom > curchar));
X			strcpy(genbuf, linebuf + curchar);
X			Eof();
X			ins_str(genbuf, NO);
X		} else {
X			strcpy(genbuf, linebuf + curchar);
X			Eof();
X			gp = genbuf;
X			lp = linebuf;
X			while (*lp == *gp && *lp != '\0') {
X				lp += 1;
X				gp += 1;
X			}
X			ins_str(gp, NO);
X		}
X	}
X}
X
ShellProc()
X{
X	char	*shbuf = "*shell*";
X	register Buffer	*b;
X
X	b = buf_exists(shbuf);
X	if (b == 0 || isdead(b->b_process))
X		proc_strt(shbuf, NO, Shell, "-i", (char *) 0);
X	pop_wind(shbuf, NO, -1);
X}
X
Iprocess()
X{
X	extern char	ShcomBuf[100],
X			*MakeName();
X	register char	*command;
X	char	scratch[64],
X		*bufname;
X	int	cnt = 1;
X	Buffer	*bp;
X
X	command = ask(ShcomBuf, ProcFmt);
X	null_ncpy(ShcomBuf, command, (sizeof ShcomBuf) - 1);
X	bufname = MakeName(command);
X	strcpy(scratch, bufname);
X	while ((bp = buf_exists(scratch)) && !isdead(bp->b_process))
X		sprintf(scratch, "%s.%d", bufname, cnt++);
X	proc_strt(scratch, YES, Shell, ShFlags, command, (char *) 0);
X}
X
proc_child()
X{
X	union wait	w;
X	register int	pid;
X
X	for (;;) {
X#ifndef BSD4_2
X		pid = wait2(&w.w_status, (WNOHANG | WUNTRACED));
X#else
X		pid = wait3(&w, (WNOHANG | WUNTRACED), (struct rusage *) 0);
X#endif
X		if (pid <= 0)
X			break;
X		kill_off(pid, w);
X	}
X}
X
kill_off(pid, w)
register int	pid;
union wait	w;
X{
X	register Process	*child;
X
X	if ((child = proc_pid(pid)) == 0)
X		return;
X
X	UpdModLine = YES;		/* we're changing state ... */
X	if (WIFSTOPPED(w))
X		child->p_state = STOPPED;
X	else {
X		child->p_state = DEAD;
X		if (WIFEXITED(w))
X			child->p_howdied = EXITED;
X		else if (WIFSIGNALED(w)) {
X			child->p_reason = w.w_termsig;
X			child->p_howdied = KILLED;
X		}
X		{
X			Buffer	*save = curbuf;
X			char	mesg[128];
X
X			/* insert status message now */
X			sprintf(mesg, "[Process %s: %s]\n",
X				proc_cmd(child),
X				pstate(child));
X			SetBuf(child->p_buffer);
X			ins_str(mesg, NO);
X			SetBuf(save);
X			redisplay();
X		}
X	}
X}
X
X/* Push/pod process bindings.  I openly acknowledge that this is a
X   kludge, but I can't be bothered making it right. */
X
struct proc_bind {
X	int		pb_key;
X	data_obj	**pb_map;
X	data_obj	*pb_push;
X	data_obj	*pb_cmd;
X	struct proc_bind *pb_next;
X};
X
struct proc_bind *PBinds = 0;
X
PopPBs()
X{
X	register struct proc_bind *p;
X
X	for (p = PBinds; p != 0; p = p->pb_next)
X		p->pb_map[p->pb_key] = p->pb_push;
X}
X
PushPBs()
X{
X	register struct proc_bind *p;
X
X	for (p = PBinds; p != 0; p = p->pb_next) {
X		p->pb_push = p->pb_map[p->pb_key];
X		p->pb_map[p->pb_key] = p->pb_cmd;
X	}
X}
X/* VARARGS0 */
X
ProcBind()
X{
X	register data_obj	*d;
X
X	if ((d = findcom(ProcFmt)) == 0)
X		return;
X	s_mess(": %f %s ", d->Name);
X	ProcB2(mainmap, EOF, d);
X}
X
ProcB2(map, lastkey, cmd)
data_obj	**map,
X		*cmd;
X{
X	register struct proc_bind *p;
X	register data_obj	**nextmap;
X	int	c;
X
X	c = addgetc();
X	if (c == EOF) {
X		if (lastkey == EOF)
X			complain("[Empty key sequence]");
X		complain("[Unexpected end-of-line]");
X	} else {
X		if (nextmap = IsPrefix(map[c]))
X			ProcB2(nextmap, c, cmd);
X		else {
X			if (curbuf->b_process)
X				PopPBs();
X
X			for (p = PBinds; p != 0; p = p->pb_next)
X				if (p->pb_key == c && p->pb_map == map)
X					break;
X			if (p == 0) {
X				p = (struct proc_bind *) emalloc(sizeof *p);
X				p->pb_next = PBinds;
X				PBinds = p;
X			}
X			p->pb_map = map;
X			p->pb_key = c;
X			p->pb_cmd = cmd;
X
X			if (curbuf->b_process)
X				PushPBs();
X		}
X	}
X}
X
X#endif /* IPROCS */
X
END_OF_FILE
if test 9262 -ne `wc -c <'./iproc.c'`; then
    echo shar: \"'./iproc.c'\" unpacked with wrong size!
fi
# end of './iproc.c'
fi
if test -f './misc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./misc.c'\"
else
echo shar: Extracting \"'./misc.c'\" \(7989 characters\)
sed "s/^X//" >'./misc.c' <<'END_OF_FILE'
X/***************************************************************************
X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
X * is provided to you without charge, and with no warranty.  You may give  *
X * away copies of JOVE, including sources, provided that this notice is    *
X * included in all the files.                                              *
X ***************************************************************************/
X
X#include "jove.h"
X#include "ctype.h"
X#include <signal.h>
X#ifdef ANSICODES
X#include "termcap.h"
X#endif
X
void
prCTIME()
X{
X	s_mess(": %f %s", get_time((time_t *) 0, (char *) 0, 0, -1));
X}
X
void
ChrToOct()
X{
X	int	c,
X		slow;
X
X	c = waitchar(&slow);
X	if (slow)
X		message(key_strokes);
X	ins_str(sprint("\\%03o", c), NO);
X}
X
void
StrLength()
X{
X	static char	inquotes[] = "Where are the quotes?";
X	char	*first = StrIndex(-1, linebuf, curchar, '"'),
X		*last = StrIndex(1, linebuf, curchar + 1, '"'),
X		c;
X	int	numchars = 0;
X
X	if (first == 0 || last == 0)
X		complain(inquotes);
X	first += 1;
X	while (first < last) {
X		c = *first++;
X		if (c == '\\') {
X			int	num;
X
X			if (!isdigit(*first))
X				first += 1;
X			else {
X				num = 3;
X				while (num-- && isdigit(*first++) && first < last)
X					;
X			}
X		}
X		numchars += 1;
X	}
X	s_mess("%d characters", numchars);
X}
X
X/* Transpos cur_char with cur_char - 1 */
X
void
TransChar()
X{
X	char	before;
X
X	if (curchar == 0 || (eolp() && curchar == 1))
X		complain((char *) 0);	/* BEEP */
X	if (eolp())
X		b_char(1);
X	before = linebuf[curchar - 1];
X	del_char(BACKWARD, 1);
X	f_char(1);
X	insert_c(before, 1);
X}
X
X/* Switch current line with previous one */
X
void
TransLines()
X{
X	disk_line	old_prev;
X
X	if (firstp(curline))
X		return;
X	lsave();
X	old_prev = curline->l_prev->l_dline;
X	curline->l_prev->l_dline = curline->l_dline;
X	curline->l_dline = old_prev;
X	getDOT();
X	if (!lastp(curline))
X		line_move(FORWARD, 1, NO);
X	modify();
X}
X
void
Leave()
X{
X	longjmp(mainjmp, QUIT);
X}
X
X/* If argument is specified, kill that many lines down.  Otherwise,
X   if we "appear" to be at the end of a line, i.e. everything to the
X   right of the cursor is white space, we delete the line separator
X   as if we were at the end of the line. */
X
void
KillEOL()
X{
X	Line	*line2;
X	int	char2;
X	int	num = arg_value();
X
X	if (is_an_arg()) {
X		if (num == 0) {	/* Kill to beginning of line */
X			line2 = curline;
X			char2 = 0;
X		} else {
X			line2 = next_line(curline, num);
X			if ((LineDist(curline, line2) < num) || (line2 == curline))
X				char2 = length(line2);
X			else
X				char2 = 0;
X		}
X	} else if (blnkp(&linebuf[curchar])) {
X		line2 = next_line(curline, 1);
X		if (line2 == curline)
X			char2 = length(curline);
X		else
X			char2 = 0;
X	} else {
X		line2 = curline;
X		char2 = length(curline);
X	}
X	reg_kill(line2, char2, 0);
X}
X
X/* kill to beginning of sentence */
X
void
KillBos()
X{
X	negate_arg_value();
X	KillEos();
X}
X
X/* Kill to end of sentence */
X
void
KillEos()
X{
X	Line	*line1;
X	int	char1;
X
X	line1 = curline;
X	char1 = curchar;
X	Eos();
X	reg_kill(line1, char1, 1);
X}
X
void
KillExpr()
X{
X	Line	*line1;
X	int	char1;
X
X	line1 = curline;
X	char1 = curchar;
X	FSexpr();
X	reg_kill(line1, char1, 1);
X}
X
void
EscPrefix()
X{
X	HandlePref(pref1map);
X}
X
void
CtlxPrefix()
X{
X	HandlePref(pref2map);
X}
X
void
MiscPrefix()
X{
X	HandlePref(miscmap);
X}
X
void
HandlePref(map)
data_obj	**map;
X{
X	register data_obj	*cp;
X	register int	c;
X	int	slow;
X
X	c = waitchar(&slow);
X	if (c == AbortChar) {
X		message("[Aborted]");
X		rbell();
X		return;
X	}
X
X	if (slow)
X		message(key_strokes);
X
X	cp = map[c];
X	if (cp == 0) {
X		s_mess("[%sunbound]", key_strokes);
X		rbell();
X	} else
X		ExecCmd(cp);
X}
X
void
Yank()
X{
X	Line	*line,
X		*lp;
X	Bufpos	*dot;
X
X	if (killbuf[killptr] == 0)
X		complain("[Nothing to yank!]");
X	lsave();
X	this_cmd = YANKCMD;
X	line = killbuf[killptr];
X	lp = lastline(line);
X	dot = DoYank(line, 0, lp, length(lp), curline, curchar, curbuf);
X	set_mark();
X	SetDot(dot);
X}
X
void
WtModBuf()
X{
X	if (!ModBufs(NO))
X		message("[No buffers need saving]");
X	else
X		put_bufs(is_an_arg());
X}
X
void
put_bufs(askp)
X{
X	register Buffer	*oldb = curbuf,	
X			*b;		
X
X	for (b = world; b != 0; b = b->b_next) {
X		if (!IsModified(b) || b->b_type != B_FILE)
X			continue;
X		SetBuf(b);	/* Make this current Buffer */
X		if (curbuf->b_fname == 0) {
X			char	*newname;
X
X			newname = ask(NullStr, "Buffer \"%s\" needs a file name; type Return to skip: ", b->b_name);
X			if (*newname == 0)
X				continue;
X			setfname(b, newname);
X		}
X		if (askp && (yes_or_no_p("Write %s? ", curbuf->b_fname) == NO))
X			continue;
X		filemunge(curbuf->b_fname);
X#ifndef MAC
X#ifndef MSDOS
X		chk_mtime(curbuf, curbuf->b_fname, "save");
X#endif /* MSDOS */
X#endif /* MAC */
X		file_write(curbuf->b_fname, 0);
X		unmodify();
X	}
X	SetBuf(oldb);
X}
X
void
ToIndent()
X{
X	register char	*cp,
X			c;
X
X	for (cp = linebuf; c = *cp; cp++)
X		if (c != ' ' && c != '\t')
X			break;
X	curchar = cp - linebuf;
X}
X
X/* GoLine -- go to a line, usually wired to goto-line, ESC g or ESC G.
X   If no argument is specified it asks for a line number. */
void
GoLine()
X{
X  	Line	*newline;
X
X#ifndef ANSICODES
X 	if (!is_an_arg())
X 		set_arg_value(ask_int("Line: ",10));
X#else /* not ANSICODES */
X 	if (!is_an_arg() || arg_value() <= 0) {
X  		if (SP) {
X  			putpad(SP, 1);	/* Ask for cursor position */
X			return;
X		}
X 		set_arg_value(ask_int("Line: ", 10));
X  	}
X#endif /* ANSICODES */
X 	newline = next_line(curbuf->b_first, arg_value() - 1);
X  	PushPntp(newline);
X  	SetLine(newline);
X}
X
X#ifdef ANSICODES
void
MoveToCursor(line, col)
X{
X	register struct scrimage *sp = &PhysScreen[line];
X
X	while (sp->s_id == 0)
X		sp = &PhysScreen[--line];
X	if (sp->s_flags & MODELINE)
X		complain((char *) 0);
X	if (curwind != sp->s_window)
X		SetWind(sp->s_window);
X	SetLine(sp->s_lp);
X	curchar = how_far(sp->s_lp, col);
X}
X
void
AnsiCodes()
X{
X	int	c;
X	int	num1 = 0;
X	int	num2;
X	static char *unsupported = "[Unsupported ANSI code received]";
X
X	while (isdigit(c = getch()))
X		num1 = (num1 * 10) + (c - '0');
X
X	switch (c) {
X	case ';':
X		num2 = 0;
X		while (isdigit(c = getch()))
X			num2 = (num2 * 10) + (c - '0');
X		switch (c) {
X		case 'R':
X			MoveToCursor(--num1, --num2);
X			break;
X		case 'H':
X			Eow();
X			Bol();
X			break;
X		default:
X			complain(unsupported);
X		}
X		break;
X	case 'A':
X		PrevLine();
X		break;
X	case 'B':
X		NextLine();
X		break;
X	case 'C':
X		ForChar();
X		break;
X	case 'D':
X		BackChar();
X		break;
X	case 'H':
X		Bow();
X		break;
X	case 'J':
X		if (num1 == 2) {
X			ClAndRedraw();
X			break;
X		}
X	case 'z':	/* Sun function keys send <esc>[Nz */
X		switch(num1) {
X			case 193:	/* L2 */
X				SetMark();
X				break;
X			case 194:	/* L3 */
X				PopMark();
X				break;
X			case 195:	/* L4 */
X				DelReg();
X				break;
X			case 208:	/* R1 */
X				QRepSearch();
X				break;
X			case 209:	/* R2 */
X				IncFSearch();
X				break;
X			case 210:	/* R3 */
X				WtModBuf();
X				break;
X			case 211:	/* R4 */
X				RepSearch();
X				break;
X			case 212:	/* R5 */
X				IncRSearch();
X				break;
X			case 213:	/* R6 */
X				Leave();
X				break;
X			case 214:	/* R7 */
X				BackWord();
X				break;
X			case 215:	/* R8 == UpArrow */
X				break;
X			case 216:	/* R9 */
X				ForWord();
X				break;
X			case 217:	/* R10 == LeftArrow */
X				break;
X			case 218:	/* R11 */
X				NextWindow();
X				break;
X			case 219:	/* R12 == RightArrow */
X				break;
X			case 220:	/* R13 */
X			case 221:	/* R14 == DownArrow */
X				break;
X			case 222:	/* R15 */
X			case 225:	/* F2 */
X			case 226:	/* F3 */
X			case 227:	/* F4 */
X				break;
X			case 228:	/* F5 */
X				break;
X			case 229:	/* F6 */
X				break;
X			case 230:	/* F7 */
X				break;
X			case 231:	/* F8 */
X				break;
X			case 232:	/* F9 */
X				break;
X			default:
X				num1 = -1;	/* Hack flags failure */
X				break;
X		}
X		if (num1 >= 0)
X			break;
X	case 'P':
X		PrevPage();
X		break;
X
X	case 'Q':
X		NextPage();
X		break;
X
X	case 'R':
X		UpScroll();
X		break;
X
X	case 'S':
X		DownScroll();
X		break;
X	default:
X		complain(unsupported);
X	}
X}
X#endif /* ANSICODES */
X
void
NotModified()
X{
X	unmodify();
X}
X
void
SetLMargin()
X{
X	LMargin = calc_pos(linebuf, curchar);
X}
X
void
SetRMargin()
X{
X	RMargin = calc_pos(linebuf, curchar);
X}
END_OF_FILE
if test 7989 -ne `wc -c <'./misc.c'`; then
    echo shar: \"'./misc.c'\" unpacked with wrong size!
fi
# end of './misc.c'
fi
if test -f './wind.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./wind.c'\"
else
echo shar: Extracting \"'./wind.c'\" \(9907 characters\)
sed "s/^X//" >'./wind.c' <<'END_OF_FILE'
X/***************************************************************************
X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
X * is provided to you without charge, and with no warranty.  You may give  *
X * away copies of JOVE, including sources, provided that this notice is    *
X * included in all the files.                                              *
X ***************************************************************************/
X
X/* This creates/deletes/divides/grows/shrinks windows.  */
X
X#include "jove.h"
X#include "termcap.h"
X
private char	onlyone[] = "You only have one window!",
X		toosmall[] = "Resulting window would be too small.";
X
Window	*curwind,
X	*fwind = 0;
X
X/* First line in a Window */
X
int
FLine(w)
register Window	*w;
X{
X	register Window	*wp = fwind;
X	register int	lineno = -1;
X
X	do {
X		if (wp == w)
X			return lineno + 1;
X		lineno += wp->w_height;
X		wp = wp->w_next;
X	} while (wp != fwind);
X	complain("window?");
X	/* NOTREACHED */
X}
X
X/* Delete `wp' from the screen.  If it is the only window left
X   on the screen, then complain.  It gives its body
X   to the next window if there is one, otherwise the previous
X   window gets the body.  */
X
void
del_wind(wp)
register Window	*wp;
X{
X	register Window	*prev = wp->w_prev;
X
X	if (one_windp())
X		complain(onlyone);
X
X	wp->w_prev->w_next = wp->w_next;
X	wp->w_next->w_prev = wp->w_prev;
X	
X	if (fwind == wp) {
X		fwind = wp->w_next;
X		fwind->w_height += wp->w_height;
X		/* Here try to do something intelligent for redisplay() */
X		SetTop(fwind, prev_line(fwind->w_top, wp->w_height));
X		if (curwind == wp)
X			SetWind(fwind);
X	} else {
X		prev->w_height += wp->w_height;
X		if (curwind == wp)
X			SetWind(prev);
X	}
X#ifdef MAC
X	RemoveScrollBar(wp);
X	Windchange++;
X#endif
X	free((char *) wp);
X}
X
X/* Divide the window WP N times, or at least once.  Complains if WP is too
X   small to be split into that many pieces.  It returns the new window. */
X
Window *
div_wind(wp, n)
register Window	*wp;
X{
X	register Window	*new;
X	int	amt;
X
X	if (n < 1)
X		n = 1;
X	amt = wp->w_height / (n + 1);
X	if (amt < 2)
X		complain(toosmall);
X
X	while (--n >= 0) {
X		new = (Window *) emalloc(sizeof (Window));
X		new->w_flags = 0;
X		new->w_LRscroll = 0;
X
X		new->w_height = amt;
X		wp->w_height -= amt;
X
X		/* set the lines such that w_line is the center in
X		   each Window */
X		new->w_line = wp->w_line;
X		new->w_char = wp->w_char;
X		new->w_bufp = wp->w_bufp;
X		new->w_top = prev_line(new->w_line, HALF(new));
X
X		/* Link the new window into the list */
X		new->w_prev = wp;
X		new->w_next = wp->w_next;
X		new->w_next->w_prev = new;
X		wp->w_next = new;
X#ifdef MAC
X		new->w_control = 0;
X#endif
X	}
X#ifdef MAC
X	Windchange++;
X#endif
X	return new;
X}
X
X/* Initialze the first window setting the bounds to the size of the
X   screen.  There is no buffer with this window.  See parse for the
X   setting of this window. */
X
void
winit()
X{
X	register Window	*w;
X
X	w = curwind = fwind = (Window *) emalloc(sizeof (Window));
X	w->w_line = w->w_top = 0;
X	w->w_LRscroll = 0;
X	w->w_flags = 0;
X	w->w_char = 0;
X	w->w_next = w->w_prev = fwind;
X	w->w_height = ILI;
X#ifdef MAC
X	w->w_control = 0;
X	Windchange++;
X#endif
X}
X
X/* Change to previous window. */
X
void
PrevWindow()
X{
X	register Window	*new = curwind->w_prev;
X
X	if (Asking)
X		complain((char *) 0);
X	if (one_windp())
X		complain(onlyone);
X	SetWind(new);
X}
X
X/* Make NEW the current Window */
X
void
SetWind(new)
register Window	*new;
X{
X	if (!Asking) {		/* can you say kludge? */
X		curwind->w_line = curline;
X		curwind->w_char = curchar;
X		curwind->w_bufp = curbuf;
X	}
X	if (new == curwind)
X		return;
X	SetBuf(new->w_bufp);
X	if (!inlist(new->w_bufp->b_first, new->w_line)) {
X		new->w_line = curline;
X		new->w_char = curchar;
X	}
X	DotTo(new->w_line, new->w_char);
X	if (curchar > strlen(linebuf))
X		new->w_char = curchar = strlen(linebuf);
X	curwind = new;
X}
X
X/* delete the current window if it isn't the only one left */
X
void
DelCurWindow()
X{
X	SetABuf(curwind->w_bufp);
X	del_wind(curwind);
X}
X
X/* put the current line of `w' in the middle of the window */
X
void
CentWind(w)
register Window	*w;
X{
X	SetTop(w, prev_line(w->w_line, HALF(w)));
X}
X
int	ScrollStep = 0;		/* full scrolling */
X
X/* Calculate the new topline of the window.  If ScrollStep == 0
X   it means we should center the current line in the window. */
X
void
CalcWind(w)
register Window	*w;
X{
X	register int	up;
X	int	scr_step;
X	Line	*newtop;
X
X	if (ScrollStep == 0)	/* Means just center it */
X		CentWind(w);
X	else {
X		up = inorder(w->w_line, 0, w->w_top, 0);
X		if (up == -1) {
X			CentWind(w);
X			return;
X		}
X		scr_step = (ScrollStep < 0) ? SIZE(w) + ScrollStep :
X			   ScrollStep - 1;
X		if (up)		/* point is above the screen */
X			newtop = prev_line(w->w_line, scr_step);
X		else
X			newtop = prev_line(w->w_line, (SIZE(w) - 1 - scr_step));
X		if (LineDist(newtop, w->w_top) >= SIZE(w) - 1)
X			CentWind(w);
X		else
X			SetTop(w, newtop);
X	}
X}
X
X/* This is bound to C-X 4 [BTF].  To make the screen stay the
X   same we have to remember various things, like the current
X   top line in the current window.  It's sorta gross, but it's
X   necessary because of the way this is implemented (i.e., in
X   terms of do_find(), do_select() which manipulate the windows. */
X
void
WindFind()
X{
X	register Buffer	*obuf = curbuf,
X			*nbuf;
X	Line	*ltop = curwind->w_top;
X	Bufpos	savedot;
X	extern void
X		FindTag(),
X		BufSelect(),
X		FindFile();
X
X	DOTsave(&savedot);
X
X	switch (waitchar((int *) 0)) {
X	case 't':
X	case 'T':
X		ExecCmd((data_obj *) FindCmd(FindTag));
X		break;
X
X	case 'b':
X	case 'B':
X		ExecCmd((data_obj *) FindCmd(BufSelect));
X		break;
X
X	case 'f':
X	case 'F':
X		ExecCmd((data_obj *) FindCmd(FindFile));
X		break;
X
X	default:
X		complain("T: find-tag, F: find-file, B: select-buffer.");
X	}
X
X	nbuf = curbuf;
X	SetBuf(obuf);
X	SetDot(&savedot);
X	SetTop(curwind, ltop);	/* there! it's as if we did nothing */
X
X	if (one_windp())
X		(void) div_wind(curwind, 1);
X
X	tiewind(curwind->w_next, nbuf);
X	SetWind(curwind->w_next);
X}
X
X/* Go into one window mode by deleting all the other windows */
X
void
OneWindow()
X{
X	while (curwind->w_next != curwind)
X		del_wind(curwind->w_next);
X}
X
Window *
windbp(bp)
register Buffer	*bp;
X{
X
X	register Window	*wp = fwind;
X
X	if (bp == 0)
X		return 0;
X	do {
X		if (wp->w_bufp == bp)
X			return wp;
X		wp = wp->w_next;
X	} while (wp != fwind);
X	return 0;
X}
X
X/* Change window into the next window.  Curwind becomes the new window. */
X
void
NextWindow()
X{
X	register Window	*new = curwind->w_next;
X
X	if (Asking)
X		complain((char *) 0);
X	if (one_windp())
X		complain(onlyone);
X	SetWind(new);
X}
X
X/* Scroll the next Window */
X
void
PageNWind()
X{
X	if (one_windp())
X		complain(onlyone);
X	NextWindow();
X	NextPage();
X	PrevWindow();
X}
X
Window *
w_nam_typ(name, type)
register char	*name;
X{
X	register Window *w;
X	register Buffer	*b;
X
X	b = buf_exists(name);
X	w = fwind;
X	if (b) do {
X		if (w->w_bufp == b)
X			return w;
X	} while ((w = w->w_next) != fwind);
X
X	w = fwind;
X	do {
X		if (w->w_bufp->b_type == type)
X			return w;
X	} while ((w = w->w_next) != fwind);
X
X	return 0;
X}
X
X/* Put a window with the buffer `name' in it.  Erase the buffer if
X   `clobber' is non-zero. */
X
void
pop_wind(name, clobber, btype)
register char	*name;
X{
X	register Window	*wp;
X	register Buffer	*newb;
X
X	if (newb = buf_exists(name))
X		btype = -1;	/* if the buffer exists, don't change
X				   it's type */
X	if ((wp = w_nam_typ(name, btype)) == 0) {
X		if (one_windp())
X			SetWind(div_wind(curwind, 1));
X		else
X			PrevWindow();
X	} else
X		SetWind(wp);
X
X	newb = do_select((Window *) 0, name);
X	if (clobber) {
X		initlist(newb);
X		newb->b_modified = NO;
X	}
X	tiewind(curwind, newb);
X	if (btype != -1)
X		newb->b_type = btype;
X	SetBuf(newb);
X}
X
void
GrowWindow()
X{
X	WindSize(curwind, abs(arg_value()));
X}
X
void
ShrWindow()
X{
X	WindSize(curwind, -abs(arg_value()));
X}
X
X/* Change the size of the window by inc.  First arg is the window,
X   second is the increment. */
X
void
WindSize(w, inc)
register Window	*w;
register int	inc;
X{
X	if (one_windp())
X		complain(onlyone);
X
X	if (inc == 0)
X		return;
X	else if (inc < 0) {	/* Shrinking this Window. */
X		if (w->w_height + inc < 2)
X			complain(toosmall);
X		w->w_height += inc;
X		w->w_prev->w_height -= inc;
X	} else			/* Growing the window. */
X		WindSize(w->w_next, -inc);
X#ifdef MAC
X	Windchange++;
X#endif
X}
X
X/* Set the topline of the window, calculating its number in the buffer.
X   This is for numbering the lines only. */
X
void
SetTop(w, line)
Window	*w;
register Line	*line;
X{
X	register Line	*lp = w->w_bufp->b_first;
X	register int	num = 0;
X
X	w->w_top = line;
X	if (w->w_flags & W_NUMLINES) {
X		while (lp) {
X			num += 1;
X			if (line == lp)
X				break;
X			lp = lp->l_next;
X		}
X		w->w_topnum = num;
X	}
X}
X
void
WNumLines()
X{
X	curwind->w_flags ^= W_NUMLINES; 
X	SetTop(curwind, curwind->w_top);
X}
X
void
WVisSpace()
X{
X	curwind->w_flags ^= W_VISSPACE;
X	ClAndRedraw();
X}
X
X/* Return the line number that `line' occupies in `windes' */
X
int
in_window(windes, line)
register Window	*windes;
register Line	*line;
X{
X	register int	i;
X	register Line	*top = windes->w_top;
X
X	for (i = 0; top && i < windes->w_height - 1; i++, top = top->l_next)
X		if (top == line)
X			return FLine(windes) + i;
X	return -1;
X}
X
void
SplitWind()
X{
X	SetWind(div_wind(curwind, is_an_arg() ? (arg_value() - 1) : 1));
X}
X
X/* Goto the window with the named buffer.  If no such window
X   exists, pop one and attach the buffer to it. */
void
GotoWind()
X{
X	extern Buffer	*lastbuf;
X	char	*bname;
X	Window	*w;
X
X	bname = ask_buf(lastbuf);
X	w = curwind->w_next;
X	do {
X		if (w->w_bufp->b_name == bname) {
X			SetABuf(curbuf);
X			SetWind(w);
X			return;
X		}
X		w = w->w_next;
X	} while (w != curwind);
X	SetABuf(curbuf);
X	pop_wind(bname, NO, -1);
X}
X
void
ScrollRight()
X{
X	int	amt = (is_an_arg() ? arg_value() : 10);
X
X	if (curwind->w_LRscroll - amt < 0)
X		curwind->w_LRscroll = 0;
X	else
X		curwind->w_LRscroll -= amt;
X	UpdModLine = YES;
X}
X
void
ScrollLeft()
X{
X	int	amt = (is_an_arg() ? arg_value() : 10);
X
X	curwind->w_LRscroll += amt;
X	UpdModLine = YES;
X}
END_OF_FILE
if test 9907 -ne `wc -c <'./wind.c'`; then
    echo shar: \"'./wind.c'\" unpacked with wrong size!
fi
# end of './wind.c'
fi
echo shar: End of archive 4 \(of 21\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 21 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.