/* * SWINDOWS A program to allow you to open windows on any screen by * supplying the screen name in thw window title * * Copyright 1989 by Davide P. Cervone. * You may use this code, provided this copywrite notice is kept intact. */ #include "swMain.h" #include "sWindows.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 swHandlerInfo *swHandlerData; /* data shared with the handler */ static long Segment; /* the loaded handler segment */ static SLISTITEM *ScreenList; /* screen item linked list */ static WLISTITEM *WindowList; /* window item linked list */ /* * FreeAllMemory() * * After the function vectors have been restored, the linked lists are * freed. If any tasks are waiting for the close signal before * closing their screens, then these tasks are signalled immediately. * Allowing the screen to close before the windows are all closed, however, * is not a good idea. */ void FreeAllMemory() { SLISTITEM theScreen; WLISTITEM theWindow; Forbid(); while (*WindowList) { theWindow = *WindowList; *WindowList = theWindow->Next; FREE(WindowListItem,theWindow); } while (*ScreenList) { theScreen = *ScreenList; *ScreenList = theScreen->Next; if (theScreen->CloseTask) Signal(theScreen->CloseTask,theScreen->CloseSignal); FREE(ScreenListItem,theScreen); } Permit(); } /* * 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; } FreeAllMemory(); 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 swHandler 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 swHandlerInfo *(*Setup)(); if ((Segment = LoadSeg(HANDLER)) == NULL) if ((Segment = LoadSeg(handler)) == NULL) DoExit("Can't load %s",handler); Setup = (struct swHandlerInfo *(*)()) ((Segment << 2) + 4); swHandlerData = (*Setup)(LOADVERS); if (swHandlerData) { if (var(MajVers) > 1) DoExit("Version mismatch with %s",HANDLER); *thePort = &(swHandlerData->swPort); } else { DoExit("%s reports a version mismatch",HANDLER); } var(Segment) = Segment; var(LoadVers) = LOADVERS; } /* * SetVerctors() * * Set the Intuition library vectors for the OpenWindow, CloseWindow * and CloseScreen to 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(OldCloseScreen) = SetFunction(IntuitionBase,&LVOCloseScreen,var(aCloseScreen)); } /* * 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,NewCloseWindow,NewCloseScreen; int status = TRUE; NewOpenWindow = SetFunction(IntuitionBase,&LVOOpenWindow,VAR(OldOpenWindow)); NewCloseWindow = SetFunction(IntuitionBase,&LVOCloseWindow,VAR(OldCloseWindow)); NewCloseScreen = SetFunction(IntuitionBase,&LVOCloseScreen,VAR(OldCloseScreen)); if (NewOpenWindow != (long) var(aOpenWindow) || NewCloseWindow != (long) var(aCloseWindow) || NewCloseScreen != (long) var(aCloseScreen)) { SetFunction(IntuitionBase,&LVOOpenWindow,NewOpenWindow); SetFunction(IntuitionBase,&LVOCloseWindow,NewCloseWindow); SetFunction(IntuitionBase,&LVOCloseScreen,NewCloseScreen); status = FALSE; } return(status); } /* * SetVariables() * * The swHandlerData 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; ScreenList = var(ScreenList); WindowList = var(WindowList); } /* * GetVariables() * * Look up the values stored in the swHandlerData 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; { swHandlerData = (struct swHandlerInfo *) thePort; IntuitionBase = VAR(IntuitionBase); ScreenList = var(ScreenList); WindowList = var(WindowList); } /* * Main() * * Look for the sWindows port, which indicates that sWindows already exists. * If the port does not exist, then sWindows 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 the the handler routines * Notify the user that all is ready. * else (the port already exists, so sWindows alreay is active) * Get the pointer to the swHandlerData 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. * Free any window and screen item memory from the linked lists. * Unload the handler segment list. * Notify the user that sWindows is deactivated. * Close Intuition. * else (we could not replace the functions) * Inform the user that sWindows 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); printf("%s v%d.%d.%d Installed\n",program, var(MajVers),var(MinVers),var(LoadVers)); } else { GetVariables(NamedPort); if (var(LoadVers) > LOADVERS) { printf("Loader version mismatch\n"); printf("Current handler was started by a higher-version loader\n"); printf("%s not removed\n",program); } else { if (UnSetVectors(NamedPort)) { RemPort(NamedPort); FreeAllMemory(); UnLoadSeg(var(Segment)); printf("%s removed\n",program); CloseLibrary(IntuitionBase); } else { printf("SetFunction vectors have been changed!\n"); printf("Cannot remove %s\n",program); } } } }