textrendering/texthandling/stext/TXTFMLYR.CPP
changeset 0 1fb32624e06b
child 40 91ef7621b7fc
equal deleted inserted replaced
-1:000000000000 0:1fb32624e06b
       
     1 /*
       
     2 * Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <e32std.h>
       
    20 #include <e32base.h>
       
    21 #include "TXTFRMAT.H"
       
    22 #include "TXTFMLYR.H"
       
    23 #include <txtfmstm.h>
       
    24 #include "TXTSTD.H"
       
    25 
       
    26 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    27 #include "TXTFMLYR_INTERNAL.H"
       
    28 #endif
       
    29 
       
    30 CFormatLayer::CFormatLayer()
       
    31 	{
       
    32 	}
       
    33 
       
    34 
       
    35 CFormatLayer::~CFormatLayer()
       
    36 	{
       
    37 	iStore.Reset();
       
    38 	}
       
    39 
       
    40 
       
    41 DLLEXPORT_C void CFormatLayer::__DbgTestInvariant() const
       
    42 	{
       
    43 	}
       
    44 
       
    45 
       
    46  
       
    47 EXPORT_C void CFormatLayer::SetBase(const CFormatLayer* aBaseFormatLayer)
       
    48 /** Sets the format layer which this layer's based-on link points to.
       
    49 
       
    50 @param aBaseFormatLayer The format layer which this layer's based-on link 
       
    51 points to. Specify NULL if this is the final layer in the chain (the layer 
       
    52 on which all other layers are based). */
       
    53 	{
       
    54 	iBasedOn = aBaseFormatLayer;
       
    55 	}
       
    56 
       
    57 
       
    58  
       
    59 EXPORT_C const CFormatLayer* CFormatLayer::SenseBase() const
       
    60 /** Gets the format layer which this layer's based-on link points to. If NULL, 
       
    61 this layer is the final layer in the chain.
       
    62 
       
    63 @return The format layer on which this layer is based. */
       
    64 	{
       
    65 	return iBasedOn;
       
    66 	}
       
    67 
       
    68 
       
    69  
       
    70 EXPORT_C TInt CFormatLayer::ChainCount() const
       
    71 /** Gets the number of format layers in the chain, inclusive of itself. Assumes 
       
    72 that the format layer chain has been correctly set up to terminate with a 
       
    73 NULL based-on link.
       
    74 
       
    75 @return The number of format layers in the chain, counting from the current 
       
    76 layer. */
       
    77 	{
       
    78 	TInt chainCount=1;
       
    79 	const CFormatLayer* next=iBasedOn;
       
    80 	while (next)
       
    81 		{
       
    82 		++chainCount;
       
    83 		next=next->iBasedOn;
       
    84 		}
       
    85 	return chainCount;
       
    86 	}
       
    87 
       
    88 
       
    89 
       
    90 const TUint8* CFormatLayer::Ptr(TInt& aSize)const
       
    91 /** Return a pointer to the stored bytecode.*/	
       
    92     {
       
    93 	return iStore.Ptr(aSize);
       
    94 	}
       
    95 
       
    96 
       
    97 
       
    98 EXPORT_C void CFormatLayer::Reset()
       
    99 /** Deletes the contents of the format layer. The based-on link is not affected. */
       
   100 	{
       
   101 	iStore.Reset();
       
   102 	}
       
   103 
       
   104 
       
   105 
       
   106 EXPORT_C void CFormatLayer::InternalizeChainL(RReadStream& aStream,const CFormatLayer* aBase)
       
   107 /** Restores a chain of format layers from a read stream. The layer at the end 
       
   108 of the chain (the one furthest from this layer) is set to be based on the 
       
   109 specified layer aBase, which may be NULL. This layer is set to be at the head 
       
   110 of the restored chain (i.e. no other layers are based on it).
       
   111 
       
   112 @param aStream Stream from which the format layer chain should be internalised. 
       
   113 
       
   114 @param aBase The format layer at the end of the chain (furthest from this layer). 
       
   115 May be NULL. */
       
   116 	{
       
   117 	TInt chainLength=aStream.ReadInt8L();
       
   118 	if (chainLength<1)
       
   119 		User::Leave(KErrCorrupt);  // Must restore at least one layer (this), else corrupt stream.
       
   120 	TInt descendentCount=chainLength-1;
       
   121 	for (TInt loop=0;loop<descendentCount;loop++)
       
   122 		{// Restore each descendent of [this] layer.
       
   123 		CFormatLayer* layer=RestoreNewL(aStream);
       
   124 		layer->SetBase(aBase);
       
   125 		CleanupStack::PushL(layer);
       
   126 		aBase=layer;
       
   127 		}
       
   128 	aStream>> *this;
       
   129 	SetBase(aBase);
       
   130 	CleanupStack::Pop(descendentCount);
       
   131 	}
       
   132 
       
   133 
       
   134 
       
   135 
       
   136 EXPORT_C void CFormatLayer::ExternalizeChainL(RWriteStream& aStream,TInt aExcludeCount)const
       
   137 /** Stores a chain of format layers. By default an entire chain is stored unless 
       
   138 an exclude count is provided. In this case, the length of the chain stored 
       
   139 is the ChainCount() minus the exclude count. The excluded layers are the ones 
       
   140 starting with the layer with the NULL based-on link.
       
   141 
       
   142 Note
       
   143 
       
   144 The exclude count must be zero or greater but must be less than the total 
       
   145 number of layers in the chain, otherwise a panic occurs.
       
   146 
       
   147 @param aStream Stream to which the format layer chain should be externalised. 
       
   148 @param aExcludeCount The number of layers to be excluded. By default, zero. */
       
   149 	{
       
   150 // ASSERT: aExcludeCount is positive.
       
   151 	__ASSERT_ALWAYS(aExcludeCount>=0,Panic(ECannotStoreFormatLayerChain));
       
   152 // ASSERT: The number of layers to be excluded is less than the total no. of layers.
       
   153 	__ASSERT_ALWAYS(aExcludeCount<ChainCount(),Panic(ECannotStoreFormatLayerChain));
       
   154 	TInt aCount=ChainCount()-aExcludeCount;
       
   155 	aStream.WriteInt8L(aCount);  // Store the chain length.
       
   156 	ExternalizeLayersRecurseL(aStream,--aCount);
       
   157 	}	
       
   158 	
       
   159 
       
   160 void CFormatLayer::ExternalizeLayersRecurseL(RWriteStream& aStream,TInt aDescendantCount)const
       
   161 /** Stores a format layer chain with *aLength* number of layers in a stack-like 
       
   162 fashion. This necessitates navigating to the end of the chain and storing the 
       
   163 layers as we unwind back to the top of the chain.*/
       
   164 //
       
   165 	{
       
   166 	if (aDescendantCount)
       
   167 		{
       
   168 // ASSERT: The format layer chain is consistent.
       
   169 		__ASSERT_ALWAYS(iBasedOn!=NULL,Panic(ECorruptFormatLayerChain));
       
   170 		iBasedOn->ExternalizeLayersRecurseL(aStream,--aDescendantCount);
       
   171 		}
       
   172 	aStream<< *this;
       
   173 	}
       
   174 	
       
   175 /** Implementations of this function compare another format layer with the
       
   176 current object. For the two layers to be equal, they must have the same 
       
   177 contents and (if the second parameter is ETrue),their based-on links must 
       
   178 point to the same format layer.
       
   179 
       
   180 @param aLayer The layer to compare to this format layer.
       
   181 @param aCheckBasedOnLink If ETrue, both layers' based-on links must point to 
       
   182 the same format layer. If EFalse, the based-on links are not used in the 
       
   183 comparison. By default, ETrue.
       
   184 @return  ETrue if the two layers are identical, otherwise EFalse. */
       
   185 TBool CFormatLayer::IsIdentical(const TUint8* aPtr,TInt aSize) const
       
   186 	{
       
   187 	TInt size=0;
       
   188 	const TUint8* ptr=iStore.Ptr(size);
       
   189 	if ((ptr==NULL && aPtr!=NULL) || (ptr!=NULL && aPtr==NULL))
       
   190 		return EFalse;
       
   191 	if (ptr==NULL && aPtr==NULL)
       
   192 		return ETrue;
       
   193 	return (!(TBool)(Mem::Compare(ptr,size,aPtr,aSize)));
       
   194 	}
       
   195 
       
   196 /** Tests whether any formatting is stored in the format layer.
       
   197 
       
   198 @return ETrue if no formatting is stored in the format layer, otherwise returns 
       
   199 EFalse. */
       
   200 EXPORT_C TBool CFormatLayer::IsEmpty() const
       
   201 	{
       
   202 	TInt size=0;
       
   203 	return iStore.Ptr(size)==NULL;
       
   204 	}
       
   205 
       
   206 /** Swaps the contents of this with aLayer.
       
   207 @param aLayer The layer to swap contents with.
       
   208 @internalComponent */
       
   209 void CFormatLayer::Swap(CFormatLayer& aLayer)
       
   210 	{
       
   211 	iStore.Swap(aLayer.iStore);
       
   212 	const CFormatLayer* t = iBasedOn;
       
   213 	iBasedOn = aLayer.iBasedOn;
       
   214 	aLayer.iBasedOn = t;
       
   215 	}
       
   216 
       
   217 /** Allocates and constructs an empty CParaFormatLayer. Its based-on link is 
       
   218 NULL.
       
   219 
       
   220 Note: Use SetL() to set format attributes in the layer. Use SetBase(), defined 
       
   221 in the base class CFormatLayer, to set the layer's based on link.
       
   222 
       
   223 @return Pointer to the new paragraph format layer. */
       
   224 EXPORT_C CParaFormatLayer* CParaFormatLayer::NewL()
       
   225 	{
       
   226 	return new(ELeave) CParaFormatLayer;
       
   227 	}
       
   228 
       
   229 
       
   230 EXPORT_C CParaFormatLayer* CParaFormatLayer::NewL(RReadStream& aStream)
       
   231 /** Allocates and constructs a CParaFormatLayer, restoring its format attributes 
       
   232 from a stream. The layer's based-on link is set to NULL.
       
   233 
       
   234 @param aStream Stream from which the layer is restored. 
       
   235 @return Pointer to the new paragraph format layer. */
       
   236 	{
       
   237 	CParaFormatLayer* self=NewL();
       
   238 	CleanupStack::PushL(self);
       
   239 	self->InternalizeL(aStream);
       
   240 	CleanupStack::Pop();
       
   241 	return self;
       
   242 	}
       
   243 
       
   244 
       
   245 EXPORT_C CParaFormatLayer* CParaFormatLayer::NewL(const CParaFormat* aFormat,const TParaFormatMask& aMask)
       
   246 /** Allocates and constructs a CParaFormatLayer. The attributes which are set 
       
   247 in the mask are initialised to the values specified in the format container 
       
   248 aParaFormat. The attributes which are not set in the mask are initialised to 
       
   249 the default values for class CParaFormat. The new layer's based-on link is set 
       
   250 to NULL.
       
   251 
       
   252 @param aParaFormat Contains the attribute values to assign to the format layer. 
       
   253 @param aMask Mask specifying which attributes should be initialized from 
       
   254 aParaFormat. 
       
   255 @return Pointer to ParaFormatLayer the new paragraph format layer. */
       
   256 	{
       
   257 	CParaFormatLayer* self=NewL();
       
   258 	CleanupStack::PushL(self);
       
   259 	self->SetL(aFormat,aMask);
       
   260 	CleanupStack::Pop();
       
   261 	return self;
       
   262 	}
       
   263 
       
   264 
       
   265 CParaFormatLayer* CParaFormatLayer::NewL(const CParaFormatLayer* aLayer)
       
   266 /** Copying construction
       
   267  does not copy the based on link*/
       
   268 	{
       
   269 	CParaFormatLayer* self=NewL();  // based-on is NULL
       
   270 	CleanupStack::PushL(self);
       
   271 	aLayer->CloneLayerL(self);
       
   272 	CleanupStack::Pop();			// self
       
   273 	return self;
       
   274 	}
       
   275 
       
   276 CParaFormatLayer* CParaFormatLayer::NewCopyBaseL(const CParaFormatLayer* aLayer)
       
   277 /** Copying construction
       
   278  copies based-on link*/
       
   279 	{
       
   280 	CParaFormatLayer* self=NewL(aLayer);  // based-on is NULL
       
   281 	self->iBasedOn=aLayer->iBasedOn;
       
   282 	return self;
       
   283 	}
       
   284 
       
   285 CParaFormatLayer::CParaFormatLayer()
       
   286 /** Constructor.*/
       
   287 // No ConstructL method since allocation is postponed until first Set.
       
   288 //
       
   289 	{
       
   290 	}
       
   291 
       
   292 EXPORT_C void CParaFormatLayer::ExternalizeL(RWriteStream& aStream)const
       
   293 /** Externalises the paragraph format layer but not its based-on link to a 
       
   294 write stream. The presence of this function means that the standard templated 
       
   295 operator<<() (defined in s32strm.h) is available to externalise objects of 
       
   296 this class.
       
   297 
       
   298 @param aStream Stream to which the format layer should be externalised. */
       
   299 	{aStream<< iStore;}
       
   300 
       
   301 EXPORT_C void CParaFormatLayer::InternalizeL(RReadStream& aStream,const CFormatLayer* aBase)
       
   302 /** Internalises the paragraph format layer but not its based-on link from a 
       
   303 read stream. The presence of this function means that the standard templated 
       
   304 operator>>() (defined in s32strm.h) is available to internalise objects of 
       
   305 this class. The internalised layer is set to be based on the layer specified.
       
   306 
       
   307 @param aStream Stream from which the format layer should be internalised. 
       
   308 @param aBase The based-on link to assign to the layer. By default NULL. */
       
   309 	{
       
   310 	aStream>> iStore;
       
   311 	SetBase(aBase);
       
   312 	}
       
   313 
       
   314 EXPORT_C void CParaFormatLayer::SetL(const CParaFormat* aDesiredEffectiveFormat,const TParaFormatMask& aMask)
       
   315 /** Sets the layer's format attributes. The attributes which are set in the 
       
   316 mask are set in the layer to the values specified in the format container 
       
   317 aDesiredEffectiveFormat. The attributes which are not set in the mask are not 
       
   318 changed.
       
   319 
       
   320 Note: Any tab stops in aDesiredEffectiveFormat are merged with the tab stops in 
       
   321 the current layer.
       
   322 
       
   323 @param aDesiredEffectiveFormat Contains the attribute values to assign to 
       
   324 the format layer. 
       
   325 @param aMask Mask specifying which attributes should be set from 
       
   326 aDesiredEffectiveFormat. */
       
   327 	{
       
   328 	if ( !aDesiredEffectiveFormat )
       
   329 		{
       
   330 		return;
       
   331 		}
       
   332 	
       
   333 	const CParaFormat& desiredFormat = *aDesiredEffectiveFormat;
       
   334 	CParaFormat currentEffectiveFormat;
       
   335 	ResetOnCleanupL( &currentEffectiveFormat);
       
   336 	if (iBasedOn)
       
   337 		((CParaFormatLayer*)iBasedOn)->SenseEffectiveL(&currentEffectiveFormat);
       
   338 	iStore.SetParaFormatL(desiredFormat,aMask,currentEffectiveFormat);
       
   339 	CleanupStack::Pop();
       
   340 	}
       
   341 
       
   342 EXPORT_C void CParaFormatLayer::SenseEffectiveL(CParaFormat* aParaFormat,CParaFormat::TParaFormatGetMode aMode)const
       
   343 /** Senses the layer's effective format, searching all based-on links. The 
       
   344 resulting aParaFormat is fully populated, except that if aMode is 
       
   345 EFixedAttributes, then only the fixed attributes (not tabs, paragraph borders 
       
   346 or bullets) are written to it.
       
   347 
       
   348 Notes:
       
   349 
       
   350 The function also "tidies up" the layer's effective paragraph formatting, 
       
   351 so that any zero height bullets, paragraph borders with a NULL line style 
       
   352 or NULL tab stops are removed. 
       
   353 
       
   354 The function can only leave if aMode has a value of EAllAttributes.
       
   355 
       
   356 @param aParaFormat On return, contains the layer's effective formatting. 
       
   357 Depending on the value of aMode, tabs, borders and bullets may be excluded. 
       
   358 Must not be NULL or a panic occurs. 
       
   359 @param aMode Controls which attributes are written to aParaFormat. If 
       
   360 EAllAttributes, all attributes are written; if EFixedAttributes, tabs, 
       
   361 bullets and borders are not written. */
       
   362 	{
       
   363 	__ASSERT_ALWAYS(aParaFormat!=NULL,Panic(ENullFormatPointer));
       
   364 	aParaFormat->Reset();
       
   365 	TParaFormatMask mask;
       
   366 	FillParaFormatL(aParaFormat,mask,aMode);
       
   367 	CleanupEffectiveFormat(aParaFormat,mask);
       
   368 	}
       
   369 
       
   370 EXPORT_C void CParaFormatLayer::SenseL(CParaFormat* aParaFormat,TParaFormatMask& aMask,CParaFormat::TParaFormatGetMode aMode)const
       
   371 /** Senses the formatting which has been applied to the current layer only. No 
       
   372 based-on links are searched. This function does not get the effective formatting, 
       
   373 but the resulting aParaFormat is useable even if not all attributes are flagged 
       
   374 for sensing in aMask because any attribute values not sensed from the current 
       
   375 layer, are set to default values.
       
   376 
       
   377 The function can only leave if aMode has a value of EAllAttributes.
       
   378 
       
   379 @param aParaFormat On return, contains the formatting which has been applied 
       
   380 to the current layer only. Any attributes not explicitly set in the current 
       
   381 layer are initialised to the default values for a CParaFormat. Attributes 
       
   382 specified in aMask are not sensed from this layer. The values for these 
       
   383 attributes are also initialised to the default settings. Must not be NULL or 
       
   384 a panic occurs. 
       
   385 @param aMask A bitmask. Any attributes which are set in the mask as passed 
       
   386 into the function are not sensed from the current layer. On return, indicates 
       
   387 the attributes which were sensed from this layer. So, normally, when passed 
       
   388 to the function, all attributes in the mask should be unset. 
       
   389 @param aMode Controls which attributes are written to aParaFormat. If 
       
   390 EAllAttributes, all attributes are written; if EFixedAttributes, tabs, bullets 
       
   391 and borders are not written. */
       
   392 	{
       
   393 	__ASSERT_ALWAYS(aParaFormat!=NULL,Panic(ENullFormatPointer));
       
   394 
       
   395 	iStore.SenseParaFormatL(*aParaFormat,aMask,aMode);
       
   396 	}
       
   397 
       
   398 
       
   399 void CFormatLayer::CloneLayerL(CFormatLayer* aClone)const
       
   400 	{
       
   401 	aClone->iStore.CopyL(iStore);
       
   402 	}
       
   403 
       
   404 
       
   405 EXPORT_C CFormatLayer* CParaFormatLayer::DoCloneL()const
       
   406 //
       
   407 //
       
   408 	{
       
   409 	return NewL(this);  // use copy construction
       
   410 	}
       
   411 
       
   412 
       
   413 
       
   414 EXPORT_C TBool CParaFormatLayer::IsIdenticalL(const CParaFormat* aParaFormat,const TParaFormatMask& aMask)const
       
   415 /** Compares a format attribute container with the current layer. For the two 
       
   416 objects to be identical, the current layer must contain only the attributes 
       
   417 specified in the argument aMask, and these attributes must have the same values 
       
   418 as those in aParaFormat. None of the current layer's based-on links are searched.
       
   419 
       
   420 @param aParaFormat Contains the attribute values used in the comparison. 
       
   421 @param aMask A bitmask specifying which attributes are relevant to the function. 
       
   422 
       
   423 @return ETrue if the formatting of the current layer exactly matches that 
       
   424 contained in aParaFormat. Otherwise EFalse. */
       
   425 	{
       
   426 	CParaFormat* thisParaFormat=CParaFormat::NewLC();
       
   427 	TParaFormatMask thisParaFormatMask;
       
   428 	SenseL(thisParaFormat,thisParaFormatMask);
       
   429 	TBool result=EFalse;
       
   430 	if (thisParaFormatMask!=aMask)
       
   431 		result=EFalse;
       
   432 	else if (thisParaFormat->IsEqual(*aParaFormat,aMask))
       
   433 		result=ETrue;
       
   434 	CleanupStack::PopAndDestroy();
       
   435 	return result;
       
   436 	}
       
   437 
       
   438 EXPORT_C TBool CParaFormatLayer::IsIdentical(CFormatLayer* aLayer,TBool aCheckBasedOnLink)const
       
   439 /** Compares another paragraph format layer with the current layer. For the two 
       
   440 layers to be equal, they must have the same contents and (if the second 
       
   441 parameter is ETrue), their based-on links must point to the same format layer.
       
   442 
       
   443 @param aLayer The paragraph format layer to compare to this format layer. 
       
   444 @param aCheckBasedOnLink If ETrue, both layers' based-on links must point to 
       
   445 the same format layer. If EFalse, the based-on links are not used in the 
       
   446 comparison. By default, ETrue. 
       
   447 @return ETrue if the two layers are identical, otherwise EFalse. */
       
   448 	{
       
   449 	if (aCheckBasedOnLink)
       
   450 		{
       
   451 		if (iBasedOn!=aLayer->SenseBase())
       
   452 			return EFalse;
       
   453 		}
       
   454 	TInt size;
       
   455 	const TUint8* ptr=((CParaFormatLayer*)aLayer)->Ptr(size);		// some design went wrong here!
       
   456 	return CFormatLayer::IsIdentical(ptr,size);
       
   457 	}
       
   458 
       
   459 EXPORT_C const TUint8* CParaFormatLayer::Ptr(TInt& aSize)const
       
   460 /** Gets a pointer to the start of the buffer containing the layer's format 
       
   461 attribute values.
       
   462 
       
   463 @param aSize On return, set to the size of the buffer. 
       
   464 @return Pointer to the buffer which contains the layer's format attribute 
       
   465 values. */
       
   466 	{return CFormatLayer::Ptr(aSize);}
       
   467 
       
   468 EXPORT_C TUid CParaFormatLayer::Type()const
       
   469 /** Returns the paragraph format layer UID. This can be used to distinguish 
       
   470 between an ordinary paragraph format layer and paragraph styles, which have a 
       
   471 different UID.
       
   472 
       
   473 @return The UID of a paragraph format layer (KNormalParagraphStyleUid). */
       
   474 	{return KNormalParagraphStyleUid;}
       
   475 
       
   476 CFormatLayer* CParaFormatLayer::RestoreNewL(RReadStream& aStream)
       
   477 /** Return a new CParaFormatLayer, having restored it from aStream.
       
   478  Overrides the base class method, to provide a new format layer of the correct 
       
   479  type.*/
       
   480 	{return NewL(aStream);}
       
   481 
       
   482 void CParaFormatLayer::FillParaFormatL(CParaFormat* aParaFormat,TParaFormatMask& aMask,CParaFormat::TParaFormatGetMode aMode)const
       
   483 /** Fills aParaFormat by dumping the current format layer into it.  
       
   484 Next traverse the 'basedOn' link if it is not NULL, and repeat.*/
       
   485 	{
       
   486 	if ( !aParaFormat )
       
   487 		{
       
   488 		return;
       
   489 		}
       
   490 	
       
   491 	CParaFormat& senseFormat = *aParaFormat;
       
   492 
       
   493 	iStore.SenseParaFormatL(senseFormat,aMask,aMode);
       
   494 	if (iBasedOn)
       
   495 		((CParaFormatLayer*)iBasedOn)->FillParaFormatL(aParaFormat,aMask,aMode);
       
   496 	}
       
   497 
       
   498 void CParaFormatLayer::CleanupEffectiveFormat(CParaFormat* aParaFormat,TParaFormatMask aMask)const
       
   499 /** Removes anti-tabs, zero height and null bullets, and paragraph borders with
       
   500  null linestyles, from aParaFormat.  An effective format does not support the
       
   501  notion of anti-tabs etc.*/
       
   502 	{
       
   503 	if (aMask.AttribIsSet(EAttBullet))
       
   504 		{
       
   505 		if (aParaFormat->iBullet->iStyle == TBullet::ENullStyle || aParaFormat->iBullet->iHeightInTwips <= 0)
       
   506 			{
       
   507 			delete aParaFormat->iBullet;
       
   508 			aParaFormat->iBullet = NULL;
       
   509 			}
       
   510 		}
       
   511 
       
   512 	if (aMask.AttribIsSet(EAttTopBorder) ||
       
   513 		aMask.AttribIsSet(EAttBottomBorder) ||
       
   514 		aMask.AttribIsSet(EAttLeftBorder) ||
       
   515 		aMask.AttribIsSet(EAttRightBorder))
       
   516 		CleanupBorders(aParaFormat);
       
   517 
       
   518 	if (aMask.AttribIsSet(EAttTabStop))
       
   519 		{
       
   520 		int index = 0;
       
   521 		while (index < aParaFormat->TabCount())
       
   522 			{
       
   523 			TTabStop tab = aParaFormat->TabStop(index);
       
   524 			if (tab.iType == TTabStop::ENullTab)
       
   525 				aParaFormat->RemoveTab(tab.iTwipsPosition);
       
   526 			else
       
   527 				index++;
       
   528 			}
       
   529 		}
       
   530 	}
       
   531 
       
   532 
       
   533 void CParaFormatLayer::CleanupBorders(CParaFormat* aParaFormat)const
       
   534 /** Destroys the paragraph border if it is of NULL linestyle,
       
   535  and nulls the pointer to it (aBorder).*/
       
   536 	{
       
   537 	if (aParaFormat->ParaBorder(CParaFormat::EParaBorderTop).iLineStyle==TParaBorder::ENullLineStyle &&
       
   538 		aParaFormat->ParaBorder(CParaFormat::EParaBorderBottom).iLineStyle==TParaBorder::ENullLineStyle &&
       
   539 		aParaFormat->ParaBorder(CParaFormat::EParaBorderLeft).iLineStyle==TParaBorder::ENullLineStyle &&
       
   540 		aParaFormat->ParaBorder(CParaFormat::EParaBorderRight).iLineStyle==TParaBorder::ENullLineStyle)
       
   541 		{
       
   542 		aParaFormat->RemoveAllBorders();
       
   543 		}
       
   544 	}
       
   545 
       
   546 
       
   547 EXPORT_C CCharFormatLayer* CCharFormatLayer::NewL()
       
   548 /** Allocates and constructs an empty CCharFormatLayer. Its based-on link is 
       
   549 NULL.
       
   550 
       
   551 Note: Use SetL() to set format attributes in the layer. Use SetBase(), defined 
       
   552 in the base class CFormatLayer, to set the layers based on link.
       
   553 
       
   554 @return Pointer to the new character format layer. */
       
   555 	{return new(ELeave)CCharFormatLayer;}
       
   556 
       
   557 
       
   558 
       
   559 EXPORT_C CCharFormatLayer* CCharFormatLayer::NewL(RReadStream& aStream)
       
   560 /** Allocates and constructs a CCharFormatLayer, restoring its format attributes 
       
   561 from a stream. The layer's based-on link is set to NULL.
       
   562 
       
   563 @param aStream Stream from which the layer is restored. 
       
   564 @return Pointer to the new character format layer. */
       
   565 	{
       
   566 	CCharFormatLayer* self=NewL();
       
   567 	CleanupStack::PushL(self);
       
   568 	self->InternalizeL(aStream);
       
   569 	CleanupStack::Pop();
       
   570 	return self;
       
   571 	}
       
   572 
       
   573 
       
   574 EXPORT_C CCharFormatLayer* CCharFormatLayer::NewL(const TCharFormat& aFormat,const TCharFormatMask& aMask)
       
   575 /** Returns a handle to a new charFormatLayer, after constructing
       
   576  it and setting it with the specified format and format mask.*/
       
   577 	{
       
   578 	CCharFormatLayer* self=NewL();
       
   579 	CleanupStack::PushL(self);
       
   580 	self->SetL(aFormat,aMask);
       
   581 	CleanupStack::Pop();
       
   582 	return self;
       
   583 	}
       
   584 
       
   585 
       
   586 CCharFormatLayer* CCharFormatLayer::NewL(const TCharFormatX& aFormat,const TCharFormatXMask& aMask)
       
   587 	{
       
   588 	CCharFormatLayer* self = NewL();
       
   589 	CleanupStack::PushL(self);
       
   590 	self->SetL(aFormat,aMask);
       
   591 	CleanupStack::Pop();
       
   592 	return self;
       
   593 	}
       
   594 
       
   595 
       
   596 CCharFormatLayer* CCharFormatLayer::NewL(const CCharFormatLayer* aLayer)
       
   597 /** Copying construction
       
   598  does not copy based-on link.*/
       
   599 	{
       
   600 	CCharFormatLayer* self=NewL();  // based-on is NULL
       
   601 	CleanupStack::PushL(self);
       
   602 	aLayer->CloneLayerL(self);
       
   603 	CleanupStack::Pop();			// self
       
   604 	return self;
       
   605 	}
       
   606 
       
   607 CCharFormatLayer* CCharFormatLayer::NewCopyBaseL(const CCharFormatLayer* aLayer)
       
   608 /** Copying construction
       
   609  copies based-on link*/
       
   610 	{
       
   611 	CCharFormatLayer* self=NewL(aLayer);  // based-on is NULL
       
   612 	self->iBasedOn=aLayer->iBasedOn;
       
   613 	return self;
       
   614 	}
       
   615 
       
   616 
       
   617 CCharFormatLayer::CCharFormatLayer()
       
   618 	{
       
   619 	}
       
   620 
       
   621 EXPORT_C void CCharFormatLayer::ExternalizeL(RWriteStream& aStream)const
       
   622 /** Externalises the character format layer but not its based-on link to a 
       
   623 write stream. The presence of this function means that the standard templated 
       
   624 operator<<() (defined in s32strm.h) is available to externalise objects of 
       
   625 this class.
       
   626 
       
   627 @param aStream Stream to which the format layer should be externalised. */
       
   628 	{
       
   629 	aStream << iStore;
       
   630 	}
       
   631 
       
   632 EXPORT_C void CCharFormatLayer::InternalizeL(RReadStream& aStream,const CFormatLayer* aBase)
       
   633 /** Internalises the character format layer but not its based-on link from a 
       
   634 read stream. The presence of this function means that the standard templated 
       
   635 operator>>() (defined in s32strm.h) is available to internalise objects of 
       
   636 this class. The internalised layer is set to be based on the layer specified.
       
   637 
       
   638 @param aStream Stream from which the format layer should be internalised. 
       
   639 @param aBase The based-on link to assign to the layer. By default NULL. */
       
   640 	{
       
   641 	aStream >> iStore;
       
   642 	SetBase(aBase);
       
   643 	}
       
   644 
       
   645 
       
   646 EXPORT_C const TUint8* CCharFormatLayer::Ptr(TInt& aSize)const
       
   647 /** Gets a pointer to the start of the buffer containing the layer's format 
       
   648 attribute values.
       
   649 
       
   650 @param aSize On return, set to the size of the buffer. 
       
   651 @return Pointer to the buffer which contains the layer's format attribute 
       
   652 values. */
       
   653 	{
       
   654 	return CFormatLayer::Ptr(aSize);
       
   655 	}
       
   656 
       
   657 EXPORT_C void CCharFormatLayer::SetL(const TCharFormat& aCharFormat,const TCharFormatMask& aMask)
       
   658 /** Sets the layer's format attributes. The attributes which are set in the 
       
   659 mask are set in the layer to the values specified in the format container 
       
   660 aCharFormat. The attributes which are not set in the mask are not changed.
       
   661 
       
   662 @param aCharFormat Contains the attribute values to assign to the format layer. 
       
   663 @param aMask Mask specifying which attributes should be set from aCharFormat. */
       
   664 	{
       
   665 	TCharFormatX format(aCharFormat);
       
   666 	iStore.SetCharFormatL(format,aMask);
       
   667 	}
       
   668 
       
   669 void CCharFormatLayer::SetL(const TCharFormatX& aCharFormat,const TCharFormatXMask& aMask)
       
   670 /** Sets the layer's format attributes. The attributes which are set in the 
       
   671 mask are set in the layer to the values specified in the format container 
       
   672 aCharFormat. The attributes which are not set in the mask are not changed.
       
   673 
       
   674 @param aCharFormat Contains the attribute values to assign to the format layer. 
       
   675 @param aMask Mask specifying which attributes should be set from aCharFormat. */
       
   676 	{
       
   677 	iStore.SetCharFormatL(aCharFormat,aMask);
       
   678 	}
       
   679 
       
   680 EXPORT_C void CCharFormatLayer::SenseEffective(TCharFormat& aCharFormat)const
       
   681 /** Senses the layer's effective format, searching all based-on links. The 
       
   682 resulting aCharFormat is fully populated.
       
   683 
       
   684 @param aCharFormat On return, contains the layer's effective formatting. */
       
   685 	{
       
   686 	TCharFormatX format;
       
   687 	TCharFormatXMask mask;
       
   688 	FillCharFormat(format,mask);
       
   689 	aCharFormat = format.iCharFormat;
       
   690 	}
       
   691 
       
   692 void CCharFormatLayer::SenseEffective(TCharFormatX& aCharFormat) const
       
   693 /** Senses the layer's effective format, searching all based-on links. The 
       
   694 resulting aCharFormat is fully populated.
       
   695 
       
   696 @param aCharFormat On return, contains the layer's effective formatting. */
       
   697 	{
       
   698 	TCharFormatXMask mask;
       
   699 	aCharFormat = TCharFormatX(); // initialise character format; FillCharFormat doesn't do this
       
   700 	FillCharFormat(aCharFormat,mask);
       
   701 	}
       
   702 
       
   703 EXPORT_C void CCharFormatLayer::Sense(TCharFormat& aCharFormat,TCharFormatMask& aMask)const
       
   704 /** Senses the formatting which has been applied to the current layer only. No 
       
   705 based-on links are searched. This function does not get the layer's effective 
       
   706 formatting, but the resulting aCharFormat is fully populated, even if not 
       
   707 all attributes are flagged for sensing in aMask because any attribute values 
       
   708 not sensed from the current layer are set to default values.
       
   709 
       
   710 @param aCharFormat On return, contains the formatting which has been applied 
       
   711 to the current layer only. Any attributes not explicitly set in the current 
       
   712 layer are set to the default values for a TCharFormat. Any attributes specified 
       
   713 in aMask are not sensed from this layer. The values for these attributes are 
       
   714 also initialised to the default settings. 
       
   715 @param aMask A bitmask. Any attributes which are set in the mask as passed 
       
   716 into the function are not sensed from the current layer. On return, indicates 
       
   717 the attributes which were sensed from this layer. So, normally, when passed 
       
   718 to the function, all attributes in the mask should be unset. */
       
   719 	{
       
   720 	TCharFormatX format(aCharFormat);
       
   721 	TCharFormatXMask mask = aMask;
       
   722 	iStore.SenseCharFormat(format,mask);
       
   723 	aCharFormat = format.iCharFormat;
       
   724 	mask.ClearExtendedAttribs();
       
   725 	aMask = mask;
       
   726 	}
       
   727 
       
   728 void CCharFormatLayer::Sense(TCharFormatX& aCharFormat,TCharFormatXMask& aMask) const
       
   729 /** Senses the formatting which has been applied to the current layer only. No 
       
   730 based-on links are searched. This function does not get the layer's effective 
       
   731 formatting, but the resulting aCharFormat is fully populated, even if not 
       
   732 all attributes are flagged for sensing in aMask because any attribute values 
       
   733 not sensed from the current layer are set to default values.
       
   734 
       
   735 @param aCharFormat On return, contains the formatting which has been applied 
       
   736 to the current layer only. Any attributes not explicitly set in the current 
       
   737 layer are set to the default values for a TCharFormat. Any attributes specified 
       
   738 in aMask are not sensed from this layer. The values for these attributes are 
       
   739 also initialised to the default settings. 
       
   740 @param aMask A bitmask. Any attributes which are set in the mask as passed 
       
   741 into the function are not sensed from the current layer. On return, indicates 
       
   742 the attributes which were sensed from this layer. So, normally, when passed 
       
   743 to the function, all attributes in the mask should be unset. */
       
   744 	{
       
   745 	iStore.SenseCharFormat(aCharFormat,aMask);
       
   746 	}
       
   747 
       
   748 
       
   749 EXPORT_C CFormatLayer* CCharFormatLayer::DoCloneL()const
       
   750 	{
       
   751 	return NewL(this);  // use copy construction
       
   752 	}
       
   753 
       
   754 
       
   755 EXPORT_C TBool CCharFormatLayer::IsIdentical(CFormatLayer* aLayer,TBool aCheckBasedOnLink)const
       
   756 /** Compares another character format layer with the current layer. For the two 
       
   757 layers to be equal, they must have the same contents and (if the second 
       
   758 parameter is ETrue), their based-on links must point to the same format layer.
       
   759 
       
   760 @param aLayer The character format layer to compare to this format layer. 
       
   761 @param aCheckBasedOnLink If ETrue, both layers' based-on links must point to 
       
   762 the same format layer. If EFalse, the based-on links are not used in the 
       
   763 comparison. By default, ETrue. 
       
   764 @return ETrue if the two layers are identical, otherwise EFalse. */
       
   765 	{
       
   766 	if (aCheckBasedOnLink)
       
   767 		{
       
   768 		if (iBasedOn!=aLayer->SenseBase())
       
   769 			return EFalse;
       
   770 		}
       
   771 	TInt size;
       
   772 	const TUint8* ptr=((CCharFormatLayer*)aLayer)->Ptr(size);		// some naff design at work here!
       
   773 	return CFormatLayer::IsIdentical(ptr,size);
       
   774 	}
       
   775 
       
   776 EXPORT_C TBool CCharFormatLayer::IsIdentical(const TCharFormat& aCharFormat,const TCharFormatMask& aMask)const
       
   777 /** Compares a format attribute container with the current layer. For the two 
       
   778 objects to be identical, the current layer must contain only the attributes 
       
   779 specified in the argument aMask, and these attributes must have the same 
       
   780 values as those in aCharFormat. None of the current layer's based-on links are 
       
   781 searched.
       
   782 
       
   783 @param aCharFormat Contains the attribute values used in the comparison. 
       
   784 @param aMask A bitmask specifying which attributes are relevant to the function. 
       
   785 
       
   786 @return ETrue if the formatting of the current layer exactly matches that 
       
   787 contained in aCharFormat, otherwise EFalse. */
       
   788 	{
       
   789 	TCharFormat thisCharFormat;
       
   790 	TCharFormatMask thisCharFormatMask;
       
   791 	Sense(thisCharFormat,thisCharFormatMask);
       
   792 	if (thisCharFormatMask!=aMask)
       
   793 		return EFalse;
       
   794 	return thisCharFormat.IsEqual(aCharFormat,aMask);
       
   795 	}
       
   796 
       
   797 
       
   798 CFormatLayer* CCharFormatLayer::RestoreNewL(RReadStream& aStream)
       
   799 /** Return a new CCharFormatLayer, having restored it from aStream.
       
   800 Overrides the base class method, to provide a new format layer of 
       
   801 the correct type.*/
       
   802 	{return CCharFormatLayer::NewL(aStream);}
       
   803 
       
   804 
       
   805 void CCharFormatLayer::FillCharFormat(TCharFormatX& aCharFormat,TCharFormatXMask& aMask)const
       
   806 /** Fills aCharFormat by dumping the current format layer into it, then follows 
       
   807 each 'BasedOn' link in turn if it is not null.  It is assumed that all based on 
       
   808 links eventually terminate with nulls.*/
       
   809 	{
       
   810 	iStore.SenseCharFormat(aCharFormat,aMask);
       
   811 	if (iBasedOn)
       
   812 		((CCharFormatLayer*)iBasedOn)->FillCharFormat(aCharFormat,aMask);
       
   813 	}