Legacy Documentclose button

Important: The information in this document is obsolete and should not be used for new development.

Previous Book Contents Book Index Next

Inside Macintosh: Operating System Utilities /
Chapter 1 - Gestalt Manager


Using the Gestalt Manager

The Gestalt Manager includes three functions--Gestalt, NewGestalt, and ReplaceGestalt. You can use the Gestalt function to get information about hardware or software components available on the current machine. You can use NewGestalt to register new software modules (such as drivers and patches) with the Gestalt Manager. You can use ReplaceGestalt to replace the function associated with a particular selector code.

Note
Most applications do not need to use either NewGestalt or ReplaceGestalt.
If the Gestalt Manager is not present, you can get a brief description of the operating environment by calling the 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 function NGetTrapAddress, specifying the trap number of Gestalt, and comparing the result with the address of the code that is executed when you invoke an unimplemented instruction. If Gestalt is available, you can safely assume that NewGestalt and ReplaceGestalt 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 variable gHasGestalt.

Listing 1-1 Determining whether Gestalt is available

gHasGestalt := MySWRoutineAvailable(_Gestalt);
For a sample definition of the application-defined function MySWRoutineAvailable, 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 the Gestalt 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 the NewGestalt 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 the response parameter and returns a result code of noErr. If Gestalt cannot obtain the information, it returns a result code indicating the cause of the error; in that case, the value of the response parameter is undefined. You should always check the result code returned by Gestalt to make sure that the response 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 by Gestalt 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 from Gestalt 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 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 use Gestalt 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 that Gestalt returns in the response parameter depends on the selector code with which it was called. For example, if you call Gestalt using the gestaltTimeMgrVersion selector, it returns a version code in the response 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 the response parameter. For example, if the suffix in a Gestalt selector is Size, then Gestalt returns a size in the response parameter. Table 1-1 lists the meaningful suffixes.
Table 1-1 Gestalt selector suffixes and their meanings
SuffixReturned value
AttrA range of 32 bits, the meanings of which are defined by a list of constants. Bit 0 is the least significant bit of the long word.
CountA number indicating how many of the indicated type of item exist.
SizeA size, usually in bytes.
TableThe base address of a table.
TypeAn index to a list of feature descriptions.
VersionA version number, which can be either a constant with a defined meaning or an actual version number, usually stored as four hexadecimal digits in the low-order word of the return value. Implied decimal points may separate digits. The value $0701, for example, returned in response to the gestaltSystemVersion selector, represents system software version 7.0.1.

Selectors that have the suffix Attr deserve special attention. They cause Gestalt to return a bit field that your application must interpret to determine whether a desired feature is present. For example, the application-defined sample function MyGetSoundAttr, defined in Listing 1-2 on page 1-6, returns a LongInt that contains the Sound Manager attributes field retrieved from Gestalt. To determine whether a particular feature is available, you need to look at the designated bit. The application-defined sample function MyIsStereoMixing 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;
The MyIsStereoMixing function uses the MPW Pascal function BTst and the application-defined MyGetSoundAttr function to determine whether the stereo-mixing bit is set in the response value returned by Gestalt when it's called with the gestaltSoundAttr selector. The constant gestaltStereoMixing is defined in the header files.

Adding a New Selector Code

You can add your own selector code to those already understood by Gestalt by calling the NewGestalt 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 call Gestalt 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 a Gestalt selector code of 'PIPE'.

Note
Apple reserves for its own use all four-character sequences consisting solely of lowercase letters and nonalphabetic ASCII characters.
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 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;
The Gestalt function passes its input parameters on to your selector function. Your function places the requested information in the LongInt pointed to by the response parameter and returns an error code, which Gestalt 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 the response 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 of noErr. The application-defined sample function, MyGestaltPipe, is isolated in a UNIT 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 Pipeline
To add a Gestalt selector code, you first move the selector function into the system heap and then call the NewGestalt function, which adds the selector code and its function to the Gestalt repertoire.

WARNING
Take special care when accessing memory in the system heap; it persists even after your application terminates.
Listing 1-5 illustrates the installation of a new 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 procedure MyInstallGestFunc 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.

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 about FlushInstructionCache.
Finally, MyInstallGestFunc calls NewGestalt 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 the response 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 code gestaltDupSelectorErr.

Modifying a Selector Function

You can use the ReplaceGestalt function to modify the function that Gestalt 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 of ReplaceGestalt before calling Gestalt with that selector or attempting to use the response parameter.

Note
If you modify the function associated with an existing Gestalt selector, do not use any bits in the response parameter that are not documented in this chapter. Apple reserves all undocumented bits in the response parameters returned by Apple-defined Gestalt selectors.
Because 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 the SysEnvirons function, which predates the Gestalt Manager, to get a brief description of the operating environment. The SysEnvirons function is available on all models of the Macintosh computer since the Macintosh SE and Macintosh II.

Note
The SysEnvirons function is not part of the Gestalt Manager, but is documented in this chapter for the sake of completeness.
The 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 through Gestalt: the working directory reference number of the folder or volume that holds the System file (although that information is available through the FindFolder function). See "The System Environment Record" beginning on page 1-28 for a complete description of the system environment record.


Previous Book Contents Book Index Next

© Apple Computer, Inc.
6 JUL 1996