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*/
 | 
