home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / Samples / CSAPE32.ARJ / SOURCE / OWLSCR / KBMACRO.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-07  |  13.6 KB  |  590 lines

  1. /*
  2.       kbmacro.c
  3.  
  4.     % kb_Macro        keystroke macro recorder.
  5.  
  6.     OWL 1.2
  7.     Copyright (c) 1990 by Oakland Group, Inc.
  8.     ALL RIGHTS RESERVED.
  9.  
  10.     Revision History:
  11.     -----------------
  12.      8/23/90 jdc    fixed *indexp++ and warnings
  13.      8/29/90 jdc    ifdef'ed out mouse support, added msg_fptr
  14.      9/07/90 jmd    changed index to indeks to avoid conflicts
  15.      9/09/90 jmd    made do_macmsg macro
  16.     10/28/90 jdc    fixed boolean/int ret conflict
  17.     10/30/90 jdc    allowed original value 'bleed through' for looped macros
  18.     12/07/90 jmd    changed local variable 'keyindex' to keyindex to avoid
  19.                     conflict with array of the same name
  20. */
  21.  
  22. #include "oakhead.h"
  23. #include "disppriv.h"
  24.  
  25. #include "scancode.h"
  26. #include "kbrecord.h"
  27.  
  28. #include <ctype.h>
  29.  
  30. OSTATIC int        krec_Check(unsigned wait);
  31. OSTATIC int        krec_Read(moupos_struct *mposp);
  32. OSTATIC boolean key_mousecheck(int keyind, int *indexp, moupos_struct *mposp);
  33. OSTATIC int     key_FindKeyS(int key);
  34. OSTATIC int     key_FindNameS(char *name);
  35.  
  36. #define            KBMACRO_MAXNEST        22
  37.  
  38. /** static data **/
  39.  
  40. static boolean    macron        = FALSE;    /* macros on or off */
  41. static int        macmode        = KB_MACRO;    /* mode value */
  42. static int        learnkey     = FN5;        /* key to begin/end learning */
  43. static int        learnindex     = 0;        /* index of current key learning */
  44.  
  45. static int        nest        = -1;                /* macro nest level */
  46. static int        keyindex[KBMACRO_MAXNEST+2];    /* index into kb_keylist */
  47. static int        indeks[KBMACRO_MAXNEST+2];    /* index for into macro iarray */
  48.  
  49. static dig_hReadEvent_func    ((*hReadEventFptr)) = FNULL;
  50. static dig_hCheckEvent_func    ((*hCheckEventFptr)) = FNULL;
  51. static macromsg_fptr        msgfptr = FNULL;
  52.  
  53. #define do_macmsg(m, k)        ((msgfptr == FNULL) ? TRUE : msgfptr(m, k))
  54. /* -------------------------------------------------------------------------- */
  55.  
  56. boolean kb_Macro(int mode, int key, moupos_struct *mposp, macromsg_fptr macromsg)
  57. /*
  58.     Operates a key mapped macro handler.
  59.  
  60.     'mode' determines the operating mode, 'key' is a scancode.
  61.     it is also passed as a message to the msgfptr.
  62.  
  63.     KB_MACRO        initialize for macro use.                learnkey = key;
  64.  
  65.     KB_MACKEY        set for learning, set currkey.            currkey  = key;
  66.     KB_MACLEARN        add a keystroke to the currkey macro.    mackey      = key;
  67.     KB_MACSTOP        finish learning keystrokes.
  68.  
  69.     KB_MACOFF        restore previous keystroke processing.
  70.     KB_MACCLEAR        clear a macro.                            currkey     = key;
  71.     KB_MACRESET        clear all macros.
  72.  
  73.     KB_MACSTART        msg for macro message function from krec_Read.
  74.  
  75.     if 0 is passed as the learnkey then it remains unchanged.
  76.  
  77.     if size == -1 (see kb_keylist in kblist.c) then no macro is allowed
  78.     for that key.
  79. */
  80. {
  81.     int i;
  82.     boolean ret = TRUE;
  83.  
  84.     owl_Assert(disp_Ok(), OE_KR_DISP);
  85.  
  86.     if (mode == KB_MACPLAY || mode == KB_MACSTOP) {
  87.         ret = do_macmsg(mode, key);
  88.     }
  89.     else if (mode == KB_MACOFF) {
  90.         if (macron == TRUE && (ret = do_macmsg(mode, key)) == TRUE) {
  91.  
  92.             macron = FALSE;
  93.             macmode = KB_MACOFF;
  94.  
  95.             /* restore keybord handler */
  96.             curr_dmgr->disp.dig.hReadEvent = hReadEventFptr;
  97.             curr_dmgr->disp.dig.hCheckEvent = hCheckEventFptr;
  98.         }
  99.         return(ret);
  100.     }
  101.     else if (mode == KB_MACRESET) {
  102.  
  103.         if (!do_macmsg(mode, key)) {
  104.             return(FALSE);
  105.         }
  106.         for (i = 0; kb_keylist[i].scan != 0; i++) {
  107.  
  108.             if (kb_keylist[i].macro != NULL) {
  109.                 ia_Close(kb_keylist[i].macro);
  110.                 kb_keylist[i].macro = NULL;
  111.                 kb_keylist[i].size = 0;
  112.             }
  113.         }
  114.         macmode = (macron) ? KB_MACRO:KB_MACOFF;
  115.         return(TRUE);
  116.     }            
  117.     else if (mode == KB_MACCLEAR) {
  118.  
  119.         if ((i = key_FindKeyS(key)) != 0 && kb_keylist[i].macro != NULL
  120.         && (ret = do_macmsg(mode, key)) == TRUE) {
  121.             ia_Close(kb_keylist[i].macro);
  122.             kb_keylist[i].macro = NULL;
  123.             kb_keylist[i].size = 0;
  124.         }
  125.         return(ret);
  126.     }
  127.     else if (macron == FALSE) {
  128.  
  129.         if (!do_macmsg(KB_MACRO, key)) {
  130.             return(FALSE);
  131.         }
  132.         macron = TRUE;
  133.  
  134.         /* save old keyboard handler */
  135.         hReadEventFptr = curr_dmgr->disp.dig.hReadEvent;
  136.         hCheckEventFptr = curr_dmgr->disp.dig.hCheckEvent;
  137.  
  138.         /* set new keyboard handler */
  139.         curr_dmgr->disp.dig.hReadEvent = krec_Read;
  140.         curr_dmgr->disp.dig.hCheckEvent = krec_Check;
  141.     }
  142.     macmode = KB_MACRO;
  143.  
  144.     if (mode == KB_MACRO) {
  145.  
  146.         if (key != 0) {
  147.             learnkey = key;
  148.         }
  149.         msgfptr = macromsg;
  150.     }
  151.     else if (mode == KB_MACSTART) {
  152.         if (do_macmsg(KB_MACSTART, key)) {
  153.             macmode = KB_MACKEY;
  154.         }
  155.     }
  156.     else if (mode == KB_MACLEARN) {
  157.  
  158.         if (kb_keylist[learnindex].scan == 0         /* not in keylist */
  159.         || (kb_keylist[learnindex]).size == -1        /* no macro allowed */
  160.         || !do_macmsg(KB_MACLEARN, key)) {
  161.             return(FALSE);
  162.         }
  163.  
  164.         ia_Put((kb_keylist[learnindex]).macro, (kb_keylist[learnindex]).size, key);
  165.         (kb_keylist[learnindex]).size++;
  166.  
  167. #ifdef MOUSE_MACROS
  168.         if (key == HARD_MEV) {
  169.             ia_Put((kb_keylist[learnindex]).macro, (kb_keylist[learnindex]).size, mposp->x);
  170.             (kb_keylist[learnindex]).size++;
  171.             ia_Put((kb_keylist[learnindex]).macro, (kb_keylist[learnindex]).size, mposp->y);
  172.             (kb_keylist[learnindex]).size++;
  173.             ia_Put((kb_keylist[learnindex]).macro, (kb_keylist[learnindex]).size, mposp->event);
  174.             (kb_keylist[learnindex]).size++;
  175.         }
  176. #else
  177.     oak_notused(mposp);
  178. #endif
  179.         macmode = KB_MACLEARN;
  180.     }
  181.     else if (mode == KB_MACKEY) {
  182.  
  183.         learnindex = key_FindKeyS(key);
  184.  
  185.         if (kb_keylist[learnindex].scan == 0        /* not in keylist */
  186.         || (kb_keylist[learnindex]).size == -1        /* no macro allowed */
  187.         || !do_macmsg(KB_MACKEY, key)) {
  188.             return(FALSE);
  189.         }
  190.  
  191.         (kb_keylist[learnindex]).size = 0;
  192.  
  193.         if ((kb_keylist[learnindex]).macro == NULL
  194.         && ((kb_keylist[learnindex]).macro = ia_Open(1)) == NULL) {
  195.             return(FALSE);
  196.         }
  197.         macmode = KB_MACLEARN;
  198.     }
  199.  
  200.     return(ret);
  201. }
  202.  
  203. int key_GetCurrKey(void)
  204. /*
  205.     return the currkey (current learning key).
  206.  
  207.     returns KEY_NONE if no learning key.
  208. */
  209. {
  210.     if (macmode == KB_MACOFF || kb_keylist[learnindex].scan == 0) {
  211.         return(KEY_NONE);
  212.     }
  213.  
  214.     return(kb_keylist[learnindex].scan);
  215. }
  216.  
  217. int    key_GetLearnKey(void)
  218. /*
  219.     return the key that toggles macro learning.
  220. */
  221. {
  222.     return(learnkey);
  223. }
  224.  
  225. int key_GetMode(void)
  226. /*
  227.     return the current mode value.
  228. */
  229. {
  230.     return(macmode);
  231. }
  232.  
  233. char *key_GetName(int key)
  234. /*
  235.     return name of 'key'
  236. */
  237. {
  238.     char *name;
  239.  
  240.     name = kb_keylist[key_FindKeyS(key)].name;
  241.  
  242.     return((*name == '\0') ? NULL : name);
  243. }
  244.  
  245. boolean key_IsMacro(int key)
  246. /*
  247.     returns:     TRUE if key has a macro and mode != KB_MACOFF
  248.                 FALSE otherwise
  249. */
  250. {
  251.     return((macmode != KB_MACOFF && kb_keylist[key_FindKeyS(key)].size > 0)
  252.         ? TRUE : FALSE);
  253. }
  254.  
  255. boolean key_SetMacroStr(char *str)
  256. /*    
  257.     set a macro from the macro string 'str'.
  258.  
  259.     format: "{currkey}:{mackey1}abc def{mackey2}{mackey3}..."
  260.  
  261.     returns: FALSE if 'str' is not valid, TRUE if sucessful.
  262. */
  263. {
  264.     int key, i, j, k, numcount, commacount;
  265.     char buff[KB_NAME_MAXLEN + 2];
  266.     moupos_struct mpos;
  267.  
  268.     /* find the currkey name; {name}: */
  269.  
  270.     if (*str != '{') {
  271.         return(FALSE);
  272.     }
  273.     str++;                /* allow for opening brace */
  274.  
  275.     /* copy the currkey into buff, find the closing brace */
  276.     for (i = 0; str[i] != '}'; i++) {
  277.         if (i > KB_NAME_MAXLEN || str[i] == '\0') return(FALSE);
  278.         buff[i] = str[i];
  279.     }
  280.     buff[i] = '\0';
  281.         
  282.     /* set the currkey */
  283.     if ((key = kb_keylist[key_FindNameS(buff)].scan) == 0
  284.     || !kb_Macro(KB_MACKEY, key, &mpos, FNULL)) {
  285.  
  286.         return(FALSE);
  287.     }
  288.  
  289.     i += 2;        /* move past the colon */
  290.     do {
  291.         /* skip newlines, find the opening brace or printable character */
  292.         for ( ; str[i] == '\n'; i++) ;
  293.  
  294.         if (str[i] == '\0') break;            /* done */
  295.  
  296.         if (str[i] == '{') {
  297.  
  298.             /* move past opening brace */
  299.             i++;
  300.  
  301.             if (str[i] == '{') {
  302.  
  303.                 /* opening braces are in braces */
  304.                 for ( ; str[i] == '{'; i++) {
  305.                     key = (int)str[i];
  306.                 }
  307.             }
  308.             else {
  309.                 /* copy the key name into buff, find the closing brace */
  310.                 /* deal with mouse case */
  311.                 for (j = 0, numcount = 0, commacount = 0, k = -1;
  312.                  str[i] != '}'; j++, i++) {
  313.  
  314.                     if (j > KB_NAME_MAXLEN || str[i] == '\0') return(FALSE);
  315.                     buff[j] = str[i];
  316.  
  317.                     if (isdigit(str[i]) && numcount == commacount) {
  318.                         numcount++;
  319.                         if (k == -1) k = j;
  320.                     }
  321.                     else if (str[i] == ',' && commacount == numcount - 1) {
  322.                         commacount++;
  323.                     }
  324.                 }
  325.                 buff[j] = '\0';
  326.                 if (numcount == 3 && commacount == 2) {
  327.                     sscanf(buff + k, "%d,%d,%u", &(mpos.x), &(mpos.y), &(mpos.event));
  328.                     buff[k] = '\0';
  329.                 }
  330.  
  331.                 if ((key = kb_keylist[key_FindNameS(buff)].scan) == 0) {
  332.                     return(FALSE);
  333.                 }
  334.             }
  335.             i++;     /* move past the closing brace */
  336.         }
  337.         else {
  338.             key = (int)str[i];
  339.             i++;
  340.         }
  341.         kb_Macro(KB_MACLEARN, key, &mpos, FNULL);
  342.  
  343.     } while (str[i] != '\0');
  344.  
  345.     kb_Macro(KB_MACSTOP, 0, &mpos, FNULL);
  346.     return(TRUE);
  347. }
  348.  
  349. boolean key_GetMacroStr(int key, char *str)
  350. /*    
  351.     fill 'str' with the macro string for 'key'.
  352.  
  353.     format: "{currkey}:{mackey1}abc def{mackey2}{mackey3}..."
  354.  
  355.     returns: FALSE if 'key' has no macro, TRUE otherwise.
  356. */
  357. {
  358.     int i, indeks;
  359.     char *s, *keyname;
  360.  
  361.     *str = '\0';
  362.  
  363.     if (kb_keylist[(indeks = key_FindKeyS(key))].scan == 0
  364.     || kb_keylist[indeks].size <= 0) {
  365.         return(FALSE);                        /* no macro */
  366.     }
  367.     *str++ = '{';
  368.     for (s = kb_keylist[indeks].name; *s != '\0'; s++, str++) {
  369.         *str = *s;
  370.     }
  371.     *str++ = '}';
  372.     *str++ = ':';
  373.  
  374.     for (i = 0; i < kb_keylist[indeks].size; ) {
  375.  
  376.         key = ia_Get(kb_keylist[indeks].macro, i);
  377.  
  378.         if (key == '{') {            /* opening braces are in braces */
  379.             *str++ = '{';
  380.  
  381.             do {
  382.                 *str++ = '{';
  383.                 i++;
  384.             } while (ia_Get(kb_keylist[indeks].macro, i) == '{');
  385.  
  386.             *str++ = '}';
  387.         }
  388.         else if (*(keyname = kb_keylist[key_FindKeyS(key)].name) == '\0') {
  389.             *str++ = (char)key;
  390.             i++;
  391.         }
  392.         else {        
  393.             *str++ = '{';
  394.             for (s = keyname; *s != '\0'; s++) {
  395.                 *str++ = *s;
  396.             }
  397.  
  398. #ifdef MOUSE_MACROS
  399.             if (key == HARD_MEV) {
  400.                 sprintf(str, "%d,%d,%u", 
  401.                     ia_Get(kb_keylist[indeks].macro, i + 1),
  402.                     ia_Get(kb_keylist[indeks].macro, i + 2),
  403.                     ia_Get(kb_keylist[indeks].macro, i + 3));
  404.                 i += 3;
  405.                 str += strlen(str);
  406.             }
  407. #endif
  408.             *str++ = '}';
  409.             i++;
  410.         }
  411.     }
  412.     *str = '\0';
  413.  
  414.     return(TRUE);
  415. }
  416.  
  417. /* -------------------------------------------------------------------------- */
  418.  
  419. static int krec_Check(unsigned wait)
  420. /*
  421.     Substitute kb_Check handler
  422.  
  423.     returns TRUE if in a multi keystroke macro 
  424.     or the original check function return.
  425. */
  426. {
  427.     return(nest >= 0 || (*hCheckEventFptr)(wait));
  428. }
  429.  
  430. static int krec_Read(moupos_struct *mposp)
  431. /*
  432.     effects:    reads next key from keyboard buffer.
  433.     returns:    ASCII value of character in bits 0-7,
  434.                 and the scan code of the character in
  435.                 bits 8-15.
  436.  
  437.     see kb_Macro().
  438. */
  439. {
  440.     int    scancode, scan1;
  441.  
  442.     if (nest >= 0) {            /* in a multi-keystroke macro */
  443.  
  444.         if (indeks[nest] >= kb_keylist[keyindex[nest]].size) {
  445.  
  446.             if (--nest >= 0) {
  447.                 indeks[nest]++;
  448.             }
  449.         }
  450.  
  451.         if (nest >= 0) {
  452.  
  453.             scancode = ia_Get((kb_keylist[keyindex[nest]]).macro, indeks[nest]);
  454.             if (++nest > KBMACRO_MAXNEST) {
  455.                 do_macmsg(KB_MAXNEST, scancode);
  456.                 nest = -1;
  457.                 return(KEY_NONE);
  458.             }
  459.             keyindex[nest] = key_FindKeyS(scancode);
  460.  
  461.             while (keyindex[nest] != keyindex[nest -1] && (kb_keylist[keyindex[nest]]).size > 0) {
  462.  
  463.                 indeks[nest] = 0;
  464.                 scancode = ia_Get((kb_keylist[keyindex[nest]]).macro, indeks[nest]);
  465.                 if (++nest > KBMACRO_MAXNEST) {
  466.                     do_macmsg(KB_MAXNEST, scancode);
  467.                     nest = -1;
  468.                     return(KEY_NONE);
  469.                 }
  470.                 if ((keyindex[nest] = key_FindKeyS(scancode)) == keyindex[nest -1]) {
  471.                     break;
  472.                 }
  473.             }
  474.             nest--;
  475.  
  476.             key_mousecheck(keyindex[nest], &(indeks[nest]), mposp);
  477.             indeks[nest]++;
  478.  
  479.             return(scancode);
  480.         }
  481.     }
  482.  
  483.     scan1 = scancode = (*hReadEventFptr)(mposp);/* read a raw keystroke */
  484.  
  485.     if (scancode == learnkey) {            /* toggle learn mode */
  486.         if (macmode == KB_MACRO) {
  487.             kb_Macro(KB_MACSTART, scancode, mposp, FNULL);
  488.         }
  489.         else {
  490.             kb_Macro(KB_MACSTOP, scancode, mposp, FNULL);
  491.         }
  492.     }
  493.     else if (macmode == KB_MACKEY) {    /* key to learn for */
  494.         kb_Macro(KB_MACKEY, scancode, mposp, FNULL);
  495.     }
  496.     else if (macron) {                    /* begin macro playback */
  497.  
  498.         if (macmode == KB_MACLEARN) {
  499.             kb_Macro(KB_MACLEARN, scancode, mposp, FNULL);
  500.         }
  501.         else if (!kb_Macro(KB_MACPLAY, scancode, mposp, FNULL)) {
  502.             return(scancode);
  503.         }
  504.  
  505.         nest = 0;
  506.         keyindex[nest] = key_FindKeyS(scancode);
  507.  
  508.         if ((kb_keylist[keyindex[nest]]).size <= 0) {
  509.             nest = -1;
  510.         }
  511.         else {
  512.             while ((kb_keylist[keyindex[nest]]).size > 0) {
  513.  
  514.                 indeks[nest] = 0;
  515.                 scancode = ia_Get((kb_keylist[keyindex[nest]]).macro, indeks[nest]);
  516.                 if (++nest > KBMACRO_MAXNEST) {
  517.                     do_macmsg(KB_MAXNEST, scancode);
  518.                     nest = -1;
  519.                     return(scan1);
  520.                 }
  521.                 if ((keyindex[nest] = key_FindKeyS(scancode)) == keyindex[nest -1]) {
  522.                     break;
  523.                 }
  524.             }
  525.             nest--;
  526.  
  527.             key_mousecheck(keyindex[nest], &(indeks[nest]), mposp);
  528.             indeks[nest]++;
  529.         }
  530.     }
  531.  
  532.     return(scancode);
  533. }
  534.  
  535. static boolean key_mousecheck(int keyind, int *indexp, moupos_struct *mposp)
  536. {
  537.     boolean ret = FALSE;
  538.  
  539. #ifdef MOUSE_MACROS
  540.     if (kb_keylist[keyind].scan == HARD_MEV) {
  541.         (*indexp)++;
  542.         mposp->x = ia_Get((kb_keylist[keyind]).macro, *indexp);
  543.         (*indexp)++;
  544.         mposp->y = ia_Get((kb_keylist[keyind]).macro, *indexp);
  545.         (*indexp)++;
  546.         mposp->event = ia_Get((kb_keylist[keyind]).macro, *indexp);
  547.  
  548.         ret = TRUE;
  549.     }
  550. #else
  551.     oak_notused(mposp);
  552.     oak_notused(keyind);
  553.     oak_notused(indexp);
  554. #endif
  555.  
  556.     return(ret);
  557. }
  558.  
  559. static int key_FindKeyS(int key)
  560. /*
  561.     Given a key value find its key_struct index.
  562. */
  563. {
  564.     int i;
  565.     
  566.     for (i = 0; kb_keylist[i].scan != 0; i++) {
  567.         if (kb_keylist[i].scan == key) {
  568.             break;
  569.         }
  570.     }
  571.  
  572.     return(i);
  573. }
  574.  
  575. static int key_FindNameS(char *name)
  576. /*
  577.     Given a key name find the key_struct index.
  578. */
  579. {
  580.     int i;
  581.     
  582.     for (i = 0; kb_keylist[i].scan != 0; i++) {
  583.         if (strcmp(kb_keylist[i].name, name) == 0) {
  584.             break;
  585.         }
  586.     }
  587.  
  588.     return(i);
  589. }
  590.