319 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			319 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* ELLE - Copyright 1982, 1984, 1987 by Ken Harrenstien, SRI International
 | 
						||
 *	This software is quasi-public; it may be used freely with
 | 
						||
 *	like software, but may NOT be sold or made part of licensed
 | 
						||
 *	products without permission of the author.
 | 
						||
 */
 | 
						||
 | 
						||
/* EECMDS	Command table lookup and profile code
 | 
						||
 */
 | 
						||
 | 
						||
#include "elle.h"
 | 
						||
 | 
						||
/* Function table, see the included file for explanation. */
 | 
						||
 | 
						||
	/* First must pre-declare function addrs */
 | 
						||
#define EFUN(rtn,rtnstr,name) int rtn();
 | 
						||
#define EFUNHOLE
 | 
						||
#include "eefdef.h"
 | 
						||
 | 
						||
	/* Now re-insert to define function table */
 | 
						||
int (*funtab[])() =
 | 
						||
{
 | 
						||
#undef EFUN		/* Avoid redefinition error message */
 | 
						||
#undef EFUNHOLE
 | 
						||
#define EFUN(rtn,rtnstr,name) rtn,
 | 
						||
#define EFUNHOLE 0,
 | 
						||
#include "eefdef.h"
 | 
						||
};
 | 
						||
int funmax = sizeof(funtab)/sizeof(funtab[0]);	/* 1st illegal function # */
 | 
						||
 | 
						||
/* Insert default command char map tables and profile structure */
 | 
						||
 | 
						||
#include "defprf.c"
 | 
						||
 | 
						||
/* EFUN: "Prefix Meta" */
 | 
						||
/*	Meta-prefix command.
 | 
						||
 *	For now, very simple.  Perhaps later try to hair up with
 | 
						||
 *	time-out "M-" prompt?
 | 
						||
 */
 | 
						||
f_pfxmeta()
 | 
						||
{	return(cmd_xct(cmd_read()|CB_META));
 | 
						||
}
 | 
						||
 | 
						||
/* EFUN: "Prefix Extend" */
 | 
						||
/*	Extended-prefix command.
 | 
						||
 *	Likewise trivial; perhaps later hair up with timeout "^X-" prompt?
 | 
						||
 */
 | 
						||
f_pfxext()
 | 
						||
{	return(cmd_xct(cmd_read()|CB_EXT));
 | 
						||
}
 | 
						||
 | 
						||
/* EFUN: "Universal Arg" */
 | 
						||
/*	This routine is also called by "Argument Digit" with a special arg
 | 
						||
 * of -1 in order to share code.  Since that invocation always sets unrchf,
 | 
						||
 * it should always complete at least one digit read loop.
 | 
						||
 * Note that exp and exp_p are set to 1 and 0 at the top-level command
 | 
						||
 * loop.
 | 
						||
 */
 | 
						||
f_uarg(ch)
 | 
						||
int ch;
 | 
						||
{	register int c, oc, i;
 | 
						||
 | 
						||
	/* Set distinguishing exp_p value depending on whether invoked
 | 
						||
	 * by CTRL-U or another function (Argument Digit, Negative Argument)
 | 
						||
	 */
 | 
						||
	exp_p = (ch < 0) ? 1 : 4;
 | 
						||
	i = 0;			/* Read numerical arg if any follows */
 | 
						||
	for(;;)
 | 
						||
	  {	oc = cmd_read();	/* Get next input char */
 | 
						||
		c = oc & 0177;
 | 
						||
		if(c == '-' && !i)
 | 
						||
		  {	exp_p = -1;
 | 
						||
			exp = 1;	/* Set in case no digits follow */
 | 
						||
		  }
 | 
						||
		else if('0' <= c && c <= '9')	/* If it's a digit too, */
 | 
						||
		  {	i = (i * 10) + c - '0';	/* add digit in. */
 | 
						||
			if(exp_p >= 0) exp_p = 1;
 | 
						||
			exp = i;
 | 
						||
		  }
 | 
						||
		else break;
 | 
						||
	  }
 | 
						||
	exp *= exp_p;		/* Multiply arg appropriately */
 | 
						||
	unrchf = oc;		/* Not a digit, re-read it next. */
 | 
						||
 | 
						||
	this_cmd = ARGCMD;
 | 
						||
}
 | 
						||
 | 
						||
/* EFUN: "Negative Argument" */
 | 
						||
f_negarg(ch)
 | 
						||
int ch;
 | 
						||
{	f_uarg(-1);		/* Invoke code from Universal Arg */
 | 
						||
	exp = -exp;
 | 
						||
}
 | 
						||
 | 
						||
/* EFUN: "Argument Digit" */
 | 
						||
f_argdig(ch)
 | 
						||
int ch;
 | 
						||
{	unrchf = ch;		/* Re-read the digit */
 | 
						||
	f_uarg(-1);		/* Invoke code from Universal Arg */
 | 
						||
}
 | 
						||
 | 
						||
/* EFUN: "Set Profile" */
 | 
						||
/*	Asks for a profile file and sets profile from it.
 | 
						||
 */
 | 
						||
f_setprof()
 | 
						||
{	int set_profile();
 | 
						||
	hack_file("Set Profile: ", set_profile);
 | 
						||
}
 | 
						||
 | 
						||
#if FX_VTBUTTONS
 | 
						||
/* EFUN: "VT100 Button Hack" */
 | 
						||
/*	This must be bound to Meta-O if anything, because the VT100 sends
 | 
						||
 *	an ESC O prefix when the function buttons are used.
 | 
						||
 */
 | 
						||
f_vtbuttons ()			/* vt100 function buttons */
 | 
						||
{
 | 
						||
	switch(cmd_read())
 | 
						||
	  {	case ('A'): 
 | 
						||
			return (f_uprline ());
 | 
						||
		case ('B'): 
 | 
						||
			return (f_dnrline ());
 | 
						||
		case ('C'): 
 | 
						||
			return (f_fword ());
 | 
						||
		case ('D'): 
 | 
						||
			return (f_bword ());
 | 
						||
		case ('Q'): 		/* PF1 */
 | 
						||
			return (f_kregion());
 | 
						||
		default: 
 | 
						||
			ring_bell ();
 | 
						||
		break;
 | 
						||
	  }
 | 
						||
}
 | 
						||
#endif /*FX_VTBUTTONS*/
 | 
						||
 | 
						||
/* CMD_WAIT() - Return TRUE if any command input waiting.
 | 
						||
*/
 | 
						||
cmd_wait()
 | 
						||
{	return(unrchf >= 0
 | 
						||
#if FX_SKMAC
 | 
						||
		|| km_inwait()		/* Check for kbdmac input waiting */
 | 
						||
#endif /*FX_SKMAC*/
 | 
						||
		|| tinwait());
 | 
						||
}
 | 
						||
 | 
						||
/* CMD_READ() - Read a command (single char) from user, and return it.
 | 
						||
*/
 | 
						||
cmd_read()
 | 
						||
{	register int c;
 | 
						||
 | 
						||
	if((c = unrchf) >= 0)	/* Re-reading last char? */
 | 
						||
	  {	unrchf = -1;
 | 
						||
		return(c);
 | 
						||
	  }
 | 
						||
#if FX_SKMAC			/* Hacking keyboard macros? */
 | 
						||
	return(km_getc());	/* Yes.  This calls tgetc if no kbd macro */
 | 
						||
#else
 | 
						||
	return(tgetc());
 | 
						||
#endif /*-FX_SKMAC*/
 | 
						||
}
 | 
						||
 | 
						||
/* CMD_XCT(ch) - Command Execution dispatch routine.
 | 
						||
**	Takes char and executes the function (efun) bound to that command key.
 | 
						||
*/
 | 
						||
cmd_xct(ch)
 | 
						||
int ch;
 | 
						||
{	register int (*funct) ();
 | 
						||
	register int c;
 | 
						||
	int (*(cmd_fun())) ();
 | 
						||
 | 
						||
	if(funct = cmd_fun(c = ch))		/* Get function to run */
 | 
						||
		return((*funct) (c&0177));	/* Invoke with char arg */
 | 
						||
	ring_bell();		/* Undefined command char, error. */
 | 
						||
}
 | 
						||
 | 
						||
/* CMD_FUN(ch) - Return function for char, 0 if none
 | 
						||
*/
 | 
						||
int (*cmd_fun(c))()
 | 
						||
int c;
 | 
						||
{
 | 
						||
	return(funtab[cmd_idx(c)]);
 | 
						||
}
 | 
						||
 | 
						||
/* CMD_IDX(ch) - Given command char, return function index for it
 | 
						||
*/
 | 
						||
cmd_idx(c)
 | 
						||
register int c;
 | 
						||
{	register char *cp;
 | 
						||
	register int i;
 | 
						||
 | 
						||
	if(c&CB_EXT)
 | 
						||
	  {	cp = def_prof.extvec;
 | 
						||
		i = def_prof.extvcnt;
 | 
						||
		goto inlup;
 | 
						||
	  }
 | 
						||
	if(c&CB_META)
 | 
						||
	  {	cp = def_prof.metavec;
 | 
						||
		i = def_prof.metavcnt;
 | 
						||
	inlup:	c = upcase(c);
 | 
						||
		do {	if(*cp++ != c) cp++;
 | 
						||
			else
 | 
						||
			  {	i = *cp&0377;
 | 
						||
				break;
 | 
						||
			  }
 | 
						||
		  } while(--i);		/* If counts out, will return 0! */
 | 
						||
	  }
 | 
						||
	else i = def_prof.chrvec[c&0177]&0377;
 | 
						||
	if(i >= funmax)
 | 
						||
		return(0);
 | 
						||
	return(i);
 | 
						||
}
 | 
						||
 | 
						||
/* Profile hacking */
 | 
						||
 | 
						||
#if TOPS20
 | 
						||
#include <sys/file.h>		/* for O_BINARY */
 | 
						||
#endif
 | 
						||
 | 
						||
set_profile(filename)
 | 
						||
char *filename;
 | 
						||
{	char pfile[200];
 | 
						||
	register int pfd, len;
 | 
						||
	chroff sbx_fdlen();
 | 
						||
	register char *profptr;
 | 
						||
	struct stored_profile st_prof;
 | 
						||
 | 
						||
	if(filename) strcpy(pfile,filename);
 | 
						||
	else		/* Check for user's profile */
 | 
						||
	  {
 | 
						||
		strcat(strcat(strcpy(pfile,homedir),"/"),ev_profile);
 | 
						||
	  }
 | 
						||
	if((pfd = open(pfile,
 | 
						||
#if TOPS20
 | 
						||
				O_BINARY
 | 
						||
#else
 | 
						||
				0
 | 
						||
#endif
 | 
						||
					)) < 0)
 | 
						||
	  {	if(filename)
 | 
						||
		  {	ding("Cannot open file");
 | 
						||
		  }
 | 
						||
		return;
 | 
						||
	  }
 | 
						||
	if((len = (int)sbx_fdlen(pfd)) < sizeof(struct stored_profile))
 | 
						||
		goto badfil;
 | 
						||
	profptr = memalloc((SBMO)len);
 | 
						||
	if(read(pfd,profptr,len) != len)
 | 
						||
		goto badfmt;
 | 
						||
 | 
						||
	/* Have read profile into memory, now set up ptrs etc */
 | 
						||
	bcopy((SBMA)profptr,(SBMA)&st_prof,sizeof(struct stored_profile));
 | 
						||
	def_prof.version = prof_upack(st_prof.version);
 | 
						||
	if(def_prof.version != 1)
 | 
						||
		goto badfmt;
 | 
						||
	def_prof.chrvcnt = prof_upack(st_prof.chrvcnt);
 | 
						||
	def_prof.chrvec  = profptr + prof_upack(st_prof.chrvec);
 | 
						||
	def_prof.metavcnt = prof_upack(st_prof.metavcnt);
 | 
						||
	def_prof.metavec = profptr + prof_upack(st_prof.metavec);
 | 
						||
	def_prof.extvcnt = prof_upack(st_prof.extvcnt);
 | 
						||
	def_prof.extvec  = profptr + prof_upack(st_prof.extvec);
 | 
						||
#if SUN
 | 
						||
	def_prof.menuvcnt = prof_upack(st_prof.menuvcnt);
 | 
						||
	def_prof.menuvec = profptr + prof_upack(st_prof.menuvec);
 | 
						||
#endif /*SUN*/
 | 
						||
	goto done;
 | 
						||
 | 
						||
badfmt:	chkfree(profptr);
 | 
						||
badfil:	ding("Bad profile format");
 | 
						||
done:	close(pfd);
 | 
						||
}
 | 
						||
 | 
						||
#if SUN
 | 
						||
/* SUN Menu profile hacking.
 | 
						||
 *	This is here, instead of e_sun.c, because
 | 
						||
 * the profile format is still evolving and for the time being I want to
 | 
						||
 * keep all profile-hacking code in one place. --KLH
 | 
						||
 */
 | 
						||
#include "suntool/tool_hs.h"
 | 
						||
#include "suntool/menu.h"
 | 
						||
 | 
						||
#define MENUMAX	16
 | 
						||
 | 
						||
/* Defined in eesun.c */
 | 
						||
extern struct menu *menuptr;
 | 
						||
extern struct menu menu;
 | 
						||
 | 
						||
char *funamtab[] = {
 | 
						||
#undef EFUN
 | 
						||
#undef EFUNHOLE
 | 
						||
#define EFUN(rtn,rtnstr,name) name,
 | 
						||
#define EFUNHOLE 0,
 | 
						||
#include "eefdef.h"
 | 
						||
};
 | 
						||
 | 
						||
init_menu() /* initialize the menu for elle from user profile */
 | 
						||
{
 | 
						||
	register struct menuitem *mi;
 | 
						||
	register int n, i, fni;
 | 
						||
 | 
						||
	if((n = def_prof.menuvcnt) <= 0)
 | 
						||
		return;
 | 
						||
	if(n > MENUMAX) n = MENUMAX;
 | 
						||
	mi = menu.m_items = (struct menuitem *) calloc(n, sizeof *mi);
 | 
						||
 | 
						||
	menu.m_itemcount = 0;
 | 
						||
	for(i = 0; i < n; i++)
 | 
						||
	  {	fni = def_prof.menuvec[i]&0377;
 | 
						||
		if(fni >= funmax) continue;
 | 
						||
		if(funtab[fni] && funamtab[fni])
 | 
						||
		  {	mi->mi_data = (caddr_t) funtab[fni];
 | 
						||
			mi->mi_imagedata = (caddr_t) strdup(funamtab[fni]);
 | 
						||
			mi->mi_imagetype = MENU_IMAGESTRING;
 | 
						||
			mi++;
 | 
						||
			menu.m_itemcount++;
 | 
						||
		  }
 | 
						||
	  }
 | 
						||
	if(menu.m_itemcount)
 | 
						||
		menuptr = &menu;
 | 
						||
}
 | 
						||
#endif /*SUN*/
 |