Milán Major

netscape-revival

1 branch
Code

lib/mac/VText/V_PowerPlant_Mods/LDragTube.cp

//	===========================================================================
//	LDragTube.cp					©1994 Metrowerks Inc. All rights reserved.
//	===========================================================================

//	For routine descriptions see LDataTube.cp.

#ifdef PowerPlant_PCH
#include PowerPlant_PCH
#endif

#include	"LDragTube.h"
#include	<UMemoryMgr.h>
#include	<LDynamicArray.h>
#include	<LTubeableItem.h>

#ifndef __ERRORS__
#include	<Errors.h>
#endif

#pragma	warn_unusedarg off

Boolean	LDragTube::sSendingData = false;

LDragTube::LDragTube(
	DragReference	inDragRef)
{
	mDragRef = inDragRef;

	mSwapDepth = 2;

	mAddSendsData = false;
}

LDragTube::LDragTube(
	DragReference		inDragRef,
	const LTubeableItem	*inTubeableItem,
	Boolean				inReqdFlavorsOnly
)
{
	mDragRef = inDragRef;
	
	mSwapDepth = 2;
	
	mAddSendsData = false;

	FillFrom(inTubeableItem, inReqdFlavorsOnly);
}

LDragTube::~LDragTube()
{
}

//	----------------------------------------------------------------------
//	Read:

Boolean	LDragTube::FlavorExists(FlavorType inFlavor) const
{
	Boolean	rval = false;
	
	if (mTubeDepth == mSwapDepth) {
		OSErr		err;
		FlavorFlags	flags;
		
		err = GetFlavorFlags(mDragRef, mItemRef, inFlavor, &flags);
		
		if (err == noErr)
			rval = true;
		else if (err == badDragFlavorErr)
			;
		else
			ThrowIfOSErr_(err);

	} else {
		rval = inherited::FlavorExists(inFlavor);
	}
	
	return rval;
}

Size	LDragTube::GetFlavorSize(FlavorType inFlavor) const
{
	Size	rval = 0;
	
	if (mTubeDepth == mSwapDepth) {
		OSErr		err;
		Size		dataSize;
		
		err = GetFlavorDataSize(mDragRef, mItemRef, inFlavor, &dataSize);
		
#if	0
		//	for debugging...
		if (err != noErr) {
			OSErr			err2;
			short			i;
			unsigned short	numItems;
			ItemReference	item;
			LTubeableItem	*tubeItem;
			
			Assert_(false);
			err2 = CountDragItems(mDragRef, &numItems);
			
			for (i = 1; i <= numItems; i++)  {
				err2 = GetDragItemReferenceNumber(mDragRef, i, &item);
				tubeItem = (LTubeableItem *) item;
			}
		}
#endif

		ThrowIfOSErr_(err);
		
		rval = dataSize;
	} else {
		rval = inherited::GetFlavorSize(inFlavor);
	}
	
	return rval;
}

void *	LDragTube::GetFlavorData(
	FlavorType	inFlavor,
	void		*outFlavorData
) const
{
	void	*rval = NULL;
	
	if (mTubeDepth == mSwapDepth) {
		OSErr		err;
		Size		preDataSize, dataSize;
		
		Assert_(outFlavorData);
		
		preDataSize = dataSize = GetFlavorSize(inFlavor);
		
		err = ::GetFlavorData(mDragRef, mItemRef, inFlavor, outFlavorData, &dataSize, 0);
		ThrowIfOSErr_(err);
		
		Assert_(dataSize == preDataSize);
		
		rval = NULL;
	} else {
		rval = inherited::GetFlavorData(inFlavor, outFlavorData);
	}
	
	return rval;
}

Int32	LDragTube::CountItems(void) const
{
	Int32	rval = 0;

	if (mTubeDepth == mSwapDepth-1) {
		Uint16	count = 0;
		OSErr	err = CountDragItems(mDragRef, &count);
		ThrowIfOSErr_(err);
		rval = count;
	} else {
		rval = inherited::CountItems();
	}
	
	return rval;
}

LDataTube	LDragTube::KeyedItem(ItemReference inItemRef) const
{
	if (mTubeDepth == mSwapDepth-1) {		
		OSErr			err;
		LAESubDesc		sd;
		
		do {
			FlavorFlags		flags;
			Size			dataSize = 0;

			err = GetFlavorFlags(mDragRef, inItemRef, typeTubeMapItems, &flags);
			if (err == badDragFlavorErr)
				break;
			ThrowIfOSErr_(err);
			
			err = GetFlavorDataSize(mDragRef, inItemRef, typeTubeMapItems, &dataSize);
			ThrowIfOSErr_(err);			
			if (!dataSize)
				Throw_(paramErr);
				
			//	Get typeTubeMapItems data
			StHandleBlock	h(dataSize);
			StHandleLocker	lock(h);
			err = ::GetFlavorData(mDragRef, inItemRef, typeTubeMapItems, *(h.mHandle), &dataSize, 0);
			ThrowIfOSErr_(err);
			
			//	Swap mOwnedDesc
			AEDesc	*desc = &(((LDragTube *)this)->mOwnedDesc.mDesc);
			AEDisposeDesc(desc);
			desc->descriptorType = typeAERecord;
			desc->dataHandle = h.mHandle;
			h.mHandle = NULL;			
			sd = LAESubDesc(*desc);
		} while (false);
		
		return LDataTube(this, inItemRef, sd, mTubeDepth + 1);
		
	} else {

		return inherited::KeyedItem(inItemRef);

	}
}

LDataTube	LDragTube::NthItem(Int32 inIndex, ItemReference *outReference) const
{
	if (mTubeDepth == mSwapDepth-1) {
		ItemReference	ref;
		
		OSErr err = GetDragItemReferenceNumber(mDragRef, inIndex, &ref);
		ThrowIfOSErr_(err);
	
		if (outReference)
			*outReference = ref;
		
		return KeyedItem(ref);

	} else {

		return inherited::NthItem(inIndex, outReference);

	}
}

//	----------------------------------------------------------------------

Int32	LDragTube::FlavorCount(void) const
{
	Int32	rval = 0;
	OSErr	err;
	
	if (mTubeDepth == mSwapDepth) {
		Uint16	flavors = 0;
		
		err = CountDragItemFlavors(mDragRef, mItemRef, &flavors);
		ThrowIfOSErr_(err);
		
		if (FlavorExists(typeTubeMapItems))
			flavors--;
		
		rval = flavors;			
	} else {
		rval = inherited::FlavorCount();
	}
	
	return rval;
}

FlavorType	LDragTube::NthFlavor(Int32 inIndex) const
{
	OSErr		err;
	FlavorType	rval = typeNull;
	
	if (mTubeDepth == mSwapDepth) {
		FlavorType	keyFound;
		Int32		index = 0;
		
		Assert_((0 < inIndex) && (inIndex <= FlavorCount()));
		
		do {
			index++;
			err = GetFlavorType(mDragRef, mItemRef, index, &keyFound);
			ThrowIfOSErr_(err);
			
			if (keyFound == typeTubeMapItems)
				index++;
			inIndex--;
		} while (inIndex > 0);
		
		rval = keyFound;
	} else {
		rval = inherited::NthFlavor(inIndex);
	}
	
	return rval;
}

//	----------------------------------------------------------------------
//	Write:

void	LDragTube::AddFlavor(FlavorType inFlavor)
{
	if (mItemStack.Depth() == mSwapDepth) {	
		OSErr	err;
		
		err = AddDragItemFlavor(mDragRef, mItemStack.Top().ref, inFlavor, NULL, 0, 0);
		ThrowIfOSErr_(err);
	} else {
		inherited::AddFlavor(inFlavor);
	}
}

void	LDragTube::SetFlavorData(
	FlavorType	inFlavor,
	const void	*inFlavorData,
	Int32		inFlavorSize
)
{
	if (!mItemStack.Depth() && sSendingData) {
		OSErr	err = SetDragItemFlavorData(mDragRef, mItemRef, inFlavor, inFlavorData, inFlavorSize, 0);
		ThrowIfOSErr_(err);	//	If -48 see note above.
	} else if ((mItemStack.Depth() == mSwapDepth)) {
		OSErr		err;
		
		//	for debugging
		#if	0
		{
			unsigned short	count,
							i;
			ItemReference	item;
			Boolean			found = false;
			
			err = CountDragItems(inDrag, &count);
			ThrowIfOSErr_(err);
			
			for (i = 1; i <= count; i++) {
				err = GetDragItemReferenceNumber(inDrag, i, &item);
				ThrowIfOSErr_(err);
				
				if (item == (ItemReference) this) {
					found = true;
					break;
				}
			}
			
			Assert_(found);	//	Discovery!  If this fails or something above
							//	throws a -48 error, it is most likely a sign
							//	the Drag Mgr has died -- time to reboot.
		}
		#endif
		
		err = SetDragItemFlavorData(mDragRef, mItemStack.Top().ref, inFlavor, inFlavorData, inFlavorSize, 0);
		ThrowIfOSErr_(err);	//	If -48 see note above.
	} else {
		inherited::SetFlavorData(inFlavor, inFlavorData, inFlavorSize);
	}
}

void	LDragTube::OpenItem(
			const LTubeableItem	*inItem,
			ItemReference		inItemRef
)
{
	if (mTubeDepth == mSwapDepth) {
		if (inItemRef != defaultItemReference)
			Throw_(paramErr);	//	Sorry, but you can't specify item ref's w/ base level drag items.
								//	To do so would require LDragTube to keep a cache of tubeable items
								//	and tubable item refs -- all to fulfill delayed "gets" of flavors.
	}
	
	if (mTubeDepth >= mSwapDepth)
		mAddSendsData = true;
		
	inherited::OpenItem(inItem, (ItemReference) inItem);
}

void	LDragTube::CloseItem(void)
{
	if (mTubeDepth <= mSwapDepth)
		mAddSendsData = false;
	
	inherited::CloseItem();
}

//	----------------------------------------------------------------------

void	LDragTube::SendFlavorData(ItemReference inItemRef, FlavorType inFlavor)
{
	LTubeableItem		*item = (LTubeableItem *) inItemRef;

	ThrowIfNULL_(item);
//	Assert_(member(item, LTubeableItem));

	Assert_(!mItemStack.Depth());
	
	StValueChanger<Int32>	change(mItemRef, inItemRef);
	StValueChanger<Boolean>	change2(sSendingData, true);
	
	item->SendFlavorTo(inFlavor, this);
}