[alt.sources] Vile 02/17 - vi feel-alike

pgf@cayman.COM (Paul Fox) (06/08/91)

#!/bin/sh
# this is vileshar.02 (part 2 of Vile)
# do not concatenate these parts, unpack them in order with /bin/sh
# file bind.c continued
#
if test ! -r _shar_seq_.tmp; then
	echo 'Please unpack part 1 first!'
	exit 1
fi
(read Scheck
 if test "$Scheck" != 2; then
	echo Please unpack part "$Scheck" next!
	exit 1
 else
	exit 0
 fi
) < _shar_seq_.tmp || exit 1
echo 'x - continuing file bind.c'
sed 's/^X//' << 'SHAR_EOF' >> 'bind.c' &&
X		if (nptr->n_cmd == cfp) {
X			return(nptr->n_name);
X		}
X	}
X	return NULL;
}
X
#if NEEDED
/* translate a function pointer to its associated flags */
fnc2flags(func)
CMDFUNC *cfp;	/* ptr to the requested function to bind to */
{
X	register NTAB *nptr;	/* pointer into the name binding table */
X
X	/* skim through the table, looking for a match */
X	nptr = nametbl;
X	while (nptr->n_cmd != NULL) {
X		if (nptr->n_cmd == cfp) {
X			return nptr->n_flags;
X		}
X		++nptr;
X	}
X	return NONE;
}
#endif
X
X
/* engl2fnc: match name to a function in the names table
X	translate english name to function pointer
X 		 return any match or NULL if none
X */
CMDFUNC *
engl2fnc(fname)
char *fname;	/* name to attempt to match */
{
X	register NTAB *nptr;	/* pointer to entry in name binding table */
X
X	/* scan through the table, returning any match */
X	nptr = nametbl;
X	while (nptr->n_cmd != NULL) {
X		if (strcmp(fname, nptr->n_name) == 0) {
X			return nptr->n_cmd;
X		}
X		++nptr;
X	}
X	return NULL;
}
X
/* prc2kcod: translate printable code to 10 bit keycode */
int 
prc2kcod(k)
char *k;		/* name of key to translate to Command key form */
{
X	register int c;	/* key sequence to return */
X
X	/* parse it up */
X	c = 0;
X
X	/* first, the CTLA prefix */
X	if (*k == '^' && *(k+1) == toalpha(cntl_a) && *(k+2) == '-') {
X		c = CTLA;
X		k += 3;
X	}
X
X	/* next the function prefix */
X	if (*k == 'F' && *(k+1) == 'N' && *(k+2) == '-') {
X		c |= SPEC;
X		k += 3;
X	}
X
X	/* control-x as well... (but not with FN) */
X	if (*k == '^' && *(k+1) == toalpha(cntl_x) && 
X				*(k+2) == '-' && !(c & SPEC)) {
X		c |= CTLX;
X		k += 3;
X	}
X
X	/* a control char? */
X	if (*k == '^' && *(k+1) != 0) {
X		++k;
X		c |= *k;
X		if (islower(c)) c = toupper(c);
X		c = tocntrl(c);
X	} else if (!strcmp(k,"<sp>")) {
X		c |= ' ';
X	} else if (!strcmp(k,"<tab>")) {
X		c |= '\t';
X	} else {
X		c |= *k;
X	}
X	return c;
}
X
#if ! SMALLER
X
/* translate printable code (like "M-r") to english command name */
char *
prc2engl(skey)	/* string key name to binding name.... */
char *skey;	/* name of keey to get binding for */
{
X	char *bindname;
X
X	bindname = fnc2engl(kcod2fnc(prc2kcod(skey)));
X	if (bindname == NULL)
X		bindname = "ERROR";
X
X	return bindname;
}
#endif
X
/* get an english command name from the user. Command completion means
X * that pressing a <SPACE> will attempt to complete an unfinished command
X * name if it is unique.
X */
char *
kbd_engl()
{
X	int status;
X	char *buf;
X
X
X	status = kbd_engl_stat(&buf);
X	if (status == SORTOFTRUE) /* something was tungetc'ed */
X		(void)tgetc();
X	if (status == TRUE)
X		return buf;
X	return NULL;
}
X
/* *bufp only valid if return is TRUE */
kbd_engl_stat(bufp)
char **bufp;
{
#if	ST520 & LATTICE
#define register		
#endif
X	register int c;
X	register int cpos;	/* current column on screen output */
X	register char *sp;	/* pointer to string for output */
X	register NTAB *nbp;	/* first ptr to entry in name binding table */
X	register NTAB *cnbp;	/* current ptr to entry in name binding table */
X	register NTAB *lnbp;	/* last ptr to entry in name binding table */
X	static char buf[NLINE]; /* buffer to hold tentative command name */
X
X	cpos = 0;
X
X	*bufp = NULL;
X
X	/* if we are executing a command line just get the next arg and return */
X	if (clexec) {
X		if (macarg(buf) != TRUE) {
X			return FALSE;
X		}
X		*bufp = buf;
X		return TRUE;
X	}
X
X	lineinput = TRUE;
X
X	/* build a name string from the keyboard */
X	while (TRUE) {
X		c = tgetc();
X
X		if (cpos == 0) {
X			if (isbackspace(c) ||
X			    c == kcod2key(abortc) ||
X			    c == kcod2key(killc) ||
X			    c == '\r' ||
X			    islinespecchar(c) ) {
X				tungetc(c);
X				return SORTOFTRUE;
X			}
X		}
X
X		if (c == '\r') {
X			buf[cpos] = 0;
X			lineinput = FALSE;
X			*bufp = buf;
X			return TRUE;
X
X		} else if (c == kcod2key(abortc)) {	/* Bell, abort */
X			buf[0] = '\0';
X			lineinput = FALSE;
X			return FALSE;
X
X		} else if (isbackspace(c)) {
X			TTputc('\b');
X			TTputc(' ');
X			TTputc('\b');
X			--ttcol;
X			--cpos;
X			TTflush();
X
X		} else if (c == kcod2key(killc)) {	/* ^U, kill */
X			while (cpos != 0) {
X				TTputc('\b');
X				TTputc(' ');
X				TTputc('\b');
X				--cpos;
X				--ttcol;
X			}
X			TTflush();
X			tungetc(c);
X			return SORTOFTRUE;
X
X		} /* else... */
/* the following mess causes the command to terminate if:
X	we've got a space
X		-or-
X	we're in the first few chars and we're switching from punctuation
X	to alphanumerics, or vice-versa.  oh yeah -- '!' is considered
X	alphanumeric today.
X	All this allows things like:
X		: e#
X		: !ls
X		: q!
X	to work properly.
X	If we pass this "if" with c != ' ', then c is ungotten below,
X	so it can be picked up by the commands argument getter later.
*/
X		else if (c == ' ' || (cpos > 0 && cpos < 3 &&
X			     ((!ispunct(c) &&  ispunct(buf[cpos-1])) ||
X	   ((c != '!' && ispunct(c)) &&
X	   	 (buf[cpos-1] == '!' || !ispunct(buf[cpos-1]))) )
X			      		)
X			) {
/* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
X	/* attempt a completion */
X	buf[cpos] = 0;		/* terminate it for us */
X	nbp = nametbl;	/* scan for matches */
X	while (nbp->n_cmd != NULL) {
X		if (strncmp(buf, nbp->n_name, strlen(buf)) == 0) {
X			/* a possible match! exact? no more than one? */
X			if (strcmp(buf, nbp->n_name) == 0 || /* exact? */
X				(nbp + 1)->n_cmd == NULL ||
X				strncmp(buf, (nbp+1)->n_name, strlen(buf)) != 0)
X			{
X				/* exact or only one like it.  print it */
X				sp = nbp->n_name + cpos;
X				while (*sp)
X					TTputc(*sp++);
X				TTflush();
X				if (c != ' ')  /* put it back */
X					tungetc(c);
X				lineinput = FALSE;
X				/* return nbp->n_name; */
X				strncpy(buf,nbp->n_name,NLINE);
X				*bufp = buf;
X				return TRUE;
X			} else {
/* << << << << << << << << << << << << << << << << << */
X	/* try for a partial match against the list */
X
X	/* first scan down until we no longer match the current input */
X	lnbp = (nbp + 1);
X	while ((lnbp+1)->n_cmd != NULL) {
X		if (strncmp(buf, (lnbp+1)->n_name, strlen(buf)) != 0)
X			break;
X		++lnbp;
X	}
X
X	/* and now, attempt to partial complete the string, char at a time */
X	while (TRUE) {
X		/* add the next char in */
X		buf[cpos] = nbp->n_name[cpos];
X
X		/* scan through the candidates */
X		cnbp = nbp + 1;
X		while (cnbp <= lnbp) {
X			if (cnbp->n_name[cpos] != buf[cpos])
X				goto onward;
X			++cnbp;
X		}
X
X		/* add the character */
X		TTputc(buf[cpos++]);
X	}
/* << << << << << << << << << << << << << << << << << */
X			}
X		}
X		++nbp;
X	}
X
X	/* no match.....beep and onward */
X	TTbeep();
onward:;
X	TTflush();
/* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
X		} else {
X			if (cpos < NLINE-1 && isprint(c)) {
X				buf[cpos++] = c;
X				TTputc(c);
X			}
X
X			++ttcol;
X			TTflush();
X		}
X	}
}
X
SHAR_EOF
echo 'File bind.c is complete' &&
chmod 0444 bind.c ||
echo 'restore of bind.c failed'
Wc_c="`wc -c < 'bind.c'`"
test 21479 -eq "$Wc_c" ||
	echo 'bind.c: original size 21479, current size' "$Wc_c"
# ============= buffer.c ==============
echo 'x - extracting buffer.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'buffer.c' &&
/*
X * Buffer management.
X * Some of the functions are internal,
X * and some are actually attached to user
X * keys. Like everyone else, they set hints
X * for the display system.
X */
#include        <stdio.h>
#include	"estruct.h"
#include        "edef.h"
X
static lastlookup = -1;
X
/* c is either first character of a filename, or an index into buffer list */
char *
hist_lookup(c)
{
X	register BUFFER *bp;
X	static char buf[NBUFN];
X	buf[0] = '\0';
X
X	if (curbp != bheadp)
X		mlwrite("BUG: hist_lookup: curbp != bheadp");
X		
X	bp = curbp->b_bufp; /* always skip the current */
X	while (bp != NULL) {
X		if (!(bp->b_flag & (BFINVS|BFSCRTCH)) && (--c == 0))
X			break;
X		bp = bp->b_bufp;
X	}
X	if (bp)
X		return bp->b_bname;
X	return NULL;
}
X
hist_show()
{
X	int i;
X	char line[NLINE];
X	BUFFER *bp;
X	
X	if (curbp != bheadp)
X		mlwrite("BUG: hist_show: curbp != bheadp");
X	
X	strcpy(line,"");
X	for (i = 0, bp = curbp->b_bufp; i < 10 && bp != NULL; bp = bp->b_bufp) {
X		if (!(bp->b_flag & (BFINVS|BFSCRTCH))) {
X			strcat(line, "  %d");
X			if (bp->b_flag & BFCHG)
X				strcat(line, "* ");
X			else
X				strcat(line, " ");
X			strcat(line, bp->b_bname);
X			i++;
X		}
X	}
X	if (strcmp(line,"")) {
X		mlwrite(line,1,2,3,4,5,6,7,8,9,10);
X		return TRUE;
X	} else {
X		return FALSE;
X	}
}
X
histbuff(f,n)
{
X	register int thiscmd, c;
X        register BUFFER *bp;
X	char *bufn;
X
X	if (curbp->b_bufp == NULL) {
X		TTbeep();
X		mlwrite("No other buffers.");
X		return(FALSE);
X	}
X
X	if (f == FALSE) {
X		hist_show();
X		thiscmd = lastcmd;
X		c = kbd_seq();
X		mlerase();
X		if (c == thiscmd) {
X			c = 1;
X		} else if (isdigit(c)) {
X			c = c - '0';
X		} else {
X			tungetc(c);
X			return FALSE;
X		}
X	} else {
X		c = n;
X	}
X	
X	bufn = hist_lookup(c);
X	if (bufn == NULL) {
X		TTbeep();
X		mlwrite("No such buffer.");
X		return FALSE;
X	}
X	/* first assume its a buffer name, then a file name */
X        if ((bp=bfind(bufn, NO_CREAT, 0)) == NULL)
X		return getfile(bufn,TRUE);
X	else {
X		return swbuffer(bp);
X	}
}
X
altbuff(f,n)
{
X	return(histbuff(TRUE,1));
}
X
/*
X * Attach a buffer to a window. The
X * values of dot and mark come from the buffer
X * if the use count is 0. Otherwise, they come
X * from some other window.
X */
usebuffer(f, n)
{
X        register BUFFER *bp;
X        register int    s;
X        char            bufn[NBUFN];
X
X	bufn[0] = 0;
X        if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE)
X                return s;
X        if ((bp=bfind(bufn, OK_CREAT, 0)) == NULL)
X                return FALSE;
X	return swbuffer(bp);
}
X
nextbuffer(f, n)	/* switch to the next buffer in the buffer list */
int f, n;	/* default flag, numeric argument */
{
X	register BUFFER *bp;	/* eligable buffer to switch to*/
X	register BUFFER *stopatbp;	/* eligable buffer to switch to*/
X	
X	stopatbp = NULL;
X	while (stopatbp != bheadp) {
X		/* get the last buffer in the list */
X		for (bp = bheadp; bp->b_bufp != stopatbp; bp = bp->b_bufp)
X			;
X		/* if that one's invisible, back up and try again */
X		if (bp->b_flag & BFINVS)
X			stopatbp = bp;
X		else
X			return swbuffer(bp);
X	}
X	/* we're back to the top -- they were all invisible */
X	return swbuffer(stopatbp);
X	
}
X
X
swbuffer(bp)	/* make buffer BP current */
register BUFFER *bp;
{
X        register WINDOW *wp;
X
X	if (curbp == bp)  /* no switching to be done */
X		return TRUE;
X
X        if (curbp) {
X        	/* if we'll have to take over this window, and it's the last */
X		if (bp->b_nwnd == 0 && --curbp->b_nwnd == 0) {
X			undispbuff(curbp,curwp);
X		}
X        }
X	make_current(bp);
X	
X	/* get it already on the screen if possible */
X        if (bp->b_nwnd > 0)  { /* then it's on the screen somewhere */
X        	register WINDOW *wp;
X        	int nw;
X		for (wp = wheadp, nw= 1;
X			 wp->w_bufp != bp && wp->w_wndp != NULL;
X					 nw++, wp = wp->w_wndp)
X			;
X		if (!wp)
X			mlwrite("BUG: swbuffer: wp still NULL");
X		curwp = wp;
X		upmode();
X		return TRUE;
X	}
X	
X	/* oh well, suck it into this window */
X        curwp->w_bufp  = bp;
X        curwp->w_linep = bp->b_linep;           /* For macros, ignored. */
X        curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty.         */
X        if (bp->b_nwnd++ == 0) {                /* First use.           */
X                curwp->w_dotp  = bp->b_dotp;
X                curwp->w_doto  = bp->b_doto;
X                curwp->w_mkp = bp->b_markp;
X                curwp->w_mko = bp->b_marko;
X                curwp->w_ldmkp = bp->b_ldmkp;
X                curwp->w_ldmko = bp->b_ldmko;
X                curwp->w_sideways = bp->b_sideways;
X        }
X	if (bp->b_active != TRUE) {		/* buffer not active yet*/
X		/* read it in and activate it */
X		(void)readin(bp->b_fname, TRUE, bp, TRUE);
X		curwp->w_dotp = lforw(bp->b_linep);
X		curwp->w_doto = 0;
X		bp->b_active = TRUE;
X	}
#if     NeWS
X        newsreportmodes() ;
#endif
X        return TRUE;
}
X
X
undispbuff(bp,wp)
register BUFFER *bp;
register WINDOW *wp;
{
X	/* get rid of it completely if it's a scratch buffer,
X		or it's empty and unmodified */
X	if ( (bp->b_flag & BFSCRTCH) || ( !(bp->b_flag & BFCHG) && 
X				lforw(bp->b_linep) == bp->b_linep ) ) {
X		(void)zotbuf(bp);
X	} else {  /* otherwise just adjust it off the screen */
X		bp->b_dotp  = wp->w_dotp;
X		bp->b_doto  = wp->w_doto;
X		bp->b_markp = wp->w_mkp;
X		bp->b_marko = wp->w_mko;
X		bp->b_ldmkp = wp->w_ldmkp;
X		bp->b_ldmko = wp->w_ldmko;
X		bp->b_sideways = wp->w_sideways;
X	}
}
X
/* bring nbp to the top of the list, where curbp _always_ lives */
make_current(nbp)
BUFFER *nbp;
{
X	register BUFFER *bp;
X	
X	if (nbp == bheadp) {	/* already at the head */
X		curbp = bheadp;
X		return;
X	}
X		
X	/* remove nbp from the list */
X	for (bp = bheadp; bp->b_bufp != nbp; bp = bp->b_bufp)
X		;
X	bp->b_bufp = nbp->b_bufp;
X	
X	/* put it at the head */
X	nbp->b_bufp = bheadp;
X	
X	bheadp = nbp;
X	curbp = nbp;
}
X
/*
X * Dispose of a buffer, by name.
X * Ask for the name. Look it up (don't get too
X * upset if it isn't there at all!). Get quite upset
X * if the buffer is being displayed. Clear the buffer (ask
X * if the buffer has been changed). Then free the header
X * line and the buffer header.
X */
killbuffer(f, n)
{
X	register BUFFER *bp;
X        register int    s;
X        char bufn[NBUFN];
X
X	bufn[0] = 0;
X        if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE)
X                return(s);
X        if ((bp=bfind(bufn, NO_CREAT, 0)) == NULL) { /* Easy if unknown.     */
X        	mlwrite("No such buffer");
X                return FALSE;
X        }
X	if(bp->b_flag & BFINVS)		/* Deal with special buffers	*/
X			return (TRUE);		/* by doing nothing.	*/
X	s = zotbuf(bp);
X	if (s == TRUE)
X                mlwrite("Buffer %s gone", bufn);
X	return s;
}
X
zotbuf(bp)	/* kill the buffer pointed to by bp */
register BUFFER *bp;
{
X        register BUFFER *bp1;
X        register BUFFER *bp2;
X        register int    s;
X
X        if (bp->b_nwnd != 0) {                  /* Error if on screen.  */
X                mlwrite("Buffer is being displayed");
X                return (FALSE);
X        }
X        if ((s=bclear(bp)) != TRUE)             /* Blow text away.      */
X                return (s);
X                
X        lfree(bp->b_linep);             /* Release header line. */
X        bp1 = NULL;                             /* Find the header.     */
X        bp2 = bheadp;
X        while (bp2 != bp) {
X                bp1 = bp2;
X                bp2 = bp2->b_bufp;
X        }
X        bp2 = bp2->b_bufp;                      /* Next one in chain.   */
X        if (bp1 == NULL)                        /* Unlink it.           */
X                bheadp = bp2;
X        else
X                bp1->b_bufp = bp2;
X        free((char *) bp);                      /* Release buffer block */
X        return (TRUE);
}
X
namebuffer(f,n)		/*	Rename the current buffer	*/
int f, n;		/* default Flag & Numeric arg */
{
X	register BUFFER *bp;	/* pointer to scan through all buffers */
X	static char bufn[NBUFN];	/* buffer to hold buffer name */
X	char *prompt = "New name for buffer: ";
X
X	/* prompt for and get the new buffer name */
ask:	if (mlreply(prompt, bufn, NBUFN) != TRUE)
X		return(FALSE);
X
X	/* and check for duplicates */
X	bp = bheadp;
X	while (bp != NULL) {
X		if (bp != curbp) {
X			/* if the names the same */
X			if (strcmp(bufn, bp->b_bname) == 0) {
X				prompt = "That name's been used.  New name: ";
X				goto ask;  /* try again */
X			}
X		}
X		bp = bp->b_bufp;	/* onward */
X	}
X
X	strcpy(curbp->b_bname, bufn);	/* copy buffer name to structure */
X	curwp->w_flag |= WFMODE;	/* make mode line replot */
X	mlerase();
X	return(TRUE);
}
X
/* create or find a window, and stick this buffer in it.  when 
X	done, we own the window and the buffer, but they are _not_
X	necessarily curwp and curbp */
popupbuff(bp)
BUFFER *bp;
{
X        register WINDOW *wp;
X
X	if (!curbp) {
X		curbp = bp;  /* possibly at startup time */
X		curwp->w_bufp = curbp;
X                ++curbp->b_nwnd;
X	} else if (bp->b_nwnd == 0) {              /* Not on screen yet.   */
X                if ((wp = wpopup()) == NULL)
X                        return FALSE;
X                if (--wp->w_bufp->b_nwnd == 0)
X                	undispbuff(wp->w_bufp,wp);
X                wp->w_bufp  = bp;
X                ++bp->b_nwnd;
X        }
X        wp = wheadp;
X        while (wp != NULL) {
X                if (wp->w_bufp == bp) {
X                        wp->w_linep = lforw(bp->b_linep);
X                        wp->w_dotp  = lforw(bp->b_linep);
X                        wp->w_doto  = 0;
X                        wp->w_mkp = NULL;
X                        wp->w_mko = 0;
X                        wp->w_ldmkp = NULL;
X                        wp->w_ldmko = 0;
X                        wp->w_sideways = 0;
X                        wp->w_flag |= WFMODE|WFHARD;
X				
X                }
X                wp = wp->w_wndp;
X        }
X        return TRUE;
}
X
/*
X	List all of the active buffers.  First update the special
X	buffer that holds the list.  Next make sure at least 1
X	window is displaying the buffer list, splitting the screen
X	if this is what it takes.  Lastly, repaint all of the
X	windows that are displaying the list.
X	A numeric argument forces it to list invisable buffers as
X	well.
*/
togglelistbuffers(f, n)
{
X        register WINDOW *wp;
X        register BUFFER *bp;
X	int s;
X
X	/* if it doesn't exist, create it */
X	if ((bp = bfind("[List]", NO_CREAT, BFSCRTCH)) == NULL)
X		return listbuffers(f,n);
X
X	/* if it does exist, delete the window, which in turn 
X		will kill the BFSCRTCH buffer */
X        wp = wheadp;
X	s = TRUE;
X        while (wp != NULL && s) {
X                if (wp->w_bufp == bp) {
X			s = delwp(wp);
X                	break;
X		}
X                wp = wp->w_wndp;
X	}
X	return s;
}
X
listbuffers(f, n)
{
X        register BUFFER *bp;
X        register int    s;
X
X	/* create the buffer list buffer   */
X	bp = bfind("[List]", OK_CREAT, BFSCRTCH);
X	if (bp == NULL)
X		return FALSE;
X	
X        if ((s=bclear(bp)) != TRUE) /* clear old text (?) */
X                return (s);
X	bp->b_flag |= BFSCRTCH;
X        s = makelist(f,bp);
X	if (!s || popupbuff(bp) == FALSE) {
X		mlwrite("[Sorry, can't list. ]");
X		zotbuf(bp);
X                return (FALSE);
X        }
X        sprintf(bp->b_fname, "       %s   %s",prognam,version);
X        bp->b_flag &= ~BFCHG;               /* Don't complain!      */
X        bp->b_active = TRUE;
X
X        return TRUE;
}
X
/*
X * This routine rebuilds the
X * text in the buffer
X * that holds the buffer list. It is called
X * by the list buffers command. Return TRUE
X * if everything works. Return FALSE if there
X * is an error (if there is no memory). Iflag
X * indicates whether to list hidden buffers.
X */
/* returns no. of lines in list */
int
makelist(iflag,blistp)
int iflag;	/* list hidden buffer flag */
BUFFER *blistp;
{
X        register char   *cp1;
X        register char   *cp2;
X        register int    c;
X        register BUFFER *bp;
X        register LINE   *lp;
X        register int    s;
X	register int	i;
X        long nbytes;		/* # of bytes in current buffer */
X	int nbuf = 0;	/* no. of buffers */
X        int nlines = 0;  /* no. of lines in list */
X        char b[10];
X        char line[NFILEN+NBUFN+30];
X        static char dashes[] =
X			"-------------------------------------------------";
X	int footnote = FALSE;
X
X	sprintf(line,"    %-*s %7s %-*s %s",
X			NUMMODES,"Modes","Size",NBUFN,"Buffer name","Contents");
X        if(addline(blistp,line, -1) == FALSE)
X                return (FALSE);
X        nlines++;
X                
X	/* put some spaces into the separator line... */
X	dashes[3] = dashes[NUMMODES+4] = dashes[NUMMODES+4+8] = 
X		dashes[NUMMODES+4+8+NBUFN+1] = ' ';
X        if (addline(blistp,dashes, -1) == FALSE)
X                return (FALSE);
X        nlines++;
X
X        bp = bheadp;                            /* For all buffers      */
X
X	/* output the list of buffers */
X        while (bp != NULL) {
X		/* skip invisible buffers and ourself if iflag is false */
X                if (((bp->b_flag&(BFINVS|BFSCRTCH)) != 0) && (iflag != TRUE)) {
X                        bp = bp->b_bufp;
X                        continue;
X                }
X
X
X                cp1 = &line[0];                 /* Start at left edge   */
X		/* output status of ACTIVE flag (has the file been read in? */
X                if (bp->b_active == TRUE) {   /* if activated       */
X	                if ((bp->b_flag&BFCHG) != 0) {    /* if changed     */
X	                        *cp1++ = 'm';
X				footnote = TRUE;
X	                } else {
X	                        *cp1++ = ' ';
X			}
X		} else {
X                        *cp1++ = 'u';
X			footnote = TRUE;
X		}
X
X		sprintf(cp1,"%2d ",nbuf++);
X
X                cp1 = &line[strlen(line)];
X
X		/* output the mode codes */
X		for (i = 0; i < NUMMODES; i++) {
X			if (bp->b_mode & (1 << i))
X				*cp1++ = modecode[i];
X			else
X				*cp1++ = '.';
X		}
X                *cp1++ = ' ';                   /* Gap.                 */
X                nbytes = 0L;                    /* Count bytes in buf.  */
X                lp = lforw(bp->b_linep);
X                while (lp != bp->b_linep) {
X                        nbytes += (long)llength(lp)+1L;
X                        lp = lforw(lp);
X                }
X		sprintf(cp1,"%7ld %-*s %s",nbytes,
X			NBUFN, bp->b_bname, bp->b_fname);
X                if (addline(blistp,line,-1) == FALSE)
X                        return (FALSE);
X	        nlines++;
X                bp = bp->b_bufp;
X        }
X
X	if (footnote == TRUE) {
X	        if (addline(blistp,
X	        	"('m' means modified, 'u' means unread)",-1)
X								 == FALSE) {
X			return FALSE;
X		}
X	        nlines++;
X	}
X
X	/* build line to report global mode settings */
X	sprintf(line,"    ");
X	cp1 = &line[4];
X
X	/* output the mode codes */
X	for (i = 0; i < NUMMODES; i++)
X		if (gmode & (1 << i))
X			*cp1++ = modecode[i];
X		else
X			*cp1++ = '.';
X	strcpy(cp1, "    are the global modes");
X	if (addline(blistp,line,-1) == FALSE)
X		return(FALSE);
X
X	sprintf(line," tabstop = %d; fillcol = %d", TABVAL, fillcol);
X	if (addline(blistp,line,-1) == FALSE)
X		return(FALSE);
X
X	sprintf(line," lazy filename matching is %s",
X					(othmode & OTH_LAZY) ? "on":"off");
X	if (addline(blistp,line,-1) == FALSE)
X		return(FALSE);
X
X	nlines++;
X
X        return (nlines);
}
X
ltoa(buf, width, num)
char   buf[];
int    width;
long   num;
{
X        buf[width] = 0;                         /* End of string.       */
X        while (num >= 10) {                     /* Conditional digits.  */
X                buf[--width] = (int)(num%10L) + '0';
X                num /= 10L;
X        }
X        buf[--width] = (int)num + '0';          /* Always 1 digit.      */
X        while (width != 0)                      /* Pad with blanks.     */
X                buf[--width] = ' ';
}
X
/*
X * The argument "text" points to
X * a string. Append this line to the
X * buffer. Handcraft the EOL
X * on the end. Return TRUE if it worked and
X * FALSE if you ran out of room.
X */
addline(bp,text,len)
register BUFFER *bp;
char    *text;
int len;
{
X        register LINE   *lp;
X        register int    i;
X        register int    ntext;
X
X        ntext = (len < 0) ? strlen(text) : len;
X        if ((lp=lalloc(ntext)) == NULL)
X                return (FALSE);
X        for (i=0; i<ntext; ++i)
X                lputc(lp, i, text[i]);
X        bp->b_linep->l_bp->l_fp = lp;       /* Hook onto the end    */
X        lp->l_bp = bp->b_linep->l_bp;
X        bp->b_linep->l_bp = lp;
X        lp->l_fp = bp->b_linep;
X        if (bp->b_dotp == bp->b_linep)  /* If "." is at the end */
X                bp->b_dotp = lp;            /* move it to new line  */
X        return (TRUE);
}
X
/*
X * Look through the list of
X * buffers. Return TRUE if there
X * are any changed buffers. Buffers
X * that hold magic internal stuff are
X * not considered; who cares if the
X * list of buffer names is hacked.
X * Return FALSE if no buffers
X * have been changed.
X */
anycb()
{
X        register BUFFER *bp;
X	register int cnt = 0;
X
X        bp = bheadp;
X        while (bp != NULL) {
X                if ((bp->b_flag&BFINVS)==0 && (bp->b_flag&BFCHG)!=0)
X			cnt++;
X                bp = bp->b_bufp;
X        }
X        return (cnt);
}
X
/*
X * Find a buffer, by name. Return a pointer
X * to the BUFFER structure associated with it.
X * If the buffer is not found
X * and the "cflag" is OK_CREAT, create it. The "bflag" is
X * the settings for the flags in in buffer.
X */
BUFFER  *
bfind(bname, cflag, bflag)
char   *bname;
{
X        register BUFFER *bp;
X        register LINE   *lp;
X	register BUFFER *lastb = NULL;	/* buffer to insert after */
X
X        bp = bheadp;
X        while (bp != NULL) {
X                if (strncmp(bname, bp->b_bname, NBUFN) == 0)
X                        return (bp);
X                lastb = bp;
X                bp = bp->b_bufp;
X        }
X	if (cflag == NO_CREAT)	/* don't create it */
X		return NULL;
X	
X        if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
X                return (NULL);
X        if ((lp=lalloc(0)) == NULL) {
X                free((char *) bp);
X                return (NULL);
X        }
X
X	/* and set up the other buffer fields */
X	bp->b_active = FALSE;
X        bp->b_dotp  = lp;
X        bp->b_doto  = 0;
X        bp->b_markp = NULL;
X        bp->b_marko = 0;
X        bp->b_ldmkp = NULL;
X        bp->b_ldmko = 0;
X        bp->b_nmmarks = NULL;
X        bp->b_flag  = bflag;
X	bp->b_mode  = gmode & ~(MDCMOD|MDDOS); /* handled in readin() */
X        bp->b_nwnd  = 0;
X        bp->b_sideways = 0;
X        bp->b_linep = lp;
X        strcpy(bp->b_fname, "");
X        strcpy(bp->b_bname, bname);
#if	CRYPT
X	bp->b_key[0] = 0;
#endif
X	bp->b_udstks[0] = bp->b_udstks[1] = NULL;
X	bp->b_udstkindx = 0;
X        bp->b_ulinep = NULL;
X        lp->l_fp = lp;
X        lp->l_bp = lp;
X        
X	/* append at the end */
X	if (lastb)
X	        lastb->b_bufp = bp;
X	else
X		bheadp = bp;
X        bp->b_bufp = NULL;
X
X        return (bp);
}
X
/*
X * This routine blows away all of the text
X * in a buffer. If the buffer is marked as changed
X * then we ask if it is ok to blow it away; this is
X * to save the user the grief of losing text. The
X * window chain is nearly always wrong if this gets
X * called; the caller must arrange for the updates
X * that are required. Return TRUE if everything
X * looks good.
X */
bclear(bp)
register BUFFER *bp;
{
X        register LINE   *lp;
X        register int    s;
X
X        if ((bp->b_flag&(BFINVS|BFSCRTCH)) == 0 /* Not invisible or scratch */
X		        && (bp->b_flag&BFCHG) != 0 ) {      /* Something changed    */
X		char ques[50];
X		strcpy(ques,"Discard changes to ");
X		strcat(ques,bp->b_bname);
X	        if (mlyesno(ques) != TRUE)
X	                return FALSE;
X	}
X        bp->b_flag  &= ~BFCHG;                  /* Not changed          */
X	freeundostacks(bp);	/* do this before removing lines */
X        while ((lp=lforw(bp->b_linep)) != bp->b_linep) {
X                lremove(bp,lp);
X                lfree(lp);
X	}
X        bp->b_dotp  = bp->b_linep;              /* Fix "."              */
X        bp->b_doto  = 0;
X        bp->b_markp = NULL;                     /* Invalidate "mark"    */
X        bp->b_marko = 0;
X        bp->b_ldmkp = NULL;                     /* Invalidate "mark"    */
X        bp->b_ldmko = 0;
X	if (bp->b_nmmarks != NULL) { /* free the named marks */
X		free((char *)(bp->b_nmmarks));
X		bp->b_nmmarks = NULL;
X	}
X        return (TRUE);
}
X
unmark(f, n)	/* unmark the current buffers change flag */
int f, n;	/* unused command arguments */
{
X	curbp->b_flag &= ~BFCHG;
X	curwp->w_flag |= WFMODE;
X	return(TRUE);
}
SHAR_EOF
chmod 0444 buffer.c ||
echo 'restore of buffer.c failed'
Wc_c="`wc -c < 'buffer.c'`"
test 20200 -eq "$Wc_c" ||
	echo 'buffer.c: original size 20200, current size' "$Wc_c"
# ============= buglist ==============
echo 'x - extracting buglist (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'buglist' &&
X
X	(E means enhancement, L,M,H are low, medium, high priority)
----------------------
X
H	the gotoeop motion and regions interract wrongly.  For instance,
X	using ^W} to write the rest of the paragraph to a file writes
X	the wrong number of characters.
X
H	when reading the output of a shell command, it's far too slow -- should
X	read as much as possible, put it into the buffer, and _then_ update
X	[ This has been fixed for BSD -- other implementations not yet ]
X
M	output doesn't flush properly after a shell escape
X
M	longnames cause severe portability constraint -- does the shortnames
X	stuff take care of this?  I can't test it...
X
M	:k, to set a mark, won't work as ":ka" or ":kb".  Must use ":k a"
X
M	:set all should be made to work (fix help)
X
L	formatregion sometimes appends a space to the last line, for instance
X	when a paragraph is reformatted
X
L	dos-style is set even when file is majority unix-lines?
X
L	why does file reading seem so slow?
X
L	why is searching so slow?
X
L	with two window displayed, hitting * twice makes one go away.
X	perhaps popup should _always_ split a window, rather than sometimes
X	taking over an existing one.  but then we'd have to remember who we
X	split, so we could give the space back to the donor.
X
E	patterns as addresses do not work, e.g. ":/str1/,/str2/d".  They're
X	hard to parse the way things are set up right now.  We could accumulate
X	the whole commandline, and then parse it, the way real vi does, but we'd
X	lose the "prompt and display last response" behavior.
X
E	In vi, the join command is supposed to act either on a region (from
X	the command line, as in ":13,15j"), or it should take a simple
X	count, from vi mode, as in "3j".  Right now vile _only_ does the
X	simple count form of the command.
X
E	should add an option to support file locking, rather than the
X	current ifdef stuff -- but this is only useful if we match the
X	GNU locking protocol, which I'm not inclined to do
X
E	Wow. the scrsearch functions could become region based -- as in "search for
X	the next occrence of the region", which would usually be a word.  And
X	the ^A/ version could become "a/ (search for teh contents of buffer a),
X	if you know what I mean.
X
E	need a "file newer than buffer" warning.  Should stat the file, and
X	store it's mod time, compare to current when going back to that window,
X	after performing some shell command.  e.g., if you're editing a file
X	that is created by a script you're testing, then you want to be warned
X	that the file is out of date after doing a test run of the script.
X
E	should be able to refer to remote tags file, and have paths
X	contained there be relative to _its_ location, rather than the current
X	directory.
X
E	add a command-line expansion character to be the list of files
X	mentioned in "tags"
X
E	should there be a "significant-length" for tags?
X
E	another mode, which will "!get -p" an SCCS or RCS file if 
X	the clear-text file isn't found
X
E	add _another_ mode, similar to the above, which will do a caseless 
X	match against filenames mentioned in tags
X
E	it would be nice if ^X!! reran the last command into [Output]
X
E	add support for sh or C comments to formatregion() code
X
E	why can't I kill a displayed buffer?  simply bring up the previous.
X	
E	g should become a region command.  Then it could take ranges, as
X	it should, and could also become an operator command.
X
E	add C comments to CFENCE matching code
X
E	add C ifdefs to CFENCE matching code
X
E	adjust window size of popups based on length of buffer.  currently
X	popups get half the window they're splitting, no matter what
X
E	collapse command execution code to as few places as possible.
X	Its currently spread through main(), execute(), operator(),
X	docmd(), and usekreg().
X	
E	mlreply line should ideally be a one line buffer, so editing
X	and history can be done on it.
X
E	BSD interrupt processing is botched during a read() of the keyboard.
X	The read doesn't return -1 as it does under sysV (USG).
X	So you can bang on ^C all day and nothing will happen.
X	[I'm not sure this is true anymore  -pgf]
X	
E	This editor does not virtualize buffers out to disk.  It is quite 
X	a memory hog.  But isn't that what /dev/swap is for?  But
X	seriously, I haven't even come close to testing it for
X	memory-full conditions.  Some malloc() packages give 95%
X	warnings -- perhaps something like that should be done for
X	safety.
X
E	to make the code shrink, could probably try to eliminate
X	sprintf and its brethren.  mlwrite already does format
X	expansion, it could probably be turned into a doprnt-like
X	beast, and that used as a basis for our own sprintf,fprintf
X	How does one write [sfp]printf and doprnt using varargs?
X
E	likewise for scanf
X
E	marks should perhaps be linked onto lines.  this would make a lot
X        of things a lot easier, since a mark would travel with the
X        line, instead of having to be moved when the line is
X        reallocated etc.  the U line could be treated as a special
X        mark.  The "copied" flag needed by undo could be a special
X        sort of mark as well.  Implementation of the "tag stack"
X	would be aided by this as well.
X
E	there is currently no way to change working directories -- it's
X	not clear whether that should be a global thing, or perhaps
X	a per-buffer notion.
X
E	there is code (in imdying()) that attempts to save unwritten buffers
X	on hangups.  It is fairly crude, having been written quickly
X	in self-defense during debugging.  It should be examined and
X	fixed.
X
E	:e and :n should be able to deal with multiple filenames resulting
X	from filename globbing.  vi has this problem too.  At least
X	vile lets you choose to choose the first such name.  if should show
X	you the first name, so you know whether to accept it or not.
X
E	^W should erase word in input mode, and killc should erase line 
X	in input mode.  (but only back to where the input started, if it
X	started on this line.  right now we have no record of that, hence
X	you can backspace past the insert point)
X
E	All code should pass lint.  This won't be easy... :-)
X	
SHAR_EOF
chmod 0444 buglist ||
echo 'restore of buglist failed'
Wc_c="`wc -c < 'buglist'`"
test 6009 -eq "$Wc_c" ||
	echo 'buglist: original size 6009, current size' "$Wc_c"
# ============= cmdtbl ==============
echo 'x - extracting cmdtbl (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'cmdtbl' &&
X
# This file contains all of the editor's command and key linkages.
#
# It should be processed by the "mktbls" program, which produces the
#  headers #included by main.c
#
# All that is necessary to add a new function to the editor is to add
#  an entry to this file, write the function, make sure it's in the
#  makefile, and rebuild.  (This is not to be confused with adding a
#  new key binding, which can be done with the rebind command if it
#  was compiled in.)
#
# If you want to know which keyboard bindings are already taken, look
#  at nebind.h, after you build it.
#
# The entries are functions within the editor.  They _must_ match the
#  functions' names.  On the same line as the name is the set of flags
#  describing that function.
# Also accompanying each function is a list of english names  for the 
#  command, in double quotes, and a list of keys bound to the command,
#  in single quotes.  These are the default key bindings -- they can change
#  at runtime.  English names must be all lowercase.
# Any function, name, or key may be followed by a conditional, i.e. the
#  name of a preprocessor #define which must be defined non-zero for that
#  line to become part of the editor.  If a function name is made conditional,
#  the names and keys listed with it will be conditional also.
# The names and keys must be preceded by a tab character.
# Blank lines must be completely empty.
# For convenience only, this table is kept in roughly alphabetical order, 
#  by first character of function name.
#
# For example, consider the following entry:
#
# 	somefunc	ABS|MOTION		BSD|DOS
#		"funkycom"
#		'^X-F'
#		'FN-2'				DOS
#
# This says that somefunc() is an absolute motion command, that it should
#  only be included in the editor if we're running BSD or DOS, that its
#  english name as one would type on the command line is "funkycom", and
#  that it is bound to ^X-F, and also to function key 2 under DOS.
#
# Function flags have the following meanings:
#	REDO means the dotcmd command recorder should be halted, so that
#		the command can be redone.
#	UNDO means the undo stacks should be cleared, in preparation for
#		an undoable command.
#	OPER means the command is an "operator", that is, it acts on a region
#		demarcated by the current cursor postion and the cursor position
#		following a subsequent motion command.
#	MOTION means this command moves dot, and specifically is compatible
#		with the operator commands.
#	FL only occurs with MOTION, means that if the motion is an argument
#		to an operator, the operation should affect Full Lines
#	ABS only occurs with MOTION, means that the motion is absolute,
#		i.e. not relative to the current postion or screen.  It causes
#		the "lastdotmark", ldmark to be set to dot before the move
#		takes place.
#	GOAL signifies a motion that will attempt to retain the 
#		current column postition after the motion.
#	GLOBOK says the function can follow a global command
#		(e.g. the 'd' in "g/pattern/d")
#
#	This file was designed and constructed by Paul Fox for vile, (c)1990
#
#	The flags given in parentheses are "ex" flags, related to what
#		kind of line-range arguments the command can take.  Not all are
#		currently used or implemented, but they were defined in the command
#		table for the Steve Kirkendall's elvis editor, so I included them
#		here for completeness.
X
altbuff		NONE
X	"alternate-buffer"		!FEWNAMES
X	'^^'
append		REDO|UNDO
X	"appendchar"			!FEWNAMES
X	'a'
appendeol	REDO|UNDO
X	"append-eol"			!FEWNAMES
X	'A'
apro		NONE			APROP|REBIND
X	"apropos"
backchar	MOTION
X	"backward-character"		!FEWNAMES
X	'h'
X	'^H'
backdelchar	REDO|UNDO
X	"delete-previous-character"	!FEWNAMES
X	'X'
backhunt	ABS|MOTION		!SMALLER
X	"hunt-backward"
backhpage	NONE
X	"previous-half-page"		!FEWNAMES
X	'^U'
backline	GOAL|MOTION|FL
X	"previous-line"			!FEWNAMES
X	'k'
backbline	MOTION|FL
X	"previous-line-at-bol"		!FEWNAMES
X	'-'
backpage	MOTION
X	"previous-page"			!FEWNAMES
X	'^B'
backword	MOTION
X	"previous-word"			!FEWNAMES
X	'B'
backviword	MOTION
X	"previous-punc-word"		!FEWNAMES
X	'b'
backsearch	ABS|MOTION
X	"search-reverse"		!FEWNAMES
X	'?'
bcsrch		MOTION
X	"backward-char-scan"		!FEWNAMES
X	'F'
bcsrch_to	MOTION
X	"backward-char-scan-to"		!FEWNAMES
X	'T'
bindkey		NONE			REBIND
X	"bind-key"
X	"rebind-key"
bktoshell	NONE			UNIX&&defined(SIGTSTP)
X	"suspend-emacs"			!FEWNAMES
X	'^Z'
cntl_xf		NONE
X	"cntl_x-prefix"			!FEWNAMES
X	'^X'
chgchar		REDO|UNDO
X	"change-char"			!FEWNAMES
X	's'
chgline		REDO|UNDO
X	"change-line"			!FEWNAMES
X	'S'
chgtoeol	REDO|UNDO
X	"change-to-end-of-line"		!FEWNAMES
X	'C'
clrmes		NONE
X	"clear-message-line"		!FEWNAMES
consearch	ABS|MOTION
X	"continue-search"		!FEWNAMES
X	'n'
opercopy		OPER|(RANGE|EXTRA)
X	"copy"
X	"c"
ctlxlp		NONE
X	"begin-macro"			!FEWNAMES
X	'^X-('
ctlxrp		NONE
X	"end-macro"			!FEWNAMES
X	'^X-)'
ctlxe		REDO
X	"execute-macro"			!FEWNAMES
X	'^X-&'
cbuf1		REDO
X	"execute-macro-1"		!FEWNAMES
X	'FN-1'				TERMCAP
cbuf2		REDO
X	"execute-macro-2"		!FEWNAMES
X	'FN-2'				TERMCAP
cbuf3		REDO
X	"execute-macro-3"		!FEWNAMES
X	'FN-3'				TERMCAP
cbuf4		REDO
X	"execute-macro-4"		!FEWNAMES
X	'FN-4'				TERMCAP
cbuf5		REDO
X	"execute-macro-5"		!FEWNAMES
X	'FN-5'				TERMCAP
cbuf6		REDO
X	"execute-macro-6"		!FEWNAMES
X	'FN-6'				TERMCAP
cbuf7		REDO
X	"execute-macro-7"		!FEWNAMES
X	'FN-7'				TERMCAP
cbuf8		REDO
X	"execute-macro-8"		!FEWNAMES
X	'FN-8'				TERMCAP
cbuf9		REDO
X	"execute-macro-9"		!FEWNAMES
X	'FN-9'				TERMCAP
cbuf10		REDO
X	"execute-macro-10"		!FEWNAMES
cbuf11		REDO			!SMALLER
X	"execute-macro-11"		!FEWNAMES
cbuf12		REDO			!SMALLER
X	"execute-macro-12"		!FEWNAMES
cbuf13		REDO			!SMALLER
X	"execute-macro-13"		!FEWNAMES
cbuf14		REDO			!SMALLER
X	"execute-macro-14"		!FEWNAMES
cbuf15		REDO			!SMALLER
X	"execute-macro-15"		!FEWNAMES
cbuf16		REDO			!SMALLER
X	"execute-macro-16"		!FEWNAMES
cbuf17		REDO			!SMALLER
X	"execute-macro-17"		!FEWNAMES
cbuf18		REDO			!SMALLER
X	"execute-macro-18"		!FEWNAMES
cbuf19		REDO			!SMALLER
X	"execute-macro-19"		!FEWNAMES
cbuf20		REDO			!SMALLER
X	"execute-macro-20"		!FEWNAMES
cbuf21		REDO			!SMALLER
X	"execute-macro-21"		!FEWNAMES
cbuf22		REDO			!SMALLER
X	"execute-macro-22"		!FEWNAMES
cbuf23		REDO			!SMALLER
X	"execute-macro-23"		!FEWNAMES
cbuf24		REDO			!SMALLER
X	"execute-macro-24"		!FEWNAMES
cbuf25		REDO			!SMALLER
X	"execute-macro-25"		!FEWNAMES
cbuf26		REDO			!SMALLER
X	"execute-macro-26"		!FEWNAMES
cbuf27		REDO			!SMALLER
X	"execute-macro-27"		!FEWNAMES
cbuf28		REDO			!SMALLER
X	"execute-macro-28"		!FEWNAMES
cbuf29		REDO			!SMALLER
X	"execute-macro-29"		!FEWNAMES
cbuf30		REDO			!SMALLER
X	"execute-macro-30"		!FEWNAMES
cbuf31		REDO			!SMALLER
X	"execute-macro-31"		!FEWNAMES
cbuf32		REDO			!SMALLER
X	"execute-macro-32"		!FEWNAMES
cbuf33		REDO			!SMALLER
X	"execute-macro-33"		!FEWNAMES
cbuf34		REDO			!SMALLER
X	"execute-macro-34"		!FEWNAMES
cbuf35		REDO			!SMALLER
X	"execute-macro-35"		!FEWNAMES
cbuf36		REDO			!SMALLER
X	"execute-macro-36"		!FEWNAMES
cbuf37		REDO			!SMALLER
X	"execute-macro-37"		!FEWNAMES
cbuf38		REDO			!SMALLER
X	"execute-macro-38"		!FEWNAMES
cbuf39		REDO			!SMALLER
X	"execute-macro-39"		!FEWNAMES
cbuf40		REDO			!SMALLER
X	"execute-macro-40"		!FEWNAMES
delwind		NONE
X	"delete-window"			!FEWNAMES
X	'^K'
X	'^X-0'
deblank		REDO|UNDO		AEDIT
X	"delete-blank-lines"		!FEWNAMES
X	'^A-o'
delgmode	NONE
X	"delete-global-mode"		!FEWNAMES
X	"setgno"
X	"unsetg"
delmode		NONE|(EXRCOK|EXTRA)
X	"delete-mode"			!FEWNAMES
X	"setno"
X	"unset"
deltoeol	REDO|UNDO
X	"delete-to-end-of-line"		!FEWNAMES
X	'D'
desbind		NONE			REBIND
X	"describe-bindings"
deskey		NONE			REBIND
X	"describe-key"
detab		REDO|UNDO		AEDIT
X	"detab-line"			!FEWNAMES
X	'^A- '
dotcmdplay	NONE
X	"repeat-last-cmd"		!FEWNAMES
X	'.'
execbuf		NONE			!SMALLER
X	"execute-buffer"		!FEWNAMES
execcmd		NONE			NEVER
X	"execute-command-line"		!FEWNAMES
execfile	NONE			!SMALLER
X	"execute-file"			!FEWNAMES
execproc	REDO			PROC
X	"execute-procedure"		!FEWNAMES
X	"run"
enlargewind	NONE
X	"grow-window"			!FEWNAMES
X	'V'
entab		REDO|UNDO		AEDIT
X	"entab-line"			!FEWNAMES
X	'^A-^I'
esc		NONE
X	"abort-command"			!FEWNAMES
X	'^['
fcsrch		MOTION
X	"forward-char-scan"		!FEWNAMES
X	'f'
fcsrch_to	MOTION
X	"forward-char-scan-to"		!FEWNAMES
X	't'
filefind	NONE|(BANG|FILE1|PLUS)
X	"e"
X	"E"
X	"edit-file"			!FEWNAMES
X	"find-file"			!FEWNAMES
X	'^X-e'
filename	NONE|(NAMEDF)
X	"change-file-name"		!FEWNAMES
X	"f"
X	"file"
X	"filename"
fileread	NONE
X	"e!"
X	"replace-with-file"		!FEWNAMES
filesave	NONE			!SMALLER
X	"save-file"
filewrite	NONE
#	"w"
#	"W"
X	"write-file"			!FEWNAMES
filter		REDO|UNDO
X	"|"
X	"filter-buffer"			!FEWNAMES
finderr		NONE			FINDERR
X	"find-next-error"		!FEWNAMES
X	'^X-^X'
firstnonwhite	MOTION
X	"first-nonwhite"		!FEWNAMES
X	'^'
fisearch	NONE			ISRCH
X	"incremental-search"		!FEWNAMES
X	'^X-S'
flipchar	REDO|UNDO
X	"flip-character"		!FEWNAMES
X	'~'
fnclabel	NONE			FLABEL
X	"label-function-key"		!FEWNAMES
X	"label-fkey"
forwdelchar	REDO|UNDO
X	"delete-next-character"		!FEWNAMES
X	'x'
forwhpage	NONE
X	"next-half-page"		!FEWNAMES
X	'^D'
forwchar	MOTION
X	"forward-character"		!FEWNAMES
X	' '
X	'l'
forwpage	MOTION
X	"next-page"			!FEWNAMES
X	'^F'
forwline	GOAL|MOTION|FL
X	"next-line"			!FEWNAMES
X	'j'
X	'^J'
forwbline	MOTION|FL
X	"next-line-at-bol"		!FEWNAMES
X	'+'
X	'^M'
forwword	MOTION
X	"next-word"			!FEWNAMES
X	'W'
forwviword	MOTION
X	"next-punc-word"		!FEWNAMES
X	'w'
forwendw	MOTION
X	"next-word-end"			!FEWNAMES
X	'E'
forwviendw	MOTION
X	"next-punc-word-end"		!FEWNAMES
X	'e'
forwhunt	ABS|MOTION		!SMALLER
X	"hunt-forward"			!FEWNAMES
forwsearch	ABS|MOTION
X	"search-forward"		!FEWNAMES
X	'/'
getfence	ABS|MOTION		CFENCE
X	"goto-matching-fence"		!FEWNAMES
X	'%'
globals		NONE			GLOBALS
X	"og"
# this function is for internal use only, for the operator commands
godotplus	MOTION|FL
X
# this function is for internal use only, for ex commands
gomark		MOTION|FL|(RANGE)
X
gotobop		ABS|MOTION		WORDPRO
X	"previous-paragraph"		!FEWNAMES
X	'{'
gotoeop		ABS|MOTION		WORDPRO
X	"next-paragraph"		!FEWNAMES
X	'}'
gotobob		ABS|MOTION		!SMALLER
X	"beginning-of-file"		!FEWNAMES
gotoeob		ABS|MOTION		!SMALLER
X	"end-of-file"			!FEWNAMES
gotobol		MOTION
X	"beginning-of-line"		!FEWNAMES
X	'0'
gotoeol		MOTION|GOAL
X	"end-of-line"			!FEWNAMES
X	'$'
gotobos		MOTION|FL
X	"beginning-of-screen"		!FEWNAMES
X	'H'
gotomos		MOTION|FL
X	"middle-of-screen"		!FEWNAMES
X	'M'
gotoeos		MOTION|FL
X	"end-of-screen"			!FEWNAMES
X	'L'
gotobosec	ABS|MOTION		WORDPRO
X	"previous-section"		!FEWNAMES
X	'['
gotoeosec	ABS|MOTION		WORDPRO
X	"next-section"			!FEWNAMES
X	']'
gototag		NONE|(BANG|WORD1)		TAGS
X	"ta"
X	"tag"
X	"find-tag"			!FEWNAMES
X	'^]'
gotocol		MOTION
X	"goto-column"			!FEWNAMES
X	'|'
gotoline	ABS|MOTION|FL|(RANGE)
X	"goto-line"			!FEWNAMES
X	'G'
# golinenmmark and goexactnmmark are special cases--	
# 	no ABS even though they are absolute, since these are the commands
#	that maintain the last-dot-mark
golinenmmark	MOTION|FL
X	"goto-named-mark"		!FEWNAMES
#  single quote -- can't use '''
X	'\047'
goexactnmmark	MOTION
X	"goto-named-mark-exact"		!FEWNAMES
X	'`'
help		NONE
X	"h"
X	"help"
X	'^A-h'
X	'^X-h'
histbuff	NONE
X	"historical-buffer"		!FEWNAMES
X	'_'
X	"_"
insert		REDO|UNDO
X	"insertchar"			!FEWNAMES
X	'i'
insertbol	REDO|UNDO
X	"insert-bol"			!FEWNAMES
X	'I'
insfiletop		REDO|UNDO	BEFORE
X	"R"
X	"insert-file-at-top"			!FEWNAMES
insfile		REDO|UNDO|GLOBOK|(FROM|ZERO|NAMEDF)
X	"r"
X	"insert-file"			!FEWNAMES
X	'^R'
insspace	REDO|UNDO		!SMALLER
X	"insert-space"			!FEWNAMES
istring		REDO|UNDO		!SMALLER
X	"insert-string"
join		REDO|UNDO
X	"join-lines"			!FEWNAMES
X	'J'
killbuffer	NONE
X	"delete-buffer"			!FEWNAMES
X	"kill-buffer"			!FEWNAMES
X	"ki"
showlength	NONE
X	"buffer-length"			!FEWNAMES
X	"="
lastnonwhite	MOTION			!SMALLER
X	"last-nonwhite"			!FEWNAMES
listbuffers	NONE
X	"list-buffers"			!FEWNAMES
X	'^A-*'
lineputafter	REDO|UNDO|GLOBOK|(FROM|ZERO|WORD1)
X	"put-as-lines-after"		!FEWNAMES
X	"put"
X	'^X-p'
lineputbefore	REDO|UNDO|GLOBOK|(FROM|WORD1)
X	"put-as-lines-before"		!FEWNAMES
X	"Put"
X	'^X-P'
lineundo	NONE
X	"undo-line-changes"		!FEWNAMES
X	'U'
map		NONE|(EXRCOK|BANG|EXTRA)
X	"map"
cntl_af		NONE
X	"cntl_a-prefix"
X	'^A'
opermove	OPER|(RANGE|EXTRA)
X	"move"
X	"m"
mvdnnxtwind	NONE
X	"move-next-window-down"		!FEWNAMES
X	'^A-^E'
mvupnxtwind	NONE
X	"move-next-window-up"		!FEWNAMES
X	'^A-^Y'
mvdnwind	GOAL
X	"move-window-down"		!FEWNAMES
X	'^E'
mvupwind	GOAL
X	"move-window-up"		!FEWNAMES
X	'^Y'
mvrightwind	GOAL
X	"move-window-right"		!FEWNAMES
X	'^X-^R'
mvleftwind	GOAL
X	"move-window-left"		!FEWNAMES
X	'^X-^L'
nextbuffer	NONE|(BANG|NAMEDFS)
X	"n"
X	"next-buffer"			!FEWNAMES
namebuffer	NONE
X	"rename-buffer"
newline		REDO|UNDO		!SMALLER
X	"newline"
newlength	NONE
X	"screen-rows"
newwidth	NONE
X	"screen-columns"
nextwind	NONE
X	"next-window"			!FEWNAMES
X	'^N'
nullproc	NONE
X	"nop"				!FEWNAMES
X	'^Q'
X	'^S'
onamedcmd	NONE
X	"execute-named-command-old"	!FEWNAMES
X	'^A-:'
namedcmd	NONE
X	"execute-named-command"		!FEWNAMES
X	":"
X	':'
ex	NONE|(BANG|FILE1)
X	"ex"
operchg		OPER|REDO|UNDO
X	"change-til"			!FEWNAMES
X	'c'
operlinechg	OPER|REDO|UNDO|(RANGE)
X	"change-lines-til"		!FEWNAMES
X	"ch"
X	'^X-c'
operdel		OPER|REDO|UNDO
X	"delete-til"			!FEWNAMES
X	'd'
operlinedel	OPER|REDO|UNDO|GLOBOK|(RANGE+WORD1)
X	"delete-lines-til"		!FEWNAMES
X	"d"
X	'^X-d'
operfilter	OPER|REDO|UNDO|(EXRCOK|RANGE|NAMEDFS|DFLNONE|NL)
X	"filter-til"			!FEWNAMES
X	"!"
X	'!'
operformat	OPER|REDO|UNDO|(RANGE)		WORDPRO
X	"format-til"			!FEWNAMES
X	'^A-f'
X	'^A-j'
operflip	OPER|REDO|UNDO|GLOBOK|(RANGE)
X	"flip-til"			!FEWNAMES
X	"~"
X	'^A-~'
# RANGE commented out, since it's not done.... 
operglobals	OPER|(/*RANGE|*/BANG|EXTRA|DFLALL)	GLOBALS
X	"global"
X	"g"
opervglobals	OPER|(RANGE|BANG|EXTRA|DFLALL)	GLOBALS
X	"vglobal"
X	"v"
operlower	OPER|REDO|UNDO|GLOBOK|(RANGE)
X	"lower-til"			!FEWNAMES
X	"L"
X	'^A-l'
operlist	OPER|GLOBOK|(RANGE)		GLOBALS
X	"list-lines-til"		!FEWNAMES
X	"l"
operprint	OPER|GLOBOK|(RANGE)		GLOBALS
X	"print-lines-til"		!FEWNAMES
X	"p"
operupper	OPER|REDO|UNDO|GLOBOK|(RANGE)
X	"upper-til"			!FEWNAMES
X	"U"
X	'^A-u'
operlshift	OPER|REDO|UNDO|GLOBOK|(RANGE)
X	"shift-left-til"		!FEWNAMES
X	"<"
X	'<'
operrshift	OPER|REDO|UNDO|GLOBOK|(RANGE)
X	"shift-right-til"		!FEWNAMES
X	">"
X	'>'
opersubst	OPER|REDO|UNDO|GLOBOK|(RANGE|EXTRA)
X	"substitute"			!FEWNAMES
X	"s"
X	'^X-s'
operyank	OPER
X	"yank-til"			!FEWNAMES
X	'y'
operlineyank	OPER|(RANGE|WORD1)
X	"yank-lines-til"		!FEWNAMES
X	"y"
X	'^X-y'
openup		REDO|UNDO|(FROM)
X	"open-line-above"		!FEWNAMES
X	"insert"
X	"i"
X	'O'
opendown	REDO|UNDO|(FROM|ZERO)
X	"open-line-below"		!FEWNAMES
X	"append"
X	"a"
X	'o'
operwrite	OPER|(RANGE|BANG|FILE1|DFLALL)
X	"w"
X	"W"
X	"write-til"			!FEWNAMES
X	'^W'
overwrite	REDO|UNDO
X	"overwrite"			!FEWNAMES
X	'R'
onlywind	NONE
X	"delete-other-windows"		!FEWNAMES
X	'^O'
X	'^X-1'
poswind		NONE
X	"position-window"		!FEWNAMES
X	'z'
prevwind	NONE
X	"previous-window"		!FEWNAMES
X	'^P'
pipecmd		NONE
X	"pipe-command"			!FEWNAMES
X	'^X-!'
putafter	REDO|UNDO
X	"put-after"			!FEWNAMES
X	'p'
putbefore	REDO|UNDO
X	"put-before"			!FEWNAMES
X	'P'
quit		NONE|(BANG)
X	"q"
X	"Q"
X	"exit"
X	'Q'
X	'^X-^C'
quithard	NONE
X	"q!"
quickexit	NONE|(BANG|NL)
X	"x"
X	"xit"
X	"quick-exit"			!FEWNAMES
X	'Z'
quote		REDO|UNDO
X	"quote-character"		!FEWNAMES
X	'^V'
refresh		NONE
X	"clear-and-redraw"		!FEWNAMES
X	'^L'
reposition	NONE			!SMALLER
X	"redraw-display"
rep_csrch	MOTION
X	"repeat-char-scan"		!FEWNAMES
X	';'
replacechar	REDO|UNDO
X	"replace-character"		!FEWNAMES
X	'r'
respawn		NONE
X	"!!"
X	"rerun-shell-command"		!FEWNAMES
resize		NONE			!SMALLER
X	"resize-window"
restwnd		NONE			!SMALLER
X	"restore-window"
rev_csrch	MOTION
X	"reverse-char-scan"		!FEWNAMES
X	','
risearch	NONE			ISRCH
X	"reverse-incremental-search"	!FEWNAMES
X	'^X-R'
revsearch	ABS|MOTION
X	"reverse-search"		!FEWNAMES
X	'N'
scrforwsearch	ABS|MOTION
X	"screen-search-forward"		!FEWNAMES
X	'^X-/'
scrbacksearch	ABS|MOTION
X	"screen-search-reverse"		!FEWNAMES
X	'^X-?'
scrsearchpat	NONE
X	"screen-search-pattern-grab"	!FEWNAMES
X	'^A-/'
settab		NONE
X	"handle-tab"			!FEWNAMES
X	"set-tab"
X	'^X-t'
spawncli	NONE
X	"sh"
X	"shell"
X	"i-shell"			!FEWNAMES
savewnd		NONE			!SMALLER
X	"save-window"
scrnextup	NONE
X	"scroll-next-up"		!FEWNAMES
X	'^A-^U'
scrnextdw	NONE
X	"scroll-next-down"		!FEWNAMES
X	'^A-^D'
setfillcol	NONE
X	"set-fill-column"
X	'^X-f'
setkey		NONE			CRYPT
X	"set-crypt-key"
X	'^X-X'
setmode		NONE|(EXRCOK|EXTRA)
X	"set"
X	"set-mode"			!FEWNAMES
setgmode	NONE
X	"setg"
X	"set-global-mode"
setnmmark	NONE|(FROM+WORD1)
X	"set-named-mark"		!FEWNAMES
X	"k"
X	'm'
setvar		NONE			!SMALLER
X	"setv"
X	"set-variable"
setvmalloc	NONE			VMALLOC
X	"vmalloc"
X	'^X-v'
showcpos	NONE
X	"position"		!FEWNAMES
X	'^G'
X	'^X-='
showmodes	NONE
X	"modes"
X	"show-modes"
X	"setall"
showgmodes	NONE
X	"gmodes"
X	"show-global-modes"
X	"setgall"
showversion	NONE|(EXRCOK)
X	"version"
shrinkwind	NONE
X	"shrink-window"			!FEWNAMES
X	'v'
source		NONE|(EXRCOK|NAMEDF)
X	"source"
spawn		NONE
#	"!"
X	"shell-command"			!FEWNAMES
splitwind	NONE
X	"split-current-window"		!FEWNAMES
X	'^T'
X	'^X-2'
storemac	NONE
X	"store-macro"
storeproc	NONE			PROC
X	"store-procedure"
subst_again	REDO|UNDO|GLOBOK|(RANGE|EXTRA)
X	"substitute-again"		!FEWNAMES
X	"&"
opertransf	OPER|(RANGE+EXTRA)
X	"t"
togglelistbuffers	NONE
X	"*"
X	"toggle-buffer-list"		!FEWNAMES
X	'*'
trimline		REDO|UNDO|GLOBOK
X	"trim-line"			!FEWNAMES
X	"trim"
X	'^A-t'
twiddle		REDO|UNDO		!SMALLER
X	"transpose-characters"		!FEWNAMES
unbindkey	NONE			REBIND
X	"unbind-key"
undo		NONE
X	"undo-change"			!FEWNAMES
X	'u'
unarg		NONE
X	"universal-argument"		!FEWNAMES
X	'K'
unimpl		NONE
X	"unimplemented-command"		!FEWNAMES
X	'('
X	')'
unmark		NONE
X	"unmark-buffer"
unmap		NONE|(EXRCOK|BANG|EXTRA)
X	"unmap"
untagpop	NONE			TAGS
X	"untag-pop"			!FEWNAMES
X	'^X-^]'
upscreen	NONE			!SMALLER
X	"update-screen"
usebuffer	NONE
X	"b"
X	"buffer"
X	"select-buffer"			!FEWNAMES
usekreg		REDO
X	"use-named-kill-register"	!FEWNAMES
X	'"'
visual		NONE
X	"visual"
vglobals	NONE			GLOBALS
X	"ov"
viewfile	NONE
X	"view-file"
writequit	NONE|(NL)
X	"wq"
X	"Wq"
X	"WQ"
X	"write-file-and-quit"		!FEWNAMES
wrapword	REDO|UNDO		!SMALLER
X	"wrap-word"
writemsg	NONE			!SMALLER
X	"write-message"
yankline	NONE
X	"yank-line"			!FEWNAMES
X	'Y'
X
SHAR_EOF
chmod 0444 cmdtbl ||
echo 'restore of cmdtbl failed'
Wc_c="`wc -c < 'cmdtbl'`"
test 17753 -eq "$Wc_c" ||
	echo 'cmdtbl: original size 17753, current size' "$Wc_c"
# ============= crypt.c ==============
echo 'x - extracting crypt.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'crypt.c' &&
/*	Crypt:	Encryption routines for MicroEMACS
X		written by Dana Hoggatt and Daniel Lawrence
*/
X
#include	<stdio.h>
#include	"estruct.h"
#include	"edef.h"
X
#if	CRYPT
setkey(f, n)	/* reset encryption key of current buffer */
X
int f;		/* default flag */
int n;		/* numeric argument */
X
{
X	register int status;	/* return status */
X	int odisinp;		/* original vlaue of disinp */
X	char key[NPAT];		/* new encryption string */
X
X	/* turn command input echo off */
X	odisinp = disinp;
X	disinp = FALSE;
X
X	/* get the string to use as an encrytion string */
X	key[0] = 0;
X	status = mlreply("Encryption String: ", key, NPAT - 1);
X	disinp = odisinp;
X        if (status != TRUE)
X                return(status);
X
X	/* and encrypt it */
X	crypt((char *)NULL, 0);
X	crypt(key, strlen(key));
X
X	/* and save it off */
X	strcpy(curbp->b_key, key);
X	mlwrite(" ");		/* clear it off the bottom line */
X	return(TRUE);
}
X
/**********
X *
X *	crypt - in place encryption/decryption of a buffer
X *
X *	(C) Copyright 1986, Dana L. Hoggatt
X *	1216, Beck Lane, Lafayette, IN
X *
X *	When consulting directly with the author of this routine, 
X *	please refer to this routine as the "DLH-POLY-86-B CIPHER".  
X *
X *	This routine was written for Dan Lawrence, for use in V3.8 of
X *	MicroEMACS, a public domain text/program editor.  
X *
X *	I kept the following goals in mind when preparing this function:
X *
X *	    1.	All printable characters were to be encrypted back
X *		into the printable range, control characters and
X *		high-bit characters were to remain unaffected.  this
X *		way, encrypted would still be just as cheap to 
X *		transmit down a 7-bit data path as they were before.
X *
X *	    2.	The encryption had to be portable.  The encrypted 
SHAR_EOF
true || echo 'restore of crypt.c failed'
echo 'End of Vile part 2'
echo 'File crypt.c is continued in part 3'
echo 3 > _shar_seq_.tmp
exit 0
-- 
		paul fox, pgf@cayman.com, (617)494-1999
		Cayman Systems, 26 Landsdowne St., Cambridge, MA 02139