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 theGestalt
function to get information about hardware or software components available on the current machine. You can useNewGestalt
to register new software modules (such as drivers and patches) with the Gestalt Manager. You can useReplaceGestalt
to 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
NewGestalt
orReplaceGestalt
.SysEnvirons
function.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
Gestalt
function 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. IfGestalt
is available, you can safely assume thatNewGestalt
andReplaceGestalt
are 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 theGestalt
function, 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 theNewGestalt
function (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
Gestalt
can determine the requested information, it returns that information in theresponse
parameter 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 theresponse
parameter is undefined. You should always check the result code returned byGestalt
to make sure that theresponse
parameter contains meaningful information.Listing 1-2 illustrates an application-defined function that retrieves the sound attributes of the current operating environment. The application-defined
MyGetSoundAttr
function checks the function result returned byGestalt
and 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 fromGestalt
by 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
Gestalt
when 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 useGestalt
to 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 thatGestalt
returns in theresponse
parameter depends on the selector code with which it was called. For example, if you callGestalt
using thegestaltTimeMgrVersion
selector, it returns a version code in theresponse
parameter. 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
Gestalt
to place in theresponse
parameter. For example, if the suffix in aGestalt
selector isSize
, thenGestalt
returns a size in theresponse
parameter. Table 1-1 lists the meaningful suffixes.Selectors that have the suffix
Attr
deserve special attention. They causeGestalt
to 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 aLongInt
that 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 functionMyIsStereoMixing
in 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;TheMyIsStereoMixing
function uses the MPW Pascal functionBTst
and the application-definedMyGetSoundAttr
function to determine whether the stereo-mixing bit is set in theresponse
value returned byGestalt
when it's called with thegestaltSoundAttr
selector. The constantgestaltStereoMixing
is defined in the header files.Adding a New Selector Code
You can add your own selector code to those already understood byGestalt
by calling theNewGestalt
function. 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 callGestalt
to make sure the debugger is available before invoking those instructions.The
NewGestalt
function requires two parameters: the new selector to be registered and the address of the associated selector function.Gestalt
executes 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 aGestalt
selector 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.
Gestalt
with 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;TheGestalt
function passes its input parameters on to your selector function. Your function places the requested information in theLongInt
pointed to by theresponse
parameter and returns an error code, whichGestalt
returns 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
Gestalt
and pass it other selector codes. Note that theresponse
parameter 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
response
parameter and returns an error code ofnoErr
. The application-defined sample function,MyGestaltPipe
, is isolated in aUNIT
element 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 aGestalt
selector code, you first move the selector function into the system heap and then call theNewGestalt
function, which adds the selector code and its function to theGestalt
repertoire.
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.
Gestalt
selector.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 procedureMyInstallGestFunc
loads 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
FlushInstructionCache
procedure every time you modify code in RAM. See the chapter "Memory Management Utilities" in Inside Macintosh: Memory for details aboutFlushInstructionCache
.MyInstallGestFunc
callsNewGestalt
to register the selector code'PIPE'
and its selector function with the Gestalt Manager.Because the new selector function resides in the system heap,
Gestalt
recognizes 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 theresponse
value. 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
Gestalt
already recognizes,NewGestalt
returns the error codegestaltDupSelectorErr
.Modifying a Selector Function
You can use theReplaceGestalt
function to modify the function thatGestalt
executes 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,
ReplaceGestalt
returns the address of the previous function.If you attempt to redefine a selector that is not yet defined,
ReplaceGestalt
returns an error code; in that case, the address of the previous function is undefined. Always test the result code ofReplaceGestalt
before callingGestalt
with that selector or attempting to use theresponse
parameter.
Because
- Note
- If you modify the function associated with an existing
Gestalt
selector, do not use any bits in theresponse
parameter that are not documented in this chapter. Apple reserves all undocumented bits in theresponse
parameters returned by Apple-definedGestalt
selectors.ReplaceGestalt
supplies 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 theSysEnvirons
function, which predates the Gestalt Manager, to get a brief description of the operating environment. TheSysEnvirons
function is available on all models of the Macintosh computer since the Macintosh SE and Macintosh II.
The
- Note
- The
SysEnvirons
function is not part of the Gestalt Manager, but is documented in this chapter for the sake of completeness.SysEnvirons
function 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 theFindFolder
function). See "The System Environment Record" beginning on page 1-28 for a complete description of the system environment record.