/* * ClickUpFront.c Brings a window to the front when you double-click * in it (unless specified qualifier keys are also pressed). * * Copyright (c) 1987 by Davide P. Cervone * You may use this code provided this copyright notice is left intact. */ #include #include #include #include #include #include #include static char *program = "ClickUpFront"; static char *version = "v1.0"; static char *date = "July 1987"; static char *author = "Copyright (c) 1987 by Davide P. Cervone"; static char *PortName = "ClickUpFrontPort"; static char *handler = "L:Click-Handler"; /* the handler file */ #define HANDLER &(handler[2]) /* without the "L:" */ #define STAYMASK (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT) /* * This is the structure that holds the handler information between calls * to ClickUpFront. 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; /* library base used by the handler */ struct LayersBase *Lbase; /* library base used by the handler */ long Segment; /* pointer from LoadSeg() */ }; #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 */ /* * 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; 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 (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. */ 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. */ 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. */ void CreateHandler(argc,argv) int argc; char **argv; { long (*Setup)(); long flags = STAYMASK; CheckLibOpen(&IntuitionBase,"intuition.library",INTUITION_REV); CheckLibOpen(&LayersBase,"layers.library",LAYERS_REV); if (argc > 1) sscanf(argv[1],"%lx",&flags); 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,flags)); HandlerInfo->Handler.is_Node.ln_Pri = 51; TellInputDevice(IND_ADDHANDLER); printf("%s %s (%s) Installed\n",program,version,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. */ void DeleteHandler() { IntuitionBase = HandlerInfo->Ibase; LayersBase = HandlerInfo->Lbase; TellInputDevice(IND_REMHANDLER); UnLoadSeg(HandlerInfo->Segment); printf("%s Removed\n",program); 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 ClickUpFront 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 ClickUpFront 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; CreateHandler(argc,argv); } else { HandlerInfo = (struct HandlerBlock *)(NamedPort->mp_SigTask); DeleteHandler(); FreeMem(HandlerInfo->PortName,NAMESIZE); FreeMem(HandlerInfo,HANDLERINFOSIZE); DeletePort(NamedPort); } }