home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 152.lha / DMouse_v1.09 / dmouse-handler.c < prev    next >
C/C++ Source or Header  |  1988-04-26  |  15KB  |  378 lines

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