home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d3xx / d352 / mg.lha / MG / src.LZH / mg / bind.c < prev    next >
C/C++ Source or Header  |  1990-05-23  |  9KB  |  342 lines

  1. /*
  2.  * Key binding & rebinding & unbinding. 
  3.  */
  4. #include    "no_macro.h"
  5.  
  6. #include    "def.h"
  7. #include    "kbd.h"
  8. #include    "buffer.h"
  9.  
  10. #ifndef NO_MACRO
  11. #include    "macro.h"
  12. #endif
  13.  
  14. #ifdef    ANSI
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #endif
  18.  
  19. static int remap 
  20. PROTO((struct keymap * curmap, int c, struct function * funct));
  21. static int dobind 
  22. PROTO((struct keymap * curmap, char *p, int unbind));
  23. static int growelement 
  24. PROTO((struct keymap *, struct map_element *, int));
  25. static int initelement 
  26. PROTO((struct keymap *, struct map_element *, int));
  27. static struct keymap *realocmap 
  28. PROTO((struct keymap * curmap));
  29. static VOID fixmap 
  30. PROTO((struct keymap *, struct keymap *, struct keymap *));
  31.  
  32. /*
  33.  * Bind a key to a function. No attempt is made to reclaim space no longer
  34.  * used, if this is a problem flags must be added to indicate malloced verses
  35.  * static storage in both keymaps and map_elements. 
  36.  */
  37. static int
  38. remap(curmap, c, funct)
  39.     register struct keymap *curmap;
  40.     int             c;
  41.     struct function *funct;
  42. {
  43.     extern struct map_element *ele;
  44.  
  45.     /*
  46.      * At this point, we know that A) curmap is the map that's going to
  47.      * be changed; B) c is the key that's going to change in that map; C)
  48.      * ele is one of three things: 1) beyond the end of the map, 2) above
  49.      * c, and the preceeding element is below it, or 3) the element that
  50.      * needs to be changed. 
  51.      *
  52.      * We deal with this by changing the map for case 1 & 2, and then
  53.      * letting the case 3 code deal with the changes. 
  54.      */
  55.  
  56.     if (ele >= &curmap->map_element[curmap->map_num]) {
  57.         /*
  58.          * Case 1: ele is past the end of the map. In this case, we
  59.          * try to grow the last element to encompass the char if it's
  60.          * close enough. If it isn't, we create a new map element,
  61.          * and put the the char in that. 
  62.          */
  63.         if ((--ele)->k_num + MAPELEDEF >= c) {
  64.             if (growelement(curmap, ele, c) == NULL)
  65.                 return FALSE;
  66.         } else if ((curmap = realocmap(curmap)) == NULL)
  67.             return FALSE;
  68.         else if (initelement(curmap, ++ele, c) == FALSE)
  69.             return FALSE;
  70.         else
  71.             curmap->map_num += 1;
  72.     } else if (c < ele->k_base) {
  73.         /*
  74.          * Case 2: c lands between map elements. Ele points to the
  75.          * next one. As before, but with three cases: try to grow ele
  76.          * down to c; try to grow ele - 1 up to c; and if all else
  77.          * fails, get a new element inited for c put between them. 
  78.          */
  79.  
  80.         if (ele->k_base <= c + MAPELEDEF) {
  81.             if (growelement(curmap, ele, c) == FALSE)
  82.                 return FALSE;
  83.         } else if (ele > curmap->map_element
  84.                && ele[-1].k_num + MAPELEDEF >= c) {
  85.             if (growelement(curmap, --ele, c) == FALSE)
  86.                 return FALSE;
  87.         } else if ((curmap = realocmap(curmap)) == NULL)
  88.             return FALSE;
  89.         else {
  90.             /*
  91.              * adding a new element to the map. If this code
  92.              * didn't leak memory already, I'd seriously consider
  93.              * checking on the possiblities of an element merge
  94.              * here. 
  95.              */
  96.             struct map_element save;
  97.             register struct map_element *ep;
  98.  
  99.             if (initelement(curmap, &save, c) == FALSE)
  100.                 return FALSE;
  101.  
  102.             /* Shuffle upper elements up */
  103.             for (ep = &curmap->map_element[curmap->map_num]; ep > ele; ep -= 1)
  104.                 ep[0] = ep[-1];
  105.             *ep = save;
  106.             curmap->map_num += 1;
  107.         }
  108.     }
  109.     /*
  110.      * Case 3: Just change the key in the existing map. The other two
  111.      * cases twiddle the kemap so it's right, then fall through to this
  112.      * code. 
  113.      */
  114.     ele->k_entry[c - ele->k_base] = *funct;
  115.     return TRUE;
  116. }
  117.  
  118. /*
  119.  * growelement - grow an element up/down to encompass the given character,
  120.  * shuffling things as needed. We don't check the reasonableness of doing
  121.  * that extension, as the caller (which should only be remap) has to do that
  122.  * before calling us. 
  123.  */
  124. static int
  125. growelement(curmap, ele, c)
  126.     struct keymap  *curmap;
  127.     register struct map_element *ele;
  128.     register int    c;
  129. {
  130.     register int    newnum, newbase, i;
  131.     register struct function *fp;
  132.  
  133.     if (c < ele->k_base) {    /* growing down */
  134.         newbase = c;
  135.         newnum = ele->k_num;
  136.     } else {        /* Growing up */
  137.         newbase = ele->k_base;
  138.         newnum = c;
  139.     }
  140.  
  141.     if ((fp = (struct function *)
  142.     malloc((newnum - newbase + 1) * sizeof(struct function))) == NULL) {
  143.         ewprintf("Out of memory");
  144.         return FALSE;
  145.     }
  146.     for (i = newbase; i < ele->k_base; i += 1)
  147.         fp[i - newbase] = *curmap->map_default;
  148.     for (; i <= ele->k_num; i += 1)
  149.         fp[i - newbase] = ele->k_entry[i - ele->k_base];
  150.     for (; i < newnum; i += 1)
  151.         fp[i - newbase] = *curmap->map_default;
  152.  
  153.     ele->k_entry = fp;
  154.     ele->k_base = newbase;
  155.     ele->k_num = newnum;
  156.     return TRUE;
  157. }
  158.  
  159. /*
  160.  * initelement sets up the existing element pointer as apropos for the
  161.  * character and map it just got passed. 
  162.  */
  163. static int
  164. initelement(curmap, ele, c)
  165.     struct keymap  *curmap;
  166.     register struct map_element *ele;
  167.     int             c;
  168. {
  169.     register struct function *fp;
  170.  
  171.     if ((fp = (struct function *) malloc(sizeof(struct function))) == NULL)
  172.         return FALSE;
  173.     ele->k_base = c;
  174.     ele->k_num = c;
  175.     ele->k_entry = fp;
  176.     return TRUE;
  177. }
  178.  
  179. /*
  180.  * Adds another element to the map - moving it if necessary. Also makes sure
  181.  * that the global ele points to the same place afterwards. 
  182.  */
  183. static struct keymap *
  184. realocmap(curmap)
  185.     register struct keymap *curmap;
  186. {
  187.     register struct keymap *mp;
  188.     register int    i;
  189.     extern int      nmaps;
  190.  
  191.  
  192.     if (curmap->map_num < curmap->map_max)
  193.         return curmap;
  194.  
  195.     if ((mp = (struct keymap *) malloc((unsigned) (sizeof(struct keymap) +
  196.                                (curmap->map_max + MAPGROW - 1) * sizeof(struct map_element)))) == NULL) {
  197.         ewprintf("Out of memory");
  198.         return NULL;
  199.     }
  200.     mp->map_num = curmap->map_num;
  201.     mp->map_max = curmap->map_max + MAPGROW;
  202.     mp->map_default = curmap->map_default;
  203.  
  204.     for (i = curmap->map_num; i--;)
  205.         mp->map_element[i] = curmap->map_element[i];
  206.  
  207.     for (i = nmaps; i--;) {
  208.         if (map_table[i].p_map == curmap)
  209.             map_table[i].p_map = mp;
  210.         else
  211.             fixmap(curmap, mp, map_table[i].p_map);
  212.     }
  213.     ele = &mp->map_element[ele - &curmap->map_element[0]];
  214.     return mp;
  215. }
  216.  
  217. /* fix references to a realocated keymap (recursive) */
  218. static          VOID
  219. fixmap(curmap, mp, mt)
  220.     struct keymap  *curmap, *mp;
  221.     register struct keymap *mt;
  222. {
  223.     register int    i, j;
  224.     register struct map_element *ele;
  225.     register struct function *fp;
  226.  
  227.     for (i = mt->map_num; i--;) {
  228.         ele = &(mt->map_element[i]);
  229.         for (j = ele->k_num; j >= ele->k_base; j -= 1) {
  230.             fp = &(ele->k_entry[j - ele->k_base]);
  231.             if (fp->f_type == F_PREFIX)
  232.                 if ((struct keymap *) fp->f_pref == curmap)
  233.                     fp->f_pref = (int (*) ()) mp;
  234.                 else
  235.                     fixmap(curmap, mp, (struct keymap *) fp->f_pref);
  236.         }
  237.     }
  238. }
  239.  
  240. /*
  241.  * do the input for local-set-key, global-set-key  and define-key then call
  242.  * remap to do the work. 
  243.  */
  244. static int
  245. dobind(curmap, p, unbind)
  246.     register struct keymap *curmap;
  247.     char           *p;
  248.     int             unbind;
  249. {
  250.     char            prompt[80];
  251.     char           *pep;
  252.     int             c;
  253.     int             s;
  254.     int             rescan();
  255.     struct function funct;
  256.  
  257.     (VOID) strcpy(prompt, p);
  258.     pep = prompt + strlen(prompt);
  259.     for (;;) {
  260.         ewprintf("%s", prompt);
  261.         pep[-1] = ' ';
  262.         pep = keyname(pep, c = getkey(DISSCR));
  263.         funct = *doscan(curmap, c);
  264.         if (funct.f_type != F_PREFIX)
  265.             break;
  266.         *pep++ = '-';
  267.         *pep = '\0';
  268.         curmap = (struct keymap *) funct.f_pref;
  269.     }
  270.     if (unbind)
  271.         funct.f_funcp = rescan;
  272.     else {
  273.         if ((s = eread("%s to command: ", prompt, 80, EFFUNC | EFNEW, prompt))
  274.             != TRUE)
  275.             return s;
  276.         if ((funct.f_funcp = name_function(prompt)) != NULL)
  277.             funct.f_type = F_CFUNCT;
  278. #ifndef    NO_MACRO
  279.         else if ((funct.f_macro = (int (*) ()) find_macro(prompt)) != NULL)
  280.             funct.f_type = F_MACRO;
  281. #endif
  282.         else if ((funct.f_pref = (int (*) ()) name_map(prompt)) != NULL)
  283.             funct.f_type = F_PREFIX;
  284.         else {
  285.             ewprintf("[No match]");
  286.             return FALSE;
  287.         }
  288.     }
  289.     return remap(curmap, c, &funct);
  290. }
  291. /*
  292.  * This function redefines a key in any keymap. 
  293.  */
  294. /* ARGSUSED */
  295. define_key(f, n)
  296. {
  297.     static char     buf[48] = "Define key map: ";
  298.     struct maps    *mp;
  299.     char           *strncat();
  300.  
  301.     buf[16] = '\0';
  302.     if (eread(buf, &buf[16], 48 - 16, EFNEW) != TRUE)
  303.         return FALSE;
  304.     if ((mp = name_mode(&buf[16])) == NULL) {
  305.         ewprintf("Unknown map %s", &buf[16]);
  306.         return FALSE;
  307.     }
  308.     (VOID) strncat(&buf[16], " key: ", 48 - 16 - 1);
  309.     return dobind(mp->p_map, buf, FALSE);
  310. }
  311. /*
  312.  * This function modifies the fundamental keyboard map. 
  313.  */
  314. /* ARGSUSED */
  315. bindtokey(f, n)
  316. {
  317.     return dobind(map_table[0].p_map, "Global set key: ", FALSE);
  318. }
  319.  
  320. /*
  321.  * This function modifies the current mode's keyboard map. 
  322.  */
  323. /* ARGSUSED */
  324. localbind(f, n)
  325. {
  326.     return dobind(curbp->b_modes[curbp->b_nmodes]->p_map, "Local set key: ",
  327.               FALSE);
  328. }
  329.  
  330. unbindtokey(f, n)
  331.     int             f, n;
  332. {
  333.     return dobind(map_table[0].p_map, "Global unset key: ", TRUE);
  334. }
  335.  
  336. localunbind(f, n)
  337.     int             f, n;
  338. {
  339.     return dobind(curbp->b_modes[curbp->b_nmodes]->p_map, "Local unset key: ",
  340.               TRUE);
  341. }
  342.