home *** CD-ROM | disk | FTP | other *** search
- /*
- pchard.c
-
- % PC keyboard, mouse, timer, and speaker routines
-
- 5/16/88 by Ted.
-
- OWL 1.1
- Copyright (c) 1988, by Oakland Group, Inc.
- ALL RIGHTS RESERVED.
-
- Revision History:
- -----------------
- 9/09/88 jmd Fixed kRead and kCheck
- 10/19/88 ted Changed how dopause works, extracted dig_SubHsecs
- 11/22/88 ted Merged key&hard structures, added ReadEvent.
- 12/12/88 ted Merged CheckKey and CheckMouse into CheckEvent.
- 12/14/88 ted Changed CheckEvent to unsigned so it can return MOU_EVENT.
- 2/07/89 Ted added timeout wait arg to hCheckEvent function.
- 2/09/89 Ted added setmousebox implementation
- 2/28/89 ted moved Control, CheckEvent and ReadEvent out to pcevent.c
- 3/26/89 ted Added wait feature for CheckEvent.
- 4/04/89 ted Added mouse de-initialization feature.
- 4/22/89 ted moved Control, CheckEvent and ReadEvent back in.
- 7/10/89 ted moved pchdatastruc back in here (it was in its own file).
- 7/12/89 ted Added OSTATIC's and '_func' macros.
- 8/11/89 ted Added SETMOUSESHAPE.
- 8/24/89 ted Added GETMOUSESHAPE.
- 8/31/89 ted Added CLEAREVENTS.
- 8/31/89 jmd Added call to disp_EvCheck
- 9/12/89 ted Removed ref. to pcdata in mouseshape that messed up FAMILYAPI.
- */
-
- #include "pcpriv.h"
- #include "scancode.h" /* for mouse pseudo-scancodes */
-
- OGLOBAL pchdata_struct pchdatastruc;
-
- OSTATIC dig_hCheckEvent_func (pc_hCheckEvent);
- OSTATIC dig_hReadEvent_func (pc_hReadEvent);
- OSTATIC dig_hControl_func (pc_hControl);
- OSTATIC dig_hGetShift_func (pc_hGetShift);
- OSTATIC dig_hPause_func (pc_hPause);
- OSTATIC dig_hSound_func (pc_hSound);
-
- OSTATIC int DIGPRIV mousecheck(_arg1(void));
- OSTATIC boolean DIGPRIV getmousepos(_arg1(moupos_struct *));
- OSTATIC boolean DIGPRIV setmousebox(_arg1(opbox *mbox));
- OSTATIC boolean DIGPRIV setmouseshape(_arg1(mouseshape_struct *mshape));
- OSTATIC boolean DIGPRIV makemasks(_arg2(mouseshape_struct *mshape, unsigned short *msmask));
- OSTATIC void DIGPRIV dopause(_arg1(unsigned duration));
- /* -------------------------------------------------------------------------- */
-
- void pc_hOpen(digp)
- dig_struct *digp;
- /*
- Init hardware pointers.
- Note: not declared digpriv so it can be called from os2hard, which may be
- in a different segment.
- */
- {
- digp->hCheckEvent = pc_hCheckEvent;
- digp->hReadEvent = pc_hReadEvent;
- digp->hGetShift = pc_hGetShift;
- digp->hTimer = pc_hTimer;
- digp->hPause = pc_hPause;
- digp->hSound = pc_hSound;
- digp->hControl = pc_hControl;
- }
- /* -------------------------------------------------------------------------- */
-
- static unsigned pc_hCheckEvent(wait)
- unsigned wait;
- /*
- Return scancode if pending key event, HARD_MEV if no key but mouse event pending,
- or KEY_NONE if no event is available before the wait time expires.
- */
- {
- OREGS regs;
- unsigned itime;
-
- if (wait != 0 && wait != (unsigned) -1) {
- itime = pc_hTimer();
- }
- for (;;) { /* loop until timeout */
- regs.h.ah = KBINT_STATUS;
- if (oakint86(BIOS_KBINT, ®s) & PC_ZFLAG) { /* no key ready */
- if (getmousepos(NULL)) { /* mouse ready */
- pchdata->eventchecked = TRUE;
- return(HARD_MEV); /* no key, but mouse ready */
- }
- /* else no mouse or key ready */
- }
- else { /* key ready */
- pchdata->eventchecked = TRUE;
- return(regs.x.ax);
- }
- /* No key or mouse ready - see if wait duration has expired */
- if (wait == 0) {
- break;
- }
- else if (wait != (unsigned)-1) {
- if (dig_SubHsecs(itime, pc_hTimer()) > wait) {
- break; /* break out of the loop and give up if time out */
- }
- }
- }
- return(KEY_NONE);
- }
- /* -------------------------------------------------------------------------- */
-
- static unsigned pc_hReadEvent(mouposp)
- moupos_struct *mouposp;
- /*
- Returns key scancode if key event is available first, or HARD_MEV if
- mouse event is available first. Returns key event if both key and mouse
- event are available when it is called.
- */
- {
- OREGS regs;
-
- for (;;) {
- /* Return when keyboard character is available */
- regs.h.ah = KBINT_STATUS;
- if (!(oakint86(BIOS_KBINT, ®s) & PC_ZFLAG)) {
- regs.h.ah = KBINT_READ;
- oakint86(BIOS_KBINT, ®s);
- pchdata->eventchecked = FALSE;
- return((unsigned) regs.x.ax);
- }
- if (mouposp != NULL) {
- if (getmousepos(NULL)) {
- getmousepos(mouposp);
-
- if (pchdata->eventchecked) {
- pchdata->eventchecked = FALSE;
- /* If we promised a mouse return but the mouse was deinitted */
- /* before we could return it, just return a 0 key event now. */
- if (!pchdata->ismouse) {
- return(KEY_NONE);
- }
- }
- return(HARD_MEV);
- }
- }
- }
- }
- /* -------------------------------------------------------------------------- */
-
- static int pc_hControl(msg, indata, outdata)
- dig_hcmsg msg;
- VOID *indata;
- VOID *outdata;
- {
- /* static default cursor masks - needed in case of first 'getcursorshape' */
- static bmap_struct(16,16) arrowimage = {
- 16, 16,
- 0x00,0x00, 0x40,0x00, 0x60,0x00, 0x70,0x00,
- 0x78,0x00, 0x7C,0x00, 0x7E,0x00, 0x7F,0x00,
- 0x7F,0x80, 0x7C,0x00, 0x6C,0x00, 0x46,0x00,
- 0x06,0x00, 0x03,0x00, 0x03,0x00, 0x00,0x00
- };
- static bmap_struct(16,16) arrowmask = {
- 16, 16,
- 0x3F,0xFF, 0x1F,0xFF, 0x0F,0xFF, 0x07,0xFF,
- 0x03,0xFF, 0x01,0xFF, 0x00,0xFF, 0x00,0x7F,
- 0x00,0x3F, 0x00,0x1F, 0x01,0xFF, 0x10,0xFF,
- 0x30,0xFF, 0xF8,0x7F, 0xF8,0x7F, 0xFC,0x7F
- };
- static mouseshape_struct defmouseshape = {
- (bmap_type)(&arrowimage), (bmap_type)(&arrowmask), 0, 0, 0x77FF, 0x7700
- };
- /* indata not needed in any of these cases so far */ oak_notused(indata);
- /* outdata not needed in any of these cases so far */ oak_notused(outdata);
-
- switch (msg) {
- case HC_OPEN:
- pchdata->soundon = TRUE;
- pchdata->ismouse = FALSE;
- /* rest of mouse vars handled in HC_INITMOUSE method */
- break;
- case HC_INITMOUSE:
- if ((pchdata->ismouse = mousecheck()) != 0) { /* remember if mouse found */
- pchdata->xlastmou = pchdata->ylastmou = 0;
- pchdata->blastmou = 0;
- pchdata->eventchecked = FALSE;
- pchdata->curmouseshape = &defmouseshape;
- }
- /* no break; */
- case HC_ISMOUSEON:
- return((int)pchdata->ismouse);
-
- case HC_DEINITMOUSE:
- pchdata->ismouse = FALSE;
- break;
- case HC_SETMOUSEBOX:
- return((int)setmousebox((opbox *) indata));
-
- case HC_SETMOUSESHAPE:
- /*
- Note: any bmaps passed here must not be freed as long as someone
- might call 'getmouseshape' and then 'setmouseshape' again with the
- gotten shape struct and its pointers to your old bmaps.
- */
- if (!setmouseshape((mouseshape_struct *) indata)) {
- return(FALSE);
- }
- memmove((VOID *)pchdata->curmouseshape, indata, sizeof(mouseshape_struct));
- break;
- case HC_GETMOUSESHAPE:
- memmove(outdata, (VOID *)pchdata->curmouseshape, sizeof(mouseshape_struct));
- break;
-
- case HC_SETSOUNDON:
- pchdata->soundon = TRUE;
- break;
- case HC_SETSOUNDOFF:
- pchdata->soundon = FALSE;
- break;
- case HC_GETSOUNDON:
- return((int)pchdata->soundon);
- case HC_CLEAREVENTS:
- { /* Call ReadEvent until nothing in kb buffer */
- moupos_struct mouposdum;
-
- if (disp_EvCheck()) {
- while (pc_hCheckEvent(0) != KEY_NONE) {
- pc_hReadEvent(&mouposdum);
- }
- }
- break;
- }
- }
- return(TRUE);
- }
- /* -------------------------------------------------------------------------- */
-
- static unsigned pc_hGetShift()
- /*
- effects: gets the state of the keyboard shift keys.
- returns: an encoding of the shift keys as follows:
- LSB bit 0 - right shift
- bit 1 - left shift
- bit 2 - control
- bit 3 - alt
- bit 4 - scroll lock
- bit 5 - num lock
- bit 6 - caps lock
- bit 7 - insert
- MSB bits 8-15 - not used
- */
- {
- OREGS regs;
-
- regs.h.ah = KBINT_GETSHIFT;
- oakint86(BIOS_KBINT, ®s);
- return((unsigned)regs.h.al);
- }
- /* -------------------------------------------------------------------------- */
-
- unsigned pc_hTimer()
- /*
- effects: Calculates current time stamp with 1/100 sec. resolution.
- Events with duration up to TIMER_LIMIT / 100 seconds
- can be timed.
- returns: An integer between 0 and TIMER_LIMIT - 1, which represents
- a time stamp. This time stamp can be compared to previous
- time stamps to calculate elapsed time in hundredths of
- seconds. The timer 'rolls over' at TIMER_LIMIT - 1.
- */
- {
- OREGS regs;
- unsigned hsecs, secs, mins;
-
- regs.h.ah = DOS_GETTIME;
- oakint86(DOS_INT, ®s);
-
- hsecs = regs.h.dl;
- secs = regs.h.dh;
- mins = regs.h.cl % 10;
-
- return((unsigned)(hsecs + secs * 100 + mins * 6000));
- }
- /* -------------------------------------------------------------------------- */
-
- static void pc_hPause(duration)
- unsigned duration; /* duration in hundredths of secs */
- {
- dopause(duration);
- }
- /* -------------------------------------------------------------------------- */
-
- static void pc_hSound(pitch, duration)
- unsigned int pitch;
- unsigned int duration; /* duration in hundredths of secs */
- {
- if (pchdata->soundon) {
- outp( SPKR_CNTRL2, SPKR_MODE3); /* put timer 2 into mode 3 */
- outp( SPKR_TIMER2, pitch & 0x00FF); /* wavelength for timer 2 */
- outp( SPKR_TIMER2, pitch / 0x00FF);
-
- outp(DOS_PORTB, inp(DOS_PORTB) | 0x03); /* turn on speaker */
- dopause(duration); /* wait... */
- outp(DOS_PORTB, inp(DOS_PORTB) & 0xFC); /* turn off speaker */
- }
- }
- /* -------------------------------------------------------------------------- */
- /* -------------------------------------------------------------------------- */
-
- static int DIGPRIV mousecheck()
- /*
- Return 1 for mouse, 0 for not installed
- */
- {
- OREGS regs;
- long mousevec;
-
- /* Peek at mouse interrupt vector to see if it is null */
- ram_segtomem(0x00, 4 * BIOS_MOUSEINT, (byte *) &mousevec, 4);
- if (mousevec == 0) {
- return 0; /* if no seg or offset return 0 */
- }
- /* Try the mouse interupt - if it leaves ax alone it's not real */
- regs.x.ax = BMOU_INIT;
- oakint86(BIOS_MOUSEINT, ®s);
- return(regs.x.ax != BMOU_INIT);
- }
- /* -------------------------------------------------------------------------- */
-
- static boolean DIGPRIV getmousepos(mouposp)
- moupos_struct *mouposp;
- /*
- If mouposp != NULL, wait for a mouse event and return it in mouposp.
- Otherwise, don't wait and return whether an event is ready or not.
- */
- {
- opcoord mx, my;
- boolean motion;
- OREGS regs;
-
- if (!pchdata->ismouse) {
- return(FALSE);
- }
- if (mouposp == NULL) { /* CheckEvent call */
- if (pchdata->eventchecked) {
- return(TRUE);
- }
- }
- for (;;) {
- regs.x.ax = BMOU_GETPOS;
- oakint86(BIOS_MOUSEINT, ®s);
-
- mx = regs.x.cx / pchdata->xmouscale;
- my = regs.x.dx / pchdata->ymouscale;
-
- motion = (mx != pchdata->xlastmou || my != pchdata->ylastmou);
-
- if (!motion && pchdata->blastmou == regs.x.bx) {
- /* If no change in mouse position or buttons: try again */
- if (mouposp == NULL) { /* CheckEvent call */
- return(FALSE); /* Return if this is just a CheckMouse */
- }
- /* If we previously reported a change, return an */
- /* event now, even though the change went away again */
- /* Otherwise, go around for another mouse read */
- if (!pchdata->eventchecked) continue;
- else motion = TRUE; /* Fudge it: report motion anyway */
- }
- if (mouposp == NULL) { /* CheckEvent call */
- return(TRUE);
- }
- pchdata->xlastmou = mx;
- pchdata->ylastmou = my;
- pchdata->blastmou = regs.x.bx;
-
- mouposp->x = mx;
- mouposp->y = my;
- mouposp->event = 0;
- if (regs.x.bx & 0x01) {
- if (motion) mouposp->event |= MEV_BUT1MOVE;
- else mouposp->event |= MEV_BUT1;
- }
- if (regs.x.bx & 0x02) {
- if (motion) mouposp->event |= MEV_BUT2MOVE;
- else mouposp->event |= MEV_BUT2;
- }
- if (regs.x.bx & 0x04) {
- if (motion) mouposp->event |= MEV_BUT3MOVE;
- else mouposp->event |= MEV_BUT3;
- }
- if (motion && mouposp->event == 0) {
- mouposp->event |= MEV_MOVE;
- }
- break;
- }
- return(TRUE);
- }
- /* -------------------------------------------------------------------------- */
-
- static boolean DIGPRIV setmousebox(mbox)
- opbox *mbox;
- {
- OREGS regs;
-
- regs.x.ax = BMOU_XRANGE;
- regs.x.cx = mbox->xmin * pchdata->xmouscale;
- regs.x.dx = (mbox->xmax-1) * pchdata->xmouscale;
- oakint86(BIOS_MOUSEINT, ®s);
-
- regs.x.ax = BMOU_YRANGE;
- regs.x.cx = mbox->ymin * pchdata->ymouscale;
- regs.x.dx = (mbox->ymax-1) * pchdata->ymouscale;
- oakint86(BIOS_MOUSEINT, ®s);
-
- return(TRUE);
- }
- /* -------------------------------------------------------------------------- */
-
- static boolean DIGPRIV setmouseshape(mshape)
- mouseshape_struct *mshape;
- /*
- Return TRUE if graphics cursor shape was set, FALSE if not. Text cursor is
- always set in any case.
- */
- {
- OREGS regs;
- unsigned short msmask[2*16];
-
- if (!pchdata->ismouse) {
- return(FALSE);
- }
- if (ofont_GetWidth(disp_GetDefFont()) == 1) { /* text mode */
- if (mshape->tsmask == 0 && mshape->tcmask == 0) {
- return(FALSE); /* Fail if 0 cursor and mask given */
- }
- /* Set software text mode mouse cursor in text mode */
- regs.x.ax = BMOU_TMSHAPE;
- regs.x.bx = 0;
- regs.x.cx = mshape->tsmask;
- regs.x.dx = mshape->tcmask;
- oakint86(BIOS_MOUSEINT, ®s);
- }
- else {
- /* Convert given pmaps to cursor shape and mask bit arrays */
- if (!makemasks(mshape, msmask)) {
- return(FALSE);
- }
- /* Set graphics mode cursor shape and mask */
- regs.x.ax = BMOU_MSHAPE;
- regs.x.bx = mshape->xhot * pchdata->xmouscale;
- regs.x.cx = mshape->yhot * pchdata->ymouscale;
- regs.a.esdx = msmask;
- oakint86es(BIOS_MOUSEINT, ®s, sizeof(msmask));
- }
- return(TRUE);
- }
- /* -------------------------------------------------------------------------- */
-
- static boolean DIGPRIV makemasks(mshape, msmask)
- mouseshape_struct *mshape;
- unsigned short *msmask;
- {
- int i;
- byte *inb, *outb;
-
- if (mshape->mask == NULL || mshape->image == NULL) {
- return(FALSE);
- }
- outb = (byte *)msmask;
- for (i = 0; i < 16; i++) {
- if (i < mshape->mask->height) {
- inb = bmap_GetLine(mshape->mask, i);
- *(outb++) = *(inb+1); *(outb++) = *inb;
- }
- else {
- *(outb++) = 0xFF; *(outb++) = 0xFF;
- }
- }
- for (i = 0; i < 16; i++) {
- if (i < mshape->image->height) {
- inb = bmap_GetLine(mshape->image, i);
- *(outb++) = *(inb+1); *(outb++) = *inb;
- }
- else {
- *(outb++) = 0x00; *(outb++) = 0x00;
- }
- }
- return(TRUE);
- }
- /* -------------------------------------------------------------------------- */
-
- static void DIGPRIV dopause(duration)
- unsigned duration; /* duration in hundredths of secs */
- /*
- This function uses the system clock and causes a delay
- of the specified duration.
- */
- {
- unsigned tstart;
-
- tstart = pc_hTimer();
- while (dig_SubHsecs(tstart, pc_hTimer()) < duration);
- }
- /* -------------------------------------------------------------------------- */
-