home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d1xx
/
d131
/
mg1b.lha
/
Mg1b
/
Source
/
extend.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-03-14
|
11KB
|
394 lines
/*
* Extended (M-X) commands.
*/
#include "def.h"
/*
* This function modifies the keyboard
* binding table, by adjusting the entries in the
* big "bindings" array. Most of the grief deals with the
* prompting for additional arguments.
*/
extern KEY *kbdnext ;
/*ARGSUSED*/
bindtokey(f, n, k) {
register int s;
register SYMBOL *sp;
int c;
char xname[NXNAME];
if (kbdmop == NULL)
ewprintf("Set key globally: ") ;
c = (int) getkey(0);
if ((s=eread("Set key %c to command: ", xname, NXNAME, EFNEW|EFFUNC,
#ifdef VARARGS
c
#else
(char *) &c, (char *) NULL
#endif
)) != TRUE)
return (s);
if ((sp=symlookup(xname)) == NULL) {
ewprintf("[No match]");
return (FALSE);
}
binding[(KEY) c] = sp; /* rebind new. */
return (TRUE);
}
/*
* User function to unbind keys. Just call the unbind we already have.
*/
/*ARGSUSED*/
unsetkey(f, n, k) {
register KEY key;
if (kbdmop == NULL) ewprintf("Unset key globally: ") ;
key = getkey(0);
if (key == (KCTRL|'G') || key == (KCTLX|KCTRL|'G')
|| key == (KMETA|KCTRL|'G')) {
(VOID) ctrlg(FALSE, 1, KRANDOM);
return ABORT;
}
binding[key] = NULL;
return TRUE;
}
/*
* Extended command. Call the message line
* routine to read in the command name and apply autocompletion
* to it. When it comes back, look the name up in the symbol table
* and run the command if it is found and has the right type.
* Print an error if there is anything wrong.
*/
/*ARGSUSED*/
extend(f, n, k) {
register SYMBOL *sp;
register int s;
char xname[NXNAME];
if (f == FALSE)
s = eread("M-x ", xname, NXNAME, EFNEW|EFFUNC
#ifndef VARARGS
, (char *) NULL
#endif
) ;
else
s = eread("%d M-x ", xname, NXNAME, EFNEW|EFFUNC,
#ifdef VARARGS
n
#else
(char *) &n, (char *) NULL
#endif
) ;
if (s != TRUE) return (s);
if ((sp=symlookup(xname)) != NULL)
return ((*sp->s_funcp)(f, n, KRANDOM));
ewprintf("[No match]");
return FALSE;
}
/*
* Read a key from the keyboard, and look it
* up in the binding table. Display the name of the function
* currently bound to the key. Say that the key is not bound
* if it is indeed not bound, or if the type is not a
* "builtin". This is a bit of overkill, because this is the
* only kind of function there is.
*/
/*ARGSUSED*/
desckey(f, n, k) {
register SYMBOL *sp;
register KEY c;
if (kbdmop == NULL) ewprintf("Describe key briefly: ");
c = getkey(0);
if (kbdmop != NULL) return TRUE;
if ((sp=binding[c]) == NULL)
ewprintf("%c is undefined", (int) c);
else
ewprintf("%c runs the command %s", (int) c, sp->s_name);
return (TRUE);
}
/*
* This function creates a table, listing all
* of the command keys and their current bindings, and stores
* the table in the standard pop-op buffer (the one used by the
* directory list command, the buffer list command, etc.). This
* lets MicroEMACS produce it's own wall chart. The bindings to
* "ins-self" are only displayed if there is an argument.
*/
/*ARGSUSED*/
wallchart(f, n, k) {
register int key;
register SYMBOL *sp;
register char *cp1;
register char *cp2;
BUFFER *bp;
char buf[64];
bp = bfind("*Help*", TRUE);
if (bclear(bp) != TRUE) /* Clear it out. */
return TRUE;
for (key=0; key<NKEYS; ++key) { /* For all keys. */
sp = binding[key];
if (sp != NULL
&& (f!=FALSE
|| strcmp(sp->s_name, "self-insert-command")!=0)) {
keyname(buf, key);
cp1 = &buf[0]; /* Find end. */
while (*cp1 != 0)
++cp1;
while (cp1 < &buf[32]) /* Goto column 32. */
*cp1++ = ' ';
cp2 = sp->s_name; /* Add function name. */
while (*cp1++ = *cp2++)
;
if (addline(bp, buf) == FALSE)
return (FALSE);
}
}
return popbuf(bp) == NULL ? FALSE : TRUE;
}
#ifdef STARTUP
/*
* Define the commands needed to do startup-file processing.
* This code is mostly a kludge just so we can get startup-file processing.
*
* If you're serious about having this code, you should rewrite it.
* To wit:
* It has lots of funny things in it to make the startup-file look
* like a GNU startup file; mostly dealing with parens and semicolons.
* This should all vanish.
*
* It uses the same buffer as keyboard macros. The fix is easy (make
* a new function "execmacro" that takes a pointer to char and
* does what ctlxe does on it. Make ctlxe and excline both call it.)
* but would slow down the non-micro version.
*
* We define eval-expression because it's easy. It's pretty useless,
* since it duplicates the functionality of execute-extended-command.
* All of this is just to support startup files, and should be turned
* off for micros.
*/
/*
* evalexpr - get one line from the user, and run it. Identical in function
* to extend, but easy.
*/
/*ARGSUSED*/
evalexpr(f, n, k) {
register int s;
char exbuf[NKBDM];
if ((s = ereply("Eval: ", exbuf, NKBDM)) != TRUE)
return s;
return excline(exbuf);
}
/*
* evalbuffer - evaluate the current buffer as line commands. Useful
* for testing startup files.
*/
/*ARGSUSED*/
evalbuffer(f, n, k) {
register LINE *lp;
register BUFFER *bp = curbp;
register int s;
static char excbuf[NKBDM];
char *strncpy();
for (lp = lforw(bp->b_linep); lp != bp->b_linep; lp = lforw(lp)) {
if (llength(lp) >= NKBDM + 1) return FALSE ;
(VOID) strncpy(excbuf, ltext(lp), NKBDM);
if ((s = excline(excbuf)) != TRUE) return s;
}
return TRUE;
}
/*
* evalfile - go get a file and evaluate it as line commands. You can
* go get your own startup file if need be.
*/
/*ARGSUSED*/
evalfile(f, n, k) {
register int s;
char fname[NFILEN];
if ((s = ereply("Load file: ", fname, NFILEN)) != TRUE)
return s;
return load(fname);
}
/*
* load - go load the file name we got passed.
*/
load(fname) char *fname; {
register int s;
char excbuf[NKBDM];
if (((s = ffropen(fname)) == FIOERR) || (s == FIOFNF))
return FALSE;
while ((s = ffgetline(excbuf, NKBDM)) == FIOSUC)
if (excline(excbuf) != TRUE) break;
(VOID) ffclose();
return s == FIOEOF;
}
int myupper(c)
int c ;
{
if ('a'<=c&&c<='z')
return(c - ('a'-'A')) ;
else
return(c) ;
}
char *skipwhite(s)
char *s ;
{
while (*s && *s <= ' ')
s++ ;
return(s) ;
}
/*
* excline - run a line from a load file or eval-expression.
* Now broken into two pieces; the piece which gets the
* line into the macro buffer starting at kbdnext, and the
* part which decides what to do with it.
*
* This has been rewritten considerably. Now, everything
* must be typed explicitly, just as if it were coming in
* from the keyboard. Thus, you might have:
*
* ^U 10 $X 'kill-line'
*
* Anything in quotes is taken verbatim, including spaces.
* A ^ is combined with the preceding character into a control
* character. A \nnn is turned into that character. White
* space is ignored outside of quotes. A \" gets turned into
* a single quote. $ gets turned into a meta. Note that
* we currently allow macros to be defined by this. The end of
* a ' string gets turned into a null, as it is then an argument
* to something.
*/
/* Don't want to get the objects in isdigit.c just for this */
#define isdigit(c) (((c) >= '0') && ((c) <= '9'))
excline(line) register char *line; {
register char *funcp, *argp = NULL;
int status;
KEY *kbdst, *p ;
int inquote ;
int buckies ;
int c ;
long param ;
if (kbdmip > kbdnext)
kbdnext = kbdmip + 1 ;
kbdst = kbdnext + 10 ;
inquote = 0 ;
param = 0 ;
for (funcp = line; *funcp !=0 && kbdst < &kbdm[NKBDM-6]; funcp++) {
buckies = 0 ;
floop:
if (!inquote)
funcp = skipwhite(funcp) ;
if (*funcp != 0) {
while (*funcp == '^' || *funcp == '$') {
if (*funcp == '^')
buckies |= KCTRL ;
else
buckies |= KMETA ;
funcp++ ;
if (!inquote)
funcp = skipwhite(funcp) ;
if ((c=myupper(*funcp))=='X' && (buckies & KCTRL)) {
buckies = KCTLX ;
funcp++ ;
}
}
gloop:
if (buckies) {
if (!inquote)
funcp = skipwhite(funcp) ;
if ((c = myupper(*funcp))) {
if (c=='U' && (buckies & KCTRL)) {
if (param == 0)
param = 4 ;
else
param <<= 2 ;
} else {
if (param != 0) {
*kbdst++ = (KCTRL | 'U') ;
*kbdst++ = param ;
param = 0 ;
}
*kbdst++ = buckies | c ;
}
funcp++ ;
buckies = 0 ;
goto floop ;
} else {
ewprintf("Need alpha after $ or ^") ;
return(FALSE) ;
}
}
if (param != 0) {
if (!inquote)
funcp = skipwhite(funcp) ;
if (isdigit(*funcp)) {
param = 0 ;
while (isdigit(*funcp)) {
param = param * 10 + *funcp++ - '0' ;
}
}
*kbdst++ = (KCTRL | 'U') ;
*kbdst++ = param ;
param = 0 ;
buckies = 0 ;
goto floop ;
}
if (*funcp == '"' || *funcp == '\'') {
if (*funcp == inquote) {
if (inquote == '\'')
*kbdst++ = 0 ;
inquote = 0 ;
} else if (inquote == 0) {
inquote = *funcp ;
} else {
*kbdst++ = *funcp ;
}
} else if (*funcp == '\\') {
funcp++ ;
if (*funcp == 'F' || *funcp == 'f') {
funcp++ ;
c = 0 ;
while (isdigit(*funcp))
c = 10 * c + *funcp++ - '0' ;
c += KFIRST ;
if (c > KLAST)
c = KFIRST ;
*kbdst++ = c ;
} else if ('0' <= *funcp && *funcp <= '7') {
c = 0 ;
while (isdigit(*funcp))
c = 10 * c + *funcp++ - '0' ;
*kbdst++ = c ;
} else {
*kbdst++ = *funcp ;
}
} else {
*kbdst++ = *funcp ;
}
}
if (*funcp == 0)
break ;
}
if (*funcp != 0)
return(FALSE) ;
*kbdst++ = (KEY) (KCTLX|')');
*kbdst++ = (KEY) (KCTLX|')');
*kbdst++ = '\0';
status = ctlxe(FALSE, 1, KMACCUR);
return status;
}
#endif STARTUP