Checking the Operating Environment
CallingExitToShellis the preferred way to terminate your application if for some reason you don't want to return to your main event loop. You might also want to callDoBadErrorto terminate your application before you even get to the main event loop. This might happen if your application requires system software routines that aren't available in all operating environments. In general, if your application uses any system software routines that aren't available in all operating environments, you need to make sure that they are available in the current environment. Otherwise, your application will crash.For example, the Venn Diagrammer application uses the
FindFolderfunction to find the Preferences folder containing the application's preferences file (see Listing 3-3 on page 62). BecauseFindFolderwas introduced in system software version 7.0, Venn Diagrammer will crash if it callsFindFolderwhen running in an earlier system software version.To avoid crashing in environments that don't support the
FindFolderfunction, the Venn Diagrammer application makes sure that the function is available before calling it. It calls theGestaltfunction to see ifFindFolderis present, as shown in Listing 9-6.Listing 9-6 Checking that
FindFolderis present
FUNCTION IsFindFolder: Boolean; VAR myResult: OSErr; myFeature: LongInt; BEGIN IsFindFolder := FALSE; {assume it's not available} myResult := Gestalt(gestaltFindFolderAttr, myFeature); IF myResult = noErr THEN IsFindFolder := BTST(myFeature, gestaltFindFolderPresent); END;TheGestaltfunction is part of the Gestalt Manager, which you can use to determine what software and hardware features are available in the current operating environment. When passed thegestaltFindFolderAttrselector code, theGestaltfunction fills in the long integer passed in its second parameter (myFeature) with a bit field that encodes information about the features of theFindFolderfunction. Currently only one bit is defined, specified using the constantgestaltFindFolderPresent. If that bit is set, thenFindFolderis present in the operating environment. The Venn Diagrammer application callsIsFindFolderas follows (see Listing 3-3 on page 62):
IF IsFindFolder THEN myResult := FindFolder(kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder, myVRefNum, myDirID);If
- Note
- For complete details about using the
Gestaltfunction to determine the features of the current operating environment, see the chapter "Gestalt Manager" in Inside Macintosh: Operating System Utilities.![]()
FindFolderfunction isn't available, Venn Diagrammer looks in the default directory instead of in the Preferences folder for the user's preferences file. This isn't the best strategy possible, but it's good enough for a simple application like Venn Diagrammer. More generally, however, you need to decide what the base system software requirements of your application are and how you want to react if necessary services aren't available. In some cases, working around a problem isn't so easy. In those cases, informing the user that your software won't run in the current system configuration and then exiting is probably the right thing to do.A second way to determine the availability of a particular system software routine is to test directly for the existence of the routine by inspecting its trap number (a number that identifies each system software routine), using the technique illustrated in Listing 9-7. You should use this method to test for the existence of routines not included in managers about which
Gestaltcan report.Listing 9-7 Determining whether a trap is available
FUNCTION NumToolboxTraps: Integer; BEGIN IF NGetTrapAddress(_InitGraf, ToolTrap) = NGetTrapAddress($AA6E, ToolTrap) THEN NumToolboxTraps := $200 ELSE NumToolboxTraps := $400; END; FUNCTION GetTrapType (theTrap: Integer): TrapType; CONST TrapMask = $0800; BEGIN IF BAND(theTrap, TrapMask) > 0 THEN GetTrapType := ToolTrap ELSE GetTrapType := OSTrap; END; FUNCTION TrapAvailable (theTrap: Integer): Boolean; VAR tType: TrapType; BEGIN tType := GetTrapType(theTrap); IF tType = ToolTrap THEN BEGIN theTrap := BAND(theTrap, $07FF); IF theTrap >= NumToolboxTraps THEN theTrap := _Unimplemented; END; TrapAvailable := NGetTrapAddress(theTrap, tType) <> NGetTrapAddress(_Unimplemented, ToolTrap); END;Listing 9-8 shows how to use theTrapAvailablefunction defined in Listing 9-7 to determine whether theWaitNextEventfunction is available.Listing 9-8 Checking for the availability of the
WaitNextEventfunction
FUNCTION WNEAvailable: Boolean; CONST _WaitNextEvent = $A860; {trap number of WaitNextEvent} BEGIN WNEAvailable := TrapAvailable(_WaitNextEvent); END;TheNumToolboxTrapsfunction relies on the fact that theInitGraftrap (trap number $A86E) is always implemented. If the trap dispatch table is large enough (that is, has more than $200 entries), then $AA6E always points to either_Unimplementedor something else, but never toInitGraf. As a result, you can check the size of the trap dispatch table by checking to see if the address of trap $A86E is the same as $AA6E.After receiving the information about the size of the dispatch table, the
TrapAvailablefunction first checks to see if the trap to be tested has a trap number greater than the total number of traps available on the machine. If so, it sets thetheTrapvariable to_Unimplementedbefore testing it against the_Unimplementedtrap. See the discussion of the trap dispatch table utilities in Inside Macintosh: Operating System Utilities for complete details on trap numbers and the trap dispatch table.
- IMPORTANT
- There's one final twist in this story. Your software development system might provide glue routines that mimic the operation of some system software routines, thereby allowing you to call them in earlier system software versions. (For instance, MPW versions 3.2 and later provide glue that allows you to call
FindFolderin system software versions prior to 7.0.) However, you cannot in general useGestaltor the technique shown in Listing 9-7 to test for the availability of routines provided as glue. Instead, you'll need to consult the documentation for your development system to find out what glue routines it provides.![]()