From: radcliff@apple.com (Dave Radcliffe)
Newsgroups: comp.sys.mac.programmer
Subject: Re: Gestalt Selectors in APPL
Date: 31 Dec 92 22:30:51 GMT
Organization: Apple Computer

In article <BzqC31.FAM@world.std.com>, zobkiw@world.std.com (Joe Zobkiw) writes:
> 
> I need an application to install a gestalt selector. 
> I know I need to load it into the System Heap but I 
> have a few questions and comments.
> 
> 1) Can I perform a "6-byte-xdef" type trick on this 
> code? I'm not sure I can since even if I mark the 
> 6-byte resource as sysHeap the code it points to is 
> still in my application heap.
> 
> 2) If I place my Gestalt selector function in a separate 
> CODE resource, can I mark that resource as sysHeap and 
> have it work properly? This would be WITHOUT any 6-byte 
> tricks.
> 
> 3) How can I remove the Gestalt selector once the app 
> quits? Will
> 
>     err = ReplaceGestalt(selector, nil, &oldGestaltFunction);
> 
> work or will this cause the System to jump to location 0 
> the next time someone calls my selector?
> 
> What's the easiest way? Thanks in advance! :)
> 
> Joe Zobkiw

There is glue code on the January Developer CD that, assuming all you want your 
Gestalt function to do is return a value, solves all your problems.  It is
called GestaltValue.  The ReadMe file is pasted below:

GestaltValue Read Me
) Copyright 1992 Apple Computer, Inc.
All rights reserved
------------------------------------
This document describes the GestaltValue functionality as implemented in 
GestaltValue.o.  Interfaces to GestaltValue are provided in 
GestaltValue.h and GestaltValue.p.

GestaltValue is a set of routines, implemented as glue, that extend and 
enhance existing Gestalt functionality.  For a complete description of 
Gestalt, refer to Chapter 3 of Inside Macintosh VI. 

Rationale

Existing Gestalt functionality allows developers to put Gestalt to use in 
their own applications by registering a Gestalt selector using the 
NewGestalt or ReplaceGestalt calls, and providing a function which can 
return the appropriate response.

While this is a powerful feature of Gestalt, in practice, it is difficult 
to take advantage of for a number of reasons:

1) The supplied function must entirely reside in the system heap.

2) The function should be reentrant and not move memory because Gestalt 
(and therefore the function) may be called at interrupt time.

3) The function must effectively remain resident until restart.  This is 
a problem for applications which may come and go multiple times.

4) Since the purpose of the function is to return a response value, the 
function must know how to locate, or otherwise manage that value.

All of this means a lot of work just to allow code to retrieve the response 
value via Gestalt.

GestaltValue addresses all these issues.  It is built to deal with the most 
common case, simply returning a 32-bit value.  It safely implements and 
installs a single common, shared gestalt function and reports back values
via the existing Gestalt mechanism.  This gestalt function gets installed 
the first time the glue gets invoked.  Subsequent calls to the glue 
(either from the same application, or a different one) cooperate with 
the gestalt function to maintain a table of selectors and values for the 
function to report.

GestaltValue will eventually be implemented as a standard system trap, in 
which case, the glue will simply call the trap.  Although currently provided
as a standalone object file, GestaltValue will eventually be rolled into 
development libraries; watch for it in a development system near you.

All three GestaltValue functions defined below can move memory, so they 
cannot be called at interrupt time.  But the shared gestalt function that 
GestaltValue installs in the system heap is reentrant and does not move 
memory (i.e., it satisfies criteria (2) above), so any values registered 
via this mechanism can be safely retrieved at interrupt time via the 
standard Gestalt mechanism.

Interface

Pascal:

FUNCTION NewGestaltValue(selector: OSType;newValue: LONGINT): OSErr;
FUNCTION ReplaceGestaltValue(selector: OSType;replacementValue: LONGINT): OSErr;
FUNCTION DeleteGestaltValue(selector: OSType): OSErr;

C:

pascal OSErr NewGestaltValue (OSType selector, long newValue);
pascal OSErr ReplaceGestaltValue (OSType selector, long replacementValue);
pascal OSErr DeleteGestaltValue (OSType selector);

NewGestaltValue and ReplaceGestaltValue are analogous to NewGestalt and 
ReplaceGestalt.  They take a standard 4 character OSType value and a new
or replacement value.  ReplaceGestaltValue has no parameter analogous 
to the oldGestaltFunction parameter of ReplaceGestalt.  If you desire 
saving the previous value, you should call Gestalt for that selector 
before calling ReplaceGestaltValue.

The usual restrictions on the selector parameter still apply.  Apple 
recommends you use your four-character creator sequence for your selector.  
All lowercase letter and nonalphabetic ASCII sequences are reserved for Apple.

DeleteGestaltValue makes a Gestalt value unknown to Gestalt.  Subsequent
calls to Gestalt for that selector will return gestaltUndefSelectorErr.

Return values

GestaltValue requires that the _Gestalt trap be implemented.  You will get 
unimpErr (-4) if _Gestalt is unavailable.

NewGestaltValue returns gestaltDupSelectorErr (-5552) if you attempt to add 
a new value for an existing selector.  You should use ReplaceGestaltValue 
instead.

ReplaceGestaltValue returns gestaltUndefSelectorErr (-5551) if you attempt 
to replace a non-existent selector.  You should use NewGestaltValue instead.

Both NewGestaltValue and ReplaceGestalt value may return memory errors if 
they cannot allocate sufficient room in the system heap for their code and 
data.

DeleteGestaltValue returns gestaltUndefSelectorErr if you attempt to delete 
a selector unknown to GestaltValue (such as a pre-defined gestalt selector 
such as 'fpu ').
----
I hope this helps.  Have fun,

Dave Radcliffe
Apple Computer
MacDTS
Newsgroups: comp.sys.mac.programmer