home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 2: PC / frozenfish_august_1995.bin / bbs / d09xx / d0912.lha / Yak / Source / Source.lha / handler.c < prev    next >
C/C++ Source or Header  |  1993-07-31  |  13KB  |  504 lines

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