home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff258.lzh / DMouse / dmouse-handler.c < prev    next >
C/C++ Source or Header  |  1989-10-18  |  17KB  |  678 lines

  1.  
  2. /*
  3.  *  DMOUSE-HANDLER.C
  4.  *
  5.  *  (c)Copyright 1989 by Matthew Dillon, All Rights Reserved
  6.  *
  7.  *  V1.20, last revision 3 August 1989
  8.  *
  9.  *  Note on upping the handler process priority.  This is done to cause the
  10.  *  handler task to get CPU before the current input event completes its
  11.  *  processing so intuition calls made by the process are executed before
  12.  *  the event is propogated.  If said intuition calls block, it's ok
  13.  *  because they are not blocking the input handler process.
  14.  */
  15.  
  16. #include "dmouse.h"
  17.  
  18. #ifdef LATTICE
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #endif
  23.  
  24. /*typedef struct Layer          LAYER;*/
  25. typedef struct IE        *IEP;
  26. typedef struct IORequest    IORequest;
  27.  
  28. DMS    *Dms               = NULL;
  29. IBASE    *IntuitionBase           = NULL;
  30. GFXBASE *GfxBase           = NULL;
  31. struct LayersBase  *LayersBase = NULL;
  32. struct ExecBase    *SysBase    = NULL;
  33.  
  34. static PORT    *IOPort = NULL;     /*    For IPC messages          */
  35. static LIST    BlankList;        /*    list of external blanker programs */
  36.  
  37. static char    STimedout = 0;
  38. static char    MTimedout = 0;
  39. static long    STime = 0, MTime = 0;
  40. #ifdef DEBUG
  41. static long    DBFh = NULL;
  42. #endif
  43. static void    *ReqCache = NULL;   /*    to prevent massive AllocMem()s    */
  44.  
  45.  
  46. #define IBASE IntuitionBase
  47.  
  48. NS    Ns = {    0, 0, 64, -1, 1, -1, -1, 0, CUSTOMSCREEN|SCREENQUIET };
  49. IE DummyIE = { 0 };
  50.  
  51. short    NRMe;    /*  Don't Repeat Mouse Events   */
  52.  
  53. #ifdef LATTICE
  54. __asm __saveds IEP handler(register __a0 IE *event);
  55. #else
  56. IE *handler();
  57. #endif
  58.  
  59. LAYER *WhichMouseLayer ARGS((void));
  60. void sendrequest ARGS((long, IE *));
  61. LAYER *WhichMouseLayer ARGS((void));
  62. int doipcmsg ARGS((short));
  63. void DeleteBlanker ARGS((IORequest *));
  64. __saveds void noname ARGS((void));
  65.  
  66. #ifdef LATTICE
  67. __saveds void
  68. noname()
  69. #else
  70. _main()
  71. #endif
  72. {
  73.  
  74.     reg DMS *dms;
  75.     IOR  *ior;
  76.     INT addhand;
  77.  
  78. #ifndef LATTICE
  79.     geta4();
  80. #endif
  81.     SysBase = *(struct ExecBase **)4;
  82. #ifdef LATTICE
  83.     {
  84.     DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 0);
  85.     }
  86. #endif
  87.     {
  88.     reg PROC *proc = (PROC *)FindTask(NULL);
  89.     proc->pr_ConsoleTask = NULL;
  90.     }
  91.     NRMe = 0;
  92.     dms = Dms = (DMS *)FindPort(PORTNAME);
  93.     if (!dms)
  94.     return;
  95.     dms->Port.mp_Flags = PA_SIGNAL;
  96.     dms->Port.mp_SigBit = AllocSignal(-1);
  97.     dms->Port.mp_SigTask = FindTask(NULL);
  98.     dms->HandTask = dms->Port.mp_SigTask;
  99.     ior = CreateStdIO(&dms->Port);
  100.     IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 0);
  101.     GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0);
  102.     LayersBase = (struct LayersBase *)OpenLibrary("layers.library", 0);
  103.     IOPort = CreatePort("DMouse.ipc", 0);
  104.     NewList(&BlankList);
  105.  
  106.     if (!IntuitionBase || !GfxBase || !LayersBase)
  107.     goto startupfail;
  108.     addhand.is_Node.ln_Pri = dms->IPri;
  109.     addhand.is_Code = (FPTR)handler;
  110.     addhand.is_Data = NULL;
  111.  
  112.     if (OpenDevice("input.device", 0, ior, 0)) {
  113.     goto startupfail;
  114.     } else {
  115.     SCR *scr = NULL;
  116.     uword *SprSavePtr = NULL;
  117.     long ipc_mask;
  118.  
  119.     Signal(dms->ShakeTask, 1 << dms->ShakeSig);
  120.     ior->io_Command = IND_ADDHANDLER;
  121.     ior->io_Data = (APTR)&addhand;
  122.     ior->io_Message.mn_Node.ln_Type = NT_MESSAGE;
  123.     DoIO(ior);
  124.  
  125.     ipc_mask = 1 << IOPort->mp_SigBit;
  126.  
  127.     for (;;) {
  128.         reg long sigs = Wait(SBF_C|(1<<dms->Port.mp_SigBit)|ipc_mask);
  129.         if (sigs & (1 << dms->Port.mp_SigBit)) {
  130.         reg REQ *msg;
  131.         while (msg = (REQ *)GetMsg(&dms->Port)) {
  132.             switch((long)msg->Msg.mn_Node.ln_Name) {
  133.             case REQ_SCREENON:
  134.             if (scr)
  135.                 CloseScreen(scr);
  136.             scr = NULL;
  137.             doipcmsg(0x82);
  138.             break;
  139.             case REQ_SCREENOFF:
  140.             if (scr)
  141.                 ScreenToFront(scr);
  142.             if (doipcmsg(0x83) == 0 && scr == NULL) {
  143.                 if (scr = OpenScreen(&Ns))
  144.                 SetRGB4(&scr->ViewPort, 0, 0, 0, 0);
  145.             }
  146.             break;
  147.             case REQ_MOUSEON:
  148.             if (SprSavePtr) {
  149.                 register COPINIT *ci = GfxBase->copinit;
  150.                 ci->sprstrtup[1] = (ulong)SprSavePtr >> 16;
  151.                 ci->sprstrtup[3] = (uword)(long)SprSavePtr;
  152.                 SprSavePtr = NULL;
  153.             }
  154.             doipcmsg(0x80);
  155.             break;
  156.             case REQ_MOUSEOFF:
  157.             if (doipcmsg(0x81) == 0) {
  158.                 reg COPINIT *ci = GfxBase->copinit;
  159.                 if (ci->sprstrtup[0] != 0x120 || ci->sprstrtup[2] != 0x122)
  160.                 break;
  161.  
  162.                 if (!SprSavePtr)
  163.                 SprSavePtr = (uword *)((ci->sprstrtup[1] << 16) | ci->sprstrtup[3]);
  164.                 ci->sprstrtup[1] = (ulong)dms->NoSprData >> 16;
  165.                 ci->sprstrtup[3] = (uword)(long)dms->NoSprData;
  166.             }
  167.             break;
  168.             case REQ_DOCMD:
  169.             {
  170.                 long fh = (long)Open("nil:", 1006);
  171.                 Execute(dms->Cmd, NULL, fh);
  172.                 if (fh)
  173.                 Close(fh);
  174.             }
  175.             break;
  176.             case REQ_RAWMOUSE:
  177.             {
  178.                 register LAYER *layer;
  179.  
  180.                 NRMe = 0;
  181.                 Forbid();
  182.                 layer = WhichMouseLayer();
  183.                 if (msg->ie_Code == IECODE_RBUTTON && dms->LMBEnable && (msg->ie_Qualifier & dms->RQual)) {
  184.                 register WIN *win;
  185.                 if (layer && (win = (WIN *)layer->Window) && !(win->Flags & BACKDROP) && (win->NextWindow || win->WScreen->FirstWindow != win)) {
  186.                     if (dms->Workbench)
  187.                     WindowToBack(win);
  188.                     else
  189.                     BehindLayer(0, layer);
  190.                 } else if (IBASE->FirstScreen)
  191.                     ScreenToBack(IBASE->FirstScreen);
  192.                 }
  193.                 if (layer && layer->Window) {
  194.                 if (msg->ie_Code == IECODE_LBUTTON && !(((WIN *)layer->Window)->Flags & BACKDROP) && dms->LMBEnable && layer->ClipRect && layer->ClipRect->Next) {
  195.                     /*
  196.                      *    Note: Case where it is the 'first' click in a series, where dms->CTime is
  197.                      *          garbage, works properly no matter what DoubleClick returns.
  198.                      */
  199.                     if (dms->LQual == 0 || (msg->ie_Qualifier & dms->LQual)) {
  200.                     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))
  201.                         --dms->CLeft;
  202.                     else
  203.                         dms->CLeft = dms->Clicks - 1;
  204.                     dms->CTime = msg->ie_TimeStamp;
  205.                     dms->CWin = (WIN *)layer->Window;
  206.                     if (dms->CLeft == 0) {
  207.                         dms->CLeft = dms->Clicks;
  208.                         if (dms->Workbench)
  209.                         WindowToFront((WIN *)layer->Window);
  210.                         else
  211.                         UpfrontLayer(0, layer);
  212.                     }
  213.                     }
  214.                 }
  215.                 if ((dms->AAEnable & 1) && (void *)layer->Window != (void *)IBASE->ActiveWindow && msg->ie_Code == IECODE_NOBUTTON && !(msg->ie_Qualifier & 0x7000)) {
  216.                     if (!IBASE->ActiveWindow || !IBASE->ActiveWindow->FirstRequest)
  217.                     ActivateWindow((WIN *)layer->Window);
  218.                 }
  219.                 }
  220.                 Permit();
  221.             }
  222.             break;
  223.             case REQ_RAWKEY:
  224.             {
  225.                 register LAYER *layer;
  226.  
  227.                 Forbid();
  228.                 layer = WhichMouseLayer();
  229.                 if (layer && layer->Window && (void *)layer->Window != (void *)IBASE->ActiveWindow) {
  230.                 if (!IBASE->ActiveWindow || !IBASE->ActiveWindow->FirstRequest)
  231.                     ActivateWindow((WIN *)layer->Window);
  232.                 }
  233.                 Permit();
  234.             }
  235.             break;
  236. #ifdef DEBUG
  237.             case REQ_DEBUG:
  238.             {
  239.                 char buf[128];
  240.                 if (!DBFh) {
  241.                 DBFh = Open("con:0/0/400/100/dmouse-debug", 1006);
  242.                 if (!DBFh)
  243.                     break;
  244.                 }
  245.                 sprintf(buf, "%02lx %04lx %04lx\n",
  246.                 msg->ie_Class,
  247.                 msg->ie_Code,
  248.                 msg->ie_Qualifier
  249.                 );
  250.                 Write(DBFh, buf, strlen(buf));
  251.             }
  252.             break;
  253.             case REQ_DEBUGOFF:
  254.             if (DBFh) {
  255.                 Close(DBFh);
  256.                 DBFh = NULL;
  257.             }
  258.             break;
  259. #endif
  260.             }
  261.             if (ReqCache == NULL && msg->Msg.mn_Length == sizeof(REQ))
  262.             ReqCache = (void *)msg;
  263.             else
  264.             FreeMem(msg, msg->Msg.mn_Length);
  265.         }
  266.         }
  267.         if (sigs & SBF_C)
  268.         break;
  269.  
  270.         /*
  271.          *    IPC request.
  272.          */
  273.  
  274.         if (sigs & ipc_mask) {
  275.         reg IORequest *ior;
  276.         while (ior = (IORequest *)GetMsg(IOPort)) {
  277.             long req = 0;
  278.  
  279.             if (ior->io_Message.mn_Node.ln_Type == NT_REPLYMSG) {
  280.             FreeMem(ior, ior->io_Message.mn_Length);
  281.             continue;
  282.             }
  283.  
  284.             ior->io_Error = 0;
  285.             switch(ior->io_Command) {
  286.             case 0x80:    /* mouse on  */
  287.             req = REQ_MOUSEON;
  288.             break;
  289.             case 0x81:    /* mouse off */
  290.             req = REQ_MOUSEOFF;
  291.             MTimedout = 1;
  292.             break;
  293.             case 0x82:    /* screen on */
  294.             req = REQ_SCREENON;
  295.             break;
  296.             case 0x83:    /* screen off*/
  297.             req = REQ_SCREENOFF;
  298.             STimedout = 1;
  299.             break;
  300.             case 0x84:    /* add hand  */
  301.             AddHead(&BlankList, ior);
  302.             ior = NULL;
  303.             break;
  304.             case 0x85:    /* rem hand  */
  305.             DeleteBlanker(ior);
  306.             ior = NULL;
  307.             break;
  308.             }
  309.             if (req)
  310.             sendrequest(req, NULL);
  311.             if (ior)
  312.             ReplyMsg(&ior->io_Message);
  313.         }
  314.         }
  315.     }
  316. #ifdef DEBUG
  317.     if (DBFh) {
  318.         Close(DBFh);
  319.         DBFh = NULL;
  320.     }
  321. #endif
  322.     ior->io_Command = IND_REMHANDLER;
  323.     ior->io_Data = (APTR)&addhand;
  324.     ior->io_Message.mn_Node.ln_Type = NT_MESSAGE;
  325.     DoIO(ior);
  326.     ior->io_Command = IND_WRITEEVENT;    /*  NULL EVENT    */
  327.     ior->io_Length = sizeof(IE);
  328.     ior->io_Data = (APTR)&DummyIE;
  329.     ior->io_Message.mn_Node.ln_Type = NT_MESSAGE;
  330.     DoIO(ior);
  331.     CloseDevice(ior);
  332.     {
  333.         reg MSG *msg;
  334.         while (msg = GetMsg(&dms->Port))
  335.         FreeMem(msg, msg->mn_Length);
  336.     }
  337.     if (scr)
  338.         CloseScreen(scr);
  339.     if (SprSavePtr) {
  340.         reg COPINIT *ci = GfxBase->copinit;
  341.         ci->sprstrtup[1] = (ulong)SprSavePtr >> 16;
  342.         ci->sprstrtup[3] = (uword)(long)SprSavePtr;
  343.         SprSavePtr = NULL;
  344.     }
  345.     }
  346.     goto closedown;
  347. startupfail:
  348.     dms->StartupError = 1;
  349.     Signal(dms->ShakeTask, 1 << dms->ShakeSig);
  350.     Wait(SBF_C);
  351. closedown:
  352.     DeleteStdIO(ior);
  353. fail:
  354.     if (IOPort) {
  355.     IORequest *ior;     /*    wait for RemReq messages */
  356.  
  357.     doipcmsg(0x86);     /*  send closedown requests  */
  358.     Forbid();
  359.     while (GetHead(&BlankList)) {
  360.         WaitPort(IOPort);
  361.         while (ior = (IORequest *)GetMsg(IOPort)) {
  362.         if (ior->io_Message.mn_Node.ln_Type == NT_REPLYMSG) {
  363.             FreeMem(ior, ior->io_Message.mn_Length);
  364.             continue;
  365.         }
  366.         if (ior->io_Command == 0x85)    /*  receive remove req  */
  367.             DeleteBlanker(ior);
  368.         else
  369.             ReplyMsg(&ior->io_Message);              /*  ignore other reqs   */
  370.         }
  371.     }
  372.     DeletePort(IOPort);
  373.     Permit();
  374.     }
  375.     if (IntuitionBase)
  376.     CloseLibrary((LIB *)IntuitionBase);
  377.     if (GfxBase)
  378.     CloseLibrary((LIB *)GfxBase);
  379.     if (LayersBase)
  380.     CloseLibrary((LIB *)LayersBase);
  381. #ifdef LATTICE
  382.     {
  383.     CloseLibrary((LIB *)DOSBase);
  384.     }
  385. #endif
  386.     if (ReqCache)
  387.     FreeMem(ReqCache, sizeof(REQ));
  388.     Forbid();
  389.     Signal(dms->ShakeTask, 1 << dms->ShakeSig);
  390. }
  391.  
  392. void
  393. DeleteBlanker(ior)
  394. IORequest *ior;
  395. {
  396.     IORequest *io2;
  397.  
  398.     ior->io_Error = 0;
  399.     for (io2 = GetHead(&BlankList); io2; io2 = GetSucc(io2)) {
  400.     if (io2->io_Unit == ior->io_Unit) {
  401.         Remove(io2);
  402.         if (ior)
  403.         ReplyMsg(&ior->io_Message);
  404.         ReplyMsg(&io2->io_Message);
  405.         ior = NULL;
  406.     }
  407.     }
  408.     if (ior) {
  409.     ior->io_Error = -1;
  410.     ReplyMsg(&ior->io_Message);
  411.     }
  412. }
  413.  
  414. doipcmsg(cmd)
  415. short cmd;
  416. {
  417.     short count = 0;
  418.     short flags = 1 << (cmd & 0x7F);    /*  enable flags */
  419.     IORequest *iob, *io;
  420.  
  421.     for (iob = GetHead(&BlankList); iob; iob = GetSucc(iob)) {
  422.     if (cmd == 0x86 || (iob->io_Flags & flags)) {
  423.         io = AllocMem(sizeof(IORequest), MEMF_PUBLIC|MEMF_CLEAR);
  424.         if (io) {
  425.         io->io_Command = cmd;
  426.         io->io_Unit = iob->io_Unit;
  427.         io->io_Message.mn_ReplyPort = IOPort;
  428.         io->io_Message.mn_Length = sizeof(IORequest);
  429.         PutMsg(iob->io_Message.mn_ReplyPort, &io->io_Message);
  430.         ++count;
  431.         }
  432.     }
  433.     }
  434.     return((int)count);
  435. }
  436.  
  437. /*
  438.  *  The INPUT.DEVICE HANDLER
  439.  *
  440.  *  Note that for Lattice V5.02 and beyond we need no
  441.  *  assembly tags because we can specify that the arguments
  442.  *  are passed in registers.
  443.  */
  444.  
  445. #ifndef LATTICE
  446.  
  447. #asm
  448.         ;    A0 = pointer to event linked list
  449.         ;    A1 = pointer to my data segment
  450.         ;    return new event linked list in D0
  451.  
  452.         public  _CHandler
  453.  
  454. _handler:
  455.         movem.l D2/D3/A0/A1/A4/A6,-(sp)
  456.         jsr     _CHandler
  457.         movem.l (sp)+,D2/D3/A0/A1/A4/A6
  458.         rts
  459.  
  460. #endasm
  461.  
  462. #endif
  463.  
  464. /*
  465.  *  (1) Accellerate mouse movements.
  466.  *  (2) Auto-Select window
  467.  */
  468.  
  469. #ifdef LATTICE
  470.  
  471. __asm __saveds IEP
  472. handler(register __a0 IE *Ev)
  473. {
  474.  
  475. #else
  476.  
  477. IE *
  478. CHandler(scr0, scr1, Ev)
  479. long scr0;
  480. long scr1;
  481. IE *Ev;
  482. {
  483. #endif
  484.     reg IE *ev;
  485.     reg DMS *dms;
  486.  
  487. #ifndef LATTICE
  488.     geta4();
  489. #endif
  490.     dms = Dms;
  491.     for (ev = Ev; ev; ev = Ev->ie_NextEvent) {
  492. #ifdef DEBUG
  493.     if (dms->Debug) {
  494.         if (ev->ie_Class != IECLASS_TIMER)
  495.         sendrequest(REQ_DEBUG, ev);
  496.     } else if (DBFh) {
  497.         sendrequest(REQ_DEBUGOFF, ev);
  498.     }
  499. #endif
  500.     switch(ev->ie_Class) {
  501.     case IECLASS_RAWMOUSE:
  502.         /*
  503.          *    Mouse events restore both the screen and mouse pointer.
  504.          */
  505.  
  506.         STime = ev->ie_TimeStamp.tv_secs + dms->STo;
  507.         MTime = ev->ie_TimeStamp.tv_secs + dms->MTo;
  508.         if (STimedout)
  509.         sendrequest(REQ_SCREENON, ev);
  510.         if (MTimedout)
  511.         sendrequest(REQ_MOUSEON, ev);
  512.         STimedout = MTimedout = 0;
  513.  
  514.         /*
  515.          *    Mouse Acceleration
  516.          */
  517.         {
  518.         register short n;
  519.         register short s;
  520.  
  521.         if (dms->Acc != 1) {
  522.             n = ev->ie_X;
  523.             s = 1;
  524.             if (n < 0) {
  525.             n = -n;
  526.             s = -1;
  527.             }
  528.             if (n > dms->AThresh)
  529.             ev->ie_X = s * (short)((n - dms->AThresh - 1) * dms->Acc + dms->AThresh + 1);
  530.             n = ev->ie_Y;
  531.             s = 1;
  532.             if (n < 0) {
  533.             n = -n;
  534.             s = -1;
  535.             }
  536.             if (n > dms->AThresh)
  537.             ev->ie_Y = s * (short)((n - dms->AThresh - 1) * dms->Acc + dms->AThresh + 1);
  538.         }
  539.         }
  540.  
  541.         /*
  542.          *    Auto Activate and LMB (win/scrn front/bak)
  543.          */
  544.  
  545.         if (dms->LMBEnable && ev->ie_Code == IECODE_RBUTTON && (ev->ie_Qualifier & dms->RQual))
  546.         ev->ie_Class = IECLASS_NULL;    /*  remove event    */
  547.         if (NRMe == 0 && ((dms->AAEnable & 1) || dms->LMBEnable)) {
  548.         register short old;
  549.         NRMe = 1;
  550.         if (ev->ie_Code != IECODE_NOBUTTON)
  551.             old = SetTaskPri(dms->Port.mp_SigTask, 21);
  552.         sendrequest(REQ_RAWMOUSE, ev);
  553.         if (ev->ie_Code != IECODE_NOBUTTON) {
  554.             SetTaskPri(dms->Port.mp_SigTask, old);
  555.             WaitTOF();  /*  cause a delay   */
  556.         }
  557.         }
  558.         break;
  559.     case IECLASS_RAWKEY:
  560.         /*
  561.          *    Keyboard events will kill the screen timeout but not
  562.          *    the mouse timeout.  Note that the priority of the
  563.          *    co-process must be upped to ensure it is able to make the
  564.          *    window active before the keystroke is passed further.
  565.          *
  566.          *    key releases are ignored
  567.          *
  568.          *    note: ie_Qualifier may or may not have bit 15 set
  569.          */
  570.         if (ev->ie_Code & 0x80)
  571.         break;
  572.         if (dms->AAEnable & 2) {
  573.         register short old;
  574.         old = SetTaskPri(dms->Port.mp_SigTask, 21);
  575.         sendrequest(REQ_RAWKEY, ev);
  576.         SetTaskPri(dms->Port.mp_SigTask, old);
  577.         WaitTOF();  /*  cause a delay   */
  578.         }
  579.         STime = ev->ie_TimeStamp.tv_secs + dms->STo;
  580.         if (STimedout) {
  581.         sendrequest(REQ_SCREENON, ev);
  582.         if (dms->MTo == 0)
  583.             sendrequest(REQ_MOUSEON, ev);
  584.         }
  585.         STimedout = 0;
  586.  
  587.         if (ev->ie_Code == dms->Code && (ev->ie_Qualifier | 0x8000) == dms->Qual) {
  588.         sendrequest(REQ_DOCMD, ev);
  589.         ev->ie_Class = IECLASS_NULL;    /*  remove event    */
  590.         }
  591.         break;
  592.     case IECLASS_TIMER:
  593.         /*
  594.          *    On a timer event, if timeout has occured execute the operation
  595.          *    and reset the timeout.    Note that this will cause continuous
  596.          *    timeouts every STo and MTo seconds... required because at any
  597.          *    time Intuition might turn the mouse back on or open a screen or
  598.          *    something and I want the blanker's to work in the long run.
  599.          */
  600.         {
  601.         register long old;
  602.         if (dms->Reset) {
  603.             dms->Reset = 0;
  604.             STime = ev->ie_TimeStamp.tv_secs + dms->STo;
  605.             MTime = ev->ie_TimeStamp.tv_secs + dms->MTo;
  606.         }
  607.         if (dms->STo && (old = STime - ev->ie_TimeStamp.tv_secs) < 0) {
  608.             STime = ev->ie_TimeStamp.tv_secs + dms->STo + 10;
  609.             STimedout = 1;
  610.             MTimedout = 1;
  611.             if (old > -10) {
  612.             sendrequest(REQ_SCREENOFF, ev);
  613.             sendrequest(REQ_MOUSEOFF, ev);
  614.             }
  615.         }
  616.         if (dms->MTo && (old = MTime - ev->ie_TimeStamp.tv_secs) < 0) {
  617.             MTime = ev->ie_TimeStamp.tv_secs + dms->MTo + 1;
  618.             MTimedout = 1;
  619.             if (old > -10)
  620.             sendrequest(REQ_MOUSEOFF, ev);
  621.         }
  622.         }
  623.         break;
  624.     }
  625.     }
  626.     return(Ev);
  627. }
  628.  
  629. void
  630. sendrequest(creq, ev)
  631. long creq;
  632. reg IE *ev;
  633. {
  634.     reg REQ *req;
  635.  
  636.     if (req = ReqCache)
  637.     ReqCache = NULL;
  638.     else
  639.     req = AllocMem(sizeof(REQ), MEMF_PUBLIC);
  640.  
  641.     if (req) {
  642.     req->Msg.mn_Node.ln_Name = (char *)creq;
  643.     req->Msg.mn_ReplyPort = NULL;
  644.     req->Msg.mn_Length = sizeof(REQ);
  645.     if (ev) {
  646.         req->ie_Class= ev->ie_Class;
  647.         req->ie_Code = ev->ie_Code;
  648.         req->ie_Qualifier = ev->ie_Qualifier;
  649.         req->ie_TimeStamp = ev->ie_TimeStamp;
  650.     }
  651.     PutMsg(&Dms->Port, (MSG *)req);
  652.     }
  653. }
  654.  
  655. LAYER *
  656. WhichMouseLayer()
  657. {
  658.     register struct IntuitionBase *ib = IBASE;
  659.     register LAYER *layer = NULL;
  660.     register SCR *scr = ib->FirstScreen;
  661.  
  662.     for (scr = ib->FirstScreen; scr; scr = scr->NextScreen) {
  663.     register short mousey = ib->MouseY;
  664.     register short mousex = ib->MouseX;
  665.     if (!(scr->ViewPort.Modes & LACE))
  666.         mousey >>= 1;
  667.     if (!(scr->ViewPort.Modes & HIRES))
  668.         mousex >>= 1;
  669.     if (layer = WhichLayer(&scr->LayerInfo, mousex, mousey - scr->ViewPort.DyOffset))
  670.         break;
  671.     if (mousey >= scr->ViewPort.DyOffset)
  672.         break;
  673.     }
  674.     return(layer);
  675. }
  676.  
  677.  
  678.