home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / games / gi / kbd.c < prev    next >
C/C++ Source or Header  |  1993-11-07  |  16KB  |  494 lines

  1. /*--------------------------------------------------------------------------*/
  2. /*                                                                          */
  3. /*   Main-Module   : Keyboard-Interface mit Game-Support & Self-Config      */
  4. /*                                                                          */
  5. /*   Version       : V1.00                                                  */
  6. /*                                                                          */
  7. /*   Date          : 23.04.93                                               */
  8. /*                                                                          */
  9. /*   Written       : RF                                                     */
  10. /*                                                                          */
  11. /*     Revision History :
  12.  
  13.     28.04.93    RF  ConfigKey fein-finish
  14.     10.05.93    RF  PreCompiled-Headers, os2.h wird vom Modul geholt
  15.     12.05.93    RF  Threshold wird richtig berechnet...
  16.     14.05.93    RF  exportierte Funktionen haben C-Calling conventions
  17.     15.05.93    RF  Init-Konzept überarbeitet
  18.     13.07.93 RF+MH  Monitor works OK !!
  19.     11.08.93 RF+MH  Konvertier-Tabelle Mon-Scan->PM-Scan implementiert
  20.     12.08.93    RF  Tasten werden vom KBD-Mon weitergegeben. Appl. muss sie
  21.                     abfackeln!
  22.     29.10.93    RF    kbd.h wird nicht mehr importiert
  23.                                                                             */
  24. /*--------------------------------------------------------------------------*/
  25. #define INCL_WINHOOKS
  26. #define INCL_DOSPROCESS
  27. #define INCL_PM
  28. #include <os2.h>
  29. #pragma hdrstop
  30.  
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <stddef.h>
  34. #include <mem.h>
  35. #include <string.h>
  36. #include <gi.h>
  37. #include <checkbox.hpp>
  38. #include <listbox.hpp>
  39. #include <slider.hpp>
  40. #include <kbdconv.h>
  41.  
  42. #define MAXSTATUS   50
  43. #define STDNUMDIR   6           // Up, Right, Down, Left, B1, B2
  44. #define DEFNAME     "kbd.cfg"
  45. #define MAXSCANCODE 110
  46.  
  47. #define ORD_DOSMONOPEN      4
  48. #define ORD_DOSMONCLOSE     3
  49. #define ORD_DOSMONREG       5
  50. #define ORD_DOSMONREAD      2
  51. #define ORD_DOSMONWRITE     1
  52. #define DosMonOpen      Dos16MonOpen
  53. #define DosMonClose     Dos16MonClose
  54. #define DosMonReg       Dos16MonReg
  55. #define DosMonRead      Dos16MonRead
  56. #define DosMonWrite     Dos16MonWrite
  57. #define DosGetInfoSeg   Dos16GetInfoSeg
  58.  
  59. /*--------------------------------------------------------------------------*/
  60. extern "C" {
  61. APIRET16 APIENTRY16 DosMonOpen  (PCHAR16 name, PUSHORT16 phand);
  62. APIRET16 APIENTRY16 DosMonClose (USHORT hand);
  63. APIRET16 APIENTRY16 DosMonReg   (USHORT hand, PUCHAR16 in, PUCHAR16 out, USHORT pos, USHORT group);
  64. APIRET16 APIENTRY16 DosMonRead  (PUCHAR16 in, USHORT wait, PUCHAR16 data, PUSHORT16 cnt);
  65. APIRET16 APIENTRY16 DosMonWrite (PUCHAR16 out, PUCHAR16 data, USHORT cnt);
  66. APIRET16 APIENTRY16 DosGetInfoSeg (PUSHORT16 iseg, PUSHORT16 lseg);
  67. }
  68. /*--------------------------------------------------------------------------*/
  69. //typedef struct _CHARMSG KEYSTRUCT;
  70.  
  71. struct KP {
  72.         USHORT          flags;
  73.         char            ascii;
  74.         unsigned char   scan;
  75.         char            foo[8];
  76.         USHORT          ddflags;
  77.         };
  78.  
  79. typedef struct
  80.         {
  81.         BOOL            init;
  82.         unsigned        numdir;
  83.         unsigned        threshold;
  84.         unsigned        scan[STDNUMDIR], flags[STDNUMDIR];
  85.         } KBDCONFIG, *KBDCONFIGP;
  86. /*--------------------------------------------------------------------------*/
  87. HMODULE     module;
  88. BOOL        inconfig=FALSE;
  89. char        statustext[3][MAXSTATUS];
  90. char        keytext[MAXSTATUS];
  91. char        scankey[15], nonetext[15];
  92. HWND        wid[8], but_ok, but_cancel;
  93. SLIDER      slider;
  94. LISTBOX     lb;
  95. char        *dirname[] = { "", "  Up", "  Right", "  Down", "  Left", "  Button 1",
  96.                                 "  Button 2" };
  97. unsigned    mode;
  98. BOOL        k[MAXSCANCODE];     // Aktuell gedrückte Tasten
  99. unsigned    flags=0;    // Aktuell gedrückte Sonder-Tasten
  100. unsigned    cscan, cflags;
  101. TID         monid;
  102. KBDCONFIGP  kc;
  103.  
  104. /*--------------------------------------------------------------------------*/
  105. extern "C" {
  106. ULONG _dllmain (ULONG termflag, HMODULE modhandle)
  107.     {
  108.     if (!termflag)  // Init...
  109.         module = modhandle;
  110.  
  111.     return (TRUE);
  112.     }
  113. }
  114. /*--------------------------------------------------------------------------*/
  115. USHORT getcurgroup (void)  // The Mega-Hack of '93 !  (still AM)
  116.     {
  117.     USHORT      iseg, lseg;
  118.     PUCHAR16    gdt;
  119.  
  120.     DosGetInfoSeg (&iseg, &lseg);
  121.     gdt = (PUCHAR16)((long)iseg<<16);
  122.     return (gdt[24]);
  123.     }
  124. /*--------------------------------------------------------------------------*/
  125. #pragma argsused
  126. void APIENTRY kbd_monitor (ULONG arg)
  127.     {
  128.     UCHAR           ib[128], ob[128];        // buffer
  129.     USHORT          kplen;
  130.     struct KP       kp;
  131.     BOOL            release=FALSE;
  132.     USHORT          monhan;
  133.     USHORT          ff, tscan;
  134.  
  135.     // init variables & open monitor
  136.     ib[0] = ob[0]    = 128;
  137.     ib[1] = ob[1]    = 0;
  138.     DosSetPriority (PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, monid);
  139.  
  140.     if (DosMonOpen ("KBD$", &monhan))
  141.         DosBeep (1000,1000);
  142.  
  143.     if (DosMonReg (monhan, ib, ob, 1, getcurgroup ()))
  144.         DosBeep (2000,1000);
  145.  
  146.     while (TRUE)
  147.         {
  148.         // read key    and copy to backup
  149.         kplen = sizeof (struct KP);
  150.         DosMonRead  (ib, 0, (PUCHAR16)&kp, &kplen);
  151.         DosMonWrite (ob, (PUCHAR16)&kp, kplen);
  152.  
  153.         // extract information
  154.         release = (kp.ddflags & 0x0040)>>6;
  155.  
  156.         if (kp.scan == 0)       // flags
  157.             {
  158.             kp.flags = (kp.flags & 0x7f00) >> 8;
  159.             ff = 0;
  160.             if (kp.flags == 0x2a || kp.flags == 0x36)
  161.                 ff = KC_SHIFT;
  162.             else if (kp.flags == 0x1d)
  163.                 ff = KC_CTRL;
  164.             else if (kp.flags == 0x38)
  165.                 ff = KC_ALT;
  166.  
  167.             flags ^= ff;
  168.             }
  169.         tscan = montopm[kp.scan];
  170.         k[tscan] = !release;
  171.         }
  172.     }
  173. /*--------------------------------------------------------------------------*/
  174. extern "C" {
  175. #pragma argsused
  176. BOOL cdecl hook (HAB hab, PQMSG pqmsg, USHORT msgflag)
  177.     {
  178.     char    s;
  179.  
  180.     if (pqmsg->msg != WM_CHAR || inconfig)
  181.         return (FALSE);
  182.  
  183.     s = CHAR4FROMMP (pqmsg->mp1);
  184.     if (s>=MAXSCANCODE)
  185.         DosBeep (2000,1000);
  186.     else
  187.         {
  188.         k[s] = !(SHORT1FROMMP (pqmsg->mp1) & KC_KEYUP);
  189.         flags = SHORT1FROMMP (pqmsg->mp1) & (KC_CTRL | KC_SHIFT | KC_ALT);
  190.         }
  191.     return (FALSE);
  192.     }
  193. }
  194. /*--------------------------------------------------------------------------*/
  195. extern "C" {
  196. unsigned _export GetDataSize (void)
  197.     {
  198.     return (sizeof(KBDCONFIG));
  199.     }
  200. }
  201. /*--------------------------------------------------------------------------*/
  202. extern "C" {
  203. unsigned _export InitializeDLL (char __far16 *dd)
  204.     {
  205.     PTIB        tib;
  206.     PPIB        pib;
  207.     KBDCONFIGP  kc;
  208.  
  209.     kc = (KBDCONFIGP)dd;
  210.     if (!kc->init)
  211.         {
  212.         kc->init = TRUE;
  213.         kc->numdir = STDNUMDIR;
  214.         kc->threshold = THRESHOLD;
  215.         }
  216.  
  217.     // Get run-mode
  218.     DosGetInfoBlocks (&tib, &pib);
  219.     if (pib->pib_ultype == 3)   // Install a PM-Hook
  220.         {
  221.            if (!WinSetHook (WinInitialize (0), HMQ_CURRENT, HK_INPUT, (PFN)hook, module))
  222.             {
  223.             return (EHOOK);
  224.             }
  225.         }
  226.     else                    // Install KBD-Mon
  227.         {
  228.         DosCreateThread (&monid, kbd_monitor, 0, 0, 4096);
  229.         }
  230.  
  231.     return (NOERR);
  232.     }
  233. }
  234. /*--------------------------------------------------------------------------*/
  235. extern "C" {
  236. unsigned _export Name (char __far16 *target)
  237.     {
  238.     strcpy (target, "Keyboard");
  239.     return (0);
  240.     }
  241. }
  242. /*--------------------------------------------------------------------------*/
  243. void SetState ()
  244.     {
  245.     char    num[10];
  246.  
  247.     WinEnableWindow (wid[0], mode==0);
  248.     WinEnableWindow (wid[1], mode!=0);
  249.     WinEnableWindow (wid[2], mode==0);
  250.  
  251.     WinEnableWindow (wid[5], mode==1);
  252.     WinEnableWindow (wid[6], mode==1);
  253.     WinEnableWindow (wid[7], mode==1);
  254.  
  255.     WinEnableWindow (but_ok, mode==0);
  256.     WinEnableWindow (but_cancel, mode==0);
  257.  
  258.     WinSetWindowText (wid[3], statustext[mode]);
  259.  
  260.     if (cscan)
  261.         {
  262.         strcpy (keytext, scankey);
  263.         itoa (cscan, num, 10);
  264.         strcat (keytext, num);
  265.         }
  266.     else
  267.         strcpy (keytext, nonetext);
  268.  
  269.     WinSetWindowText (wid[4], keytext);
  270.  
  271.     CheckBoxSet (wid[5], cflags & KC_SHIFT ? TRUE : FALSE);
  272.     CheckBoxSet (wid[6], cflags & KC_ALT   ? TRUE : FALSE);
  273.     CheckBoxSet (wid[7], cflags & KC_CTRL  ? TRUE : FALSE);
  274.     }
  275. /*--------------------------------------------------------------------------*/
  276. MRESULT    EXPENTRY dlgproc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  277.     {
  278.     HAB         hab=WinInitialize (0);
  279.     int         i;
  280.     unsigned    tscan, tflags;
  281.  
  282.     switch (msg)
  283.         {
  284.         case WM_INITDLG:
  285.             for (i=0; i<8; i++)
  286.                 wid[i] = WinWindowFromID (hwnd, i+101);
  287.             but_ok      = WinWindowFromID (hwnd, DID_OK);
  288.             but_cancel  = WinWindowFromID (hwnd, DID_CANCEL);
  289.             WinLoadString (hab, module, 100, MAXSTATUS, statustext[0]);
  290.             WinLoadString (hab, module, 101, MAXSTATUS, statustext[1]);
  291.             WinLoadString (hab, module, 102, MAXSTATUS, statustext[2]);
  292.             WinLoadString (hab, module, 103, 15, scankey);
  293.             WinLoadString (hab, module, 104, 15, nonetext);
  294.             mode = 0;
  295.             SetState ();
  296.             return (FALSE);
  297.         case WM_COMMAND:
  298.             switch (SHORT1FROMMP (mp1))
  299.                 {
  300.                 case DID_OK:
  301.                     WinDismissDlg (hwnd, TRUE);
  302.                     break;
  303.                 case DID_CANCEL:
  304.                     WinDismissDlg (hwnd, FALSE);
  305.                     break;
  306.                 case 101:   // Start...
  307.                     mode = 1;
  308.                     SetState ();
  309.                     break;
  310.                 case 102:   // Stop...
  311.                     cflags = 0;
  312.                     if (CheckBoxQuery (wid[5]))
  313.                         cflags |= KC_SHIFT;
  314.                     if (CheckBoxQuery (wid[6]))
  315.                         cflags |= KC_ALT;
  316.                     if (CheckBoxQuery (wid[7]))
  317.                         cflags |= KC_CTRL;
  318.                     mode = 0;
  319.                     SetState ();
  320.                     break;
  321.                 case 103:   // Test...
  322.                     mode = 2;
  323.                     SetState ();
  324.                     break;
  325.                 }
  326.             break;
  327.         case WM_CHAR:
  328.             if (mode == 1)
  329.                 {
  330.                 cscan  = CHAR4FROMMP (mp1);
  331.                 cflags = SHORT1FROMMP (mp1) & (KC_ALT | KC_CTRL | KC_SHIFT);
  332.                 SetState ();
  333.                 break;
  334.                 }
  335.             else if (mode == 2)
  336.                 {
  337.                 tscan  = CHAR4FROMMP (mp1);
  338.                 tflags = SHORT1FROMMP (mp1) & (KC_ALT | KC_CTRL | KC_SHIFT);
  339.                 if (tscan == cscan && tflags == cflags)
  340.                     DosBeep (1000,100);
  341.                 }
  342.         default:
  343.             return (WinDefDlgProc (hwnd, msg, mp1, mp2));
  344.         }
  345.     return (0L);
  346.     }
  347. /*--------------------------------------------------------------------------*/
  348. unsigned _export ConfigKey (unsigned *scanp, unsigned *flagsp)
  349.     {
  350.     cscan  = *scanp;
  351.     cflags = *flagsp;
  352.  
  353.     if (WinDlgBox (HWND_DESKTOP, HWND_DESKTOP, dlgproc, module, 100, NULL) == TRUE)
  354.         {
  355.         *scanp = cscan;
  356.         *flagsp= cflags;
  357.         }
  358.     return (0);
  359.     }
  360. /*--------------------------------------------------------------------------*/
  361. void DrawListBox ()
  362.     {
  363.     int     i;
  364.  
  365.     lb.DeleteAll ();
  366.     for (i=1; i<=kc->numdir; i++)
  367.         {
  368.         if (kc->scan[i-1] || kc->flags[i-1])
  369.             dirname[i][0] = '*';
  370.         else
  371.             dirname[i][0] = ' ';
  372.         lb.Insert (LIT_END, dirname[i]);
  373.         }
  374.     }
  375. /*--------------------------------------------------------------------------*/
  376. MRESULT    EXPENTRY configproc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  377.     {
  378.     USHORT      i;
  379.     int         sel;
  380.  
  381.     switch (msg)
  382.         {
  383.         case WM_INITDLG:
  384.             lb.Set (WinWindowFromID (hwnd, 201));
  385.             DrawListBox ();
  386.             slider.Set (WinWindowFromID (hwnd, 206));
  387.             for (i=0; i<11; i++)
  388.                 slider.SetTickSize (i, 6);
  389.             slider.SetScaleText (0, "0%");
  390.             slider.SetScaleText (5, "50%");
  391.             slider.SetScaleText (10, "100%");
  392.             slider.SetSliderPos (kc->threshold/10);
  393.             break;
  394.         case WM_COMMAND:
  395.             switch (SHORT1FROMMP (mp1))
  396.                 {
  397.                 case DID_OK:
  398.                     kc->threshold = 10*slider.QuerySliderPos ();
  399.                     WinDismissDlg (hwnd, TRUE);
  400.                     break;
  401.                 case DID_CANCEL:
  402.                     WinDismissDlg (hwnd, FALSE);
  403.                     break;
  404.                 case 202:   // New...
  405.                     sel = lb.Selection ();
  406.                     if (sel >= 0)    // Item selected
  407.                         {
  408.                         kc->scan[sel] = kc->flags[sel] = 0;
  409.                         ConfigKey (&kc->scan[sel], &kc->flags[sel]);
  410.                         DrawListBox ();
  411.                         }
  412.                     break;
  413.                 case 203:   // Define...
  414.                     sel = lb.Selection ();
  415.                      if (sel >= 0)    // Item selected
  416.                         {
  417.                         ConfigKey (&kc->scan[sel], &kc->flags[sel]);
  418.                         DrawListBox ();
  419.                         }
  420.                       break;
  421.                 case 204:   // Delete...
  422.                     sel = lb.Selection ();
  423.                     if (sel >= 0)    // Item selected
  424.                         {
  425.                         kc->scan[sel] = kc->flags[sel] = 0;
  426.                         DrawListBox ();
  427.                         }
  428.                     break;
  429.                 }
  430.             break;
  431.         case WM_CONTROL:
  432.             if (SHORT1FROMMP (mp1)==201 && SHORT2FROMMP (mp1)==LN_ENTER)
  433.                 {
  434.                 sel = lb.Selection ();
  435.                 ConfigKey (&kc->scan[sel], &kc->flags[sel]);
  436.                 DrawListBox ();
  437.                 }
  438.             break;
  439.         default:
  440.             return (WinDefDlgProc (hwnd, msg, mp1, mp2));
  441.         }
  442.     return (0);
  443.     }
  444.  
  445. /*--------------------------------------------------------------------------*/
  446. extern "C" {
  447. unsigned _export ConfigDLL (char __far16 *dd)
  448.     {
  449.     KBDCONFIG   back;
  450.  
  451.     memcpy (&back, dd, sizeof (KBDCONFIG));
  452.     kc = (KBDCONFIGP)dd;
  453.     inconfig = TRUE;
  454.  
  455.     if (WinDlgBox (HWND_DESKTOP, HWND_DESKTOP, configproc, module, 200, NULL) == FALSE)
  456.         {
  457.         memcpy (dd, &back, sizeof(KBDCONFIG));
  458.         }
  459.  
  460.     inconfig = FALSE;
  461.     return (NOERR);
  462.     }
  463. }
  464. /*--------------------------------------------------------------------------*/
  465. extern "C" {
  466. unsigned _export Threshold (char __far16 *dd)
  467.     {
  468.     return (((KBDCONFIGP)dd)->threshold);
  469.     }
  470. }
  471. /*--------------------------------------------------------------------------*/
  472. extern "C" {
  473. unsigned _export Direction (char __far16 *dd, char __far16 *de)
  474.     {
  475.     PLAYERINFOP pi;
  476.     KBDCONFIGP  kc;
  477.     int         i;
  478.  
  479.     kc = (KBDCONFIGP)dd;
  480.     pi = (PLAYERINFOP)de;
  481.     for (i=0; i<STDNUMDIR; i++)
  482.         {
  483.         if (k[kc->scan[i]] && kc->flags[i] == flags)
  484.             pi->dir[i] = kc->threshold;
  485.         else
  486.             pi->dir[i] = 0;
  487.         }
  488.     return (0);
  489.     }
  490. }
  491. /*--------------------------------------------------------------------------*/
  492.  
  493.  
  494.