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