home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c185 / 2.ddi / OWLSRC.EXE / CSCAPE / SOURCE / PCHARD.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-09-12  |  14.5 KB  |  506 lines

  1. /*
  2.     pchard.c
  3.  
  4.     % PC keyboard, mouse, timer, and speaker routines
  5.  
  6.     5/16/88  by Ted.
  7.  
  8.     OWL 1.1
  9.     Copyright (c) 1988, by Oakland Group, Inc.
  10.     ALL RIGHTS RESERVED.
  11.  
  12.     Revision History:
  13.     -----------------
  14.      9/09/88 jmd    Fixed kRead and kCheck
  15.     10/19/88 ted    Changed how dopause works, extracted dig_SubHsecs
  16.     11/22/88 ted    Merged key&hard structures, added ReadEvent.
  17.     12/12/88 ted    Merged CheckKey and CheckMouse into CheckEvent.
  18.     12/14/88 ted    Changed CheckEvent to unsigned so it can return MOU_EVENT.
  19.      2/07/89 Ted    added timeout wait arg to hCheckEvent function.
  20.      2/09/89 Ted    added setmousebox implementation
  21.      2/28/89 ted    moved Control, CheckEvent and ReadEvent out to pcevent.c
  22.      3/26/89 ted    Added wait feature for CheckEvent.
  23.      4/04/89 ted    Added mouse de-initialization feature.
  24.      4/22/89 ted    moved Control, CheckEvent and ReadEvent back in.
  25.      7/10/89 ted    moved pchdatastruc back in here (it was in its own file).
  26.      7/12/89 ted    Added OSTATIC's and '_func' macros.
  27.      8/11/89 ted    Added SETMOUSESHAPE.
  28.      8/24/89 ted    Added GETMOUSESHAPE.
  29.      8/31/89 ted    Added CLEAREVENTS.
  30.      8/31/89 jmd    Added call to disp_EvCheck
  31.      9/12/89 ted    Removed ref. to pcdata in mouseshape that messed up FAMILYAPI.
  32. */
  33.  
  34. #include "pcpriv.h"
  35. #include "scancode.h"    /* for mouse pseudo-scancodes */
  36.  
  37. OGLOBAL pchdata_struct pchdatastruc;
  38.  
  39. OSTATIC dig_hCheckEvent_func    (pc_hCheckEvent);
  40. OSTATIC dig_hReadEvent_func        (pc_hReadEvent);
  41. OSTATIC dig_hControl_func        (pc_hControl);
  42. OSTATIC dig_hGetShift_func        (pc_hGetShift);
  43. OSTATIC dig_hPause_func            (pc_hPause);
  44. OSTATIC dig_hSound_func            (pc_hSound);
  45.  
  46. OSTATIC int         DIGPRIV mousecheck(_arg1(void));
  47. OSTATIC boolean        DIGPRIV getmousepos(_arg1(moupos_struct *));
  48. OSTATIC boolean        DIGPRIV setmousebox(_arg1(opbox *mbox));
  49. OSTATIC boolean        DIGPRIV setmouseshape(_arg1(mouseshape_struct *mshape));
  50. OSTATIC boolean        DIGPRIV makemasks(_arg2(mouseshape_struct *mshape, unsigned short *msmask));
  51. OSTATIC void        DIGPRIV dopause(_arg1(unsigned duration));
  52. /* -------------------------------------------------------------------------- */
  53.  
  54. void pc_hOpen(digp)
  55.     dig_struct *digp;
  56. /*
  57.     Init hardware pointers.
  58.     Note: not declared digpriv so it can be called from os2hard, which may be
  59.     in a different segment.
  60. */
  61. {
  62.     digp->hCheckEvent = pc_hCheckEvent;
  63.     digp->hReadEvent  = pc_hReadEvent;
  64.     digp->hGetShift = pc_hGetShift;
  65.     digp->hTimer   = pc_hTimer;
  66.     digp->hPause   = pc_hPause;
  67.     digp->hSound   = pc_hSound;
  68.     digp->hControl = pc_hControl;
  69. }
  70. /* -------------------------------------------------------------------------- */
  71.  
  72. static unsigned pc_hCheckEvent(wait)
  73.     unsigned wait;
  74. /* 
  75.     Return scancode if pending key event, HARD_MEV if no key but mouse event pending,
  76.     or KEY_NONE if no event is available before the wait time expires.
  77. */
  78. {
  79.     OREGS regs;
  80.     unsigned itime;
  81.  
  82.     if (wait != 0 && wait != (unsigned) -1) {
  83.         itime = pc_hTimer();
  84.     }
  85.     for (;;) {        /* loop until timeout */
  86.         regs.h.ah = KBINT_STATUS;
  87.         if (oakint86(BIOS_KBINT, ®s) & PC_ZFLAG) {    /* no key ready */
  88.             if (getmousepos(NULL)) {                    /* mouse ready */
  89.                 pchdata->eventchecked = TRUE;
  90.                 return(HARD_MEV);    /* no key, but mouse ready */
  91.             }
  92.         /*    else no mouse or key ready */
  93.         }
  94.         else {        /* key ready */
  95.             pchdata->eventchecked = TRUE;
  96.             return(regs.x.ax);
  97.         }
  98.         /* No key or mouse ready - see if wait duration has expired */
  99.         if (wait == 0) {
  100.             break;
  101.         }
  102.         else if (wait != (unsigned)-1) {
  103.             if (dig_SubHsecs(itime, pc_hTimer()) > wait) {
  104.                 break;        /* break out of the loop and give up if time out */
  105.             }
  106.         }
  107.     }
  108.     return(KEY_NONE);
  109. }
  110. /* -------------------------------------------------------------------------- */
  111.  
  112. static unsigned pc_hReadEvent(mouposp)
  113.     moupos_struct *mouposp;
  114. /*
  115.     Returns key scancode if key event is available first, or HARD_MEV if
  116.     mouse event is available first. Returns key event if both key and mouse
  117.     event are available when it is called.
  118. */
  119. {
  120.     OREGS regs;
  121.  
  122.     for (;;) {
  123.     /* Return when keyboard character is available */
  124.         regs.h.ah = KBINT_STATUS;
  125.         if (!(oakint86(BIOS_KBINT, ®s) & PC_ZFLAG)) {
  126.             regs.h.ah = KBINT_READ;
  127.             oakint86(BIOS_KBINT, ®s);
  128.             pchdata->eventchecked = FALSE;
  129.             return((unsigned) regs.x.ax);
  130.         }
  131.         if (mouposp != NULL) {
  132.             if (getmousepos(NULL)) {
  133.                 getmousepos(mouposp);
  134.  
  135.                 if (pchdata->eventchecked) {
  136.                     pchdata->eventchecked = FALSE;
  137.                 /* If we promised a mouse return but the mouse was deinitted */
  138.                 /*  before we could return it, just return a 0 key event now. */
  139.                     if (!pchdata->ismouse) {
  140.                         return(KEY_NONE);
  141.                     }
  142.                 }
  143.                 return(HARD_MEV);
  144.             }
  145.         }
  146.     }
  147. }
  148. /* -------------------------------------------------------------------------- */
  149.  
  150. static int pc_hControl(msg, indata, outdata)
  151.     dig_hcmsg msg;
  152.     VOID *indata;
  153.     VOID *outdata;
  154. {
  155.     /* static default cursor masks - needed in case of first 'getcursorshape' */
  156.     static bmap_struct(16,16) arrowimage = {
  157.         16, 16,
  158.         0x00,0x00, 0x40,0x00, 0x60,0x00, 0x70,0x00,
  159.         0x78,0x00, 0x7C,0x00, 0x7E,0x00, 0x7F,0x00,
  160.         0x7F,0x80, 0x7C,0x00, 0x6C,0x00, 0x46,0x00,
  161.         0x06,0x00, 0x03,0x00, 0x03,0x00, 0x00,0x00
  162.     };
  163.     static bmap_struct(16,16) arrowmask = {
  164.         16, 16,
  165.         0x3F,0xFF, 0x1F,0xFF, 0x0F,0xFF, 0x07,0xFF,
  166.         0x03,0xFF, 0x01,0xFF, 0x00,0xFF, 0x00,0x7F,
  167.         0x00,0x3F, 0x00,0x1F, 0x01,0xFF, 0x10,0xFF,
  168.         0x30,0xFF, 0xF8,0x7F, 0xF8,0x7F, 0xFC,0x7F
  169.     };
  170.     static mouseshape_struct defmouseshape = {
  171.         (bmap_type)(&arrowimage), (bmap_type)(&arrowmask), 0, 0, 0x77FF, 0x7700
  172.     };
  173.     /* indata not needed in any of these cases so far */ oak_notused(indata);
  174.     /* outdata not needed in any of these cases so far */ oak_notused(outdata);
  175.  
  176.     switch (msg) {
  177.     case HC_OPEN:
  178.         pchdata->soundon = TRUE;
  179.         pchdata->ismouse = FALSE;
  180.     /*  rest of mouse vars handled in HC_INITMOUSE method */
  181.         break;
  182.     case HC_INITMOUSE:
  183.         if ((pchdata->ismouse = mousecheck()) != 0) { /* remember if mouse found */
  184.             pchdata->xlastmou  = pchdata->ylastmou = 0;
  185.             pchdata->blastmou = 0;
  186.             pchdata->eventchecked = FALSE;
  187.             pchdata->curmouseshape = &defmouseshape;
  188.         }
  189.         /* no break; */
  190.     case HC_ISMOUSEON:
  191.         return((int)pchdata->ismouse);
  192.  
  193.     case HC_DEINITMOUSE:
  194.         pchdata->ismouse = FALSE;
  195.         break;
  196.     case HC_SETMOUSEBOX:
  197.         return((int)setmousebox((opbox *) indata));
  198.  
  199.     case HC_SETMOUSESHAPE:
  200.         /*
  201.         Note: any bmaps passed here must not be freed as long as someone
  202.          might call 'getmouseshape' and then 'setmouseshape' again with the
  203.          gotten shape struct and its pointers to your old bmaps.
  204.         */
  205.         if (!setmouseshape((mouseshape_struct *) indata)) {
  206.             return(FALSE);
  207.         }
  208.           memmove((VOID *)pchdata->curmouseshape, indata, sizeof(mouseshape_struct));
  209.         break;
  210.     case HC_GETMOUSESHAPE:
  211.           memmove(outdata, (VOID *)pchdata->curmouseshape, sizeof(mouseshape_struct));
  212.         break;
  213.  
  214.     case HC_SETSOUNDON:
  215.         pchdata->soundon = TRUE;
  216.         break;
  217.     case HC_SETSOUNDOFF:
  218.         pchdata->soundon = FALSE;
  219.         break;
  220.     case HC_GETSOUNDON:
  221.         return((int)pchdata->soundon);
  222.     case HC_CLEAREVENTS:
  223.     {    /* Call ReadEvent until nothing in kb buffer */
  224.         moupos_struct mouposdum;
  225.  
  226.         if (disp_EvCheck()) {
  227.             while (pc_hCheckEvent(0) != KEY_NONE) {
  228.                 pc_hReadEvent(&mouposdum);
  229.             }
  230.         }
  231.         break;
  232.     }
  233.     }
  234.     return(TRUE);
  235. }
  236. /* -------------------------------------------------------------------------- */
  237.  
  238. static unsigned pc_hGetShift()
  239. /*
  240.     effects:    gets the state of the keyboard shift keys.
  241.     returns:    an encoding of the shift keys as follows:
  242.                 LSB    bit 0 - right shift
  243.                     bit 1 - left shift
  244.                     bit 2 - control
  245.                     bit 3 - alt
  246.                     bit 4 - scroll lock
  247.                     bit 5 - num lock
  248.                     bit 6 - caps lock
  249.                     bit 7 - insert
  250.                 MSB bits 8-15 - not used
  251. */
  252. {
  253.     OREGS regs;
  254.     
  255.     regs.h.ah = KBINT_GETSHIFT;
  256.     oakint86(BIOS_KBINT, ®s);
  257.     return((unsigned)regs.h.al);
  258. }
  259. /* -------------------------------------------------------------------------- */
  260.  
  261. unsigned pc_hTimer()
  262. /*
  263.     effects:    Calculates current time stamp with 1/100 sec. resolution.
  264.                 Events with duration up to TIMER_LIMIT / 100 seconds
  265.                 can be timed.
  266.     returns:    An integer between 0 and TIMER_LIMIT - 1, which represents
  267.                 a time stamp. This time stamp can be compared to previous
  268.                 time stamps to calculate elapsed time in hundredths of
  269.                 seconds. The timer 'rolls over' at TIMER_LIMIT - 1.
  270. */
  271. {
  272.     OREGS regs;
  273.     unsigned hsecs, secs, mins;
  274.  
  275.     regs.h.ah = DOS_GETTIME;
  276.     oakint86(DOS_INT, ®s);
  277.  
  278.     hsecs = regs.h.dl;
  279.     secs = regs.h.dh;
  280.     mins = regs.h.cl % 10;
  281.  
  282.     return((unsigned)(hsecs + secs * 100 + mins * 6000));
  283. }
  284. /* -------------------------------------------------------------------------- */
  285.  
  286. static void pc_hPause(duration)
  287.     unsigned duration;                /* duration in hundredths of secs */
  288. {
  289.     dopause(duration);
  290. }
  291. /* -------------------------------------------------------------------------- */
  292.  
  293. static void pc_hSound(pitch, duration)
  294.     unsigned int pitch;
  295.     unsigned int duration;        /* duration in hundredths of secs */
  296. {
  297.     if (pchdata->soundon) {
  298.         outp( SPKR_CNTRL2, SPKR_MODE3);                /* put timer 2 into mode 3 */
  299.         outp( SPKR_TIMER2, pitch & 0x00FF);            /* wavelength for timer 2 */
  300.         outp( SPKR_TIMER2, pitch / 0x00FF);
  301.  
  302.         outp(DOS_PORTB, inp(DOS_PORTB) | 0x03);        /* turn on speaker */
  303.         dopause(duration);                            /* wait... */
  304.         outp(DOS_PORTB, inp(DOS_PORTB) & 0xFC);        /* turn off speaker */
  305.     }
  306. }
  307. /* -------------------------------------------------------------------------- */
  308. /* -------------------------------------------------------------------------- */
  309.  
  310. static int DIGPRIV mousecheck()
  311. /*
  312.     Return 1 for mouse, 0 for not installed
  313. */
  314. {
  315.     OREGS regs;
  316.     long mousevec;
  317.  
  318.     /* Peek at mouse interrupt vector to see if it is null */
  319.     ram_segtomem(0x00, 4 * BIOS_MOUSEINT, (byte *) &mousevec, 4);
  320.     if (mousevec == 0) {
  321.         return 0;    /* if no seg or offset return 0 */
  322.     }
  323.     /* Try the mouse interupt - if it leaves ax alone it's not real */
  324.     regs.x.ax = BMOU_INIT;
  325.     oakint86(BIOS_MOUSEINT, ®s);
  326.     return(regs.x.ax != BMOU_INIT);
  327. }
  328. /* -------------------------------------------------------------------------- */
  329.  
  330. static boolean DIGPRIV getmousepos(mouposp)
  331.     moupos_struct *mouposp;
  332. /*
  333.     If mouposp != NULL, wait for a mouse event and return it in mouposp.
  334.     Otherwise, don't wait and return whether an event is ready or not.
  335. */
  336. {
  337.     opcoord mx, my;
  338.     boolean motion;
  339.     OREGS regs;
  340.  
  341.     if (!pchdata->ismouse) {
  342.         return(FALSE);
  343.     }
  344.     if (mouposp == NULL) {    /* CheckEvent call */
  345.         if (pchdata->eventchecked) {
  346.             return(TRUE);
  347.         }
  348.     }
  349.     for (;;) {
  350.         regs.x.ax = BMOU_GETPOS;
  351.         oakint86(BIOS_MOUSEINT, ®s);
  352.  
  353.         mx = regs.x.cx / pchdata->xmouscale;
  354.         my = regs.x.dx / pchdata->ymouscale;
  355.  
  356.         motion = (mx != pchdata->xlastmou || my != pchdata->ylastmou);
  357.  
  358.         if (!motion && pchdata->blastmou == regs.x.bx) {
  359.         /* If no change in mouse position or buttons: try again */
  360.             if (mouposp == NULL) {    /* CheckEvent call */
  361.                 return(FALSE);    /* Return if this is just a CheckMouse */
  362.             }
  363.         /* If we previously reported a change, return an */
  364.         /* event now, even though the change went away again */
  365.         /* Otherwise, go around for another mouse read */
  366.             if (!pchdata->eventchecked) continue;
  367.             else motion = TRUE;    /* Fudge it: report motion anyway */
  368.         }
  369.         if (mouposp == NULL) {    /* CheckEvent call */
  370.             return(TRUE);
  371.         }
  372.         pchdata->xlastmou = mx;
  373.         pchdata->ylastmou = my;
  374.         pchdata->blastmou = regs.x.bx;
  375.  
  376.         mouposp->x = mx;
  377.         mouposp->y = my;
  378.         mouposp->event = 0;
  379.         if (regs.x.bx & 0x01) {
  380.             if (motion) mouposp->event |= MEV_BUT1MOVE;
  381.             else mouposp->event |= MEV_BUT1;
  382.         }
  383.         if (regs.x.bx & 0x02) {
  384.             if (motion) mouposp->event |= MEV_BUT2MOVE;
  385.             else mouposp->event |= MEV_BUT2;
  386.         }
  387.         if (regs.x.bx & 0x04) {
  388.             if (motion) mouposp->event |= MEV_BUT3MOVE;
  389.             else mouposp->event |= MEV_BUT3;
  390.         }
  391.         if (motion && mouposp->event == 0) {
  392.             mouposp->event |= MEV_MOVE;
  393.         }
  394.         break;
  395.     }
  396.     return(TRUE);
  397. }
  398. /* -------------------------------------------------------------------------- */
  399.  
  400. static boolean DIGPRIV setmousebox(mbox)
  401.     opbox *mbox;
  402. {
  403.     OREGS regs;
  404.  
  405.     regs.x.ax = BMOU_XRANGE;
  406.     regs.x.cx = mbox->xmin * pchdata->xmouscale;
  407.     regs.x.dx = (mbox->xmax-1) * pchdata->xmouscale;
  408.     oakint86(BIOS_MOUSEINT, ®s);
  409.  
  410.     regs.x.ax = BMOU_YRANGE;
  411.     regs.x.cx = mbox->ymin * pchdata->ymouscale;
  412.     regs.x.dx = (mbox->ymax-1) * pchdata->ymouscale;
  413.     oakint86(BIOS_MOUSEINT, ®s);
  414.  
  415.     return(TRUE);
  416. }
  417. /* -------------------------------------------------------------------------- */
  418.  
  419. static boolean DIGPRIV setmouseshape(mshape)
  420.     mouseshape_struct *mshape;
  421. /*
  422.     Return TRUE if graphics cursor shape was set, FALSE if not. Text cursor is
  423.     always set in any case.
  424. */
  425. {
  426.     OREGS regs;
  427.     unsigned short msmask[2*16];
  428.  
  429.     if (!pchdata->ismouse) {
  430.         return(FALSE);
  431.     }
  432.     if (ofont_GetWidth(disp_GetDefFont()) == 1) {    /* text mode */
  433.         if (mshape->tsmask == 0 && mshape->tcmask == 0) {
  434.             return(FALSE);    /* Fail if 0 cursor and mask given */
  435.         }
  436.         /* Set software text mode mouse cursor in text mode */
  437.         regs.x.ax = BMOU_TMSHAPE;
  438.         regs.x.bx = 0;
  439.         regs.x.cx = mshape->tsmask;
  440.         regs.x.dx = mshape->tcmask;
  441.         oakint86(BIOS_MOUSEINT, ®s);
  442.     }
  443.     else {
  444.         /* Convert given pmaps to cursor shape and mask bit arrays */
  445.         if (!makemasks(mshape, msmask)) {
  446.             return(FALSE);
  447.         }
  448.         /* Set graphics mode cursor shape and mask */
  449.         regs.x.ax = BMOU_MSHAPE;
  450.         regs.x.bx = mshape->xhot * pchdata->xmouscale;
  451.         regs.x.cx = mshape->yhot * pchdata->ymouscale;
  452.         regs.a.esdx = msmask;
  453.         oakint86es(BIOS_MOUSEINT, ®s, sizeof(msmask));
  454.     }
  455.     return(TRUE);
  456. }
  457. /* -------------------------------------------------------------------------- */
  458.  
  459. static boolean DIGPRIV makemasks(mshape, msmask)
  460.     mouseshape_struct *mshape;
  461.     unsigned short *msmask;
  462. {
  463.     int i;
  464.     byte *inb, *outb;
  465.  
  466.     if (mshape->mask == NULL || mshape->image == NULL) {
  467.         return(FALSE);
  468.     }
  469.     outb = (byte *)msmask;
  470.     for (i = 0; i < 16; i++) {
  471.         if (i < mshape->mask->height) {
  472.             inb = bmap_GetLine(mshape->mask, i);
  473.             *(outb++) = *(inb+1); *(outb++) = *inb;
  474.         }
  475.         else {
  476.             *(outb++) = 0xFF; *(outb++) = 0xFF;
  477.         }
  478.     }
  479.     for (i = 0; i < 16; i++) {
  480.         if (i < mshape->image->height) {
  481.             inb = bmap_GetLine(mshape->image, i);
  482.             *(outb++) = *(inb+1); *(outb++) = *inb;
  483.         }
  484.         else {
  485.             *(outb++) = 0x00; *(outb++) = 0x00;
  486.         }
  487.     }
  488.     return(TRUE);
  489. }
  490. /* -------------------------------------------------------------------------- */
  491.  
  492. static void DIGPRIV dopause(duration)
  493.     unsigned duration;                /* duration in hundredths of secs */
  494. /*
  495.     This function uses the system clock and causes a delay 
  496.     of the specified duration.
  497. */
  498. {
  499.     unsigned tstart;
  500.  
  501.     tstart = pc_hTimer();
  502.     while (dig_SubHsecs(tstart, pc_hTimer()) < duration);
  503. }
  504. /* -------------------------------------------------------------------------- */
  505.  
  506.