home *** CD-ROM | disk | FTP | other *** search
- /* NAME:
- ExtensionShell.c
-
- WRITTEN BY:
- Dair Grant, dair@kagi.com
-
- DESCRIPTION:
- This file contains the main entry point of Extension Shell. It
- calls everything else to do the actual work.
-
- NOTES:
- We don't lock our code resource down by hand, so we depend on
- having the System Heap and Locked attributes set.
-
- RELEASE INFORMATION:
- Extension Shell is freeware, and Copyright © 1993-96 Dair Grant.
-
- You may not charge for Extension Shell itself, or redistribute
- it as part of a commercial package without my prior permission.
-
- If you use Extension Shell in a commercial Extension, you are
- obliged to display some form of indication that your product
- uses Extension Shell. This notice must be plainly visible to
- users (either in the 'vers' resource, or in some other form of
- documentation), and not just those curious enough to use ResEdit.
-
- Shareware and Freeware products can use the code without notice.
-
- ___________________________________________________________________________
- */
- //=============================================================================
- // Include files
- //-----------------------------------------------------------------------------
- #include <MixedMode.h>
- #include <Resources.h>
- #include <Gestalt.h>
- #include "A4Stuff.h"
- #include "SetupA4.h"
- #include "ES.h"
- #include "ES Address Table.h"
- #include "ExtensionShell.h"
- #include "InstallCode.h"
- #include "UninstallCode.h"
- #include "ShowIcon.h"
- #include "NotifyMsg.h"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //=============================================================================
- // Private function prototypes
- //-----------------------------------------------------------------------------
- void main(void);
- void InitToolbox(void);
- void InitParamBlock(void);
- void CallESHandler(short theMsg);
- OSErr DoInstall(void);
- void DoUninstall(void);
- void DoErrors(void);
- void DoIcons(void);
- pascal Boolean IsKeyMouseDown(short keyCode, Boolean checkMouse);
- pascal Boolean IsTrapAvailable(short trapWord);
- pascal Boolean IsPowerMac(void);
- pascal Boolean IsTrapNative(short trapWord);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //=============================================================================
- // Global variables
- //-----------------------------------------------------------------------------
- FakeQD gTheQDGlobals;
- ESParamBlock gTheParamBlock;
- ESAddressTable *gTheESAddressTable;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //=============================================================================
- // main : Entry point to our 'INIT' code resource.
- //-----------------------------------------------------------------------------
- // Note : We need to set up A4 so that we can access our globals. We
- // do this using the standard Metrowerks routines.
- //
- // We don't lock ourself down in memory, or call DetachResource
- // on ourselves. We assume that the 'INIT' resource was compiled
- // with the System Heap and Locked attributes set.
- //-----------------------------------------------------------------------------
- void main(void)
- { long oldA4;
- THz oldZone;
-
-
-
-
- // Set up A4 and switch to the System Zone
- #ifndef powerc
- oldA4 = SetCurrentA4();
- #endif
- oldZone = GetZone();
- SetZone(SystemZone());
-
-
-
- // Initialise Extension Shell and the ES Handler
- InitToolbox();
- InitParamBlock();
- CallESHandler(kInitialiseParamBlock);
-
-
-
- // Install everything the ES Handler requested
- if (DoInstall() != noErr)
- {
- // If there's a problem, let the handler know
- CallESHandler(kHandleError);
-
-
- // If we're allowed to, try and clean up after ourselves
- if (gTheParamBlock.removeInstalledCode)
- DoUninstall();
- }
-
-
- // If the ES Handler has registered an error, handle it
- if (gTheParamBlock.beepNow || gTheParamBlock.postError)
- DoErrors();
-
-
- // Show any icons which are to be shown
- DoIcons();
-
-
- // Restore the heap zone and A4
- SetZone(oldZone);
- #ifndef powerc
- SetA4(oldA4);
- #endif
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //=============================================================================
- // InitToolbox : Initialises the Toolbox.
- //-----------------------------------------------------------------------------
- // Note : If we initialise all the Toolbox Managers, we will erase the
- // screen. This looks ugly - so don't define __InitAllToolbox__
- // unless you really don't care.
- //-----------------------------------------------------------------------------
- void InitToolbox(void)
- {
-
-
-
- // Initialise the bits of the Toolbox that we need
- InitGraf(&gTheQDGlobals.thePort);
-
-
- #ifdef __InitAllToolbox__
- // This fixes the pre-Mac II bug that can happen if we try
- // and create a window from within an INIT.
- *((void**)DragHook) = nil;
- *((void**)DeskHook) = nil;
-
-
- // Initialise the rest of the Toolbox
- InitFonts();
- InitWindows();
- InitCursor();
- InitMenus();
- InitDialogs(nil);
- TEInit();
- #endif
-
-
- // Flush out any events that may be lurking
- FlushEvents(everyEvent, 0);
- FlushEvents(everyEvent, 0);
- FlushEvents(everyEvent, 0);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //=============================================================================
- // InitParamBlock : Initialise gTheParamBlock.
- //-----------------------------------------------------------------------------
- // Note : We want to minimise the work the ES Handler has to do, so
- // we initialise the fields to their most 'normal' values.
- //-----------------------------------------------------------------------------
- void InitParamBlock(void)
- { OSErr myErr;
-
-
-
-
- // Initialise the general values
- myErr = Gestalt(gestaltSystemVersion, &gTheParamBlock.systemVersion);
- gTheParamBlock.NotificationMsg = NotificationMessage;
- gTheParamBlock.IsKeyMouseDown = IsKeyMouseDown;
- gTheParamBlock.IsTrapAvailable = IsTrapAvailable;
- gTheParamBlock.IsPowerMac = IsPowerMac;
- gTheParamBlock.IsTrapNative = IsTrapNative;
-
-
- // Initialise the Icon related values
- gTheParamBlock.numIcons = 0;
- gTheParamBlock.animationDelay = 3;
-
-
- // Initialise the installable code related values
- gTheParamBlock.installAddressTable = false;
- gTheParamBlock.numCodeResources = 0;
- gTheParamBlock.errorIndex = 0;
- gTheParamBlock.theErr = noErr;
-
-
- // Initialise the error handling related values
- gTheParamBlock.removeInstalledCode = false;
- gTheParamBlock.beepNow = false;
- gTheParamBlock.postError = false;
- gTheParamBlock.errorStringsID = 0;
- gTheParamBlock.errorStringIndex = 0;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //=============================================================================
- // CallESHandler : Execute the ES Handler CODE resource.
- //-----------------------------------------------------------------------------
- // Note : This routine can be called several times. We load the CODE
- // resource in once, and save it in a static variable. When
- // the System closes our resource fork, the code will get
- // flushed out (we're not calling DetachResource).
- //
- // If we can't find the ES Handler, we drop into the Debugger.
- //-----------------------------------------------------------------------------
- void CallESHandler(short theMsg)
- { static ESHandlerProc theHandler = (ESHandlerProc) nil;
- Handle theHnd;
-
-
-
- // If we've not already loaded the code, do so, and lock it down
- if (theHandler == nil)
- {
- theHnd = Get1Resource(kESHandlerCodeType, kESHandlerCodeID);
- if (theHnd == nil)
- DebugStr("\pExtension Shell - couldn't find ES Handler");
- else
- HLock(theHnd);
-
- theHandler = (ESHandlerProc) StripAddress(*theHnd);
- }
-
-
- // Call the code with the message and the param block
- (*theHandler)(theMsg, &gTheParamBlock);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //=============================================================================
- // DoInstall : Install what the ES Handler wants installed.
- //-----------------------------------------------------------------------------
- // Note : This routine attempts to install the routines the ES Handler
- // has requested. If there is a problem, the appropriate fields
- // in gTheParamBlock will be filled in, and an error code
- // returned.
- //-----------------------------------------------------------------------------
- OSErr DoInstall(void)
- { short i;
- OSErr theErr = noErr;
-
-
-
- // Install the address table, if one has been requested. This has to
- // be done first in case installed code is going to be called before
- // we're finished (e.g., a trap patch to GetResource).
- //
- // If the address table is installed correctly, we call the ES
- // Handler to give it a chance to initialise any fields it may
- // have added. If it sets gTheParamBlock.theErr to anything other
- // than noErr, we abort the installation process.
- if (gTheParamBlock.installAddressTable)
- {
- InstallESAddressTable();
-
- CallESHandler(kInitialiseAddrsTable);
- if (gTheParamBlock.theErr != noErr)
- return(gTheParamBlock.theErr);
- }
-
-
- // Install each resource in turn. If there's a problem, we save the
- // error details and break out of the loop.
- if (gTheParamBlock.numCodeResources >= 1)
- {
- for (i = 1; i <= gTheParamBlock.numCodeResources && theErr == noErr; i++)
- {
- theErr = InstallCode(i);
- if (theErr != noErr)
- {
- gTheParamBlock.errorIndex = i;
- gTheParamBlock.theErr = theErr;
- }
- }
- }
-
-
- // Return any error code
- return(gTheParamBlock.theErr);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //=============================================================================
- // DoUninstall : Try and uninstall anything which has been installed.
- //-----------------------------------------------------------------------------
- // Note : This routine attempts to remove the routines the ES Handler
- // resource tried to install. The error index is assumed to
- // indicate which resource could not be installed, and so
- // only entries before this index are candidates for removal.
-
- // We make *no* guarantees as to what can be removed. Hopefully,
- // most things can, but you never know.
- //-----------------------------------------------------------------------------
- void DoUninstall(void)
- { short i;
-
-
-
- // gTheParamBlock.ErrorIndex contains the index of the item that
- // couldn't be installed. We try and uninstall everything before this.
- if (gTheParamBlock.errorIndex > 1 && gTheParamBlock.numCodeResources >= 1)
- {
- for (i = 1; i < gTheParamBlock.errorIndex; i++)
- UninstallCode(i);
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //=============================================================================
- // DoErrors : Provide some error handling capabilities.
- //-----------------------------------------------------------------------------
- // Note : This routine is how Extension Shell communicates errors to the
- // user. The two functions it offers are to beep, and to post a
- // Notification Manager dialog to the user.
- //-----------------------------------------------------------------------------
- void DoErrors(void)
- {
-
-
- // If we're to beep, do so now
- if (gTheParamBlock.beepNow)
- SysBeep(30);
-
-
- // If we're to post a NM message, do so
- if (gTheParamBlock.postError)
- NotificationMessage(gTheParamBlock.errorStringsID, gTheParamBlock.errorStringIndex);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //=============================================================================
- // DoIcons : Call PlotINITIcon to display the icons.
- //-----------------------------------------------------------------------------
- // Note : We pull the values out of gTheParamBlock, and let PlotINITIcon
- // do all the work.
- //-----------------------------------------------------------------------------
- void DoIcons(void)
- { Boolean useIconSuite;
-
-
-
-
- // Call PlotINITIcon to do the work
- useIconSuite = IsTrapAvailable(_OpenCPort) && IsTrapAvailable(_IconDispatch);
- PlotINITIcon(useIconSuite,
- gTheParamBlock.animationDelay,
- gTheParamBlock.numIcons,
- &gTheParamBlock.theIcons);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //=============================================================================
- // IsKeyMouseDown : Called by the ES Handler to scan the keyboard.
- //-----------------------------------------------------------------------------
- // Note : We return true if the key corresponding to KeyCode is pressed,
- // and false otherwise.
- //
- // If checkMouse is true, we also return false if the mouse is not
- // pressed, and true if it is.
- //-----------------------------------------------------------------------------
- pascal Boolean IsKeyMouseDown(short keyCode, Boolean checkMouse)
- { unsigned char theKeys[16];
-
-
-
-
- // First check the keyboard
- GetKeys((void *) theKeys);
- if ((theKeys[keyCode >> 3] >> (keyCode & 7)) & 1)
- return(true);
-
-
- // Then check the mouse, if we're allowed to
- if (checkMouse)
- return(Button());
-
-
- // If we've got this far, nothing is being pressed
- return(false);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //=============================================================================
- // IsTrapAvailable : Determines if a given trap number is implemented.
- //-----------------------------------------------------------------------------
- pascal Boolean IsTrapAvailable(short trapWord)
- { TrapType trapType;
- short numToolboxTraps;
-
-
-
- // Check trap word for Toolbox bit
- trapType = (trapWord & 0x0800) ? ToolTrap : OSTrap;
-
-
- // If it's a Toolbox trap...
- if (trapType == ToolTrap)
- {
- // Mask through largest # of traps available
- trapWord &= 0x07FF;
-
-
- // Is _InitGraf at the same address as 0xAA6E?
- if (NGetTrapAddress(kInitGrafTrap,ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
- numToolboxTraps = 0x0200; // Yes, only this many entries in dispatch table
- else
- numToolboxTraps = 0x0400; // No, dispatch table is larger
-
-
- // Trap # bigger than dispatch table? If so it's a bogus trap, so abort
- if (trapWord > numToolboxTraps)
- return(false);
- }
-
-
-
- // Return trap address if it's not an unimplemented trap
- return(NGetTrapAddress(trapWord, trapType) != NGetTrapAddress(kUnimplementedTrap, ToolTrap));
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //=============================================================================
- // IsPowerMac : Is this a PowerMac?
- //-----------------------------------------------------------------------------
- pascal Boolean IsPowerMac(void)
- { long result;
- OSErr theErr;
-
-
- theErr = Gestalt(gestaltSysArchitecture, &result);
- if (theErr == noErr && result == gestaltPowerPC)
- return(true);
- else
- return(false);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //=============================================================================
- // IsTrapNative : Is a trap native?
- //-----------------------------------------------------------------------------
- pascal Boolean IsTrapNative(short trapWord)
- { TrapType trapType;
- short *theCode;
-
-
-
- // Get the address of the trap code
- trapType = (trapWord & 0x0800) ? ToolTrap : OSTrap;
- theCode = (short *) NGetTrapAddress(trapWord, trapType);
-
-
- // If the trap is native, it will start with the Mixed Mode Magic word
- return(*theCode == _MixedModeMagic);
- }
-