home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d1xx
/
d145
/
dmouse.lha
/
DMouse
/
dmouse-handler.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-05-26
|
9KB
|
349 lines
/*
* 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<<dms->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);
}