v08i022: The JOVE text editor, Part03/13

sources-request at mirror.UUCP sources-request at mirror.UUCP
Wed Feb 4 14:59:07 AEST 1987


Submitted by: seismo!rochester!jpayne (Jonathan Payne)
Mod.sources: Volume 8, Issue 22
Archive-name: jove/Part03

#! /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 all goes well, you will see the message "End of archive 3 (of 13)."
# Contents:  extend.c fp.c funcdefs.c insert.c table.c
PATH=/bin:/usr/bin:/usr/ucb; export PATH
echo shar: extracting "'extend.c'" '(17969 characters)'
if test -f 'extend.c' ; then 
  echo shar: will not over-write existing file "'extend.c'"
else
sed 's/^X//' >extend.c <<'@//E*O*F extend.c//'
X/************************************************************************
X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
X * provided to you without charge, and with no warranty.  You may give  *
X * away copies of JOVE, including sources, provided that this notice is *
X * included in all the files.                                           *
X ************************************************************************/
X
X#include "jove.h"
X#include "io.h"
X#include "termcap.h"
X#include "ctype.h"
X#ifdef JOB_CONTROL
X#	include <signal.h>
X#endif
X
X#include <varargs.h>
X
Xint	InJoverc = 0;
X
Xextern int	getch(),
X		getchar();
X
X/* Auto execute code */
X
X#define NEXECS	20
X
Xprivate struct {
X	char	*a_pattern;
X	data_obj	*a_cmd;
X} AutoExecs[NEXECS] = {0};
X
Xprivate int	ExecIndex = 0;
X
X/* Command auto-execute. */
X
XCAutoExec()
X{
X	DefAutoExec(findcom);
X}
X
X/* Macro auto-execute. */
X
XMAutoExec()
X{
X	DefAutoExec(findmac);
X}
X
X/* VARARGS0 */
X
XDefAutoExec(proc)
Xdata_obj	*(*proc)();
X{
X	data_obj	*d;
X	char	*pattern;
X	int	i;
X
X	if (ExecIndex >= NEXECS)
X		complain("Too many auto-executes, max %d.", NEXECS);
X	if ((d = (*proc)(ProcFmt)) == 0)
X		return;
X	pattern = ask((char *) 0, ": %f %s ", d->Name);
X	for (i = 0; i < ExecIndex; i++)
X		if ((AutoExecs[i].a_cmd == d) &&
X		    (strcmp(pattern, AutoExecs[i].a_pattern) == 0))
X		    	return;		/* Eliminate duplicates. */
X	AutoExecs[ExecIndex].a_pattern = copystr(pattern);
X	AutoExecs[ExecIndex].a_cmd = d;
X	ExecIndex++;
X}
X
X/* DoAutoExec: NEW and OLD are file names, and if NEW and OLD aren't the
X   same kind of file (i.e., match the same pattern) or OLD is 0 and it
X   matches, we execute the command associated with that kind of file. */
X 
XDoAutoExec(new, old)
Xregister char	*new,
X		*old;
X{
X	register int	i;
X
X	exp_p = YES;
X	exp = 1;	/* So minor modes don't toggle.  We always want
X			   them on. */
X	if (new == 0)
X		return;
X	for (i = 0; i < ExecIndex; i++)
X		if ((LookingAt(AutoExecs[i].a_pattern, new, 0)) &&
X		    (old == 0 || !LookingAt(AutoExecs[i].a_pattern, old, 0)))
X			ExecCmd(AutoExecs[i].a_cmd);
X}
X
XBindAKey()
X{
X	BindSomething(findcom);
X}
X
XBindMac()
X{
X	BindSomething(findmac);
X}
X
Xextern int	EscPrefix(),
X		CtlxPrefix(),
X		MiscPrefix();
X
Xdata_obj **
XIsPrefix(cp)
Xdata_obj	*cp;
X{
X	int	(*proc)();
X
X	if (cp == 0 || (cp->Type & TYPEMASK) != FUNCTION)
X		return 0;
X	proc = ((struct cmd *) cp)->c_proc;
X	if (proc == EscPrefix)
X		return pref1map;
X	if (proc == CtlxPrefix)
X		return pref2map;
X	if (proc == MiscPrefix)
X		return miscmap;
X	return 0;
X}
X
Xunbind_aux(c)
X{
X	if (c == CR || c == LF)
X		return FALSE;	/* tells do_ask to return */
X	Insert(c);
X	return !FALSE;
X}
X
XUnbindC()
X{
X	char	*keys;
X	data_obj	**map = mainmap;
X
X	keys = do_ask("\r\n\01\02\03\04\05\06\010\011\013\014\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037", unbind_aux, (char *) 0, ProcFmt);
X	if (keys == 0)
X		return;
X	for (;;) {
X		if (keys[1] == '\0')
X			break;
X		if ((map = IsPrefix(map[*keys])) == 0)
X			break;
X		keys++;
X	}
X	if (keys[1] != 0)
X		complain("That's not a legitimate key sequence.");
X	map[keys[0]] = 0;
X}
X		
Xaddgetc()
X{
X	int	c;
X
X	if (!InJoverc)
X		Asking = strlen(mesgbuf);
X	c = getch();
X	if (InJoverc) {
X		if (c == '\n')
X			return EOF;	/* this isn't part of the sequence */
X		else if (c == '\\') {
X			if ((c = getch()) == LF)
X				complain("[Premature end of line]");
X		} else if (c == '^') {
X			if ((c = getch()) == '?')
X				c = RUBOUT;
X			else if (isalpha(c) || index("[\\]^_", c))
X				c = c - '@';
X			else
X				complain("[Unknown control character]");
X		}
X	}
X
X	Asking = 0;
X	add_mess("%p ", c);
X
X	return c;
X}
X
XBindWMap(map, lastkey, cmd)
Xdata_obj	**map,
X		*cmd;
X{
X	data_obj	**nextmap;
X	int	c;
X
X	c = addgetc();
X	if (c == EOF) {
X		if (lastkey == EOF)
X			complain("[Empty key sequence]");
X		complain("[Premature end of key sequence]");
X	} else {
X		if (nextmap = IsPrefix(map[c]))
X			BindWMap(nextmap, c, cmd);
X		else
X			map[c] = cmd;
X	}
X}
X
X/* VARARGS0 */
X
XBindSomething(proc)
Xdata_obj	*(*proc)();
X{
X	data_obj	*d;
X
X	if ((d = (*proc)(ProcFmt)) == 0)
X		return;
X	s_mess(": %f %s ", d->Name);
X	BindWMap(mainmap, EOF, d);
X}
X
X/* Describe key */
X
XDescWMap(map, key)
Xdata_obj	**map;
X{
X	data_obj	*cp = map[key],
X			**prefp;
X
X	if (cp == 0)
X		add_mess("is unbound.");
X	else if (prefp = IsPrefix(cp))
X		DescWMap(prefp, addgetc());
X	else
X		add_mess("is bound to %s.", cp->Name);
X}
X
XKeyDesc()
X{
X	s_mess(ProcFmt);
X	DescWMap(mainmap, addgetc());
X}
X
XDescCom()
X{
X	data_obj	*dp;
X	char	pattern[100],
X		doc_type[40],
X		*file = CmdDb;
X	File	*fp;
X
X	if (!strcmp(LastCmd->Name, "describe-variable"))
X		dp = (data_obj *) findvar(ProcFmt);
X	else
X		dp = (data_obj *) findcom(ProcFmt);
X
X	if (dp == 0)
X		return;
X	fp = open_file(file, iobuff, F_READ, COMPLAIN, QUIET);
X	Placur(ILI, 0);
X	flusho();
X	sprintf(pattern, "^:entry \"%s\" \"\\([^\"]*\\)\"", dp->Name);
X	TOstart("Help", TRUE);
X	for (;;) {
X		if (f_gets(fp, genbuf, LBSIZE) == EOF) {
X			Typeout("There is no documentation for \"%s\".", dp->Name);
X			goto outahere;
X		}
X		if ((strncmp(genbuf, ":entry", 6) == 0) && LookingAt(pattern, genbuf, 0))
X			break;
X	}
X	/* found it ... let's print it */
X	putmatch(1, doc_type, sizeof doc_type);
X	if (strcmp("Variable", doc_type) == 0)
X		Typeout(dp->Name);
X	else if (strcmp("Command", doc_type) == 0) {
X		char	binding[128];
X
X		find_binds(dp, binding);
X		if (blnkp(binding))
X			Typeout("To invoke %s, type \"ESC X %s<cr>\".",
X				dp->Name,
X				dp->Name);
X		else
X			Typeout("Type \"%s\" to invoke %s.", binding, dp->Name);
X	}
X	Typeout("");
X	while (f_gets(fp, genbuf, LBSIZE) != EOF)
X		if (strncmp(genbuf, ":entry", 6) == 0)
X			goto outahere;
X		else
X			Typeout("%s", genbuf);
Xoutahere:
X	f_close(fp);
X	TOstop();
X}
X
XDescBindings()
X{
X	extern int	Typeout();
X
X	TOstart("Key Bindings", TRUE);
X	DescMap(mainmap, NullStr);
X	TOstop();
X}
X
XDescMap(map, pref)
Xdata_obj	**map;
Xchar	*pref;
X{
X	int	c1,
X		c2 = 0,
X		numbetween;
X	char	keydescbuf[40];
X	data_obj	**prefp;
X
X	for (c1 = 0; c1 < 0200 && c2 < 0200; c1 = c2 + 1) {
X		c2 = c1;
X		if (map[c1] == 0)
X			continue;
X		while (++c2 < 0200 && map[c1] == map[c2])
X			;
X		c2--;
X		numbetween = c2 - c1;
X		if (numbetween == 1)
X			sprintf(keydescbuf, "%s {%p,%p}", pref, c1, c2);
X		else if (numbetween == 0)
X			sprintf(keydescbuf, "%s %p", pref, c1);
X		else
X			sprintf(keydescbuf, "%s [%p-%p]", pref, c1, c2);
X		if (prefp = IsPrefix(map[c1]))
X			DescMap(prefp, keydescbuf);
X		else
X			Typeout("%-14s%s", keydescbuf, map[c1]->Name);
X	}
X}
X
Xprivate
Xfind_binds(dp, buf)
Xdata_obj	*dp;
Xchar	*buf;
X{
X	char	*endp;
X
X	buf[0] = '\0';
X	fb_aux(dp, mainmap, (char *) 0, buf);
X	endp = buf + strlen(buf) - 2;
X	if ((endp > buf) && (strcmp(endp, ", ") == 0))
X		*endp = '\0';
X}
X
Xprivate
Xfb_aux(cp, map, prefix, buf)
Xregister data_obj	*cp,
X			**map;
Xchar	*buf,
X	*prefix;
X{
X	int	c1,
X		c2;
X	char	*bufp = buf + strlen(buf),
X		prefbuf[20];
X	data_obj	**prefp;
X
X	for (c1 = c2 = 0; c1 < 0200 && c2 < 0200; c1 = c2 + 1) {
X		c2 = c1;
X		if (map[c1] == cp) {
X			while (++c2 < 0200 && map[c1] == map[c2])
X				;
X			c2--;
X			if (prefix)
X				sprintf(bufp, "%s ", prefix);
X			bufp += strlen(bufp);
X			switch (c2 - c1) {
X			case 0:
X				sprintf(bufp, "%p, ", c1);
X				break;
X	
X			case 1:
X				sprintf(bufp, "{%p,%p}, ", c1, c2);
X				break;
X	
X			default:
X				sprintf(bufp, "[%p-%p], ", c1, c2);
X				break;
X			}
X		}
X		if (prefp = IsPrefix(map[c1])) {
X			sprintf(prefbuf, "%p", c1);
X			fb_aux(cp, prefp, prefbuf, bufp);
X		}
X		bufp += strlen(bufp);
X	}
X}
X
XApropos()
X{
X	register struct cmd	*cp;
X	register struct macro	*m;
X	register struct variable	*v;
X	char	*ans;
X	int	anyfs = 0,
X		anyvs = 0,
X		anyms = 0;
X	char	buf[256];
X
X	ans = ask((char *) 0, ": %f (keyword) ");
X	TOstart("Help", TRUE);
X	for (cp = commands; cp->Name != 0; cp++)
X		if (sindex(ans, cp->Name)) {
X			if (anyfs == 0) {
X				Typeout("Commands");
X				Typeout("--------");
X			}
X			find_binds((data_obj *) cp, buf);
X			if (buf[0])
X				Typeout(": %-35s(%s)", cp->Name, buf);
X			else
X				Typeout(": %s", cp->Name);
X			anyfs++;
X		}
X	if (anyfs)
X		Typeout(NullStr);
X	for (v = variables; v->Name != 0; v++)
X		if (sindex(ans, v->Name)) {
X			if (anyvs == 0) {
X				Typeout("Variables");
X				Typeout("---------");
X			}
X			anyvs++;
X			vpr_aux(v, buf);
X			Typeout(": set %-26s%s", v->Name, buf);
X		}
X	if (anyvs)
X		Typeout(NullStr);
X	for (m = macros; m != 0; m = m->m_nextm)
X		if (sindex(ans, m->Name)) {
X			if (anyms == 0) {
X				Typeout("Macros");
X				Typeout("------");
X			}
X			anyms++;
X			find_binds((data_obj *) m, buf);
X			if (buf[0])
X				Typeout(": %-35s(%s)", m->Name, buf);
X			else
X				Typeout(": %-35s%s", "execute-macro", m->Name);
X		}
X	TOstop();
X}
X
XExtend()
X{
X	data_obj	*d;
X
X	if (d = findcom(": "))
X		ExecCmd(d);
X}
X
X/* Read a positive integer from CP.  It must be in base BASE, and
X   complains if it isn't.  If allints is nonzero, all the characters
X   in the string must be integers or we return -1; otherwise we stop
X   reading at the first nondigit. */
X
Xchr_to_int(cp, base, allints)
Xregister char	*cp;
X{
X	register int	c;
X	int	value = 0;
X
X	while (c = *cp++) {
X		if (!isdigit(c)) {
X			if (allints)
X				return -1;
X			break;
X		}
X		c = c - '0';
X		if (c >= base)
X			complain("You must specify in base %d.", base);
X		value = value * base + c;
X	}
X	return value;
X}
X
Xask_int(prompt, base)
Xchar	*prompt;
Xint	base;
X{
X	char	*val = ask((char *) 0, prompt);
X	int	value = chr_to_int(val, base, 1);
X
X	if (value < 0)
X		complain("That's not a number!");
X	return value;
X}
X
Xprivate
Xvpr_aux(vp, buf)
Xregister struct variable	*vp;
Xchar	*buf;
X{
X	switch (vp->v_flags & V_TYPEMASK) {
X	case V_BASE10:
X		sprintf(buf, "%d", *(vp->v_value));
X		break;
X
X	case V_BASE8:
X		sprintf(buf, "%o", *(vp->v_value));
X		break;
X
X	case V_BOOL:
X		sprintf(buf, (*(vp->v_value)) ? "on" : "off");
X		break;
X
X	case V_STRING:
X	case V_FILENAME:
X		sprintf(buf, "%s", (char *) vp->v_value);
X		break;
X
X	case V_CHAR:
X		sprintf(buf, "%p", *(vp->v_value));
X		break;
X	}
X}
X
XPrVar()
X{
X	struct variable	*vp;
X	char	prbuf[256];
X
X	if ((vp = (struct variable *) findvar(ProcFmt)) == 0)
X		return;
X	vpr_aux(vp, prbuf);
X	s_mess(": %f %s => %s", vp->Name, prbuf);
X}
X
XSetVar()
X{
X	struct variable	*vp;
X	char	*prompt;
X
X	if ((vp = (struct variable *) findvar(ProcFmt)) == 0)
X		return;
X	prompt = sprint(": %f %s ", vp->Name);
X
X	switch (vp->v_flags & V_TYPEMASK) {
X	case V_BASE10:
X	case V_BASE8:
X	    {
X	    	int	value;
X
X		value = ask_int(prompt, ((vp->v_flags & V_TYPEMASK) == V_BASE10)
X					  ? 10 : 8);
X		*(vp->v_value) = value;
X	    	break;
X	    }
X
X	case V_BOOL:
X	    {
X	    	char	*def = *(vp->v_value) ? "off" : "on",
X	    		*on_off;
X	    	int	value;
X
X	    	on_off = ask(def, prompt);
X		if (casecmp(on_off, "on") == 0)
X			value = ON;
X	    	else if (casecmp(on_off, "off") == 0)
X	    		value = OFF;
X	    	else
X	    		complain("Boolean variables must be ON or OFF.");
X	    	*(vp->v_value) = value;
X	    	s_mess("%s%s", prompt, value ? "on" : "off");
X	    	break;
X	    }
X
X	case V_FILENAME:
X	    {
X		char	fbuf[FILESIZE];
X
X	    	sprintf(&prompt[strlen(prompt)], "(default %s) ", vp->v_value);
X	    	(void) ask_file(prompt, (char *) vp->v_value, fbuf);
X		strcpy((char *) vp->v_value, fbuf);
X	    	break;
X	    }
X
X	case V_STRING:
X	    {
X		char	*str;
X
X	    	/* Do_ask() so you can set string to "" if you so desire. */
X	    	str = do_ask("\r\n", (int (*)()) 0, (char *) vp->v_value, prompt);
X	    	if (str == 0)
X			str = NullStr;
X	    	strcpy((char *) vp->v_value, str);
X		/* ... and hope there is enough room. */
X	    	break;
X	    }
X	case V_CHAR:
X		f_mess(prompt);
X	    	*(vp->v_value) = addgetc();
X		break;	    	
X
X	}
X	if (vp->v_flags & V_MODELINE)
X		UpdModLine++;
X	if (vp->v_flags & V_CLRSCREEN)
X		ClAndRedraw();
X	if (vp->v_flags & V_TTY_RESET)
X		tty_reset();
X}
X			
X/* Command completion - possible is an array of strings, prompt is
X   the prompt to use, and flags are ... well read jove.h.
X
X   If flags are RET_STATE, and the user hits <return> what they typed
X   so far is in the Minibuf string. */
X
Xprivate char	**Possible;
Xprivate int	comp_value,
X		comp_flags;
X
Xaux_complete(c)
X{
X	int	command,
X		length,
X		i;
X
X	if (comp_flags & CASEIND) {
X		char	*lp;
X
X		for (lp = linebuf; *lp != '\0'; lp++)
X			if (isupper(*lp))
X				*lp = tolower(*lp);
X	}
X	switch (c) {
X	case EOF:
X		comp_value = -1;
X		return 0;
X
X	case '\r':
X	case '\n':
X		command = match(Possible, linebuf);
X		if (command >= 0) {
X			comp_value = command;
X			return 0;	/* tells ask to stop */
X		}
X		if (eolp() && bolp()) {
X			comp_value = NULLSTRING;
X			return 0;
X		}
X		if (comp_flags & RET_STATE) switch (command) {
X			case UNIQUE:
X			case ORIGINAL:
X			case NULLSTRING:
X				comp_value = command;
X				return 0;
X
X			default:
X				break;
X		}
X		if (InJoverc)
X			complain("[\"%s\" unknown]", linebuf);
X		rbell();
X		break;
X
X	case '\t':
X	case ' ':
X	    {
X		int	minmatch = 1000,
X	    		maxmatch = 0,
X	    		numfound = 0,
X	    		lastmatch = -1,
X			length = strlen(linebuf);
X
X		for (i = 0; Possible[i] != 0; i++) {
X			int	this_len;
X
X			this_len = numcomp(Possible[i], linebuf);
X			maxmatch = max(maxmatch, this_len);
X			if (this_len >= length) {
X				if (numfound)
X					minmatch = min(minmatch, numcomp(Possible[lastmatch], Possible[i]));
X				else
X					minmatch = strlen(Possible[i]);
X				numfound++;
X				lastmatch = i;
X				if (strcmp(linebuf, Possible[i]) == 0)
X					break;
X			}
X		}
X
X		if (numfound == 0) {
X			rbell();
X			if (InJoverc)
X				complain("[\"%s\" unknown]", linebuf);
X			/* If we're not in the .joverc then
X			   let's do something helpful for the
X			   user. */
X			if (maxmatch < length) {
X				char	*cp;
X
X				cp = linebuf + maxmatch;
X				*cp = 0;
X				Eol();
X			}
X			break;
X		}
X	    	if (c != '\t' && numfound == 1) {
X	    		comp_value = lastmatch;
X			return 0;
X		}
X		null_ncpy(linebuf, Possible[lastmatch], minmatch);
X	    	Eol();
X		if (minmatch == length)	/* No difference */
X			rbell();
X		break;
X	    }
X
X	case '?':
X		if (InJoverc)
X			complain((char *) 0);
X		/* kludge: in case we're using UseBuffers, in which case
X		   linebuf gets written all over */
X		strcpy(Minibuf, linebuf);
X		length = strlen(Minibuf);
X		TOstart("Completion", TRUE);	/* for now ... */
X		for (i = 0; Possible[i]; i++)
X			if (numcomp(Possible[i], Minibuf) >= length) {
X				Typeout(Possible[i]);
X				if (TOabort != 0)
X					break;
X			}
X
X		TOstop();
X		break;
X	}
X	return !FALSE;
X}
X
Xcomplete(possible, prompt, flags)
Xregister char	*possible[];
Xchar	*prompt;
X{
X	Possible = possible;
X	comp_flags = flags;
X	(void) do_ask("\r\n \t?", aux_complete, NullStr, prompt);
X	return comp_value;
X}
X
Xmatch(choices, what)
Xregister char	**choices,
X		*what;
X{
X	register int	len;
X	int	i,
X		found = 0,
X		save,
X		exactmatch = -1;
X
X	len = strlen(what);
X	if (len == 0)
X		return NULLSTRING;
X	for (i = 0; choices[i]; i++) {
X		if (strncmp(what, choices[i], len) == 0) {
X			if (strcmp(what, choices[i]) == 0)
X				exactmatch = i;
X			save = i;
X			found++;	/* Found one. */
X		}
X	}
X
X	if (found == 0)
X		save = ORIGINAL;
X	else if (found > 1) {
X		if (exactmatch != -1)
X			save = exactmatch;
X		else
X			save = AMBIGUOUS;
X	}
X
X	return save;
X}
X
XSource()
X{
X	char	*com,
X		buf[FILESIZE];
X
X	sprintf(buf, "%s/.joverc", getenv("HOME"));
X	com = ask_file((char *) 0, buf, buf);
X	if (joverc(buf) == NIL)
X		complain(IOerr("read", com));
X}
X
XBufPos()
X{
X	register Line	*lp = curbuf->b_first;
X	register int	i,
X			dotline;
X	long	dotchar,
X		nchars;
X
X	for (i = nchars = 0; lp != 0; i++, lp = lp->l_next) {
X		if (lp == curline) {
X			dotchar = nchars + curchar;
X			dotline = i + 1;
X		}
X		nchars += length(lp) + (lp->l_next != 0); /* include the NL */
X	}
X
X	s_mess("[\"%s\" line %d of %d, char %D of %D (%d%%)]",
X			filename(curbuf),
X			dotline,
X			i,
X			dotchar,
X			nchars,
X			(int) (((long) dotchar * 100) / nchars));
X}
X
X#define IF_UNBOUND	-1
X#define IF_TRUE		1
X#define IF_FALSE	!IF_TRUE
X
Xdo_if(cmd)
Xchar	*cmd;
X{
X	int	pid,
X		status;
X
X	switch (pid = fork()) {
X	case -1:
X		complain("[Fork failed: if]");
X
X	case 0:
X	    {
X		char	*args[12],
X			*cp = cmd,
X			**ap = args;
X
X	    	*ap++ = cmd;
X	    	for (;;) {
X			if ((cp = index(cp, ' ')) == 0)
X				break;
X			*cp++ = '\0';
X			*ap++ = cp;
X		}
X		*ap = 0;
X
X		close(0);	/*	we want reads to fail */
X		/* close(1);	 but not writes or ioctl's
X		close(2);    */
X
X	    	(void) execvp(args[0], args);
X		_exit(-10);	/* signals exec error (see below) */
X	    }
X	}
X#ifdef IPROCS
X	sighold(SIGCHLD);
X#endif
X	dowait(pid, &status);
X#ifdef IPROCS
X	sigrelse(SIGCHLD);
X#endif
X	if (status == -10)
X		complain("[Exec failed]");
X	if (status < 0)
X		complain("[Exit %d]", status);
X	return (status == 0);	/* 0 means successful */
X}
X
Xjoverc(file)
Xchar	*file;
X{
X	char	buf[LBSIZE],
X		lbuf[128];
X	int	lnum = 0,
X		eof = FALSE;
X	jmp_buf	savejmp;
X	int	IfStatus = IF_UNBOUND;
X	File	*fp;
X
X	fp = open_file(file, buf, F_READ, !COMPLAIN, QUIET);
X	if (fp == NIL)
X		return NIL;
X
X	/* Catch any errors, here, and do the right thing with them,
X	   and then restore the error handle to whoever did a setjmp
X	   last. */
X
X	push_env(savejmp);
X	if (setjmp(mainjmp)) {
X		Buffer	*savebuf = curbuf;
X
X		SetBuf(do_select((Window *) 0, "RC errors"));
X		ins_str(sprint("%s:%d:%s\t%s\n", pr_name(file), lnum, lbuf, mesgbuf), NO);
X		unmodify();
X		SetBuf(savebuf);
X		Asking = 0;
X	}
X	InJoverc = 1;
X	if (!eof) do {
X		eof = (f_gets(fp, lbuf, sizeof lbuf) == EOF);
X		lnum++;
X		if (casencmp(lbuf, "if", 2) == 0) {
X			char	cmd[128];
X
X			if (IfStatus != IF_UNBOUND)
X				complain("[Cannot have nested if's]");
X			if (LookingAt("if[ \t]*\\(.*\\)$", lbuf, 0) == 0)
X				complain("[If syntax error]");
X			putmatch(1, cmd, sizeof cmd);
X			IfStatus = do_if(cmd) ? IF_TRUE : IF_FALSE;
X			continue;
X		} else if (casencmp(lbuf, "else", 4) == 0) {
X			if (IfStatus == IF_UNBOUND)
X				complain("[Unexpected `else']");
X			IfStatus = !IfStatus;
X			continue;
X		} else if (casencmp(lbuf, "endif", 5) == 0) {
X			if (IfStatus == IF_UNBOUND)
X				complain("[Unexpected `endif']");
X			IfStatus = IF_UNBOUND;
X			continue;
X		}
X		if (IfStatus == IF_FALSE)
X			continue;
X		(void) strcat(lbuf, "\n");
X		Inputp = lbuf;
X		while (*Inputp == ' ' || *Inputp == '\t')
X			Inputp++;	/* skip white space */
X		Extend();
X	} while (!eof);
X
X	f_close(fp);
X	pop_env(savejmp);
X	Inputp = 0;
X	Asking = 0;
X	InJoverc = 0;
X	if (IfStatus != IF_UNBOUND)
X		complain("[Missing endif]");
X	return !NIL;
X}
@//E*O*F extend.c//
if test 17969 -ne "`wc -c <'extend.c'`"; then
    echo shar: error transmitting "'extend.c'" '(should have been 17969 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'fp.c'" '(5151 characters)'
if test -f 'fp.c' ; then 
  echo shar: will not over-write existing file "'fp.c'"
else
sed 's/^X//' >fp.c <<'@//E*O*F fp.c//'
X/************************************************************************
X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
X * provided to you without charge, and with no warranty.  You may give  *
X * away copies of JOVE, including sources, provided that this notice is *
X * included in all the files.                                           *
X ************************************************************************/
X
X#include "jove.h"
X#include "io.h"
X#include "termcap.h"
X#include <sys/stat.h>
X#include <sys/file.h>
X#include <errno.h>
X
X#define MAXFILES	20	/* good enough for my purposes */
X
Xstatic File	_openfiles[MAXFILES] = {0};
X
Xstatic File *
Xf_alloc(name, flags, fd, buffer, buf_size)
Xchar	*name,
X	*buffer;
X{
X	register File	*fp;
X	register int	i;
X
X	for (fp = _openfiles, i = 0; i < MAXFILES; i++, fp++)
X		if (fp->f_flags == 0)
X			break;
X	if (i == MAXFILES)
X		complain("[Too many open files!]");
X	fp->f_bufsize = buf_size;
X	fp->f_cnt = 0;
X	fp->f_fd = fd;
X	fp->f_flags = flags;
X	if (buffer == 0) {
X		buffer = emalloc(buf_size);
X		fp->f_flags |= F_MYBUF;
X	}
X	fp->f_base = fp->f_ptr = buffer;
X	fp->f_name = copystr(name);
X
X	return fp;
X}
X
Xgc_openfiles()
X{
X	register File	*fp;
X
X	for (fp = _openfiles; fp < &_openfiles[MAXFILES]; fp++)
X		if (fp->f_flags != 0 && (fp->f_flags & F_LOCKED) == 0)
X			f_close(fp);
X}
X
XFile *
Xfd_open(name, flags, fd, buffer, bsize)
Xchar	*name,
X	*buffer;
X{
X	return f_alloc(name, flags, fd, buffer, bsize);
X}
X
XFile *
Xf_open(name, flags, buffer, buf_size)
Xchar	*name,
X	*buffer;
X{
X	register int	fd;
X	int	mode = F_MODE(flags);
X
X	if (mode == F_READ)
X		fd = open(name, 0);
X	if (mode == F_APPEND) {
X		fd = open(name, 1);
X		if (fd == -1)
X			mode = F_WRITE;
X		else
X			(void) lseek(fd, 0L, 2);
X	}
X	if (mode == F_WRITE)
X		fd = creat(name, CreatMode);
X	if (fd == -1)
X		return NIL;
X	return f_alloc(name, flags, fd, buffer, buf_size);
X}
X
Xf_close(fp)
XFile	*fp;
X{
X	flush(fp);
X#ifdef BSD4_2 
X	if (fp->f_flags & (F_WRITE|F_APPEND))
X		(void) fsync(fp->f_fd);
X#endif 
X	(void) close(fp->f_fd);
X	if (fp->f_flags & F_MYBUF)
X		free(fp->f_base);
X	free(fp->f_name);
X	fp->f_flags = 0;	/* indicates that we're available */
X}
X
Xfilbuf(fp)
XFile	*fp;
X{
X	if (fp->f_flags & (F_EOF|F_ERR))
X		return EOF;
X	fp->f_ptr = fp->f_base;
X	fp->f_cnt = read(fp->f_fd, fp->f_base, fp->f_bufsize);
X	if (fp->f_cnt == -1) {
X		printf("[Read error %d]", errno);
X		fp->f_flags |= F_ERR;
X	}
X	if (fp->f_cnt == 0) {
X		fp->f_flags |= F_EOF;
X		return EOF;
X	}
X	io_chars += fp->f_cnt;
X	return getc(fp);
X}
X
Xputstr(s)
Xregister char	*s;
X{
X	register int	c;
X
X	while (c = *s++)
X		putchar(c);
X}
X
Xfputnchar(s, n, fp)
Xregister char	*s;
Xregister int	n;
Xregister File	*fp;
X{
X	while (--n >= 0)
X		putc(*s++, fp);
X}
X
Xflusho()
X{
X	_flush(EOF, stdout);
X}
X
Xflush(fp)
XFile	*fp;
X{
X	_flush(EOF, fp);
X}
X
X_flush(c, fp)
Xregister File	*fp;
X{
X	register int	n;
X
X	if (fp->f_flags & (F_READ | F_STRING | F_ERR))
X		return;
X	if (((n = (fp->f_ptr - fp->f_base)) > 0) &&
X	    (write(fp->f_fd, fp->f_base, n) != n) &&
X	    (fp != stdout)) {
X	    	fp->f_flags |= F_ERR;
X		error("[I/O error(%d); file = %s, fd = %d]",
X			errno, fp->f_name, fp->f_fd);
X	}
X
X	if (fp == stdout)
X		OkayAbort = YES;
X	fp->f_cnt = fp->f_bufsize;
X	fp->f_ptr = fp->f_base;
X	if (c != EOF)
X		putc(c, fp);
X}
X
Xf_gets(fp, buf, max)
Xregister File	*fp;
Xchar	*buf;
X{
X	register char	*cp = buf;
X	register int	c;
X	char	*endp = buf + max - 1;
X
X	if (fp->f_flags & F_EOF)
X		return EOF;
X	while (((c = getc(fp)) != EOF) && (c != '\n')) {
X		if (c == NULL)
X			continue;	/* sorry we don't read nulls */
X		if (cp >= endp) {
X			add_mess(" [Line too long]");
X			rbell();
X			return EOF;
X		}
X		*cp++ = c;
X	}
X	*cp = '\0';
X	if (c == EOF) {
X		if (cp != buf)
X			add_mess(" [Incomplete last line]");
X		fp->f_flags |= F_EOF;
X		return EOF;
X	}
X	io_lines++;
X	return NIL;	/* this means okay */
X}
X
X/* Deals with output to the terminal, setting up the amount of characters
X   to be buffered depending on the output baud rate.  Why it's in a 
X   separate file I don't know ... */
X
Xstatic char	one_buf;
X
Xint	BufSize = 1;
X
Xstatic File	_stdout = {1, 1, 1, F_WRITE, &one_buf, &one_buf};
XFile	*stdout = &_stdout;
X
X/* put a string with padding */
X
Xtputc(c)
X{
X	putchar(c);
X}
X
X#undef putchar		/* for files which forget to include io.h,
X			   here's a real putchar procedure. */
Xputchar(c)
X{
X	putc(c, stdout);
X}
X
Xputpad(str, lines)
Xchar	*str;
X{
X	if (str)
X		tputs(str, lines, tputc);
X}
X
X/* Determine the number of characters to buffer at each baud rate.  The
X   lower the number, the quicker the response when new input arrives.  Of
X   course the lower the number, the more prone the program is to stop in
X   output.  Decide what matters most to you. This sets BufSize to the right
X   number or chars, and initiaizes `stdout'.  */
X
Xsettout(ttbuf)
Xchar	*ttbuf;
X{
X	static int speeds[] = {
X		1,	/* 0	*/
X		1,	/* 50	*/
X		1,	/* 75	*/
X		1,	/* 110	*/
X		1,	/* 134	*/
X		1,	/* 150	*/
X		1,	/* 200	*/
X		2,	/* 300	*/
X		4,	/* 600	*/
X		8,	/* 1200 */
X		16,	/* 1800	*/
X		32,	/* 2400	*/
X		128,	/* 4800	*/
X		256,	/* 9600	*/
X		512,	/* EXTA	*/
X		512	/* EXT	*/
X	};
X	BufSize = min(512, (speeds[ospeed] * max(LI / 24, 1)));
X	stdout = fd_open("/dev/tty", F_WRITE|F_LOCKED, 1, ttbuf, BufSize);
X}
X
@//E*O*F fp.c//
if test 5151 -ne "`wc -c <'fp.c'`"; then
    echo shar: error transmitting "'fp.c'" '(should have been 5151 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'funcdefs.c'" '(15977 characters)'
if test -f 'funcdefs.c' ; then 
  echo shar: will not over-write existing file "'funcdefs.c'"
else
sed 's/^X//' >funcdefs.c <<'@//E*O*F funcdefs.c//'
X/************************************************************************
X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
X * provided to you without charge, and with no warranty.  You may give  *
X * away copies of JOVE, including sources, provided that this notice is *
X * included in all the files.                                           *
X ************************************************************************/
X
X#include "jove.h"
X
X#ifndef TXT_TO_C
Xextern int
X	EscPrefix(),
X	CtlxPrefix(),
X	MiscPrefix(),
X	UnbindC(),
X	ShowVersion(),
X	WVisSpace(),
X#ifdef ANSICODES
X	AnsiCodes(),
X#endif
X	AppReg(),
X	Apropos(),
X	BackChar(),
X	BList(),
X	FList(),
X	BUpList(),
X	FDownList(),
X	BSexpr(),
X	BackWord(),
X	Bof(),
X	Bol(),
X	Bos(),
X	Bow(),
X	BindAKey(),
X	BindMac(),
X	BufPos(),
X	CasRegLower(),
X	CasRegUpper(),
X	CapChar(),
X	CapWord(),
X	LowWord(),
X	UppWord(),
X#ifdef CHDIR
X	Chdir(),
X	prCWD(),
X	prDIRS(),
X	Pushd(),
X	Popd(),
X#endif
X	prCTIME(),
X	ChrToOct(),
X	ClAndRedraw(),
X	MakeErrors(),
X	CopyRegion(),
X	BufSelect(),
X	DelBlnkLines(),
X	DelNChar(),
X	DelNWord(),
X	OneWindow(),
X	DelPChar(),
X	DelPWord(),
X	DelReg(),
X	KillSome(),
X	DelWtSpace(),
X	DelCurWindow(),
X	KeyDesc(),
X	Digit(),
X	Digit0(),
X	Digit1(),
X	Digit2(),
X	Digit3(),
X	Digit4(),
X	Digit5(),
X	Digit6(),
X	Digit7(),
X	Digit8(),
X	Digit9(),
X	DescBindings(),
X	DescCom(),
X	Eof(),
X	Eol(),
X	Eos(),
X	Eow(),
X	ForPara(),
X	BackPara(),
X	BufErase(),
X	PtToMark(),
X	Extend(),
X	ExecMacro(),
X	RunMacro(),
X	Leave(),
X	FindFile(),
X	WindFind(),
X	FindTag(),
X	FDotTag(),
X	ToIndent(),
X	ForChar(),
X	FSexpr(),
X	ForWord(),
X	FourTime(),
X	GoLine(),
X	GrowWindow(),
X	IncFSearch(),
X	IncRSearch(),
X	InsFile(),
X	Justify(),
X	RegJustify(),
X	SetLMargin(),
X	SetRMargin(),
X	BufKill(),
X	KillBos(),
X	KillEos(),
X	KillEOL(),
X	KillExpr(),
X	BufList(),
X	NotModified(),
X	NameMac(),
X	DelMacro(),
X	Newline(),
X	OpenLine(),
X	LineAI(),
X	ShowErr(),
X	NextError(),
X	PrevError(),
X	NextLine(),
X	NextPage(),
X	NextWindow(),
X	Recur(),
X	PopMark(),
X	PageNWind(),
X	Tab(),
X	DoParen(),
X	ParseAll(),
X	XParse(),
X#ifdef SPELL
X	SpelWords(),
X#endif
X#ifdef JOB_CONTROL
X	PauseJove(),
X#endif
X	PrevLine(),
X	PrevPage(),
X	PrevWindow(),
X	Push(),
X	RegReplace(),
X	QRepSearch(),
X	QuotChar(),
X	ReadFile(),
X	ReadMacs(),
X	RedrawDisplay(),
X	ReNamBuf(),
X	RepSearch(),
X	DownScroll(),
X	UpScroll(),
X	ForSearch(),
X	FSrchND(),
X	RevSearch(),
X	RSrchND(),
X	SelfInsert(),
X	SetVar(),
X 	SetMark(),
X	ShellCom(),
X	ShToBuf(),
X	ShrWindow(),
X	Source(),
X#ifdef SPELL
X	SpelBuffer(),
X#endif
X	SplitWind(),
X	Remember(),
X	Forget(),
X	StrLength(),
X	TransChar(),
X	TransLines(),
X	SaveFile(),
X	WtModBuf(),
X	WriteFile(),
X	WriteMacs(),
X	WrtReg(),
X	Yank(),
X	YankPop(),
X	PrVar(),
X	FilterRegion(),
X	WNumLines(),
X
X#ifdef IPROCS
X	ShellProc(),
X	ProcInt(),
X	ProcQuit(),
X	ProcKill(),
X#  ifndef PIPEPROCS
X	ProcEof(),
X	ProcStop(),
X	ProcCont(),
X	ProcDStop(),
X#  endif
X	ProcSendData(),
X	ProcNewline(),
X	ProcList(),
X	ProcBind(),
X	Iprocess(),
X#endif
X
X#ifdef LISP
X	GSexpr(),	/* Grind S Expression. */
X	AddSpecial(),	/* add lisp special form */
X#endif
X	CAutoExec(),
X	MAutoExec(),
X
X	DefMAbbrev(),
X	DefGAbbrev(),
X	SaveAbbrevs(),
X	RestAbbrevs(),
X	EditAbbrevs(),
X	BindMtoW(),
X
X#ifdef CMT_FMT
X	Comment(),
X#endif
X
X	MacInter();		/* This is the last one. */
X
X
X#	define WIRED_CMD(c)	c
X
X#else TXT_TO_C
X
X#	define WIRED_CMD(c)	0
X
X#endif TXT_TO_C
X
Xstruct cmd	commands[] = {
X#ifdef LISP
X	FUNCTION, "add-lisp-special", WIRED_CMD(AddSpecial),
X#endif
X#ifdef ANSICODES
X	FUNCTION, "ansi-codes", WIRED_CMD(AnsiCodes),
X#endif
X	FUNCTION, "append-region", WIRED_CMD(AppReg),
X	FUNCTION, "apropos", WIRED_CMD(Apropos),
X	FUNCTION, "auto-execute-command", WIRED_CMD(CAutoExec),
X	FUNCTION, "auto-execute-macro", WIRED_CMD(MAutoExec),
X	DefMinor(Fill), "auto-fill-mode", 0,
X	DefMinor(Indent), "auto-indent-mode", 0,
X	FUNCTION, "backward-character", WIRED_CMD(BackChar),
X	FUNCTION, "backward-list", WIRED_CMD(BList),
X	FUNCTION, "backward-paragraph", WIRED_CMD(BackPara),
X	FUNCTION, "backward-s-expression", WIRED_CMD(BSexpr),
X	FUNCTION, "backward-sentence", WIRED_CMD(Bos),
X	FUNCTION, "backward-up-list", WIRED_CMD(BUpList),
X	FUNCTION, "backward-word", WIRED_CMD(BackWord),
X	FUNCTION, "beginning-of-file", WIRED_CMD(Bof),
X	FUNCTION, "beginning-of-line", WIRED_CMD(Bol),
X	FUNCTION, "beginning-of-window", WIRED_CMD(Bow),
X	FUNCTION, "bind-to-key", WIRED_CMD(BindAKey),
X	FUNCTION, "bind-macro-to-key", WIRED_CMD(BindMac),
X#ifdef ABBREV
X	FUNCTION, "bind-macro-to-word-abbrev", WIRED_CMD(BindMtoW),
X#endif
X	FUNCTION, "buffer-position", WIRED_CMD(BufPos),
X	DefMajor(CMODE), "c-mode", 0,
X	FUNCTION, "case-character-capitalize", WIRED_CMD(CapChar),
X	FUNCTION, "case-region-lower", WIRED_CMD(CasRegLower),
X	FUNCTION, "case-region-upper", WIRED_CMD(CasRegUpper),
X	FUNCTION, "case-word-capitalize", WIRED_CMD(CapWord),
X	FUNCTION, "case-word-lower", WIRED_CMD(LowWord),
X	FUNCTION, "case-word-upper", WIRED_CMD(UppWord),
X	FUNCTION, "character-to-octal-insert", WIRED_CMD(ChrToOct),
X#ifdef CHDIR
X	FUNCTION, "cd", WIRED_CMD(Chdir),
X#endif
X	FUNCTION, "clear-and-redraw", WIRED_CMD(ClAndRedraw),
X	FUNCTION, "compile-it", WIRED_CMD(MakeErrors),
X#ifdef IPROCS
X#  ifndef PIPEPROCS
X#    ifdef TIOCSLTC
X	FUNCTION, "continue-process", WIRED_CMD(ProcCont),
X#    endif
X#  endif
X#endif
X	FUNCTION, "copy-region", WIRED_CMD(CopyRegion),
X	FUNCTION, "current-error", WIRED_CMD(ShowErr),
X	FUNCTION, "date", WIRED_CMD(prCTIME),
X#ifdef ABBREV
X	FUNCTION, "define-mode-word-abbrev", WIRED_CMD(DefMAbbrev),
X	FUNCTION, "define-global-word-abbrev", WIRED_CMD(DefGAbbrev),
X#endif
X	FUNCTION, "delete-blank-lines", WIRED_CMD(DelBlnkLines),
X	FUNCTION, "delete-buffer", WIRED_CMD(BufKill),
X	FUNCTION, "delete-macro", WIRED_CMD(DelMacro),
X	FUNCTION, "delete-next-character", WIRED_CMD(DelNChar),
X	FUNCTION, "delete-other-windows", WIRED_CMD(OneWindow),
X	FUNCTION, "delete-previous-character", WIRED_CMD(DelPChar),
X	FUNCTION, "delete-white-space", WIRED_CMD(DelWtSpace),
X	FUNCTION, "delete-current-window", WIRED_CMD(DelCurWindow),
X	FUNCTION, "describe-bindings", WIRED_CMD(DescBindings),
X	FUNCTION, "describe-command", WIRED_CMD(DescCom),
X	FUNCTION, "describe-key", WIRED_CMD(KeyDesc),
X	FUNCTION, "describe-variable", WIRED_CMD(DescCom),
X	FUNCTION, "digit", WIRED_CMD(Digit),
X	FUNCTION, "digit-1", WIRED_CMD(Digit1),
X	FUNCTION, "digit-2", WIRED_CMD(Digit2),
X	FUNCTION, "digit-3", WIRED_CMD(Digit3),
X	FUNCTION, "digit-4", WIRED_CMD(Digit4),
X	FUNCTION, "digit-5", WIRED_CMD(Digit5),
X	FUNCTION, "digit-6", WIRED_CMD(Digit6),
X	FUNCTION, "digit-7", WIRED_CMD(Digit7),
X	FUNCTION, "digit-8", WIRED_CMD(Digit8),
X	FUNCTION, "digit-9", WIRED_CMD(Digit9),
X	FUNCTION, "digit-0", WIRED_CMD(Digit0),
X#ifdef CHDIR
X	FUNCTION, "dirs", WIRED_CMD(prDIRS),
X#endif
X	FUNCTION, "down-list", WIRED_CMD(FDownList),
X#ifdef IPROCS
X#  ifndef PIPEPROCS
X#    ifdef TIOCSLTC
X	FUNCTION, "dstop-process", WIRED_CMD(ProcDStop),
X#    endif
X#  endif
X#endif
X#ifdef ABBREV
X	FUNCTION, "edit-word-abbrevs", WIRED_CMD(EditAbbrevs),
X#endif
X	FUNCTION, "end-of-file", WIRED_CMD(Eof),
X	FUNCTION, "end-of-line", WIRED_CMD(Eol),
X	FUNCTION, "end-of-window", WIRED_CMD(Eow),
X#ifdef IPROCS
X#  ifndef PIPEPROCS
X	FUNCTION, "eof-process", WIRED_CMD(ProcEof),
X#  endif
X#endif
X	FUNCTION, "erase-buffer", WIRED_CMD(BufErase),
X	FUNCTION, "exchange-point-and-mark", WIRED_CMD(PtToMark),
X	FUNCTION, "execute-named-command", WIRED_CMD(Extend),
X	FUNCTION, "execute-keyboard-macro", WIRED_CMD(ExecMacro),
X	FUNCTION, "execute-macro", WIRED_CMD(RunMacro),
X	FUNCTION, "exit-jove", WIRED_CMD(Leave),
X#ifdef CMT_FMT
X 	FUNCTION, "fill-comment", WIRED_CMD(Comment),
X#endif CMT_FMT
X	FUNCTION, "fill-paragraph", WIRED_CMD(Justify),
X	FUNCTION, "fill-region", WIRED_CMD(RegJustify),
X	FUNCTION, "filter-region", WIRED_CMD(FilterRegion),
X	FUNCTION, "find-file", WIRED_CMD(FindFile),
X	FUNCTION, "find-tag", WIRED_CMD(FindTag),
X	FUNCTION, "find-tag-at-point", WIRED_CMD(FDotTag),
X	FUNCTION, "first-non-blank", WIRED_CMD(ToIndent),
X	FUNCTION, "forward-character", WIRED_CMD(ForChar),
X	FUNCTION, "forward-list", WIRED_CMD(FList),
X	FUNCTION, "forward-paragraph", WIRED_CMD(ForPara),
X	FUNCTION, "forward-s-expression", WIRED_CMD(FSexpr),
X	FUNCTION, "forward-sentence", WIRED_CMD(Eos),
X	FUNCTION, "forward-word", WIRED_CMD(ForWord),
X	DefMajor(FUNDAMENTAL), "fundamental-mode", 0,
X#ifdef LISP
X	FUNCTION, "grind-s-expr", WIRED_CMD(GSexpr),
X#endif
X	FUNCTION, "goto-line", WIRED_CMD(GoLine),
X	FUNCTION, "grow-window", WIRED_CMD(GrowWindow),
X	FUNCTION, "handle-tab", WIRED_CMD(Tab),
X	FUNCTION, "i-search-forward", WIRED_CMD(IncFSearch),
X	FUNCTION, "i-search-reverse", WIRED_CMD(IncRSearch),
X	FUNCTION, "insert-file", WIRED_CMD(InsFile),
X#ifdef IPROCS
X	FUNCTION, "interrupt-process", WIRED_CMD(ProcInt),
X	FUNCTION, "i-shell-command", WIRED_CMD(Iprocess),
X#endif
X	FUNCTION, "kill-next-word", WIRED_CMD(DelNWord),
X	FUNCTION, "kill-previous-word", WIRED_CMD(DelPWord),
X#ifdef IPROCS
X	FUNCTION, "kill-process", WIRED_CMD(ProcKill),
X#endif
X	FUNCTION, "kill-region", WIRED_CMD(DelReg),
X	FUNCTION, "kill-s-expression", WIRED_CMD(KillExpr),
X	FUNCTION, "kill-some-buffers", WIRED_CMD(KillSome),
X	FUNCTION, "kill-to-beginning-of-sentence", WIRED_CMD(KillBos),
X	FUNCTION, "kill-to-end-of-line", WIRED_CMD(KillEOL),
X	FUNCTION, "kill-to-end-of-sentence", WIRED_CMD(KillEos),
X	FUNCTION, "left-margin-here", WIRED_CMD(SetLMargin),
X#ifdef LISP
X	DefMajor(LISPMODE), "lisp-mode", 0,
X#endif
X	FUNCTION, "list-buffers", WIRED_CMD(BufList),
X#ifdef IPROCS
X	FUNCTION, "list-processes", WIRED_CMD(ProcList),
X#endif
X	FUNCTION, "make-buffer-unmodified", WIRED_CMD(NotModified),
X	FUNCTION, "make-macro-interactive", WIRED_CMD(MacInter),
X	FUNCTION, "name-keyboard-macro", WIRED_CMD(NameMac),
X	FUNCTION, "newline", WIRED_CMD(Newline),
X	FUNCTION, "newline-and-backup", WIRED_CMD(OpenLine),
X	FUNCTION, "newline-and-indent", WIRED_CMD(LineAI),
X	FUNCTION, "next-error", WIRED_CMD(NextError),
X	FUNCTION, "next-line", WIRED_CMD(NextLine),
X	FUNCTION, "next-page", WIRED_CMD(NextPage),
X	FUNCTION, "next-window", WIRED_CMD(NextWindow),
X	FUNCTION, "number-lines-in-window", WIRED_CMD(WNumLines),
X	DefMinor(OverWrite), "over-write-mode", 0,
X	FUNCTION, "page-next-window", WIRED_CMD(PageNWind),
X	FUNCTION, "paren-flash", WIRED_CMD(DoParen),
X	FUNCTION, "parse-errors", WIRED_CMD(ParseAll),
X	FUNCTION, "parse-special-errors", WIRED_CMD(XParse),
X#ifdef SPELL
X	FUNCTION, "parse-spelling-errors-in-buffer", WIRED_CMD(SpelWords),
X#endif
X#ifdef JOB_CONTROL
X	FUNCTION, "pause-jove", WIRED_CMD(PauseJove),
X#else
X	FUNCTION, "pause-jove", WIRED_CMD(Push),
X#endif
X	FUNCTION, "pop-mark", WIRED_CMD(PopMark),
X#ifdef CHDIR
X	FUNCTION, "popd", WIRED_CMD(Popd),
X#endif
X	FUNCTION, "prefix-1", WIRED_CMD(EscPrefix),
X	FUNCTION, "prefix-2", WIRED_CMD(CtlxPrefix),
X	FUNCTION, "prefix-3", WIRED_CMD(MiscPrefix),
X	FUNCTION, "previous-error", WIRED_CMD(PrevError),
X	FUNCTION, "previous-line", WIRED_CMD(PrevLine),
X	FUNCTION, "previous-page", WIRED_CMD(PrevPage),
X	FUNCTION, "previous-window", WIRED_CMD(PrevWindow),
X	FUNCTION, "print", WIRED_CMD(PrVar),
X#ifdef IPROCS
X	FUNCTION, "process-bind-to-key", WIRED_CMD(ProcBind),
X	FUNCTION, "process-newline", WIRED_CMD(ProcNewline),
X	FUNCTION, "process-send-data-no-return", WIRED_CMD(ProcSendData),
X#endif
X	FUNCTION, "push-shell", WIRED_CMD(Push),
X#ifdef CHDIR
X	FUNCTION, "pushd", WIRED_CMD(Pushd),
X	FUNCTION, "pwd", WIRED_CMD(prCWD),
X#endif
X	FUNCTION, "quadruple-numeric-argument", WIRED_CMD(FourTime),
X	FUNCTION, "query-replace-string", WIRED_CMD(QRepSearch),
X#ifdef IPROCS
X	FUNCTION, "quit-process", WIRED_CMD(ProcQuit),
X#endif
X	FUNCTION, "quoted-insert", WIRED_CMD(QuotChar),
X#ifdef ABBREV
X	FUNCTION, "read-word-abbrev-file", WIRED_CMD(RestAbbrevs),
X#endif
X	FUNCTION, "read-macros-from-file", WIRED_CMD(ReadMacs),
X	FUNCTION, "redraw-display", WIRED_CMD(RedrawDisplay),
X	FUNCTION, "recursive-edit", WIRED_CMD(Recur),
X	FUNCTION, "rename-buffer", WIRED_CMD(ReNamBuf),
X	FUNCTION, "replace-in-region", WIRED_CMD(RegReplace),
X	FUNCTION, "replace-string", WIRED_CMD(RepSearch),
X	FUNCTION, "right-margin-here", WIRED_CMD(SetRMargin),
X	FUNCTION, "save-file", WIRED_CMD(SaveFile),
X	FUNCTION, "scroll-down", WIRED_CMD(DownScroll),
X	FUNCTION, "scroll-up", WIRED_CMD(UpScroll),
X	FUNCTION, "search-forward", WIRED_CMD(ForSearch),
X	FUNCTION, "search-forward-nd", WIRED_CMD(FSrchND),
X	FUNCTION, "search-reverse", WIRED_CMD(RevSearch),
X	FUNCTION, "search-reverse-nd", WIRED_CMD(RSrchND),
X	FUNCTION, "select-buffer", WIRED_CMD(BufSelect),
X	FUNCTION, "self-insert", WIRED_CMD(SelfInsert),
X	FUNCTION, "set", WIRED_CMD(SetVar),
X	FUNCTION, "set-mark", WIRED_CMD(SetMark),
X#ifdef IPROCS	/* for GNU compatibility */
X	FUNCTION, "shell", WIRED_CMD(ShellProc),
X#endif
X	FUNCTION, "shell-command", WIRED_CMD(ShellCom),
X	FUNCTION, "shell-command-to-buffer", WIRED_CMD(ShToBuf),
X	DefMinor(ShowMatch), "show-match-mode", 0,
X	FUNCTION, "shrink-window", WIRED_CMD(ShrWindow),
X	FUNCTION, "source", WIRED_CMD(Source),
X#ifdef SPELL
X	FUNCTION, "spell-buffer", WIRED_CMD(SpelBuffer),
X#endif
X	FUNCTION, "split-current-window", WIRED_CMD(SplitWind),
X	FUNCTION, "start-remembering", WIRED_CMD(Remember),
X#ifdef IPROCS
X#  ifndef PIPEPROCS
X	FUNCTION, "stop-process", WIRED_CMD(ProcStop),
X#  endif
X#endif
X	FUNCTION, "stop-remembering", WIRED_CMD(Forget),
X	FUNCTION, "string-length", WIRED_CMD(StrLength),
X#ifdef JOB_CONTROL
X	FUNCTION, "suspend-jove", WIRED_CMD(PauseJove),
X#endif
X	DefMajor(TEXT), "text-mode", 0,
X	FUNCTION, "transpose-characters", WIRED_CMD(TransChar),
X	FUNCTION, "transpose-lines", WIRED_CMD(TransLines),
X	FUNCTION, "unbind-key", WIRED_CMD(UnbindC),
X	FUNCTION, "version", WIRED_CMD(ShowVersion),
X	FUNCTION, "visible-spaces-in-window", WIRED_CMD(WVisSpace),
X	FUNCTION, "visit-file", WIRED_CMD(ReadFile),
X	FUNCTION, "window-find", WIRED_CMD(WindFind),
X#ifdef ABBREV
X	DefMinor(Abbrev), "word-abbrev-mode", 0,
X	FUNCTION, "write-word-abbrev-file", WIRED_CMD(SaveAbbrevs),
X#endif
X	FUNCTION, "write-file", WIRED_CMD(WriteFile),
X	FUNCTION, "write-macros-to-file", WIRED_CMD(WriteMacs),
X	FUNCTION, "write-modified-files", WIRED_CMD(WtModBuf),
X	FUNCTION, "write-region", WIRED_CMD(WrtReg),
X	FUNCTION, "yank", WIRED_CMD(Yank),
X	FUNCTION, "yank-pop", WIRED_CMD(YankPop),
X	FUNCTION, 0, 0
X};
X
X#ifndef TXT_TO_C
Xdata_obj *
Xfindcom(prompt)
Xchar	*prompt;
X{
X	/* This is for faster startup.  This just reads until a space or a
X	   tab or a newline character is reached, and then does a
X	   semi-hashed lookup on that string.  This should be much faster
X	   than initializing the minibuffer for each line. */
X	if (InJoverc) {
X		char	cmdbuf[128];
X		register struct cmd	*cmd;
X		register char	*cp = cmdbuf;
X		register int	c;
X		struct cmd	*which;
X		int	cmdlen,
X			found = 0;
X		static struct cmd	*cmdhash[1 + 26];
X		static int	beenhere = NO;
X
X/* special case for prefix commands--only upper case ones */
X#define hash(c)	((c == 'P') ? 0 : 1 + (c - 'a'))
X
X		/* initialize the hash table */
X		if (beenhere == NO) {
X			int	lastc = 0;
X
X			for (cmd = commands; cmd->Name != 0; cmd++)
X				if (lastc != cmd->Name[0]) {
X					lastc = cmd->Name[0];
X					cmdhash[hash(lastc)] = cmd;
X				}
X			beenhere = YES;
X		}
X
X		/* gather the cmd name */
X		while (((c = getch()) != EOF) && !index(" \t\r\n", c))
X			*cp++ = c;
X		if (c == EOF)
X			return 0;
X		*cp = '\0';
X		cmdlen = cp - cmdbuf;
X		if (cmdlen == 0)
X			return 0;
X
X		/* look it up (in the reduced search space) */
X		for (cmd = cmdhash[hash(cmdbuf[0])]; cmd->Name[0] == cmdbuf[0]; cmd++) {
X			if (strncmp(cmd->Name, cmdbuf, cmdlen) == 0) {
X				if (strcmp(cmd->Name, cmdbuf) == 0)
X					return (data_obj *) cmd;
X				found++;
X				which = cmd;
X			}
X		}
X		if (found > 1)
X			complain("[\"%s\" ambiguous]", cmdbuf);
X		else if (found == 0)
X			complain("[\"%s\" unknown]", cmdbuf);
X		else
X			return (data_obj *) which;
X	} else {
X		static char	*strings[(sizeof commands) / sizeof (commands[0])];
X		static int	beenhere = 0;
X		register int	com;
X
X		if (beenhere == 0) {
X			register char	**strs = strings;
X			register struct cmd	*c = commands;
X
X			beenhere = 1;
X			for (; c->Name; c++)
X				*strs++ = c->Name;
X			*strs = 0;
X		}
X
X		if ((com = complete(strings, prompt, CASEIND)) < 0)
X			return 0;
X		return (data_obj *) &commands[com];
X	}
X	/* NOTREACHED */
X}
X#endif
@//E*O*F funcdefs.c//
if test 15977 -ne "`wc -c <'funcdefs.c'`"; then
    echo shar: error transmitting "'funcdefs.c'" '(should have been 15977 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'insert.c'" '(13582 characters)'
if test -f 'insert.c' ; then 
  echo shar: will not over-write existing file "'insert.c'"
else
sed 's/^X//' >insert.c <<'@//E*O*F insert.c//'
X/************************************************************************
X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
X * provided to you without charge, and with no warranty.  You may give  *
X * away copies of JOVE, including sources, provided that this notice is *
X * included in all the files.                                           *
X ************************************************************************/
X
X#include "jove.h"
X#include "ctype.h"
X#include "table.h"
X
X/* Make a newline after AFTER in buffer BUF, UNLESS after is 0,
X   in which case we insert the newline before after. */
X
XLine *
Xlistput(buf, after)
Xregister Buffer	*buf;
Xregister Line	*after;
X{
X	register Line	*newline = nbufline();
X
X	if (after == 0) {	/* Before the first line */
X		newline->l_next = buf->b_first;
X		newline->l_prev = 0;
X		buf->b_first = newline;
X	} else {
X		newline->l_prev = after;
X		newline->l_next = after->l_next;
X		after->l_next = newline;
X	}
X	if (newline->l_next)
X		newline->l_next->l_prev = newline;
X	else
X		if (buf)
X			buf->b_last = newline;
X	if (buf && buf->b_dot == 0)
X		buf->b_dot = newline;
X	return newline;
X}	
X
X/* Divide the current line and move the current line to the next one */
X
XLineInsert(num)
Xregister int	num;
X{
X	char	newline[LBSIZE];
X	register Line	*newdot,
X			*olddot;
X	int	oldchar;
X
X	olddot = curline;
X	oldchar = curchar;
X
X	newdot = curline;
X	while (--num >= 0) {
X		newdot = listput(curbuf, newdot);
X		SavLine(newdot, NullStr);
X	}
X
X	modify();
X	if (curchar != 0) {
X		strcpy(newline, &linebuf[curchar]);
X		linebuf[curchar] = '\0';	/* Shorten this line */
X		SavLine(curline, linebuf);
X		strcpy(linebuf, newline);
X	} else {	/* Redisplay optimization */
X		newdot->l_dline = curline->l_dline;
X		SavLine(curline, NullStr);
X	}
X
X	makedirty(curline);
X	curline = newdot;
X	curchar = 0;
X	makedirty(curline);
X	IFixMarks(olddot, oldchar, curline, curchar);
X}	
X
X/* Makes the indent of the current line == goal.  If the current indent
X   is greater than GOAL it deletes.  If more indent is needed, it uses
X   tabs and spaces to get to where it's going. */
X
Xn_indent(goal)
Xregister int	goal;
X{
X	int	dotcol,
X		incrmt;
X
X	ToIndent();
X	dotcol = calc_pos(linebuf, curchar);
X	if (goal < dotcol) {
X		DelWtSpace();
X		dotcol = 0;
X	}
X
X	for (;;) {
X		incrmt = (tabstop - (dotcol % tabstop));
X		if (dotcol + incrmt > goal)
X			break;
X		Insert('\t');
X		dotcol += incrmt;
X	}
X	if (dotcol != goal)
X		DoTimes(Insert(' '), (goal - dotcol));
X	exp_p = NO;
X	exp = 1;
X}
X
XSelfInsert()
X{
X#ifdef ABBREV
X	if (MinorMode(Abbrev) && !ismword(LastKeyStruck) &&
X	    !bolp() && ismword(linebuf[curchar - 1]))
X		AbbrevExpand();
X#endif
X	if (MinorMode(OverWrite)) {
X		register int	num,
X				i;
X
X		for (i = 0, num = exp, exp = 1; i < num; i++) {
X			int	pos = calc_pos(linebuf, curchar);
X
X			if (!eolp()) {
X				if (linebuf[curchar] == '\t') {
X					if ((pos + 1) == ((pos + tabstop) - (pos % tabstop)))
X						DelNChar();
X				} else
X					DelNChar();
X			}
X			Insert(LastKeyStruck);
X		}
X	} else
X		Insert(LastKeyStruck);
X
X	if (MinorMode(Fill) && (curchar >= RMargin ||
X			       (calc_pos(linebuf, curchar) >= RMargin)))
X		DoJustify(curline, 0, curline,
X			  curchar + strlen(&linebuf[curchar]), 1, LMargin);
X}
X
XInsert(c)
X{
X	if (exp <= 0)
X		return;
X	modify();
X	makedirty(curline);
X	ins_c(c, linebuf, curchar, exp, LBSIZE);
X	IFixMarks(curline, curchar, curline, curchar + exp);
X	curchar += exp;
X}	
X
X/* Tab in to the right place for C mode */
X
XTab()
X{
X#ifdef LISP
X	if (MajorMode(LISPMODE)) {
X		int	dotchar = curchar;
X		Mark	*m = 0;
X
X		ToIndent();
X		if (dotchar > curchar)
X			m = MakeMark(curline, dotchar, FLOATER);
X		(void) lisp_indent();
X		if (m) {
X			ToMark(m);
X			DelMark(m);
X		} else
X			ToIndent();
X		return;
X	}
X#endif
X	if (MajorMode(CMODE) && strlen(linebuf) == 0)
X		(void) c_indent(CIndIncrmt);
X	else
X		SelfInsert();
X}
X
XQuotChar()
X{
X	int	c;
X	extern int	alarmed;	/* If waitfor had to wait. */
X
X	c = waitchar();
X	if (alarmed)
X		message(key_strokes);
X	if (c == CTL(J))
X		LineInsert(exp);
X	else if (c != CTL(@))
X		Insert(c);
X}
X
X/* Insert the paren.  If in C mode and c is a '}' then insert the
X   '}' in the "right" place for C indentation; that is indented 
X   the same amount as the matching '{' is indented. */
X
Xint	PDelay = 5,	/* 1/2 a second */
X	CIndIncrmt = 8;
X
XDoParen()
X{
X	Bufpos	*bp = (Bufpos *) -1;
X	int	nx,
X		c = LastKeyStruck;
X
X	if (!isclosep(c)) {
X		SelfInsert();
X		return;
X	}
X
X	if (MajorMode(CMODE) && c == '}' && blnkp(linebuf))
X		bp = c_indent(0);
X#ifdef LISP
X	if (MajorMode(LISPMODE) && c == ')' && blnkp(linebuf))
X		bp = lisp_indent();
X#endif
X	SelfInsert();
X	if (MinorMode(ShowMatch) && !charp() && !in_macro()) {
X		BackChar();	/* Back onto the ')' */
X		if ((int) bp == -1)
X			bp = m_paren(c, BACKWARD, NO, YES);
X		ForChar();
X		if (bp != 0) {
X			nx = in_window(curwind, bp->p_line);
X			if (nx != -1) {		/* is visible */
X				Bufpos	b;
X
X				DOTsave(&b);
X				SetDot(bp);
X				SitFor(PDelay);
X				SetDot(&b);
X			} else
X				s_mess("%s", lcontents(bp->p_line));
X		}
X		mp_error();	/* display error message */
X	}
X}
X
XLineAI()
X{
X	DoNewline(TRUE);
X}
X
XNewline()
X{
X	DoNewline(MinorMode(Indent));
X}	
X
XDoNewline(indentp)
X{
X	Bufpos	save;
X	int	indent;
X
X	/* first we calculate the indent of the current line */
X	DOTsave(&save);
X	ToIndent();
X	indent = calc_pos(linebuf, curchar);
X	SetDot(&save);
X
X#ifdef ABBREV
X	if (MinorMode(Abbrev) && !ismword(LastKeyStruck) &&
X	    !bolp() && ismword(linebuf[curchar - 1]))
X		AbbrevExpand();
X#endif
X#ifdef LISP
X	if (MajorMode(LISPMODE))
X		DelWtSpace();
X#endif
X	else if (blnkp(linebuf))
X		DelWtSpace();
X		
X	/* If there is more than 2 blank lines in a row then don't make
X	   a newline, just move down one. */
X	if (exp == 1 && eolp() && TwoBlank())
X		SetLine(curline->l_next);
X	else
X		LineInsert(exp);
X
X	if (indentp)
X#ifdef LISP
X	    if (MajorMode(LISPMODE))
X		(void) lisp_indent();
X	    else
X#endif
X		n_indent((LMargin == 0) ? indent : LMargin);
X}
X
Xins_str(str, ok_nl)
Xregister char	*str;
X{
X	register char	c;
X	Bufpos	save;
X	int	llen;
X
X	if (*str == 0)
X		return;	/* ain't nothing to insert! */
X	DOTsave(&save);
X	llen = strlen(linebuf);
X	while (c = *str++) {
X		if (c == '\n' || (ok_nl && llen >= LBSIZE - 2)) {
X			IFixMarks(save.p_line, save.p_char, curline, curchar);
X			modify();
X			makedirty(curline);
X			LineInsert(1);
X			DOTsave(&save);
X			llen = strlen(linebuf);
X		}
X		if (c != '\n') {
X			ins_c(c, linebuf, curchar++, 1, LBSIZE);
X			llen++;
X		}
X	}
X	IFixMarks(save.p_line, save.p_char, curline, curchar);
X	modify();
X	makedirty(curline);
X}
X
XOpenLine()
X{
X	Bufpos	dot;
X
X	DOTsave(&dot);
X	LineInsert(exp);	/* Open the lines... */
X	SetDot(&dot);
X}
X
X/* Take the region FLINE/FCHAR to TLINE/TCHAR and insert it at
X   ATLINE/ATCHAR in WHATBUF. */
X
XBufpos *
XDoYank(fline, fchar, tline, tchar, atline, atchar, whatbuf)
XLine	*fline,
X	*tline,
X	*atline;
XBuffer	*whatbuf;
X{
X	register Line	*newline;
X	static Bufpos	bp;
X	char	save[LBSIZE],
X		buf[LBSIZE];
X	Line	*startline = atline;
X	int	startchar = atchar;
X
X	lsave();
X	if (whatbuf)
X		modify();
X	(void) ltobuf(atline, genbuf);
X	strcpy(save, &genbuf[atchar]);
X
X	(void) ltobuf(fline, buf);
X	if (fline == tline)
X		buf[tchar] = '\0';
X
X	linecopy(genbuf, atchar, &buf[fchar]);
X	atline->l_dline = putline(genbuf);
X	makedirty(atline);
X
X	fline = fline->l_next;
X	while (fline != tline->l_next) {
X		newline = listput(whatbuf, atline);
X		newline->l_dline = fline->l_dline;
X		makedirty(newline);
X		fline = fline->l_next;
X		atline = newline;
X		atchar = 0;
X	}
X
X	getline(atline->l_dline, genbuf);
X	atchar += tchar;
X	linecopy(genbuf, atchar, save);
X	atline->l_dline = putline(genbuf);
X	makedirty(atline);
X	IFixMarks(startline, startchar, atline, atchar);
X	bp.p_line = atline;
X	bp.p_char = atchar;
X	this_cmd = YANKCMD;
X	getDOT();			/* Whatever used to be in linebuf */
X	return &bp;
X}
X
XYankPop()
X{
X	Line	*line,
X		*last;
X	Mark	*mp = CurMark();
X	Bufpos	*dot;
X	int	dir = -1;	/* Direction to rotate the ring */
X
X	if (last_cmd != YANKCMD)
X		complain("Yank something first!");
X
X	lfreelist(reg_delete(mp->m_line, mp->m_char, curline, curchar));
X
X	/* Now must find a recently killed region. */
X
X	if (exp < 0)
X		dir = 1;
X
X	killptr += dir;
X	for (;;) {
X		if (killptr < 0)
X			killptr = NUMKILLS - 1;
X		else if (killptr >= NUMKILLS)
X			killptr = 0;
X		if (killbuf[killptr])
X			break;
X		killptr += dir;
X	}
X
X	this_cmd = YANKCMD;
X
X	line = killbuf[killptr];
X	last = lastline(line);
X	dot = DoYank(line, 0, last, length(last), curline, curchar, curbuf);
X	MarkSet(CurMark(), curline, curchar);
X	SetDot(dot);
X}
X
X/* This is an attempt to reduce the amount of memory taken up by each line.
X   Without this each malloc of a line uses sizeof (line) + sizeof(HEADER)
X   where line is 3 words and HEADER is 1 word.
X   This is going to allocate memory in chucks of CHUNKSIZE * sizeof (line)
X   and divide each chuck into lineS.  A line is free in a chunk when its
X   line->l_dline == 0, so freeline sets dline to 0. */
X
X#define CHUNKSIZE	300
X
Xstruct chunk {
X	int	c_nlines;	/* Number of lines in this chunk (so they
X				   don't all have to be CHUNKSIZE long). */
X	Line	*c_block;	/* Chunk of memory */
X	struct chunk	*c_nextfree;	/* Next chunk of lines */
X};
X
Xstatic struct chunk	*fchunk = 0;
Xstatic Line	*ffline = 0;	/* First free line */
X
Xfreeline(line)
Xregister Line	*line;
X{
X	line->l_dline = 0;
X	line->l_next = ffline;
X	if (ffline)
X		ffline->l_prev = line;
X	line->l_prev = 0;
X	ffline = line;
X}
X
Xlfreelist(first)
Xregister Line	*first;
X{
X	if (first)
X		lfreereg(first, lastline(first));
X}
X
X/* Append region from line1 to line2 onto the free list of lines */
X
Xlfreereg(line1, line2)
Xregister Line	*line1,
X		*line2;
X{
X	register Line	*next,
X			*last = line2->l_next;
X
X	while (line1 != last) {
X		next = line1->l_next;
X		freeline(line1);
X		line1 = next;
X	}
X}
X
Xstatic
Xnewchunk()
X{
X	register Line	*newline;
X	register int	i;
X	struct chunk	*f;
X	int	nlines = CHUNKSIZE;
X
X	f = (struct chunk *) emalloc(sizeof (struct chunk));
X	if (f == 0)
X		return 0;
X
X	if ((f->c_block = (Line *) malloc((unsigned) (sizeof (Line) * nlines))) == 0) {
X		while (nlines > 0) {
X			f->c_block = (Line *) malloc((unsigned) (sizeof (Line) * nlines));
X			if (f->c_block != 0)
X				break;
X			nlines /= 2;
X		}
X	}
X
X	if (nlines <= 0)
X		return 0;
X
X	f->c_nlines = nlines;
X	for (i = 0, newline = f->c_block; i < nlines; newline++, i++)
X		freeline(newline);
X	f->c_nextfree = fchunk;
X	fchunk = f;
X	return 1;
X}
X
X/* New BUFfer LINE */
X
XLine *
Xnbufline()
X{
X	register Line	*newline;
X
X	if (ffline == 0)	/* No free list */
X		if (newchunk() == 0)
X			complain("[Out of lines] ");
X	newline = ffline;
X	ffline = ffline->l_next;
X	if (ffline)
X		ffline->l_prev = 0;
X	return newline;
X}
X
X/* Remove the free lines, in chunk c, from the free list because they are
X   no longer free. */
X
Xstatic
Xremfreelines(c)
Xregister struct chunk	*c;
X{
X	register Line	*lp;
X	register int	i;
X
X	for (lp = c->c_block, i = 0; i < c->c_nlines; i++, lp++) {
X		if (lp->l_prev)
X			lp->l_prev->l_next = lp->l_next;
X		else
X			ffline = lp->l_next;
X		if (lp->l_next)
X			lp->l_next->l_prev = lp->l_prev;
X	}
X}
X
X/* This is used to garbage collect the chunks of lines when malloc fails
X   and we are NOT looking for a new buffer line.  This goes through each
X   chunk, and if every line in a given chunk is not allocated, the entire
X   chunk is `free'd by "free()". */
X
XGCchunks()
X{
X	register struct chunk	*cp;
X	struct chunk	*prev = 0,
X			*next = 0;
X	register int	i;
X	register Line	*newline;
X
X 	for (cp = fchunk; cp != 0; cp = next) {
X		for (i = 0, newline = cp->c_block; i < cp->c_nlines; newline++, i++)
X			if (newline->l_dline != 0)
X				break;
X
X 		next = cp->c_nextfree;
X
X		if (i == cp->c_nlines) {		/* Unlink it!!! */
X			if (prev)
X				prev->c_nextfree = cp->c_nextfree;
X			else
X				fchunk = cp->c_nextfree;
X			remfreelines(cp);
X			free((char *) cp->c_block);
X			free((char *) cp);
X		} else
X			prev = cp;
X	}
X}
X
X#ifdef LISP
X
X/* Grind S-Expr */
X
XGSexpr()
X{
X	Bufpos	dot,
X		end;
X
X	if (linebuf[curchar] != '(')
X		complain((char *) 0);
X	DOTsave(&dot);
X	FSexpr();
X	DOTsave(&end);
X	exp = 1;
X	SetDot(&dot);
X	for (;;) {
X		if (curline == end.p_line)
X			break;
X		line_move(FORWARD, NO);
X		if (!blnkp(linebuf))
X			(void) lisp_indent();
X	}
X	SetDot(&dot);
X}
X
X/* lisp_indent() indents a new line in Lisp Mode, according to where
X   the matching close-paren would go if we typed that (sort of). */
X
Xprivate Table	*specials = NIL;
X
Xprivate
Xinit_specials()
X{
X	static char *words[] = {
X		"case",
X		"def",
X		"dolist",
X		"fluid-let",
X		"lambda",
X		"let",
X		"lexpr",
X		"macro",
X		"named-l",	/* named-let and named-lambda */
X		"nlambda",
X		"prog",
X		"selectq",
X		0
X	};
X	char	**wordp = words;
X
X	specials = make_table();
X	while (*wordp)
X		add_word(*wordp++, specials);
X}
X
XAddSpecial()
X{
X	char	*word;
X
X	word = ask((char *) 0, ProcFmt);
X	if (specials == NIL)
X		init_specials();
X	add_word(copystr(word), specials);
X}
X
XBufpos *
Xlisp_indent()
X{
X	Bufpos	*bp,
X		savedot;
X	int	goal;
X
X	bp = m_paren(')', BACKWARD, NO, YES);
X
X	if (bp == 0)
X		return 0;
X
X	/* We want to end up
X	 
X	 	(atom atom atom ...
X	 	      ^ here.
X	 */
X
X	DOTsave(&savedot);
X	SetDot(bp);
X	DoTimes(ForChar(), 1);
X	if (linebuf[curchar] != '(') {
X		register Word	*wp;
X
X		if (specials == NIL)
X			init_specials();
X		for (wp = table_top(specials); wp != NIL; wp = next_word(wp))
X			if (casencmp(word_text(wp), &linebuf[curchar], word_length(wp)) == 0)
X				break;
X		if (wp == NIL) {	/* not special */
X			int	c_char = curchar;
X
X			WITH_TABLE(curbuf->b_major)
X				ForWord();
X			END_TABLE();
X			if (LookingAt("[ \t]*;\\|[ \t]*$", linebuf, curchar))
X				curchar = c_char;
X			else while (linebuf[curchar] == ' ')
X				curchar++;
X		} else
X			curchar++;
X	}
X	goal = calc_pos(linebuf, curchar);
X	SetDot(&savedot);
X	n_indent(goal);
X
X	return bp;
X}
X#endif LISP
@//E*O*F insert.c//
if test 13582 -ne "`wc -c <'insert.c'`"; then
    echo shar: error transmitting "'insert.c'" '(should have been 13582 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'table.c'" '(1122 characters)'
if test -f 'table.c' ; then 
  echo shar: will not over-write existing file "'table.c'"
else
sed 's/^X//' >table.c <<'@//E*O*F table.c//'
X/************************************************************************
X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
X * provided to you without charge, and with no warranty.  You may give  *
X * away copies of JOVE, including sources, provided that this notice is *
X * included in all the files.                                           *
X ************************************************************************/
X
X#include "jove.h"
X#include "table.h"
X
Xprivate Table	*tables = NIL;
X
XTable *
Xmake_table()
X{
X	Table	*tab = (Table *) emalloc(sizeof *tab);
X
X	tab->t_next = tables;
X	tables = tab;
X	tab->t_wordlist = NIL;
X
X	return tab;
X}
X
XWord *
Xword_in_table(text, table)
Xchar	*text;
XTable	*table;
X{
X	register Word	*w;
X
X	for (w = table_top(table); w != NIL; w = next_word(w))
X		if (strcmp(word_text(w), text) == 0)
X			break;	/* already in list */
X	return w;
X}
X
Xadd_word(wname, table)
Xchar	*wname;
XTable	*table;
X{
X	register Word	*w;
X
X	if (w = word_in_table(wname, table))
X		return;
X	w = (Word *) emalloc(sizeof *w);
X	word_text(w) = wname;
X	next_word(w) = table_top(table);
X	table_top(table) = w;
X}
@//E*O*F table.c//
if test 1122 -ne "`wc -c <'table.c'`"; then
    echo shar: error transmitting "'table.c'" '(should have been 1122 characters)'
fi
fi # end of overwriting check
echo shar: "End of archive 3 (of 13)."
cp /dev/null ark3isdone
DONE=true
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13; do
    if test -f ark${I}isdone; then
        echo "You have run archive ${I}."
    else
        echo "You still need to run archive ${I}."
        DONE=false
    fi
done
case $DONE in
    true)
        echo "You have run all 13 archives."
        echo 'Now read the README and Makefile.'
        ;;
esac
##  End of shell archive.
exit 0



More information about the Mod.sources mailing list