File:  [MW Coherent from dump] / coherent / g / usr / bin / me / execute.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:35 2019 UTC (7 years ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/*
 * This program is in public domain; written by Dave G. Conroy.
 * This file contains the functions that bind keys to macros and functions,
 * as well as the execution of macros and functions.
 * code, for the MicroEMACS screen editor.
 */
#include	<stdio.h>
#include	"ed.h"
BIND bind;
short	*kbdm;		/* Current Macro		*/
unsigned kbdlen;	/* Curent Macro len in bytes	*/
short	*kbdmip;	/* Input  for above		*/
short	*kbdmop;	/* Output for above		*/
int	thisflag;	/* Flags, this command		*/
int	lastflag;	/* Flags, last command		*/
extern  char	*realloc();
extern	FILE	*ffp;
/*
 * find keybinding or return NULL
 */
static KEYTAB *
findBind(c, tab)
int c;
KEYTAB *tab;
{
	register KEYTAB *ktp;
	register int i;

	for (i = c % HASHP; -1 != i; i = ktp->k_synonym)
		if ((ktp = tab + i)->k_code == c)
			return (ktp);
	return (NULL);
}
	
/*
 * This is the general command execution routine.
 * It handles the fake binding of all the keys to "self-insert".
 * It also clears out the "thisflag" word, and arranges to move it
 * to the "lastflag", so that the next command can look at it.
 * Return the status of command.
 */
execute(c, f, n)
register int c;
{
	register KEYTAB *ktp;
	int	status;

	if ((NULL != (ktp = findBind(c, bind.table))) ||
	    (NULL != (ktp = findBind((c & ~OBND), keytab)))) {
			thisflag = 0;
			status = (ktp->k_fun < 0) ?
				doMac(bind.macs - (2 + ktp->k_fun), f, n) :
				(*(funtab[ktp->k_fun].f_fp))(f, n);
			lastflag = thisflag;
			return (status);
	}

	if (c >= 0x20 && c <= 0xFF)	{	/* Self inserting.	*/
		if (n <= 0) {			/* Fenceposts.		*/
			lastflag = 0;
			return (n<0 ? FALSE : TRUE);
		}
		thisflag = 0;			/* For the future.	*/
		status   = linsert(n, c);
		lastflag = thisflag;

		/*
		 * If fill column is defined perform word wrap.
		 */
		if (bind.fillcol)
			wrapword();

		return (status);
	}
	lastflag = 0;				/* Fake last flags.	*/
	return (FALSE);
}

/*
 * Begin a keyboard macro.
 * Error if not at the top level in keyboard processing.
 * Set up variables and return.
 */
ctlxlp(f, n)
{
	if (kbdmip!=NULL) {
		mlwrite("Not now");
		return (FALSE);
	}
	if (NULL != kbdm)
		free(kbdm);
	mlwrite("[Start macro]");
	if (NULL == (kbdmip = kbdm = malloc(kbdlen = NKBDM))) {
		mlwrite("Out of space");
		return (FALSE);
	}
	return (TRUE);
}

/*
 * End keyboard macro.  Check for the same limit conditions as the
 * above routine.  Set up the variables and return to the caller.
 */
ctlxrp(f, n)
{
	if (kbdmip == NULL) {
		mlwrite("Not now");
		return (FALSE);
	}
	mlwrite("[End macro]");
	kbdmip[-1] = -1;			/* unique end marker */
	*kbdmip++ = 0;
	kbdm = realloc(kbdm, kbdlen = ((char *)kbdmip) - ((char *)kbdm));
	kbdmip = NULL;
	return (TRUE);
}

/*
 * Execute default macro.
 */
ctlxe(f, n)
{
	if (kbdmip!=NULL) { /* close macro first */
		mlwrite("Not now");
		return (FALSE);
	}
	return (doMac(&kbdm, f, n));
}

/*
 * Get a keybinding and remove it.
 * return the binding.
 */
static
unBind(c)
{
	register short  i;
	register KEYTAB *ktp;

	mlerase();
	if (NULL == (ktp = findBind(c, bind.table)))
		return;
	if ((i = ktp->k_fun) < 0) {
		free(bind.macs[i = -(2 + i)]);
		bind.macs[i] = NULL;
		bind.maclen[i] = 0;
	}
	if (-1 != (i = ktp->k_synonym)) {
		memcpy(ktp, (bind.table + i), sizeof(*ktp));
		bind.table[i].k_code = bind.table[i].k_synonym = -1;
	}		
	else
		ktp->k_code = -1;
}

/*
 * Create a new binding in bind.table.
 */
static
reBind(c, i)
{
	register KEYTAB *ktp, *kh;

	kh = ktp = bind.table + (c % HASHP);
	if (-1 != ktp->k_code) {
		for (ktp = bind.table + MAXREB; --ktp >= bind.table; )
			if (-1 == ktp->k_code)
				break;
		if (ktp < bind.table) {
			mlwrite("No free spaces in mod tab");
			return (FALSE);
		}
		ktp->k_synonym = kh->k_synonym;
		kh->k_synonym  = ktp - bind.table;
	}
	ktp->k_code = c;
	ktp->k_fun = i;
	return (TRUE);
}

/*
 * Bind a function PFX1|'R' to another function.
 */
bindFun()
{
	register int c, d;
	register KEYTAB *ktp;

	mlwrite("Enter old keybinding ");
	d = getbind(0);
	ktp = findBind(d, keytab);
	mlwrite("Enter new keybinding ");
	if ((PFX1|'R') == (c = getbind(0))) {
		mlwrite("Cannot rebind <ctl>-x r");
		return (FALSE);
	}
	if (d == c) {
		unBind(c);
		return (TRUE);
	}
	if (NULL == ktp) {
		mlwrite("Non existant binding");
		return (FALSE);
	}
	unBind(c);
	return (reBind(c, ktp->k_fun));
}

/*
 * Load flexable bindings from file.
 */
loadBinds()
{
	uchar		fname[NFILEN];

	if (mlreply("Load bindings file: ", fname, NFILEN) != TRUE)
		return (FALSE);
	return (loadBup(fname, FALSE));
}

/*
 * report io error in various ways.
 */
ioTrouble(fname, startsw)
uchar *fname;
{
	switch (startsw) {
	case FALSE:	/* callec from ctl-x l */
		mlwrite("I/O toruble with %s", fname);
		return (FALSE);
	case ABORT:	/* called from -f switch */
		fprintf(stderr, "I/O trouble with %s\n", fname);
		exit(1);
	case TRUE:	/* default bindings file */
		return (TRUE);
	}
}
/*
 * Actual work of load bindings.
 */
loadBup(fname, startsw)
uchar *fname;
{
	register int i;
	short magic;

	if (((ffp=fopen(fname, "rb")) == NULL) ||
	    (1 != fread(&magic, sizeof(magic), 1, ffp)) ||
	    (magic != BINDID))
		return (ioTrouble(fname, startsw));

	if (1 != fread(&bind, sizeof(bind), 1, ffp))
		return (ioTrouble(fname, ABORT));
	
	for (i = 0; i < (MAXMAC + 2); i++) {
		if (NULL != bind.macs[i]) {
			if (NULL == (bind.macs[i] = malloc(bind.maclen[i]))) {
				mlwrite("Out of memory");
				for (; i <= MAXMAC; i++)
					bind.macs[i] = NULL;
				return (FALSE);
			}
			if (1 != fread(bind.macs[i], bind.maclen[i], 1, ffp))
				return (ioTrouble(fname, ABORT));
		}
	}
	if (NULL != bind.macs[MAXMAC+1]) {
		if (NULL != kbdm)
			free(kbdm);
		kbdmip = NULL;
		kbdm = bind.macs[MAXMAC+1];
		kbdlen = bind.maclen[MAXMAC+1];
	}
	ffclose();
	return (TRUE);
}

/*
 * Store flexable bindings to a file.
 */
storBinds()
{
	register int i;
	static	short magic = BINDID;
	uchar	fname[NFILEN];

	if (mlreply("Store bindings file: ", fname, NFILEN) != TRUE)
		return (FALSE);
	if (FIOSUC != ffwopen(fname, "wb"))
		return (FALSE);
	if (kbdmip != NULL || kbdm == NULL)	/* store closed mac only */
		bind.macs[MAXMAC+1] = NULL;
	else {
		bind.macs[MAXMAC+1]   = kbdm;
		bind.maclen[MAXMAC+1] = kbdlen;
	}
	fwrite(&magic, sizeof(magic), 1, ffp);
	fwrite(&bind, sizeof(bind), 1, ffp);
	for (i = 0; i < (MAXMAC + 2); i++)
		if (NULL != bind.macs[i])
			fwrite(bind.macs[i], bind.maclen[i], 1, ffp);
	ffclose();
}

/*
 * declare macro to be a binding. PFX1|'M'
 */
nameMac()
{
	register int i, c;

	if (kbdmip != NULL)
		ctlxrp();
	if (kbdm == NULL) {
		mlwrite("Not now");
		return (FALSE);
	}
	mlwrite("Enter keybinding for macro ");
	if ((PFX1|'R') == (c = getbind(0))) {
		mlwrite("Cannot rebind <ctl>-x r");
		return (FALSE);
	}
	unBind(c);

	for (i = 0; (i < MAXMAC) && (NULL != bind.macs[i]); i++)
		;
	if (MAXMAC == i) {
		mlwrite("Too many macros bound");
		return (FALSE);
	}
	if (reBind(c, -(i + 2)) == FALSE)
		return (FALSE);
	bind.macs[i] = kbdm;
	bind.maclen[i] = kbdlen;
	kbdm = NULL;
	kbdlen = 0;
	return (TRUE);
}

/*
 * Bind current macro to initialization macro.
 */
initMac()
{
	if (kbdmip!=NULL || kbdmop!=NULL) {
		mlwrite("Not now");
		return (FALSE);
	}
	bind.macs[MAXMAC] = kbdm;
	bind.maclen[MAXMAC]  = kbdlen;
	kbdm = NULL;
	kbdlen = 0;
	mlwrite("init mac bound");
	return (TRUE);
}

/*
 * Execute a macro.
 * The command argument is the number of times to loop.  Quit as
 * soon as a command gets an error.
 * Return TRUE if all ok, else FALSE.
 */
doMac(macro, f, n)
uchar **macro;
{
	register int	c;
	register int	af;
	register int	an;
	register int	s;
	short *kbdsav;
	uchar  *macsav;

	if (!n) 
		return (TRUE);
	if (NULL == (macsav = *macro)) {
		mlwrite("Not now");
		return (FALSE);
	}
	*macro = NULL;	/* prevent regress */
	kbdsav = kbdmop;
	do {
		kbdmop = macsav;
		do {
			af = FALSE;
			an = 1;
			if ((c = *kbdmop++) == bind.repeat) {
				af = TRUE;
				an = *kbdmop++;
				c  = *kbdmop++;
			}
			s = TRUE;
		} while ((c != -1) && (s = execute(c, af, an)) == TRUE);
	} while ((s == TRUE) && ((-1 == n) || --n));
	if (-1 == n)
		s = TRUE;
	kbdmop = kbdsav;
	*macro = macsav;
	return (s);
}

static
setpf(loc, no)
int *loc, no;
{
	mlwrite("Enter prefix character %d or space ", no);
	if (' ' != (no = getkey()))
		*loc = no;
}

/*
 * Set prefix characters.
 */
setPrefix()
{
	int c;

	setpf(&bind.pfx1, 1);
	setpf(&bind.pfx2, 2);
	setpf(&bind.pfx3, 3);
	mlwrite("Enter repeat code or space ");
	if (' ' != (c = getkey()))
		bind.repeat = c;
	mlerase();
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.