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