home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 5 / FreshFish_July-August1994.bin / bbs / util / yak-1.59.lha / Yak-1.59 / Src / handler.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-22  |  17.8 KB  |  570 lines

  1.  
  2. /*
  3.  * handler.c
  4.  *
  5.  * Routines to set up handler.
  6.  * Part of Yak.
  7.  *
  8.  * Martin W. Scott, 9/92.
  9.  */
  10. #include <exec/types.h>
  11. #include <exec/exec.h>
  12. #include <hardware/custom.h>
  13. #include <hardware/dmabits.h>
  14. #include <devices/console.h>
  15. #include <devices/input.h>
  16. #include <devices/inputevent.h>
  17. #include <libraries/commodities.h>
  18. #include <graphics/gfxbase.h>
  19. #include <graphics/gfxmacros.h>
  20. #include <graphics/displayinfo.h>
  21. #include <intuition/intuition.h>
  22. #include <intuition/intuitionbase.h>
  23. #include <proto/exec.h>
  24. #include <proto/dos.h>
  25. #include <proto/layers.h>
  26. #include <proto/graphics.h>
  27. #include <proto/intuition.h>
  28. #include <proto/commodities.h>
  29. #include <string.h>
  30. #include <stdio.h>
  31.  
  32. #include "code.h"
  33. #include "yak.h"
  34. #include "beep.h"
  35.  
  36. void TurnMouseOn (void);
  37. static void TurnMouseOff (void);
  38. static __regargs void IntuiOp (void (*routine) (APTR), APTR parameter);
  39. static __regargs void PopToFront (struct Window *win);
  40. static struct Window *WindowUnderMouse (void);
  41. static __regargs BOOL StrGadgetActive (struct Window *w);
  42.  
  43. extern __far struct Custom custom;
  44.  
  45. #define REBLANKCOUNT    10      /* how long to wait to reblank mouse */
  46.  
  47. void (*intui_routine) (APTR);   /* for intui_op's */
  48. APTR intui_parameter;
  49. CxObj *clickobj;
  50. ULONG clicksigflag, intuiopsigflag;
  51. static BYTE clicksigbit, intuiopsigbit = -1;
  52. static struct Task *thistask;
  53. static BOOL misspop;
  54.  
  55.  
  56. /* for screen click-to-back */
  57. STACKARGS void
  58. MyScreenToBack (struct Screen *scr)
  59. {
  60.   RememberActiveWindow();
  61.   ScreenToBack (scr);
  62.   ActivateMouseWindow (SCREEN);
  63. }
  64.  
  65.  
  66. /* Stub for Intuition routines - passes request on to main task.
  67.  * DO NOT CALL WHILE FORBID()ING!
  68.  
  69.  * Thanks to Eddy Carroll for this.
  70.  */
  71.  
  72. #define WTB(win)        IntuiOp(WindowToBack, win)
  73. #define WTF(win)        IntuiOp(WindowToFront, win)
  74. #define WACT(win)       IntuiOp((void (*)(APTR))ActivateWindow, win)
  75. #define STB(scr)        IntuiOp(MyScreenToBack, scr)
  76. #define STF(scr)        IntuiOp(ScreenToFront, scr)
  77.  
  78. static __regargs void
  79. IntuiOp (void (*routine) (APTR), APTR parameter)
  80. {
  81.   BYTE oldpri = SetTaskPri (thistask, 21);
  82.  
  83.   intui_routine = routine;
  84.   intui_parameter = parameter;
  85.   Signal (thistask, intuiopsigflag);
  86.   SetTaskPri (thistask, oldpri);
  87. }
  88.  
  89. /* pattern-matching on screen/window titles */
  90. #define IsXXXScreen(scr, pat)  (scr && (!scr->DefaultTitle || MatchPattern(pat, scr->DefaultTitle)))
  91. #define IsClickScreen(scr)         IsXXXScreen(scr, clickscrpat)
  92. #define IsAutoScreen(scr)          IsXXXScreen(scr, autoscrpat)
  93. #define IsXXXWindow(win, pat)  (!win->Title || MatchPattern(pat, win->Title))
  94. #define IsPopWindow(win)           IsXXXWindow(win,popwinpat)
  95. #define IsClickWindow(win)         IsXXXWindow(win,clickwinpat)
  96.  
  97.  
  98. /* when is a window safe to bring to front and not already at front? */
  99. #define OkayToPop(win)  (!win->ReqCount && !(win->Flags & (WFLG_MENUSTATE|WFLG_BACKDROP)) \
  100.                          && win->WLayer->ClipRect && win->WLayer->ClipRect->Next)
  101.  
  102.  
  103. /* WindowToFront only if no requester, not backdrop, not already front... */
  104. static __regargs void
  105. PopToFront (struct Window *win)
  106. {
  107.   /* want to avoid popping immediately after mousebutton/keyboard */
  108.   if (misspop)
  109.     misspop = FALSE;
  110.   else if (OkayToPop (win))
  111.     {
  112.       /* Does it pass pattern? */
  113.       if (IsPopWindow (win))
  114.                   WTF (win);
  115.     }
  116. }
  117.  
  118. /* modified from DMouse */
  119. /* expects multitasking to be Forbid()en */
  120.  
  121. static struct Screen *mousescr; /* the screen under the mouse */
  122.  
  123.  
  124. struct Screen
  125. *ScreenUnderMouse( void )
  126. {
  127.   struct Screen *scr;
  128.   ULONG lock;
  129.  
  130.   lock = LockIBase(0);
  131.         
  132.   for (scr = FS;
  133.            scr && scr->TopEdge > 0 && scr->MouseY < 0; 
  134.            scr = scr->NextScreen);
  135.  
  136.   UnlockIBase(lock);
  137.  
  138.   return(scr);
  139. }
  140.  
  141.  
  142. static struct Window 
  143. *WindowUnderMouse( void )
  144. {
  145.   struct Layer *layer = NULL;
  146.   ULONG lock;
  147.  
  148.   lock = LockIBase(0);
  149.         
  150.   for (mousescr = FS;
  151.            mousescr && mousescr->TopEdge > 0 && mousescr->MouseY < 0; 
  152.            mousescr = mousescr->NextScreen);
  153.  
  154.   UnlockIBase(lock);
  155.  
  156.   if (mousescr)
  157.           layer = WhichLayer(&mousescr->LayerInfo, mousescr->MouseX, mousescr->MouseY);
  158.  
  159.   return (layer ? (struct Window *) layer->Window : NULL);
  160. }
  161.  
  162.  
  163. /* does active window have an active string gadget? */
  164. static __regargs BOOL
  165. StrGadgetActive (struct Window *w)
  166. {
  167.   struct Gadget *g = w->FirstGadget;
  168.  
  169.   for (; g; g = g->NextGadget)
  170.     if ((g->GadgetType & STRGADGET) && (g->Flags & GFLG_SELECTED))
  171.       return TRUE;
  172.   return FALSE;
  173. }
  174.  
  175. /* activate window under mouse */
  176. /* context sensitive; why tells routine how to behave */
  177. /* can be AUTO, KEY, SCREEN, RMBACT */
  178. __regargs void
  179. ActivateMouseWindow (BYTE why)
  180. {
  181.     struct Window *win = NULL, *IB_ActiveWindow;
  182.     ULONG lock;
  183.  
  184.     if ((why != SCREEN) || scractivate)
  185.     {
  186.         if (why == SCREEN)
  187.             win = LastActiveWindow(ScreenUnderMouse());
  188.  
  189.         if (!win)
  190.             win = WindowUnderMouse ();
  191.  
  192.  
  193.         if (win) /* window exists to activate */
  194.         {
  195.             /* either window is not active or auto-activating - need to pop? */
  196.           
  197.             if (win->Flags & WFLG_WINDOWACTIVE) /* already active - needs popped? */
  198.             {
  199.                 if (why == AUTO && autopop && IsAutoScreen (win->WScreen))
  200.                 {
  201.                     PopToFront (win);
  202.                 }
  203.             }
  204.             else if (why != AUTO || IsAutoScreen (win->WScreen))
  205.             {
  206.                 /* window is not active, should we try to activate it? */
  207.                   
  208.                 lock = LockIBase(0);
  209.                 IB_ActiveWindow = AW;   /* AW is IntuitionBase->ActiveWindow */
  210.                 UnlockIBase(lock);
  211.  
  212.                 if (!IB_ActiveWindow ||
  213.                     !(IB_ActiveWindow->Flags & WFLG_MENUSTATE) && /* not showing menus */
  214.                     !(why == KEY && StrGadgetActive (IB_ActiveWindow))) /* no str gad active */
  215.                 {
  216.                           
  217.                     /* do autopop? */
  218.                     if (why == AUTO && autopop)
  219.                         PopToFront (win);
  220.                           
  221.                     if (why == KEY)
  222.                         ActivateWindow (win); /* need this to avoid losing keys */
  223.                     else
  224.                         WACT (win); /* ...activate window */
  225.                 }
  226.             }
  227.         }
  228.         else
  229.         {
  230.             lock = LockIBase(0);
  231.             IB_ActiveWindow = AW;   /* AW is IntuitionBase->ActiveWindow */
  232.             UnlockIBase(lock);
  233.  
  234.             if (scractivate && mousescr && mousescr->FirstWindow &&
  235.                 ((why == SCREEN) || 
  236.                  (why == RMBACT && IB_ActiveWindow && IB_ActiveWindow->WScreen != mousescr)))
  237.             {
  238.                 WACT (mousescr->FirstWindow); /* ...activate window */
  239.             }
  240.         }
  241.     }
  242. }
  243.  
  244. static __chip UWORD posctldata[4];
  245. static struct SimpleSprite simplesprite =
  246. {posctldata, 0, 0, 0, 0};
  247. static BOOL mouseoff;           /* is mouse off? (MB_SPRITES only) */
  248.  
  249. void 
  250. TurnMouseOn ()                  /* restore mouse-pointer */
  251. {
  252.         if (mouseblank == MB_SPRITES) /* really dirty blanking */
  253.     {                                                   /* but guaranteed to work... */
  254.                 if (mouseoff)
  255.                 {
  256.                         Forbid ();
  257.                         WaitTOF ();
  258.                         ON_SPRITE;
  259.                         Permit ();
  260.                 }
  261.     }
  262.         /* else using FreeSprite solution - unblanks when needed */
  263.         mouseoff = FALSE;
  264. }
  265.  
  266. static void 
  267. TurnMouseOff ()                 /* blank mouse-pointer */
  268. {
  269.         if (!mouseoff)                          /* no point in turning it off twice... */
  270.     {
  271.                 Forbid ();
  272.  
  273.                 if (mouseblank == MB_SPRITES)
  274.                 {
  275.                         WaitTOF ();
  276.                         OFF_SPRITE;
  277.                         custom.spr[0].dataa = custom.spr[0].datab = 0;          }
  278.                 else
  279.                 {
  280.                         FreeSprite (0);
  281.                         GetSprite (&simplesprite, 0);
  282.                 }
  283.  
  284.                 Permit ();
  285.  
  286.                 mouseoff = TRUE;
  287.     }
  288. }
  289.  
  290. static BOOL blanked;
  291. static struct Screen *blankscr;
  292.  
  293. /* blank display, by putting up a black screen */
  294. /* this screen's displaymode is cloned from front screen */
  295. void
  296. BlankScreen ()
  297. {
  298.         ULONG modeid = INVALID_ID;
  299.         
  300.         if (blankscr)
  301.                 ScreenToFront (blankscr);
  302.         else
  303.     {
  304.                 Forbid ();
  305.                 if (FS)
  306.                         modeid = GetVPModeID (&(FS->ViewPort));
  307.                 Permit ();
  308.                 if (modeid == INVALID_ID)
  309.                         modeid = LORES_KEY;
  310.                 
  311.                 if (blankscr = OpenScreenTags (NULL, SA_Depth, 1,
  312.                                                                            SA_Quiet, TRUE,
  313.                                                                            SA_Behind, TRUE,
  314.                                                                            SA_DisplayID, modeid,
  315.                                                                            TAG_DONE))
  316.                 {
  317.                         SetRGB4 (&blankscr->ViewPort, 0, 0, 0, 0);
  318.                         ScreenToFront (blankscr);
  319.                         blanked = TRUE;
  320.                 }
  321.     }
  322.         OFF_SPRITE;
  323.         custom.spr[0].dataa = custom.spr[0].datab = 0;
  324. }
  325.  
  326. /* unblank display, i.e. close our screen */
  327. void
  328. UnBlankScreen ()
  329. {
  330.   if (blankscr)
  331.           CloseScreen (blankscr);
  332.   blankscr = NULL;
  333.   blanked = FALSE;
  334.   ON_SPRITE;
  335. }
  336.  
  337. #define ALL_BUTTONS     (IEQUALIFIER_LEFTBUTTON|IEQUALIFIER_RBUTTON|IEQUALIFIER_MIDBUTTON)
  338. #define KEY_QUAL        (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT \
  339.                         |IEQUALIFIER_CONTROL \
  340.                         |IEQUALIFIER_LALT|IEQUALIFIER_RALT \
  341.                         |IEQUALIFIER_LCOMMAND|IEQUALIFIER_RCOMMAND)
  342. #define ALL_QUALS       (ALL_BUTTONS|KEY_QUAL)
  343.  
  344. /* the input handler itself */
  345. SAVEDS void
  346. Handler (CxMsg * CxMsg, CxObj * CO)
  347. {
  348.     static struct timeval lastclick; /* last left-button click */
  349.     static WORD apcount;        /* timer events since last mousemove */
  350.     struct InputEvent *ev;
  351.     struct Window *win;  
  352.          
  353.     ev = (struct InputEvent *) CxMsgData (CxMsg);
  354.         
  355.     if (ev->ie_Class == IECLASS_TIMER)
  356.     {
  357.         /*** AUTO-ACTIVATE/POP, SCREENBLANK, MOUSEBLANK ***/
  358.         if (!(ev->ie_Qualifier & ALL_QUALS) && autopoint && !apcount--)
  359.         {
  360.             ActivateMouseWindow (AUTO);
  361.         }
  362.                 
  363.         if (blanktimeout && !--blankcount) /* blank screen? */
  364.         {
  365.             BlankScreen ();
  366.             blankcount = blanktimeout; /* reset counter */
  367.         }                       /* in case sceen opens on top */
  368.                 
  369.         if (mouseblank && !--mblankcount) /* blank mouse? */
  370.         {
  371.             mouseoff = FALSE;   /* force reblank */
  372.             TurnMouseOff ();
  373.             /* in case someone else turns it on, reset counter */
  374.             mblankcount = REBLANKCOUNT;
  375.         }
  376.     }
  377.     else 
  378.         if ((ev->ie_Class == IECLASS_RAWKEY) && !(ev->ie_Code & IECODE_UP_PREFIX))
  379.         {
  380.             /*** MOUSEBLANK, KEYACTIVATE, KEYCLICK ***/
  381.                         
  382.             blankcount = blanktimeout; /* reset blanking countdown */
  383.             if (blanked)        /* turn off screen-blanking */
  384.                 UnBlankScreen ();
  385.                         
  386.             if (mouseblank)
  387.                 if (ev->ie_Qualifier & (IEQUALIFIER_LCOMMAND | IEQUALIFIER_RCOMMAND))
  388.                 {
  389.                     /* this allows use of keyboard to move mouse and to access menus */
  390.                     mblankcount = mblanktimeout;
  391.                     TurnMouseOn ();
  392.                 }
  393.                 else
  394.                 {
  395.                     if (blankmouseonkey)
  396.                     {
  397.                         TurnMouseOff (); /* blank the mouse */
  398.                     }
  399.                 }
  400.             if (click_volume)
  401.                 Signal (thistask, clicksigflag);
  402.                         
  403.             if (keyactivate)    /* perform key-activate */
  404.                 ActivateMouseWindow (KEY);
  405.         }
  406.         else if (ev->ie_Class == IECLASS_RAWMOUSE)
  407.         {
  408.             /*** CLICKTOFRONT/BACK, AUTOACTIVATE ***/
  409.                         
  410.             /* restore screen/mouse pointer */
  411.             blankcount = blanktimeout; /* reset blanking countdowns */
  412.             mblankcount = mblanktimeout;
  413.             if (blanked)        /* turn off screen-blanking */
  414.                 UnBlankScreen ();
  415.             if (mouseoff)
  416.                 TurnMouseOn (); /* not needed for MB_COPPER */
  417.                         
  418.             /* window/screen cycling... */
  419.             /* maybe should check for depth gadgets? nah... */
  420.             if (!(ev->ie_Qualifier & KEY_QUAL))
  421.             {
  422.                 if (!(ev->ie_Qualifier & ALL_BUTTONS))
  423.                 {
  424.                     apcount = autopoint_delay; /* reset auto-activate count */
  425.                 }
  426.                 else
  427.                     /* a button - check out clicktofront etc. */
  428.                 {
  429.                     misspop = TRUE;
  430.                     apcount = -1; /* button - wait for move */
  431.  
  432.                     if (clicktofront && ev->ie_Code == IECODE_LBUTTON)
  433.                     {
  434.                         if (DoubleClick (lastclick.tv_secs,
  435.                                          lastclick.tv_micro,
  436.                                          ev->ie_TimeStamp.tv_secs,
  437.                                          ev->ie_TimeStamp.tv_micro))
  438.                         {
  439.                             win = WindowUnderMouse ();
  440.  
  441.                             if (win)
  442.                             {
  443.                                 mousescr = win->WScreen;
  444.                                                                 
  445.                                 if (IsClickScreen ( mousescr ))
  446.                                 {
  447.                                     if (!(win->Flags & WFLG_BACKDROP) 
  448.                                         && IsClickWindow (win) && OkayToPop (win))
  449.                                     {
  450.                                         WTF (win); 
  451.                                     }
  452.                                     else 
  453.                                         if (screencycle)
  454.                                         {    
  455.                                             RememberActiveWindow();
  456.                                             STF (mousescr); 
  457.                                         }
  458.                                 }
  459.                             }
  460.                             else 
  461.                             {
  462.                                 mousescr = ScreenUnderMouse();
  463.                                 if (IsClickScreen ( mousescr ) && screencycle)
  464.                                 {
  465.                                     RememberActiveWindow();
  466.                                     STF (mousescr);
  467.                                 }
  468.                             }
  469.                             lastclick.tv_secs = 0;
  470.                             lastclick.tv_micro = 0;
  471.                         }
  472.                         else
  473.                         {
  474.                             lastclick.tv_secs = ev->ie_TimeStamp.tv_secs;
  475.                             lastclick.tv_micro = ev->ie_TimeStamp.tv_micro;
  476.                         }
  477.                     }
  478.                     else 
  479.                     {
  480.                         if (ev->ie_Code == IECODE_RBUTTON && 
  481.                             (ev->ie_Qualifier & IEQUALIFIER_LEFTBUTTON) &&
  482.                             clicktoback)
  483.                         {
  484.                             win = WindowUnderMouse ();
  485.  
  486.                             if (win)
  487.                             {
  488.                                 mousescr = win->WScreen;
  489.                                 if (IsClickScreen ( mousescr ))
  490.                                 {
  491.                                     if (!(win->Flags & WFLG_BACKDROP) 
  492.                                         && (win->NextWindow || win->WScreen->FirstWindow != win))
  493.                                     {
  494.                                         WTB(win); 
  495.                                     }
  496.                                     else 
  497.                                         if (screencycle)
  498.                                         {
  499.                                             STB (mousescr); 
  500.                                         }
  501.                                 }       
  502.                             }
  503.                             else 
  504.                             {
  505.                                 mousescr = ScreenUnderMouse();
  506.                                 if (IsClickScreen ( mousescr ) && screencycle)
  507.                                 {
  508.                                     ev->ie_Class = IECLASS_NULL;
  509.                                     STB (mousescr);
  510.                                 }
  511.                             }
  512.                         }
  513.                         else
  514.                         { 
  515.                             if ((rmbactivate && (ev->ie_Code == IECODE_RBUTTON)) || 
  516.                                 (mmbactivate && (ev->ie_Code == IECODE_MBUTTON)))
  517.                             {
  518.                                 ActivateMouseWindow (RMBACT);
  519.                             }
  520.                         }
  521.                     }
  522.                 }
  523.             }
  524.         }
  525.         else 
  526.         {
  527.             if (ev->ie_Class == IECLASS_DISKINSERTED)
  528.             {
  529.                 blankcount = blanktimeout; /* reset blanking countdown */
  530.                 if (blanked)    /* turn off screen-blanking */
  531.                     UnBlankScreen ();
  532.             }
  533.         }
  534. }
  535.  
  536. /* close resources allocated for handler */
  537. void
  538. EndHandler ()
  539. {
  540.   if (clickobj)
  541.     DeleteCxObj (clickobj);
  542.   FreeAudio ();
  543.   if (intuiopsigbit != -1)
  544.     FreeSignal (intuiopsigbit);
  545.   if (clicksigbit != -1)
  546.     FreeSignal (clicksigbit);
  547.   UnBlankScreen ();
  548. }
  549.  
  550. /* open resources needed for handler */
  551. BOOL
  552. InitHandler ()
  553. {
  554.   if (((clicksigbit = AllocSignal (-1)) != -1) &&
  555.       ((intuiopsigbit = AllocSignal (-1)) != -1) &&
  556.       AllocAudio ())
  557.     {
  558.       thistask = FindTask (NULL);       /* initialize liason structure */
  559.       clicksigflag = 1 << clicksigbit;
  560.       intuiopsigflag = 1 << intuiopsigbit;
  561.  
  562.       clickobj = CxCustom (Handler, 0L);
  563.       AttachCxObj (broker, clickobj);
  564.       return TRUE;
  565.     }
  566.   EndHandler ();
  567.   return FALSE;
  568. }
  569.  
  570.