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 >
Wrap
C/C++ Source or Header
|
1988-01-02
|
10KB
|
396 lines
/*
* wKeys-Handler.c Input Handler for wKeyw, which moves and activates
* windows and screensin response to keystrokes
*
* Copyright (c) 1987 by Davide P. Cervone
* You may use this code provided this copyright notice is left intact.
*/
#include <exec/types.h>
#include <devices/inputevent.h>
#include <intuition/intuitionbase.h>
#include "wKeys.h"
static char *program = "wKeys-Handler";
static int version = 1;
static char *date = "August 1987";
static char *author = "Copyright (c) 1987 by Davide P. Cervone";
extern struct Layer *WhichLayer();
extern void myHandlerStub();
#define WINDOW(layer) ((struct Window *)((layer)->Window))
#define SCREENTOP\
(theScreen->TopEdge << ((theScreen->ViewPort.Modes & LACE)? 0: 1))
struct IntuitionBase *IntuitionBase = NULL;
struct LayersBase *LayersBase = NULL;
struct SysBase *SysBase = NULL;
static struct HotKey *Key = NULL;
static int KeyCount = 0;
/*
* Setup()
*
* wKeys calls LoadSeg() to get this handler into memory. The segment
* that it gets points to this routine. wKeys calls Setup() and
* passes the IntuitionBase, LayersBase and SysBase pointers that it
* has initialized (with OpenLibrary()). wKeys also passes the KeyArray
* and KeyCount which hold the key bindings. Setup returns a pointer to
* the actual input handler, which wKeys installs, and sets the version
* number so that hotKey can report the handler's version.
*/
long Setup(Ibase,Lbase,Sbase,theKeys,Count,VersionPtr)
struct IntuitionBase *Ibase;
struct LayersBase *Lbase;
struct SysBase *Sbase;
struct HotKey *theKeys;
int *VersionPtr;
int Count;
{
IntuitionBase = Ibase;
LayersBase = Lbase;
SysBase = Sbase;
Key = theKeys;
KeyCount = Count;
*VersionPtr = version;
return((long) &myHandlerStub);
}
/*
* TopWindow()
*
* Find the top window of the specified screen. Start at the top layer of
* the screen and move backward as long as the layer exists and has no
* window connected to it. Return the window associated with the final
* layer, if any.
*/
static struct Window *TopWindow(theScreen)
struct Screen *theScreen;
{
struct Window *theWindow = NULL;
struct Layer *theLayer;
theLayer = theScreen->LayerInfo.top_layer;
while (theLayer && WINDOW(theLayer) == NULL) theLayer = theLayer->back;
if (theLayer) theWindow = WINDOW(theLayer);
return(theWindow);
}
/*
* BottomWindow()
*
* Find the bottom window of the specified screen. Start at the top layer
* and as long as the layer exists, go to the next layer back. If the
* layer has a window attached, consider that to be the bottom window until
* a lower one is found.
*/
static struct Window *BottomWindow(theScreen)
struct Screen *theScreen;
{
struct Window *theWindow = NULL;
struct Layer *theLayer = theScreen->LayerInfo.top_layer;
while (theLayer)
{
if (WINDOW(theLayer))
theWindow = WINDOW(theLayer);
theLayer = theLayer->back;
}
return(theWindow);
}
/*
* NextWindow()
*
* Find the next window below the specified window (wrap arround to the top
* if the window is the bottom one). Start with the window's layer and go
* back until a layer with a window is found, or no more layers exist. If
* a window was found, return it, otherwise, use the top window.
*/
static struct Window *NextWindow(theWindow)
struct Window *theWindow;
{
struct Layer *theLayer = theWindow->WLayer;
do
theLayer = theLayer->back;
while (theLayer && WINDOW(theLayer) == NULL);
if (theLayer)
theWindow = WINDOW(theLayer);
else
theWindow = TopWindow(theWindow->WScreen);
return(theWindow);
}
/*
* PreviousWindow()
*
* Find the window that is on top of the specified window (or NULL if there
* are no windows above it). Start with the window's layer, and move to
* the layer in front until a layer with a (different) window is found, or
* until no more layers exist. If a window was found, return it, otherwise
* return NULL.
*/
static struct Window *PreviousWindow(theWindow)
struct Window *theWindow;
{
struct Layer *theLayer = theWindow->WLayer;
do
theLayer = theLayer->front;
while (theLayer && (WINDOW(theLayer) == NULL ||
WINDOW(theLayer) == theWindow));
if (theLayer)
theWindow = WINDOW(theLayer);
else
theWindow = NULL;
return(theWindow);
}
/*
* BackScreenToFront()
*
* Bring the bottom-most screen to the top, and activate its top window.
* While there is a screen following the current one, move the the next screen.
* Bring that screen to the front and find its top window. If one was found,
* activate the window.
*/
static void BackScreenToFront()
{
struct Screen *theScreen = IntuitionBase->FirstScreen;
struct Window *theWindow;
if (theScreen)
{
while (theScreen->NextScreen) theScreen = theScreen->NextScreen;
ScreenToFront(theScreen);
theWindow = TopWindow(theScreen);
if (theWindow) ActivateWindow(theWindow);
}
}
/*
* FrontScreenToBack()
*
* Move the top screen to the back and activate the top window on the new
* top screen.
*/
static void FrontScreenToBack()
{
struct Screen *theScreen = IntuitionBase->FirstScreen;
struct Window *theWindow;
if (theScreen)
{
ScreenToBack(theScreen);
theScreen = IntuitionBase->FirstScreen;
if (theScreen)
{
theWindow = TopWindow(theScreen);
if (theWindow) ActivateWindow(theWindow);
}
}
}
/*
* ActivatePreviousWindow()
*
* Get the window previous to the current window (if none, then get the
* bottom window in the active screen), and activate that window.
*/
static void ActivatePreviousWindow()
{
struct Window *theWindow = PreviousWindow(IntuitionBase->ActiveWindow);
if (theWindow == NULL) theWindow = BottomWindow(IntuitionBase->ActiveScreen);
if (theWindow) ActivateWindow(theWindow);
}
/*
* ActivateNextWindow()
*
* Get the window below the current window and activate it.
*/
static void ActivateNextWindow()
{
struct Window *theWindow = NextWindow(IntuitionBase->ActiveWindow);
if (theWindow) ActivateWindow(theWindow);
}
/*
* CurrentWindowToBack()
*
* Send the current window to the back of the list.
*/
static void CurrentWindowToBack()
{
struct Window *theWindow = IntuitionBase->ActiveWindow;
if (theWindow) WindowToBack(theWindow);
}
/*
* CurrentWindowToFront()
*
* Send the current window to the top of the list.
*/
static void CurrentWindowToFront()
{
struct Window *theWindow = IntuitionBase->ActiveWindow;
if (theWindow) WindowToFront(theWindow);
}
/*
* BackWindowToFront()
*
* Move the bottom window to the top and activate it. Get the bottom window,
* skipping over backdrop windows. If one is found, bring it to the front,
* and activate it.
*/
static void BackWindowToFront()
{
struct Window *theWindow = BottomWindow(IntuitionBase->ActiveScreen);
if (theWindow)
{
while (theWindow && (theWindow->Flags & BACKDROP))
theWindow = PreviousWindow(theWindow);
if (theWindow)
{
WindowToFront(theWindow);
ActivateWindow(theWindow);
}
}
}
/*
* FrontWindowToBack()
*
* Move the top window to the back, and activate the new top window.
* Get the top window, and then the window following it. Send the top window
* to the back, and activate the next window.
*/
static void FrontWindowToBack()
{
struct Window *theWindow = TopWindow(IntuitionBase->ActiveScreen);
struct Window *nextWindow = NextWindow(theWindow);
if (theWindow)
{
WindowToBack(theWindow);
if (nextWindow) ActivateWindow(nextWindow);
}
}
/*
* Array of functions that perform the different actions associated with
* the hot-keys. These are called by the handler routine.
*/
typedef void (*FUNCTION)();
static FUNCTION Action[] =
{
NULL,
&BackScreenToFront,
&FrontScreenToBack,
&ActivatePreviousWindow,
&ActivateNextWindow,
&CurrentWindowToBack,
&CurrentWindowToFront,
&BackWindowToFront,
&FrontWindowToBack
};
/*
* myHandler()
*
* This is the input handler. For each event in the event list:
* If the event is a raw key event, then
* make the KeyCode longword for that event's code and qualifier,
* binary search the Key[] array for a matching entry (only consider
* the qualifiers specified by the KeyMask). Since most keys pressed
* will NOT match a hot-key, we want the search to be as fast as
* possible, so we use a binary search rather than a linear search.
* set NoHotKey if the key is not a hot key.
* if the key was not a hot key,
* go on to the next key
* otherwise,
* perform the function for the specified hot key,
* remove the hot key from the event list.
*
* When all the events have been checked, return the event list so that
* Intuition can do its thing.
*/
struct InputEvent *myHandler(EventList,data)
struct InputEvent *EventList;
APTR data;
{
register struct InputEvent **EventPtr = &EventList;
register struct InputEvent *theEvent;
register long theKey;
register short Num,Min,Max;
register long NoHotKey;
Forbid();
while((theEvent = *EventPtr) != NULL)
{
NoHotKey = TRUE;
if (theEvent->ie_Class == IECLASS_RAWKEY)
{
theKey = KEY(theEvent);
Max = KeyCount; Min = -1;
while ((Num = (Min + Max) >> 1) != Min &&
(NoHotKey = (theKey & Key[Num].hk_KeyMask) -
Key[Num].hk_KeyCode) != 0)
if (NoHotKey > 0) Min = Num; else Max = Num;
}
if (NoHotKey)
{
EventPtr = &(theEvent->ie_NextEvent);
} else {
(*(Action[Key[Num].hk_Action]))();
*EventPtr = theEvent->ie_NextEvent;
}
}
Permit();
return(EventList);
}