home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD1.bin / gnu / src / baseline / jove-4.14.6.lha / jove-4.14.6 / keymaps.c < prev    next >
C/C++ Source or Header  |  1992-01-10  |  12KB  |  602 lines

  1. /***************************************************************************
  2.  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  3.  * is provided to you without charge, and with no warranty.  You may give  *
  4.  * away copies of JOVE, including sources, provided that this notice is    *
  5.  * included in all the files.                                              *
  6.  ***************************************************************************/
  7.  
  8. #include "jove.h"
  9. #include "list.h"
  10. #include "fp.h"
  11. #include "termcap.h"
  12. #include "chars.h"
  13. #include "disp.h"
  14. #include "re.h"
  15.  
  16. /* Up until now a keymap was an array of pointers to
  17.    data_obj's.  A data_obj was either a pointer to a built-in
  18.    command or a keyboard macro.  Now a data_obj can be a
  19.    pointer to a keymap as well, which is how prefix keys will
  20.    be handled.
  21.  
  22.    There will be a way to build keymaps and give them names,
  23.    and to look those keymaps up by name, attach them to keys.
  24.    There will be a way to specify a string of key strokes and
  25.    have a series of keymaps built automatically for those
  26.    sequences. */
  27.  
  28. private    void
  29.     fb_aux proto((data_obj *, struct keymap *, char *, char *, size_t));
  30.  
  31. private List    *keymaps;        /* list of all keymaps */
  32. private struct keymap    *mainmap;
  33. #ifdef    IPROCS
  34. private struct keymap    *procsmap;
  35. #endif
  36.  
  37. /* make a new keymap, give it name NAME, initialize the keys array
  38.    to keys, if nonzero, or make an empty one, otherwise */
  39.  
  40. private struct keymap *
  41. km_new(name, keys)
  42. char    *name;
  43. data_obj    **keys;
  44. {
  45.     struct keymap    *km;
  46.  
  47.     km = (struct keymap *) emalloc(sizeof *km);
  48.     (void) list_push(&keymaps, (UnivPtr) km);
  49.     km->Type = KEYMAP;
  50.     km->Name = name;
  51.     if (keys != NULL) {
  52.         km->k_keys = keys;
  53.         km->k_alloc_p = NO;
  54.     } else {
  55.         km->k_keys = (data_obj **) emalloc(NCHARS * sizeof (data_obj *));
  56.         byte_zero((UnivPtr) km->k_keys, NCHARS * sizeof (data_obj *));
  57.         km->k_alloc_p = YES;
  58.     }
  59.     return km;
  60. }
  61.  
  62. #ifdef    NEVER
  63.  
  64. /* free up a keymap */
  65.  
  66. private void
  67. km_destroy(km)
  68. struct keymap    *km;
  69. {
  70.     if (km->k_alloc_p == YES)
  71.         free((char *) km->k_keys);
  72.     km->k_keys = NULL;
  73.     free((char *) km);
  74. }
  75.  
  76. /* lookup a keymap by name */
  77.  
  78. private struct keymap *
  79. km_lookup(name)
  80. char    *name;
  81. {
  82.     List    *lp;
  83.  
  84.     for (lp = keymaps; lp != NULL; lp = list_next(lp))
  85.         if (strcmp(name, ((struct keymap *) list_data(lp))->Name) == 0)
  86.             break;
  87.     if (lp == NULL)
  88.         return NULL;
  89.     return (struct keymap *) list_data(lp);
  90. }
  91.  
  92. #endif
  93.  
  94. /* given a map and a key, return the object bound to that key */
  95.  
  96. #define km_getkey(m, c)    ((m)->k_keys[(c) & CHARMASK])
  97.  
  98. #ifndef    km_getkey
  99. data_obj *
  100. km_getkey(m, c)
  101. struct keymap    *m;
  102. int    c;
  103. {
  104.     return (m->k_keys[c & CHARMASK]);
  105. }
  106. #endif
  107.  
  108. private void
  109. km_setkey(m, c, d)
  110. struct keymap    *m;
  111. int    c;
  112. data_obj    *d;
  113. {
  114.     m->k_keys[c & CHARMASK] = d;
  115. }
  116.  
  117. /* get the currently active keymaps into km_buf */
  118.  
  119. private int
  120. get_keymaps(km_buf)
  121. struct keymap    **km_buf;
  122. {
  123.     int    nmaps = 0;
  124.  
  125. #ifdef    IPROCS
  126.     if (curbuf->b_process != NULL)
  127.         km_buf[nmaps++] = procsmap;
  128. #endif
  129.     if (curbuf->b_map != NULL)
  130.         km_buf[nmaps++] = curbuf->b_map;
  131.     km_buf[nmaps++] = mainmap;
  132.  
  133.     return nmaps;
  134. }
  135.  
  136. private struct keymap *
  137. IsPrefix(cp)
  138. data_obj    *cp;
  139. {
  140.     if (cp == NULL || (cp->Type & TYPEMASK) != KEYMAP)
  141.         return NULL;
  142.     return (struct keymap *) cp;
  143. }
  144.  
  145. /* Is `c' a prefix character */
  146.  
  147. int
  148. PrefChar(c)
  149. int    c;
  150. {
  151.     return (int) IsPrefix(km_getkey(mainmap, c));
  152. }
  153.  
  154. void
  155. UnbindC()
  156. {
  157.     char    *keys;
  158.     struct keymap    *map = mainmap;
  159.  
  160.     keys = ask((char *)NULL, ProcFmt);
  161.     for (;;) {
  162.         if (keys[1] == '\0')
  163.             break;
  164.         if ((map = IsPrefix(km_getkey(map, *keys))) == NULL)
  165.             break;
  166.         keys += 1;
  167.     }
  168.     if (keys[1] != '\0')
  169.         complain("That's not a legitimate key sequence.");
  170.     km_setkey(map, keys[0], (data_obj *)NULL);
  171. }
  172.  
  173. private void
  174. BindWMap(map, lastkey, cmd)
  175. struct keymap    *map;
  176. int    lastkey;
  177. data_obj     *cmd;
  178. {
  179.     struct keymap    *nextmap;
  180.     int    c;
  181.  
  182.     c = addgetc();
  183.     if (c == EOF) {
  184.         if (lastkey == EOF)
  185.             complain("[Empty key sequence]");
  186.         complain("[Premature end of key sequence]");
  187.     } else {
  188.         if ((nextmap = IsPrefix(km_getkey(map, c))) != NULL)
  189.             BindWMap(nextmap, c, cmd);
  190.         else {
  191.             km_setkey(map, c, cmd);
  192. #ifdef    MAC
  193.             ((struct cmd *) cmd)->c_key = c;    /* see about_j() in mac.c */
  194.             if (map->k_keys == MainKeys)
  195.                 ((struct cmd *) cmd)->c_map = F_MAINMAP;
  196.             else if (map->k_keys == EscKeys)
  197.                 ((struct cmd *) cmd)->c_map = F_PREF1MAP;
  198.             else if (map == (struct keymap *) CtlxKeys)
  199.                 ((struct cmd *) cmd)->c_map = F_PREF2MAP;
  200. #endif
  201.         }
  202.     }
  203. }
  204.  
  205. private void
  206. BindSomething(proc, map)
  207. data_obj    *(*proc) ptrproto((const char *));
  208. struct keymap    *map;
  209. {
  210.     data_obj    *d;
  211.  
  212.     if ((d = (*proc)(ProcFmt)) == NULL)
  213.         return;
  214.     s_mess(": %f %s ", d->Name);
  215.     BindWMap(map, EOF, d);
  216. }
  217.  
  218. void
  219. BindAKey()
  220. {
  221.     BindSomething(findcom, mainmap);
  222. }
  223.  
  224. void
  225. BindMac()
  226. {
  227.     BindSomething(findmac, mainmap);
  228. }
  229.  
  230. private void
  231. DescWMap(map, key)
  232. struct keymap    *map;
  233. int    key;
  234. {
  235.     data_obj    *cp = km_getkey(map, key);
  236.     struct keymap    *prefp;
  237.  
  238.     if (cp == NULL)
  239.         add_mess("is unbound.");
  240.     else if ((prefp = IsPrefix(cp)) != NULL)
  241.         DescWMap(prefp, addgetc());
  242.     else
  243.         add_mess("is bound to %s.", cp->Name);
  244. }
  245.  
  246. void
  247. KeyDesc()
  248. {
  249.     s_mess(ProcFmt);
  250.     DescWMap(mainmap, addgetc());
  251. }
  252.  
  253. private void
  254. DescMap(map, pref)
  255. struct keymap    *map;
  256. char    *pref;
  257. {
  258.     int    c1,
  259.         c2;
  260.     char    keydescbuf[40];
  261.     struct keymap    *prefp;
  262.  
  263.     for (c1 = 0; c1 < NCHARS; c1 = c2 + 1) {
  264.         c2 = c1;
  265.         if (km_getkey(map, c1) == 0)
  266.             continue;
  267.         do ; while (++c2 < NCHARS && km_getkey(map, c1) == km_getkey(map, c2));
  268.         c2 -= 1;
  269.         swritef(keydescbuf, sizeof(keydescbuf),
  270.             c1==c2? "%s %p" : c1==c2+1? "%s {%p,%p}" : "%s [%p-%p]",
  271.             pref, c1, c2);
  272.         if ((prefp = IsPrefix(km_getkey(map, c1)))!=NULL && (prefp != map))
  273.             DescMap(prefp, keydescbuf);
  274.         else
  275.             Typeout("%-18s%s", keydescbuf, km_getkey(map, c1)->Name);
  276.     }
  277. }
  278.  
  279. void
  280. DescBindings()
  281. {
  282.     TOstart("Key Bindings", TRUE);
  283.     DescMap(mainmap, NullStr);
  284.     TOstop();
  285. }
  286.  
  287. private void
  288. find_binds(dp, buf, size)
  289. data_obj    *dp;
  290. char    *buf;
  291. size_t    size;
  292. {
  293.     char    *endp;
  294.  
  295.     buf[0] = '\0';
  296.     fb_aux(dp, mainmap, (char *) NULL, buf, size);
  297.     endp = buf + strlen(buf) - 2;
  298.     if ((endp > buf) && (strcmp(endp, ", ") == 0))
  299.         *endp = '\0';
  300. }
  301.  
  302. private void
  303. fb_aux(cp, map, prefix, buf, size)
  304. register data_obj    *cp;
  305. struct keymap    *map;
  306. char    *prefix,
  307.     *buf;
  308. size_t    size;
  309. {
  310.     int    c1,
  311.         c2;
  312.     char    *bufp = buf + strlen(buf),
  313.         prefbuf[20];
  314.     struct keymap    *prefp;
  315.  
  316.     for (c1 = 0; c1 < NCHARS; c1 = c2 + 1) {
  317.         c2 = c1;
  318.         if (km_getkey(map, c1) == cp) {
  319.             do ; while (++c2 < NCHARS && km_getkey(map, c1) == km_getkey(map, c2));
  320.             c2 -= 1;
  321.             if (prefix)
  322.                 swritef(bufp, sizeof(buf) - (bufp-buf), "%s ",
  323.                     prefix);
  324.             bufp += strlen(bufp);
  325.             swritef(bufp, size - (bufp-buf),
  326.                 c1==c2? "%p" : c1==c2+1? "{%p,%p}" : "[%p-%p]",
  327.                 c1, c2);
  328.         }
  329.         if ((prefp = IsPrefix(km_getkey(map, c1)))!=NULL && (prefp != map))  {
  330.             swritef(prefbuf, sizeof(prefbuf), "%p", c1);
  331.             fb_aux(cp, prefp, prefbuf, bufp, size-(bufp-buf));
  332.         }
  333.         bufp += strlen(bufp);
  334.     }
  335. }
  336.  
  337. void
  338. DescCom()
  339. {
  340.     data_obj    *dp;
  341.     char    pattern[100],
  342.         *file = CmdDb;
  343.     const char    *doc_type;
  344.     static const char var_type[] = "Variable";
  345.     static const char cmd_type[] = "Command";
  346.     File    *fp;
  347.  
  348.     if (!strcmp(LastCmd->Name, "describe-variable")) {
  349.         doc_type = var_type;
  350.         dp = (data_obj *) findvar(ProcFmt);
  351.     } else {
  352.         doc_type = cmd_type;
  353.         dp = (data_obj *) findcom(ProcFmt);
  354.     }
  355.     if (dp == NULL)
  356.         return;
  357.     fp = open_file(file, iobuff, F_READ, YES, YES);
  358.     Placur(ILI, 0);
  359.     flushscreen();
  360.     swritef(pattern, sizeof(pattern), "^:entry \"%s\" \"%s\"$",
  361.         dp->Name, doc_type);
  362.     TOstart("Help", TRUE);
  363.     for (;;) {
  364.         if (f_gets(fp, genbuf, (size_t)LBSIZE)) {
  365.             Typeout("There is no documentation for \"%s\".", dp->Name);
  366.             break;
  367.         }
  368.         if (genbuf[0] == ':' && LookingAt(pattern, genbuf, 0)) {
  369.             /* found it ... let's print it */
  370.             if (doc_type == var_type)
  371.                 Typeout(dp->Name);
  372.             else if (doc_type == cmd_type) {
  373.                 char    binding[128];
  374.  
  375.                 find_binds(dp, binding, sizeof(binding));
  376.                 if (blnkp(binding))
  377.                     Typeout("To invoke %s, type \"ESC X %s<cr>\".",
  378.                         dp->Name, dp->Name);
  379.                 else
  380.                     Typeout("Type \"%s\" to invoke %s.",
  381.                         binding, dp->Name);
  382.             }
  383.             Typeout("");
  384.             while (!f_gets(fp, genbuf, (size_t)LBSIZE)
  385.             && strncmp(genbuf, ":entry", (size_t)6) != 0) {
  386.                 Typeout("%s", genbuf);
  387.             }
  388.