Important: The information in this document is obsolete and should not be used for new development.
Using the Gestalt Manager
The Gestalt Manager includes three functions--Gestalt,NewGestalt, andReplaceGestalt. You can use theGestaltfunction to get information about hardware or software components available on the current machine. You can useNewGestaltto register new software modules (such as drivers and patches) with the Gestalt Manager. You can useReplaceGestaltto replace the function associated with a particular selector code.
If the Gestalt Manager is not present, you can get a brief description of the operating environment by calling the
- Note
- Most applications do not need to use either
NewGestaltorReplaceGestalt.![]()
SysEnvironsfunction.Determining Whether the Gestalt Manager Is Available
Versions 3.2 and later of MPW provide glue routines that allow you to call the Gestalt Manager functions even if they're not in ROM or in the System file (that is, if your application is running under a system software version earlier than 6.0.4). In assembly language, however, and possibly in other development environments, you must verify that the Gestalt Manager is available before you use it.You can verify that the
Gestaltfunction is available by calling the functionNGetTrapAddress, specifying the trap number ofGestalt, and comparing the result with the address of the code that is executed when you invoke an unimplemented instruction. IfGestaltis available, you can safely assume thatNewGestaltandReplaceGestaltare also available. For efficiency, you might want to define a global Boolean variable that you can set at the beginning of your program. Listing 1-1 illustrates a test that sets the variablegHasGestalt.Listing 1-1 Determining whether Gestalt is available
gHasGestalt := MySWRoutineAvailable(_Gestalt);For a sample definition of the application-defined functionMySWRoutineAvailable, see the chapter "Trap Manager" later in this book.Getting Information About the Operating Environment
When your application needs information about a software or hardware feature, it calls theGestaltfunction, which has this interface:
FUNCTION Gestalt (selector: OSType; VAR response: LongInt): OSErr;The first parameter is a selector code, which specifies the kind of information your application needs. You can use any of the Apple-defined selector codes listed later in this section and described in more detail in the section "Constants" beginning on page 1-14. You can also define and register your own selector codes using theNewGestaltfunction (as described in "Adding a New Selector Code" beginning on page 1-10), and you can use selector codes defined and registered by other applications.If
Gestaltcan determine the requested information, it returns that information in theresponseparameter and returns a result code ofnoErr. If Gestalt cannot obtain the information, it returns a result code indicating the cause of the error; in that case, the value of theresponseparameter is undefined. You should always check the result code returned byGestaltto make sure that theresponseparameter contains meaningful information.Listing 1-2 illustrates an application-defined function that retrieves the sound attributes of the current operating environment. The application-defined
MyGetSoundAttrfunction checks the function result returned byGestaltand passes any calls with a nonzero result code to an error-handling routine.Listing 1-2 Calling Gestalt and checking its result code
FUNCTION MyGetSoundAttr: LongInt; VAR myErr: OSErr; myAttr: LongInt; BEGIN IF gHasGestalt THEN BEGIN myErr := Gestalt(gestaltSoundAttr, myAttr); IF myErr <> noErr THEN {Gestalt failed} DoError(myErr) END ELSE myAttr := 0; {Gestalt not available} MyGetSoundAttr := myAttr; END;You get different kinds of information fromGestaltby passing selectors from two kinds of Apple-defined selector codes:
It is particularly important that you understand the difference between environmental and informational selectors. The response returned by
- environmental selectors, which return information your application can use to guide its actions
- informational selectors, which return information that cannot be used to determine whether a feature is available
Gestaltwhen it is passed an informational selector is for your (or the user's) edification only; it should never be used by your application to determine whether a specific hardware or software feature is available. For example, you can useGestaltto test for the version of the ROM installed on a particular machine. You can display this information to the user, but you should not infer from it anything about the actual software available. Routines you expect to be in ROM may actually be in RAM; hence, you cannot know that a routine usually found in ROM is not present simply because the ROM version predates the routine. Also, routines contained in ROM may have been patched by the system at startup time, in which case the system might not have the features you think it has on the basis of the reported ROM version. A Macintosh Plus with an old ROM, for example, could be running System 7. Similar remarks apply to other informational selectors, including ROM size, machine type, and System file version number.To retrieve specific information about the hardware and software features available, you can use the following environmental selectors:
CONST gestaltAddressingModeAttr = 'addr'; {addressing-mode attributes} gestaltAliasMgrAttr = 'alis'; {Alias Manager attributes} gestaltAppleEventsAttr = 'evnt'; {Apple events attributes} gestaltAppleTalkVersion = 'atlk'; {old format AppleTalk version} gestaltATalkVersion = 'atkv'; {new format AppleTalk version} gestaltAUXVersion = 'a/ux'; {A/UX version, if present} gestaltCFMAttr = 'cfrg'; {Code Fragment Manager attributes} gestaltCloseViewAttr = 'BSDa'; {CloseView attributes} gestaltComponentMgr = 'cpnt'; {Component Manager version} gestaltCompressionMgr = 'icmp'; {Image Compression Manager version} gestaltConnMgrAttr = 'conn'; {Connection Manager attributes} gestaltCRMAttr = 'crm '; {Communication Resource Manager } { attributes} gestaltCTBVersion = 'ctbv'; {Communication Toolbox version} gestaltDBAccessMgrAttr = 'dbac'; {Data Access Manager attributes} gestaltDictionaryMgrAttr = 'dict'; {Dictionary Manager attributes} gestaltDisplayMgrAttr = 'dply'; {Display Manager atributes} gestaltDisplayMgrVers = 'dplv'; {Display Manager version} gestaltDITLExtAttr = 'ditl'; {Dialog Manager extensions} gestaltDragMgrAttr = 'drag'; {Drag Manager attributes} gestaltEasyAccessAttr = 'easy'; {Easy Access attributes} gestaltEditionMgrAttr = 'edtn'; {Edition Manager attributes} gestaltExtToolboxTable = 'xttt'; {Toolbox trap dispatch table info} gestaltFinderAttr = 'fndr'; {Finder attributes} gestaltFindFolderAttr = 'fold'; {FindFolder attributes} gestaltFirstSlotNumber = 'slt1'; {first physical slot} gestaltFontMgrAttr = 'font'; {Font Manager attributes} gestaltFPUType = 'fpu '; {floating-point unit (FPU) type} gestaltFSAttr = 'fs '; {file system attributes} gestaltFXfrMgrAttr = 'fxfr'; {File Transfer Manager attributes} gestaltHelpMgrAttr = 'help'; {Help Manager attributes} gestaltIconUtilitiesAttr = 'icon'; {Icon Utilities attributes} gestaltKeyboardType = 'kbd '; {keyboard type code} gestaltLogicalPageSize = 'pgsz'; {logical page size} gestaltLogicalRAMSize = 'lram'; {logical RAM size} gestaltLowMemorySize = 'lmem'; {size of low memory} gestaltMiscAttr = 'misc'; {miscellaneous attributes} gestaltMixedModeVersion = 'mixd'; {MixedMode version} gestaltMMUType = 'mmu '; {MMU type} gestaltNativeCPUtype = 'cput'; {native CPU type} gestaltNotificationMgrAttr = 'nmgr'; {Notification Manager attributes} gestaltNuBusConnectors = 'sltc'; {NuBus connector bitmap} gestaltNuBusSlotCount = 'nubs'; {number of logical NuBus slots} gestaltOSAttr = 'os '; {Operating System attributes} gestaltOSTable = 'ostt'; {base address of Operating System } { trap dispatch table} gestaltParityAttr = 'prty'; {parity attributes} gestaltPCXAttr = 'pcxg'; {PC exchange attributes} gestaltPhysicalRAMSize = 'ram '; {physical RAM size} gestaltPopupAttr = 'pop!'; {pop-up 'CDEF' attributes} gestaltPowerMgrAttr = 'powr'; {Power Manager attributes} gestaltPPCToolboxAttr = 'ppc '; {Program-to-Program Communications } { (PPC) Toolbox attributes} gestaltProcessorType = 'proc'; {microprocessor type code} gestaltQuickdrawFeatures = 'qdrw'; {QuickDraw features} gestaltQuickdrawVersion = 'qd '; {QuickDraw version} gestaltQuickTimeVersion = 'qtim'; {QuickTime version} gestaltRealTimeMgrAttr = 'rtmr'; {Realtime Manager attributes} gestaltResourceMgrAttr = 'rsrc'; {Resource Manager attributes} gestaltScrapMgrAttr = 'scra'; {Scrap Manager attributes} gestaltScriptCount = 'scr#'; {number of active script systems} gestaltScriptMgrVersion = 'scri'; {Script Manager version} gestaltSerialAttr = 'ser '; {serial hardware attributes} gestaltSlotAttr = 'slot'; {slot attributes} gestaltSoundAttr = 'snd '; {sound attributes} gestaltSpeechAttr = 'ttsc'; {Speech Manager attributes} gestaltStandardFileAttr = 'stdf'; {Standard File attributes}} gestaltStdNBPAttr = 'nlup'; {StandardNBP attributes} gestaltSysArchitecture = 'sysa'; {Native System Architecture} gestaltTEAttr = 'teat'; {TextEdit attributes} gestaltTermMgrAttr = 'term'; {Terminal Manager attributes} gestaltTextEditVersion = 'te '; {TextEdit version code} gestaltThreadMgrAttr = 'thds'; {Thread Manager attributes} gestaltTimeMgrVersion = 'tmgr'; {Time Manager version code} gestaltToolboxTable = 'tbtt'; {base address of Toolbox trap } { dispatch table} gestaltTranslationAttr = 'xlat'; {Translation Manager attributes} gestaltTSMgrVersion = 'tsmv'; {Text Services Manager version} gestaltVersion = 'vers'; {Gestalt version} gestaltVMAttr = 'vm '; {virtual memory attributes}The informational selectors are provided for your or the user's information only. You can display the information returned from these selectors, but you should never use this information as an indication of what hardware or software features may be available. You can use the following informational selectors:
CONST gestaltHardwareAttr = 'hdwr'; {hardware attributes} gestaltMachineIcon = 'micn'; {machine 'ICON'/'cicn' resource ID} gestaltMachineType = 'mach'; {Macintosh model code} gestaltROMSize = 'rom '; {ROM size} gestaltROMVersion = 'romv'; {ROM version} gestaltSystemVersion = 'sysv'; {System file version number}For a description of the return values for these environmental and informational selectors, see the next section, "Interpreting Gestalt Responses," and the list of constants beginning on page 1-14.Interpreting Gestalt Responses
The meaning of the value thatGestaltreturns in theresponseparameter depends on the selector code with which it was called. For example, if you callGestaltusing thegestaltTimeMgrVersionselector, it returns a version code in theresponseparameter. In this case, a returned value of 3 indicates that the extended Time Manager is available.In most cases, the last few characters in the selector's symbolic name form a suffix that indicates what type of value you can expect
Gestaltto place in theresponseparameter. For example, if the suffix in aGestaltselector isSize, thenGestaltreturns a size in theresponseparameter. Table 1-1 lists the meaningful suffixes.Selectors that have the suffix
Attrdeserve special attention. They causeGestaltto return a bit field that your application must interpret to determine whether a desired feature is present. For example, the application-defined sample functionMyGetSoundAttr, defined in Listing 1-2 on page 1-6, returns aLongIntthat contains the Sound Manager attributes field retrieved fromGestalt. To determine whether a particular feature is available, you need to look at the designated bit. The application-defined sample functionMyIsStereoMixingin Listing 1-3, for example, determines whether stereo mixing is available.Listing 1-3 Interpreting a Gestalt attributes response
FUNCTION MyIsStereoMixing: Boolean; BEGIN MyIsStereoMixing := BTst(MyGetSoundAttr, gestaltStereoMixing); END;TheMyIsStereoMixingfunction uses the MPW Pascal functionBTstand the application-definedMyGetSoundAttrfunction to determine whether the stereo-mixing bit is set in theresponsevalue returned byGestaltwhen it's called with thegestaltSoundAttrselector. The constantgestaltStereoMixingis defined in the header files.Adding a New Selector Code
You can add your own selector code to those already understood byGestaltby calling theNewGestaltfunction. Typically, a system extension registers itself with the Gestalt Manager so that applications that might use its services can find out whether it's there. A debugger, for example, could register its presence. Programmers working on an application could then embed instructions for the debugger in code under development and callGestaltto make sure the debugger is available before invoking those instructions.The
NewGestaltfunction requires two parameters: the new selector to be registered and the address of the associated selector function.Gestaltexecutes the selector function to determine what value to pass back when it's called with the new selector code.The selector code is a four-character sequence of type
OSType. If you have registered a creator string with Apple Computer, Inc., you are strongly encouraged to use that sequence as your selector code. The Pipeline debugger, for example, with a creator string of'PIPE', would use aGestaltselector code of'PIPE'.
When you register your own selector code with the Gestalt Manager, you supply the address of the selector function to be executed when an application calls
- Note
- Apple reserves for its own use all four-character sequences consisting solely of lowercase letters and nonalphabetic ASCII characters.
![]()
Gestaltwith that code. Your selector function must reside in the system heap and must have the following interface:
FUNCTION MySelectorFunction (selector: OSType; VAR response: LongInt): OSErr;TheGestaltfunction passes its input parameters on to your selector function. Your function places the requested information in theLongIntpointed to by theresponseparameter and returns an error code, whichGestaltreturns to its caller.Your selector function should be as simple as possible. If your function needs to use global variables from the A5 world--that of your own software or that of some other software--it must explicitly set up A5 and then restore it upon exit. (See Inside Macintosh: Memory for an explanation of setting up and restoring the A5 world.)
Your selector function can, if necessary, call
Gestaltand pass it other selector codes. Note that theresponseparameter is merely the address into which your function places the information requested. You cannot use that parameter to pass information to your selector function.Listing 1-4 illustrates a minimal selector function that sets the
responseparameter and returns an error code ofnoErr. The application-defined sample function,MyGestaltPipe, is isolated in aUNITelement for separate compilation and placement in a resource.Listing 1-4 Defining a simple Gestalt selector function
UNIT GestaltFunc; INTERFACE USES OSIntf; FUNCTION MyGestaltPipe (gestaltSelector: OSType; VAR gestaltReply: LongInt): OSErr; IMPLEMENTATION FUNCTION MyGestaltPipe; BEGIN gestaltReply := $ACE; {reply defined by Pipeline} MyGestaltPipe := noErr; {too simple for errors} END; END.This sample linking command places the compiled code in resource ID 128 of a type arbitrarily named'GDEF'.
Link GestaltFunc.p.o -rn -rt GDEF=128 -o PipelineTo add aGestaltselector code, you first move the selector function into the system heap and then call theNewGestaltfunction, which adds the selector code and its function to theGestaltrepertoire.
Listing 1-5 illustrates the installation of a new
- WARNING
- Take special care when accessing memory in the system heap; it persists even after your application terminates.
![]()
Gestaltselector.Listing 1-5 Installing a new Gestalt selector
PROCEDURE MyInstallGestFunc; VAR gestFuncHandle: Handle; gestFuncSize: Size; gestSysPtr: Ptr; myErr: OSErr; BEGIN gestFuncHandle := GetResource('GDEF', 128); IF ResError = noErr THEN BEGIN gestFuncSize := SizeResource(gestFuncHandle); gestSysPtr := NewPtrSys(gestFuncSize); IF MemError = noErr THEN BEGIN BlockMove(gestFuncHandle^, gestSysPtr, gestFuncSize); FlushInstructionCache; myErr := NewGestalt('PIPE', SelectorFunctionUUP(gestSysPtr)); END; ReleaseResource(gestFuncHandle); END; END;The application-defined sample procedureMyInstallGestFuncloads the resource and then gets its size so it can allocate a pointer in the system heap. It then copies the resource to the pointer and releases the resource.
Finally,
- WARNING
- Be sure to call the
FlushInstructionCacheprocedure every time you modify code in RAM. See the chapter "Memory Management Utilities" in Inside Macintosh: Memory for details aboutFlushInstructionCache.![]()
MyInstallGestFunccallsNewGestaltto register the selector code'PIPE'and its selector function with the Gestalt Manager.Because the new selector function resides in the system heap,
Gestaltrecognizes and responds to the new selector until the machine restarts, even if your software terminates before that time. You might therefore want your selector function to determine whether your software is still running before filling in theresponsevalue. The simplest way to report that your application is not available is to return an error code.If you attempt to add a selector code that
Gestaltalready recognizes,NewGestaltreturns the error codegestaltDupSelectorErr.Modifying a Selector Function
You can use theReplaceGestaltfunction to modify the function thatGestaltexecutes when passed a particular selector code. Your replacement selector function must reside in the system heap and must conform to the interface defined in the previous section, "Adding a New Selector Code."To allow the new function to call the function it's replacing,
ReplaceGestaltreturns the address of the previous function.If you attempt to redefine a selector that is not yet defined,
ReplaceGestaltreturns an error code; in that case, the address of the previous function is undefined. Always test the result code ofReplaceGestaltbefore callingGestaltwith that selector or attempting to use theresponseparameter.
Because
- Note
- If you modify the function associated with an existing
Gestaltselector, do not use any bits in theresponseparameter that are not documented in this chapter. Apple reserves all undocumented bits in theresponseparameters returned by Apple-definedGestaltselectors.![]()
ReplaceGestaltsupplies the address of the function it's replacing, you can use it to retrieve the address of the selector function associated with a selector code.Getting Environmental Information Without the Gestalt Manager
You can call theSysEnvironsfunction, which predates the Gestalt Manager, to get a brief description of the operating environment. TheSysEnvironsfunction is available on all models of the Macintosh computer since the Macintosh SE and Macintosh II.
The
- Note
- The
SysEnvironsfunction is not part of the Gestalt Manager, but is documented in this chapter for the sake of completeness.![]()
SysEnvironsfunction fills in a record that contains the model of the machine, the System file version number, the microprocessor type, a keyboard type code, and Boolean indicators of whether the machine has a floating-point unit or Color QuickDraw. The system environment record includes one detail not available throughGestalt: the working directory reference number of the folder or volume that holds the System file (although that information is available through theFindFolderfunction). See "The System Environment Record" beginning on page 1-28 for a complete description of the system environment record.