Milán Major

netscape-revival

1 branch
Code

lib/mac/VText/V_PowerPlant_Mods/LModelDirector.cp

// ===========================================================================
//	LModelDirector.cp		   ©1993-1996 Metrowerks Inc. All rights reserved.
// ===========================================================================
//
//	A wrapper class for AppleEvent handlers and the AE Object Support Library
//
//	You should only create one object of this class. This object handles
//	all callbacks from the AppleEvent Manager. It either handles the callback
//	itself, or calls a member function for the LModelObject that is the
//	target of an AppleEvent.
//
//	The callback functions are static functions that call a virtual member
//	function of LModelDirector. You can override these functions in a
//	subclass of LModelDirector to change how AppleEvent callbacks are
//	handled.

#ifdef PowerPlant_PCH
#include PowerPlant_PCH
#endif

#include <LModelDirector.h>
#include <LModelObject.h>
#include <LModelProperty.h>
#include <UAppleEventsMgr.h>
#include <UExtractFromAEDesc.h>
#include <UMemoryMgr.h>

//	#define	UAEGIZMOS
#ifdef	UAEGIZMOS
	#include	<UAEGizmos.h>
#endif

#ifndef __AEREGISTRY__
#include <AERegistry.h>
#endif

#ifndef __AEOBJECTS__
#include <AEObjects.h>
#endif

#ifndef __AEPACKOBJECT__
#include <AEPackObject.h>
#endif

// === Static Member Variables ===
LModelDirector*	LModelDirector::sModelDirector;


// ---------------------------------------------------------------------------
//		¥ LModelDirector
// ---------------------------------------------------------------------------
//	Default Constructor

LModelDirector::LModelDirector()
{
	sModelDirector = this;
	mResolveFlags = kAEIDoMinimum;
	UAppleEventsMgr::Initialize();
	::AEObjectInit();
	LModelObject::InitLazyList();
}


// ---------------------------------------------------------------------------
//		¥ LModelDirector(LModelObject*)
// ---------------------------------------------------------------------------
//	Constructor specifying a default Model

LModelDirector::LModelDirector(
	LModelObject	*inDefaultModel)
{
	sModelDirector = this;
	mResolveFlags = kAEIDoMinimum;
	LModelObject::SetDefaultModel(inDefaultModel);
	UAppleEventsMgr::Initialize();
	::AEObjectInit();
	InstallCallBacks();
	LModelObject::InitLazyList();
}


// ---------------------------------------------------------------------------
//		¥ ~LModelDirector
// ---------------------------------------------------------------------------
//	Destructor

LModelDirector::~LModelDirector()
{
	LModelObject::DestroyLazyList();
}


// ---------------------------------------------------------------------------
//		¥ InstallCallBacks
// ---------------------------------------------------------------------------
//	Install handler and callback functions used by the AppleEvent Manager
//		and the Object Support Library
//	Call this function only once (usually at the beginning of the program)

void
LModelDirector::InstallCallBacks()
{
	OSErr	err;
	
		// Generic handler for all AppleEvents
	
	UAppleEventsMgr::InstallAEHandlers(
			NewAEEventHandlerProc(LModelDirector::AppleEventHandler));
	
		// Specific handler for Open AppleEvent
	
	err = ::AEInstallEventHandler(kCoreEventClass, kAEOpen,
			NewAEEventHandlerProc(LModelDirector::OpenOrPrintEventHandler),
			ae_Open, false);
	ThrowIfOSErr_(err);
	
		// Specific handler for Print AppleEvent
	
	err = ::AEInstallEventHandler(kCoreEventClass, kAEPrint,
			NewAEEventHandlerProc(LModelDirector::OpenOrPrintEventHandler),
			ae_Print, false);
	ThrowIfOSErr_(err);
	
		// Specific handler for CreateElement AppleEvent
	
	err = ::AEInstallEventHandler(kAECoreSuite, kAECreateElement,
			NewAEEventHandlerProc(LModelDirector::CreateElementEventHandler),
			ae_CreateElement, false);
	ThrowIfOSErr_(err);
		
		// Generic accessor for Model Objects
		
	err = ::AEInstallObjectAccessor(typeWildCard, typeWildCard, 
				NewOSLAccessorProc(LModelDirector::ModelObjectAccessor),
				0, false);
	ThrowIfOSErr_(err);
	
		// Accessor for List of Model Objects
		
	err = ::AEInstallObjectAccessor(typeWildCard, typeAEList, 
				NewOSLAccessorProc(LModelDirector::ModelObjectListAccessor),
				0, false);
	ThrowIfOSErr_(err);
		
	err = ::AESetObjectCallbacks(
				NewOSLCompareProc(LModelDirector::OSLCompareObjects),
				NewOSLCountProc(LModelDirector::OSLCountObjects),
				NewOSLDisposeTokenProc(LModelDirector::OSLDisposeToken),
				nil,		// GetMarkToken
				nil,		// Mark
				nil,		// AdjustMarks
				nil);		// GetErrDesc
	ThrowIfOSErr_(err);
}


// ---------------------------------------------------------------------------
//		¥ HandleAppleEvent
// ---------------------------------------------------------------------------
//	Respond to an AppleEvent
//
//	This generic handler directs the AppleEvent to the ModelObject
//	specified by the keyDirectObject parameter. If the keyDirectObject
//	parmater does not exist or is not an object specifier, the default
//	model handles the AppleEvent.
//
//	You must install a separate handler for AppleEvents where the
//	keyDirectObject parameter has a different meaning.

void
LModelDirector::HandleAppleEvent(
	const AppleEvent	&inAppleEvent,
	AppleEvent			&outReply,
	Int32				inRefCon)
{
	StAEDescriptor	theResult;
	OSErr			err;
	
									// Get optional direct object parameter
	StAEDescriptor	directObj,
					theToken;
	directObj.GetOptionalParamDesc(inAppleEvent, keyDirectObject,
									typeWildCard);
	
	err = Resolve(directObj.mDesc, theToken.mDesc);
	
	if ((err == errAENotAnObjSpec) || (err == errAENoSuchObject)) {
	
			// Direct object is not an ospec, so let the default model
			// handle the AppleEvent

		(LModelObject::GetDefaultModel())->
			HandleAppleEventAll(inAppleEvent, outReply, theResult.mDesc, inRefCon);
		
	} else if (err == noErr) {
		ProcessTokenizedEvent(inAppleEvent, theToken.mDesc, theResult.mDesc,
								outReply, inRefCon);
	} else {
		Throw_(err);
	}
	
									// Put result code(s) in Reply
									// If outReply has a null descriptor,
									//   it means that the sender does not
									//   want a reply.
	if ( (theResult.mDesc.descriptorType != typeNull) &&
		 (outReply.descriptorType != typeNull) ) {
		err = ::AEPutParamDesc(&outReply, keyAEResult, &theResult.mDesc);
		ThrowIfOSErr_(err);
	}
}


// ---------------------------------------------------------------------------
//		¥ HandleOpenOrPrintEvent
// ---------------------------------------------------------------------------
//	Respond to an Open or Print AppleEvent
//
//	Open an Print AppleEvents require a special handler because the
//	keyDirectObject parameter can specify an object that does not yet
//	exist. This will happen, for example, when opening a file
//	which is not already open.

void
LModelDirector::HandleOpenOrPrintEvent(
	const AppleEvent	&inAppleEvent,
	AppleEvent			&outReply,
	Int32				inRefCon)
{
	OSErr			err;
	StAEDescriptor	theResult,
					directObjToken,
					directObj;
	
									// Get direct object parameter
	directObj.GetParamDesc(inAppleEvent, keyDirectObject, typeWildCard);
	
	if (directObj.mDesc.descriptorType != typeNull)
		err = Resolve(directObj.mDesc, directObjToken.mDesc);
	
	if ( (directObj.mDesc.descriptorType == typeNull) ||
		 (err == errAENotAnObjSpec) ||
		 (err == errAENoSuchObject) ) {
									// Direct object parameter not present
									//   or is not an object specifier.
									//   Let the default model handle it.
		(LModelObject::GetDefaultModel())->
			HandleAppleEventAll(inAppleEvent, outReply, theResult.mDesc, inRefCon);
		
	} else if (err == noErr) {	
									// Process this event using the Token
									//   representing the direct direct
		ProcessTokenizedEvent(inAppleEvent, directObjToken.mDesc, theResult.mDesc,
								outReply, inRefCon);
	} else {
		Throw_(err);
	}
									// Put result code in Reply
	if (theResult.mDesc.descriptorType != typeNull) {
		err = ::AEPutParamDesc(&outReply, keyAEResult, &theResult.mDesc);
		ThrowIfOSErr_(err);
	}
}


// ---------------------------------------------------------------------------
//		¥ HandleCreateElementEvent
// ---------------------------------------------------------------------------
//	Respond to a CreateElement AppleEvent
//
//	CreateElement requires a special handler because it does not have
//	a keyDirectObject parameter that specifies a target ModelObject which
//	should respond to the event. The target ModelObject for this event
//	is the SuperModel for the element to create.

void
LModelDirector::HandleCreateElementEvent(
	const AppleEvent	&inAppleEvent,
	AppleEvent			&outReply,
	Int32				/* inRefCon */)
{
	OSErr			err;
	StAEDescriptor	classD(inAppleEvent, keyAEObjectClass, typeType),
					insertD(inAppleEvent, keyAEInsertHere);
	DescType		elemClass;
	UExtractFromAEDesc::TheType(classD, elemClass);
	DescType		insertPosition = kAEReplace;	//	arbitrary
	LModelObject	*target = nil;
	LModelObject	*container = nil;
	LModelObject	*element = nil;
							
	switch (insertD.mDesc.descriptorType) {

		case typeInsertionLoc:
		{
			StAEDescriptor	positionD(insertD, keyAEPosition, typeEnumeration);
			UExtractFromAEDesc::TheEnum(positionD, insertPosition);
			StAEDescriptor	objectD(insertD, keyAEObject, typeObjectSpecifier),
							tokenD;
			err = Resolve(objectD, tokenD.mDesc);
			ThrowIfOSErr_(err);
			target = LModelObject::GetModelFromToken(tokenD);
			target = target->GetInsertionTarget(insertPosition);
			container = target->GetInsertionContainer(insertPosition);
			break;
		}

		case typeNull:
			// The "insert here" parameter is supposed be required. However,
			// it seems reasonable to let it be optional and use the
			// beginning of the Application as the default location.
			container = LModelObject::GetDefaultModel();	
			insertPosition = kAEBeginning;	//	arbitrary?
			break;
			
		default:
		case typeObjectSpecifier:
		{
			//	The AppleEvent was coded and resolved (using lazy objects)
			//	in such a way that the target IS the element to be created.
			//	Its container should recognize this so let its container
			//	finish the creation (setting the parameters).
			StAEDescriptor	tokenD;
			err = Resolve(insertD, tokenD.mDesc);
			ThrowIfOSErr_(err);
			target = LModelObject::GetModelFromToken(tokenD);
			target->GetInsertionTarget(typeNull);			
			container = target->GetInsertionContainer(typeNull);
			if (container == nil)
				container = LModelObject::GetDefaultModel();
			insertPosition = kAEReplace;	//	not so arbitrary
			break;
		}
	}

	ThrowIfNULL_(container);
	element = container->HandleCreateElementEventAll(
					elemClass, insertPosition, target, inAppleEvent, outReply);

	// The AppleEvents Registry specifies that an object specifier
	// for the new element be returned as the keyAEResult parameter
	// in the Reply to the AppleEvent
	if (element != nil) {
		StAEDescriptor	elementDesc;
		element->MakeSpecifier(elementDesc.mDesc);
		UAEDesc::AddKeyDesc(&outReply, keyAEResult, elementDesc.mDesc);
	}
}


void
LModelDirector::ProcessTokenizedEvent(
	const AppleEvent	&inAppleEvent,
	AEDesc				&inDirectObjToken,
	AEDesc				&outResult,
	AppleEvent			&outReply,
	Int32				inRefCon)
{
	LModelObject	*theResponder;

	if (inDirectObjToken.descriptorType != typeAEList) {
	
		theResponder = LModelObject::GetModelFromToken(inDirectObjToken);
		theResponder->HandleAppleEventAll(inAppleEvent, outReply, outResult, inRefCon);
		
	} else {

		// Direct object is a list of ModelObjects
		StAEDescriptor	insertD;
		
		insertD.GetOptionalParamDesc(inAppleEvent, keyAEInsertHere, typeWildCard);
		
		if (insertD.mDesc.descriptorType == typeNull) {
			OSErr		err = noErr;
			Int32		count,
						i;
	
			if (AECountItems(&inDirectObjToken, &count))
				count = 0;
			
			//	process model objects
			for (i = 1; i <= count; i++) {
				StAEDescriptor	token,
								resultDesc;
				DescType		bogusKeyword;
				err = AEGetNthDesc(&inDirectObjToken, i, typeWildCard, &bogusKeyword, &token.mDesc);
				ThrowIfOSErr_(err);
				theResponder = LModelObject::GetModelFromToken(token);
				theResponder->HandleAppleEventAll(inAppleEvent, outReply, resultDesc.mDesc, inRefCon);
				UAEDesc::AddDesc(&outResult, 0, resultDesc);
			}
		} else {

			//	We are going to have to process token by token AND adjust keyAEInsertHere
			//	as we go.
			OSErr	err = noErr;
			Int32	count,
					i;
								
			if (AECountItems(&inDirectObjToken, &count))
				count = 0;
			
			
			StAEDescriptor		event;
			
			err = AEDuplicateDesc(&inAppleEvent, &event.mDesc);
			ThrowIfOSErr_(err);
			
			//	process model objects
			for (i = 1; i <= count; i++) {
				StAEDescriptor	event,
								token,
								resultDesc;
				DescType		bogusKeyword;

				err = AEGetNthDesc(&inDirectObjToken, i, typeWildCard, &bogusKeyword, &token.mDesc);
				ThrowIfOSErr_(err);
				theResponder = LModelObject::GetModelFromToken(token);
				
				if (i != 1) {
					StAEDescriptor	hereD;
					UAEDesc::MakeInsertionLoc(insertD.mDesc, kAEAfter, &hereD.mDesc);
					err = AEPutKeyDesc(&event.mDesc, keyAEInsertHere, &hereD.mDesc);
					ThrowIfOSErr_(err);
				}

				theResponder->HandleAppleEventAll(event, outReply, resultDesc.mDesc, inRefCon);
				UAEDesc::AddDesc(&outResult, 0, resultDesc);
				
				err = AEDisposeDesc(&insertD.mDesc);
				err = AEDuplicateDesc(&resultDesc.mDesc, &insertD.mDesc);
				ThrowIfOSErr_(err);
			}			
		}
	}
}


// ---------------------------------------------------------------------------
//		¥ AccessModelObject
// ---------------------------------------------------------------------------
//	Get Token for ModelObject
//
//	Part of the OSL object resolution process. Given a Token for a
//	Container and a key description of some objects, make a Token
//	for those objects.

void
LModelDirector::AccessModelObject(
	const DescType	inDesiredClass,
	const AEDesc	&inContainerToken,
	const DescType	/* inContainerClass */,
	const DescType	inKeyForm,
	const AEDesc	&inKeyData,
	AEDesc			&outToken,
	Int32			/* inRefCon */)
{
	LModelObject	*theContainer = nil;

	//	The OSL normally does this.  But... it doesn't appear to in
	//	in the case of formWhose or formTest.  Since GetModelToken
	//	can "add" to existing AEDesc's, this is required.
	outToken.descriptorType = typeNull;
	outToken.dataHandle = NULL;
	
	theContainer = LModelObject::GetModelFromToken(inContainerToken);
	Try_ {
		theContainer->GetModelToken(inDesiredClass, inKeyForm, inKeyData,
										outToken);
	} Catch_ (inErr) {
		DisposeToken(outToken);		//	In case the OSL doesn't do it
		Throw_(inErr);
	} EndCatch_;
}


void
LModelDirector::AccessModelObjectList(
	const DescType	inDesiredClass,
	const AEDesc	&inContainerToken,
	const DescType	/* inContainerClass */,
	const DescType	inKeyForm,
	const AEDesc	&inKeyData,
	AEDesc			&outToken,
	Int32			/* inRefCon */)
{
	Int32		itemCount,
				i;
	OSErr		err = noErr;

	outToken.descriptorType = typeNull;
	outToken.dataHandle = NULL;
	
	if (::AECountItems(&inContainerToken, &itemCount)) {
		itemCount = 0;
	}
	
	Try_ {
		for (i = 1; i <= itemCount; i++) {
			StAEDescriptor	containerDesc,
							subModelDesc;
			LModelObject	*container = nil;
			DescType		bogusKeyword;
			
			err = ::AEGetNthDesc(&inContainerToken, i, typeWildCard,
						&bogusKeyword, &containerDesc.mDesc);
			ThrowIfOSErr_(err);

			container = LModelObject::GetModelFromToken(containerDesc.mDesc);
			container->GetModelToken(inDesiredClass, inKeyForm, inKeyData,
						subModelDesc.mDesc);
		
			if (subModelDesc.mDesc.descriptorType == typeAEList) {
				Int32		subCount;
				if (::AECountItems(&subModelDesc.mDesc, &subCount)) {
					subCount = 0;
				}
				
				for (Int32 j = 1; j <= subCount; j++) {
					StAEDescriptor	subItem;
	
					err = ::AEGetNthDesc(&subModelDesc.mDesc, j, typeWildCard,
								&bogusKeyword, &subItem.mDesc);
					ThrowIfOSErr_(err);
					UAEDesc::AddDesc(&outToken, 0, subItem.mDesc);
				}
			} else {
				UAEDesc::AddDesc(&outToken, 0, subModelDesc.mDesc);
			}
			
			ThrowIfOSErr_(err);
		}
	} Catch_(inErr) {
		DisposeToken(outToken);		//	In case the OSL doesn't do it
		Throw_(inErr);
	} EndCatch_;
}


// ---------------------------------------------------------------------------
//		¥ DisposeToken
// ---------------------------------------------------------------------------
//	A Token is no longer needed.
//
//	Will not propogate errors.

void
LModelDirector::DisposeToken(
	AEDesc		&inToken)
{
	::AEDisposeDesc(&inToken);
}


// ---------------------------------------------------------------------------
//		¥ CompareObjects
// ---------------------------------------------------------------------------
//	Pass back the result of comparing one object with another

void
LModelDirector::CompareObjects(
	DescType		inComparisonOperator,
	const AEDesc	&inBaseObject,
	const AEDesc	&inCompareObjectOrDesc,
	Boolean			&outResult)
{
		// Base Object compares itself to the other object
	
	LModelObject	*theModel = LModelObject::GetModelFromToken(inBaseObject);
	
	if (inCompareObjectOrDesc.descriptorType == type_ModelToken) {
								// Other "object" is another ModelObject
		outResult = theModel->CompareToModel(inComparisonOperator,
					LModelObject::GetModelFromToken(inCompareObjectOrDesc));
								
	} else {					// Other "object" is a Descriptor
		outResult = theModel->CompareToDescriptor(inComparisonOperator,
								inCompareObjectOrDesc);
	}
}


// ---------------------------------------------------------------------------
//		¥ CountObjects
// ---------------------------------------------------------------------------
//	Pass back the number of objects of the desiredClass that are in the
//	specified container object

void
LModelDirector::CountObjects(
	DescType		inDesiredClass,
	DescType		/* inContainerClass */,
	const AEDesc	&inContainer,
	Int32			&outCount)
{
	LModelObject	*theModel = LModelObject::GetModelFromToken(inContainer);
	outCount = theModel->CountSubModels(inDesiredClass);
}


// ===========================================================================
// ¥ Static Functions									   Static Functions ¥
// ===========================================================================

// ---------------------------------------------------------------------------
//		¥ Resolved
// ---------------------------------------------------------------------------
//	Wrapper for AEResolve.  Takes into consideration mResolveFlags and, if the
//	inSpec is typeType pSelection, will fabricate a selection property ospec
//	with a null wrapper.  (AppleScript has an annoying habit of not recreating
//	AE's exactly as they were sent.)

OSErr
LModelDirector::Resolve(
	const AEDesc	&inSpec,
	AEDesc			&outToken)
{
	OSErr		err = noErr;
	DescType	theType;
	Boolean		fabricate = false;
	
	if (inSpec.descriptorType == typeType) {
		UExtractFromAEDesc::TheType(inSpec, theType);
		if (theType == pSelection)
			fabricate = true;
	}
	
	if (fabricate) {
		StAEDescriptor	nullSpec,
						propDesc(typeType, &theType, sizeof(theType)),
						fabSpec;
						
		err = ::CreateObjSpecifier(cProperty, nullSpec, formPropertyID,
											propDesc, false, &fabSpec.mDesc);
		if (err == noErr)
			err = ::AEResolve(&fabSpec.mDesc, sModelDirector->mResolveFlags, &outToken);
	} else {
		err = ::AEResolve(&inSpec, sModelDirector->mResolveFlags, &outToken);
	}
	
	return err;
}


// ===========================================================================
// ¥ Static CallBack Functions					   Static CallBack Functions ¥
// ===========================================================================

// ---------------------------------------------------------------------------
//		¥ AppleEventHandler
// ---------------------------------------------------------------------------
//	Generic CallBack function for all AppleEvents

pascal OSErr
LModelDirector::AppleEventHandler(
	const AppleEvent	*inAppleEvent,
	AppleEvent			*outAEReply,
	Int32				inRefCon)
{
	OSErr	err = noErr;
	
	try {
		sModelDirector->HandleAppleEvent(*inAppleEvent, *outAEReply, inRefCon);
	}
	
	catch (ExceptionCode inErr) {
		err = inErr;
	}
	
	catch (...) {
		SignalPStr_("\pUnknown Exception caught");
	}

	LModelObject::FinalizeLazies();

	return err;
}


// ---------------------------------------------------------------------------
//		¥ OpenOrPrintEventHandler
// ---------------------------------------------------------------------------
//	CallBack function for Open or Print AppleEvents
	
pascal OSErr
LModelDirector::OpenOrPrintEventHandler(
	const AppleEvent	*inAppleEvent,
	AppleEvent			*outAEReply,
	Int32				inRefCon)
{
	OSErr	err = noErr;
	
	try {
		sModelDirector->HandleOpenOrPrintEvent(*inAppleEvent, *outAEReply,
							inRefCon);
	}
	
	catch (ExceptionCode inErr) {
		err = inErr;
	}
	
	catch (...) {
		SignalPStr_("\pUnknown Exception caught");
	}

	LModelObject::FinalizeLazies();

	return err;
}


// ---------------------------------------------------------------------------
//		¥ CreateElementEventHandler
// ---------------------------------------------------------------------------
//	CallBack function for CreateElement AppleEvent
	
pascal OSErr
LModelDirector::CreateElementEventHandler(
	const AppleEvent	*inAppleEvent,
	AppleEvent			*outAEReply,
	Int32				inRefCon)
{
	OSErr	err = noErr;
	
	try {
		sModelDirector->HandleCreateElementEvent(*inAppleEvent, *outAEReply,
							inRefCon);
	}
	
	catch (ExceptionCode inErr) {
		err = inErr;
	}
	
	catch (...) {
		SignalPStr_("\pUnknown Exception caught");
	}

	LModelObject::FinalizeLazies();

	return err;
}


pascal OSErr
LModelDirector::ModelObjectAccessor(
	DescType		inDesiredClass,
	const AEDesc	*inContainerToken,
	DescType		inContainerClass,
	DescType		inKeyForm,
	const AEDesc	*inKeyData,
	AEDesc*			outToken,
	Int32			inRefCon)
{
	OSErr	err = noErr;
	
	try {
		sModelDirector->AccessModelObject(inDesiredClass,
									*inContainerToken, inContainerClass,
									inKeyForm, *inKeyData,
									*outToken, inRefCon);
	}
	
	catch (ExceptionCode inErr) {
		err = inErr;
	}
	
	catch (...) {
		SignalPStr_("\pUnknown Exception caught");
	}
	
	return err;
}


pascal OSErr
LModelDirector::ModelObjectListAccessor(
	DescType		inDesiredClass,
	const AEDesc	*inContainerToken,
	DescType		inContainerClass,
	DescType		inKeyForm,
	const AEDesc	*inKeyData,
	AEDesc*			outToken,
	Int32			inRefCon)
{
	OSErr	err = noErr;
	
	try {
		sModelDirector->AccessModelObjectList(inDesiredClass,
									*inContainerToken, inContainerClass,
									inKeyForm, *inKeyData,
									*outToken, inRefCon);
	}
	
	catch (ExceptionCode inErr) {
		err = inErr;
	}
	
	catch (...) {
		SignalPStr_("\pUnknown Exception caught");
	}
	
	return err;
}


pascal OSErr
LModelDirector::OSLDisposeToken(
	AEDesc		*inToken)
{
	OSErr	err = noErr;
	
	try {
		sModelDirector->DisposeToken(*inToken);
	}
	
	catch (ExceptionCode inErr) {
		err = inErr;
	}
	
	catch (...) {
		SignalPStr_("\pUnknown Exception caught");
	}
	
	return err;
}


pascal OSErr
LModelDirector::OSLCompareObjects(
	DescType		inComparisonOperator,
	const AEDesc	&inBaseObject,
	const AEDesc	&inCompareObjectOrDesc,
	Boolean			&outResult)
{
	OSErr	err = noErr;
	
	try {
		sModelDirector->CompareObjects(inComparisonOperator, inBaseObject,
									inCompareObjectOrDesc, outResult);
	}
	
	catch (ExceptionCode inErr) {
		err = inErr;
	}
	
	catch (...) {
		SignalPStr_("\pUnknown Exception caught");
	}
	
	return err;
}


pascal OSErr
LModelDirector::OSLCountObjects(
	DescType		inDesiredClass,
	DescType		inContainerClass,
	const AEDesc	&inContainer,
	Int32			&outCount)
{
	OSErr	err = noErr;
	
	try {
		sModelDirector->CountObjects(inDesiredClass, inContainerClass,
									inContainer, outCount);
	}
	
	catch (ExceptionCode inErr) {
		err = inErr;
	}
	
	catch (...) {
		SignalPStr_("\pUnknown Exception caught");
	}
	
	return err;
}