home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d128 / wkeys.lha / wKeys / wKeys-Handler.c < prev    next >
C/C++ Source or Header  |  1988-01-02  |  10KB  |  396 lines

  1. /*
  2.  *  wKeys-Handler.c   Input Handler for wKeyw, which moves and activates 
  3.  *                    windows and screensin response to keystrokes
  4.  *
  5.  *              Copyright (c) 1987 by Davide P. Cervone
  6.  *  You may use this code provided this copyright notice is left intact.
  7.  */
  8.  
  9. #include <exec/types.h>
  10. #include <devices/inputevent.h>
  11. #include <intuition/intuitionbase.h>
  12.  
  13. #include "wKeys.h"
  14.  
  15. static char *program = "wKeys-Handler";
  16. static int   version = 1;
  17. static char *date    = "August 1987";
  18. static char *author  = "Copyright (c) 1987 by Davide P. Cervone";
  19.  
  20. extern struct Layer *WhichLayer();
  21. extern void myHandlerStub();
  22.  
  23.  
  24. #define WINDOW(layer)   ((struct Window *)((layer)->Window))
  25.  
  26. #define SCREENTOP\
  27.    (theScreen->TopEdge << ((theScreen->ViewPort.Modes & LACE)? 0: 1))
  28.  
  29.  
  30. struct IntuitionBase *IntuitionBase = NULL;
  31. struct LayersBase    *LayersBase    = NULL;
  32. struct SysBase       *SysBase       = NULL;
  33.  
  34. static struct HotKey *Key = NULL;
  35. static int KeyCount = 0;
  36.  
  37.  
  38. /*
  39.  *  Setup()
  40.  *
  41.  *  wKeys calls LoadSeg() to get this handler into memory.  The segment
  42.  *  that it gets points to this routine.  wKeys calls Setup() and 
  43.  *  passes the IntuitionBase, LayersBase and SysBase pointers that it
  44.  *  has initialized (with OpenLibrary()).  wKeys also passes the KeyArray
  45.  *  and KeyCount which hold the key bindings.  Setup returns a pointer to
  46.  *  the actual input handler, which wKeys installs, and sets the version
  47.  *  number so that hotKey can report the handler's version.
  48.  */
  49.  
  50. long Setup(Ibase,Lbase,Sbase,theKeys,Count,VersionPtr)
  51. struct IntuitionBase *Ibase;
  52. struct LayersBase *Lbase;
  53. struct SysBase *Sbase;
  54. struct HotKey *theKeys;
  55. int *VersionPtr;
  56. int Count;
  57. {
  58.    IntuitionBase = Ibase;
  59.    LayersBase = Lbase;
  60.    SysBase = Sbase;
  61.    Key = theKeys;
  62.    KeyCount = Count;
  63.    *VersionPtr = version;
  64.    return((long) &myHandlerStub);
  65. }
  66.  
  67.  
  68. /*
  69.  *  TopWindow()
  70.  *
  71.  *  Find the top window of the specified screen.  Start at the top layer of
  72.  *  the screen and move backward as long as the layer exists and has no
  73.  *  window connected to it.  Return the window associated with the final 
  74.  *  layer, if any.
  75.  */
  76.  
  77. static struct Window *TopWindow(theScreen)
  78. struct Screen *theScreen;
  79. {
  80.    struct Window *theWindow = NULL;
  81.    struct Layer *theLayer;
  82.    
  83.    theLayer = theScreen->LayerInfo.top_layer;
  84.    while (theLayer && WINDOW(theLayer) == NULL) theLayer = theLayer->back;
  85.    if (theLayer) theWindow = WINDOW(theLayer);
  86.    return(theWindow);
  87. }
  88.  
  89.  
  90. /*
  91.  *  BottomWindow()
  92.  *
  93.  *  Find the bottom window of the specified screen.  Start at the top layer
  94.  *  and as long as the layer exists, go to the next layer back.  If the
  95.  *  layer has a window attached, consider that to be the bottom window until
  96.  *  a lower one is found.
  97.  */
  98.  
  99. static struct Window *BottomWindow(theScreen)
  100. struct Screen *theScreen;
  101. {
  102.    struct Window *theWindow = NULL;
  103.    struct Layer *theLayer = theScreen->LayerInfo.top_layer;
  104.    
  105.    while (theLayer)
  106.    {
  107.       if (WINDOW(theLayer))
  108.          theWindow = WINDOW(theLayer);
  109.       theLayer = theLayer->back;
  110.    }
  111.    return(theWindow);
  112. }
  113.  
  114.  
  115. /*
  116.  *  NextWindow()
  117.  *
  118.  *  Find the next window below the specified window (wrap arround to the top
  119.  *  if the window is the bottom one).  Start with the window's layer and go
  120.  *  back until a layer with a window is found, or no more layers exist.  If
  121.  *  a window was found, return it, otherwise, use the top window.
  122.  */
  123.  
  124. static struct Window *NextWindow(theWindow)
  125. struct Window *theWindow;
  126. {
  127.    struct Layer  *theLayer  = theWindow->WLayer;
  128.    
  129.    do
  130.       theLayer = theLayer->back;
  131.    while (theLayer && WINDOW(theLayer) == NULL);
  132.    if (theLayer)
  133.       theWindow = WINDOW(theLayer);
  134.      else
  135.       theWindow = TopWindow(theWindow->WScreen);
  136.    return(theWindow);
  137. }
  138.  
  139.  
  140. /*
  141.  *  PreviousWindow()
  142.  *
  143.  *  Find the window that is on top of the specified window (or NULL if there
  144.  *  are no windows above it).  Start with the window's layer, and move to
  145.  *  the layer in front until a layer with a (different) window is found, or
  146.  *  until no more layers exist.  If a window was found, return it, otherwise
  147.  *  return NULL.
  148.  */
  149.  
  150. static struct Window *PreviousWindow(theWindow)
  151. struct Window *theWindow;
  152. {
  153.    struct Layer  *theLayer  = theWindow->WLayer;
  154.    
  155.    do
  156.       theLayer = theLayer->front;
  157.    while (theLayer && (WINDOW(theLayer) == NULL ||
  158.                        WINDOW(theLayer) == theWindow));
  159.    if (theLayer)
  160.       theWindow = WINDOW(theLayer);
  161.      else
  162.       theWindow = NULL;
  163.    return(theWindow);
  164. }
  165.  
  166.  
  167. /*
  168.  *  BackScreenToFront()
  169.  *
  170.  *  Bring the bottom-most screen to the top, and activate its top window.
  171.  *  While there is a screen following the current one, move the the next screen.
  172.  *  Bring that screen to the front and find its top window.  If one was found,
  173.  *  activate the window.
  174.  */
  175.  
  176. static void BackScreenToFront()
  177. {
  178.    struct Screen *theScreen = IntuitionBase->FirstScreen;
  179.    struct Window *theWindow;
  180.    
  181.    if (theScreen)
  182.    {
  183.       while (theScreen->NextScreen) theScreen = theScreen->NextScreen;
  184.       ScreenToFront(theScreen);
  185.       theWindow = TopWindow(theScreen);
  186.       if (theWindow) ActivateWindow(theWindow);
  187.    }
  188. }
  189.  
  190.  
  191. /*
  192.  *  FrontScreenToBack()
  193.  *
  194.  *  Move the top screen to the back and activate the top window on the new
  195.  *  top screen.
  196.  */
  197.  
  198. static void FrontScreenToBack()
  199. {
  200.    struct Screen *theScreen = IntuitionBase->FirstScreen;
  201.    struct Window *theWindow;
  202.  
  203.    if (theScreen)
  204.    {
  205.       ScreenToBack(theScreen);
  206.       theScreen = IntuitionBase->FirstScreen;
  207.       if (theScreen)
  208.       {
  209.          theWindow = TopWindow(theScreen);
  210.          if (theWindow) ActivateWindow(theWindow);
  211.       }
  212.    }
  213. }
  214.  
  215.  
  216. /*
  217.  *  ActivatePreviousWindow()
  218.  *
  219.  *  Get the window previous to the current window (if none, then get the
  220.  *  bottom window in the active screen), and activate that window.
  221.  */
  222.  
  223. static void ActivatePreviousWindow()
  224. {
  225.    struct Window *theWindow = PreviousWindow(IntuitionBase->ActiveWindow);
  226.    
  227.    if (theWindow == NULL) theWindow = BottomWindow(IntuitionBase->ActiveScreen);
  228.    if (theWindow) ActivateWindow(theWindow);
  229. }
  230.  
  231.  
  232. /*
  233.  *  ActivateNextWindow()
  234.  *
  235.  *  Get the window below the current window and activate it.
  236.  */
  237.  
  238. static void ActivateNextWindow()
  239. {
  240.    struct Window *theWindow = NextWindow(IntuitionBase->ActiveWindow);
  241.    
  242.    if (theWindow) ActivateWindow(theWindow);
  243. }
  244.  
  245.  
  246. /*
  247.  *  CurrentWindowToBack()
  248.  *
  249.  *  Send the current window to the back of the list.
  250.  */
  251.  
  252. static void CurrentWindowToBack()
  253. {
  254.    struct Window *theWindow = IntuitionBase->ActiveWindow;
  255.    
  256.    if (theWindow) WindowToBack(theWindow);
  257. }
  258.  
  259.  
  260. /*
  261.  *  CurrentWindowToFront()
  262.  *
  263.  *  Send the current window to the top of the list.
  264.  */
  265.  
  266. static void CurrentWindowToFront()
  267. {
  268.    struct Window *theWindow = IntuitionBase->ActiveWindow;
  269.    
  270.    if (theWindow) WindowToFront(theWindow);
  271. }
  272.  
  273.  
  274. /*
  275.  *  BackWindowToFront()
  276.  *
  277.  *  Move the bottom window to the top and activate it.  Get the bottom window,
  278.  *  skipping over backdrop windows.  If one is found, bring it to the front,
  279.  *  and activate it.
  280.  */
  281.  
  282. static void BackWindowToFront()
  283. {
  284.    struct Window *theWindow = BottomWindow(IntuitionBase->ActiveScreen);
  285.    
  286.    if (theWindow)
  287.    {
  288.       while (theWindow && (theWindow->Flags & BACKDROP))
  289.          theWindow = PreviousWindow(theWindow);
  290.       if (theWindow)
  291.       {
  292.          WindowToFront(theWindow);
  293.          ActivateWindow(theWindow);
  294.       }
  295.    }
  296. }
  297.  
  298.  
  299. /*
  300.  *  FrontWindowToBack()
  301.  *
  302.  *  Move the top window to the back, and activate the new top window.
  303.  *  Get the top window, and then the window following it.  Send the top window
  304.  *  to the back, and activate the next window.
  305.  */
  306.  
  307. static void FrontWindowToBack()
  308. {
  309.    struct Window *theWindow  = TopWindow(IntuitionBase->ActiveScreen);
  310.    struct Window *nextWindow = NextWindow(theWindow);
  311.    
  312.    if (theWindow)
  313.    {
  314.       WindowToBack(theWindow);
  315.       if (nextWindow) ActivateWindow(nextWindow);
  316.    }
  317. }
  318.  
  319.  
  320. /*
  321.  *  Array of functions that perform the different actions associated with 
  322.  *  the hot-keys.  These are called by the handler routine.
  323.  */
  324.  
  325. typedef void (*FUNCTION)();
  326.  
  327. static FUNCTION Action[] =
  328. {
  329.    NULL,
  330.    &BackScreenToFront,
  331.    &FrontScreenToBack,
  332.    &ActivatePreviousWindow,
  333.    &ActivateNextWindow,
  334.    &CurrentWindowToBack,
  335.    &CurrentWindowToFront,
  336.    &BackWindowToFront,
  337.    &FrontWindowToBack
  338. };
  339.  
  340.  
  341. /*
  342.  *  myHandler()
  343.  *
  344.  *  This is the input handler.  For each event in the event list:
  345.  *  If the event is a raw key event, then
  346.  *    make the KeyCode longword for that event's code and qualifier,
  347.  *    binary search the Key[] array for a matching entry (only consider
  348.  *      the qualifiers specified by the KeyMask).  Since most keys pressed
  349.  *      will NOT match a hot-key, we want the search to be as fast as 
  350.  *      possible, so we use a binary search rather than a linear search.
  351.  *    set NoHotKey if the key is not a hot key.
  352.  *  if the key was not a hot key,
  353.  *    go on to the next key
  354.  *   otherwise,
  355.  *    perform the function for the specified hot key,
  356.  *    remove the hot key from the event list.
  357.  *
  358.  *  When all the events have been checked, return the event list so that
  359.  *  Intuition can do its thing.
  360.  */
  361.  
  362. struct InputEvent *myHandler(EventList,data)
  363. struct InputEvent *EventList;
  364. APTR data;
  365. {
  366.    register struct InputEvent **EventPtr = &EventList;
  367.    register struct InputEvent *theEvent;
  368.    register long   theKey;
  369.    register short  Num,Min,Max;
  370.    register long   NoHotKey;
  371.  
  372.    Forbid();
  373.    while((theEvent = *EventPtr) != NULL)
  374.    {
  375.       NoHotKey = TRUE;
  376.       if (theEvent->ie_Class == IECLASS_RAWKEY)
  377.       {
  378.          theKey = KEY(theEvent);
  379.          Max = KeyCount; Min = -1;
  380.          while ((Num = (Min + Max) >> 1) != Min &&
  381.                 (NoHotKey = (theKey & Key[Num].hk_KeyMask) -
  382.                              Key[Num].hk_KeyCode) != 0)
  383.             if (NoHotKey > 0) Min = Num; else Max = Num;
  384.       }
  385.       if (NoHotKey)
  386.       {
  387.          EventPtr = &(theEvent->ie_NextEvent);
  388.       } else {
  389.          (*(Action[Key[Num].hk_Action]))();
  390.          *EventPtr = theEvent->ie_NextEvent;
  391.       }
  392.    }
  393.    Permit();
  394.    return(EventList);
  395. }
  396.