Newsgroups: comp.sys.mac.programmer
Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!zaphod.mps.ohio-state.edu!caen!umich!terminator!usenet
From: potts@itl.itd.umich.edu (Paul Potts)
Subject: Gestalt - new and improved methods
Message-ID: <1991Jun14.160733.14793@terminator.cc.umich.edu>
Sender: usenet@terminator.cc.umich.edu (usenet news)
Organization: Instructional Technology Laboratory, University of Michigan
Date: Fri, 14 Jun 91 16:07:33 GMT

I've been putting together some code to use Gestalt in its new and
improved form.  Since it has taken me a while to get it going, I thought
I would post it to save someone else time.

This uses the new method for checking trap availability described in IM-6,
chapter 3.  I've translated some of that code directly into THINK C.

If anyone finds an error, please post a correction. It seems to work fine.

----------- compatibility.h ------------
---- this is a header file that lists some useful function prototypes
and defines for the compatibility.c file ----------------------------

#define GESTALT_NOT_PRESENT -1
/* prototypes */
int NumToolboxTraps (void);
TrapType GetTrapType (int theTrap);
Boolean TrapAvailable (int theTrap);
Boolean WNEAvailable (void);
Boolean GestaltAvailable (void);
Boolean testAttribute (OSType selector, short attribute, short * error);
short GestaltFeature(OSType selector, long * feature);
Boolean GestaltPresent(void);

--------- compatibility.c --------------
---- here are some useful functions to work with Gestalt. ------

#include <GestaltEqu.h>
#include "Compatibility.h"	/* contains prototypes */

int NumToolboxTraps(void)
{ return ((NGetTrapAddress(_InitGraf, ToolTrap) == 
		NGetTrapAddress(0xAA6E, ToolTrap)) ? 0x200 : 0x400); }

TrapType GetTrapType (theTrap) int theTrap;
{ return ((theTrap & 0x0800) ? ToolTrap : OSTrap); }

Boolean TrapAvailable (theTrap) int theTrap;
{ TrapType tType;
	tType = GetTrapType (theTrap);
	if (tType == ToolTrap)
	{ theTrap = (theTrap & 0x07FF);
		if (theTrap >= NumToolboxTraps())
			theTrap = _Unimplemented;
	}
	return ((NGetTrapAddress(theTrap, tType) 
			!= NGetTrapAddress(_Unimplemented, ToolTrap)));
}

Boolean WNEAvailable(void)
{ return (TrapAvailable (0xA860)); }

Boolean GestaltAvailable (void)
{ return (TrapAvailable (0xA1Ad /*Gestalt*/ )); }

Boolean GestaltPresent()
{
	return GestaltAvailable();
}

short GestaltFeature(OSType selector, long * feature)
{
	return Gestalt(selector, feature);
}

Boolean testAttribute (OSType selector, short attribute, short * error)
{
	long feature;
	if (GestaltPresent())
	{	
		*error = GestaltFeature (gestaltHardwareAttr, &feature);
		return (BitTst((void*)&feature, 31 - attribute));
	}
		else
	{
		* error = -1;
	}	/* my code for Gestalt Not Present */
}

----------------------------------------------------------
------ Now here is some code that shows how you might ----
------ call these routines -------------------------------

void HandleGestaltError(short error)
{
	switch (error)
	{
		case GESTALT_NOT_PRESENT:
			error_message (NO_GESTALT);
                        /* do whatever error handling you do */
                        break;
						
		case gestaltUnknownErr:
		case gestaltUndefSelectorErr:
		/* could handle these cases separately,
                   but I just return a general message */
		default:
                        error_message (GESTALT_ERROR);
                        break;
                /* NOTE THE FALL-THROUGH which occurs when I
                   have a case without an explicit break */ 
       } /* end of switch */
} /* end of procedure */

----------- this example function tests for compatibility by
----------- looking to see if an apple sound chip is present,
----------- and returns false if it isn't.

Boolean compatible()
{
	Boolean result;
	short error;

	result = testAttribute (gestaltHardwareAttr, gestaltHasASC, &error);
	if (error !=0) /* if Gestalt returned an OS Error or -1 */
	{
		HandleGestaltError(error);
		return (FALSE);	
	}
		else /* assume result is correct */
	{
		if (!result) /* sound chip bit was zero */
		{
			error_message (NO_SOUND_CHIP); 
			return (FALSE);	
		}
			else /* sound chip bit was one */
		{
			return (result); /* return TRUE */
		}
	}	/* end of no OS Error returned case */
} /* end of procedure */

--------------- Have fun!  let me know if anyone finds errors. -------

Paul Potts
potts@itl.itd.umich.edu
Paul_Potts@um.cc.umich.edu
 
