home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
532.lha
/
NLDaemon
/
Source
/
NL-Main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-07-09
|
14KB
|
478 lines
/*
* NL-Daemon A program to force old programs to use NL gadget imagery.
*
* Copyright 1989 by Davide P. Cervone.
* You may use this code, provided this copyright notice is kept intact.
*/
#include "NL-Main.h"
#include "NL-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 NL_HandlerInfo *NL_HandlerData; /* data shared with the handler */
static long Segment; /* the loaded handler segment */
/*
* 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 (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 NL_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 NL_HandlerInfo *(*Setup)();
if ((Segment = LoadSeg(HANDLER)) == NULL)
if ((Segment = LoadSeg(handler)) == NULL)
DoExit("Can't load %s",handler);
Setup = (struct NL_HandlerInfo *(*)()) ((Segment << 2) + 4);
NL_HandlerData = (*Setup)(LOADVERS);
if (NL_HandlerData)
{
if (var(MajVers) < MINHMAJVERS ||
(var(MajVers) == MINHMAJVERS && var(MinVers) < MINHMINVERS))
DoExit("Version mismatch with %s",HANDLER);
*thePort = &(NL_HandlerData->NL_Port);
} else {
DoExit("%s reports a version mismatch",HANDLER);
}
var(Segment) = Segment;
}
/*
* InvertImage()
*
* Performs a Logical NOT on all the bits in the Image data, and
* XORs the second bitplane in the PlaneOnOff field. This makes the
* standard Intuition Imagery use color 2 as the background and color
* three as the forground (rather than 1 and 0).
*/
#define IMAGESIZE(i) ((i)->Depth*(((i)->Width+15)>>4)*(i)->Height)
static void InvertImage(theImage)
struct Image *theImage;
{
short i;
USHORT *theWord;
if (theImage)
{
theWord = theImage->ImageData;
for (i=IMAGESIZE(theImage); i; i--,theWord++) *theWord = ~(*theWord);
theImage->PlaneOnOff ^= 0x02;
}
}
/*
* 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(OldSetMenuStrip) =
SetFunction(IntuitionBase,&LVOSetMenuStrip,var(aSetMenuStrip));
VAR(OldOpenScreen) =
SetFunction(IntuitionBase,&LVOOpenScreen,var(aOpenScreen));
}
/*
* 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 NewSetMenuStrip;
long NewOpenScreen;
int status = TRUE;
NewOpenWindow = SetFunction(IntuitionBase,&LVOOpenWindow,VAR(OldOpenWindow));
NewSetMenuStrip =
SetFunction(IntuitionBase,&LVOSetMenuStrip,VAR(OldSetMenuStrip));
NewOpenScreen = SetFunction(IntuitionBase,&LVOOpenScreen,VAR(OldOpenScreen));
if (NewOpenWindow != (long) var(aOpenWindow) ||
NewSetMenuStrip != (long) var(aSetMenuStrip) ||
NewOpenScreen != (long) var(aOpenScreen))
{
SetFunction(IntuitionBase,&LVOOpenWindow,NewOpenWindow);
SetFunction(IntuitionBase,&LVOSetMenuStrip,NewSetMenuStrip);
SetFunction(IntuitionBase,&LVOOpenScreen,NewOpenScreen);
status = FALSE;
}
return(status);
}
/*
* SetVariables()
*
* The NL_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,argc)
struct MsgPort *thePort;
int argc;
{
VAR(IntuitionBase) = IntuitionBase;
VAR(SysBase) = SysBase;
if (argc == 1)
{
Forbid();
InvertImage(IntuitionBase->CheckImage[0]);
InvertImage(IntuitionBase->CheckImage[1]);
InvertImage(IntuitionBase->AmigaIcon[0]);
InvertImage(IntuitionBase->AmigaIcon[1]);
Permit();
var(Flags) |= INTUITION_CHANGED;
}
}
/*
* GetVariables()
*
* Look up the values stored in the NL_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;
{
NL_HandlerData = (struct NL_HandlerInfo *)thePort;
IntuitionBase = VAR(IntuitionBase);
}
/*
* 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. If the window has a menu strip, remove
* it and then replace it (our SetMenuStrip routine will fix the menu
* for us, since it has already be added in via SetFunction).
* 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;
struct Menu *theMenu;
if (var(SetupWindow) || var(SetupScreen))
{
Forbid();
theScreen = IntuitionBase->FirstScreen;
while (theScreen)
{
if (var(SetupScreen)) VAR(SetupScreen)(theScreen);
if (var(SetupWindow))
{
theWindow = theScreen->FirstWindow;
while (theWindow)
{
VAR(SetupWindow)(theWindow);
if (theWindow->MenuStrip)
{
theMenu = theWindow->MenuStrip;
ClearMenuStrip(theWindow);
SetMenuStrip(theWindow,theMenu);
}
theWindow = theWindow->NextWindow;
}
}
theScreen = theScreen->NextScreen;
}
Permit();
}
}
/*
* CheckGadget()
*
* Checks to see if a gadget's imagery has been changed. If so, it
* replaces the imagery with the standard Intuition imagery that we saved
* when we set up the NL gadget.
*/
static int CheckGadget(theGadget,HiResImage,LowResImage)
struct Gadget *theGadget;
APTR HiResImage,LowResImage;
{
int status = FALSE;
if (theGadget->GadgetRender == HiResImage ||
theGadget->GadgetRender == LowResImage)
{
status = TRUE;
theGadget->GadgetRender = theGadget->SelectRender;
theGadget->LeftEdge = ((LONG)theGadget->UserData) >> 16;
theGadget->Width = ((LONG)theGadget->UserData) & 0xFFFF;
}
return(status);
}
/*
* CheckGadgetList()
*
* Looks through a list of gadgets to see if any of their imagery has been
* changed, and replaces their original imagery if they where changed.
* Returns TRUE if any changes were made, FALSE otherwise.
*/
static int CheckGadgetList(theGadget)
struct Gadget *theGadget;
{
int Changed = FALSE;
while (theGadget)
{
switch(theGadget->GadgetType & ~GADGETTYPE)
{
case SIZING:
Changed |= CheckGadget(theGadget,var(SizeImage),var(LR_SizeImage));
break;
case WUPFRONT:
case SUPFRONT:
Changed |=
CheckGadget(theGadget,var(UpFrontImage),var(LR_UpFrontImage));
break;
case WDOWNBACK:
case SDOWNBACK:
Changed |=
CheckGadget(theGadget,var(DownBackImage),var(LR_DownBackImage));
break;
case CLOSE:
Changed |=
CheckGadget(theGadget,var(CloseImage),var(LR_CloseImage));
break;
case BOOLGADGET:
Changed |= CheckGadget(theGadget,var(ZoomImage),var(LR_ZoomImage));
break;
}
theGadget = theGadget->NextGadget;
}
return(Changed);
}
/*
* CleanUpWindows()
*
* Looks through the intuition Screen and Window lists to see if
* any gadgets are still using the NL gadget imagery. If so,
* replace the old imagery and detail pen, then refresh the window
* to show the original gadgets. Do this all in Forbid() mode, so
* nothing changes while we're looking at the list.
*/
static void CleanUpWindows()
{
struct Screen *theScreen;
struct Window *theWindow;
int Changed;
Forbid();
theScreen = IntuitionBase->FirstScreen;
while (theScreen)
{
theWindow = theScreen->FirstWindow;
while (theWindow)
{
Changed = CheckGadgetList(theWindow->FirstGadget);
if (theWindow->BlockPen & PENCHANGED)
{
theWindow->BlockPen = STDBLOCKPEN;
if (theWindow->DetailPen & PENCHANGED)
theWindow->DetailPen = STDDETAILPEN;
Changed = TRUE;
}
if (Changed) RefreshWindowFrame(theWindow);
theWindow = theWindow->NextWindow;
}
Changed = CheckGadgetList(theScreen->FirstGadget);
if (theScreen->BlockPen & PENCHANGED)
{
theScreen->BlockPen = STDBLOCKPEN;
if (theScreen->DetailPen & PENCHANGED)
theScreen->DetailPen = STDDETAILPEN;
Changed = TRUE;
}
if (Changed)
ShowTitle(theScreen,(theScreen->Flags & SHOWTITLE)? TRUE: FALSE);
theScreen = theScreen->NextScreen;
}
if (var(Flags) & INTUITION_CHANGED)
{
InvertImage(IntuitionBase->CheckImage[0]);
InvertImage(IntuitionBase->CheckImage[1]);
InvertImage(IntuitionBase->AmigaIcon[0]);
InvertImage(IntuitionBase->AmigaIcon[1]);
var(Flags) &= ~INTUITION_CHANGED;
}
Permit();
}
/*
* Main()
*
* Look for the NL-Daemon port, which indicates that NL-Daemon already exists.
* If the port does not exist, then NL-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
* Retro-fit any existing windows to include the NL gadgets
* Notify the user that all is ready.
* else (the port already exists, so NL-Daemon alreay is active)
* Get the pointer to the NL_HandlerData structure from the port,
* and get any variables we need from the structure.
* Check that the loader versions are compatible.
* Try to remove the SetFunction calls.
* If successfull, then
* Remove the port from the system list.
* Cleanup and windows that are still using the image data
* Unload the handler segment list.
* Notify the user that NL-Daemon is deactivated.
* Close Intuition.
* else (we could not replace the functions)
* Inform the user that NL-Daemon can not be removed
*/
void main(argc,argv)
int argc;
char **argv;
{
struct MsgPort *NamedPort;
NamedPort = FindPort(PORTNAME);
if (NamedPort == NULL)
{
CheckLibOpen(&IntuitionBase,"intuition.library",INTUITION_REV);
LoadHandler(&NamedPort);
AddPort(NamedPort);
SetVariables(NamedPort,argc);
SetVectors(NamedPort);
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 {
if (UnSetVectors(NamedPort))
{
RemPort(NamedPort);
CleanUpWindows();
UnLoadSeg(var(Segment));
printf("%s removed\n",program);
CloseLibrary(IntuitionBase);
} else {
printf("SetFunction vectors have been changed!\n");
printf("Cannot remove %s\n",program);
}
}
}
}