v08i012: A Micro-Emacs variant that resembles GNU Emacs

sources-request at mirror.UUCP sources-request at mirror.UUCP
Wed Jan 28 04:20:07 AEST 1987


Submitted by: Bob Larson <seismo!usc-oberon!blarson>
Mod.sources: Volume 8, Issue 12
Archive-name: micrognu/Part05


#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	tty/termcap/ttykbd.c
#	sys/bsd/Makefile
#	sys/bsd/fileio.c
#	sys/bsd/spawn.c
#	sys/bsd/sysdef.h
#	sys/bsd/ttyio.c
#	sys/sysv/Makefile
#	sys/sysv/fileio.c
#	sys/sysv/spawn.c
#	sys/sysv/ttyio.c
#	sys/sysv/sysdef.h
#	sys/osk/readme.osk
#	sys/osk/sysdef.h
#	sys/osk/varargs.h
#	sys/osk/fileio.c
#	sys/osk/spawn.c
#	sys/osk/ttyio.c
#	sys/osk/makefile
# This archive created: Sat Nov 15 15:16:30 1986
export PATH; PATH=/bin:$PATH
if test ! -d sys/bsd
then
mkdir sys/bsd
fi
if test ! -d sys/sysv
then
mkdir sys/sysv
fi
if test ! -d sys/osk
then
mkdir sys/osk
fi
if test -f 'tty/termcap/ttykbd.c'
then
	echo shar: will not over-write existing file "'tty/termcap/ttykbd.c'"
else
cat << \SHAR_EOF > 'tty/termcap/ttykbd.c'
/*
 * Name:	MicroEmacs
 * Version:	30
 *		Termcap keyboard driver
 * Created:	21-Aug-1986
 *		Mic Kaczmarczik ...!ihnp4!seismo!ut-sally!ut-ngp!mic
 * Last edit:	03-Sep-86
 *
 * [ Several of the nasty comments about the XKEYS code are
 *   by me.  [Bob Larson (usc-oberon!blarson)]  It is my opinion
 *   that function keys cannot be made to work with standard
 *   emacs keybindings except on a very limited set of terminals.
 *   I just work with to many that do not fit the assumptions Mic's
 *   XKEYS code makes to consider it useful to me, and think that
 *   others considering using this code should look and see what
 *   it realy does first.
 * ]
 *
 * If XKEYS is defined this routine looks for the following 
 * termcap sequences, which are obtained by "tty.c":
 *
 *	ks	-- start using the function keypad
 *	ke	-- finish using the function keypad
 *	kh	-- home key
 *	ku	-- up arrow
 *	kd	-- down arrow
 *	kl	-- left arrow
 *	kr	-- right arrow
 *	k0-k9	-- standard termcap function keys
 *	l0-l9	-- labels for termcap function keys
 *	(nonstandard)
 *	K0-K9	-- extra keys that we look for -- the get mapped
 *		   internally to F10-F19
 *	L0-L9	-- labels for same.
 *
 * Bugs/features/problems:
 *
 *	XKEYS and DPROMPT do not work together well.
 *
 *	If the META introducer is used as the initial character of
 *	a function key sequence, what should the key parser do when the
 *	user wants to type a META-ed key, or just the META introducer
 *	alone?	This is of practical importance on DEC terminals, where
 *	the META introducer is the Escape key.  Even worse things happen
 *	on terminals that have something (or more than one thing) other
 *	than the META introducer as the inital character of a function
 *	sequence.
 *
 *	The approach I took was that if the META introducer is the first
 *	character in a function sequence, and the second character c
 *	isn't part of a function key sequence, the parser returns
 *	(KMETA | c).  If it sees two META introducers in a row, it
 *	returns one instance of METACH.   This approach is subject to
 *	discussion and debate, but it works.  [In at lease some cases.]
 *
 *	If the META introducer is NOT the first character in a function
 *	sequence (including arrow keys) this code has a very nasty
 *	side effect of eating that key.  For example, on an Adds viewpoint
 *	60, six normal control characters are eaten if you have defined
 *	XKEYS and put the keys in the termcap.  More than a little 
 *	creativity is needed because ^U is one of the arrow keys, and
 *	prefixes aren't bindable.
 *
 *	[ From a quick look at the code, it seems that a single character
 *	  funciton key won't work, but it is still put in the table.
 *	]
 */
#include	"def.h"

/*
 * Default key name table.  Can be overridden by
 * definitions of l0-l9 in the termcap entry.  You
 * can't redefine the names for the arrow keys
 * and the home key.
 */

#ifdef	XKEYS
/* key sequences (from tty.c) */
extern	char	*K[], *L[], *KS, *KE, *KH, *KU, *KD, *KL, *KR;
extern	int	putpad();	/* also from tty.c */
char	*keystrings[] = {
	NULL,		"Home",		"Down-Arrow",	"Up-Arrow",
	"Left-Arrow",	"Right-Arrow",	"F0",		"F1",
	"F2",		"F3",		"F4",		"F5",
	"F6",		"F7",		"F8",		"F9",
	"F10",		"F11",		"F12",		"F13",
	"F14",		"F15",		"F16",		"F17",
	"F18",		"F19",		NULL,		NULL,
	NULL,		NULL,		NULL,		NULL
};
#else
char	*keystrings[] = {
	NULL,		NULL,		NULL,		NULL,
	NULL,		NULL,		NULL,		NULL,
	NULL,		NULL,		NULL,		NULL,
	NULL,		NULL,		NULL,		NULL,
	NULL,		NULL,		NULL,		NULL,
	NULL,		NULL,		NULL,		NULL,
	NULL,		NULL,		NULL,		NULL,
	NULL,		NULL,		NULL,		NULL
};
#endif

#ifdef	XKEYS
/*
 * Type declarations for data structure we
 * use to parse for function key sequences
 */
#define	NODE		0	/* internal node		*/
#define	VALUE		1	/* internal key code value	*/
#define SENTINEL	2	/* sentinel value		*/

typedef struct trienode {
	int type;	/* one of NODE, LEAF */
	struct trienode *sibling, *child;
	KEY value;
} TRIENODE, *TRIE;

TRIE keywords, sentinel, talloc(), tinsert();
#endif

/*
 * Get keyboard character, and interpret
 * any special keys on the keyboard.  If XKEYS is
 * #defined, use a dictionary organized as a
 * trie to keep the parsing overhead down.
 *
 * To keep the function call overhead down, do the
 * first level of parse() inside getkbd().
 *
 * Also, since ESC (the usual value of METACH) is
 * the first character in many function key sequences,
 * we  return (KMETA | ch) if METACH-<ch> is not
 * the start of an escape sequence.  Blecch.  Furthermore,
 * if we see METACH-METACH, we return the value METACH.
 * Phhhht.
 */
getkbd() {
#ifndef	XKEYS
	return (ttgetc());
#else
	register TRIE	t;
	register int	c;
	KEY		code;

	c = ttgetc();
	for (t = keywords; t->type == NODE; t = t->sibling)
		if (t->value == c) {	/* possible function key sequence  */
			if (c != METACH)
				return (parse(t->child));
			else {		/* maybe sequence, maybe META char */
				c = ttgetc();
				for (t = t->child; t->type == NODE; t = t->sibling)
					if (t->value == c)
						return (parse(t->child));
				/* METACH-METACH -> METACH */
				if (c == METACH)
					return (METACH);
				/* Else make c into a META character */
				if (ISLOWER(c) != FALSE)
					c = TOUPPER(c);
				if (c>=0x00 && c<=0x1F)
					c = KCTRL | (c+'@');
				return (KMETA | c);
			}
		}
	return (c);
#endif
}

#ifdef	XKEYS
static parse(first)
TRIE first;
{
	register TRIE	t;
	register int	c;

	if (first->type == VALUE)		/* found a match!	*/
		return (first->value);

	c = ttgetc();
	for (t = first; t->type == NODE; t = t->sibling)/* look thru list   */
		if (t->value == c)
			return (parse(t->child));	/* try next level   */
	return (c);	/* nothing matched */
}
#endif

/*
 * If XKEYS is defined, get key definitions from the termcap 
 * entry and put them in the parse table.
 */
ttykeymapinit()
{
#ifdef	XKEYS
	register int	i;
	register int	s;
	register char	*cp;
	register SYMBOL	*sp;

	if (KS && *KS)			/* turn on keypad	*/
		putpad(KS);		

	tinit();			/* set up initial trie */

	for (i = 0; i < NFKEYS; i++) {
		if (K[i] && *K[i])
			adddict(K[i], (KEY) (KF0 + i));
		if (L[i] && *L[i])	/* record new name */
			keystrings[(KF0-KFIRST)+i] = L[i];
	}

	/*
	 * Add the home and arrow keys
	 */
	if (KH && *KH)
		adddict(KH, (KEY) KHOME);
	if (KU && *KU)
		adddict(KU, (KEY) KUP);
	if (KD && *KD)
		adddict(KD, (KEY) KDOWN);
	if (KL && *KL)
		adddict(KL, (KEY) KLEFT);
	if (KR && *KR)
		adddict(KR, (KEY) KRIGHT);

	/*
	 * Bind things to the movement keys
	 */
	keydup(KHOME,	"beginning-of-buffer");	/* for now */
	keydup(KUP,	"previous-line");
	keydup(KDOWN,	"next-line");
	keydup(KLEFT,	"backward-char");
	keydup(KRIGHT,	"forward-char");

	/*
	 * These bindings sort of go with the termcap I use for my vt220
	 * clone, which is why they're #ifdef'd.  I don't really use
	 * them, but it gives you an example of what to do...
	 */
#ifdef	MPK
	keydup((KEY)KF0, "describe-key-briefly");	/* Help		*/
	keydup((KEY)KF1, "execute-extended-command");	/* Do		*/
	keydup((KEY)KF2, "search-forward");		/* Find		*/
	keydup((KEY)KF3, "yank");			/* Insert here	*/
	keydup((KEY)KF4, "kill-region");		/* Remove	*/
	keydup((KEY)KF5, "set-mark-command");		/* Select	*/
	keydup((KEY)KF6, "scroll-down");		/* Prev Screen	*/
	keydup((KEY)KF7, "scroll-up");			/* Next Screen	*/

	/* Don't expect these to make much sense, I'm just filling in	*/
	/* the keymap B-]						*/
	keydup((KEY)KF10, "suspend-emacs");		/* PF1		*/
	keydup((KEY)KF11, "query-replace");		/* PF2		*/
	keydup((KEY)KF12, "call-last-kbd-macro");	/* PF3		*/
	keydup((KEY)KF13, "save-buffers-kill-emacs");	/* PF4		*/
#endif	MPK
#endif	XKEYS
}

#ifdef	XKEYS
/*
 * Clean up the keyboard -- called by tttidy()
 */
ttykeymaptidy()
{
	tdelete(keywords);	/* get rid of parse tree	*/
	free(sentinel);		/* remove sentinel value	*/
	if (KE && *KE)
		putpad(KE);	/* turn off keypad		*/
}

/*
 * * * * * * * * Dictionary management * * * * * * * * *
 */

/*
 * Add a key string to the dictionary.
 */

static adddict(kstr, kcode)
char *kstr;
KEY kcode;
{
	keywords = tinsert(kstr, kcode, keywords);
}

/*
 * Initialize the parse tree by creating the sentinel value
 */

static tinit()
{
	keywords = sentinel = talloc();
	sentinel->type = SENTINEL;
	sentinel->value = (KEY) -1;
	sentinel->sibling = sentinel->child = sentinel;	/* set up a loop */
}

/*
 * Deallocate all the space used by the trie --
 * Tell all the siblings to deallocate space, then
 * all the children.
 */

static tdelete(t)
register TRIE t;
{
	if (t->type != SENTINEL) {
		tdelete(t->sibling);
		tdelete(t->child);
		free(t);
	}
}

/*
 * Insert a dictionary key string and a value into the dictionary,
 * returning as the value the first sibling in the current sublevel,
 * which may have been changed by an insertion into the list of siblings.
 */

static TRIE tinsert(kstring, kcode, first)
register char *kstring;
register KEY kcode;
TRIE first;
{
	register TRIE	match;
	register TRIE	p;
	
	if (!*kstring) {	/* base case -- return a value node */
		p = talloc();
		p->type = VALUE;
		p->value = kcode;
		p->sibling = p->child = sentinel;
		return (p);
	}
	/* recursive case -- insert rest of string in trie */

	/* search for sibling that matches the current character */
	match = NULL;
	for (p = first; p->type == NODE; p = p->sibling)
		if (p->value == *kstring) {
			match = p;
			break;
		}

	if (match == NULL) {	/* if not, add it to beginning of the list */
		match = talloc();
		match->type = NODE;
		match->value = *kstring;
		match->sibling = first;
		match->child = sentinel;
		first = match;
	}
	/* add rest of string to this child's subtrie */
	match->child = tinsert(kstring+1, kcode, match->child);
	return (first);
}

/*
 * Allocate a trie node
 */
static TRIE talloc()
{
	char *malloc();
	TRIE t;

	if ((t = (TRIE) malloc(sizeof(TRIENODE))) == NULL)
		panic("talloc: can't allocate trie node!");
	return (t);
}
#endif
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/bsd/Makefile'
then
	echo shar: will not over-write existing file "'sys/bsd/Makefile'"
else
cat << \SHAR_EOF > 'sys/bsd/Makefile'
# Makefile for MicroEMACS.
# Is there a better way to do the rebuilds, other than using
# the links?

SYS	= bsd
TTY	= termcap
LIBS	= -ltermcap
# CDEFS gets defines, and gets passed to lint. CFLAGS gets flags, and doesn't
# get passed to lint.
CDEFS	=  -DDO_METAKEY -DSTARTUP
CFLAGS	= -g $(CDEFS)

OBJ =	basic.o buffer.o cinfo.o display.o echo.o extend.o file.o kbd.o \
	line.o main.o match.o random.o region.o search.o symbol.o version.o \
	window.o paragraph.o prefix.o \
	word.o fileio.o spawn.o ttyio.o tty.o ttykbd.o
OSRCS = fileio.c spawn.c ttyio.c tty.c ttykbd.c
SRCS =	basic.c buffer.c cinfo.c display.c echo.c extend.c file.c kbd.c \
	line.c main.c match.c random.c region.c search.c symbol.c version.c \
	window.c word.c paragraph.c prefix.c
OINCS =	ttydef.h sysdef.h
INCS =	def.h

mg:		$(OBJ)
	cc $(CFLAGS) -o mg $(OBJ) $(LIBS)

# the v arg to lint turns off all the complaints about args f, n & k.
# It's a good idea to take that out and rerun make lint after getting
# a clean lint, just to verify that f, n & k are the ONLY unused args.
lint: $(SRCS) $(OSRCS)
	lint -ahb $(CDEFS) $(SRCS) $(OSRCS)

$(OBJ):		def.h sysdef.h ttydef.h

sysdef.h:	sys/$(SYS)/sysdef.h	# Update links, if needed.
	rm -f sysdef.h
	ln sys/$(SYS)/sysdef.h .

ttydef.h:	tty/$(TTY)/ttydef.h
	rm -f ttydef.h
	ln tty/$(TTY)/ttydef.h .

fileio.c:	sys/$(SYS)/fileio.c
	rm -f fileio.c
	ln sys/$(SYS)/fileio.c .

spawn.c:	sys/$(SYS)/spawn.c
	rm -f spawn.c
	ln sys/$(SYS)/spawn.c .

tty.c:		tty/$(TTY)/tty.c
	rm -f tty.c
	ln tty/$(TTY)/tty.c .

ttyio.c:	sys/$(SYS)/ttyio.c
	rm -f ttyio.c
	ln sys/$(SYS)/ttyio.c .

ttykbd.c:	tty/$(TTY)/ttykbd.c
	rm -f ttykbd.c
	ln tty/$(TTY)/ttykbd.c .

port: $(SRCS) $(INCS)
	rm -f port
	tar cfb port 1 $?

clean:;	rm -f $(OBJ) $(OSRCS) $(OINCS)

SHAR_EOF
fi # end of overwriting check
if test -f 'sys/bsd/fileio.c'
then
	echo shar: will not over-write existing file "'sys/bsd/fileio.c'"
else
cat << \SHAR_EOF > 'sys/bsd/fileio.c'
/*
 * 		bsd (4.2, others?) and Ultrix-32 file I/O.
 */
#include	"def.h"

static	FILE	*ffp;
extern	char	*getenv();

/*
 * handle C-shell style names
 */
static char *bsd(fn, buf, bufsiz) char *fn, *buf; int bufsiz;
{
	if (*fn != '~')
		return (fn);
	else {	/* C-shell $HOME-relative names */
		strncpy(buf, getenv("HOME"), bufsiz);
		strncat(buf, fn + 1, bufsiz);
		return (buf);
	}
}

/*
 * Open a file for reading.
 */
ffropen(fn) char *fn; {
	char buf[NFILEN];
	fn = bsd(fn, buf, sizeof(buf));
	if ((ffp=fopen(fn, "r")) == NULL)
		return (FIOFNF);
	return (FIOSUC);
}

/*
 * Open a file for writing.
 * Return TRUE if all is well, and
 * FALSE on error (cannot create).
 */
ffwopen(fn) char *fn; {
	char buf[NFILEN];
	fn = bsd(fn, buf, sizeof(buf));
	if ((ffp=fopen(fn, "w")) == NULL) {
		ewprintf("Cannot open file for writing");
		return (FIOERR);
	}
	return (FIOSUC);
}

/*
 * Close a file.
 * Should look at the status.
 */
ffclose() {
	(VOID) fclose(ffp);
	return (FIOSUC);
}

/*
 * Write a line to the already
 * opened file. The "buf" points to the
 * buffer, and the "nbuf" is its length, less
 * the free newline. Return the status.
 * Check only at the newline.
 */
ffputline(buf, nbuf) register char buf[]; {
	register int	i;

	/* What's with putc? */
	for (i=0; i<nbuf; ++i)
		putc(buf[i]&0xFF, ffp);
	putc('\n', ffp);
	if (ferror(ffp) != FALSE) {
		ewprintf("Write I/O error");
		return (FIOERR);
	}
	return (FIOSUC);
}

/*
 * Read a line from a file, and store the bytes
 * in the supplied buffer. Stop on end of file or end of
 * line. Don't get upset by files that don't have an end of
 * line on the last line; this seem to be common on CP/M-86 and
 * MS-DOS (the suspected culprit is VAX/VMS kermit, but this
 * has not been confirmed. If this is sufficiently researched
 * it may be possible to pull this kludge). Delete any CR
 * followed by an LF. This is mainly for runoff documents,
 * both on VMS and on Ultrix (they get copied over from
 * VMS systems with DECnet).
 */
ffgetline(buf, nbuf) register char buf[]; {
	register int	c;
	register int	i;

	i = 0;
	for (;;) {
		c = getc(ffp);
		if (c == '\r') {		/* Delete any non-stray	*/
			c = getc(ffp);		/* carriage returns.	*/
			if (c != '\n') {
				if (i >= nbuf-1) {
					ewprintf("File has long line");
					return (FIOERR);
				}
				buf[i++] = '\r';
			}
		}
		if (c==EOF || c=='\n')		/* End of line.		*/
			break;
		if (i >= nbuf-1) {
			ewprintf("File has long line");
			return (FIOERR);
		}
		buf[i++] = c;
	}
	if (c == EOF) {				/* End of file.		*/
		if (ferror(ffp) != FALSE) {
			ewprintf("File read error");
			return (FIOERR);
		}
		if (i == 0)			/* Don't get upset if	*/
			return (FIOEOF);	/* no newline at EOF.	*/
	}
	buf[i] = 0;
	return (FIOSUC);
}

#if	BACKUP
/*
 * Rename the file "fname" into a backup
 * copy. On Unix the backup has the same name as the
 * original file, with a "~" on the end; this seems to
 * be newest of the new-speak. The error handling is
 * all in "file.c". The "unlink" is perhaps not the
 * right thing here; I don't care that much as
 * I don't enable backups myself.
 */
fbackupfile(fn) char *fn; {
	register char	*nname;
	char		*malloc();
	char		buf[NFILEN];

	fn = bsd(fn, buf, sizeof(buf));
	if ((nname=malloc(strlen(fn)+1+1)) == NULL) {
		ewprintf("Can't get %d bytes", strlen(fn) + 1);
		return (ABORT);
	}
	(void) strcpy(nname, fn);
	(void) strcat(nname, "~");
	(void) unlink(nname);			/* Ignore errors.	*/
	if (rename(fn, nname) < 0) {
		free(nname);
		return (FALSE);
	}
	free(nname);
	return (TRUE);
}
#endif
/*
 * The string "fn" is a file name.
 * Perform any required case adjustments. All sustems
 * we deal with so far have case insensitive file systems.
 * We zap everything to lower case. The problem we are trying
 * to solve is getting 2 buffers holding the same file if
 * you visit one of them with the "caps lock" key down.
 * On UNIX file names are dual case, so we leave
 * everything alone.
 */
/*ARGSUSED*/
adjustcase(fn) register char *fn; {
#if	0
	register int	c;

	while ((c = *fn) != 0) {
		if (c>='A' && c<='Z')
			*fn = c + 'a' - 'A';
		++fn;
	}
#endif
}

#ifdef	STARTUP
#include <sys/file.h>
/*
 * find the users startup file, and return it's name. Check for
 * $HOME/.mg then for $HOME/.emacs, then give up.
 */
char *
startupfile() {
	register char	*file;
	static char	home[NFILEN];
	char		*getenv();

	if ((file = getenv("HOME")) == NULL) return NULL;
	if (strlen(file)+7 >= NFILEN - 1) return NULL;
	(VOID) strcpy(home, file);
	file = &(home[strlen(home)]);
	*file++ = '/';

	(VOID) strcpy(file, ".mg");
	if (access(home, F_OK ) == 0) return home;

	(VOID) strcpy(file, ".emacs");
	if (access(home, F_OK) == 0) return home;

	return NULL;
}
#endif
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/bsd/spawn.c'
then
	echo shar: will not over-write existing file "'sys/bsd/spawn.c'"
else
cat << \SHAR_EOF > 'sys/bsd/spawn.c'
/*
 * Spawn. New version, which
 * interracts with the job control stuff
 * in the 4.X BSD C shell.
 * Last edit:  Wed Aug 27 11:16:07 PDT 1986
 * By:	       rtech!daveb, to use stop for ksh.
 */
#include	"def.h"

#include	<sgtty.h>
#include	<signal.h>

char	*shellp	= NULL;			/* Saved "SHELL" name.		*/

extern	struct	sgttyb	oldtty;		/* There really should be a	*/
extern	struct	sgttyb	newtty;		/* nicer way of doing this, so	*/
extern	struct	sgttyb	oldtchars;	/* spawn does not need to know	*/
extern	struct	sgttyb	newtchars;	/* about the insides of the	*/
extern	struct	sgttyb	oldltchars;	/* terminal I/O code.		*/
extern	struct	sgttyb	newltchars;

extern	char	*getenv();

/*
 * This code does a one of 2 different
 * things, depending on what version of the shell
 * you are using. If you are using the C shell, which
 * implies that you are using job control, then MicroEMACS
 * moves the cursor to a nice place and sends itself a
 * stop signal. If you are using the Bourne shell it runs
 * a subshell using fork/exec. Bound to "C-C", and used
 * as a subcommand by "C-Z".
 *
 * Daveb -- changed sense of test so that we only spawn if you
 *	    are explicitly using /bin/sh.  This makes it stop
 *	    work with the ksh.
 */
/*ARGSUSED*/
spawncli(f, n, k) {
	register int	pid, wpid, (*oqsig)(), (*oisig)(), omask;
	int		status;

	if (shellp == NULL) {
		shellp = getenv("SHELL");
		if (shellp == NULL)
			shellp = getenv("shell");
		if (shellp == NULL)
			shellp = "/bin/sh";	/* Safer.		*/
	}
	ttcolor(CTEXT);
	ttnowindow();
	if (strcmp(shellp, "/bin/csh") == 0) {
		if (epresf != FALSE) {
			ttmove(nrow-1, 0);
			tteeol();
			epresf = FALSE;
		}				/* Csh types a "\n"	*/
		ttmove(nrow-2, 0);		/* before "Stopped".	*/
	} else {
		ttmove(nrow-1, 0);
		if (epresf != FALSE) {
			tteeol();
			epresf = FALSE;
		}
	}
	ttflush();
	if (ioctl(0, TIOCSLTC, (char *) &oldltchars) < 0
	||  ioctl(0, TIOCSETC, (char *) &oldtchars)  < 0
	||  ioctl(0, TIOCSETP, (char *) &oldtty)     < 0) {
		ewprintf("IOCTL #1 to terminal failed");
		return (FALSE);
	}
	if (strcmp(shellp, "/bin/sh") != 0) {	/* C shell, ksh		*/
		omask = sigsetmask(0);
		(void) kill(0, SIGTSTP);
		setttysize() ;
		(void) sigsetmask(omask);
	} else {				/* Bourne shell.	*/
		oqsig = signal(SIGQUIT, SIG_IGN);
		oisig = signal(SIGINT,  SIG_IGN);
		if ((pid=fork()) < 0) {
			(void) signal(SIGQUIT, oqsig);
			(void) signal(SIGINT,  oisig);
			ewprintf("Failed to create process");
			return (FALSE);
		}
		if (pid == 0) {
			execl(shellp, "sh", "-i", NULL);
			_exit(0);		/* Should do better!	*/
		}
		while ((wpid=wait(&status))>=0 && wpid!=pid)
			;
		(void) signal(SIGQUIT, oqsig);
		(void) signal(SIGINT,  oisig);
	}
	sgarbf = TRUE;				/* Force repaint.	*/
	if (ioctl(0, TIOCSETP, (char *) &newtty)     < 0
	||  ioctl(0, TIOCSETC, (char *) &newtchars)  < 0
	||  ioctl(0, TIOCSLTC, (char *) &newltchars) < 0) {
		ewprintf("IOCTL #2 to terminal failed");
		return (FALSE);
	}
	return (TRUE);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/bsd/sysdef.h'
then
	echo shar: will not over-write existing file "'sys/bsd/sysdef.h'"
else
cat << \SHAR_EOF > 'sys/bsd/sysdef.h'
/*
 *		Ultrix-32 system header file.
 */
#define	PCC	1			/* "[]" gets an error.		*/
#define	KBLOCK	8192			/* Kill grow.			*/
#define	GOOD	0			/* Good exit status.		*/

typedef int	RSIZE;			/* Type for file/region sizes	*/
typedef short	KEY;			/* Type for internal keystrokes	*/

/*
 * Macros used by the buffer name making code.
 * Start at the end of the file name, scan to the left
 * until BDC1 (or BDC2, if defined) is reached. The buffer
 * name starts just to the right of that location, and
 * stops at end of string (or at the next BDC3 character,
 * if defined). BDC2 and BDC3 are mainly for VMS.
 */
#define	BDC1	'/'			/* Buffer names.		*/
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/bsd/ttyio.c'
then
	echo shar: will not over-write existing file "'sys/bsd/ttyio.c'"
else
cat << \SHAR_EOF > 'sys/bsd/ttyio.c'
/*
 *		Ultrix-32 and Unix terminal I/O.
 * The functions in this file
 * negotiate with the operating system for
 * keyboard characters, and write characters to
 * the display in a barely buffered fashion.
 */
#include	"def.h"

#include	<sgtty.h>

#define	NOBUF	512			/* Output buffer size.		*/

char	obuf[NOBUF];			/* Output buffer.		*/
int	nobuf;
struct	sgttyb	oldtty;			/* V6/V7 stty data.		*/
struct	sgttyb	newtty;
struct	tchars	oldtchars;		/* V7 editing.			*/
struct	tchars	newtchars;
struct	ltchars oldltchars;		/* 4.2 BSD editing.		*/
struct	ltchars	newltchars;
#ifdef	TIOCGWINSZ
struct	winsize	winsize;		/* 4.3 BSD window sizing	*/
#endif
int	nrow;				/* Terminal size, rows.		*/
int	ncol;				/* Terminal size, columns.	*/

/*
 * This function gets called once, to set up
 * the terminal channel. On Ultrix is's tricky, since
 * we want flow control, but we don't want any characters
 * stolen to send signals. Use CBREAK mode, and set all
 * characters but start and stop to 0xFF.
 */
ttopen() {
        register char *tv_stype;
        char *getenv(), *tgetstr(), tcbuf[1024], err_str[72];

	if (ioctl(0, TIOCGETP, (char *) &oldtty) < 0)
		panic("ttopen can't get sgtty");
	newtty.sg_ospeed = oldtty.sg_ospeed;
	newtty.sg_ispeed = oldtty.sg_ispeed;
	newtty.sg_erase  = oldtty.sg_erase;
	newtty.sg_kill   = oldtty.sg_kill;
	newtty.sg_flags  = oldtty.sg_flags;
	newtty.sg_flags &= ~(ECHO|CRMOD);	/* Kill echo, CR=>NL.	*/
#ifdef FLOWCONTROL
	newtty.sg_flags |= CBREAK;		/* Half-cooked mode.	*/
#else
	newtty.sg_flags |= RAW|ANYP;		/* raw mode for 8 bit path.*/
#endif
	if (ioctl(0, TIOCSETP, (char *) &newtty) < 0)
		panic("ttopen can't set sgtty");
	if (ioctl(0, TIOCGETC, (char *) &oldtchars) < 0)
		panic("ttopen can't get chars");
	newtchars.t_intrc  = 0xFF;		/* Interrupt.		*/
	newtchars.t_quitc  = 0xFF;		/* Quit.		*/
#if FLOWCONTROL
	newtchars.t_startc = 0x11;		/* ^Q, for terminal.	*/
	newtchars.t_stopc  = 0x13;		/* ^S, for terminal.	*/
#else
	newtchars.t_startc = 0xFF;		/* ^Q, for terminal.	*/
	newtchars.t_stopc  = 0xFF;		/* ^S, for terminal.	*/
#endif
	newtchars.t_eofc   = 0xFF;
	newtchars.t_brkc   = 0xFF;
	if (ioctl(0, TIOCSETC, (char *) &newtchars) < 0)
		panic("ttopen can't set chars");
	if (ioctl(0, TIOCGLTC, (char *) &oldltchars) < 0)
		panic("ttopen can't get ltchars");
	newltchars.t_suspc  = 0xFF;		/* Suspend #1.		*/
	newltchars.t_dsuspc = 0xFF;		/* Suspend #2.		*/
	newltchars.t_rprntc = 0xFF;
	newltchars.t_flushc = 0xFF;		/* Output flush.	*/
	newltchars.t_werasc = 0xFF;
	newltchars.t_lnextc = 0xFF;		/* Literal next.	*/
	if (ioctl(0, TIOCSLTC, (char *) &newltchars) < 0)
		panic("ttopen can't set ltchars");

/* do this the REAL way */
        if ((tv_stype = getenv("TERM")) == NULL)
        {
                puts("Environment variable TERM not defined!");
                exit(1);
        }

        if((tgetent(tcbuf, tv_stype)) != 1)
        {
                (void) sprintf(err_str, "Unknown terminal type %s!", tv_stype);
                puts(err_str);
                exit(1);
        }

	setttysize() ;
}

/*
 * This function gets called just
 * before we go back home to the shell. Put all of
 * the terminal parameters back.
 */
ttclose() {
	ttflush();
	if (ioctl(0, TIOCSLTC, (char *) &oldltchars) < 0)
		panic("ttclose can't set ltchars");
	if (ioctl(0, TIOCSETC, (char *) &oldtchars) < 0)
		panic("ttclose can't set chars");
	if (ioctl(0, TIOCSETP, (char *) &oldtty) < 0)
		panic("ttclose can't set sgtty");
}

/*
 * Write character to the display.
 * Characters are buffered up, to make things
 * a little bit more efficient.
 */
ttputc(c) {
	if (nobuf >= NOBUF)
		ttflush();
	obuf[nobuf++] = c;
}

/*
 * Flush output.
 */
ttflush() {
	if (nobuf != 0) {
		if (write(1, obuf, nobuf) != nobuf)
			panic("ttflush write failed");
		nobuf = 0;
	}
}

/*
 * Read character from terminal.
 * All 8 bits are returned, so that you can use
 * a multi-national terminal.
 */
ttgetc() {
	char	buf[1];

	while (read(0, &buf[0], 1) != 1)
		;
	return (buf[0] & 0xFF);
}
/*
 * set the tty size. Functionized for 43BSD.
 */
setttysize() {

#ifdef	TIOCGWINSZ
	if (ioctl(0, TIOCGWINSZ, (char *) &winsize) == 0) {
		nrow = winsize . ws_row;
		ncol = winsize . ws_col;
	} else nrow = 0;
 	if(nrow<=0 || ncol<=0)
#endif
	if ((nrow=tgetnum ("li")) <= 0
	|| (ncol=tgetnum ("co")) <= 0) {
		nrow = 24;
		ncol = 80;
	}
	if (nrow > NROW)			/* Don't crash if the	*/
		nrow = NROW;			/* termcap entry is	*/
	if (ncol > NCOL)			/* too big.		*/
		ncol = NCOL;
}

/*
 * typeahead returns TRUE if there are characters available to be read
 * in.
 */
typeahead() {
	int	x;

	return((ioctl(0, FIONREAD, (char *) &x) < 0) ? 0 : x);
}

/*
 * panic - just exit, as quickly as we can.
 */
panic(s) char *s; {
	printf(stderr, "panic: %s\n", s);
	abort();		/* To leave a core image. */
}
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/sysv/Makefile'
then
	echo shar: will not over-write existing file "'sys/sysv/Makefile'"
else
cat << \SHAR_EOF > 'sys/sysv/Makefile'
# Makefile for MicroEMACS.
# Is there a better way to do the rebuilds, other than using
# the links?

SYS	= sysv
TTY	= termcap
# you may not need (or have) termlib...
LIBS	= -lcurses -ltermlib
# CDEFS gets defines, and gets passed to lint. CFLAGS gets flags, and doesn't
# get passed to lint.
CDEFS	= -DDO_METAKEY
CFLAGS	= -g $(CDEFS)

OBJ =	basic.o buffer.o cinfo.o display.o echo.o extend.o file.o kbd.o \
	line.o main.o match.o random.o region.o search.o symbol.o version.o \
	window.o paragraph.o prefix.o \
	word.o fileio.o spawn.o ttyio.o tty.o ttykbd.o
OSRCS = fileio.c spawn.c ttyio.c tty.c ttykbd.c
SRCS =	basic.c buffer.c cinfo.c display.c echo.c extend.c file.c kbd.c \
	line.c main.c match.o random.c region.c search.c symbol.c version.c \
	window.c word.c paragraph.c prefix.c
OINCS =	ttydef.h sysdef.h
INCS =	def.h

mg:		$(OBJ)
		cc $(CFLAGS) -o mg $(OBJ) $(LIBS)

# for AT&T UNIX-PC
mg.7300:	$(OBJ)
		ld /lib/crt0s.o /lib/shlib.ifile $(OBJ) -o mg.7300

lint: $(SRCS) $(OSRCS)
		lint $(CDEFS) $(SRCS) $(OSRCS)

$(OBJ):		def.h sysdef.h ttydef.h

sysdef.h:	sys/$(SYS)/sysdef.h	# Update links, if needed.
		rm -f sysdef.h
		ln sys/$(SYS)/sysdef.h .

ttydef.h:	tty/$(TTY)/ttydef.h
		rm -f ttydef.h
		ln tty/$(TTY)/ttydef.h .

fileio.c:	sys/$(SYS)/fileio.c
		rm -f fileio.c
		ln sys/$(SYS)/fileio.c .

spawn.c:	sys/$(SYS)/spawn.c
		rm -f spawn.c
		ln sys/$(SYS)/spawn.c .

tty.c:		tty/$(TTY)/tty.c
		rm -f tty.c
		ln tty/$(TTY)/tty.c .

ttyio.c:	sys/$(SYS)/ttyio.c
		rm -f ttyio.c
		ln sys/$(SYS)/ttyio.c .

ttykbd.c:	tty/$(TTY)/ttykbd.c
		rm -f ttykbd.c
		ln tty/$(TTY)/ttykbd.c .

clean:;		rm -f $(OBJ) $(OSRCS) $(OINCS)
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/sysv/fileio.c'
then
	echo shar: will not over-write existing file "'sys/sysv/fileio.c'"
else
cat << \SHAR_EOF > 'sys/sysv/fileio.c'
/*
 * Name:	MicroEMACS
 * 		System V file I/O
 */
#include	"def.h"

# ifndef F_OK
# define F_OK	0
# define X_OK	1
# define W_OK	2
# define R_OK	4
# endif

/*
 * Move bytes, overlaps OK (daveb).
 *
 * Doesn't really belong here, but it's system specific since it
 * is in assembler in some C libraries.
 */
bcopy( from, to, cnt )
char *from;
char *to;
int cnt;
{
	if ( from == to )
		return;

	if( from > to )
	{
		while( cnt-- )
			*to++ = *from++;
	}
	else
	{
		to += cnt;
		from += cnt;
		while( cnt-- )
			*--to = *--from;
	}
}


static	FILE	*ffp;

/*
 * Open a file for reading.
 */
ffropen(fn)
char	*fn;
{
	if ((ffp=fopen(fn, "r")) == NULL)
		return (FIOFNF);
	return (FIOSUC);
}

/*
 * Open a file for writing.
 * Return TRUE if all is well, and
 * FALSE on error (cannot create).
 */
ffwopen(fn)
char	*fn;
{
	if ((ffp=fopen(fn, "w")) == NULL) {
		ewprintf("Cannot open file for writing");
		return (FIOERR);
	}
	return (FIOSUC);
}

/*
 * Close a file.
 * Should look at the status.
 */
ffclose()
{
	(VOID) fclose(ffp);
	return (FIOSUC);
}

/*
 * Write a line to the already
 * opened file. The "buf" points to the
 * buffer, and the "nbuf" is its length, less
 * the free newline. Return the status.
 * Check only at the newline.
 */
ffputline(buf, nbuf)
register char	buf[];
{
	register int	i;

	for (i=0; i<nbuf; ++i)
		putc(buf[i]&0xFF, ffp);
	putc('\n', ffp);
	if (ferror(ffp) != FALSE) {
		ewprintf("Write I/O error");
		return (FIOERR);
	}
	return (FIOSUC);
}

/*
 * Read a line from a file, and store the bytes
 * in the supplied buffer. Stop on end of file or end of
 * line. Don't get upset by files that don't have an end of
 * line on the last line; this seem to be common on CP/M-86 and
 * MS-DOS (the suspected culprit is VAX/VMS kermit, but this
 * has not been confirmed. If this is sufficiently researched
 * it may be possible to pull this kludge). Delete any CR
 * followed by an LF. This is mainly for runoff documents,
 * both on VMS and on Ultrix (they get copied over from
 * VMS systems with DECnet).
 */
ffgetline(buf, nbuf)
register char	buf[];
{
	register int	c;
	register int	i;

	i = 0;
	for (;;) {
		c = getc(ffp);
		if (c == '\r') {		/* Delete any non-stray	*/
			c = getc(ffp);		/* carriage returns.	*/
			if (c != '\n') {
				if (i >= nbuf-1) {
					ewprintf("File has long line");
					return (FIOERR);
				}
				buf[i++] = '\r';
			}
		}
		if (c==EOF || c=='\n')		/* End of line.		*/
			break;
		if (i >= nbuf-1) {
			ewprintf("File has long line");
			return (FIOERR);
		}
		buf[i++] = c;
	}
	if (c == EOF) {				/* End of file.		*/
		if (ferror(ffp) != FALSE) {
			ewprintf("File read error");
			return (FIOERR);
		}
		if (i == 0)			/* Don't get upset if	*/
			return (FIOEOF);	/* no newline at EOF.	*/
	}
	buf[i] = 0;
	return (FIOSUC);
}

#if	BACKUP
/*
 * Rename the file "fname" into a backup
 * copy. On Unix the backup has the same name as the
 * original file, with a "~" on the end; this seems to
 * be newest of the new-speak. The error handling is
 * all in "file.c". The "unlink" is perhaps not the
 * right thing here; I don't care that much as
 * I don't enable backups myself.
 */
fbackupfile(fname)
char	*fname;
{
	register char	*nname;

	if ((nname=malloc(strlen(fname)+1+1)) == NULL)
		return (ABORT);
	(void) strcpy(nname, fname);
	(void) strcat(nname, "~");
	(void) unlink(nname);			/* Ignore errors.	*/

	/* no rename on System V, so do it dangerous way. */
	if ( link(fname, nname) < 0 || unlink(fname) < 0 ) {
		free(nname);
		return (FALSE);
	}
	free(nname);
	return (TRUE);
}
#endif

/*
 * The string "fn" is a file name.
 * Perform any required case adjustments. All sustems
 * we deal with so far have case insensitive file systems.
 * We zap everything to lower case. The problem we are trying
 * to solve is getting 2 buffers holding the same file if
 * you visit one of them with the "caps lock" key down.
 * On UNIX file names are dual case, so we leave
 * everything alone.
 */
/*ARGSUSED*/
adjustcase(fn)
register char	*fn;
{
#if	0
	register int	c;

	while ((c = *fn) != 0) {
		if (c>='A' && c<='Z')
			*fn = c + 'a' - 'A';
		++fn;
	}
#endif
}



#ifdef	STARTUP
#include <sys/types.h>
#include <sys/file.h>
/*
 * find the users startup file, and return it's name. Check for
 * $HOME/.mg then for $HOME/.emacs, then give up.
 */
char *
startupfile() 
{
	register char	*file;
	static char	home[NFILEN];
	char		*getenv();

	if ( (file = getenv("HOME")) == NULL 
	     || strlen(file)+7 >= NFILEN - 1 ) 
		return NULL;
	(VOID) strcpy(home, file);
	file = &(home[strlen(home)]);
	*file++ = '/';

	(VOID) strcpy(file, ".mg");
	if (access(home, F_OK ) == 0) return home;

	(VOID) strcpy(file, ".emacs");
	if (access(home, F_OK) == 0) return home;

	return NULL;
}
#endif
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/sysv/spawn.c'
then
	echo shar: will not over-write existing file "'sys/sysv/spawn.c'"
else
cat << \SHAR_EOF > 'sys/sysv/spawn.c'
/*
 * Name:	MicroEMACS
 *		Spawn CLI for System V.
 * Version:	0
 * Last edit:	17-Apr-86
 * By:		gonzo!daveb
 *		{sun, amdahl, mtxinu}!rtech!daveb
 *
 * Spawn for System V.
 */
#include	"def.h"

#include	<signal.h>

char	*shellp	= NULL;			/* Saved "SHELL" program.	*/
char	*shname = NULL;			/* Saved shell name		*/

extern	char	*getenv();

/*
 * On System V, we no gots job control, so always run
 * a subshell using fork/exec. Bound to "C-C", and used
 * as a subcommand by "C-Z". (daveb)
 *
 * Returns 0 if the shell executed OK, something else if
 * we couldn't start shell or it exited badly.
 */
spawncli(f, n, k)
{
	extern char	*strrchr();
	register int	pid;
	register int	wpid;
	register int	(*oqsig)();
	register int	(*oisig)();
	int		status;
	int		errp = FALSE;

	if (shellp == NULL) {
		shellp = getenv("SHELL");
		if (shellp == NULL)
			shellp = getenv("shell");
		if (shellp == NULL)
			shellp = "/bin/sh";	/* Safer.		*/
		shname = strrchr( shellp, '/' ); 
		shname = shname ? shname++ : shellp;
		
	}
	ttcolor(CTEXT);
	ttnowindow();
	ttmove(nrow-1, 0);
	if (epresf != FALSE) {
		tteeol();
		epresf = FALSE;
	}
	ttclose();
	sgarbf = TRUE;				/* Force repaint.	*/
	oqsig = signal(SIGQUIT, SIG_IGN);
	oisig = signal(SIGINT,  SIG_IGN);
	if ((pid=fork()) == 0) {
		execlp(shellp, shname, "-i", NULL);
		_exit(1);			/* Should do better!	*/
	}
	else if (pid > 0) {
		while ((wpid=wait(&status))>=0 && wpid!=pid)
			;
	}
	else errp = TRUE;

	signal(SIGINT,  oisig);
	ttopen();
	if(errp)
		ewprintf("Failed to create process");

	return ( errp | status );
}
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/sysv/ttyio.c'
then
	echo shar: will not over-write existing file "'sys/sysv/ttyio.c'"
else
cat << \SHAR_EOF > 'sys/sysv/ttyio.c'
/*
 * Name:	MicroEMACS
 *		System V terminal I/O.
 * Version:	0
 * Last edit:	Tue Aug 26 23:57:57 PDT 1986
 * By:		gonzo!daveb
 *		{sun, amdahl, mtxinu}!rtech!gonzo!daveb
 *
 * The functions in this file
 * negotiate with the operating system for
 * keyboard characters, and write characters to
 * the display in a barely buffered fashion.
 *
 * This version goes along with tty/termcap/tty.c.
 * Terminal size is determined there, rather than here, and
 * this does not open the termcap file
 */
#include	"def.h"

#include	<sys/types.h>
#include	<fcntl.h>
#include	<termio.h>

#define	NOBUF	512			/* Output buffer size.		*/

char	obuf[NOBUF];			/* Output buffer.		*/
int	nobuf;				/* buffer count			*/

static struct termio	ot;		/* entry state of the terminal	*/
static struct termio	nt;		/* editor's terminal state	*/

static int ttyactivep = FALSE;		/* terminal in editor mode?	*/
static int ttysavedp = FALSE;		/* terminal state saved?	*/

int	nrow;				/* Terminal size, rows.		*/
int	ncol;				/* Terminal size, columns.	*/

/* These are used to implement typeahead on System V */

int kbdflgs;			/* saved keyboard fd flags	*/
int kbdpoll;			/* in O_NDELAY mode			*/
int kbdqp;			/* there is a char in kbdq	*/
char kbdq;			/* char we've already read	*/

/*
 * This function gets called once, to set up
 * the terminal channel.  This version turns off flow
 * control.  This may be wrong for your system, but no
 * good solution has really been found (daveb).
 */
ttopen()
{
	register char	*cp;
	extern char	*getenv();

	if (ttyactivep)
		return;

	if( !ttysavedp )
	{
		if (ioctl(0, TCGETA, &ot) < 0)
			abort();
		nt = ot;		/* save entry state		*/
		nt.c_cc[VMIN] = 1;	/* one character read is OK	*/
		nt.c_cc[VTIME] = 0;	/* Never time out.		*/
		nt.c_iflag |= IGNBRK;
		nt.c_iflag &= ~( ICRNL | INLCR | ISTRIP | IXON | IXOFF );
		nt.c_oflag &= ~OPOST;
		nt.c_cflag |= CS8;	/* allow 8th bit on input	*/
		nt.c_cflag &= ~PARENB;	/* Don't check parity		*/
		nt.c_lflag &= ~( ECHO | ICANON | ISIG );

		kbdflgs = fcntl( 0, F_GETFL, 0 );
		kbdpoll = FALSE;
	
		ttysavedp = TRUE;
	}
	
	if (ioctl(0, TCSETAF, &nt) < 0)
		abort();

	/* This really belongs in tty/termcap... */

	if ((cp=getenv("TERMCAP")) == NULL
	|| (nrow=getvalue(cp, "li")) <= 0
	|| (ncol=getvalue(cp, "co")) <= 0) {
		nrow = 24;
		ncol = 80;
	}
	if (nrow > NROW)			/* Don't crash if the	*/
		nrow = NROW;			/* termcap entry is	*/
	if (ncol > NCOL)			/* too big.		*/
		ncol = NCOL;

	ttyactivep = TRUE;
}

/*
 * This routine scans a string, which is
 * actually the return value of a getenv call for the TERMCAP
 * variable, looking for numeric parameter "name". Return the value
 * if found. Return -1 if not there. Assume that "name" is 2
 * characters long. This limited use of the TERMCAP lets us find
 * out the size of a window on the X display.
 */
getvalue(cp, name)
register char	*cp;
register char	*name;
{
	for (;;) {
		while (*cp!=0 && *cp!=':')
			++cp;
		if (*cp++ == 0)			/* Not found.		*/
			return (-1);
		if (cp[0]==name[0] && cp[1]==name[1] && cp[2]=='#')
			return (atoi(cp+3));	/* Stops on ":".	*/
	}
}

/*
 * This function gets called just
 * before we go back home to the shell. Put all of
 * the terminal parameters back.
 */
ttclose()
{
	if(!ttysavedp || !ttyactivep)
		return;
	ttflush();
	if (ioctl(0, TCSETAF, &ot) < 0 || fcntl( 0, F_SETFL, kbdflgs ) < 0)
		abort();
	ttyactivep = FALSE;
}

/*
 * Write character to the display.
 * Characters are buffered up, to make things
 * a little bit more efficient.
 */
ttputc(c)
{
	if (nobuf >= NOBUF)
		ttflush();
	obuf[nobuf++] = c;
}

/*
 * Flush output.
 */
ttflush()
{
	if (nobuf != 0) {
		write(1, obuf, nobuf);
		nobuf = 0;
	}
}

/*
 * Read character from terminal.
 * All 8 bits are returned, so that you can use
 * a multi-national terminal.
 *
 * If keyboard 'queue' already has typeahead from a typeahead() call,
 * just return it.  Otherwise, make sure we are in blocking i/o mode
 * and read a character.
 */
ttgetc()
{
	if( kbdqp )
		kbdqp = FALSE;
	else
	{
		if( kbdpoll && fcntl( 0, F_SETFL, kbdflgs ) < 0 )
			abort();
		kbdpoll = FALSE;
		while (read(0, &kbdq, 1) != 1)
			;
	}
	return ( kbdq & 0xff );
}

/*
 * Return non-FALSE if typeahead is pending.
 *
 * If already got unread typeahead, do nothing.
 * Otherwise, set keyboard to O_NDELAY if not already, and try
 * a one character read.
 */
typeahead()
{
	if( !kbdqp )
	{
		if( !kbdpoll && fcntl( 0, F_SETFL, kbdflgs | O_NDELAY ) < 0 )
			abort();
		kbdqp = (1 == read( 0, &kbdq, 1 ));
	}
	return ( kbdqp );
}


/*
 * panic:  print error and die, leaving core file.
 * Don't know why this is needed (daveb).
 */
panic(s)
char *s;
{
	fprintf(stderr, "%s\r\n", s);
	abort();
}


/*
** This should check the size of the window, and reset if needed.
*/

setttysize()
{
#ifdef	TIOCGWINSZ
	if (ioctl(0, TIOCGWINSZ, (char *) &winsize) == 0) {
		nrow = winsize . ws_row;
		ncol = winsize . ws_col;
	} else
#endif
	if ((nrow=tgetnum ("li")) <= 0
	|| (ncol=tgetnum ("co")) <= 0) {
		nrow = 24;
		ncol = 80;
	}
	if (nrow > NROW)			/* Don't crash if the	*/
		nrow = NROW;			/* termcap entry is	*/
	if (ncol > NCOL)			/* too big.		*/
		ncol = NCOL;
}

SHAR_EOF
fi # end of overwriting check
if test -f 'sys/sysv/sysdef.h'
then
	echo shar: will not over-write existing file "'sys/sysv/sysdef.h'"
else
cat << \SHAR_EOF > 'sys/sysv/sysdef.h'
/*
 * Name:	MicroEMACS
 *		Ultrix-32 system header file same for System V.
 * Version:	29
 * Last edit:	05-Feb-86
 * By:		rex::conroy
 *		decvax!decwrl!dec-rhea!dec-rex!conroy
 */
#define	PCC	1			/* "[]" gets an error.		*/
#define	KBLOCK	8192			/* Kill grow.			*/
#define	GOOD	0			/* Good exit status.		*/

typedef int	RSIZE;			/* Type for file/region sizes	*/
typedef short	KEY;			/* Type for internal keystrokes	*/

/*
 * Macros used by the buffer name making code.
 * Start at the end of the file name, scan to the left
 * until BDC1 (or BDC2, if defined) is reached. The buffer
 * name starts just to the right of that location, and
 * stops at end of string (or at the next BDC3 character,
 * if defined). BDC2 and BDC3 are mainly for VMS.
 */
#define	BDC1	'/'			/* Buffer names.		*/
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/osk/readme.osk'
then
	echo shar: will not over-write existing file "'sys/osk/readme.osk'"
else
cat << \SHAR_EOF > 'sys/osk/readme.osk'
readme.osk for MicroGnuEmacs 1a				Nov 10, 1986

Copy sys/osk/makefile to .

copy sys/osk/varargs.h to /dd/defs/varargs.h if you don't have one.
(I think version 2.1 of the C compiler will include mine.)

Look at makefile for personal preference options and terminal selection.

Use make to compile.

Currently defined for termcap, assuming a termlib library exists.
(I've heard there will be one with version 2.1 of the C compiler.  I
can't distribute the one I have.)

Baud should be set correctly in tmode/xmode even if it is set in
hardware as it is on a QT+.  This is used for display optimization
and padding.

All files are indented assuming tabs every eight columns, and mg
itself uses tabs there.  I have no idea why Microware decided not to
follow this defacto industry standard, but at least they allow you to
change your system to whatever you want.

The enviornment variable TERM is used to determine your terminal type,
and HOME is used to find the .mg startup file.
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/osk/sysdef.h'
then
	echo shar: will not over-write existing file "'sys/osk/sysdef.h'"
else
cat << \SHAR_EOF > 'sys/osk/sysdef.h'
/*
 * Os9/68K specific definitions for micrognuemacs
 */
#define	PCC			/* "[]" gets an error.			*/
#define	KBLOCK	1024		/* Kill grow.				*/
#define	GOOD	0		/* Good exit status.			*/
#define	VARARGS			/* use my varargs.h rather than		*/
				/* the non-portable code supplied	*/
#define NO_VOID_TYPE		/* void not supported yet		*/
#define	SEOL	'\l'		/* used in search (because \r==\n)	*/
#define PC PC_			/* compiler can't handle variable called PC */
#define SR SR_			/* or SR				*/
#define NO_RESIZE		/* terminal doesn't change size		*/

/* typedefs for gnu version */
typedef int	RSIZE;		/* Type for file/region sizes	*/
typedef short	KEY;		/* Type for internal keystrokes	*/

/*
 * Macros used by the buffer name making code.
 * Start at the end of the file name, scan to the left
 * until BDC1 (or BDC2, if defined) is reached. The buffer
 * name starts just to the right of that location, and
 * stops at end of string (or at the next BDC3 character,
 * if defined). BDC2 and BDC3 are mainly for VMS.
 */
#define	BDC1	'/'			/* Buffer names.		*/

/*
 * Needed for lots of small mallocs on os9/68k.  _memmins should be 
 * (maximum malloced memory)/16.  (defalt _memmins is 4096) 
 * Note that malloc may now fail if there isn't _memmins bytes 
 * contiguous free memory.  _memins could be reduced and the malloc 
 * tried again.  (Not currently implemented.)
 */
#ifdef MAXMEM
#  define SYSINIT	{extern int _memmins;	_memmins=MAXMEM*64; }
#else
#  define SYSINIT	{extern int _memmins;	_memmins=32768; }
#endif

/* see "caveates" in the osk C manual on _strass */
#define bcopy(from,to,len)	_strass(to,from,len)

/* see comments on these in display.c.  OSK can't stand the wasted memory
 * without making the score array "remote", which generates lousy code.  
 * Besides, I don't have an extra 100kb of memory for the score array.
 */
#define	XCHAR	char
#define XSHORT	short
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/osk/varargs.h'
then
	echo shar: will not over-write existing file "'sys/osk/varargs.h'"
else
cat << \SHAR_EOF > 'sys/osk/varargs.h'
/* varargs.h for os9/68k by Robert A. Larson	*/
/* version 0 for os9/68k C 2.0 04/20/86		*/
/* varargs is a "portable" way to write a routine that takes a variable */
/* number of arguements.  This implemination agrees with both the 4.2bsd*/
/* and Sys V documentation of varargs.  Note that just because varargs.h*/
/* is used does not mean that it is used properly.			*/
/* Ignore the "expression with little effect" warnings.  (Seems to be a */
/* compiler bug.)							*/

#define va_alist	_va_arg1, _va_arg2, _va_arg3

#define va_dcl		unsigned _va_arg1, _va_arg2, _va_arg3;

typedef	struct {
	  unsigned _va_at;  /* number of arguments used, 0, 1, or more  */
                            /* (double as first arg counts as 2)        */
	  union {
	    struct {
	      unsigned _va_uns1, _va_uns2;
	    } _va_uuns;
	    double _va_udouble;
	  } _va_union;
	  char *_va_pointer;
        } va_list;

#define	va_start(pvar)	( (pvar)._va_at = 0,				\
			  (pvar)._va_union._va_uuns._va_uns1 = _va_arg1,\
			  (pvar)._va_union._va_uuns._va_uns2 = _va_arg2,\
			  (pvar)._va_pointer = (char *) &_va_arg3	\
			)

#define va_arg(pvar, type)	(				\
	((pvar)._va_at++) ? (					\
		((pvar)._va_at == 2) ? (			\
			(sizeof(type) == 8) ? (			\
				*(((type *)((pvar)._va_pointer))++)	\
			) : (type)(				\
				(pvar)._va_union._va_uuns._va_uns2	\
			)					\
		) : (						\

			*(((type *)((pvar)._va_pointer))++)	\
		)						\
	) : (							\
		(sizeof(type) == 8) ? (type)(			\
			(pvar)._va_at++,			\
			(pvar)._va_union._va_udouble		\
		) : (type)(					\
			(pvar)._va_union._va_uuns._va_uns1	\
		)						\
	)							\
)

#define va_end(pvar)				/* va_end is simple */
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/osk/fileio.c'
then
	echo shar: will not over-write existing file "'sys/osk/fileio.c'"
else
cat << \SHAR_EOF > 'sys/osk/fileio.c'
/*
 * Os9/68k fileio.c for MicroGnuEmacs by Robert A. Larson
 *	 system dependent file io routines
 */
#include	"def.h"

char	*getenv();

static	FILE	*ffp;

/*
 * Open a file for reading.
 */
ffropen(fn)
char	*fn;
{
	if ((ffp=fopen(fn, "r")) == NULL)
		return (FIOFNF);
	return (FIOSUC);
}

/*
 * Open a file for writing.
 * Return TRUE if all is well, and
 * FALSE on error (cannot create).
 */
ffwopen(fn)
char	*fn;
{
	if ((ffp=fopen(fn, "w")) == NULL) {
		ewprintf("Cannot open file for writing");
		return (FIOERR);
	}
	return (FIOSUC);
}

/*
 * Close a file.
 * Should look at the status.
 */
ffclose()
{
	fclose(ffp);
	return (FIOSUC);
}

/*
 * Write a line to the already
 * opened file. The "buf" points to the
 * buffer, and the "nbuf" is its length, less
 * the free newline. Return the status.
 * Check only at the newline.
 */
ffputline(buf, nbuf)
register char	buf[];
{
	register int	i;

	for (i=0; i<nbuf; ++i)
		putc(buf[i]&0xFF, ffp);
	putc('\n', ffp);
	if (ferror(ffp) != FALSE) {
		ewprintf("Write I/O error");
		return (FIOERR);
	}
	return (FIOSUC);
}

/*
 * Read a line from a file, and store the bytes
 * in the supplied buffer. Stop on end of file or end of
 * line. Don't get upset by files that don't have an end of
 * line on the last line; this seem to be common on CP/M-86 and
 * MS-DOS (the suspected culprit is VAX/VMS kermit, but this
 * has not been confirmed. If this is sufficiently researched
 * it may be possible to pull this kludge). 
 */
ffgetline(buf, nbuf)
register char	*buf;
{
	register int	c;
	register int	i;

	i = 0;
	for (;;) {
		c = getc(ffp);
		if (c==EOF || c=='\n')		/* End of line.		*/
			break;
		if (i >= nbuf-1) {
			ewprintf("File has long line");
			return (FIOERR);
		}
		buf[i++] = c;
	}
	if (c == EOF) {				/* End of file.		*/
		if (ferror(ffp) != FALSE) {
			ewprintf("File read error");
			return (FIOERR);
		}
		if (i == 0)			/* Don't get upset if	*/
			return (FIOEOF);	/* no newline at EOF.	*/
	}
	buf[i] = 0;
	return (FIOSUC);
}

#ifdef BACKUP
/*
 * Rename the file "fname" into a backup copy.
 * The backup copy is the same name with ".BAK" appended unless the file
 * name is to long.  If your file name is 28 characters long ending in ".BAK"
 * you lose.  The error handling is all in "file.c". 
 */
fbackupfile(fname)
char	*fname;
{
	register char	*params;
	int	status;
	register char	*fn;
	register int	fnamel;
	register int	fnl;
	char	*rindex();

	if((fn = rindex(fname, '/')) == NULL) fn = fname; else fn++;
	fnamel = strlen(fname);
	fnl = strlen(fn);
	if((params = malloc(strlen(fname)+strlen(fn)+6)) == NULL) 
		return(ABORT);
/* delete the old backup */
	strcpy(params, fname);
	if(fnl < 25) strcat(params, ".BAK");
		else strcpy(params+(fnamel-fnl+24), ".BAK");
	unlink(params);				/* ignore errors */
/* now do the rename (This is rather akward) */
	strcpy(params, fname);
	strcat(params, " ");
	strcat(params, fn);
	if(fnl < 25) strcat(params, ".BAK");
		else strcpy(params+fnamel+1+24, ".BAK");
	if(os9fork("rename", strlen(params)+1, params, 0, 0, 0, 0)==-1) {
		free(params);
		return (FALSE);
	}
	wait(&status);
	free(params);
	return ((status & 0xffff)==0);
}
#endif

/*
 * The string "fn" is a file name.
 * Perform any required case adjustments. All sustems
 * we deal with so far have case insensitive file systems.
 * We zap everything to lower case.  The problem we are trying
 * to solve is getting 2 buffers holding the same file if
 * you visit one of them with the "caps lock" key down.
 * On UNIX file names are dual case, so we leave
 * everything alone.  Os9's dual case storage but non-case sensitivity 
 * does not seem to be accounted for here.  I'm treating it as a 
 * mono-case system, but it would be better to beleive the file (if found)
 * or the user (if not).
 */
adjustcase(fn)
register char	*fn;
{
	register int	c;

	while ((c = *fn) != 0) {
		if (c>='A' && c<='Z')
			*fn = c + 'a' - 'A';
		++fn;
	}
}

#ifndef MICRO
char *startupfile()
{
	static char startname[64];
	char *cp;
  
	if ((cp = getenv("HOME")) == NULL) return ".mg";
	strncpy(startname, cp, 64 - 4);
	strcat(startname, "/.mg");
	return startname;
}
#endif
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/osk/spawn.c'
then
	echo shar: will not over-write existing file "'sys/osk/spawn.c'"
else
cat << \SHAR_EOF > 'sys/osk/spawn.c'
/*
 * Name:	MicroEMACS
 *		OS9/68k Spawn Shell
 * Version:	29ral
 * Last edit:	04/20/86
 * By:		Blarson at Usc-Ecl.Arpa
 *
 */
#include	"def.h"

#include	<sgstat.h>

extern	struct	sgbuf	oldtty;		/* There really should be a	*/
extern	struct	sgbuf	newtty;		/* nicer way of doing this, so	*/

spawncli(f, n, k)
					/* what are f, n, and k?  They 	*/
					/* arn't used by ultrix, so I	*/
					/* ignore them too.		*/
{
	register int	pid;
	register int	wpid;
	int		status;

	ttcolor(CTEXT);
	ttnowindow();
	ttmove(nrow-1, 0);
	if (epresf != FALSE) {
		tteeol();
		epresf = FALSE;
	}
	ttflush();
	if(_ss_opt(0, &oldtty) == -1) {
		ewprintf("_ss_opt #1 to terminal failed");
		return (FALSE);
	}
	if((pid=os9fork("shell", 0, "", 0, 0, 0, 0)) == -1) {
		ewprintf("Failed to create process");
		return (FALSE);
	}
	while ((wpid=wait(&status))>=0 && wpid!=pid)
		;
	sgarbf = TRUE;				/* Force repaint.	*/
	if(_ss_opt(0, &newtty) == -1) {
		ewprintf("_ss_opt #2 to terminal failed");
		return (FALSE);
	}
	return (TRUE);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/osk/ttyio.c'
then
	echo shar: will not over-write existing file "'sys/osk/ttyio.c'"
else
cat << \SHAR_EOF > 'sys/osk/ttyio.c'
/*
 *	sys/osk/ttyio.c	by Robert A. Larson
 *
 * The functions in this file
 * negotiate with the operating system for
 * keyboard characters, and write characters to
 * the display in a barely buffered fashion.
 */
#include	"def.h"

#include	<sgstat.h>
#ifdef	DPROMPT
#  include	<varargs.h>
#  define S_RDY 2437			/* arbitrary user signal */
#endif

#define	NOBUF	512			/* Output buffer size.		*/

char	obuf[NOBUF];			/* Output buffer.		*/
int	nobuf;
struct	sgbuf	oldtty, newtty;
int	nrow;				/* Terminal size, rows.		*/
int	ncol;				/* Terminal size, columns.	*/
short	ospeed;				/* Terminal speed, for termlib.l */

#ifdef	DPROMPT
wakeup(signum)
int signum;
{
	/* ignore the signal */
}
#endif

/*
 * This function gets called once, to set up
 * the terminal channel.
 */

ttopen()
{
	if(_gs_opt(0, &oldtty) == -1) panic("can't get options");
	ospeed = oldtty.sg_baud;
	_strass(&newtty, &oldtty, sizeof(newtty));	/* newtty=oldtty; */
	if(oldtty.sg_class == 0) { 			/* scf */
		newtty.sg_backsp=
		newtty.sg_delete=
		newtty.sg_echo  =
		newtty.sg_alf   =
		newtty.sg_pause =
		newtty.sg_bspch =
		newtty.sg_dlnch =
		newtty.sg_eorch =
		newtty.sg_eofch =
		newtty.sg_rlnch =
		newtty.sg_dulnch=
		newtty.sg_psch  =
		newtty.sg_kbich =
		newtty.sg_kbach = 0;
#ifndef	xon_xoff
		newtty.sg_xon   =
		newtty.sg_xoff  = 0;
#endif
		if(_ss_opt(0, &newtty) == -1) panic("can't set options");
		nrow = oldtty.sg_page == 0 ? NROW : oldtty.sg_page;
	} else {				/* not scf, fake it */
		nrow = NROW;
	}
	ncol = NCOL;
#ifdef	DPROMPT
	intercept(wakeup);		/* ignore signals */
#endif
}

/*
 * This function gets called just
 * before we go back home to the shell. Put all of
 * the terminal parameters back.
 */
ttclose()
{
	ttflush();
	if(_ss_opt(0, &oldtty) == -1) panic("can't reset options");
}

/*
 * Write character to the display.
 * Characters are buffered up, to make things
 * a little bit more efficient.
 */
ttputc(c)
{
	if (nobuf >= NOBUF)
		ttflush();
	obuf[nobuf++] = c;
}

/*
 * Flush output.
 */
ttflush()
{
	if (nobuf != 0) {
		write(1, obuf, nobuf);
		nobuf = 0;
	}
}

/*
 * Read character from terminal.
 * All 8 bits are returned, so that you can use
 * a multi-national terminal.
 */
ttgetc()
{
	char	buf[1];

	while (read(0, &buf[0], 1) != 1)
		;
	return (buf[0] & 0xFF);
}

int typeahead()
{
  return _gs_rdy(0) > 0;
}

panic(s) char *s; {
  _ss_opt(0, &oldtty);			/*  ignore errors */
  fputs("Panic: ", stdout);		/* avoid printf, don't load all that */
  puts(s);
  exit(1);
}

#ifdef	DPROMPT
ttwait() {
  if(_gs_rdy(0) > 0) return FALSE;	/* already something waiting */
  _ss_ssig(0, S_RDY);			/* wake me when you have something */
  if(sleep(2)!=0) return FALSE;		/* sleep interupted */
  _ss_rel(0);
  return TRUE;
}
#endif
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/osk/makefile'
then
	echo shar: will not over-write existing file "'sys/osk/makefile'"
else
cat << \SHAR_EOF > 'sys/osk/makefile'
# Makefile for OSK MicroGnuEMACS by Robert A. Larson
#	07/12/86	MicroGnuEMACS version
# Copy ./sys/osk/makefile to . before making.  Check
# OPTS and LIBS.
#
# mg is short for micrognuemacs.  Call it what you want.
NAME = mg
# terminal type or termcap
TERM = TERMCAP
# opts is for user definable options, such as:
#	BACKUP	define for automatic backups
#	CVMVAS	define for ^V and M-V to work in pages
#	MAXMEM	memory available to malloc in kbytes.  Default 512 (OSK only)
#	NLINE	maximum line length, default 256.  If big, use -m in LFLAGS.
#	DPROMPT	print delayed prompt strings for ESC, ^X, etc.
#	STARTUP startup file handling
#	PREFIXREGION	functions for prefixing a region
OPTS = -dBACKUP -dMAXMEM=320 -dNLINE=2048 -dDPROMPT -dSTARTUP
# termlib is needed for termcap.
LFLAGS = -l=/dd/lib/termlib.l -m=4
OBJ = basic.r \
 buffer.r \
 cinfo.r \
 display.r \
 echo.r \
 extend.r \
 file.r \
 kbd.r \
 line.r \
 main.r \
 match.r \
 paragraph.r \
 prefix.r \
 random.r \
 region.r \
 search.r \
 symbol.r \
 version.r \
 window.r \
 word.r
# these files are listed individually below
SYSOBJ = SYS/OSK/fileio.r \
 SYS/OSK/spawn.r \
 SYS/OSK/ttyio.r
# ditto
TERMOBJ = TTY/$(TERM)/tty.r \
 TTY/$(TERM)/ttykbd.r
#
$(NAME): $(OBJ) $(SYSOBJ) $(TERMOBJ) makefile
 cc -i -t=/r0 -f=$(NAME) $(LFLAGS) $(OBJ) $(SYSOBJ) $(TERMOBJ)
$(OBJ): def.h sysdef.h ttydef.h makefile
 cc -r -t=/r0 $(OPTS) $*.c
SYS/OSK/fileio.r: SYS/OSK/fileio.c def.h sysdef.h ttydef.h makefile
 cc -r=SYS/OSK -t=/r0 $(OPTS) SYS/OSK/fileio.c
SYS/OSK/spawn.r: SYS/OSK/spawn.c def.h sysdef.h ttydef.h makefile
 cc -r=SYS/OSK -t=/r0 $(OPTS) SYS/OSK/spawn.c
SYS/OSK/ttyio.r: SYS/OSK/ttyio.c def.h sysdef.h ttydef.h makefile
 cc -r=SYS/OSK -t=/r0 $(OPTS) SYS/OSK/ttyio.c
TTY/$(TERM)/tty.r: TTY/$(TERM)/tty.c def.h sysdef.h ttydef.h makefile
 cc -r=TTY/$(TERM) -t=/r0 $(OPTS) TTY/$(TERM)/tty.c
TTY/$(TERM)/ttykbd.r: TTY/$(TERM)/ttykbd.c def.h sysdef.h ttydef.h makefile
 cc -r=TTY/$(TERM) -t=/r0 $(OPTS) TTY/$(TERM)/ttykbd.c
# The touch commands are needed to update the modified time.
sysdef.h: SYS/OSK/sysdef.h
 copy -r -b=16 -w=. SYS/OSK/sysdef.h
 touch sysdef.h
ttydef.h: TTY/$(TERM)/ttydef.h makefile
 copy -r -b=16 -w=. TTY/$(TERM)/ttydef.h
 touch ttydef.h
SHAR_EOF
fi # end of overwriting check
#	End of shell archive
exit 0



More information about the Mod.sources mailing list