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

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

#!/bin/sh
# this is vileshar.05 (part 5 of Vile)
# do not concatenate these parts, unpack them in order with /bin/sh
# file efunc.h continued
#
if test ! -r _shar_seq_.tmp; then
	echo 'Please unpack part 1 first!'
	exit 1
fi
(read Scheck
 if test "$Scheck" != 5; then
	echo Please unpack part "$Scheck" next!
	exit 1
 else
	exit 0
 fi
) < _shar_seq_.tmp || exit 1
echo 'x - continuing file efunc.h'
sed 's/^X//' << 'SHAR_EOF' >> 'efunc.h' &&
#if ! SMALLER
X	{"save-window",			savewnd,	NONE },
#endif
X	{"scroll-next-up",		scrnextup,	NONE },
X	{"scroll-next-down",		scrnextdw,	NONE },
X	{"search-forward",		forwsearch,	ABS|MOTION },
X	{"search-reverse",		backsearch,	ABS|MOTION },
X	{"select-buffer",		usebuffer,	NONE },
X	{"set",				setmode,	NONE },
X	{"setall",			showmodes,	NONE },
X	{"setg",			setgmode,	NONE },
X	{"setgall",			showgmodes,	NONE },
X	{"setgno",			delgmode,	NONE },
X	{"setno",			delmode,	NONE },
#if ! SMALLER
X	{"setv",			setvar,		NONE },
#endif
#if	CRYPT
X	{"set-encryption-key",		setkey,		NONE },
#endif
X	{"set-fill-column",		setfillcol,	NONE },
X	{"set-named-mark",		setnmmark,	NONE },
X	{"set-mark",			setmark,	NONE },
X	{"sh",				spawncli,	NONE },
X	{"shell-command",		spawn,		NONE },
X	{"shift-left-til",		operlshift,	REDO|UNDO },
X	{"shift-right-til",		operrshift,	REDO|UNDO },
X	{"show-modes",			showmodes,	NONE },
X	{"show-global-modes",		showgmodes,	NONE },
X	{"shrink-window",		shrinkwind,	NONE },
X	{"split-current-window",	splitwind,	NONE },
X	{"store-macro",			storemac,	NONE },
#if	PROC
X	{"store-procedure",		storeproc,	NONE },
#endif
#if	BSD
X	{"suspend-emacs",		bktoshell,	NONE },
#endif
#if TAGS
X	{"ta",				gototag,	NONE },
X	{"tag",				gototag,	NONE },
#endif
X	{"toggle-buffer-list",		togglelistbuffers,	NONE },
#if ! SMALLER
X	{"transpose-characters",	twiddle,	REDO|UNDO },
#endif
#if	AEDIT
X	{"trim-line",			trim,		REDO|UNDO },
#endif
X	{"unbind-key",			unbindkey,	NONE },
X	{"undo-change",			undo,		NONE },
X	{"undo-line-changes",		lineundo,	NONE },
X	{"universal-argument",		unarg,		NONE },
X	{"unmark-buffer",		unmark,		NONE },
X	{"unsetg",			delgmode,	NONE },
X	{"unset",			delmode,	NONE },
X	{"update-screen",		upscreen,	NONE },
X	{"upper-til",			operupper,	REDO|UNDO },
X	{"use-named-kill-register",	usekreg,	REDO },
X	{"view-file",			viewfile,	NONE },
X	{"w",				filesave,	NONE },
#if	WORDPRO
X	{"wc",				wordcount,	NONE },
#endif
X	{"wq",				writequit,	NONE },
X	{"wrap-word",			wrapword,	REDO|UNDO },
X	{"write-file",			filewrite,	NONE },
X	{"write-file-and-quit",		writequit,	NONE },
#if ! SMALLER
X	{"write-message",		writemsg,	NONE },
#endif
X	{"write-til",			operwrite,	NONE },
X	{"x",				quickexit,	NONE },
X	{"yank-line",			yankline,	NONE },
X	{"yank-lines-til",		operlineyank,	NONE },
X	{"yank-til",			operyank,	NONE },
X
X	{"",			NULL}
};
SHAR_EOF
echo 'File efunc.h is complete' &&
chmod 0444 efunc.h ||
echo 'restore of efunc.h failed'
Wc_c="`wc -c < 'efunc.h'`"
test 27465 -eq "$Wc_c" ||
	echo 'efunc.h: original size 27465, current size' "$Wc_c"
# ============= epath.h ==============
echo 'x - extracting epath.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'epath.h' &&
/*	EPATH:	This file contains certain info needed to locate the
X		MicroEMACS files on a system dependant basis.
X
X									*/
X
/*	possible names and paths of help files under different OSs	*/
X
/* first two entries are default startup and help files, the rest are
X	possible places to look for them */
X
char *pathname[] =
X
#if	AMIGA
{
X	".vilerc",
X	"vile.hlp",
X	"",
X	"sys:c/",
X	"sys:t/",
X	"sys:s/",
X	":c/",
X	":t/",
X	":s/"
};
#endif
X
#if	ST520
{
X	"vile.rc",
X	"vile.hlp",
X	"\\",
X	"\\bin\\",
X	"\\util\\",
X	""
};
#endif
X
#if	FINDER
{
X	"vile.rc",
X	"vile.hlp",
X	"/bin",
X	"/sys/public",
X	""
};
#endif
X
#if	MSDOS
{
X	"vile.rc",
X	"vile.hlp",
X	"\\sys\\public\\",
X	"\\usr\\bin\\",
X	"\\bin\\",
X	"\\",
X	""
};
#endif
X
#if	V7 | BSD | USG
{
X	".vilerc",
X	"vile.hlp",
X	"/usr/local/",
X	"/usr/lib/",
X	"/usr/local/bin",
X	"/usr/local/lib",
X	""
};
#endif
X
#if	VMS
{
X	"vile.rc",
X	"vile.hlp",
X	"",
X	"sys$sysdevice:[vmstools]"
};
#endif
X
#define	NPNAMES	(sizeof(pathname)/sizeof(char *))
SHAR_EOF
chmod 0444 epath.h ||
echo 'restore of epath.h failed'
Wc_c="`wc -c < 'epath.h'`"
test 956 -eq "$Wc_c" ||
	echo 'epath.h: original size 956, current size' "$Wc_c"
# ============= estruct.h ==============
echo 'x - extracting estruct.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'estruct.h' &&
/*	ESTRUCT:	Structure and preprocesser defines for
X			vile.  Reshaped from the original, which
X			was for MicroEMACS 3.9
X
X			vile is by Paul Fox
X			MicroEmacs was written by Dave G. Conroy
X			modified by Steve Wilhite, George Jones
X			substantially modified by Daniel Lawrence
*/
X
#ifdef	LATTICE
#undef	LATTICE		/* don't use their definitions...use ours	*/
#endif
#ifdef	MSDOS
#undef	MSDOS
#endif
#ifdef	CPM
#undef	CPM
#endif
#ifdef	AMIGA
#undef	AMIGA
#endif
#ifdef	EGA
#undef	EGA
#endif
X
/*	Machine/OS definitions			*/
/* sun, mips, generic 386, ODT, and Ultrix, see below... */
/* unix flavors */
#define BSD	1			/* UNIX BSD 4.2	and ULTRIX	*/
#define USG	0			/* UNIX system V		*/
#define V7	0			/* V7 UNIX or Coherent or BSD4.2*/
X					/*     presumably also Minix?	*/
/* unix sub-flavors */
#define ODT	0			/* UNIX OPEN DESK TOP		*/
#define ULTRIX	0			/* UNIX ULTRIX			*/
#define POSIX	0
X
/* non-unix flavors */
#define AMIGA	0			/* AmigaDOS			*/
#define ST520	0			/* ST520, TOS		       */
#define MSDOS	0			/* MS-DOS		       */
#define CPM	0			/* CP/M-86		       */
#define VMS	0			/* VAX/VMS		       */
X
/* the following overrides for sun, i386, and mips are for convenience only */
#if sun
# undef BSD
# undef USG
# define BSD	1			/* UNIX BSD 4.2	and ULTRIX	*/
# define USG	0			/* UNIX system V		*/
#endif
X
#if i386 || mips
# undef BSD
# undef USG
# define BSD	0			/* UNIX BSD 4.2	and ULTRIX	*/
# define USG	1			/* UNIX system V		*/
#endif
X
#if ODT
# undef POSIX
# undef BSD
# undef USG
# define POSIX	1
# define BSD	0			/* UNIX BSD 4.2	and ULTRIX	*/
# define USG	1			/* UNIX system V		*/
#endif
X
#if ULTRIX
# undef POSIX
# undef BSD
# undef USG
# define POSIX	1
# define BSD	1
# define USG	0			/* UNIX system V		*/
#endif
X
#define UNIX	(V7 | BSD | USG)	/* any unix		*/
X
#define OS	(UNIX | AMIGA | ST520 | MSDOS | CPM | VMS)
#if ! OS
X  you need to choose a system #define...
#endif
X
/*	Porting constraints			*/
#define HAVE_MKDIR	1	/* if your system has the mkdir() system call */
#define SHORTNAMES	0	/* if your compiler insists on 7 char names */
X
/*	Compiler definitions			*/
#define MWC86	0	/* marc williams compiler */
#define	LATTICE	0	/* Lattice 2.14 thruough 3.0 compilers */
#define	AZTEC	0	/* Aztec C 3.20e */
#define	MSC	0	/* MicroSoft C compile version 3 & 4 */
#define	TURBO	0	/* Turbo C/MSDOS */
X
/*	Terminal Output definitions		*/
/* choose one of the following */
#define TERMCAP 1			/* Use TERMCAP			*/
#define ANSI	0			/* ANSI escape sequences	*/
#define AT386	0			/* AT style 386 unix console	*/
#define	HP150	0			/* HP150 screen driver		*/
#define	HP110	0			/* HP110 screen driver		*/
#define	VMSVT	0			/* various VMS terminal entries	*/
#define VT52	0			/* VT52 terminal (Zenith).	*/
#define RAINBOW 0			/* Use Rainbow fast video.	*/
#define	IBMPC	0			/* IBM-PC CGA/MONO/EGA driver	*/
#define	DG10	0			/* Data General system/10	*/
#define	TIPC	0			/* TI Profesional PC driver	*/
#define	Z309	0			/* Zenith 100 PC family	driver	*/
#define	MAC	0			/* Macintosh			*/
#define	ATARI	0			/* Atari 520/1040ST screen	*/
#define NeWS	0			/* distributed */
X
/*   Special keyboard definitions	     */
#define WANGPC	0		/* WangPC - mostly escape sequences	*/
/* the WANGPC stuff isn't in the cmdtbl keyboard definitions: sorry -- pgf */
X
/*	Configuration options... pick and choose as you wish */
X
/* Appearance */
#define	TYPEAH	1	/* type ahead causes screen refresh to be delayed */
#define	REVSTA	1	/* Status line appears in reverse video		*/
#define	COLOR	0	/* color commands and windows			*/
#define	CLRMSG	0	/* space clears the message line with no insert	*/
X
/* Feature turnon/turnoff */
#define	CTRLZ	0	/* add a ^Z at end of files under MSDOS only	*/
#define	DOSFILES 1	/* turn on code for DOS mode (lines that end in crlf) */
X			/* use DOSFILES, for instance, if you edit DOS- */
X			/*	created files under UNIX		*/
#define	CFENCE	1	/* do fench matching in CMODE			*/
#define	REBIND	1	/* permit rebinding of keys at run-time		*/
#define	APROP	1	/* Add code for Apropos command	(needs REBIND)	*/
#define	FILOCK	0	/* file locking under unix BSD 4.2 (uses scanf) */
#define	ISRCH	1	/* Incremental searches like ITS EMACS		*/
#define	FLABEL	0	/* function key label code [HP150]		*/
#define	CRYPT	0	/* file encryption? (not crypt(1) compatible!)	*/
#define MAGIC	1	/* include regular expression matching?		*/
#define	TAGS	1	/* tags support.  requires MAGIC		*/
#define	WORDPRO	1	/* "Advanced" word processing features		*/
#define	AEDIT	1	/* advanced editing options: e.g. en/detabbing	*/
#define	PROC	1	/* named procedures				*/
#define	FINDERR	1	/* finderr support. uses scanf()		*/
#define	GLOBALS	1	/* "global" command support.			*/
#define	PATHLOOK 1	/* look along $PATH for startup and help files	*/
#define	SCROLLCODE 1	/* code in display.c for scrolling the screen.
X			   Only useful if your display can scroll
X			   regions, or at least insert/delete lines. 
X			   ANSI, TERMCAP, and AT386 can do this		 */
X
#define CVMVAS	1	/* arguments to forward/back page and half page */
X			/* are in pages	instead of rows */
#define PRETTIER_SCROLL 1 /* can improve the appearance of a scrolling screen */
#define STUTTER_SEC_CMD 0 /* must the next/prev section commands (i.e.
X				']]' and '[[' be stuttered?  they must be
X				stuttered in real vi, I prefer them not
X				to be */
X
/*	Code size options	*/
#define	FEWNAMES 0	/* strip some names - will no longer be bindable */
#define	SMALLER	0	/* strip out a bunch of uemacs fluff */
X			/* 	(to each their own... :-)  pgf) */
X
/*	Debugging options	*/
#define	RAMSIZE	0	/* dynamic RAM memory usage tracking */
#define	RAMSHOW	0	/* auto dynamic RAM reporting */
#define	VMALLOC	0	/* verify malloc operation (slow!) */
#define	DEBUG	1	/* allows core dump from keyboard under UNIX */
#define	TIMING	0	/* shows user time spent on each user command */
X			/* TIMING doesn't work yet... sorry  -pgf */ 
#define DEBUGM	0	/* $debug triggers macro debugging		*/
#define	VISMAC	0	/* update display during keyboard macros	*/
X
X
/* That's the end of the user selections -- the rest is static definition */
/* (i.e. you shouldn't need to touch anything below here */
/* ====================================================================== */
X
#if SHORTNAMES
#include "shorten/remap.h"
#endif
X
/*	System dependant library redefinitions, structures and includes	*/
X
#if	TURBO
#include      <dos.h>
#include      <mem.h>
#undef peek
#undef poke
#define       peek(a,b,c,d)   movedata(a,b,FP_SEG(c),FP_OFF(c),d)
#define       poke(a,b,c,d)   movedata(FP_SEG(c),FP_OFF(c),a,b,d)
#endif
X
#if	VMS
#define	atoi	xatoi
#define	abs	xabs
#define	getname	xgetname
#endif
X
#if	LATTICE
#define	unsigned
#endif
X
#if	AZTEC
#undef	fputc
#undef	fgetc
#if	MSDOS
#define	fgetc	a1getc
#else
#define	fgetc	agetc
#endif
#define	fputc	aputc
#define	int86	sysint
#define	intdos(a, b)	sysint(33, a, b)
#define	inp	inportb
#define	outp	outportb
X
struct XREG {
X	int ax,bx,cx,dx,si,di;
};
X
struct HREG {
X	char al,ah,bl,bh,cl,ch,dl,dh;
};
X
union REGS {
X	struct XREG x;
X	struct HREG h;
};
#endif
X
#if	MSDOS & MWC86
#include	<dos.h>
#define	int86(a, b, c)	intcall(b, c, a)
#define	inp	in
X
struct XREG {
X	int ax,bx,cx,dx,si,di,ds,es,flags;
};
X
struct HREG {
X	char al,ah,bl,bh,cl,ch,dl,dh;
X	int ds,es,flags;
};
X
union REGS {
X	struct XREG x;
X	struct HREG h;
};
#endif
X
#if	MSDOS & MSC
#include	<dos.h>
#include	<memory.h>
#define	peek(a,b,c,d)	movedata(a,b,FP_SEG(c),FP_OFF(c),d)
#define	poke(a,b,c,d)	movedata(FP_SEG(c),FP_OFF(c),a,b,d)
#define	movmem(a, b, c)		memcpy(b, a, c)
#endif
X
#if	MSDOS & LATTICE
#undef	CPM
#undef	LATTICE
#include	<dos.h>
#undef	CPM
#endif
X
#if	VMS
#define	unlink(a)	delete(a)
#endif
X
/*	define some ability flags */
X
#if	IBMPC | Z309
#define	MEMMAP	1
#else
#define	MEMMAP	0
#endif
X
#if	((MSDOS) & (LATTICE | AZTEC | MSC | TURBO)) | UNIX
#define	ENVFUNC	1
#else
#define	ENVFUNC	0
#endif
X
#if BSD
#define strchr index
#define strrchr rindex
#endif
X
#define TABVAL tabval
#define TABMASK tabmask
X
/*	internal constants	*/
X
#define	NBINDS	100			/* max # of bound prefixed keys	*/
#define NFILEN	80			/* # of bytes, file name	*/
#define NBUFN	20			/* # of bytes, buffer name	*/
#define NLINE	256			/* # of bytes, input line	*/
#define	NSTRING	128			/* # of bytes, string buffers	*/
#define NKBDM	256			/* # of strokes, keyboard macro */
#define NPAT	128			/* # of bytes, pattern		*/
#define HUGE	60000			/* Huge number			*/
#define	NLOCKS	100			/* max # of file locks active	*/
#define	NCOLORS	8			/* number of supported colors	*/
#define	KBLOCK	256			/* sizeof kill buffer chunks	*/
#define	NKREGS	36			/* number of kill buffers	*/
#define	NBLOCK	16			/* line block chunk size	*/
#define	NVSIZE	10			/* max #chars in a var name	*/
X
/* SPEC is just 8th bit set, for convenience in some systems (like NeWS?) */
#define SPEC	0x0080			/* special key (function keys)	*/
#define CTLA	0x0100			/* ^A flag, or'ed in		*/
#define CTLX	0x0200			/* ^X flag, or'ed in		*/
X
#define kcod2key(c) (c & 0x7f)		/* strip off the above prefixes */
X
#ifdef	FALSE
#undef	FALSE
#endif
#ifdef	TRUE
#undef	TRUE
#endif
X
#define FALSE	0			/* False, no, bad, etc. 	*/
#define TRUE	1			/* True, yes, good, etc.	*/
#define ABORT	2			/* Death, ESC, abort, etc.	*/
#define	FAILED	3			/* not-quite fatal false return	*/
#define	SORTOFTRUE	4		/* really!	*/
X
#define	STOP	0			/* keyboard macro not in use	*/
#define	PLAY	1			/*	"     "	  playing	*/
#define	RECORD	2			/*	"     "   recording	*/
#define	TMPSTOP	3			/* temporary stop, record can resume */
X
/* flook options */
#define FL_HERE 1
#define FL_HERE_HOME 2
#define FL_ANYWHERE 3
X
/* bfind options */
#define OK_CREAT TRUE
#define NO_CREAT FALSE
X
/* kbd_string options */
#define EXPAND TRUE
#define NO_EXPAND FALSE
X
/*	Directive definitions	*/
X
#if ! SMALLER
X
#define	DIF		0
#define DELSE		1
#define DENDIF		2
#define DGOTO		3
#define DRETURN		4
#define DENDM		5
#define DWHILE		6
#define	DENDWHILE	7
#define	DBREAK		8
#define DFORCE		9
X
#define NUMDIRS		10
X
#else
X
#define DENDM		0
#define NUMDIRS		1
X
#endif
X
/*
X * PTBEG, PTEND, FORWARD, and REVERSE are all toggle-able values for
X * the scan routines.
X */
#define	PTBEG	0	/* Leave the point at the beginning on search	*/
#define	PTEND	1	/* Leave the point at the end on search		*/
#define	FORWARD	0			/* forward direction		*/
#define REVERSE	1			/* backwards direction		*/
X
#define FIOSUC	0			/* File I/O, success.		*/
#define FIOFNF	1			/* File I/O, file not found.	*/
#define FIOEOF	2			/* File I/O, end of file.	*/
#define FIOERR	3			/* File I/O, error.		*/
#define	FIOMEM	4			/* File I/O, out of memory	*/
#define	FIOFUN	5			/* File I/O, eod of file/bad line*/
X
/* two flavors of insert mode */
#define INSERT 1
#define OVERWRITE 2
X
/* kill register control */
#define KNEEDCLEAN   0x01		/* Kill register needs cleaning */
#define KYANK	0x02			/* Kill register resulted from yank */
#define KLINES	0x04			/* Kill register contains full lines */
#define KAPPEND  0x04			/* Kill register should be appended */
X
/* operator types.  Needed mainly because word movement changes depending on
X	whether operator is "delete" or not.  Aargh.  */
#define OPDEL 1
#define OPOTHER 2
X
/* define these so C-fence matching doesn't get confused when we're editing
X	the cfence code itself */
#define LBRACE '{'
#define RBRACE '}'
X
X
#if UNIX
#define	PATHCHR	':'
#else
#define	PATHCHR	';'
#endif
X
/* how big is the ascii rep. of an int? */
#define	INTWIDTH	sizeof(int) * 3
X
/*	Macro argument token types					*/
X
#define	TKNUL	0			/* end-of-string		*/
#define	TKARG	1			/* interactive argument		*/
#define	TKBUF	2			/* buffer argument		*/
#define	TKVAR	3			/* user variables		*/
#define	TKENV	4			/* environment variables	*/
#define	TKFUN	5			/* function....			*/
#define	TKDIR	6			/* directive			*/
#define	TKLBL	7			/* line label			*/
#define	TKLIT	8			/* numeric literal		*/
#define	TKSTR	9			/* quoted string literal	*/
#define	TKCMD	10			/* command name			*/
X
/*	Internal defined functions					*/
X
#define	nextab(a)	((a & ~TABMASK) + TABVAL)
X
#ifdef	abs
#undef	abs
#endif
X
/* these are the bits that go into the _chartypes_ array */
/* the macros below test for them */
#define N_chars 128
#define _upper 1		/* upper case */
#define _lower 2		/* lower case */
#define _digit 4		/* digits */
#define _space 8		/* whitespace */
#define _bspace 16		/* backspace character (^H, DEL, and user's) */
#define _cntrl 32		/* control characterts, including DEL */
#define _print 64		/* printable */
#define _punct 128		/* punctuation */
#define _ident 256		/* is typically legal in "normal" identifier */
#define _path 512		/* is typically legal in a file's pathname */
#define _wild 2048		/* is typically a shell wildcard char */
#define _linespec 4096		/* ex-style line range: 1,$ or 13,15 or % etc.*/
X
/* these intentionally match the ctypes.h definitions, except that
X	they force the char to 7-bit ascii first */
#define istype(sometype,c)	(_chartypes_[(c)&(N_chars-1)] & (sometype))
#define islower(c)	istype(_lower, c)
#define isupper(c)	istype(_upper, c)
#define isdigit(c)	istype(_digit, c)
#define isspace(c)	istype(_space, c)
#define iscntrl(c)	istype(_cntrl, c)
#define isprint(c)	istype(_print, c)
#define ispunct(c)	istype(_punct, c)
#define iswild(c)	istype(_wild, c)
#define isalpha(c)	istype(_lower|_upper, c)
#define isalnum(c)	istype(_lower|_upper|_digit, c)
#define isident(c)	istype(_ident, c)
#define ispath(c)	istype(_path, c)
#define isbackspace(c)	istype(_bspace, c)
#define islinespecchar(c)	istype(_linespec, c)
X
/* DIFCASE represents the difference between upper
X   and lower case letters, DIFCNTRL the difference between upper case and
X   control characters.	They are xor-able values.  */
#define	DIFCASE		0x20
#define	DIFCNTRL	0x40
#define toupper(c)	((c)^DIFCASE)
#define tolower(c)	((c)^DIFCASE)
#define tocntrl(c)	((c)^DIFCNTRL)
#define toalpha(c)	((c)^DIFCNTRL)
X
/*	Dynamic RAM tracking and reporting redefinitions	*/
X
#if	RAMSIZE
#define	malloc	allocate
#define	free	release
#endif
X
#if VMALLOC
char *vmalloc();
void vfree();
void rvverify();
char *vrealloc();
char *vcalloc();
void vdump();
# define malloc(x) vmalloc(x,__FILE__,__LINE__)
# define free(x) vfree(x,__FILE__,__LINE__)
# define realloc(x,y) vrealloc(x,y,__FILE__,__LINE__)
# define calloc(x,y) vcalloc(x,y,__FILE__,__LINE__)
# define vverify(s) rvverify(s,__FILE__,__LINE__)
#else
# define vverify(s) ;
#endif
X
/*
X * There is a window structure allocated for every active display window. The
X * windows are kept in a big list, in top to bottom screen order, with the
X * listhead at "wheadp". Each window contains its own values of dot and mark.
X * The flag field contains some bits that are set by commands to guide
X * redisplay. Although this is a bit of a compromise in terms of decoupling,
X * the full blown redisplay is just too expensive to run for every input
X * character.
X */
typedef struct	WINDOW {
X	struct	WINDOW *w_wndp; 	/* Next window			*/
X	struct	BUFFER *w_bufp; 	/* Buffer displayed in window	*/
X	struct	LINE *w_linep;		/* Top line in the window	*/
X	struct	LINE *w_dotp;		/* Line containing "."		*/
X	struct	LINE *w_mkp;	      /* Line containing "mark"       */
X	struct	LINE *w_ldmkp;	      /* Line containing "lastdotmark"*/
X	int	w_doto;		      /* Byte offset for "."	      */
X	int	w_mko;		    /* Byte offset for "mark"	    */
X	int	w_ldmko;		    /* Byte offset for "lastdotmark"*/
X	int	w_toprow;	       /* Origin 0 top row of window   */
X	int	w_ntrows;	       /* # of rows of text in window  */
X	int	w_force; 	       /* If non-zero, forcing row.   */
X	int	w_flag;		       /* Flags.		       */
X	int	w_sideways;	       /* sideways offset */
#if	COLOR
X	int	w_fcolor;		/* current forground color	*/
X	int	w_bcolor;		/* current background color	*/
#endif
}	WINDOW;
X
#define WFFORCE 0x01			/* Window needs forced reframe	*/
#define WFMOVE	0x02			/* Movement from line to line	*/
#define WFEDIT	0x04			/* Editing within a line	*/
#define WFHARD	0x08			/* Better do a full display	*/
#define WFMODE	0x10			/* Update mode line.		*/
#define	WFCOLR	0x20			/* Needs a color change		*/
#define	WFKILLS	0x40			/* something was deleted	*/
#define	WFINS	0x80			/* something was inserted	*/
X
struct MARK {
X	struct LINE *markp;
X	int marko;
};
X
/*
X * Text is kept in buffers. A buffer header, described below, exists for every
X * buffer in the system. The buffers are kept in a big list, so that commands
X * that search for a buffer by name can find the buffer header. There is a
X * safe store for the dot and mark in the header, but this is only valid if
X * the buffer is not being displayed (that is, if "b_nwnd" is 0). The text for
X * the buffer is kept in a circularly linked list of lines, with a pointer to
X * the header line in "b_linep"	Buffers may be "Inactive" which means the files associated with them
X * have not been read in yet. These get read in at "use buffer" time.
X */
typedef struct	BUFFER {
X	struct	BUFFER *b_bufp; 	/* Link to next BUFFER		*/
X	struct	MARK *b_nmmarks;	/* named marks a-z		*/
X	struct	LINE *b_linep;		/* Link to the header LINE	*/
X	struct	LINE *b_dotp;		/* Link to "." LINE structure	*/
X	struct	LINE *b_markp;		/* The same as the above two,	*/
X	struct	LINE *b_ldmkp;	        /* The same as the above two,   */
X	int	b_doto;		        /* Offset of "." in above LINE  */
X	int	b_marko;		/* same but for the "mark"	*/
X	int	b_ldmko;		/* same but for the "last dot mark" */
X	int	b_sideways;		/* sideways offset		*/
X	int	b_mode;			/* editor mode of this buffer	*/
X	struct	LINE *b_udstks[2];	/* undo stack pointers		*/
X	short	b_udstkindx;		/* which of above to use	*/
X	struct	LINE *b_uddotps[2];	/* Link to "." before undoable op*/
X	int	b_uddotos[2];		/* offset of "." before undoable op*/
X	struct	LINE *b_ulinep;		/* pointer at 'Undo' line	*/
X	int	b_active;		/* window activated flag	*/
X	int	b_nwnd;		        /* Count of windows on buffer   */
X	int	b_flag;		        /* Flags 		        */
X	char	b_fname[NFILEN];	/* File name			*/
X	char	b_bname[NBUFN]; 	/* Buffer name			*/
#if	CRYPT
X	char	b_key[NPAT];		/* current encrypted key	*/
#endif
}	BUFFER;
X
#define BFINVS	0x01			/* Internal invisable buffer	*/
#define BFCHG	0x02			/* Changed since last write	*/
#define BFSCRTCH   0x04 		/* scratch -- gone on last close */
X
/*	mode flags	*/
/* the first set are bitmapped, and are inherited from global to per-buffer */
#define	NUMMODES	11 /* # of defined modes		*/
#define	MDWRAP	0x0001			/* word wrap			*/
#define	MDCMOD	0x0002			/* C indentation and fence match*/
#define	MDSWRAP 0x0004			/* wrap-around search mode	*/
#define	MDEXACT	0x0008			/* Exact matching for searches	*/
#define	MDVIEW	0x0010			/* read-only buffer		*/
#define MDMAGIC	0x0020			/* regular expresions in search */
#define	MDCRYPT	0x0040			/* encrytion mode active	*/
#define	MDASAVE	0x0080			/* auto-save mode		*/
#define	MDLIST	0x0100			/* "list" mode -- show tabs and EOL */
#define	MDDOS	0x0200			/* "dos" mode -- lines end in crlf */
#define	MDAIND	0x0400			/* auto-indent */
X
/* the next set are global, bit-mapped, but are meaningless per-buffer */
#define	NUMOTHERMODES	2 /* # of defined modes		*/
#define OTH_LAZY 0x01
#define OTH_VERS 0x02
X
/* the last set are global, and have values */
#define	NUMVALUEMODES	2 /* # of defined modes		*/
#define VAL_TAB 0
#define VAL_FILL 1
X
/*
X * The starting position of a region, and the size of the region in
X * characters, is kept in a region structure.  Used by the region commands.
X */
typedef struct	{
X	struct	LINE *r_linep;		/* Origin LINE address. 	*/
X	int	r_offset;		/* Origin LINE offset.		*/
X	struct	LINE *r_endlinep;	/* Ending LINE address. 	*/
X	int	r_endoffset;		/* Ending LINE offset.		*/
X	long	r_size; 		/* Length in characters.	*/
}	REGION;
X
/*
X * All text is kept in circularly linked lists of "LINE" structures. These
X * begin at the header line. This line is pointed to by the "BUFFER".
X * Each line contains:
X *  number of bytes in the line (the "used" size), 
X *  the size of the text array,
X *  the text.
X * The end of line is not stored as a byte; it's implied. Future
X * additions may include update hints, and a list of marks into the line.
X *
X * Lines are additionally sometimes stacked in undo lists.
X */
typedef struct	LINE {
X	struct	LINE *l_fp;		/* Link to the next line	*/
X	struct	LINE *l_bp;		/* Link to the previous line	*/
X	int   l_size;		      /* Allocated size 	      */
X	int   l_used;		      /* Used size		      */
X	char *l_text;
X	union {
X	    struct  LINE *l_stklnk;	/* Link for undo stack		*/
X	    long	l_flag;		/* flags for undo ops		*/
X	} l;
}	LINE;
X
/* flag values */
#define LCOPIED 1	/* original line is already on an undo stack */
#define LGMARK 2	/* line matched a global scan */
X
/* macros to ease the use of lines */
#define lforw(lp)	((lp)->l_fp)
#define lback(lp)	((lp)->l_bp)
#define lgetc(lp, n)	((lp)->l_text[(n)]&0xFF)
#define lputc(lp, n, c) ((lp)->l_text[(n)]=(c))
#define llength(lp)	((lp)->l_used)
#define l_nxtundo	l.l_stklnk
#define liscopied(lp)	(lp->l.l_flag & LCOPIED)
#define lismarked(lp)	(lp->l.l_flag & LGMARK)
#define lsetcopied(lp)		(lp->l.l_flag |= LCOPIED)
#define lsetnotcopied(lp)	(lp->l.l_flag &= ~LCOPIED)
#define lsetmarked(lp)		(lp->l.l_flag |= LGMARK)
#define lsetnotmarked(lp)	(lp->l.l_flag &= ~LGMARK)
#define lsetclear(lp)	(lp->l.l_flag = 0)
#define LINENOTREAL	((int)(-1))
#define LINEUNDOPATCH	((int)(-2))
#define MARKPATCH	((int)(-3))
#define lisreal(lp)	((lp)->l_used >= 0)
#define lisnotreal(lp)	   ((lp)->l_used == LINENOTREAL)
#define lislinepatch(lp)     ((lp)->l_used == LINEUNDOPATCH)
#define lismarkpatch(lp)     ((lp)->l_used == MARKPATCH)
#define lispatch(lp)	 (lislinepatch(lp) || lismarkpatch(lp))
#define lneedscopying(lp)     ((lp)->l_copied != TRUE)
X
/*
X * The editor communicates with the display using a high level interface. A
X * "TERM" structure holds useful variables, and indirect pointers to routines
X * that do useful operations. The low level get and put routines are here too.
X * This lets a terminal, in addition to having non standard commands, have
X * funny get and put character code too. The calls might get changed to
X * "termp->t_field" style in the future, to make it possible to run more than
X * one terminal type.
X */
typedef struct	{
X	int	t_mrow;			/* max number of rows allowable */
X	int	t_nrow; 		/* current number of rows used	*/
X	int	t_mcol; 		/* max Number of columns.	*/
X	int	t_ncol; 		/* current Number of columns.	*/
X	int	t_margin;		/* min margin for extended lines*/
X	int	t_scrsiz;		/* size of scroll region "	*/
X	int	t_pause;		/* # times thru update to pause */
X	int	(*t_open)();		/* Open terminal at the start.	*/
X	int	(*t_close)();		/* Close terminal at end.	*/
X	int	(*t_kopen)();		/* Open keyboard		*/
X	int	(*t_kclose)();		/* close keyboard		*/
X	int	(*t_getchar)(); 	/* Get character from keyboard. */
X	int	(*t_putchar)(); 	/* Put character to display.	*/
X	int	(*t_flush)();		/* Flush output buffers.	*/
X	int	(*t_move)();		/* Move the cursor, origin 0.	*/
X	int	(*t_eeol)();		/* Erase to end of line.	*/
X	int	(*t_eeop)();		/* Erase to end of page.	*/
X	int	(*t_beep)();		/* Beep.			*/
X	int	(*t_rev)();		/* set reverse video state	*/
X	int	(*t_rez)();		/* change screen resolution	*/
#if	COLOR
X	int	(*t_setfor)();		/* set forground color		*/
X	int	(*t_setback)();		/* set background color		*/
#endif
#if	SCROLLCODE
X	int	(*t_scroll)();		/* scroll a region of the screen */
#endif
}	TERM;
X
/*	TEMPORARY macros for terminal I/O  (to be placed in a machine
X					    dependant place later)	*/
X
#define	TTopen		(*term.t_open)
#define	TTclose		(*term.t_close)
#define	TTkopen		(*term.t_kopen)
#define	TTkclose	(*term.t_kclose)
#define	TTgetc		(*term.t_getchar)
#define	TTputc		(*term.t_putchar)
#define	TTflush		(*term.t_flush)
#define	TTmove		(*term.t_move)
#define	TTeeol		(*term.t_eeol)
#define	TTeeop		(*term.t_eeop)
#define	TTbeep		(*term.t_beep)
#define	TTrev		(*term.t_rev)
#define	TTrez		(*term.t_rez)
#if	COLOR
#define	TTforg		(*term.t_setfor)
#define	TTbacg		(*term.t_setback)
#endif
X
X
/* Commands are represented as CMDFUNC structures, which contain a
X *	pointer to the actual function, and flags which help to classify it.
X *	(things like is it a MOTION, can it be UNDOne)
X *
X *	These structures are generated automatically from the cmdtbl file,
X *	and can be found in the file nefunc.h
*/
typedef  struct {
X	int (*c_func)();	/* function name is bound to */
X	unsigned long c_flags;		/* what sort of command is it? */
}	CMDFUNC;
X
/* when referencing a command by name (e.g ":e file") it is looked up in
X *	the nametbl, which is an array of NTAB structures, containing the
X *	name, and a pointer to the CMDFUNC structure.  There can be several
X *	entries pointing at a single CMDFUNC, since a command might have
X *	several synonymous names.
X *
X *	The nametbl array is generated automatically from the cmdtbl file,
X *	and can be found in the file nename.h
X */
typedef struct {
X	char *n_name;
X	CMDFUNC	*n_cmd;
}	NTAB;
X
/* when a command is referenced by bound key (like h,j,k,l, or "dd"), it
X *	is looked up one of two ways:  single character 7-bit ascii commands
X *	(by far the majority) are simply indexed into a 128 element array of
X *	CMDFUNC pointers.  Other commands (those with ^A, ^X, or SPEC
X *	prefixes) are searched for in a binding table, made up of KBIND
X *	structures.  This structure contains the command code, and again, a
X *	pointer to the CMDFUNC structure for the command 
X *
X *	The asciitbl array, and the kbindtbl array are generated automatically
X *	from the cmdtbl file, and can be found in the file nebind.h
X */
typedef struct {
X	short	k_code; 		/* Key code			*/
X	CMDFUNC	*k_cmd;
}	KBIND;
X
X
/* these are the flags which can appear in the CMDFUNC structure, describing
X	a command */
#define NONE	0
#define UNDO	0x01	/* command is undo-able, so clean up undo lists */
#define REDO	0x02	/* command is redo-able, record it for dotcmd */
#define MOTION	0x04	/* command causes motion, okay after operator cmds */
#define FL	0x08	/* if command causes motion, opers act on full lines */
#define ABS	0x10	/* command causes absolute (i.e. non-relative) motion */
#define GOAL	0x20	/* column goal should be retained */
#define GLOBOK	0x40	/* permitted after global command */
#define OPER	0x80	/* function is an operator, affects a region */
#define LISTED	0x100	/* internal use only -- used in describing bindings
X				to only describe each once */
X
/* these flags are ex argument descriptors. I simply moved them over 
X	from elvis.  Not all are used or honored or implemented */
#define FROM	(1<<16)		/* allow a linespec */
#define	TO	(2<<16)		/* allow a second linespec */
#define BANG	(4<<16)		/* allow a ! after the command name */
#define EXTRA	(8<<16)		/* allow extra args after command name */
#define XFILE	(16<<16)	/* expand wildcards in extra part */
#define NOSPC	(32<<16)	/* no spaces allowed in the extra part */
#define	DFLALL	(64<<16)	/* default file range is 1,$ */
#define DFLNONE	(128<<16)	/* no default file range */
#define NODFL	(256<<16)	/* do not default to the current file name */
#define EXRCOK	(512<<16)	/* can be in a .exrc file */
#define NL	(1024<<16)	/* if !exmode, then write a newline first */
#define PLUS	(2048<<16)	/* allow a line number, as in ":e +32 foo" */
#define ZERO	(4096<<16)	/* allow 0 to be given as a line number */
#define FILES	(XFILE + EXTRA)	/* multiple extra files allowed */
#define WORD1	(EXTRA + NOSPC)	/* one extra word allowed */
#define FILE1	(FILES + NOSPC)	/* 1 file allowed, defaults to current file */
#define NAMEDF	(FILE1 + NODFL)	/* 1 file allowed, defaults to "" */
#define NAMEDFS	(FILES + NODFL)	/* multiple files allowed, default is "" */
#define RANGE	(FROM + TO)	/* range of linespecs allowed */
X
/*	The editor holds deleted text chunks in the KILL registers. The
X	kill registers are logically a stream of ascii characters, however
X	due to unpredicatable size, get implemented as a linked
X	list of chunks. (The d_ prefix is for "deleted" text, as k_
X	was taken up by the keycode structure)
*/
X
typedef	struct KILL {
X	struct KILL *d_next;	/* link to next chunk, NULL if last */
X	char d_chunk[KBLOCK];	/* deleted text */
} KILL;
X
typedef struct KILLREG {
X	struct KILL *kbufp;	/* current kill register chunk pointer */
X	struct KILL *kbufh;	/* kill register header pointer	*/
X	int   kused;		/* # of bytes used in kill last chunk	*/
X	short kbflag;		/* flags describing kill register	*/
} KILLREG;
X
/*	When the command interpretor needs to get a variable's name,
X	rather than its value, it is passed back as a VDESC variable
X	description structure. The v_num field is an index into the
X	appropriate variable table.
*/
X
typedef struct VDESC {
X	int v_type;	/* type of variable */
X	int v_num;	/* ordinal pointer to variable in list */
} VDESC;
X
/*	The !WHILE directive in the execution language needs to
X	stack references to pending whiles. These are stored linked
X	to each currently open procedure via a linked list of
X	the following structure
*/
X
typedef struct WHBLOCK {
X	LINE *w_begin;		/* ptr to !while statement */
X	LINE *w_end;		/* ptr to the !endwhile statement*/
X	int w_type;		/* block type */
X	struct WHBLOCK *w_next;	/* next while */
} WHBLOCK;
X
#define	BTWHILE		1
#define	BTBREAK		2
X
/*
X * Incremental search defines.
X */
#if	ISRCH
X
#define	CMDBUFLEN	256	/* Length of our command buffer */
X
#define IS_REVERSE	tocntrl('R')	/* Search backward */
#define	IS_FORWARD	tocntrl('F')	/* Search forward */
X
#endif
X
#if	MAGIC
X
/*
X * Defines for the metacharacters in the regular expressions in search
X * routines.
X */
X
#define	MCNIL		0	/* Like the '\0' for strings.*/
#define	LITCHAR		1
#define	ANY		2
#define	CCL		3
#define	NCCL		4
#define	BOL		5
#define	EOL		6
#define	CLOSURE		256	/* An or-able value.*/
#define	MASKCL		CLOSURE - 1
X
#define	MC_ANY		'.'	/* 'Any' character (except newline).*/
#define	MC_CCL		'['	/* Character class.*/
#define	MC_NCCL		'^'	/* Negate character class.*/
#define	MC_RCCL		'-'	/* Range in character class.*/
#define	MC_ECCL		']'	/* End of character class.*/
#define	MC_BOL		'^'	/* Beginning of line.*/
#define	MC_EOL		'$'	/* End of line.*/
#define	MC_CLOSURE	'*'	/* Closure - does not extend past newline.*/
X
#define	MC_ESC		'\\'	/* Escape - suppress meta-meaning.*/
X
#define	BIT(n)		(1 << (n))	/* An integer with one bit set.*/
#define	CHCASE(c)	((c) ^ DIFCASE)	/* Toggle the case of a letter.*/
X
/* HICHAR - 1 is the largest character we will deal with.
X * HIBYTE represents the number of bytes in the bitmap.
X */
X
#define	HICHAR		256
#define	HIBYTE		HICHAR >> 3
X
typedef char	*BITMAP;
X
typedef	struct {
X	short int	mc_type;
X	union {
X		int	lchar;
X		BITMAP	cclmap;
X	} u;
} MC;
#endif
X
SHAR_EOF
chmod 0444 estruct.h ||
echo 'restore of estruct.h failed'
Wc_c="`wc -c < 'estruct.h'`"
test 30449 -eq "$Wc_c" ||
	echo 'estruct.h: original size 30449, current size' "$Wc_c"
# ============= eval.c ==============
echo 'x - extracting eval.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'eval.c' &&
/*	EVAL.C:	Expresion evaluation functions for
X		MicroEMACS
X
X	written 1986 by Daniel Lawrence				*/
X
#include	<stdio.h>
#include	"estruct.h"
#include	"edef.h"
#include	"evar.h"
X
varinit()		/* initialize the user variable list */
X
{
#if ! SMALLER
X	register int i;
X
X	for (i=0; i < MAXVARS; i++)
X		uv[i].u_name[0] = 0;
#endif
}
X
#if ! SMALLER
char *gtfun(fname)	/* evaluate a function */
char *fname;		/* name of function to evaluate */
{
X	register int fnum;		/* index to function to eval */
X	register int status;		/* return status */
X	char arg1[NSTRING];		/* value of first argument */
X	char arg2[NSTRING];		/* value of second argument */
X	char arg3[NSTRING];		/* value of third argument */
X	static char result[2 * NSTRING];	/* string result */
#if	ENVFUNC
X	char *getenv();
#endif
X
X	/* look the function up in the function table */
X	fname[3] = 0;	/* only first 3 chars significant */
X	mklower(fname);	/* and let it be upper or lower case */
X	for (fnum = 0; fnum < NFUNCS; fnum++)
X		if (strcmp(fname, funcs[fnum].f_name) == 0)
X			break;
X
X	/* return errorm on a bad reference */
X	if (fnum == NFUNCS)
X		return(errorm);
X
X	/* if needed, retrieve the first argument */
X	if (funcs[fnum].f_type >= MONAMIC) {
X		if ((status = macarg(arg1)) != TRUE)
X			return(errorm);
X
X		/* if needed, retrieve the second argument */
X		if (funcs[fnum].f_type >= DYNAMIC) {
X			if ((status = macarg(arg2)) != TRUE)
X				return(errorm);
X	
X			/* if needed, retrieve the third argument */
X			if (funcs[fnum].f_type >= TRINAMIC)
X				if ((status = macarg(arg3)) != TRUE)
X					return(errorm);
X		}
X	}
X		
X
X	/* and now evaluate it! */
X	switch (fnum) {
X		case UFADD:	return(itoa(atoi(arg1) + atoi(arg2)));
X		case UFSUB:	return(itoa(atoi(arg1) - atoi(arg2)));
X		case UFTIMES:	return(itoa(atoi(arg1) * atoi(arg2)));
X		case UFDIV:	return(itoa(atoi(arg1) / atoi(arg2)));
X		case UFMOD:	return(itoa(atoi(arg1) % atoi(arg2)));
X		case UFNEG:	return(itoa(-atoi(arg1)));
X		case UFCAT:	strcpy(result, arg1);
X				return(strcat(result, arg2));
X		case UFLEFT:	return(strncpy(result, arg1, atoi(arg2)));
X		case UFRIGHT:	return(strcpy(result, &arg1[atoi(arg2)-1]));
X		case UFMID:	return(strncpy(result, &arg1[atoi(arg2)-1],
X					atoi(arg3)));
X		case UFNOT:	return(ltos(stol(arg1) == FALSE));
X		case UFEQUAL:	return(ltos(atoi(arg1) == atoi(arg2)));
X		case UFLESS:	return(ltos(atoi(arg1) < atoi(arg2)));
X		case UFGREATER:	return(ltos(atoi(arg1) > atoi(arg2)));
X		case UFSEQUAL:	return(ltos(strcmp(arg1, arg2) == 0));
X		case UFSLESS:	return(ltos(strcmp(arg1, arg2) < 0));
X		case UFSGREAT:	return(ltos(strcmp(arg1, arg2) > 0));
X		case UFIND:	return(tokval(arg1));
X		case UFAND:	return(ltos(stol(arg1) && stol(arg2)));
X		case UFOR:	return(ltos(stol(arg1) || stol(arg2)));
X		case UFLENGTH:	return(itoa(strlen(arg1)));
X		case UFUPPER:	return(mkupper(arg1));
X		case UFLOWER:	return(mklower(arg1));
X		case UFTRUTH:	return(ltos(atoi(arg1) == 42));
X		case UFASCII:	return(itoa((int)arg1[0]));
X		case UFCHR:	result[0] = atoi(arg1);
X				result[1] = 0;
X				return(result);
X		case UFGTKEY:	result[0] = tgetc();
X				result[1] = 0;
X				return(result);
X		case UFRND:	return(itoa((ernd() % abs(atoi(arg1))) + 1));
X		case UFABS:	return(itoa(abs(atoi(arg1))));
X		case UFSINDEX:	return(itoa(sindex(arg1, arg2)));
X		case UFENV:
#if	ENVFUNC
X				return(getenv(arg1) == NULL ? "" : getenv(arg1));
#else
X				return("");
#endif
X		case UFBIND:	return(prc2engl(arg1));
X	}
X
X	exit(-11);	/* never should get here */
}
X
char *gtusr(vname)	/* look up a user var's value */
char *vname;		/* name of user variable to fetch */
{
X
X	register int vnum;	/* ordinal number of user var */
X
X	/* scan the list looking for the user var name */
X	for (vnum = 0; vnum < MAXVARS; vnum++)
X		if (strcmp(vname, uv[vnum].u_name) == 0)
X			break;
X
X	/* return errorm on a bad reference */
X	if (vnum == MAXVARS)
X		return(errorm);
X
X	return(uv[vnum].u_value);
}
X
char *gtenv(vname)
char *vname;		/* name of environment variable to retrieve */
{
X	register int vnum;	/* ordinal number of var refrenced */
X	char *getkill();
X
X	/* scan the list, looking for the referenced name */
X	for (vnum = 0; vnum < NEVARS; vnum++)
X		if (strcmp(vname, envars[vnum]) == 0)
X			break;
X
X	/* return errorm on a bad reference */
X	if (vnum == NEVARS)
X		return(errorm);
X
X	/* otherwise, fetch the appropriate value */
X	switch (vnum) {
X		case EVFILLCOL:	return(itoa(fillcol));
X		case EVPAGELEN:	return(itoa(term.t_nrow + 1));
X		case EVCURCOL:	return(itoa(getccol(FALSE)));
X		case EVCURLINE: return(itoa(getcline()));
X		case EVRAM:	return(itoa((int)(envram / 1024l)));
X		case EVFLICKER:	return(ltos(flickcode));
X		case EVCURWIDTH:return(itoa(term.t_nrow));
X		case EVCBUFNAME:return(curbp->b_bname);
X		case EVCFNAME:	return(curbp->b_fname);
X		case EVSRES:	return(sres);
X		case EVDEBUG:	return(ltos(macbug));
X		case EVSTATUS:	return(ltos(cmdstatus));
X		case EVPALETTE:	return(palstr);
X		case EVASAVE:	return(itoa(gasave));
X		case EVACOUNT:	return(itoa(gacount));
X		case EVLASTKEY: return(itoa(lastkey));
X		case EVCURCHAR:
X			return(curwp->w_dotp->l_used ==
X					curwp->w_doto ? itoa('\n') :
X				itoa(lgetc(curwp->w_dotp, curwp->w_doto)));
X		case EVDISCMD:	return(ltos(discmd));
X		case EVVERSION:	return(version);
X		case EVPROGNAME:return(prognam);
X		case EVSEED:	return(itoa(seed));
X		case EVDISINP:	return(ltos(disinp));
X		case EVWLINE:	return(itoa(curwp->w_ntrows));
X		case EVCWLINE:	return(itoa(getwpos()));
X		case EVSEARCH:	return(pat);
X		case EVREPLACE:	return(rpat);
X		case EVMATCH:	return((patmatch == NULL)? "": patmatch);
X		case EVKILL:	return(getkill());
X		case EVCMODE:	return(itoa(curbp->b_mode));
X		case EVGMODE:	return(itoa(gmode));
X		case EVTPAUSE:	return(itoa(term.t_pause));
X		case EVPENDING:
#if	TYPEAH
X				return(ltos(typahead()));
#else
X				return(falsem);
#endif
X		case EVLWIDTH:	return(itoa(llength(curwp->w_dotp)));
X		case EVLINE:	return(getctext());
X	}
X	exit(-12);	/* again, we should never get here */
}
X
char *getkill()		/* return some of the contents of the kill buffer */
X
{
X	register int size;	/* max number of chars to return */
X	char value[NSTRING];	/* temp buffer for value */
X
X	if (kbs[0].kbufh == NULL)
X		/* no kill buffer....just a null string */
X		value[0] = 0;
X	else {
X		/* copy in the contents... */
X		if (kbs[0].kused < NSTRING)
X			size = kbs[0].kused;
X		else
X			size = NSTRING - 1;
X		strncpy(value, kbs[0].kbufh->d_chunk, size);
X	}
X
X	/* and return the constructed value */
X	return(value);
}
X
int setvar(f, n)		/* set a variable */
X
int f;		/* default flag */
int n;		/* numeric arg (can overide prompted value) */
X
{
X	register int status;	/* status return */
#if	DEBUGM
X	register char *sp;	/* temp string pointer */
X	register char *ep;	/* ptr to end of outline */
#endif
X	VDESC vd;		/* variable num/type */
X	static char var[NVSIZE+1];	/* name of variable to fetch */
X	char value[NSTRING];	/* value to set variable to */
X
X	/* first get the variable to set.. */
X	if (clexec == FALSE) {
X		status = mlreply("Variable to set: ", &var[0], NVSIZE);
X		if (status != TRUE)
X			return(status);
X	} else {	/* macro line argument */
X		/* grab token and skip it */
X		execstr = token(execstr, var);
X	}
X
X	/* check the legality and find the var */
X	findvar(var, &vd);
X	
X	/* if its not legal....bitch */
X	if (vd.v_type == -1) {
X		mlwrite("%%No such variable as '%s'", var);
X		return(FALSE);
X	}
X
X	/* get the value for that variable */
X	if (f == TRUE)
X		strcpy(value, itoa(n));
X	else {
X		value[0] = 0;
X		status = mlreply("Value: ", &value[0], NSTRING);
X		if (status != TRUE)
X			return(status);
X	}
X
X	/* and set the appropriate value */
X	status = svar(&vd, value);
X
#if	DEBUGM
X	/* if $debug == TRUE, every assignment will echo a statment to
X	   that effect here. */
X	
X	if (macbug) {
X		strcpy(outline, "(((");
X
X		/* assignment status */
X		strcat(outline, ltos(status));
X		strcat(outline, ":");
X
X		/* variable name */
X		strcat(outline, var);
X		strcat(outline, ":");
X
X		/* and lastly the value we tried to assign */
X		strcat(outline, value);
X		strcat(outline, ")))");
X
X		/* expand '%' to "%%" so mlwrite wont bitch */
X		sp = outline;
X		while (*sp)
X			if (*sp++ == '%') {
X				/* advance to the end */
X				ep = --sp;
X				while (*ep++)
X					;
X				/* null terminate the string one out */
X				*(ep + 1) = 0;
X				/* copy backwards */
X				while(ep-- > sp)
X					*(ep + 1) = *ep;
X
X				/* and advance sp past the new % */
X				sp += 2;					
X			}
X
X		/* write out the debug line */
X		mlforce(outline);
X		update(TRUE);
X
X		/* and get the keystroke to hold the output */
X		if (kbd_key() == abortc) {
X			mlforce("[Macro aborted]");
X			status = FALSE;
X		}
X	}
#endif
X
X	/* and return it */
X	return(status);
}
X
findvar(var, vd)	/* find a variables type and name */
X
char *var;	/* name of var to get */
VDESC *vd;	/* structure to hold type and ptr */
X
{
X	register int vnum;	/* subscript in varable arrays */
X	register int vtype;	/* type to return */
X
fvar:	vtype = -1;
X	switch (var[0]) {
X
X		case '$': /* check for legal enviromnent var */
X			for (vnum = 0; vnum < NEVARS; vnum++)
X				if (strcmp(&var[1], envars[vnum]) == 0) {
X					vtype = TKENV;
X					break;
X				}
X			break;
X
X		case '%': /* check for existing legal user variable */
X			for (vnum = 0; vnum < MAXVARS; vnum++)
X				if (strcmp(&var[1], uv[vnum].u_name) == 0) {
X					vtype = TKVAR;
X					break;
X				}
X			if (vnum < MAXVARS)
X				break;
X
X			/* create a new one??? */
X			for (vnum = 0; vnum < MAXVARS; vnum++)
X				if (uv[vnum].u_name[0] == 0) {
X					vtype = TKVAR;
X					strcpy(uv[vnum].u_name, &var[1]);
X					break;
X				}
X			break;
X
X		case '&':	/* indirect operator? */
X			var[4] = 0;
X			if (strcmp(&var[1], "ind") == 0) {
X				/* grab token, and eval it */
X				execstr = token(execstr, var);
X				strcpy(var, tokval(var));
X				goto fvar;
X			}
X	}
X
X	/* return the results */
X	vd->v_num = vnum;
X	vd->v_type = vtype;
X	return;
}
X
int svar(var, value)		/* set a variable */
X
VDESC *var;	/* variable to set */
char *value;	/* value to set to */
X
{
X	register int vnum;	/* ordinal number of var refrenced */
X	register int vtype;	/* type of variable to set */
X	register int status;	/* status return */
X	register int c;		/* translated character */
X	register char * sp;	/* scratch string pointer */
X
X	/* simplify the vd structure (we are gonna look at it a lot) */
X	vnum = var->v_num;
X	vtype = var->v_type;
X
X	/* and set the appropriate value */
X	status = TRUE;
X	switch (vtype) {
X	case TKVAR: /* set a user variable */
X		if (uv[vnum].u_value != NULL)
X			free(uv[vnum].u_value);
X		sp = malloc(strlen(value) + 1);
X		if (sp == NULL)
X			return(FALSE);
X		strcpy(sp, value);
X		uv[vnum].u_value = sp;
X		break;
X
X	case TKENV: /* set an environment variable */
X		status = TRUE;	/* by default */
X		switch (vnum) {
X		case EVFILLCOL:	fillcol = atoi(value);
X				break;
X		case EVCURCOL:	status = gotocol(TRUE,atoi(value));
X				break;
X		case EVCURLINE:	status = gotoline(TRUE, atoi(value));
X				break;
X		case EVRAM:	break;
X		case EVFLICKER:	flickcode = stol(value);
X				break;
X		case EVCURWIDTH:status = newwidth(TRUE, atoi(value));
X				break;
X		case EVPAGELEN:	status = newlength(TRUE,atoi(value));
X				break;
X		case EVCBUFNAME:strcpy(curbp->b_bname, value);
X				curwp->w_flag |= WFMODE;
X				break;
X		case EVCFNAME:	strcpy(curbp->b_fname, value);
X				curwp->w_flag |= WFMODE;
X				break;
X		case EVSRES:	status = TTrez(value);
X				break;
X		case EVDEBUG:	macbug = stol(value);
X				break;
X		case EVSTATUS:	cmdstatus = stol(value);
X				break;
X		case EVPALETTE:	strncpy(palstr, value, 48);
X				spal(palstr);
X				break;
X		case EVASAVE:	gasave = atoi(value);
X				break;
X		case EVACOUNT:	gacount = atoi(value);
X				break;
X		case EVLASTKEY:	lastkey = atoi(value);
X				break;
X		case EVCURCHAR:	ldelete(1, FALSE);	/* delete 1 char */
X				c = atoi(value);
X				if (c == '\n')
X					lnewline(FALSE, 1);
X				else
X					linsert(1, c);
X				backchar(FALSE, 1);
X				break;
X		case EVDISCMD:	discmd = stol(value);
X				break;
X		case EVVERSION:	break;
X		case EVPROGNAME:break;
X		case EVSEED:	seed = atoi(value);
X				break;
X		case EVDISINP:	disinp = stol(value);
X				break;
X		case EVWLINE:	status = resize(TRUE, atoi(value));
X				break;
X		case EVCWLINE:	status = forwline(TRUE,
X						atoi(value) - getwpos());
X				break;
X		case EVSEARCH:	strcpy(pat, value);
X				rvstrcpy(tap, pat);
X				mcclear();
X				break;
X		case EVREPLACE:	strcpy(rpat, value);
X				break;
X		case EVMATCH:	break;
X		case EVKILL:	break;
X		case EVCMODE:	curbp->b_mode = atoi(value);
X				curwp->w_flag |= WFMODE;
X				break;
X		case EVGMODE:	gmode = atoi(value);
X				break;
X		case EVTPAUSE:	term.t_pause = atoi(value);
X				break;
X		case EVPENDING:	break;
X		case EVLWIDTH:	break;
X		case EVLINE:	putctext(value);
X		}
X		break;
X	}
X	return(status);
}
#endif
X
/*	atoi:	ascii string to integer......This is too
X		inconsistant to use the system's	*/
X
atoi(st)
char *st;
{
X	int result;	/* resulting number */
X	int sign;	/* sign of resulting number */
X	char c;		/* current char being examined */
X
X	result = 0;
X	sign = 1;
X
X	/* skip preceding whitespace */
X	while (isspace(*st))
X		++st;
X
X	/* check for sign */
X	if (*st == '-') {
X		sign = -1;
X		++st;
X	}
X	if (*st == '+')
X		++st;
X
X	/* scan digits, build value */
X	while ((c = *st++))
X		if (isdigit(c))
X			result = result * 10 + c - '0';
X		else
X			return(0);
X
X	return(result * sign);
}
X
#if ! SMALLER
X
/*	itoa:	integer to ascii string.......... This is too
X		inconsistant to use the system's	*/
X
char *itoa(i)
int i;	/* integer to translate to a string */
{
X	register int digit;		/* current digit being used */
X	register char *sp;		/* pointer into result */
X	register int sign;		/* sign of resulting number */
X	static char result[INTWIDTH+1];	/* resulting string */
X
X	/* record the sign...*/
X	sign = 1;
X	if (i < 0) {
X		sign = -1;
X		i = -i;
X	}
X
X	/* and build the string (backwards!) */
X	sp = result + INTWIDTH;
X	*sp = 0;
X	do {
X		digit = i % 10;
X		*(--sp) = '0' + digit;	/* and install the new digit */
X		i = i / 10;
X	} while (i);
X
X	/* and fix the sign */
X	if (sign == -1) {
X		*(--sp) = '-';	/* and install the minus sign */
X	}
X
X	return(sp);
}
#endif
X
int toktyp(tokn)	/* find the type of a passed token */
char *tokn;	/* token to analyze */
{
X	register char c;	/* first char in token */
X
X	/* grab the first char (this is all we need) */
X	c = *tokn;
X
X	/* no blanks!!! */
X	if (c == 0)
X		return(TKNUL);
X
X	/* a numeric literal? */
X	if (isdigit(c))
X		return(TKLIT);
X
#if ! SMALLER
X	switch (c) {
X		case '"':	return(TKSTR);
X
X		case '~':	return(TKDIR);
X		case '@':	return(TKARG);
X		case '#':	return(TKBUF);
X		case '$':	return(TKENV);
X		case '%':	return(TKVAR);
X		case '&':	return(TKFUN);
X		case '*':	return(TKLBL);
X
X		default:	return(TKCMD);
X	}
#else
X	return(TKCMD);
#endif
}
X
char *
tokval(tokn)	/* find the value of a token */
char *tokn;		/* token to evaluate */
{
#if ! SMALLER
X	register int status;	/* error return */
X	register BUFFER *bp;	/* temp buffer pointer */
X	register int blen;	/* length of buffer argument */
X	register int distmp;	/* temporary discmd flag */
X	char pad[20];		/* pad 20 bytes on stack for safety */
X	char buf[NSTRING];	/* string buffer for some returns */
X
X	switch (toktyp(tokn)) {
X		case TKNUL:	return("");
X
X		case TKARG:	/* interactive argument */
X				strcpy(tokn, tokval(&tokn[1]));
X				distmp = discmd;	/* echo it always! */
X				discmd = TRUE;
X				status = kbd_string(tokn,
X					   buf, NSTRING, '\n',EXPAND);
X				discmd = distmp;
X				if (status == ABORT)
X					return(errorm);
X				return(buf);
X
X		case TKBUF:	/* buffer contents fetch */
X
X				/* grab the right buffer */
X				strcpy(tokn, tokval(&tokn[1]));
X				bp = bfind(tokn, NO_CREAT, 0);
X				if (bp == NULL)
X					return(errorm);
X		
X				/* if the buffer is displayed, get the window
X				   vars instead of the buffer vars */
X				if (bp->b_nwnd > 0) {
X					curbp->b_dotp = curwp->w_dotp;
X					curbp->b_doto = curwp->w_doto;
X				}
X
X				/* make sure we are not at the end */
X				if (bp->b_linep == bp->b_dotp)
X					return(errorm);
X		
X				/* grab the line as an argument */
X				blen = bp->b_dotp->l_used - bp->b_doto;
X				if (blen > NSTRING)
X					blen = NSTRING;
X				strncpy(buf, bp->b_dotp->l_text + bp->b_doto,
X					blen);
X				buf[blen] = 0;
X		
X				/* and step the buffer's line ptr ahead a line */
X				bp->b_dotp = bp->b_dotp->l_fp;
X				bp->b_doto = 0;
X
X				/* if displayed buffer, reset window ptr vars*/
X				if (bp->b_nwnd > 0) {
X					curwp->w_dotp = curbp->b_dotp;
X					curwp->w_doto = 0;
X					curwp->w_flag |= WFMOVE;
X				}
X
X				/* and return the spoils */
X				return(buf);		
X
X		case TKVAR:	return(gtusr(tokn+1));
X		case TKENV:	return(gtenv(tokn+1));
X		case TKFUN:	return(gtfun(tokn+1));
X		case TKDIR:	return(errorm);
X		case TKLBL:	return(itoa(gtlbl(tokn)));
X		case TKLIT:	return(tokn);
X		case TKSTR:	return(tokn+1);
X		case TKCMD:	return(tokn);
X	}
#else
X	return tokn;
#endif
}
X
#if ! SMALLER
X
gtlbl(tokn)	/* find the line number of the given label */
char *tokn;	/* label name to find */
{
X	return(1);
}
X
int stol(val)	/* convert a string to a numeric logical */
char *val;	/* value to check for stol */
{
X	/* check for logical values */
X	if (val[0] == 'F')
X		return(FALSE);
X	if (val[0] == 'T')
X		return(TRUE);
X
X	/* check for numeric truth (!= 0) */
X	return((atoi(val) != 0));
}
X
char *ltos(val)		/* numeric logical to string logical */
int val;	/* value to translate */
{
X	if (val)
X		return(truem);
X	else
X		return(falsem);
}
X
char *mkupper(str)	/* make a string upper case */
char *str;		/* string to upper case */
{
X	char *sp;
X
X	sp = str;
X	while (*sp) {
X		if (islower(*sp))
X			*sp += 'A' - 'a';
X		++sp;
X	}
X	return(str);
}
#endif
X
#if ! SMALLER || MSDOS
X
char *mklower(str)	/* make a string lower case */
char *str;		/* string to lower case */
{
X	char *sp;
X
X	sp = str;
X	while (*sp) {
X		if (isupper(*sp))
X			*sp += 'a' - 'A';
X		++sp;
X	}
X	return(str);
}
#endif
X
#if ! SMALLER
X
int abs(x)	/* take the absolute value of an integer */
int x;
{
X	return(x < 0 ? -x : x);
}
X
int ernd()	/* returns a random integer */
{
X	seed = abs(seed * 1721 + 10007);
X	return(seed);
}
X
int sindex(source, pattern)	/* find pattern within source */
char *source;	/* source string to search */
char *pattern;	/* string to look for */
{
X	char *sp;	/* ptr to current position to scan */
X	char *csp;	/* ptr to source string during comparison */
X	char *cp;	/* ptr to place to check for equality */
X
X	/* scanning through the source string */
X	sp = source;
X	while (*sp) {
X		/* scan through the pattern */
X		cp = pattern;
X		csp = sp;
X		while (*cp) {
X			if (!eq(*cp, *csp))
X				break;
X			++cp;
X			++csp;
X		}
X
X		/* was it a match? */
X		if (*cp == 0)
X			return((int)(sp - source) + 1);
X		++sp;
X	}
X
X	/* no match at all.. */
X	return(0);
}
X
#endif
SHAR_EOF
chmod 0444 eval.c ||
echo 'restore of eval.c failed'
Wc_c="`wc -c < 'eval.c'`"
test 18430 -eq "$Wc_c" ||
	echo 'eval.c: original size 18430, current size' "$Wc_c"
# ============= evar.h ==============
echo 'x - extracting evar.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'evar.h' &&
/*	EVAR.H:	Environment and user variable definitions
X		for MicroEMACS (and now vile)
X
X		written 1986 by Daniel Lawrence
*/
X
#if !SMALLER
X
/*	structure to hold user variables and their definitions	*/
X
typedef struct UVAR {
X	char u_name[NVSIZE + 1];		/* name of user variable */
X	char *u_value;				/* value (string) */
} UVAR;
X
/*	current user variables (This structure will probably change)	*/
X
#define	MAXVARS		255
X
UVAR uv[MAXVARS];	/* user variables */
SHAR_EOF
true || echo 'restore of evar.h failed'
echo 'End of Vile part 5'
echo 'File evar.h is continued in part 6'
echo 6 > _shar_seq_.tmp
exit 0
-- 
		paul fox, pgf@cayman.com, (617)494-1999
		Cayman Systems, 26 Landsdowne St., Cambridge, MA 02139