home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d1xx
/
d128
/
wkeys.lha
/
wKeys
/
wKeys.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-01-02
|
10KB
|
308 lines
/*
* wKeys.c Moves and activates windows and screens via 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 <libraries/dos.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <exec/interrupts.h>
#include <devices/input.h>
#include <devices/inputevent.h>
#include "wKeys.h"
static char *program = "wKeys";
static int version = 1;
static char *date = "August 1987";
static char *author = "Copyright (c) 1987 by Davide P. Cervone";
static int hversion = 0;
static char *PortName = "wKeysPort";
static char *handler = "L:wKeys-Handler"; /* the handler file */
#define HANDLER &(handler[2]) /* without the "L:" */
/*
* This is the structure that holds the handler information between calls
* to wKeys. We create a named, public message-port that points to
* an instance of this structure so that we can find this information
* when we are asked to remove the handler. The PortName is stored here
* (NamedPort->mp_Node.ln_Name uses this area for it's name). The other
* data are what we need in order to remove the handler and clean up properly.
*/
struct HandlerBlock
{
char *PortName; /* name of the public, named message-port */
struct Interrupt Handler; /* the handler added to the handler chain */
struct IntuitionBase *Ibase; /* an error if the handler can't be found */
struct LayersBase *Lbase; /* library base used by the handler */
long Segment; /* pointer from LoadSeg() */
struct HotKey *Keys; /* pointer to Key array */
int KeyCount; /* size of Key array */
};
#define HANDLERINFOSIZE sizeof(struct HandlerBlock)
#define NAMESIZE (strlen(PortName)+1)
extern struct MsgPort *CreatePort();
extern struct IOStdReq *CreateStdIO();
extern struct MsgPort *FindPort(), *CreatePort();
extern APTR AllocMem();
extern long LoadSeg();
#define INTUITION_REV 0L
#define LAYERS_REV 0L
struct IntuitionBase *IntuitionBase = NULL;
struct LayersBase *LayersBase = NULL;
extern struct SysBase *SysBase;
struct MsgPort *InputPort = NULL; /* Port used to talk to Input.Device */
struct IOStdReq *InputBlock = NULL; /* request block used with Input.Device */
LONG InputDevice = 0; /* flag whether Input.Device is open */
struct MsgPort *NamedPort = NULL; /* holds info needed to remove handler */
struct HandlerBlock *HandlerInfo = NULL; /* holds info stored in NamedPort */
extern struct HotKeyItem *KeyList;
extern struct HotKey *KeyArray;
extern int KeyCount;
#define KEYARRAYSIZE (KeyCount*sizeof(struct HotKey))
extern void GetKeyArray();
/*
* DoExit()
*
* General purpose exit routine. If 's' is not NULL, then print an
* error message with up to three parameters. Free any memory, close
* any open device, delete any ports, close any libraries, etc.
*/
void DoExit(s,x1,x2,x3)
char *s, *x1, *x2, *x3;
{
long status = RETURN_OK;
struct HotKeyItem *TempKey;
if (s != NULL)
{
printf(s,x1,x2,x3);
printf("\n");
status = RETURN_ERROR;
}
if (InputDevice) CloseDevice(InputBlock);
if (InputBlock) DeleteStdIO(InputBlock);
if (InputPort) DeletePort(InputPort);
if (NamedPort) DeletePort(NamedPort);
if (HandlerInfo)
{
if (HandlerInfo->PortName) FreeMem(HandlerInfo->PortName,NAMESIZE);
FreeMem(HandlerInfo,HANDLERINFOSIZE);
}
if (KeyArray) FreeMem(KeyArray,KEYARRAYSIZE);
while (KeyList)
{
TempKey = KeyList;
KeyList = KeyList->Next;
FreeMem(TempKey,sizeof(*TempKey));
}
if (IntuitionBase) CloseLibrary(IntuitionBase);
if (LayersBase) CloseLibrary(LayersBase);
exit(status);
}
/*
* CheckLibOpen()
*
* General library open routine. It opens a library and sets a pointer
* to it. It checks that the library was openned successfully.
*/
static void CheckLibOpen(lib,name,rev)
APTR *lib;
char *name;
int rev;
{
extern APTR OpenLibrary();
if ((*lib = OpenLibrary(name,(LONG)rev)) == NULL)
DoExit("Can't open '%s'\n",name);
}
/*
* Macros that make memory allocation easier.
*/
#define NEW(s,var) (var = (struct s *)New("var",sizeof(struct s)))
#define NEWCHAR(var,s) (var = (char *)New("var",s))
/*
* New()
*
* Allocate public memory of a given size and set it to all zeros. If there
* is not enough memory, then exit with an error, otherwise return the
* pointer to the newly allocated memory.
*/
APTR New(name,size)
char *name;
int size;
{
APTR ptr;
if ((ptr = AllocMem(size,MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
DoExit("Can't Get Memory for '%s'");
return(ptr);
}
/*
* TellInputDevice()
*
* Create a port and I/O block, and open the input device. Set up the
* I/O block to add or remove the input handler, and send the request
* to the input device. Finally, close the device and delete the
* I/O block and port.
*/
static void TellInputDevice(function)
int function;
{
long status;
if ((InputPort = CreatePort(0,0)) == NULL) DoExit("Can't Create Port");
if ((InputBlock = CreateStdIO(InputPort)) == NULL)
DoExit("Can't Create Standard IO Block");
InputDevice = (OpenDevice("input.device",0,InputBlock,0) == 0);
if (InputDevice == FALSE) DoExit("Can't Open 'input.device'");
InputBlock->io_Command = (long) function;
InputBlock->io_Data = (APTR) &(HandlerInfo->Handler);
if (status = DoIO(InputBlock)) DoExit("Error from DoIO: %ld",status);
CloseDevice(InputBlock);
DeleteStdIO(InputBlock);
DeletePort(InputPort);
}
/*
* CreateHandler()
*
* Open the libraries needed by the input handler and store their locations
* in the HandlerInfo structure (so we can close them later). Try to
* LoadSeg() the handler. If it is not in the current directory, try the
* L: directory. Exit with an error if the handler can't be found.
* Convert the segment pointer into a pointer to the Setup() routine (the
* first routine in the handler executable). Call Setup() and pass it
* the pointers to the libraries that it will need to use. Setup() returns
* a pointer to the actual handler routine that should be added into the
* input handler chain. Store this in the HandlerInfo structure so we
* can use it to remove the handler later. Set the handler priority to
* 51 so that it is ahead of Intuition.
*
* Finally, add the handler in the chain and tell the user that the
* handler has been installed.
*/
static void CreateHandler()
{
long (*Setup)();
CheckLibOpen(&IntuitionBase,"intuition.library",INTUITION_REV);
CheckLibOpen(&LayersBase,"layers.library",LAYERS_REV);
HandlerInfo->Ibase = IntuitionBase;
HandlerInfo->Lbase = LayersBase;
if ((HandlerInfo->Segment = LoadSeg(HANDLER)) == NULL)
if ((HandlerInfo->Segment = LoadSeg(handler)) == NULL)
DoExit("Can't Load '%s'",handler);
Setup = (long (*)()) ((HandlerInfo->Segment << 2) + 4);
HandlerInfo->Handler.is_Code =
(void (*)()) ((*Setup)(IntuitionBase,LayersBase,SysBase,
KeyArray,KeyCount,&hversion));
HandlerInfo->Handler.is_Node.ln_Pri = 51;
HandlerInfo->Keys = KeyArray;
HandlerInfo->KeyCount = KeyCount;
TellInputDevice(IND_ADDHANDLER);
printf("%s v%d.%d (%s) Installed\n",program,version,hversion,date);
}
/*
* Delete Handler()
*
* Retreive the library pointers fro mthe HandlerInfo structure, where
* we stored them when we originally installed the handler, then remove
* the handler from the input handler chain. Tell the user that the
* handler is gone, and then close the libraries that are no longer needed.
*/
static void DeleteHandler()
{
IntuitionBase = HandlerInfo->Ibase;
LayersBase = HandlerInfo->Lbase;
KeyArray = HandlerInfo->Keys;
KeyCount = HandlerInfo->KeyCount;
TellInputDevice(IND_REMHANDLER);
UnLoadSeg(HandlerInfo->Segment);
printf("%s Removed\n",program);
FreeMem(KeyArray,KEYARRAYSIZE);
CloseLibrary(IntuitionBase);
CloseLibrary(LayersBase);
}
/*
* main()
*
* Check if a message port with our name already exists.
* If not, then the handler is not already installed, so:
* Allocate a new HandlerInfo structure and initialize the port name.
* Create a public, named message-port (we will look for this the next
* time wKeys is called).
* Make the message port point to the HandlerInfo structure so we
* can use it later when the user asks us to remove the handler.
* Note that the port is not actually used for putting and getting
* messages, so the Task field is never used, so we can take it for
* our own uses.
* Finally, add the input handler into the chain.
* Otherwise, the port exists, so wKeys already is installed:
* Retreive the HandlerInfo poiner from the port, and remove the
* handler from the input handler chain.
* Free the memory used by the HandlerInfo, and delete the message port.
*/
void main(argc,argv)
int argc;
char **argv;
{
NamedPort = FindPort(PortName);
if (NamedPort == NULL)
{
NEW(HandlerBlock,HandlerInfo);
NEWCHAR(HandlerInfo->PortName,NAMESIZE);
strcpy(HandlerInfo->PortName,PortName);
if ((NamedPort = CreatePort(HandlerInfo->PortName,0)) == NULL)
DoExit("Can't Create Message Port '%s'",PortName);
NamedPort->mp_SigTask = (struct Task *)HandlerInfo;
GetKeyArray(argc,argv);
CreateHandler();
} else {
HandlerInfo = (struct HandlerBlock *)(NamedPort->mp_SigTask);
DeleteHandler();
FreeMem(HandlerInfo->PortName,NAMESIZE);
FreeMem(HandlerInfo,HANDLERINFOSIZE);
DeletePort(NamedPort);
}
}