textrendering/texthandling/stext/TXTFMSTM.CPP
changeset 0 1fb32624e06b
child 40 91ef7621b7fc
equal deleted inserted replaced
-1:000000000000 0:1fb32624e06b
       
     1 /*
       
     2 * Copyright (c) 1997-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 
       
    21 #include <s32strm.h>
       
    22 #include <s32mem.h>
       
    23 #include "TXTFRMAT.H"
       
    24 #include <txtfmstm.h>
       
    25 
       
    26 #include "TXTSTD.H"
       
    27 
       
    28 const TInt KMaxFormatStreamLength=0x400;  // 1024 bytes
       
    29 
       
    30 // Standard attributes
       
    31 const TUint KFontProportional=0x01;
       
    32 const TUint KFontSerif=0x02;
       
    33 const TUint KFontSymbol=0x04;
       
    34 
       
    35 const TUint KTypefaceFlags=sizeof(TUint8);
       
    36 const TInt KTypeSize=sizeof(TUint8);
       
    37 const TInt KColor=sizeof(TUint8)+sizeof(TUint8)+sizeof(TUint8);
       
    38 const TInt KFontHeight=sizeof(TInt32);
       
    39 const TInt KParaBorderThickness=sizeof(TInt32);
       
    40 const TInt KTabPosition=sizeof(TUint32);
       
    41 const TInt KTabType=sizeof(TUint8);
       
    42 
       
    43 // Paragraph format attributes
       
    44 const TInt KVariableLengthAttribute=0;
       
    45 const TInt KParaLanguage=sizeof(TUint8);
       
    46 const TInt KParaFillColor=KColor;
       
    47 const TInt KParaLeftMargin=sizeof(TInt32);
       
    48 const TInt KParaRightMargin=sizeof(TInt32);
       
    49 const TInt KParaIndent=sizeof(TInt32);
       
    50 const TInt KParaAlignment=sizeof(TUint8);
       
    51 const TInt KParaVerticalAlignment=sizeof(TUint8);
       
    52 const TInt KParaLineSpacing=sizeof(TInt32);
       
    53 const TInt KParaLineSpacingControl=sizeof(TUint8);
       
    54 const TInt KParaSpaceBefore=sizeof(TInt32);
       
    55 const TInt KParaSpaceAfter=sizeof(TInt32);
       
    56 const TInt KParaKeepTogether=sizeof(TUint8);
       
    57 const TInt KParaKeepWithNext=sizeof(TUint8);
       
    58 const TInt KParaStartNewPage=sizeof(TUint8);
       
    59 const TInt KParaWidowOrphan=sizeof(TUint8);
       
    60 const TInt KParaWrap=sizeof(TUint8);
       
    61 const TInt KParaBorderMargin=sizeof(TInt32);
       
    62 const TInt KParaTopBorder=sizeof(TUint8)+KParaBorderThickness+KColor+sizeof(TUint8);//linestyle/thickness/color/autocolor
       
    63 const TInt KParaBottomBorder=KParaTopBorder;
       
    64 const TInt KParaLeftBorder=KParaTopBorder;
       
    65 const TInt KParaRightBorder=KParaTopBorder;
       
    66 const TInt KParaBullet=KVariableLengthAttribute;
       
    67 const TInt KParaDefaultTabWidth=sizeof(TUint32);
       
    68 const TInt KParaTabStop=KTabPosition+KTabType;
       
    69 const TInt KParaFillSystemColor=sizeof(TUint8);
       
    70 const TInt KParaBulletSystemColor=sizeof(TUint8);
       
    71 const TInt KParaTopBorderSystemColor=sizeof(TUint8);
       
    72 const TInt KParaBottomBorderSystemColor=sizeof(TUint8);
       
    73 const TInt KParaLeftBorderSystemColor=sizeof(TUint8);
       
    74 const TInt KParaRightBorderSystemColor=sizeof(TUint8);
       
    75 const TInt KParaLanguageX=sizeof(TInt32);
       
    76 const TInt KParaBulletX=sizeof(TInt32) + 2;
       
    77 const TInt KBitmapType=sizeof(TUint8);
       
    78 
       
    79 // Character format attributes
       
    80 const TInt KCharLanguage=sizeof(TUint8);
       
    81 const TInt KCharColor=KColor;
       
    82 const TInt KCharHighlightColor=KColor;
       
    83 const TInt KCharHighlightStyle=sizeof(TUint8);
       
    84 const TInt KCharStrikethrough=sizeof(TUint8);
       
    85 const TInt KCharUnderline=sizeof(TUint8);
       
    86 const TInt KCharStrokeWeight=sizeof(TUint8);
       
    87 const TInt KCharPosture=sizeof(TUint8);
       
    88 const TInt KCharPrintPos=sizeof(TUint8);
       
    89 const TInt KCharFontHeight=KFontHeight;
       
    90 const TInt KCharTypeface=KVariableLengthAttribute;
       
    91 const TInt KCharHiddenText=sizeof(TUint8);
       
    92 const TInt KCharPictureAlignment=sizeof(TUint8);
       
    93 const TInt KCharTextSystemColor=sizeof(TUint8);
       
    94 const TInt KCharFontHighlightSystemColor=sizeof(TUint8);
       
    95 const TInt KCharLanguageX=sizeof(TInt32);
       
    96 const TInt KCharParserTag=sizeof(TUint32);
       
    97 
       
    98 /*
       
    99 Lookup table indexed by TTextFormatAttribute enumerated constants.
       
   100 Specifies the length in bytes of the format attributes.
       
   101 */
       
   102 static const TInt8 TheAttributeLength[EAttributeCount] =
       
   103 	{
       
   104 	// Paragraph attribute value lengths.	
       
   105 	KParaLanguage,
       
   106 	KParaFillColor,
       
   107 	KParaLeftMargin,
       
   108 	KParaRightMargin,
       
   109 	KParaIndent,
       
   110 	KParaAlignment,
       
   111 	KParaVerticalAlignment,
       
   112 	KParaLineSpacing,
       
   113 	KParaLineSpacingControl,
       
   114 	KParaSpaceBefore,
       
   115 	KParaSpaceAfter,
       
   116 	KParaKeepTogether,
       
   117 	KParaKeepWithNext,
       
   118 	KParaStartNewPage,
       
   119 	KParaWidowOrphan,
       
   120 	KParaWrap,
       
   121 	KParaBorderMargin,
       
   122 	KParaTopBorder,
       
   123 	KParaBottomBorder,
       
   124 	KParaLeftBorder,
       
   125 	KParaRightBorder,
       
   126 	KParaBullet,
       
   127 	KParaDefaultTabWidth,
       
   128 	KParaTabStop,
       
   129 
       
   130 	// Character attribute value lengths.
       
   131 	KCharLanguage,
       
   132 	KCharColor,
       
   133 	KCharHighlightColor,
       
   134 	KCharHighlightStyle,
       
   135 	KCharFontHeight,
       
   136 	KCharStrikethrough,
       
   137 	KCharUnderline,
       
   138 	KCharStrokeWeight,
       
   139 	KCharPosture,
       
   140 	KCharPrintPos,
       
   141 	KCharTypeface,
       
   142 	KCharHiddenText,
       
   143 	KCharPictureAlignment,
       
   144 
       
   145 	// Lengths of extended attributes.
       
   146 	KParaFillSystemColor,
       
   147 	KParaBulletSystemColor,
       
   148 	KParaTopBorderSystemColor,
       
   149 	KParaBottomBorderSystemColor,
       
   150 	KParaLeftBorderSystemColor,
       
   151 	KParaRightBorderSystemColor,
       
   152 	KCharTextSystemColor,
       
   153 	KCharFontHighlightSystemColor,
       
   154 	KParaLanguageX,
       
   155 	KCharLanguageX,
       
   156 	KParaBulletX,
       
   157     KBitmapType,
       
   158 
       
   159 	// Lengths of internal attributes
       
   160 	KCharParserTag
       
   161 	};
       
   162 
       
   163 
       
   164 DLLEXPORT_C void RFormatStream::__DbgTestInvariant()const
       
   165 // Provides class invariants.
       
   166 // This class invariant checks the integrity of a completed format stream.
       
   167 // As such, this invariant is only called by those methods that act upon a completed
       
   168 // format stream; that is, not the set methods, since the format stream will not be complete until
       
   169 // this call has completed.
       
   170 //
       
   171 	{
       
   172 #ifdef _DEBUG
       
   173 		__ASSERT_DEBUG(DoInvariantCheck(),User::Invariant());
       
   174 #endif
       
   175 	}
       
   176 
       
   177 void RFormatStream::TestInvariantL()const
       
   178 // Provides class invariants.
       
   179 // This class invariant checks the integrity of a completed format stream.
       
   180 // As such, this invariant is only called by those methods that act upon a completed
       
   181 // format stream; that is, not the set methods, since the format stream will not be complete until
       
   182 // this call has completed.
       
   183 //
       
   184 	{
       
   185 	if (!DoInvariantCheck())
       
   186 		User::Leave(KErrCorrupt);
       
   187 	}
       
   188 
       
   189 TBool RFormatStream::DoInvariantCheck() const
       
   190 // Provides class invariants.
       
   191 // This class invariant checks the integrity of a completed format stream.
       
   192 // As such, this invariant is only called by those methods that act upon a completed
       
   193 // format stream; that is, not the set methods, since the format stream will not be complete until
       
   194 // this call has completed.
       
   195 //
       
   196 	{
       
   197 	if (!iBase)
       
   198 		return ETrue;
       
   199 	if (iEnd>iBase)
       
   200 		{// Assert: stream is self consistent
       
   201 		// Walks through the stream (aBuffer), checking that it is in a consistent state.
       
   202 		// (1) All entries in the buffer conform to a TYPE-VALUE structure, checking that
       
   203 		// types do not occur in contiguous bytes.  ie there is a value.
       
   204 		// (2) Checks that all encountered types are valid types.
       
   205 		// (3) Checks that the buffer has not changed size as a result of this check
       
   206 		// (4) Checks that all attributes in the stream occur only once.  Done by taking a register
       
   207 		// as each attribute is read from the stream.  (The exception to this rule are Tab identifiers
       
   208 		// which, if present, will typically occur several times in the stream).
       
   209 		//
       
   210 		enum {ENotPresent,EPresent};
       
   211 		TInt8 attributeRegister[EAttributeCount];
       
   212 		for (TInt offset=0;offset<EAttributeCount;offset++)
       
   213 			{// Mark attributeRegister as all absent
       
   214 			attributeRegister[offset]=(TInt8)ENotPresent;  // clear all items in the register
       
   215 			}
       
   216 		TUint8* tempStreamLoc=iBase;
       
   217 		TUint8* streamLoc=iBase;
       
   218 		TUint8* endOfStreamLoc=iEnd;
       
   219 		TUint8 data=0;
       
   220 		while (streamLoc<endOfStreamLoc)
       
   221 			{
       
   222 			data=*streamLoc;
       
   223 			streamLoc++;
       
   224 // Assert: data read is a valid format attribute type.
       
   225 			if (!(data<((TUint8)EAttributeCount))) return EFalse;
       
   226 			if (data!=EAttTabStop)
       
   227 				{// Tab Identifiers can occur multiple times in a stream!!
       
   228 // Assert: attribute type does not already exist in attributeRegister.
       
   229 				if (!(attributeRegister[data]!=(TInt8)EPresent)) return EFalse;
       
   230 				}
       
   231 			attributeRegister[data]=(TInt8)EPresent;
       
   232 			tempStreamLoc=streamLoc+Length(streamLoc,(TTextFormatAttribute)data);
       
   233 			if (!(tempStreamLoc>=streamLoc)) return EFalse;
       
   234 			streamLoc=tempStreamLoc;
       
   235 			}
       
   236 // Assert: everything is still the same size.
       
   237 		if (!(streamLoc==endOfStreamLoc)) return EFalse;
       
   238 		}
       
   239 	return ETrue;
       
   240 	}
       
   241 
       
   242 static inline TUint32 Read32(const TUint8* aPtr)
       
   243 	{
       
   244 	TUint32 val = aPtr[0];
       
   245 	val |= aPtr[1] << 8;
       
   246 	val |= aPtr[2] << 16;
       
   247 	val |= aPtr[3] << 24;
       
   248 	return val;
       
   249 	}
       
   250 
       
   251 
       
   252 static inline void Write32(TUint8*& aPtr,TUint32 aVal)
       
   253 	{
       
   254 	*aPtr++ = TUint8(aVal);
       
   255 	*aPtr++ = TUint8(aVal >> 8);
       
   256 	*aPtr++ = TUint8(aVal >> 16);
       
   257 	*aPtr++ = TUint8(aVal >> 24);
       
   258 	}
       
   259 
       
   260 
       
   261 RFormatStream::RFormatStream():
       
   262 	iBase(NULL),
       
   263 	iEnd(NULL)
       
   264 	{
       
   265 	}
       
   266 
       
   267 		
       
   268 // Allocate the buffer
       
   269 void RFormatStream::AllocL(TInt aSize)
       
   270 	{
       
   271     TUint8* pT = reinterpret_cast<TUint8*>(User::ReAllocL(iBase, aSize));
       
   272     
       
   273     iBase=pT;
       
   274     iEnd=pT+aSize;
       
   275 	}
       
   276 
       
   277 
       
   278 void RFormatStream::Reset()
       
   279 // Free all storage
       
   280 //
       
   281 	{
       
   282 	if (iBase)
       
   283 		{
       
   284 		User::Free(iBase);
       
   285 		iBase = iEnd = NULL;
       
   286 		}
       
   287 	}
       
   288 
       
   289 
       
   290 void RFormatStream::CopyL(const RFormatStream& aSource)
       
   291 	{
       
   292 	TInt size = aSource.iEnd - aSource.iBase;
       
   293 	__ASSERT_DEBUG(size >= 0,Panic(EDebug));
       
   294 	if (size == 0)
       
   295 		Reset();
       
   296 	else
       
   297 		{
       
   298 		AllocL(size);
       
   299 		Mem::Copy(iBase,aSource.iBase,size);
       
   300 		}
       
   301 	}
       
   302 
       
   303 
       
   304 /*
       
   305 Write the bytecode to a stream. Don't write internal attributes; these are not part of the stored format,
       
   306 but are used for transitory marking of text by URL parsers, etc.
       
   307 */
       
   308 void RFormatStream::ExternalizeL(RWriteStream& aStream) const
       
   309 	{
       
   310 	__TEST_INVARIANT;
       
   311 	
       
   312 	const TUint8* base=iBase;
       
   313 	if (base)
       
   314 		{
       
   315 		const TUint8* end = base;
       
   316 		while (end < iEnd && *end < EExternalizedAttributeCount)
       
   317 			{
       
   318 			int bytes = TheAttributeLength[*end++];
       
   319 			if (bytes == 0)
       
   320 				bytes = *end++;
       
   321 			end += bytes;
       
   322 			}
       
   323 		int length = end - base;
       
   324 		aStream.WriteInt32L(length);
       
   325 		aStream.WriteL(base,length);
       
   326 		}
       
   327 	else
       
   328 		aStream.WriteInt32L(0);
       
   329 	}
       
   330 
       
   331 
       
   332 void RFormatStream::InternalizeL(RReadStream& aStream)
       
   333 // Load the buffer from the specified stream
       
   334 //
       
   335 	{
       
   336 	TestInvariantL();
       
   337 
       
   338 	TInt length=aStream.ReadInt32L();
       
   339 	//
       
   340 	if (length<0 || length>KMaxFormatStreamLength)
       
   341 		User::Leave(KErrCorrupt);
       
   342 	//
       
   343 	if (length==0)
       
   344 		Reset();
       
   345 	else
       
   346 		{
       
   347 		AllocL(length);
       
   348 		aStream.ReadL(iBase,length);
       
   349 		}
       
   350 
       
   351 	TestInvariantL();
       
   352 	}
       
   353 
       
   354 
       
   355 // Return a pointer to the stored bytecode and put its length in bytes in aLength.
       
   356 const TUint8* RFormatStream::Ptr(TInt& aLength) const
       
   357 	{
       
   358 	__TEST_INVARIANT;
       
   359 	aLength=iEnd-iBase;
       
   360 	__ASSERT_DEBUG((iBase==NULL && aLength==0) || (iBase!=NULL && aLength>0),Panic(ECorruptFormatLayer));
       
   361 	return iBase;
       
   362 	}
       
   363 
       
   364 
       
   365 // Save the attributes of aCharFormat specified by the corresponding mask aMask.
       
   366 void RFormatStream::SetCharFormatL(const TCharFormatX& aCharFormatX,const TCharFormatXMask& aMask)
       
   367 	{
       
   368 	TInt size=DoCalcSizeCharFormat(aCharFormatX,aMask);
       
   369 	if (size==0)
       
   370 		Reset();
       
   371 	else
       
   372 		{
       
   373 		AllocL(size);  // delete the current contents, after allocing a temporary
       
   374 		DoStoreCharFormat(aCharFormatX,aMask);
       
   375 		}
       
   376 
       
   377 	__TEST_INVARIANT;
       
   378 	}
       
   379 
       
   380 
       
   381 void RFormatStream::SetParaFormatL(const CParaFormat& aDesiredFormat,const TParaFormatMask& aDesiredMask,
       
   382 											const CParaFormat& aCurrentFormat)
       
   383 // Sets the format layer with the specified paragraph format attributes.
       
   384 // If a leave occurs at any stage, then revert back to original state, and
       
   385 // propagate the leave.
       
   386 //
       
   387 	{
       
   388 	TInt size=DoCalcSizeParaFormat(aDesiredFormat,aDesiredMask,aCurrentFormat);
       
   389 	if (size==0)
       
   390 		Reset();
       
   391 	else
       
   392 		{
       
   393 		AllocL(size);  // delete the current contents, after allocing a temporary
       
   394 		DoSetParaFormat(aDesiredFormat,aDesiredMask,aCurrentFormat);
       
   395 		}
       
   396 
       
   397 	__TEST_INVARIANT;
       
   398 	}
       
   399 	
       
   400 // Write an auxiliary attribute for a system colour byte. Update aPtr.
       
   401 static void WriteSystemColor(TUint8*& aPtr,TTextFormatNonMaskableAttribute aAttrib,const TLogicalRgb& aColor)
       
   402 	{
       
   403 	TUint8 index = (TUint8)aColor.SystemColorIndex();
       
   404 	if (index)
       
   405 		{
       
   406 		*aPtr++ = TUint8(aAttrib);
       
   407 		*aPtr++ = index;
       
   408 		}
       
   409 	}
       
   410 
       
   411 
       
   412 // Read a system colour byte into a logical colour. Don't change aPtr.
       
   413 static void ReadSystemColor(const TUint8* aPtr,TLogicalRgb& aColor)
       
   414 	{
       
   415 	TUint index = *aPtr;
       
   416 	aColor.SetSystemColorIndex(index); 
       
   417 	}
       
   418 
       
   419 
       
   420 // Write paragraph attributes specified by aDesiredMask from aDesiredFormat to the stream.
       
   421 void RFormatStream::DoSetParaFormat(const CParaFormat& aDesiredFormat,
       
   422 									TParaFormatMask aMask,
       
   423 									const CParaFormat& aCurrentFormat)
       
   424 	{
       
   425 	TUint8* ptr=iBase;
       
   426 	if (aMask.AttribIsSet(EAttFillColor))
       
   427 		{
       
   428 		*ptr++=TUint8(EAttFillColor);
       
   429 		ptr=Store(ptr,aDesiredFormat.iFillColor);
       
   430 		}
       
   431 	if (aMask.AttribIsSet(EAttLeftMargin))
       
   432 		{
       
   433 		*ptr++=TUint8(EAttLeftMargin);
       
   434 		Write32(ptr,aDesiredFormat.iLeftMarginInTwips);
       
   435 		}
       
   436 	if (aMask.AttribIsSet(EAttRightMargin))
       
   437 		{
       
   438 		*ptr++=TUint8(EAttRightMargin);
       
   439 		Write32(ptr,aDesiredFormat.iRightMarginInTwips);
       
   440 		}
       
   441 	if (aMask.AttribIsSet(EAttIndent))
       
   442 		{
       
   443 		*ptr++=TUint8(EAttIndent);
       
   444 		Write32(ptr,aDesiredFormat.iIndentInTwips);
       
   445 		}
       
   446 	if (aMask.AttribIsSet(EAttAlignment))
       
   447 		{
       
   448 		*ptr++=TUint8(EAttAlignment);
       
   449 		*ptr++=TUint8(aDesiredFormat.iHorizontalAlignment);
       
   450 		}
       
   451 	if (aMask.AttribIsSet(EAttVerticalAlignment))
       
   452 		{
       
   453 		*ptr++=TUint8(EAttVerticalAlignment);
       
   454 		*ptr++=TUint8(aDesiredFormat.iVerticalAlignment);
       
   455 		}
       
   456 	if (aMask.AttribIsSet(EAttLineSpacing))
       
   457 		{
       
   458 		*ptr++=TUint8(EAttLineSpacing);
       
   459 		Write32(ptr,aDesiredFormat.iLineSpacingInTwips);
       
   460 		}
       
   461 	if (aMask.AttribIsSet(EAttLineSpacingControl))
       
   462 		{
       
   463 		*ptr++=TUint8(EAttLineSpacingControl);
       
   464 		*ptr++=TUint8(aDesiredFormat.iLineSpacingControl);
       
   465 		}
       
   466 	if (aMask.AttribIsSet(EAttSpaceBefore))
       
   467 		{
       
   468 		*ptr++=TUint8(EAttSpaceBefore);
       
   469 		Write32(ptr,aDesiredFormat.iSpaceBeforeInTwips);
       
   470 		}
       
   471 	if (aMask.AttribIsSet(EAttSpaceAfter))
       
   472 		{
       
   473 		*ptr++=TUint8(EAttSpaceAfter);
       
   474 		Write32(ptr,aDesiredFormat.iSpaceAfterInTwips);
       
   475 		}
       
   476 	if (aMask.AttribIsSet(EAttKeepTogether))
       
   477 		{
       
   478 		*ptr++=TUint8(EAttKeepTogether);
       
   479 		*ptr++=TUint8(aDesiredFormat.iKeepTogether!=EFalse);
       
   480 		}
       
   481 	if (aMask.AttribIsSet(EAttKeepWithNext))
       
   482 		{
       
   483 		*ptr++=TUint8(EAttKeepWithNext);
       
   484 		*ptr++=TUint8(aDesiredFormat.iKeepWithNext!=EFalse);
       
   485 		}
       
   486 	if (aMask.AttribIsSet(EAttStartNewPage))
       
   487 		{
       
   488 		*ptr++=TUint8(EAttStartNewPage);
       
   489 		*ptr++=TUint8(aDesiredFormat.iStartNewPage!=EFalse);
       
   490 		}
       
   491 	if (aMask.AttribIsSet(EAttWidowOrphan))
       
   492 		{
       
   493 		*ptr++=TUint8(EAttWidowOrphan);
       
   494 		*ptr++=TUint8(aDesiredFormat.iWidowOrphan!=EFalse);
       
   495 		}
       
   496 	if (aMask.AttribIsSet(EAttWrap))
       
   497 		{
       
   498 		*ptr++=TUint8(EAttWrap);
       
   499 		*ptr++=TUint8(aDesiredFormat.iWrap!=EFalse);
       
   500 		}
       
   501 	if (aMask.AttribIsSet(EAttBorderMargin))
       
   502 		{
       
   503 		*ptr++=TUint8(EAttBorderMargin);
       
   504 		Write32(ptr,aDesiredFormat.iBorderMarginInTwips);
       
   505 		}
       
   506 	if ( aDesiredFormat.BordersPresent() || aCurrentFormat.BordersPresent() )
       
   507 		{
       
   508 		if (aMask.AttribIsSet(EAttTopBorder))
       
   509 			ptr=StoreBorder(ptr,EAttTopBorder,aDesiredFormat.ParaBorder(CParaFormat::EParaBorderTop));
       
   510 		if (aMask.AttribIsSet(EAttBottomBorder))
       
   511 			ptr=StoreBorder(ptr,EAttBottomBorder,aDesiredFormat.ParaBorder(CParaFormat::EParaBorderBottom));
       
   512 		if (aMask.AttribIsSet(EAttLeftBorder))
       
   513 			ptr=StoreBorder(ptr,EAttLeftBorder,aDesiredFormat.ParaBorder(CParaFormat::EParaBorderLeft));
       
   514 		if (aMask.AttribIsSet(EAttRightBorder))
       
   515 			ptr=StoreBorder(ptr,EAttRightBorder,aDesiredFormat.ParaBorder(CParaFormat::EParaBorderRight));
       
   516 		}
       
   517 	if (aMask.AttribIsSet(EAttDefaultTabWidth))
       
   518 		{
       
   519 		*ptr++=TUint8(EAttDefaultTabWidth);
       
   520 		Write32(ptr,aDesiredFormat.iDefaultTabWidthInTwips);
       
   521 		}
       
   522 	if (aMask.AttribIsSet(EAttTabStop))
       
   523 		{
       
   524 		TUint8* tptr=ptr;	// prevent stacking of ptr;
       
   525 		StoreTabs(tptr,aDesiredFormat,aCurrentFormat,ETrue);
       
   526 		ptr=tptr;
       
   527 		}
       
   528 	if (aMask.AttribIsSet(EAttBullet))
       
   529 		{
       
   530 		if (aDesiredFormat.iBullet || aCurrentFormat.iBullet)
       
   531 			{
       
   532 			if (aDesiredFormat.iBullet)
       
   533 				ptr = StoreBullet(ptr,*aDesiredFormat.iBullet);
       
   534 			else if (aCurrentFormat.iBullet)
       
   535 				ptr = StoreBullet(ptr,TBullet());
       
   536 			}
       
   537 		}
       
   538 	if (!(aDesiredFormat.iLanguage & ~0xFF) && aMask.AttribIsSet(EAttParaLanguage))
       
   539 		{
       
   540 		*ptr++=TUint8(EAttParaLanguage);
       
   541 		*ptr++=TUint8(aDesiredFormat.iLanguage);
       
   542 		}
       
   543 
       
   544 	/*
       
   545 	Write the auxiliary attributes for system colours, language codes greater than 255, etc.
       
   546 	These must go at the end of the stream because they will not be recognised by earlier versions
       
   547 	of ETEXT and will prevent any further attributes from being read.
       
   548 	*/
       
   549 	if (aMask.AttribIsSet(EAttFillColor))
       
   550 		WriteSystemColor(ptr,EAttFillSystemColor,aDesiredFormat.iFillColor);
       
   551 	if (aMask.AttribIsSet(EAttBullet))
       
   552 		{
       
   553 		if (aDesiredFormat.iBullet)
       
   554 			WriteSystemColor(ptr,EAttBulletSystemColor,aDesiredFormat.iBullet->iColor);
       
   555 		else if (aCurrentFormat.iBullet)
       
   556 			WriteSystemColor(ptr,EAttBulletSystemColor,TBullet().iColor);
       
   557 		}
       
   558 	if (aDesiredFormat.BordersPresent())
       
   559 		{
       
   560 		if (aMask.AttribIsSet(EAttTopBorder))
       
   561 			WriteSystemColor(ptr,EAttTopBorderSystemColor,aDesiredFormat.ParaBorder(CParaFormat::EParaBorderTop).iColor);
       
   562 		if (aMask.AttribIsSet(EAttBottomBorder))
       
   563 			WriteSystemColor(ptr,EAttBottomBorderSystemColor,aDesiredFormat.ParaBorder(CParaFormat::EParaBorderBottom).iColor);
       
   564 		if (aMask.AttribIsSet(EAttLeftBorder))
       
   565 			WriteSystemColor(ptr,EAttLeftBorderSystemColor,aDesiredFormat.ParaBorder(CParaFormat::EParaBorderLeft).iColor);
       
   566 		if (aMask.AttribIsSet(EAttRightBorder))
       
   567 			WriteSystemColor(ptr,EAttRightBorderSystemColor,aDesiredFormat.ParaBorder(CParaFormat::EParaBorderRight).iColor);
       
   568 		}
       
   569 	if ((aDesiredFormat.iLanguage & ~0xFF) && aMask.AttribIsSet(EAttParaLanguage))
       
   570 		{
       
   571 		*ptr++ = TUint8(EAttParaLanguageX);
       
   572 		Write32(ptr,aDesiredFormat.iLanguage);
       
   573 		}
       
   574 	if (aMask.AttribIsSet(EAttBullet))
       
   575 		{
       
   576 		if (aDesiredFormat.iBullet || aCurrentFormat.iBullet)
       
   577 			{
       
   578 			TBullet bullet;
       
   579 			const TBullet* b = aDesiredFormat.iBullet;
       
   580 			if (!b)
       
   581 				b = &bullet;
       
   582 			*ptr++ = TUint8(EAttBulletX);
       
   583 			*ptr++ = TUint8(b->iStyle);
       
   584 			Write32(ptr,b->iStartNumber);
       
   585 			*ptr++ = TUint8(b->iAlignment);
       
   586 			}
       
   587 		}
       
   588 	}
       
   589 
       
   590 
       
   591 TInt RFormatStream::DoCalcSizeParaFormat(const CParaFormat& aDesiredFormat,TParaFormatMask aMask,
       
   592 										 const CParaFormat& aCurrentFormat)
       
   593 // determine the amount of memory required to store the
       
   594 // specified attriubutes from the specified paragraph format.
       
   595 //
       
   596 	{
       
   597 	TInt size=0;
       
   598 	if (aMask.AttribIsSet(EAttFillColor))
       
   599 		{
       
   600 		size+=(KTypeSize+KParaFillColor);
       
   601 		if (aDesiredFormat.iFillColor.SystemColorIndex())
       
   602 			size += KTypeSize + KParaFillSystemColor;
       
   603 		}
       
   604 	if (aMask.AttribIsSet(EAttLeftMargin))
       
   605 		size+=(KTypeSize+KParaLeftMargin);
       
   606 	if (aMask.AttribIsSet(EAttRightMargin))
       
   607 		size+=(KTypeSize+KParaRightMargin);
       
   608 	if (aMask.AttribIsSet(EAttIndent))
       
   609 		size+=(KTypeSize+KParaIndent);
       
   610 	if (aMask.AttribIsSet(EAttAlignment))
       
   611 		size+=(KTypeSize+KParaAlignment);
       
   612 	if (aMask.AttribIsSet(EAttVerticalAlignment))
       
   613 		size+=(KTypeSize+KParaVerticalAlignment);
       
   614 	if (aMask.AttribIsSet(EAttLineSpacing))
       
   615 		size+=(KTypeSize+KParaLineSpacing);
       
   616 	if (aMask.AttribIsSet(EAttLineSpacingControl))
       
   617 		size+=(KTypeSize+KParaLineSpacingControl);
       
   618 	if (aMask.AttribIsSet(EAttSpaceBefore))
       
   619 		size+=(KTypeSize+KParaSpaceBefore);
       
   620 	if (aMask.AttribIsSet(EAttSpaceAfter))
       
   621 		size+=(KTypeSize+KParaSpaceAfter);
       
   622 	if (aMask.AttribIsSet(EAttKeepTogether))
       
   623 		size+=(KTypeSize+KParaKeepTogether);
       
   624 	if (aMask.AttribIsSet(EAttKeepWithNext))
       
   625 		size+=(KTypeSize+KParaKeepWithNext);
       
   626 	if (aMask.AttribIsSet(EAttStartNewPage))
       
   627 		size+=(KTypeSize+KParaStartNewPage);
       
   628 	if (aMask.AttribIsSet(EAttWidowOrphan))
       
   629 		size+=(KTypeSize+KParaWidowOrphan);
       
   630 	if (aMask.AttribIsSet(EAttWrap))
       
   631 		size+=(KTypeSize+KParaWrap);
       
   632 	if (aMask.AttribIsSet(EAttBorderMargin))
       
   633 		size+=(KTypeSize+KParaBorderMargin);
       
   634 	if ( aDesiredFormat.BordersPresent() || aCurrentFormat.BordersPresent() )
       
   635 		{
       
   636 		if (aMask.AttribIsSet(EAttTopBorder))
       
   637 			{
       
   638 			size+=(KTypeSize+
       
   639 			sizeof(TUint8)+  // line style
       
   640 			sizeof(TInt32)+  // line thickness
       
   641 			KColor+
       
   642 			sizeof(TUint8));  // auto color flag
       
   643 			if (aDesiredFormat.ParaBorder(CParaFormat::EParaBorderTop).iColor.SystemColorIndex())
       
   644 				size += KTypeSize + KParaTopBorderSystemColor;
       
   645 			}
       
   646 		if (aMask.AttribIsSet(EAttBottomBorder))
       
   647 			{
       
   648 			size+=(KTypeSize+
       
   649 			sizeof(TUint8)+  // line style
       
   650 			sizeof(TInt32)+  // line thickness
       
   651 			KColor+
       
   652 			sizeof(TUint8));  // auto color flag
       
   653 			if (aDesiredFormat.ParaBorder(CParaFormat::EParaBorderBottom).iColor.SystemColorIndex())
       
   654 				size += KTypeSize + KParaBottomBorderSystemColor;
       
   655 			}
       
   656 		if (aMask.AttribIsSet(EAttLeftBorder))
       
   657 			{
       
   658 			size+=(KTypeSize+
       
   659 			sizeof(TUint8)+  // line style
       
   660 			sizeof(TInt32)+  // line thickness
       
   661 			KColor+
       
   662 			sizeof(TUint8));  // auto color flag
       
   663 			if (aDesiredFormat.ParaBorder(CParaFormat::EParaBorderLeft).iColor.SystemColorIndex())
       
   664 				size += KTypeSize + KParaLeftBorderSystemColor;
       
   665 			}
       
   666 		if (aMask.AttribIsSet(EAttRightBorder))
       
   667 			{
       
   668 			size+=(KTypeSize+
       
   669 			sizeof(TUint8)+  // line style
       
   670 			sizeof(TInt32)+  // line thickness
       
   671 			KColor+
       
   672 			sizeof(TUint8));  // auto color flag
       
   673 			if (aDesiredFormat.ParaBorder(CParaFormat::EParaBorderRight).iColor.SystemColorIndex())
       
   674 				size += KTypeSize + KParaBulletSystemColor;
       
   675 			}
       
   676 		}
       
   677 	if (aMask.AttribIsSet(EAttDefaultTabWidth))
       
   678 		size+=(KTypeSize+KParaDefaultTabWidth);
       
   679 	if (aMask.AttribIsSet(EAttTabStop))
       
   680 		{
       
   681 		TUint8* ptr=NULL;
       
   682 		size+=StoreTabs(ptr,aDesiredFormat,aCurrentFormat,EFalse);
       
   683 		}
       
   684 	if (aMask.AttribIsSet(EAttBullet))
       
   685 		{
       
   686 		if (aDesiredFormat.iBullet || aCurrentFormat.iBullet)
       
   687 			{
       
   688 			size += KTypeSize +
       
   689 					sizeof(TUint8) +		// length of following data
       
   690 					sizeof(TText) +			// iCharacterCode
       
   691 					KFontHeight +			// iHeightInTwips
       
   692 					sizeof(TUint8) +		// iHanging indent
       
   693 					KCharColor +			// iColor
       
   694 					sizeof(TUint8) +		// typeface name size
       
   695 					KTypefaceFlags;			// typeface flags
       
   696 
       
   697 			if (aDesiredFormat.iBullet)
       
   698 				size += aDesiredFormat.iBullet->iTypeface.iName.Size();  // font name
       
   699 
       
   700 			if ((aDesiredFormat.iBullet && aDesiredFormat.iBullet->iColor.SystemColorIndex()) ||
       
   701 				(aCurrentFormat.iBullet))
       
   702 				size += KTypeSize + KParaBulletSystemColor;
       
   703 
       
   704 			size += KTypeSize + KParaBulletX;
       
   705 			}
       
   706 		}
       
   707 	if (aMask.AttribIsSet(EAttParaLanguage))
       
   708 		{
       
   709 		if (aDesiredFormat.iLanguage & ~0xFF)
       
   710 			size += KTypeSize + KParaLanguageX;
       
   711 		else
       
   712 			size += KTypeSize + KParaLanguage;
       
   713 		}
       
   714 	return size;
       
   715 	}
       
   716 
       
   717 
       
   718 // Store the specified values in this (allocated) format stream.
       
   719 void RFormatStream::DoStoreCharFormat(const TCharFormatX& aCharFormat,TCharFormatXMask aMask)
       
   720 	{
       
   721 	TUint8* ptr = iBase;
       
   722 	const TCharFormat format = aCharFormat.iCharFormat;
       
   723 
       
   724 	if (aMask.AttribIsSet(EAttColor))
       
   725 		{
       
   726 		*ptr++=TUint8(EAttColor);
       
   727 		ptr=Store(ptr,format.iFontPresentation.iTextColor);
       
   728 		}
       
   729 	if (aMask.AttribIsSet(EAttFontHighlightColor))
       
   730 		{
       
   731 		*ptr++=TUint8(EAttFontHighlightColor);
       
   732 		ptr=Store(ptr,format.iFontPresentation.iHighlightColor);
       
   733 		}
       
   734 	if (aMask.AttribIsSet(EAttFontHighlightStyle))
       
   735 		{
       
   736 		*ptr++=TUint8(EAttFontHighlightStyle);
       
   737 		*ptr++=(TUint8)format.iFontPresentation.iHighlightStyle;
       
   738 		}
       
   739 	if (aMask.AttribIsSet(EAttFontStrikethrough))
       
   740 		{
       
   741 		*ptr++=TUint8(EAttFontStrikethrough);
       
   742 		*ptr++=(TUint8)format.iFontPresentation.iStrikethrough;
       
   743 		}
       
   744 	if (aMask.AttribIsSet(EAttFontUnderline))
       
   745 		{
       
   746 		*ptr++=TUint8(EAttFontUnderline);
       
   747 		*ptr++=(TUint8)format.iFontPresentation.iUnderline;
       
   748 		}
       
   749 	if (aMask.AttribIsSet(EAttFontHeight))
       
   750 		{
       
   751 		*ptr++=TUint8(EAttFontHeight);
       
   752 		Write32(ptr,format.iFontSpec.iHeight);
       
   753 		}
       
   754 	if (aMask.AttribIsSet(EAttFontPosture))
       
   755 		{
       
   756 		*ptr++=TUint8(EAttFontPosture);
       
   757 		*ptr++=TUint8(format.iFontSpec.iFontStyle.Posture());
       
   758 		}
       
   759 	if (aMask.AttribIsSet(EAttFontStrokeWeight))
       
   760 		{
       
   761 		*ptr++=TUint8(EAttFontStrokeWeight);
       
   762 		*ptr++=TUint8(format.iFontSpec.iFontStyle.StrokeWeight());
       
   763 		}
       
   764 	if (aMask.AttribIsSet(EAttFontPrintPos))
       
   765 		{
       
   766 		*ptr++=TUint8(EAttFontPrintPos);
       
   767 		*ptr++=TUint8(format.iFontSpec.iFontStyle.PrintPosition());
       
   768 		}
       
   769 	if (aMask.AttribIsSet(EAttFontTypeface))
       
   770 		{
       
   771 		*ptr++=TUint8(EAttFontTypeface);
       
   772 		ptr=Store(ptr,format.iFontSpec.iTypeface);
       
   773 		*ptr++=TUint8(EAttBitmapType);
       
   774 		*ptr++=TUint8(format.iFontSpec.iFontStyle.BitmapType());
       
   775 		}
       
   776 	if (!(format.iLanguage & ~0xFF) && aMask.AttribIsSet(EAttCharLanguage))
       
   777 		{
       
   778 		*ptr++=TUint8(EAttCharLanguage);
       
   779 		*ptr++=TUint8(format.iLanguage);
       
   780 		}
       
   781 	if (aMask.AttribIsSet(EAttFontHiddenText))
       
   782 		{
       
   783 		*ptr++=TUint8(EAttFontHiddenText);
       
   784 		*ptr++=TUint8(format.iFontPresentation.iHiddenText!=EFalse);
       
   785 		}
       
   786 	if (aMask.AttribIsSet(EAttFontPictureAlignment))
       
   787 		{
       
   788 		*ptr++=TUint8(EAttFontPictureAlignment);
       
   789 		*ptr++=TUint8(format.iFontPresentation.iPictureAlignment);
       
   790 		}
       
   791 
       
   792 	// Auxiliary attributes for system colours, etc.
       
   793 	if (aMask.AttribIsSet(EAttColor))
       
   794 		WriteSystemColor(ptr,EAttTextSystemColor,format.iFontPresentation.iTextColor);
       
   795 	if (aMask.AttribIsSet(EAttFontHighlightColor))
       
   796 		WriteSystemColor(ptr,EAttFontHighlightSystemColor,format.iFontPresentation.iHighlightColor);
       
   797 	if ((format.iLanguage & ~0xFF) && aMask.AttribIsSet(EAttCharLanguage))
       
   798 		{
       
   799 		*ptr++ = TUint8(EAttCharLanguageX);
       
   800 		Write32(ptr,format.iLanguage);
       
   801 		}
       
   802 
       
   803 	// Internal character attributes:
       
   804 	if (aMask.AttribIsSet(EAttParserTag))
       
   805 		{
       
   806 		*ptr++ = TUint8(EAttParserTag);
       
   807 		Write32(ptr,aCharFormat.iParserTag);
       
   808 		}
       
   809 	}
       
   810 
       
   811 
       
   812 TInt RFormatStream::DoCalcSizeCharFormat(const TCharFormatX& aCharFormatX,const TCharFormatXMask& aMask)
       
   813 	{
       
   814 	TInt size = 0;
       
   815 	const TCharFormat format = aCharFormatX.iCharFormat;
       
   816 
       
   817 	if (aMask.AttribIsSet(EAttColor))
       
   818 		{
       
   819 		size+=(KTypeSize+KCharColor);
       
   820 		if (format.iFontPresentation.iTextColor.SystemColorIndex())
       
   821 			size += KTypeSize + KCharTextSystemColor;
       
   822 		}
       
   823 	if (aMask.AttribIsSet(EAttFontHighlightColor))
       
   824 		{
       
   825 		size+=(KTypeSize+KCharHighlightColor);
       
   826 		if (format.iFontPresentation.iHighlightColor.SystemColorIndex())
       
   827 			size += KTypeSize + KCharFontHighlightSystemColor;
       
   828 		}
       
   829 	if (aMask.AttribIsSet(EAttFontHighlightStyle))
       
   830 		size+=(KTypeSize+KCharHighlightStyle);
       
   831 	if (aMask.AttribIsSet(EAttFontStrikethrough))
       
   832 		size+=(KTypeSize+KCharStrikethrough);
       
   833 	if (aMask.AttribIsSet(EAttFontUnderline))
       
   834 		size+=(KTypeSize+KCharUnderline);
       
   835 	if (aMask.AttribIsSet(EAttFontHeight))
       
   836 		size+=(KTypeSize+KCharFontHeight);
       
   837 	if (aMask.AttribIsSet(EAttFontPosture))
       
   838 		size+=(KTypeSize+KCharPosture);
       
   839 	if (aMask.AttribIsSet(EAttFontStrokeWeight))
       
   840 		size+=(KTypeSize+KCharStrokeWeight);
       
   841 	if (aMask.AttribIsSet(EAttFontPrintPos))
       
   842 		size+=(KTypeSize+KCharPrintPos);
       
   843 	if (aMask.AttribIsSet(EAttFontTypeface))
       
   844 		{
       
   845 		TUint8 length=(TUint8)format.iFontSpec.iTypeface.iName.Size();
       
   846 		size+=(KTypeSize+sizeof(TUint8)+length+sizeof(TUint8));  // size in bytes
       
   847 		size+=(KTypeSize+KBitmapType);
       
   848 		}
       
   849 	if (aMask.AttribIsSet(EAttCharLanguage))
       
   850 		{
       
   851 		if (format.iLanguage & ~0xFF)
       
   852 			size += KTypeSize + KCharLanguageX;
       
   853 		else
       
   854 			size += KTypeSize + KCharLanguage;
       
   855 		}
       
   856 	if (aMask.AttribIsSet(EAttFontHiddenText))
       
   857 		size+=(KTypeSize+KCharHiddenText);
       
   858 	if (aMask.AttribIsSet(EAttFontPictureAlignment))
       
   859 		size+=(KTypeSize+KCharPictureAlignment);
       
   860 
       
   861 	// Internal character attributes
       
   862 	if (aMask.AttribIsSet(EAttParserTag))
       
   863 		size += KTypeSize + KCharParserTag;
       
   864 	
       
   865 	return size;
       
   866 	}
       
   867 
       
   868 void RFormatStream::RemoveRedundantCharFormat(TCharFormatMask& aMask,
       
   869 											  const TCharFormatX& aFormat,const TCharFormatX& aEffectiveFormat)
       
   870 	{
       
   871 	TCharFormatXMask mask = aMask;
       
   872 	const TCharFormat format = aFormat.iCharFormat;
       
   873 	const TCharFormat effective_format = aEffectiveFormat.iCharFormat;
       
   874 
       
   875 	if (mask.AttribIsSet(EAttColor))
       
   876 		{
       
   877 		if (format.iFontPresentation.iTextColor==effective_format.iFontPresentation.iTextColor)
       
   878 			mask.ClearAttrib(EAttColor);
       
   879 		}
       
   880 	if (mask.AttribIsSet(EAttFontHighlightColor))
       
   881 		{
       
   882 		if (format.iFontPresentation.iHighlightColor==effective_format.iFontPresentation.iHighlightColor)
       
   883 			mask.ClearAttrib(EAttFontHighlightColor);
       
   884 		}
       
   885 	if (mask.AttribIsSet(EAttFontHighlightStyle))
       
   886 		{
       
   887 		if (format.iFontPresentation.iHighlightStyle==effective_format.iFontPresentation.iHighlightStyle)
       
   888 			mask.ClearAttrib(EAttFontHighlightStyle);
       
   889 		}
       
   890 	if (mask.AttribIsSet(EAttFontStrikethrough))
       
   891 		{
       
   892 		if (format.iFontPresentation.iStrikethrough==effective_format.iFontPresentation.iStrikethrough)
       
   893 			mask.ClearAttrib(EAttFontStrikethrough);
       
   894 		}
       
   895 	if (mask.AttribIsSet(EAttFontUnderline))
       
   896 		{
       
   897 		if (format.iFontPresentation.iUnderline==effective_format.iFontPresentation.iUnderline)
       
   898 			mask.ClearAttrib(EAttFontUnderline);
       
   899 		}
       
   900 	if (mask.AttribIsSet(EAttFontHeight))
       
   901 		{
       
   902 		if (format.iFontSpec.iHeight==effective_format.iFontSpec.iHeight)
       
   903 			mask.ClearAttrib(EAttFontHeight);
       
   904 		}
       
   905 	if (mask.AttribIsSet(EAttFontPosture))
       
   906 		{
       
   907 		if (format.iFontSpec.iFontStyle.Posture()==effective_format.iFontSpec.iFontStyle.Posture())
       
   908 			mask.ClearAttrib(EAttFontPosture);
       
   909 		}
       
   910 	if (mask.AttribIsSet(EAttFontStrokeWeight))
       
   911 		{
       
   912 		if (format.iFontSpec.iFontStyle.StrokeWeight()==effective_format.iFontSpec.iFontStyle.StrokeWeight())
       
   913 			mask.ClearAttrib(EAttFontStrokeWeight);
       
   914 		}
       
   915 	if (mask.AttribIsSet(EAttFontPrintPos))
       
   916 		{
       
   917 		if (format.iFontSpec.iFontStyle.PrintPosition()==effective_format.iFontSpec.iFontStyle.PrintPosition())
       
   918 			mask.ClearAttrib(EAttFontPrintPos);
       
   919 		}
       
   920 	if (mask.AttribIsSet(EAttFontTypeface))
       
   921 		{
       
   922 		if (format.iFontSpec.iTypeface==effective_format.iFontSpec.iTypeface)
       
   923 			mask.ClearAttrib(EAttFontTypeface);
       
   924 		}
       
   925 	if (mask.AttribIsSet(EAttCharLanguage))
       
   926 		{
       
   927 		if (format.iLanguage==effective_format.iLanguage)
       
   928 			mask.ClearAttrib(EAttCharLanguage);
       
   929 		}
       
   930 	if (mask.AttribIsSet(EAttFontHiddenText))
       
   931 		{
       
   932 		if (format.iFontPresentation.iHiddenText==effective_format.iFontPresentation.iHiddenText)
       
   933 			mask.ClearAttrib(EAttFontHiddenText);
       
   934 		}
       
   935 	if (mask.AttribIsSet(EAttFontPictureAlignment))
       
   936 		{
       
   937 		if (format.iFontPresentation.iPictureAlignment==effective_format.iFontPresentation.iPictureAlignment)
       
   938 			mask.ClearAttrib(EAttFontPictureAlignment);
       
   939 		}
       
   940 	if (mask.AttribIsSet(EAttParserTag))
       
   941 		{
       
   942 		if (aFormat.iParserTag == aEffectiveFormat.iParserTag)
       
   943 			mask.ClearAttrib(EAttParserTag);
       
   944 		}
       
   945 	aMask = mask;
       
   946 	}
       
   947 
       
   948 
       
   949 void RFormatStream::SenseParaFormatL(CParaFormat& aParaFormat,TParaFormatMask& aMask,CParaFormat::TParaFormatGetMode aMode)const
       
   950 // Dumps contents of the stream into aParaFormat.  The attributes written to aParaFormat
       
   951 // are determined by the mode, aMode.
       
   952 // If the mode is EAllAttributes, then all attributes are written,
       
   953 // if the mode is EFixedAttributes, then only the fixed atttibutes are written,
       
   954 // ie, not tabs,borders,bullet (which are variable).
       
   955 // For each format attribute found in the stream:
       
   956 // write it into a ParaFormat if the corresponding flag in aMask is not set,
       
   957 // and set this flag showing the attribute has been written into aParaFormat.
       
   958 //
       
   959 // If aMode is EAllAttributes this function may leave through out-of-memory allocating paragraph borders,
       
   960 // bullets or tabs.
       
   961 // If aMode is EFixedAttributes, this function is guaranteed not to leave.
       
   962 //
       
   963 	{
       
   964 	__TEST_INVARIANT;
       
   965 
       
   966 	TUint8* ptr=iBase;
       
   967 	if (ptr==NULL)
       
   968 		return;
       
   969 	TParaFormatMask old_mask = aMask;
       
   970 	TParaFormatMask new_mask = aMask;
       
   971 	TUint8* end=iEnd;
       
   972 	TParaBorder* b = NULL;
       
   973 
       
   974 	while (ptr < end)
       
   975 		{
       
   976 		TUint8 type = *ptr;
       
   977 		ptr += KTypeSize;
       
   978 		switch (type)
       
   979 			{
       
   980 			case EAttFillColor:
       
   981 				if (!old_mask.AttribIsSet(EAttFillColor))
       
   982 					{
       
   983 					new_mask.SetAttrib(EAttFillColor);
       
   984 					ptr=ReadValue(ptr,aParaFormat.iFillColor);
       
   985 					}
       
   986 				else
       
   987 					ptr+=KParaFillColor;
       
   988 				break;
       
   989 			case EAttLeftMargin:
       
   990 				if (!old_mask.AttribIsSet(EAttLeftMargin))
       
   991 					{
       
   992 					new_mask.SetAttrib(EAttLeftMargin);
       
   993 					aParaFormat.iLeftMarginInTwips = Read32(ptr);
       
   994 					}
       
   995 				ptr+=KParaLeftMargin;
       
   996 				break;
       
   997 			case EAttRightMargin:
       
   998 				if (!old_mask.AttribIsSet(EAttRightMargin))
       
   999 					{
       
  1000 					new_mask.SetAttrib(EAttRightMargin);
       
  1001 					aParaFormat.iRightMarginInTwips = Read32(ptr);
       
  1002 					}
       
  1003 				ptr+=KParaRightMargin;
       
  1004 				break;
       
  1005 			case EAttIndent:
       
  1006 				if (!old_mask.AttribIsSet(EAttIndent))
       
  1007 					{
       
  1008 					new_mask.SetAttrib(EAttIndent);
       
  1009 					aParaFormat.iIndentInTwips = Read32(ptr);
       
  1010 					}
       
  1011 				ptr+=KParaIndent;
       
  1012 				break;
       
  1013 			case EAttAlignment:
       
  1014 				if (!old_mask.AttribIsSet(EAttAlignment))
       
  1015 					{
       
  1016 					new_mask.SetAttrib(EAttAlignment);
       
  1017 					aParaFormat.iHorizontalAlignment=CParaFormat::TAlignment(*ptr);
       
  1018 					}
       
  1019 				ptr+=KParaAlignment;
       
  1020 				break;
       
  1021 			case EAttVerticalAlignment:
       
  1022 				if (!old_mask.AttribIsSet(EAttVerticalAlignment))
       
  1023 					{
       
  1024 					new_mask.SetAttrib(EAttVerticalAlignment);
       
  1025 					aParaFormat.iVerticalAlignment=CParaFormat::TAlignment(*ptr);
       
  1026 					}
       
  1027 				ptr+=KParaVerticalAlignment;
       
  1028 				break;
       
  1029 			case EAttLineSpacing:
       
  1030 				if (!old_mask.AttribIsSet(EAttLineSpacing))
       
  1031 					{
       
  1032 					new_mask.SetAttrib(EAttLineSpacing);
       
  1033 					aParaFormat.iLineSpacingInTwips = Read32(ptr);
       
  1034 					}
       
  1035 				ptr+=KParaLineSpacing;
       
  1036 				break;
       
  1037 			case EAttLineSpacingControl:
       
  1038 				if (!old_mask.AttribIsSet(EAttLineSpacingControl))
       
  1039 					{
       
  1040 					new_mask.SetAttrib(EAttLineSpacingControl);
       
  1041 					aParaFormat.iLineSpacingControl=(CParaFormat::TLineSpacingControl)*ptr;
       
  1042 					}
       
  1043 				ptr+=KParaLineSpacingControl;
       
  1044 				break;
       
  1045 			case EAttSpaceBefore:
       
  1046 				if (!old_mask.AttribIsSet(EAttSpaceBefore))
       
  1047 					{
       
  1048 					new_mask.SetAttrib(EAttSpaceBefore);
       
  1049 					aParaFormat.iSpaceBeforeInTwips = Read32(ptr);
       
  1050 					}
       
  1051 				ptr+=KParaSpaceBefore;
       
  1052 				break;
       
  1053 			case EAttSpaceAfter:
       
  1054 				if (!old_mask.AttribIsSet(EAttSpaceAfter))
       
  1055 					{
       
  1056 					new_mask.SetAttrib(EAttSpaceAfter);
       
  1057 					aParaFormat.iSpaceAfterInTwips = Read32(ptr);
       
  1058 					}
       
  1059 				ptr+=KParaSpaceAfter;
       
  1060 				break;
       
  1061 			case EAttKeepTogether:
       
  1062 				if (!old_mask.AttribIsSet(EAttKeepTogether))
       
  1063 					{
       
  1064 					new_mask.SetAttrib(EAttKeepTogether);
       
  1065 					aParaFormat.iKeepTogether=TBool(*ptr);
       
  1066 					}
       
  1067 				ptr+=KParaKeepTogether;
       
  1068 				break;
       
  1069 			case EAttKeepWithNext:
       
  1070 				if (!old_mask.AttribIsSet(EAttKeepWithNext))
       
  1071 					{
       
  1072 					new_mask.SetAttrib(EAttKeepWithNext);
       
  1073 					aParaFormat.iKeepWithNext=(TBool)*ptr;
       
  1074 					}
       
  1075 				ptr+=KParaKeepWithNext;
       
  1076 				break;
       
  1077 			case EAttStartNewPage:
       
  1078 				if (!old_mask.AttribIsSet(EAttStartNewPage))
       
  1079 					{
       
  1080 					new_mask.SetAttrib(EAttStartNewPage);
       
  1081 					aParaFormat.iStartNewPage=TBool(*ptr);
       
  1082 					}
       
  1083 				ptr+=KParaStartNewPage;
       
  1084 				break;
       
  1085 			case EAttWidowOrphan:
       
  1086 				if (!old_mask.AttribIsSet(EAttWidowOrphan))
       
  1087 					{
       
  1088 					new_mask.SetAttrib(EAttWidowOrphan);
       
  1089 					aParaFormat.iWidowOrphan=TBool(*ptr);
       
  1090 					}
       
  1091 				ptr+=KParaWidowOrphan;
       
  1092 				break;
       
  1093 			case EAttWrap:
       
  1094 				if (!old_mask.AttribIsSet(EAttWrap))
       
  1095 					{
       
  1096 					new_mask.SetAttrib(EAttWrap);
       
  1097 					aParaFormat.iWrap=TBool(*ptr);
       
  1098 					}
       
  1099 				ptr+=KParaWrap;
       
  1100 				break;
       
  1101 			case EAttBorderMargin:
       
  1102 				if (!old_mask.AttribIsSet(EAttBorderMargin))
       
  1103 					{
       
  1104 					new_mask.SetAttrib(EAttBorderMargin);
       
  1105 					aParaFormat.iBorderMarginInTwips = Read32(ptr);
       
  1106 					}
       
  1107 				ptr+=KParaBorderMargin;
       
  1108 				break;
       
  1109 			case EAttTopBorder:
       
  1110 				if (aMode==CParaFormat::EFixedAttributes || old_mask.AttribIsSet(EAttTopBorder) )
       
  1111 					{
       
  1112 					ptr+=KParaTopBorder;
       
  1113 					}
       
  1114 				else
       
  1115 					{
       
  1116 					TParaBorder border;
       
  1117 					ptr=ReadValue(ptr,border);
       
  1118 					aParaFormat.SetParaBorderL(CParaFormat::EParaBorderTop,border);
       
  1119 					new_mask.SetAttrib(EAttTopBorder);
       
  1120 					}
       
  1121 				break;
       
  1122 			case EAttBottomBorder:
       
  1123 				if (aMode==CParaFormat::EFixedAttributes || old_mask.AttribIsSet(EAttBottomBorder))
       
  1124 					{
       
  1125 					ptr+=KParaBottomBorder;
       
  1126 					}
       
  1127 				else
       
  1128 					{
       
  1129 					TParaBorder border;
       
  1130 					ptr=ReadValue(ptr,border);
       
  1131 					aParaFormat.SetParaBorderL(CParaFormat::EParaBorderBottom,border);
       
  1132 					new_mask.SetAttrib(EAttBottomBorder);
       
  1133 					}
       
  1134 				break;
       
  1135 			case EAttLeftBorder:
       
  1136 				if (aMode==CParaFormat::EFixedAttributes || old_mask.AttribIsSet(EAttLeftBorder))
       
  1137 					{
       
  1138 					ptr+=KParaLeftBorder;
       
  1139 					}
       
  1140 				else
       
  1141 					{
       
  1142 					TParaBorder border;
       
  1143 					ptr=ReadValue(ptr,border);
       
  1144 					aParaFormat.SetParaBorderL(CParaFormat::EParaBorderLeft,border);
       
  1145 					new_mask.SetAttrib(EAttLeftBorder);
       
  1146 					}
       
  1147 				break;
       
  1148 			case EAttRightBorder:
       
  1149 				if (aMode==CParaFormat::EFixedAttributes || old_mask.AttribIsSet(EAttRightBorder))
       
  1150 					{
       
  1151 					ptr+=KParaRightBorder;
       
  1152 					}
       
  1153 				else
       
  1154 					{
       
  1155 					TParaBorder border;
       
  1156 					ptr=ReadValue(ptr,border);
       
  1157 					aParaFormat.SetParaBorderL(CParaFormat::EParaBorderRight,border);
       
  1158 					new_mask.SetAttrib(EAttRightBorder);
       
  1159 					}
       
  1160 				break;
       
  1161 			case EAttDefaultTabWidth:
       
  1162 				if (!old_mask.AttribIsSet(EAttDefaultTabWidth))
       
  1163 					{
       
  1164 					new_mask.SetAttrib(EAttDefaultTabWidth);
       
  1165 					aParaFormat.iDefaultTabWidthInTwips = Read32(ptr);
       
  1166 					}
       
  1167 				ptr+=KParaDefaultTabWidth;
       
  1168 				break;
       
  1169 			case EAttTabStop:
       
  1170 				{
       
  1171 				if (aMode==CParaFormat::EFixedAttributes || old_mask.AttribIsSet(EAttTabStop))
       
  1172 					ptr += KParaTabStop;
       
  1173 				else
       
  1174 					{
       
  1175 					ptr=ReadTabL(ptr,aParaFormat);
       
  1176 					new_mask.SetAttrib(EAttTabStop);
       
  1177 					}
       
  1178 				break;
       
  1179 				}
       
  1180 			case EAttBullet:
       
  1181 				{
       
  1182 				if (aMode==CParaFormat::EFixedAttributes || old_mask.AttribIsSet(EAttBullet))
       
  1183 					{
       
  1184 					ptr+=*ptr+1;  // variable length attribute
       
  1185 					}
       
  1186 				else
       
  1187 					{
       
  1188 					TBullet* bullet=aParaFormat.iBullet;
       
  1189 					if (!bullet)
       
  1190 						aParaFormat.iBullet=bullet=new(ELeave) TBullet;
       
  1191 					ptr=ReadValue(ptr,*bullet);
       
  1192 					new_mask.SetAttrib(EAttBullet);
       
  1193 					//coverity[memory_leak]
       
  1194 					}
       
  1195 				break;
       
  1196 				}
       
  1197 			case EAttParaLanguage:
       
  1198 				if (!old_mask.AttribIsSet(EAttParaLanguage))
       
  1199 					{
       
  1200 					new_mask.SetAttrib(EAttParaLanguage);
       
  1201 					aParaFormat.iLanguage=TInt32(*ptr);
       
  1202 					}
       
  1203 				ptr+=KParaLanguage;
       
  1204 				break;
       
  1205 
       
  1206 			// Auxiliary attributes for system colours, etc.
       
  1207 			case EAttFillSystemColor:
       
  1208 				if (!old_mask.AttribIsSet(EAttFillColor))
       
  1209 					ReadSystemColor(ptr,aParaFormat.iFillColor);
       
  1210 				ptr++;
       
  1211 				break;
       
  1212 			case EAttBulletSystemColor:
       
  1213 				if (aMode != CParaFormat::EFixedAttributes && !old_mask.AttribIsSet(EAttBullet) &&
       
  1214 					aParaFormat.iBullet)
       
  1215 					ReadSystemColor(ptr,aParaFormat.iBullet->iColor);
       
  1216 				ptr++;					
       
  1217 				break;
       
  1218 			case EAttTopBorderSystemColor:
       
  1219 				if (aMode != CParaFormat::EFixedAttributes && !old_mask.AttribIsSet(EAttTopBorder))
       
  1220 					{
       
  1221 					b = aParaFormat.ParaBorderPtr(CParaFormat::EParaBorderTop);
       
  1222 					if (b)
       
  1223 						ReadSystemColor(ptr,b->iColor);
       
  1224 					}
       
  1225 				ptr++;
       
  1226 				break;
       
  1227 			case EAttBottomBorderSystemColor:
       
  1228 				if (aMode != CParaFormat::EFixedAttributes && !old_mask.AttribIsSet(EAttBottomBorder))
       
  1229 					{
       
  1230 					b = aParaFormat.ParaBorderPtr(CParaFormat::EParaBorderBottom);
       
  1231 					if (b)
       
  1232 						ReadSystemColor(ptr,b->iColor);
       
  1233 					}
       
  1234 				ptr++;
       
  1235 				break;
       
  1236 			case EAttLeftBorderSystemColor:
       
  1237 				if (aMode != CParaFormat::EFixedAttributes && !old_mask.AttribIsSet(EAttLeftBorder))
       
  1238 					{
       
  1239 					b = aParaFormat.ParaBorderPtr(CParaFormat::EParaBorderLeft);
       
  1240 					if (b)
       
  1241 						ReadSystemColor(ptr,b->iColor);
       
  1242 					}
       
  1243 				ptr++;
       
  1244 				break;
       
  1245 			case EAttRightBorderSystemColor:
       
  1246 				if (aMode != CParaFormat::EFixedAttributes && !old_mask.AttribIsSet(EAttRightBorder))
       
  1247 					{
       
  1248 					b = aParaFormat.ParaBorderPtr(CParaFormat::EParaBorderRight);
       
  1249 					if (b)
       
  1250 						ReadSystemColor(ptr,b->iColor);
       
  1251 					}
       
  1252 				ptr++;
       
  1253 				break;
       
  1254 			case EAttParaLanguageX:
       
  1255 				if (!old_mask.AttribIsSet(EAttParaLanguage))
       
  1256 					{
       
  1257 					new_mask.SetAttrib(EAttParaLanguage);
       
  1258 					aParaFormat.iLanguage = Read32(ptr);
       
  1259 					}
       
  1260 				ptr += KParaLanguageX;
       
  1261 				break;
       
  1262 			case EAttBulletX:
       
  1263 				if (aMode == CParaFormat::EFixedAttributes || old_mask.AttribIsSet(EAttBullet) ||
       
  1264 					!aParaFormat.iBullet)
       
  1265 					ptr += KParaBulletX;
       
  1266 				else
       
  1267 					{
       
  1268 					aParaFormat.iBullet->iStyle = (TBullet::TStyle)(*ptr++);
       
  1269 					aParaFormat.iBullet->iStartNumber = Read32(ptr);
       
  1270 					ptr += sizeof(TInt32);
       
  1271 					aParaFormat.iBullet->iAlignment = (TBullet::TAlignment)(*ptr++);
       
  1272 					}
       
  1273 				break;
       
  1274 
       
  1275 			default:  // have maybe read an attribute defined by a later version; stop here
       
  1276 				aMask = new_mask;
       
  1277 				return;
       
  1278 			}
       
  1279 		}
       
  1280 	aMask = new_mask;
       
  1281 	}
       
  1282 
       
  1283 /*
       
  1284 Extract format attributes selected by cleared bits in aMask.
       
  1285 Put them into aCharFormatX if the corresponding bit in aMask is NOT set, and set the bit.
       
  1286 */
       
  1287 void RFormatStream::SenseCharFormat(TCharFormatX& aCharFormat,TCharFormatXMask& aMask) const
       
  1288 	{
       
  1289 	__TEST_INVARIANT;
       
  1290 
       
  1291 	TUint8* ptr = iBase;
       
  1292 	if (ptr == NULL)
       
  1293 		return;
       
  1294 	TCharFormatXMask old_mask = aMask;
       
  1295 	TCharFormatXMask new_mask = aMask;
       
  1296 	TUint8* end = iEnd;
       
  1297 	TCharFormat& format = aCharFormat.iCharFormat;
       
  1298 
       
  1299 	while (ptr<end)
       
  1300 		{
       
  1301 		TUint8 type = *ptr;
       
  1302 		ptr+=KTypeSize;
       
  1303 		switch (type)
       
  1304 			{
       
  1305 			case EAttColor:
       
  1306 				if (!old_mask.AttribIsSet(EAttColor))
       
  1307 					{
       
  1308 					new_mask.SetAttrib(EAttColor);
       
  1309 					ptr=ReadValue(ptr,format.iFontPresentation.iTextColor);
       
  1310 					}
       
  1311 				else
       
  1312 					ptr+=KCharColor;
       
  1313 				break;
       
  1314 			case EAttFontHighlightColor:
       
  1315 				if (!old_mask.AttribIsSet(EAttFontHighlightColor))
       
  1316 					{
       
  1317 					new_mask.SetAttrib(EAttFontHighlightColor);
       
  1318 					ptr=ReadValue(ptr,format.iFontPresentation.iHighlightColor);
       
  1319 					}
       
  1320 				else
       
  1321 					ptr+=KCharHighlightColor;
       
  1322 				break;
       
  1323 			case EAttFontHighlightStyle:
       
  1324 				if (!old_mask.AttribIsSet(EAttFontHighlightStyle))
       
  1325 					{
       
  1326 					new_mask.SetAttrib(EAttFontHighlightStyle);
       
  1327 					format.iFontPresentation.iHighlightStyle=(TFontPresentation::TFontHighlightStyle)*ptr;
       
  1328 					}
       
  1329 				ptr+=KCharHighlightStyle;
       
  1330 				break;
       
  1331 			case EAttFontStrikethrough:
       
  1332 				if (!old_mask.AttribIsSet(EAttFontStrikethrough))
       
  1333 					{
       
  1334 					new_mask.SetAttrib(EAttFontStrikethrough);
       
  1335 					format.iFontPresentation.iStrikethrough=(TFontStrikethrough)*ptr;
       
  1336 					}
       
  1337 				ptr+=KCharStrikethrough;
       
  1338 				break;
       
  1339 			case EAttFontUnderline:
       
  1340 				if (!old_mask.AttribIsSet(EAttFontUnderline))
       
  1341 					{
       
  1342 					new_mask.SetAttrib(EAttFontUnderline);
       
  1343 					format.iFontPresentation.iUnderline=(TFontUnderline)*ptr;
       
  1344 					}
       
  1345 				ptr+=KCharUnderline;
       
  1346 				break;
       
  1347 			case EAttFontHeight:
       
  1348 				if (!old_mask.AttribIsSet(EAttFontHeight))
       
  1349 					{
       
  1350 					new_mask.SetAttrib(EAttFontHeight);
       
  1351 					format.iFontSpec.iHeight = Read32(ptr);
       
  1352 					}
       
  1353 				ptr+=KCharFontHeight;
       
  1354 				break;
       
  1355 			case EAttFontPosture:
       
  1356 				if (!old_mask.AttribIsSet(EAttFontPosture))
       
  1357 					{
       
  1358 					new_mask.SetAttrib(EAttFontPosture);
       
  1359 					format.iFontSpec.iFontStyle.SetPosture((TFontPosture)*ptr);
       
  1360 					}
       
  1361 				ptr+=KCharPosture;
       
  1362 				break;
       
  1363 			case EAttFontStrokeWeight:
       
  1364 				if (!old_mask.AttribIsSet(EAttFontStrokeWeight))
       
  1365 					{
       
  1366 					new_mask.SetAttrib(EAttFontStrokeWeight);
       
  1367 					format.iFontSpec.iFontStyle.SetStrokeWeight((TFontStrokeWeight)*ptr);
       
  1368 					}
       
  1369 				ptr+=KCharStrokeWeight;
       
  1370 				break;
       
  1371 			case EAttFontPrintPos:
       
  1372 				if (!old_mask.AttribIsSet(EAttFontPrintPos))
       
  1373 					{
       
  1374 					new_mask.SetAttrib(EAttFontPrintPos);
       
  1375 					format.iFontSpec.iFontStyle.SetPrintPosition((TFontPrintPosition)*ptr);
       
  1376 					}
       
  1377 				ptr+=KCharPrintPos;
       
  1378 				break;
       
  1379 			case EAttFontTypeface:
       
  1380 				if (!old_mask.AttribIsSet(EAttFontTypeface))
       
  1381 					{
       
  1382 					new_mask.SetAttrib(EAttFontTypeface);
       
  1383 					ptr=ReadValue(ptr,format.iFontSpec.iTypeface);  // updates ptr
       
  1384 					}
       
  1385 				else
       
  1386 					ptr+=*ptr+1;	// variable length attribute
       
  1387 				break;
       
  1388 			case EAttBitmapType:
       
  1389 				if (!old_mask.AttribIsSet(EAttFontTypeface))
       
  1390 					{
       
  1391 					format.iFontSpec.iFontStyle.SetBitmapType(static_cast <TGlyphBitmapType> (*ptr));
       
  1392 					}
       
  1393 				ptr+=KBitmapType;
       
  1394 				break;
       
  1395 			case EAttCharLanguage:
       
  1396 				if (!old_mask.AttribIsSet(EAttCharLanguage))
       
  1397 					{
       
  1398 					new_mask.SetAttrib(EAttCharLanguage);
       
  1399 					format.iLanguage=*ptr;
       
  1400 					}
       
  1401 				ptr+=KCharLanguage;
       
  1402 				break;
       
  1403 			case EAttFontHiddenText:
       
  1404 				if (!old_mask.AttribIsSet(EAttFontHiddenText))
       
  1405 					{
       
  1406 					new_mask.SetAttrib(EAttFontHiddenText);
       
  1407 					format.iFontPresentation.iHiddenText=(TBool)*ptr;
       
  1408 					}
       
  1409 				ptr+=KCharHiddenText;
       
  1410 				break;
       
  1411 			case EAttFontPictureAlignment:
       
  1412 				if (!old_mask.AttribIsSet(EAttFontPictureAlignment))
       
  1413 					{
       
  1414 					new_mask.SetAttrib(EAttFontPictureAlignment);
       
  1415 					format.iFontPresentation.iPictureAlignment=(TFontPresentation::TAlignment)*ptr;
       
  1416 					}
       
  1417 				ptr+=KCharPictureAlignment;
       
  1418 				break;
       
  1419 
       
  1420 			// Auxiliary attributes for system colours, etc.
       
  1421 			case EAttTextSystemColor:
       
  1422 				if (!old_mask.AttribIsSet(EAttColor))
       
  1423 					ReadSystemColor(ptr,format.iFontPresentation.iTextColor);
       
  1424 				ptr++;
       
  1425 				break;
       
  1426 
       
  1427 			case EAttFontHighlightSystemColor:
       
  1428 				if (!old_mask.AttribIsSet(EAttFontHighlightColor))
       
  1429 					ReadSystemColor(ptr,format.iFontPresentation.iHighlightColor);
       
  1430 				ptr++;
       
  1431 				break;
       
  1432 
       
  1433 			case EAttCharLanguageX:
       
  1434 				if (!old_mask.AttribIsSet(EAttCharLanguage))
       
  1435 					{
       
  1436 					new_mask.SetAttrib(EAttCharLanguage);
       
  1437 					format.iLanguage = Read32(ptr);
       
  1438 					}
       
  1439 				ptr += KCharLanguageX;
       
  1440 				break;
       
  1441 
       
  1442 			// Internal character attributes:
       
  1443 			case EAttParserTag:
       
  1444 				if (!old_mask.AttribIsSet(EAttParserTag))
       
  1445 					{
       
  1446 					new_mask.SetAttrib(EAttParserTag);
       
  1447 					aCharFormat.iParserTag = Read32(ptr);
       
  1448 					}
       
  1449 				ptr += KCharParserTag;
       
  1450 				break;
       
  1451 
       
  1452 			default:	// have maybe read an attribute defined by a later version; stop here
       
  1453 				aMask = new_mask;
       
  1454 				return;
       
  1455 			}
       
  1456 		}
       
  1457 	aMask = new_mask;
       
  1458 	}
       
  1459 
       
  1460 /** Swaps the contents of this stream with aStream.
       
  1461 @param aStream Object to swap contents with. */
       
  1462 void RFormatStream::Swap(RFormatStream& aStream)
       
  1463 	{
       
  1464 	TUint8* t = iBase;
       
  1465 	iBase = aStream.iBase;
       
  1466 	aStream.iBase = t;
       
  1467 	t = iEnd;
       
  1468 	iEnd = aStream.iEnd;
       
  1469 	aStream.iEnd = t;
       
  1470 	}
       
  1471 
       
  1472 TInt RFormatStream::StoreTabs(TUint8*& aPtr,const CParaFormat& aDesiredFormat,const CParaFormat& aCurrentFormat,TBool aStoreData)
       
  1473 // Merges the tabs from the desired paraFormat with those from the current effective paraFormat, resolving differences
       
  1474 // as described below, and store the resultant tablist in this layer.
       
  1475 // If aStoreData is false, then return the number of bytes necessary to store all required tabs
       
  1476 //
       
  1477 	{
       
  1478 	TInt requiredTabCount=0;
       
  1479 	TInt desiredTabCount=aDesiredFormat.TabCount();
       
  1480 	TInt currentTabCount=aCurrentFormat.TabCount();
       
  1481 	if (desiredTabCount==0 && currentTabCount==0)
       
  1482 		{// Nothing needs to be stored.
       
  1483 		return requiredTabCount;
       
  1484 		}
       
  1485 	if (desiredTabCount>0 && currentTabCount>0)
       
  1486 		{// The 2 tab lists need merging.
       
  1487 		requiredTabCount=MergeTabLists(aPtr,aDesiredFormat,desiredTabCount,aCurrentFormat,currentTabCount,aStoreData);
       
  1488 		}
       
  1489 	else if (desiredTabCount>0 && currentTabCount==0)
       
  1490 			{// There are no previous tabs to merge so just store all the desired ones.
       
  1491 			if (aStoreData)
       
  1492 				StoreAllTabs(aPtr,aDesiredFormat);
       
  1493 			else
       
  1494 				requiredTabCount+=desiredTabCount;
       
  1495 			}
       
  1496 		else if (desiredTabCount==0 && currentTabCount>0)
       
  1497 				{// We want to delete (NULL) all existing tabs.
       
  1498 				if (aStoreData)
       
  1499 					{
       
  1500 					for (TInt index=0;index<currentTabCount;index++)
       
  1501 						{
       
  1502 						TTabStop tab=aCurrentFormat.TabStop(index);
       
  1503 						tab.iType=TTabStop::ENullTab;
       
  1504 						StoreTab(aPtr,tab);
       
  1505 						}
       
  1506 					}
       
  1507 				else requiredTabCount+=currentTabCount;
       
  1508 				}
       
  1509 	return requiredTabCount*(KTypeSize+KParaTabStop);
       
  1510 	}
       
  1511 
       
  1512 
       
  1513 TInt RFormatStream::MergeTabLists(TUint8*& aPtr,const CParaFormat& aDesiredFormat,TInt aDesiredTabCount,
       
  1514 								  const CParaFormat& aCurrentFormat,TInt aCurrentTabCount,TBool aStoreData)
       
  1515 // Compares the desired tablist (from a dialog interaction) with that of the current tablist.
       
  1516 // The resulting tab stop is stored if aStoreData is TRUE.
       
  1517 // There may be 2 tabs for any for any given tabstops.
       
  1518 // The possible results of the comparison are:
       
  1519 // (1) Tab is in desired but not current --> Store the desired tab.
       
  1520 // (2) Tab is in current but not desired --> Null the current and store.
       
  1521 // (3) Tab is in both current and desired -->
       
  1522 //			(i) if tab type is the same then store nothing -- rely on the base one being inherited.
       
  1523 //			(ii)if tab type is not same then store the current -- overriding whatevers in the base.
       
  1524 //
       
  1525 	{
       
  1526 	TInt requiredTabCount=0;
       
  1527 	TInt offsetInDesired,offsetInCurrent;
       
  1528 	offsetInDesired=offsetInCurrent=0;
       
  1529 	TTabStop desiredTab,currentTab;
       
  1530 	while ((offsetInDesired!=aDesiredTabCount) && (offsetInCurrent!=aCurrentTabCount))
       
  1531 		{// Do this until we exhaust one of the tab lists.
       
  1532 		desiredTab=aDesiredFormat.TabStop(offsetInDesired);
       
  1533 		currentTab=aCurrentFormat.TabStop(offsetInCurrent);
       
  1534 		if (desiredTab.iTwipsPosition<currentTab.iTwipsPosition)
       
  1535 			{
       
  1536 			if (aStoreData)
       
  1537 				aPtr=StoreTab(aPtr,desiredTab);  // Store desiredTab.
       
  1538 			else 
       
  1539 				requiredTabCount++;
       
  1540 			offsetInDesired++;  // Move to the next tab in the desired tablist.
       
  1541 			continue;
       
  1542 			}
       
  1543 		if (desiredTab.iTwipsPosition>currentTab.iTwipsPosition)
       
  1544 			{
       
  1545 			if (aStoreData)
       
  1546 				{
       
  1547 				currentTab.iType=TTabStop::ENullTab;  // Null the current current tab.
       
  1548 				aPtr=StoreTab(aPtr,currentTab);  // Store NULL'd currentTab
       
  1549 				}
       
  1550 			else
       
  1551 				requiredTabCount++;
       
  1552 			offsetInCurrent++;  // Move to the next tab in the current tablist.
       
  1553 			continue;
       
  1554 			}
       
  1555 		if (desiredTab.iTwipsPosition==currentTab.iTwipsPosition)
       
  1556 			{
       
  1557 			if (desiredTab.iType!=currentTab.iType)
       
  1558 				{// Store desired type to override the one from the lower layer.
       
  1559 				if (aStoreData)
       
  1560 					aPtr=StoreTab(aPtr,desiredTab);
       
  1561 				else
       
  1562 					requiredTabCount++;
       
  1563 				}// Otherwise rely on the one in the base - store nothing but increment.
       
  1564 			offsetInDesired++;
       
  1565 			offsetInCurrent++;
       
  1566 			continue;
       
  1567 			}
       
  1568 		}
       
  1569 	TInt currentLeftToDo=aCurrentTabCount-offsetInCurrent;
       
  1570 	TInt desiredLeftToDo=aDesiredTabCount-offsetInDesired;
       
  1571 	// Spot which list is exhausted and process the rest of the remainder appropriately.
       
  1572 	if (currentLeftToDo)
       
  1573 		{// Store null'd remainder of current tab list.
       
  1574 		for (;offsetInCurrent<aCurrentTabCount;offsetInCurrent++)
       
  1575 			{
       
  1576 			if (aStoreData)
       
  1577 				{
       
  1578 				currentTab=aCurrentFormat.TabStop(offsetInCurrent);
       
  1579 				currentTab.iType=TTabStop::ENullTab;  // Null the current current tab.
       
  1580 				aPtr=StoreTab(aPtr,currentTab);  // Store NULL'd currentTab
       
  1581 				}
       
  1582 			else
       
  1583 				requiredTabCount++;
       
  1584 			}
       
  1585 		}
       
  1586 	if (desiredLeftToDo)
       
  1587 		{// Store remainder of desired tab list.
       
  1588 		for (;offsetInDesired<aDesiredTabCount;offsetInDesired++)
       
  1589 			{
       
  1590 			if (aStoreData)
       
  1591 				aPtr=StoreTab(aPtr,aDesiredFormat.TabStop(offsetInDesired));
       
  1592 			else
       
  1593 				requiredTabCount++;
       
  1594 			}
       
  1595 		}
       
  1596 // ASSERT: The tabList offsets are as we would expect in a normal (correct) completion.	
       
  1597 	__ASSERT_ALWAYS(offsetInDesired==aDesiredTabCount,Panic(EStoreTabError));
       
  1598 	__ASSERT_ALWAYS(offsetInCurrent==aCurrentTabCount,Panic(EStoreTabError));
       
  1599 	return requiredTabCount;
       
  1600 	}
       
  1601 
       
  1602 
       
  1603 // Writes all tabs from aSource.
       
  1604 void RFormatStream::StoreAllTabs(TUint8*& aPtr,const CParaFormat& aSource)
       
  1605 	{
       
  1606 	int tabs = aSource.TabCount();
       
  1607 	for (TInt index = 0;index < tabs; index++)
       
  1608 		aPtr = StoreTab(aPtr,TTabStop(aSource.TabStop(index)));
       
  1609 	}
       
  1610 
       
  1611 
       
  1612 TUint8* RFormatStream::StoreBullet(TUint8* aPtr,const TBullet& aBullet)
       
  1613 	{
       
  1614 	// Write the attribute code and leave a gap for the length.
       
  1615 	*aPtr++ = TUint8(EAttBullet);
       
  1616 	TUint8* length_ptr = aPtr++;
       
  1617 
       
  1618 	// Store the font height.
       
  1619 	Write32(aPtr,aBullet.iHeightInTwips);
       
  1620 
       
  1621 	// Store the bullet character code.
       
  1622 	aPtr[0] = (TUint8)(aBullet.iCharacterCode);
       
  1623 	aPtr[1] = (TUint8)(aBullet.iCharacterCode >> 8);
       
  1624 	aPtr += sizeof(TText);
       
  1625 
       
  1626 	// Store the hanging indent
       
  1627 	*aPtr++ = TUint8(aBullet.iHangingIndent != FALSE);
       
  1628 
       
  1629 	// Store the colour.
       
  1630 	aPtr = Store(aPtr,aBullet.iColor);
       
  1631 
       
  1632 	// Store the typeface
       
  1633 	aPtr = Store(aPtr,aBullet.iTypeface);
       
  1634 
       
  1635 	// Store the number of data bytes stored.
       
  1636 	*length_ptr = (TUint8)(aPtr - length_ptr - 1);
       
  1637 
       
  1638 	return aPtr;
       
  1639 	}
       
  1640 
       
  1641 
       
  1642 TUint8* RFormatStream::StoreBorder(TUint8* aPtr,TTextFormatAttribute aType,const TParaBorder& aSource)
       
  1643 // Stores paragraph border attributes.
       
  1644 // Writes the line style, thickness,autoColor flag
       
  1645 // and Color, from aSource to the end of the format stream.
       
  1646 // aType is converted from an enum to a TUint8 as it is stored in the format stream.
       
  1647 //
       
  1648 	{
       
  1649 	*aPtr++=TUint8(aType);
       
  1650 	// border line style
       
  1651 	*aPtr++=TUint8(aSource.iLineStyle);
       
  1652 	// border line thickness
       
  1653 	Write32(aPtr,aSource.iThickness);
       
  1654 	// border color
       
  1655 	aPtr=Store(aPtr,aSource.iColor);
       
  1656 	// border autocolor
       
  1657 	*aPtr++=TUint8(aSource.iAutoColor!=EFalse);
       
  1658 	return aPtr;
       
  1659 	}
       
  1660 
       
  1661 
       
  1662 TUint8* RFormatStream::StoreTab(TUint8* aPtr,const TTabStop& aSource)
       
  1663 // Stores a tabstop compound attribute at the end of the stream.
       
  1664 // Writes the tabstop twips position and the tab type, from aSource, to the end of the format stream.
       
  1665 // aType is converted from an enum to a TUint8 as it is stored in the format stream.
       
  1666 // The tab type is compressed from a TTabType enum to a TUint8.
       
  1667 // Uses InsertL, which may cause expansion of the stream storage, and thus may fail.
       
  1668 //
       
  1669 	{
       
  1670 	*aPtr++=TUint8(EAttTabStop);
       
  1671 	// Store tab poisition.
       
  1672 	Write32(aPtr,aSource.iTwipsPosition);
       
  1673 	// Compress the tab type.
       
  1674 	*aPtr++=TUint8(aSource.iType);
       
  1675 	return aPtr;
       
  1676 	}
       
  1677 
       
  1678 
       
  1679 TUint8* RFormatStream::Store(TUint8* aPtr,const TLogicalRgb& aRgb)
       
  1680    // Store color value
       
  1681    //
       
  1682    	{
       
  1683 	*aPtr++=TUint8(aRgb.Red());
       
  1684 	*aPtr++=TUint8(aRgb.Green());
       
  1685 	*aPtr++=TUint8(aRgb.Blue());
       
  1686 	return aPtr;
       
  1687    	}
       
  1688 
       
  1689 
       
  1690 TUint8* RFormatStream::Store(TUint8* aPtr,const TTypeface& aTypeface)
       
  1691 // Stores typeface name and flags.
       
  1692 //
       
  1693 	{
       
  1694 	//
       
  1695 	// Store typeface name size
       
  1696 	TUint8 length=TUint8(aTypeface.iName.Size());
       
  1697 	length+=KTypefaceFlags;
       
  1698 	*aPtr++=length;  // byte count.
       
  1699 	//
       
  1700 	// Store typeface name
       
  1701 	aPtr=Mem::Copy(aPtr,aTypeface.iName.Ptr(),length-KTypefaceFlags);
       
  1702 	//
       
  1703 	// Store typeface flags
       
  1704 	TUint8 flags=0;
       
  1705 	if (aTypeface.IsProportional())
       
  1706 		flags|=KFontProportional;
       
  1707 	if (aTypeface.IsSerif())
       
  1708 		flags|=KFontSerif;	
       
  1709 	if (aTypeface.IsSymbol())
       
  1710 		flags|=KFontSymbol;
       
  1711 	*aPtr=flags;
       
  1712 	aPtr+=KTypefaceFlags;
       
  1713 	//
       
  1714 	return aPtr;
       
  1715 	}
       
  1716 
       
  1717 TUint8* RFormatStream::ReadValue(TUint8* aPtr,TLogicalRgb& aRgb)const
       
  1718 // Reads a color value from storage.
       
  1719 //
       
  1720 	{
       
  1721 	aRgb.SetRed(*aPtr++);
       
  1722 	aRgb.SetGreen(*aPtr++);
       
  1723 	aRgb.SetBlue(*aPtr++);
       
  1724 	aRgb.SetSystemColorIndex(0);
       
  1725 	return aPtr;
       
  1726 	}
       
  1727 
       
  1728 
       
  1729 TUint8* RFormatStream::ReadValue(TUint8* aPtr,TParaBorder& aBorder)const
       
  1730 // Reads a paragraph border from storage.
       
  1731 //
       
  1732 	{
       
  1733 	// Read line style
       
  1734 	aBorder.iLineStyle=TParaBorder::TLineStyle(*aPtr++);
       
  1735 	// Read thickness
       
  1736 	aBorder.iThickness = Read32(aPtr);
       
  1737 	aPtr+=sizeof(TInt32);
       
  1738 	// Read color
       
  1739 	aPtr=ReadValue(aPtr,aBorder.iColor);  // returns aPtr
       
  1740 	// Read autocolor
       
  1741 	aBorder.iAutoColor=TBool(*aPtr++);
       
  1742 	return aPtr;
       
  1743 	}
       
  1744 
       
  1745 
       
  1746 TUint8* RFormatStream::ReadValue(TUint8* aPtr,TBullet& aBullet)const
       
  1747 // Read the bullet compound attribute.
       
  1748 //
       
  1749 	{
       
  1750 	// Read the length of this bullet attribute
       
  1751 	aPtr++;  // length not used in this context, skip it
       
  1752 	// Read bullet twips height into target
       
  1753 	aBullet.iHeightInTwips = Read32(aPtr);
       
  1754 	aPtr+=sizeof(TInt32);
       
  1755 	// Read bullet character code into target.
       
  1756 	aBullet.iCharacterCode = (TText)aPtr[0] | ((TText)aPtr[1] << 8);
       
  1757 	aPtr+=sizeof(TText);
       
  1758 	// Read hanging indent.
       
  1759 	aBullet.iHangingIndent=TBool(*aPtr++);
       
  1760 	// Read Color.
       
  1761 	aPtr=ReadValue(aPtr,aBullet.iColor);  // returns aPtr
       
  1762 	// Read typeface
       
  1763 	return ReadValue(aPtr,aBullet.iTypeface);  // returns aPtr
       
  1764 	}
       
  1765 
       
  1766 
       
  1767 TUint8* RFormatStream::ReadValue(TUint8* aPtr,TTypeface& aTypeface)const
       
  1768 // Read a typeface name from storage and associated flags.
       
  1769 //
       
  1770 	{
       
  1771 	//
       
  1772 	// Read typeface name size
       
  1773 	TInt length=*aPtr++;
       
  1774 	//
       
  1775 	// Read typeface name
       
  1776 	TInt typefaceLength=length-KTypefaceFlags;
       
  1777 	__ASSERT_DEBUG((typefaceLength%2)==0,Panic(ECorruptFormatLayer)); // must be an even number
       
  1778 
       
  1779 	TPtr name=aTypeface.iName.Des();
       
  1780 	Mem::Copy(CONST_CAST(TText*,name.Ptr()),aPtr,typefaceLength);
       
  1781 	typefaceLength>>=1;
       
  1782 	name.SetLength(typefaceLength);
       
  1783 
       
  1784 	aPtr+=length-KTypefaceFlags;
       
  1785 	//
       
  1786 	// Read typeface name flags
       
  1787 	TInt attrib=0;
       
  1788 	TUint flags=*aPtr;
       
  1789 	if (flags & KFontProportional)
       
  1790 		attrib|=TTypeface::EProportional;
       
  1791 	if (flags & KFontSerif)
       
  1792 		attrib|=TTypeface::ESerif;
       
  1793 	if (flags & KFontSymbol)
       
  1794 		attrib|=TTypeface::ESymbol;
       
  1795 	aTypeface.SetAttributes(attrib);  // reset the attributes
       
  1796 	return aPtr+KTypefaceFlags;
       
  1797 	}
       
  1798 
       
  1799 
       
  1800 TUint8* RFormatStream::ReadTabL(TUint8* aPtr,CParaFormat& aTarget)const
       
  1801 // Read the tab stop data from the stream, located at aPos, into 
       
  1802 // a temporary TTabStop, and use this to fill in aTarget.
       
  1803 // Does not read the tab if one already exists at the same twips position.
       
  1804 // (Implementation of tab inheritance policy).
       
  1805 // aPos is updated manually, rather than using Length(), since this is
       
  1806 // a compound attribute.
       
  1807 //
       
  1808 	{
       
  1809 	TTabStop tab;
       
  1810 	// Read tab position
       
  1811 	tab.iTwipsPosition = Read32(aPtr);
       
  1812 	aPtr+=sizeof(TInt32);
       
  1813 	// Read tab type
       
  1814 	tab.iType=TTabStop::TTabType(*aPtr++);
       
  1815 	// Set this tab in the paragraph format
       
  1816 	TInt ret=aTarget.LocateTab(tab.iTwipsPosition);		// is this necessary
       
  1817 	if (ret==KTabNotFound)
       
  1818 		aTarget.StoreTabL(tab);
       
  1819 	return aPtr;
       
  1820 	}
       
  1821 
       
  1822 
       
  1823 TInt RFormatStream::Length(TUint8*& aPtr,TTextFormatAttribute aType) const
       
  1824 // Returns the length of a Type's value
       
  1825 // A length of zero in the lookup table, indicates a variable
       
  1826 // length value.  In this case, the length is stored in the byte
       
  1827 // following the type, which is read and returned.
       
  1828 // aPtr is incremented by the appropriate amount following a read.
       
  1829 //
       
  1830 	{
       
  1831 	TInt length=TheAttributeLength[aType];
       
  1832 
       
  1833 	__ASSERT_DEBUG(length>=0,Panic(EAttributeLengthLookupNegative));
       
  1834 	if (length>0)
       
  1835 		return length;
       
  1836 	else
       
  1837 		return *aPtr++;
       
  1838 	}