home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Libraries / stdwin / Ports / alfa / bind.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-10-21  |  7.0 KB  |  389 lines  |  [TEXT/????]

  1. /* TERMCAP STDWIN -- KEY BINDING. */
  2.  
  3. /* Separated from the default tables; the application may override
  4.    the tables but not the executable code. */
  5.  
  6. #ifdef SYSV
  7. #define TERMIO
  8. #endif
  9.  
  10. #ifdef unix
  11. #ifndef TERMIO
  12. #define DO_SGTTY
  13. #endif
  14. #define DO_TERMCAP
  15. #endif
  16.  
  17. #include "alfa.h"
  18.  
  19. #ifdef DO_SGTTY
  20. #include <sgtty.h>
  21. #endif
  22. #ifdef TERMIO
  23. #include <termio.h>
  24. #endif
  25.  
  26. #ifdef DO_TERMCAP
  27. /* Termcap functions: */
  28. char *tgetstr();
  29. int tgetnum();
  30. bool tgetflag();
  31. #endif /* DO_TERMCAP */
  32.  
  33. static void charbinding(), tcbinding(), setbinding();
  34.  
  35. /* Get key definitions from tty settings. */
  36.  
  37. void
  38. getttykeydefs(fd)
  39.     int fd;
  40. {
  41. #ifdef unix
  42. #ifdef DO_SGTTY
  43.     struct sgttyb gttybuf;
  44.     struct tchars tcharbuf;
  45. #endif
  46. #ifdef TERMIO
  47.     struct termio tio;
  48. #endif
  49.  
  50.     copydefaults();
  51.     
  52. #ifdef DO_SGTTY
  53.     gtty(fd, >tybuf);
  54.     charbinding(SHORTCUT, 0, FIRST_CMD+WC_BACKSPACE,(int)gttybuf.sg_erase);
  55.     
  56.     ioctl(fd, TIOCGETC, (char *) &tcharbuf);
  57.     charbinding(SHORTCUT, 0, FIRST_CMD+WC_CANCEL, (int)tcharbuf.t_intrc);
  58. #endif
  59. #ifdef TERMIO
  60.     ioctl(fd, TCGETA, &tio);
  61.     charbinding(SHORTCUT, 0, FIRST_CMD+WC_BACKSPACE, (int)tio.c_cc[2]);
  62.     charbinding(SHORTCUT, 0, FIRST_CMD+WC_CANCEL, (int)tio.c_cc[0]);
  63. #endif
  64.  
  65. #ifdef TIOCGLTC
  66.     {
  67.         struct ltchars ltcharbuf;
  68.         
  69.         ioctl(fd, TIOCGLTC, (char *) <charbuf);
  70.         charbinding(SHORTCUT, 0, SUSPEND_PROC, ltcharbuf.t_suspc);
  71.         charbinding(SHORTCUT, 0, REDRAW_SCREEN, ltcharbuf.t_rprntc);
  72.         charbinding(SHORTCUT, 0, LITERAL_NEXT, ltcharbuf.t_lnextc);
  73.     }
  74. #endif /* TIOCGLTC */
  75. #endif /* unix */
  76. }
  77.  
  78. #ifdef unix
  79. static void
  80. charbinding(type, id, item, key)
  81.     int type;
  82.     int id, item;
  83.     int key;
  84. {
  85.     if (key != 0 && (key&0xff) != 0xff) {
  86.         char keys[2];
  87.         keys[0]= key;
  88.         keys[1]= EOS;
  89.         setbinding(&_wprimap[*keys & 0xff], type, id, item, keys);
  90.     }
  91. }
  92. #endif /* unix */
  93.  
  94. /* Get key definitions from termcap. */
  95.  
  96. void
  97. gettckeydefs()
  98. {
  99. #ifdef DO_TERMCAP
  100.     copydefaults();
  101.     tcbinding(SHORTCUT, 0, FIRST_CMD+WC_BACKSPACE,    "kb");
  102.     tcbinding(SHORTCUT, 0, FIRST_CMD+WC_LEFT,    "kl");
  103.     tcbinding(SHORTCUT, 0, FIRST_CMD+WC_RIGHT,    "kr");
  104.     tcbinding(SHORTCUT, 0, FIRST_CMD+WC_UP,        "ku");
  105.     tcbinding(SHORTCUT, 0, FIRST_CMD+WC_DOWN,    "kd");
  106.     /*
  107.     tcbinding(SHORTCUT, 0, FIRST_CMD+WC_CLEAR,    "kC");
  108.     tcbinding(SHORTCUT, 0, FIRST_CMD+WC_HOME,    "kh");
  109.     tcbinding(SHORTCUT, 0, FIRST_CMD+WC_HOME_DOWN,    "kH");
  110.     */
  111. #endif /* DO_TERMCAP */
  112. }
  113.  
  114. #ifdef DO_TERMCAP
  115. static void
  116. tcbinding(type, id, item, capname)
  117.     int type;
  118.     int id, item;
  119.     char capname[2];    /* Termcap capability name, e.g. "k1" */
  120. {
  121.     char buf[100];
  122.     char *p= buf;
  123.     char *keys;
  124.     
  125.     keys= tgetstr(capname, &p);
  126.     if (keys != NULL)
  127.         setbinding(&_wprimap[*keys & 0xff], type, id, item, keys);
  128. }
  129. #endif /* DO_TERMCAP */
  130.  
  131. /* Bind a menu item to a meta-key.
  132.    As there are no meta-keys on standard Unix,
  133.    this is translated to ESC-key. */
  134.  
  135. void
  136. wsetmetakey(id, item, key)
  137.     int id, item;
  138.     int key;
  139. {
  140.     char buf[3];
  141.     
  142.     buf[0]= '\033'; /* ESC */
  143.     buf[1]= key;
  144.     buf[2]= EOS;
  145.     wsetshortcut(id, item, buf);
  146. }
  147.  
  148. /* Bind a menu item to a key sequence.
  149.    Note that this call is not part of the universal STDWIN interface,
  150.    only of the Unix interface for ASCII terminals. */
  151.  
  152. void
  153. wsetshortcut(id, item, keys)
  154.     int id, item;
  155.     char *keys;
  156. {
  157.     if (keys == NULL || *keys == EOS)
  158.         return; /* Can't bind empty string */
  159.     copydefaults();
  160.     setbinding(&_wprimap[*keys & 0xff], SHORTCUT, id, item, keys);
  161. }
  162.  
  163. static struct keymap *extendmap();
  164.  
  165. static int
  166. mapsize(map)
  167.     struct keymap *map;
  168. {
  169.     int size;
  170.     
  171.     if (map == NULL)
  172.         return 0;
  173.     for (size= 0; map[size].type != SENTINEL; ++size)
  174.         ;
  175.     return size+1;
  176. }
  177.  
  178. static void
  179. setbinding(map, type, id, item, keys)
  180.     struct keymap *map;
  181.     int type;
  182.     int id, item;
  183.     char *keys;
  184. {
  185.     if (keys[1] == EOS) {
  186.         map->key= *keys;
  187.         map->type= type;
  188.         map->id= id;
  189.         map->item= item;
  190.     }
  191.     else {
  192.         struct keymap *nmap;
  193.         if (map->type != SECONDARY) {
  194.             map->type= SECONDARY;
  195.             map->id= createmap();
  196.         }
  197.         for (nmap= _wsecmap[map->id];
  198.             nmap->type != SENTINEL; ++nmap) {
  199.             if (nmap->key == keys[1])
  200.                 break;
  201.         }
  202.         if (nmap->type == SENTINEL)
  203.             nmap= extendmap((int) map->id, (int) keys[1]);
  204.         if (nmap != NULL)
  205.             setbinding(nmap, type, id, item, keys+1);
  206.     }
  207. }
  208.  
  209. static struct keymap *
  210. extendmap(imap, c)
  211.     int imap;
  212.     int c;
  213. {
  214.     L_DECLARE(size, map, struct keymap);
  215.     
  216.     if (imap == 0 || imap >= SECMAPSIZE || (map= _wsecmap[imap]) == NULL)
  217.         return NULL;
  218.     size= mapsize(map);
  219.     L_EXTEND(size, map, struct keymap, 1);
  220.     _wsecmap[imap]= map;
  221.     if (map == NULL)
  222.         return NULL;
  223.     map += size - 2;
  224.     map->type= ORDINARY;
  225.     map->key= c;
  226.     map[1].type= SENTINEL;
  227.     return map;
  228. }
  229.  
  230. static int
  231. createmap()
  232. {
  233.     L_DECLARE(size, map, struct keymap);
  234.     int i;
  235.     
  236.     L_EXTEND(size, map, struct keymap, 1);
  237.     if (map == NULL)
  238.         return 0;
  239.     map->type= SENTINEL;
  240.     for (i= 0; i < SECMAPSIZE && _wsecmap[i] != NULL; ++i)
  241.         ;
  242.     if (i >= SECMAPSIZE) { /* Overflow of _wsecmap array */
  243.         L_DEALLOC(size, map);
  244.         return 0;
  245.     }
  246.     else {
  247.         _wsecmap[i]= map;
  248.         return i;
  249.     }
  250. }
  251.  
  252. /* Copy existing secondary key maps to dynamic memory.
  253.    Note: don't copy map 0, which is a dummy to force a dead-end street. */
  254.  
  255. static
  256. copydefaults()
  257. {
  258.     static bool been_here= FALSE;
  259.     int i;
  260.     struct keymap *map;
  261.     
  262.     if (been_here)
  263.         return;
  264.     been_here= TRUE;
  265.     
  266.     for (i= 1; i < SECMAPSIZE; ++i) {
  267.         map= _wsecmap[i];
  268.         if (map != NULL) {
  269.             int size= mapsize(map);
  270.             struct keymap *nmap;
  271.             int k;
  272.             nmap= (struct keymap *) malloc(
  273.                 (unsigned) (size * sizeof(struct keymap)));
  274.             if (nmap != NULL) {
  275.                 for (k= 0; k < size; ++k)
  276.                     nmap[k]= map[k];
  277.             }
  278.             _wsecmap[i]= nmap;
  279.         }
  280.     }
  281. }
  282.  
  283. /* Routines to get a nice description of a menu item's shortcuts.
  284.    TO DO: protect against buffer overflow; cache output so it
  285.    isn't called so often (i.e., twice for each drawitem call!). */
  286.  
  287. static char *
  288. charrepr(c)
  289.     int c;
  290. {
  291.     static char repr[10];
  292.  
  293.     switch (c) {
  294.  
  295.     case 033:
  296.         return "ESC";
  297.     
  298.     case '\r':
  299.         return "CR";
  300.     
  301.     case '\b':
  302.         return "BS";
  303.     
  304.     case '\t':
  305.         return "TAB";
  306.     
  307.     case 0177:
  308.         return "DEL";
  309.  
  310.     default:
  311.         if (c < ' ') {
  312.             repr[0]= '^';
  313.             repr[1]= c|'@';
  314.             repr[2]= '\0';
  315.         }
  316.         else if (c < 0177) {
  317.             repr[0]= c;
  318.             repr[1]= '\0';
  319.         }
  320.         else {
  321.             repr[0]= '\\';
  322.             repr[1]= '0' + (c>>6);
  323.             repr[2]= '0' + ((c>>3) & 07);
  324.             repr[3]= '0' + (c & 07);
  325.             repr[4]= '\0';
  326.         }
  327.         return repr;
  328.  
  329.     }
  330. }
  331.  
  332. static char *
  333. addrepr(cp, c)
  334.     char *cp;
  335.     int c;
  336. {
  337.     char *rp= charrepr(c);
  338.     
  339.     while (*rp != '\0')
  340.         *cp++ = *rp++;
  341.     return cp;
  342. }
  343.  
  344. static char *
  345. followmap(cp, map, id, item, stack, level)
  346.     char *cp;
  347.     struct keymap *map;
  348.     int id, item;
  349.     unsigned char *stack;
  350.     int level;
  351. {
  352.     if (map->type == SHORTCUT) {
  353.         if (map->id == id && map->item == item) {
  354.             int i;
  355.             for (i= 0; i < level; ++i) {
  356.                 cp= addrepr(cp, (int) stack[i]);
  357.                 *cp++ = '-';
  358.             }
  359.             cp= addrepr(cp, (int) map->key);
  360.             *cp++ = ',';
  361.             *cp++ = ' ';
  362.         }
  363.     }
  364.     else if (map->type == SECONDARY) {
  365.         stack[level]= map->key;
  366.         map= _wsecmap[map->id];
  367.         for (; map->type != SENTINEL; ++map)
  368.             cp= followmap(cp, map, id, item, stack, level+1);
  369.     }
  370.     return cp;
  371. }
  372.  
  373. void
  374. getbindings(buf, id, item)
  375.     char *buf;
  376.     int id;
  377.     int item;
  378. {
  379.     char *cp= buf;
  380.     unsigned char stack[50];
  381.     struct keymap *map;
  382.     
  383.     for (map= _wprimap; map < &_wprimap[256]; ++map)
  384.         cp= followmap(cp, map, id, item, stack, 0);
  385.     if (cp > buf)
  386.         cp -= 2;
  387.     *cp= EOS;
  388. }
  389.