640 lines
16 KiB
C
640 lines
16 KiB
C
/* Copyright 1992 - 1999 by Abacus Research and
|
|
* Development, Inc. All rights reserved.
|
|
*/
|
|
|
|
#if !defined (OMIT_RCSID_STRINGS)
|
|
char ROMlib_rcsid_gestalt[] =
|
|
"$Id: gestalt.c 139 2006-07-11 23:35:04Z ctm $";
|
|
#endif
|
|
|
|
/* Forward declarations in Gestalt.h (DO NOT DELETE THIS LINE) */
|
|
|
|
#include "rsys/common.h"
|
|
#include "MemoryMgr.h"
|
|
#include "Gestalt.h"
|
|
|
|
#include "rsys/prefs.h"
|
|
#include "rsys/soundopts.h"
|
|
#include "rsys/mman.h"
|
|
#include "rsys/gestalt.h"
|
|
#include "rsys/version.h"
|
|
#include "rsys/vdriver.h"
|
|
|
|
#if defined (CYGWIN32)
|
|
#include "win_dongle.h"
|
|
#include "win_print.h"
|
|
#endif
|
|
|
|
typedef struct
|
|
{
|
|
OSType selector;
|
|
LONGINT value;
|
|
} gestaltentry_t;
|
|
|
|
#define UNKNOWN 0xFFFF
|
|
|
|
PRIVATE gestaltentry_t gtable[] = {
|
|
{ gestaltAddressingModeAttr, gestalt32BitAddressing |
|
|
gestalt32BitSysZone |
|
|
gestalt32BitCapable, },
|
|
|
|
/*
|
|
* note: PageMaker 4.2 does a Gestalt call for the AliasMgr and then
|
|
* proceeds to use the Alias Manager, even if we say it's not
|
|
* present. However, it will avoid use of the Alias Manager
|
|
* if the Gestalt call itself returns an error. This doesn't
|
|
* appear to be within spec (IMVI), but it looks like we should
|
|
* just not know the descriptors that we don't support. Boo.
|
|
*
|
|
* MacInTax '93 does the same thing with the Edition Manager that
|
|
* PageMaker does with the Alias Manager. It's unclear how widespread
|
|
* this problem is.
|
|
*
|
|
* Claris Works does the same thing with Apple Events... bad!
|
|
*/
|
|
|
|
/* gestaltAliasMgrAttr, 0, */
|
|
/* gestaltApplEventsAttr, 0, */
|
|
/* gestaltAppleTalkVersion, 0, */
|
|
/* gestaltAUXVersion, UNKNOWN,*//* Should return gestaltUnknownErr */
|
|
/* gestaltConnMgrAttr, 0, */
|
|
/* gestaltCRMAttr, 0, */
|
|
/* gestaltCTBVersion, UNKNOWN,*//* should return gestaltUnknownErr */
|
|
/* gestaltDBAccessMgrAttr, 0, */
|
|
{ gestaltDITLExtAttr, gestaltDITLExtPresent, },
|
|
/* gestaltEasyAccessAttr, gestaltEasyAccessOff, */
|
|
|
|
|
|
/* gestaltEditionMgrAttr, 0, */
|
|
|
|
{ gestaltFindFolderAttr, 1 },
|
|
|
|
/* gestaltFontMgrAttr, 0, */
|
|
{ gestaltFSAttr, gestaltStandardFile58|gestaltHasFSSpecCalls, },
|
|
/* gestaltFXfrMgrAttr, 0, */
|
|
/* gestaltHardwareAttr, 0, */
|
|
/* gestaltHelpMgrAttr, 0, */
|
|
/* gestaltMiscAttr, 0, */
|
|
/* gestaltNotificatinMgrAttr, 0, */
|
|
/* gestaltNuBusConnectors, 0, */
|
|
/* gestaltOSAttr, 0, */
|
|
/* gestaltPopupAttr, 0, */
|
|
/* gestaltPowerMgrAttr, 0, */
|
|
/* gestaltPPCToolboxAttr, 0, */
|
|
/* gestaltResourceMgrAttr, 0, */
|
|
/* gestaltScriptCount, 0, */
|
|
/* gestaltScriptMgrVersion, UNKNOWN,*//* should return gestaltUnknownErr */
|
|
/* gestaltSerialAttr, 0, */
|
|
{ gestaltSoundAttr, 0x0C00, },
|
|
/* gestaltStdNBPAttr, 0, */
|
|
/* gestaltTermMgrAttr, 0, */
|
|
/* gestaltParityAttr, 0, */
|
|
|
|
/*
|
|
* TODO: instead of casting these to LONGINT, shouldn't we be using something
|
|
* like US_TO_SYN68K here, or if not, soemthing that takes ROMlib_offset
|
|
* into account?
|
|
*/
|
|
|
|
#if defined(BINCOMPAT) && SIZEOF_CHAR_P == 4
|
|
{ gestaltExtToolboxTable, (LONGINT) (tooltraptable + 0x200), },
|
|
{ gestaltToolboxTable, (LONGINT) tooltraptable, },
|
|
{ gestaltOSTable, (LONGINT) ostraptable, },
|
|
#else
|
|
{ gestaltExtToolboxTable, UNKNOWN, },
|
|
{ gestaltOSTable, UNKNOWN, },
|
|
{ gestaltToolboxTable, UNKNOWN, },
|
|
#warning gestalt{ExtToolboxTable,ToolboxTable,OSTable} not initialized
|
|
#endif
|
|
|
|
#if defined(SYN68K)
|
|
{ gestaltFPUType, 0, }, /* gestaltNoFPU */
|
|
#else
|
|
{ gestaltFPUType, gestalt68881+2, /* 'tis a lie; we're an 040 */ },
|
|
#endif
|
|
{ gestaltKeyboardType, gestaltMacKbd, },
|
|
{ gestaltLogicalPageSize, 8 * 1024, },
|
|
{ gestaltLogicalRAMSize, (LONGINT) 3 * 1024 * 1024, },
|
|
{ gestaltLowMemorySize, 0x1000, },
|
|
#if !defined (SYN68K)
|
|
{ gestaltMMUType, gestalt68040MMu, /* ack */ },
|
|
#else
|
|
{ gestaltMMUType, gestaltNoMMU, },
|
|
#endif
|
|
{ gestaltPhysicalRAMSize, (LONGINT) 3 * 1024 * 1024, },
|
|
#if defined(SYN68K)
|
|
{ gestaltProcessorType, gestalt68040, },
|
|
#else
|
|
{ gestaltProcessorType, gestalt68040, /* TODO: need to fill in
|
|
different info on 030*/ },
|
|
#endif
|
|
|
|
#if defined (powerpc) || defined(__ppc__)
|
|
{ gestaltNativeCPUtype, gestaltCPU750, },
|
|
{ gestaltMachineType, gestaltMacQuadra610, }, /* change this */
|
|
|
|
{ gestaltSysArchitecture, gestaltPowerPC, },
|
|
#warning questionable gestalt values for StuffitExpander
|
|
{ gestaltOSAttr, 0x3FF },
|
|
{ T('t','h','d','s'), 0 },
|
|
#else
|
|
{ gestaltNativeCPUtype, gestaltCPU68040, },
|
|
{ gestaltMachineType, gestaltMacQuadra610, },
|
|
#endif
|
|
|
|
#if defined (ORIGINAL_QD)
|
|
{ gestaltQuickdrawVersion, gestaltOriginalQD, },
|
|
#else
|
|
/*
|
|
* Star Trek demo needs 32-bit QD 1.1 at least.
|
|
*/
|
|
{ gestaltQuickdrawVersion, gestalt32BitQD13 },
|
|
#endif
|
|
{ gestaltQuickdrawFeatures, ( (1 << gestaltHasColor)
|
|
| (1 << gestaltHasDeepGWorlds)
|
|
| (1 << gestaltHasDirectPixMaps)) },
|
|
|
|
{ gestaltTimeMgrVersion, gestaltStandardTimeMgr, },
|
|
{ gestaltVersion, 1, },
|
|
|
|
/* We don't want ClarisWorks 3 calling funky IMVI memory manager
|
|
* routines so we don't recognize gestaltVMAddr at all. NOTE:
|
|
* ClarisWorks 3 will also not call those "funky routines" if we
|
|
* recognize the gestaltVMAttr selector, but say we don't support
|
|
* it. Furthermore, saying we don't support it breaks MacBench
|
|
* (which is kludgily worked around elsewhere). The ONLY REASON we
|
|
* say we don't even recognize this selector (and do the MacBench
|
|
* hack elsewhere) is paranoia: "our original ClarisWorks workaround
|
|
* was to not recognize this selector, and we've done much testing
|
|
* since then. Perhaps some other program out there would die if we
|
|
* recognized the VM selector."
|
|
*
|
|
* Once Executor 2 is out and we are next free to potentially break
|
|
* programs, we should take out this #if 0 and recognize the VMAttr
|
|
* selector, but claim we don't have any VM.
|
|
*/
|
|
#if 0
|
|
{ gestaltVMAttr, 0 },
|
|
#endif
|
|
{ gestaltMachineIcon, UNKNOWN, },
|
|
{ gestaltROMSize, (LONGINT) 128 * 1024, },
|
|
{ gestaltROMVersion, 0x7c, },
|
|
{ gestaltSystemVersion, 0x607, },
|
|
{ gestaltTextEditVersion, gestaltTE1, },
|
|
|
|
#if 0
|
|
#warning DO NOT CHECK THIS IN
|
|
{ T ('d', 'r', 'a', 'g'), 0, },
|
|
#endif
|
|
|
|
/* The following four will be ignored unless they are specifically enabled
|
|
by the corresponding ROMlib_pretend_xxx flags */
|
|
|
|
{ gestaltHelpMgrAttr, 1 }, /* must be 1 */
|
|
{ gestaltScriptMgrVersion, 0x001 }, /* have gotten away with 0x001 */
|
|
{ gestaltEditionMgrAttr, 1 }, /* must be 1 */
|
|
{ gestaltAliasMgrAttr, 1 }, /* must be 1 */
|
|
|
|
{ gestaltPHYSICAL, 0 }, /* will be filled in w/ callback address */
|
|
|
|
#define SYSTEM_7_EXTRAS 2
|
|
|
|
{ gestaltStandardFileAttr, gestaltStandardFile58, },
|
|
{ gestaltApplEventsAttr, 1 }, /* got away with 0, but that may
|
|
give us trouble elsewhere */
|
|
|
|
|
|
#if defined (THESE_REALLY_ARENT_NEEDED)
|
|
{ T ('i', 'c', 'm', 'p'), 17 }, /* QuickTime ... don't want this! */
|
|
{ T ('s', 'y', 's', 'a'), 0x4F30 },
|
|
{ gestaltOSAttr, 0x3FF },
|
|
{ gestaltPopupAttr, 1 }, /* perhaps we should admit to this */
|
|
{ gestaltFontMgrAttr, 7 },
|
|
#endif
|
|
|
|
};
|
|
|
|
PRIVATE OSType gtable_selectors_to_patch[] =
|
|
{
|
|
gestaltExtToolboxTable,
|
|
gestaltToolboxTable,
|
|
gestaltOSTable,
|
|
};
|
|
|
|
|
|
/*
|
|
gestaltSystemVersion 'sysv' Executor version numeric encoding
|
|
gestaltPhysicalRAMSize 'ram '
|
|
*/
|
|
|
|
#define TO_BE_FILLED_IN (0)
|
|
|
|
PRIVATE gestaltentry_t phystable[] =
|
|
{
|
|
{ gestaltSystemVersion, EXECUTOR_VERSION_NUMERIC },
|
|
#if SIZEOF_CHAR_P == 4
|
|
{ gestaltExecutorVersionString, (long) EXECUTOR_VERSION },
|
|
#else
|
|
#warning gestaltExecutorVersionString not currently available
|
|
#endif
|
|
#if defined (LINUX) || defined (CYGWIN32)
|
|
{ gestaltPhysicalRAMSize, TO_BE_FILLED_IN },
|
|
#endif
|
|
{ gestaltScreenSize, TO_BE_FILLED_IN },
|
|
#if defined (CYGWIN32)
|
|
{ gestaltGhostScriptVersion, TO_BE_FILLED_IN },
|
|
#endif
|
|
};
|
|
|
|
PRIVATE OSType phystable_selectors_to_patch[] =
|
|
{
|
|
gestaltExecutorVersionString,
|
|
};
|
|
|
|
typedef struct gestalt_link_str
|
|
{
|
|
OSType selector;
|
|
ProcPtr selectorFunction;
|
|
struct gestalt_link_str *next;
|
|
}
|
|
gestalt_link_t;
|
|
|
|
PRIVATE gestalt_link_t *gestalt_head;
|
|
|
|
PRIVATE gestalt_link_t *
|
|
find_selector_on_list(OSType selector)
|
|
{
|
|
gestalt_link_t *gp;
|
|
|
|
for (gp = gestalt_head; gp && gp->selector != selector; gp = gp->next)
|
|
;
|
|
return gp;
|
|
}
|
|
|
|
PRIVATE gestaltentry_t *
|
|
find_selector_in_table(OSType selector, gestaltentry_t table[],
|
|
int table_length)
|
|
{
|
|
INTEGER i;
|
|
gestaltentry_t *retval;
|
|
|
|
if (system_version < 0x700 && table == gtable)
|
|
table_length -= SYSTEM_7_EXTRAS;
|
|
|
|
switch (selector)
|
|
{
|
|
case gestaltHelpMgrAttr:
|
|
if (!ROMlib_pretend_help)
|
|
selector = -1;
|
|
break;
|
|
case gestaltScriptMgrVersion:
|
|
if (!ROMlib_pretend_script)
|
|
selector = -1;
|
|
break;
|
|
case gestaltEditionMgrAttr:
|
|
if (!ROMlib_pretend_edition)
|
|
selector = -1;
|
|
break;
|
|
case gestaltAliasMgrAttr:
|
|
if (!ROMlib_pretend_alias)
|
|
selector = -1;
|
|
break;
|
|
}
|
|
|
|
for (i = 0; i < table_length && table[i].selector != selector; ++i)
|
|
;
|
|
if (i < table_length)
|
|
retval = &table[i];
|
|
else
|
|
retval = 0;
|
|
|
|
return retval;
|
|
}
|
|
|
|
PRIVATE void
|
|
replace_selector_in_table (OSType selector, LONGINT new_value,
|
|
gestaltentry_t table[], int table_length)
|
|
{
|
|
gestaltentry_t *gp;
|
|
|
|
gp = find_selector_in_table (selector, table, table_length);
|
|
if (gp)
|
|
gp->value = new_value;
|
|
}
|
|
|
|
#define REPLACE_SELECTOR_IN_TABLE(selector, new_value, table) \
|
|
replace_selector_in_table (selector, new_value, table, NELEM (table))
|
|
|
|
PUBLIC void
|
|
replace_physgestalt_selector (OSType selector, uint32 new_value)
|
|
{
|
|
REPLACE_SELECTOR_IN_TABLE (selector, new_value, phystable);
|
|
}
|
|
|
|
PUBLIC void
|
|
gestalt_set_memory_size (uint32 size)
|
|
{
|
|
REPLACE_SELECTOR_IN_TABLE (gestaltLogicalRAMSize , size, gtable);
|
|
REPLACE_SELECTOR_IN_TABLE (gestaltPhysicalRAMSize, size, gtable);
|
|
}
|
|
|
|
PUBLIC void
|
|
gestalt_set_system_version (uint32 version)
|
|
{
|
|
REPLACE_SELECTOR_IN_TABLE (gestaltSystemVersion, version, gtable);
|
|
}
|
|
|
|
PUBLIC void
|
|
gestalt_set_physical_gestalt_callback (void)
|
|
{
|
|
REPLACE_SELECTOR_IN_TABLE (gestaltPHYSICAL,
|
|
(long) US_TO_SYN68K (P_PhysicalGestalt), gtable);
|
|
}
|
|
|
|
#if defined (powerpc) || defined (__ppc__)
|
|
PUBLIC void
|
|
gestalt_set_cpu_type (uint32 type)
|
|
{
|
|
REPLACE_SELECTOR_IN_TABLE (gestaltPHYSICAL, type, gtable);
|
|
}
|
|
#endif
|
|
|
|
PRIVATE OSErrRET
|
|
gestalt_helper(OSType selector, LONGINT *responsep, BOOLEAN searchlist,
|
|
gestaltentry_t table[], int length)
|
|
{
|
|
OSErr retval;
|
|
gestalt_link_t *gp;
|
|
|
|
retval = gestaltUndefSelectorErr;
|
|
|
|
if (selector == gestaltSoundAttr && ROMlib_PretendSound == soundoff)
|
|
selector = 0;
|
|
|
|
*responsep = CLC (0); /* better safe than sorry */
|
|
|
|
if (searchlist && (gp = find_selector_on_list(selector)))
|
|
retval = CToPascalCall(gp->selectorFunction, CTOP_GestaltTablesOnly,
|
|
selector, responsep);
|
|
else
|
|
{
|
|
gestaltentry_t *gep;
|
|
|
|
gep = find_selector_in_table(selector, table, length);
|
|
if (gep)
|
|
{
|
|
if (gep->value == UNKNOWN)
|
|
retval = gestaltUnknownErr;
|
|
else
|
|
{
|
|
retval = noErr;
|
|
*responsep = CL (gep->value);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Log the gestalt call if appropriate. */
|
|
warning_trace_info ("sel `%c%c%c%c'; rsp `%d'; retval `%d'",
|
|
(selector >> 24) & 0xFF,
|
|
(selector >> 16) & 0xFF,
|
|
(selector >> 8) & 0xFF,
|
|
(selector) & 0xFF,
|
|
CL (*responsep),
|
|
retval);
|
|
|
|
return retval;
|
|
}
|
|
|
|
PRIVATE void
|
|
offset_address (gestaltentry_t *gp, int ngp, OSType sel)
|
|
{
|
|
for (;ngp > 0 && gp->selector != sel; --ngp, ++gp)
|
|
;
|
|
if (ngp > 0)
|
|
gp->value = US_TO_SYN68K (gp->value);
|
|
}
|
|
|
|
PRIVATE void
|
|
offset_addresses (gestaltentry_t *gp, int ngp, OSType *selp, int nsels)
|
|
{
|
|
while (nsels-- > 0)
|
|
offset_address (gp, ngp, *selp++);
|
|
}
|
|
|
|
#define OFFSET_ADDRESSES(table) \
|
|
offset_addresses (table, NELEM (table), \
|
|
table ## _selectors_to_patch, \
|
|
NELEM (table ## _selectors_to_patch))
|
|
|
|
/*
|
|
* This is for gestalt entries that are hard-wired via configuration
|
|
* files. They can't be altered by ReplaceGestalt.
|
|
*/
|
|
|
|
|
|
typedef struct
|
|
{
|
|
OSType selector;
|
|
OSErr retval;
|
|
uint32 value;
|
|
}
|
|
gestalt_list_entry_t;
|
|
|
|
PRIVATE gestalt_list_entry_t *gestalt_listp = NULL;
|
|
PRIVATE size_t listp_size = 0;
|
|
|
|
PUBLIC void
|
|
ROMlib_clear_gestalt_list (void)
|
|
{
|
|
free (gestalt_listp);
|
|
gestalt_listp = NULL;
|
|
listp_size = 0;
|
|
}
|
|
|
|
PUBLIC void
|
|
ROMlib_add_to_gestalt_list (OSType selector, OSErr retval, uint32 new_value)
|
|
{
|
|
typeof (gestalt_listp) new_listp;
|
|
|
|
new_listp = realloc (gestalt_listp, listp_size + sizeof *gestalt_listp);
|
|
if (!new_listp)
|
|
warning_unexpected ("out of memory");
|
|
else
|
|
{
|
|
typeof (gestalt_listp) entryp;
|
|
|
|
gestalt_listp = new_listp;
|
|
entryp = (typeof (entryp)) ((char *) gestalt_listp + listp_size);
|
|
entryp->selector = selector;
|
|
entryp->retval = retval;
|
|
entryp->value = CL (new_value);
|
|
listp_size += sizeof *gestalt_listp;
|
|
}
|
|
}
|
|
|
|
A2(PUBLIC trap, OSErrRET, Gestalt, OSType, selector, LONGINT *, responsep)
|
|
{
|
|
static boolean_t been_here = FALSE;
|
|
|
|
warning_trace_info ("IN: sel `%c%c%c%c'",
|
|
(selector >> 24) & 0xFF,
|
|
(selector >> 16) & 0xFF,
|
|
(selector >> 8) & 0xFF,
|
|
(selector) & 0xFF);
|
|
#if defined (CYGWIN32)
|
|
if ((uint32) selector == 0xb7d20e84)
|
|
{
|
|
OSErrRET retval;
|
|
|
|
warning_trace_info("about to dongle_query");
|
|
retval = dongle_query (responsep);
|
|
warning_trace_info("dongle_queried");
|
|
return retval;
|
|
}
|
|
#endif
|
|
|
|
{
|
|
gestalt_list_entry_t *p, *ep;
|
|
|
|
for (p = gestalt_listp, ep = (typeof (ep))((char *) p + listp_size);
|
|
p != ep && p->selector != selector;
|
|
++p)
|
|
;
|
|
if (p != ep)
|
|
{
|
|
*responsep = p->value;
|
|
return p->retval;
|
|
}
|
|
}
|
|
|
|
if (!been_here)
|
|
{
|
|
gestalt_set_physical_gestalt_callback ();
|
|
OFFSET_ADDRESSES (gtable);
|
|
OFFSET_ADDRESSES (phystable);
|
|
been_here = TRUE;
|
|
}
|
|
return gestalt_helper(selector, responsep, TRUE, gtable, NELEM (gtable));
|
|
}
|
|
|
|
P2(PUBLIC pascal trap, OSErrRET, PhysicalGestalt, OSType, selector,
|
|
LONGINT *, responsep)
|
|
{
|
|
OSErrRET retval;
|
|
|
|
switch (selector)
|
|
{
|
|
case gestaltScreenSize:
|
|
replace_physgestalt_selector (gestaltScreenSize,
|
|
((vdriver_height << 16)|
|
|
(uint16)vdriver_width));
|
|
break;
|
|
#if defined (CYGWIN32)
|
|
case gestaltGhostScriptVersion:
|
|
set_gs_gestalt_info ();
|
|
break;
|
|
#endif
|
|
default:
|
|
break;
|
|
}
|
|
|
|
retval = gestalt_helper(selector, responsep, FALSE, phystable,
|
|
NELEM (phystable));
|
|
if (retval == gestaltUndefSelectorErr)
|
|
retval = physicalUndefSelectorErr;
|
|
return retval;
|
|
}
|
|
|
|
|
|
P2(PUBLIC pascal trap, OSErrRET, GestaltTablesOnly, OSType, selector,
|
|
LONGINT *, responsep)
|
|
{
|
|
return gestalt_helper(selector, responsep, FALSE, gtable, NELEM (gtable));
|
|
}
|
|
|
|
PRIVATE BOOLEAN
|
|
syszone_p(ProcPtr p)
|
|
{
|
|
THz syszone;
|
|
|
|
syszone = MR(SysZone);
|
|
return ((unsigned long) p >= (unsigned long) &syszone->heapData
|
|
&& (unsigned long) p < (unsigned long) MR(syszone->bkLim));
|
|
}
|
|
|
|
PRIVATE OSErr
|
|
new_link(OSType selector, ProcPtr selFunc)
|
|
{
|
|
OSErr retval;
|
|
|
|
if (!syszone_p(selFunc))
|
|
retval = gestaltLocationErr;
|
|
else
|
|
{
|
|
ZONE_SAVE_EXCURSION
|
|
(SysZone,
|
|
{
|
|
gestalt_link_t *gp;
|
|
|
|
gp = (gestalt_link_t *) NewPtr(sizeof(*gp));
|
|
if (!gp)
|
|
retval = memFullErr;
|
|
else
|
|
{
|
|
retval = noErr;
|
|
gp->selector = selector;
|
|
gp->selectorFunction = selFunc;
|
|
gp->next = gestalt_head;
|
|
gestalt_head = gp;
|
|
}
|
|
});
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
A2(PUBLIC trap, OSErrRET, NewGestalt, OSType, selector, ProcPtr, selFunc)
|
|
{
|
|
OSErr retval;
|
|
|
|
if (find_selector_on_list(selector)
|
|
|| find_selector_in_table(selector, gtable, NELEM (gtable)))
|
|
retval = gestaltDupSelectorErr;
|
|
else
|
|
retval = new_link(selector, selFunc);
|
|
return retval;
|
|
}
|
|
|
|
A3(PUBLIC trap, OSErrRET, ReplaceGestalt, OSType, selector, ProcPtr, selFunc,
|
|
ProcPtr *, oldSelFuncp)
|
|
{
|
|
OSErr retval;
|
|
gestalt_link_t *gp;
|
|
|
|
gp = find_selector_on_list(selector);
|
|
if (gp)
|
|
{
|
|
if (syszone_p(selFunc))
|
|
{
|
|
*oldSelFuncp = gp->selectorFunction;
|
|
gp->selectorFunction = selFunc;
|
|
retval = noErr;
|
|
}
|
|
else
|
|
retval = gestaltLocationErr;
|
|
}
|
|
else
|
|
{
|
|
gestaltentry_t *gep;
|
|
|
|
gep = find_selector_in_table(selector, gtable, NELEM (gtable));
|
|
if (!gep)
|
|
retval = gestaltUndefSelectorErr;
|
|
else
|
|
{
|
|
*oldSelFuncp = P_GestaltTablesOnly;
|
|
retval = new_link(selector, selFunc);
|
|
}
|
|
}
|
|
return retval;
|
|
}
|