rsalz@bbn.com (Rich Salz) (04/26/88)
Submitted-by: Jonathan Payne <jpayne@cs.rochester.edu> Posting-number: Volume 14, Issue 59 Archive-name: jove4.9/part03 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 3 (of 21)." PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f './Ovmakefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./Ovmakefile'\" else echo shar: Extracting \"'./Ovmakefile'\" \(6758 characters\) sed "s/^X//" >'./Ovmakefile' <<'END_OF_FILE' X########################################################################### X# This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE # X# is provided to you without charge, and with no warranty. You may give # X# away copies of JOVE, including sources, provided that this notice is # X# included in all the files. # X########################################################################### X X# TMPDIR is where the tmp files get stored, usually /tmp or /tmp/jove. If X# your system does not remove subdirectories of /tmp on reboot (lots do X# remove them these days) then it makes sense to make TMPDIR be /tmp/jove. X# But if you want to recover buffers on system crashes, you should create a X# directory that doesn't get clearned upon reboot, and use that instead. X# You would probably want to clean out that directory periodically with X# /etc/cron. LIBDIR is for online documentation, the PORTSRV process, X# RECOVER, and the system-wide .joverc file. BINDIR is where to put the X# executables JOVE and TEACHJOVE. MANDIR is where the manual pages go for X# JOVE, RECOVER and TEACHJOVE. MANEXT is the extension for the man pages, X# e.g., jove.1 or jove.l or jove.m. X DESTDIR = TMPDIR = /tmp LIBDIR = /usr/lib/jove BINDIR = /bin MANDIR = /usr/man/man1 MANEXT = 1 SHELL = /bin/csh X X# 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) X X# Select the right libraries for your system. X# 2.9BSD: LIBS = -ltermlib -ljobs X# v7: LIBS = -ltermlib X# 4.1BSD: LIBS = -ltermlib -ljobs X# 4.2BSD: LIBS = -ltermlib X# 4.3BSD: LIBS = -ltermlib X OVLIBS = -lovtermcap -lovjobs LIBS = -ltermcap -ljobs X X# If you are not VMUNIX (vax running Berkeley Version 4), you must specify X# the -i flags (split I/D space) and maybe the -x option (for adb to work). X# 2.9BSD: LDFLAGS = -x -i X# v7: LDFLAGS = -x -i X# 4.1BSD: LDFLAGS = X# 4.2BSD: LDFLAGS = X# 4.3BSD: LDFLAGS = X LDFLAGS = -x -i X CFLAGS = -O -V X COFLAGS = -rworking -q X BASESEG = funcdefs.o keymaps.o argcount.o ask.o buf.o ctype.o delete.o disp.o fmt.o fp.o \ X insert.o io.o jove.o malloc.o marks.o misc.o move.o re.o \ X 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 X OBJECTS = $(BASESEG) $(OVLAY1) $(OVLAY2) $(OVLAY3) $(OVLAY4) $(OVLAY5) X C-FILES = funcdefs.c abbrev.c argcount.c ask.c buf.c c.c case.c ctype.c delete.c disp.c \ X extend.c fmt.c fp.c insert.c io.c iproc.c iproc-pipes.c iproc-ptys.c \ X jove.c macros.c malloc.c marks.c misc.c move.c paragraph.c proc.c \ X re.c re1.c rec.c scandir.c screen.c table.c term.c util.c vars.c version.c \ X wind.c X H-FILES = ctype.h io.h jove.h re.h rec.h table.h temp.h termcap.h tune.h X BACKUPS = $(C-FILES) $(H-FILES) $(DOCS) teachjove.c recover.c setmaps.c portsrv.c \ X tune.template Makefile Ovmakefile keymaps.txt README tags X DOCS = doc/cmds.doc.nr doc/example.rc doc/jove.1 doc/jove.2 doc/jove.3 \ X doc/jove.4 doc/jove.nr doc/recover.nr doc/system.rc doc/teach-jove \ X doc/teachjove.nr doc/README X all: xjove recover teachjove portsrv X xjove: $(OBJECTS) X ld $(LDFLAGS) /lib/crt0.o \ X -Z $(OVLAY1) \ X -Z $(OVLAY2) \ X -Z $(OVLAY3) \ X -Z $(OVLAY4) \ X -Z $(OVLAY5) \ X -L $(BASESEG) \ X -o xjove $(OVLIBS) -lovc X checkobj xjove X @-size xjove X @-date X portsrv: portsrv.c X cc -o portsrv -n -O portsrv.c $(LIBS) X recover: recover.c tune.o rec.h temp.h X cc -o recover -n -O recover.c tune.o -ljobs X teachjove: teachjove.c X cc -o teachjove -n -O -DTEACHJOVE=\"$(TEACH-JOVE)\" teachjove.c X setmaps: setmaps.c funcdefs.c X cc -o setmaps setmaps.c X keymaps.c: setmaps keymaps.txt X setmaps < keymaps.txt > keymaps.c X tune.c: Makefile tune.template X @echo "/* Changes should be made in Makefile, not to this file! */" > tune.c X @echo "" >> tune.c X @sed -e 's;TMPDIR;$(TMPDIR);' \ X -e 's;LIBDIR;$(LIBDIR);' \ X -e 's;BINDIR;$(BINDIR);' \ X -e 's;SHELL;$(SHELL);' tune.template >> tune.c X install: $(LIBDIR) $(TEACH-JOVE) $(CMDS.DOC) $(JOVERC) $(PORTSRV) $(RECOVER) \ X $(JOVE) $(TEACHJOVE) $(JOVEM) $(RECOVERM) $(TEACHJOVEM) X X$(DESTDIR)$(LIBDIR): X -mkdir (DESTDIR)$(LIBDIR) X X$(TEACH-JOVE): doc/teach-jove X install -c -m 644 doc/teach-jove $(TEACH-JOVE) X X$(CMDS.DOC): doc/cmds.doc X install -c -m 644 doc/cmds.doc $(CMDS.DOC) X X$(JOVERC): doc/system.rc X install -c -m 644 doc/system.rc $(JOVERC) X X$(PORTSRV): portsrv X install -c -m 755 portsrv $(PORTSRV) X X$(RECOVER): recover X install -c -m 755 recover $(RECOVER) X X$(JOVE): xjove X install -c -m 755 xjove $(JOVE) X X$(TEACHJOVE): teachjove X install -c -m 755 teachjove $(TEACHJOVE) X X$(JOVEM): doc/jove.nr X @sed -e 's;TMPDIR;$(TMPDIR);' \ X -e 's;LIBDIR;$(LIBDIR);' \ X -e 's;SHELL;$(SHELL);' doc/jove.nr > /tmp/jove.nr X install -m 644 /tmp/jove.nr $(JOVEM) X X$(RECOVERM): doc/recover.nr X @sed -e 's;TMPDIR;$(TMPDIR);' \ X -e 's;LIBDIR;$(LIBDIR);' \ X -e 's;SHELL;$(SHELL);' doc/recover.nr > /tmp/recover.nr X install -m 644 /tmp/recover.nr $(RECOVERM) X X$(TEACHJOVEM): doc/teachjove.nr X @sed -e 's;TMPDIR;$(TMPDIR);' \ X -e 's;LIBDIR;$(LIBDIR);' \ X -e 's;SHELL;$(SHELL);' doc/teachjove.nr > /tmp/teachjove.nr X install -m 644 /tmp/teachjove.nr $(TEACHJOVEM) X echo: X @echo $(C-FILES) $(H-FILES) X lint: X lint -x $(C-FILES) X echo Done X tags: X ctags -w $(C-FILES) $(H-FILES) X X jove.shar: X shar $(BACKUPS) doc/* > jove.shar X backup: X tar cf backup $(BACKUPS) X tape-backup: X tar cbf 20 /dev/rmt0 $(BACKUPS) X clean: X rm -f a.out core $(OBJECTS) keymaps.c xjove \ X portsrv recover setmaps teachjove X X# abbrev.o: jove.h tune.h X# ask.o: jove.h tune.h X# buf.o: jove.h tune.h X# c.o: jove.h tune.h X# delete.o: jove.h tune.h X# disp.o: jove.h tune.h termcap.h X# extend.o: jove.h tune.h X# fmt.o: jove.h tune.h termcap.h X# funcdefs.o: jove.h tune.h X# insert.o: jove.h tune.h X# io.o: jove.h tune.h termcap.h temp.h X# iproc.o: jove.h tune.h X# jove.o: jove.h tune.h termcap.h X# macros.o: jove.h tune.h X# marks.o: jove.h tune.h X# misc.o: jove.h tune.h X# move.o: jove.h tune.h X# portsrv.o: jove.h tune.h X# proc.o: jove.h tune.h X# re.o: jove.h tune.h X# rec.o: jove.h tune.h temp.h rec.h X# recover.o: jove.h tune.h temp.h rec.h X# screen.o: jove.h tune.h temp.h termcap.h X# setmaps.o: jove.h tune.h X# term.o: jove.h tune.h X# tune.o: tune.h X# util.o: jove.h tune.h X# wind.o: jove.h tune.h termcap.h END_OF_FILE if test 6758 -ne `wc -c <'./Ovmakefile'`; then echo shar: \"'./Ovmakefile'\" unpacked with wrong size! fi # end of './Ovmakefile' fi if test -f './abbrev.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./abbrev.c'\" else echo shar: Extracting \"'./abbrev.c'\" \(6522 characters\) sed "s/^X//" >'./abbrev.c' <<'END_OF_FILE' X/*************************************************************************** X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE * X * is provided to you without charge, and with no warranty. You may give * X * away copies of JOVE, including sources, provided that this notice is * X * included in all the files. * X ***************************************************************************/ X X#include "jove.h" X X#ifdef ABBREV X X#include "io.h" X#include "ctype.h" X X#ifdef MSDOS X#include <io.h> X#endif X#define HASHSIZE 20 X struct abbrev { X unsigned int a_hash; X char *a_abbrev, X *a_phrase; X struct abbrev *a_next; X data_obj *a_cmdhook; X}; X X#ifdef MAC X# undef private X# define private X#endif X X#ifdef LINT_ARGS private void X define(struct abbrev **, char *, char *), X def_abbrev(struct abbrev **), X rest_abbrevs(char *), X save_abbrevs(char *); X private unsigned int hash(char *); private struct abbrev * lookup(struct abbrev **, char *); X#else private void X define(), X def_abbrev(), X rest_abbrevs(), X save_abbrevs(); X private unsigned int hash(); private struct abbrev * lookup(); X#endif /* LINT_ARGS */ X X#ifdef MAC X# undef private X# define private static X#endif X X#define GLOBAL NMAJORS private struct abbrev *A_tables[NMAJORS + 1][HASHSIZE] = {0}; X int AutoCaseAbbrev = 1; X private unsigned int hash(a) register char *a; X{ X register unsigned int hashval = 0; X register int c; X X while (c = *a++) X hashval = (hashval << 2) + c; X X return hashval; X} X private void def_abbrev(table) struct abbrev *table[HASHSIZE]; X{ X char abbrev[100], X phrase[100]; X X strcpy(abbrev, ask((char *) 0, "abbrev: ")); X strcpy(phrase, ask((char *) 0, "abbrev: %s phrase: ", abbrev)); X define(table, abbrev, phrase); X} X private struct abbrev * lookup(table, abbrev) register struct abbrev *table[HASHSIZE]; register char *abbrev; X{ X register struct abbrev *ap; X unsigned int h; X X h = hash(abbrev); X for (ap = table[h % HASHSIZE]; ap; ap = ap->a_next) X if (ap->a_hash == h && strcmp(ap->a_abbrev, abbrev) == 0) X break; X return ap; X} X private void define(table, abbrev, phrase) register struct abbrev *table[HASHSIZE]; char *abbrev, X *phrase; X{ X register struct abbrev *ap; X X ap = lookup(table, abbrev); X if (ap == 0) { X register unsigned int h = hash(abbrev); X X ap = (struct abbrev *) emalloc(sizeof *ap); X ap->a_hash = h; X ap->a_abbrev = copystr(abbrev); X h %= HASHSIZE; X ap->a_next = table[h]; X ap->a_cmdhook = 0; X table[h] = ap; X } else X free(ap->a_phrase); X ap->a_phrase = copystr(phrase); X} X void AbbrevExpand() X{ X Bufpos point; X char wordbuf[100]; X register char *wp = wordbuf, X *cp; X#if !(defined(IBMPC) || defined(MAC)) X register int c; X#else X int c; X#endif X int UC_count = 0; X struct abbrev *ap; X X DOTsave(&point); X WITH_TABLE(curbuf->b_major) X b_word(1); X while (curchar < point.p_char && ismword(c = linebuf[curchar])) { X if (AutoCaseAbbrev) { X if (isupper(c)) { X UC_count += 1; X#if (defined(IBMPC) || defined(MAC)) X lower(&c); X#else X c = tolower(c); X#endif X } X } X *wp++ = c; X curchar += 1; X } X *wp = '\0'; X END_TABLE(); X X if ((ap = lookup(A_tables[curbuf->b_major], wordbuf)) == 0 && X (ap = lookup(A_tables[GLOBAL], wordbuf)) == 0) { X SetDot(&point); X return; X } X del_char(BACKWARD, (wp - wordbuf)); X X for (cp = ap->a_phrase; c = *cp; ) { X if (AutoCaseAbbrev) { X insert_c(islower(c) && UC_count && X (cp == ap->a_phrase || (UC_count > 1 && (cp[-1] == ' '))) ? X toupper(c) : c, 1); X } else X insert_c(c, 1); X cp += 1; X } X if (ap->a_cmdhook != 0) X ExecCmd(ap->a_cmdhook); X} X private char *mode_names[NMAJORS + 1] = { X "Fundamental Mode", X "Text Mode", X "C Mode", X#ifdef LISP X "Lisp Mode", X#endif X "Global" X}; X private void save_abbrevs(file) char *file; X{ X File *fp; X struct abbrev *ap, X **tp; X char buf[LBSIZE]; X int i, X count = 0; X X fp = open_file(file, buf, F_WRITE, COMPLAIN, QUIET); X for (i = 0; i <= GLOBAL; i++) { X fprintf(fp, "------%s abbrevs------\n", mode_names[i]); X for (tp = A_tables[i]; tp < &A_tables[i][HASHSIZE]; tp++) X for (ap = *tp; ap; ap = ap->a_next) { X fprintf(fp, "%s:%s\n", X ap->a_abbrev, X ap->a_phrase); X count += 1; X } X } X f_close(fp); X add_mess(" %d written.", count); X} X private void rest_abbrevs(file) char *file; X{ X int eof = 0, X mode = -1, /* Will be ++'d immediately */ X lnum = 0; X char *phrase_p; X File *fp; X char buf[LBSIZE]; X X fp = open_file(file, buf, F_READ, COMPLAIN, QUIET); X while (mode <= GLOBAL) { X eof = f_gets(fp, genbuf, LBSIZE); X if (eof || genbuf[0] == '\0') X break; X lnum += 1; X if (strncmp(genbuf, "------", 6) == 0) { X mode += 1; X continue; X } X if (mode == -1) fmterr: complain("Abbrev. format error, line %d.", file, lnum); X phrase_p = index(genbuf, ':'); X if (phrase_p == 0) X goto fmterr; X *phrase_p++ = '\0'; /* Null terminate the abbrev. */ X define(A_tables[mode], genbuf, phrase_p); X } X f_close(fp); X message(NullStr); X} X void DefGAbbrev() X{ X def_abbrev(A_tables[GLOBAL]); X} X void DefMAbbrev() X{ X def_abbrev(A_tables[curbuf->b_major]); X} X void SaveAbbrevs() X{ X char filebuf[FILESIZE]; X X save_abbrevs(ask_file((char *) 0, (char *) 0, filebuf)); X} X void RestAbbrevs() X{ X char filebuf[FILESIZE]; X X rest_abbrevs(ask_file((char *) 0, (char *) 0, filebuf)); X} X void EditAbbrevs() X{ X char *tname = "jove_wam.$$$", X *EditName = "Abbreviation Edit"; X Buffer *obuf = curbuf, X *ebuf; X X if (ebuf = buf_exists(EditName)) { X if (ebuf->b_type != B_SCRATCH) X confirm("Over-write buffer %b?", ebuf); X } X SetBuf(ebuf = do_select(curwind, EditName)); X ebuf->b_type = B_SCRATCH; X initlist(ebuf); X /* Empty buffer. Save the definitions to a tmp file X and read them into this buffer so we can edit them. */ X save_abbrevs(tname); X read_file(tname, NO); X message("[Edit definitions and then type C-X C-C]"); X Recur(); /* We edit them ... now */ X /* RESetBuf in case we deleted the buffer while we were editing. */ X SetBuf(ebuf = do_select(curwind, EditName)); X if (IsModified(ebuf)) { X SetBuf(ebuf); X file_write(tname, 0); X rest_abbrevs(tname); X unmodify(); X } X (void) unlink(tname); X SetBuf(do_select(curwind, obuf->b_name)); X} X void BindMtoW() X{ X struct abbrev *ap; X char *word; X data_obj *hook; X X word = ask((char *) 0, "Word: "); X X if ((ap = lookup(A_tables[curbuf->b_major], word)) == 0 && X (ap = lookup(A_tables[GLOBAL], word)) == 0) X complain("%s: unknown abbrev.", word); X X hook = findmac("Macro: "); X if (hook == 0) X complain("[Undefined macro]"); X ap->a_cmdhook = hook; X} X X#endif /* ABBREV */ END_OF_FILE if test 6522 -ne `wc -c <'./abbrev.c'`; then echo shar: \"'./abbrev.c'\" unpacked with wrong size! fi # end of './abbrev.c' fi if test -f './delete.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./delete.c'\" else echo shar: Extracting \"'./delete.c'\" \(6544 characters\) sed "s/^X//" >'./delete.c' <<'END_OF_FILE' X/*************************************************************************** X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE * X * is provided to you without charge, and with no warranty. You may give * X * away copies of JOVE, including sources, provided that this notice is * X * included in all the files. * X ***************************************************************************/ X X/* Routines to perform all kinds of deletion. */ X X#include "jove.h" X X/* Assumes that either line1 or line2 is actual the current line, so it can X put its result into linebuf. */ X void patchup(line1, char1, line2, char2) Line *line1, X *line2; register int char1, X char2; X{ X if (line1 != line2) X ChkWindows(line1, line2); X DotTo(line1, char1); X modify(); X linecopy(linebuf, curchar, lcontents(line2) + char2); X X /* The following is a redisplay optimization. */ X if (line1 != line2 && (char1 == 0 && char2 == 0)) X line1->l_dline = line2->l_dline; X X DFixMarks(line1, char1, line2, char2); X makedirty(curline); X} X X/* Deletes the region by unlinking the lines in the middle, X and patching things up. The unlinked lines are still in X order. */ X Line * reg_delete(line1, char1, line2, char2) Line *line1, X *line2; X{ X register Line *retline; X X if ((line1 == line2 && char1 == char2) || line2 == 0) X complain((char *) 0); X (void) fixorder(&line1, &char1, &line2, &char2); X X retline = nbufline(); /* New buffer line */ X X (void) ltobuf(line1, genbuf); X if (line1 == line2) X genbuf[char2] = '\0'; X X retline->l_prev = 0; X retline->l_dline = putline(&genbuf[char1]); X patchup(line1, char1, line2, char2); X X if (line1 == line2) X retline->l_next = 0; X else { X retline->l_next = line1->l_next; X (void) ltobuf(line2, genbuf); X genbuf[char2] = '\0'; X line2->l_dline = putline(genbuf); X /* Shorten this line */ X } X X if (line1 != line2) { X line1->l_next = line2->l_next; X if (line1->l_next) X line1->l_next->l_prev = line1; X else X curbuf->b_last = line1; X line2->l_next = 0; X } X X return retline; X} X void lremove(line1, line2) register Line *line1, X *line2; X{ X Line *next = line1->l_next; X X if (line1 == line2) X return; X line1->l_next = line2->l_next; X if (line1->l_next) X line1->l_next->l_prev = line1; X else X curbuf->b_last = line1; X lfreereg(next, line2); /* Put region at end of free line list. */ X} X X/* Delete character forward */ X void DelNChar() X{ X del_char(FORWARD, arg_value()); X} X X/* Delete character backward */ X void DelPChar() X{ X if (MinorMode(OverWrite)) { X int count = min(arg_value(), curchar); X X b_char(count); X X /* overwrite with spaces */ X set_arg_value(count); X LastKeyStruck = ' '; X SelfInsert(); X X b_char(count); X } else X del_char(BACKWARD, arg_value()); X} X X/* Delete some characters. If deleting forward then call for_char X to the final position otherwise call back_char. Then delete the X region between the two with patchup(). */ X void del_char(dir, num) X{ X Bufpos before, X after; X int killp = (abs(num) > 1); X X DOTsave(&before); X if (dir == FORWARD) f_char(num); X else b_char(num); X if (before.p_line == curline && before.p_char == curchar) X complain((char *) 0); X if (killp) X reg_kill(before.p_line, before.p_char, 1); X else { X DOTsave(&after); X (void) fixorder(&before.p_line, &before.p_char, &after.p_line, &after.p_char); X patchup(before.p_line, before.p_char, after.p_line, after.p_char); X lremove(before.p_line, after.p_line); X } X} X X/* This kills a region between point, and line1/char1 and puts it on X the kill-ring. If the last command was one of the kill commands, X the region is appended (prepended if backwards) to the last entry. */ X int killptr = 0; Line *killbuf[NUMKILLS]; X void reg_kill(line2, char2, dot_moved) Line *line2; X{ X Line *nl, X *line1 = curline; X int char1 = curchar; X int backwards; X X backwards = !fixorder(&line1, &char1, &line2, &char2); X /* This is a kludge! But it possible for commands that don't X know which direction they are deleting in (e.g., delete X previous word could have been called with a negative argument X in which case, it wouldn't know that it really deleted X forward. */ X X if (!dot_moved) X backwards = !backwards; X X DotTo(line1, char1); X X nl = reg_delete(line1, char1, line2, char2); X X if (last_cmd != KILLCMD) { X killptr = ((killptr + 1) % NUMKILLS); X lfreelist(killbuf[killptr]); X killbuf[killptr] = nl; X } else { X Line *lastln = lastline(nl); X X if (backwards) X (void) DoYank(nl, 0, lastln, length(lastln), killbuf[killptr], 0, (Buffer *) 0); X else { X Line *olastln = lastline(killbuf[killptr]); X X (void) DoYank(nl, 0, lastln, length(lastln), olastln, length(olastln), (Buffer *) 0); X } X } X this_cmd = KILLCMD; X} X void DelReg() X{ X register Mark *mp = CurMark(); X X reg_kill(mp->m_line, mp->m_char, 0); X} X X/* Save a region. A pretend kill. */ X void CopyRegion() X{ X register Line *nl; X register Mark *mp; X register int status; X X mp = CurMark(); X if (mp->m_line == curline && mp->m_char == curchar) X complain((char *) 0); X X killptr = ((killptr + 1) % NUMKILLS); X if (killbuf[killptr]) X lfreelist(killbuf[killptr]); X nl = killbuf[killptr] = nbufline(); X SavLine(nl, NullStr); X nl->l_next = nl->l_prev = 0; X X status = inorder(mp->m_line, mp->m_char, curline, curchar); X if (status == -1) X return; X X if (status) X (void) DoYank(mp->m_line, mp->m_char, curline, curchar, X nl, 0, (Buffer *) 0); X else X (void) DoYank(curline, curchar, mp->m_line, mp->m_char, X nl, 0, (Buffer *) 0); X} X void DelWtSpace() X{ X register char *ep = &linebuf[curchar], X *sp = &linebuf[curchar]; X X while (*ep == ' ' || *ep == '\t') X ep += 1; X while (sp > linebuf && *(sp - 1) == ' ' || *(sp - 1) == '\t') X sp -= 1; X if (sp != ep) { X curchar = sp - linebuf; X DFixMarks(curline, curchar, curline, curchar + (ep - sp)); X strcpy(sp, ep); X makedirty(curline); X modify(); X } X} X void DelBlnkLines() X{ X register Mark *dot; X int all; X X if (!blnkp(&linebuf[curchar])) X return; X dot = MakeMark(curline, curchar, M_FLOATER); X all = !blnkp(linebuf); X while (blnkp(linebuf) && curline->l_prev) X SetLine(curline->l_prev); X all |= (firstp(curline)); X Eol(); X DelWtSpace(); X line_move(FORWARD, 1, NO); X while (blnkp(linebuf) && !eobp()) { X DelWtSpace(); X del_char(FORWARD, 1); X } X if (!all && !eobp()) X open_lines(1); X ToMark(dot); X DelMark(dot); X} X void DelNWord() X{ X dword(1); X} X void DelPWord() X{ X dword(0); X} X void dword(forward) X{ X Bufpos savedot; X X DOTsave(&savedot); X if(forward) ForWord(); X else BackWord(); X reg_kill(savedot.p_line, savedot.p_char, 1); X} END_OF_FILE if test 6544 -ne `wc -c <'./delete.c'`; then echo shar: \"'./delete.c'\" unpacked with wrong size! fi # end of './delete.c' fi if test -f './fp.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./fp.c'\" else echo shar: Extracting \"'./fp.c'\" \(7807 characters\) sed "s/^X//" >'./fp.c' <<'END_OF_FILE' X/*************************************************************************** X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE * X * is provided to you without charge, and with no warranty. You may give * X * away copies of JOVE, including sources, provided that this notice is * X * included in all the files. * X ***************************************************************************/ X X#include "jove.h" X#include "io.h" X#include "ctype.h" X#include "termcap.h" X X#ifdef MAC X# include "mac.h" X#else X# include <sys/stat.h> X# ifndef MSDOS X# include <sys/file.h> X# else /* MSDOS */ X# include <fcntl.h> X# include <io.h> X# endif /* MSDOS */ X#endif /* MAC */ X X#include <errno.h> X X#ifdef MAC X# undef private X# define private X#endif X X#ifdef LINT_ARGS private File * f_alloc(char *, int, int, char *, int); X#ifdef RAINBOW private int rbwrite(int, char *, int); X#endif X#else private File * f_alloc(); X#ifdef RAINBOW private int rbwrite(); X#endif X#endif /* LINT_ARGS */ X X#ifdef MAC X# undef private X# define private static X#endif X X#ifndef L_SET X# define L_SET 0 X#endif X X#define MAXFILES 20 /* good enough for my purposes */ X private File _openfiles[MAXFILES] = {0}; X private File * f_alloc(name, flags, fd, buffer, buf_size) char *name, X *buffer; X{ X register File *fp; X register int i; X X for (fp = _openfiles, i = 0; i < MAXFILES; i++, fp++) X if (fp->f_flags == 0) X break; X if (i == MAXFILES) X complain("[Too many open files!]"); X fp->f_bufsize = buf_size; X fp->f_cnt = 0; X fp->f_fd = fd; X fp->f_flags = flags; X if (buffer == 0) { X buffer = emalloc(buf_size); X fp->f_flags |= F_MYBUF; X } X fp->f_base = fp->f_ptr = buffer; X fp->f_name = copystr(name); X X return fp; X} X void gc_openfiles() X{ X register File *fp; X X for (fp = _openfiles; fp < &_openfiles[MAXFILES]; fp++) X if (fp->f_flags != 0 && (fp->f_flags & F_LOCKED) == 0) X f_close(fp); X} X File * fd_open(name, flags, fd, buffer, bsize) char *name, X *buffer; X{ X return f_alloc(name, flags, fd, buffer, bsize); X} X File * f_open(name, flags, buffer, buf_size) char *name, X *buffer; X{ X register int fd; X int mode = F_MODE(flags); X X if (mode == F_READ) X fd = open(name, 0); X if (mode == F_APPEND) { X fd = open(name, 1); X if (fd == -1) X mode = F_WRITE; X else X (void) lseek(fd, 0L, 2); X } X if (mode == F_WRITE) X fd = creat(name, CreatMode); X if (fd == -1) X return NIL; X#ifdef MSDOS X else X setmode(fd, 0x8000); X#endif /* MSDOS */ X return f_alloc(name, flags, fd, buffer, buf_size); X} X void f_close(fp) File *fp; X{ X flush(fp); X#ifdef BSD4_2 X if (fp->f_flags & (F_WRITE|F_APPEND)) X (void) fsync(fp->f_fd); X#endif X (void) close(fp->f_fd); X if (fp->f_flags & F_MYBUF) X free(fp->f_base); X free(fp->f_name); X fp->f_flags = 0; /* indicates that we're available */ X} X int filbuf(fp) File *fp; X{ X if (fp->f_flags & (F_EOF|F_ERR)) X return EOF; X fp->f_ptr = fp->f_base; X#ifndef MSDOS X do X#endif /* MSDOS */ X fp->f_cnt = read(fp->f_fd, fp->f_base, fp->f_bufsize); X#ifndef MSDOS X while (fp->f_cnt == -1 && errno == EINTR); X#endif /* MSDOS */ X if (fp->f_cnt == -1) { X printf("[Read error %d]", errno); X fp->f_flags |= F_ERR; X } X if (fp->f_cnt == 0) { X fp->f_flags |= F_EOF; X return EOF; X } X io_chars += fp->f_cnt; X return getc(fp); X} X void putstr(s) register char *s; X{ X#ifndef IBMPC X register int c; X X while (c = *s++) X putchar(c); X#else /* IBMPC */ X write_emif(s); X#endif /* IBMPC */ X} X void fputnchar(s, n, fp) register char *s; register int n; register File *fp; X{ X while (--n >= 0) X putc(*s++, fp); X} X void flusho() X{ X#ifndef IBMPC X _flush(EOF, stdout); X#endif /* IBMPC */ X} X void flush(fp) File *fp; X{ X _flush(EOF, fp); X} X void f_seek(fp, offset) register File *fp; off_t offset; X{ X if (fp->f_flags & F_WRITE) X flush(fp); X fp->f_cnt = 0; /* next read will filbuf(), next write X will flush() with no bad effects */ X lseek(fp->f_fd, (long) offset, L_SET); X} X int /* is void - but for lints sake */ X_flush(c, fp) register File *fp; X{ X register int n; X X if (fp->f_flags & (F_READ | F_STRING | F_ERR)) X return EOF; X if (((n = (fp->f_ptr - fp->f_base)) > 0) && X#ifndef RAINBOW X (write(fp->f_fd, fp->f_base, n) != n) && X#else X (rbwrite(fp->f_fd, fp->f_base, n) != n) && X#endif X (fp != stdout)) { X fp->f_flags |= F_ERR; X error("[I/O error(%d); file = %s, fd = %d]", X errno, fp->f_name, fp->f_fd); X } X X fp->f_cnt = fp->f_bufsize; X fp->f_ptr = fp->f_base; X if (c != EOF) X return putc(c, fp); X} X int f_gets(fp, buf, max) register File *fp; char *buf; X{ X register char *cp = buf; X register int c; X char *endp = buf + max - 1; X X if (fp->f_flags & F_EOF) X return EOF; X while (((c = getc(fp)) != EOF) && (c != '\n')) { X if (c == '\0') /* possibly different from NULL */ X break; /* sorry we don't read nulls */ X#ifdef MSDOS X if (c == '\r') { X if ((c = getc(fp)) == '\n') X break; X else X *cp++ = '\r'; X } X#endif /* MSDOS */ X if (cp >= endp) { X add_mess(" [Line too long]"); X rbell(); X return EOF; X } X *cp++ = c; X } X *cp = '\0'; X if (c == EOF) { X if (cp != buf) X add_mess(" [Incomplete last line]"); X fp->f_flags |= F_EOF; X return EOF; X } X io_lines += 1; X return 0; /* this means okay */ X} X X/* skip to beginning of next line, i.e., next read returns first X character of new line */ X void f_toNL(fp) register File *fp; X{ X register int c; X X if (fp->f_flags & F_EOF) X return; X while (((c = getc(fp)) != EOF) && (c != '\n')) X ; X if (c == EOF) X fp->f_flags |= F_EOF; X} X void f_readn(fp, addr, n) register File *fp; register char *addr; register int n; X{ X while (--n >= 0) X *addr++ = getc(fp); X} X int f_getint(fp) File *fp; X{ X int n = 0, X c; X X while (isdigit(c = getc(fp))) X n = (n * 10) + c; X return n; X} X X/* Deals with output to the terminal, setting up the amount of characters X to be buffered depending on the output baud rate. Why it's in a X separate file I don't know ... */ X private char one_buf; X int BufSize = 1; X private File _stdout = {1, 1, 1, F_WRITE, &one_buf, &one_buf}; File *stdout = &_stdout; X X/* put a string with padding */ X X#ifndef IBMPC void tputc(c) X{ X putchar(c); X} X X#undef putchar /* for files which forget to include io.h, X here's a real putchar procedure. */ void putchar(c) X{ X putc(c, stdout); X} X X#endif /* IBMPC */ X#ifndef MAC void putpad(str, lines) char *str; X{ X#ifndef IBMPC X if (str) X tputs(str, lines, tputc); X#else /* IBMPC */ X write_emif(str); X#endif /* IBMPC */ X} X#endif X X/* Determine the number of characters to buffer at each baud rate. The X lower the number, the quicker the response when new input arrives. Of X course the lower the number, the more prone the program is to stop in X output. Decide what matters most to you. This sets BufSize to the right X number or chars, and initiaizes `stdout'. */ X void settout(ttbuf) char *ttbuf; X{ X#ifndef MAC X#ifndef MSDOS X static int speeds[] = { X 1, /* 0 */ X 1, /* 50 */ X 1, /* 75 */ X 1, /* 110 */ X 1, /* 134 */ X 1, /* 150 */ X 1, /* 200 */ X 2, /* 300 */ X 4, /* 600 */ X 8, /* 1200 */ X 16, /* 1800 */ X 32, /* 2400 */ X 128, /* 4800 */ X 256, /* 9600 */ X 512, /* EXTA */ X 1024 /* EXT */ X }; X flusho(); /* flush the one character buffer */ X BufSize = min(MAXTTYBUF, speeds[ospeed] * max(LI / 24, 1)); X stdout = fd_open("/dev/tty", F_WRITE|F_LOCKED, 1, ttbuf, BufSize); X#else /* MSDOS */ X#ifndef IBMPC X flusho(); /* flush the one character buffer */ X BufSize = BUFSIZ; X stdout = fd_open("con", F_WRITE|F_LOCKED, 1, ttbuf, BufSize); X#endif /* IBMPC */ X#endif /* MSDOS */ X#endif /* MAC */ X} X X#ifdef RAINBOW X X/* X * use the Rainbow's video output function X */ X X#include <dos.h> X private int rbwrite(fd, buf, cnt) char *buf; X{ X union REGS vr; X X if (fd != 1) { X write(fd, buf, cnt); X } else { X while (cnt-- > 0) { X vr.x.ax = *buf++; X vr.x.di = 0; X int86(0x18, &vr, &vr); X } X } X} X#endif /* RAINBOW */ END_OF_FILE if test 7807 -ne `wc -c <'./fp.c'`; then echo shar: \"'./fp.c'\" unpacked with wrong size! fi # end of './fp.c' fi if test -f './iproc-pipes.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./iproc-pipes.c'\" else echo shar: Extracting \"'./iproc-pipes.c'\" \(5928 characters\) sed "s/^X//" >'./iproc-pipes.c' <<'END_OF_FILE' X/*************************************************************************** X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE * X * is provided to you without charge, and with no warranty. You may give * X * away copies of JOVE, including sources, provided that this notice is * X * included in all the files. * X ***************************************************************************/ X X#ifdef BSD4_2 X# include <sys/wait.h> X#else X# include <wait.h> X#endif X#include <signal.h> X#include <sgtty.h> X X#define DEAD 1 /* Dead but haven't informed user yet */ X#define STOPPED 2 /* Job stopped */ X#define RUNNING 3 /* Just running */ X#define NEW 4 /* This process is brand new */ X X/* If process is dead, flags says how. */ X#define EXITED 1 X#define KILLED 2 X X#define isdead(p) (p == 0 || proc_state(p) == DEAD || p->p_toproc == -1) X#define makedead(p) (proc_state(p) = DEAD) X X#define proc_buf(p) (p->p_buffer->b_name) X#define proc_cmd(p) (p->p_name) X#define proc_state(p) (p->p_state) X private Process *procs = 0; X int ProcInput, X ProcOutput, X NumProcs = 0; X char * pstate(p) Process *p; X{ X switch (proc_state(p)) { X case NEW: X return "Pre-birth"; X X case STOPPED: X return "Stopped"; X X case RUNNING: X return "Running"; X X case DEAD: X if (p->p_howdied == EXITED) { X if (p->p_reason == 0) X return "Done"; X return sprint("Exit %d", p->p_reason); X } X return sprint("Killed %d", p->p_reason); X X default: X return "Unknown state"; X } X} X static Process * proc_pid(pid) X{ X register Process *p; X X for (p = procs; p != 0; p = p->p_next) X if (p->p_portpid == pid) X break; X X return p; X} X procs_read() X{ X struct header { X int pid; X int nbytes; X } header; X int n; X long nbytes; X static int here = NO; X X if (here) X return; X sighold(SIGCHLD); /* block any other children */ X here = YES; X for (;;) { X (void) ioctl(ProcInput, FIONREAD, (struct sgttyb *) &nbytes); X if (nbytes < sizeof header) X break; X n = read(ProcInput, (char *) &header, sizeof header); X if (n != sizeof header) X finish(1); X read_proc(header.pid, header.nbytes); X } X here = NO; X sigrelse(SIGCHLD); X} X read_proc(pid, nbytes) int pid; register int nbytes; X{ X register Process *p; X int n; X char ibuf[512]; X X if ((p = proc_pid(pid)) == 0) { X printf("\riproc: unknown pid (%d)", pid); X return; X } X if (proc_state(p) == NEW) { X int rpid; X /* pid of real child, not of portsrv */ X X doread(ProcInput, (char *) &rpid, nbytes); X nbytes -= sizeof rpid; X p->p_pid = rpid; X p->p_state = RUNNING; X } X X if (nbytes == EOF) { /* okay to clean up this process */ X proc_close(p); X makedead(p); X return; X } X X while (nbytes > 0) { X n = min((sizeof ibuf) - 1, nbytes); X doread(ProcInput, ibuf, n); X ibuf[n] = 0; /* Null terminate for convenience */ X nbytes -= n; X proc_rec(p, ibuf); X } X} X ProcKill() X{ X proc_kill(curbuf->b_process, SIGKILL); X} X ProcInt() X{ X proc_kill(curbuf->b_process, SIGINT); X} X ProcQuit() X{ X proc_kill(curbuf->b_process, SIGQUIT); X} X private proc_close(p) Process *p; X{ X sighold(SIGCHLD); X X if (p->p_toproc >= 0) { X (void) close(p->p_toproc); X p->p_toproc = -1; /* writes will fail */ X NumProcs -= 1; X } X X sigrelse(SIGCHLD); X} X do_rtp(mp) register Mark *mp; X{ X register Process *p = curbuf->b_process; X Line *line1 = curline, X *line2 = mp->m_line; X int char1 = curchar, X char2 = mp->m_char; X char *gp; X X if (isdead(p) || p->p_buffer != curbuf) X return; X X (void) fixorder(&line1, &char1, &line2, &char2); X while (line1 != line2->l_next) { X gp = ltobuf(line1, genbuf) + char1; X if (line1 == line2) X gp[char2] = '\0'; X else X strcat(gp, "\n"); X (void) write(p->p_toproc, gp, strlen(gp)); X line1 = line1->l_next; X char1 = 0; X } X} X X/* VARARGS3 */ X private proc_strt(bufname, clobber, va_alist) char *bufname; va_dcl X{ X Window *owind = curwind; X int toproc[2], X pid; X Process *newp; X Buffer *newbuf; X char *argv[32], X *cp, X foo[10], X cmdbuf[128]; X int i; X va_list ap; X X isprocbuf(bufname); /* make sure BUFNAME is either nonexistant X or is of type B_PROCESS */ X dopipe(toproc); X X sighold(SIGCHLD); X#ifdef SIGWINCH X sighold(SIGWINCH); X#endif X switch (pid = fork()) { X case -1: X pclose(toproc); X complain("[Fork failed.]"); X X case 0: X sigrelse(SIGCHLD); X#ifdef SIGWINCH X sigrelse(SIGWINCH); X#endif X argv[0] = "portsrv"; X argv[1] = foo; X sprintf(foo, "%d", ProcInput); X va_start(ap); X make_argv(&argv[2], ap); X va_end(ap); X (void) dup2(toproc[0], 0); X (void) dup2(ProcOutput, 1); X (void) dup2(ProcOutput, 2); X pclose(toproc); X execv(Portsrv, argv); X printf("execl failed\n"); X _exit(1); X } X X newp = (Process *) malloc(sizeof *newp); X newp->p_next = procs; X newp->p_state = NEW; X newp->p_cmd = 0; X X cmdbuf[0] = '\0'; X va_start(ap); X while (cp = va_arg(ap, char *)) X sprintf(&cmdbuf[strlen(cmdbuf)], "%s ", cp); X va_end(ap); X newp->p_name = copystr(cmdbuf); X procs = newp; X newp->p_portpid = pid; X newp->p_pid = -1; X X newbuf = do_select((Window *) 0, bufname); X newbuf->b_type = B_PROCESS; X newp->p_buffer = newbuf; X newbuf->b_process = newp; /* sorta circular, eh? */ X pop_wind(bufname, clobber, B_PROCESS); X ToLast(); X if (!bolp()) X LineInsert(1); X /* Pop_wind() after everything is set up; important! X Bindings won't work right unless newbuf->b_process is already X set up BEFORE NEWBUF is first SetBuf()'d. */ X newp->p_mark = MakeMark(curline, curchar, M_FLOATER); X X newp->p_toproc = toproc[1]; X newp->p_reason = 0; X NumProcs += 1; X (void) close(toproc[0]); X SetWind(owind); X sigrelse(SIGCHLD); X#ifdef SIGWINCH X sigrelse(SIGWINCH); X#endif X} X pinit() X{ X int p[2]; X X (void) signal(SIGCHLD, proc_child); X (void) pipe(p); X ProcInput = p[0]; X ProcOutput = p[1]; X (void) signal(INPUT_SIG, procs_read); X sighold(INPUT_SIG); /* Released during terminal read */ X} X doread(fd, buf, n) char *buf; X{ X int nread; X X if ((nread = read(fd, buf, n)) != n) X complain("Cannot read %d (got %d) bytes.", n, nread); X} END_OF_FILE if test 5928 -ne `wc -c <'./iproc-pipes.c'`; then echo shar: \"'./iproc-pipes.c'\" unpacked with wrong size! fi # end of './iproc-pipes.c' fi if test -f './iproc-ptys.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./iproc-ptys.c'\" else echo shar: Extracting \"'./iproc-ptys.c'\" \(7915 characters\) sed "s/^X//" >'./iproc-ptys.c' <<'END_OF_FILE' X/*************************************************************************** X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE * X * is provided to you without charge, and with no warranty. You may give * X * away copies of JOVE, including sources, provided that this notice is * X * included in all the files. * X ***************************************************************************/ X X#ifdef BSD4_2 X# include <sys/wait.h> X#else X# include <wait.h> X#endif X#include <signal.h> X#include <sgtty.h> X#include <errno.h> X X#define DEAD 1 /* dead but haven't informed user yet */ X#define STOPPED 2 /* job stopped */ X#define RUNNING 3 /* just running */ X#define NEW 4 /* brand new, never been ... received no input */ X X/* If process is dead, flags says how. */ X#define EXITED 1 X#define KILLED 2 X X#define isdead(p) (p == 0 || proc_state(p) == DEAD || p->p_fd == -1) X#define makedead(p) (proc_state(p) = DEAD) X X#define proc_buf(p) (p->p_buffer->b_name) X#define proc_cmd(p) (p->p_name) X#define proc_state(p) (p->p_state) X private Process *procs = 0; X long global_fd = 1; int NumProcs = 0; X X#ifdef BRLUNIX X extern struct sg_brl sg1; X#else X extern struct sgttyb sg1; X#endif X extern struct tchars tc1; X X#ifdef TIOCSLTC X extern struct ltchars ls1; X#endif X char * pstate(p) Process *p; X{ X switch (proc_state(p)) { X case STOPPED: X return "Stopped"; X X case RUNNING: X return "Running"; X X case DEAD: X if (p->p_howdied == EXITED) { X if (p->p_reason == 0) X return "Done"; X return sprint("Exit %d", p->p_reason); X } X return sprint("Killed %d", p->p_reason); X X case NEW: X return "New"; X X default: X return "Unknown state"; X } X} X static Process * proc_pid(pid) X{ X register Process *p; X X for (p = procs; p != 0; p = p->p_next) X if (p->p_pid == pid) X break; X X return p; X} X read_proc(fd) register int fd; X{ X register Process *p; X unsigned int n; X char ibuf[1024]; X X for (p = procs; p != 0; p = p->p_next) X if (p->p_fd == fd) X break; X X if (p == 0) { X printf("\riproc: unknown fd %d", fd); X return; X } X X n = read(fd, ibuf, sizeof(ibuf) - 1); X if (n == -1 && errno == EIO) { X if (proc_state(p) == NEW) X return; X proc_close(p); X makedead(p); X return; X } else { X if (proc_state(p) != RUNNING) { X proc_state(p) = RUNNING; X UpdModLine = YES; X } X } X if (n <= 0) { X if (n == 0) X strcpy(ibuf, "[Process EOF]"); X else X sprintf(ibuf, "\n[pty read error: %d]\n", errno); X } else X ibuf[n] = '\0'; X proc_rec(p, ibuf); X} X ProcKill() X{ X register Buffer *b; X Process *buf_to_proc(); X char *bname; X X bname = ask_buf(curbuf); X X if ((b = buf_exists(bname)) == 0) X complain("[No such buffer]"); X if (b->b_process == 0) X complain("%s not tied to a process.", bname); X proc_kill(b->b_process, SIGKILL); X} X ProcCont() X{ X Process *p; X X if ((p = curbuf->b_process) == 0) X complain("[No process]"); X if (p->p_state != DEAD) { X proc_kill(p, SIGCONT); X p->p_state = RUNNING; X } X} X ProcEof() X{ X send_p(tc1.t_eofc); X} X ProcInt() X{ X send_p(tc1.t_intrc); X} X ProcQuit() X{ X send_p(tc1.t_quitc); X} X ProcStop() X{ X send_p(ls1.t_suspc); X} X ProcDStop() X{ X send_p(ls1.t_dsuspc); X} X send_p(c) char c; X{ X Process *p; X char buf[2]; X X if ((p = curbuf->b_process) == 0) X complain("[No process]"); X ToLast(); X buf[0] = c; X buf[1] = '\0'; X proc_rec(p, buf); X (void) write(p->p_fd, &c, 1); X} X private proc_close(p) Process *p; X{ X sighold(SIGCHLD); /* be mutually exclusive */ X X if (p->p_fd >= 0) { X (void) close(p->p_fd); X global_fd &= ~(1L << p->p_fd); X NumProcs -= 1; X p->p_fd = -1; X } X X sigrelse(SIGCHLD); X} X do_rtp(mp) register Mark *mp; X{ X register Process *p = curbuf->b_process; X Line *line1 = curline, X *line2 = mp->m_line; X int char1 = curchar, X char2 = mp->m_char; X char *gp; X int nbytes; X X if (isdead(p) || p->p_buffer != curbuf) X return; X X (void) fixorder(&line1, &char1, &line2, &char2); X while (line1 != line2->l_next) { X gp = ltobuf(line1, genbuf) + char1; X if (line1 == line2) X gp[char2] = '\0'; X else X strcat(gp, "\n"); X if (nbytes = strlen(gp)) X (void) write(p->p_fd, gp, nbytes); X line1 = line1->l_next; X char1 = 0; X } X} X X/* VARARGS2 */ X private proc_strt(bufname, clobber, va_alist) char *bufname; va_dcl X{ X va_list ap; X char *argv[32], X *cp; X Window *owind = curwind; X int pid; X Process *newp; X Buffer *newbuf; X int i, X ptyfd, X ttyfd, X ldisc, X lmode; X register char *s, X *t; X extern int errno; X static char ttybuf[11], X ptybuf[11]; X char cmdbuf[128]; X#ifdef BRLUNIX X struct sg_brl sg; X#else X struct sgttyb sg; X#endif X X#ifdef TIOCGWINSZ X struct winsize win; X#else X# ifdef BTL_BLIT X# include <sys/jioctl.h> X struct jwinsize jwin; X# endif X#endif X X isprocbuf(bufname); /* make sure BUFNAME is either nonexistant X or is of type B_PROCESS */ X for (s = "pqrs"; *s; s++) { X for (t = "0123456789abcdef"; *t; t++) { X sprintf(ptybuf, "/dev/pty%c%c", *s, *t); X if ((ptyfd = open(ptybuf, 2)) >= 0) { X strcpy(ttybuf, ptybuf); X ttybuf[5] = 't'; X /* make sure both ends are available */ X if ((i = open(ttybuf, 2)) < 0) X continue; X (void) close(i); X goto out; X } X } X } X out: if (s == 0 && t == 0) X complain("[Out of ptys!]"); X X#ifdef TIOCGETD X (void) ioctl(0, TIOCGETD, (struct sgttyb *) &ldisc); X#endif X#ifdef TIOCLGET X (void) ioctl(0, TIOCLGET, (struct sgttyb *) &lmode); X#endif X#ifdef TIOCGWINSZ X (void) ioctl(0, TIOCGWINSZ, (struct sgttyb *) &win); X#else X# ifdef BTL_BLIT X (void) ioctl(0, JWINSIZE, (struct sgttyb *) &jwin); X# endif /* BTL_BLIT */ X#endif X X sighold(SIGCHLD); X#ifdef SIGWINCH X sighold(SIGWINCH); X#endif X switch (pid = fork()) { X case -1: X (void) close(ptyfd); X message("[Fork failed!]"); X goto fail; X X case 0: X sigrelse(SIGCHLD); X#ifdef SIGWINCH X sigrelse(SIGWINCH); X#endif X for (i = 0; i < 32; i++) X (void) close(i); X X#ifdef TIOCNOTTY X if ((i = open("/dev/tty", 2)) >= 0) { X (void) ioctl(i, TIOCNOTTY, (struct sgttyb *) 0); X (void) close(i); X } X#endif X if ((ttyfd = open(ttybuf, 2)) < 0) X exit(-1); X (void) dup2(ttyfd, 1); X (void) dup2(ttyfd, 2); X X#ifdef TIOCSETD X (void) ioctl(0, TIOCSETD, (struct sgttyb *) &ldisc); X#endif X#ifdef TIOCLSET X (void) ioctl(0, TIOCLSET, (struct sgttyb *) &lmode); X#endif X#ifdef TIOCSETC X (void) ioctl(0, TIOCSETC, (struct sgttyb *) &tc1); X#endif X#ifdef TIOCSLTC X (void) ioctl(0, TIOCSLTC, (struct sgttyb *) &ls1); X#endif X X#ifdef TIOCGWINSZ X# ifdef SIGWINCH X (void) signal(SIGWINCH, SIG_IGN); X# endif X win.ws_row = curwind->w_height; X (void) ioctl(0, TIOCSWINSZ, (struct sgttyb *) &win); X#else X# ifdef BTL_BLIT X jwin.bytesy = curwind->w_height; X (void) ioctl(0, JSWINSIZE, (struct sgttyb *) &jwin); X# endif X#endif X X sg = sg1; X sg.sg_flags &= ~(ECHO | CRMOD); X (void) stty(0, &sg); X X i = getpid(); X (void) ioctl(0, TIOCSPGRP, (struct sgttyb *) &i); X (void) setpgrp(0, i); X va_start(ap); X make_argv(argv, ap); X va_end(ap); X execv(argv[0], &argv[1]); X (void) write(1, "execve failed!\n", 15); X _exit(errno + 1); X } X X newp = (Process *) emalloc(sizeof *newp); X X newp->p_fd = ptyfd; X newp->p_pid = pid; X X newbuf = do_select((Window *) 0, bufname); X newbuf->b_type = B_PROCESS; X newp->p_buffer = newbuf; X newbuf->b_process = newp; /* sorta circular, eh? */ X pop_wind(bufname, clobber, B_PROCESS); X /* Pop_wind() after everything is set up; important! X Bindings won't work right unless newbuf->b_process is already X set up BEFORE NEWBUF is first SetBuf()'d. */ X ToLast(); X if (!bolp()) X LineInsert(1); X X cmdbuf[0] = '\0'; X va_start(ap); X while (cp = va_arg(ap, char *)) X sprintf(&cmdbuf[strlen(cmdbuf)], "%s ", cp++); X va_end(ap); X X newp->p_name = copystr(cmdbuf); X newp->p_state = NEW; X newp->p_reason = 0; X newp->p_mark = MakeMark(curline, curchar, M_FLOATER); X X newp->p_next = procs; X procs = newp; X NumProcs += 1; X global_fd |= 1L << newp->p_fd; X SetWind(owind); X fail: sigrelse(SIGCHLD); X#ifdef SIGWINCH X sigrelse(SIGWINCH); X#endif X} X pinit() X{ X (void) signal(SIGCHLD, proc_child); X} X END_OF_FILE if test 7915 -ne `wc -c <'./iproc-ptys.c'`; then echo shar: \"'./iproc-ptys.c'\" unpacked with wrong size! fi # end of './iproc-ptys.c' fi if test -f './macros.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./macros.c'\" else echo shar: Extracting \"'./macros.c'\" \(7870 characters\) sed "s/^X//" >'./macros.c' <<'END_OF_FILE' X/*************************************************************************** X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE * X * is provided to you without charge, and with no warranty. You may give * X * away copies of JOVE, including sources, provided that this notice is * X * included in all the files. * X ***************************************************************************/ X X#include "jove.h" X#include "ctype.h" X#include "io.h" X X#ifdef MAC X# undef private X# define private X#endif X X#ifdef LINT_ARGS private void X add_mac(struct macro *), X del_mac(struct macro *), X pop_macro_stack(void), X push_macro_stack(struct macro *, int); X private int X PrefChar(int); X private struct macro * mac_exists(char *); X#else private void X add_mac(), X del_mac(), X pop_macro_stack(), X push_macro_stack(); X private int X PrefChar(); X private struct macro * mac_exists(); X#endif /* LINT_ARGS */ X X#ifdef MAC X# undef private X# define private static X#endif X struct macro *macros = 0; /* macros */ int InMacDefine = NO; X private void add_mac(new) struct macro *new; X{ X register struct macro *mp, X *prev = 0; X X for (mp = macros; mp != 0; prev = mp, mp = mp->m_nextm) X if (mp == new) X return; X X if (prev) X prev->m_nextm = new; X else X macros = new; X new->m_nextm = 0; X new->Type = MACRO; X} X private void del_mac(mac) struct macro *mac; X{ X register struct macro *m; X X for (m = macros; m != 0; m = m->m_nextm) X if (m->m_nextm == mac) { X m->m_nextm = mac->m_nextm; X break; X } X free(mac->Name); X free(mac->m_body); X free((char *) mac); X} X struct macro KeyMacro; /* Macro used for defining */ X X/* To execute a macro, we have a "stack" of running macros. Whenever X we execute a macro, we push it on the stack, run it, then pop it X from the stack. */ struct m_thread { X struct m_thread *mt_prev; X struct macro *mt_mp; X int mt_offset, X mt_count; X}; X private struct m_thread *mac_stack = 0; X void unwind_macro_stack() X{ X while (mac_stack != 0) X pop_macro_stack(); X} X private void pop_macro_stack() X{ X register struct m_thread *m; X X if ((m = mac_stack) == 0) X return; X mac_stack = m->mt_prev; X free_mthread(m); X} X struct m_thread * alloc_mthread() X{ X return (struct m_thread *) emalloc(sizeof (struct m_thread)); X} X void free_mthread(t) struct m_thread *t; X{ X free((char *) t); X} X private void push_macro_stack(m, count) struct macro *m; X{ X struct m_thread *t; X X t = alloc_mthread(); X t->mt_prev = mac_stack; X mac_stack = t; X t->mt_offset = 0; X t->mt_mp = m; X t->mt_count = count; X} X void do_macro(mac) struct macro *mac; X{ X push_macro_stack(mac, arg_value()); X} X private struct macro * mac_exists(name) char *name; X{ X register struct macro *mp; X X for (mp = macros; mp; mp = mp->m_nextm) X if (strcmp(mp->Name, name) == 0) X return mp; X return 0; X} X void mac_init() X{ X add_mac(&KeyMacro); X KeyMacro.Name = "keyboard-macro"; X KeyMacro.m_len = 0; X KeyMacro.m_buflen = 16; X KeyMacro.m_body = emalloc(KeyMacro.m_buflen); X} X void mac_putc(c) int c; X{ X if (KeyMacro.m_len >= KeyMacro.m_buflen) { X KeyMacro.m_buflen += 16; X KeyMacro.m_body = realloc(KeyMacro.m_body, (unsigned) KeyMacro.m_buflen); X if (KeyMacro.m_body == 0) { X KeyMacro.m_buflen = KeyMacro.m_len = 0; X complain("[Can't allocate storage for keyboard macro]"); X } X } X KeyMacro.m_body[KeyMacro.m_len++] = c; X} X int in_macro() X{ X return (mac_stack != 0); X} X int mac_getc() X{ X struct m_thread *mthread; X struct macro *m; X X if ((mthread = mac_stack) == 0) X return -1; X m = mthread->mt_mp; X if (mthread->mt_offset == m->m_len) { X mthread->mt_offset = 0; X if (--mthread->mt_count == 0) X pop_macro_stack(); X return mac_getc(); X } X return m->m_body[mthread->mt_offset++]; X} X void NameMac() X{ X char *name; X struct macro *m; X X if (KeyMacro.m_len == 0) X complain("[No keyboard macro to name!]"); X if (in_macro() || InMacDefine) X complain("[Can't name while defining/executing]"); X if ((m = mac_exists(name = ask((char *) 0, ProcFmt))) == 0) X m = (struct macro *) emalloc(sizeof *m); X else { X if (strcmp(name, KeyMacro.Name) == 0) X complain("[Can't name it that!]"); X free(m->Name); X free(m->m_body); X } X name = copystr(name); X m->Type = KeyMacro.Type; X m->m_len = KeyMacro.m_len; X m->m_buflen = KeyMacro.m_buflen; X m->m_body = emalloc(m->m_buflen); X byte_copy(KeyMacro.m_body, m->m_body, m->m_len); X m->m_flags = SAVE; X m->Name = name; X add_mac(m); X} X void RunMacro() X{ X struct macro *m; X X if (m = (struct macro *) findmac(ProcFmt)) X do_macro(m); X} X void pr_putc(c, fp) File *fp; X{ X if (c == '\\' || c == '^') X putc('\\', fp); X else if (isctrl(c)) { X putc('^', fp); X c = (c == RUBOUT) ? '?' : (c + '@'); X } X putc(c, fp); X} X void WriteMacs() X{ X struct macro *m; X char *file, X filebuf[FILESIZE]; X File *fp; X int i; X X file = ask_file((char *) 0, (char *) 0, filebuf); X fp = open_file(file, iobuff, F_WRITE, COMPLAIN, QUIET); X X /* Don't write the keyboard macro which is always the first */ X for (m = macros->m_nextm; m != 0; m = m->m_nextm) { X fprintf(fp, "define-macro %s ", m->Name); X for (i = 0; i < m->m_len; i++) X pr_putc(m->m_body[i], fp); X putc('\n', fp); X m->m_flags &= ~SAVE; X } X close_file(fp); X} X void DefKBDMac() X{ X char *macro_name, X *macro_body, X nextc, X c, X macro_buffer[LBSIZE]; X int i; X struct macro *m; X X macro_name = do_ask(" \r\n", (int (*)()) 0, (char *) 0, ProcFmt); X if (macro_name == 0) X complain("[No default]"); X macro_name = copystr(macro_name); X if (m = mac_exists(macro_name)) X del_mac(m); X macro_body = ask((char *) 0, ": %f %s enter body: ", macro_name); X i = 0; X while ((c = *macro_body++) != '\0') { X if (c == '\\') { X if ((nextc = *macro_body++) == LF) X complain("[Premature end of line]"); X c = nextc; X } else if (c == '^') { X if ((nextc = *macro_body++) == '?') X c = RUBOUT; X else if (isalpha(nextc) || index("@[\\]^_", nextc)) X c = CTL(nextc); X else X complain("Bad control-character: '%c'", nextc); X } X macro_buffer[i++] = c; X } X m = (struct macro *) emalloc(sizeof (*m)); X m->Name = macro_name; X m->m_len = m->m_buflen = i; X m->m_body = emalloc(i); X m->m_flags = InJoverc ? 0 : SAVE; X byte_copy(macro_buffer, m->m_body, i); X add_mac(m); X} X void Remember() X{ X /* We're already executing the macro; ignore any attempts X to define the keyboard macro while we are executing. */ X if (in_macro()) X return; X if (InMacDefine) X message("[Already defining ... continue with definition]"); X else { X UpdModLine = YES; X InMacDefine = YES; X KeyMacro.m_len = 0; X message("Defining..."); X } X} X X/* Is `c' a prefix character */ X private int PrefChar(c) X{ X return (int) IsPrefix(mainmap[c]); X} X void Forget() X{ X char *cp; X struct macro *m = &KeyMacro; X X UpdModLine = YES; X if (InMacDefine) { X message("Keyboard macro defined."); X InMacDefine = NO; X X /* try and strip off the key sequence that invoked us */ X cp = &m->m_body[m->m_len - 2]; X if (PrefChar(*cp)) X m->m_len -= 2; X else if (commands[cp[1]].c_proc == Forget) X m->m_len -= 1; X } else X complain("[end-kbd-macro: not currently defining macro!]"); X} X void ExecMacro() X{ X do_macro(&KeyMacro); X} X void MacInter() X{ X extern int Interactive; X X if (!Asking) X return; X Interactive = 1; X} X int ModMacs() X{ X register struct macro *m; X X for (m = macros->m_nextm; m != 0; m = m->m_nextm) X if (m->m_flags & SAVE) X return YES; X return NO; X} X data_obj * findmac(prompt) char *prompt; X{ X char *strings[100]; X register char **strs = strings; X register int com; X register struct macro *m = macros; X X for (; m != 0; m = m->m_nextm) X *strs++ = m->Name; X *strs = 0; X X if ((com = complete(strings, prompt, NOTHING)) < 0) X return 0; X m = macros; X while (--com >= 0) X m = m->m_nextm; X return (data_obj *) m; X} X void DelMacro() X{ X struct macro *m; X X if ((m = (struct macro *) findmac(ProcFmt)) == 0) X return; X if (m == &KeyMacro) X complain("[It's illegal to delete the keyboard-macro!]"); X del_mac(m); X} END_OF_FILE if test 7870 -ne `wc -c <'./macros.c'`; then echo shar: \"'./macros.c'\" unpacked with wrong size! fi # end of './macros.c' fi echo shar: End of archive 3 \(of 21\). cp /dev/null ark3isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 21 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.