textrendering/texthandling/stext/TXTSTYLE.CPP
changeset 0 1fb32624e06b
child 40 91ef7621b7fc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/textrendering/texthandling/stext/TXTSTYLE.CPP	Tue Feb 02 02:02:46 2010 +0200
@@ -0,0 +1,604 @@
+/*
+* Copyright (c) 1997-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 <s32strm.h>
+
+#include "TXTSTYLE.H"
+#include "TXTFRMAT.H"
+#include "TXTSTD.H"
+
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include "TXTFMLYR_INTERNAL.H"
+#include "TXTSTYLE_INTERNAL.H"
+#endif
+
+// Return the handle of a new paragraph style
+ 
+
+EXPORT_C CParagraphStyle* CParagraphStyle::NewL(const CParaFormatLayer& aGlobalParaFormatLayer,
+												const CCharFormatLayer& aGlobalCharFormatLayer)
+/** Allocates and constructs a CParagraphStyle object whose formatting is based 
+on a global paragraph and character format layer. The type UID is initialised 
+to KUserDefinedParagraphStyleUid. The outline level is not initialised.
+
+@param aGlobalParaFormatLayer The paragraph format layer on which the style's 
+paragraph formatting is based. 
+@param aGlobalCharFormatLayer The character format layer on which the style's 
+character formatting is based. 
+@return Pointer to the new CParagraphStyle object. */
+	{
+	CParagraphStyle* self=new(ELeave) CParagraphStyle();
+	CleanupStack::PushL(self);
+	self->ConstructL(aGlobalParaFormatLayer,aGlobalCharFormatLayer);
+	CleanupStack::Pop();
+	return self;
+	}
+
+
+CParagraphStyle::CParagraphStyle():
+	iType(KUserDefinedParagraphStyleUid)
+	{
+	}
+
+
+// Create style and base it on the specified 'Normal' layers
+void CParagraphStyle::ConstructL(const CParaFormatLayer& aGlobalParaFormatLayer,
+										  const CCharFormatLayer& aGlobalCharFormatLayer)
+	{
+	SetBase(&aGlobalParaFormatLayer);
+	//
+	// Force para format layer storage allocation with empty layer
+	TParaFormatMask paraMask;
+	SetL((CParaFormat*)NULL,paraMask);
+	//
+	// Force char format layer storage allocation with empty layer;
+/*	TCharFormat format;
+	TCharFormatMask mask;
+	iCharFormatLayer=CCharFormatLayer::NewL(format,mask);
+*/
+	iCharFormatLayer=CCharFormatLayer::NewL();
+	iCharFormatLayer->SetBase(&aGlobalCharFormatLayer);
+	}
+ 
+
+EXPORT_C CParagraphStyle::~CParagraphStyle()
+/** The destructor frees all resources owned by the object, prior to its destruction. */
+	{
+	delete iCharFormatLayer;
+	}
+
+
+EXPORT_C CFormatLayer* CParagraphStyle::DoCloneL()const
+	{
+	const CCharFormatLayer* charLayer=STATIC_CAST(const CCharFormatLayer*,iCharFormatLayer->SenseBase());
+	CParagraphStyle* clone=CParagraphStyle::NewL(STATIC_CAST(const CParaFormatLayer&,*SenseBase()),*charLayer);
+	CleanupStack::PushL(clone);
+	CloneLayerL(clone);  // clones the paragraph format layer
+	delete clone->iCharFormatLayer;
+	clone->iCharFormatLayer=NULL;  // necessary precaution if next instruction leaves
+	clone->iCharFormatLayer=iCharFormatLayer->CloneL();  // clones the character format layer
+	clone->iCharFormatLayer->SetBase(charLayer);  // restore the based on link
+	CleanupStack::Pop();  // clone
+	//
+	clone->SetType(Type());
+	clone->SetOutlineLevel(OutlineLevel());
+	clone->iName=iName;
+	//
+	return clone;
+	}
+
+
+ 
+
+EXPORT_C TUid CParagraphStyle::Type()const
+/** Gets the style's type UID.
+
+@return The style's type UID. */
+	{return iType;}
+
+
+CParagraphStyle* CParagraphStyle::NewL(RReadStream& aStream,
+										const CParaFormatLayer& aGlobalParaFormatLayer,
+										const CCharFormatLayer& aGlobalCharFormatLayer)
+	{
+	CParagraphStyle* self=new(ELeave) CParagraphStyle();
+	CleanupStack::PushL(self);
+	self->ConstructL(aGlobalParaFormatLayer,aGlobalCharFormatLayer);
+	self->InternalizeL(aStream,&aGlobalParaFormatLayer,&aGlobalCharFormatLayer);
+	CleanupStack::Pop();
+	return self;
+	}
+
+
+// Load into this style from the specified readStream.  Base this style on the layer aBase - Default NULL
+void CParagraphStyle::InternalizeL(RReadStream& aStream,const CFormatLayer* aParaLayerBase,const CFormatLayer* aCharLayerBase)
+	{
+	aStream>> iName;
+	aStream>> iType;
+	iOutlineLevel=aStream.ReadInt32L();
+	iCharFormatLayer->InternalizeL(aStream,aCharLayerBase);
+	//
+	CParaFormatLayer::InternalizeL(aStream,aParaLayerBase);
+	}
+
+
+// Save the style in the specified WriteStream. The based on link is *NOT* stored.
+void CParagraphStyle::ExternalizeL(RWriteStream& aStream)const
+	{
+	aStream<< iName;
+	aStream<< iType;
+	aStream.WriteInt32L(iOutlineLevel);
+	aStream<< *iCharFormatLayer;
+	//
+	CParaFormatLayer::ExternalizeL(aStream);
+	}
+
+
+DLLEXPORT_C void CStyleList::__DbgTestInvariant()const
+// Provides class invariants.  Explanations below:
+//
+	{
+#ifdef _DEBUG
+	TInt styleCount=Count();
+	for (TInt nn=0;nn<styleCount;nn++)
+		{
+		RParagraphStyleInfo info=iList->At(nn);
+		if (info.iStyleForNextPara)
+			{
+			TInt index=IndexByPtr(info.iStyleForNextPara);
+			// ASSERT: The style-to-follow is present in the list.
+			__ASSERT_DEBUG(
+				(info.iStyleForNextPara==NULL) ||
+				((info.iStyleForNextPara) && (index!=KErrNotFound && index>=0 && index<styleCount)),User::Invariant());
+			}
+		}
+#endif
+	}
+
+
+ 
+
+EXPORT_C CStyleList* CStyleList::NewL(TInt aCapacity /*=KMaxStyleListGranularity*/)
+/** Allocates and constructs an empty CStyleList object with an array granularity.
+
+@param aCapacity The number of entries by which the array of styles expands 
+when its buffer is reallocated. By default, KMaxStyleListGranularity (= 4). 
+Must be positive or a panic occurs. 
+@return Pointer to the new style list. */
+	{
+	CStyleList* self=new(ELeave) CStyleList();
+	CleanupStack::PushL(self);
+	self->ConstructL(aCapacity);
+	CleanupStack::Pop();
+	return self;
+	}
+
+
+EXPORT_C CStyleList* CStyleList::NewL(RReadStream& aStream,
+									  const CParaFormatLayer* aGlobalParaFormatLayer,
+									  const CCharFormatLayer* aGlobalCharFormatLayer)
+/** Allocates and constructs a CStyleList, restoring its contents from the specified 
+stream store. Each style in the list is set to be based on the global format 
+layers specified.
+
+@param aStream Stream store from which the style list is restored. 
+@param aGlobalParaFormatLayer Pointer to the global paragraph format layer 
+on which all styles in the list are based. 
+@param aGlobalCharFormatLayer Pointer to the global character format layer 
+on which all styles in the list are based. 
+@return Pointer to the new style list. */
+	{
+	CStyleList* self=new(ELeave) CStyleList();
+	CleanupStack::PushL(self);
+	self->InternalizeL(aStream,aGlobalParaFormatLayer,aGlobalCharFormatLayer);
+	CleanupStack::Pop();
+	return self;
+	}
+
+
+EXPORT_C CStyleList::CStyleList()
+	{
+	}
+
+
+EXPORT_C void CStyleList::ConstructL(TInt aCount)
+// Allocate the style list.
+//
+	{
+	iList=new(ELeave) CArrayFixFlat<RParagraphStyleInfo>(aCount);
+	}
+
+
+ 
+
+EXPORT_C CStyleList::~CStyleList()
+/** Deletes all the entries in the list and the list itself. */
+	{
+	KillStyleList();
+	}
+
+
+ 
+
+EXPORT_C const RParagraphStyleInfo& CStyleList::At(TInt aIndex)const
+/** Gets a style from the style list, from its index into the array. Two versions 
+are supplied. The compiler chooses the appropriate version based on the use 
+made of the returned reference. If it is used in an expression where that 
+reference can be modified, then the non-const version is chosen.
+
+@param aIndex The index of the style into the list. The first style is at 
+position zero. Must be within the bounds of the array, or a panic occurs. 
+@return A const reference to the style at position aIndex in the array. 
+@return A non-const reference to the style at position aIndex in the array. */
+	{
+	__ASSERT_ALWAYS(iList,Panic(EStyleIntegrityError));
+	__ASSERT_DEBUG(aIndex>=0 && aIndex<iList->Count(),Panic(EStyleIndexOutOfRange));
+	
+	return (*iList)[aIndex];
+	}
+
+
+EXPORT_C RParagraphStyleInfo& CStyleList::At(TInt aIndex)
+	{
+	__ASSERT_ALWAYS(iList,Panic(EStyleIntegrityError));
+	__ASSERT_DEBUG(aIndex>=0 && aIndex<iList->Count(),Panic(EStyleIndexOutOfRange));
+
+	return (*iList)[aIndex];
+	}
+
+
+ 
+EXPORT_C void CStyleList::Reset()
+ /** Deletes the contents of the list. */
+	{
+	__TEST_INVARIANT;
+	
+	TInt styleCount=Count();
+	for (TInt nn=0;nn<styleCount;nn++)
+		delete (iList->At(nn)).iStyle;
+	if (iList)
+		iList->Reset();
+
+	__TEST_INVARIANT;
+	}
+
+
+void CStyleList::KillStyleList()
+	{
+	Reset();
+	delete iList;
+	}
+
+
+
+EXPORT_C TStreamId CStyleList::StoreL(CStreamStore& aStore)const
+/** Stores the style list to a stream store.
+
+@param aStore Stream store to which the style list is written. 
+@return The ID of the stream store. */
+	{
+	__TEST_INVARIANT;
+
+	RStoreWriteStream stream;
+	TStreamId id=stream.CreateLC(aStore);
+	//
+	stream<< *this;
+	//
+	stream.CommitL();
+	CleanupStack::PopAndDestroy();
+	return id;
+	}
+
+
+
+
+EXPORT_C void CStyleList::ExternalizeL(RWriteStream& aStream)const
+/** Externalises the style list 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. Does not externalise any styles' based-on 
+links.
+
+@param aStream Stream to which the object should be externalised. */
+	{
+	__TEST_INVARIANT;
+	
+	TInt count=Count();
+	aStream.WriteUint8L(count);
+	for (TInt mm=0;mm<count;mm++)
+		{
+		CParagraphStyle* style=(iList->At(mm)).iStyle;
+		style->ExternalizeL(aStream);
+		}
+	for (TInt nn=0;nn<count;nn++)
+		{
+		RParagraphStyleInfo set=iList->At(nn);
+		CParagraphStyle* style=set.iStyle;
+		TInt offset=(set.iStyleForNextPara!=NULL)
+			? IndexByPtr(style)
+			: -1;
+		__ASSERT_DEBUG(offset==-1 || (offset>=0 && offset<Count()),Panic(EStyleIntegrityError));
+		aStream.WriteInt8L(offset);
+		}
+	}
+
+
+
+EXPORT_C void CStyleList::InternalizeL(RReadStream& aStream,
+									   const CParaFormatLayer* aGlobalParaFormatLayer,
+									   const CCharFormatLayer* aGlobalCharFormatLayer)
+/** Internalises the style list 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. Any existing style list contents are 
+replaced.
+
+@param aStream Stream store from which the style list is internalised. 
+@param aGlobalParaFormatLayer Pointer to the global paragraph format layer 
+on which all styles in the list are based. 
+@param aGlobalCharFormatLayer Pointer to the global character format layer 
+on which all styles in the list are based. */
+	{
+	KillStyleList();
+	TInt styleCount=aStream.ReadUint8L();
+	ConstructL(Max(1,styleCount));  // panics if granularity==0
+	RParagraphStyleInfo holdingSet;
+	iList->AppendL(holdingSet,styleCount);
+	for (TInt mm=0;mm<styleCount;mm++)
+		{// restore the paragraph styles
+		CParagraphStyle* style=CParagraphStyle::NewL(aStream,*aGlobalParaFormatLayer,*aGlobalCharFormatLayer);
+		iList->At(mm).iStyle=style;
+		}
+	for (TInt nn=0;nn<styleCount;nn++)
+		{// restore the "style for next paragraph" for each paragraph
+		TInt offset=aStream.ReadInt8L();
+		iList->At(nn).iStyleForNextPara=(offset==-1)
+			? NULL
+			: iList->At(offset).iStyle;
+		}
+
+	__TEST_INVARIANT;
+	}
+
+
+
+EXPORT_C TInt CStyleList::AppendL(RParagraphStyleInfo* aStyleSet)
+/** Appends a style to the style list. The list takes ownership of the style.
+
+@param aStyleSet The style (and optional style for the following paragraph) 
+to append to the list. 
+@return KErrNone if successful, or KErrAlreadyExists if the style is already 
+present in the list. */
+	{
+	__TEST_INVARIANT;
+	
+	TInt count=Count();
+	for (TInt ii=0;ii<count;ii++)
+		{
+		if (aStyleSet->iStyle==iList->At(ii).iStyle)
+			return KErrAlreadyExists;  // we already own this style
+		}
+	CleanupStack::PushL(aStyleSet->iStyle);
+	iList->AppendL(*aStyleSet);  // if the append fails, we must take responsibility for the style
+	CleanupStack::Pop();  // aStyleSet.iStyle
+
+	__TEST_INVARIANT;
+	return KErrNone;
+	}
+
+
+EXPORT_C void CStyleList::Remove(CParagraphStyle* aStyle)
+/** Removes a style from the style list. If the style is owned by the list, it 
+is deleted. If the style is not owned by the list, but is referenced by a 
+style owned by the list, (i.e. a style in the list is based on it, or references 
+it as its iStyleForNextPara pointer) then the pointer to aStyle is set to 
+NULL.
+
+@param aStyle Pointer to the style to remove from the style list, or to set 
+to NULL. */
+	{
+	__TEST_INVARIANT;
+
+	TInt styles = Count();
+	TInt index = -1;
+	for (TInt i = 0; i < styles; i++)
+		{
+		RParagraphStyleInfo& cur_style = (*iList)[i];
+		if (cur_style.iStyleForNextPara == aStyle)
+			cur_style.iStyleForNextPara = NULL;
+		if (cur_style.iStyle->iBasedOn == aStyle)
+			cur_style.iStyle->iBasedOn = NULL;
+		if (cur_style.iStyle == aStyle)
+			{
+			// Assert that the style must occur only once in the style list.
+			__ASSERT_DEBUG(index == -1,Panic(EStyleIntegrityError));
+			index = i;
+			}
+		}
+
+	if (index != -1)
+		{
+		delete aStyle;
+		iList->Delete(index);
+		}
+	
+	__TEST_INVARIANT;
+	}
+
+
+
+EXPORT_C TInt CStyleList::SetStyleToFollow(const RParagraphStyleInfo& aStyleSet)
+/** Sets the style to use for the following paragraph for a style in the style 
+list. Both the style (aStyleSet.iStyle) and the style to set for the following 
+paragraph (aStyleSet.iStyleForNextPara) must exist in the style list.
+
+The function first locates the style (aStyleSet.iStyle) in the list, then 
+sets the style to use for the next paragraph to aStyleSet.iStyleForNextPara.
+
+If aStyleSet.iStyle does not exist in the style list, the function returns 
+with KErrNotFound. If aStyleSet.iStyleForNextPara does not exist in the style 
+list, a panic occurs.
+
+@param aStyleSet Identifies a style in the list, and a style to use for its 
+following paragraph. 
+@return KErrNone if successful, or KErrNotFound if the first style contained 
+in the argument (aStyleSet.iStyle) is not in the style list. */
+	{
+	__ASSERT_ALWAYS( IndexByPtr(aStyleSet.iStyleForNextPara) != KErrNotFound, Panic(EStyleIntegrityError) );
+	__TEST_INVARIANT;
+	
+	TInt index = IndexByPtr(aStyleSet.iStyle);
+	if (index == KErrNotFound)
+		return index;
+	
+	(*iList)[index].iStyleForNextPara = aStyleSet.iStyleForNextPara;
+	
+	__TEST_INVARIANT;
+	
+	return KErrNone;
+
+	}
+	
+
+
+
+EXPORT_C RParagraphStyleInfo* CStyleList::PtrByName(const TParagraphStyleName& aName) const
+/** Gets the style with the specified name from the style list.
+
+@param aName The name of the style to retrieve. 
+@return Pointer to the style with the name specified. NULL if there is no style 
+with this name in the list. */
+	{
+	// Return a pointer to the named style if it's in the list, or null if not.
+	__TEST_INVARIANT;
+	
+	int count = Count();
+	for (int i = 0; i < count; i++)
+		{
+		RParagraphStyleInfo& style_info = (*iList)[i];
+		if (style_info.iStyle != NULL && style_info.iStyle->iName == aName)
+			return &style_info;
+		}
+	return NULL;
+	}
+
+
+
+
+EXPORT_C RParagraphStyleInfo* CStyleList::PtrByType(const TUid aType) const
+/** Gets the style with the specified type UID from the style list.
+
+@param aType The UID of the style to retrieve. 
+@return Pointer to the style with the type UID specified. NULL if there is 
+no style with this type in the list. */
+	{
+	// Return a pointer to the first style with the specified type if any; or null if there are none with this type.
+	__TEST_INVARIANT;
+
+	int count = Count();
+	for (int i = 0; i < count; i++)
+		{
+		RParagraphStyleInfo& style_info = (*iList)[i];
+		if (style_info.iStyle != NULL && style_info.iStyle->Type() == aType)
+			return &style_info;
+		}
+	return NULL;
+	}
+
+
+
+
+EXPORT_C TInt CStyleList::IndexByPtr(const CParaFormatLayer* aPtr)const
+/** Gets the index into the style list of a specified paragraph style.
+
+@param aPtr Pointer to the style. 
+@return The style's index into the style list. KErrNotFound if the style is 
+not found in the style list, or if aPtr is a paragraph format layer rather 
+than a style. */
+	{
+	if (aPtr->Type()==KNormalParagraphStyleUid)
+		return KErrNotFound;
+	TInt count=Count();
+	if (count==0)
+		return KErrNotFound;  // ptr cannot be matched cos list is empty.
+	TInt index=0;
+	CParagraphStyle* style=NULL;
+	while (index<count)
+		{
+		style=(*iList)[index].iStyle;
+		if (style==aPtr)
+			break;
+		index++;
+		}
+	return (index<count)
+		? index
+		: KErrNotFound;
+	}
+
+
+
+
+EXPORT_C TInt CStyleList::IndexByName(const TDesC& aName)const
+/** Gets the index into the style list of a specified paragraph style, identified 
+by its name.
+
+@param aName The name of the style. 
+@return The style's index into the style list. KErrNotFound if the style name 
+is not found in the style list. */
+	{
+	TInt count=Count();
+	if (count==0)
+		return KErrNotFound;  // name cannot be in list cos its empty.
+	TInt index=0;
+	CParagraphStyle* style=NULL;
+	while (index<count)
+		{
+		style=(*iList)[index].iStyle;
+		if (style != NULL && style->iName == aName)
+			break;
+		index++;
+		}
+	return (index<count)
+		? index
+		: KErrNotFound;
+	}
+
+
+
+EXPORT_C CStyleList* CStyleList::DeepCloneL() const
+/** Creates and returns a style list which is a clone of the current style list.
+
+@return Pointer to a clone of the current style list. */
+	{
+	__TEST_INVARIANT;
+	
+	CStyleList* newList = CStyleList::NewL();
+	CleanupStack::PushL(newList);
+
+	TInt styleCount=Count();
+	for (TInt styleItem=0;styleItem<styleCount;styleItem++)
+		{
+		const RParagraphStyleInfo& source=iList->At(styleItem);
+		CParagraphStyle* style=source.iStyle->CloneL();
+		RParagraphStyleInfo info(style,source.iStyleForNextPara);
+		newList->AppendL(&info);
+		}
+
+	CleanupStack::Pop();
+	return newList;
+	}