[mod.sources] v09i039: MicroEMACS 3.8b, Part07/14

sources-request@mirror.UUCP (03/14/87)

Submitted by: ihnp4!itivax!duncan!lawrence (Daniel Lawrence)
Mod.sources: Volume 9, Issue 39
Archive-name: uemacs3.8b/Part07

#! /bin/sh
# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
# If this archive is complete, you will see the message:
#		"End of archive 7 (of 14)."
# Contents:  exec.c spawn.c window.c
# Wrapped by rs@mirror on Fri Mar 13 13:24:22 1987
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo shar: Extracting \"exec.c\" \(16413 characters\)
if test -f exec.c ; then 
  echo shar: Will not over-write existing file \"exec.c\"
else
sed "s/^X//" >exec.c <<'END_OF_exec.c'
X/*	This file is for functions dealing with execution of
X	commands, command lines, buffers, files and startup files
X
X	written 1986 by Daniel Lawrence				*/
X
X#include	<stdio.h>
X#include	"estruct.h"
X#include	"edef.h"
X
X#if	MEGAMAX & ST520
Xoverlay	"exec"
X#endif
X
X#if	DEBUGM
Xchar outline[NSTRING];		/* global string to hold debug line text */
X#endif
X
X/* namedcmd:	execute a named command even if it is not bound */
X
Xnamedcmd(f, n)
X
Xint f, n;	/* command arguments [passed through to command executed] */
X
X{
X	register (*kfunc)();	/* ptr to the requexted function to bind to */
X	int (*getname())();
X
X	/* prompt the user to type a named command */
X	mlwrite(": ");
X
X	/* and now get the function name to execute */
X	kfunc = getname();
X	if (kfunc == NULL) {
X		mlwrite("[No such function]");
X		return(FALSE);
X	}
X
X	/* and then execute the command */
X	return((*kfunc)(f, n));
X}
X
X/*	execcmd:	Execute a command line command to be typed in
X			by the user					*/
X
Xexeccmd(f, n)
X
Xint f, n;	/* default Flag and Numeric argument */
X
X{
X	register int status;		/* status return */
X	char cmdstr[NSTRING];		/* string holding command to execute */
X
X	/* get the line wanted */
X	if ((status = mlreply(": ", cmdstr, NSTRING)) != TRUE)
X		return(status);
X
X	execlevel = 0;
X	return(docmd(cmdstr));
X}
X
X/*	docmd:	take a passed string as a command line and translate
X		it to be executed as a command. This function will be
X		used by execute-command-line and by all source and
X		startup files. Lastflag/thisflag is also updated.
X
X	format of the command line is:
X
X		{# arg} <command-name> {<argument string(s)>}
X
X	Directives start with a "!" and include:
X
X	!endm		End a macro
X	!if (cond)	conditional execution
X	!else
X	!endif
X	!return		Return (terminating current macro)
X	!goto <label>	Jump to a label in the current macro
X
X	Line Labels begin with a "*" in column 1, like:
X
X	*LBL01
X*/
X
Xdocmd(cline)
X
Xchar *cline;	/* command line to execute */
X
X{
X	register int f;		/* default argument flag */
X	register int n;		/* numeric repeat value */
X	register int i;
X	int (*fnc)();		/* function to execute */
X	int status;		/* return status of function */
X	int oldcle;		/* old contents of clexec flag */
X	int llen;		/* length of cline */
X	int force;		/* force TRUE result? */
X	char *tmp;		/* tmp pointer into cline */
X	struct LINE *lp;	/* a line pointer */
X	char *oldestr;		/* original exec string */
X	char token[NSTRING];	/* next token off of command line */
X	int (*fncmatch())();
X#if	DEBUGM
X	/* if $debug == TRUE, every line to execute
X	   gets echoed and a key needs to be pressed to continue
X	   ^G will abort the command */
X	register char *sp;	/* pointer into buf to expand %s */
X
X	if (macbug) {
X		strcpy(outline, "<<<");
X#if	1	/* debug if levels */
X		strcat(outline, itoa(execlevel));
X		strcat(outline, ":");
X#endif
X		strcat(outline, cline);
X		strcat(outline, ">>>");
X
X		/* change all '%' to ':' so mlwrite won't expect arguments */
X		sp = outline;
X		while (*sp) {
X			if (*sp++ == '%')
X				*(sp-1) = ':';
X		}
X
X		/* write out the debug line */
X		mlwrite(outline);
X		update(TRUE);
X
X		/* and get the keystroke */
X		if (tgetc() == 7) {
X			mlwrite("[Macro aborted]");
X			return(FALSE);
X		}
X	}
X#endif
X		
X	/* dump comments and labels here */
X	if (*cline == ';' || *cline == '*')
X		return(TRUE);
X
X	/* eat leading spaces */
X	while (*cline == ' ' || *cline == '\t')
X		++cline;
X
X	/* check to see if this line turns macro storage off */
X	if (cline[0] == '!' && strncmp(&cline[1], "endm", 4) == 0) {
X		mstore = FALSE;
X		bstore = NULL;
X		return(TRUE);
X	}
X
X	/* if macro store is on, just salt this away */
X	if (mstore) {
X		/* allocate the space for the line */
X		llen = strlen(cline);
X		if ((lp=lalloc(llen)) == NULL) {
X			mlwrite("Out of memory while storing macro");
X			return (FALSE);
X		}
X
X		/* copy the text into the new line */
X		for (i=0; i<llen; ++i)
X			lputc(lp, i, cline[i]);
X
X		/* attach the line to the end of the buffer */
X       		bstore->b_linep->l_bp->l_fp = lp;
X		lp->l_bp = bstore->b_linep->l_bp;
X		bstore->b_linep->l_bp = lp;
X		lp->l_fp = bstore->b_linep;
X		return (TRUE);
X	}
X	
X	force = FALSE;
X	oldestr = execstr;	/* save last ptr to string to execute */
X	execstr = cline;	/* and set this one as current */
X
X	/* process directives */
X	if (*cline == '!') {
X		/* save directive location and skip it */
X		tmp = cline;
X		while (*execstr && *execstr != ' ' && *execstr != '\t')
X			++execstr;
X
X		if (tmp[1] == 'f' && tmp[2] == 'o') {
X			force = TRUE;
X			goto do001;
X
X		} else if (tmp[1] == 'i' && tmp[2] == 'f') {
X
X			/* IF directive */
X			/* grab the value of the logical exp */
X			if (execlevel == 0) {
X				if ((status = macarg(token)) != TRUE) {
X					execstr = oldestr;
X					return(status);
X				}
X				status = stol(token);
X			} else
X				status = TRUE;
X
X			if (status) {
X
X				/* IF (TRUE) */
X				if (execlevel != 0)
X					++execlevel;
X			} else {
X
X				/* IF (FALSE) */
X				++execlevel;
X			}
X
X		} else if (tmp[1] == 'e' && tmp[2] == 'l') {
X
X			/* ELSE directive */
X			if (execlevel == 1)
X				--execlevel;
X			else if (execlevel == 0 )
X				++execlevel;
X
X		} else if (tmp[1] == 'e' && tmp[2] == 'n') {
X
X			/* ENDIF directive */
X			if (execlevel)
X				--execlevel;
X
X		} else if (tmp[1] == 'r' && tmp[2] == 'e') {
X
X			/* RETURN directive */
X			execstr = oldestr;
X			return(RET);
X
X		} else if (tmp[1] == 'g' && tmp[2] == 'o') {
X
X			/* GOTO directive */
X			/* .....only if we are currently executing */
X			if (execlevel) {
X				execstr = oldestr;
X				return(TRUE);
X			}
X
X			while (*execstr == ' ' || *execstr == '\t')
X				++execstr;
X			strncpy(golabel, execstr, NPAT - 1);
X			return(GOLINE);
X
X		} else {
X			mlwrite("%%Unknown Directive");
X			return(FALSE);
X		}
X
X		/* restore execstr and exit */
X		execstr = oldestr;
X		return(TRUE);
X	}
X
Xdo001:	/* if we are scanning and not executing..go back here */
X	if (execlevel) {
X		execstr = oldestr;
X		return(TRUE);
X	}
X
X	/* first set up the default command values */
X	f = FALSE;
X	n = 1;
X	lastflag = thisflag;
X	thisflag = 0;
X
X	if ((status = macarg(token)) != TRUE) {	/* and grab the first token */
X		execstr = oldestr;
X		return(status);
X	}
X
X	/* process leadin argument */
X	if (gettyp(token) != TKCMD) {
X		f = TRUE;
X		n = atoi(getval(token));
X
X		/* and now get the command to execute */
X		if ((status = macarg(token)) != TRUE) {
X			execstr = oldestr;
X			return(status);	
X		}	
X	}
X
X	/* and match the token to see if it exists */
X	if ((fnc = fncmatch(token)) == NULL) {
X		mlwrite("[No such Function]");
X		execstr = oldestr;
X		return(FALSE);
X	}
X	
X	/* save the arguments and go execute the command */
X	oldcle = clexec;		/* save old clexec flag */
X	clexec = TRUE;			/* in cline execution */
X	status = (*fnc)(f, n);		/* call the function */
X	cmdstatus = status;		/* save the status */
X	if (force)			/* force the status */
X		status = TRUE;
X	clexec = oldcle;		/* restore clexec flag */
X	execstr = oldestr;
X	return(status);
X}
X
X/* token:	chop a token off a string
X		return a pointer past the token
X*/
X
Xchar *token(src, tok)
X
Xchar *src, *tok;	/* source string, destination token string */
X
X{
X	register int quotef;	/* is the current string quoted? */
X
X	/* first scan past any whitespace in the source string */
X	while (*src == ' ' || *src == '\t')
X		++src;
X
X	/* scan through the source string */
X	quotef = FALSE;
X	while (*src) {
X		/* process special characters */
X		if (*src == '~') {
X			++src;
X			if (*src == 0)
X				break;
X			switch (*src++) {
X				case 'r':	*tok++ = 13; break;
X				case 'n':	*tok++ = 10; break;
X				case 't':	*tok++ = 9;  break;
X				case 'b':	*tok++ = 8;  break;
X				case 'f':	*tok++ = 12; break;
X				default:	*tok++ = *(src-1);
X			}
X		} else {
X			/* check for the end of the token */
X			if (quotef) {
X				if (*src == '"')
X					break;
X			} else {
X				if (*src == ' ' || *src == '\t')
X					break;
X			}
X
X			/* set quote mode if qoute found */
X			if (*src == '"')
X				quotef = TRUE;
X
X			/* record the character */
X			*tok++ = *src++;
X		}
X	}
X
X	/* terminate the token and exit */
X	if (*src)
X		++src;
X	*tok = 0;
X	return(src);
X}
X
Xmacarg(tok)	/* get a macro line argument */
X
Xchar *tok;	/* buffer to place argument */
X
X{
X	int savcle;	/* buffer to store original clexec */
X	int status;
X
X	savcle = clexec;	/* save execution mode */
X	clexec = TRUE;		/* get the argument */
X	status = nextarg("", tok, NSTRING, ctoec('\n'));
X	clexec = savcle;	/* restore execution mode */
X	return(status);
X}
X
X/*	nextarg:	get the next argument	*/
X
Xnextarg(prompt, buffer, size, terminator)
X
Xchar *prompt;		/* prompt to use if we must be interactive */
Xchar *buffer;		/* buffer to put token into */
Xchar *size;		/* size of the buffer */
Xint terminator;		/* terminating char to be used on interactive fetch */
X
X{
X	/* if we are interactive, go get it! */
X	if (clexec == FALSE)
X		return(getstring(prompt, buffer, size, terminator));
X
X	/* grab token and advance past */
X	execstr = token(execstr, buffer);
X
X	/* evaluate it */
X	strcpy(buffer, getval(buffer));
X	return(TRUE);
X}
X
X/*	storemac:	Set up a macro buffer and flag to store all
X			executed command lines there			*/
X
Xstoremac(f, n)
X
Xint f;		/* default flag */
Xint n;		/* macro number to use */
X
X{
X	register struct BUFFER *bp;	/* pointer to macro buffer */
X	char bname[NBUFN];		/* name of buffer to use */
X
X	/* must have a numeric argument to this function */
X	if (f == FALSE) {
X		mlwrite("No macro specified");
X		return(FALSE);
X	}
X
X	/* range check the macro number */
X	if (n < 1 || n > 40) {
X		mlwrite("Macro number out of range");
X		return(FALSE);
X	}
X
X	/* construct the macro buffer name */
X	strcpy(bname, "[Macro xx]");
X	bname[7] = '0' + (n / 10);
X	bname[8] = '0' + (n % 10);
X
X	/* set up the new macro buffer */
X	if ((bp = bfind(bname, TRUE, BFINVS)) == NULL) {
X		mlwrite("Can not create macro");
X		return(FALSE);
X	}
X
X	/* and make sure it is empty */
X	bclear(bp);
X
X	/* and set the macro store pointers to it */
X	mstore = TRUE;
X	bstore = bp;
X	return(TRUE);
X}
X
X/*	execbuf:	Execute the contents of a buffer of commands	*/
X
Xexecbuf(f, n)
X
Xint f, n;	/* default flag and numeric arg */
X
X{
X        register BUFFER *bp;		/* ptr to buffer to execute */
X        register int status;		/* status return */
X        char bufn[NBUFN];		/* name of buffer to execute */
X
X	/* find out what buffer the user wants to execute */
X        if ((status = mlreply("Execute buffer: ", bufn, NBUFN)) != TRUE)
X                return(status);
X
X	/* find the pointer to that buffer */
X        if ((bp=bfind(bufn, FALSE, 0)) == NULL) {
X		mlwrite("No such buffer");
X                return(FALSE);
X        }
X
X	/* and now execute it as asked */
X	while (n-- > 0)
X		if ((status = dobuf(bp)) != TRUE)
X			return(status);
X	return(TRUE);
X}
X
X/*	dobuf:	execute the contents of the buffer pointed to
X		by the passed BP				*/
X
Xdobuf(bp)
X
XBUFFER *bp;	/* buffer to execute */
X
X{
X        register int status;		/* status return */
X	register LINE *lp;		/* pointer to line to execute */
X	register LINE *hlp;		/* pointer to line header */
X	register LINE *glp;		/* line to goto */
X	register int linlen;		/* length of line to execute */
X	register WINDOW *wp;		/* ptr to windows to scan */
X	char *eline;			/* text of line to execute */
X
X	/* clear IF level flags */
X	execlevel = 0;
X
X	/* starting at the beginning of the buffer */
X	hlp = bp->b_linep;
X	lp = hlp->l_fp;
X	while (lp != hlp) {
X		/* allocate eline and copy macro line to it */
X		linlen = lp->l_used;
X		if ((eline = malloc(linlen+1)) == NULL) {
X			mlwrite("%%Out of Memory during macro execution");
X			return(FALSE);
X		}
X		strncpy(eline, lp->l_text, linlen);
X		eline[linlen] = 0;	/* make sure it ends */
X
X		/* trim leading whitespace */
X		while (eline[0] == ' ' || eline[0] == '\t')
X			strcpy(eline, &eline[1]);
X
X		/* if it is not a comment, execute it */
X		if (eline[0] != 0 && eline[0] != ';') {
X			status = docmd(eline);
X
X			/* if it is a !GOTO directive, deal with it */
X			if (status == GOLINE) {
X				linlen = strlen(golabel);
X				glp = hlp->l_fp;
X				while (glp != hlp) {
X					if (*glp->l_text == '*' &&
X					    (strncmp(&glp->l_text[1], golabel,
X					            linlen) == 0)) {
X						lp = glp;
X						status = TRUE;
X					}
X				glp = glp->l_fp;
X				}
X			}
X
X			if (status == GOLINE) {
X				mlwrite("%%No such label");
X				return(FALSE);
X			}
X
X			/* if it is a !RETURN directive...do so */
X			if (status == RET) {
X				free(eline);
X				break;
X			}
X
X			/* check for a command error */
X			if (status != TRUE) {
X				/* look if buffer is showing */
X				wp = wheadp;
X				while (wp != NULL) {
X					if (wp->w_bufp == bp) {
X						/* and point it */
X						wp->w_dotp = lp;
X						wp->w_doto = 0;
X						wp->w_flag |= WFHARD;
X					}
X					wp = wp->w_wndp;
X				}
X				/* in any case set the buffer . */
X				bp->b_dotp = lp;
X				bp->b_doto = 0;
X				free(eline);
X				execlevel = 0;
X				return(status);
X			}
X		}
X
X		/* on to the next line */
X		free(eline);
X		lp = lp->l_fp;
X	}
X
X	/* exit the current function */
X	execlevel = 0;
X        return(TRUE);
X}
X
Xexecfile(f, n)	/* execute a series of commands in a file
X*/
X
Xint f, n;	/* default flag and numeric arg to pass on to file */
X
X{
X	register int status;	/* return status of name query */
X	char *fname[NSTRING];	/* name of file to execute */
X
X	if ((status = mlreply("File to execute: ", fname, NSTRING -1)) != TRUE)
X		return(status);
X
X	/* otherwise, execute it */
X	while (n-- > 0)
X		if ((status=dofile(fname)) != TRUE)
X			return(status);
X
X	return(TRUE);
X}
X
X/*	dofile:	yank a file into a buffer and execute it
X		if there are no errors, delete the buffer on exit */
X
Xdofile(fname)
X
Xchar *fname;	/* file name to execute */
X
X{
X	register BUFFER *bp;	/* buffer to place file to exeute */
X	register BUFFER *cb;	/* temp to hold current buf while we read */
X	register int status;	/* results of various calls */
X	char bname[NBUFN];	/* name of buffer */
X
X	makename(bname, fname);		/* derive the name of the buffer */
X	if ((bp = bfind(bname, TRUE, 0)) == NULL) /* get the needed buffer */
X		return(FALSE);
X
X	bp->b_mode = MDVIEW;	/* mark the buffer as read only */
X	cb = curbp;		/* save the old buffer */
X	curbp = bp;		/* make this one current */
X	/* and try to read in the file to execute */
X	if ((status = readin(fname, FALSE)) != TRUE) {
X		curbp = cb;	/* restore the current buffer */
X		return(status);
X	}
X
X	/* go execute it! */
X	curbp = cb;		/* restore the current buffer */
X	if ((status = dobuf(bp)) != TRUE)
X		return(status);
X
X	/* if not displayed, remove the now unneeded buffer and exit */
X	if (bp->b_nwnd == 0)
X		zotbuf(bp);
X	return(TRUE);
X}
X
X/*	cbuf:	Execute the contents of a numbered buffer	*/
X
Xcbuf(f, n, bufnum)
X
Xint f, n;	/* default flag and numeric arg */
Xint bufnum;	/* number of buffer to execute */
X
X{
X        register BUFFER *bp;		/* ptr to buffer to execute */
X        register int status;		/* status return */
X	static char bufname[] = "[Macro xx]";
X
X	/* make the buffer name */
X	bufname[7] = '0' + (bufnum / 10);
X	bufname[8] = '0' + (bufnum % 10);
X
X	/* find the pointer to that buffer */
X        if ((bp=bfind(bufname, FALSE, 0)) == NULL) {
X        	mlwrite("Macro not defined");
X                return(FALSE);
X        }
X
X	/* and now execute it as asked */
X	while (n-- > 0)
X		if ((status = dobuf(bp)) != TRUE)
X			return(status);
X	return(TRUE);
X}
X
Xcbuf1(f, n)
X
X{
X	cbuf(f, n, 1);
X}
X
Xcbuf2(f, n)
X
X{
X	cbuf(f, n, 2);
X}
X
Xcbuf3(f, n)
X
X{
X	cbuf(f, n, 3);
X}
X
Xcbuf4(f, n)
X
X{
X	cbuf(f, n, 4);
X}
X
Xcbuf5(f, n)
X
X{
X	cbuf(f, n, 5);
X}
X
Xcbuf6(f, n)
X
X{
X	cbuf(f, n, 6);
X}
X
Xcbuf7(f, n)
X
X{
X	cbuf(f, n, 7);
X}
X
Xcbuf8(f, n)
X
X{
X	cbuf(f, n, 8);
X}
X
Xcbuf9(f, n)
X
X{
X	cbuf(f, n, 9);
X}
X
Xcbuf10(f, n)
X
X{
X	cbuf(f, n, 10);
X}
X
Xcbuf11(f, n)
X
X{
X	cbuf(f, n, 11);
X}
X
Xcbuf12(f, n)
X
X{
X	cbuf(f, n, 12);
X}
X
Xcbuf13(f, n)
X
X{
X	cbuf(f, n, 13);
X}
X
Xcbuf14(f, n)
X
X{
X	cbuf(f, n, 14);
X}
X
Xcbuf15(f, n)
X
X{
X	cbuf(f, n, 15);
X}
X
Xcbuf16(f, n)
X
X{
X	cbuf(f, n, 16);
X}
X
Xcbuf17(f, n)
X
X{
X	cbuf(f, n, 17);
X}
X
Xcbuf18(f, n)
X
X{
X	cbuf(f, n, 18);
X}
X
Xcbuf19(f, n)
X
X{
X	cbuf(f, n, 19);
X}
X
Xcbuf20(f, n)
X
X{
X	cbuf(f, n, 20);
X}
X
Xcbuf21(f, n)
X
X{
X	cbuf(f, n, 21);
X}
X
Xcbuf22(f, n)
X
X{
X	cbuf(f, n, 22);
X}
X
Xcbuf23(f, n)
X
X{
X	cbuf(f, n, 23);
X}
X
Xcbuf24(f, n)
X
X{
X	cbuf(f, n, 24);
X}
X
Xcbuf25(f, n)
X
X{
X	cbuf(f, n, 25);
X}
X
Xcbuf26(f, n)
X
X{
X	cbuf(f, n, 26);
X}
X
Xcbuf27(f, n)
X
X{
X	cbuf(f, n, 27);
X}
X
Xcbuf28(f, n)
X
X{
X	cbuf(f, n, 28);
X}
X
Xcbuf29(f, n)
X
X{
X	cbuf(f, n, 29);
X}
X
Xcbuf30(f, n)
X
X{
X	cbuf(f, n, 30);
X}
X
Xcbuf31(f, n)
X
X{
X	cbuf(f, n, 31);
X}
X
Xcbuf32(f, n)
X
X{
X	cbuf(f, n, 32);
X}
X
Xcbuf33(f, n)
X
X{
X	cbuf(f, n, 33);
X}
X
Xcbuf34(f, n)
X
X{
X	cbuf(f, n, 34);
X}
X
Xcbuf35(f, n)
X
X{
X	cbuf(f, n, 35);
X}
X
Xcbuf36(f, n)
X
X{
X	cbuf(f, n, 36);
X}
X
Xcbuf37(f, n)
X
X{
X	cbuf(f, n, 37);
X}
X
Xcbuf38(f, n)
X
X{
X	cbuf(f, n, 38);
X}
X
Xcbuf39(f, n)
X
X{
X	cbuf(f, n, 39);
X}
X
Xcbuf40(f, n)
X
X{
X	cbuf(f, n, 40);
X}
X
X
END_OF_exec.c
if test 16413 -ne `wc -c <exec.c`; then
    echo shar: \"exec.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: Extracting \"spawn.c\" \(16459 characters\)
if test -f spawn.c ; then 
  echo shar: Will not over-write existing file \"spawn.c\"
else
sed "s/^X//" >spawn.c <<'END_OF_spawn.c'
X/*	Spawn:	various DOS access commands
X		for MicroEMACS
X*/
X
X#include        <stdio.h>
X#include	"estruct.h"
X#include        "edef.h"
X
X#if     AMIGA
X#define  NEW   1006
X#endif
X
X#if		ST520
X#include <osbind.h>
X#include <string.h>
X#define LOAD_EXEC 0 	/* load and execute the program */
Xchar	*STcmd,		/* the command filename & path  */
X	*STargs,	/* command args (if any)        */
X	*STenv,		/* environment                  */
X	*STwork;	/* work area			*/
X#endif
X
X#if     VMS
X#define EFN     0                               /* Event flag.          */
X
X#include        <ssdef.h>                       /* Random headers.      */
X#include        <stsdef.h>
X#include        <descrip.h>
X#include        <iodef.h>
X
Xextern  int     oldmode[3];                     /* In "termio.c"        */
Xextern  int     newmode[3];                     /* In "termio.c"        */
Xextern  short   iochan;                         /* In "termio.c"        */
X#endif
X
X#if     V7 | USG | BSD
X#include        <signal.h>
Xextern int vttidy();
X#endif
X
X#if	MSDOS & MSC
X#include	<process.h>
X#define	system(a)	spawnlp(P_WAIT, a, NULL)
X#endif
X
X/*
X * Create a subjob with a copy of the command intrepreter in it. When the
X * command interpreter exits, mark the screen as garbage so that you do a full
X * repaint. Bound to "^X C". The message at the start in VMS puts out a newline.
X * Under some (unknown) condition, you don't get one free when DCL starts up.
X */
Xspawncli(f, n)
X{
X#if     AMIGA
X        long newcli;
X#endif
X
X#if     V7 | USG | BSD
X        register char *cp;
X        char    *getenv();
X#endif
X
X	/* don't allow this command if restricted */
X	if (restflag)
X		return(resterr());
X
X#if	AMIGA
X        newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW);
X        mlwrite("[Starting new CLI]");
X        sgarbf = TRUE;
X        Execute("", newcli, 0);
X        Close(newcli);
X        return(TRUE);
X#endif
X
X#if     VMS
X        movecursor(term.t_nrow, 0);             /* In last line.        */
X        mlputs("[Starting DCL]\r\n");
X        TTflush(); 	                     /* Ignore "ttcol".      */
X        sgarbf = TRUE;
X        return (sys(NULL));                     /* NULL => DCL.         */
X#endif
X#if     CPM
X        mlwrite("Not in CP/M-86");
X#endif
X#if	ST520
X	mlwrite("Not in TOS");
X#endif
X#if     MSDOS & AZTEC
X        movecursor(term.t_nrow, 0);             /* Seek to last line.   */
X        TTflush();
X	TTkclose();
X	system("command.com");
X	TTkopen();
X        sgarbf = TRUE;
X        return(TRUE);
X#endif
X#if     MSDOS & LATTICE
X        movecursor(term.t_nrow, 0);             /* Seek to last line.   */
X        TTflush();
X	TTkclose();
X        sys("\\command.com", "");               /* Run CLI.             */
X	TTkopen();
X        sgarbf = TRUE;
X        return(TRUE);
X#endif
X#if     V7 | USG | BSD
X        movecursor(term.t_nrow, 0);             /* Seek to last line.   */
X        TTflush();
X        TTclose();                              /* stty to old settings */
X        if ((cp = getenv("SHELL")) != NULL && *cp != '\0')
X                system(cp);
X        else
X#if	BSD
X                system("exec /bin/csh");
X#else
X                system("exec /bin/sh");
X#endif
X        sgarbf = TRUE;
X        sleep(2);
X        TTopen();
X        return(TRUE);
X#endif
X}
X
X#if	BSD
X
Xbktoshell()		/* suspend MicroEMACS and wait to wake up */
X{
X	int pid;
X
X	vttidy();
X	pid = getpid();
X	kill(pid,SIGTSTP);
X}
X
Xrtfrmshell()
X{
X	TTopen();
X	curwp->w_flag = WFHARD;
X	sgarbf = TRUE;
X}
X#endif
X
X/*
X * Run a one-liner in a subjob. When the command returns, wait for a single
X * character to be typed, then mark the screen as garbage so a full repaint is
X * done. Bound to "C-X !".
X */
Xspawn(f, n)
X{
X        register int    s;
X        char            line[NLINE];
X
X#if	ST520
X	int i,j,k;
X	char *sptr,*tptr;
X#endif
X
X#if     AMIGA
X        long newcli;
X#endif
X
X	/* don't allow this command if restricted */
X	if (restflag)
X		return(resterr());
X
X#if	AMIGA
X        if ((s=mlreply("!", line, NLINE)) != TRUE)
X                return (s);
X        newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW);
X        Execute(line,0,newcli);
X        Close(newcli);
X        tgetc();     /* Pause.               */
X        sgarbf = TRUE;
X        return(TRUE);
X#endif
X#if     ST520
X        if ((s=mlreply("!", line, NLINE)) != TRUE)
X                return(s);
X	movecursor(term.t_nrow - 1, 0);
X	TTclose();
X/*
X * break the line into the command and its args
X * be cute about it, if there is no '.' in the filename, try
X * to find .prg, .tos or .ttp in that order
X * in any case check to see that the file exists before we run 
X * amok
X */
X	STenv = NULL;
X	if((tptr = index(&line[0],' ')) == NULL) { /* no args */
X		STcmd = (char *)malloc(strlen(line) + 1);
X		strcpy(STcmd,line);
X		STargs = NULL;
X	}
X	else {  /* seperate out the args from the command */
X		/* resist the temptation to do ptr arithmetic */
X		STcmd = (char *)malloc(strlen(line) + 1);
X		for(i = 0,sptr = &line[0]; sptr != tptr; sptr++,i++)
X			STcmd[i] = *sptr;
X		STcmd[i] = '\0';
X		for(; *tptr == ' ' || *tptr == '\t'; tptr++);
X		if(*tptr == '\0')
X			STargs = NULL;
X		else {
X			STargs = (char *)malloc(strlen(tptr) + 2);
X/* first byte of STargs is the length of the string */
X			STargs[0] = strlen(tptr);
X			STargs[1] = NULL; /* fake it for strcat */
X			strcat(STargs,tptr);
X		}
X	}
X/*
X * before we issue the command look for the '.', if it's not there
X * try adding .prg, .tos and .ttp to see if they exist, if not
X * issue the command as is
X */
X	if((tptr = index(STcmd,'.')) == NULL) {
X 		STwork = (char *)malloc(strlen(STcmd) + 4);
X 		strcpy(STwork,STcmd);
X 		strcat(STwork,".prg");
X 		tptr = index(STwork,'.');
X 		if(Fsfirst(1,STwork) != 0) { /* try .tos */
X 			strcpy(tptr,".tos");
X 			if(Fsfirst(1,STwork) != 0) { /* try .ttp */
X 				strcpy(tptr,".ttp");
X 				if(Fsfirst(1,STwork) != 0) /* never mind */
X 					*STwork = NULL;
X 				}
X 			}
X 	}
X 	if(*STwork != NULL)
X	        Pexec(LOAD_EXEC,STwork,STargs,STenv); 		
X	else
X	        Pexec(LOAD_EXEC,STcmd,STargs,STenv);
X	TTopen();
X        mlputs("\r\n\n[End]");                  /* Pause.               */
X        TTgetc();			     /* Pause.               */
X        sgarbf = TRUE;
X        return (TRUE);
X#endif
X#if     VMS
X        if ((s=mlreply("!", line, NLINE)) != TRUE)
X                return (s);
X        TTputc('\n');                /* Already have '\r'    */
X        TTflush();
X        s = sys(line);                          /* Run the command.     */
X        mlputs("\r\n\n[End]");                  /* Pause.               */
X        TTflush();
X        tgetc();
X        sgarbf = TRUE;
X        return (s);
X#endif
X#if     CPM
X        mlwrite("Not in CP/M-86");
X        return (FALSE);
X#endif
X#if     MSDOS
X        if ((s=mlreply("!", line, NLINE)) != TRUE)
X                return(s);
X	movecursor(term.t_nrow - 1, 0);
X	TTkclose();
X        system(line);
X	TTkopen();
X	/* if we are interactive, pause here */
X	if (clexec == FALSE) {
X	        mlputs("\r\n\n[End]");
X        	tgetc();
X        }
X        sgarbf = TRUE;
X        return (TRUE);
X#endif
X#if     V7 | USG | BSD
X        if ((s=mlreply("!", line, NLINE)) != TRUE)
X                return (s);
X        TTputc('\n');                /* Already have '\r'    */
X        TTflush();
X        TTclose();                              /* stty to old modes    */
X        system(line);
X        TTopen();
X        mlputs("[End]");                        /* Pause.               */
X        TTflush();
X        while ((s = tgetc()) != '\r' && s != ' ')
X                ;
X        sgarbf = TRUE;
X        return (TRUE);
X#endif
X}
X
X/*
X * Pipe a one line command into a window
X * Bound to ^X @
X */
Xpipe(f, n)
X{
X        register int    s;	/* return status from CLI */
X	register WINDOW *wp;	/* pointer to new window */
X	register BUFFER *bp;	/* pointer to buffer to zot */
X        char	line[NLINE];	/* command line send to shell */
X	static char bname[] = "command";
X
X#if	AMIGA
X	static char filnam[] = "ram:command";
X        long newcli;
X#else
X	static char filnam[] = "command";
X#endif
X
X#if	MSDOS
X	char *tmp;
X	char *getenv();
X	FILE *fp;
X	FILE *fopen();
X#endif
X
X	/* don't allow this command if restricted */
X	if (restflag)
X		return(resterr());
X
X#if	MSDOS
X	if ((tmp = getenv("TMP")) == NULL)
X		strcpy(filnam, "command");
X	else
X		strcpy(filnam, tmp);
X#endif
X
X#if     VMS
X	mlwrite("Not availible under VMS");
X	return(FALSE);
X#endif
X#if     CPM
X        mlwrite("Not availible under CP/M-86");
X        return(FALSE);
X#endif
X
X	/* get the command to pipe in */
X        if ((s=mlreply("@", line, NLINE)) != TRUE)
X                return(s);
X
X	/* get rid of the command output buffer if it exists */
X        if ((bp=bfind(bname, FALSE, 0)) != FALSE) {
X		/* try to make sure we are off screen */
X		wp = wheadp;
X		while (wp != NULL) {
X			if (wp->w_bufp == bp) {
X				onlywind(FALSE, 1);
X				break;
X			}
X			wp = wp->w_wndp;
X		}
X		if (zotbuf(bp) != TRUE)
X			return(FALSE);
X	}
X
X#if     AMIGA
X        newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW);
X	strcat(line, " >");
X	strcat(line, filnam);
X        Execute(line,0,newcli);
X	s = TRUE;
X        Close(newcli);
X        sgarbf = TRUE;
X#endif
X#if     MSDOS
X	strcat(line," >>");
X	strcat(line,filnam);
X	movecursor(term.t_nrow - 1, 0);
X	TTkclose();
X        system(line);
X	TTkopen();
X        sgarbf = TRUE;
X	if ((fp = fopen(filnam, "r")) == NULL) {
X		s = FALSE;
X	} else {
X		fclose(fp);
X		s = TRUE;
X	}
X#endif
X#if     V7 | USG | BSD
X        TTputc('\n');                /* Already have '\r'    */
X        TTflush();
X        TTclose();                              /* stty to old modes    */
X	strcat(line,">");
X	strcat(line,filnam);
X        system(line);
X        TTopen();
X        TTflush();
X        sgarbf = TRUE;
X        s = TRUE;
X#endif
X
X	if (s != TRUE)
X		return(s);
X
X	/* split the current window to make room for the command output */
X	if (splitwind(FALSE, 1) == FALSE)
X			return(FALSE);
X
X	/* and read the stuff in */
X	if (getfile(filnam, FALSE) == FALSE)
X		return(FALSE);
X
X	/* make this window in VIEW mode, update all mode lines */
X	curwp->w_bufp->b_mode |= MDVIEW;
X	wp = wheadp;
X	while (wp != NULL) {
X		wp->w_flag |= WFMODE;
X		wp = wp->w_wndp;
X	}
X
X	/* and get rid of the temporary file */
X	unlink(filnam);
X	return(TRUE);
X}
X
X/*
X * filter a buffer through an external DOS program
X * Bound to ^X #
X */
Xfilter(f, n)
X
X{
X        register int    s;	/* return status from CLI */
X	register BUFFER *bp;	/* pointer to buffer to zot */
X        char line[NLINE];	/* command line send to shell */
X	char tmpnam[NFILEN];	/* place to store real file name */
X	static char bname1[] = "fltinp";
X
X#if	AMIGA
X	static char filnam1[] = "ram:fltinp";
X	static char filnam2[] = "ram:fltout";
X        long newcli;
X#else
X	static char filnam1[] = "fltinp";
X	static char filnam2[] = "fltout";
X#endif
X
X	/* don't allow this command if restricted */
X	if (restflag)
X		return(resterr());
X
X	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
X		return(rdonly());	/* we are in read only mode	*/
X
X#if     VMS
X	mlwrite("Not availible under VMS");
X	return(FALSE);
X#endif
X#if     CPM
X        mlwrite("Not availible under CP/M-86");
X        return(FALSE);
X#endif
X
X	/* get the filter name and its args */
X        if ((s=mlreply("#", line, NLINE)) != TRUE)
X                return(s);
X
X	/* setup the proper file names */
X	bp = curbp;
X	strcpy(tmpnam, bp->b_fname);	/* save the original name */
X	strcpy(bp->b_fname, bname1);	/* set it to our new one */
X
X	/* write it out, checking for errors */
X	if (writeout(filnam1) != TRUE) {
X		mlwrite("[Cannot write filter file]");
X		strcpy(bp->b_fname, tmpnam);
X		return(FALSE);
X	}
X
X#if     AMIGA
X        newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW);
X	strcat(line, " <ram:fltinp >ram:fltout");
X        Execute(line,0,newcli);
X	s = TRUE;
X        Close(newcli);
X        sgarbf = TRUE;
X#endif
X#if     MSDOS
X	strcat(line," <fltinp >fltout");
X	movecursor(term.t_nrow - 1, 0);
X	TTkclose();
X        system(line);
X	TTkopen();
X        sgarbf = TRUE;
X	s = TRUE;
X#endif
X#if     V7 | USG | BSD
X        TTputc('\n');                /* Already have '\r'    */
X        TTflush();
X        TTclose();                              /* stty to old modes    */
X	strcat(line," <fltinp >fltout");
X        system(line);
X        TTopen();
X        TTflush();
X        sgarbf = TRUE;
X        s = TRUE;
X#endif
X
X	/* on failure, escape gracefully */
X	if (s != TRUE || (readin(filnam2,FALSE) == FALSE)) {
X		mlwrite("[Execution failed]");
X		strcpy(bp->b_fname, tmpnam);
X		unlink(filnam1);
X		unlink(filnam2);
X		return(s);
X	}
X
X	/* reset file name */
X	strcpy(bp->b_fname, tmpnam);	/* restore name */
X	bp->b_flag |= BFCHG;		/* flag it as changed */
X
X	/* and get rid of the temporary file */
X	unlink(filnam1);
X	unlink(filnam2);
X	return(TRUE);
X}
X
X#if     VMS
X/*
X * Run a command. The "cmd" is a pointer to a command string, or NULL if you
X * want to run a copy of DCL in the subjob (this is how the standard routine
X * LIB$SPAWN works. You have to do wierd stuff with the terminal on the way in
X * and the way out, because DCL does not want the channel to be in raw mode.
X */
Xsys(cmd)
Xregister char   *cmd;
X{
X        struct  dsc$descriptor  cdsc;
X        struct  dsc$descriptor  *cdscp;
X        long    status;
X        long    substatus;
X        long    iosb[2];
X
X        status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
X                          oldmode, sizeof(oldmode), 0, 0, 0, 0);
X        if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
X                return (FALSE);
X        cdscp = NULL;                           /* Assume DCL.          */
X        if (cmd != NULL) {                      /* Build descriptor.    */
X                cdsc.dsc$a_pointer = cmd;
X                cdsc.dsc$w_length  = strlen(cmd);
X                cdsc.dsc$b_dtype   = DSC$K_DTYPE_T;
X                cdsc.dsc$b_class   = DSC$K_CLASS_S;
X                cdscp = &cdsc;
X        }
X        status = LIB$SPAWN(cdscp, 0, 0, 0, 0, 0, &substatus, 0, 0, 0);
X        if (status != SS$_NORMAL)
X                substatus = status;
X        status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
X                          newmode, sizeof(newmode), 0, 0, 0, 0);
X        if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
X                return (FALSE);
X        if ((substatus&STS$M_SUCCESS) == 0)     /* Command failed.      */
X                return (FALSE);
X        return (TRUE);
X}
X#endif
X
X#if	~AZTEC & MSDOS
X
X/*
X * This routine, once again by Bob McNamara, is a C translation of the "system"
X * routine in the MWC-86 run time library. It differs from the "system" routine
X * in that it does not unconditionally append the string ".exe" to the end of
X * the command name. We needed to do this because we want to be able to spawn
X * off "command.com". We really do not understand what it does, but if you don't
X * do it exactly "malloc" starts doing very very strange things.
X */
Xsys(cmd, tail)
Xchar    *cmd;
Xchar    *tail;
X{
X#if MWC_86
X        register unsigned n;
X        extern   char     *__end;
X
X        n = __end + 15;
X        n >>= 4;
X        n = ((n + dsreg() + 16) & 0xFFF0) + 16;
X        return(execall(cmd, tail, n));
X#endif
X
X#if LATTICE
X        return(forklp(cmd, tail, (char *)NULL));
X#endif
X
X#if	MSC
X	return(spawnlp(P_WAIT, cmd, tail, NULL));
X#endif
X}
X#endif
X
X#if	MSDOS & LATTICE
X/*	System: a modified version of lattice's system() function
X		that detects the proper switchar and uses it
X		written by Dana Hogget				*/
X
Xsystem(cmd)
X
Xchar *cmd;	/*  Incoming command line to execute  */
X
X{
X	char *getenv();
X	static char *swchar = "/C";	/*  Execution switch  */
X	union REGS inregs;	/*  parameters for dos call  */
X	union REGS outregs;	/*  Return results from dos call  */
X	char *shell;		/*  Name of system command processor  */
X	char *p;		/*  Temporary pointer  */
X	int ferr;		/*  Error condition if any  */
X
X	/*  get name of system shell  */
X	if ((shell = getenv("COMSPEC")) == NULL) {
X		return (-1);		/*  No shell located  */
X	}
X
X	p = cmd;
X	while (isspace(*p)) {		/*  find out if null command */
X		p++;
X	}
X
X	/**  If the command line is not empty, bring up the shell  **/
X	/**  and execute the command.  Otherwise, bring up the     **/
X	/**  shell in interactive mode.   **/
X
X	if (p && *p) {
X		/**  detect current switch character and us it  **/
X		inregs.h.ah = 0x37;	/*  get setting data  */
X		inregs.h.al = 0x00;	/*  get switch character  */
X		intdos(&inregs, &outregs);
X		*swchar = outregs.h.dl;
X		ferr = forkl(shell, "command", swchar, cmd, (char *)NULL);
X	} else {
X		ferr = forkl(shell, "command", (char *)NULL);
X	}
X
X	return (ferr ? ferr : wait());
X}
X#endif
X
END_OF_spawn.c
if test 16459 -ne `wc -c <spawn.c`; then
    echo shar: \"spawn.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: Extracting \"window.c\" \(18023 characters\)
if test -f window.c ; then 
  echo shar: Will not over-write existing file \"window.c\"
else
sed "s/^X//" >window.c <<'END_OF_window.c'
X/*
X * Window management. Some of the functions are internal, and some are
X * attached to keys that the user actually types.
X */
X
X#include        <stdio.h>
X#include        "estruct.h"
X#include	"edef.h"
X
X#if	MEGAMAX & ST520
Xoverlay	"window"
X#endif
X
X/*
X * Reposition dot in the current window to line "n". If the argument is
X * positive, it is that line. If it is negative it is that line from the
X * bottom. If it is 0 the window is centered (this is what the standard
X * redisplay code does). With no argument it defaults to 0. Bound to M-!.
X */
Xreposition(f, n)
X    {
X    if (f == FALSE)	/* default to 0 to center screen */
X	n = 0;
X    curwp->w_force = n;
X    curwp->w_flag |= WFFORCE;
X    return (TRUE);
X    }
X
X/*
X * Refresh the screen. With no argument, it just does the refresh. With an
X * argument it recenters "." in the current window. Bound to "C-L".
X */
Xrefresh(f, n)
X    {
X    if (f == FALSE)
X        sgarbf = TRUE;
X    else
X        {
X        curwp->w_force = 0;             /* Center dot. */
X        curwp->w_flag |= WFFORCE;
X        }
X
X    return (TRUE);
X    }
X
X/*
X * The command make the next window (next => down the screen) the current
X * window. There are no real errors, although the command does nothing if
X * there is only 1 window on the screen. Bound to "C-X C-N".
X *
X * with an argument this command finds the <n>th window from the top
X *
X */
Xnextwind(f, n)
X
Xint f, n;	/* default flag and numeric argument */
X
X{
X	register WINDOW *wp;
X	register int nwindows;		/* total number of windows */
X
X	if (f) {
X
X		/* first count the # of windows */
X		wp = wheadp;
X		nwindows = 1;
X		while (wp->w_wndp != NULL) {
X			nwindows++;
X			wp = wp->w_wndp;
X		}
X
X		/* if the argument is negative, it is the nth window
X		   from the bottom of the screen			*/
X		if (n < 0)
X			n = nwindows + n + 1;
X
X		/* if an argument, give them that window from the top */
X		if (n > 0 && n <= nwindows) {
X			wp = wheadp;
X			while (--n)
X				wp = wp->w_wndp;
X		} else {
X			mlwrite("Window number out of range");
X			return(FALSE);
X		}
X	} else
X		if ((wp = curwp->w_wndp) == NULL)
X			wp = wheadp;
X	curwp = wp;
X	curbp = wp->w_bufp;
X	upmode();
X	return (TRUE);
X}
X
X/*
X * This command makes the previous window (previous => up the screen) the
X * current window. There arn't any errors, although the command does not do a
X * lot if there is 1 window.
X */
Xprevwind(f, n)
X{
X	register WINDOW *wp1;
X	register WINDOW *wp2;
X
X	/* if we have an argument, we mean the nth window from the bottom */
X	if (f)
X		return(nextwind(f, -n));
X
X	wp1 = wheadp;
X	wp2 = curwp;
X
X	if (wp1 == wp2)
X		wp2 = NULL;
X
X	while (wp1->w_wndp != wp2)
X		wp1 = wp1->w_wndp;
X
X	curwp = wp1;
X	curbp = wp1->w_bufp;
X	upmode();
X	return (TRUE);
X}
X
X/*
X * This command moves the current window down by "arg" lines. Recompute the
X * top line in the window. The move up and move down code is almost completely
X * the same; most of the work has to do with reframing the window, and picking
X * a new dot. We share the code by having "move down" just be an interface to
X * "move up". Magic. Bound to "C-X C-N".
X */
Xmvdnwind(f, n)
X
Xint n;
X
X{
X	return (mvupwind(f, -n));
X}
X
X/*
X * Move the current window up by "arg" lines. Recompute the new top line of
X * the window. Look to see if "." is still on the screen. If it is, you win.
X * If it isn't, then move "." to center it in the new framing of the window
X * (this command does not really move "."; it moves the frame). Bound to
X * "C-X C-P".
X */
Xmvupwind(f, n)
X    int n;
X    {
X    register LINE *lp;
X    register int i;
X
X    lp = curwp->w_linep;
X
X    if (n < 0)
X        {
X        while (n++ && lp!=curbp->b_linep)
X            lp = lforw(lp);
X        }
X    else
X        {
X        while (n-- && lback(lp)!=curbp->b_linep)
X            lp = lback(lp);
X        }
X
X    curwp->w_linep = lp;
X    curwp->w_flag |= WFHARD;            /* Mode line is OK. */
X
X    for (i = 0; i < curwp->w_ntrows; ++i)
X        {
X        if (lp == curwp->w_dotp)
X            return (TRUE);
X        if (lp == curbp->b_linep)
X            break;
X        lp = lforw(lp);
X        }
X
X    lp = curwp->w_linep;
X    i  = curwp->w_ntrows/2;
X
X    while (i-- && lp != curbp->b_linep)
X        lp = lforw(lp);
X
X    curwp->w_dotp  = lp;
X    curwp->w_doto  = 0;
X    return (TRUE);
X    }
X
X/*
X * This command makes the current window the only window on the screen. Bound
X * to "C-X 1". Try to set the framing so that "." does not have to move on the
X * display. Some care has to be taken to keep the values of dot and mark in
X * the buffer structures right if the distruction of a window makes a buffer
X * become undisplayed.
X */
Xonlywind(f, n)
X{
X        register WINDOW *wp;
X        register LINE   *lp;
X        register int    i;
X
X        while (wheadp != curwp) {
X                wp = wheadp;
X                wheadp = wp->w_wndp;
X                if (--wp->w_bufp->b_nwnd == 0) {
X                        wp->w_bufp->b_dotp  = wp->w_dotp;
X                        wp->w_bufp->b_doto  = wp->w_doto;
X                        wp->w_bufp->b_markp = wp->w_markp;
X                        wp->w_bufp->b_marko = wp->w_marko;
X                }
X                free((char *) wp);
X        }
X        while (curwp->w_wndp != NULL) {
X                wp = curwp->w_wndp;
X                curwp->w_wndp = wp->w_wndp;
X                if (--wp->w_bufp->b_nwnd == 0) {
X                        wp->w_bufp->b_dotp  = wp->w_dotp;
X                        wp->w_bufp->b_doto  = wp->w_doto;
X                        wp->w_bufp->b_markp = wp->w_markp;
X                        wp->w_bufp->b_marko = wp->w_marko;
X                }
X                free((char *) wp);
X        }
X        lp = curwp->w_linep;
X        i  = curwp->w_toprow;
X        while (i!=0 && lback(lp)!=curbp->b_linep) {
X                --i;
X                lp = lback(lp);
X        }
X        curwp->w_toprow = 0;
X        curwp->w_ntrows = term.t_nrow-1;
X        curwp->w_linep  = lp;
X        curwp->w_flag  |= WFMODE|WFHARD;
X        return (TRUE);
X}
X
X/*
X * Delete the current window, placing its space in the window above,
X * or, if it is the top window, the window below. Bound to C-X 0.
X */
X
Xdelwind(f,n)
X
Xint f, n;	/* arguments are ignored for this command */
X
X{
X	register WINDOW *wp;	/* window to recieve deleted space */
X	register WINDOW *lwp;	/* ptr window before curwp */
X	register int target;	/* target line to search for */
X
X	/* if there is only one window, don't delete it */
X	if (wheadp->w_wndp == NULL) {
X		mlwrite("Can not delete this window");
X		return(FALSE);
X	}
X
X	/* find window before curwp in linked list */
X	wp = wheadp;
X	lwp = NULL;
X	while (wp != NULL) {
X		if (wp == curwp)
X			break;
X		lwp = wp;
X		wp = wp->w_wndp;
X	}
X
X	/* find recieving window and give up our space */
X	wp = wheadp;
X	if (curwp->w_toprow == 0) {
X		/* find the next window down */
X		target = curwp->w_ntrows + 1;
X		while (wp != NULL) {
X			if (wp->w_toprow == target)
X				break;
X			wp = wp->w_wndp;
X		}
X		if (wp == NULL)
X			return(FALSE);
X		wp->w_toprow = 0;
X		wp->w_ntrows += target;
X	} else {
X		/* find the next window up */
X		target = curwp->w_toprow - 1;
X		while (wp != NULL) {
X			if ((wp->w_toprow + wp->w_ntrows) == target)
X				break;
X			wp = wp->w_wndp;
X		}
X		if (wp == NULL)
X			return(FALSE);
X		wp->w_ntrows += 1 + curwp->w_ntrows;
X	}
X
X	/* get rid of the current window */
X	if (--curwp->w_bufp->b_nwnd == 0) {
X		curwp->w_bufp->b_dotp = curwp->w_dotp;
X		curwp->w_bufp->b_doto = curwp->w_doto;
X		curwp->w_bufp->b_markp = curwp->w_markp;
X		curwp->w_bufp->b_marko = curwp->w_marko;
X	}
X	if (lwp == NULL)
X		wheadp = curwp->w_wndp;
X	else
X		lwp->w_wndp = curwp->w_wndp;
X	free((char *)curwp);
X	curwp = wp;
X	wp->w_flag |= WFHARD;
X	curbp = wp->w_bufp;
X	upmode();
X	return(TRUE);
X}
X
X/*
X
XSplit the current window.  A window smaller than 3 lines cannot be
Xsplit.  An argument of 1 forces the cursor into the upper window, an
Xargument of two forces the cursor to the lower window.  The only other
Xerror that is possible is a "malloc" failure allocating the structure
Xfor the new window.  Bound to "C-X 2". 
X
X */
Xsplitwind(f, n)
X
Xint f, n;	/* default flag and numeric argument */
X
X{
X        register WINDOW *wp;
X        register LINE   *lp;
X        register int    ntru;
X        register int    ntrl;
X        register int    ntrd;
X        register WINDOW *wp1;
X        register WINDOW *wp2;
X	char *malloc();
X
X        if (curwp->w_ntrows < 3) {
X                mlwrite("Cannot split a %d line window", curwp->w_ntrows);
X                return (FALSE);
X        }
X        if ((wp = (WINDOW *) malloc(sizeof(WINDOW))) == NULL) {
X                mlwrite("Cannot allocate WINDOW block");
X                return (FALSE);
X        }
X        ++curbp->b_nwnd;                        /* Displayed twice.     */
X        wp->w_bufp  = curbp;
X        wp->w_dotp  = curwp->w_dotp;
X        wp->w_doto  = curwp->w_doto;
X        wp->w_markp = curwp->w_markp;
X        wp->w_marko = curwp->w_marko;
X        wp->w_flag  = 0;
X        wp->w_force = 0;
X#if	COLOR
X	/* set the colors of the new window */
X	wp->w_fcolor = gfcolor;
X	wp->w_bcolor = gbcolor;
X#endif
X        ntru = (curwp->w_ntrows-1) / 2;         /* Upper size           */
X        ntrl = (curwp->w_ntrows-1) - ntru;      /* Lower size           */
X        lp = curwp->w_linep;
X        ntrd = 0;
X        while (lp != curwp->w_dotp) {
X                ++ntrd;
X                lp = lforw(lp);
X        }
X        lp = curwp->w_linep;
X        if (((f == FALSE) && (ntrd <= ntru)) || ((f == TRUE) && (n == 1))) {
X                /* Old is upper window. */
X                if (ntrd == ntru)               /* Hit mode line.       */
X                        lp = lforw(lp);
X                curwp->w_ntrows = ntru;
X                wp->w_wndp = curwp->w_wndp;
X                curwp->w_wndp = wp;
X                wp->w_toprow = curwp->w_toprow+ntru+1;
X                wp->w_ntrows = ntrl;
X        } else {                                /* Old is lower window  */
X                wp1 = NULL;
X                wp2 = wheadp;
X                while (wp2 != curwp) {
X                        wp1 = wp2;
X                        wp2 = wp2->w_wndp;
X                }
X                if (wp1 == NULL)
X                        wheadp = wp;
X                else
X                        wp1->w_wndp = wp;
X                wp->w_wndp   = curwp;
X                wp->w_toprow = curwp->w_toprow;
X                wp->w_ntrows = ntru;
X                ++ntru;                         /* Mode line.           */
X                curwp->w_toprow += ntru;
X                curwp->w_ntrows  = ntrl;
X                while (ntru--)
X                        lp = lforw(lp);
X        }
X        curwp->w_linep = lp;                    /* Adjust the top lines */
X        wp->w_linep = lp;                       /* if necessary.        */
X        curwp->w_flag |= WFMODE|WFHARD;
X        wp->w_flag |= WFMODE|WFHARD;
X        return (TRUE);
X}
X
X/*
X * Enlarge the current window. Find the window that loses space. Make sure it
X * is big enough. If so, hack the window descriptions, and ask redisplay to do
X * all the hard work. You don't just set "force reframe" because dot would
X * move. Bound to "C-X Z".
X */
Xenlargewind(f, n)
X{
X        register WINDOW *adjwp;
X        register LINE   *lp;
X        register int    i;
X
X        if (n < 0)
X                return (shrinkwind(f, -n));
X        if (wheadp->w_wndp == NULL) {
X                mlwrite("Only one window");
X                return (FALSE);
X        }
X        if ((adjwp=curwp->w_wndp) == NULL) {
X                adjwp = wheadp;
X                while (adjwp->w_wndp != curwp)
X                        adjwp = adjwp->w_wndp;
X        }
X        if (adjwp->w_ntrows <= n) {
X                mlwrite("Impossible change");
X                return (FALSE);
X        }
X        if (curwp->w_wndp == adjwp) {           /* Shrink below.        */
X                lp = adjwp->w_linep;
X                for (i=0; i<n && lp!=adjwp->w_bufp->b_linep; ++i)
X                        lp = lforw(lp);
X                adjwp->w_linep  = lp;
X                adjwp->w_toprow += n;
X        } else {                                /* Shrink above.        */
X                lp = curwp->w_linep;
X                for (i=0; i<n && lback(lp)!=curbp->b_linep; ++i)
X                        lp = lback(lp);
X                curwp->w_linep  = lp;
X                curwp->w_toprow -= n;
X        }
X        curwp->w_ntrows += n;
X        adjwp->w_ntrows -= n;
X        curwp->w_flag |= WFMODE|WFHARD;
X        adjwp->w_flag |= WFMODE|WFHARD;
X        return (TRUE);
X}
X
X/*
X * Shrink the current window. Find the window that gains space. Hack at the
X * window descriptions. Ask the redisplay to do all the hard work. Bound to
X * "C-X C-Z".
X */
Xshrinkwind(f, n)
X{
X        register WINDOW *adjwp;
X        register LINE   *lp;
X        register int    i;
X
X        if (n < 0)
X                return (enlargewind(f, -n));
X        if (wheadp->w_wndp == NULL) {
X                mlwrite("Only one window");
X                return (FALSE);
X        }
X        if ((adjwp=curwp->w_wndp) == NULL) {
X                adjwp = wheadp;
X                while (adjwp->w_wndp != curwp)
X                        adjwp = adjwp->w_wndp;
X        }
X        if (curwp->w_ntrows <= n) {
X                mlwrite("Impossible change");
X                return (FALSE);
X        }
X        if (curwp->w_wndp == adjwp) {           /* Grow below.          */
X                lp = adjwp->w_linep;
X                for (i=0; i<n && lback(lp)!=adjwp->w_bufp->b_linep; ++i)
X                        lp = lback(lp);
X                adjwp->w_linep  = lp;
X                adjwp->w_toprow -= n;
X        } else {                                /* Grow above.          */
X                lp = curwp->w_linep;
X                for (i=0; i<n && lp!=curbp->b_linep; ++i)
X                        lp = lforw(lp);
X                curwp->w_linep  = lp;
X                curwp->w_toprow += n;
X        }
X        curwp->w_ntrows -= n;
X        adjwp->w_ntrows += n;
X        curwp->w_flag |= WFMODE|WFHARD;
X        adjwp->w_flag |= WFMODE|WFHARD;
X        return (TRUE);
X}
X
X/*	Resize the current window to the requested size	*/
X
Xresize(f, n)
X
Xint f, n;	/* default flag and numeric argument */
X
X{
X	int clines;	/* current # of lines in window */
X	
X	/* must have a non-default argument, else ignore call */
X	if (f == FALSE)
X		return(TRUE);
X
X	/* find out what to do */
X	clines = curwp->w_ntrows;
X
X	/* already the right size? */
X	if (clines == n)
X		return(TRUE);
X
X	return(enlargewind(TRUE, n - clines));
X}
X
X/*
X * Pick a window for a pop-up. Split the screen if there is only one window.
X * Pick the uppermost window that isn't the current window. An LRU algorithm
X * might be better. Return a pointer, or NULL on error.
X */
XWINDOW  *
Xwpopup()
X{
X        register WINDOW *wp;
X
X        if (wheadp->w_wndp == NULL              /* Only 1 window        */
X        && splitwind(FALSE, 0) == FALSE)        /* and it won't split   */
X                return (NULL);
X        wp = wheadp;                            /* Find window to use   */
X        while (wp!=NULL && wp==curwp)
X                wp = wp->w_wndp;
X        return (wp);
X}
X
Xscrnextup(f, n)		/* scroll the next window up (back) a page */
X
X{
X	nextwind(FALSE, 1);
X	backpage(f, n);
X	prevwind(FALSE, 1);
X}
X
Xscrnextdw(f, n)		/* scroll the next window down (forward) a page */
X
X{
X	nextwind(FALSE, 1);
X	forwpage(f, n);
X	prevwind(FALSE, 1);
X}
X
Xsavewnd(f, n)		/* save ptr to current window */
X
X{
X	swindow = curwp;
X	return(TRUE);
X}
X
Xrestwnd(f, n)		/* restore the saved screen */
X
X{
X	register WINDOW *wp;
X
X	/* find the window */
X	wp = wheadp;
X	while (wp != NULL) {
X		if (wp == swindow) {
X			curwp = wp;
X			curbp = wp->w_bufp;
X			upmode();
X			return (TRUE);
X		}
X		wp = wp->w_wndp;
X	}
X
X	mlwrite("[No such window exists]");
X	return(FALSE);
X}
X
Xnewsize(f, n)	/* resize the screen, re-writing the screen */
X
Xint f;	/* default flag */
Xint n;	/* numeric argument */
X
X{
X	WINDOW *wp;	/* current window being examined */
X	WINDOW *nextwp;	/* next window to scan */
X	WINDOW *lastwp;	/* last window scanned */
X	int lastline;	/* screen line of last line of current window */
X
X	/* if the command defaults, assume the largest */
X	if (f == FALSE)
X		n = term.t_mrow + 1;
X
X	/* make sure it's in range */
X	if (n < 3 || n > term.t_mrow + 1) {
X		mlwrite("%%Screen size out of range");
X		return(FALSE);
X	}
X
X	if (term.t_nrow == n - 1)
X		return(TRUE);
X	else if (term.t_nrow < n - 1) {
X
X		/* go to the last window */
X		wp = wheadp;
X		while (wp->w_wndp != NULL)
X			wp = wp->w_wndp;
X
X		/* and enlarge it as needed */
X		wp->w_ntrows = n - wp->w_toprow - 2;
X		wp->w_flag |= WFHARD|WFMODE;
X
X	} else {
X
X		/* rebuild the window structure */
X		nextwp = wheadp;
X		wp = NULL;
X		lastwp = NULL;
X		while (nextwp != NULL) {
X			wp = nextwp;
X			nextwp = wp->w_wndp;
X	
X			/* get rid of it if it is too low */
X			if (wp->w_toprow > n - 2) {
X
X				/* save the point/mark if needed */
X				if (--wp->w_bufp->b_nwnd == 0) {
X					wp->w_bufp->b_dotp = wp->w_dotp;
X					wp->w_bufp->b_doto = wp->w_doto;
X					wp->w_bufp->b_markp = wp->w_markp;
X					wp->w_bufp->b_marko = wp->w_marko;
X				}
X	
X				/* update curwp and lastwp if needed */
X				if (wp == curwp)
X					curwp = wheadp;
X					curbp = curwp->w_bufp;
X				if (lastwp != NULL)
X					lastwp->w_wndp = NULL;
X
X				/* free the structure */
X				free((char *)wp);
X				wp = NULL;
X
X			} else {
X				/* need to change this window size? */
X				lastline = wp->w_toprow + wp->w_ntrows - 1;
X				if (lastline >= n - 2) {
X					wp->w_ntrows = n - wp->w_toprow - 2;
X					wp->w_flag |= WFHARD|WFMODE;
X				}
X			}
X	
X			lastwp = wp;
X		}
X	}
X
X	/* screen is garbage */
X	term.t_nrow = n - 1;
X	sgarbf = TRUE;
X	return(TRUE);
X}
X
Xnewwidth(f, n)	/* resize the screen, re-writing the screen */
X
Xint f;	/* default flag */
Xint n;	/* numeric argument */
X
X{
X	/* if the command defaults, assume the largest */
X	if (f == FALSE)
X		n = term.t_mcol;
X
X	/* make sure it's in range */
X	if (n < 10 || n > term.t_mcol) {
X		mlwrite("%%Screen width out of range");
X		return(FALSE);
X	}
X
X	/* otherwise, just re-width it (no big deal) */
X	term.t_ncol = n;
X	term.t_margin = n / 10;
X	term.t_scrsiz = n - (term.t_margin * 2);
X	curwp->w_flag |= WFHARD | WFMOVE;
X	sgarbf = TRUE;
X	return(TRUE);
X}
END_OF_window.c
if test 18023 -ne `wc -c <window.c`; then
    echo shar: \"window.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 7 \(of 14\).
cp /dev/null ark7isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 14 archives.
    echo "See the readme file"
    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