/* * 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 #include #include #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); }