/* * DMOUSE-HANDLER.C compile 32 bit integers (+L) * AZTEC COMPILATION * 18 May 1988 */ #include "dmouse.h" #define IBASE IntuitionBase DMS *Dms; struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; long *LayersBase; NS Ns = { 0, 0, 64, -1, 1, -1, -1, 0, CUSTOMSCREEN|SCREENQUIET }; IE *handler(); _main() { register DMS *dms; IOR *ior; INT addhand; { register PROC *proc = (PROC *)FindTask(NULL); proc->pr_ConsoleTask = NULL; } dms = Dms = FindPort(PORTNAME); if (!dms) _exit(0); dms->Port.mp_Flags = PA_SIGNAL; dms->Port.mp_SigBit = AllocSignal(-1); dms->Port.mp_SigTask = FindTask(NULL); dms->HandTask = dms->Port.mp_SigTask; ior = CreateStdIO(&dms->Port); IntuitionBase = OpenLibrary("intuition.library", 0); GfxBase = OpenLibrary("graphics.library", 0); LayersBase = OpenLibrary("layers.library", 0); if (!IntuitionBase || !GfxBase || !LayersBase) goto startupfail; addhand.is_Node.ln_Pri = 51; addhand.is_Code = (FPTR)handler; addhand.is_Data = NULL; if (OpenDevice("input.device", 0, ior, 0)) { goto startupfail; } else { SCR *scr = NULL; uword *SprSavePtr = NULL; Signal(dms->ShakeTask, 1 << dms->ShakeSig); ior->io_Command = IND_ADDHANDLER; ior->io_Data = (APTR)&addhand; DoIO(ior); for (;;) { register long sigs = Wait(SBF_C|(1<Port.mp_SigBit)); if (sigs & (1 << dms->Port.mp_SigBit)) { register MSG *msg; while (msg = GetMsg(&dms->Port)) { switch((long)msg->mn_Node.ln_Name) { case REQ_SCREENON: if (scr) CloseScreen(scr); scr = NULL; break; case REQ_SCREENOFF: if (scr) { ScreenToFront(scr); } else { if (scr = OpenScreen(&Ns)) SetRGB4(&scr->ViewPort, 0, 0, 0, 0); } break; case REQ_MOUSEON: if (SprSavePtr) { register COPINIT *ci = GfxBase->copinit; ci->sprstrtup[1] = (ulong)SprSavePtr >> 16; ci->sprstrtup[3] = (uword)(long)SprSavePtr; SprSavePtr = NULL; } break; case REQ_MOUSEOFF: { register COPINIT *ci = GfxBase->copinit; if (!SprSavePtr) SprSavePtr = (uword *)((ci->sprstrtup[1] << 16) | ci->sprstrtup[3]); ci->sprstrtup[1] = (ulong)dms->NoSprData >> 16; ci->sprstrtup[3] = (uword)(long)dms->NoSprData; } break; case REQ_DOCMD: { long fh = Open("nil:", 1006); Execute(dms->Cmd, NULL, fh); if (fh) Close(fh); } break; } FreeMem(msg, msg->mn_Length); } } if (sigs & SBF_C) break; } Forbid(); ior->io_Command = IND_REMHANDLER; ior->io_Data = (APTR)&addhand; DoIO(ior); Permit(); CloseDevice(ior); { register MSG *msg; while (msg = GetMsg(&dms->Port)) FreeMem(msg, msg->mn_Length); } if (scr) CloseScreen(scr); if (SprSavePtr) { register COPINIT *ci = GfxBase->copinit; ci->sprstrtup[1] = (ulong)SprSavePtr >> 16; ci->sprstrtup[3] = (uword)(long)SprSavePtr; SprSavePtr = NULL; } } goto closedown; startupfail: dms->StartupError = 1; Signal(dms->ShakeTask, 1 << dms->ShakeSig); Wait(SBF_C); closedown: DeleteStdIO(ior); fail: if (IntuitionBase) CloseLibrary(IntuitionBase); if (GfxBase) CloseLibrary(GfxBase); if (LayersBase) CloseLibrary(LayersBase); Forbid(); Signal(dms->ShakeTask, 1 << dms->ShakeSig); } #asm ; A0 = pointer to event linked list ; A1 = pointer to my data segment ; return new event linked list in D0 public _CHandler _handler: movem.l D2/D3/A0/A1/A4/A6,-(sp) jsr _CHandler movem.l (sp)+,D2/D3/A0/A1/A4/A6 rts #endasm /* * (1) Accellerate mouse movements. * (2) Auto-Select window */ IE * CHandler(scr0, scr1, Ev) IE *Ev; { register IE *ev; register DMS *dms; static char STimedout; static char MTimedout; static long STime, MTime; geta4(); dms = Dms; for (ev = Ev; ev; ev = Ev->ie_NextEvent) { switch(ev->ie_Class) { case IECLASS_RAWMOUSE: /* * Mouse events restore both the screen and mouse pointer. */ STime = ev->ie_TimeStamp.tv_secs + dms->STo; MTime = ev->ie_TimeStamp.tv_secs + dms->MTo; if (STimedout) sendrequest(REQ_SCREENON); if (MTimedout) sendrequest(REQ_MOUSEON); STimedout = MTimedout = 0; /* * Mouse Acceleration */ { register short n; register short s; if (dms->Acc != 1) { n = ev->ie_X; s = 1; if (n < 0) { n = -n; s = -1; } if (n > dms->AThresh) ev->ie_X = s * (short)((n - dms->AThresh - 1) * dms->Acc + dms->AThresh + 1); n = ev->ie_Y; s = 1; if (n < 0) { n = -n; s = -1; } if (n > dms->AThresh) ev->ie_Y = s * (short)((n - dms->AThresh - 1) * dms->Acc + dms->AThresh + 1); } } /* * Auto Activate and LMB (win/scrn front/bak) */ if (dms->AAEnable | dms->LMBEnable) { register LAYER *layer; Forbid(); layer = WhichMouseLayer(); if (dms->LMBEnable && ev->ie_Code == IECODE_RBUTTON && (ev->ie_Qualifier & dms->RQual)) { register WIN *win; if (layer && (win = (WIN *)layer->Window) && !(win->Flags & BACKDROP) && (win->NextWindow || win->WScreen->FirstWindow != win)) WindowToBack(layer->Window); else if (IBASE->FirstScreen) ScreenToBack(IBASE->FirstScreen); ev->ie_Class = IECLASS_NULL; /* remove event */ } if (layer && layer->Window) { if (dms->LMBEnable && ev->ie_Code == IECODE_LBUTTON && layer->ClipRect && layer->ClipRect->Next) { /* * Note: Case where it is the 'first' click in a series, where dms->CTime is * garbage, works properly no matter what DoubleClick returns. */ if ((APTR)dms->CWin == layer->Window && DoubleClick(dms->CTime.tv_secs, dms->CTime.tv_micro, ev->ie_TimeStamp.tv_secs, ev->ie_TimeStamp.tv_micro)) --dms->CLeft; else dms->CLeft = dms->Clicks - 1; dms->CTime = ev->ie_TimeStamp; dms->CWin = (WIN *)layer->Window; if (dms->CLeft == 0) { dms->CLeft = dms->Clicks; WindowToFront(layer->Window); } } if (dms->AAEnable && ev->ie_Code == IECODE_NOBUTTON && !(ev->ie_Qualifier & 0x7000) && layer->Window != IBASE->ActiveWindow) ActivateWindow(layer->Window); } Permit(); } break; case IECLASS_RAWKEY: /* * Keyboard events will kill the screen timeout but not * the mouse timeout. */ { register LAYER *layer; Forbid(); layer = WhichMouseLayer(); if (layer && layer->Window) { if (dms->AAEnable && layer->Window != IBASE->ActiveWindow) ActivateWindow(layer->Window); } Permit(); } STime = ev->ie_TimeStamp.tv_secs + dms->STo; if (STimedout) sendrequest(REQ_SCREENON); STimedout = 0; if (ev->ie_Code == dms->Code && ev->ie_Qualifier == dms->Qual) { sendrequest(REQ_DOCMD); ev->ie_Class = IECLASS_NULL; /* remove event */ } break; case IECLASS_TIMER: /* * On a timer event, if timeout has occured execute the operation * and reset the timeout. Note that this will cause continuous * timeouts every STo and MTo seconds... required because at any * time Intuition might turn the mouse back on or open a screen or * something and I want the blanker's to work in the long run. */ { register long old; if (dms->STo && (old = STime - ev->ie_TimeStamp.tv_secs) < 0) { STime = ev->ie_TimeStamp.tv_secs + dms->STo + 10; STimedout = 1; if (old > -10) sendrequest(REQ_SCREENOFF); } if (dms->MTo && (old = MTime - ev->ie_TimeStamp.tv_secs) < 0) { MTime = ev->ie_TimeStamp.tv_secs + dms->MTo + 1; MTimedout = 1; if (old > -10) sendrequest(REQ_MOUSEOFF); } } break; } } return(Ev); } sendrequest(req) long req; { register MSG *msg = AllocMem(sizeof(MSG), MEMF_PUBLIC); if (msg) { msg->mn_Node.ln_Name = (char *)req; msg->mn_ReplyPort = NULL; msg->mn_Length = sizeof(MSG); PutMsg(&Dms->Port, msg); } } LAYER * WhichMouseLayer() { register struct IntuitionBase *ib = IBASE; register LAYER *layer = NULL; register SCR *scr = ib->FirstScreen; for (scr = ib->FirstScreen; scr; scr = scr->NextScreen) { register short mousey = ib->MouseY; if (!(scr->ViewPort.Modes & LACE)) mousey >>= 1; if (layer = WhichLayer(&scr->LayerInfo, ib->MouseX, mousey - scr->ViewPort.DyOffset)) break; if (mousey >= scr->ViewPort.DyOffset) break; } return(layer); }