Milán Major

netscape-revival

1 branch
Code

lib/mac/VText/V_PowerPlant_Mods/LTextElemAEOM.cp

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

#ifdef PowerPlant_PCH
#include PowerPlant_PCH
#endif

#include	"LTextElemAEOM.h"

#include	<LTextModel.h>
#include	<LTextEngine.h>
#include	<LDataTube.h>
#include	<UDrawingState.h>
#include	<UDrawingUtils.h>
#include	<LHandlerView.h>
#include	<LListIterator.h>
#include	<URegions.h>

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

//	===========================================================================
//	Maintenance

LTextElemAEOM::LTextElemAEOM(
	const TextRangeT	&inRange,
	DescType			inKind,
	LModelObject		*inSuperModel,
	LTextModel			*inTextModel,
	LTextEngine			*inTextEngine)
	:	LSelectableItem(inSuperModel, inKind)
{
	mRange = inRange;

	mTextEngine = inTextEngine;
	mTextModel = inTextModel;

	Assert_(mTextEngine);
	Assert_(mTextModel);
	
	//	Text elem's are not AE "accessed" through the submodel list.
	//	But, the submodel list is used to keep a list of all instantiated
	//	text objects that need to be updated when the text changes.
	//	See AdjustRanges.
	SetUseSubModelList(true);
	
	SetLaziness(true);
}

LTextElemAEOM::~LTextElemAEOM()
{
}

LTextEngine *	LTextElemAEOM::GetTextEngine(void) const
{
	return mTextEngine;
}

LTextModel *	LTextElemAEOM::GetTextModel(void) const
{
	return mTextModel;
}

//	===========================================================================
//	LSelectableItem implementation

Boolean	LTextElemAEOM::IsSubstantive(void) const
{
	return mRange.Length() > 0;
}

Boolean	LTextElemAEOM::EquivalentTo(const LSelectableItem *inItem) const
{
	Boolean	rval = false;
	
	if (inItem) {
		LTextElemAEOM*	that = (LTextElemAEOM*) inItem;
//		Assert_(member(that, LTextElemAEOM));
		
		rval = mRange == that->GetRange();
	}
	
	return rval;
}

Boolean	LTextElemAEOM::AdjacentWith(const LSelectableItem *inItem) const
{
	Boolean	rval = false;
	
	if (inItem) {
		LTextElemAEOM*	that = (LTextElemAEOM*) inItem;
//		Assert_(member(that, LTextElemAEOM));

		rval = mRange.Adjacent(that->GetRange());
	}
	
	return rval;
}

Boolean	LTextElemAEOM::IndependentFrom(const LSelectableItem *inItem) const
{
	Boolean	rval = true;
	
	if (inItem) {
		LTextElemAEOM*	that = (LTextElemAEOM*) inItem;
//		Assert_(member(that, LTextElemAEOM));

		rval = !mRange.Intersects(that->GetRange());
	}

	return rval;
}

LSelectableItem	*	LTextElemAEOM::FindExtensionItem(const LSelectableItem *inItem) const
{
	if (inItem) {
		TextRangeT		newRange = GetRange();
		DescType		newType;
		LTextElemAEOM	*inTextItem = (LTextElemAEOM *)inItem;
//		Assert_(member(inTextItem, LTextElemAEOM));
	
		newRange.Union(inTextItem->GetRange());
		
		if (GetModelKind() == inTextItem->GetModelKind())
			newType = GetModelKind();
		else
			newType = cChar;
	
		return mTextModel->MakeNewElem(newRange, newType);
	} else {
		return (LTextElemAEOM *)this;
	}
}

Boolean	LTextElemAEOM::PointInRepresentation(Point inWhere) const
{
	SPoint32		where;
	LHandlerView	*theView;
	
	theView = mTextEngine->GetHandlerView();
	ThrowIfNULL_(theView);
	theView->LocalToImagePoint(inWhere, where);

	return mTextEngine->PointInRange(where, mRange);
}

//	---------------------------------------------------------------------------
//	Visual representation implementation.

void	LTextElemAEOM::DrawSelfSelected(void)
{
	StRegion		rgn;
	StColorPenState	savePen;
		
	mTextEngine->GetRangeRgn(mRange, &rgn.mRgn);
	
	StColorPenState::Normalize();
	UDrawingUtils::SetHiliteModeOn();
	InvertRgn(rgn.mRgn);
	ThrowIfOSErr_(QDError());
}

void	LTextElemAEOM::DrawSelfLatent(void)
{
	StRegion		rgn;
	StColorPenState	savePen;
		
	mTextEngine->GetRangeRgn(mRange, &rgn.mRgn);
	
	PenPat(&UQDGlobals::GetQDGlobals()->black);
	PenMode(srcXor);
	UDrawingUtils::SetHiliteModeOn();
	FrameRgn(rgn.mRgn);
	ThrowIfOSErr_(QDError());
}

void	LTextElemAEOM::UnDrawSelfSelected(void)
{
	DrawSelfSelected();
}

void	LTextElemAEOM::UnDrawSelfLatent(void)
{
	DrawSelfLatent();
}

void	LTextElemAEOM::DrawSelfReceiver(void)
{
	StRegion		rgn;
	StColorPenState	savePen;
		
	mTextEngine->GetRangeRgn(mRange, &rgn.mRgn);
	
	StColorPenState::Normalize();
	PenPat(&UQDGlobals::GetQDGlobals()->black);
	PenMode(srcXor);
	InvertRgn(rgn.mRgn);
	ThrowIfOSErr_(QDError());

	LSelectableItem::DrawSelfReceiver();
}

//	===========================================================================
//	Data tubing

void	LTextElemAEOM::AddFlavorTypesTo(LDataTube *inTube) const
{
	Assert_(this == (LSelectableItem *)this);	//	If this fails... it is bad and something must be systemically fixed.

	mTextModel->AddFlavorTypesTo(mRange, inTube);

	if (!inTube->GetOnlyReqdFlavors())
		LSelectableItem::AddFlavorTypesTo(inTube);
}

Boolean	LTextElemAEOM::SendFlavorTo(FlavorType inFlavor, LDataTube *inTube) const
{
	if (mTextModel->SendFlavorTo(inFlavor, mRange, inTube)) {
		return true;
	} else {
		return LSelectableItem::SendFlavorTo(inFlavor, inTube);
	}
}

FlavorType	LTextElemAEOM::PickFlavorFrom(const LDataTube *inTube) const
{
	return mTextModel->PickFlavorFrom(mRange, inTube);
}

void	LTextElemAEOM::ReceiveDataFrom(LDataTube *inTube)
{
	TextRangeT	range = mRange,
				preTotRange = mTextEngine->GetTotalRange();
	
	Assert_(GetSuperRange().WeakContains(range));
	
	//	Do the transfer
	mTextModel->ReceiveDataFrom(range, inTube);
	
	//	Fix up this elem's range...
	TextRangeT	newTotRange = mTextEngine->GetTotalRange(),
				resultRange = range,
				superRange = GetSuperRange();
	Int32		resultLength = newTotRange.Length() - (preTotRange.Length() - range.Length());
	
	if (resultLength < 0) {
		Assert_(false);
		Throw_(paramErr);
	}
	
	if (resultLength) {
		resultRange.SetLength(resultLength);
		Assert_(superRange.Contains(resultRange));
	} else {
		resultRange.Front();
		resultRange.Crop(superRange);
	}

	SetRange(resultRange);
}

//	===========================================================================
//	Implementation

const TextRangeT &	LTextElemAEOM::GetSuperRange(void) const
{
	if ((this == mTextModel->GetTextLink()) || !mTextModel->GetTextLink()) {
		//	This model is the link and has no super range
		Assert_(mTextEngine->GetTotalRange() == mRange);

		return GetRange();
	} else {
		const LTextElemAEOM	*super = dynamic_cast<LTextElemAEOM *>(GetSuperModel());
		
		ThrowIfNULL_(super);

		return super->GetRange();
	}
}

const TextRangeT &	LTextElemAEOM::GetRange(void) const
{
	return mRange;
}

void	LTextElemAEOM::SetRange(const TextRangeT &inRange)
{
	if (mRange != inRange) {

		if (this != mTextModel->GetTextLink()) {
			Assert_(GetSuperRange().Contains(inRange));
		}
	
		mRange = inRange;
	}
}

const Ptr	LTextElemAEOM::GetTextPtr(void) const
/*
	Result is valid only until next memory move.
	You may not change data pointed to by the result.
	The data pointed to by the result is only valid for mRange.Length() characters.
*/
{
	Ptr	rval = *mTextEngine->GetTextHandle();
	rval += mRange.Start();
	return rval;
}

void	LTextElemAEOM::AdjustRanges(const TextRangeT &inRange, Int32 inLengthDelta)
{
	AdjustRange(inRange, inLengthDelta);

	if (mSubModels) {
		LListIterator	iterator(*mSubModels, iterate_FromStart);
		LModelObject	*p = NULL;
		LTextElemAEOM	*q;
				
		while (iterator.Next(&p)) {
			ThrowIfNULL_(p);
			switch(p->GetModelKind()) {
				case cWord:
				case cLine:
				case cParagraph:
				case cChar:
					q = (LTextElemAEOM *)p;
//					Assert_(member(q, LTextElemAEOM));
					q->AdjustRanges(inRange, inLengthDelta);
					break;
				default:
					break;
			}
		}
	}
}

void	LTextElemAEOM::AdjustRange(const TextRangeT &inRange, Int32 inLengthDelta)
{
	if (mTextModel->GetTextLink() == this) {
		mRange.Adjust(inRange, inLengthDelta, true);
		mTextModel->FixLink();
	} else {
		mRange.Adjust(inRange, inLengthDelta, false);
		mRange.Crop(GetSuperRange());
	}
}