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 >
C/C++ Source or Header  |  1988-03-14  |  11KB  |  394 lines

  1. /*
  2.  *        Extended (M-X) commands.
  3.  */
  4. #include    "def.h"
  5.  
  6. /*
  7.  * This function modifies the keyboard
  8.  * binding table, by adjusting the entries in the
  9.  * big "bindings" array. Most of the grief deals with the
  10.  * prompting for additional arguments.
  11.  */
  12. extern KEY *kbdnext ;
  13. /*ARGSUSED*/
  14. bindtokey(f, n, k) {
  15.     register int    s;
  16.     register SYMBOL    *sp;
  17.     int        c;
  18.     char        xname[NXNAME];
  19.  
  20.     if (kbdmop == NULL)
  21.         ewprintf("Set key globally: ") ;
  22.     c = (int) getkey(0);
  23.     if ((s=eread("Set key %c to command: ", xname, NXNAME, EFNEW|EFFUNC,
  24. #ifdef VARARGS
  25.              c
  26. #else
  27.              (char *) &c, (char *) NULL
  28. #endif
  29.              )) != TRUE)
  30.         return (s);
  31.     if ((sp=symlookup(xname)) == NULL) {
  32.         ewprintf("[No match]");
  33.         return (FALSE);
  34.     }
  35.     binding[(KEY) c] = sp;            /* rebind new.        */
  36.     return (TRUE);
  37. }
  38.  
  39. /*
  40.  * User function to unbind keys. Just call the unbind we already have. 
  41.  */
  42. /*ARGSUSED*/
  43. unsetkey(f, n, k) {
  44.     register KEY    key;
  45.     
  46.     if (kbdmop == NULL) ewprintf("Unset key globally: ") ;
  47.     key = getkey(0);
  48.     if (key == (KCTRL|'G') || key == (KCTLX|KCTRL|'G')
  49.     || key == (KMETA|KCTRL|'G')) {
  50.         (VOID) ctrlg(FALSE, 1, KRANDOM);
  51.         return ABORT;
  52.     }
  53.     binding[key] = NULL;
  54.     return TRUE;
  55. }
  56.  
  57. /*
  58.  * Extended command. Call the message line
  59.  * routine to read in the command name and apply autocompletion
  60.  * to it. When it comes back, look the name up in the symbol table
  61.  * and run the command if it is found and has the right type.
  62.  * Print an error if there is anything wrong.
  63.  */
  64. /*ARGSUSED*/
  65. extend(f, n, k) {
  66.     register SYMBOL    *sp;
  67.     register int    s;
  68.     char        xname[NXNAME];
  69.  
  70.     if (f == FALSE)
  71.         s = eread("M-x ", xname, NXNAME, EFNEW|EFFUNC
  72. #ifndef VARARGS
  73.              , (char *) NULL
  74. #endif
  75.              ) ;
  76.     else
  77.         s = eread("%d M-x ", xname, NXNAME, EFNEW|EFFUNC, 
  78. #ifdef    VARARGS
  79.              n
  80. #else
  81.              (char *) &n, (char *) NULL
  82. #endif
  83.              ) ;
  84.     if (s != TRUE) return (s);
  85.     if ((sp=symlookup(xname)) != NULL)
  86.         return ((*sp->s_funcp)(f, n, KRANDOM));
  87.     ewprintf("[No match]");
  88.     return FALSE;
  89. }
  90.  
  91. /*
  92.  * Read a key from the keyboard, and look it
  93.  * up in the binding table. Display the name of the function
  94.  * currently bound to the key. Say that the key is not bound
  95.  * if it is indeed not bound, or if the type is not a
  96.  * "builtin". This is a bit of overkill, because this is the
  97.  * only kind of function there is.
  98.  */
  99. /*ARGSUSED*/
  100. desckey(f, n, k) {
  101.     register SYMBOL    *sp;
  102.     register KEY    c;
  103.  
  104.     if (kbdmop == NULL) ewprintf("Describe key briefly: ");
  105.     c = getkey(0);
  106.     if (kbdmop != NULL) return TRUE;
  107.     if ((sp=binding[c]) == NULL)
  108.         ewprintf("%c is undefined", (int) c);
  109.     else
  110.         ewprintf("%c runs the command %s", (int) c, sp->s_name);
  111.     return (TRUE);
  112. }
  113.  
  114. /*
  115.  * This function creates a table, listing all
  116.  * of the command keys and their current bindings, and stores
  117.  * the table in the standard pop-op buffer (the one used by the
  118.  * directory list command, the buffer list command, etc.). This
  119.  * lets MicroEMACS produce it's own wall chart. The bindings to
  120.  * "ins-self" are only displayed if there is an argument.
  121.  */
  122. /*ARGSUSED*/
  123. wallchart(f, n, k) {
  124.     register int    key;
  125.     register SYMBOL    *sp;
  126.     register char    *cp1;
  127.     register char    *cp2;
  128.     BUFFER        *bp;
  129.     char        buf[64];
  130.  
  131.     bp = bfind("*Help*", TRUE);
  132.     if (bclear(bp) != TRUE)            /* Clear it out.    */
  133.         return TRUE;
  134.     for (key=0; key<NKEYS; ++key) {        /* For all keys.    */
  135.         sp = binding[key];
  136.         if (sp != NULL
  137.         && (f!=FALSE
  138.         || strcmp(sp->s_name, "self-insert-command")!=0)) {
  139.             keyname(buf, key);
  140.             cp1 = &buf[0];        /* Find end.        */
  141.             while (*cp1 != 0)
  142.                 ++cp1;
  143.             while (cp1 < &buf[32])    /* Goto column 32.    */
  144.                 *cp1++ = ' ';                
  145.             cp2 = sp->s_name;    /* Add function name.    */
  146.             while (*cp1++ = *cp2++)
  147.                 ;
  148.             if (addline(bp, buf) == FALSE)
  149.                 return (FALSE);
  150.         }
  151.     }
  152.     return popbuf(bp) == NULL ? FALSE : TRUE;
  153. }
  154.  
  155. #ifdef    STARTUP
  156. /*
  157.  * Define the commands needed to do startup-file processing.
  158.  * This code is mostly a kludge just so we can get startup-file processing.
  159.  *
  160.  * If you're serious about having this code, you should rewrite it.
  161.  * To wit: 
  162.  *    It has lots of funny things in it to make the startup-file look
  163.  *    like a GNU startup file; mostly dealing with parens and semicolons.
  164.  *    This should all vanish.
  165.  *
  166.  *    It uses the same buffer as keyboard macros. The fix is easy (make
  167.  *    a new function "execmacro" that takes a pointer to char and
  168.  *    does what ctlxe does on it. Make ctlxe and excline both call it.)
  169.  *    but would slow down the non-micro version.
  170.  *
  171.  * We define eval-expression because it's easy. It's pretty useless,
  172.  * since it duplicates the functionality of execute-extended-command.
  173.  * All of this is just to support startup files, and should be turned
  174.  * off for micros.
  175.  */
  176.  
  177. /*
  178.  * evalexpr - get one line from the user, and run it. Identical in function
  179.  *    to extend, but easy.
  180.  */
  181. /*ARGSUSED*/
  182. evalexpr(f, n, k) {
  183.     register int    s;
  184.     char        exbuf[NKBDM];
  185.  
  186.     if ((s = ereply("Eval: ", exbuf, NKBDM)) != TRUE)
  187.         return s;
  188.     return excline(exbuf);
  189. }
  190. /*
  191.  * evalbuffer - evaluate the current buffer as line commands. Useful
  192.  *    for testing startup files.
  193.  */
  194. /*ARGSUSED*/
  195. evalbuffer(f, n, k) {
  196.     register LINE    *lp;
  197.     register BUFFER    *bp = curbp;
  198.     register int    s;
  199.     static char    excbuf[NKBDM];
  200.     char        *strncpy();
  201.  
  202.     for (lp = lforw(bp->b_linep); lp != bp->b_linep; lp = lforw(lp)) {
  203.         if (llength(lp) >= NKBDM + 1) return FALSE ;
  204.         (VOID) strncpy(excbuf, ltext(lp), NKBDM);
  205.         if ((s = excline(excbuf)) != TRUE) return s;
  206.     }
  207.     return TRUE;
  208. }
  209. /*
  210.  * evalfile - go get a file and evaluate it as line commands. You can
  211.  *    go get your own startup file if need be.
  212.  */
  213. /*ARGSUSED*/
  214. evalfile(f, n, k) {
  215.     register int    s;
  216.     char        fname[NFILEN];
  217.  
  218.     if ((s = ereply("Load file: ", fname, NFILEN)) != TRUE)
  219.         return s;
  220.     return load(fname);
  221. }
  222.  
  223. /*
  224.  * load - go load the file name we got passed.
  225.  */
  226. load(fname) char *fname; {
  227.     register int    s;
  228.     char        excbuf[NKBDM];
  229.  
  230.     if (((s = ffropen(fname)) == FIOERR) || (s == FIOFNF))
  231.         return FALSE;
  232.     while ((s = ffgetline(excbuf, NKBDM)) == FIOSUC)
  233.         if (excline(excbuf) != TRUE) break;
  234.     (VOID) ffclose();
  235.     return s == FIOEOF;
  236. }
  237. int myupper(c)
  238. int c ;
  239. {
  240.    if ('a'<=c&&c<='z')
  241.       return(c - ('a'-'A')) ;
  242.    else
  243.       return(c) ;
  244. }
  245. char *skipwhite(s)
  246. char *s ;
  247. {
  248.    while (*s && *s <= ' ')
  249.       s++ ;
  250.    return(s) ;
  251. }
  252. /*
  253.  * excline - run a line from a load file or eval-expression.
  254.  * Now broken into two pieces; the piece which gets the
  255.  * line into the macro buffer starting at kbdnext, and the
  256.  * part which decides what to do with it.
  257.  *
  258.  *   This has been rewritten considerably.  Now, everything
  259.  *   must be typed explicitly, just as if it were coming in
  260.  *   from the keyboard.  Thus, you might have:
  261.  *
  262.  *   ^U 10 $X 'kill-line'
  263.  *
  264.  *   Anything in quotes is taken verbatim, including spaces.
  265.  *   A ^ is combined with the preceding character into a control
  266.  *   character.  A \nnn is turned into that character.  White
  267.  *   space is ignored outside of quotes.  A \" gets turned into
  268.  *   a single quote.  $ gets turned into a meta.  Note that
  269.  *   we currently allow macros to be defined by this.  The end of
  270.  *   a ' string gets turned into a null, as it is then an argument
  271.  *   to something.
  272.  */
  273. /* Don't want to get the objects in isdigit.c just for this */
  274. #define    isdigit(c)    (((c) >= '0') && ((c) <= '9'))
  275. excline(line) register char *line; {
  276.     register char    *funcp, *argp = NULL;
  277.     int        status;
  278.         KEY             *kbdst, *p ;
  279.     int        inquote ;
  280.         int        buckies ;
  281.         int        c ;
  282.         long            param ;
  283.  
  284.     if (kbdmip > kbdnext)
  285.            kbdnext = kbdmip + 1 ;
  286.     kbdst = kbdnext + 10 ;
  287.         inquote = 0 ;
  288.         param = 0 ;
  289.         for (funcp = line; *funcp !=0 && kbdst < &kbdm[NKBDM-6]; funcp++) {
  290.            buckies = 0 ;
  291. floop:
  292.        if (!inquote)
  293.           funcp = skipwhite(funcp) ;
  294.            if (*funcp != 0) {
  295.               while (*funcp == '^' || *funcp == '$') {
  296.                  if (*funcp == '^')
  297.                     buckies |= KCTRL ;
  298.                  else
  299.                     buckies |= KMETA ;
  300.                  funcp++ ;
  301.                  if (!inquote)
  302.                     funcp = skipwhite(funcp) ;
  303.                  if ((c=myupper(*funcp))=='X' && (buckies & KCTRL)) {
  304.                     buckies = KCTLX ;
  305.                     funcp++ ;
  306.                  }
  307.               }
  308. gloop:
  309.               if (buckies) {
  310.                  if (!inquote)
  311.                     funcp = skipwhite(funcp) ;
  312.                  if ((c = myupper(*funcp))) {
  313.                     if (c=='U' && (buckies & KCTRL)) {
  314.                        if (param == 0)
  315.                           param = 4 ;
  316.                        else
  317.                           param <<= 2 ;
  318.                     } else {
  319.                        if (param != 0) {
  320.                           *kbdst++ = (KCTRL | 'U') ;
  321.                           *kbdst++ = param ;
  322.                           param = 0 ;
  323.                        }
  324.                        *kbdst++ = buckies | c ;
  325.                     }
  326.                     funcp++ ;
  327.                     buckies = 0 ;
  328.                     goto floop ;
  329.                  } else {
  330.                     ewprintf("Need alpha after $ or ^") ;
  331.                     return(FALSE) ;
  332.                  }
  333.               }
  334.               if (param != 0) {
  335.                  if (!inquote)
  336.                     funcp = skipwhite(funcp) ;
  337.                  if (isdigit(*funcp)) {
  338.                     param = 0 ;
  339.                     while (isdigit(*funcp)) {
  340.                        param = param * 10 + *funcp++ - '0' ;
  341.                     }
  342.                  }
  343.                  *kbdst++ = (KCTRL | 'U') ;
  344.                  *kbdst++ = param ;
  345.                  param = 0 ;
  346.                  buckies = 0 ;
  347.                  goto floop ;
  348.               }
  349.               if (*funcp == '"' || *funcp == '\'') {
  350.                  if (*funcp == inquote) {
  351.                     if (inquote == '\'')
  352.                        *kbdst++ = 0 ;
  353.                     inquote = 0 ;
  354.                  } else if (inquote == 0) {
  355.                     inquote = *funcp ;
  356.                  } else {
  357.                     *kbdst++ = *funcp ;
  358.                  }
  359.               } else if (*funcp == '\\') {
  360.                  funcp++ ;
  361.                  if (*funcp == 'F' || *funcp == 'f') {
  362.                     funcp++ ;
  363.                     c = 0 ;
  364.                     while (isdigit(*funcp))
  365.                        c = 10 * c + *funcp++ - '0' ;
  366.                     c += KFIRST ;
  367.                     if (c > KLAST)
  368.                        c = KFIRST ;
  369.                     *kbdst++ = c ;
  370.                  } else if ('0' <= *funcp && *funcp <= '7') {
  371.                     c = 0 ;
  372.                     while (isdigit(*funcp))
  373.                        c = 10 * c + *funcp++ - '0' ;
  374.                     *kbdst++ = c ;
  375.                  } else {
  376.                     *kbdst++ = *funcp ;
  377.                  }
  378.               } else {
  379.                  *kbdst++ = *funcp ;
  380.               }
  381.            }
  382.            if (*funcp == 0)
  383.               break ;
  384.         }
  385.         if (*funcp != 0)
  386.            return(FALSE) ;
  387.         *kbdst++ = (KEY) (KCTLX|')');
  388.         *kbdst++ = (KEY) (KCTLX|')');
  389.         *kbdst++ = '\0';
  390.         status = ctlxe(FALSE, 1, KMACCUR);
  391.     return status;
  392. }
  393. #endif    STARTUP
  394.