home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d168 / dillonstuff.lha / src / dmouse / dmouse-handler.c next >
C/C++ Source or Header  |  1988-11-22  |  12KB  |  464 lines

  1.  
  2. /*
  3.  *  DMOUSE-HANDLER.C        compile 32 bit integers (+L), c32.lib
  4.  *                AZTEC COMPILATION
  5.  *  28 June 1988
  6.  *
  7.  *  Note on upping the handler process priority.  This is done to cause the
  8.  *  handler task to get CPU before the current input event completes its
  9.  *  processing so intuition calls made by the process are executed before
  10.  *  the event is propogated.  If said intuition calls block, it's ok
  11.  *  because they are not blocking the input handler process.
  12.  */
  13.  
  14. #include "dmouse.h"
  15.  
  16.  
  17. DMS    *Dms;
  18. IBASE    *IntuitionBase;
  19. GFXBASE *GfxBase;
  20. long    *LayersBase;
  21. long    *DResBase;
  22.  
  23. static PORT    *IPCPort = NULL;
  24.  
  25. static char    STimedout = 0;
  26. static char    MTimedout = 0;
  27. static long    STime = 0, MTime = 0;
  28.  
  29.  
  30. #define IBASE IntuitionBase
  31.  
  32. NS    Ns = {    0, 0, 64, -1, 1, -1, -1, 0, CUSTOMSCREEN|SCREENQUIET };
  33. IE DummyIE = { 0 };
  34.  
  35. IE *handler();
  36.  
  37. short    NRMe;    /*  Don't Repeat Mouse Events   */
  38.  
  39. _main()
  40. {
  41.     register DMS *dms;
  42.     IOR  *ior;
  43.     INT addhand;
  44.  
  45.     {
  46.     register PROC *proc = (PROC *)FindTask(NULL);
  47.     proc->pr_ConsoleTask = NULL;
  48.     }
  49.     NRMe = 0;
  50.     dms = Dms = (DMS *)FindPort(PORTNAME);
  51.     if (!dms)
  52.     _exit(0);
  53.     dms->Port.mp_Flags = PA_SIGNAL;
  54.     dms->Port.mp_SigBit = AllocSignal(-1);
  55.     dms->Port.mp_SigTask = FindTask(NULL);
  56.     dms->HandTask = dms->Port.mp_SigTask;
  57.     ior = CreateStdIO(&dms->Port);
  58.     IntuitionBase = OpenLibrary("intuition.library", 0);
  59.     GfxBase = OpenLibrary("graphics.library", 0);
  60.     LayersBase = OpenLibrary("layers.library", 0);
  61.     DResBase = OpenLibrary("dres.library", 0);      /*  not required    */
  62.  
  63.     if (!IntuitionBase || !GfxBase || !LayersBase)
  64.     goto startupfail;
  65.     addhand.is_Node.ln_Pri = dms->IPri;
  66.     addhand.is_Code = (FPTR)handler;
  67.     addhand.is_Data = NULL;
  68.  
  69.     if (OpenDevice("input.device", 0, ior, 0)) {
  70.     goto startupfail;
  71.     } else {
  72.     SCR *scr = NULL;
  73.     uword *SprSavePtr = NULL;
  74.     long ipc_mask = 0;
  75.  
  76.     Signal(dms->ShakeTask, 1 << dms->ShakeSig);
  77.     ior->io_Command = IND_ADDHANDLER;
  78.     ior->io_Data = (APTR)&addhand;
  79.     ior->io_Message.mn_Node.ln_Type = NT_MESSAGE;
  80.     DoIO(ior);
  81.  
  82.     if (DResBase) {
  83.         if (IPCPort = OpenIPC("dmouse.CMD", 0))
  84.         ipc_mask = 1 << IPCPort->mp_SigBit;
  85.     }
  86.     for (;;) {
  87.         register long sigs = Wait(SBF_C|(1<<dms->Port.mp_SigBit)|ipc_mask);
  88.         if (sigs & (1 << dms->Port.mp_SigBit)) {
  89.         register REQ *msg;
  90.         while (msg = GetMsg(&dms->Port)) {
  91.             switch((long)msg->Msg.mn_Node.ln_Name) {
  92.             case REQ_SCREENON:
  93.             if (scr)
  94.                 CloseScreen(scr);
  95.             scr = NULL;
  96.             break;
  97.             case REQ_SCREENOFF:
  98.             if (scr) {
  99.                 ScreenToFront(scr);
  100.             } else {
  101.                 if (scr = OpenScreen(&Ns))
  102.                 SetRGB4(&scr->ViewPort, 0, 0, 0, 0);
  103.             }
  104.             break;
  105.             case REQ_MOUSEON:
  106.             if (SprSavePtr) {
  107.                 register COPINIT *ci = GfxBase->copinit;
  108.                 ci->sprstrtup[1] = (ulong)SprSavePtr >> 16;
  109.                 ci->sprstrtup[3] = (uword)(long)SprSavePtr;
  110.                 SprSavePtr = NULL;
  111.             }
  112.             break;
  113.             case REQ_MOUSEOFF:
  114.             {
  115.                 register COPINIT *ci = GfxBase->copinit;
  116.                 if (!SprSavePtr)
  117.                 SprSavePtr = (uword *)((ci->sprstrtup[1] << 16) | ci->sprstrtup[3]);
  118.                 ci->sprstrtup[1] = (ulong)dms->NoSprData >> 16;
  119.                 ci->sprstrtup[3] = (uword)(long)dms->NoSprData;
  120.             }
  121.             break;
  122.             case REQ_DOCMD:
  123.             {
  124.                 long fh = Open("nil:", 1006);
  125.                 Execute(dms->Cmd, NULL, fh);
  126.                 if (fh)
  127.                 Close(fh);
  128.             }
  129.             break;
  130.             case REQ_RAWMOUSE:
  131.             {
  132.                 register LAYER *layer;
  133.  
  134.                 NRMe = 0;
  135.                 Forbid();
  136.                 layer = WhichMouseLayer();
  137.                 if (msg->ie_Code == IECODE_RBUTTON && dms->LMBEnable && (msg->ie_Qualifier & dms->RQual)) {
  138.                 register WIN *win;
  139.                 if (layer && (win = (WIN *)layer->Window) && !(win->Flags & BACKDROP) && (win->NextWindow || win->WScreen->FirstWindow != win)) {
  140.                     if (dms->Workbench)
  141.                     WindowToBack(win);
  142.                     else
  143.                     BehindLayer(0, layer);
  144.                 } else if (IBASE->FirstScreen)
  145.                     ScreenToBack(IBASE->FirstScreen);
  146.                 }
  147.                 if (layer && layer->Window) {
  148.                 if (msg->ie_Code == IECODE_LBUTTON && !(((WIN *)layer->Window)->Flags & BACKDROP) && dms->LMBEnable && layer->ClipRect && layer->ClipRect->Next) {
  149.                     /*
  150.                      *    Note: Case where it is the 'first' click in a series, where dms->CTime is
  151.                      *          garbage, works properly no matter what DoubleClick returns.
  152.                      */
  153.                     if (dms->LQual == 0 || (msg->ie_Qualifier & dms->LQual)) {
  154.                     if ((APTR)dms->CWin == layer->Window && DoubleClick(dms->CTime.tv_secs, dms->CTime.tv_micro, msg->ie_TimeStamp.tv_secs, msg->ie_TimeStamp.tv_micro))
  155.                         --dms->CLeft;
  156.                     else
  157.                         dms->CLeft = dms->Clicks - 1;
  158.                     dms->CTime = msg->ie_TimeStamp;
  159.                     dms->CWin = (WIN *)layer->Window;
  160.                     if (dms->CLeft == 0) {
  161.                         dms->CLeft = dms->Clicks;
  162.                         if (dms->Workbench)
  163.                         WindowToFront(layer->Window);
  164.                         else
  165.                         UpfrontLayer(0, layer);
  166.                     }
  167.                     }
  168.                 }
  169.                 if ((dms->AAEnable & 1) && layer->Window != IBASE->ActiveWindow && msg->ie_Code == IECODE_NOBUTTON && !(msg->ie_Qualifier & 0x7000)) {
  170.                     if (!IBASE->ActiveWindow || !IBASE->ActiveWindow->FirstRequest)
  171.                     ActivateWindow(layer->Window);
  172.                 }
  173.                 }
  174.                 Permit();
  175.             }
  176.             break;
  177.             case REQ_RAWKEY:
  178.             {
  179.                 register LAYER *layer;
  180.  
  181.                 Forbid();
  182.                 layer = WhichMouseLayer();
  183.                 if (layer && layer->Window && layer->Window != IBASE->ActiveWindow) {
  184.                 if (!IBASE->ActiveWindow || !IBASE->ActiveWindow->FirstRequest)
  185.                     ActivateWindow(layer->Window);
  186.                 }
  187.                 Permit();
  188.             }
  189.             break;
  190.             }
  191.             FreeMem(msg, msg->Msg.mn_Length);
  192.         }
  193.         }
  194.         if (sigs & SBF_C)
  195.         break;
  196.         if (sigs & ipc_mask) {
  197.         register IPCMSG *msg;
  198.         register char *ptr;
  199.         long req;
  200.         while (msg = GetMsg(IPCPort)) {
  201.             req = 0;
  202.             if (ptr = (char *)msg->TBuf) {
  203.             while (*ptr++);
  204.             if (strcmp(ptr, "blank") == 0) {
  205.                 req = REQ_SCREENOFF;
  206.                 STimedout = 1;
  207.             }
  208.             if (strcmp(ptr, "noblank") == 0)
  209.                 req = REQ_SCREENON;
  210.             if (strcmp(ptr, "mouse") == 0)
  211.                 req = REQ_MOUSEON;
  212.             if (strcmp(ptr, "nomouse") == 0) {
  213.                 MTimedout = 1;
  214.                 req = REQ_MOUSEOFF;
  215.             }
  216.             }
  217.             if (req)
  218.             sendrequest(req, NULL);
  219.             ReplyIPC(msg, NULL, 0, ((req)?0:IF_NOTFND));
  220.         }
  221.         }
  222.     }
  223.     ior->io_Command = IND_REMHANDLER;
  224.     ior->io_Data = (APTR)&addhand;
  225.     ior->io_Message.mn_Node.ln_Type = NT_MESSAGE;
  226.     DoIO(ior);
  227.     ior->io_Command = IND_WRITEEVENT;    /*  NULL EVENT    */
  228.     ior->io_Length = sizeof(IE);
  229.     ior->io_Data = (APTR)&DummyIE;
  230.     ior->io_Message.mn_Node.ln_Type = NT_MESSAGE;
  231.     DoIO(ior);
  232.     CloseDevice(ior);
  233.     {
  234.         register MSG *msg;
  235.         while (msg = GetMsg(&dms->Port))
  236.         FreeMem(msg, msg->mn_Length);
  237.     }
  238.     if (scr)
  239.         CloseScreen(scr);
  240.     if (SprSavePtr) {
  241.         register COPINIT *ci = GfxBase->copinit;
  242.         ci->sprstrtup[1] = (ulong)SprSavePtr >> 16;
  243.         ci->sprstrtup[3] = (uword)(long)SprSavePtr;
  244.         SprSavePtr = NULL;
  245.     }
  246.     }
  247.     goto closedown;
  248. startupfail:
  249.     dms->StartupError = 1;
  250.     Signal(dms->ShakeTask, 1 << dms->ShakeSig);
  251.     Wait(SBF_C);
  252. closedown:
  253.     DeleteStdIO(ior);
  254. fail:
  255.     if (IPCPort)
  256.     CloseIPC(IPCPort);
  257.     if (DResBase)
  258.     CloseLibrary(DResBase);
  259.     if (IntuitionBase)
  260.     CloseLibrary(IntuitionBase);
  261.     if (GfxBase)
  262.     CloseLibrary(GfxBase);
  263.     if (LayersBase)
  264.     CloseLibrary(LayersBase);
  265.     Forbid();
  266.     Signal(dms->ShakeTask, 1 << dms->ShakeSig);
  267. }
  268.  
  269.  
  270. #asm
  271.         ;    A0 = pointer to event linked list
  272.         ;    A1 = pointer to my data segment
  273.         ;    return new event linked list in D0
  274.  
  275.         public  _CHandler
  276.  
  277. _handler:
  278.         movem.l D2/D3/A0/A1/A4/A6,-(sp)
  279.         jsr     _CHandler
  280.         movem.l (sp)+,D2/D3/A0/A1/A4/A6
  281.         rts
  282.  
  283. #endasm
  284.  
  285. /*
  286.  *  (1) Accellerate mouse movements.
  287.  *  (2) Auto-Select window
  288.  */
  289.  
  290. IE *
  291. CHandler(scr0, scr1, Ev)
  292. IE *Ev;
  293. {
  294.     register IE *ev;
  295.     register DMS *dms;
  296.  
  297.     geta4();
  298.     dms = Dms;
  299.     for (ev = Ev; ev; ev = Ev->ie_NextEvent) {
  300.     switch(ev->ie_Class) {
  301.     case IECLASS_RAWMOUSE:
  302.         /*
  303.          *    Mouse events restore both the screen and mouse pointer.
  304.          */
  305.  
  306.         STime = ev->ie_TimeStamp.tv_secs + dms->STo;
  307.         MTime = ev->ie_TimeStamp.tv_secs + dms->MTo;
  308.         if (STimedout)
  309.         sendrequest(REQ_SCREENON, ev);
  310.         if (MTimedout)
  311.         sendrequest(REQ_MOUSEON, ev);
  312.         STimedout = MTimedout = 0;
  313.  
  314.         /*
  315.          *    Mouse Acceleration
  316.          */
  317.         {
  318.         register short n;
  319.         register short s;
  320.  
  321.         if (dms->Acc != 1) {
  322.             n = ev->ie_X;
  323.             s = 1;
  324.             if (n < 0) {
  325.             n = -n;
  326.             s = -1;
  327.             }
  328.             if (n > dms->AThresh)
  329.             ev->ie_X = s * (short)((n - dms->AThresh - 1) * dms->Acc + dms->AThresh + 1);
  330.             n = ev->ie_Y;
  331.             s = 1;
  332.             if (n < 0) {
  333.             n = -n;
  334.             s = -1;
  335.             }
  336.             if (n > dms->AThresh)
  337.             ev->ie_Y = s * (short)((n - dms->AThresh - 1) * dms->Acc + dms->AThresh + 1);
  338.         }
  339.         }
  340.  
  341.         /*
  342.          *    Auto Activate and LMB (win/scrn front/bak)
  343.          */
  344.  
  345.         if (dms->LMBEnable && ev->ie_Code == IECODE_RBUTTON && (ev->ie_Qualifier & dms->RQual))
  346.         ev->ie_Class = IECLASS_NULL;    /*  remove event    */
  347.         if (NRMe == 0 && ((dms->AAEnable & 1) || dms->LMBEnable)) {
  348.         register short old;
  349.         NRMe = 1;
  350.         if (ev->ie_Code != IECODE_NOBUTTON)
  351.             old = SetTaskPri(dms->Port.mp_SigTask, 21);
  352.         sendrequest(REQ_RAWMOUSE, ev);
  353.         if (ev->ie_Code != IECODE_NOBUTTON)
  354.             SetTaskPri(dms->Port.mp_SigTask, old);
  355.         }
  356.         break;
  357.     case IECLASS_RAWKEY:
  358.         /*
  359.          *    Keyboard events will kill the screen timeout but not
  360.          *    the mouse timeout.  Note that the priority of the
  361.          *    co-process must be upped to ensure it is able to make the
  362.          *    window active before the keystroke is passed further.
  363.          *
  364.          *    key releases are ignored
  365.          */
  366.         if (ev->ie_Code & 0x80)
  367.         break;
  368.         if (dms->AAEnable & 2) {
  369.         register short old = SetTaskPri(dms->Port.mp_SigTask, 21);
  370.         sendrequest(REQ_RAWKEY, ev);
  371.         SetTaskPri(dms->Port.mp_SigTask, old);
  372.         }
  373.         STime = ev->ie_TimeStamp.tv_secs + dms->STo;
  374.         if (STimedout) {
  375.         sendrequest(REQ_SCREENON, ev);
  376.         if (dms->MTo == 0)
  377.             sendrequest(REQ_MOUSEON, ev);
  378.         }
  379.         STimedout = 0;
  380.         if (ev->ie_Code == dms->Code && ev->ie_Qualifier == dms->Qual) {
  381.         sendrequest(REQ_DOCMD, ev);
  382.         ev->ie_Class = IECLASS_NULL;    /*  remove event    */
  383.         }
  384.         break;
  385.     case IECLASS_TIMER:
  386.         /*
  387.          *    On a timer event, if timeout has occured execute the operation
  388.          *    and reset the timeout.    Note that this will cause continuous
  389.          *    timeouts every STo and MTo seconds... required because at any
  390.          *    time Intuition might turn the mouse back on or open a screen or
  391.          *    something and I want the blanker's to work in the long run.
  392.          */
  393.         {
  394.         register long old;
  395.         if (dms->Reset) {
  396.             dms->Reset = 0;
  397.             STime = ev->ie_TimeStamp.tv_secs + dms->STo;
  398.             MTime = ev->ie_TimeStamp.tv_secs + dms->MTo;
  399.         }
  400.         if (dms->STo && (old = STime - ev->ie_TimeStamp.tv_secs) < 0) {
  401.             STime = ev->ie_TimeStamp.tv_secs + dms->STo + 10;
  402.             STimedout = 1;
  403.             MTimedout = 1;
  404.             if (old > -10) {
  405.             sendrequest(REQ_SCREENOFF, ev);
  406.             sendrequest(REQ_MOUSEOFF, ev);
  407.             }
  408.         }
  409.         if (dms->MTo && (old = MTime - ev->ie_TimeStamp.tv_secs) < 0) {
  410.             MTime = ev->ie_TimeStamp.tv_secs + dms->MTo + 1;
  411.             MTimedout = 1;
  412.             if (old > -10)
  413.             sendrequest(REQ_MOUSEOFF, ev);
  414.         }
  415.         }
  416.         break;
  417.     }
  418.     }
  419.     return(Ev);
  420. }
  421.  
  422. sendrequest(creq, ev)
  423. long creq;
  424. register IE *ev;
  425. {
  426.     register REQ *req = AllocMem(sizeof(REQ), MEMF_PUBLIC);
  427.  
  428.     if (req) {
  429.     req->Msg.mn_Node.ln_Name = (char *)creq;
  430.     req->Msg.mn_ReplyPort = NULL;
  431.     req->Msg.mn_Length = sizeof(REQ);
  432.     if (ev) {
  433.         req->ie_Code = ev->ie_Code;
  434.         req->ie_Qualifier = ev->ie_Qualifier;
  435.         req->ie_TimeStamp = ev->ie_TimeStamp;
  436.     }
  437.     PutMsg(&Dms->Port, req);
  438.     }
  439. }
  440.  
  441. LAYER *
  442. WhichMouseLayer()
  443. {
  444.     register struct IntuitionBase *ib = IBASE;
  445.     register LAYER *layer = NULL;
  446.     register SCR *scr = ib->FirstScreen;
  447.  
  448.     for (scr = ib->FirstScreen; scr; scr = scr->NextScreen) {
  449.     register short mousey = ib->MouseY;
  450.     register short mousex = ib->MouseX;
  451.     if (!(scr->ViewPort.Modes & LACE))
  452.         mousey >>= 1;
  453.     if (!(scr->ViewPort.Modes & HIRES))
  454.         mousex >>= 1;
  455.     if (layer = WhichLayer(&scr->LayerInfo, mousex, mousey - scr->ViewPort.DyOffset))
  456.         break;
  457.     if (mousey >= scr->ViewPort.DyOffset)
  458.         break;
  459.     }
  460.     return(layer);
  461. }
  462.  
  463.  
  464.