sl@0: /*
sl@0: * Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: * All rights reserved.
sl@0: * This component and the accompanying materials are made available
sl@0: * under the terms of "Eclipse Public License v1.0"
sl@0: * which accompanies this distribution, and is available
sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: *
sl@0: * Initial Contributors:
sl@0: * Nokia Corporation - initial contribution.
sl@0: *
sl@0: * Contributors:
sl@0: *
sl@0: * Description: 
sl@0: *
sl@0: */
sl@0: 
sl@0: 
sl@0: #include <e32std.h>
sl@0: #include <e32base.h>
sl@0: #include "TXTFRMAT.H"
sl@0: #include "TXTFMLYR.H"
sl@0: #include <txtfmstm.h>
sl@0: #include "TXTSTD.H"
sl@0: 
sl@0: #include "OstTraceDefinitions.h"
sl@0: #ifdef OST_TRACE_COMPILER_IN_USE
sl@0: #include "TXTFMLYRTraces.h"
sl@0: #endif
sl@0: 
sl@0: #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
sl@0: #include "TXTFMLYR_INTERNAL.H"
sl@0: #endif
sl@0: 
sl@0: CFormatLayer::CFormatLayer()
sl@0: 	{
sl@0: 	}
sl@0: 
sl@0: 
sl@0: CFormatLayer::~CFormatLayer()
sl@0: 	{
sl@0: 	iStore.Reset();
sl@0: 	}
sl@0: 
sl@0: 
sl@0: DLLEXPORT_C void CFormatLayer::__DbgTestInvariant() const
sl@0: 	{
sl@0: 	}
sl@0: 
sl@0: 
sl@0:  
sl@0: EXPORT_C void CFormatLayer::SetBase(const CFormatLayer* aBaseFormatLayer)
sl@0: /** Sets the format layer which this layer's based-on link points to.
sl@0: 
sl@0: @param aBaseFormatLayer The format layer which this layer's based-on link 
sl@0: points to. Specify NULL if this is the final layer in the chain (the layer 
sl@0: on which all other layers are based). */
sl@0: 	{
sl@0: 	iBasedOn = aBaseFormatLayer;
sl@0: 	}
sl@0: 
sl@0: 
sl@0:  
sl@0: EXPORT_C const CFormatLayer* CFormatLayer::SenseBase() const
sl@0: /** Gets the format layer which this layer's based-on link points to. If NULL, 
sl@0: this layer is the final layer in the chain.
sl@0: 
sl@0: @return The format layer on which this layer is based. */
sl@0: 	{
sl@0: 	return iBasedOn;
sl@0: 	}
sl@0: 
sl@0: 
sl@0:  
sl@0: EXPORT_C TInt CFormatLayer::ChainCount() const
sl@0: /** Gets the number of format layers in the chain, inclusive of itself. Assumes 
sl@0: that the format layer chain has been correctly set up to terminate with a 
sl@0: NULL based-on link.
sl@0: 
sl@0: @return The number of format layers in the chain, counting from the current 
sl@0: layer. */
sl@0: 	{
sl@0: 	TInt chainCount=1;
sl@0: 	const CFormatLayer* next=iBasedOn;
sl@0: 	while (next)
sl@0: 		{
sl@0: 		++chainCount;
sl@0: 		next=next->iBasedOn;
sl@0: 		}
sl@0: 	return chainCount;
sl@0: 	}
sl@0: 
sl@0: 
sl@0: 
sl@0: const TUint8* CFormatLayer::Ptr(TInt& aSize)const
sl@0: /** Return a pointer to the stored bytecode.*/	
sl@0:     {
sl@0: 	return iStore.Ptr(aSize);
sl@0: 	}
sl@0: 
sl@0: 
sl@0: 
sl@0: EXPORT_C void CFormatLayer::Reset()
sl@0: /** Deletes the contents of the format layer. The based-on link is not affected. */
sl@0: 	{
sl@0: 	iStore.Reset();
sl@0: 	}
sl@0: 
sl@0: 
sl@0: 
sl@0: EXPORT_C void CFormatLayer::InternalizeChainL(RReadStream& aStream,const CFormatLayer* aBase)
sl@0: /** Restores a chain of format layers from a read stream. The layer at the end 
sl@0: of the chain (the one furthest from this layer) is set to be based on the 
sl@0: specified layer aBase, which may be NULL. This layer is set to be at the head 
sl@0: of the restored chain (i.e. no other layers are based on it).
sl@0: 
sl@0: @param aStream Stream from which the format layer chain should be internalised. 
sl@0: 
sl@0: @param aBase The format layer at the end of the chain (furthest from this layer). 
sl@0: May be NULL. */
sl@0: 	{
sl@0: 	TInt chainLength=aStream.ReadInt8L();
sl@0: 	if (chainLength<1)
sl@0: 		User::Leave(KErrCorrupt);  // Must restore at least one layer (this), else corrupt stream.
sl@0: 	TInt descendentCount=chainLength-1;
sl@0: 	for (TInt loop=0;loop<descendentCount;loop++)
sl@0: 		{// Restore each descendent of [this] layer.
sl@0: 		CFormatLayer* layer=RestoreNewL(aStream);
sl@0: 		layer->SetBase(aBase);
sl@0: 		CleanupStack::PushL(layer);
sl@0: 		aBase=layer;
sl@0: 		}
sl@0: 	aStream>> *this;
sl@0: 	SetBase(aBase);
sl@0: 	CleanupStack::Pop(descendentCount);
sl@0: 	}
sl@0: 
sl@0: 
sl@0: 
sl@0: 
sl@0: EXPORT_C void CFormatLayer::ExternalizeChainL(RWriteStream& aStream,TInt aExcludeCount)const
sl@0: /** Stores a chain of format layers. By default an entire chain is stored unless 
sl@0: an exclude count is provided. In this case, the length of the chain stored 
sl@0: is the ChainCount() minus the exclude count. The excluded layers are the ones 
sl@0: starting with the layer with the NULL based-on link.
sl@0: 
sl@0: Note
sl@0: 
sl@0: The exclude count must be zero or greater but must be less than the total 
sl@0: number of layers in the chain, otherwise a panic occurs.
sl@0: 
sl@0: @param aStream Stream to which the format layer chain should be externalised. 
sl@0: @param aExcludeCount The number of layers to be excluded. By default, zero. */
sl@0: 	{
sl@0: // ASSERT: aExcludeCount is positive.
sl@0: 	if (aExcludeCount<0)
sl@0: 	    {
sl@0: 	    OstTrace0( TRACE_FATAL, CFORMATLAYER_EXTERNALIZECHAINL, "ECannotStoreFormatLayerChain" );
sl@0: 	    }
sl@0: 	__ASSERT_ALWAYS(aExcludeCount>=0,Panic(ECannotStoreFormatLayerChain));
sl@0: // ASSERT: The number of layers to be excluded is less than the total no. of layers.
sl@0: 	if (aExcludeCount>=ChainCount())
sl@0: 	    {
sl@0: 	    OstTrace0( TRACE_FATAL, DUP1_CFORMATLAYER_EXTERNALIZECHAINL, "ECannotStoreFormatLayerChain" );
sl@0: 	    }
sl@0: 	__ASSERT_ALWAYS(aExcludeCount<ChainCount(),Panic(ECannotStoreFormatLayerChain));
sl@0: 	TInt aCount=ChainCount()-aExcludeCount;
sl@0: 	aStream.WriteInt8L(aCount);  // Store the chain length.
sl@0: 	ExternalizeLayersRecurseL(aStream,--aCount);
sl@0: 	}	
sl@0: 	
sl@0: 
sl@0: void CFormatLayer::ExternalizeLayersRecurseL(RWriteStream& aStream,TInt aDescendantCount)const
sl@0: /** Stores a format layer chain with *aLength* number of layers in a stack-like 
sl@0: fashion. This necessitates navigating to the end of the chain and storing the 
sl@0: layers as we unwind back to the top of the chain.*/
sl@0: //
sl@0: 	{
sl@0: 	if (aDescendantCount)
sl@0: 		{
sl@0: // ASSERT: The format layer chain is consistent.
sl@0: 		if (iBasedOn==NULL)
sl@0: 		    {
sl@0: 		    OstTrace0( TRACE_DUMP, CFORMATLAYER_EXTERNALIZELAYERSRECURSEL, "ECorruptFormatLayerChain" );
sl@0: 		    }
sl@0: 		__ASSERT_ALWAYS(iBasedOn!=NULL,Panic(ECorruptFormatLayerChain));
sl@0: 		iBasedOn->ExternalizeLayersRecurseL(aStream,--aDescendantCount);
sl@0: 		}
sl@0: 	aStream<< *this;
sl@0: 	}
sl@0: 	
sl@0: /** Implementations of this function compare another format layer with the
sl@0: current object. For the two layers to be equal, they must have the same 
sl@0: contents and (if the second parameter is ETrue),their based-on links must 
sl@0: point to the same format layer.
sl@0: 
sl@0: @param aLayer The layer to compare to this format layer.
sl@0: @param aCheckBasedOnLink If ETrue, both layers' based-on links must point to 
sl@0: the same format layer. If EFalse, the based-on links are not used in the 
sl@0: comparison. By default, ETrue.
sl@0: @return  ETrue if the two layers are identical, otherwise EFalse. */
sl@0: TBool CFormatLayer::IsIdentical(const TUint8* aPtr,TInt aSize) const
sl@0: 	{
sl@0: 	TInt size=0;
sl@0: 	const TUint8* ptr=iStore.Ptr(size);
sl@0: 	if ((ptr==NULL && aPtr!=NULL) || (ptr!=NULL && aPtr==NULL))
sl@0: 		return EFalse;
sl@0: 	if (ptr==NULL && aPtr==NULL)
sl@0: 		return ETrue;
sl@0: 	return (!(TBool)(Mem::Compare(ptr,size,aPtr,aSize)));
sl@0: 	}
sl@0: 
sl@0: /** Tests whether any formatting is stored in the format layer.
sl@0: 
sl@0: @return ETrue if no formatting is stored in the format layer, otherwise returns 
sl@0: EFalse. */
sl@0: EXPORT_C TBool CFormatLayer::IsEmpty() const
sl@0: 	{
sl@0: 	TInt size=0;
sl@0: 	return iStore.Ptr(size)==NULL;
sl@0: 	}
sl@0: 
sl@0: /** Swaps the contents of this with aLayer.
sl@0: @param aLayer The layer to swap contents with.
sl@0: @internalComponent */
sl@0: void CFormatLayer::Swap(CFormatLayer& aLayer)
sl@0: 	{
sl@0: 	iStore.Swap(aLayer.iStore);
sl@0: 	const CFormatLayer* t = iBasedOn;
sl@0: 	iBasedOn = aLayer.iBasedOn;
sl@0: 	aLayer.iBasedOn = t;
sl@0: 	}
sl@0: 
sl@0: /** Allocates and constructs an empty CParaFormatLayer. Its based-on link is 
sl@0: NULL.
sl@0: 
sl@0: Note: Use SetL() to set format attributes in the layer. Use SetBase(), defined 
sl@0: in the base class CFormatLayer, to set the layer's based on link.
sl@0: 
sl@0: @return Pointer to the new paragraph format layer. */
sl@0: EXPORT_C CParaFormatLayer* CParaFormatLayer::NewL()
sl@0: 	{
sl@0: 	return new(ELeave) CParaFormatLayer;
sl@0: 	}
sl@0: 
sl@0: 
sl@0: EXPORT_C CParaFormatLayer* CParaFormatLayer::NewL(RReadStream& aStream)
sl@0: /** Allocates and constructs a CParaFormatLayer, restoring its format attributes 
sl@0: from a stream. The layer's based-on link is set to NULL.
sl@0: 
sl@0: @param aStream Stream from which the layer is restored. 
sl@0: @return Pointer to the new paragraph format layer. */
sl@0: 	{
sl@0: 	CParaFormatLayer* self=NewL();
sl@0: 	CleanupStack::PushL(self);
sl@0: 	self->InternalizeL(aStream);
sl@0: 	CleanupStack::Pop();
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: 
sl@0: EXPORT_C CParaFormatLayer* CParaFormatLayer::NewL(const CParaFormat* aFormat,const TParaFormatMask& aMask)
sl@0: /** Allocates and constructs a CParaFormatLayer. The attributes which are set 
sl@0: in the mask are initialised to the values specified in the format container 
sl@0: aParaFormat. The attributes which are not set in the mask are initialised to 
sl@0: the default values for class CParaFormat. The new layer's based-on link is set 
sl@0: to NULL.
sl@0: 
sl@0: @param aParaFormat Contains the attribute values to assign to the format layer. 
sl@0: @param aMask Mask specifying which attributes should be initialized from 
sl@0: aParaFormat. 
sl@0: @return Pointer to ParaFormatLayer the new paragraph format layer. */
sl@0: 	{
sl@0: 	CParaFormatLayer* self=NewL();
sl@0: 	CleanupStack::PushL(self);
sl@0: 	self->SetL(aFormat,aMask);
sl@0: 	CleanupStack::Pop();
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: 
sl@0: CParaFormatLayer* CParaFormatLayer::NewL(const CParaFormatLayer* aLayer)
sl@0: /** Copying construction
sl@0:  does not copy the based on link*/
sl@0: 	{
sl@0: 	CParaFormatLayer* self=NewL();  // based-on is NULL
sl@0: 	CleanupStack::PushL(self);
sl@0: 	aLayer->CloneLayerL(self);
sl@0: 	CleanupStack::Pop();			// self
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: CParaFormatLayer* CParaFormatLayer::NewCopyBaseL(const CParaFormatLayer* aLayer)
sl@0: /** Copying construction
sl@0:  copies based-on link*/
sl@0: 	{
sl@0: 	CParaFormatLayer* self=NewL(aLayer);  // based-on is NULL
sl@0: 	self->iBasedOn=aLayer->iBasedOn;
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: CParaFormatLayer::CParaFormatLayer()
sl@0: /** Constructor.*/
sl@0: // No ConstructL method since allocation is postponed until first Set.
sl@0: //
sl@0: 	{
sl@0: 	}
sl@0: 
sl@0: EXPORT_C void CParaFormatLayer::ExternalizeL(RWriteStream& aStream)const
sl@0: /** Externalises the paragraph format layer but not its based-on link to a 
sl@0: write stream. The presence of this function means that the standard templated 
sl@0: operator<<() (defined in s32strm.h) is available to externalise objects of 
sl@0: this class.
sl@0: 
sl@0: @param aStream Stream to which the format layer should be externalised. */
sl@0: 	{aStream<< iStore;}
sl@0: 
sl@0: EXPORT_C void CParaFormatLayer::InternalizeL(RReadStream& aStream,const CFormatLayer* aBase)
sl@0: /** Internalises the paragraph format layer but not its based-on link from a 
sl@0: read stream. The presence of this function means that the standard templated 
sl@0: operator>>() (defined in s32strm.h) is available to internalise objects of 
sl@0: this class. The internalised layer is set to be based on the layer specified.
sl@0: 
sl@0: @param aStream Stream from which the format layer should be internalised. 
sl@0: @param aBase The based-on link to assign to the layer. By default NULL. */
sl@0: 	{
sl@0: 	aStream>> iStore;
sl@0: 	SetBase(aBase);
sl@0: 	}
sl@0: 
sl@0: EXPORT_C void CParaFormatLayer::SetL(const CParaFormat* aDesiredEffectiveFormat,const TParaFormatMask& aMask)
sl@0: /** Sets the layer's format attributes. The attributes which are set in the 
sl@0: mask are set in the layer to the values specified in the format container 
sl@0: aDesiredEffectiveFormat. The attributes which are not set in the mask are not 
sl@0: changed.
sl@0: 
sl@0: Note: Any tab stops in aDesiredEffectiveFormat are merged with the tab stops in 
sl@0: the current layer.
sl@0: 
sl@0: @param aDesiredEffectiveFormat Contains the attribute values to assign to 
sl@0: the format layer. 
sl@0: @param aMask Mask specifying which attributes should be set from 
sl@0: aDesiredEffectiveFormat. */
sl@0: 	{
sl@0: 	if ( !aDesiredEffectiveFormat )
sl@0: 		{
sl@0: 		return;
sl@0: 		}
sl@0: 	
sl@0: 	const CParaFormat& desiredFormat = *aDesiredEffectiveFormat;
sl@0: 	CParaFormat currentEffectiveFormat;
sl@0: 	ResetOnCleanupL( &currentEffectiveFormat);
sl@0: 	if (iBasedOn)
sl@0: 		((CParaFormatLayer*)iBasedOn)->SenseEffectiveL(&currentEffectiveFormat);
sl@0: 	iStore.SetParaFormatL(desiredFormat,aMask,currentEffectiveFormat);
sl@0: 	CleanupStack::Pop();
sl@0: 	}
sl@0: 
sl@0: EXPORT_C void CParaFormatLayer::SenseEffectiveL(CParaFormat* aParaFormat,CParaFormat::TParaFormatGetMode aMode)const
sl@0: /** Senses the layer's effective format, searching all based-on links. The 
sl@0: resulting aParaFormat is fully populated, except that if aMode is 
sl@0: EFixedAttributes, then only the fixed attributes (not tabs, paragraph borders 
sl@0: or bullets) are written to it.
sl@0: 
sl@0: Notes:
sl@0: 
sl@0: The function also "tidies up" the layer's effective paragraph formatting, 
sl@0: so that any zero height bullets, paragraph borders with a NULL line style 
sl@0: or NULL tab stops are removed. 
sl@0: 
sl@0: The function can only leave if aMode has a value of EAllAttributes.
sl@0: 
sl@0: @param aParaFormat On return, contains the layer's effective formatting. 
sl@0: Depending on the value of aMode, tabs, borders and bullets may be excluded. 
sl@0: Must not be NULL or a panic occurs. 
sl@0: @param aMode Controls which attributes are written to aParaFormat. If 
sl@0: EAllAttributes, all attributes are written; if EFixedAttributes, tabs, 
sl@0: bullets and borders are not written. */
sl@0: 	{
sl@0: 	if (aParaFormat==NULL)
sl@0: 	    {
sl@0: 	    OstTrace0( TRACE_FATAL, CPARAFORMATLAYER_SENSEEFFECTIVEL, "ENullFormatPointer" );
sl@0: 	    }
sl@0: 	__ASSERT_ALWAYS(aParaFormat!=NULL,Panic(ENullFormatPointer));
sl@0: 	aParaFormat->Reset();
sl@0: 	TParaFormatMask mask;
sl@0: 	FillParaFormatL(aParaFormat,mask,aMode);
sl@0: 	CleanupEffectiveFormat(aParaFormat,mask);
sl@0: 	}
sl@0: 
sl@0: EXPORT_C void CParaFormatLayer::SenseL(CParaFormat* aParaFormat,TParaFormatMask& aMask,CParaFormat::TParaFormatGetMode aMode)const
sl@0: /** Senses the formatting which has been applied to the current layer only. No 
sl@0: based-on links are searched. This function does not get the effective formatting, 
sl@0: but the resulting aParaFormat is useable even if not all attributes are flagged 
sl@0: for sensing in aMask because any attribute values not sensed from the current 
sl@0: layer, are set to default values.
sl@0: 
sl@0: The function can only leave if aMode has a value of EAllAttributes.
sl@0: 
sl@0: @param aParaFormat On return, contains the formatting which has been applied 
sl@0: to the current layer only. Any attributes not explicitly set in the current 
sl@0: layer are initialised to the default values for a CParaFormat. Attributes 
sl@0: specified in aMask are not sensed from this layer. The values for these 
sl@0: attributes are also initialised to the default settings. Must not be NULL or 
sl@0: a panic occurs. 
sl@0: @param aMask A bitmask. Any attributes which are set in the mask as passed 
sl@0: into the function are not sensed from the current layer. On return, indicates 
sl@0: the attributes which were sensed from this layer. So, normally, when passed 
sl@0: to the function, all attributes in the mask should be unset. 
sl@0: @param aMode Controls which attributes are written to aParaFormat. If 
sl@0: EAllAttributes, all attributes are written; if EFixedAttributes, tabs, bullets 
sl@0: and borders are not written. */
sl@0: 	{
sl@0: 	if (aParaFormat==NULL)
sl@0: 	    {
sl@0: 	    OstTrace0( TRACE_FATAL, CPARAFORMATLAYER_SENSEL, "ENullFormatPointer" );
sl@0: 	    }
sl@0: 	__ASSERT_ALWAYS(aParaFormat!=NULL,Panic(ENullFormatPointer));
sl@0: 
sl@0: 	iStore.SenseParaFormatL(*aParaFormat,aMask,aMode);
sl@0: 	}
sl@0: 
sl@0: 
sl@0: void CFormatLayer::CloneLayerL(CFormatLayer* aClone)const
sl@0: 	{
sl@0: 	aClone->iStore.CopyL(iStore);
sl@0: 	}
sl@0: 
sl@0: 
sl@0: EXPORT_C CFormatLayer* CParaFormatLayer::DoCloneL()const
sl@0: //
sl@0: //
sl@0: 	{
sl@0: 	return NewL(this);  // use copy construction
sl@0: 	}
sl@0: 
sl@0: 
sl@0: 
sl@0: EXPORT_C TBool CParaFormatLayer::IsIdenticalL(const CParaFormat* aParaFormat,const TParaFormatMask& aMask)const
sl@0: /** Compares a format attribute container with the current layer. For the two 
sl@0: objects to be identical, the current layer must contain only the attributes 
sl@0: specified in the argument aMask, and these attributes must have the same values 
sl@0: as those in aParaFormat. None of the current layer's based-on links are searched.
sl@0: 
sl@0: @param aParaFormat Contains the attribute values used in the comparison. 
sl@0: @param aMask A bitmask specifying which attributes are relevant to the function. 
sl@0: 
sl@0: @return ETrue if the formatting of the current layer exactly matches that 
sl@0: contained in aParaFormat. Otherwise EFalse. */
sl@0: 	{
sl@0: 	CParaFormat* thisParaFormat=CParaFormat::NewLC();
sl@0: 	TParaFormatMask thisParaFormatMask;
sl@0: 	SenseL(thisParaFormat,thisParaFormatMask);
sl@0: 	TBool result=EFalse;
sl@0: 	if (thisParaFormatMask!=aMask)
sl@0: 		result=EFalse;
sl@0: 	else if (thisParaFormat->IsEqual(*aParaFormat,aMask))
sl@0: 		result=ETrue;
sl@0: 	CleanupStack::PopAndDestroy();
sl@0: 	return result;
sl@0: 	}
sl@0: 
sl@0: EXPORT_C TBool CParaFormatLayer::IsIdentical(CFormatLayer* aLayer,TBool aCheckBasedOnLink)const
sl@0: /** Compares another paragraph format layer with the current layer. For the two 
sl@0: layers to be equal, they must have the same contents and (if the second 
sl@0: parameter is ETrue), their based-on links must point to the same format layer.
sl@0: 
sl@0: @param aLayer The paragraph format layer to compare to this format layer. 
sl@0: @param aCheckBasedOnLink If ETrue, both layers' based-on links must point to 
sl@0: the same format layer. If EFalse, the based-on links are not used in the 
sl@0: comparison. By default, ETrue. 
sl@0: @return ETrue if the two layers are identical, otherwise EFalse. */
sl@0: 	{
sl@0: 	if (aCheckBasedOnLink)
sl@0: 		{
sl@0: 		if (iBasedOn!=aLayer->SenseBase())
sl@0: 			return EFalse;
sl@0: 		}
sl@0: 	TInt size;
sl@0: 	const TUint8* ptr=((CParaFormatLayer*)aLayer)->Ptr(size);		// some design went wrong here!
sl@0: 	return CFormatLayer::IsIdentical(ptr,size);
sl@0: 	}
sl@0: 
sl@0: EXPORT_C const TUint8* CParaFormatLayer::Ptr(TInt& aSize)const
sl@0: /** Gets a pointer to the start of the buffer containing the layer's format 
sl@0: attribute values.
sl@0: 
sl@0: @param aSize On return, set to the size of the buffer. 
sl@0: @return Pointer to the buffer which contains the layer's format attribute 
sl@0: values. */
sl@0: 	{return CFormatLayer::Ptr(aSize);}
sl@0: 
sl@0: EXPORT_C TUid CParaFormatLayer::Type()const
sl@0: /** Returns the paragraph format layer UID. This can be used to distinguish 
sl@0: between an ordinary paragraph format layer and paragraph styles, which have a 
sl@0: different UID.
sl@0: 
sl@0: @return The UID of a paragraph format layer (KNormalParagraphStyleUid). */
sl@0: 	{return KNormalParagraphStyleUid;}
sl@0: 
sl@0: CFormatLayer* CParaFormatLayer::RestoreNewL(RReadStream& aStream)
sl@0: /** Return a new CParaFormatLayer, having restored it from aStream.
sl@0:  Overrides the base class method, to provide a new format layer of the correct 
sl@0:  type.*/
sl@0: 	{return NewL(aStream);}
sl@0: 
sl@0: void CParaFormatLayer::FillParaFormatL(CParaFormat* aParaFormat,TParaFormatMask& aMask,CParaFormat::TParaFormatGetMode aMode)const
sl@0: /** Fills aParaFormat by dumping the current format layer into it.  
sl@0: Next traverse the 'basedOn' link if it is not NULL, and repeat.*/
sl@0: 	{
sl@0: 	if ( !aParaFormat )
sl@0: 		{
sl@0: 		return;
sl@0: 		}
sl@0: 	
sl@0: 	CParaFormat& senseFormat = *aParaFormat;
sl@0: 
sl@0: 	iStore.SenseParaFormatL(senseFormat,aMask,aMode);
sl@0: 	if (iBasedOn)
sl@0: 		((CParaFormatLayer*)iBasedOn)->FillParaFormatL(aParaFormat,aMask,aMode);
sl@0: 	}
sl@0: 
sl@0: void CParaFormatLayer::CleanupEffectiveFormat(CParaFormat* aParaFormat,TParaFormatMask aMask)const
sl@0: /** Removes anti-tabs, zero height and null bullets, and paragraph borders with
sl@0:  null linestyles, from aParaFormat.  An effective format does not support the
sl@0:  notion of anti-tabs etc.*/
sl@0: 	{
sl@0: 	if (aMask.AttribIsSet(EAttBullet))
sl@0: 		{
sl@0: 		if (aParaFormat->iBullet->iStyle == TBullet::ENullStyle || aParaFormat->iBullet->iHeightInTwips <= 0)
sl@0: 			{
sl@0: 			delete aParaFormat->iBullet;
sl@0: 			aParaFormat->iBullet = NULL;
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 	if (aMask.AttribIsSet(EAttTopBorder) ||
sl@0: 		aMask.AttribIsSet(EAttBottomBorder) ||
sl@0: 		aMask.AttribIsSet(EAttLeftBorder) ||
sl@0: 		aMask.AttribIsSet(EAttRightBorder))
sl@0: 		CleanupBorders(aParaFormat);
sl@0: 
sl@0: 	if (aMask.AttribIsSet(EAttTabStop))
sl@0: 		{
sl@0: 		int index = 0;
sl@0: 		while (index < aParaFormat->TabCount())
sl@0: 			{
sl@0: 			TTabStop tab = aParaFormat->TabStop(index);
sl@0: 			if (tab.iType == TTabStop::ENullTab)
sl@0: 				aParaFormat->RemoveTab(tab.iTwipsPosition);
sl@0: 			else
sl@0: 				index++;
sl@0: 			}
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: 
sl@0: void CParaFormatLayer::CleanupBorders(CParaFormat* aParaFormat)const
sl@0: /** Destroys the paragraph border if it is of NULL linestyle,
sl@0:  and nulls the pointer to it (aBorder).*/
sl@0: 	{
sl@0: 	if (aParaFormat->ParaBorder(CParaFormat::EParaBorderTop).iLineStyle==TParaBorder::ENullLineStyle &&
sl@0: 		aParaFormat->ParaBorder(CParaFormat::EParaBorderBottom).iLineStyle==TParaBorder::ENullLineStyle &&
sl@0: 		aParaFormat->ParaBorder(CParaFormat::EParaBorderLeft).iLineStyle==TParaBorder::ENullLineStyle &&
sl@0: 		aParaFormat->ParaBorder(CParaFormat::EParaBorderRight).iLineStyle==TParaBorder::ENullLineStyle)
sl@0: 		{
sl@0: 		aParaFormat->RemoveAllBorders();
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: 
sl@0: EXPORT_C CCharFormatLayer* CCharFormatLayer::NewL()
sl@0: /** Allocates and constructs an empty CCharFormatLayer. Its based-on link is 
sl@0: NULL.
sl@0: 
sl@0: Note: Use SetL() to set format attributes in the layer. Use SetBase(), defined 
sl@0: in the base class CFormatLayer, to set the layers based on link.
sl@0: 
sl@0: @return Pointer to the new character format layer. */
sl@0: 	{return new(ELeave)CCharFormatLayer;}
sl@0: 
sl@0: 
sl@0: 
sl@0: EXPORT_C CCharFormatLayer* CCharFormatLayer::NewL(RReadStream& aStream)
sl@0: /** Allocates and constructs a CCharFormatLayer, restoring its format attributes 
sl@0: from a stream. The layer's based-on link is set to NULL.
sl@0: 
sl@0: @param aStream Stream from which the layer is restored. 
sl@0: @return Pointer to the new character format layer. */
sl@0: 	{
sl@0: 	CCharFormatLayer* self=NewL();
sl@0: 	CleanupStack::PushL(self);
sl@0: 	self->InternalizeL(aStream);
sl@0: 	CleanupStack::Pop();
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: 
sl@0: EXPORT_C CCharFormatLayer* CCharFormatLayer::NewL(const TCharFormat& aFormat,const TCharFormatMask& aMask)
sl@0: /** Returns a handle to a new charFormatLayer, after constructing
sl@0:  it and setting it with the specified format and format mask.*/
sl@0: 	{
sl@0: 	CCharFormatLayer* self=NewL();
sl@0: 	CleanupStack::PushL(self);
sl@0: 	self->SetL(aFormat,aMask);
sl@0: 	CleanupStack::Pop();
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: 
sl@0: CCharFormatLayer* CCharFormatLayer::NewL(const TCharFormatX& aFormat,const TCharFormatXMask& aMask)
sl@0: 	{
sl@0: 	CCharFormatLayer* self = NewL();
sl@0: 	CleanupStack::PushL(self);
sl@0: 	self->SetL(aFormat,aMask);
sl@0: 	CleanupStack::Pop();
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: 
sl@0: CCharFormatLayer* CCharFormatLayer::NewL(const CCharFormatLayer* aLayer)
sl@0: /** Copying construction
sl@0:  does not copy based-on link.*/
sl@0: 	{
sl@0: 	CCharFormatLayer* self=NewL();  // based-on is NULL
sl@0: 	CleanupStack::PushL(self);
sl@0: 	aLayer->CloneLayerL(self);
sl@0: 	CleanupStack::Pop();			// self
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: CCharFormatLayer* CCharFormatLayer::NewCopyBaseL(const CCharFormatLayer* aLayer)
sl@0: /** Copying construction
sl@0:  copies based-on link*/
sl@0: 	{
sl@0: 	CCharFormatLayer* self=NewL(aLayer);  // based-on is NULL
sl@0: 	self->iBasedOn=aLayer->iBasedOn;
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: 
sl@0: CCharFormatLayer::CCharFormatLayer()
sl@0: 	{
sl@0: 	}
sl@0: 
sl@0: EXPORT_C void CCharFormatLayer::ExternalizeL(RWriteStream& aStream)const
sl@0: /** Externalises the character format layer but not its based-on link to a 
sl@0: write stream. The presence of this function means that the standard templated 
sl@0: operator<<() (defined in s32strm.h) is available to externalise objects of 
sl@0: this class.
sl@0: 
sl@0: @param aStream Stream to which the format layer should be externalised. */
sl@0: 	{
sl@0: 	aStream << iStore;
sl@0: 	}
sl@0: 
sl@0: EXPORT_C void CCharFormatLayer::InternalizeL(RReadStream& aStream,const CFormatLayer* aBase)
sl@0: /** Internalises the character format layer but not its based-on link from a 
sl@0: read stream. The presence of this function means that the standard templated 
sl@0: operator>>() (defined in s32strm.h) is available to internalise objects of 
sl@0: this class. The internalised layer is set to be based on the layer specified.
sl@0: 
sl@0: @param aStream Stream from which the format layer should be internalised. 
sl@0: @param aBase The based-on link to assign to the layer. By default NULL. */
sl@0: 	{
sl@0: 	aStream >> iStore;
sl@0: 	SetBase(aBase);
sl@0: 	}
sl@0: 
sl@0: 
sl@0: EXPORT_C const TUint8* CCharFormatLayer::Ptr(TInt& aSize)const
sl@0: /** Gets a pointer to the start of the buffer containing the layer's format 
sl@0: attribute values.
sl@0: 
sl@0: @param aSize On return, set to the size of the buffer. 
sl@0: @return Pointer to the buffer which contains the layer's format attribute 
sl@0: values. */
sl@0: 	{
sl@0: 	return CFormatLayer::Ptr(aSize);
sl@0: 	}
sl@0: 
sl@0: EXPORT_C void CCharFormatLayer::SetL(const TCharFormat& aCharFormat,const TCharFormatMask& aMask)
sl@0: /** Sets the layer's format attributes. The attributes which are set in the 
sl@0: mask are set in the layer to the values specified in the format container 
sl@0: aCharFormat. The attributes which are not set in the mask are not changed.
sl@0: 
sl@0: @param aCharFormat Contains the attribute values to assign to the format layer. 
sl@0: @param aMask Mask specifying which attributes should be set from aCharFormat. */
sl@0: 	{
sl@0: 	TCharFormatX format(aCharFormat);
sl@0: 	iStore.SetCharFormatL(format,aMask);
sl@0: 	}
sl@0: 
sl@0: void CCharFormatLayer::SetL(const TCharFormatX& aCharFormat,const TCharFormatXMask& aMask)
sl@0: /** Sets the layer's format attributes. The attributes which are set in the 
sl@0: mask are set in the layer to the values specified in the format container 
sl@0: aCharFormat. The attributes which are not set in the mask are not changed.
sl@0: 
sl@0: @param aCharFormat Contains the attribute values to assign to the format layer. 
sl@0: @param aMask Mask specifying which attributes should be set from aCharFormat. */
sl@0: 	{
sl@0: 	iStore.SetCharFormatL(aCharFormat,aMask);
sl@0: 	}
sl@0: 
sl@0: EXPORT_C void CCharFormatLayer::SenseEffective(TCharFormat& aCharFormat)const
sl@0: /** Senses the layer's effective format, searching all based-on links. The 
sl@0: resulting aCharFormat is fully populated.
sl@0: 
sl@0: @param aCharFormat On return, contains the layer's effective formatting. */
sl@0: 	{
sl@0: 	TCharFormatX format;
sl@0: 	TCharFormatXMask mask;
sl@0: 	FillCharFormat(format,mask);
sl@0: 	aCharFormat = format.iCharFormat;
sl@0: 	}
sl@0: 
sl@0: void CCharFormatLayer::SenseEffective(TCharFormatX& aCharFormat) const
sl@0: /** Senses the layer's effective format, searching all based-on links. The 
sl@0: resulting aCharFormat is fully populated.
sl@0: 
sl@0: @param aCharFormat On return, contains the layer's effective formatting. */
sl@0: 	{
sl@0: 	TCharFormatXMask mask;
sl@0: 	aCharFormat = TCharFormatX(); // initialise character format; FillCharFormat doesn't do this
sl@0: 	FillCharFormat(aCharFormat,mask);
sl@0: 	}
sl@0: 
sl@0: EXPORT_C void CCharFormatLayer::Sense(TCharFormat& aCharFormat,TCharFormatMask& aMask)const
sl@0: /** Senses the formatting which has been applied to the current layer only. No 
sl@0: based-on links are searched. This function does not get the layer's effective 
sl@0: formatting, but the resulting aCharFormat is fully populated, even if not 
sl@0: all attributes are flagged for sensing in aMask because any attribute values 
sl@0: not sensed from the current layer are set to default values.
sl@0: 
sl@0: @param aCharFormat On return, contains the formatting which has been applied 
sl@0: to the current layer only. Any attributes not explicitly set in the current 
sl@0: layer are set to the default values for a TCharFormat. Any attributes specified 
sl@0: in aMask are not sensed from this layer. The values for these attributes are 
sl@0: also initialised to the default settings. 
sl@0: @param aMask A bitmask. Any attributes which are set in the mask as passed 
sl@0: into the function are not sensed from the current layer. On return, indicates 
sl@0: the attributes which were sensed from this layer. So, normally, when passed 
sl@0: to the function, all attributes in the mask should be unset. */
sl@0: 	{
sl@0: 	TCharFormatX format(aCharFormat);
sl@0: 	TCharFormatXMask mask = aMask;
sl@0: 	iStore.SenseCharFormat(format,mask);
sl@0: 	aCharFormat = format.iCharFormat;
sl@0: 	mask.ClearExtendedAttribs();
sl@0: 	aMask = mask;
sl@0: 	}
sl@0: 
sl@0: void CCharFormatLayer::Sense(TCharFormatX& aCharFormat,TCharFormatXMask& aMask) const
sl@0: /** Senses the formatting which has been applied to the current layer only. No 
sl@0: based-on links are searched. This function does not get the layer's effective 
sl@0: formatting, but the resulting aCharFormat is fully populated, even if not 
sl@0: all attributes are flagged for sensing in aMask because any attribute values 
sl@0: not sensed from the current layer are set to default values.
sl@0: 
sl@0: @param aCharFormat On return, contains the formatting which has been applied 
sl@0: to the current layer only. Any attributes not explicitly set in the current 
sl@0: layer are set to the default values for a TCharFormat. Any attributes specified 
sl@0: in aMask are not sensed from this layer. The values for these attributes are 
sl@0: also initialised to the default settings. 
sl@0: @param aMask A bitmask. Any attributes which are set in the mask as passed 
sl@0: into the function are not sensed from the current layer. On return, indicates 
sl@0: the attributes which were sensed from this layer. So, normally, when passed 
sl@0: to the function, all attributes in the mask should be unset. */
sl@0: 	{
sl@0: 	iStore.SenseCharFormat(aCharFormat,aMask);
sl@0: 	}
sl@0: 
sl@0: 
sl@0: EXPORT_C CFormatLayer* CCharFormatLayer::DoCloneL()const
sl@0: 	{
sl@0: 	return NewL(this);  // use copy construction
sl@0: 	}
sl@0: 
sl@0: 
sl@0: EXPORT_C TBool CCharFormatLayer::IsIdentical(CFormatLayer* aLayer,TBool aCheckBasedOnLink)const
sl@0: /** Compares another character format layer with the current layer. For the two 
sl@0: layers to be equal, they must have the same contents and (if the second 
sl@0: parameter is ETrue), their based-on links must point to the same format layer.
sl@0: 
sl@0: @param aLayer The character format layer to compare to this format layer. 
sl@0: @param aCheckBasedOnLink If ETrue, both layers' based-on links must point to 
sl@0: the same format layer. If EFalse, the based-on links are not used in the 
sl@0: comparison. By default, ETrue. 
sl@0: @return ETrue if the two layers are identical, otherwise EFalse. */
sl@0: 	{
sl@0: 	if (aCheckBasedOnLink)
sl@0: 		{
sl@0: 		if (iBasedOn!=aLayer->SenseBase())
sl@0: 			return EFalse;
sl@0: 		}
sl@0: 	TInt size;
sl@0: 	const TUint8* ptr=((CCharFormatLayer*)aLayer)->Ptr(size);		// some naff design at work here!
sl@0: 	return CFormatLayer::IsIdentical(ptr,size);
sl@0: 	}
sl@0: 
sl@0: EXPORT_C TBool CCharFormatLayer::IsIdentical(const TCharFormat& aCharFormat,const TCharFormatMask& aMask)const
sl@0: /** Compares a format attribute container with the current layer. For the two 
sl@0: objects to be identical, the current layer must contain only the attributes 
sl@0: specified in the argument aMask, and these attributes must have the same 
sl@0: values as those in aCharFormat. None of the current layer's based-on links are 
sl@0: searched.
sl@0: 
sl@0: @param aCharFormat Contains the attribute values used in the comparison. 
sl@0: @param aMask A bitmask specifying which attributes are relevant to the function. 
sl@0: 
sl@0: @return ETrue if the formatting of the current layer exactly matches that 
sl@0: contained in aCharFormat, otherwise EFalse. */
sl@0: 	{
sl@0: 	TCharFormat thisCharFormat;
sl@0: 	TCharFormatMask thisCharFormatMask;
sl@0: 	Sense(thisCharFormat,thisCharFormatMask);
sl@0: 	if (thisCharFormatMask!=aMask)
sl@0: 		return EFalse;
sl@0: 	return thisCharFormat.IsEqual(aCharFormat,aMask);
sl@0: 	}
sl@0: 
sl@0: 
sl@0: CFormatLayer* CCharFormatLayer::RestoreNewL(RReadStream& aStream)
sl@0: /** Return a new CCharFormatLayer, having restored it from aStream.
sl@0: Overrides the base class method, to provide a new format layer of 
sl@0: the correct type.*/
sl@0: 	{return CCharFormatLayer::NewL(aStream);}
sl@0: 
sl@0: 
sl@0: void CCharFormatLayer::FillCharFormat(TCharFormatX& aCharFormat,TCharFormatXMask& aMask)const
sl@0: /** Fills aCharFormat by dumping the current format layer into it, then follows 
sl@0: each 'BasedOn' link in turn if it is not null.  It is assumed that all based on 
sl@0: links eventually terminate with nulls.*/
sl@0: 	{
sl@0: 	iStore.SenseCharFormat(aCharFormat,aMask);
sl@0: 	if (iBasedOn)
sl@0: 		((CCharFormatLayer*)iBasedOn)->FillCharFormat(aCharFormat,aMask);
sl@0: 	}