/* This file is for functions having to do with key bindings, descriptions, help commands, and command line execution. written 11-feb-86 by Daniel Lawrence */ #include #include "estruct.h" #include "edef.h" #include "epath.h" deskey(f, n) /* describe the command for a certain key */ { register int c; /* command character to describe */ register char *ptr; /* string pointer to scan output strings */ register KEYTAB *ktp; /* pointer into the command table */ register int found; /* matched command flag */ register NBIND *nptr; /* pointer into the name binding table */ char outseq[80]; /* output buffer for command sequence */ /* prompt the user to type us a key to describe */ mlwrite(": describe-key "); /* get the command sequence to describe */ c = getckey(); /* get a command sequence */ /* change it to something we can print as well */ cmdstr(c, &outseq[0]); /* and dump it out */ ptr = &outseq[0]; while (*ptr) (*term.t_putchar)(*ptr++); (*term.t_putchar)(' '); /* space it out */ /* find the right ->function */ ktp = &keytab[0]; found = FALSE; while (ktp->k_fp != NULL) { if (ktp->k_code == c) { found = TRUE; break; } ++ktp; } if (!found) strcpy(outseq,"Not Bound"); else { /* match it against the name binding table */ nptr = &names[0]; strcpy(outseq,"[Bad binding]"); while (nptr->n_func != NULL) { if (nptr->n_func == ktp->k_fp) { strcpy(outseq, nptr->n_name); break; } ++nptr; } } /* output the command sequence */ ptr = &outseq[0]; while (*ptr) (*term.t_putchar)(*ptr++); } cmdstr(c, seq) /* change a key command to a string we can print out */ int c; /* sequence to translate */ char *seq; /* destination string for sequence */ { char *ptr; /* pointer into current position in sequence */ ptr = seq; /* apply meta sequence if needed */ if (c & META) { *ptr++ = 'M'; *ptr++ = '-'; } /* apply ^X sequence if needed */ if (c & CTLX) { *ptr++ = '^'; *ptr++ = 'X'; } /* apply SPEC sequence if needed */ if (c & SPEC) { *ptr++ = 'F'; *ptr++ = 'N'; } /* apply control sequence if needed */ if (c & CTRL) { *ptr++ = '^'; } c = c & 255; /* strip the prefixes */ /* and output the final sequence */ *ptr++ = c; *ptr = 0; /* terminate the string */ } help(f, n) /* give me some help!!!! bring up a fake buffer and read the help file into it with view mode */ { register int status; /* status of I/O operations */ register WINDOW *wp; /* scnaning pointer to windows */ register int i; /* index into help file names */ char fname[NSTRING]; /* buffer to construct file name in */ /* search through the list of help files */ for (i=2; i < NPNAMES; i++) { strcpy(fname, pathname[i]); strcat(fname, pathname[1]); status = ffropen(fname); if (status == FIOSUC) break; } if (status == FIOFNF) { mlwrite("[Help file is not online]"); return(FALSE); } ffclose(); /* close the file to prepare for to read it in */ /* split the current window to make room for the help stuff */ if (splitwind(FALSE, 1) == FALSE) return(FALSE); /* and read the stuff in */ if (getfile(fname, FALSE) == FALSE) return(FALSE); /* make this window in VIEW mode, update all mode lines */ curwp->w_bufp->b_mode |= MDVIEW; wp = wheadp; while (wp != NULL) { wp->w_flag |= WFMODE; wp = wp->w_wndp; } return(TRUE); } int (*fncmatch(fname))() /* match fname to a function in the names table and return any match or NULL if none */ char *fname; /* name to attempt to match */ { register NBIND *ffp; /* pointer to entry in name binding table */ /* scan through the table, returning any match */ ffp = &names[0]; while (ffp->n_func != NULL) { if (strcmp(fname, ffp->n_name) == 0) return(ffp->n_func); ++ffp; } return(NULL); } /* bindtokey: add a new key to the key binding table */ bindtokey(f, n) int f, n; /* command arguments [IGNORED] */ { register int c; /* command key to bind */ register (*kfunc)(); /* ptr to the requexted function to bind to */ register char *ptr; /* ptr to dump out input key string */ register KEYTAB *ktp; /* pointer into the command table */ register int found; /* matched command flag */ char outseq[80]; /* output buffer for keystroke sequence */ int (*getname())(); /* prompt the user to type in a key to bind */ mlwrite(": bind-to-key "); /* get the function name to bind it to */ kfunc = getname(); if (kfunc == NULL) { mlwrite("[No such function]"); return(FALSE); } (*term.t_putchar)(' '); /* space it out */ (*term.t_flush)(); /* get the command sequence to bind */ c = getckey(); /* get a command sequence */ /* change it to something we can print as well */ cmdstr(c, &outseq[0]); /* and dump it out */ ptr = &outseq[0]; while (*ptr) (*term.t_putchar)(*ptr++); /* search the table to see if it exists */ ktp = &keytab[0]; found = FALSE; while (ktp->k_fp != NULL) { if (ktp->k_code == c) { found = TRUE; break; } ++ktp; } if (found) { /* it exists, just change it then */ ktp->k_fp = kfunc; } else { /* otherwise we need to add it to the end */ /* if we run out of binding room, bitch */ if (ktp >= &keytab[NBINDS]) { mlwrite("Binding table FULL!"); return(FALSE); } ktp->k_code = c; /* add keycode */ ktp->k_fp = kfunc; /* and the function pointer */ ++ktp; /* and make sure the next is null */ ktp->k_code = 0; ktp->k_fp = NULL; } return(TRUE); } /* unbindkey: delete a key from the key binding table */ unbindkey(f, n) int f, n; /* command arguments [IGNORED] */ { register int c; /* command key to unbind */ register char *ptr; /* ptr to dump out input key string */ register KEYTAB *ktp; /* pointer into the command table */ register KEYTAB *sktp; /* saved pointer into the command table */ register int found; /* matched command flag */ char outseq[80]; /* output buffer for keystroke sequence */ /* prompt the user to type in a key to unbind */ mlwrite(": unbind-key "); /* get the command sequence to unbind */ c = getckey(); /* get a command sequence */ /* change it to something we can print as well */ cmdstr(c, &outseq[0]); /* and dump it out */ ptr = &outseq[0]; while (*ptr) (*term.t_putchar)(*ptr++); /* search the table to see if the key exists */ ktp = &keytab[0]; found = FALSE; while (ktp->k_fp != NULL) { if (ktp->k_code == c) { found = TRUE; break; } ++ktp; } /* if it isn't bound, bitch */ if (!found) { mlwrite("[Key not bound]"); return(FALSE); } /* save the pointer and scan to the end of the table */ sktp = ktp; while (ktp->k_fp != NULL) ++ktp; --ktp; /* backup to the last legit entry */ /* copy the last entry to the current one */ sktp->k_code = ktp->k_code; sktp->k_fp = ktp->k_fp; /* null out the last one */ ktp->k_code = 0; ktp->k_fp = NULL; return(TRUE); } /* namedcmd: execute a named command even if it is not bound */ namedcmd(f, n) int f, n; /* command arguments [passed through to command executed] */ { register (*kfunc)(); /* ptr to the requexted function to bind to */ int (*getname())(); /* prompt the user to type a named command */ mlwrite(": "); /* and now get the function name to execute */ kfunc = getname(); if (kfunc == NULL) { mlwrite("[No such function]"); return(FALSE); } /* and then execute the command */ return((*kfunc)(f, n)); } desbind(f, n) /* describe bindings bring up a fake buffer and list the key bindings into it with view mode */ { register WINDOW *wp; /* scnaning pointer to windows */ register KEYTAB *ktp; /* pointer into the command table */ register NBIND *nptr; /* pointer into the name binding table */ register BUFFER *bp; /* buffer to put binding list into */ char *strp; /* pointer int string to send */ int cpos; /* current position to use in outseq */ char outseq[80]; /* output buffer for keystroke sequence */ /* split the current window to make room for the binding list */ if (splitwind(FALSE, 1) == FALSE) return(FALSE); /* and get a buffer for it */ bp = bfind("Binding list", TRUE, 0); if (bp == NULL || bclear(bp) == FALSE) { mlwrite("Can not display binding list"); return(FALSE); } /* let us know this is in progress */ mlwrite("[Building buffer list]"); /* disconect the current buffer */ if (--curbp->b_nwnd == 0) { /* Last use. */ curbp->b_dotp = curwp->w_dotp; curbp->b_doto = curwp->w_doto; curbp->b_markp = curwp->w_markp; curbp->b_marko = curwp->w_marko; } /* connect the current window to this buffer */ curbp = bp; /* make this buffer current in current window */ bp->b_mode = 0; /* no modes active in binding list */ bp->b_nwnd++; /* mark us as more in use */ wp = curwp; wp->w_bufp = bp; wp->w_linep = bp->b_linep; wp->w_flag = WFHARD|WFFORCE|WFHARD; wp->w_dotp = bp->b_dotp; wp->w_doto = bp->b_doto; wp->w_markp = NULL; wp->w_marko = 0; /* build the contents of this window, inserting it line by line */ nptr = &names[0]; while (nptr->n_func != NULL) { /* add in the command name */ strcpy(outseq, nptr->n_name); cpos = strlen(outseq); /* search down any keys bound to this */ ktp = &keytab[0]; while (ktp->k_fp != NULL) { if (ktp->k_fp == nptr->n_func) { /* padd out some spaces */ while (cpos < 25) outseq[cpos++] = ' '; /* add in the command sequence */ cmdstr(ktp->k_code, &outseq[cpos]); while (outseq[cpos] != 0) ++cpos; /* and add it as a line into the buffer */ strp = &outseq[0]; while (*strp != 0) linsert(1, *strp++); lnewline(); cpos = 0; /* and clear the line */ } ++ktp; } /* if no key was bound, we need to dump it anyway */ if (cpos > 0) { outseq[cpos] = 0; strp = &outseq[0]; while (*strp != 0) linsert(1, *strp++); lnewline(); } /* and on to the next name */ ++nptr; } curwp->w_bufp->b_mode |= MDVIEW;/* put this buffer view mode */ curbp->b_flag &= ~BFCHG; /* don't flag this as a change */ wp->w_dotp = lforw(bp->b_linep);/* back to the begining */ wp->w_doto = 0; wp = wheadp; /* and update ALL mode lines */ while (wp != NULL) { wp->w_flag |= WFMODE; wp = wp->w_wndp; } mlwrite(""); /* clear the mode line */ return(TRUE); } /* execcmd: Execute a command line command to be typed in by the user */ execcmd(f, n) int f, n; /* default Flag and Numeric argument */ { register int status; /* status return */ char cmdstr[NSTRING]; /* string holding command to execute */ /* get the line wanted */ if ((status = mlreply(": ", cmdstr, NSTRING)) != TRUE) return(status); return(docmd(cmdstr)); } /* docmd: take a passed string as a command line and translate it to be executed as a command. This function will be used by execute-command-line and by all source and startup files. format of the command line is: {# arg} {} */ docmd(cline) char *cline; /* command line to execute */ { register char *cp; /* pointer to current position in command */ register char *tp; /* pointer to current position in token */ register int f; /* default argument flag */ register int n; /* numeric repeat value */ register int sign; /* sign of numeric argument */ register int (*fnc)(); /* function to execute */ register int status; /* return status of function */ register int oldcle; /* old contents of clexec flag */ char token[NSTRING]; /* next token off of command line */ int (*fncmatch())(); char *gettok(); /* first set up the default command values */ f = FALSE; n = 1; cp = cline; /* start at the begining of the line */ cp = gettok(cp, token); /* and grab the first token */ /* check for and process numeric leadin argument */ if ((token[0] >= '0' && token[0] <= '9') || token[0] == '-') { f = TRUE; n = 0; tp = &token[0]; /* check for a sign! */ sign = 1; if (*tp == '-') { ++tp; sign = -1; } /* calc up the digits in the token string */ while(*tp) { if (*tp >= '0' && *tp <= '9') n = n * 10 + *tp - '0'; ++tp; } n *= sign; /* adjust for the sign */ /* and now get the command to execute */ cp = gettok(cp, token); /* grab the next token */ } /* and match the token to see if it exists */ if ((fnc = fncmatch(token)) == NULL) { mlwrite("[No such Function]"); return(FALSE); } /* save the arguments and go execute the command */ strcpy(sarg, cp); /* save the rest */ oldcle = clexec; /* save old clexec flag */ clexec = TRUE; /* in cline execution */ status = (*fnc)(f, n); /* call the function */ clexec = oldcle; /* restore clexec flag */ return(status); } /* gettok: chop a token off a string return a pointer past the token */ char *gettok(src, tok) char *src, *tok; /* source string, destination token */ { /* first scan past any whitespace in the source string */ while (*src == ' ' || *src == '\t') ++src; /* if quoted, go till next quote */ if (*src == '"') { ++src; /* past the quote */ while (*src != 0 && *src != '"') *tok++ = *src++; ++src; /* past the last quote */ *tok = 0; /* terminate token and return */ return(src); } /* copy until we find the end or whitespace */ while (*src != 0 && *src != ' ' && *src != '\t') *tok++ = *src++; /* terminate tok and return */ *tok = 0; return(src); } /* nxtarg: grab the next token out of sarg, return it, and chop it of sarg */ nxtarg(tok) char *tok; /* buffer to put token into */ { char *newsarg; /* pointer to new begining of sarg */ char *gettok(); newsarg = gettok(sarg, tok); /* grab the token */ strcpy(sarg, newsarg); /* and chop it of sarg */ return(TRUE); } getckey() /* get a command key sequence from the keyboard */ { register int c; /* character fetched */ register char *tp; /* pointer into the token */ char tok[NSTRING]; /* command incoming */ /* check to see if we are executing a command line */ if (clexec) { nxtarg(tok); /* get the next token */ /* parse it up */ tp = &tok[0]; c = 0; /* first, the META prefix */ if (*tp == 'M' && *(tp+1) == '-') { c = META; tp += 2; } /* next the function prefix */ if (*tp == 'F' && *(tp+1) == 'N') { c |= SPEC; tp += 2; } /* control-x as well... */ if (*tp == '^' && *(tp+1) == 'X') { c |= CTLX; tp += 2; } /* a control char? */ if (*tp == '^' & *(tp+1) != 0) { c |= CTRL; ++tp; } /* make sure we are not lower case */ if (c >= 'a' && c <= 'z') c -= 32; /* the final sequence... */ c |= *tp; return(c); } /* or the normal way */ c = getkey(); /* get a command sequence */ if (c == (CTRL|'X')) /* get control-x sequence */ c = CTLX | getctl(); return(c); } /* execbuf: Execute the contents of a named buffer */ execbuf(f, n) int f, n; /* default flag and numeric arg */ { register BUFFER *bp; /* ptr to buffer to execute */ register int status; /* status return */ char bufn[NBUFN]; /* name of buffer to execute */ /* find out what buffer the user wants to execute */ if ((status = mlreply("Execute buffer: ", bufn, NBUFN)) != TRUE) return(status); /* find the pointer to that buffer */ if ((bp=bfind(bufn, TRUE, 0)) == NULL) return(FALSE); /* and now execute it as asked */ while (n-- > 0) if ((status = dobuf(bp)) != TRUE) return(status); return(TRUE); } /* dobuf: execute the contents of the buffer pointed to by the passed BP */ dobuf(bp) BUFFER *bp; /* buffer to execute */ { register int status; /* status return */ register LINE *lp; /* pointer to line to execute */ register LINE *hlp; /* pointer to line header */ register int linlen; /* length of line to execute */ register WINDOW *wp; /* ptr to windows to scan */ char eline[NSTRING]; /* text of line to execute */ /* starting at the beginning of the buffer */ hlp = bp->b_linep; lp = hlp->l_fp; while (lp != hlp) { /* calculate the line length and make a local copy */ linlen = lp->l_used; if (linlen > NSTRING - 1) linlen = NSTRING - 1; strncpy(eline, lp->l_text, linlen); eline[linlen] = 0; /* make sure it ends */ /* if it is not a comment, execute it */ if (eline[0] != ';' && eline[0] != 0) { status = docmd(eline); if (status != TRUE) { /* a command error */ /* look if buffer is showing */ wp = wheadp; while (wp != NULL) { if (wp->w_bufp == bp) { /* and point it */ wp->w_dotp = lp; wp->w_doto = 0; wp->w_flag |= WFHARD; } wp = wp->w_wndp; } /* in any case set the buffer . */ bp->b_dotp = lp; bp->b_doto = 0; return(status); } } lp = lp->l_fp; /* on to the next line */ } return(TRUE); } execfile(f, n) /* execute a series of commands in a file */ int f, n; /* default flag and numeric arg to pass on to file */ { register int status; /* return status of name query */ char *fname[NSTRING]; /* name of file to execute */ if ((status = mlreply("File to execute: ", fname, NSTRING -1)) != TRUE) return(status); /* otherwise, execute it */ while (n-- > 0) if ((status=dofile(fname)) != TRUE) return(status); return(TRUE); } /* dofile: yank a file into a buffer and execute it if there are no errors, delete the buffer on exit */ dofile(fname) char *fname; /* file name to execute */ { register BUFFER *bp; /* buffer to place file to exeute */ register BUFFER *cb; /* temp to hold current buf while we read */ register int status; /* results of various calls */ char bname[NBUFN]; /* name of buffer */ makename(bname, fname); /* derive the name of the buffer */ if ((bp = bfind(bname, TRUE, 0)) == NULL) /* get the needed buffer */ return(FALSE); bp->b_mode = MDVIEW; /* mark the buffer as read only */ cb = curbp; /* save the old buffer */ curbp = bp; /* make this one current */ /* and try to read in the file to execute */ if ((status = readin(fname, FALSE)) != TRUE) { curbp = cb; /* restore the current buffer */ return(status); } /* go execute it! */ curbp = cb; /* restore the current buffer */ if ((status = dobuf(bp)) != TRUE) return(status); /* if not displayed, remove the now unneeded buffer and exit */ if (bp->b_nwnd == 0) zotbuf(bp); return(TRUE); } /* execute the startup file */ startup() { register int status; /* status of I/O operations */ register int i; /* index into help file names */ char fname[NSTRING]; /* buffer to construct file name in */ #if (MSDOS & LATTICE) | V7 char *homedir; /* pointer to your home directory */ char *getenv(); /* get the HOME from the environment */ if ((homedir = getenv("HOME")) != NULL) { /* build the file name */ strcpy(fname, homedir); strcat(fname, "/"); strcat(fname, pathname[0]); /* and test it */ status = ffropen(fname); if (status == FIOSUC) { ffclose(); return(dofile(fname)); } } #endif /* search through the list of startup files */ for (i=2; i < NPNAMES; i++) { strcpy(fname, pathname[i]); strcat(fname, pathname[0]); status = ffropen(fname); if (status == FIOSUC) break; } /* if it isn't around, don't sweat it */ if (status == FIOFNF) return(TRUE); ffclose(); /* close the file to prepare for to read it in */ return(dofile(fname)); }