home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 1
/
GoldFishApril1994_CD2.img
/
d4xx
/
d498
/
zoomdaemon
/
source
/
zoom-main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-06-06
|
11KB
|
381 lines
/*
* ZOOM-DAEMON A program that implements Zoom gadgets for all Intuition
* windows that are opened while it is running.
*
* Copyright 1989 by Davide P. Cervone.
* You may use this code, provided this copyright notice is kept intact.
*/
#include "Zoom-Main.h"
#include "Zoom-Daemon.h"
struct IntuitionBase *IntuitionBase = NULL;
extern struct SysBase *SysBase;
static char *program = PROGRAM;
static char *copyright = COPYRIGHT;
static char *handler = HANDLERCODE; /* The name of the handler file */
#define HANDLER &(handler[2]) /* Handler without the L: */
static struct Zoom_HandlerInfo *Zoom_HandlerData; /* data shared with handler */
static long Segment; /* The loaded handler segment */
static struct ExtGadget *FirstZoom; /* The list of zoom gadgets */
static struct MsgPort *InputPort; /* To talk to Input.Device */
static struct IOStdReq *InputBlock; /* IO block for Input.Device */
static int InputDevice; /* Is Input.Device open? */
static int VectorsSet; /* TRUE after SetFunction */
/*
* DoExit()
*
* General purpose error-exit routine. Print an error message if one was
* supplied (it can have up to three parameters), and then clean up any
* memory, libraries, etc. that need to be handled before exiting.
*/
static void DoExit(s,x1,x2,x3)
char *s, *x1, *x2, *x3;
{
long status = EXIT_OK;
if (s != NULL)
{
printf(s,x1,x2,x3);
printf("\n");
status = EXIT_ERROR;
}
if (VectorsSet) UnSetVectors();
if (InputDevice) CloseDevice(InputBlock);
if (InputBlock) DeleteStdIO(InputBlock);
if (InputPort) DeletePort(InputPort);
if (Segment) UnLoadSeg(Segment);
if (IntuitionBase) CloseLibrary(IntuitionBase);
exit(status);
}
/*
* CheckLibOpen()
*
* Call OpenLibrary() for the specified library, and check that the
* open succeeded.
*/
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",name);
}
/*
* LoadHandler()
*
* Try to LoadSeg the handler from the current directory, and if it is not
* found, try the L: directory. If neither can be loaded, exit with an
* error message. Once the handler is loaded, call the Setup routine
* in the handler code and pass the loader version number. The handler will
* check the version for compatibility and returns NULL if there is a
* mismatch, or a pointer to the shared data if everything is OK.
* Check the handler version number, and then store the loader version
* and the segment list pointer for use in unloading the handler later.
* The MsgPort is the first item in the Zoom_Handler structure. It is used
* to link the information into the system port list, where we can find it
* later.
*/
void LoadHandler(thePort)
struct MsgPort **thePort;
{
struct Zoom_HandlerInfo *(*Setup)();
if ((Segment = LoadSeg(HANDLER)) == NULL)
if ((Segment = LoadSeg(handler)) == NULL)
DoExit("Can't load %s",handler);
Setup = (struct Zoom_HandlerInfo *(*)()) ((Segment << 2) + 4);
Zoom_HandlerData = (*Setup)(LOADVERS);
if (Zoom_HandlerData)
{
if (var(MajVers) < MINHMAJVERS ||
(var(MajVers) == MINHMAJVERS && var(MinVers) < MINHMINVERS))
DoExit("Version mismatch with %s",HANDLER);
*thePort = &(Zoom_HandlerData->Zoom_Port);
} else {
DoExit("%s reports a version mismatch",HANDLER);
}
var(Segment) = Segment;
}
/*
* TellInputDevice()
*
* Create a port and I/O block, then 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;
extern struct MsgPort *CreatePort();
extern struct IOStdReq *CreateStdIO();
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) var(Zoom_Interrupt);
if (status = DoIO(InputBlock)) DoExit("Error from DoIO: %ld",status);
CloseDevice(InputBlock); InputDevice = FALSE;
DeleteStdIO(InputBlock); InputBlock = NULL;
DeletePort(InputPort); InputPort = NULL;
}
/*
* SetVectors()
*
* Set the Intuition library vectors for the routines specified by the
* handler. Save the old routine pointers for later replacement.
*/
void SetVectors()
{
VAR(OldOpenWindow) =
SetFunction(IntuitionBase,&LVOOpenWindow,var(aOpenWindow));
VAR(OldCloseWindow) =
SetFunction(IntuitionBase,&LVOCloseWindow,var(aCloseWindow));
VAR(OldAddGadget) =
SetFunction(IntuitionBase,&LVOAddGadget,var(aAddGadget));
VAR(OldAddGList) =
SetFunction(IntuitionBase,&LVOAddGList,var(aAddGList));
VectorsSet = TRUE;
}
/*
* UnSetVectors()
*
* Replace the old Intuition library vectors, but make sure that no one
* else has changed them behind our back. If they are not the same as
* what we set them to originally, then put back the ones that we found,
* and return an error status.
*/
int UnSetVectors()
{
long NewOpenWindow;
long NewCloseWindow;
long NewAddGadget;
long NewAddGList;
int status = TRUE;
Forbid();
NewOpenWindow =
SetFunction(IntuitionBase,&LVOOpenWindow,VAR(OldOpenWindow));
NewCloseWindow =
SetFunction(IntuitionBase,&LVOCloseWindow,VAR(OldCloseWindow));
NewAddGadget =
SetFunction(IntuitionBase,&LVOAddGadget,VAR(OldAddGadget));
NewAddGList =
SetFunction(IntuitionBase,&LVOAddGList,VAR(OldAddGList));
if (NewOpenWindow != (long) var(aOpenWindow) ||
NewCloseWindow != (long) var(aCloseWindow) ||
NewAddGadget != (long) var(aAddGadget) ||
NewAddGList != (long) var(aAddGList))
{
SetFunction(IntuitionBase,&LVOOpenWindow,NewOpenWindow);
SetFunction(IntuitionBase,&LVOCloseWindow,NewCloseWindow);
SetFunction(IntuitionBase,&LVOAddGadget,NewAddGadget);
SetFunction(IntuitionBase,&LVOAddGList,NewAddGList);
status = FALSE;
}
Permit();
return(status);
}
/*
* SetVariables()
*
* The Zoom_HandlerData structure is used to allow the loading program to
* set up variables needed by the handler (like Intuitionbase, etc.). This
* keeps the handler code to a minimum. The loader retains pointers to the
* linked lists, in case it needs to free memory on behalf of the handler.
*/
void SetVariables(thePort)
struct MsgPort *thePort;
{
VAR(IntuitionBase) = IntuitionBase;
VAR(SysBase) = SysBase;
VAR(FirstZoom) = NULL;
}
/*
* GetVariables()
*
* Look up the values stored in the Zoom_HandlerData structure. The
* Intuition library already was opened, and we will need to close it.
* The data in the linked lists may need to be freed.
*/
void GetVariables(thePort)
struct MsgPort *thePort;
{
Zoom_HandlerData = (struct Zoom_HandlerInfo *)thePort;
IntuitionBase = VAR(IntuitionBase);
FirstZoom = VAR(FirstZoom);
}
/*
* SetupWindows()
*
* Looks through the Intuition screen and windows lists and
* calls the Handler's SetupWindow routine to add the imagery to
* each pre-existing window.
*
* All of this is done in Forbid() mode so that the list won't change
* while we're looking.
*/
static void SetupWindows()
{
struct Screen *theScreen;
struct Window *theWindow;
if (var(SetupWindow))
{
Forbid();
theScreen = IntuitionBase->FirstScreen;
while (theScreen)
{
theWindow = theScreen->FirstWindow;
while (theWindow)
{
VAR(SetupWindow)(theWindow);
theWindow = theWindow->NextWindow;
}
theScreen = theScreen->NextScreen;
}
Permit();
}
}
/*
* FreeAllZoomGadgets();
*
* Goes through the linked list of zoom gadgets and removes each
* from its associated window, refreshes the window, and frees
* the memory associated with the zoom gadget.
*/
void FreeAllZoomGadgets()
{
struct ExtGadget *theGadget;
while (FirstZoom)
{
theGadget = FirstZoom;
FirstZoom = theGadget->Next;
RemoveGadget(theGadget->Window,&(theGadget->Gadget));
RefreshWindowFrame(theGadget->Window);
FreeMem(theGadget,EXTGADGETSIZE);
}
FirstZoom = NULL;
}
/*
* Main()
*
* Look for the Zoom-Daemon port.
* If the port does not exist, then Zoom-Daemon is not active, so:
* Open Intuition.
* Load the handler code and check its version.
* Add the port (supplied by the handler) into the system list so we
* can find it later.
* Set the variables needed by the handler.
* Set the Intuition Library vectors for the handler routines
* Add the input handler into the Input Device chain
* Retro-fit existing windows to include the Zoom Gadgets
* Notify the user that all is ready.
* else (the port already exists, so Zoom-Daemon alreay is active)
* Get the pointer to the Zoom_HandlerData structure from the port,
* and get any variables we need from the structure.
* Check that the loader versions are compatible.
* Remove the input handler from the Input Device chain
* Try to remove the SetFunction calls.
* If successfull, then
* Remove the port from the system list.
* Cleanup and windows that are still using the Zoom Gadgets
* Unload the handler segment list.
* Notify the user that Zoom-Daemon is deactivated.
* Close Intuition.
* else (we could not replace the functions)
* Put back the input handler
* Inform the user that Zoom-Daemon can not be removed
*/
void main()
{
struct MsgPort *NamedPort;
NamedPort = FindPort(PORTNAME);
if (NamedPort == NULL)
{
CheckLibOpen(&IntuitionBase,"intuition.library",INTUITION_REV);
LoadHandler(&NamedPort);
AddPort(NamedPort);
SetVariables(NamedPort);
SetVectors(NamedPort);
TellInputDevice(IND_ADDHANDLER);
SetupWindows();
printf("%s v%d.%d.%d Installed\n",program,
var(MajVers),var(MinVers),LOADVERS);
} else {
GetVariables(NamedPort);
if (var(MinLoadVers) > LOADVERS || var(MajVers) < MINHMAJVERS ||
(var(MajVers) == MINHMAJVERS && var(MinVers) < MINHMINVERS))
{
printf("Loader version mismatch\n");
printf("%s not removed\n",program);
} else {
TellInputDevice(IND_REMHANDLER);
if (UnSetVectors(NamedPort))
{
RemPort(NamedPort);
FreeAllZoomGadgets();
UnLoadSeg(var(Segment));
printf("%s removed\n",program);
CloseLibrary(IntuitionBase);
} else {
TellInputDevice(IND_ADDHANDLER);
printf("SetFunction vectors have been changed!\n");
printf("Cannot remove %s\n",program);
}
}
}
}