BSD 4_3_Tahoe development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Mon, 14 Mar 1988 09:38:15 +0000 (01:38 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Mon, 14 Mar 1988 09:38:15 +0000 (01:38 -0800)
Work on file usr/src/new/jove/Makefile.dos
Work on file usr/src/new/jove/Ovmakefile
Work on file usr/src/new/jove/README
Work on file usr/src/new/jove/Readme.dos
Work on file usr/src/new/jove/abbrev.c
Work on file usr/src/new/jove/Readme.mac
Work on file usr/src/new/jove/argcount.c
Work on file usr/src/new/jove/case.c
Work on file usr/src/new/jove/ctype.h
Work on file usr/src/new/jove/fmt.c
Work on file usr/src/new/jove/funcdefs.c
Work on file usr/src/new/jove/fp.c
Work on file usr/src/new/jove/getch.c
Work on file usr/src/new/jove/insert.c
Work on file usr/src/new/jove/iproc-pipes.c
Work on file usr/src/new/jove/io.h
Work on file usr/src/new/jove/iproc-ptys.c
Work on file usr/src/new/jove/iproc.c
Work on file usr/src/new/jove/mac.h
Work on file usr/src/new/jove/macvert.c
Work on file usr/src/new/jove/marks.c
Work on file usr/src/new/jove/menumaps.txt
Work on file usr/src/new/jove/mjovers.Hqx
Work on file usr/src/new/jove/paragraph.c
Work on file usr/src/new/jove/portsrv.c
Work on file usr/src/new/jove/re.c
Work on file usr/src/new/jove/re.h
Work on file usr/src/new/jove/re1.c
Work on file usr/src/new/jove/rec.h
Work on file usr/src/new/jove/rec.c
Work on file usr/src/new/jove/recover.c
Work on file usr/src/new/jove/setmaps.c
Work on file usr/src/new/jove/table.c
Work on file usr/src/new/jove/table.h
Work on file usr/src/new/jove/teachjove.c
Work on file usr/src/new/jove/temp.h
Work on file usr/src/new/jove/termcap.h
Work on file usr/src/new/jove/tune.dos
Work on file usr/src/new/jove/tune.template
Work on file usr/src/new/jove/vars.c
Work on file usr/src/new/jove/version.c
Work on file usr/src/new/jove/wind.c

Synthesized-from: CSRG/cd2/4.3tahoe

42 files changed:
usr/src/new/jove/Makefile.dos [new file with mode: 0644]
usr/src/new/jove/Ovmakefile [new file with mode: 0644]
usr/src/new/jove/README [new file with mode: 0644]
usr/src/new/jove/Readme.dos [new file with mode: 0644]
usr/src/new/jove/Readme.mac [new file with mode: 0644]
usr/src/new/jove/abbrev.c [new file with mode: 0644]
usr/src/new/jove/argcount.c [new file with mode: 0644]
usr/src/new/jove/case.c [new file with mode: 0644]
usr/src/new/jove/ctype.h [new file with mode: 0644]
usr/src/new/jove/fmt.c [new file with mode: 0644]
usr/src/new/jove/fp.c [new file with mode: 0644]
usr/src/new/jove/funcdefs.c [new file with mode: 0644]
usr/src/new/jove/getch.c [new file with mode: 0644]
usr/src/new/jove/insert.c [new file with mode: 0644]
usr/src/new/jove/io.h [new file with mode: 0644]
usr/src/new/jove/iproc-pipes.c [new file with mode: 0644]
usr/src/new/jove/iproc-ptys.c [new file with mode: 0644]
usr/src/new/jove/iproc.c [new file with mode: 0644]
usr/src/new/jove/mac.h [new file with mode: 0644]
usr/src/new/jove/macvert.c [new file with mode: 0644]
usr/src/new/jove/marks.c [new file with mode: 0644]
usr/src/new/jove/menumaps.txt [new file with mode: 0644]
usr/src/new/jove/mjovers.Hqx [new file with mode: 0644]
usr/src/new/jove/paragraph.c [new file with mode: 0644]
usr/src/new/jove/portsrv.c [new file with mode: 0644]
usr/src/new/jove/re.c [new file with mode: 0644]
usr/src/new/jove/re.h [new file with mode: 0644]
usr/src/new/jove/re1.c [new file with mode: 0644]
usr/src/new/jove/rec.c [new file with mode: 0644]
usr/src/new/jove/rec.h [new file with mode: 0644]
usr/src/new/jove/recover.c [new file with mode: 0644]
usr/src/new/jove/setmaps.c [new file with mode: 0644]
usr/src/new/jove/table.c [new file with mode: 0644]
usr/src/new/jove/table.h [new file with mode: 0644]
usr/src/new/jove/teachjove.c [new file with mode: 0644]
usr/src/new/jove/temp.h [new file with mode: 0644]
usr/src/new/jove/termcap.h [new file with mode: 0644]
usr/src/new/jove/tune.dos [new file with mode: 0644]
usr/src/new/jove/tune.template [new file with mode: 0644]
usr/src/new/jove/vars.c [new file with mode: 0644]
usr/src/new/jove/version.c [new file with mode: 0644]
usr/src/new/jove/wind.c [new file with mode: 0644]

diff --git a/usr/src/new/jove/Makefile.dos b/usr/src/new/jove/Makefile.dos
new file mode 100644 (file)
index 0000000..6513423
--- /dev/null
@@ -0,0 +1,60 @@
+###########################################################################
+# This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE #
+# is provided to you without charge, and with no warranty.  You may give  #
+# away copies of JOVE, including sources, provided that this notice is    #
+# included in all the files.                                              #
+###########################################################################
+
+MEM = L                        # M for medium or L for large
+DEB = -Gs -Ot          # use -Zi and MEM = M for debugging
+#
+# define LINT_ARGS to use function prototypes
+#
+CFLAGS = -A$(MEM) -J -Zp $(DEB) -DIBMPC
+LIB = C:\C\LIB
+#
+# linker flags: for debugging use /NOE/NOI/F/B/PAC/CO/STACK:0x2000
+#
+LDFLAGS = /NOE/NOI/MAP/F/B/E/PAC/STACK:0x2000
+#
+# set VPATH as below if you have sources in SRC
+#
+SRC = .
+# VPATH = .;.. # should read .;$(SRC) - but doesn't work
+
+OBJECTS = keymaps.obj funcdefs.obj abbrev.obj ask.obj buf.obj c.obj \
+       case.obj ctype.obj delete.obj extend.obj argcount.obj \
+       insert.obj io.obj jove.obj macros.obj marks.obj misc.obj move.obj \
+       paragrap.obj proc.obj re.obj re1.obj scandir.obj \
+       table.obj tune.obj util.obj vars.obj wind.obj \
+       fmt.obj disp.obj term.obj version.obj fp.obj screen.obj getch.obj
+
+HEADERS = ctype.h io.h jove.h re.h table.h temp.h termcap.h tune.h externs.h
+
+jove.exe:      $(OBJECTS) $(HEADERS)
+       link $(OBJECTS) $(LIB)\setargv,jove $(LDFLAGS);
+
+$(OBJECTS): $(HEADERS)
+
+setmaps.exe:   setmaps.obj funcdefs.c
+       cl setmaps.obj
+
+setmaps.obj:   funcdefs.c keymaps.txt
+       cl $(CFLAGS) $(SRC)\setmaps.c
+
+keymaps.c:     setmaps.exe keymaps.txt
+       setmaps < keymaps.txt > keymaps.c
+
+keymaps.obj:   keymaps.c jove.h
+       $(CC) $(CFLAGS) -I$(SRC) -c keymaps.c
+
+# to avoid accidental loss under unix
+tune.c:        tune.dos
+       copy tune.dos tune.c
+
+tune.obj: tune.c
+       $(CC) $(CFLAGS) -I$(SRC) -c tune.c
+
+clean:
+       -rm *.obj setmaps.exe keymaps.c *.bak *.map
+
diff --git a/usr/src/new/jove/Ovmakefile b/usr/src/new/jove/Ovmakefile
new file mode 100644 (file)
index 0000000..e48c5bf
--- /dev/null
@@ -0,0 +1,224 @@
+###########################################################################
+# This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE #
+# is provided to you without charge, and with no warranty.  You may give  #
+# away copies of JOVE, including sources, provided that this notice is    #
+# included in all the 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 clearned upon reboot, and use that instead.
+# You would probably want to clean out that directory periodically with
+# /etc/cron.  LIBDIR is for online documentation, the PORTSRV process,
+# RECOVER, and the system-wide .joverc file.  BINDIR is where to put the
+# executables JOVE and TEACHJOVE.  MANDIR is where the manual pages go for
+# JOVE, RECOVER and TEACHJOVE.  MANEXT is the extension for the man pages,
+# e.g., jove.1 or jove.l or jove.m.
+
+DESTDIR =
+TMPDIR = /tmp
+LIBDIR = /usr/lib/jove
+BINDIR = /bin
+MANDIR = /usr/man/man1
+MANEXT = 1
+SHELL = /bin/csh
+
+# These should all just be right if the above ones are.
+JOVE = $(DESTDIR)$(BINDIR)/jove
+RECOVER = $(DESTDIR)$(LIBDIR)/recover
+TEACHJOVE = $(DESTDIR)$(BINDIR)/teachjove
+JOVERC = $(DESTDIR)$(LIBDIR)/.joverc
+CMDS.DOC = $(DESTDIR)$(LIBDIR)/cmds.doc
+TEACH-JOVE = $(DESTDIR)$(LIBDIR)/teach-jove
+PORTSRV = $(DESTDIR)$(LIBDIR)/portsrv
+JOVEM = $(DESTDIR)$(MANDIR)/jove.$(MANEXT)
+RECOVERM = $(DESTDIR)$(MANDIR)/recover.$(MANEXT)
+TEACHJOVEM = $(DESTDIR)$(MANDIR)/teachjove.$(MANEXT)
+
+# Select the right libraries for your system.
+#      2.9BSD: LIBS =  -ltermlib -ljobs
+#      v7:     LIBS =  -ltermlib
+#      4.1BSD: LIBS =  -ltermlib -ljobs
+#      4.2BSD: LIBS =  -ltermlib
+#      4.3BSD: LIBS =  -ltermlib
+
+OVLIBS = -lovtermcap -lovjobs
+LIBS = -ltermcap -ljobs
+
+# If you are not VMUNIX (vax running Berkeley Version 4), you must specify
+# the -i flags (split I/D space) and maybe the -x option (for adb to work).
+#      2.9BSD: LDFLAGS = -x -i
+#      v7:     LDFLAGS = -x -i
+#      4.1BSD: LDFLAGS =
+#      4.2BSD: LDFLAGS =
+#      4.3BSD: LDFLAGS =
+
+LDFLAGS =  -x -i
+
+CFLAGS = -O -V
+
+COFLAGS = -rworking -q
+
+BASESEG = funcdefs.o keymaps.o argcount.o ask.o buf.o ctype.o delete.o disp.o fmt.o fp.o \
+         insert.o io.o jove.o malloc.o marks.o misc.o move.o re.o \
+         screen.o table.o tune.o util.o version.o
+OVLAY1 = abbrev.o rec.o paragraph.o macros.o
+OVLAY2 = c.o wind.o vars.o
+OVLAY3 = extend.o
+OVLAY4 = iproc.o re1.o
+OVLAY5 = proc.o scandir.o term.o case.o
+
+OBJECTS = $(BASESEG) $(OVLAY1) $(OVLAY2) $(OVLAY3) $(OVLAY4) $(OVLAY5)
+
+C-FILES = funcdefs.c abbrev.c argcount.c ask.c buf.c c.c case.c ctype.c delete.c disp.c \
+       extend.c fmt.c fp.c insert.c io.c iproc.c iproc-pipes.c iproc-ptys.c \
+       jove.c macros.c malloc.c marks.c misc.c move.c paragraph.c proc.c \
+       re.c re1.c rec.c scandir.c screen.c table.c term.c util.c vars.c version.c \
+       wind.c
+
+H-FILES = ctype.h io.h jove.h re.h rec.h table.h temp.h termcap.h tune.h
+
+BACKUPS = $(C-FILES) $(H-FILES) $(DOCS) teachjove.c recover.c setmaps.c portsrv.c \
+       tune.template Makefile Ovmakefile keymaps.txt README tags
+
+DOCS = doc/cmds.doc.nr doc/example.rc doc/jove.1 doc/jove.2 doc/jove.3 \
+       doc/jove.4 doc/jove.nr doc/recover.nr doc/system.rc doc/teach-jove \
+       doc/teachjove.nr doc/README
+
+all:   xjove recover teachjove portsrv
+
+xjove: $(OBJECTS)
+       ld $(LDFLAGS) /lib/crt0.o \
+               -Z $(OVLAY1) \
+               -Z $(OVLAY2) \
+               -Z $(OVLAY3) \
+               -Z $(OVLAY4) \
+               -Z $(OVLAY5) \
+               -L $(BASESEG) \
+               -o xjove $(OVLIBS) -lovc
+       checkobj xjove
+       @-size xjove
+       @-date
+
+portsrv:       portsrv.c
+       cc -o portsrv -n -O portsrv.c $(LIBS)
+
+recover:       recover.c tune.o rec.h temp.h
+       cc -o recover -n -O recover.c tune.o -ljobs
+
+teachjove:     teachjove.c
+       cc -o teachjove -n -O -DTEACHJOVE=\"$(TEACH-JOVE)\" teachjove.c
+
+setmaps:       setmaps.c funcdefs.c
+       cc -o setmaps setmaps.c
+
+keymaps.c:     setmaps keymaps.txt
+       setmaps < keymaps.txt > keymaps.c
+
+tune.c: Makefile tune.template
+       @echo "/* Changes should be made in Makefile, not to this file! */" > tune.c
+       @echo "" >> tune.c
+       @sed -e 's;TMPDIR;$(TMPDIR);' \
+            -e 's;LIBDIR;$(LIBDIR);' \
+            -e 's;BINDIR;$(BINDIR);' \
+            -e 's;SHELL;$(SHELL);' tune.template >> tune.c
+
+install: $(LIBDIR) $(TEACH-JOVE) $(CMDS.DOC) $(JOVERC) $(PORTSRV) $(RECOVER) \
+        $(JOVE) $(TEACHJOVE) $(JOVEM) $(RECOVERM) $(TEACHJOVEM)
+
+$(DESTDIR)$(LIBDIR):
+       -mkdir (DESTDIR)$(LIBDIR)
+
+$(TEACH-JOVE): doc/teach-jove
+       install -c -m 644 doc/teach-jove $(TEACH-JOVE)
+
+$(CMDS.DOC): doc/cmds.doc
+       install -c -m 644 doc/cmds.doc $(CMDS.DOC)
+
+$(JOVERC): doc/system.rc
+       install -c -m 644 doc/system.rc $(JOVERC)
+
+$(PORTSRV): portsrv
+       install -c -m 755 portsrv $(PORTSRV)
+
+$(RECOVER): recover
+       install -c -m 755 recover $(RECOVER)
+
+$(JOVE): xjove
+       install -c -m 755 xjove $(JOVE)
+
+$(TEACHJOVE): teachjove
+       install -c -m 755 teachjove $(TEACHJOVE)
+
+$(JOVEM): doc/jove.nr
+       @sed -e 's;TMPDIR;$(TMPDIR);' \
+            -e 's;LIBDIR;$(LIBDIR);' \
+            -e 's;SHELL;$(SHELL);' doc/jove.nr > /tmp/jove.nr
+       install -m 644 /tmp/jove.nr $(JOVEM)
+
+$(RECOVERM): doc/recover.nr
+       @sed -e 's;TMPDIR;$(TMPDIR);' \
+            -e 's;LIBDIR;$(LIBDIR);' \
+            -e 's;SHELL;$(SHELL);' doc/recover.nr > /tmp/recover.nr
+       install -m 644 /tmp/recover.nr $(RECOVERM)
+
+$(TEACHJOVEM): doc/teachjove.nr
+       @sed -e 's;TMPDIR;$(TMPDIR);' \
+            -e 's;LIBDIR;$(LIBDIR);' \
+            -e 's;SHELL;$(SHELL);' doc/teachjove.nr > /tmp/teachjove.nr
+       install -m 644 /tmp/teachjove.nr $(TEACHJOVEM)
+
+echo:
+       @echo $(C-FILES) $(H-FILES)
+
+lint:
+       lint -x $(C-FILES)
+       echo Done
+
+tags:
+       ctags -w $(C-FILES) $(H-FILES)
+
+
+jove.shar:
+       shar $(BACKUPS) doc/* > jove.shar
+
+backup:
+       tar cf backup $(BACKUPS)
+
+tape-backup:
+       tar cbf 20 /dev/rmt0 $(BACKUPS)
+
+clean:
+       rm -f a.out core $(OBJECTS) keymaps.c xjove \
+               portsrv recover setmaps teachjove
+
+# abbrev.o: jove.h tune.h
+# ask.o: jove.h tune.h
+# buf.o: jove.h tune.h
+# c.o: jove.h tune.h
+# delete.o: jove.h tune.h
+# disp.o: jove.h tune.h termcap.h
+# extend.o: jove.h tune.h
+# fmt.o: jove.h tune.h termcap.h
+# funcdefs.o: jove.h tune.h
+# insert.o: jove.h tune.h
+# io.o: jove.h tune.h termcap.h temp.h
+# iproc.o: jove.h tune.h
+# jove.o: jove.h tune.h termcap.h
+# macros.o: jove.h tune.h
+# marks.o: jove.h tune.h
+# misc.o: jove.h tune.h
+# move.o: jove.h tune.h
+# portsrv.o: jove.h tune.h
+# proc.o: jove.h tune.h
+# re.o: jove.h tune.h
+# rec.o: jove.h tune.h temp.h rec.h
+# recover.o: jove.h tune.h temp.h rec.h
+# screen.o: jove.h tune.h temp.h termcap.h
+# setmaps.o: jove.h tune.h
+# term.o: jove.h tune.h
+# tune.o: tune.h
+# util.o: jove.h tune.h
+# wind.o: jove.h tune.h termcap.h
diff --git a/usr/src/new/jove/README b/usr/src/new/jove/README
new file mode 100644 (file)
index 0000000..a32dc0f
--- /dev/null
@@ -0,0 +1,172 @@
+###########################################################################
+# This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE #
+# is provided to you without charge, and with no warranty.  You may give  #
+# away copies of JOVE, including sources, provided that this notice is    #
+# included in all the files.                                              #
+###########################################################################
+
+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.
+
+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
+/etc/cron.
+
+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.
+
+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.
+
+Here's a list of the compile time options and what they mean:
+
+ABBREV    - Enables word-abbrev-mode which again is nice for paper writers.
+
+BACKUPFILES - This enables backing up files on write.  I guess lots of
+             people like this feature.  It enables the feature but you
+             can still control whether files are backed up with the
+             make-backup-files variable.
+
+BIFF      - This enables turning on and off BIFF so your screen doesn't
+             get messed up with messages from BIFF.
+
+BSD4_2     - Obviously, if you're a Berkeley 4.2 system.
+
+BSD4_3    - If you're running a Berkeley 4.3 or 2.10 system.
+            This will automatically define BSD4_2, also.
+
+CHDIR     - This enables the directory commands; PUSHD, POPD, DIRS and
+             CD.  These simulate the csh commands exactly, I think.  As
+             a side-effect, absolute path names are enabled, which means
+             JOVE parses file names for "." and ".." and all that to get
+             at what you REALLY mean.  It's nicer when this is enabled,
+             but not essential.
+
+CMT_FMT           - This enables code to format and indent C comments.
+
+ID_CHAR           - Enables support for Insert/Delete character on terminals
+            that have those capabilities.  Couple of problems with this code:
+            it's large, takes up lots of I space which is a problem for the
+            smaller computers (pdp11).  Also, it isn't particularly smart
+            and sometimes does really stupid things.  It sometimes uses
+            insert/delete character when simply redrawing would have been
+            faster.  And if you look at code you'll understand why I don't
+            like it all that much.
+
+IPROCS    - Nice feature which lets you run interactive UNIX commands in
+            windows.  In particular, there is a shell command built
+            in which starts up an interactive shell in a window.  This works
+            only on systems with JOB_CONTROL since it relies on the fancy
+            signal mechanism.
+
+JOB_CONTROL - Versions of UNIX that have the job control facility.
+             Berkeley 2.9-10 systems, and the 4.1-3 systems I know have
+             job stopping, so if you're one of those, define
+             this.  The reason MENLO_JCL is defined when JOB_CONTROL
+             is that the 2.9 signal.h file only defines all of the job
+             stopping signals only when MENLO_JCL is defined.
+
+LISP      - Enables Lisp Mode.  This includes code to indent "properly"
+            for Lisp code and new routines to move over s-expressions.
+            You probably won't want (or need) this on PDP-11's.
+
+MY_MALLOC  - Use the older version of malloc that is more memory efficient
+            than the newer 4BSD version.  The 4BSD version places more
+            importance on the speed of the allocation than the amount of
+            memory it uses.  Make your choice ... JOVE hardly ever calls
+            malloc, anyway, relatively speaking, since it allocates
+            lines in big chunks.  NOTE: This doesn't seem to work on suns
+            and the iAPX286.
+
+PIPEPROCS  - If NOT defined, JOVE will use Berkeley pseudo-ttys when
+            doing interactive processes.  This is infinitely better,
+            since you get job control and all that stuff on i-procs.
+            If defined, the portsrv program will have to be made, and
+            all communication between jove and i-procs will be done using
+            pipes.
+
+RESHAPING  - This is for BRL or Berkeley 4.3 and 2.10 systems.  When the
+            window size of the terminal jove is running in is changed
+            a SIGWINCH is sent to all processes in the tty group.  This
+            define enables code in jove to catch that signal and reshape
+            its windows.
+
+SPELL     - Enables the spell-buffer and parse-spelling-errors commands.
+            They are nice especially if you have lots of paper writers.
+
+WIRED_TERMS - Include compiled-in hard-wired code for certain terminals,
+            like the Concept 100.  If you don't have these terminals,
+            you probably don't need this (but no point in taking it
+            out unless you're low on space).
+
+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
+       macvert old-style-macros-file > new-style-macro-file
+
+"doc/system.rc" and "doc/example.rc" are jove initialization files.
+"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.
+
+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.
+
+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.
+
+Thanks to Jay (hack) Fenlason for writing the original pty code.
+
+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.
+
+Thanks to Jeff Mc Carrell at Berkeley for finding bugs and adding
+features, in particular, the comment formatter.
+
+Thanks to Karl Gegenfurtner for making the PC version.
+
+(Thanks to Brian Harvey for teaching me about linked lists ...)
+
+Good luck, have fun.
+
+       Jonathan Payne (jpayne@cs.rochester.edu until '88)
diff --git a/usr/src/new/jove/Readme.dos b/usr/src/new/jove/Readme.dos
new file mode 100644 (file)
index 0000000..666ce89
--- /dev/null
@@ -0,0 +1,225 @@
+###########################################################################
+# This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE #
+# is provided to you without charge, and with no warranty.  You may give  #
+# away copies of JOVE, including sources, provided that this notice is    #
+# included in all the files.                                              #
+###########################################################################
+
+HOW TO GET STARTED WITH JOVE:
+=============================
+
+You can immediately start using Jove if you have an IBMPC
+compatible PC, XT or AT. You can fine tune some things by setting
+certain environment variables, but it's not really necessary
+If your computer is not IBM BIOS compatible, you have to set some 
+environment variables before starting Jove.
+What follows is a description of those variables.
+
+ENVIRONMENT VARIABLES USED BY JOVE:
+===================================
+
+TMP (or TMPDIR)
+Jove uses the value of TMP to determine the directory where it should
+put its temporary file. The default is the current directory, and this
+is probably not what you want. In general editing is faster, if TMP
+points to a ramdisk, like "set tmp=d:". You have to know however that
+the temporary file can grow quite big when editing many big files at
+once. So please make sure that you have enough space available on your
+ramdisk. If Jove runs out of space on the device which holds the
+temporary file, you have to leave the editor immediately. You can save
+your work without any trouble, but you have to start over. Please note
+also that the current version of Jove has a big cache for the
+temporary file in memory, which makes it quite fast even if you don't
+have a ramdisk.
+
+DESCRIBE
+This variable tells Jove, where it can find the file that holds the
+online documentation. You should set DESCRIBE to the complete
+path-specification of the file "cmds.doc", which is included as part
+of the documentation. The default for DESCRIBE is "c:/unix/cmds.doc".
+
+JOVERC
+This is the complete path for Jove's startup file. All commands in the
+file, that JOVERC points to, are executed every time when you run
+Jove. If there is a file called "jove.rc" in the current directory,
+then it is also "sourced", ie. the commands in that file are executed.
+That way you can customize Jove to your own taste.
+
+The next two variables are not used by the IBMPC version, and have to
+do with specifying the type of terminal in use on a generic msdos
+computer.
+
+TERM
+This variable should specify the name of the terminal you are using.
+For example, if you have a DEC vt-100 terminal attached to your msdos
+computer, you should give the command "set TERM=vt100" prior to
+starting Jove.
+
+TERMCAP
+This environment variable holds the name of a database with
+descriptions of different terminal types. If you are familiar with the
+Unix operating system, you probably know about TERMCAP. For each
+terminal type, specified by TERM, the TERMCAP database holds an entry,
+which describes how to set the cursor, how to scroll, and many other
+things, for that particular terminal. A small example TERMCAP file
+comes with Jove. If your terminal is not included there, you should ask a
+local Unix guru for help. If you don't have one, you can ask me.
+
+METAKEY
+Some kinds of terminals have a special shift key that Jove can recognize, 
+the so called MetaKey. When the environment variable METAKEY is set, Jove
+assumes that you have such a terminal, and treats the codes that your
+terminal sends in a slightly different way. Pressing down the MetaKey
+and another key at the same time is a then a shorthand for pressing
+first the "esc" key, and then the other key.
+
+
+DIFFERENT VERSIONS OF JOVE:
+===========================
+
+The text above already indicated that Jove comes in different versions
+for different types of computers. Not only that, there also exist
+versions that differ in the way they use the memory of the computer. 
+
+The "large" versions of Jove use all the memory available if it is
+necessary. The temporary file can grow infinitely large in those
+versions. The number of lines that can be edited with the large
+version is about 20000 to 25000 on a PC with 640 kB of memory. Note
+that there is no limit on the size of the file itself.
+The "medium" versions of Jove are more conservative in their use of
+memory. They always take up about 130 kB of memory, which leaves a big
+rest for executing large programs, like the C-Compiler from within
+Jove. The size of the temporary file is also limited to 512 kB in the
+medium versions. The leads to a limit of approximately 4500 to 5000
+lines that can be edited at one time. 
+The standard executable files that are distributed in binary form, are
+usually the large ones. If you need a medium version, you either have
+to recompile Jove from the sources (see below), or you can get get
+it from someone else who has compiled it, for example from me.
+
+There currently exist versions of Jove for three different types of
+msdos computers. PCJOVE is for IBMPC compatible computers. Compatible
+means here that the ROM Bios of your computer has to support the same
+Video output calls as the PC's. So even if your "clone" has trouble
+with many other programs, there's a high chance that Jove will work.
+MSJOVE should generally run on any computer that runs the msdos
+operating system. It strictly uses only well documented system calls
+to do its task. RBJOVE is a special version of MSJOVE for DEC Rainbow
+computers, which uses the Rainbows Bios for screen output and keyboard
+input. This makes it much faster than MSJOVE on the Rainbow.
+
+
+DIFFERENCES BETWEEN JOVE UNDER MSDOS AND UNIX JOVE:
+===================================================
+
+The msdos version of Jove currently supports all of the features that
+are possible to implement under msdos in a reasonable way.
+Version 4.8b in particular supports:
+       filename completion
+       comment filling 
+       creation of backup files
+       word abbreviation mode
+       Lisp mode
+       change directory within Jove
+       executing commands from within Jove
+       filtering regions through msdos commands
+You have to look into the manual for more explanations of these
+features. The things that are missing under msdos are:
+       spell-buffer (obsolete under msdos)
+       interactive shells in a window (not possible)
+There are however some features added, which are specific to the PC
+version.
+
+Variables:
+ Background-color specifies the background color of the screen. The default
+    value is 0, which stands for black.
+ Foreground-color specifies the foreground color of the screen. The default
+    is 1, which stands for white. The attribute used for writing to the
+    screen is formed by (bg&7)<<4 & (fg&7).
+ Mode-line-color specifies the color of the modeline. Its default
+    value is 0, and in that case it is drawn in reverse video. If it has
+    any other value, this value is used as the attribute in Bios calls. 
+ (note that on a monochrome monitor the best thing is to leave the
+ default colors - anything else can lead to blank screens very easily)
+
+Commands:
+ Scroll-previous-page continuously scrolls down screen-full lines.
+ Scroll-next-page continuously scrolls up screen-full lines.
+ Select-buffer-n, where n is in the range 0 to 9, selects buffer n as the
+    working buffer. These commands are bound to the <alt>[0-9] keys by
+    default. For example, pressing the alt key and 3 at the same time
+    switches immediately to buffer 3.
+
+General:
+ PCJOVE supports the whole 8 bit character set of the IBMPC. You can
+ use all the line drawing characters in your files. It also knows
+ about some special foreign characters (Umlaute), which are treated
+ correctly as part of words and in case conversions.
+
+
+VIDEO MODES ON THE IBMPC:
+=========================
+
+This concerns PCJOVE only. When Jove is started, it automatically
+checks which video mode is currently used, and adjusts itself
+correspondingly. This means that Jove will work correctly even in
+40x25 mode. If you have an Ega card, and want to use the special mode
+with 43 lines, set the environment variable TERM to the value EGA, or
+set the variable EGA to any value. This will tell Jove to set the
+screen in 80x43 mode. The regular 80x25 mode is restored upon exit.
+On a color monitor, you can change the screen colors by using the
+commands mentioned above.
+There is a problem in using Jove together with Hershey
+MicroComputing's FansiConsole screen driver. FansiConsole doesn't
+properly set some of the values in the Bios control area. This usually
+leads to a crash when Jove starts. You can restore the information
+Jove needs by giving the command "mode co80" before starting Jove.
+Note that Kermit version 2.30 has the same problem, and that it can
+only be fixed by fixing FansiConsole.
+
+
+COMPILING JOVE UNDER MSDOS:
+===========================
+
+Jove can currently only be compiled with the Version 5.0 of the
+Microsoft C Compiler. Jove uses some library function calls that were
+not included with version 4.0 or earlier of Microsoft C. The makefile
+that is included with the sources will not work with Microsofts lousy
+make. I recommend that you use ndmake, a public domain (or is it
+shareware) make utility, which is much better than Microsofts.
+Jove can be compiled with the medium, or the large memory model. To
+get the IBMPC version, the option "-DIBMPC" should be given at the
+command line for the Compiler. Similarly, the define for the Rainbow
+version is RAINBOW. The variable MSDOS is always defined by the
+compiler. If you want to disable some features you can do so by making
+changes to tune.h.
+If you want to give away the version of Jove you are compiling to
+other people, don't use the loop optimizations or intrinsic
+functions!!! The compiler currently has some bugs in the optimizer,
+which causes it to produce wrong code sometimes, and in unpredictable
+places. Look at the function DoJustify(), in paragraph.c, for an
+example. Note that the #pragma is commented out. because compilers on
+other machines don't like it. If you find that the version you just
+compiled behaves strange in some way, and you compiled with
+optimizations on, check whether it works ok with optimizations
+disabled before you tell all the world about a new bug in Jove.
+If you want to compile MSJOVE or RBJOVE, you need the library MTERMLIB
+or LTERMLIB, for medium or large memory model, respectively. These
+libraries contain the functions for dealing with the termcap database.
+
+If you want to compile Jove with Turbo-C, the port has already been
+done by Brian Campbell (brianc@cognos.uucp). A separate file with the
+diffs is currently available from him, and will probably be included
+as ifdefs in future versions.
+
+If you find a bug in Jove, have some questions, or some suggestions,
+you are always welcome. Just send mail to me. My address is:
+
+          Karl Gegenfurtner
+
+arpa:     karl@hipl.psych.nyu.edu
+uucp      {ihnp4|seismo|allegra}!cmcl2!xp!hipl!karl
+usps:     New York University
+          Dept. of Psychology
+          6 Washington Place 8th floor
+          New York, NY 10003
diff --git a/usr/src/new/jove/Readme.mac b/usr/src/new/jove/Readme.mac
new file mode 100644 (file)
index 0000000..df6c005
--- /dev/null
@@ -0,0 +1,387 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+Introduction
+
+This file contains a brief description of MacJove, along with
+information necessary to make MacJove from the source files.
+It is assumed that the reader is familiar with Jove from other
+systems, and is somewhat familiar with the Macintosh as well. In
+the future there may be a separate user's manual for MacJove: 
+for the time being, the reader should refer to the Jove manual
+for Unix users.
+
+Description
+
+MacJove is a direct port of Jove to the Macintosh, with the
+overall structure, commands and key bindings left intact. In
+addition, elements of the Macintosh user interface - menus,
+window controls, and the mouse, have been integrated in a manner
+consistent with the overall functioning of Jove.
+
+While the integration of these tools into the Jove environment
+is consistent and, to most users, familiar, Jove departs in
+several places from "Macintosh User Interface Guidelines". Most
+notably, the mouse is used to position the point only, not to
+drag or select text, and the Jove buffer structure is not
+integrated with the clipboard. Also, key bindings conform to
+Jove/Emacs tradition, and not to Macintosh guidelines: i.e.
+control (command)-N is next-line, not "NewFile". The reason for
+these departures is that the majority of MacJove users are likely
+to be those already familiar with Jove or other Emacs editors
+on other systems, and for these users, consistency between machines
+and operating systems is more important than fully exploiting
+the features of a single system. There are numerous other text
+editors which fully follow the Macintosh User Interface Guidelines.
+
+MacJove retains most features of other Joves, but certain commands
+cannot be implemented because of the Macintosh operating system.
+Thus, there is no way to run a sub-process or a shell in a window,
+because there are no shells to run on the Macintosh, and a program
+(currently) can only transfer control to another program, not run
+a child process. For similar reasons, commands dealing with mail,
+with running make, and checking errors, are omitted.
+
+
+
+                      Running MacJove
+
+System Requirements
+
+MacJove should run without difficulty on any Macintosh Plus, SE, or
+Macintosh II, providing that the hierarchical file system (HFS) is used, and
+assuming a reasonably current system file is used. An upgraded 512K Mac
+(with 128K rom) should also work if there is enough memory.  MacJove was
+developed on a Macintosh Plus and Macintosh II running system 4.2 and Finder
+6.0., and has not been fully tested on earlier systems - however, it is
+likely that it will run on system 3.2 and later versions. MacJove has been
+used to a limited extent with Switcher and under Multifinder. In both cases,
+it is important to reserve enough memory for MacJove, as discussed below.
+
+MacJove, as compiled from the sources, uses memory as follows:
+
+   Program Code     approx 116K
+   Static Data      approx  20K
+   Tempfile Cache           64K (heap)
+                           ____
+                           200K total before stack/heap considerations
+
+To this must be added stack and heap space. A bare minimum for this is
+probably 100K or so, but the usage will vary as buffers are created.  With
+Jove, the file itself takes up space only in the tempfile and its cache, but
+the buffer structure requires 3 pointers (12 bytes) for each line in the
+file. For a reasonable editing session with files totalling, say 10000 to
+20000 lines, this additional space can add up. For this reason, it is
+unrealistic to expect to run Jove on a 512K system, unless a very small
+system file is used, few, small files are edited each session, and the
+tempfile cache is reduced (see cache size under Making Jove). You can
+experiment with various memory allocations under Switcher and Multifinder to
+see what works with your editing habits (backup your files first!), but a
+realistic minimum is 400K - 500K and more is great.
+
+When first using MacJove, and if memory space is questionable, SAVE YOUR
+FILES FREQUENTLY. If it is necessary to edit many files, it is often better
+to exit MacJove and restart once in a while, especially if there is a
+question of limited memory.
+
+Operation
+
+
+Running MacJove is similar to other Macintosh applications, and should be
+intuitive. You start up MacJove by either opening, or double-clicking,
+the MacJove icon. If you have previously saved files created with MacJove,
+double-clicking on them will also start up the program, and the files will
+be put into buffers. Several files can be selected simultaneously by this
+method. There is no current way to select command-line options with
+MacJove, but this may change in the future.
+
+The .joverc file, if used, must be present in the same directory as MacJove,
+the "home" directory. The help file, "cmds.doc", must also be in this
+directory. The tempfile, ".joveXXX", will be placed in whatever directory is
+current when the tempfile is first opened - this may or may not be the home
+directory, and may change in the future. The recover file, ".jrecXXX" is
+placed in the home directory. While this file is created and updated as on
+Unix versions of Jove, there is currently no "recover" program for MacJove.
+Hopefully, this will be available soon.
+
+MacJove can edit any text file on the Macintosh, whether created with
+MacJove or another editor. It cannot be used to edit graphics material, and
+graphics material cannot be inserted during operation of MacJove. Files
+created with MacJove are of type 'TEXT' and of signature 'JV01'. This
+signature is being registered with Apple, and may change if necessary. Note
+that once MacJove files have been re-edited with another editor, they likely
+will have new signatures, and double-clicking on them will start the other
+editor, not MacJove.
+
+The standard Macintosh keyboard is inadequate for MacJove (and most anything
+else), so that it is necessary to change a couple of keys. The "`" key
+becomes the ESCAPE key, since it is in the right place for one: to send a
+real "'", hold the command key down while typing it. The command key is used
+for a control key - unfortunately, the location of it is horrible for such a
+purpose. On Macintosh SE and Macintosh II models, a real escape key exists,
+and also a real control key. Note, however, that because of a small bug in
+the keyboard encoding in MacJove, you cannot directly send a NUL (control-@)
+with the control key. Typing command-@ or command-2 will still do this,
+however.
+
+During operation, you can use the keyboard as you would when running Jove on
+any other system. However, many commands also have menu equivalents:  as
+long as MacJove is waiting for a command, you can use either the keyboard or
+the menus. Once you begin selecting a command with either the menus or the
+keyboard, the other is locked out: thus, once you type control-X, MacJove
+expects more characters, and will not let you choose menu items.  Also, if
+you are prompted for input on the command line, the menus are locked out.
+Regardless of how a command is begun, however, only the prompt line (message
+line) is used for input: MacJove does not use dialog boxes, except under the
+"About Jove" menu selection.
+
+Commands listed in the menus are given exactly as their string name in
+the command list, for example "write-file". In addition, variables are
+listed under the "Set" menu. Variables are grouped by type. Non-boolean
+variables are changed on the message line after being selected. Boolean
+variables are marked with a check mark if on, and selecting them toggles
+the value of the variable.
+
+The "Buffer" menu is a special menu, whose action is different than the
+others. The first entries on this menu are the major and minor modes of
+operation, with those of the current buffer marked with check marks.
+Clicking on a major mode will change the major mode of the current buffer to
+that mode, while clicking on a minor mode will toggle that mode's status
+(on/off) for the current buffer. Beneath this is a list of buffers, one for
+each menu item, with the current buffer marked. Clicking on a buffer selects
+that as the current buffer, and the active window will change accordingly.
+
+Window controls (scroll bars) work as expected, and are simply bound to
+the appropriate MacJove command. Occassionally the position of the
+scroll bar may appear inaccurate, particularly with a small buffer.
+
+Files and directories may be selected in two ways. The default method
+is to use the message line to input filenames, and to change directories
+using "cd". If the variable "macify" is set, however, filenames and
+directories can also be set using the standard file dialogs familiar to
+most Mac users. Filename paths are normally given via Unix conventions,
+and not Macintosh conventions: i.e. directories are separated with "/"
+and not ":". On the Buffer menu, however, filenames are listed with ":"
+as the separation character, since "/" cannot be displayed in menu items.
+It is not possible to back up directories beyond the volume level, so
+there is not true "root". To change volumes (disks), macify must be on,
+and the "Drive" selection used.
+
+"Macify" only works for those commands which REQUIRE a file operation, such
+as "visit-file", "insert-file", "write-file".  Operations which first look
+in buffers for files, such as "window-find" and "find-file" never use the
+standard file dialogs.
+
+For a list of all commands and bindings, click on "About Jove" in the
+Apple menu. In the future this may also support the help file.
+
+                      Making MacJove
+
+System Requirements
+
+To make MacJove from the sources, you need a hard disk based Macintosh, at
+least 1 mb of ram, and the LightspeedC compiler, version 2.13 or later.
+Earlier versions may work but have not been used recently. Allow for the
+MacJove files to take up to 1.5 mb of your hard disk. You will need a copy
+of the "BinHex" utility, also.
+
+Since LightspeedC does not work with a Makefile, none is supplied. In
+general, the compiler itself will figure out dependencies for you, within a
+"project". Since there are three separate projects to MacJove, you will
+still have to keep track of some changes, particularly for the setmaps
+project. Also, since LightspeedC only knows of .c and .h dependencies,
+you will have to keep track of setmaps.txt and menumaps.txt yourself.
+
+Preliminary Steps
+
+0) CREATE A FOLDER (DIRECTORY) FOR JOVE. If I have to tell you how to do
+that, don't go any further! Copy the source files - a few aren't needed
+by MacJove, but copy them anyway, so you'll have them in one place. You
+do not need anything in the "doc" subdirectory to create MacJove (but
+you will eventually need cmds.doc, the help file, if you want the
+"describe-command" command to work).
+
+1) CREATE THE RESOURCE FILE: There is only one eight-bit file supplied,
+"mjove.rsrc". This is a small file which contains the program icon and a
+dialog template. This file must have the same name as the MacJove project,
+plus extension ".rsrc". The MacJove project (below), has name "mjove", so
+this file is "mjove.rsrc".  IF YOU RENAME THE PROJECT YOU MUST RENAME THIS
+FILE, ALSO. Using "BinHex", unload the file "mjovers.Hqx" --> "mjove.rsrc".
+
+2) CREATE THE "MJOVELIB" PROJECT: MacJove does not use many of the library
+functions. Despite what the LightspeedC manual states, projects are loaded
+as a whole: since we need only a few functions, we will build a "library" of
+them in the form of a project. Run LightspeedC and create a new project,
+and name it "mjovelib". Add the following files, from the Library Sources,
+to the project. They all go in the same segment:
+
+     onexit.c
+     qsort.c
+     stddata_ctype.c
+     unixexit.c
+     unixid.c
+     unixmem.c
+     unixtime.c
+
+3) EXAMINE THE FILE UNIXTIME.C and make the following correction, if
+necessary. The LightspeedC library function "unixtime.c" returns a string
+containing the time for what is supposed to be Greenwich Mean Time, instead
+of local time. Using the LightspeedC editor, and with the project open,
+examine the file, comment out the definition of "GMTzonedif", and add:
+
+     #define GMTzonedif 0
+
+4) MAKE THE "MJOVELIB" PROJECT. Keeping the edited "unixtime.c" open,
+run "make" on the project - everything will be compiled, with the altered
+version of "unixtime.c". You do not have to permanently save the change
+to unixtime.c, but if you do not, the next time you run "make" on the
+project, it will tell you that it needs recompiling - simply ignore it.
+After the mjovelib project is made, close it. You do not have to convert it
+to a library - it is okay to leave it as a project.
+
+6) CREATE THE "MSETMAPS" PROJECT. Create a new project, name it "msetmaps",
+and add the following files to it:
+
+     setmaps.c
+     stdio
+     strings           (segment 1)
+     unix
+     unix main.c
+     --------
+     MacTraps          (segment 2)
+
+7) EDIT THE FILE "TUNE.H". The only thing you should have to do with this
+file is to make certain that MAC is defined. Uncomment the following line,
+near the beginning of the file
+
+Change:
+
+  /*#define MAC 1                /* alas, there is no command line for this */
+
+to:
+
+  #define MAC 1                /* alas, there is no command line for this */
+
+You should not change anything else at this point - unless you want to
+reduce memory requirements (see "Running MacJove", above). If it is
+necessary to reduce the memory requirements, then reduce the number of cache
+buffers, NBUF, which is defined near the end of the file (each buffer takes
+up 1K of space while MacJove is running).
+
+     #ifdef MAC
+     #  undef F_COMPLETION        /* can't do it with spaces in filenames */
+     #  undef CHDIR
+     #  define CHDIR 1
+     #  define rindex strrchr
+     #  define index strchr
+     #  define bzero(s,n) setmem(s,n,0)
+     #  define LINT_ARGS
+     #  define NBUF 64 <----------reduce this if necessary.
+     #  define BUFSIZ 1024
+     #endif
+
+8) MAKE THE "MSETMAPS" PROJECT. Then choose "Build Application",and name it
+"setmaps". 
+
+9) RUN "SETMAPS" ON THE KEYMAPS.TXT FILE. You can either run "setmaps" from
+LightspeedC, before closing the project, or as the standalone application.
+When prompted for the "Unix command line", enter:
+
+     < keymaps.txt > keymaps.c
+
+You will get a few messages from setmaps that it can't find certain
+commands. You can ignore these.
+
+10) RUN "SETMAPS" ON THE MENUMAPS.TXT FILE. Just as before, run "setmaps"
+and enter the following command line:
+
+     < menumaps.txt > menumaps.c
+
+You should not get any messages from setmaps. If the "msetmaps" project is
+still open, close it.
+
+11) CREATE THE "MJOVE" PROJECT. Create a new project, name it "MJOVE" and
+set the Creator (signature) to 'JV01'. Add the following files in the
+following segments:
+
+     abbrev.c
+     argcount.c
+     ask.c
+     buf.c
+     c.c
+     case.c        (segment 1)
+     ctype.c
+     delete.c
+     disp.c
+     extend.c
+     --------
+     fmt.c
+     fp.c
+     funcdefs.c    (segment 2)
+     insert.c
+     io.c
+     jove.c
+     keymaps.c
+     --------
+     mac.c
+     macros.c
+     marks.c
+     menumaps.c    (segment 3)
+     misc.c
+     move.c
+     paragraph.c
+     --------
+     re.c
+     re1.c
+     rec.c
+     screen.c
+     table.c       (segment 4)
+     term.c
+     util.c
+     vars.c
+     version.c
+     wind.c
+     --------
+     MacTraps
+     mjovelib
+     setjmp.Lib    (segment 5)
+     storage
+     strings
+
+12) MAKE THE MJOVE PROJECT. If you experience any errors, it will most
+likely be from #include files not being in the default path - see the
+LightspeedC manual on setting up your directories. When you are done,
+run the program from the compiler to verify that it is okay, then save it as
+"MacJove" using the "Build Application" command.
+
+13) (Optional) CREATE THE HELP FILE, "CMDS.DOC". If you do not have a copy
+of "cmds.doc", it must be created using nroff. Assuming you have the Jove
+sources on a Unix machine, run "Make doc/cmds.doc" to create this file in
+the "doc" subdirectory, then move the file to the Mac. If you obtained the
+sources from a non-Unix source, this file may already be supplied. Place the
+file in the same directory that MacJove will be in.
+
+                      COMMENTS AND QUESTIONS, BUGS
+
+This is the first version of MacJove to receive widespread use, and problems
+are anticipated. All comments and suggestions are appreciated. Before asking
+for help in making MacJove, make sure you understand the above directions,
+have followed them closely, and have a good copy of the sources. I will try
+to reply to everyone, but have a busy schedule, and cannot guarantee any
+time frame of response. I can promise you, however, that questions received
+via the net or mail will be answered more promptly than those from via US
+Mail. PLEASE DO NOT SEND ME DISKS!
+
+
+    Ken Mitchum
+    Decision Systems Laboratory
+    University of Pittsburgh
+    1360 Scaife Hall
+    Pittsburgh, Pa. 15261
+
+    (km@cadre.dsl.pittsburgh.edu)
+
diff --git a/usr/src/new/jove/abbrev.c b/usr/src/new/jove/abbrev.c
new file mode 100644 (file)
index 0000000..564dee5
--- /dev/null
@@ -0,0 +1,331 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+#include "jove.h"
+
+#ifdef ABBREV
+
+#include "io.h"
+#include "ctype.h"
+
+#ifdef MSDOS
+#include <io.h>
+#endif
+#define HASHSIZE       20
+
+struct abbrev {
+       unsigned int    a_hash;
+       char    *a_abbrev,
+               *a_phrase;
+       struct abbrev   *a_next;
+       data_obj        *a_cmdhook;
+};
+
+#ifdef MAC
+#      undef private
+#      define private
+#endif
+
+#ifdef LINT_ARGS
+private        void
+       define(struct abbrev **, char *, char *),
+       def_abbrev(struct abbrev **),
+       rest_abbrevs(char *),
+       save_abbrevs(char *);
+
+private        unsigned int hash(char *);
+private        struct abbrev * lookup(struct abbrev **, char *);
+#else
+private        void
+       define(),
+       def_abbrev(),
+       rest_abbrevs(),
+       save_abbrevs();
+
+private        unsigned int hash();
+private        struct abbrev * lookup();
+#endif /* LINT_ARGS */
+
+#ifdef MAC
+#      undef private
+#      define private static
+#endif
+
+#define GLOBAL NMAJORS
+private struct abbrev  *A_tables[NMAJORS + 1][HASHSIZE] = {0};
+
+int AutoCaseAbbrev = 1;
+
+private unsigned int
+hash(a)
+register char  *a;
+{
+       register unsigned int   hashval = 0;
+       register int    c;
+
+       while (c = *a++)
+               hashval = (hashval << 2) + c;
+
+       return hashval;
+}
+
+private void
+def_abbrev(table)
+struct abbrev  *table[HASHSIZE];
+{
+       char    abbrev[100],
+               phrase[100];
+
+       strcpy(abbrev, ask((char *) 0, "abbrev: "));
+       strcpy(phrase, ask((char *) 0, "abbrev: %s phrase: ", abbrev));
+       define(table, abbrev, phrase);
+}
+
+private struct abbrev *
+lookup(table, abbrev)
+register struct abbrev *table[HASHSIZE];
+register char  *abbrev;
+{
+       register struct abbrev  *ap;
+       unsigned int    h;
+
+       h = hash(abbrev);
+       for (ap = table[h % HASHSIZE]; ap; ap = ap->a_next)
+               if (ap->a_hash == h && strcmp(ap->a_abbrev, abbrev) == 0)
+                       break;
+       return ap;
+}
+
+private void
+define(table, abbrev, phrase)
+register struct abbrev *table[HASHSIZE];
+char   *abbrev,
+       *phrase;
+{
+       register struct abbrev  *ap;
+
+       ap = lookup(table, abbrev);
+       if (ap == 0) {
+               register unsigned int   h = hash(abbrev);
+
+               ap = (struct abbrev *) emalloc(sizeof *ap);
+               ap->a_hash = h;
+               ap->a_abbrev = copystr(abbrev);
+               h %= HASHSIZE;
+               ap->a_next = table[h];
+               ap->a_cmdhook = 0;
+               table[h] = ap;
+       } else
+               free(ap->a_phrase);
+       ap->a_phrase = copystr(phrase);
+}
+
+void
+AbbrevExpand()
+{
+       Bufpos  point;
+       char    wordbuf[100];
+       register char   *wp = wordbuf,
+                       *cp;
+#if !(defined(IBMPC) || defined(MAC))
+       register int    c;
+#else
+       int c;
+#endif 
+       int     UC_count = 0;
+       struct abbrev   *ap;
+
+       DOTsave(&point);
+    WITH_TABLE(curbuf->b_major)
+       b_word(1);
+       while (curchar < point.p_char && ismword(c = linebuf[curchar])) {
+               if (AutoCaseAbbrev) {
+                       if (isupper(c)) {
+                               UC_count += 1;
+#if (defined(IBMPC) || defined(MAC))
+                               lower(&c);
+#else
+                               c = tolower(c);
+#endif                         
+                       }
+               }
+               *wp++ = c;
+               curchar += 1;
+       }
+       *wp = '\0';
+    END_TABLE();
+
+       if ((ap = lookup(A_tables[curbuf->b_major], wordbuf)) == 0 &&
+           (ap = lookup(A_tables[GLOBAL], wordbuf)) == 0) {
+               SetDot(&point);
+               return;
+       }
+       del_char(BACKWARD, (wp - wordbuf));
+
+       for (cp = ap->a_phrase; c = *cp; ) {
+               if (AutoCaseAbbrev) {
+                       insert_c(islower(c) && UC_count &&
+                              (cp == ap->a_phrase || (UC_count > 1 && (cp[-1] == ' '))) ?
+                               toupper(c) : c, 1);
+               } else
+                       insert_c(c, 1);
+               cp += 1;
+       }
+       if (ap->a_cmdhook != 0)
+               ExecCmd(ap->a_cmdhook);
+}
+
+private char   *mode_names[NMAJORS + 1] = {
+       "Fundamental Mode",
+       "Text Mode",
+       "C Mode",
+#ifdef LISP
+       "Lisp Mode",
+#endif
+       "Global"
+};
+
+private void
+save_abbrevs(file)
+char   *file;
+{
+       File    *fp;
+       struct abbrev   *ap,
+                       **tp;
+       char    buf[LBSIZE];
+       int     i,
+               count = 0;
+
+       fp = open_file(file, buf, F_WRITE, COMPLAIN, QUIET);
+       for (i = 0; i <= GLOBAL; i++) {
+               fprintf(fp, "------%s abbrevs------\n", mode_names[i]);
+               for (tp = A_tables[i]; tp < &A_tables[i][HASHSIZE]; tp++)
+                       for (ap = *tp; ap; ap = ap->a_next) {
+                               fprintf(fp, "%s:%s\n",
+                                       ap->a_abbrev,
+                                       ap->a_phrase);
+                               count += 1;
+                       }
+       }
+       f_close(fp);
+       add_mess(" %d written.", count);
+}
+
+private void
+rest_abbrevs(file)
+char   *file;
+{
+       int     eof = 0,
+               mode = -1,      /* Will be ++'d immediately */
+               lnum = 0;
+       char    *phrase_p;
+       File    *fp;
+       char    buf[LBSIZE];
+
+       fp = open_file(file, buf, F_READ, COMPLAIN, QUIET);
+       while (mode <= GLOBAL) {
+               eof = f_gets(fp, genbuf, LBSIZE);
+               if (eof || genbuf[0] == '\0')
+                       break;
+               lnum += 1;
+               if (strncmp(genbuf, "------", 6) == 0) {
+                       mode += 1;
+                       continue;
+               }
+               if (mode == -1)
+fmterr:                        complain("Abbrev. format error, line %d.", file, lnum);
+               phrase_p = index(genbuf, ':');
+               if (phrase_p == 0)
+                       goto fmterr;
+               *phrase_p++ = '\0';     /* Null terminate the abbrev. */
+               define(A_tables[mode], genbuf, phrase_p);
+       }
+       f_close(fp);
+       message(NullStr);
+}
+
+void
+DefGAbbrev()
+{
+       def_abbrev(A_tables[GLOBAL]);
+}
+
+void
+DefMAbbrev()
+{
+       def_abbrev(A_tables[curbuf->b_major]);
+}
+
+void
+SaveAbbrevs()
+{
+       char    filebuf[FILESIZE];
+
+       save_abbrevs(ask_file((char *) 0, (char *) 0, filebuf));
+}
+
+void
+RestAbbrevs()
+{
+       char    filebuf[FILESIZE];
+
+       rest_abbrevs(ask_file((char *) 0, (char *) 0, filebuf));
+}
+
+void
+EditAbbrevs()
+{
+       char    *tname = "jove_wam.$$$",
+               *EditName = "Abbreviation Edit";
+       Buffer  *obuf = curbuf,
+               *ebuf;
+
+       if (ebuf = buf_exists(EditName)) {
+               if (ebuf->b_type != B_SCRATCH)
+                       confirm("Over-write buffer %b?", ebuf);
+       }
+       SetBuf(ebuf = do_select(curwind, EditName));
+       ebuf->b_type = B_SCRATCH;
+       initlist(ebuf);
+       /* Empty buffer.  Save the definitions to a tmp file
+          and read them into this buffer so we can edit them. */
+       save_abbrevs(tname);
+       read_file(tname, NO);
+       message("[Edit definitions and then type C-X C-C]");
+       Recur();                /* We edit them ... now */
+       /* RESetBuf in case we deleted the buffer while we were editing. */
+       SetBuf(ebuf = do_select(curwind, EditName));
+       if (IsModified(ebuf)) {
+               SetBuf(ebuf);
+               file_write(tname, 0);
+               rest_abbrevs(tname);
+               unmodify();
+       }
+       (void) unlink(tname);
+       SetBuf(do_select(curwind, obuf->b_name));
+}
+
+void
+BindMtoW()
+{
+       struct abbrev   *ap;
+       char    *word;
+       data_obj        *hook;
+
+       word = ask((char *) 0, "Word: ");
+
+       if ((ap = lookup(A_tables[curbuf->b_major], word)) == 0 &&
+           (ap = lookup(A_tables[GLOBAL], word)) == 0)
+               complain("%s: unknown abbrev.", word);
+
+       hook = findmac("Macro: ");
+       if (hook == 0)
+               complain("[Undefined macro]");
+       ap->a_cmdhook = hook;
+}
+
+#endif /* ABBREV */
diff --git a/usr/src/new/jove/argcount.c b/usr/src/new/jove/argcount.c
new file mode 100644 (file)
index 0000000..ccf5383
--- /dev/null
@@ -0,0 +1,243 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+#include "jove.h"
+#include <ctype.h>
+
+#ifdef MAC
+#      undef private
+#      define private
+#endif
+
+#ifdef LINT_ARGS
+private        void
+       gather_numeric_argument(int),
+       quad_numeric_arg(void);
+#else
+private        void
+       gather_numeric_argument(),
+       quad_numeric_arg();
+#endif
+
+#ifdef MAC
+#      undef private
+#      define private static
+#endif
+
+private int    arg_supplied_p,
+               arg_count;
+
+int
+arg_type()
+{
+       return arg_supplied_p;
+}
+
+void
+set_is_an_arg(there_is)
+{
+       arg_supplied_p = there_is;
+}
+
+void
+set_arg_value(n)
+{
+       arg_supplied_p = YES;
+       arg_count = n;
+}
+
+void
+negate_arg_value()
+{
+       arg_count = -arg_count;
+}
+
+void
+clr_arg_value()
+{
+       arg_supplied_p = NO;
+       arg_count = 1;
+}
+
+/* return whether there is currently a numeric argument */
+
+int
+is_an_arg()
+{
+       return (arg_supplied_p != NO);
+}
+
+/* return the numeric argument */
+
+int
+arg_value()
+{
+       return arg_count;
+}
+
+/* called by C-U to gather a numeric argument, either C-U's or digits,
+   but not both */
+
+void
+TimesFour()
+{
+       quad_numeric_arg();
+}
+
+/* This initializes the numeric argument to 1 and starts multiplying
+   by 4 (the magic number Stallman came up with).  It is an error to
+   invoke quad_numeric_arg() interactively (via TimesFour()), because
+   it uses the LastKeyStruck variable to know what character signals
+   to multiply again (in the loop). */
+private void
+quad_numeric_arg()
+{
+       int     oldc = LastKeyStruck,
+               newc,
+               narg_count,
+               slow;
+
+       slow = 0;
+       arg_supplied_p = YES;
+       arg_count = 1;
+       this_cmd = ARG_CMD;
+       do {
+               if ((narg_count = arg_count * 4) != 0)
+                       arg_count = narg_count;
+               if (!slow)
+                       newc = waitchar(&slow);
+               else
+                       newc = getch();
+               if (isdigit(newc) || newc == '-') {
+                    arg_supplied_p = NO;
+                    gather_numeric_argument(newc);
+                    return;
+               }
+               if (slow)
+                       message(key_strokes);
+       } while (newc == oldc);
+       Ungetc(newc);
+}
+
+private void
+gather_numeric_argument(c)
+{
+       int     sign = 0;
+       static int      digited;
+       int     slow = 0;
+
+       if (!isdigit(c) && c != '-')
+               complain((char *) 0);
+       if (arg_supplied_p == NO) {     /* if we just got here */
+               arg_count = 0;  /* start over */
+               digited = NO;
+       } else if (arg_supplied_p == YES_NODIGIT) {
+               sign = (arg_count < 0) ? -1 : 1;
+               arg_count = 0;
+       }
+
+       if (!sign)
+               sign = (arg_count < 0) ? -1 : 1;
+       if (sign == -1)
+               arg_count = -arg_count;
+       if (c == '-') {
+               sign = -sign;
+               goto goread;
+       }
+       for (;;) {
+               if (slow)
+                       message(key_strokes);
+               if (isdigit(c)) {
+                       arg_count = (arg_count * 10) + (c - '0');
+                       digited = YES;
+               } else {
+                       if (digited)
+                               arg_supplied_p = YES;
+                       else {
+                               arg_count = 1;
+                               if (arg_supplied_p == NO)
+                                       arg_supplied_p = YES_NODIGIT;
+                       }
+                       arg_count *= sign;
+                       this_cmd = ARG_CMD;
+                       Ungetc(c);
+                       return;
+               }
+goread:                if (!slow)
+                       c = waitchar(&slow);
+               else {
+                       add_mess(NullStr);
+                       c = getch();
+               }
+       }
+}
+
+void
+Digit()
+{
+       gather_numeric_argument(LastKeyStruck);
+}
+
+void
+Digit0()
+{
+       gather_numeric_argument('0');
+}
+
+void
+Digit1()
+{
+       gather_numeric_argument('1');
+}
+
+void
+Digit2()
+{
+       gather_numeric_argument('2');
+}
+
+void
+Digit3()
+{
+       gather_numeric_argument('3');
+}
+
+void
+Digit4()
+{
+       gather_numeric_argument('4');
+}
+
+void
+Digit5()
+{
+       gather_numeric_argument('5');
+}
+
+void
+Digit6()
+{
+       gather_numeric_argument('6');
+}
+
+void
+Digit7()
+{
+       gather_numeric_argument('7');
+}
+
+void
+Digit8()
+{
+       gather_numeric_argument('8');
+}
+
+void
+Digit9()
+{
+       gather_numeric_argument('9');
+}
diff --git a/usr/src/new/jove/case.c b/usr/src/new/jove/case.c
new file mode 100644 (file)
index 0000000..ba26bb4
--- /dev/null
@@ -0,0 +1,228 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+#include "jove.h"
+#include "ctype.h"
+
+#ifdef MAC
+#      undef private
+#      define private
+#endif
+
+#ifdef LINT_ARGS
+private        int
+#if !(defined(IBMPC) || defined(MAC))
+       lower(char *),
+#endif
+       upper(char *);
+#else
+private        int
+#if !(defined(IBMPC) || defined(MAC))
+       lower(),
+#endif
+       upper();
+#endif /* LINT_ARGS */
+
+#ifdef MAC
+#      undef private
+#      define private static
+#endif
+
+void
+CapChar()
+{
+       register int    num,
+                       restore = NO;
+       Bufpos  b;
+
+       DOTsave(&b);
+
+       num = arg_value();
+       if (num < 0) {
+               restore = YES;
+               num = -num;
+               b_char(num);    /* Cap previous EXP chars */
+       }
+       while (num--) {
+               if (upper(&linebuf[curchar])) {
+                       modify();
+                       makedirty(curline);
+               }
+               if (eolp()) {
+                       if (curline->l_next == 0)
+                               break;
+                       SetLine(curline->l_next);
+               } else
+                       curchar += 1;
+       }
+       if (restore)
+               SetDot(&b);
+}
+
+void
+CapWord()
+{
+       register int    num,
+                       restore = NO;
+       Bufpos  b;
+
+       DOTsave(&b);
+       num = arg_value();
+       if (num < 0) {
+               restore = YES;
+               num = -num;
+               b_word(num);            /* Cap previous EXP words */
+       }
+       while (num--) {
+               to_word(1);     /* Go to the beginning of the next word. */
+               if (eobp())
+                       break;
+               if (upper(&linebuf[curchar])) {
+                       modify();
+                       makedirty(curline);
+               }
+               curchar += 1;
+               while (!eolp() && isword(linebuf[curchar])) {
+                       if (lower(&linebuf[curchar])) {
+                               modify();
+                               makedirty(curline);
+                       }
+                       curchar += 1;
+               }
+       }
+       if (restore)
+               SetDot(&b);
+}
+
+void
+case_word(up)
+{
+       Bufpos  before;
+
+       DOTsave(&before);
+       ForWord();      /* this'll go backward if negative argument */
+       case_reg(before.p_line, before.p_char, curline, curchar, up);
+}
+
+private int
+upper(c)
+register char  *c;
+{
+       if (islower(*c)) {
+#ifndef ASCII                  /* check for IBM extended character set */
+               if (*c <= 127)
+#endif /* ASCII */
+               *c -= ' ';
+#ifdef IBMPC                   /* ... and change Umlaute       */
+               else 
+                  switch (*c) {
+                    case 129: *c = 154; break;         /* ue */
+                    case 132: *c = 142; break;         /* ae */
+                    case 148: *c = 153; break;         /* oe */
+                  }
+#endif /* IBMPC */
+#ifdef MAC
+               else *c = CaseEquiv[*c];
+#endif
+               return 1;
+       }
+       return 0;
+}
+
+#if !(defined(IBMPC) || defined(MAC))
+private
+#endif
+int
+lower(c)
+char   *c;
+{
+       if (isupper(*c)) {
+#ifndef ASCII
+               if (*c <= 127) 
+#endif /* ASCII */
+               *c += ' ';
+#ifdef IBMPC
+               else
+                  switch (*c) {
+                    case 142: *c = 132; break;         /* Ae */
+                    case 153: *c = 148; break;         /* Oe */
+                    case 154: *c = 129; break;         /* Ue */
+                  }
+#endif /* IBMPC */
+#ifdef MAC
+               else {
+                       int n;
+                       
+                       for(n = 128; n < 256; n++) {
+                               if((CaseEquiv[n] == *c) && islower(n)) {
+                                       *c = n;
+                                       break;
+                               }
+                       }
+                       if(n > 255) return(0);
+               }
+#endif /* MAC */               
+               return 1;
+       }
+       return 0;
+}
+
+void
+case_reg(line1, char1, line2, char2, up)
+Line   *line1,
+       *line2;
+int    char1;
+{
+       (void) fixorder(&line1, &char1, &line2, &char2);
+       DotTo(line1, char1);
+
+       for (;;) {
+               if (curline == line2 && curchar == char2)
+                       break;
+               if (!eolp())
+                       if ((up) ? upper(&linebuf[curchar]) : lower(&linebuf[curchar])) {
+                               makedirty(curline);
+                               modify();
+                       }
+               f_char(1);
+       }
+}
+
+void
+CasRegLower()
+{
+       CaseReg(0);
+}
+
+void
+CasRegUpper()
+{
+       CaseReg(1);
+}
+
+void
+CaseReg(up)
+{
+       register Mark   *mp = CurMark();
+       Bufpos  savedot;
+
+       DOTsave(&savedot);
+       case_reg(curline, curchar, mp->m_line, mp->m_char, up);
+       SetDot(&savedot);
+}
+
+void
+UppWord()
+{
+       case_word(1);
+}
+
+void
+LowWord()
+{
+       case_word(0);
+}
diff --git a/usr/src/new/jove/ctype.h b/usr/src/new/jove/ctype.h
new file mode 100644 (file)
index 0000000..8104063
--- /dev/null
@@ -0,0 +1,51 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+/* The code in this file was snarfed from ctype.h and modified for JOVE. */
+
+#define        _U      01
+#define        _L      02
+#define        _N      04
+#define _P     010
+#define _C     020
+#define _W     040
+#define _Op    0100
+#define _Cl    0200
+
+extern int     SyntaxTable;
+#define iswhite(c)     (isspace(c))
+#define isword(c)      ((CharTable[SyntaxTable])[c]&(_W))
+#define        isalpha(c)      ((CharTable[SyntaxTable])[c]&(_U|_L))
+#define        isupper(c)      ((CharTable[SyntaxTable])[c]&_U)
+#define        islower(c)      ((CharTable[SyntaxTable])[c]&_L)
+#define        isdigit(c)      ((CharTable[SyntaxTable])[c]&_N)
+#define        isspace(c)      (c == ' ' || c == '\t')
+#define ispunct(c)     ((CharTable[SyntaxTable])[c]&_P)
+
+
+#define toascii(c)     ((c)&CHARMASK)
+#define isctrl(c)      ((CharTable[0][c&CHARMASK])&_C)
+#define isopenp(c)     ((CharTable[0][c&CHARMASK])&_Op)
+#define isclosep(c)    ((CharTable[0][c&CHARMASK])&_Cl)
+#define has_syntax(c,s)        ((CharTable[SyntaxTable][c&CHARMASK])&s)
+
+#ifdef ASCII
+#define toupper(c)     ((c)&~040)
+#define tolower(c)     ((c)|040)
+#else /* IBMPC or MAC */
+#define toupper(c)     (CaseEquiv[c])
+/* #define tolower(c)  ((c)|040)       */
+#endif /* IBMPC */
+
+#define WITH_TABLE(x) \
+{ \
+       int     push = SyntaxTable; \
+       SyntaxTable = x;
+
+#define END_TABLE() \
+       SyntaxTable = push; \
+}
diff --git a/usr/src/new/jove/fmt.c b/usr/src/new/jove/fmt.c
new file mode 100644 (file)
index 0000000..f7b9422
--- /dev/null
@@ -0,0 +1,439 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+#include "jove.h"
+#include "io.h"
+#include "termcap.h"
+
+#ifdef MAC
+#      include  "mac.h"
+#else
+#      include <varargs.h>
+#endif
+
+#ifdef MAC
+#      undef private
+#      define private
+#endif
+
+#ifdef LINT_ARGS
+private void
+       doformat(File *, char *, ...),
+       outld(long, int),
+       pad(int, int),
+       PPchar(int, char *),
+       putld(long, int),
+       puts(char *);
+#else
+private void
+       doformat(),
+       outld(),
+       pad(),
+       PPchar(),
+       putld(),
+       puts();
+#endif /* LINT_ARGS */
+
+#ifdef MAC
+#      undef private
+#      define private static
+#endif
+
+
+char   mesgbuf[MESG_SIZE];
+
+/* VARARGS2 */
+
+void
+format(buf, len, fmt, ap)
+char   *buf,
+       *fmt;
+va_list        ap;
+{
+       File    strbuf,
+               *sp = &strbuf;
+
+       sp->f_ptr = sp->f_base = buf;
+       sp->f_fd = -1;          /* Not legit for files */
+       sp->f_cnt = len;
+       sp->f_flags = F_STRING;
+       sp->f_bufsize = len;
+
+       doformat(sp, fmt, ap);
+       putc('\0', sp);
+}
+
+#ifdef IBMPC
+int    specialmap = 0,
+       specialkey = 0;
+
+#define Empty ""
+
+char *altseq[133] = {
+Empty, Empty, Empty, "Ctrl-@", Empty, Empty, Empty, Empty,
+Empty, Empty, Empty, Empty, Empty, Empty, Empty, "Left", 
+"Alt-Q", "Alt-W", "Alt-E", "Alt-R", "Alt-T", "Alt-Y", "Alt-U", "Alt-I",
+"Alt-O", "Alt-P", Empty, Empty, Empty, Empty, "Alt-A", "Alt-S",
+"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",
+"Alt-B", "Alt-N", "Alt-M", Empty, Empty, Empty, Empty, Empty,
+Empty, Empty, Empty, "F1", "F2", "F3", "F4", "F5", 
+"F6", "F7", "F8", "F9", "F10", Empty, Empty, "Home",
+"Up", "PageUp", Empty, "Left", Empty, "Right", Empty, "End",
+"Down", "PageDown", "Ins", "Del", "Shift F1", "Shift F2", "Shift F3", "Shift F4", 
+"Shift F5", "Shift F6", "Shift F7", "Shift F8", "Shift F9", "Shift F10", "Ctrl F1", "Ctrl F2",
+"Ctrl F3", "Ctrl F4", "Ctrl F5", "Ctrl F6", "Ctrl F7", "Ctrl F8", "Ctrl F9", "Ctrl F10", 
+"Alt F1", "Alt F2", "Alt F3", "Alt F4", "Alt F5", "Alt F6", "Alt F7", "Alt F8",
+"Alt F9", "Alt F10", "Ctrl PrtSc", "Ctrl Left", "Ctrl Right", "Ctrl End", "Ctrl PageDown", "Ctrl Home",
+"Alt 1", "Alt 2", "Alt 3", "Alt 4", "Alt 5", "Alt 6", "Alt 7", "Alt 8",
+"Alt 9", "Alt 0", "Alt Minus", "Alt Equals", "Ctrl PageUp" 
+};
+#endif
+
+
+private void
+PPchar(c, str)
+int    c;
+char   *str;
+{
+       char    *cp = str;
+
+#ifdef IBMPC
+       if (specialmap || specialkey) {
+               if (c < 0 || c > 132)
+                       c = 0;
+               strcpy(cp, altseq[c]);
+       } else
+#endif 
+       if (c == '\033')
+               strcpy(cp, "ESC");
+#ifdef IBMPC                           /* this character is invisible */
+       else if (c == '\377') {
+                       *cp = 0;
+       }
+#endif /* IBMPC */
+       else if (c < ' ')
+               sprintf(cp, "C-%c", c + '@');
+       else if (c == '\177')
+               strcpy(cp, "^?");
+       else
+               sprintf(cp, "%c", c);
+}
+
+private struct fmt_state {
+       int     precision,
+               width,
+               leftadj;
+       char    padc;
+       File    *iop;
+} current_fmt;
+
+private void
+putld(d, base)
+long   d;
+{
+       int     length = 1;
+       long    tmpd = d;
+
+       if (current_fmt.width == 0 && current_fmt.precision) {
+               current_fmt.width = current_fmt.precision;
+               current_fmt.padc = '0';
+       }
+       while (tmpd = (tmpd / base))
+               length += 1;
+       if (d < 0)
+               length += 1;
+       if (!current_fmt.leftadj)
+               pad(current_fmt.padc, current_fmt.width - length);
+       if (d < 0) {
+               putc('-', current_fmt.iop);
+               d = -d;
+       }
+       outld(d, base);
+       if (current_fmt.leftadj)
+               pad(current_fmt.padc, current_fmt.width - length);
+}
+
+private void
+outld(d, base)
+long   d;
+{
+       register long   n;
+       static char     chars[] = {'0', '1', '2', '3', '4', '5', '6',
+                                   '7', '8', '9', 'a', 'b', 'c', 'd',
+                                   'e', 'f'};
+
+       if (n = (d / base))
+               outld(n, base);
+       putc((int) (chars[(int) (d % base)]), current_fmt.iop);
+}
+
+private void
+puts(str)
+char   *str;
+{
+       int     length;
+       register char   *cp;
+
+       if (str == 0)
+#if pyr
+               str = "";
+#else
+               str = "(null)";
+#endif
+       length = strlen(str);
+       if (current_fmt.precision == 0 || length < current_fmt.precision)
+               current_fmt.precision = length;
+       else
+               length = current_fmt.precision;
+       cp = str;
+       if (!current_fmt.leftadj)
+               pad(' ', current_fmt.width - length);
+       while (--current_fmt.precision >= 0)
+               putc(*cp++, current_fmt.iop);
+       if (current_fmt.leftadj)
+               pad(' ', current_fmt.width - length);
+}
+
+private void
+pad(c, amount)
+register int   c,
+               amount;
+{
+       while (--amount >= 0)
+               putc(c, current_fmt.iop);
+}
+
+private void
+doformat(sp, fmt, ap)
+register File  *sp;
+register char  *fmt;
+va_list        ap;
+{
+       register char   c;
+       struct fmt_state        prev_fmt;
+
+       prev_fmt = current_fmt;
+       current_fmt.iop = sp;
+
+       while (c = *fmt++) {
+               if (c != '%') {
+                       putc(c, current_fmt.iop);
+                       continue;
+               }
+
+               current_fmt.padc = ' ';
+               current_fmt.precision = current_fmt.leftadj = current_fmt.width = 0;
+               c = *fmt++;
+               if (c == '-') {
+                       current_fmt.leftadj = YES;
+                       c = *fmt++;
+               }
+               if (c == '0') {
+                       current_fmt.padc = '0';
+                       c = *fmt++;
+               }
+               while (c >= '0' && c <= '9') {
+                       current_fmt.width = current_fmt.width * 10 + (c - '0');
+                       c = *fmt++;
+               }
+               if (c == '*') {
+                       current_fmt.width = va_arg(ap, int);
+                       c = *fmt++;
+               }
+               if (c == '.') {
+                       c = *fmt++;
+                       while (c >= '0' && c <= '9') {
+                               current_fmt.precision = current_fmt.precision * 10 + (c - '0');
+                               c = *fmt++;
+                       }
+                       if (c == '*') {
+                               current_fmt.precision = va_arg(ap, int);
+                               c = *fmt++;
+                       }
+               }
+       reswitch:
+               /* At this point, fmt points at one past the format letter. */
+               switch (c) {
+               case '%':
+                       putc('%', current_fmt.iop);
+                       break;
+       
+               case 'O':
+               case 'D':
+               case 'X':
+                       putld(va_arg(ap, long), (c == 'O') ? 8 :
+                                               (c == 'D') ? 10 : 16);
+                       break;
+       
+               case 'b':
+                   {
+                       Buffer  *b = va_arg(ap, Buffer *);
+
+                       puts(b->b_name);
+                       break;
+                   }
+
+               case 'c':
+                       putc(va_arg(ap, int), current_fmt.iop);
+                       break;
+       
+               case 'o':
+               case 'd':
+               case 'x':
+                       putld((long) va_arg(ap, int), (c == 'o') ? 8 :
+                                               (c == 'd') ? 10 : 16);
+                       break;
+       
+               case 'f':       /* current command name gets inserted here! */
+                       puts(LastCmd->Name);
+                       break;
+
+               case 'l':
+                       c = CharUpcase(*++fmt);
+                       goto reswitch;
+       
+               case 'n':
+                       if (va_arg(ap, int) != 1)
+                               puts("s");
+                       break;
+
+               case 'p':
+                   {
+                       char    cbuf[20];
+
+                       PPchar(va_arg(ap, int), cbuf);
+                       puts(cbuf);
+                       break;
+                   }
+
+               case 's':
+                       puts(va_arg(ap, char *));
+                       break;
+               
+               default:
+                       complain("Unknown format directive: \"%%%c\"", c);
+               }
+       }
+       current_fmt = prev_fmt;
+}
+
+/* VARARGS1 */
+
+char *
+sprint(fmt, va_alist)
+char   *fmt;
+va_dcl
+{
+       va_list ap;
+       static char     line[100];
+
+       va_start(ap);
+       format(line, sizeof line, fmt, ap);
+       va_end(ap);
+       return line;
+}
+
+/* VARARGS1 */
+
+void
+printf(fmt, va_alist)
+char   *fmt;
+va_dcl
+{
+       va_list ap;
+
+       va_start(ap);
+#ifndef IBMPC
+       doformat(stdout, fmt, ap);
+#else /* IBMPC */
+       write_em(sprint(fmt, ap));
+       /* doformat(stdout, fmt, ap); */
+#endif /* IBMPC */
+       va_end(ap);
+}
+
+/* VARARGS1 */
+
+void
+fprintf(fp, fmt, va_alist)
+File   *fp;
+char   *fmt;
+va_dcl
+{
+       va_list ap;
+
+       va_start(ap);
+       doformat(fp, fmt, ap);
+       va_end(ap);
+}
+
+/* VARARGS2 */
+
+void
+sprintf(str, fmt, va_alist)
+char   *str,
+       *fmt;
+va_dcl
+{
+       va_list ap;
+
+       va_start(ap);
+       format(str, 130, fmt, ap);
+       va_end(ap);
+}
+
+/* VARARGS1 */
+
+void
+s_mess(fmt, va_alist)
+char   *fmt;
+va_dcl
+{
+       va_list ap;
+
+       if (InJoverc)
+               return;
+       va_start(ap);
+       format(mesgbuf, sizeof mesgbuf, fmt, ap);
+       va_end(ap);
+       message(mesgbuf);
+}
+
+/* VARARGS1 */
+
+void
+f_mess(fmt, va_alist)
+char   *fmt;
+va_dcl
+{
+       va_list ap;
+
+       va_start(ap);
+       format(mesgbuf, sizeof mesgbuf, fmt, ap);
+       va_end(ap);
+       DrawMesg(NO);
+       UpdMesg = YES;  /* still needs updating (for convenience) */
+}
+
+/* VARARGS1 */
+
+void
+add_mess(fmt, va_alist)
+char   *fmt;
+va_dcl
+{
+       int     mesg_len = strlen(mesgbuf);
+       va_list ap;
+
+       if (InJoverc)
+               return;
+       va_start(ap);
+       format(&mesgbuf[mesg_len], (sizeof mesgbuf) - mesg_len, fmt, ap);
+       va_end(ap);
+       message(mesgbuf);
+}
diff --git a/usr/src/new/jove/fp.c b/usr/src/new/jove/fp.c
new file mode 100644 (file)
index 0000000..a269273
--- /dev/null
@@ -0,0 +1,438 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+#include "jove.h"
+#include "io.h"
+#include "ctype.h"
+#include "termcap.h"
+
+#ifdef MAC
+#      include "mac.h"
+#else
+#      include <sys/stat.h>
+#      ifndef MSDOS
+#              include <sys/file.h>
+#      else /* MSDOS */
+#              include <fcntl.h>
+#              include <io.h>
+#      endif /* MSDOS */
+#endif /* MAC */
+
+#include <errno.h>
+
+#ifdef MAC
+#      undef private
+#      define private
+#endif
+
+#ifdef LINT_ARGS
+private File * f_alloc(char *, int, int, char *, int);
+#ifdef RAINBOW
+private int rbwrite(int, char *, int);
+#endif
+#else
+private File * f_alloc();
+#ifdef RAINBOW
+private int rbwrite();
+#endif
+#endif /* LINT_ARGS */
+
+#ifdef MAC
+#      undef private
+#      define private static
+#endif
+
+#ifndef L_SET
+#      define L_SET 0
+#endif
+
+#define MAXFILES       20      /* good enough for my purposes */
+
+private File   _openfiles[MAXFILES] = {0};
+
+private File *
+f_alloc(name, flags, fd, buffer, buf_size)
+char   *name,
+       *buffer;
+{
+       register File   *fp;
+       register int    i;
+
+       for (fp = _openfiles, i = 0; i < MAXFILES; i++, fp++)
+               if (fp->f_flags == 0)
+                       break;
+       if (i == MAXFILES)
+               complain("[Too many open files!]");
+       fp->f_bufsize = buf_size;
+       fp->f_cnt = 0;
+       fp->f_fd = fd;
+       fp->f_flags = flags;
+       if (buffer == 0) {
+               buffer = emalloc(buf_size);
+               fp->f_flags |= F_MYBUF;
+       }
+       fp->f_base = fp->f_ptr = buffer;
+       fp->f_name = copystr(name);
+
+       return fp;
+}
+
+void
+gc_openfiles()
+{
+       register File   *fp;
+
+       for (fp = _openfiles; fp < &_openfiles[MAXFILES]; fp++)
+               if (fp->f_flags != 0 && (fp->f_flags & F_LOCKED) == 0)
+                       f_close(fp);
+}
+
+File *
+fd_open(name, flags, fd, buffer, bsize)
+char   *name,
+       *buffer;
+{
+       return f_alloc(name, flags, fd, buffer, bsize);
+}
+
+File *
+f_open(name, flags, buffer, buf_size)
+char   *name,
+       *buffer;
+{
+       register int    fd;
+       int     mode = F_MODE(flags);
+
+       if (mode == F_READ)
+               fd = open(name, 0);
+       if (mode == F_APPEND) {
+               fd = open(name, 1);
+               if (fd == -1)
+                       mode = F_WRITE;
+               else
+                       (void) lseek(fd, 0L, 2);
+       }
+       if (mode == F_WRITE)
+               fd = creat(name, CreatMode);
+       if (fd == -1)
+               return NIL;
+#ifdef MSDOS
+       else
+               setmode(fd, 0x8000);
+#endif /* MSDOS */
+       return f_alloc(name, flags, fd, buffer, buf_size);
+}
+
+void
+f_close(fp)
+File   *fp;
+{
+       flush(fp);
+#ifdef BSD4_2 
+       if (fp->f_flags & (F_WRITE|F_APPEND))
+               (void) fsync(fp->f_fd);
+#endif 
+       (void) close(fp->f_fd);
+       if (fp->f_flags & F_MYBUF)
+               free(fp->f_base);
+       free(fp->f_name);
+       fp->f_flags = 0;        /* indicates that we're available */
+}
+
+int
+filbuf(fp)
+File   *fp;
+{
+       if (fp->f_flags & (F_EOF|F_ERR))
+               return EOF;
+       fp->f_ptr = fp->f_base;
+#ifndef MSDOS
+       do
+#endif /* MSDOS */
+               fp->f_cnt = read(fp->f_fd, fp->f_base, fp->f_bufsize);
+#ifndef MSDOS
+       while (fp->f_cnt == -1 && errno == EINTR);
+#endif /* MSDOS */
+       if (fp->f_cnt == -1) {
+               printf("[Read error %d]", errno);
+               fp->f_flags |= F_ERR;
+       }
+       if (fp->f_cnt == 0) {
+               fp->f_flags |= F_EOF;
+               return EOF;
+       }
+       io_chars += fp->f_cnt;
+       return getc(fp);
+}
+
+void
+putstr(s)
+register char  *s;
+{
+#ifndef IBMPC
+       register int    c;
+
+       while (c = *s++)
+               putchar(c);
+#else /* IBMPC */
+       write_emif(s);
+#endif /* IBMPC */
+}
+
+void
+fputnchar(s, n, fp)
+register char  *s;
+register int   n;
+register File  *fp;
+{
+       while (--n >= 0)
+               putc(*s++, fp);
+}
+
+void
+flusho()
+{
+#ifndef IBMPC
+       _flush(EOF, stdout);
+#endif /* IBMPC */
+}
+
+void
+flush(fp)
+File   *fp;
+{
+       _flush(EOF, fp);
+}
+
+void
+f_seek(fp, offset)
+register File  *fp;
+off_t  offset;
+{
+       if (fp->f_flags & F_WRITE)
+               flush(fp);
+       fp->f_cnt = 0;          /* next read will filbuf(), next write
+                                  will flush() with no bad effects */
+       lseek(fp->f_fd, (long) offset, L_SET);
+}
+
+int            /* is void - but for lints sake */
+_flush(c, fp)
+register File  *fp;
+{
+       register int    n;
+
+       if (fp->f_flags & (F_READ | F_STRING | F_ERR))
+               return EOF;
+       if (((n = (fp->f_ptr - fp->f_base)) > 0) &&
+#ifndef RAINBOW
+           (write(fp->f_fd, fp->f_base, n) != n) &&
+#else
+           (rbwrite(fp->f_fd, fp->f_base, n) != n) &&
+#endif
+           (fp != stdout)) {
+               fp->f_flags |= F_ERR;
+               error("[I/O error(%d); file = %s, fd = %d]",
+                       errno, fp->f_name, fp->f_fd);
+       }
+
+       fp->f_cnt = fp->f_bufsize;
+       fp->f_ptr = fp->f_base;
+       if (c != EOF)
+               return putc(c, fp);
+}
+
+int
+f_gets(fp, buf, max)
+register File  *fp;
+char   *buf;
+{
+       register char   *cp = buf;
+       register int    c;
+       char    *endp = buf + max - 1;
+
+       if (fp->f_flags & F_EOF)
+               return EOF;
+       while (((c = getc(fp)) != EOF) && (c != '\n')) {
+               if (c == '\0')  /* possibly different from NULL */
+                       break;          /* sorry we don't read nulls */
+#ifdef MSDOS
+               if (c == '\r') {
+                       if ((c = getc(fp)) == '\n')
+                          break;
+                       else
+                          *cp++ = '\r';
+               }
+#endif /* MSDOS */
+               if (cp >= endp) {
+                       add_mess(" [Line too long]");
+                       rbell();
+                       return EOF;
+               }
+               *cp++ = c;
+       }
+       *cp = '\0';
+       if (c == EOF) {
+               if (cp != buf)
+                       add_mess(" [Incomplete last line]");
+               fp->f_flags |= F_EOF;
+               return EOF;
+       }
+       io_lines += 1;
+       return 0;       /* this means okay */
+}
+
+/* skip to beginning of next line, i.e., next read returns first
+   character of new line */
+
+void
+f_toNL(fp)
+register File  *fp;
+{
+       register int    c;
+
+       if (fp->f_flags & F_EOF)
+               return;
+       while (((c = getc(fp)) != EOF) && (c != '\n'))
+               ;
+       if (c == EOF)
+               fp->f_flags |= F_EOF;
+}
+
+void
+f_readn(fp, addr, n)
+register File  *fp;
+register char  *addr;
+register int   n;
+{
+       while (--n >= 0)
+               *addr++ = getc(fp);
+}
+
+int
+f_getint(fp)
+File   *fp;
+{
+       int     n = 0,
+               c;
+
+       while (isdigit(c = getc(fp)))
+               n = (n * 10) + c;
+       return n;
+}
+
+/* Deals with output to the terminal, setting up the amount of characters
+   to be buffered depending on the output baud rate.  Why it's in a 
+   separate file I don't know ... */
+
+private char   one_buf;
+
+int    BufSize = 1;
+
+private File   _stdout = {1, 1, 1, F_WRITE, &one_buf, &one_buf};
+File   *stdout = &_stdout;
+
+/* put a string with padding */
+
+#ifndef IBMPC
+void
+tputc(c)
+{
+       putchar(c);
+}
+
+#undef putchar         /* for files which forget to include io.h,
+                                          here's a real putchar procedure. */
+void
+putchar(c)
+{
+       putc(c, stdout);
+}
+
+#endif /* IBMPC */
+#ifndef MAC
+void
+putpad(str, lines)
+char   *str;
+{
+#ifndef IBMPC
+       if (str)
+               tputs(str, lines, tputc);
+#else /* IBMPC */
+       write_emif(str);
+#endif /* IBMPC */
+}
+#endif
+
+/* Determine the number of characters to buffer at each baud rate.  The
+   lower the number, the quicker the response when new input arrives.  Of
+   course the lower the number, the more prone the program is to stop in
+   output.  Decide what matters most to you. This sets BufSize to the right
+   number or chars, and initiaizes `stdout'.  */
+
+void
+settout(ttbuf)
+char   *ttbuf;
+{
+#ifndef MAC
+#ifndef MSDOS
+       static int speeds[] = {
+               1,      /* 0    */
+               1,      /* 50   */
+               1,      /* 75   */
+               1,      /* 110  */
+               1,      /* 134  */
+               1,      /* 150  */
+               1,      /* 200  */
+               2,      /* 300  */
+               4,      /* 600  */
+               8,      /* 1200 */
+               16,     /* 1800 */
+               32,     /* 2400 */
+               128,    /* 4800 */
+               256,    /* 9600 */
+               512,    /* EXTA */
+               1024    /* EXT  */
+       };
+       flusho();               /* flush the one character buffer */
+       BufSize = min(MAXTTYBUF, speeds[ospeed] * max(LI / 24, 1));
+       stdout = fd_open("/dev/tty", F_WRITE|F_LOCKED, 1, ttbuf, BufSize);
+#else /* MSDOS */
+#ifndef IBMPC
+       flusho();               /* flush the one character buffer */
+       BufSize = BUFSIZ; 
+       stdout = fd_open("con", F_WRITE|F_LOCKED, 1, ttbuf, BufSize);
+#endif /* IBMPC */
+#endif /* MSDOS */
+#endif /* MAC */
+}
+
+#ifdef RAINBOW
+
+/*
+ * use the Rainbow's video output function
+ */
+
+#include <dos.h>
+
+private int
+rbwrite(fd, buf, cnt)
+char *buf;
+{
+       union REGS vr;
+
+       if (fd != 1) {
+               write(fd, buf, cnt);
+       } else {
+               while (cnt-- > 0) {
+                       vr.x.ax = *buf++;
+                       vr.x.di = 0;
+                       int86(0x18, &vr, &vr);
+               }
+       }
+}
+#endif /* RAINBOW */
diff --git a/usr/src/new/jove/funcdefs.c b/usr/src/new/jove/funcdefs.c
new file mode 100644 (file)
index 0000000..eea425f
--- /dev/null
@@ -0,0 +1,681 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+#include "jove.h"
+#include "ctype.h"
+
+#if !defined(TXT_TO_C) 
+extern void
+       EscPrefix(),
+       CtlxPrefix(),
+       MiscPrefix(),
+       UnbindC(),
+       ShowVersion(),
+       WVisSpace(),
+#ifdef ANSICODES
+       AnsiCodes(),
+#endif
+       AppReg(),
+       Apropos(),
+       BackChar(),
+       BList(),
+       FList(),
+       BUpList(),
+       FDownList(),
+       BSexpr(),
+       BackWord(),
+       Bof(),
+       Bol(),
+       Bos(),
+       Bow(),
+       BindAKey(),
+       BindMac(),
+       BufPos(),
+#ifdef MSDOS
+       Buf1Select(),
+       Buf2Select(),
+       Buf3Select(),
+       Buf4Select(),
+       Buf5Select(),
+       Buf6Select(),
+       Buf7Select(),
+       Buf8Select(),
+       Buf9Select(),
+       Buf10Select(),
+#endif /* MSDOS */
+       CasRegLower(),
+       CasRegUpper(),
+       CapChar(),
+       CapWord(),
+       LowWord(),
+       UppWord(),
+#ifdef CHDIR
+       Chdir(),
+       prCWD(),
+       prDIRS(),
+       Pushd(),
+       Popd(),
+#endif
+       prCTIME(),
+       ChrToOct(),
+       ClAndRedraw(),
+#ifndef MAC
+       MakeErrors(),
+#endif
+       CopyRegion(),
+       BufSelect(),
+       DelBlnkLines(),
+       DelNChar(),
+       DelNWord(),
+       OneWindow(),
+       DelPChar(),
+       DelPWord(),
+       DelReg(),
+       KillSome(),
+       DelWtSpace(),
+       DelCurWindow(),
+       KeyDesc(),
+       Digit(),
+       Digit0(),
+       Digit1(),
+       Digit2(),
+       Digit3(),
+       Digit4(),
+       Digit5(),
+       Digit6(),
+       Digit7(),
+       Digit8(),
+       Digit9(),
+       DescBindings(),
+       DescCom(),
+       Eof(),
+       Eol(),
+       Eos(),
+       Eow(),
+       ForPara(),
+       BackPara(),
+       BufErase(),
+       PtToMark(),
+       Extend(),
+       ExecMacro(),
+       RunMacro(),
+       Leave(),
+       FindFile(),
+       WindFind(),
+       FindTag(),
+       FDotTag(),
+       ToIndent(),
+       ForChar(),
+       FSexpr(),
+       ForWord(),
+       TimesFour(),
+       GoLine(),
+       GrowWindow(),
+       IncFSearch(),
+       IncRSearch(),
+       InsFile(),
+       Justify(),
+       RegJustify(),
+       SetLMargin(),
+       SetRMargin(),
+       BufKill(),
+       KillBos(),
+       KillEos(),
+       KillEOL(),
+       KillExpr(),
+       BufList(),
+       NotModified(),
+       NameMac(),
+       DelMacro(),
+       Newline(),
+       OpenLine(),
+       LineAI(),
+#ifndef MAC
+       ShowErr(),
+       NextError(),
+#endif /* MAC */
+#ifdef MSDOS
+       PageScrollUp(),
+       PageScrollDown(),
+#endif /* MSDOS */
+#ifndef MAC
+       PrevError(),
+#endif /* MAC */
+       NextLine(),
+       NextPage(),
+       NextWindow(),
+       Recur(),
+       PopMark(),
+       PageNWind(),
+       Tab(),
+       DoParen(),
+#ifndef MAC
+       ParseAll(),
+#endif
+#ifdef SPELL
+       SpelWords(),
+#endif
+#ifdef JOB_CONTROL
+       PauseJove(),
+#endif
+       PrevLine(),
+       PrevPage(),
+       PrevWindow(),
+#ifndef MAC
+       Push(),
+#endif
+       RegReplace(),
+       QRepSearch(),
+       QuotChar(),
+       ReadFile(),
+       DefKBDMac(),
+       RedrawDisplay(),
+       ReNamBuf(),
+       RepSearch(),
+       DownScroll(),
+       UpScroll(),
+       ForSearch(),
+       FSrchND(),
+       RevSearch(),
+       RSrchND(),
+       SelfInsert(),
+       SetVar(),
+       SetMark(),
+#ifndef MAC
+       ShellCom(),
+       ShNoBuf(),
+       Shtypeout(),
+       ShToBuf(),
+#endif
+       ShrWindow(),
+       Source(),
+#ifdef SPELL
+       SpelBuffer(),
+#endif
+       SplitWind(),
+       GotoWind(),
+       Remember(),
+       Forget(),
+       StrLength(),
+       TransChar(),
+       TransLines(),
+       SaveFile(),
+       WtModBuf(),
+       WriteFile(),
+       WriteMacs(),
+       WrtReg(),
+       Yank(),
+       YankPop(),      PrVar(),
+#ifndef MAC
+       FilterRegion(),
+#endif
+       WNumLines(),
+#ifdef IPROCS
+       ShellProc(),
+       ProcInt(),
+       ProcQuit(),
+       ProcKill(),
+#  ifndef PIPEPROCS
+       ProcEof(),
+       ProcStop(),
+       ProcCont(),
+       ProcDStop(),
+#  endif
+       ProcSendData(),
+       ProcNewline(),
+       ProcList(),
+       ProcBind(),
+       Iprocess(),
+#endif
+
+#ifdef LISP
+       GSexpr(),       /* Grind S Expression. */
+       AddSpecial(),   /* add lisp special form */
+#endif
+       CAutoExec(),
+       MAutoExec(),
+
+       DefMAbbrev(),
+       DefGAbbrev(),
+       SaveAbbrevs(),
+       RestAbbrevs(),
+       EditAbbrevs(),
+       BindMtoW(),
+
+#ifdef CMT_FMT
+       Comment(),
+#endif
+
+       ScrollLeft(),
+       ScrollRight(),
+       MacInter();             /* This is the last one. */
+
+
+#ifdef MAC
+#      define WIRED_CMD(c) c,'\0','\0' /* for About Jove... */
+#else
+#      define WIRED_CMD(c)     c
+#endif /* MAC */
+
+#else /* TXT_TO_C */
+
+#ifdef MAC
+#      define WIRED_CMD(c) 0,'\0','\0'
+#else
+#      define WIRED_CMD(c)     0
+#endif
+#endif /* TXT_TO_C */
+
+struct cmd     commands[] = {
+#ifdef LISP
+       FUNCTION, "add-lisp-special", WIRED_CMD(AddSpecial),
+#endif
+#ifdef ANSICODES
+       FUNCTION, "ansi-codes", WIRED_CMD(AnsiCodes),
+#endif
+       FUNCTION, "append-region", WIRED_CMD(AppReg),
+       FUNCTION, "apropos", WIRED_CMD(Apropos),
+       FUNCTION, "auto-execute-command", WIRED_CMD(CAutoExec),
+       FUNCTION, "auto-execute-macro", WIRED_CMD(MAutoExec),
+       DefMinor(Fill), "auto-fill-mode", WIRED_CMD(0),
+       DefMinor(Indent), "auto-indent-mode", WIRED_CMD(0),
+       FUNCTION, "backward-character", WIRED_CMD(BackChar),
+       FUNCTION, "backward-list", WIRED_CMD(BList),
+       FUNCTION, "backward-paragraph", WIRED_CMD(BackPara),
+       FUNCTION, "backward-s-expression", WIRED_CMD(BSexpr),
+       FUNCTION, "backward-sentence", WIRED_CMD(Bos),
+       FUNCTION, "backward-up-list", WIRED_CMD(BUpList),
+       FUNCTION, "backward-word", WIRED_CMD(BackWord),
+       FUNCTION, "begin-kbd-macro", WIRED_CMD(Remember),
+       FUNCTION, "beginning-of-file", WIRED_CMD(Bof),
+       FUNCTION, "beginning-of-line", WIRED_CMD(Bol),
+       FUNCTION, "beginning-of-window", WIRED_CMD(Bow),
+       FUNCTION, "bind-to-key", WIRED_CMD(BindAKey),
+       FUNCTION, "bind-macro-to-key", WIRED_CMD(BindMac),
+#ifdef ABBREV
+       FUNCTION, "bind-macro-to-word-abbrev", WIRED_CMD(BindMtoW),
+#endif
+       FUNCTION, "buffer-position", WIRED_CMD(BufPos),
+       DefMajor(CMODE), "c-mode", WIRED_CMD(0),
+       FUNCTION, "case-character-capitalize", WIRED_CMD(CapChar),
+       FUNCTION, "case-region-lower", WIRED_CMD(CasRegLower),
+       FUNCTION, "case-region-upper", WIRED_CMD(CasRegUpper),
+       FUNCTION, "case-word-capitalize", WIRED_CMD(CapWord),
+       FUNCTION, "case-word-lower", WIRED_CMD(LowWord),
+       FUNCTION, "case-word-upper", WIRED_CMD(UppWord),
+       FUNCTION, "character-to-octal-insert", WIRED_CMD(ChrToOct),
+#ifdef CHDIR
+       FUNCTION, "cd", WIRED_CMD(Chdir),
+#endif
+       FUNCTION, "clear-and-redraw", WIRED_CMD(ClAndRedraw),
+#ifndef MAC
+       FUNCTION, "compile-it", WIRED_CMD(MakeErrors),
+#endif
+#ifdef IPROCS
+#  ifndef PIPEPROCS
+#    ifdef TIOCSLTC
+       FUNCTION, "continue-process", WIRED_CMD(ProcCont),
+#    endif
+#  endif
+#endif
+       FUNCTION, "copy-region", WIRED_CMD(CopyRegion),
+#ifndef MAC
+       FUNCTION, "current-error", WIRED_CMD(ShowErr),
+#endif
+       FUNCTION, "date", WIRED_CMD(prCTIME),
+#ifdef ABBREV
+       FUNCTION, "define-global-word-abbrev", WIRED_CMD(DefGAbbrev),
+       FUNCTION, "define-mode-word-abbrev", WIRED_CMD(DefMAbbrev),
+#endif
+       FUNCTION, "define-macro", WIRED_CMD(DefKBDMac),
+       FUNCTION, "delete-blank-lines", WIRED_CMD(DelBlnkLines),
+       FUNCTION, "delete-buffer", WIRED_CMD(BufKill),
+       FUNCTION, "delete-macro", WIRED_CMD(DelMacro),
+       FUNCTION, "delete-next-character", WIRED_CMD(DelNChar),
+       FUNCTION, "delete-other-windows", WIRED_CMD(OneWindow),
+       FUNCTION, "delete-previous-character", WIRED_CMD(DelPChar),
+       FUNCTION, "delete-white-space", WIRED_CMD(DelWtSpace),
+       FUNCTION, "delete-current-window", WIRED_CMD(DelCurWindow),
+       FUNCTION, "describe-bindings", WIRED_CMD(DescBindings),
+       FUNCTION, "describe-command", WIRED_CMD(DescCom),
+       FUNCTION, "describe-key", WIRED_CMD(KeyDesc),
+       FUNCTION, "describe-variable", WIRED_CMD(DescCom),
+       FUNCTION, "digit", WIRED_CMD(Digit),
+       FUNCTION, "digit-1", WIRED_CMD(Digit1),
+       FUNCTION, "digit-2", WIRED_CMD(Digit2),
+       FUNCTION, "digit-3", WIRED_CMD(Digit3),
+       FUNCTION, "digit-4", WIRED_CMD(Digit4),
+       FUNCTION, "digit-5", WIRED_CMD(Digit5),
+       FUNCTION, "digit-6", WIRED_CMD(Digit6),
+       FUNCTION, "digit-7", WIRED_CMD(Digit7),
+       FUNCTION, "digit-8", WIRED_CMD(Digit8),
+       FUNCTION, "digit-9", WIRED_CMD(Digit9),
+       FUNCTION, "digit-0", WIRED_CMD(Digit0),
+#ifdef CHDIR
+       FUNCTION, "dirs", WIRED_CMD(prDIRS),
+#endif
+       FUNCTION, "down-list", WIRED_CMD(FDownList),
+#ifdef IPROCS
+#  ifndef PIPEPROCS
+#    ifdef TIOCSLTC
+       FUNCTION, "dstop-process", WIRED_CMD(ProcDStop),
+#    endif
+#  endif
+#endif
+#ifdef ABBREV
+       FUNCTION, "edit-word-abbrevs", WIRED_CMD(EditAbbrevs),
+#endif
+       FUNCTION, "end-kbd-macro", WIRED_CMD(Forget),
+       FUNCTION, "end-of-file", WIRED_CMD(Eof),
+       FUNCTION, "end-of-line", WIRED_CMD(Eol),
+       FUNCTION, "end-of-window", WIRED_CMD(Eow),
+#ifdef IPROCS
+#  ifndef PIPEPROCS
+       FUNCTION, "eof-process", WIRED_CMD(ProcEof),
+#  endif
+#endif
+       FUNCTION, "erase-buffer", WIRED_CMD(BufErase),
+       FUNCTION, "exchange-point-and-mark", WIRED_CMD(PtToMark),
+       FUNCTION, "execute-named-command", WIRED_CMD(Extend),
+       FUNCTION, "execute-kbd-macro", WIRED_CMD(ExecMacro),
+       FUNCTION, "execute-macro", WIRED_CMD(RunMacro),
+       FUNCTION, "exit-jove", WIRED_CMD(Leave),
+#ifdef CMT_FMT
+       FUNCTION, "fill-comment", WIRED_CMD(Comment),
+#endif /* CMT_FMT */
+       FUNCTION, "fill-paragraph", WIRED_CMD(Justify),
+       FUNCTION, "fill-region", WIRED_CMD(RegJustify),
+#ifndef MAC
+       FUNCTION, "filter-region", WIRED_CMD(FilterRegion),
+#endif
+       FUNCTION, "find-file", WIRED_CMD(FindFile),
+       FUNCTION, "find-tag", WIRED_CMD(FindTag),
+       FUNCTION, "find-tag-at-point", WIRED_CMD(FDotTag),
+       FUNCTION, "first-non-blank", WIRED_CMD(ToIndent),
+       FUNCTION, "forward-character", WIRED_CMD(ForChar),
+       FUNCTION, "forward-list", WIRED_CMD(FList),
+       FUNCTION, "forward-paragraph", WIRED_CMD(ForPara),
+       FUNCTION, "forward-s-expression", WIRED_CMD(FSexpr),
+       FUNCTION, "forward-sentence", WIRED_CMD(Eos),
+       FUNCTION, "forward-word", WIRED_CMD(ForWord),
+       DefMajor(FUNDAMENTAL), "fundamental-mode", WIRED_CMD(0),
+       FUNCTION, "gather-numeric-argument", WIRED_CMD(TimesFour),
+#ifdef LISP
+       FUNCTION, "grind-s-expr", WIRED_CMD(GSexpr),
+#endif
+       FUNCTION, "goto-line", WIRED_CMD(GoLine),
+       FUNCTION, "goto-window-with-buffer", WIRED_CMD(GotoWind),
+       FUNCTION, "grow-window", WIRED_CMD(GrowWindow),
+       FUNCTION, "handle-tab", WIRED_CMD(Tab),
+       FUNCTION, "i-search-forward", WIRED_CMD(IncFSearch),
+       FUNCTION, "i-search-reverse", WIRED_CMD(IncRSearch),
+       FUNCTION, "insert-file", WIRED_CMD(InsFile),
+#ifdef IPROCS
+       FUNCTION, "interrupt-process", WIRED_CMD(ProcInt),
+       FUNCTION, "i-shell-command", WIRED_CMD(Iprocess),
+#endif
+       FUNCTION, "kill-next-word", WIRED_CMD(DelNWord),
+       FUNCTION, "kill-previous-word", WIRED_CMD(DelPWord),
+#ifdef IPROCS
+       FUNCTION, "kill-process", WIRED_CMD(ProcKill),
+#endif
+       FUNCTION, "kill-region", WIRED_CMD(DelReg),
+       FUNCTION, "kill-s-expression", WIRED_CMD(KillExpr),
+       FUNCTION, "kill-some-buffers", WIRED_CMD(KillSome),
+       FUNCTION, "kill-to-beginning-of-sentence", WIRED_CMD(KillBos),
+       FUNCTION, "kill-to-end-of-line", WIRED_CMD(KillEOL),
+       FUNCTION, "kill-to-end-of-sentence", WIRED_CMD(KillEos),
+       FUNCTION, "left-margin-here", WIRED_CMD(SetLMargin),
+#ifdef LISP
+       DefMajor(LISPMODE), "lisp-mode", WIRED_CMD(0),
+#endif
+       FUNCTION, "list-buffers", WIRED_CMD(BufList),
+#ifdef IPROCS
+       FUNCTION, "list-processes", WIRED_CMD(ProcList),
+#endif
+       FUNCTION, "make-buffer-unmodified", WIRED_CMD(NotModified),
+       FUNCTION, "make-macro-interactive", WIRED_CMD(MacInter),
+       FUNCTION, "name-kbd-macro", WIRED_CMD(NameMac),
+       FUNCTION, "newline", WIRED_CMD(Newline),
+       FUNCTION, "newline-and-backup", WIRED_CMD(OpenLine),
+       FUNCTION, "newline-and-indent", WIRED_CMD(LineAI),
+#ifndef MAC
+       FUNCTION, "next-error", WIRED_CMD(NextError),
+#endif
+       FUNCTION, "next-line", WIRED_CMD(NextLine),
+       FUNCTION, "next-page", WIRED_CMD(NextPage),
+       FUNCTION, "next-window", WIRED_CMD(NextWindow),
+       FUNCTION, "number-lines-in-window", WIRED_CMD(WNumLines),
+       DefMinor(OverWrite), "over-write-mode", WIRED_CMD(0),
+       FUNCTION, "page-next-window", WIRED_CMD(PageNWind),
+       FUNCTION, "paren-flash", WIRED_CMD(DoParen),
+#ifndef MAC
+       FUNCTION, "parse-errors", WIRED_CMD(ErrParse),
+#endif
+#ifdef SPELL
+       FUNCTION, "parse-spelling-errors-in-buffer", WIRED_CMD(SpelWords),
+#endif
+#ifdef JOB_CONTROL
+       FUNCTION, "pause-jove", WIRED_CMD(PauseJove),
+#else
+#      ifndef MAC
+       FUNCTION, "pause-jove", WIRED_CMD(Push),
+#      endif
+#endif
+       FUNCTION, "pop-mark", WIRED_CMD(PopMark),
+#ifdef CHDIR
+       FUNCTION, "popd", WIRED_CMD(Popd),
+#endif
+       FUNCTION, "prefix-1", WIRED_CMD(EscPrefix),
+       FUNCTION, "prefix-2", WIRED_CMD(CtlxPrefix),
+       FUNCTION, "prefix-3", WIRED_CMD(MiscPrefix),
+#ifndef MAC
+       FUNCTION, "previous-error", WIRED_CMD(PrevError),
+#endif
+       FUNCTION, "previous-line", WIRED_CMD(PrevLine),
+       FUNCTION, "previous-page", WIRED_CMD(PrevPage),
+       FUNCTION, "previous-window", WIRED_CMD(PrevWindow),
+       FUNCTION, "print", WIRED_CMD(PrVar),
+#ifdef IPROCS
+       FUNCTION, "process-bind-to-key", WIRED_CMD(ProcBind),
+       FUNCTION, "process-newline", WIRED_CMD(ProcNewline),
+       FUNCTION, "process-send-data-no-return", WIRED_CMD(ProcSendData),
+#endif
+#ifndef MAC
+       FUNCTION, "push-shell", WIRED_CMD(Push),
+#endif
+#ifdef CHDIR
+       FUNCTION, "pushd", WIRED_CMD(Pushd),
+       FUNCTION, "pwd", WIRED_CMD(prCWD),
+#endif
+       FUNCTION, "query-replace-string", WIRED_CMD(QRepSearch),
+#ifdef IPROCS
+       FUNCTION, "quit-process", WIRED_CMD(ProcQuit),
+#endif
+       FUNCTION, "quoted-insert", WIRED_CMD(QuotChar),
+#ifdef ABBREV
+       FUNCTION, "read-word-abbrev-file", WIRED_CMD(RestAbbrevs),
+#endif
+       FUNCTION, "redraw-display", WIRED_CMD(RedrawDisplay),
+       FUNCTION, "recursive-edit", WIRED_CMD(Recur),
+       FUNCTION, "rename-buffer", WIRED_CMD(ReNamBuf),
+       FUNCTION, "replace-in-region", WIRED_CMD(RegReplace),
+       FUNCTION, "replace-string", WIRED_CMD(RepSearch),
+       FUNCTION, "right-margin-here", WIRED_CMD(SetRMargin),
+       FUNCTION, "save-file", WIRED_CMD(SaveFile),
+       FUNCTION, "scroll-down", WIRED_CMD(DownScroll),
+       FUNCTION, "scroll-left", WIRED_CMD(ScrollLeft),
+#ifdef MSDOS
+       FUNCTION, "scroll-next-page", WIRED_CMD(PageScrollUp),
+       FUNCTION, "scroll-previous-page", WIRED_CMD(PageScrollDown),
+#endif /* MSDOS */
+       FUNCTION, "scroll-right", WIRED_CMD(ScrollRight),
+       FUNCTION, "scroll-up", WIRED_CMD(UpScroll),
+       FUNCTION, "search-forward", WIRED_CMD(ForSearch),
+       FUNCTION, "search-forward-nd", WIRED_CMD(FSrchND),
+       FUNCTION, "search-reverse", WIRED_CMD(RevSearch),
+       FUNCTION, "search-reverse-nd", WIRED_CMD(RSrchND),
+       FUNCTION, "select-buffer", WIRED_CMD(BufSelect),
+#ifdef MSDOS
+       FUNCTION, "select-buffer-1", WIRED_CMD(Buf1Select),
+       FUNCTION, "select-buffer-2", WIRED_CMD(Buf2Select),
+       FUNCTION, "select-buffer-3", WIRED_CMD(Buf3Select),
+       FUNCTION, "select-buffer-4", WIRED_CMD(Buf4Select),
+       FUNCTION, "select-buffer-5", WIRED_CMD(Buf5Select),
+       FUNCTION, "select-buffer-6", WIRED_CMD(Buf6Select),
+       FUNCTION, "select-buffer-7", WIRED_CMD(Buf7Select),
+       FUNCTION, "select-buffer-8", WIRED_CMD(Buf8Select),
+       FUNCTION, "select-buffer-9", WIRED_CMD(Buf9Select),
+       FUNCTION, "select-buffer-10", WIRED_CMD(Buf10Select),
+#endif /* MSDOS */
+       FUNCTION, "self-insert", WIRED_CMD(SelfInsert),
+       FUNCTION, "set", WIRED_CMD(SetVar),
+       FUNCTION, "set-mark", WIRED_CMD(SetMark),
+#ifdef IPROCS  /* for GNU compatibility */
+       FUNCTION, "shell", WIRED_CMD(ShellProc),
+#endif
+#ifndef MAC
+       FUNCTION, "shell-command", WIRED_CMD(ShellCom),
+       FUNCTION, "shell-command-no-buffer", WIRED_CMD(ShNoBuf),
+       FUNCTION, "shell-command-to-buffer", WIRED_CMD(ShToBuf),
+       FUNCTION, "shell-command-with-typeout", WIRED_CMD(Shtypeout),
+#endif
+       DefMinor(ShowMatch), "show-match-mode", WIRED_CMD(0),
+       FUNCTION, "shrink-window", WIRED_CMD(ShrWindow),
+       FUNCTION, "source", WIRED_CMD(Source),
+#ifdef SPELL
+       FUNCTION, "spell-buffer", WIRED_CMD(SpelBuffer),
+#endif
+       FUNCTION, "split-current-window", WIRED_CMD(SplitWind),
+       FUNCTION, "start-remembering", WIRED_CMD(Remember),
+#ifdef IPROCS
+#  ifndef PIPEPROCS
+       FUNCTION, "stop-process", WIRED_CMD(ProcStop),
+#  endif
+#endif
+       FUNCTION, "stop-remembering", WIRED_CMD(Forget),
+       FUNCTION, "string-length", WIRED_CMD(StrLength),
+#ifdef JOB_CONTROL
+       FUNCTION, "suspend-jove", WIRED_CMD(PauseJove),
+#endif
+       DefMajor(TEXT), "text-mode", WIRED_CMD(0),
+       FUNCTION, "transpose-characters", WIRED_CMD(TransChar),
+       FUNCTION, "transpose-lines", WIRED_CMD(TransLines),
+       FUNCTION, "unbind-key", WIRED_CMD(UnbindC),
+       FUNCTION, "version", WIRED_CMD(ShowVersion),
+       FUNCTION, "visible-spaces-in-window", WIRED_CMD(WVisSpace),
+       FUNCTION, "visit-file", WIRED_CMD(ReadFile),
+       FUNCTION, "window-find", WIRED_CMD(WindFind),
+#ifdef ABBREV
+       DefMinor(Abbrev), "word-abbrev-mode", WIRED_CMD(0),
+       FUNCTION, "write-word-abbrev-file", WIRED_CMD(SaveAbbrevs),
+#endif
+       FUNCTION, "write-file", WIRED_CMD(WriteFile),
+       FUNCTION, "write-macros-to-file", WIRED_CMD(WriteMacs),
+       FUNCTION, "write-modified-files", WIRED_CMD(WtModBuf),
+       FUNCTION, "write-region", WIRED_CMD(WrtReg),
+       FUNCTION, "yank", WIRED_CMD(Yank),
+       FUNCTION, "yank-pop", WIRED_CMD(YankPop),
+       FUNCTION, 0, 0
+};
+
+#ifndef TXT_TO_C
+data_obj *
+findcom(prompt)
+char   *prompt;
+{
+       /* This is for faster startup.  This just reads until a space or a
+          tab or a newline character is reached, and then does a
+          semi-hashed lookup on that string.  This should be much faster
+          than initializing the minibuffer for each line. */
+       if (InJoverc) {
+               char    cmdbuf[128];
+               register struct cmd     *cmd;
+               register char   *cp = cmdbuf;
+#if !(defined(IBMPC) || defined(MAC))
+               register int    c;
+#else
+               int c;
+#endif         
+               struct cmd      *which;
+               int     cmdlen,
+                       found = 0;
+               static struct cmd       *cmdhash[26];
+               static int      beenhere = NO;
+
+/* special case for prefix commands--only upper case ones */
+#define hash(c)        (c - 'a')
+
+               /* initialize the hash table */
+               if (beenhere == NO) {
+                       int     lastc = 0;
+
+                       for (cmd = commands; cmd->Name != 0; cmd++)
+                               if (lastc != cmd->Name[0]) {
+                                       lastc = cmd->Name[0];
+                                       cmdhash[hash(lastc)] = cmd;
+                               }
+                       beenhere = YES;
+               }
+#ifdef MAC
+               menus_off();    /* Block menu choices during input */
+#endif
+               /* gather the cmd name */
+               while (((c = getch()) != EOF) && !index(" \t\r\n", c)) {
+#if (defined(IBMPC) || defined(MAC))
+                       lower(&c);
+#else                  
+                       if (isupper(c))
+                               c = tolower(c);
+#endif
+                       *cp++ = c;
+               }
+               if (c == EOF)
+                       return 0;
+               *cp = '\0';
+               cmdlen = cp - cmdbuf;
+               if (cmdlen == 0)
+                       return 0;
+
+               /* look it up (in the reduced search space) */
+               if (islower(cmdbuf[0]))
+                   for (cmd = cmdhash[hash(cmdbuf[0])]; cmd != 0 && cmd->Name[0] == cmdbuf[0]; cmd++) {
+                       if (strncmp(cmd->Name, cmdbuf, cmdlen) == 0) {
+                               if (strcmp(cmd->Name, cmdbuf) == 0)
+                                       return (data_obj *) cmd;
+                               found += 1;
+                               which = cmd;
+                       }
+                   }
+               if (found > 1)
+                       complain("[\"%s\" ambiguous]", cmdbuf);
+               else if (found == 0)
+                       complain("[\"%s\" unknown]", cmdbuf);
+               else
+                       return (data_obj *) which;
+       } else {
+               static char     *strings[(sizeof commands) / sizeof (commands[0])];
+               static int      beenhere = NO;
+               register int    com;
+
+               if (beenhere == NO) {
+                       register char   **strs = strings;
+                       register struct cmd     *c;
+
+                       for (c = commands; c->Name != 0; c++)
+                               *strs++ = c->Name;
+                       *strs = 0;
+                       beenhere = YES;
+               }
+
+               if ((com = complete(strings, prompt, CASEIND)) < 0)
+                       return 0;
+               return (data_obj *) &commands[com];
+       }
+       /* NOTREACHED */
+}
+#endif
diff --git a/usr/src/new/jove/getch.c b/usr/src/new/jove/getch.c
new file mode 100644 (file)
index 0000000..da7bc59
--- /dev/null
@@ -0,0 +1,134 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+#include "tune.h"
+
+#ifdef MSDOS
+
+#include <bios.h>
+#include <dos.h>
+
+#include "jove.h"
+
+#ifdef LINT_ARGS
+private void waitfun(void);
+#else
+private void waitfun();
+#endif
+
+extern int UpdModLine;
+#ifdef IBMPC
+static char last = 0;
+extern int specialkey;
+#endif
+
+getrawinchar()
+{
+#ifdef RAINBOW
+       union REGS regs;
+#endif /* RAINBOW */
+#ifdef IBMPC
+       unsigned scan;
+       
+       if (specialkey = last) {
+               scan = last;
+               last = 0;
+               return scan;
+       }
+#endif /* IBMPC */
+
+       while (!rawkey_ready())
+               waitfun();
+
+#ifdef IBMPC
+       scan = _bios_keybrd(_KEYBRD_READ);
+       if ((scan&0xff) == 0) {
+               last = (char) (scan >> 8);
+               return 0xff;
+       }
+       return scan&0xff;
+#else /* IBMPC */
+#ifdef RAINBOW
+waitloop:
+       regs.x.di = 2;
+       int86(0x18, &regs, &regs);
+       if (regs.h.al != 0)     /* should never happen, but who knows */
+               return regs.h.al;
+       else
+               goto waitloop;
+#else /* RAINBOW */
+       return bdos(0x06, 0x00ff, 0xff) & 0xff;
+#endif /* RAINBOW */
+#endif /* IBMPC */
+}
+
+static int waiting = 0;
+
+rawkey_ready()
+{
+#ifndef IBMPC
+       union REGS regs;
+#endif
+
+       if (waiting)
+               return 0;
+#ifdef IBMPC
+       if (last) 
+               return 1;
+
+       return _bios_keybrd(_KEYBRD_READY);
+#else /* IBMPC */
+#ifdef RAINBOW
+       regs.x.di = 4;
+       int86(0x18, &regs, &regs);
+       return regs.h.cl != 0;
+#else /* RAINBOW */
+       regs.h.ah = 0x44;               /* ioctl call */
+       regs.x.bx = 0;                  /* stdin file handle */
+       regs.h.al = 0x06;               /* get input status */
+       intdos(&regs, &regs);
+       return regs.h.al & 1;
+#endif /* RAINBOW */
+#endif /* IBMPC */
+}
+
+#ifdef IBMPC
+static long timecount, lastcount = 0;
+#else
+static char lastmin = 0;
+#endif
+
+
+private void
+waitfun()
+{
+#ifndef IBMPC
+       struct dostime_t tc;
+#endif
+
+       if (UpdModLine) {
+               waiting = 1;
+               redisplay();
+               waiting = 0;
+               return;
+       }
+#ifdef IBMPC
+       if (_bios_timeofday(_TIME_GETCLOCK, &timecount) ||  /* after midnight */
+            (timecount > lastcount + 0x444) ) {
+               lastcount = timecount;
+               UpdModLine = 1;
+       }
+#else
+       _dos_gettime(&tc);
+       if (tc.minute != lastmin) {
+               UpdModLine = 1;
+               lastmin = tc.minute;
+       }
+#endif
+}
+
+#endif /* MSDOS */
diff --git a/usr/src/new/jove/insert.c b/usr/src/new/jove/insert.c
new file mode 100644 (file)
index 0000000..80003c2
--- /dev/null
@@ -0,0 +1,763 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+#include "jove.h"
+#include "ctype.h"
+#include "table.h"
+
+#ifdef MAC
+#      undef private
+#      define private
+#endif
+
+#ifdef LINT_ARGS
+private int
+       newchunk(void);
+private void   
+       init_specials(void),
+       remfreelines(struct chunk *);
+#else
+private int
+       newchunk();
+private void   
+       init_specials(),
+       remfreelines();
+#endif /* LINT_ARGS */
+
+#ifdef MAC
+#      undef private
+#      define private static
+#endif
+
+/* Make a newline after AFTER in buffer BUF, UNLESS after is 0,
+   in which case we insert the newline before after. */
+
+Line *
+listput(buf, after)
+register Buffer        *buf;
+register Line  *after;
+{
+       register Line   *newline = nbufline();
+
+       if (after == 0) {       /* Before the first line */
+               newline->l_next = buf->b_first;
+               newline->l_prev = 0;
+               buf->b_first = newline;
+       } else {
+               newline->l_prev = after;
+               newline->l_next = after->l_next;
+               after->l_next = newline;
+       }
+       if (newline->l_next)
+               newline->l_next->l_prev = newline;
+       else
+               if (buf)
+                       buf->b_last = newline;
+       if (buf && buf->b_dot == 0)
+               buf->b_dot = newline;
+       return newline;
+}      
+
+/* Divide the current line and move the current line to the next one */
+
+void
+LineInsert(num)
+register int   num;
+{
+       char    newline[LBSIZE];
+       register Line   *newdot,
+                       *olddot;
+       int     oldchar;
+
+       olddot = curline;
+       oldchar = curchar;
+
+       newdot = curline;
+       while (--num >= 0) {
+               newdot = listput(curbuf, newdot);
+               SavLine(newdot, NullStr);
+       }
+
+       modify();
+       if (curchar != 0) {
+               strcpy(newline, &linebuf[curchar]);
+               linebuf[curchar] = '\0';        /* Shorten this line */
+               SavLine(curline, linebuf);
+               strcpy(linebuf, newline);
+       } else {        /* Redisplay optimization */
+               newdot->l_dline = curline->l_dline;
+               SavLine(curline, NullStr);
+       }
+
+       makedirty(curline);
+       curline = newdot;
+       curchar = 0;
+       makedirty(curline);
+       IFixMarks(olddot, oldchar, curline, curchar);
+}      
+
+/* Makes the indent of the current line == goal.  If the current indent
+   is greater than GOAL it deletes.  If more indent is needed, it uses
+   tabs and spaces to get to where it's going. */
+
+void
+n_indent(goal)
+register int   goal;
+{
+       int     dotcol,
+               incrmt;
+
+       ToIndent();
+       dotcol = calc_pos(linebuf, curchar);
+       if (goal < dotcol) {
+               DelWtSpace();
+               dotcol = 0;
+       }
+
+       for (;;) {
+               incrmt = (tabstop - (dotcol % tabstop));
+               if (dotcol + incrmt > goal)
+                       break;
+               insert_c('\t', 1);
+               dotcol += incrmt;
+       }
+       if (dotcol != goal)
+               insert_c(' ', (goal - dotcol));
+}
+
+#ifdef ABBREV
+void
+MaybeAbbrevExpand()
+{
+       if (MinorMode(Abbrev) && !ismword(LastKeyStruck) &&
+           !bolp() && ismword(linebuf[curchar - 1]))
+               AbbrevExpand();
+}
+#endif
+
+void
+SelfInsert()
+{
+#ifdef ABBREV
+       MaybeAbbrevExpand();
+#endif
+       if (LastKeyStruck != CTL('J') && MinorMode(OverWrite)) {
+               register int    num,
+                               i;
+
+               for (i = 0, num = arg_value(); i < num; i++) {
+                       int     pos = calc_pos(linebuf, curchar);
+
+                       if (!eolp()) {
+                               if (linebuf[curchar] == '\t') {
+                                       if ((pos + 1) == ((pos + tabstop) - (pos % tabstop)))
+                                               del_char(FORWARD, 1);
+                               } else
+                                       del_char(FORWARD, 1);
+                       }
+                       insert_c(LastKeyStruck, 1);
+               }
+       } else
+               Insert(LastKeyStruck);
+
+       if (MinorMode(Fill) && (curchar >= RMargin ||
+                              (calc_pos(linebuf, curchar) >= RMargin))) {
+               int margin;
+               Bufpos save;
+
+               if (MinorMode(Indent)) {
+                       DOTsave(&save);
+                       ToIndent();
+                       margin = calc_pos(linebuf, curchar);
+                       SetDot(&save);
+               } else
+                       margin = LMargin;
+               DoJustify(curline, 0, curline,
+                         curchar + strlen(&linebuf[curchar]), 1, margin);
+       }
+}
+
+void
+Insert(c)
+{
+       if (c == CTL('J'))
+               LineInsert(arg_value());
+       else
+               insert_c(c, arg_value());
+}
+
+/* insert character C N times at point */
+void
+insert_c(c, n)
+{
+       if (n <= 0)
+               return;
+       modify();
+       makedirty(curline);
+       ins_c(c, linebuf, curchar, n, LBSIZE);
+       IFixMarks(curline, curchar, curline, curchar + n);
+       curchar += n;
+}      
+
+/* Tab in to the right place for C mode */
+
+void
+Tab()
+{
+#ifdef LISP
+       if (MajorMode(LISPMODE) && (bolp() || !eolp())) {
+               int     dotchar = curchar;
+               Mark    *m = 0;
+
+               ToIndent();
+               if (dotchar > curchar)
+                       m = MakeMark(curline, dotchar, M_FLOATER);
+               (void) lisp_indent();
+               if (m) {
+                       ToMark(m);
+                       DelMark(m);
+               } else
+                       ToIndent();
+               return;
+       }
+#endif
+       if (MajorMode(CMODE) && strlen(linebuf) == 0)
+               (void) c_indent(CIndIncrmt);
+       else
+               SelfInsert();
+}
+
+void
+QuotChar()
+{
+       int     c,
+               slow;
+
+       c = waitchar(&slow);
+       if (slow)
+               message(key_strokes);
+       if (c != CTL('@'))
+               Insert(c);
+}
+
+/* Insert the paren.  If in C mode and c is a '}' then insert the
+   '}' in the "right" place for C indentation; that is indented 
+   the same amount as the matching '{' is indented. */
+
+int    PDelay = 5,     /* 1/2 a second */
+       CIndIncrmt = 8;
+
+void
+DoParen()
+{
+       Bufpos  *bp = (Bufpos *) -1;
+       int     nx,
+               c = LastKeyStruck;
+
+       if (!isclosep(c)) {
+               SelfInsert();
+               return;
+       }
+
+       if (MajorMode(CMODE) && c == '}' && blnkp(linebuf))
+               bp = c_indent(0);
+#ifdef LISP
+       if (MajorMode(LISPMODE) && c == ')' && blnkp(linebuf))
+               bp = lisp_indent();
+#endif
+       SelfInsert();
+#ifdef MAC
+       if (MinorMode(ShowMatch) && !in_macro()) {
+#else
+       if (MinorMode(ShowMatch) && !charp() && !in_macro()) {
+#endif
+               b_char(1);      /* Back onto the ')' */
+               if ((int) bp == -1)
+                       bp = m_paren(c, BACKWARD, NO, YES);
+               f_char(1);
+               if (bp != 0) {
+                       nx = in_window(curwind, bp->p_line);
+                       if (nx != -1) {         /* is visible */
+                               Bufpos  b;
+
+                               DOTsave(&b);
+                               SetDot(bp);
+                               SitFor(PDelay);
+                               SetDot(&b);
+                       } else
+                               s_mess("%s", lcontents(bp->p_line));
+               }
+               mp_error();     /* display error message */
+       }
+}
+
+void
+LineAI()
+{
+       DoNewline(TRUE);
+}
+
+void
+Newline()
+{
+       DoNewline(MinorMode(Indent));
+}      
+
+void
+DoNewline(indentp)
+{
+       Bufpos  save;
+       int     indent;
+
+       /* first we calculate the indent of the current line */
+       DOTsave(&save);
+       ToIndent();
+       indent = calc_pos(linebuf, curchar);
+       SetDot(&save);
+
+#ifdef ABBREV
+       MaybeAbbrevExpand();
+#endif
+#ifdef LISP
+       if (MajorMode(LISPMODE))
+               DelWtSpace();
+       else
+#endif
+           if (indentp || blnkp(linebuf))
+               DelWtSpace();
+               
+       /* If there is more than 2 blank lines in a row then don't make
+          a newline, just move down one. */
+       if (arg_value() == 1 && eolp() && TwoBlank())
+               SetLine(curline->l_next);
+       else
+               LineInsert(arg_value());
+
+       if (indentp)
+#ifdef LISP
+           if (MajorMode(LISPMODE))
+               (void) lisp_indent();
+           else
+#endif
+               n_indent((LMargin == 0) ? indent : LMargin);
+}
+
+void
+ins_str(str, ok_nl)
+register char  *str;
+{
+       register char   c;
+       Bufpos  save;
+       int     llen;
+
+       if (*str == 0)
+               return;         /* ain't nothing to insert! */
+       DOTsave(&save);
+       llen = strlen(linebuf);
+       while (c = *str++) {
+               if (c == '\n' || (ok_nl && llen >= LBSIZE - 2)) {
+                       IFixMarks(save.p_line, save.p_char, curline, curchar);
+                       modify();
+                       makedirty(curline);
+                       LineInsert(1);
+                       DOTsave(&save);
+                       llen = strlen(linebuf);
+               }
+               if (c != '\n') {
+                       ins_c(c, linebuf, curchar++, 1, LBSIZE);
+                       llen += 1;
+               }
+       }
+       IFixMarks(save.p_line, save.p_char, curline, curchar);
+       modify();
+       makedirty(curline);
+}
+
+void
+open_lines(n)
+{
+       Bufpos  dot;
+
+       DOTsave(&dot);
+       LineInsert(n);  /* Open the lines... */
+       SetDot(&dot);
+}
+
+void
+OpenLine()
+{
+       open_lines(arg_value());
+}
+
+/* Take the region FLINE/FCHAR to TLINE/TCHAR and insert it at
+   ATLINE/ATCHAR in WHATBUF. */
+
+Bufpos *
+DoYank(fline, fchar, tline, tchar, atline, atchar, whatbuf)
+Line   *fline,
+       *tline,
+       *atline;
+Buffer *whatbuf;
+{
+       register Line   *newline;
+       static Bufpos   bp;
+       char    save[LBSIZE],
+               buf[LBSIZE];
+       Line    *startline = atline;
+       int     startchar = atchar;
+
+       lsave();
+       if (whatbuf)
+               modify();
+       (void) ltobuf(atline, genbuf);
+       strcpy(save, &genbuf[atchar]);
+
+       (void) ltobuf(fline, buf);
+       if (fline == tline)
+               buf[tchar] = '\0';
+
+       linecopy(genbuf, atchar, &buf[fchar]);
+       atline->l_dline = putline(genbuf);
+       makedirty(atline);
+
+       fline = fline->l_next;
+       while (fline != tline->l_next) {
+               newline = listput(whatbuf, atline);
+               newline->l_dline = fline->l_dline;
+               makedirty(newline);
+               fline = fline->l_next;
+               atline = newline;
+               atchar = 0;
+       }
+
+       getline(atline->l_dline, genbuf);
+       atchar += tchar;
+       linecopy(genbuf, atchar, save);
+       atline->l_dline = putline(genbuf);
+       makedirty(atline);
+       IFixMarks(startline, startchar, atline, atchar);
+       bp.p_line = atline;
+       bp.p_char = atchar;
+       this_cmd = YANKCMD;
+       getDOT();                       /* Whatever used to be in linebuf */
+       return &bp;
+}
+
+void
+YankPop()
+{
+       Line    *line,
+               *last;
+       Mark    *mp = CurMark();
+       Bufpos  *dot;
+       int     dir = -1;       /* Direction to rotate the ring */
+
+       if (last_cmd != YANKCMD)
+               complain("Yank something first!");
+
+       lfreelist(reg_delete(mp->m_line, mp->m_char, curline, curchar));
+
+       /* Now must find a recently killed region. */
+
+       if (arg_value() < 0)
+               dir = 1;
+
+       killptr += dir;
+       for (;;) {
+               if (killptr < 0)
+                       killptr = NUMKILLS - 1;
+               else if (killptr >= NUMKILLS)
+                       killptr = 0;
+               if (killbuf[killptr])
+                       break;
+               killptr += dir;
+       }
+
+       this_cmd = YANKCMD;
+
+       line = killbuf[killptr];
+       last = lastline(line);
+       dot = DoYank(line, 0, last, length(last), curline, curchar, curbuf);
+       MarkSet(CurMark(), curline, curchar);
+       SetDot(dot);
+}
+
+/* This is an attempt to reduce the amount of memory taken up by each line.
+   Without this each malloc of a line uses sizeof (line) + sizeof(HEADER)
+   where line is 3 words and HEADER is 1 word.
+   This is going to allocate memory in chucks of CHUNKSIZE * sizeof (line)
+   and divide each chuck into lineS.  A line is free in a chunk when its
+   line->l_dline == 0, so freeline sets dline to 0. */
+
+#define CHUNKSIZE      300
+
+struct chunk {
+       int     c_nlines;       /* Number of lines in this chunk (so they
+                                  don't all have to be CHUNKSIZE long). */
+       Line    *c_block;       /* Chunk of memory */
+       struct chunk    *c_nextfree;    /* Next chunk of lines */
+};
+
+private struct chunk   *fchunk = 0;
+private Line   *ffline = 0;    /* First free line */
+
+void
+freeline(line)
+register Line  *line;
+{
+       line->l_dline = 0;
+       line->l_next = ffline;
+       if (ffline)
+               ffline->l_prev = line;
+       line->l_prev = 0;
+       ffline = line;
+}
+
+void
+lfreelist(first)
+register Line  *first;
+{
+       if (first)
+               lfreereg(first, lastline(first));
+}
+
+/* Append region from line1 to line2 onto the free list of lines */
+
+void
+lfreereg(line1, line2)
+register Line  *line1,
+               *line2;
+{
+       register Line   *next,
+                       *last = line2->l_next;
+
+       while (line1 != last) {
+               next = line1->l_next;
+               freeline(line1);
+               line1 = next;
+       }
+}
+
+private int
+newchunk()
+{
+       register Line   *newline;
+       register int    i;
+       struct chunk    *f;
+       int     nlines = CHUNKSIZE;
+
+       f = (struct chunk *) emalloc(sizeof (struct chunk));
+       if (f == 0)
+               return 0;
+
+       if ((f->c_block = (Line *) malloc((unsigned) (sizeof (Line) * nlines))) == 0) {
+               while (nlines > 0) {
+                       f->c_block = (Line *) malloc((unsigned) (sizeof (Line) * nlines));
+                       if (f->c_block != 0)
+                               break;
+                       nlines /= 2;
+               }
+       }
+
+       if (nlines <= 0)
+               return 0;
+
+       f->c_nlines = nlines;
+       for (i = 0, newline = f->c_block; i < nlines; newline++, i++)
+               freeline(newline);
+       f->c_nextfree = fchunk;
+       fchunk = f;
+       return 1;
+}
+
+/* New BUFfer LINE */
+
+Line *
+nbufline()
+{
+       register Line   *newline;
+
+       if (ffline == 0)        /* No free list */
+               if (newchunk() == 0)
+                       complain("[Out of lines] ");
+       newline = ffline;
+       ffline = ffline->l_next;
+       if (ffline)
+               ffline->l_prev = 0;
+       return newline;
+}
+
+/* Remove the free lines, in chunk c, from the free list because they are
+   no longer free. */
+
+private void
+remfreelines(c)
+register struct chunk  *c;
+{
+       register Line   *lp;
+       register int    i;
+
+       for (lp = c->c_block, i = 0; i < c->c_nlines; i++, lp++) {
+               if (lp->l_prev)
+                       lp->l_prev->l_next = lp->l_next;
+               else
+                       ffline = lp->l_next;
+               if (lp->l_next)
+                       lp->l_next->l_prev = lp->l_prev;
+       }
+}
+
+/* This is used to garbage collect the chunks of lines when malloc fails
+   and we are NOT looking for a new buffer line.  This goes through each
+   chunk, and if every line in a given chunk is not allocated, the entire
+   chunk is `free'd by "free()". */
+
+void
+GCchunks()
+{
+       register struct chunk   *cp;
+       struct chunk    *prev = 0,
+                       *next = 0;
+       register int    i;
+       register Line   *newline;
+
+       for (cp = fchunk; cp != 0; cp = next) {
+               for (i = 0, newline = cp->c_block; i < cp->c_nlines; newline++, i++)
+                       if (newline->l_dline != 0)
+                               break;
+
+               next = cp->c_nextfree;
+
+               if (i == cp->c_nlines) {                /* Unlink it!!! */
+                       if (prev)
+                               prev->c_nextfree = cp->c_nextfree;
+                       else
+                               fchunk = cp->c_nextfree;
+                       remfreelines(cp);
+                       free((char *) cp->c_block);
+                       free((char *) cp);
+               } else
+                       prev = cp;
+       }
+}
+
+#ifdef LISP
+
+/* Grind S-Expr */
+
+void
+GSexpr()
+{
+       Bufpos  dot,
+               end;
+
+       if (linebuf[curchar] != '(')
+               complain((char *) 0);
+       DOTsave(&dot);
+       FSexpr();
+       DOTsave(&end);
+       SetDot(&dot);
+       for (;;) {
+               if (curline == end.p_line)
+                       break;
+               line_move(FORWARD, 1, NO);
+               if (!blnkp(linebuf))
+                       (void) lisp_indent();
+       }
+       SetDot(&dot);
+}
+
+/* lisp_indent() indents a new line in Lisp Mode, according to where
+   the matching close-paren would go if we typed that (sort of). */
+
+private Table  *specials = NIL;
+
+private void
+init_specials()
+{
+       static char *words[] = {
+               "case",
+               "def",
+               "dolist",
+               "fluid-let",
+               "lambda",
+               "let",
+               "lexpr",
+               "macro",
+               "named-l",      /* named-let and named-lambda */
+               "nlambda",
+               "prog",
+               "selectq",
+               0
+       };
+       char    **wordp = words;
+
+       specials = make_table();
+       while (*wordp)
+               add_word(*wordp++, specials);
+}
+
+void
+AddSpecial()
+{
+       char    *word;
+
+       word = ask((char *) 0, ProcFmt);
+       if (specials == NIL)
+               init_specials();
+       add_word(copystr(word), specials);
+}
+
+Bufpos *
+lisp_indent()
+{
+       Bufpos  *bp,
+               savedot;
+       int     goal;
+
+       bp = m_paren(')', BACKWARD, NO, YES);
+
+       if (bp == 0)
+               return 0;
+
+       /* We want to end up
+        
+               (atom atom atom ...
+                     ^ here.
+        */
+
+       DOTsave(&savedot);
+       SetDot(bp);
+       f_char(1);
+       if (linebuf[curchar] != '(') {
+               register Word   *wp;
+
+               if (specials == NIL)
+                       init_specials();
+               for (wp = table_top(specials); wp != NIL; wp = next_word(wp))
+                       if (casencmp(word_text(wp), &linebuf[curchar], word_length(wp)) == 0)
+                               break;
+               if (wp == NIL) {        /* not special */
+                       int     c_char = curchar;
+
+                       WITH_TABLE(curbuf->b_major)
+                               f_word(1);
+                       END_TABLE();
+                       if (LookingAt("[ \t]*;\\|[ \t]*$", linebuf, curchar))
+                               curchar = c_char;
+                       else while (linebuf[curchar] == ' ')
+                               curchar += 1;
+               } else
+                       curchar += 1;
+       }
+       goal = calc_pos(linebuf, curchar);
+       SetDot(&savedot);
+       n_indent(goal);
+
+       return bp;
+}
+#endif /* LISP */
diff --git a/usr/src/new/jove/io.h b/usr/src/new/jove/io.h
new file mode 100644 (file)
index 0000000..0b881cf
--- /dev/null
@@ -0,0 +1,48 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+#define putchar(c)     putc(c, stdout)
+#define putc(c, fp)    (--(fp)->f_cnt >= 0 ? (*(fp)->f_ptr++ = (c)) : _flush((c), fp))
+#define getc(fp)       (((--(fp)->f_cnt < 0) ? filbuf(fp) : *(fp)->f_ptr++))
+
+typedef struct File {
+       int     f_cnt,          /* number of characters left in buffer */
+               f_bufsize,      /* size of what f_base points to */
+               f_fd,           /* fildes */
+               f_flags;        /* various flags */
+       char    *f_ptr,         /* current offset */
+               *f_base;        /* pointer to base */
+       char    *f_name;        /* name of open file */
+} File;
+
+#define F_READ         01
+#define F_WRITE                02
+#define F_APPEND       04
+#define F_MODE(x)      (x&07)
+#define F_EOF          010
+#define F_STRING       020
+#define F_ERR          040
+#define F_LOCKED       0100    /* don't close this file upon error */
+#define F_MYBUF                0200    /* f_alloc allocated the buffer, so
+                                  f_close knows to free it up */
+#define F_TELLALL      0400    /* whether to display info upon close */
+
+extern long    io_chars;
+extern int     io_lines;
+
+extern File
+       *stdout,
+
+       *open_file(),
+       *fd_open(),
+       *f_open();
+
+#ifdef VMUNIX
+#   define MAXTTYBUF   2048
+#else
+#   define MAXTTYBUF   512
+#endif
diff --git a/usr/src/new/jove/iproc-pipes.c b/usr/src/new/jove/iproc-pipes.c
new file mode 100644 (file)
index 0000000..e45e26e
--- /dev/null
@@ -0,0 +1,307 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+#ifdef BSD4_2
+#   include <sys/wait.h>
+#else
+#   include <wait.h>
+#endif
+#include <signal.h>
+#include <sgtty.h>
+
+#define DEAD   1       /* Dead but haven't informed user yet */
+#define STOPPED        2       /* Job stopped */
+#define RUNNING        3       /* Just running */
+#define NEW    4       /* This process is brand new */
+
+/* If process is dead, flags says how. */
+#define EXITED 1
+#define KILLED 2
+
+#define isdead(p)      (p == 0 || proc_state(p) == DEAD || p->p_toproc == -1)
+#define makedead(p)    (proc_state(p) = DEAD)
+
+#define proc_buf(p)    (p->p_buffer->b_name)
+#define proc_cmd(p)    (p->p_name)
+#define proc_state(p)  (p->p_state)
+
+private Process        *procs = 0;
+
+int    ProcInput,
+       ProcOutput,
+       NumProcs = 0;
+
+char *
+pstate(p)
+Process        *p;
+{
+       switch (proc_state(p)) {
+       case NEW:
+               return "Pre-birth";
+
+       case STOPPED:
+               return "Stopped";
+
+       case RUNNING:
+               return "Running";
+
+       case DEAD:
+               if (p->p_howdied == EXITED) {
+                       if (p->p_reason == 0)
+                               return "Done";
+                       return sprint("Exit %d", p->p_reason);
+               }
+               return sprint("Killed %d", p->p_reason);
+
+       default:
+               return "Unknown state";
+       }
+}
+
+static Process *
+proc_pid(pid)
+{
+       register Process        *p;
+
+       for (p = procs; p != 0; p = p->p_next)
+               if (p->p_portpid == pid)
+                       break;
+
+       return p;
+}
+
+procs_read()
+{
+       struct header {
+               int     pid;
+               int     nbytes;
+       } header;
+       int     n;
+       long    nbytes;
+       static int      here = NO;
+
+       if (here)       
+               return;
+       sighold(SIGCHLD);       /* block any other children */
+       here = YES;
+       for (;;) {
+               (void) ioctl(ProcInput, FIONREAD, (struct sgttyb *) &nbytes);
+               if (nbytes < sizeof header)
+                       break;
+               n = read(ProcInput, (char *) &header, sizeof header);
+               if (n != sizeof header)
+                       finish(1);
+               read_proc(header.pid, header.nbytes);
+       }
+       here = NO;
+       sigrelse(SIGCHLD);
+}
+
+read_proc(pid, nbytes)
+int    pid;
+register int   nbytes;
+{
+       register Process        *p;
+       int     n;
+       char    ibuf[512];
+
+       if ((p = proc_pid(pid)) == 0) {
+               printf("\riproc: unknown pid (%d)", pid);
+               return;
+       }
+       if (proc_state(p) == NEW) {
+               int     rpid;
+               /* pid of real child, not of portsrv */
+
+               doread(ProcInput, (char *) &rpid, nbytes);
+               nbytes -= sizeof rpid;
+               p->p_pid = rpid;
+               p->p_state = RUNNING;
+       }
+
+       if (nbytes == EOF) {            /* okay to clean up this process */
+               proc_close(p);
+               makedead(p);
+               return;
+       }
+
+       while (nbytes > 0) {
+               n = min((sizeof ibuf) - 1, nbytes);
+               doread(ProcInput, ibuf, n);
+               ibuf[n] = 0;    /* Null terminate for convenience */
+               nbytes -= n;
+               proc_rec(p, ibuf);
+       }
+}
+
+ProcKill()
+{
+       proc_kill(curbuf->b_process, SIGKILL);
+}
+
+ProcInt()
+{
+       proc_kill(curbuf->b_process, SIGINT);
+}
+
+ProcQuit()
+{
+       proc_kill(curbuf->b_process, SIGQUIT);
+}
+
+private
+proc_close(p)
+Process        *p;
+{
+       sighold(SIGCHLD);
+
+       if (p->p_toproc >= 0) {
+               (void) close(p->p_toproc);
+               p->p_toproc = -1;       /* writes will fail */
+               NumProcs -= 1;
+       }
+
+       sigrelse(SIGCHLD);
+}
+
+do_rtp(mp)
+register Mark  *mp;
+{
+       register Process        *p = curbuf->b_process;
+       Line    *line1 = curline,
+               *line2 = mp->m_line;
+       int     char1 = curchar,
+               char2 = mp->m_char;
+       char    *gp;
+
+       if (isdead(p) || p->p_buffer != curbuf)
+               return;
+
+       (void) fixorder(&line1, &char1, &line2, &char2);
+       while (line1 != line2->l_next) {
+               gp = ltobuf(line1, genbuf) + char1;
+               if (line1 == line2)
+                       gp[char2] = '\0';
+               else
+                       strcat(gp, "\n");
+               (void) write(p->p_toproc, gp, strlen(gp));
+               line1 = line1->l_next;
+               char1 = 0;
+       }
+}
+
+/* VARARGS3 */
+
+private
+proc_strt(bufname, clobber, va_alist)
+char   *bufname;
+va_dcl
+{
+       Window  *owind = curwind;
+       int     toproc[2],
+               pid;
+       Process *newp;
+       Buffer  *newbuf;
+       char    *argv[32],
+               *cp,
+               foo[10],
+               cmdbuf[128];
+       int     i;
+       va_list ap;
+
+       isprocbuf(bufname);     /* make sure BUFNAME is either nonexistant
+                                  or is of type B_PROCESS */
+       dopipe(toproc);
+
+       sighold(SIGCHLD);
+#ifdef SIGWINCH
+       sighold(SIGWINCH);
+#endif
+       switch (pid = fork()) {
+       case -1:
+               pclose(toproc);
+               complain("[Fork failed.]");
+
+       case 0:
+               sigrelse(SIGCHLD);
+#ifdef SIGWINCH
+               sigrelse(SIGWINCH);
+#endif
+               argv[0] = "portsrv";
+               argv[1] = foo;
+               sprintf(foo, "%d", ProcInput);
+               va_start(ap);
+               make_argv(&argv[2], ap);
+               va_end(ap);
+               (void) dup2(toproc[0], 0);
+               (void) dup2(ProcOutput, 1);
+               (void) dup2(ProcOutput, 2);
+               pclose(toproc);
+               execv(Portsrv, argv);
+               printf("execl failed\n");
+               _exit(1);
+       }
+
+       newp = (Process *) malloc(sizeof *newp);
+       newp->p_next = procs;
+       newp->p_state = NEW;
+       newp->p_cmd = 0;
+
+       cmdbuf[0] = '\0';
+       va_start(ap);
+       while (cp = va_arg(ap, char *))
+               sprintf(&cmdbuf[strlen(cmdbuf)], "%s ", cp);
+       va_end(ap);
+       newp->p_name = copystr(cmdbuf);
+       procs = newp;
+       newp->p_portpid = pid;
+       newp->p_pid = -1;
+
+       newbuf = do_select((Window *) 0, bufname);
+       newbuf->b_type = B_PROCESS;
+       newp->p_buffer = newbuf;
+       newbuf->b_process = newp;       /* sorta circular, eh? */
+       pop_wind(bufname, clobber, B_PROCESS);
+       ToLast();
+       if (!bolp())
+               LineInsert(1);
+       /* Pop_wind() after everything is set up; important!
+          Bindings won't work right unless newbuf->b_process is already
+          set up BEFORE NEWBUF is first SetBuf()'d. */
+       newp->p_mark = MakeMark(curline, curchar, M_FLOATER);
+
+       newp->p_toproc = toproc[1];
+       newp->p_reason = 0;
+       NumProcs += 1;
+       (void) close(toproc[0]);
+       SetWind(owind);
+       sigrelse(SIGCHLD);
+#ifdef SIGWINCH
+       sigrelse(SIGWINCH);
+#endif
+}
+
+pinit()
+{
+       int     p[2];
+
+       (void) signal(SIGCHLD, proc_child);
+       (void) pipe(p);
+       ProcInput = p[0];
+       ProcOutput = p[1];
+       (void) signal(INPUT_SIG, procs_read);
+       sighold(INPUT_SIG);     /* Released during terminal read */
+}
+
+doread(fd, buf, n)
+char   *buf;
+{
+       int     nread;
+
+       if ((nread = read(fd, buf, n)) != n)
+               complain("Cannot read %d (got %d) bytes.", n, nread);
+}
diff --git a/usr/src/new/jove/iproc-ptys.c b/usr/src/new/jove/iproc-ptys.c
new file mode 100644 (file)
index 0000000..b9f5958
--- /dev/null
@@ -0,0 +1,427 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+#ifdef BSD4_2
+#   include <sys/wait.h>
+#else
+#   include <wait.h>
+#endif
+#include <signal.h>
+#include <sgtty.h>
+#include <errno.h>
+
+#define DEAD   1       /* dead but haven't informed user yet */
+#define STOPPED        2       /* job stopped */
+#define RUNNING        3       /* just running */
+#define NEW    4       /* brand new, never been ... received no input */
+
+/* If process is dead, flags says how. */
+#define EXITED 1
+#define KILLED 2
+
+#define isdead(p)      (p == 0 || proc_state(p) == DEAD || p->p_fd == -1)
+#define makedead(p)    (proc_state(p) = DEAD)
+
+#define proc_buf(p)    (p->p_buffer->b_name)
+#define proc_cmd(p)    (p->p_name)
+#define proc_state(p)  (p->p_state)
+
+private Process        *procs = 0;
+
+long   global_fd = 1;
+int    NumProcs = 0;
+
+#ifdef BRLUNIX
+       extern struct sg_brl sg1;
+#else
+       extern struct sgttyb sg1;
+#endif
+
+extern struct tchars tc1;
+
+#ifdef TIOCSLTC
+       extern struct ltchars ls1;
+#endif
+
+char *
+pstate(p)
+Process        *p;
+{
+       switch (proc_state(p)) {
+       case STOPPED:
+               return "Stopped";
+
+       case RUNNING:
+               return "Running";
+
+       case DEAD:
+               if (p->p_howdied == EXITED) {
+                       if (p->p_reason == 0)
+                               return "Done";
+                       return sprint("Exit %d", p->p_reason);
+               }
+               return sprint("Killed %d", p->p_reason);
+
+       case NEW:
+               return "New";
+
+       default:
+               return "Unknown state";
+       }
+}
+
+static Process *
+proc_pid(pid)
+{
+       register Process        *p;
+
+       for (p = procs; p != 0; p = p->p_next)
+               if (p->p_pid == pid)
+                       break;
+
+       return p;
+}
+
+read_proc(fd)
+register int   fd;
+{
+       register Process        *p;
+       unsigned int    n;
+       char    ibuf[1024];
+
+       for (p = procs; p != 0; p = p->p_next)
+               if (p->p_fd == fd)
+                       break;
+
+       if (p == 0) {
+               printf("\riproc: unknown fd %d", fd);
+               return;
+       }
+
+       n = read(fd, ibuf, sizeof(ibuf) - 1);
+       if (n == -1 && errno == EIO) {
+               if (proc_state(p) == NEW)
+                       return;
+               proc_close(p);
+               makedead(p);
+               return;
+       } else {
+               if (proc_state(p) != RUNNING) {
+                       proc_state(p) = RUNNING;
+                       UpdModLine = YES;
+               }
+       }
+       if (n <= 0) {
+               if (n == 0)
+                       strcpy(ibuf, "[Process EOF]");
+               else
+                       sprintf(ibuf, "\n[pty read error: %d]\n", errno);
+       } else
+               ibuf[n] = '\0';
+       proc_rec(p, ibuf);
+}
+
+ProcKill()
+{
+       register Buffer *b;
+       Process *buf_to_proc();
+       char    *bname;
+
+       bname = ask_buf(curbuf);
+
+       if ((b = buf_exists(bname)) == 0)
+               complain("[No such buffer]");
+       if (b->b_process == 0)
+               complain("%s not tied to a process.", bname);
+       proc_kill(b->b_process, SIGKILL);
+}
+
+ProcCont()
+{
+       Process *p;
+
+       if ((p = curbuf->b_process) == 0)
+               complain("[No process]");
+       if (p->p_state != DEAD) {
+               proc_kill(p, SIGCONT);
+               p->p_state = RUNNING;
+       }               
+}
+
+ProcEof()
+{
+       send_p(tc1.t_eofc);
+}
+
+ProcInt()
+{
+       send_p(tc1.t_intrc);
+}
+
+ProcQuit()
+{
+       send_p(tc1.t_quitc);
+}
+
+ProcStop()
+{
+       send_p(ls1.t_suspc);
+}
+
+ProcDStop()
+{
+       send_p(ls1.t_dsuspc);
+}
+
+send_p(c)
+char   c;
+{
+       Process *p;
+       char    buf[2];
+
+       if ((p = curbuf->b_process) == 0)
+               complain("[No process]");
+       ToLast();
+       buf[0] = c;
+       buf[1] = '\0';
+       proc_rec(p, buf);
+       (void) write(p->p_fd, &c, 1);
+}
+
+private
+proc_close(p)
+Process *p;
+{
+       sighold(SIGCHLD);       /* be mutually exclusive */
+
+       if (p->p_fd >= 0) {
+               (void) close(p->p_fd);
+               global_fd &= ~(1L << p->p_fd);
+               NumProcs -= 1;
+               p->p_fd = -1;
+       }
+
+       sigrelse(SIGCHLD);
+}
+
+do_rtp(mp)
+register Mark  *mp;
+{
+       register Process        *p = curbuf->b_process;
+       Line    *line1 = curline,
+               *line2 = mp->m_line;
+       int     char1 = curchar,
+               char2 = mp->m_char;
+       char    *gp;
+       int     nbytes;
+
+       if (isdead(p) || p->p_buffer != curbuf)
+               return;
+
+       (void) fixorder(&line1, &char1, &line2, &char2);
+       while (line1 != line2->l_next) {
+               gp = ltobuf(line1, genbuf) + char1;
+               if (line1 == line2)
+                       gp[char2] = '\0';
+               else
+                       strcat(gp, "\n");
+               if (nbytes = strlen(gp))
+                       (void) write(p->p_fd, gp, nbytes);
+               line1 = line1->l_next;
+               char1 = 0;
+       }
+}
+
+/* VARARGS2 */
+
+private
+proc_strt(bufname, clobber, va_alist)
+char   *bufname;
+va_dcl
+{
+       va_list ap;
+       char    *argv[32],
+               *cp;
+       Window *owind = curwind;
+       int     pid;
+       Process *newp;
+       Buffer  *newbuf;
+       int     i,
+               ptyfd,
+               ttyfd,
+               ldisc,
+               lmode;
+       register char   *s,
+                       *t;
+       extern int      errno;
+       static char     ttybuf[11],
+                       ptybuf[11];
+       char    cmdbuf[128];
+#ifdef BRLUNIX
+       struct sg_brl sg;
+#else
+       struct sgttyb sg;
+#endif
+
+#ifdef TIOCGWINSZ
+       struct winsize win;
+#else
+#  ifdef BTL_BLIT
+#  include <sys/jioctl.h>
+       struct jwinsize jwin;
+#  endif
+#endif
+
+       isprocbuf(bufname);     /* make sure BUFNAME is either nonexistant
+                                  or is of type B_PROCESS */
+       for (s = "pqrs"; *s; s++) {
+               for (t = "0123456789abcdef"; *t; t++) {
+                       sprintf(ptybuf, "/dev/pty%c%c", *s, *t);
+                       if ((ptyfd = open(ptybuf, 2)) >= 0) {
+                               strcpy(ttybuf, ptybuf);
+                               ttybuf[5] = 't';
+                               /* make sure both ends are available */
+                               if ((i = open(ttybuf, 2)) < 0)
+                                       continue;
+                               (void) close(i);
+                               goto out;
+                       }
+               }
+       }
+
+out:   if (s == 0 && t == 0)
+               complain("[Out of ptys!]");
+
+#ifdef TIOCGETD
+       (void) ioctl(0, TIOCGETD, (struct sgttyb *) &ldisc);
+#endif
+#ifdef TIOCLGET
+       (void) ioctl(0, TIOCLGET, (struct sgttyb *) &lmode);
+#endif
+#ifdef TIOCGWINSZ
+       (void) ioctl(0, TIOCGWINSZ, (struct sgttyb *) &win);
+#else
+#  ifdef BTL_BLIT
+       (void) ioctl(0, JWINSIZE, (struct sgttyb *) &jwin);
+#  endif /* BTL_BLIT */
+#endif
+
+       sighold(SIGCHLD);
+#ifdef SIGWINCH
+       sighold(SIGWINCH);
+#endif
+       switch (pid = fork()) {
+       case -1:
+               (void) close(ptyfd);
+               message("[Fork failed!]");
+               goto fail;
+
+       case 0:
+               sigrelse(SIGCHLD);
+#ifdef SIGWINCH
+               sigrelse(SIGWINCH);
+#endif
+               for (i = 0; i < 32; i++)
+                       (void) close(i);
+
+#ifdef TIOCNOTTY
+               if ((i = open("/dev/tty", 2)) >= 0) {
+                       (void) ioctl(i, TIOCNOTTY, (struct sgttyb *) 0);
+                       (void) close(i);
+               }
+#endif
+               if ((ttyfd = open(ttybuf, 2)) < 0)
+                       exit(-1);
+               (void) dup2(ttyfd, 1);
+               (void) dup2(ttyfd, 2);
+
+#ifdef TIOCSETD
+               (void) ioctl(0, TIOCSETD, (struct sgttyb *) &ldisc);
+#endif
+#ifdef TIOCLSET
+               (void) ioctl(0, TIOCLSET, (struct sgttyb *) &lmode);
+#endif
+#ifdef TIOCSETC
+               (void) ioctl(0, TIOCSETC, (struct sgttyb *) &tc1);
+#endif
+#ifdef TIOCSLTC
+               (void) ioctl(0, TIOCSLTC, (struct sgttyb *) &ls1);
+#endif
+
+#ifdef TIOCGWINSZ
+#    ifdef SIGWINCH
+               (void) signal(SIGWINCH, SIG_IGN);
+#    endif
+               win.ws_row = curwind->w_height;
+               (void) ioctl(0, TIOCSWINSZ, (struct sgttyb *) &win);
+#else
+#  ifdef BTL_BLIT
+               jwin.bytesy = curwind->w_height;
+               (void) ioctl(0, JSWINSIZE, (struct sgttyb *) &jwin);
+#  endif
+#endif
+
+               sg = sg1;
+               sg.sg_flags &= ~(ECHO | CRMOD);
+               (void) stty(0, &sg);
+
+               i = getpid();
+               (void) ioctl(0, TIOCSPGRP, (struct sgttyb *) &i);
+               (void) setpgrp(0, i);
+               va_start(ap);
+               make_argv(argv, ap);
+               va_end(ap);
+               execv(argv[0], &argv[1]);
+               (void) write(1, "execve failed!\n", 15);
+               _exit(errno + 1);
+       }
+
+       newp = (Process *) emalloc(sizeof *newp);
+
+       newp->p_fd = ptyfd;
+       newp->p_pid = pid;
+
+       newbuf = do_select((Window *) 0, bufname);
+       newbuf->b_type = B_PROCESS;
+       newp->p_buffer = newbuf;
+       newbuf->b_process = newp;       /* sorta circular, eh? */
+       pop_wind(bufname, clobber, B_PROCESS);
+       /* Pop_wind() after everything is set up; important!
+          Bindings won't work right unless newbuf->b_process is already
+          set up BEFORE NEWBUF is first SetBuf()'d. */
+       ToLast();
+       if (!bolp())
+               LineInsert(1);
+
+       cmdbuf[0] = '\0';
+       va_start(ap);
+       while (cp = va_arg(ap, char *))
+               sprintf(&cmdbuf[strlen(cmdbuf)], "%s ", cp++);
+       va_end(ap);
+
+       newp->p_name = copystr(cmdbuf);
+       newp->p_state = NEW;
+       newp->p_reason = 0;
+       newp->p_mark = MakeMark(curline, curchar, M_FLOATER);
+
+       newp->p_next = procs;
+       procs = newp;
+       NumProcs += 1;
+       global_fd |= 1L << newp->p_fd;
+       SetWind(owind);
+
+fail:  sigrelse(SIGCHLD);
+#ifdef SIGWINCH
+       sigrelse(SIGWINCH);
+#endif
+}
+       
+pinit()
+{
+       (void) signal(SIGCHLD, proc_child);
+}
+
diff --git a/usr/src/new/jove/iproc.c b/usr/src/new/jove/iproc.c
new file mode 100644 (file)
index 0000000..87dfa84
--- /dev/null
@@ -0,0 +1,423 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+#include "jove.h"
+#include "re.h"
+#include <varargs.h>
+
+#ifdef IPROCS
+
+int    proc_child();
+
+#ifdef PIPEPROCS
+#   include "iproc-pipes.c"
+#else
+#   include "iproc-ptys.c"
+#endif
+
+char   proc_prompt[128] = "% ";
+
+KillProcs()
+{
+       register Process        *p;
+       register int    killem = -1;            /* -1 means undetermined */
+       register char   *yorn;
+
+       for (p = procs; p != 0; p = p->p_next)
+               if (!isdead(p)) {
+                       if (killem == -1) {
+                               yorn = ask("y", "Should I kill your i-processes? ");
+                               killem = (CharUpcase(*yorn) == 'Y');
+                       }
+                       if (killem)
+                               proc_kill(p, SIGKILL);
+               }
+}
+
+pbuftiedp(b)
+register Buffer        *b;
+{
+       register Process        *p = b->b_process;
+
+       if (!isdead(p))
+               complain("Process %s, attached to %b, is %s.",
+                        proc_cmd(p), b, pstate(p));
+}
+
+/* Process receive: receives the characters in buf, and appends them to
+   the buffer associated with p. */
+
+private
+proc_rec(p, buf)
+register Process       *p;
+char   *buf;
+{
+       Buffer  *saveb = curbuf;
+       register Window *w;
+       register Mark   *savepoint;
+       int     sameplace = NO,
+               do_disp = NO;
+
+       if (curwind->w_bufp == p->p_buffer)
+               w = curwind;
+       else
+               w = windbp(p->p_buffer);        /* Is this window visible? */
+       if (w != 0)
+               do_disp = (in_window(w, p->p_mark->m_line) != -1);
+       SetBuf(p->p_buffer);
+       savepoint = MakeMark(curline, curchar, M_FLOATER);
+       ToMark(p->p_mark);              /* where output last stopped */
+       if (savepoint->m_line == curline && savepoint->m_char == curchar)
+               sameplace = YES;
+
+       ins_str(buf, YES);
+       MarkSet(p->p_mark, curline, curchar);
+       if (!sameplace)
+               ToMark(savepoint);      /* back to where we were */
+       DelMark(savepoint);
+       /* redisplay now, instead of right after the ins_str, so that
+          we don't get a bouncing effect if point is not the same as
+          the process output position */
+       if (do_disp) {
+               w->w_line = curline;
+               w->w_char = curchar;
+               redisplay();
+       }
+       SetBuf(saveb);
+}
+
+proc_kill(p, sig)
+register Process       *p;
+{
+       if (isdead(p))
+               return;
+       if (killpg(p->p_pid, sig) == -1)
+               s_mess("Cannot kill %s!", proc_buf(p));
+}
+
+/* Free process CHILD.  Do all the necessary cleaning up (closing fd's,
+   etc.). */
+
+free_proc(child)
+Process        *child;
+{
+       register Process        *p,
+                               *prev = 0;
+
+       if (!isdead(child))
+               return; 
+       for (p = procs; p != child; prev = p, p = p->p_next)
+               ;
+       if (prev == 0)
+               procs = child->p_next;
+       else
+               prev->p_next = child->p_next;
+       proc_close(child);              /* if not already closed */
+       
+       /* It's possible that the buffer has been given another process
+          between the time CHILD dies and CHILD's death is noticed (via
+          list-processes).  So we only set it the buffer's process to
+          0 if CHILD is still the controlling process. */
+       if (child->p_buffer->b_process == child) {
+               child->p_buffer->b_process = 0;
+               if (curbuf == child->p_buffer)
+                       PopPBs();
+       }
+       {
+               Buffer  *old = curbuf;
+
+               SetBuf(child->p_buffer);
+               DelMark(child->p_mark);
+               SetBuf(old);
+       }
+       free((char *) child->p_name);
+       free((char *) child);
+}
+
+ProcList()
+{
+       register Process        *p,
+                               *next;
+       char    *fmt = "%-15s  %-15s  %-8s %s",
+               pidstr[16];
+
+       if (procs == 0) {
+               message("[No subprocesses]");
+               return;
+       }
+       TOstart("Process list", TRUE);
+
+       Typeout(fmt, "Buffer", "Status", "Pid ", "Command");
+       Typeout(fmt, "------", "------", "--- ", "-------");
+       for (p = procs; p != 0; p = next) {
+               next = p->p_next;
+               sprintf(pidstr, "%d", p->p_pid);
+               Typeout(fmt, proc_buf(p), pstate(p), pidstr, p->p_name);
+               if (isdead(p)) {
+                       free_proc(p);
+                       UpdModLine = YES;
+               }
+       }
+       TOstop();
+}
+
+ProcNewline()
+{
+#ifdef ABBREV
+       MaybeAbbrevExpand();
+#endif
+       SendData(YES);
+}
+
+ProcSendData()
+{
+#ifdef ABBREV
+       MaybeAbbrevExpand();
+#endif
+       SendData(NO);
+}
+
+private
+SendData(newlinep)
+{
+       register Process        *p = curbuf->b_process;
+       register char   *lp,
+                       *gp;    /* JF fix for better prompt handling */
+
+       if (isdead(p))
+               return;
+       /* If the process mark was involved in a big deletion, because
+          the user hit ^W or something, then let's do some magic with
+          the process mark.  Problem is that if the user yanks back the
+          text he deleted, the mark stays at the beginning of the region,
+          and so the next time SendData() is called the entire region
+          will be sent.  That's not good.  So, to deal with that we reset
+          the mark to the last line, after skipping over the prompt, etc. */
+       if (p->p_mark->m_flags & M_BIG_DELETE) {
+               Bufpos  bp;
+
+               p->p_mark->m_flags &= ~M_BIG_DELETE;
+
+               DOTsave(&bp);
+               ToLast();
+               Bol();
+               /* While we're looking at a prompt, and while we're
+                  moving forward.  This is for people who accidently
+                  set their process-prompt to ">*" which will always
+                  match! */
+               while ((LookingAt(proc_prompt, linebuf, curchar)) &&
+                      (REeom > curchar))
+                       curchar = REeom;
+               MarkSet(p->p_mark, curline, curchar);
+               SetDot(&bp);
+       }
+
+       if (lastp(curline)) {
+               Eol();
+               if (newlinep)
+                       LineInsert(1);
+               do_rtp(p->p_mark);
+               MarkSet(p->p_mark, curline, curchar);
+       } else {
+               /* Either we're looking at a prompt, or we're not, in
+                  which case we want to strip off the beginning of the
+                  line anything that looks like what the prompt at the
+                  end of the file is.  In other words, if "(dbx) stop in
+                  ProcessNewline" is the line we're on, and the last
+                  line in the buffer is "(dbx) ", then we strip off the
+                  leading "(dbx) " from this line, because we know it's
+                  part of the prompt.  But this only happens if "(dbx) "
+                  isn't one of the process prompts ... follow what I'm
+                  saying? */
+               Bol();
+               if (LookingAt(proc_prompt, linebuf, curchar)) {
+                       do
+                               curchar = REeom;
+                       while ((LookingAt(proc_prompt, linebuf, curchar)) &&
+                              (REeom > curchar));
+                       strcpy(genbuf, linebuf + curchar);
+                       Eof();
+                       ins_str(genbuf, NO);
+               } else {
+                       strcpy(genbuf, linebuf + curchar);
+                       Eof();
+                       gp = genbuf;
+                       lp = linebuf;
+                       while (*lp == *gp && *lp != '\0') {
+                               lp += 1;
+                               gp += 1;
+                       }
+                       ins_str(gp, NO);
+               }
+       }
+}
+
+ShellProc()
+{
+       char    *shbuf = "*shell*";
+       register Buffer *b;
+
+       b = buf_exists(shbuf);
+       if (b == 0 || isdead(b->b_process))
+               proc_strt(shbuf, NO, Shell, "-i", (char *) 0);
+       pop_wind(shbuf, NO, -1);
+}
+
+Iprocess()
+{
+       extern char     ShcomBuf[100],
+                       *MakeName();
+       register char   *command;
+       char    scratch[64],
+               *bufname;
+       int     cnt = 1;
+       Buffer  *bp;
+
+       command = ask(ShcomBuf, ProcFmt);
+       null_ncpy(ShcomBuf, command, (sizeof ShcomBuf) - 1);
+       bufname = MakeName(command);
+       strcpy(scratch, bufname);
+       while ((bp = buf_exists(scratch)) && !isdead(bp->b_process))
+               sprintf(scratch, "%s.%d", bufname, cnt++);
+       proc_strt(scratch, YES, Shell, ShFlags, command, (char *) 0);
+}
+
+proc_child()
+{
+       union wait      w;
+       register int    pid;
+
+       for (;;) {
+#ifndef BSD4_2
+               pid = wait2(&w.w_status, (WNOHANG | WUNTRACED));
+#else
+               pid = wait3(&w, (WNOHANG | WUNTRACED), (struct rusage *) 0);
+#endif
+               if (pid <= 0)
+                       break;
+               kill_off(pid, w);
+       }
+}
+
+kill_off(pid, w)
+register int   pid;
+union wait     w;
+{
+       register Process        *child;
+
+       if ((child = proc_pid(pid)) == 0)
+               return;
+
+       UpdModLine = YES;               /* we're changing state ... */
+       if (WIFSTOPPED(w))
+               child->p_state = STOPPED;
+       else {
+               child->p_state = DEAD;
+               if (WIFEXITED(w))
+                       child->p_howdied = EXITED;
+               else if (WIFSIGNALED(w)) {
+                       child->p_reason = w.w_termsig;
+                       child->p_howdied = KILLED;
+               }
+               {
+                       Buffer  *save = curbuf;
+                       char    mesg[128];
+
+                       /* insert status message now */
+                       sprintf(mesg, "[Process %s: %s]\n",
+                               proc_cmd(child),
+                               pstate(child));
+                       SetBuf(child->p_buffer);
+                       ins_str(mesg, NO);
+                       SetBuf(save);
+                       redisplay();
+               }
+       }
+}
+
+/* Push/pod process bindings.  I openly acknowledge that this is a
+   kludge, but I can't be bothered making it right. */
+
+struct proc_bind {
+       int             pb_key;
+       data_obj        **pb_map;
+       data_obj        *pb_push;
+       data_obj        *pb_cmd;
+       struct proc_bind *pb_next;
+};
+
+struct proc_bind *PBinds = 0;
+
+PopPBs()
+{
+       register struct proc_bind *p;
+
+       for (p = PBinds; p != 0; p = p->pb_next)
+               p->pb_map[p->pb_key] = p->pb_push;
+}
+
+PushPBs()
+{
+       register struct proc_bind *p;
+
+       for (p = PBinds; p != 0; p = p->pb_next) {
+               p->pb_push = p->pb_map[p->pb_key];
+               p->pb_map[p->pb_key] = p->pb_cmd;
+       }
+}
+/* VARARGS0 */
+
+ProcBind()
+{
+       register data_obj       *d;
+
+       if ((d = findcom(ProcFmt)) == 0)
+               return;
+       s_mess(": %f %s ", d->Name);
+       ProcB2(mainmap, EOF, d);
+}
+
+ProcB2(map, lastkey, cmd)
+data_obj       **map,
+               *cmd;
+{
+       register struct proc_bind *p;
+       register data_obj       **nextmap;
+       int     c;
+
+       c = addgetc();
+       if (c == EOF) {
+               if (lastkey == EOF)
+                       complain("[Empty key sequence]");
+               complain("[Unexpected end-of-line]");
+       } else {
+               if (nextmap = IsPrefix(map[c]))
+                       ProcB2(nextmap, c, cmd);
+               else {
+                       if (curbuf->b_process)
+                               PopPBs();
+
+                       for (p = PBinds; p != 0; p = p->pb_next)
+                               if (p->pb_key == c && p->pb_map == map)
+                                       break;
+                       if (p == 0) {
+                               p = (struct proc_bind *) emalloc(sizeof *p);
+                               p->pb_next = PBinds;
+                               PBinds = p;
+                       }
+                       p->pb_map = map;
+                       p->pb_key = c;
+                       p->pb_cmd = cmd;
+
+                       if (curbuf->b_process)
+                               PushPBs();
+               }
+       }
+}
+
+#endif /* IPROCS */
+
diff --git a/usr/src/new/jove/mac.h b/usr/src/new/jove/mac.h
new file mode 100644 (file)
index 0000000..e2661ab
--- /dev/null
@@ -0,0 +1,154 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+/* Macintosh related things. K. Mitchum 2/88 */
+
+
+#define NMENUS 6
+#define NMENUITEMS 40  /* This has GOT to be enough! */
+       
+typedef data_obj *menumap[NMENUITEMS];
+#ifndef _mac
+       typedef char **MenuHandle;
+#endif
+struct menu {
+       char *Name;
+       int menu_id;
+       MenuHandle Mn;
+       menumap m;
+};
+
+struct stat {
+       int st_dev;             /* volume number */
+       long st_ino;            /* file number on volume */
+       dev_t st_rdev;
+       off_t st_size;          /* logical end of file */
+       int st_mode;
+       time_t st_mtime;        /* last modified */
+};
+
+#define S_IFDIR 2
+
+typedef char *va_list;
+#define va_dcl va_list va_alist;
+#define va_start(l) l = (va_list)&va_alist
+#define va_arg(l,m) ((m*)(l += sizeof(m)))[-1]
+#define va_end(l) l = NULL
+
+#ifdef _mac
+extern struct menu Menus[NMENUS];
+
+static EventRecord the_Event;
+
+/* keycodes (from Inside MacIntosh I-251). because of changes with
+the MacPlus, there are some duplicate codes between cursor keys and
+keypad keys. these can be deciphered by the corresponding character
+codes, which are different. this table simply translates a keycode
+into a character code that is appropriate. */
+
+#define NOKEY -1
+#define RET 0x0D       
+#define TAB 0x09       
+#define BACKSP 0x08
+#define ENTERL NOKEY   /* left enter key absent on MacPlus */
+#define COMMAND NOKEY  /* will be no translation anyway for these */
+#define SHIFT NOKEY
+#define CAPSLOCK NOKEY
+#define OPTION NOKEY
+#define PADDOT '.'             /* PAD period */
+#define PAD0 '0'
+#define PAD1 '1'
+#define PAD2 '2'
+#define PAD3 '3'
+#define PAD4 '4'
+#define PAD5 '5'
+#define PAD6 '6'
+#define PAD7 '7'
+#define PAD8 '8'
+#define PAD9 '9'
+#define LEFTCURS 'B'           /* jove only, make like commands */
+#define RIGHTCURS 'F'
+#define UPCURS 'P'
+#define DOWNCURS 'N'
+#define PADENTER RET
+#define PADMINUS '-'
+#define CLEAR 0
+
+static char nsh_keycodes[] = {
+       'a','s','d','f','h',                                            /* 0 - 4 */
+       'g','z','x','c','v',                                            /* 5 - 9 */
+       NOKEY,'b','q','w','e',                                  /* 10 - 14 */
+       'r','y','t','1','2',                                    /* 15 - 19 */
+       '3','4','6','5','=',                                    /* 20 - 24 */
+       '9','7','-','8','0',                                    /* 25 - 29 */
+       ']','O','u','[','i',                                    /* 30 - 34 */
+       'p',RET,'l','j','\'',                                   /* 35 - 39 */
+       'k',';','\\',',','/',                                   /* 40 - 44 */
+       'n','m','.',TAB,NOKEY,                                  /* 45 - 49 */
+       '`',BACKSP,ENTERL,NOKEY,NOKEY,                  /* 50 - 54 */
+       COMMAND,SHIFT,CAPSLOCK,OPTION, NOKEY,   /* 55 - 59 */
+       NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,                  /* 60 - 64 */
+       PADDOT,RIGHTCURS,NOKEY,NOKEY,NOKEY,             /* 65 - 69 */
+       LEFTCURS,CLEAR,DOWNCURS,NOKEY,NOKEY,    /* 70 - 74 */
+       NOKEY,PADENTER,UPCURS,PADMINUS,NOKEY,   /* 75 - 79 */
+       NOKEY,NOKEY,PAD0,PAD1,PAD2,                             /* 80 - 84 */
+       PAD3,PAD4,PAD5,PAD6,PAD7,                               /* 85 - 89 */
+       NOKEY,PAD8,PAD9
+};
+
+static char sh_keycodes[] = {
+       'A','S','D','F','H',                                            /* 0 - 4 */
+       'G','Z','X','C','V',                                            /* 5 - 9 */
+       NOKEY,'B','Q','W','E',                                  /* 10 - 14 */
+       'R','Y','T','!','@',                                    /* 15 - 19 */
+       '#','$','^','%','+',                                    /* 20 - 24 */
+       '(','&','_','*',')',                                    /* 25 - 29 */
+       '}','O','U','{','I',                                    /* 30 - 34 */
+       'P',RET,'L','J','\'',                                   /* 35 - 39 */
+       'K',';','|','<','?',                                    /* 40 - 44 */
+       'N','M','>',TAB,NOKEY,                                  /* 45 - 49 */
+       '~',BACKSP,ENTERL,NOKEY,NOKEY,                  /* 50 - 54 */
+       COMMAND,SHIFT,CAPSLOCK,OPTION, NOKEY,   /* 55 - 59 */
+       NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,                  /* 60 - 64 */
+       PADDOT,RIGHTCURS,NOKEY,NOKEY,NOKEY,             /* 65 - 69 */
+       LEFTCURS,CLEAR,DOWNCURS,NOKEY,NOKEY,    /* 70 - 74 */
+       NOKEY,PADENTER,UPCURS,PADMINUS,NOKEY,   /* 75 - 79 */
+       NOKEY,NOKEY,PAD0,PAD1,PAD2,                             /* 80 - 84 */
+       PAD3,PAD4,PAD5,PAD6,PAD7,                               /* 85 - 89 */
+       NOKEY,PAD8,PAD9
+};
+
+
+
+/* tn.h Modified for variable screen size 11/21/87. K. Mitchum */
+
+static int tn_rows, tn_cols, tn_top, tn_left, tn_bottom, tn_right;
+int MAXROW, MAXCOL;
+
+#define SCREENSIZE (tn_rows * ROWSIZE)
+#define FONT monaco
+#define TEXTSIZE 9
+
+#define HEIGHT 11
+#define WIDTH 6
+#define DESCENT 2
+#define TWIDTH tn_cols * WIDTH
+#define THEIGHT tn_rows * HEIGHT
+
+/* window specs */
+
+#define SCROLLWIDTH 16 /* width of scroll bar control in pixels */
+#define WINDWIDTH tn_right - tn_left - SCROLLWIDTH - 1/* local coordinates */
+#define WINDHEIGHT tn_bottom - tn_top  /* local coordinates */
+
+/* for keyboard routines */
+#define MCHARS 32      /* must be power of two */
+#define NMASK MCHARS -1        /* circular buffer */
+
+#endif /* _mac */
+
+
diff --git a/usr/src/new/jove/macvert.c b/usr/src/new/jove/macvert.c
new file mode 100644 (file)
index 0000000..1b19aff
--- /dev/null
@@ -0,0 +1,167 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+/* Macvert converts old style macro files to the new style.  The old
+   style macros were binary files, the new ones are text files suitable
+   for loading with the "source" command of JOVE. */
+
+#include <stdio.h>
+
+extern int     read(),
+               write();
+
+int    mac_fd;
+
+mac_io(fcn, ptr, nbytes)
+int    (*fcn)();
+char   *ptr;
+{
+       int     nio;
+
+       if ((nio = (*fcn)(mac_fd, ptr, nbytes)) != nbytes)
+               fprintf(stderr, "[Macro %s error: %d got %d]",
+                        (fcn == read) ? "read" : "write",
+                        nbytes,
+                        nio);
+}
+
+#define NEWWAY 1
+#define OLDWAY 0
+
+int    int_how = NEWWAY;
+
+/* Formatting int's the old way or the new "improved" way? */
+
+#if vax || pdp11
+long htonl(x)
+register long x;
+{
+       return( (((x >>  0) & 0377) << 24) |
+               (((x >>  8) & 0377) << 16) |
+               (((x >> 16) & 0377) <<  8) |
+               (((x >> 24) & 0377) <<  0) );
+}
+
+short htons(x)
+register short x;
+{
+       return( (((x >>  0) & 0377) << 8) |
+               (((x >>  8) & 0377) << 0) );
+}
+
+long ntohl(x)
+register long x;
+{
+       return( (((x >>  0) & 0377) << 24) |
+               (((x >>  8) & 0377) << 16) |
+               (((x >> 16) & 0377) <<  8) |
+               (((x >> 24) & 0377) <<  0) );
+}
+
+short ntohs(x)
+register short x;
+{
+       return( (((x >>  0) & 0377) << 8) |
+               (((x >>  8) & 0377) << 0) );
+}
+#else
+long htonl(x)
+register long x;
+{
+       return(x);
+}
+
+short htons(x)
+register short x;
+{
+       return(x);
+}
+
+long ntohl(x)
+register long x;
+{
+       return(x);
+}
+
+short ntohs(x)
+register short x;
+{
+       return(x);
+}
+#endif
+
+int_fmt(i)
+{
+       if (int_how == NEWWAY)
+               return ntohl(i);
+       return i;
+}
+
+read_and_write_macros(filein)
+char   *filein;
+{
+       int     namelen,
+               bodylen,
+               tmp;
+       char    macname[256],
+               macbuf[1024];
+
+       if ((mac_fd = open(filein, 0)) == -1)
+               fprintf(stderr, "Cannot open %s\n", filein);
+
+       while (read(mac_fd, (char *) &tmp, sizeof tmp) == (sizeof tmp)) {
+retry:         bodylen = int_fmt(tmp);
+               if (bodylen <= 0 || bodylen > 10000) {
+                       if (int_how == NEWWAY) {
+                               int_how = OLDWAY;
+                               goto retry;
+                       } else {
+                               fprintf(stderr, "I don't think \"%s\" is an old style JOVE macro file\n", filein);
+                               exit(1);
+                       }
+               }
+               mac_io(read, (char *) &namelen, sizeof namelen);
+               namelen = int_fmt(namelen);
+               mac_io(read, macname, namelen);
+               mac_io(read, macbuf, bodylen);
+               output_new_definition(macname, macbuf, bodylen);
+       }               
+}
+
+pr_putc(c)
+{
+       if (c == '\\' || c == '^')
+               putchar('\\');
+        else if (c < ' ' || c == '\177') {
+               putchar('^');
+               c = (c == '\177') ? '?' : (c + '@');
+       }
+       putchar(c);
+}
+
+output_new_definition(name, body, bodylen)
+char   *name,
+       *body;
+{
+       int     i;
+
+       fprintf(stdout, "define-macro %s ", name);
+       for (i = 0; i < bodylen; i++)
+               pr_putc(body[i]);
+       putchar('\n');
+}
+
+main(argc, argv)
+char   *argv[];
+{
+       if (argc != 2) {
+               fprintf(stderr, "usage: macvert <old-style-macro-file>\n");
+               exit(1);
+       }
+
+       read_and_write_macros(argv[1]);
+}
diff --git a/usr/src/new/jove/marks.c b/usr/src/new/jove/marks.c
new file mode 100644 (file)
index 0000000..78f1dd7
--- /dev/null
@@ -0,0 +1,239 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+int    MarksShouldFloat = 1;
+
+#include "jove.h"
+
+Mark *
+MakeMark(line, column, type)
+register Line  *line;
+{
+       register Mark   *newmark = (Mark *) emalloc(sizeof *newmark);
+
+       MarkSet(newmark, line, column);
+       newmark->m_next = curbuf->b_marks;
+       newmark->m_flags = type;
+       curbuf->b_marks = newmark;
+       return newmark;
+}
+
+void
+flush_marks(b)
+Buffer *b;
+{
+       register Mark   *m,
+                       *next;
+
+       m = b->b_marks;
+       while (m != 0) {
+               next = m->m_next;
+               free((char *) m);
+               m = next;
+       }
+}
+
+void
+DelMark(m)
+register Mark  *m;
+{
+       register Mark   *mp = curbuf->b_marks;
+
+       if (m == mp)
+               curbuf->b_marks = m->m_next;
+       else {
+               while (mp != 0 && mp->m_next != m)
+                       mp = mp->m_next;
+               if (mp == 0)
+                       complain("Unknown mark!");
+               mp->m_next = m->m_next;
+       }
+       free((char *) m);
+}
+
+void
+AllMarkSet(b, line, col)
+Buffer *b;
+register Line  *line;
+{
+       register Mark   *mp;
+
+       for (mp = b->b_marks; mp != 0; mp = mp->m_next)
+               MarkSet(mp, line, col);
+}
+
+void
+MarkSet(m, line, column)
+Mark   *m;
+Line   *line;
+{
+       m->m_line = line;
+       m->m_char = column;
+}
+
+void
+PopMark()
+{
+       int     pmark;
+
+       if (curmark == 0)
+               return;
+       if (curbuf->b_markring[(curbuf->b_themark + 1) % NMARKS] == 0) {
+               pmark = curbuf->b_themark;
+               do {
+                       if (--pmark < 0)
+                               pmark = NMARKS - 1;
+               } while (curbuf->b_markring[pmark] != 0);
+
+               curbuf->b_markring[pmark] = MakeMark(curline, curchar, MarksShouldFloat ? M_FLOATER : M_FIXED);
+               ToMark(curmark);
+               DelMark(curmark);
+               curmark = 0;
+       } else
+               PtToMark();
+
+       pmark = curbuf->b_themark - 1;
+       if (pmark < 0)
+               pmark = NMARKS - 1;
+       curbuf->b_themark = pmark;
+}
+
+void
+SetMark()
+{
+       if (is_an_arg())
+               PopMark();
+       else
+               set_mark();
+}
+
+void
+set_mark()
+{
+       do_set_mark(curline, curchar);
+}
+
+void
+do_set_mark(l, c)
+Line   *l;
+{
+       curbuf->b_themark = (curbuf->b_themark + 1) % NMARKS;
+       if (curmark == 0)
+               curmark = MakeMark(l, c, MarksShouldFloat ? M_FLOATER : M_FIXED);
+       else
+               MarkSet(curmark, l, c);
+       s_mess("[Point pushed]");
+}
+
+/* Move point to Mark */
+
+void
+ToMark(m)
+Mark   *m;
+{
+       int     len;
+
+       if (m == 0)
+               return;
+       DotTo(m->m_line, m->m_char);
+       if (curchar > (len = length(curline)))
+               curchar = len;
+}
+
+Mark *
+CurMark()
+{
+       if (curmark == 0)
+               complain("No mark.");
+       return curmark;
+}
+
+void
+PtToMark()
+{
+       Line    *mline;
+       int     mchar;
+       Mark    *m = CurMark();
+
+       mline = curline;
+       mchar = curchar;
+
+       ToMark(m);
+       MarkSet(m, mline, mchar);
+}
+
+/* Fix marks for after a deletion.  For now, even marks that don't
+   float will actually float, because we can't allow marks to point
+   to non-existant lines. */
+
+void
+DFixMarks(line1, char1, line2, char2)
+register Line  *line1,
+               *line2;
+{
+       register Mark   *m;
+       Line    *lp = line1;
+
+       if (curbuf->b_marks == 0)
+               return;
+       while (lp != line2->l_next) {
+               for (m = curbuf->b_marks; m != 0; m = m->m_next)
+                       if (m->m_line == lp)
+                               m->m_char |= (1 << 15);
+               lp = lp->l_next;
+       }
+       for (m = curbuf->b_marks; m; m = m->m_next) {
+               if ((m->m_char & (1 << 15)) == 0)
+                       continue;       /* Not effected */
+               m->m_char &= ~(1 << 15);
+               if (m->m_line == line1 && m->m_char < char1)
+                       continue;       /* This mark is not affected */
+               if (line1 == line2) {
+                       if (m->m_char >= char1 && m->m_char <= char2)
+                               m->m_char = char1;
+                       else if (m->m_char > char2)
+                               m->m_char -= (char2 - char1);
+                       /* Same line move the mark backward */
+               } else if (m->m_line == line2) {
+                       if (m->m_char > char2)
+                               m->m_char = char1 + (m->m_char - char2);
+                       else
+                               m->m_char = char1;
+                       m->m_flags |= M_BIG_DELETE;
+                       m->m_line = line1;
+               } else {
+                       m->m_char = char1;
+                       m->m_line = line1;
+                       m->m_flags |= M_BIG_DELETE;
+               }
+       }
+}
+
+/* Fix marks after an insertion.  Marks that don't float are ignored
+   on insertion, which means PtToMark has to be careful ... */
+
+void
+IFixMarks(line1, char1, line2, char2)
+register Line  *line1,
+               *line2;
+{
+       register Mark   *m;
+
+       for (m = curbuf->b_marks; m != 0; m = m->m_next) {
+               if ((m->m_flags & M_FLOATER) == 0)
+                       continue;
+               if (m->m_line == line1) {
+                       if (m->m_char > char1) {
+                               m->m_line = line2;
+                               if (line1 == line2)
+                                       m->m_char += (char2 - char1);
+                               else
+                                       m->m_char = char2 + (m->m_char - char1);
+                       }
+               } 
+       }
+}
diff --git a/usr/src/new/jove/menumaps.txt b/usr/src/new/jove/menumaps.txt
new file mode 100644 (file)
index 0000000..67c4999
--- /dev/null
@@ -0,0 +1,131 @@
+/************************************************************************
+ * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is      *
+ * provided to you without charge, and with no warranty.  You may give *
+ * away copies of JOVE, including sources, provided that this notice is *
+ * included in all the files.                                          *
+ ************************************************************************/
+
+/* menumaps.txt K. Mitchum 1/88. The same warnings apply as in keymaps.txt.
+   You MUST use a version of setmaps compiled with MAC defined for this
+   file to be converted correctly. */
+
+
+#include "jove.h"
+#include "mac.h"
+#MENU
+data_obj MDIV = { STRING, "(-" };
+data_obj MAJM = { STRING, "(Major Modes:" };
+data_obj MINM = { STRING, "(Minor Modes:" };
+data_obj BOOL = { STRING, "(Boolean:" };
+data_obj DECM = { STRING, "(Decimal:" };
+data_obj STRM = { STRING, "(String:" };
+data_obj CHAR = { STRING, "(Character:" };
+#define MENU_DIV &MDIV
+
+struct menu Menus[NMENUS] = {
+"File",101,0, {
+       "visit-file",
+       "find-file",
+       "insert-file",
+       MENU_DIV,
+       "save-file",
+       "write-file",
+       MENU_DIV,
+       "write-modified-files",
+       "write-region",
+       MENU_DIV,
+       "write-macros-to-file",
+       MENU_DIV,
+       "exit-jove",
+       0
+},
+
+"Buffer",103,0, {
+       &MAJM,
+       "c-mode",
+       "fundamental-mode",
+       "lisp-mode",
+       "text-mode",
+       &MINM,
+       "auto-fill-mode",
+       "auto-indent-mode",
+       "over-write-mode",
+       "show-match-mode",
+       "word-abbrev-mode",
+       MENU_DIV,
+       0
+},
+
+"Window",104,0, {
+       "grow-window",
+       "shrink-window",
+       MENU_DIV,
+       "split-current-window",
+       "delete-other-windows",
+       "window-find",
+       MENU_DIV,
+       "number-lines-in-window",
+       0
+},
+
+"Point",105,0, {
+       "set-mark",
+       "exchange-point-and-mark",
+       MENU_DIV,
+       "search-forward",
+       "search-reverse",
+       "i-search-forward",
+       "i-search-reverse",
+       "query-replace-string",
+       "replace-string",
+       MENU_DIV,
+       "find-tag",
+       0
+},
+
+"Command",106,0, {
+       "begin-kbd-macro",
+       "end-kbd-macro",
+       "name-kbd-macro",
+       "execute-kbd-macro",
+       "execute-macro",
+       MENU_DIV,
+       "bind-macro-to-key",
+       "bind-to-key",
+       "describe-key",
+       MENU_DIV,
+       "execute-named-command",
+       0
+},
+
+"Set",107,0, {
+       &BOOL,
+       "allow-bad-filenames",
+       "auto-case-abbrev",
+       "case-ignore-search",
+       "files-should-end-with-newline",
+       "macify",
+       "make-backup-files",
+       "marks-should-float",
+       "match-regular-expressions",
+       "send-typeout-to-buffer",
+       "wrap-search",
+       &DECM,
+       "c-indentation-increment",
+       "internal-tabstop",
+       "left-margin",
+       "mark-threshold",
+       "paren-flash-delay",
+       "right-margin",
+       "scroll-step",
+       "sync-frequency",
+       &STRM,
+       "comment-format",
+       "mode-line",
+       "tag-file",
+       &CHAR,
+       "abort-char",
+       0
+}
+};
+
diff --git a/usr/src/new/jove/mjovers.Hqx b/usr/src/new/jove/mjovers.Hqx
new file mode 100644 (file)
index 0000000..a2bbc9a
--- /dev/null
@@ -0,0 +1,19 @@
+(This file must be converted with BinHex 4.0)
+
+:#QeUEhCP,R*cFQ-!2j!%5PB`-3#3#!1JIqJ!N!3"!*!$![i!!!(q!*!$SJ%,!3F
+""J%'!3F"#3%(!3J"#3%+!38!"J!'!3S"#`!(#QeUEhCP,R*cFQ0b!J#30Cj)c4F
+!N!B$S!-5!!N!!J#3!c-!N$+L!%e5J!#3$`(!!*!,!`#3"6!!!!)Dd!#3#"!!N"-
+F5PB`-3#3!`&*3diM!*!&J%C548B!N!@!!*!("d&38%`!N!8"!2q3!`#J!!%![q-
+"`+!!!8#2rm&`J!!"8)2rm9b!!!&8Mrr"9)!!!95i!!&8J!!"92q3!e5!!!&8[q-
+"9)!!!952rm&8J!!"9)2rm95!!!&8Mrr"9)!!!95i!!&8J!!"92q3!e6rN!08)!!
+!9$rrrp3)!!!8$rrrp!)!!!3$rrrmrj!$!2q3!`$rN!2!rj!$`2q3!r$rN!2`rj!
+$r2q3!rcrN!2mrj!$r2q3!rcrN!2mrj!$r2q3!rcrN!2mrj!$r2q3!rcrN!2mrj!
+$r2q3!rcrN!2mrj!$r2q3!rcrN!2mrj!$r2q3!r`rrrrm2rrrr!rrrr`2rrrm!rr
+rr!2rrr`!N!1Z!!B!N!@q!A)!dJ'Z"!*25`#3"5J!&!$`!8m!N!F$!"3!$3(##!*
+H-!#3"3m!&!!M!A`)!Pia!*!&+!&H!$F"c!J2B#!p)%963d&345"VCANZ%J#3"6F
+"AJ"'!F`)%N0[E@eKEQ3JB#!p)'!JDf9j,J#3"8X"AJ"Z!F`))80[ER4bEf`J25"
+$EfeYB@jN)'pb)%0[ER4bEf`J5f9j,JJ!N!-9!*!%!33"c!!"!*!)"q3!N!-"!*!
+$![i!!!(q!*!$SJ!"h(B%DJ#3!a`!PJ!&3Nj%6!#3!c*+9M!a!*!$2NC548B!N!0
++5801)`#3!eC%594-!*!$BN4-6dF!N!0Z!)$rr`#3"3(XXJ!!rrm!N!-J!!(Y!J#
+!rrm!N!-N!!(H8J#!rrm!N!-[!!(XpJINrrm!!!%c!!(XeJI3!*!%!H8!!HbL#d&
+#6e98AdT%6%p(Ep3:
diff --git a/usr/src/new/jove/paragraph.c b/usr/src/new/jove/paragraph.c
new file mode 100644 (file)
index 0000000..64f594b
--- /dev/null
@@ -0,0 +1,552 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+#include "jove.h"
+
+#ifdef MAC
+#      undef private
+#      define private
+#endif
+
+#ifdef LINT_ARGS
+private int    get_indent(Line *);
+private Line   * tailrule(Line *);
+#else
+private int    get_indent();
+private Line   * tailrule();
+#endif
+
+#ifdef MAC
+#      undef private
+#      define private static
+#endif
+
+/* Thanks to Brian Harvey for this paragraph boundery finding algorithm.
+   It's really quite hairy figuring it out.  This deals with paragraphs that
+   are seperated by blank lines, lines beginning with a Period (assumed to
+   be an nroff command), lines beginning with BackSlash (assumed to be Tex
+   commands).  Also handles paragraphs that are separated by lines of
+   different indent; and it deals with outdented paragraphs, too.  It's
+   really quite nice.  Here's Brian's algorithm.
+
+   Definitions:
+   
+   THIS means the line containing the cursor.
+   PREV means the line above THIS.
+   NEXT means the line below THIS.
+   
+   BLANK means empty, empty except for spaces and tabs, starts with a period
+   or a backslash, or nonexistent (because the edge of the buffer is
+   reached).  ((BH 12/24/85 A line starting with backslash is blank only if
+   the following line also starts with backslash.  This is so that \noindent
+   is part of a paragraph, but long strings of TeX commands don't get
+   rearranged.  It still isn't perfect but it's better.))
+
+   BSBLANK means BLANK or starts with a backslash.  (BH 12/24/85)
+   
+   HEAD means the first (nonblank) line of the paragraph containing THIS.
+   BODY means all other (nonblank) lines of the paragraph.
+   TAIL means the last (nb) line of the paragraph.  (TAIL is part of BODY.)
+   
+   HEAD INDENT means the indentation of HEAD.  M-J should preserve this.
+   BODY INDENT means the indentation of BODY.  Ditto.
+   
+   Subprocedures:
+   
+   TAILRULE(BODYLINE)
+   If BODYLINE is BLANK, the paragraph has only one line, and there is no
+   BODY and therefore no TAIL.  Return.  Otherwise, starting from BODYLINE,
+   move down until you find a line that either is BSBLANK or has a different
+   indentation from BODYLINE.  The line above that different line is TAIL.
+   Return.
+   
+   Rules:
+   
+   1.  If THIS is BLANK, which command are you doing?  If M-J or M-[, then go
+   up to the first non-BLANK line and start over.  (If there is no non-BLANK
+   line before THIS, ring the bell.)  If M-], then the first non-BLANK line
+   below THIS is HEAD, and the second consecutive non-BSBLANK line (if any) is
+   the beginning of BODY.  (If there is no non-BLANK line after THIS, ring
+   the bell.)  Do TAILRULE(beginning-of-BODY).  Go to rule A.
+
+   2.  If PREV is BLANK or THIS is BSBLANK, then THIS is HEAD, and NEXT (if
+   not BSBLANK) is in BODY.  Do TAILRULE(NEXT).  Go to rule A.
+
+   3.  If NEXT is BSBLANK, then THIS is TAIL, therefore part of BODY.  Go to
+   rule 5 to find HEAD.
+   
+   4.  If either NEXT or PREV has the same indentation as THIS, then THIS is
+   part of BODY.  Do TAILRULE(THIS).  Go to rule 5 to find HEAD.  Otherwise,
+   go to rule 6.
+   
+   5.  Go up until you find a line that is either BSBLANK or has a different
+   indentation from THIS.  If that line is BLANK, the line below it is HEAD.
+   If that line is non-BLANK, then call that new line THIS for what follows.
+   If (the new) PREV has the same indent as THIS, then (the new) NEXT is
+   HEAD.  If PREV has a different indent from THIS, then THIS is HEAD.  Go to
+   rule A.
+   
+   6.  If you got here, then both NEXT and PREV are nonblank and are
+   differently indented from THIS.  This is a tricky case and there is no
+   guarantee that you're going to win.  The most straightforward thing to do
+   is assume that we are not using hanging indentation.  In that case:
+   whichever of PREV and THIS is indented further is HEAD.  Do
+   TAILRULE(HEAD+1).  Go to rule A.
+   
+   6+.  A more complicated variant would be this: if THIS is indented further
+   than PREV, we are using regular indentation and rule 6 applies.  If PREV
+   is indented further than THIS, look at both NEXT and the line after NEXT.
+   If those two lines are indented equally, and more than THIS, then we are
+   using hanging indent, THIS is HEAD, and NEXT is the first line of BODY.
+   Do TAILRULE(NEXT).  Otherwise, rule 6 applies.
+   
+   A.  You now know where HEAD and TAIL are.  The indentation of HEAD is HEAD
+   INDENT; the indentation of TAIL is BODY INDENT.
+   
+   B.  If you are trying to M-J, you are now ready to do it.
+   
+   C.  If you are trying to M-], leave point after the newline that ends
+   TAIL.  In other words, leave the cursor at the beginning of the line
+   after TAIL.  It is not possible for this to leave point where it started
+   unless it was already at the end of the buffer.
+   
+   D.  If you are trying to M-[, if the line before HEAD is not BLANK, then
+   leave point just before HEAD.  That is, leave the cursor at the beginning
+   of HEAD.  If the line before HEAD is BLANK, then leave the cursor at the
+   beginning of that line.  If the cursor didn't move, go up to the first
+   earlier non-BLANK line and start over.
+
+
+   End of Algorithm.  I implemented rule 6+ because it seemed nicer.  */
+
+int    RMargin = 78,
+       LMargin = 0;
+Line   *para_head,
+       *para_tail;
+int    head_indent,
+       body_indent;
+static int     use_lmargin;
+
+/* some defines for paragraph boundery checking */
+#define I_EMPTY                -1      /* line "looks" empty (spaces and tabs) */
+#define I_PERIOD       -2      /* line begins with "." or "\" */
+#define I_BUFEDGE      -3      /* line is nonexistent (edge of buffer) */
+
+static int     bslash;         /* Nonzero if get_indent finds line starting
+                                  with backslash */
+
+int
+i_bsblank(lp)
+Line   *lp;
+{
+       if (i_blank(lp))
+               return 1;
+       return bslash;
+}
+
+int
+i_blank(lp)
+Line   *lp;
+{
+       return (get_indent(lp) < 0);
+}
+
+private int
+get_indent(lp)
+register Line  *lp;
+{
+       Bufpos  save;
+       register int    indent;
+
+       bslash = 0;
+       if (lp == 0)
+               return I_BUFEDGE;
+       DOTsave(&save);
+       SetLine(lp);
+       if (blnkp(linebuf))
+               indent = I_EMPTY;
+       else if (linebuf[0] == '.')
+               indent = I_PERIOD;
+       else if (linebuf[0] == '\\') {
+               /* BH 12/24/85.  Backslash is BLANK only if next line
+                  also starts with Backslash. */
+               bslash += 1;
+               SetLine(lp->l_next);
+               if (linebuf[0] == '\\')
+                       indent = I_PERIOD;
+               else
+                       indent = 0;
+       } else {
+               ToIndent();
+               indent = calc_pos(linebuf, curchar);
+       }
+       SetDot(&save);
+
+       return indent;
+}
+
+private Line *
+tailrule(lp)
+register Line  *lp;
+{
+       int     i;
+
+       i = get_indent(lp);
+       if (i < 0)
+               return lp;      /* one line paragraph */
+       do {
+               if ((get_indent(lp->l_next) != i) || bslash)
+                       /* BH line with backslash is head of next para */
+                       break;
+       } while ((lp = lp->l_next) != 0);
+       if (lp == 0)
+               complain((char *) 0);
+       return lp;
+}
+
+/* Finds the beginning, end and indent of the current paragraph, and sets
+   the above global variables.  HOW says how to behave when we're between
+   paragraphs.  That is, it's either FORWARD or BACKWARD depending on which
+   way we're favoring. */
+
+void
+find_para(how)
+{
+       Line    *this,
+               *prev,
+               *next,
+               *head = 0,
+               *body = 0,
+               *tail = 0;
+       int     this_indent;
+       Bufpos  orig;           /* remember where we were when we started */
+
+       DOTsave(&orig);
+strt:
+       this = curline;
+       prev = curline->l_prev;
+       next = curline->l_next;
+       this_indent = get_indent(this);
+
+       if (i_blank(this)) {            /* rule 1 */
+               if (how == BACKWARD) {
+                       while (i_blank(curline))
+                               if (firstp(curline))
+                                       complain((char *) 0);
+                               else
+                                       line_move(BACKWARD, 1, NO);
+                       goto strt;
+               } else {
+                       while (i_blank(curline))
+                               if (lastp(curline))
+                                       complain((char *) 0);
+                               else
+                                       line_move(FORWARD, 1, NO);
+                       head = curline;
+                       next = curline->l_next;
+                       if (!i_bsblank(next))
+                               body = next;
+                       else
+                               body = head;
+               }
+       } else if (i_bsblank(this) || i_blank(prev)) {  /* rule 2 */
+               head = this;
+               if (!i_bsblank(next))
+                       body = next;
+       } else if (i_bsblank(next)) {   /* rule 3 */
+               tail = this;
+               body = this;
+       } else if ((get_indent(next) == this_indent) || /* rule 4 */
+                  (get_indent(prev) == this_indent))
+               body = this;
+       else {          /* rule 6+ */
+               if (get_indent(prev) > this_indent) {
+                       /* hanging indent maybe? */
+                       if ((next != 0) &&
+                           (get_indent(next) == get_indent(next->l_next))) {
+                               head = this;
+                               body = next;
+                       }
+               }
+               /* Now we handle hanging indent else and the other
+                  case of this_indent > get_indent(prev).  That is,
+                  if we didn't resolve HEAD in the above if, then
+                  we are not a hanging indent. */
+               if (head == 0) {        /* still don't know */
+                       if (this_indent > get_indent(prev))
+                               head = this;
+                       else
+                               head = prev;
+                       body = head->l_next;
+               }
+       }
+       /* rule 5 -- find the missing parts */
+       if (head == 0) {    /* haven't found head of paragraph so do so now */
+               Line    *lp;
+               int     i;
+
+               lp = this;
+               do {
+                       i = get_indent(lp->l_prev);
+                       if (i < 0)      /* is blank */
+                               head = lp;
+                       else if (i != this_indent || bslash) {
+                               Line    *this = lp->l_prev;
+
+                               if (get_indent(this->l_prev) == i)
+                                       head = this->l_next;
+                               else
+                                       head = this;
+                       }
+               } while (head == 0 && (lp = lp->l_prev) != 0);
+               if (lp == 0)
+                       complain((char *) 0);
+       }
+       if (body == 0)          /* this must be a one line paragraph */
+               body = head;
+       if (tail == 0)
+               tail = tailrule(body);
+       if (tail == 0 || head == 0 || body == 0)
+               complain("BUG! tail(%d),head(%d),body(%d)!", tail, head, body);
+       para_head = head;
+       para_tail = tail;
+       head_indent = get_indent(head);
+       body_indent = get_indent(body);
+
+       SetDot(&orig);
+}
+
+void
+Justify()
+{
+       use_lmargin = is_an_arg();
+       find_para(BACKWARD);
+       DoJustify(para_head, 0, para_tail, length(para_tail), NO,
+                 use_lmargin ? LMargin : body_indent);
+}
+
+Line *
+max_line(l1, l2)
+Line   *l1,
+       *l2;
+{
+       if (inorder(l1, 0, l2, 0))
+               return l2;
+       return l1;
+}
+
+Line *
+min_line(l1, l2)
+Line   *l1,
+       *l2;
+{
+       if (inorder(l1, 0, l2, 0))
+               return l1;
+       return l2;
+}
+
+void
+RegJustify()
+{
+       Mark    *mp = CurMark(),
+               *tailmark;
+       Line    *l1 = curline,
+               *l2 = mp->m_line;
+       int     c1 = curchar,
+               c2 = mp->m_char;
+       Line    *rl1,
+               *rl2;
+
+       use_lmargin = is_an_arg();
+       (void) fixorder(&l1, &c1, &l2, &c2);
+       do {
+               DotTo(l1, c1);
+               find_para(FORWARD);
+               rl1 = max_line(l1, para_head);
+               rl2 = min_line(l2, para_tail);
+               tailmark = MakeMark(para_tail, 0, M_FLOATER);
+               DoJustify(rl1, (rl1 == l1) ? c1 : 0, rl2,
+                         (rl2 == l2) ? c2 : length(rl2),
+                         NO, use_lmargin ? LMargin : body_indent);
+               l1 = tailmark->m_line->l_next;
+               DelMark(tailmark);
+               c1 = 0;
+       } while (l1 != 0 && l2 != rl2);
+}
+
+void
+do_rfill(ulm)
+{
+       Mark    *mp = CurMark();
+       Line    *l1 = curline,
+               *l2 = mp->m_line;
+       int     c1 = curchar,
+               c2 = mp->m_char;
+
+       use_lmargin = ulm;
+       (void) fixorder(&l1, &c1, &l2, &c2);
+       DoJustify(l1, c1, l2, c2, NO, use_lmargin ? LMargin : 0);
+}
+
+void
+do_space()
+{
+       int     c1 = curchar,
+               c2 = c1,
+               diff,
+               nspace;
+       char    ch;
+
+       while (c1 > 0 && ((ch = linebuf[c1 - 1]) == ' ' || ch == '\t'))
+               c1 -= 1;
+       while ((ch = linebuf[c2]) == ' ' || ch == '\t')
+               c2 += 1;
+       diff = (c2 - c1);
+       curchar = c2;
+
+       if (diff == 0)
+               return;
+       if (c1 > 0) {
+               int     topunct = c1 - 1;
+
+               nspace = 1;
+               if (diff >= 2) {
+                       while (index("\")]", linebuf[topunct])) {
+                               if (topunct == 0)
+                                       break;
+                               topunct -= 1;
+                       }
+                       if (index("?!.:", linebuf[topunct]))
+                               nspace = 2;
+               }
+       } else
+               nspace = 0;
+
+       if (diff > nspace)
+               del_char(BACKWARD, (diff - nspace));
+       else if (diff < nspace)
+               insert_c(' ', (nspace - diff));
+}
+
+#ifdef MSDOS
+/*#pragma loop_opt(off) */
+#endif
+
+void
+DoJustify(l1, c1, l2, c2, scrunch, indent)
+Line   *l1,
+       *l2;
+{
+       int     okay_char = -1;
+       char    *cp;
+       Mark    *savedot = MakeMark(curline, curchar, M_FLOATER),
+               *endmark;
+
+       (void) fixorder(&l1, &c1, &l2, &c2);    /* l1/c1 will be before l2/c2 */
+       DotTo(l1, c1);
+       if (get_indent(l1) >= c1) {
+               if (use_lmargin) {
+                       n_indent(indent + (head_indent - body_indent));
+                       use_lmargin = 0;        /* turn this off now */
+               }
+               ToIndent();
+       }
+       endmark = MakeMark(l2, c2, M_FLOATER);
+
+       for (;;) {
+               while (calc_pos(linebuf, curchar) < RMargin) {
+                       if (curline == endmark->m_line && curchar >= endmark->m_char)
+                               goto outahere;
+                       okay_char = curchar;
+                       if (eolp()) {
+                               del_char(FORWARD, 1);   /* Delete line separator. */
+                               ins_str("  ", NO);
+                       } else {
+                               cp = StrIndex(1, linebuf, curchar + 1, ' ');
+                               if (cp == 0)
+                                       Eol();
+                               else
+                                       curchar = (cp - linebuf);
+                       }
+                       do_space();
+               }
+               if (okay_char > 0)
+                       curchar = okay_char;                    
+               if (curline == endmark->m_line && curchar >= endmark->m_char)
+                       goto outahere;
+
+               /* Can't fit in small margin, so we do the best we can. */
+               if (eolp()) {
+                       line_move(FORWARD, 1, NO);
+                       n_indent(indent);
+               } else {
+                       DelWtSpace();
+                       LineInsert(1);
+                       if (scrunch && TwoBlank()) {
+                               Eol();
+                               del_char(FORWARD, 1);
+                       }
+                       n_indent(indent);
+               }
+       }
+outahere:
+       ToMark(savedot);        /* Back to where we were */
+       DelMark(endmark);       /* Free up marks */
+       DelMark(savedot);
+       this_cmd = last_cmd = 0; /* So everything is under control */
+       f_mess("");
+}
+
+#ifdef MSDOS
+/*#pragma loop_opt() */
+#endif
+
+extern Line    *para_head,
+               *para_tail;
+
+void
+DoPara(dir)
+{
+       register int    num = arg_value(),
+                       first_time = TRUE;      
+
+       while (--num >= 0) {
+tryagain:      find_para(dir);         /* find paragraph bounderies */
+               if ((dir == BACKWARD) &&
+                   ((!first_time) || ((para_head == curline) && bolp()))) {
+                       if (bobp())
+                               complain((char *) 0);
+                       b_char(1);
+                       first_time = !first_time;
+                       goto tryagain;
+               }
+               SetLine((dir == BACKWARD) ? para_head : para_tail);
+               if (dir == BACKWARD && !firstp(curline) &&
+                   i_blank(curline->l_prev))
+                       line_move(BACKWARD, 1, NO);
+               else if (dir == FORWARD) {
+                       if (lastp(curline)) {
+                               Eol();
+                               break;
+                       }
+                       /* otherwise */
+                       line_move(FORWARD, 1, NO);
+               }
+       }
+}
+
+void
+BackPara()
+{
+       DoPara(BACKWARD);
+}
+
+void
+ForPara()
+{
+       DoPara(FORWARD);
+}
diff --git a/usr/src/new/jove/portsrv.c b/usr/src/new/jove/portsrv.c
new file mode 100644 (file)
index 0000000..8b54949
--- /dev/null
@@ -0,0 +1,167 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+/* This is a server for jove sub processes.  It runs the command and
+   signals jove when there is some output ready to send to jove. By the
+   time we get here, out standard output goes to jove's process input. */
+
+#include "tune.h"
+
+#ifdef PIPEPROCS       /* the whole file! */
+
+#include "jove.h"
+
+#include <signal.h>
+#include <sys/ioctl.h>
+#ifdef BSD4_2
+#   include <sys/wait.h>
+#else
+#   include <wait.h>
+#endif
+
+struct header {
+       int     pid;
+       int     nbytes;
+       char    buf[512];
+} header;
+
+#define HEADSIZE       ((sizeof header.pid) + sizeof (header.nbytes))
+
+error(str)
+char   *str;
+{
+       header.pid = getpid();
+       header.nbytes = strlen(str);
+       strcpy(header.buf, str);
+       proc_write(&header, header.nbytes + HEADSIZE);
+       exit(-2);
+}
+
+int    ppid,
+       InputFD,
+       JovesInput;
+
+p_inform()
+{
+       long    nbytes;
+
+       ioctl(JovesInput, FIONREAD, (char *) &nbytes);
+       if (nbytes > 0)
+               kill(ppid, INPUT_SIG);
+}
+
+proc_write(ptr, n)
+char   *ptr;
+{
+       long    nbytes;
+
+       ioctl(1, FIONREAD, (char *) &nbytes);
+       
+       if (nbytes == 0)
+               kill(ppid, INPUT_SIG);
+
+       (void) write(1, ptr, n);
+       alarm(1);
+}
+
+read_pipe()
+{
+       register int    n;
+       
+       (void) signal(SIGALRM, p_inform);
+
+       while ((header.nbytes = read(InputFD, header.buf, sizeof header.buf)) > 0) {
+               n = HEADSIZE + header.nbytes;
+               proc_write(&header, n);
+       }
+}
+
+/* ARGSUSED */
+main(argc, argv)
+char   *argv[];
+{
+       int     p[2];
+       int     pid;
+       int     tty_fd,
+               i;
+
+/*     tty_fd = open("/dev/tty", 1); */
+
+       if (pipe(p) == -1)
+               error("Cannot pipe jove portsrv.\n");
+
+/*     for (i = 0; i < argc; i++) {
+               write(tty_fd, "*argv++ = ", 10);
+               write(tty_fd, argv[i], strlen(argv[i]));
+               write(tty_fd, "\n", 1);
+       } */
+
+       ppid = getppid();
+       switch (pid = fork()) {
+       case -1:
+               error("portsrv: cannot fork.\n");
+
+       case 0:
+               /* We'll intercept childs output in p[0] */
+               (void) dup2(p[1], 1);
+               (void) dup2(p[1], 2);
+               (void) close(p[0]);
+               (void) close(p[1]);
+                       
+               (void) setpgrp(getpid(), getpid());
+               execv(argv[2], &argv[3]);
+               _exit(-4);
+
+       default:
+               (void) close(0);
+
+                /* don't want this guy to read anything jove sends to
+                   our soon to be created child */
+
+               JovesInput = atoi(argv[1]);
+               (void) signal(SIGINT, SIG_IGN);
+               (void) signal(SIGQUIT, SIG_IGN);
+               (void) close(p[1]);
+
+               /* tell jove the pid of the real child as opposed to us */
+               header.pid = getpid();
+               header.nbytes = sizeof (int);
+               *(int *) header.buf = pid;
+               (void) write(1, (char *) &header, sizeof pid + HEADSIZE);
+               p_inform();     /* Inform jove */
+
+               /* read proc's output and send it to jove */
+               InputFD = p[0];
+               read_pipe();
+               (void) close(p[0]);
+               header.pid = getpid();
+               header.nbytes = EOF;    /* tell jove we are finished */
+               (void) write(1, (char *) &header, HEADSIZE);
+               p_inform();
+               /* try to exit like our child did ... */
+               {
+                       union wait      w;
+
+#ifndef BSD4_2
+                       while (wait2(&w.w_status, 0) != pid)
+#else
+                       while (wait3(&w.w_status, 0, 0) != pid)
+#endif
+                               ;
+                       if (WIFEXITED(w))
+                               exit(w.w_retcode);
+                       else if (WIFSIGNALED(w))
+                               kill(getpid(), w.w_termsig);
+               }
+       }
+}
+
+#else /* PIPEPROCS */
+main()
+{
+}
+#endif
diff --git a/usr/src/new/jove/re.c b/usr/src/new/jove/re.c
new file mode 100644 (file)
index 0000000..6466f4f
--- /dev/null
@@ -0,0 +1,958 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+/* search package */
+
+#include "jove.h"
+#include "ctype.h"
+#ifdef MAC
+#      undef private
+#      define private
+#endif
+
+#ifdef LINT_ARGS
+private char * insert(char *, char *, int);
+
+private void
+       REreset(void),
+       search(int, int, int);
+private int
+       backref(int, char *),
+       do_comp(int),
+       member(char *, int, int),
+       REgetc(void),
+       REmatch(char *, char *);
+#else
+private char * insert();
+
+private void
+       REreset(),
+       search();
+private int
+       backref(),
+       do_comp(),
+       member(),
+       REgetc(),
+       REmatch();
+#endif /* LINT_ARGS */
+
+#ifdef MAC
+#      undef private
+#      define private static
+#endif
+
+#define NALTS  16      /* number of alternate search strings */
+
+char   searchstr[128],
+       compbuf[256],           /* global default compbuf */
+       rep_search[128],        /* replace search string */
+       rep_str[128],           /* contains replacement string */
+       *cur_compb,             /* usually points at compbuf */
+       REbuf[LBSIZE],          /* points at line we're scanning */
+       *alternates[NALTS];
+
+int    REdirection;
+
+int    CaseIgnore = 0,
+       WrapScan = 0,
+       UseRE = 0;
+
+#define cind_cmp(a, b) (CaseEquiv[a] == CaseEquiv[b])
+
+private int    REpeekc;
+private char   *REptr;
+
+private int
+REgetc()
+{
+       int     c;
+
+       if ((c = REpeekc) != -1)
+               REpeekc = -1;
+       else if (*REptr)
+               c = *REptr++;
+       else
+               c = 0;
+
+       return c;
+}
+
+#define STAR   01      /* Match any number of last RE. */
+#define AT_BOL 2       /* ^ */
+#define AT_EOL 4       /* $ */
+#define AT_BOW 6       /* \< */
+#define AT_EOW 8       /* \> */
+#define OPENP  10      /* \( */
+#define CLOSEP 12      /* \) */
+#define CURLYB 14      /* \{ */
+
+#define NOSTR  14      /* Codes <= NOSTR can't be *'d. */
+
+#define ANYC   NOSTR+2         /* . */
+#define NORMC  ANYC+2          /* normal character */
+#define CINDC  NORMC+2         /* case independent character */
+#define ONE_OF CINDC+2         /* [xxx] */
+#define NONE_OF        ONE_OF+2        /* [^xxx] */
+#define BACKREF        NONE_OF+2       /* \# */
+#define EOP    BACKREF+2       /* end of pattern */
+
+#define NPAR   10      /* [0-9] - 0th is the entire matched string, i.e. & */
+private int    nparens;
+private char   *comp_p,
+               *start_p,
+               **alt_p,
+               **alt_endp;
+
+void
+REcompile(pattern, re, into_buf, alt_bufp)
+char   *pattern,
+       *into_buf,
+       **alt_bufp;
+{
+       REptr = pattern;
+       REpeekc = -1;
+       comp_p = cur_compb = start_p = into_buf;
+       alt_p = alt_bufp;
+       alt_endp = alt_p + NALTS;
+       *alt_p++ = comp_p;
+       nparens = 0;
+       (void) do_comp(re ? OKAY_RE : NORM);
+       *alt_p = 0;
+}
+
+/* compile the pattern into an internal code */
+
+private int
+do_comp(kind)
+{
+       char    *last_p,
+               *chr_cnt = 0;
+       int     parens[NPAR],
+               *parenp,
+               c,
+               ret_code;
+
+       parenp = parens;
+       last_p = 0;
+       ret_code = 1;
+
+       if (kind == OKAY_RE) {
+               *comp_p++ = OPENP;
+               *comp_p++ = nparens;
+               *parenp++ = nparens++;
+               start_p = comp_p;
+       }
+
+       while (c = REgetc()) {
+               if (comp_p > &cur_compb[(sizeof compbuf) - 6])
+toolong:               complain("Search string too long/complex.");
+               if (c != '*')
+                       last_p = comp_p;
+
+               if (kind == NORM && index(".[*", c) != 0)
+                       goto defchar;
+               switch (c) {
+               case '\\':
+                       switch (c = REgetc()) {
+                       case 0:
+                               complain("Premature end of pattern.");
+
+                       case '{':
+                           {
+                               char    *wcntp;         /* word count */
+
+                               *comp_p++ = CURLYB;
+                               wcntp = comp_p;
+                               *comp_p++ = 0;
+                               for (;;) {
+                                       int     comp_val;
+                                       char    *comp_len;
+
+                                       comp_len = comp_p++;
+                                       comp_val = do_comp(IN_CB);
+                                       *comp_len = comp_p - comp_len;
+                                       (*wcntp) += 1;
+                                       if (comp_val == 0)
+                                               break;
+                               }
+                               break;
+                           }
+
+                       case '}':
+                               if (kind != IN_CB)
+                                       complain("Unexpected \}.");
+                               ret_code = 0;
+                               goto outahere;
+
+                       case '(':
+                               if (nparens >= NPAR)
+                                       complain("Too many ('s; max is %d.", NPAR);
+                               *comp_p++ = OPENP;
+                               *comp_p++ = nparens;
+                               *parenp++ = nparens++;
+                               break;
+
+                       case ')':
+                               if (parenp == parens)
+                                       complain("Too many )'s.");
+                               *comp_p++ = CLOSEP;
+                               *comp_p++ = *--parenp;
+                               break;
+
+                       case '|':
+                               if (alt_p >= alt_endp)
+                                       complain("Too many alternates; max %d.", NALTS);
+                               *comp_p++ = CLOSEP;
+                               *comp_p++ = *--parenp;
+                               *comp_p++ = EOP;
+                               *alt_p++ = comp_p;
+                               nparens = 0;
+                               *comp_p++ = OPENP;
+                               *comp_p++ = nparens;
+                               *parenp++ = nparens++;
+                               start_p = comp_p;
+                               break;
+
+                       case '1':
+                       case '2':
+                       case '3':
+                       case '4':
+                       case '5':
+                       case '6':
+                       case '7':
+                       case '8':
+                       case '9':
+                               *comp_p++ = BACKREF;
+                               *comp_p++ = c - '0';
+                               break;
+
+                       case '<':
+                               *comp_p++ = AT_BOW;
+                               break;
+
+                       case '>':
+                               *comp_p++ = AT_EOW;
+                               break;
+
+                       default:
+                               goto defchar;
+                       }
+                       break;
+
+               case ',':
+                       if (kind != IN_CB)
+                               goto defchar;
+                       goto outahere;
+
+               case '.':
+                       *comp_p++ = ANYC;
+                       break;
+
+               case '^':
+                       if (comp_p == start_p) {
+                               *comp_p++ = AT_BOL;
+                               break;
+                       }
+                       goto defchar;
+
+               case '$':
+                       if ((REpeekc = REgetc()) != 0 && REpeekc != '\\')
+                               goto defchar;
+                       *comp_p++ = AT_EOL;
+                       break;
+
+               case '[':
+                   {
+                       int     chrcnt;
+
+                       *comp_p++ = ONE_OF;
+                       if (comp_p + 16 >= &cur_compb[(sizeof compbuf)])
+                               goto toolong;
+                       bzero(comp_p, 16);
+                       if ((REpeekc = REgetc()) == '^') {
+                               *last_p = NONE_OF;
+                               /* Get it for real this time. */
+                               (void) REgetc();
+                       }
+                       chrcnt = 1;
+                       while ((c = REgetc()) != ']' && c != 0) {
+                               if (c == '\\')
+                                       c = REgetc();
+                               else if ((REpeekc = REgetc()) == '-') {
+                                       int     c2;
+
+                                       (void) REgetc();     /* reread '-' */
+                                       c2 = REgetc();
+                                       while (c < c2) {
+                                               comp_p[c/8] |= (1 << (c%8));
+                                               c += 1;
+                                       }
+                               }
+                               comp_p[c/8] |= (1 << (c%8));
+                               chrcnt += 1;
+                       }
+                       if (c == 0)
+                               complain("Missing ].");
+                       if (chrcnt == 1)
+                               complain("Empty [].");
+                       comp_p += 16;
+                       break;
+                   }
+
+               case '*':
+                       if (last_p == 0 || *last_p <= NOSTR)
+                               goto defchar;
+
+                       /* The * operator applies only to the previous
+                          character.  If we were building a chr_cnt at
+                          the time we got the *, we have to remove the
+                          last character from the chr_cnt (by decrementing
+                          *chr_cnt) and replacing it with a new STAR entry.
+
+                          If we are decrementing the count to 0, we just
+                          delete the chr_cnt entry altogether, replacing
+                          it with the STAR entry. */
+
+                       if (chr_cnt) {
+                               char    lastc = chr_cnt[*chr_cnt];
+                       /* The * operator applies only to the previous
+                          character.  If we were building a chr_cnt at
+                          the time we got the *, we have to remove the
+                          last character from the chr_cnt (by decrementing
+                          *chr_cnt) and replacing it with a new STAR entry.
+                          If we are decrementing the count to 0, we just
+                          delete the chr_cnt entry altogether, replacing
+                          it with the STAR entry. */
+                               if (*chr_cnt == 1) {
+                                       comp_p = chr_cnt;
+                                       comp_p[-1] |= STAR;
+                                       *comp_p++ = lastc;
+                               } else {
+                                       comp_p = chr_cnt + *chr_cnt;
+                                       (*chr_cnt) -= 1;
+                                       *comp_p++ = chr_cnt[-1] | STAR;
+                                       *comp_p++ = lastc;
+                               }
+                       } else
+                               *last_p |= STAR;
+                       break;
+               default:
+defchar:               if (chr_cnt)
+                               (*chr_cnt) += 1;
+                       else {
+                               *comp_p++ = (CaseIgnore) ? CINDC : NORMC;
+                               chr_cnt = comp_p++;
+                               *chr_cnt = 1;   /* last_p[1] = 1; */
+                       }
+                       *comp_p++ = c;
+                       continue;
+               }
+               chr_cnt = FALSE;
+       }
+outahere:
+       /* End of pattern, let's do some error checking. */
+       if (kind == OKAY_RE) {
+               *comp_p++ = CLOSEP;
+               *comp_p++ = *--parenp;
+       }
+       if (parenp != parens)
+               complain("Unmatched ()'s.");
+       if (kind == IN_CB && c == 0)    /* End of pattern with \}. */
+               complain("Missing \}.");
+       *comp_p++ = EOP;
+
+       return ret_code;
+}
+
+private char   *pstrtlst[NPAR],        /* index into REbuf */
+               *pendlst[NPAR],
+               *REbolp,
+               *locs,
+               *loc1,
+               *loc2;
+
+int    REbom,
+       REeom,          /* beginning and end of match */
+       REalt_num;      /* if alternatives, which one matched? */
+
+private int
+backref(n, linep)
+register char  *linep;
+{
+       register char   *backsp,
+                       *backep;
+
+       backsp = pstrtlst[n];
+       backep = pendlst[n];
+       while (*backsp++ == *linep++)
+               if (backsp >= backep)
+                       return 1;
+       return 0;
+}
+
+private int
+member(comp_p, c, af)
+register char  *comp_p;
+register int   c,
+               af;
+{
+       if (c == 0)
+               return 0;       /* try to match EOL always fails */
+       if (comp_p[c/8] & (1 << (c%8)))
+               return af;
+       return !af;
+}
+
+private int
+REmatch(linep, comp_p)
+register char  *linep,
+               *comp_p;
+{
+       char    *first_p = linep;
+       register int    n;
+
+       for (;;) switch (*comp_p++) {
+       case NORMC:
+               n = *comp_p++;
+               while (--n >= 0)
+                       if (*linep++ != *comp_p++)
+                               return 0;
+               continue;
+
+       case CINDC:     /* case independent comparison */
+               n = *comp_p++;
+               while (--n >= 0)
+                       if (!cind_cmp(*linep++, *comp_p++))
+                               return 0;
+               continue;
+
+       case EOP:
+               loc2 = linep;
+               REeom = (loc2 - REbolp);
+               return 1;       /* Success! */
+
+       case AT_BOL:
+               if (linep == REbolp)
+                       continue;
+               return 0;
+
+       case AT_EOL:
+               if (*linep == 0)
+                       continue;
+               return 0;
+
+       case ANYC:
+               if (*linep++ != 0)
+                       continue;
+               return 0;
+
+       case AT_BOW:
+               if (ismword(*linep) && (linep == REbolp || !ismword(linep[-1])))
+                       continue;
+               return 0;
+
+       case AT_EOW:
+               if ((*linep == 0 || !ismword(*linep)) &&
+                   (linep != REbolp && ismword(linep[-1])))
+                       continue;
+               return 0;
+
+       case ONE_OF:
+       case NONE_OF:
+               if (member(comp_p, *linep++, comp_p[-1] == ONE_OF)) {
+                       comp_p += 16;
+                       continue;
+               }
+               return 0;
+
+       case OPENP:
+               pstrtlst[*comp_p++] = linep;
+               continue;
+
+       case CLOSEP:
+               pendlst[*comp_p++] = linep;
+               continue;
+
+       case BACKREF:
+               if (pstrtlst[n = *comp_p++] == 0) {
+                       s_mess("\\%d was not specified.", n + 1);
+                       return 0;
+               }
+               if (backref(n, linep)) {
+                       linep += pendlst[n] - pstrtlst[n];
+                       continue;
+               }
+               return 0;
+
+       case CURLYB:
+           {
+               int     wcnt,
+                       any;
+
+               wcnt = *comp_p++;
+               any = 0;
+
+               while (--wcnt >= 0) {
+                       if (any == 0)
+                               any = REmatch(linep, comp_p + 1);
+                       comp_p += *comp_p;
+               }
+               if (any == 0)
+                       return 0;
+               linep = loc2;
+               continue;
+           }
+
+       case ANYC | STAR:
+               first_p = linep;
+               while (*linep++)
+                       ;
+               goto star;
+
+       case NORMC | STAR:
+               first_p = linep;
+               while (*comp_p == *linep++)
+                       ;
+               comp_p += 1;
+               goto star;
+
+       case CINDC | STAR:
+               first_p = linep;
+               while (cind_cmp(*comp_p, *linep++))
+                       ;
+               comp_p += 1;
+               goto star;
+
+       case ONE_OF | STAR:
+       case NONE_OF | STAR:
+               first_p = linep;
+               while (member(comp_p, *linep++, comp_p[-1] == (ONE_OF | STAR)))
+                       ;
+               comp_p += 16;
+               goto star;
+
+       case BACKREF | STAR:
+               first_p = linep;
+               n = *comp_p++;
+               while (backref(n, linep))
+                       linep += pendlst[n] - pstrtlst[n];
+               while (linep >= first_p) {
+                       if (REmatch(linep, comp_p))
+                               return 1;
+                       linep -= pendlst[n] - pstrtlst[n];
+               }
+               continue;
+
+star:          do {
+                       linep -= 1;
+                       if (linep < locs)
+                               break;
+                       if (REmatch(linep, comp_p))
+                               return 1;
+               } while (linep > first_p);
+               return 0;
+
+       default:
+               complain("RE error match (%d).", comp_p[-1]);
+       }
+       /* NOTREACHED. */
+}
+
+private void
+REreset()
+{
+       register int    i;
+
+       for (i = 0; i < NPAR; i++)
+               pstrtlst[i] = pendlst[i] = 0;
+}
+
+/* Index LINE at OFFSET, the compiled EXPR, with alternates ALTS.  If
+   lbuf_okay is nonzero it's okay to use linebuf if LINE is the current
+   line.  This should save lots of time in things like paren matching in
+   LISP mode.  Saves all that copying from linebuf to REbuf.  substitute()
+   is the guy who calls re_lindex with lbuf_okay as 0, since the substitution
+   gets placed in linebuf ... doesn't work too well when the source and
+   destination strings are the same.  I hate all these arguments!
+
+   This code is cumbersome, repetetive for reasons of efficiency.  Fast
+   search is a must as far as I am concerned. */
+
+int
+re_lindex(line, offset, expr, alts, lbuf_okay)
+Line   *line;
+char   *expr,
+       **alts;
+{
+       int     isquick;
+       register int    firstc,
+                       c;
+       register char   *resp;
+
+       REreset();
+       if (lbuf_okay) {
+               REbolp = lbptr(line);
+               if (offset == -1)
+                       offset = strlen(REbolp);        /* arg! */
+       } else {
+               REbolp = ltobuf(line, REbuf);
+               if (offset == -1) {     /* Reverse search, find end of line. */
+                       extern int      Jr_Len;
+
+                       offset = Jr_Len;        /* Just Read Len. */
+               }
+       }
+       resp = REbolp;
+       isquick = ((expr[0] == NORMC || expr[0] == CINDC) &&
+                  (alternates[1] == 0));
+       if (isquick) {
+               firstc = expr[2];
+               if (expr[0] == CINDC)
+                       firstc = CaseEquiv[firstc];
+       }
+       locs = REbolp + offset;
+
+       if (REdirection == FORWARD) {
+           do {
+               char    **altp = alts;
+
+               if (isquick) {
+                       if (expr[0] == NORMC)
+                               while ((c = *locs++) != 0 && c != firstc)
+                                       ;
+                       else
+                               while (((c = *locs++) != 0) &&
+                                       (CaseEquiv[c] != firstc))
+                                       ;
+                       if (*--locs == 0)
+                               break;
+               }
+               REalt_num = 1;
+               while (*altp) {
+                       if (REmatch(locs, *altp++)) {
+                               loc1 = locs;
+                               REbom = loc1 - REbolp;
+                               return 1;
+                       }
+                       REalt_num += 1;
+               }
+           } while (*locs++);
+       } else {
+           do {
+               char    **altp = alts;
+
+               if (isquick) {
+                       if (expr[0] == NORMC) {
+                               while (locs >= REbolp && *locs-- != firstc)
+                                       ;
+                               if (*++locs != firstc)
+                                       break;
+                       } else {
+                               while (locs >= REbolp && CaseEquiv[*locs--] != firstc)
+                                       ;
+                               if (CaseEquiv[*++locs] != firstc)
+                                       break;
+                       }
+               }
+               REalt_num = 1;
+               while (*altp) {
+                       if (REmatch(locs, *altp++)) {
+                               loc1 = locs;
+                               REbom = loc1 - REbolp;
+                               return 1;
+                       }
+                       REalt_num += 1;
+               }
+           } while (--locs >= resp);
+       }
+
+       return 0;
+}
+
+int    okay_wrap = 0;  /* Do a wrap search ... not when we're
+                          parsing errors ... */
+
+Bufpos *
+dosearch(pattern, dir, re)
+char   *pattern;
+{
+       Bufpos  *pos;
+
+       if (bobp() && eobp())   /* Can't match!  There's no buffer. */
+               return 0;
+
+       REcompile(pattern, re, compbuf, alternates);
+
+       pos = docompiled(dir, compbuf, alternates);
+       return pos;
+}
+
+Bufpos *
+docompiled(dir, expr, alts)
+char   *expr,
+       **alts;
+{
+       static Bufpos   ret;
+       register Line   *lp;
+       register int    offset;
+       int     we_wrapped = NO;
+
+       lsave();
+       /* Search now lsave()'s so it doesn't make any assumptions on
+          whether the the contents of curline/curchar are in linebuf.
+          Nowhere does search write all over linebuf.  However, we have to
+          be careful about what calls we make here, because many of them
+          assume (and rightly so) that curline is in linebuf. */
+
+       REdirection = dir;
+       lp = curline;
+       offset = curchar;
+       if (dir == BACKWARD) {
+               if (bobp()) {
+                       if (okay_wrap && WrapScan)
+                               goto doit;
+                       return 0;
+               }
+               /* here we simulate BackChar() */
+               if (bolp()) {
+                       lp = lp->l_prev;
+                       offset = strlen(lbptr(lp));
+               } else
+                       offset -= 1;
+       } else if ((dir == FORWARD) &&
+                  (lbptr(lp)[offset] == '\0') &&
+                  !lastp(lp)) {
+               lp = lp->l_next;
+               offset = 0;
+       }
+
+       do {
+               if (re_lindex(lp, offset, expr, alts, YES))
+                       break;
+doit:          lp = (dir == FORWARD) ? lp->l_next : lp->l_prev;
+               if (lp == 0) {
+                       if (okay_wrap && WrapScan) {
+                               lp = (dir == FORWARD) ?
+                                    curbuf->b_first : curbuf->b_last;
+                               we_wrapped = YES;
+                       } else
+                                break;
+               }
+               if (dir == FORWARD)
+                       offset = 0;
+               else
+                       offset = -1;    /* signals re_lindex ... */
+       } while (lp != curline);
+
+       if (lp == curline && we_wrapped)
+               lp = 0;
+       if (lp == 0)
+               return 0;
+       ret.p_line = lp;
+       ret.p_char = (dir == FORWARD) ? REeom : REbom;
+       return &ret;
+}
+
+private char *
+insert(off, endp, which)
+char   *off,
+       *endp;
+{
+       register char   *pp;
+       register int    n;
+
+       n = pendlst[which] - pstrtlst[which];
+       pp = pstrtlst[which];
+       while (--n >= 0) {
+               *off++ = *pp++;
+               if (off >= endp)
+                       len_error(ERROR);
+       }
+       return off;
+}
+
+/* Perform the substitution.  If DELP is nonzero the matched string is
+   deleted, i.e., the substitution string is not inserted. */
+
+void
+re_dosub(tobuf, delp)
+char   *tobuf;
+{
+       register char   *tp,
+                       *rp,
+                       *repp;
+       int     c;
+       char    *endp;
+
+       tp = tobuf;
+       endp = tp + LBSIZE;
+       rp = REbuf;
+       repp = rep_str;
+
+       while (rp < loc1)
+               *tp++ = *rp++;
+
+       if (!delp) while (c = *repp++) {
+               if (c == '\\') {
+                       c = *repp++;
+                       if (c == '\0') {
+                               *tp++ = '\\';
+                               goto endchk;
+                       } else if (c >= '1' && c <= nparens + '1') {
+                               tp = insert(tp, endp, c - '0');
+                               continue;
+                       }
+               } else if (c == '&') {
+                       tp = insert(tp, endp, 0);
+                       continue;
+               }
+               *tp++ = c;
+endchk:                if (tp >= endp)
+                       len_error(ERROR);
+       }
+       rp = loc2;
+       loc2 = REbuf + max(1, tp - tobuf);
+       REeom = loc2 - REbuf;
+       /* At least one character past the match, to prevent an infinite
+          number of replacements in the same position, e.g.,
+          replace "^" with "". */
+       while (*tp++ = *rp++)
+               if (tp >= endp)
+                       len_error(ERROR);
+}
+
+void
+putmatch(which, buf, size)
+char   *buf;
+{
+       *(insert(buf, buf + size, which)) = 0;
+}
+
+void
+setsearch(str)
+char   *str;
+{
+       strcpy(searchstr, str);
+}
+
+char *
+getsearch()
+{
+       return searchstr;
+}
+
+void
+RErecur()
+{
+       char    sbuf[sizeof searchstr],
+               cbuf[sizeof compbuf],
+               repbuf[sizeof rep_str],
+               *altbuf[NALTS];
+       int     npars;
+       Mark    *m = MakeMark(curline, REbom, M_FLOATER);
+
+       message("Type C-X C-C to continue with query replace.");
+
+       npars = nparens;
+       byte_copy(compbuf, cbuf, sizeof compbuf);
+       byte_copy(searchstr, sbuf, sizeof searchstr);
+       byte_copy(rep_str, repbuf, sizeof rep_str);
+       byte_copy((char *) alternates, (char *) altbuf, sizeof alternates);
+       Recur();
+       nparens = npars;
+       byte_copy(cbuf, compbuf, sizeof compbuf);
+       byte_copy(sbuf, searchstr, sizeof searchstr);
+       byte_copy(repbuf, rep_str, sizeof rep_str);
+       byte_copy((char *) altbuf, (char *) alternates, sizeof alternates);
+       if (!is_an_arg())
+               ToMark(m);
+       DelMark(m);
+}
+
+void
+ForSearch()
+{
+       search(FORWARD, UseRE, YES);
+}
+
+void
+RevSearch()
+{
+       search(BACKWARD, UseRE, YES);
+}
+
+void
+FSrchND()
+{
+       search(FORWARD, UseRE, NO);
+}
+
+void
+RSrchND()
+{
+       search(BACKWARD, UseRE, NO);
+}
+
+private void
+search(dir, re, setdefault)
+{
+       Bufpos  *newdot;
+       char    *s;
+
+       s = ask(searchstr, ProcFmt);
+       if (setdefault)
+               setsearch(s);
+       okay_wrap = YES;
+       newdot = dosearch(s, dir, re);
+       okay_wrap = NO;
+       if (newdot == 0) {
+               if (WrapScan)
+                       complain("No \"%s\" in buffer.", s);
+               else
+                       complain("No \"%s\" found to %s.", s,
+                                (dir == FORWARD) ? "bottom" : "top");
+       }
+       PushPntp(newdot->p_line);
+       SetDot(newdot);
+}
+
+/* Do we match PATTERN at OFFSET in BUF? */
+
+int
+LookingAt(pattern, buf, offset)
+char   *pattern,
+       *buf;
+{
+       register char   **alt = alternates;
+
+       REcompile(pattern, 1, compbuf, alternates);
+       REreset();
+       locs = buf + offset;
+       REbolp = buf;
+
+       while (*alt)
+               if (REmatch(locs, *alt++))
+                       return 1;
+       return 0;
+}
+
+int
+look_at(expr)
+char   *expr;
+{
+       REcompile(expr, 0, compbuf, alternates);
+       REreset();
+       locs = linebuf + curchar;
+       REbolp = linebuf;
+       if (REmatch(locs, alternates[0]))
+               return 1;
+       return 0;
+}
+
diff --git a/usr/src/new/jove/re.h b/usr/src/new/jove/re.h
new file mode 100644 (file)
index 0000000..1353fa9
--- /dev/null
@@ -0,0 +1,21 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+#define NALTS  10      /* number of alternate search strings */
+
+extern char    searchstr[128],
+               compbuf[128],           /* global default compbuf */
+               rep_search[128],        /* replace search string */
+               rep_str[128],           /* contains replacement string */
+               *cur_compb,             /* usually points at compbuf */
+               REbuf[LBSIZE],          /* points at line we're scanning */
+               *alternates[NALTS];
+
+extern int     REdirection,
+               REeom,
+               REbom,
+               REalt_num;
diff --git a/usr/src/new/jove/re1.c b/usr/src/new/jove/re1.c
new file mode 100644 (file)
index 0000000..41e4a5c
--- /dev/null
@@ -0,0 +1,588 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+#include "jove.h"
+#include "io.h"
+#include "re.h"
+#include "ctype.h"
+
+#ifdef MAC
+#      include "mac.h"
+#else
+#      include <sys/stat.h>
+#endif
+
+#ifdef MAC
+#      undef private
+#      define private
+#endif
+
+#ifdef LINT_ARGS
+private Bufpos * doisearch(int, int, int);
+
+private void
+       IncSearch(int),
+       replace(int, int);
+private int
+       isearch(int, Bufpos *),
+       lookup(char *, char *, char *, char *),
+       substitute(int, Line *, int, Line *, int);
+#else
+private Bufpos * doisearch();
+
+private void
+       IncSearch(),
+       replace();
+private int
+       isearch(),
+       lookup(),
+       substitute();
+#endif /* LINT_ARGS */
+
+#ifdef MAC
+#      undef private
+#      define private static
+#endif
+
+private int
+substitute(query, l1, char1, l2, char2)
+Line   *l1,
+       *l2;
+{
+       Line    *lp;
+       int     numdone = 0,
+               offset = curchar,
+               stop = NO;
+       disk_line       UNDO_da = 0;
+       Line            *UNDO_lp = 0;
+
+       lsave();
+       REdirection = FORWARD;
+
+       lp = l1;
+       for (lp = l1; (lp != l2->l_next) && !stop; lp = lp->l_next) {
+               offset = (lp == l1) ? char1 : 0;
+               while (!stop && re_lindex(lp, offset, compbuf, alternates, 0)) {
+                       if (lp == l2 && REeom > char2)  /* nope, leave this alone */
+                               break;
+                       DotTo(lp, REeom);
+                       offset = curchar;
+                       if (query) {
+                               message("Replace (Type '?' for help)? ");
+reswitch:                      redisplay();
+                               switch (CharUpcase(getchar())) {
+                               case '.':
+                                       stop = YES;
+                                       /* Fall into ... */
+
+                               case ' ':
+                               case 'Y':
+                                       break;
+
+                               case BS:
+                               case RUBOUT:
+                               case 'N':
+                                       if (linebuf[offset++] == '\0')
+                                               goto nxtline;
+                                       continue;
+
+                               case CTL('W'):
+                                       re_dosub(linebuf, YES);
+                                       numdone += 1;
+                                       offset = curchar = REbom;
+                                       makedirty(curline);
+                                       /* Fall into ... */
+
+                               case CTL('R'):
+                               case 'R':
+                                       RErecur();
+                                       offset = curchar;
+                                       lp = curline;
+                                       continue;
+
+                               case CTL('U'):
+                               case 'U':
+                                       if (UNDO_lp == 0)
+                                               continue;
+                                       lp = UNDO_lp;
+                                       lp->l_dline = UNDO_da | DIRTY;
+                                       offset = 0;
+                                       numdone -= 1;
+                                       continue;
+
+                               case 'P':
+                               case '!':
+                                       query = 0;
+                                       break;
+
+                               case CR:
+                               case LF:
+                               case 'Q':
+                                       goto done;
+
+                               case CTL('L'):
+                                       RedrawDisplay();
+                                       goto reswitch;
+
+                               default:
+                                       rbell();
+message("Space or Y, Period, Rubout or N, C-R or R, C-W, C-U or U, P or !, Return.");
+                                       goto reswitch;
+                               }
+                       }
+                       re_dosub(linebuf, NO);
+                       numdone += 1;
+                       modify();
+                       offset = curchar = REeom;
+                       makedirty(curline);
+                       if (query) {
+                               message(mesgbuf);       /* no blinking */
+                               redisplay();            /* show the change */
+                       }
+                       UNDO_da = curline->l_dline;
+                       UNDO_lp = curline;
+                       if (linebuf[offset] == 0)
+nxtline:                       break;
+               }
+       }
+done:  return numdone;
+}
+
+/* prompt for search and replacement strings and do the substitution */
+private void
+replace(query, inreg)
+{
+       Mark    *m;
+       char    *rep_ptr;
+       Line    *l1 = curline,
+               *l2 = curbuf->b_last;
+       int     char1 = curchar,
+               char2 = length(curbuf->b_last),
+               numdone;
+
+       if (inreg) {
+               m = CurMark();
+               l2 = m->m_line;
+               char2 = m->m_char;
+               (void) fixorder(&l1, &char1, &l2, &char2);
+       }
+
+       /* get search string */
+       strcpy(rep_search, ask(rep_search[0] ? rep_search : (char *) 0, ProcFmt));
+       REcompile(rep_search, UseRE, compbuf, alternates);
+       /* Now the replacement string.  Do_ask() so the user can play with
+          the default (previous) replacement string by typing C-R in ask(),
+          OR, he can just hit Return to replace with nothing. */
+       rep_ptr = do_ask("\r\n", (int (*)()) 0, rep_str, ": %f %s with ", rep_search);
+       if (rep_ptr == 0)
+               rep_ptr = NullStr;
+       strcpy(rep_str, rep_ptr);
+
+       if (((numdone = substitute(query, l1, char1, l2, char2)) != 0) &&
+           (inreg == NO)) {
+               do_set_mark(l1, char1);
+               add_mess(" ");          /* just making things pretty */
+       } else
+               message("");
+       add_mess("(%d substitution%n)", numdone, numdone);
+}
+
+void
+RegReplace()
+{
+       replace(0, YES);
+}
+
+void
+QRepSearch()
+{
+       replace(1, NO);
+}
+
+void
+RepSearch()
+{
+       replace(0, NO);
+}
+
+/* Lookup a tag in tag file FILE.  FILE is assumed to be sorted
+   alphabetically.  The FASTTAGS code, which is implemented with
+   a binary search, depends on this assumption.  If it's not true
+   it is possible to comment out the fast tag code (which is clearly
+   labeled) and everything else will just work. */
+
+private int
+lookup(searchbuf, filebuf, tag, file)
+char   *searchbuf,
+       *filebuf,
+       *tag,
+       *file;
+{
+       register int    taglen = strlen(tag);
+       char    line[BUFSIZ],
+               pattern[128];
+       register File   *fp;
+       struct stat     stbuf;
+       int     fast = YES,
+               success = NO;
+       register off_t  lower, upper;
+
+       sprintf(pattern, "^%s[^\t]*\t*\\([^\t]*\\)\t*[?/]\\([^?/]*\\)[?/]", tag);
+       fp = open_file(file, iobuff, F_READ, !COMPLAIN, QUIET);
+       if (fp == NIL)
+               return 0;
+
+       /* ********BEGIN FAST TAG CODE******** */
+
+       if (stat(file, &stbuf) < 0)
+               fast = NO;
+       else {
+               lower = 0;
+               upper = stbuf.st_size;
+               if (upper - lower < BUFSIZ)
+                       fast = NO;
+       }
+       if (fast == YES) for (;;) {
+               off_t   mid;
+               int     whichway,
+                       chars_eq;
+
+               if (upper - lower < BUFSIZ) {
+                       f_seek(fp, lower);
+                       break;                  /* stop this nonsense */
+               }
+               mid = (lower + upper) / 2;
+               f_seek(fp, mid);
+               f_toNL(fp);
+               if (f_gets(fp, line, sizeof line) == EOF)
+                       break;
+               chars_eq = numcomp(line, tag);
+               if (chars_eq == taglen && iswhite(line[chars_eq]))
+                       goto found;
+               whichway = line[chars_eq] - tag[chars_eq];
+               if (whichway < 0) {             /* line is BEFORE tag */
+                       lower = mid;
+                       continue;
+               } else if (whichway > 0) {      /* line is AFTER tag */
+                       upper = mid;
+                       continue;
+               }
+       }
+       f_toNL(fp);
+       /* END FAST TAG CODE */
+
+       while (f_gets(fp, line, sizeof line) != EOF) {
+               int     cmp;
+
+               if (line[0] > *tag)
+                       break;
+               else if ((cmp = strncmp(line, tag, taglen)) > 0)
+                       break;
+               else if (cmp < 0)
+                       continue;
+               /* if we get here, we've found the match */
+found:         if (!LookingAt(pattern, line, 0)) {
+                       complain("I thought I saw it!");
+                       break;
+               } else {
+                       putmatch(1, filebuf, FILESIZE);
+                       putmatch(2, searchbuf, 100);
+                       success = YES;
+                       break;
+               }
+       }
+       close_file(fp);
+               
+       if (success == NO)
+               s_mess("Can't find tag \"%s\".", tag);
+       return success;
+}
+
+#ifndef MSDOS
+char   TagFile[FILESIZE] = "./tags";
+#else /* MSDOS */
+char   TagFile[FILESIZE] = "tags";
+#endif /* MSDOS */
+
+void
+find_tag(tag, localp)
+char   *tag;
+{
+       char    filebuf[FILESIZE],
+               sstr[100],
+               tfbuf[FILESIZE];
+       register Bufpos *bp;
+       register Buffer *b;
+       char    *tagfname;
+
+       if (!localp) {
+               char    prompt[128];
+
+               sprintf(prompt, "With tag file (%s default): ", TagFile);
+               tagfname = ask_file(prompt, TagFile, tfbuf);
+       } else
+               tagfname = TagFile;
+       if (lookup(sstr, filebuf, tag, tagfname) == 0)
+               return;
+       set_mark();
+       b = do_find(curwind, filebuf, 0);
+       if (curbuf != b)
+               SetABuf(curbuf);
+       SetBuf(b);
+       if ((bp = dosearch(sstr, BACKWARD, 0)) == 0 &&
+           ((bp = dosearch(sstr, FORWARD, 0)) == 0))
+               message("Well, I found the file, but the tag is missing.");
+       else
+               SetDot(bp);
+}
+
+void
+FindTag()
+{
+       int     localp = !is_an_arg();
+       char    tag[128];
+
+       strcpy(tag, ask((char *) 0, ProcFmt));
+       find_tag(tag, localp);
+}
+
+/* Find Tag at Dot. */
+
+void
+FDotTag()
+{
+       int     c1 = curchar,
+               c2 = c1;
+       char    tagname[50];
+
+       if (!ismword(linebuf[curchar]))
+               complain("Not a tag!");
+       while (c1 > 0 && ismword(linebuf[c1 - 1]))
+               c1 -= 1;
+       while (ismword(linebuf[c2]))
+               c2 += 1;
+
+       null_ncpy(tagname, linebuf + c1, c2 - c1);
+       find_tag(tagname, !is_an_arg());
+}
+
+/* I-search returns a code saying what to do:
+   STOP:       We found the match, so unwind the stack and leave
+               where it is.
+   DELETE:     Rubout the last command.
+   BACKUP:     Back up to where the isearch was last NOT failing.
+
+   When a character is typed it is appended to the search string, and
+   then, isearch is called recursively.  When C-S or C-R is typed, isearch
+   is again called recursively. */
+
+#define STOP   1
+#define DELETE 2
+#define BACKUP 3
+#define TOSTART        4
+
+static char    ISbuf[128],
+               *incp = 0;
+int    SExitChar = CR;
+
+#define cmp_char(a, b) ((a) == (b) || (CaseIgnore && (CharUpcase(a) == CharUpcase(b))))
+
+static Bufpos *
+doisearch(dir, c, failing)
+register int   c,
+               dir,
+               failing;
+{
+       static Bufpos   buf;
+       Bufpos  *bp;
+       extern int      okay_wrap;
+
+       if (c == CTL('S') || c == CTL('R'))
+               goto dosrch;
+
+       if (failing)
+               return 0;
+       DOTsave(&buf);
+       if (dir == FORWARD) {
+               if (cmp_char(linebuf[curchar], c)) {
+                       buf.p_char = curchar + 1;
+                       return &buf;
+               }
+       } else {
+               if (look_at(ISbuf))
+                       return &buf;
+       }
+dosrch:        okay_wrap = YES;
+       if ((bp = dosearch(ISbuf, dir, 0)) == 0)
+               rbell();        /* ring the first time there's no match */
+       okay_wrap = NO;
+       return bp;
+}
+
+void
+IncFSearch()
+{
+       IncSearch(FORWARD);
+}
+
+void
+IncRSearch()
+{
+       IncSearch(BACKWARD);
+}
+
+private void
+IncSearch(dir)
+{
+       Bufpos  save_env;
+
+       DOTsave(&save_env);
+       ISbuf[0] = 0;
+       incp = ISbuf;
+       if (isearch(dir, &save_env) == TOSTART)
+               SetDot(&save_env);
+       else {
+               if (LineDist(curline, save_env.p_line) >= MarkThresh)
+                       do_set_mark(save_env.p_line, save_env.p_char);
+       }
+       setsearch(ISbuf);
+}
+
+/* Nicely recursive. */
+
+private int
+isearch(dir, bp)
+Bufpos *bp;
+{
+       Bufpos  pushbp;
+       int     c,
+               ndir,
+               failing;
+       char    *orig_incp;
+
+       if (bp != 0) {          /* Move to the new position. */
+               pushbp.p_line = bp->p_line;
+               pushbp.p_char = bp->p_char;
+               SetDot(bp);
+               failing = 0;
+       } else {
+               DOTsave(&pushbp);
+               failing = 1;
+       }
+       orig_incp = incp;
+       ndir = dir;             /* Same direction as when we got here, unless
+                                  we change it with C-S or C-R. */
+       for (;;) {
+               SetDot(&pushbp);
+               message(NullStr);
+               if (failing)
+                       add_mess("Failing ");
+               if (dir == BACKWARD)
+                       add_mess("reverse-");
+               add_mess("I-search: %s", ISbuf);
+               DrawMesg(NO);
+               add_mess(NullStr);      /* tell me this is disgusting ... */
+               c = getch();
+               if (c == SExitChar)
+                       return STOP;
+               if (c == AbortChar) {
+                       /* If we're failing, we backup until we're no longer
+                          failing or we've reached the beginning; else, we
+                          just about the search and go back to the start. */
+                       if (failing)
+                               return BACKUP;
+                       return TOSTART;
+               }
+               switch (c) {
+               case RUBOUT:
+               case BS:
+                       return DELETE;
+
+               case CTL('\\'):
+                       c = CTL('S');
+
+               case CTL('S'):
+               case CTL('R'):
+                       /* If this is the first time through and we have a
+                          search string left over from last time, use that
+                          one now. */
+                       if (incp == ISbuf) {
+                               strcpy(ISbuf, getsearch());
+                               incp = &ISbuf[strlen(ISbuf)];
+                       }
+                       ndir = (c == CTL('S')) ? FORWARD : BACKWARD;
+                       /* If we're failing and we're not changing our
+                          direction, don't recur since there's no way
+                          the search can work. */
+                       if (failing && ndir == dir) {
+                               rbell();
+                               continue;
+                       }
+                       break;
+
+               case '\\':
+                       if (incp > &ISbuf[(sizeof ISbuf) - 1]) {
+                               rbell();
+                               continue;
+                       }
+                       *incp++ = '\\';
+                       add_mess("\\");
+                       /* Fall into ... */
+
+               case CTL('Q'):
+               case CTL('^'):
+                       add_mess("");
+                       c = getch() | 0400;
+                       /* Fall into ... */
+
+               default:
+                       if (c & 0400)
+                               c &= CHARMASK;
+                       else {
+#ifdef IBMPC
+                               if (c == RUBOUT || c == 0xff || (c < ' ' && c != '\t')) {
+#else
+                               if (c > RUBOUT || (c < ' ' && c != '\t')) {
+#endif
+                                       Ungetc(c);
+                                       return STOP;
+                               }
+                       }
+                       if (incp > &ISbuf[(sizeof ISbuf) - 1]) {
+                               rbell();
+                               continue;
+                       }
+                       *incp++ = c;
+                       *incp = 0;
+                       break;
+               }
+               add_mess("%s", orig_incp);
+               add_mess(" ...");       /* so we know what's going on */
+               DrawMesg(NO);           /* do it now */
+               switch (isearch(ndir, doisearch(ndir, c, failing))) {
+               case TOSTART:
+                       return TOSTART;
+
+               case STOP:
+                       return STOP;
+
+               case BACKUP:
+                       /* If we're not failing, we just continue to to the
+                          for loop; otherwise we keep returning to the 
+                          previous levels until we find one that isn't
+                          failing OR we reach the beginning. */
+                       if (failing)
+                               return BACKUP;
+                       /* Fall into ... */
+
+               case DELETE:
+                       incp = orig_incp;
+                       *incp = 0;
+                       continue;
+               }
+       }
+}
diff --git a/usr/src/new/jove/rec.c b/usr/src/new/jove/rec.c
new file mode 100644 (file)
index 0000000..c406732
--- /dev/null
@@ -0,0 +1,169 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+#include "jove.h"
+#include "io.h"
+#include "rec.h"
+
+#ifndef MAC
+#      include <sys/file.h>
+#endif
+
+private int    rec_fd = -1;
+private char   *recfname;
+private File   *rec_out;
+
+#ifndef L_SET
+#      define L_SET 0
+#endif
+
+private struct rec_head        Header;
+
+recinit()
+{
+       char    buf[128];
+
+#ifdef MAC
+       sprintf(buf, "%s/%s", HomeDir, p_tempfile);
+#else
+       sprintf(buf, "%s/%s", TmpFilePath, p_tempfile);
+#endif
+       recfname = copystr(buf);
+       recfname = mktemp(recfname);
+       rec_fd = creat(recfname, 0644);
+       if (rec_fd == -1) {
+               complain("Cannot create \"%s\"; recovery disabled.", recfname);
+               return;
+       }
+       /* initialize the record IO */
+       rec_out = fd_open(recfname, F_WRITE|F_LOCKED, rec_fd, iobuff, LBSIZE);
+
+       /* Initialize the record header. */
+       Header.Uid = getuid();
+       Header.Pid = getpid();
+       Header.UpdTime = 0L;
+       Header.Nbuffers = 0;
+       (void) write(rec_fd, (char *) &Header, sizeof Header);
+}
+
+recclose()
+{
+       if (rec_fd == -1)
+               return;
+       (void) close(rec_fd);
+       rec_fd = -1;
+       (void) unlink(recfname);
+}
+
+private
+putaddr(addr, p)
+disk_line      addr;
+register File  *p;
+{
+       register char   *cp = (char *) &addr;
+       register int    nchars = sizeof (disk_line);
+
+       while (--nchars >= 0)
+               putc(*cp++ & 0377, p);
+}
+
+private
+putn(cp, nbytes)
+register char  *cp;
+register int   nbytes;
+{
+       while (--nbytes >= 0)
+               putc(*cp++ & 0377, rec_out);
+}
+
+/* Write out the line pointers for buffer B. */
+
+private
+dmppntrs(b)
+register Buffer        *b;
+{
+       register Line   *lp;
+
+       for (lp = b->b_first; lp != 0; lp = lp->l_next)
+               putaddr(lp->l_dline, rec_out);
+}
+
+/* dump the buffer info and then the actual line pointers. */
+
+private
+dmp_buf_header(b)
+register Buffer        *b;
+{
+       struct rec_entry        record;
+       register Line   *lp;
+       register int    nlines = 0;
+
+       for (lp = b->b_first; lp != 0; lp = lp->l_next, nlines++)
+               if (lp == b->b_dot)
+                       record.r_dotline = nlines;
+       strcpy(record.r_fname, b->b_fname ? b->b_fname : NullStr);
+       strcpy(record.r_bname, b->b_name);
+       record.r_nlines = nlines;
+       record.r_dotchar = b->b_char;
+       putn((char *) &record, sizeof record);
+}
+
+/* Goes through all the buffers and syncs them to the disk. */
+
+int    SyncFreq = 50;
+
+SyncRec()
+{
+       extern disk_line        DFree;
+       register Buffer *b;
+       static int      beenhere = NO;
+
+       if (beenhere == NO) {
+               recinit();      /* Init recover file. */
+               beenhere = YES;
+       }
+       if (rec_fd == -1)
+               return;
+       lseek(rec_fd, 0L, L_SET);
+       (void) time(&Header.UpdTime);
+       Header.Nbuffers = 0;
+       for (b = world; b != 0; b = b->b_next)
+               if (b->b_type == B_SCRATCH || !IsModified(b))
+                       continue;
+               else
+                       Header.Nbuffers += 1;
+       Header.FreePtr = DFree;
+       putn((char *) &Header, sizeof Header);
+       if (Header.Nbuffers != 0) {
+               lsave();        /* this makes things really right */
+               SyncTmp();
+               for (b = world; b != 0; b = b->b_next)
+                       if (b->b_type == B_SCRATCH || !IsModified(b))
+                               continue;
+                       else
+                               dmp_buf_header(b);
+               for (b = world; b != 0; b = b->b_next)
+                       if (b->b_type == B_SCRATCH || !IsModified(b))
+                               continue;
+                       else
+                               dmppntrs(b);
+       }
+       flush(rec_out);
+}
+
+/* Full Recover.  What we have to do is go find the name of the tmp
+   file data/rec pair and use those instead of the ones we would have
+   created eventually.  The rec file has a list of buffers, and then
+   the actual pointers.  Stored for each buffer is the buffer name,
+   the file name, the number of lines, the current line, the current
+   character.  The current modes do not need saving as they will be
+   saved when the file name is set.  If a process was running in a
+   buffer, it will be lost. */
+
+FullRecover()
+{
+}
diff --git a/usr/src/new/jove/rec.h b/usr/src/new/jove/rec.h
new file mode 100644 (file)
index 0000000..e1cf0d3
--- /dev/null
@@ -0,0 +1,22 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+struct rec_head {
+       int             Uid,            /* uid of owner */
+                       Pid;            /* pid of jove process */
+       time_t          UpdTime;        /* last time this was updated */
+       int             Nbuffers;       /* number of buffers */
+       disk_line       FreePtr;        /* position of DFree */
+};
+
+struct rec_entry {
+       char    r_bname[128],
+               r_fname[128];
+       int     r_nlines,
+               r_dotline,      /* so we can really save the context */
+               r_dotchar;
+};
diff --git a/usr/src/new/jove/recover.c b/usr/src/new/jove/recover.c
new file mode 100644 (file)
index 0000000..873ae07
--- /dev/null
@@ -0,0 +1,730 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+/* Recovers JOVE files after a system/editor crash.
+   Usage: recover [-d directory] [-syscrash]
+   The -syscrash option is specified in /etc/rc and what it does is
+   move all the jove tmp files from TMP_DIR to REC_DIR.
+
+   The -d option lets you specify the directory to search for tmp files when
+   the default isn't the right one.
+
+   Look in Makefile to change the default directories. */
+
+#include <stdio.h>     /* Do stdio first so it doesn't override OUR
+                          definitions. */
+#undef EOF
+#undef BUFSIZ
+#undef putchar
+#undef getchar
+
+#define STDIO
+
+#include "jove.h"
+#include "temp.h"
+#include "rec.h"
+#include <signal.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/dir.h>
+
+#ifndef L_SET
+#      define L_SET    0
+#      define L_INCR   1
+#endif
+
+char   blk_buf[BUFSIZ];
+int    nleft;
+FILE   *ptrs_fp;
+int    data_fd;
+struct rec_head        Header;
+char   datafile[40],
+       pntrfile[40];
+long   Nchars,
+       Nlines;
+char   tty[] = "/dev/tty";
+int    UserID,
+       Verbose = 0;
+char   *Directory = 0;         /* the directory we're looking in */
+
+struct file_pair {
+       char    *file_data,
+               *file_rec;
+#define INSPECTED      01
+       int     file_flags;
+       struct file_pair        *file_next;
+} *First = 0,
+  *Last = 0;
+
+struct rec_entry       *buflist[100] = {0};
+
+#ifndef BSD4_2
+
+typedef struct {
+       int     d_fd;           /* File descriptor for this directory */
+} DIR;
+
+DIR *
+opendir(dir)
+char   *dir;
+{
+       DIR     *dp = (DIR *) malloc(sizeof *dp);
+
+       if ((dp->d_fd = open(dir, 0)) == -1)
+               return NULL;
+       return dp;
+}
+
+closedir(dp)
+DIR    *dp;
+{
+       (void) close(dp->d_fd);
+       free(dp);
+}
+
+struct direct *
+readdir(dp)
+DIR    *dp;
+{
+       static struct direct    dir;
+
+       do
+               if (read(dp->d_fd, &dir, sizeof dir) != sizeof dir)
+                       return NULL;
+#if defined(elxsi) && defined(SYSV)
+       /*
+        * Elxsi has a BSD4.2 implementation which may or may not use
+        * `twisted inodes' ...  Anyone able to check?
+        */
+       while (*(unsigned short *)&dir.d_ino == 0);
+#else
+       while (dir.d_ino == 0);
+#endif
+
+       return &dir;
+}
+
+#endif /* BSD4_2 */
+
+/* Get a line at `tl' in the tmp file into `buf' which should be LBSIZE
+   long. */
+
+getline(tl, buf)
+disk_line      tl;
+char   *buf;
+{
+       register char   *bp,
+                       *lp;
+       register int    nl;
+       char    *getblock();
+
+       lp = buf;
+       bp = getblock(tl >> 1);
+       nl = nleft;
+       tl = blk_round(tl);
+
+       while (*lp++ = *bp++) {
+               if (--nl == 0) {
+                       tl = forward_block(tl);
+                       bp = getblock(tl >> 1);
+                       nl = nleft;
+               }
+       }
+}
+
+char *
+getblock(atl)
+disk_line      atl;
+{
+       int     bno,
+               off;
+       static int      curblock = -1;
+
+       bno = da_to_bno(atl);
+       off = da_to_off(atl);
+       nleft = BUFSIZ - off;
+
+       if (bno != curblock) {
+               lseek(data_fd, (long) bno * BUFSIZ, L_SET);
+               read(data_fd, blk_buf, BUFSIZ);
+               curblock = bno;
+       }
+       return blk_buf + off;
+}
+
+char *
+copystr(s)
+char   *s;
+{
+       char    *str;
+
+       str = malloc(strlen(s) + 1);
+       strcpy(str, s);
+
+       return str;
+}
+
+/* Scandir returns the number of entries or -1 if the directory cannoot
+   be opened or malloc fails. */
+
+scandir(dir, nmptr, qualify, sorter)
+char   *dir;
+struct direct  ***nmptr;
+int    (*qualify)();
+struct direct  *(*sorter)();
+{
+       DIR     *dirp;
+       struct direct   *entry,
+                       **ourarray;
+       int     nalloc = 10,
+               nentries = 0;
+
+       if ((dirp = opendir(dir)) == NULL)
+               return -1;
+       ourarray = (struct direct **) malloc(nalloc * sizeof (struct direct *));
+       while ((entry = readdir(dirp)) != NULL) {
+               if (qualify != 0 && (*qualify)(entry) == 0)
+                       continue;
+               if (nentries == nalloc) {
+                       ourarray = (struct direct **) realloc(ourarray, (nalloc += 10) * sizeof (struct direct));
+                       if (ourarray == NULL)
+                               return -1;
+               }
+               ourarray[nentries] = (struct direct *) malloc(sizeof *entry);
+               *ourarray[nentries] = *entry;
+               nentries += 1;
+       }
+       closedir(dirp);
+       if (nentries != nalloc)
+               ourarray = (struct direct **) realloc(ourarray,
+                                       (nentries * sizeof (struct direct)));
+       if (sorter != 0)
+               qsort(ourarray, nentries, sizeof (struct direct **), sorter);
+       *nmptr = ourarray;
+
+       return nentries;
+}
+
+alphacomp(a, b)
+struct direct  **a,
+               **b;
+{
+       return strcmp((*a)->d_name, (*b)->d_name);
+}
+
+char   *CurDir;
+
+/* Scan the DIRNAME directory for jove tmp files, and make a linked list
+   out of them. */
+
+get_files(dirname)
+char   *dirname;
+{
+       int     add_name();
+       struct direct   **nmptr;
+
+       CurDir = dirname;
+       scandir(dirname, &nmptr, add_name, (int (*)())0);
+}
+
+add_name(dp)
+struct direct  *dp;
+{
+       char    dfile[128],
+               rfile[128];
+       struct file_pair        *fp;
+       struct rec_head         header;
+       int     fd;
+
+       if (strncmp(dp->d_name, "jrec", 4) != 0)
+               return 0;
+       /* If we get here, we found a "recover" tmp file, so now
+          we look for the corresponding "data" tmp file.  First,
+          though, we check to see whether there is anything in
+          the "recover" file.  If it's 0 length, there's no point
+          in saving its name. */
+       (void) sprintf(rfile, "%s/%s", CurDir, dp->d_name);
+       (void) sprintf(dfile, "%s/jove%s", CurDir, dp->d_name + 4);
+       if ((fd = open(rfile, 0)) != -1) {
+               if ((read(fd, (char *) &header, sizeof header) != sizeof header)) {
+                       close(fd);
+                       return 0;
+               } else
+                       close(fd);
+       }
+       if (access(dfile, 0) != 0) {
+               fprintf(stderr, "recover: can't find the data file for %s/%s\n", Directory, dp->d_name);
+               fprintf(stderr, "so deleting...\n");
+               (void) unlink(rfile);
+               (void) unlink(dfile);
+               return 0;
+       }
+       /* If we get here, we've found both files, so we put them
+          in the list. */
+       fp = (struct file_pair *) malloc (sizeof *fp);
+       if ((char *) fp == 0) {
+               fprintf(stderr, "recover: cannot malloc for file_pair.\n");
+               exit(-1);
+       }
+       fp->file_data = copystr(dfile);
+       fp->file_rec = copystr(rfile);
+       fp->file_flags = 0;
+       fp->file_next = First;
+       First = fp;
+
+       return 1;
+}
+
+options()
+{
+       printf("Options are:\n");
+       printf("        ?               list options.\n");
+       printf("        get             get a buffer to a file.\n");
+       printf("        list            list known buffers.\n");
+       printf("        print           print a buffer to terminal.\n");
+       printf("        quit            quit and delete jove tmp files.\n");
+       printf("        restore         restore all buffers.\n");
+}
+
+/* Returns a legitimate buffer # */
+
+struct rec_entry **
+getsrc()
+{
+       char    name[128];
+       int     number;
+
+       for (;;) {
+               tellme("Which buffer ('?' for list)? ", name);
+               if (name[0] == '?')
+                       list();
+               else if (name[0] == '\0')
+                       return 0;
+               else if ((number = atoi(name)) > 0 && number <= Header.Nbuffers)
+                       return &buflist[number];
+               else {
+                       int     i;
+
+                       for (i = 1; i <= Header.Nbuffers; i++)
+                               if (strcmp(buflist[i]->r_bname, name) == 0)
+                                       return &buflist[i];
+                       printf("%s: unknown buffer.\n", name);
+               }
+       }
+}
+
+/* Get a destination file name. */
+
+static char *
+getdest()
+{
+       static char     filebuf[256];
+
+       tellme("Output file: ", filebuf);
+       if (filebuf[0] == '\0')
+               return 0;
+       return filebuf;
+}
+
+#include "ctype.h"
+
+char *
+readword(buf)
+char   *buf;
+{
+       int     c;
+       char    *bp = buf;
+
+       while (index(" \t\n", c = getchar()))
+               ;
+
+       do {
+               if (index(" \t\n", c))
+                       break;
+               *bp++ = c;
+       } while ((c = getchar()) != EOF);
+       *bp = 0;
+
+       return buf;
+}
+
+tellme(quest, answer)
+char   *quest,
+       *answer;
+{
+       if (stdin->_cnt <= 0) {
+               printf("%s", quest);
+               fflush(stdout);
+       }
+       readword(answer);
+}
+
+/* Print the specified file to strandard output. */
+
+jmp_buf        int_env;
+
+catch()
+{
+       longjmp(int_env, 1);
+}
+
+restore()
+{
+       register int    i;
+       char    tofile[100],
+               answer[30];
+       int     nrecovered = 0;
+
+       for (i = 1; i <= Header.Nbuffers; i++) {
+               (void) sprintf(tofile, "#%s", buflist[i]->r_bname);
+tryagain:
+               printf("Restoring %s to %s, okay?", buflist[i]->r_bname,
+                                                    tofile);
+               tellme(" ", answer);
+               switch (answer[0]) {
+               case 'y':
+                       break;
+
+               case 'n':
+                       continue;
+
+               default:
+                       tellme("What file should I use instead? ", tofile);
+                       goto tryagain;
+               }
+               get(&buflist[i], tofile);
+               nrecovered += 1;
+       }
+       printf("Recovered %d buffers.\n", nrecovered);
+}
+
+get(src, dest)
+struct rec_entry       **src;
+char   *dest;
+{
+       FILE    *outfile;
+
+       if (src == 0 || dest == 0)
+               return;
+       (void) signal(SIGINT, catch);
+       if (setjmp(int_env) == 0) {
+               if ((outfile = fopen(dest, "w")) == NULL) {
+                       printf("recover: cannot create %s.\n", dest);
+                       return;
+               }
+               if (dest != tty)
+                       printf("\"%s\"", dest);
+               dump_file(src - buflist, outfile);
+       } else
+               printf("\nAborted!\n");
+       fclose(outfile);
+       if (dest != tty)
+               printf(" %ld lines, %ld characters.\n", Nlines, Nchars);
+       (void) signal(SIGINT, SIG_DFL);
+}
+
+char **
+scanvec(args, str)
+register char  **args,
+               *str;
+{
+       while (*args) {
+               if (strcmp(*args, str) == 0)
+                       return args;
+               args += 1;
+       }
+       return 0;
+}
+
+read_rec(recptr)
+struct rec_entry       *recptr;
+{
+       if (fread((char *) recptr, sizeof *recptr, 1, ptrs_fp) != 1)
+               fprintf(stderr, "recover: cannot read record.\n");
+}
+
+seekto(which)
+{
+       struct rec_entry        rec;
+       long    offset;
+       int     i;
+
+       offset = sizeof (Header) + (Header.Nbuffers * sizeof (rec));
+       for (i = 1; i < which; i++)
+               offset += buflist[i]->r_nlines * sizeof (disk_line);
+       fseek(ptrs_fp, offset, L_SET);
+}
+
+makblist()
+{
+       int     i;
+
+       fseek(ptrs_fp, (long) sizeof (Header), L_SET);
+       for (i = 1; i <= Header.Nbuffers; i++) {
+               if (buflist[i] == 0)
+                       buflist[i] = (struct rec_entry *) malloc (sizeof (struct rec_entry));
+               read_rec(buflist[i]);
+       }
+       while (buflist[i]) {
+               free((char *) buflist[i]);
+               buflist[i] = 0;
+               i += 1;
+       }
+}
+
+disk_line
+getaddr(fp)
+register FILE  *fp;
+{
+       register int    nchars = sizeof (disk_line);
+       disk_line       addr;
+       register char   *cp = (char *) &addr;
+
+       while (--nchars >= 0)
+               *cp++ = getc(fp);
+
+       return addr;
+}
+
+dump_file(which, out)
+FILE   *out;
+{
+       register int    nlines;
+       register disk_line      daddr;
+       char    buf[BUFSIZ];
+
+       seekto(which);
+       nlines = buflist[which]->r_nlines;
+       Nchars = Nlines = 0L;
+       while (--nlines >= 0) {
+               daddr = getaddr(ptrs_fp);
+               getline(daddr, buf);
+               Nlines += 1;
+               Nchars += 1 + strlen(buf);
+               fputs(buf, out);
+               if (nlines > 0)
+                       fputc('\n', out);
+       }
+       if (out != stdout)
+               fclose(out);
+}
+
+/* List all the buffers. */
+
+list()
+{
+       int     i;
+
+       for (i = 1; i <= Header.Nbuffers; i++)
+               printf("%d) buffer %s  \"%s\" (%d lines)\n", i,
+                       buflist[i]->r_bname,
+                       buflist[i]->r_fname,
+                       buflist[i]->r_nlines);
+}
+
+doit(fp)
+struct file_pair       *fp;
+{
+       char    answer[30];
+       char    *datafile = fp->file_data,
+               *pntrfile = fp->file_rec;
+
+       ptrs_fp = fopen(pntrfile, "r");
+       if (ptrs_fp == NULL) {
+               if (Verbose)
+                       fprintf(stderr, "recover: cannot read rec file (%s).\n", pntrfile);
+               return 0;
+       }
+       fread((char *) &Header, sizeof Header, 1, ptrs_fp);
+       if (Header.Uid != UserID)
+               return 0;
+
+       /* Don't ask about JOVE's that are still running ... */
+#ifdef KILL0
+       if (kill(Header.Pid, 0) == 0)
+               return 0;
+#endif /* KILL0 */
+
+       if (Header.Nbuffers == 0) {
+               printf("There are no modified buffers in %s; should I delete the tmp file?", pntrfile);
+               ask_del(" ", fp);
+               return 1;
+       }
+               
+       if (Header.Nbuffers < 0) {
+               fprintf(stderr, "recover: %s doesn't look like a jove file.\n", pntrfile);
+               ask_del("Should I delete it? ", fp);
+               return 1;       /* We'll, we sort of found something. */
+       }
+       printf("Found %d buffer%s last updated: %s",
+               Header.Nbuffers,
+               Header.Nbuffers != 1 ? "s" : "",
+               ctime(&Header.UpdTime));
+       data_fd = open(datafile, 0);
+       if (data_fd == -1) {
+               fprintf(stderr, "recover: but I can't read the data file (%s).\n", datafile);
+               ask_del("Should I delete the tmp files? ", fp);
+               return 1;
+       }
+       makblist();
+       list();
+
+       for (;;) {
+               tellme("(Type '?' for options): ", answer);
+               switch (answer[0]) {
+               case '\0':
+                       continue;
+
+               case '?':
+                       options();
+                       break;
+
+               case 'l':
+                       list();
+                       break;
+
+               case 'p':
+                       get(getsrc(), tty);
+                       break;
+
+               case 'q':
+                       ask_del("Shall I delete the tmp files? ", fp);
+                       return 1;
+
+               case 'g':
+                   {   /* So it asks for src first. */
+                       char    *dest;
+                       struct rec_entry        **src;
+
+                       if ((src = getsrc()) == 0)
+                               break;
+                       dest = getdest();
+                       get(src, dest);
+                       break;
+                   }
+
+               case 'r':
+                       restore();
+                       break;
+
+               default:
+                       printf("I don't know how to \"%s\"!\n", answer);
+                       break;
+               }
+       }
+}
+
+ask_del(prompt, fp)
+char   *prompt;
+struct file_pair       *fp;
+{
+       char    yorn[20];
+
+       tellme(prompt, yorn);
+       if (yorn[0] == 'y')
+               del_files(fp);
+}
+
+del_files(fp)
+struct file_pair       *fp;
+{
+       (void) unlink(fp->file_data);
+       (void) unlink(fp->file_rec);
+}
+
+#ifdef notdef
+savetmps()
+{
+       struct file_pair        *fp;
+       int     status,
+               pid;
+
+       if (strcmp(TMP_DIR, REC_DIR) == 0)
+               return;         /* Files are moved to the same place. */
+       get_files(TMP_DIR);
+       for (fp = First; fp != 0; fp = fp->file_next) {
+               switch (pid = fork()) {
+               case -1:
+                       fprintf(stderr, "recover: can't fork\n!");
+                       exit(-1);
+
+               case 0:
+                       execl("/bin/cp", "cp", fp->file_data, fp->file_rec, 
+                                 REC_DIR, (char *)0);
+                       fprintf(stderr, "recover: cannot execl /bin/cp.\n");
+                       exit(-1);
+
+               default:
+                       while (wait(&status) != pid)
+                               ;
+                       if (status != 0)
+                               fprintf(stderr, "recover: non-zero status (%d) returned from copy.\n", status);
+               }
+       }
+}
+#endif
+
+lookup(dir)
+char   *dir;
+{
+       struct file_pair        *fp;
+       struct rec_head         header;
+       char    yorn[20];
+       int     nfound = 0,
+               this_one;
+
+       printf("Checking %s ...\n", dir);
+       Directory = dir;
+       get_files(dir);
+       for (fp = First; fp != 0; fp = fp->file_next) {
+               nfound += doit(fp);
+               if (ptrs_fp)
+                       (void) fclose(ptrs_fp);
+               if (data_fd > 0)
+                       (void) close(data_fd);
+       }
+       return nfound;
+}
+
+main(argc, argv)
+int    argc;
+char   *argv[];
+{
+       int     nfound;
+       char    **argvp;
+
+       UserID = getuid();
+
+       if (scanvec(argv, "-help")) {
+               printf("recover: usage: recover [-d directory]\n");
+               printf("Use \"recover\" after JOVE has died for some\n");
+               printf("unknown reason.\n\n");
+/*             printf("Use \"recover -syscrash\" when the system is in the process\n");
+               printf("of rebooting.  This is done automatically at reboot time\n");
+               printf("and so most of you don't have to worry about that.\n\n");
+ */
+               printf("Use \"recover -d directory\" when the tmp files are store\n");
+               printf("in DIRECTORY instead of the default one (/tmp).\n");
+               exit(0);
+       }
+       if (scanvec(argv, "-v"))
+               Verbose = YES;
+/*     if (scanvec(argv, "-syscrash")) {
+               printf("Recovering jove files ... ");
+               savetmps();
+               printf("Done.\n");
+               exit(0);
+       } */
+       if (argvp = scanvec(argv, "-uid"))
+               UserID = atoi(argvp[1]);
+       if (argvp = scanvec(argv, "-d"))
+               nfound = lookup(argvp[1]);
+       else
+               nfound = lookup(TmpFilePath);
+       if (nfound == 0)
+               printf("There's nothing to recover.\n");
+}
diff --git a/usr/src/new/jove/setmaps.c b/usr/src/new/jove/setmaps.c
new file mode 100644 (file)
index 0000000..a02d738
--- /dev/null
@@ -0,0 +1,209 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+#define TXT_TO_C       1       /* must be a number for MAC compiler */
+
+#include "funcdefs.c"
+
+#ifdef MAC
+#include "vars.c"
+#endif
+
+#undef putchar /* From jove.h via funcdefs.c, conflicts with STDIO */
+#undef putc
+#undef getc
+#undef EOF
+#undef FILE
+#undef BUFSIZ
+#undef NULL
+#include <stdio.h>
+
+matchcmd(choices, what)
+register struct cmd    choices[];
+register char  *what;
+{
+       register int    len;
+       int     i,
+               found = 0,
+               save,
+               exactmatch = -1;
+
+       len = strlen(what);
+       for (i = 0; choices[i].Name != 0; i++) {
+               if (*what != *choices[i].Name)
+                       continue;
+#ifdef MAC /* see "left-margin" and "left-margin-here" */
+               if (strcmp(what, choices[i].Name) == 0)
+#else
+               if (strncmp(what, choices[i].Name, len) == 0)
+#endif
+               return i;
+       }
+       return -1;
+}
+
+#ifdef MAC
+matchvar(choices, what)
+register struct variable choices[];
+register char  *what;
+{
+       register int    len;
+       int     i,
+               found = 0,
+               save,
+               exactmatch = -1;
+
+       len = strlen(what);
+       for (i = 0; choices[i].Name != 0; i++) {
+               if (*what != *choices[i].Name)
+                       continue;
+               if (strcmp(what, choices[i].Name) == 0)
+                       return i;
+       }
+       return -1;
+}
+#endif
+
+char *
+PPchar(c)
+int    c;
+{
+       static char     str[16];
+       char    *cp = str;
+
+       if (c & 0200) {
+               c &= ~0200;
+               strcpy(cp, "M-");
+               cp += 2;
+       }
+       if (c == '\033')
+               strcpy(cp, "ESC");
+#ifdef IBMPC
+       else if (c == '\377')
+               strcpy(cp, "M");
+#endif /* IBMPC */
+       else if (c < ' ')
+               (void) sprintf(cp, "C-%c", c + '@');
+       else if (c == '\177')
+               strcpy(cp, "^?");
+       else
+               (void) sprintf(cp, "%c", c);
+       return str;
+}
+
+void
+extract(into, from)
+char   *into,
+       *from;
+{
+       from += 2;      /* Past tab and first double quote. */
+       while ((*into = *from++) != '"')
+               into += 1;
+       *into = 0;
+}
+
+
+void
+
+#ifdef MAC
+_main()                /* for Mac, so we can use redirection */
+#else
+main()
+#endif
+{
+       FILE    *ifile,
+               *of;
+       char    line[100],
+#ifdef MAC
+               *which,
+#endif
+               comname[70];
+       int     comnum,
+               ch,
+#ifdef MAC
+               inmenu = 0,
+#endif
+               savech = -1,
+               errors = 0;
+
+       ifile = stdin;
+       of = stdout;
+       if (ifile == NULL || of == NULL) {
+               printf("Cannot read input or write output.\n");
+               exit(1);
+       }
+       while (fgets(line, sizeof line, ifile) != NULL) {
+               if (strncmp(line, "#if", 3) == 0) {
+                       savech = ch;
+                       fprintf(of, line);
+                       continue;
+               } else if (strncmp(line, "#else", 5) == 0) {
+                       if (savech == -1)
+                               fprintf(stderr, "WARNING: ifdef/endif mismatch!\n");
+                       else
+                               ch = savech;
+                       fprintf(of, line);
+                       continue;
+               } else if (strncmp(line, "#endif", 6) == 0) {
+                       savech = -1;
+                       fprintf(of, line);
+                       continue;
+#ifdef MAC
+               } else if (strncmp(line, "#MENU", 5) == 0) {
+                       inmenu = 1;
+                       continue;
+#endif
+               } else if (strncmp(line, "\t\"", 2) != 0) {
+                       fprintf(of, line);
+                       ch = 0;
+                       continue;
+               }
+               extract(comname, line);
+               if (strcmp(comname, "unbound") == 0)
+                       comnum = 12345;
+               else {
+#ifdef MAC
+                       which = "commands";
+#endif
+                       comnum = matchcmd(commands, comname);
+#ifdef MAC
+                       if (comnum < 0 && inmenu) {
+                               comnum = matchvar(variables, comname);
+                               which = "variables";
+                       }
+#endif
+                       if (comnum < 0) {
+#ifdef MAC
+                               fprintf(stderr, "Warning: cannot find item \"%s\".\n", comname);
+#else
+                               fprintf(stderr, "Warning: cannot find command \"%s\".\n", comname);
+#endif
+                               errors += 1;
+                               comnum = 12345;
+                       }
+               }
+#ifdef MAC
+               if(inmenu) {
+                       if (comnum == 12345)
+                               fprintf(of, "   (data_obj *) 0,\n");
+                       else
+                               fprintf(of, "   (data_obj *) &%s[%d],\n",which, comnum);
+               } 
+               else {
+#endif
+               if (comnum == 12345)
+                       fprintf(of, "   (data_obj *) 0,                 /* %s */\n", PPchar(ch++));
+               else
+                       fprintf(of, "   (data_obj *) &commands[%d],     /* %s */\n", comnum, PPchar(ch++));
+       }
+#ifdef MAC
+       }
+#endif
+       fclose(of);
+       fclose(ifile);
+       exit(errors);
+}
diff --git a/usr/src/new/jove/table.c b/usr/src/new/jove/table.c
new file mode 100644 (file)
index 0000000..b36f766
--- /dev/null
@@ -0,0 +1,51 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+#include "jove.h"
+#include "table.h"
+
+private Table  *tables = NIL;
+
+Table *
+make_table()
+{
+       Table   *tab = (Table *) emalloc(sizeof *tab);
+
+       tab->t_next = tables;
+       tables = tab;
+       tab->t_wordlist = NIL;
+
+       return tab;
+}
+
+Word *
+word_in_table(text, table)
+char   *text;
+Table  *table;
+{
+       register Word   *w;
+
+       for (w = table_top(table); w != NIL; w = next_word(w))
+               if (strcmp(word_text(w), text) == 0)
+                       break;  /* already in list */
+       return w;
+}
+
+void
+add_word(wname, table)
+char   *wname;
+Table  *table;
+{
+       register Word   *w;
+
+       if (w = word_in_table(wname, table))
+               return;
+       w = (Word *) emalloc(sizeof *w);
+       word_text(w) = wname;
+       next_word(w) = table_top(table);
+       table_top(table) = w;
+}
diff --git a/usr/src/new/jove/table.h b/usr/src/new/jove/table.h
new file mode 100644 (file)
index 0000000..edea224
--- /dev/null
@@ -0,0 +1,28 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+typedef struct word    Word;
+typedef struct table   Table;
+
+struct word {
+       Word    *wd_next;
+       char    *wd_text;
+};
+
+struct table {
+       Table   *t_next;
+       Word    *t_wordlist;
+};
+
+extern Table   *make_table();
+extern Word    *word_in_table();
+
+#define        table_top(table)        (table->t_wordlist)
+#define next_word(w)           (w->wd_next)
+#define last_word_p(w)         (w->wd_next == NIL)
+#define word_text(w)           (w->wd_text)
+#define word_length(w)         (strlen(word_text(w)))
diff --git a/usr/src/new/jove/teachjove.c b/usr/src/new/jove/teachjove.c
new file mode 100644 (file)
index 0000000..a9ba7ac
--- /dev/null
@@ -0,0 +1,40 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+#include <sys/types.h>
+#include <sys/file.h>
+
+#ifndef TEACHJOVE
+#    define TEACHJOVE  "/usr/lib/jove/teach-jove"
+#endif
+
+#ifndef W_OK
+#   define W_OK        2
+#   define F_OK        0
+#endif
+
+extern char    *getenv();
+
+main()
+{
+       char    cmd[256],
+               fname[256],
+               *home;
+
+       if ((home = getenv("HOME")) == 0) {
+               printf("teachjove: cannot find your home!\n");
+               exit(-1);
+       }
+       (void) sprintf(fname, "%s/teach-jove", home);
+       if (access(fname, F_OK) != 0) {
+               (void) sprintf(cmd, "cp %s %s", TEACHJOVE, fname);
+               system(cmd);
+       }
+       (void) execlp("jove", "teachjove", fname, (char *) 0);
+       printf("teachjove: cannot execl jove!\n");
+}
+
diff --git a/usr/src/new/jove/temp.h b/usr/src/new/jove/temp.h
new file mode 100644 (file)
index 0000000..327be26
--- /dev/null
@@ -0,0 +1,84 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+/* The tmp file is indexed in chunks of CH_SIZE characters.  CH_SIZE is
+   (1 << CH_BITS).  New lines are added to the end of the tmp file.  The
+   file is not garbage collected because that would be too painful.  As a
+   result, commands like Yank and Kill are really easy; basically all we
+   do is make copies of the disk addresses of the lines (as opposed to
+   the contents).  So, putline(buf) writes BUF to the disk and returns a
+   new disk address.  Getline(addr, buf) is the opposite of putline().
+   f_getputl(line, fp) reads from open FP directly into the tmp file (into
+   the buffer cache (see below)) and stores the address in LINE.  This is
+   used during read_file to minimize compying.
+
+   Lines do NOT cross block bounderies in the tmp file so that accessing
+   the contents of lines can be much faster.  Pointers to offsets into
+   disk buffers are returned instead of copying the contents into local
+   arrays and then using them.  This cuts down on the amount of copying a
+   great deal, at the expense of less efficiency.  The lower bit of disk
+   addresses is used for marking lines as needing redisplay done.
+
+   There is a buffer cache of NBUF buffers (64 on !SMALL machines and the
+   3 on small ones).  The blocks are stored in LRU order and each block
+   is also stored in a hash table by block #.  When a block is requested
+   it can quickly be looked up in the hash table.  If it's not there the
+   LRU block is assigned the new block #.  If it finds that the LRU block
+   is dirty (i.e., has pending IO) it syncs the WHOLE tmp file, i.e.,
+   does all the pending writes.  This works much better on floppy disk
+   systems, like the IBM PC, if the blocks are sorted before sync'ing. */
+
+#ifdef SMALL
+#   define CH_BITS             4
+#   if BUFSIZ == 512
+#      define MAX_BLOCKS       1024
+#   else
+#      define MAX_BLOCKS       512
+#   endif
+#else
+#   define CH_BITS             0
+#   define MAX_BLOCKS          4096    /* basically unlimited */
+#endif /* SMALL */
+
+#if BUFSIZ == 512
+#   define BNO_SHIFT           (9 - CH_BITS)
+#else
+#   define BNO_SHIFT           (10 - CH_BITS)
+#endif
+
+/* CH_SIZE is how big each chunk is.  For each 1 the DFree pointer
+   is incremented we extend the tmp file by CH_SIZE characters.
+   CH_PBLOCK is the # of chunks per block.  RND_MASK is used to mask
+   off the lower order bits of the daddr to round down to the beginning
+   of a block.  OFF_MASK masks off the higher order bits so we can get
+   at the offset into the disk buffer.
+
+   NOTE:  It's pretty important that these numbers be multiples of
+         2.  Be careful if you change things. */
+#ifndef MAC
+#define CH_SIZE                        (1 << CH_BITS)
+#define CH_PBLOCK              (BUFSIZ / CH_SIZE)
+#define RND_MASK               (CH_PBLOCK - 1)
+#define OFF_MASK               (BUFSIZ - 1)
+#define BNO_MASK               (MAX_BLOCKS - 1)
+#define blk_round(daddr)       (daddr & ~RND_MASK)
+#define forward_block(daddr)   (daddr + CH_PBLOCK)
+#define da_to_bno(daddr)       ((daddr >> BNO_SHIFT) & BNO_MASK)
+#define da_to_off(daddr)       ((daddr << CH_BITS) & OFF_MASK)
+#define da_too_huge(daddr)     ((daddr >> BNO_SHIFT) >= MAX_BLOCKS)
+#else
+#define CH_SIZE                        ((disk_line)1 << CH_BITS)
+#define CH_PBLOCK              ((disk_line)BUFSIZ / CH_SIZE)
+#define RND_MASK               ((disk_line)CH_PBLOCK - 1)
+#define OFF_MASK               ((disk_line)BUFSIZ - 1)
+#define BNO_MASK               ((disk_line)MAX_BLOCKS - 1)
+#define blk_round(daddr)       ((disk_line)daddr & ~RND_MASK)
+#define forward_block(daddr)   ((disk_line)daddr + CH_PBLOCK)
+#define da_to_bno(daddr)       ((disk_line)(daddr >> BNO_SHIFT) & BNO_MASK)
+#define da_to_off(daddr)       ((disk_line)(daddr << CH_BITS) & OFF_MASK)
+#define da_too_huge(daddr)     ((disk_line)(daddr >> BNO_SHIFT) >= MAX_BLOCKS)
+#endif
diff --git a/usr/src/new/jove/termcap.h b/usr/src/new/jove/termcap.h
new file mode 100644 (file)
index 0000000..e56eccc
--- /dev/null
@@ -0,0 +1,79 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+#define MAXCOLS                256     /* maximum number of columns */
+
+#ifndef MAC
+#ifndef _TERM
+
+/* termcap definitions */
+
+extern char
+       *UP,    /* Scroll reverse, or up */
+       *CS,    /* If on vt100 */
+       *SO,    /* Start standout */
+       *SE,    /* End standout */
+       *CM,    /* The cursor motion string */
+       *CL,    /* Clear screen */
+       *CE,    /* Clear to end of line */
+       *HO,    /* Home cursor */
+       *AL,    /* Addline (insert line) */
+       *DL,    /* Delete line */
+       *VS,    /* Visual start */
+       *VE,    /* Visual end */
+       *KS,    /* Keypad mode start */
+       *KE,    /* Keypad mode end */
+       *TI,    /* Cursor addressing start */
+       *TE,    /* Cursor addressing end */
+       *IC,    /* Insert char */
+       *DC,    /* Delete char */
+       *IM,    /* Insert mode */
+       *EI,    /* End insert mode */
+       *LL,    /* Last line, first column */
+       *M_IC,  /* Insert char with arg */
+       *M_DC,  /* Delete char with arg */
+       *M_AL,  /* Insert line with arg */
+       *M_DL,  /* Delete line with arg */
+       *SF,    /* Scroll forward */
+       *SR,    /* Scroll reverse */
+       *SP,    /* Send cursor position */
+       *VB,    /* visible bell */
+       *BL,    /* audible bell */
+       *IP,    /* insert pad after character inserted */
+       *lPC,
+       *NL;    /* newline character (usually \n) */
+
+extern int
+       LI,             /* number of lines */
+       ILI,            /* number of internal lines */
+       CO,             /* number of columns */
+
+       UL,             /* underscores don't replace chars already on screen */
+       MI,             /* okay to move while in insert mode */
+       SG,             /* number of magic cookies left by SO and SE */
+
+       TABS,           /* whether we are in tabs mode */
+       UPlen,          /* length of the UP string */
+       HOlen,          /* length of Home string */
+       LLlen;          /* length of lower string */
+
+extern char
+       PC,
+       *BC;            /* back space */
+
+extern short   ospeed;
+
+#endif /* _TERM */
+
+#else /* MAC */        
+extern int     /* probably should clean this up */
+       LI,             /* number of lines */
+       ILI,            /* number of internal lines */
+       CO,             /* number of columns */
+       TABS,
+       SG;
+#endif /* MAC */
diff --git a/usr/src/new/jove/tune.dos b/usr/src/new/jove/tune.dos
new file mode 100644 (file)
index 0000000..85efc06
--- /dev/null
@@ -0,0 +1,22 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+#define NOEXTERNS
+
+#include "tune.h"
+
+/* these are variables that can be set with the set command, so they are
+   allocated more memory than they actually need for the defaults */
+char   TmpFilePath[64] = ".",
+       Shell[64] = "command",
+       ShFlags[16] = "-c",
+       CmdDb[64] = "c:/unix/cmds.doc";
+
+/* these guys are not settable */
+char   *d_tempfile = "joveXXXXXX",     /* buffer lines go here */
+       *Joverc = "jove.rc";
+
diff --git a/usr/src/new/jove/tune.template b/usr/src/new/jove/tune.template
new file mode 100644 (file)
index 0000000..c85d5a0
--- /dev/null
@@ -0,0 +1,29 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+#define NOEXTERNS
+
+#include "tune.h"
+
+char   *d_tempfile = "joveXXXXXX",     /* buffer lines go here */
+       *p_tempfile = "jrecXXXXXX",     /* line pointers go here */
+       *Recover = "LIBDIR/recover",
+       *CmdDb = "LIBDIR/cmds.doc",
+               /* copy of "cmds.doc" lives in the doc subdirectory */
+
+       *Joverc = "LIBDIR/.joverc",
+
+#ifdef PIPEPROCS
+       *Portsrv = "LIBDIR/portsrv",
+#endif
+
+/* these are variables that can be set with the set command, so they are
+   allocated more memory than they actually need for the defaults */
+
+       TmpFilePath[128] = "TMPDIR",
+       Shell[128] = "SHELL",
+       ShFlags[16] = "-c";
diff --git a/usr/src/new/jove/vars.c b/usr/src/new/jove/vars.c
new file mode 100644 (file)
index 0000000..758646b
--- /dev/null
@@ -0,0 +1,130 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+#ifndef TXT_TO_C       /* so that jove.h isn't included twice in setmaps */
+#include "jove.h"
+#endif
+
+struct variable        variables[] = {
+       VARIABLE, "abort-char", &AbortChar, V_CHAR,
+#ifdef UNIX
+       VARIABLE, "allow-^S-and-^Q", &OKXonXoff, V_BOOL|V_TTY_RESET,
+#endif /* UNIX */
+       VARIABLE, "allow-bad-filenames", &OkayBadChars, V_BOOL,
+#ifdef ABBREV
+       VARIABLE, "auto-case-abbrev", &AutoCaseAbbrev, V_BOOL,
+#endif
+#ifdef IBMPC
+       VARIABLE, "background-color", &Bgcolor, V_BASE10|V_CLRSCREEN,
+#endif /* IBMPC */
+#ifdef F_COMPLETION
+       VARIABLE, "bad-filename-extensions", (int *) BadExtensions, V_STRING,
+#endif
+       VARIABLE, "c-indentation-increment", &CIndIncrmt, V_BASE10,
+       VARIABLE, "case-ignore-search", &CaseIgnore, V_BOOL,
+#ifdef CMT_FMT
+       VARIABLE, "comment-format", (int *) CmtFmt, V_STRING,
+#endif
+#ifdef BIFF
+       VARIABLE, "disable-biff", &BiffChk, V_BOOL,
+#endif
+#ifdef F_COMPLETION
+       VARIABLE, "display-bad-filenames", &DispBadFs, V_BOOL,
+#endif
+#ifndef MAC
+       VARIABLE, "error-format-string", (int *) ErrFmtStr, V_STRING,
+       VARIABLE, "error-window-size", &EWSize, V_BASE10,
+#endif
+       VARIABLE, "expand-environment-variables", &DoEVexpand, V_BOOL,
+       VARIABLE, "file-creation-mode", &CreatMode, V_BASE8,
+       VARIABLE, "files-should-end-with-newline", &EndWNewline, V_BOOL,
+#ifdef IBMPC
+       VARIABLE, "foreground-color", &Fgcolor, V_BASE10|V_CLRSCREEN,
+#endif /* IBMPC */
+       VARIABLE, "internal-tabstop", &tabstop, V_BASE10|V_CLRSCREEN,
+       VARIABLE, "left-margin", &LMargin, V_BASE10,
+#ifdef UNIX
+       VARIABLE, "mailbox", (int *) Mailbox, V_FILENAME,
+       VARIABLE, "mail-check-frequency", (int *) &MailInt, V_BASE10,
+#endif /* UNIX */
+#ifdef MAC
+       VARIABLE, "macify", &Macmode, V_BOOL,
+#endif
+#ifdef BACKUPFILES
+       VARIABLE, "make-backup-files", &BkupOnWrite, V_BOOL,
+#endif
+       VARIABLE, "mark-threshold", &MarkThresh, V_BASE10,
+       VARIABLE, "marks-should-float", &MarksShouldFloat, V_BOOL,
+       VARIABLE, "match-regular-expressions", &UseRE, V_BOOL,
+       VARIABLE, "meta-key", &MetaKey, V_BOOL|V_TTY_RESET,
+       VARIABLE, "mode-line", (int *) ModeFmt, V_STRING|V_MODELINE,
+#ifdef IBMPC
+       VARIABLE, "mode-line-color", &Mdcolor, V_BASE10|V_MODELINE,
+#endif 
+       VARIABLE, "mode-line-should-standout", &BriteMode, V_BOOL|V_MODELINE,
+       VARIABLE, "paren-flash-delay", &PDelay, V_BASE10,
+#ifndef MAC
+       VARIABLE, "physical-tabstop", &phystab, V_BASE10|V_CLRSCREEN,
+#endif
+#ifdef IPROCS
+       VARIABLE, "process-prompt", (int *) proc_prompt, V_STRING,
+#endif
+       VARIABLE, "interrupt-character", &IntChar, V_CHAR|V_TTY_RESET,
+       VARIABLE, "right-margin", &RMargin, V_BASE10,
+       VARIABLE, "scroll-step", &ScrollStep, V_BASE10,
+       VARIABLE, "scroll-all-lines", &ScrollAll, V_BOOL,
+       VARIABLE, "search-exit-char", &SExitChar, V_CHAR,
+       VARIABLE, "send-typeout-to-buffer", &UseBuffers, V_BOOL,
+#ifndef MAC
+       VARIABLE, "shell", (int *) Shell, V_STRING,
+       VARIABLE, "shell-flags", (int *) ShFlags, V_STRING,
+#endif
+#ifndef MSDOS
+       VARIABLE, "sync-frequency", &SyncFreq, V_BASE10,
+#endif /* MSDOS */
+       VARIABLE, "tag-file", (int *) TagFile, V_FILENAME,
+#ifndef MAC
+       VARIABLE, "tmp-file-pathname", (int *) TmpFilePath, V_FILENAME,
+#endif
+#ifdef UNIX
+       VARIABLE, "update-time-frequency", &UpdFreq, V_BASE10,
+#endif /* UNIX */
+#ifdef ID_CHAR
+       VARIABLE, "use-i/d-char", &UseIC, V_BOOL,
+#endif
+       VARIABLE, "visible-bell", &VisBell, V_BOOL,
+       VARIABLE, "wrap-search", &WrapScan, V_BOOL,
+#ifndef MAC
+       VARIABLE, "write-files-on-make", &WtOnMk, V_BOOL,
+#endif
+       VARIABLE, 0, 0, 0
+};
+
+#ifndef TXT_TO_C
+data_obj *
+findvar(prompt)
+char   *prompt;
+{
+       static char     *strings[(sizeof variables) / sizeof (struct variable)];
+       static int      beenhere = 0;
+       register int    com;
+
+       if (beenhere == 0) {
+               register char   **strs = strings;
+               register struct variable        *v = variables;
+
+               beenhere = 1;
+               for (; v->Name; v++)
+                       *strs++ = v->Name;
+               *strs = 0;
+       }
+
+       if ((com = complete(strings, prompt, NOTHING)) < 0)
+               return 0;
+       return (data_obj *) &variables[com];
+}
+#endif
diff --git a/usr/src/new/jove/version.c b/usr/src/new/jove/version.c
new file mode 100644 (file)
index 0000000..bafe837
--- /dev/null
@@ -0,0 +1,8 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+char   *version = "4.9";
diff --git a/usr/src/new/jove/wind.c b/usr/src/new/jove/wind.c
new file mode 100644 (file)
index 0000000..969879c
--- /dev/null
@@ -0,0 +1,529 @@
+/***************************************************************************
+ * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
+ * is provided to you without charge, and with no warranty.  You may give  *
+ * away copies of JOVE, including sources, provided that this notice is    *
+ * included in all the files.                                              *
+ ***************************************************************************/
+
+/* This creates/deletes/divides/grows/shrinks windows.  */
+
+#include "jove.h"
+#include "termcap.h"
+
+private char   onlyone[] = "You only have one window!",
+               toosmall[] = "Resulting window would be too small.";
+
+Window *curwind,
+       *fwind = 0;
+
+/* First line in a Window */
+
+int
+FLine(w)
+register Window        *w;
+{
+       register Window *wp = fwind;
+       register int    lineno = -1;
+
+       do {
+               if (wp == w)
+                       return lineno + 1;
+               lineno += wp->w_height;
+               wp = wp->w_next;
+       } while (wp != fwind);
+       complain("window?");
+       /* NOTREACHED */
+}
+
+/* Delete `wp' from the screen.  If it is the only window left
+   on the screen, then complain.  It gives its body
+   to the next window if there is one, otherwise the previous
+   window gets the body.  */
+
+void
+del_wind(wp)
+register Window        *wp;
+{
+       register Window *prev = wp->w_prev;
+
+       if (one_windp())
+               complain(onlyone);
+
+       wp->w_prev->w_next = wp->w_next;
+       wp->w_next->w_prev = wp->w_prev;
+       
+       if (fwind == wp) {
+               fwind = wp->w_next;
+               fwind->w_height += wp->w_height;
+               /* Here try to do something intelligent for redisplay() */
+               SetTop(fwind, prev_line(fwind->w_top, wp->w_height));
+               if (curwind == wp)
+                       SetWind(fwind);
+       } else {
+               prev->w_height += wp->w_height;
+               if (curwind == wp)
+                       SetWind(prev);
+       }
+#ifdef MAC
+       RemoveScrollBar(wp);
+       Windchange++;
+#endif
+       free((char *) wp);
+}
+
+/* Divide the window WP N times, or at least once.  Complains if WP is too
+   small to be split into that many pieces.  It returns the new window. */
+
+Window *
+div_wind(wp, n)
+register Window        *wp;
+{
+       register Window *new;
+       int     amt;
+
+       if (n < 1)
+               n = 1;
+       amt = wp->w_height / (n + 1);
+       if (amt < 2)
+               complain(toosmall);
+
+       while (--n >= 0) {
+               new = (Window *) emalloc(sizeof (Window));
+               new->w_flags = 0;
+               new->w_LRscroll = 0;
+
+               new->w_height = amt;
+               wp->w_height -= amt;
+
+               /* set the lines such that w_line is the center in
+                  each Window */
+               new->w_line = wp->w_line;
+               new->w_char = wp->w_char;
+               new->w_bufp = wp->w_bufp;
+               new->w_top = prev_line(new->w_line, HALF(new));
+
+               /* Link the new window into the list */
+               new->w_prev = wp;
+               new->w_next = wp->w_next;
+               new->w_next->w_prev = new;
+               wp->w_next = new;
+#ifdef MAC
+               new->w_control = 0;
+#endif
+       }
+#ifdef MAC
+       Windchange++;
+#endif
+       return new;
+}
+
+/* Initialze the first window setting the bounds to the size of the
+   screen.  There is no buffer with this window.  See parse for the
+   setting of this window. */
+
+void
+winit()
+{
+       register Window *w;
+
+       w = curwind = fwind = (Window *) emalloc(sizeof (Window));
+       w->w_line = w->w_top = 0;
+       w->w_LRscroll = 0;
+       w->w_flags = 0;
+       w->w_char = 0;
+       w->w_next = w->w_prev = fwind;
+       w->w_height = ILI;
+#ifdef MAC
+       w->w_control = 0;
+       Windchange++;
+#endif
+}
+
+/* Change to previous window. */
+
+void
+PrevWindow()
+{
+       register Window *new = curwind->w_prev;
+
+       if (Asking)
+               complain((char *) 0);
+       if (one_windp())
+               complain(onlyone);
+       SetWind(new);
+}
+
+/* Make NEW the current Window */
+
+void
+SetWind(new)
+register Window        *new;
+{
+       if (!Asking) {          /* can you say kludge? */
+               curwind->w_line = curline;
+               curwind->w_char = curchar;
+               curwind->w_bufp = curbuf;
+       }
+       if (new == curwind)
+               return;
+       SetBuf(new->w_bufp);
+       if (!inlist(new->w_bufp->b_first, new->w_line)) {
+               new->w_line = curline;
+               new->w_char = curchar;
+       }
+       DotTo(new->w_line, new->w_char);
+       if (curchar > strlen(linebuf))
+               new->w_char = curchar = strlen(linebuf);
+       curwind = new;
+}
+
+/* delete the current window if it isn't the only one left */
+
+void
+DelCurWindow()
+{
+       SetABuf(curwind->w_bufp);
+       del_wind(curwind);
+}
+
+/* put the current line of `w' in the middle of the window */
+
+void
+CentWind(w)
+register Window        *w;
+{
+       SetTop(w, prev_line(w->w_line, HALF(w)));
+}
+
+int    ScrollStep = 0;         /* full scrolling */
+
+/* Calculate the new topline of the window.  If ScrollStep == 0
+   it means we should center the current line in the window. */
+
+void
+CalcWind(w)
+register Window        *w;
+{
+       register int    up;
+       int     scr_step;
+       Line    *newtop;
+
+       if (ScrollStep == 0)    /* Means just center it */
+               CentWind(w);
+       else {
+               up = inorder(w->w_line, 0, w->w_top, 0);
+               if (up == -1) {
+                       CentWind(w);
+                       return;
+               }
+               scr_step = (ScrollStep < 0) ? SIZE(w) + ScrollStep :
+                          ScrollStep - 1;
+               if (up)         /* point is above the screen */
+                       newtop = prev_line(w->w_line, scr_step);
+               else
+                       newtop = prev_line(w->w_line, (SIZE(w) - 1 - scr_step));
+               if (LineDist(newtop, w->w_top) >= SIZE(w) - 1)
+                       CentWind(w);
+               else
+                       SetTop(w, newtop);
+       }
+}
+
+/* This is bound to C-X 4 [BTF].  To make the screen stay the
+   same we have to remember various things, like the current
+   top line in the current window.  It's sorta gross, but it's
+   necessary because of the way this is implemented (i.e., in
+   terms of do_find(), do_select() which manipulate the windows. */
+
+void
+WindFind()
+{
+       register Buffer *obuf = curbuf,
+                       *nbuf;
+       Line    *ltop = curwind->w_top;
+       Bufpos  savedot;
+       extern void
+               FindTag(),
+               BufSelect(),
+               FindFile();
+
+       DOTsave(&savedot);
+
+       switch (waitchar((int *) 0)) {
+       case 't':
+       case 'T':
+               ExecCmd((data_obj *) FindCmd(FindTag));
+               break;
+
+       case 'b':
+       case 'B':
+               ExecCmd((data_obj *) FindCmd(BufSelect));
+               break;
+
+       case 'f':
+       case 'F':
+               ExecCmd((data_obj *) FindCmd(FindFile));
+               break;
+
+       default:
+               complain("T: find-tag, F: find-file, B: select-buffer.");
+       }
+
+       nbuf = curbuf;
+       SetBuf(obuf);
+       SetDot(&savedot);
+       SetTop(curwind, ltop);  /* there! it's as if we did nothing */
+
+       if (one_windp())
+               (void) div_wind(curwind, 1);
+
+       tiewind(curwind->w_next, nbuf);
+       SetWind(curwind->w_next);
+}
+
+/* Go into one window mode by deleting all the other windows */
+
+void
+OneWindow()
+{
+       while (curwind->w_next != curwind)
+               del_wind(curwind->w_next);
+}
+
+Window *
+windbp(bp)
+register Buffer        *bp;
+{
+
+       register Window *wp = fwind;
+
+       if (bp == 0)
+               return 0;
+       do {
+               if (wp->w_bufp == bp)
+                       return wp;
+               wp = wp->w_next;
+       } while (wp != fwind);
+       return 0;
+}
+
+/* Change window into the next window.  Curwind becomes the new window. */
+
+void
+NextWindow()
+{
+       register Window *new = curwind->w_next;
+
+       if (Asking)
+               complain((char *) 0);
+       if (one_windp())
+               complain(onlyone);
+       SetWind(new);
+}
+
+/* Scroll the next Window */
+
+void
+PageNWind()
+{
+       if (one_windp())
+               complain(onlyone);
+       NextWindow();
+       NextPage();
+       PrevWindow();
+}
+
+Window *
+w_nam_typ(name, type)
+register char  *name;
+{
+       register Window *w;
+       register Buffer *b;
+
+       b = buf_exists(name);
+       w = fwind;
+       if (b) do {
+               if (w->w_bufp == b)
+                       return w;
+       } while ((w = w->w_next) != fwind);
+
+       w = fwind;
+       do {
+               if (w->w_bufp->b_type == type)
+                       return w;
+       } while ((w = w->w_next) != fwind);
+
+       return 0;
+}
+
+/* Put a window with the buffer `name' in it.  Erase the buffer if
+   `clobber' is non-zero. */
+
+void
+pop_wind(name, clobber, btype)
+register char  *name;
+{
+       register Window *wp;
+       register Buffer *newb;
+
+       if (newb = buf_exists(name))
+               btype = -1;     /* if the buffer exists, don't change
+                                  it's type */
+       if ((wp = w_nam_typ(name, btype)) == 0) {
+               if (one_windp())
+                       SetWind(div_wind(curwind, 1));
+               else
+                       PrevWindow();
+       } else
+               SetWind(wp);
+
+       newb = do_select((Window *) 0, name);
+       if (clobber) {
+               initlist(newb);
+               newb->b_modified = NO;
+       }
+       tiewind(curwind, newb);
+       if (btype != -1)
+               newb->b_type = btype;
+       SetBuf(newb);
+}
+
+void
+GrowWindow()
+{
+       WindSize(curwind, abs(arg_value()));
+}
+
+void
+ShrWindow()
+{
+       WindSize(curwind, -abs(arg_value()));
+}
+
+/* Change the size of the window by inc.  First arg is the window,
+   second is the increment. */
+
+void
+WindSize(w, inc)
+register Window        *w;
+register int   inc;
+{
+       if (one_windp())
+               complain(onlyone);
+
+       if (inc == 0)
+               return;
+       else if (inc < 0) {     /* Shrinking this Window. */
+               if (w->w_height + inc < 2)
+                       complain(toosmall);
+               w->w_height += inc;
+               w->w_prev->w_height -= inc;
+       } else                  /* Growing the window. */
+               WindSize(w->w_next, -inc);
+#ifdef MAC
+       Windchange++;
+#endif
+}
+
+/* Set the topline of the window, calculating its number in the buffer.
+   This is for numbering the lines only. */
+
+void
+SetTop(w, line)
+Window *w;
+register Line  *line;
+{
+       register Line   *lp = w->w_bufp->b_first;
+       register int    num = 0;
+
+       w->w_top = line;
+       if (w->w_flags & W_NUMLINES) {
+               while (lp) {
+                       num += 1;
+                       if (line == lp)
+                               break;
+                       lp = lp->l_next;
+               }
+               w->w_topnum = num;
+       }
+}
+
+void
+WNumLines()
+{
+       curwind->w_flags ^= W_NUMLINES; 
+       SetTop(curwind, curwind->w_top);
+}
+
+void
+WVisSpace()
+{
+       curwind->w_flags ^= W_VISSPACE;
+       ClAndRedraw();
+}
+
+/* Return the line number that `line' occupies in `windes' */
+
+int
+in_window(windes, line)
+register Window        *windes;
+register Line  *line;
+{
+       register int    i;
+       register Line   *top = windes->w_top;
+
+       for (i = 0; top && i < windes->w_height - 1; i++, top = top->l_next)
+               if (top == line)
+                       return FLine(windes) + i;
+       return -1;
+}
+
+void
+SplitWind()
+{
+       SetWind(div_wind(curwind, is_an_arg() ? (arg_value() - 1) : 1));
+}
+
+/* Goto the window with the named buffer.  If no such window
+   exists, pop one and attach the buffer to it. */
+void
+GotoWind()
+{
+       extern Buffer   *lastbuf;
+       char    *bname;
+       Window  *w;
+
+       bname = ask_buf(lastbuf);
+       w = curwind->w_next;
+       do {
+               if (w->w_bufp->b_name == bname) {
+                       SetABuf(curbuf);
+                       SetWind(w);
+                       return;
+               }
+               w = w->w_next;
+       } while (w != curwind);
+       SetABuf(curbuf);
+       pop_wind(bname, NO, -1);
+}
+
+void
+ScrollRight()
+{
+       int     amt = (is_an_arg() ? arg_value() : 10);
+
+       if (curwind->w_LRscroll - amt < 0)
+               curwind->w_LRscroll = 0;
+       else
+               curwind->w_LRscroll -= amt;
+       UpdModLine = YES;
+}
+
+void
+ScrollLeft()
+{
+       int     amt = (is_an_arg() ? arg_value() : 10);
+
+       curwind->w_LRscroll += amt;
+       UpdModLine = YES;
+}