textrendering/texthandling/stext/TXTRICH.CPP
changeset 0 1fb32624e06b
child 24 71313a964664
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 #include <e32base.h>
       
    21 
       
    22 #include "TXTRICH.H"
       
    23 #include "TXTINDEX.H"
       
    24 #include "TXTSTD.H"
       
    25 #include "TXTRTPFL.H"
       
    26 #include "ParseLst.h"
       
    27 #include "TXTCLIPBOARD.H"
       
    28 
       
    29 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    30 #include "TXTETEXT_INTERNAL.H"
       
    31 #include "TXTRICH_INTERNAL.H"
       
    32 #endif
       
    33 
       
    34 EXPORT_C void CRichText::__DbgTestInvariant()const
       
    35 // Provides class invariants.  Explanations below:
       
    36 //
       
    37 	{
       
    38 #ifdef _DEBUG
       
    39 // ASSERT: The global format layers are never null.
       
    40 	__ASSERT_DEBUG(iGlobalParaFormatLayer != NULL, User::Invariant());
       
    41 	__ASSERT_DEBUG(iGlobalCharFormatLayer != NULL, User::Invariant());
       
    42 	if (IndexPresent())
       
    43 		{
       
    44 // ASSERT: The sum of para lengths == the length as described by the document storage.
       
    45 		TInt cumulativeParaLength = 0;
       
    46 		TInt maxPara = iIndex->iParaIx->Count();
       
    47 		for (TInt offset = 0; offset < maxPara; offset++)
       
    48 			{
       
    49 			TParaAttribsEntry entry = (*iIndex->iParaIx)[offset];
       
    50 			cumulativeParaLength += entry.iLength;
       
    51 			}
       
    52 		__ASSERT_DEBUG(cumulativeParaLength == (DocumentLength() + 1), User::Invariant());
       
    53 		}
       
    54 		// Change here for defect INC005336.
       
    55 		// This defect is present when the assertion below fails.
       
    56 		__ASSERT_DEBUG( (iParserData == NULL) || \
       
    57 			(!iParserData->HaveRange()) || \
       
    58 			(iParserData->EndParse() <= DocumentLength()), User::Invariant());
       
    59 #endif
       
    60 	}
       
    61 
       
    62 EXPORT_C CRichText* CRichText::NewL(const CParaFormatLayer* aGlobalParaLayer,const CCharFormatLayer* aGlobalCharLayer,
       
    63 									TDocumentStorage aStorage,TInt aDefaultTextGranularity,TParaType aParaType)
       
    64 /** Allocates and constructs an empty rich text object, with a global character
       
    65 and paragraph format layer. A single end-of-document delimiter is inserted.
       
    66 No style list is allocated.
       
    67 
       
    68 @param aGlobalParaLayer Pointer to the paragraph format layer referenced by
       
    69 the rich text object. Must not be NULL, or a panic occurs.
       
    70 @param aGlobalCharLayer Pointer to the character format layer referenced by
       
    71 the rich text object. Must not be NULL, or a panic occurs.
       
    72 @param aStorage The type of in-memory buffer to use. Defaults to ESegmentedStorage
       
    73 which should rarely need to be changed.
       
    74 @param aDefaultTextGranularity Specifies the granularity of the in-memory buffer.
       
    75 Default is EDefaultTextGranularity bytes (=256), and this should rarely need
       
    76 to be changed.
       
    77 @param aParaType This argument indicates whether you are using a single paragraph
       
    78 or multiple paragraphs, and thus affects the granularity of aggregate objects
       
    79 used internally for storing paragraph attributes. Default = EMultiPara.
       
    80 @return The rich text object. */
       
    81 	{
       
    82 	// Create new rich text containing just a single end-of-document character.
       
    83 	__ASSERT_ALWAYS(aGlobalParaLayer != NULL, Panic(ENullFormatLayerHandle));
       
    84 	__ASSERT_ALWAYS(aGlobalCharLayer != NULL, Panic(ENullFormatLayerHandle));
       
    85 
       
    86 	CRichText* self = new(ELeave) CRichText(aGlobalParaLayer, aGlobalCharLayer);
       
    87 	CleanupStack::PushL(self);
       
    88 	self->ConstructL(aStorage, aDefaultTextGranularity, aParaType);
       
    89 	CleanupStack::Pop();
       
    90 	return self;
       
    91 	}
       
    92 
       
    93 
       
    94 // Create new rich text that supports Paragraph Styles, containing just a single end-of-document character.
       
    95 EXPORT_C CRichText* CRichText::NewL(const CParaFormatLayer* aGlobalParaLayer,const CCharFormatLayer* aGlobalCharLayer,
       
    96 									const CStyleList& aStyleList,
       
    97 									TDocumentStorage aStorage,TInt aDefaultTextGranularity,TParaType aParaType)
       
    98 /** Allocates and constructs an empty rich text object which supports styles. It
       
    99 is constructed with a global character and paragraph format layer and a style
       
   100 list. A single end-of-document delimiter is inserted. The rich text object
       
   101 takes ownership of the style list.
       
   102 
       
   103 Note:
       
   104 
       
   105 A rich text object not constructed with a style list may still use styles,
       
   106 by calling SetStyleListExternallyOwned() at any time after construction. In
       
   107 this case, the rich text object does not own the style list.
       
   108 
       
   109 @param aGlobalParaLayer Pointer to the paragraph format layer referenced by
       
   110 the rich text object. Must not be NULL, or a panic occurs.
       
   111 @param aGlobalCharLayer Pointer to the character format layer referenced by
       
   112 the rich text object. Must not be NULL, or a panic occurs.
       
   113 @param aStyleList Style list. Holds the set of paragraph styles which can be
       
   114 used in the rich text object.
       
   115 @param aStorage The type of in-memory buffer to use. Defaults to ESegmentedStorage
       
   116 which should rarely need to be changed.
       
   117 @param aDefaultTextGranularity Specifies the granularity of the in-memory buffer.
       
   118 Default is EDefaultTextGranularity bytes (=256), and this should rarely need
       
   119 to be changed.
       
   120 @param aParaType This argument indicates whether you are using a single paragraph
       
   121 or multiple paragraphs, and thus affects the granularity of aggregate objects
       
   122 used internally for storing paragraph attributes. Default = EMultiPara.
       
   123 @return The new rich text object. */
       
   124 	{
       
   125 	__ASSERT_ALWAYS(aGlobalParaLayer != NULL, Panic(ENullFormatLayerHandle));
       
   126 	__ASSERT_ALWAYS(aGlobalCharLayer != NULL, Panic(ENullFormatLayerHandle));
       
   127 
       
   128 	CRichText* self = new(ELeave) CRichText(aGlobalParaLayer, aGlobalCharLayer, CONST_CAST(CStyleList*, &aStyleList));
       
   129 	CleanupStack::PushL(self);
       
   130 	self->ConstructL(aStorage, aDefaultTextGranularity, aParaType);
       
   131 	CleanupStack::Pop();
       
   132 	return self;
       
   133 	}
       
   134 
       
   135 
       
   136 // Restore into a new rich text object, using the specified global layers.
       
   137 EXPORT_C CRichText* CRichText::NewL(const CStreamStore& aStore,TStreamId aStreamId,
       
   138 									const CParaFormatLayer* aGlobalParaLayer,const CCharFormatLayer* aGlobalCharLayer,
       
   139 									MTextFieldFactory* aFieldFactory,
       
   140 									TDocumentStorage aStorage)
       
   141 /** Allocates and constructs a rich text object with a field factory. Its text
       
   142 content is internalized from a stream store.
       
   143 
       
   144 Note:
       
   145 
       
   146 A rich text object not constructed with a field factory may still support
       
   147 the addition of fields, by calling SetFieldFactory(), defined in the base
       
   148 class CPlainText.
       
   149 
       
   150 @param aStore Stream store from which the object is restored.
       
   151 @param aStreamId ID of the stream store.
       
   152 @param aGlobalParaLayer Pointer to the paragraph format layer referenced by
       
   153 the rich text object. Must not be NULL, or a panic occurs.
       
   154 @param aGlobalCharLayer Pointer to the character format layer referenced by
       
   155 the rich text object. Must not be NULL, or a panic occurs.
       
   156 @param aFieldFactory Pointer to a field factory. A field factory must be provided
       
   157 if the text object supports fields.
       
   158 @param aStorage The type of in-memory buffer to use. Defaults to ESegmentedStorage
       
   159 which should rarely need to be changed.
       
   160 @return The new rich text object. */
       
   161 	{
       
   162 	__ASSERT_ALWAYS(aGlobalParaLayer != NULL, Panic(ENullFormatLayerHandle));
       
   163 	__ASSERT_ALWAYS(aGlobalCharLayer != NULL, Panic(ENullFormatLayerHandle));
       
   164 
       
   165 	CRichText* self = new(ELeave) CRichText(aGlobalParaLayer, aGlobalCharLayer);
       
   166 	CleanupStack::PushL(self);
       
   167 	self->ConstructL(aStore, aStreamId, NULL, NULL, aFieldFactory, aStorage);
       
   168 	CleanupStack::Pop();
       
   169 	return self;
       
   170 	}
       
   171 
       
   172 
       
   173 EXPORT_C CRichText* CRichText::NewL(const CStreamStore& aStore, TStreamId aStreamId,
       
   174 									const CParaFormatLayer* aGlobalParaLayer, const CCharFormatLayer* aGlobalCharLayer,
       
   175 									MPictureFactory* aPictureFactory, MRichTextStoreResolver* aStoreResolver,
       
   176 									MTextFieldFactory* aFieldFactory,
       
   177 									TDocumentStorage aStorage)
       
   178 /** Allocates and constructs a rich text object with a field factory and a picture
       
   179 factory. Its text content is internalized from a stream store.
       
   180 
       
   181 Note:
       
   182 
       
   183 A rich text object not constructed with a field factory may still support
       
   184 the addition of fields, by calling SetFieldFactory(), defined in the base
       
   185 class CPlainText.
       
   186 
       
   187 @param aStore Stream store from which the object is restored.
       
   188 @param aStreamId ID of the stream store.
       
   189 @param aGlobalParaLayer Pointer to the paragraph format layer referenced by
       
   190 the rich text object. Must not be NULL, or a panic occurs.
       
   191 @param aGlobalCharLayer Pointer to the character format layer referenced by
       
   192 the rich text object. Must not be NULL, or a panic occurs.
       
   193 @param aPictureFactory The picture factory. This is needed to load pictures
       
   194 into memory, (see PictureHandleL()). If a store resolver is specified (not
       
   195 NULL), then a factory must also be specified, or a panic occurs.
       
   196 @param aStoreResolver A store resolver. This determines which file store the
       
   197 picture is stored in. It is used to get from a reference to an embedded picture
       
   198 within a CRichText object to the actual picture itself. Picture loading is
       
   199 done by the picture factory.
       
   200 @param aFieldFactory Pointer to a field factory. A field factory must be provided
       
   201 if the text object supports fields.
       
   202 @param aStorage The type of in-memory buffer to use. Defaults to ESegmentedStorage
       
   203 which should rarely need to be changed.
       
   204 @return The new rich text object. */
       
   205 	{
       
   206 	// Restore a new rich text from the specified stream, that uses the specified global layers, and the
       
   207 	// specified picture header factory and store, if this rich text supports pictures.
       
   208 	__ASSERT_ALWAYS(!(!aPictureFactory && aStoreResolver), Panic(EInvalidPictureFactorySettings));
       
   209 	__ASSERT_ALWAYS(aGlobalParaLayer != NULL, Panic(ENullFormatLayerHandle));
       
   210 	__ASSERT_ALWAYS(aGlobalCharLayer != NULL, Panic(ENullFormatLayerHandle));
       
   211 
       
   212 	CRichText* self = new(ELeave) CRichText(aGlobalParaLayer, aGlobalCharLayer);
       
   213 	CleanupStack::PushL(self);
       
   214 	self->ConstructL(aStore, aStreamId, aPictureFactory, aStoreResolver, aFieldFactory, aStorage);
       
   215 	CleanupStack::Pop();
       
   216 	return self;
       
   217 	}
       
   218 
       
   219 
       
   220 EXPORT_C CRichText::CRichText(const CParaFormatLayer* aGlobalParaLayer, const CCharFormatLayer* aGlobalCharLayer,
       
   221 							  CStyleList* aStyleList):
       
   222 	CGlobalText(aGlobalParaLayer, aGlobalCharLayer),
       
   223 	iStyleList(aStyleList)
       
   224 	{
       
   225 	}
       
   226 
       
   227 
       
   228 EXPORT_C void CRichText::ConstructL(TDocumentStorage aStorage, TInt aDefaultTextGranularity, TParaType aParaType)
       
   229 // Initialises and updates the index following the CPlainText::ConstructL
       
   230 // insertion of the end-of-document character.
       
   231 //
       
   232 	{
       
   233 	CPlainText::ConstructL(aStorage, aDefaultTextGranularity);
       
   234 	SetParaTypeIsSingle(aParaType == ESinglePara);
       
   235 	iParserData = new(ELeave) CParserData(DocumentLength());
       
   236 	TInt a;
       
   237 	TInt b;
       
   238 	ParseText(a, b, ETrue);
       
   239 
       
   240 	__TEST_INVARIANT;
       
   241 	}
       
   242 
       
   243 
       
   244 EXPORT_C void CRichText::ConstructL(const CStreamStore& aStore,TStreamId aStreamId,
       
   245 									MPictureFactory* aPictureFactory, MRichTextStoreResolver* aStoreResolver,
       
   246 									MTextFieldFactory* aFieldFactory,
       
   247 									TDocumentStorage aStorage)
       
   248 // Initialises and updates the index following the CPlainText::ConstructL
       
   249 // insertion of the end-of-document character.
       
   250 // Sets the picture header factory if provided.
       
   251 //
       
   252 	{
       
   253 	CPlainText::ConstructL(aStore, aStreamId, aFieldFactory, aStorage);
       
   254 	SetPictureFactory(aPictureFactory, aStoreResolver);
       
   255 	if (iParserData == NULL)
       
   256 		iParserData = new(ELeave) CParserData(DocumentLength());
       
   257 	TInt a;
       
   258 	TInt b;
       
   259 	ParseText(a, b, ETrue);
       
   260 
       
   261 	__TEST_INVARIANT;
       
   262 	}
       
   263 
       
   264 
       
   265 EXPORT_C CRichText::~CRichText()
       
   266 /** The destructor frees all resources owned by the rich text object, prior to
       
   267 its destruction. */
       
   268 	{
       
   269 	// We cannot call DestroyParserSystem() here because it applies to all instances in the thread
       
   270 	delete iParserData;
       
   271 	KillStyleList();
       
   272 	KillIndex();
       
   273 	}
       
   274 
       
   275 
       
   276 void CRichText::KillStyleList()
       
   277 // Free up the style table
       
   278 //
       
   279 	{
       
   280 	if (StyleListPresent() && !StyleListExternallyOwned())
       
   281 		{
       
   282 		delete iStyleList.AsPtr();
       
   283 		iStyleList = NULL;
       
   284 		}
       
   285 	}
       
   286 
       
   287 
       
   288 void CRichText::KillIndex()
       
   289 // Delete the rich text index if it's resident in memory.
       
   290 //
       
   291 	{
       
   292 	if (IndexPresent())
       
   293 		delete iIndex.AsPtr();
       
   294 	iIndex=NULL;
       
   295 	}
       
   296 
       
   297 
       
   298 TBool CRichText::CreateEmptyMarkupComponentL()
       
   299 // If necessary, creates an empty markup component.
       
   300 // Returns ETrue if the markup component was created as a result of this function,
       
   301 // otherwise returns EFalse.
       
   302 //
       
   303 	{
       
   304 	if (IndexPresent())
       
   305 		return EFalse;
       
   306 	TInt paraGran = (ParaTypeIsSingle()) ? KSingleParaGranularity : KMultiParaGranularity;
       
   307 	TInt phrGran = (ParaTypeIsSingle()) ? KSmallPhraseGranularity : KLargePhraseGranularity;
       
   308 	iIndex = CRichTextIndex::NewL(iGlobalParaFormatLayer, iGlobalCharFormatLayer, *this,paraGran,phrGran);
       
   309 	return ETrue;
       
   310 	}
       
   311 
       
   312 
       
   313 void CRichText::CreateAndGenerateMarkupComponentL()
       
   314 // Checks if the rich text index needs to be created and does so if necessary.
       
   315 // Called by all public rich text functions that manipulate specific formatting.
       
   316 //
       
   317 	{
       
   318 	if (CreateEmptyMarkupComponentL())
       
   319 		{
       
   320 		TRAPD(ret, GenerateMarkupL());
       
   321 		if (ret != KErrNone)
       
   322 			{// destroy this partially set markup component
       
   323 			delete iIndex.AsPtr();
       
   324 			iIndex = NULL;
       
   325 			User::Leave(ret);
       
   326 			}
       
   327 		}
       
   328 	}
       
   329 
       
   330 
       
   331 void CRichText::GenerateMarkupL()
       
   332 // Generate markup data corresponding to the current text content.
       
   333 //
       
   334 	{
       
   335 	TInt remainingLength = DocumentLength();
       
   336 	TInt startPos = 0;
       
   337 	while (remainingLength)
       
   338 		{
       
   339 		TPtrC buf = Read(startPos);
       
   340 		TInt consumed = buf.Length();
       
   341 		if (consumed > remainingLength)
       
   342 			{
       
   343 			consumed = remainingLength;
       
   344 			buf.Set(buf.Ptr(), consumed);
       
   345 			}
       
   346 		iIndex->InsertL(startPos, buf, *iGlobalParaFormatLayer);
       
   347 		remainingLength -= consumed;
       
   348 		startPos += consumed;
       
   349 		}
       
   350 	}
       
   351 
       
   352 EXPORT_C void CRichText::CopyToStoreL(CStreamStore& aStore,CStreamDictionary& aDictionary,TInt aPos,TInt aLength) const
       
   353 /** Copies a portion of the rich text object, with components to the clipboard.
       
   354 
       
   355 A panic occurs in the following circumstances:
       
   356 
       
   357 aPos is an invalid document position
       
   358 
       
   359 aLength is invalid (zero or less)
       
   360 
       
   361 the sum of aPos and aLength is greater than or equal to the number of characters
       
   362 in the document
       
   363 
       
   364 @param aStore Stream store to which the rich text is written.
       
   365 @param aDictionary The stream dictionary.
       
   366 @param aPos The document position from which to begin copying.
       
   367 @param aLength The number of characters to copy. */
       
   368 	{
       
   369 	if (aLength > 0)
       
   370 		{
       
   371 		TStreamId plainTextId = CPlainText::DoCopyToStoreL(aStore,aDictionary,aPos,aLength);
       
   372 		TStreamId id = DoCopyToStoreL(aStore,aPos,aLength,plainTextId,FALSE);
       
   373 		aDictionary.AssignL(KClipboardUidTypeRichText,id);
       
   374 		TStreamId idStyles = DoCopyToStoreL(aStore,aPos,aLength,plainTextId,TRUE);
       
   375 		aDictionary.AssignL(KClipboardUidTypeRichTextWithStyles,idStyles);
       
   376 		}
       
   377 	}
       
   378 
       
   379 
       
   380 // Copy the selected region of rich text, with components, to the specified store.
       
   381 TStreamId CRichText::DoCopyToStoreL(CStreamStore& aStore,TInt aPos,TInt aLength,TStreamId aPlainTextId,TBool aCopyStyles) const
       
   382 	{
       
   383 	__TEST_INVARIANT;
       
   384 
       
   385 	TInt documentLength = DocumentLength();
       
   386 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= documentLength,Panic(ECharPosBeyondDocument));
       
   387 	__ASSERT_ALWAYS(aLength >= 0,Panic(ECopyToClipboardNegativeLength));
       
   388 	__ASSERT_ALWAYS(aPos + aLength <= documentLength,Panic(ECharPosBeyondDocument));
       
   389 
       
   390 	if (aLength == 0)
       
   391 		return KNullStreamId;
       
   392 
       
   393 	CStoreMap* map = CStoreMap::NewLC(aStore);
       
   394 	CopyComponentsL(aStore,*map,aPos,aLength,aPlainTextId);
       
   395 	RStoreWriteStream stream(*map);
       
   396 	TStreamId id = stream.CreateLC(aStore);
       
   397 	CopyToStreamL(stream,aPos,aLength,aPlainTextId,aCopyStyles);
       
   398 	stream.CommitL();
       
   399 	map->Reset();
       
   400 	CleanupStack::PopAndDestroy(2);
       
   401 
       
   402 	__TEST_INVARIANT;
       
   403 	return id;
       
   404 	}
       
   405 
       
   406 
       
   407 EXPORT_C void CRichText::CopyComponentsL(CStreamStore& aStore,CStoreMap& aMap,TInt aPos,TInt aLength,TStreamId aPlainTextId) const
       
   408 	{
       
   409 	if (aPlainTextId == KNullStreamId)
       
   410 		CPlainText::CopyComponentsL(aStore,aMap,aPos,aLength);
       
   411 	if (IndexPresent())
       
   412 		iIndex->StorePicturesL(aStore,aMap,aPos,aLength);
       
   413 	}
       
   414 
       
   415 
       
   416 // Copy the selected region of rich text and components to the specified stream.
       
   417 EXPORT_C void CRichText::CopyToStreamL(RWriteStream& aStream,TInt aPos,TInt aLength) const
       
   418 	{
       
   419 	__TEST_INVARIANT;
       
   420 	CopyToStreamL(aStream, aPos, aLength, KNullStreamId);
       
   421 	}
       
   422 
       
   423 
       
   424 /*
       
   425 Copy the selected region of rich text and components to the specified stream.
       
   426 If aPlainTextId is NULL the plain text component is stored in-line,
       
   427 otherwise the reference to the plain text stream component is stored.
       
   428 */
       
   429 EXPORT_C void CRichText::CopyToStreamL(RWriteStream& aStream,TInt aPos,TInt aLength,TStreamId aPlainTextId) const
       
   430 	{
       
   431 	CopyToStreamL(aStream,aPos,aLength,aPlainTextId,TRUE);
       
   432 	}
       
   433 
       
   434 
       
   435 void CRichText::CopyToStreamL(RWriteStream& aStream,TInt aPos,TInt aLength,TStreamId aPlainTextId,TBool aCopyStyles) const
       
   436 	{
       
   437 	if (aPlainTextId == KNullStreamId)
       
   438 		{
       
   439 		aStream.WriteUint8L(TRUE);
       
   440 		CPlainText::CopyToStreamL(aStream,aPos,aLength);
       
   441 		}
       
   442 	else
       
   443 		{
       
   444 		aStream.WriteUint8L(FALSE);
       
   445 		aStream << aPlainTextId;
       
   446 		}
       
   447 
       
   448 	if (!IndexPresent())
       
   449 		CONST_CAST(CRichText*,this)->CreateAndGenerateMarkupComponentL();
       
   450 	aStream.WriteUint8L(TRUE);
       
   451 	iIndex->CopyToStreamL(aStream,aPos,aLength,aCopyStyles);
       
   452 	}
       
   453 
       
   454 EXPORT_C TInt CRichText::PasteFromStoreL(const CStreamStore& aStore, const CStreamDictionary& aDictionary, TInt aPos, CParagraphStyle::TStylePasteMode aStylePasteMode)
       
   455 /** Pastes the contents of the clipboard into the rich text object at the
       
   456 specified document position. Returns the number of characters pasted.
       
   457 
       
   458 If the text in the clipboard has been formatted using styles, the
       
   459 aStylePasteMode argument indicates whether the styles should be preserved
       
   460 or discarded. If the argument is not specified, the pasted rich text
       
   461 retains all formatting specified in the styles, and any new style
       
   462 definitions are added to the style list of the rich text object into which
       
   463 it is pasted.
       
   464 
       
   465 @param aStore The stream store from which to paste the rich text.
       
   466 @param aDictionary The stream dictionary.
       
   467 @param aPos The document position at which to paste the rich text. Must be
       
   468 valid, or a panic occurs.
       
   469 @param aStylePasteMode Indicates whether styles in the pasted text should be
       
   470 preserved or discarded.
       
   471 @return The number of characters pasted. */
       
   472 	{
       
   473 	return DoPasteRtFromStoreL(aStore, aDictionary, aPos, aStylePasteMode);
       
   474 	}
       
   475 
       
   476 
       
   477 EXPORT_C TInt CRichText::PasteFromStoreL(const CStreamStore& aStore, const CStreamDictionary& aDictionary, TInt aPos)
       
   478 // Paste the lesser of i) aMaxPasteLength ii) the entire clipboard contents.
       
   479 // Return a count of the number of characters pasted.
       
   480 //
       
   481 	{
       
   482 	return DoPasteRtFromStoreL(aStore, aDictionary, aPos, CParagraphStyle::EAddNewStyles);
       
   483 	}
       
   484 
       
   485 
       
   486 TInt CRichText::DoPasteRtFromStoreL(const CStreamStore& aStore, const CStreamDictionary& aDictionary, TInt aPos, CParagraphStyle::TStylePasteMode aStylePasteMode)
       
   487 // Paste the rich text data from the specified clipboard, inserting it into this
       
   488 // instance at character position aPos.  Returns the number of characters pasted.
       
   489 // May be 0.
       
   490 //
       
   491 	{
       
   492 	__TEST_INVARIANT;
       
   493 	__ASSERT_ALWAYS(aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
   494 
       
   495 	TUid type = KClipboardUidTypeRichTextWithStyles;
       
   496 	TStreamId id = aDictionary.At(type);
       
   497 	if (id == KNullStreamId)
       
   498 		{
       
   499 		type = KClipboardUidTypeRichText;
       
   500 		id = aDictionary.At(type);
       
   501 		}
       
   502 	if (id == KNullStreamId)
       
   503 		{
       
   504 		type = KClipboardUidTypePlainText;
       
   505 		id = aDictionary.At(type);
       
   506 		}
       
   507 	TInt consumed = 0;
       
   508 	if (id == KNullStreamId)
       
   509 		return consumed;
       
   510 	if (type == KClipboardUidTypeRichText || type == KClipboardUidTypeRichTextWithStyles)
       
   511 		consumed = PasteRichTextFromStoreL(aStore, aDictionary, id, aPos, aStylePasteMode);
       
   512 	else if (type == KClipboardUidTypePlainText)
       
   513 		consumed = PastePlainTextFromStoreL(aStore, id, aPos);
       
   514 
       
   515 	if (consumed)
       
   516 		{
       
   517 		iParserData->MergeRange(aPos,0,consumed);
       
   518 		CallEditObserver(aPos, consumed);
       
   519 		}
       
   520 
       
   521 	SetHasChanged(ETrue);
       
   522 	__TEST_INVARIANT;
       
   523 	return consumed;
       
   524 	}
       
   525 
       
   526 
       
   527 TInt CRichText::PasteRichTextFromStoreL(const CStreamStore& aStore, const CStreamDictionary& aDictionary, TStreamId& aRichTextStreamId, TInt aPos,CParagraphStyle::TStylePasteMode aStylePasteMode)
       
   528 // Paste the plain text stream, then open and paste the rich text markup from the specified stream.
       
   529 //
       
   530 	{
       
   531 	if (!IndexPresent())
       
   532 		CreateAndGenerateMarkupComponentL();  // create the index if it does not already exist
       
   533 	TStreamId id = aDictionary.At(KClipboardUidTypePlainText);
       
   534 // ASSERT: We have rich text, so the plain text stream must exist.
       
   535 	__ASSERT_ALWAYS(id != KNullStreamId,Panic(EClipboardIntegrity));
       
   536 	TInt consumed = CPlainText::DoPasteFromStoreL(aStore, id, aPos);
       
   537 	TRAPD(ret, CompletePasteRichTextFromStoreL(aStore, aRichTextStreamId, aPos, aStylePasteMode));
       
   538 	if (ret != KErrNone)
       
   539 		{
       
   540 		CPlainText::Delete(aPos,consumed);
       
   541 		User::Leave(ret);
       
   542 		}
       
   543 	return consumed;
       
   544 	}
       
   545 
       
   546 
       
   547 void CRichText::CompletePasteRichTextFromStoreL(const CStreamStore& aStore, TStreamId& aRichTextStreamId, TInt aPos, CParagraphStyle::TStylePasteMode aStylePasteMode)
       
   548 //
       
   549 	{
       
   550 	RStoreReadStream stream;
       
   551 	stream.OpenLC(aStore, aRichTextStreamId);
       
   552 	TBool plainTextInline = (TBool)stream.ReadUint8L();
       
   553 	if (!plainTextInline)
       
   554 		{
       
   555 		TStreamId dummy;
       
   556 		stream >> dummy;
       
   557 		}
       
   558 	TBool markupPresentInClipboard = (TBool)stream.ReadUint8L();
       
   559 	if (markupPresentInClipboard)
       
   560 		iIndex->PasteFromStreamL(aStore, stream, aPos,aStylePasteMode, iGlobalParaFormatLayer, iGlobalCharFormatLayer);
       
   561 	CleanupStack::PopAndDestroy();  // stream
       
   562 	}
       
   563 
       
   564 
       
   565 TInt CRichText::PastePlainTextFromStoreL(const CStreamStore& aStore, TStreamId& anId, TInt aPos)
       
   566 // Paste the plain text stream, then update the rich text index to show any paragraph delimiters pasted.
       
   567 //
       
   568 	{
       
   569 	TInt consumed = CPlainText::DoPasteFromStoreL(aStore, anId, aPos);
       
   570 	//
       
   571 	if (IndexPresent())
       
   572 		{
       
   573 		TRAPD(ret, CompletePastePlainTextL(aPos, consumed));
       
   574 		if (ret != KErrNone)
       
   575 			{
       
   576 			CPlainText::Delete(aPos,consumed);
       
   577 			User::Leave(ret);
       
   578 			}
       
   579 		}
       
   580 	return consumed;
       
   581 	}
       
   582 
       
   583 void CRichText::CompletePastePlainTextL(TInt aPos, TInt aCharacterCount)
       
   584 // Updates the rich text index following the pasting of global text.
       
   585 //
       
   586 	{
       
   587 	HBufC* buf = HBufC::NewLC(aCharacterCount);
       
   588 	TPtr bf = buf->Des();
       
   589 	Extract(bf, aPos, aCharacterCount);
       
   590 	iIndex->InsertL(aPos, bf, *iGlobalParaFormatLayer);
       
   591 	CleanupStack::PopAndDestroy();  // buf
       
   592 	}
       
   593 
       
   594 EXPORT_C void CRichText::Reset()
       
   595 /** Resets the document's contents to a single end-of-document delimiter. Also
       
   596 deletes the style list if owned by the object. */
       
   597 	{
       
   598 	// Resets document contents to single end-of-document charcter,
       
   599 	// and resets the index to match document content.
       
   600 	TInt length = DocumentLength();
       
   601 	CPlainText::Reset();  // remove all content bar eod character
       
   602 	KillStyleList();  // does not get destroyed if externally owned
       
   603 	KillIndex();
       
   604 	SetHasChanged(ETrue);
       
   605 	iParserData->KillRange();
       
   606 	iParserData->iLastKnownCursor = -1;
       
   607 	CallEditObserver(0, -length);
       
   608 
       
   609 	__TEST_INVARIANT;
       
   610 	}
       
   611 
       
   612 EXPORT_C void CRichText::InsertL(TInt aPos, const TChar& aChar)
       
   613 /** Inserts either a single character or a descriptor into the text object
       
   614 at a specified document position.
       
   615 
       
   616 The insertion position must be valid or a panic occurs.Note:A panic
       
   617 occurs if the text object is in an "insert pending" state (i.e.
       
   618 SetInsertCharFormatL() has been called and has not been
       
   619 cancelled using CancelInsertCharFormat()) and aPos is not
       
   620 the same as the insertion point.
       
   621 
       
   622 @param aPos The document position at which to insert the character/descriptor.
       
   623 @param aChar The character to insert. Must not be a picture character or a
       
   624 panic occurs.
       
   625 @param aBuf The descriptor to insert. */
       
   626 	{
       
   627 	__TEST_INVARIANT;
       
   628 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
   629 	__ASSERT_ALWAYS(aChar!= EPictureCharacter, Panic(ENonOverloadedInsertCalledWithPictureCharacter));
       
   630 
       
   631 	TBuf<1> content;
       
   632 	content.Append(aChar);
       
   633 	RtInsertL(aPos, content);
       
   634 
       
   635 	__TEST_INVARIANT;
       
   636 	}
       
   637 
       
   638 
       
   639 EXPORT_C void CRichText::InsertL(TInt aPos, const TDesC& aBuf)
       
   640 // Inserts the contents of aBuf into the text component at character position aPos.
       
   641 //
       
   642 	{
       
   643 	__ETEXT_WATCH(INSERT_DESC);
       
   644 
       
   645 	RtInsertL(aPos, aBuf);
       
   646 
       
   647 	__ETEXT_WATCH_END(INSERT_DESC);
       
   648 	}
       
   649 
       
   650 
       
   651 EXPORT_C void CRichText::RtInsertL(TInt aPos, const TDesC& aBuf)
       
   652 // Inserts the contents a aBuf into the text component at position aPos.
       
   653 // Updates the index accordingly, and accounts for all embedded paragraph delimiters
       
   654 // in the passed buffer aBuf.
       
   655 //
       
   656 	{
       
   657 	__TEST_INVARIANT;
       
   658 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
   659 
       
   660 	int length = aBuf.Length();
       
   661 	CPlainText::InsertL(aPos, aBuf);
       
   662 	if (IndexPresent())
       
   663 		{
       
   664 		TRAPD(ret, iIndex->InsertL(aPos, aBuf, *iGlobalParaFormatLayer));
       
   665 		if (ret != KErrNone)
       
   666 			{
       
   667 			CPlainText::Delete(aPos,length);
       
   668 			User::Leave(ret);
       
   669 			}
       
   670 		SetHasChanged(ETrue);
       
   671 		}
       
   672 
       
   673 	iParserData->MergeRange(aPos,0,length);
       
   674 	CallEditObserver(aPos,length);
       
   675 
       
   676 	__TEST_INVARIANT;
       
   677 	}
       
   678 
       
   679 
       
   680 EXPORT_C void CRichText::InsertL(TInt aPos,const TPictureHeader& aHeader)
       
   681 /**Inserts a picture header into the text object at a specified document
       
   682 position. The picture header specified must reference a valid picture, or
       
   683 a panic occurs.
       
   684 
       
   685 A panic also occurs if the text object is in an "insert pending" state
       
   686 (SetInsertCharFormatL() has been called and has not been cancelled using
       
   687 CancelInsertCharFormat()) and aPos is not the same as the insertion point.
       
   688 
       
   689 This method takes ownership of a picture referenced in aHeader.
       
   690 
       
   691 @param aPos The document position at which to insert the picture header. Must
       
   692 be valid, or a panic occurs.
       
   693 @param aHeader A picture header. This holds a pointer to the picture to insert,
       
   694 and information about the picture. */
       
   695 	{
       
   696 	__TEST_INVARIANT;
       
   697 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
   698 
       
   699 	CleanupStack::PushL(aHeader.iPicture);
       
   700 
       
   701 	if (!IndexPresent())
       
   702 		CreateAndGenerateMarkupComponentL();
       
   703 	TBuf<1> picture;
       
   704 	picture.Append(EPictureCharacter);
       
   705 	CPlainText::InsertL(aPos, picture);
       
   706 
       
   707     CleanupStack::Pop(aHeader.iPicture);
       
   708 
       
   709 	TBool pictureOwnershipTaken(EFalse);
       
   710 	TRAPD(ret, iIndex->InsertL(aPos, aHeader,pictureOwnershipTaken));
       
   711 	if (ret != KErrNone)
       
   712 		{
       
   713 		if(!pictureOwnershipTaken)
       
   714 		    {
       
   715 		    const_cast <TPictureHeader&> (aHeader).DeletePicture();
       
   716 		    }
       
   717 		CPlainText::Delete(aPos,picture.Length());  // remove the picture place-holder
       
   718     	User::Leave(ret);
       
   719 		}
       
   720 
       
   721 	SetHasChanged(ETrue);
       
   722 	iParserData->MergeRange(aPos,0,1);
       
   723 	CallEditObserver(aPos,1);
       
   724 	__TEST_INVARIANT;
       
   725 	}
       
   726 
       
   727 
       
   728 EXPORT_C TBool CRichText::DeleteL(TInt aPos, TInt aLength)
       
   729 /** Deletes one or more characters beginning at, and including, the character at
       
   730 a specified document position. Can leave because paragraphs may be merged
       
   731 and reformatted by the function.
       
   732 
       
   733 @param aPos The start of the range of characters to delete. Must be valid
       
   734 or a panic occurs.
       
   735 @param aLength The number of characters to delete. Must be positive or a panic
       
   736 occurs. The sum of aPos and aLength must be less than the document length,
       
   737 or a panic occurs.
       
   738 @return Indicates whether two paragraphs have been merged as a result of the
       
   739 delete, indicating that the formatting of part of the resulting paragraph
       
   740 may have changed. */
       
   741 	{
       
   742 	// Deletes aRange number of characters from the text component
       
   743 	// and the corresponding index data.
       
   744 	// Delete commences at, and includes, character position aPos.
       
   745 	__TEST_INVARIANT;
       
   746 
       
   747 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
   748 	__ASSERT_ALWAYS(aLength >= 0, Panic(EDebugDeleteZeroLength));
       
   749 	__ASSERT_ALWAYS(aPos + (aLength - 1) <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
   750 
       
   751 	TBool requireMerge = EFalse;
       
   752 	if (!IndexPresent())
       
   753 		CPlainText::Delete(aPos,aLength);
       
   754 	else
       
   755 		{
       
   756 		iIndex->CancelInsertCharFormat();
       
   757 		TIndexDeleteInfo info;
       
   758 		iIndex->SetForDeleteL(info, aPos, aLength);
       
   759 		CPlainText::Delete(aPos,aLength);
       
   760 		requireMerge = iIndex->DeleteNow(info);
       
   761 		}
       
   762 	iParserData->MergeRange(aPos,aLength,0);
       
   763 	CallEditObserver(aPos,-aLength);
       
   764 
       
   765 	__TEST_INVARIANT;
       
   766 	return requireMerge;
       
   767 	}
       
   768 
       
   769 EXPORT_C void CRichText::DeleteParagraph(TInt aPos, TInt aLength)
       
   770 /** Deletes one or more whole paragraphs of text. No paragraphs can be merged together
       
   771 by this function, so it cannot leave it must only be used to delete entire
       
   772 paragraphs.
       
   773 
       
   774 @param aPos The document position of the start of the first paragraph to delete.
       
   775 Must be a valid position or a panic occurs.
       
   776 @param aLength The number of characters to delete. */
       
   777 	{
       
   778 	// Use to remove entire paragraphs of text.
       
   779 	// Leave-safe if called in this context.
       
   780 	// MUST NOT CALL if not in this context.
       
   781 	__TEST_INVARIANT;
       
   782 
       
   783 	// Store the length of the text before we commence with deletions.
       
   784 	TInt initialDocLen=DocumentLength();
       
   785 
       
   786 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= initialDocLen, Panic(ECharPosBeyondDocument));
       
   787 	__ASSERT_ALWAYS(aPos + aLength <= initialDocLen + 1, Panic(ECharPosBeyondDocument));
       
   788 
       
   789 	if (aLength <= 0)
       
   790 		return;
       
   791 
       
   792 	if (IndexPresent())
       
   793 		iIndex->DeleteParagraph(aPos, aLength);
       
   794 	CPlainText::Delete(aPos,aLength);
       
   795 
       
   796 	// Change here for defect INC005336.
       
   797 	// Previously the MergeRange call (see else line) was incorrectly handling
       
   798 	// the scenario where all but the first paragraph was deleted e.g. pasting
       
   799 	// multi line buffer into a single line text control in a new email on Techview
       
   800 	// emulator.
       
   801 	// This was because the deletion in the two lines above would delete the
       
   802 	// 'end-of-text' maker causing the iEndParse member of CParserData to
       
   803 	// index the char right after the end of test marker. This would panic
       
   804 	// plugin parsers thatsubsquently executed.
       
   805 
       
   806 	if (aPos+aLength > initialDocLen)
       
   807 		// When deletion includes the end-of-text marker, adjust start
       
   808 		// supplied so that it appears to MergeRange that we are
       
   809 		// deleting the paragraph and CR just before it which belongs
       
   810 		// to the previous paragraph and not the end-of-text marker.
       
   811 		// This is actually the end result of the deletion anyway!
       
   812 		iParserData->MergeRange(initialDocLen-aLength,aLength,0);
       
   813 	else
       
   814 		// All other deletions which don't.
       
   815 		iParserData->MergeRange(aPos,aLength,0);
       
   816 
       
   817 	CallEditObserver(aPos,-aLength);
       
   818 
       
   819 	__TEST_INVARIANT;
       
   820 	}
       
   821 
       
   822 EXPORT_C void CRichText::DeleteFromParagraph(TInt aPos, TInt aLength)
       
   823 /** Removes a range of characters from within a single paragraph only. Should not
       
   824 be used for deleting an entire paragraph or paragraphs because this may cause
       
   825 it to leave. Otherwise, it is guaranteed not to leave.
       
   826 
       
   827 @param aPos The document position of the start of the range of characters
       
   828 to delete. Must be a valid document position, or a panic occurs.
       
   829 @param aLength The number of characters to delete. The sum of aPos and aLength
       
   830 must be less than the document length, or a panic occurs. */
       
   831 	{
       
   832 	// Removes aLength characters from *within* a single paragraph only.
       
   833 	// Guaranteed not to leave if this pre-condition holds true.
       
   834 	__TEST_INVARIANT;
       
   835 
       
   836 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
   837 	__ASSERT_ALWAYS(aPos + (aLength - 1) <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
   838 
       
   839 	if (aLength <= 0)
       
   840 		return;
       
   841 
       
   842 	if (IndexPresent())
       
   843 		iIndex->DeleteFromParagraph(aPos, aLength);
       
   844 	CPlainText::Delete(aPos,aLength);
       
   845 	iParserData->MergeRange(aPos,aLength,0);
       
   846 	CallEditObserver(aPos,-aLength);
       
   847 
       
   848 	__TEST_INVARIANT;
       
   849 	}
       
   850 
       
   851 EXPORT_C TInt CRichText::ParagraphCount()const
       
   852 /** Gets a count of the number of paragraphs in the text object.
       
   853 
       
   854 Note:
       
   855 
       
   856 The paragraph delimiter which terminates every text object means this function
       
   857 always returns a count of at least one.
       
   858 
       
   859 @return The number of paragraphs in the document. */
       
   860 	{
       
   861 	// Returns a count of the number of paragraphs
       
   862 	// in the document.
       
   863 	//
       
   864 	__TEST_INVARIANT;
       
   865 
       
   866 	if (IndexPresent())
       
   867 		return iIndex->ParagraphCount();
       
   868 	else
       
   869 		return CPlainText::ParagraphCount();
       
   870 	}
       
   871 
       
   872 
       
   873 EXPORT_C TEtextComponentInfo CRichText::ComponentInfo() const
       
   874 /** Gets information about the number of components contained in the text object
       
   875 (the field count, the picture count and the style count).
       
   876 
       
   877 @return Contains the component information. */
       
   878 	{
       
   879 	return TEtextComponentInfo(FieldCount(), PictureCount(), StyleCount());
       
   880 	}
       
   881 
       
   882 EXPORT_C TInt CRichText::CharPosOfParagraph(TInt& aLength, TInt aParaOffset) const
       
   883 /** Finds the length and the start position of a paragraph identified by its
       
   884 paragraph number. The first paragraph is numbered zero.
       
   885 
       
   886 Notes:
       
   887 
       
   888 if aParaOffset is invalid, (equal to or greater than the total number of
       
   889 paragraphs), the function's return value is EScanEndOfData (= -1)
       
   890 
       
   891 @param aLength On return contains the length of the specified paragraph.
       
   892 @param aParaOffset The paragraph number. The first paragraph is numbered zero.
       
   893 @return The document position of the first character in the paragraph. */
       
   894 	{
       
   895 	// Returns the character position of the first character of paragraph aParaOffset,
       
   896 	// where aParaOffset specifies the nth paragraph.
       
   897 	// The length of this nth paragraph is written to aLength.
       
   898 	//
       
   899 	// If aParaOffset specifies a paragraph that does not exist, EScanEndOfData is returned.
       
   900 	//
       
   901 	__TEST_INVARIANT;
       
   902 
       
   903 	if (IndexPresent())
       
   904 		return iIndex->CharPosOfParagraph(aLength, aParaOffset);
       
   905 	else
       
   906 		return CPlainText::CharPosOfParagraph(aLength, aParaOffset);
       
   907 	}
       
   908 
       
   909 EXPORT_C TInt CRichText::ParagraphNumberForPos(TInt& aPos) const
       
   910 /** Gets the number of the paragraph which contains a document position.
       
   911 Paragraph numbering begins at zero.
       
   912 
       
   913 @param aPos A document position. Must be valid or a panic occurs. On return,
       
   914 contains the document position of the first character in the paragraph in
       
   915 which it is located.
       
   916 @return The number of the paragraph containing the specified document position. */
       
   917 	{
       
   918 	// Returns the paragraph offset for the specified character position aPos.
       
   919 	// aPos is in turn modified to hold the character position of the first character
       
   920 	// of this paragraph.  If aPos is already on a paragraph boundary then do nothing.
       
   921 	//
       
   922 	__TEST_INVARIANT;
       
   923 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
   924 
       
   925 	if (IndexPresent())
       
   926 		return iIndex->ParagraphNumberForPos(aPos);
       
   927 	else
       
   928 		return CPlainText::ParagraphNumberForPos(aPos);
       
   929 	}
       
   930 
       
   931 /** Applies character formatting to a zero length selection, for example
       
   932 turning bold on. This has the effect that the formatting will be applied to
       
   933 text subsequently inserted at the position. This "insert pending" state is
       
   934 cancelled by calling CancelInsertCharFormat().
       
   935 
       
   936 Note 1: After calling this function, if text is inserted at a different
       
   937 position to aPos, a panic will occur, unless CancelInsertCharFormat() has been
       
   938 called before the insertion to cancel the "insert pending" state.
       
   939 
       
   940 Note 2: If the insert character format is being set for the end of the
       
   941 paragraph, the paragraph delimiter is set to that format as well. This helps
       
   942 end-of-paragraph behaviour be more similar to other places.
       
   943 
       
   944 @param aFormat The character format values to apply.
       
   945 @param aMask Character format mask specifying the attributes affected.
       
   946 @param aPos The document position at which to insert the character format.
       
   947 @pre aPos must be a valid position, or a panic will occur. */
       
   948 EXPORT_C void CRichText::SetInsertCharFormatL(const TCharFormat& aFormat,
       
   949 	const TCharFormatMask& aMask, TInt aPos)
       
   950 	{
       
   951 	SetExtendedInsertCharFormatL(aFormat, aMask,aPos);
       
   952 	}
       
   953 
       
   954 void CancelInsertCharFormat(TAny* aCRichTextIndex)
       
   955 	{
       
   956 	reinterpret_cast<CRichTextIndex*>(aCRichTextIndex)->CancelInsertCharFormat();
       
   957 	}
       
   958 
       
   959 void CRichText::SetExtendedInsertCharFormatL(const TCharFormatX& aFormat, const TCharFormatXMask& aMask, TInt aPos)
       
   960 	{
       
   961 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
   962 	CreateAndGenerateMarkupComponentL();
       
   963 	CRichTextIndex* index = iIndex.AsPtr();
       
   964 	if (index->InsertCharFormatIsActive())
       
   965 		{
       
   966 		TCharFormatX format = aFormat;
       
   967         TCharFormatXMask mask = aMask;
       
   968         CCharFormatLayer* currentLayer = index->GetCurrentInsertCharFormat();
       
   969         currentLayer->Sense(format,mask);
       
   970 		CCharFormatLayer* newLayer = CCharFormatLayer::NewCopyBaseL(currentLayer);
       
   971 		CleanupStack::PushL(newLayer);
       
   972         newLayer->SetL(format,mask);
       
   973 		if (Read(aPos, 1)[0] == EParagraphDelimiter)
       
   974 			index->ApplyCharFormatL(aFormat, aMask, aPos, 1, EFalse);
       
   975 		if (index->InsertCharFormatIsActive())
       
   976 			{
       
   977 			currentLayer = index->GetCurrentInsertCharFormat();
       
   978 			currentLayer->Swap(*newLayer);
       
   979 			}
       
   980 		CleanupStack::PopAndDestroy(newLayer);
       
   981 		}
       
   982 	else
       
   983 		{
       
   984 		TCleanupItem cleanup(::CancelInsertCharFormat, index);
       
   985 		CleanupStack::PushL(cleanup);
       
   986 		index->NewInsertCharFormatL(aFormat, aMask, aPos);
       
   987 		if (Read(aPos, 1)[0] == EParagraphDelimiter)
       
   988 			index->ApplyCharFormatL(aFormat, aMask, aPos, 1, EFalse);
       
   989 		CleanupStack::Pop();
       
   990 		}
       
   991 	SetHasChanged(TRUE);
       
   992 	}
       
   993 	
       
   994 EXPORT_C void CRichText::ExtendedInterface(TAny*& aInterface, TUid aInterfaceId)
       
   995 /**
       
   996 Returns the interface corresponding to the specified UID if it exists, or 0 if not. 
       
   997 Overridden versions should base call rather than returning 0.
       
   998 For KUidRichText, CRichText will be returned if rich text is supported.
       
   999 
       
  1000 @param aInterfaceId The UID indicating the interface to return
       
  1001 @param aInterface The interface corresponding to aInterfaceId
       
  1002 if it is supported, or 0 if it is not
       
  1003 */
       
  1004 	{ 
       
  1005 	if(KUidRichText == aInterfaceId) 
       
  1006 		{
       
  1007 		aInterface = REINTERPRET_CAST(TAny*, this);
       
  1008 		}
       
  1009 	else
       
  1010 		{
       
  1011 	    CGlobalText::ExtendedInterface(aInterface, aInterfaceId);
       
  1012 		}
       
  1013 	}
       
  1014 
       
  1015 EXPORT_C TBool CRichText::DelSetInsertCharFormatL(TInt aPos, TInt aLength)
       
  1016 /** Deletes a range of characters. The range affected is from aPos to
       
  1017 aPos+(aLength-1) inclusive. It differs from DeleteL() in that this function
       
  1018 preserves the formatting of the deleted character at position aPos, so that
       
  1019 any text subsequently inserted at aPos will have that formatting applied to it.
       
  1020 
       
  1021 A panic occurs if:
       
  1022 
       
  1023 after calling this function, text is inserted at a different position to aPos,
       
  1024 without calling CancelInsertCharFormat() before the insertion
       
  1025 
       
  1026 aPos is invalid
       
  1027 
       
  1028 aLength is negative
       
  1029 
       
  1030 the range goes beyond the end of the document
       
  1031 
       
  1032 @param aPos The document position of the first character to delete.
       
  1033 @param aLength The number of characters to delete.
       
  1034 @return ETrue if two paragraphs have been merged as a result of the deletion;
       
  1035 EFalse if there has been no paragraph merge. */
       
  1036 	{
       
  1037 	// Delete aLength characters, commencing at, and including, aPos.
       
  1038 	// If aPos is on a phrase boundary, and the whole phrase or more is deleted then
       
  1039 	// remember temporarily the phrase format.  This is applied to any content that is
       
  1040 	// immediately inserted.
       
  1041 	//
       
  1042 	__TEST_INVARIANT;
       
  1043 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1044 	__ASSERT_ALWAYS(aLength >= 0, Panic(EDebugDeleteZeroLength));
       
  1045 	__ASSERT_ALWAYS(aPos + (aLength - 1) <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1046 
       
  1047 	TBool parasMerged = EFalse;
       
  1048 	if (!IndexPresent())
       
  1049 		CPlainText::DeleteL(aPos, aLength);
       
  1050 	else
       
  1051 		{
       
  1052 		parasMerged = iIndex->DelSetInsertCharFormatL(aPos, aLength);
       
  1053 		CPlainText::Delete(aPos,aLength);
       
  1054 		SetHasChanged(ETrue);
       
  1055 		}
       
  1056 	iParserData->MergeRange(aPos,aLength,0);
       
  1057 	CallEditObserver(aPos,-aLength);
       
  1058 
       
  1059 	__TEST_INVARIANT;
       
  1060 	return parasMerged;
       
  1061 	}
       
  1062 
       
  1063 EXPORT_C void CRichText::CancelInsertCharFormat()
       
  1064 /** Cancels the "insert pending" state set by a call to SetInsertCharFormatL()
       
  1065 or DelSetInsertCharFormatL().
       
  1066 
       
  1067 This function removes the restriction on the text insertion position imposed
       
  1068 by these two functions. It is recommended that it is called before every cursor
       
  1069 movement, scroll, paste, etc. This call is a small overhead, and has no effect
       
  1070 if not applicable. */
       
  1071 	{
       
  1072 	// Cancels the transitory state where a specified character format
       
  1073 	// is applied *on top of* any inherited formatting.  eg, when bold is on.
       
  1074 	// Cancel when: (1) the text position is altered.  (2) the first character
       
  1075 	// has been inserted following the setting of this state.
       
  1076 	//
       
  1077 	if (IndexPresent() && iIndex->InsertCharFormatIsActive())
       
  1078 		{
       
  1079 		iIndex->CancelInsertCharFormat();
       
  1080 		SetHasChanged(ETrue);
       
  1081 		}
       
  1082 	}
       
  1083 
       
  1084 EXPORT_C void CRichText::ApplyParaFormatL(const CParaFormat* aFormat, const TParaFormatMask& aMask, TInt aPos, TInt aLength)
       
  1085 /** Applies paragraph formatting to a range of paragraphs. The attributes which
       
  1086 are set in the mask are taken from aFormat and applied. The attributes which
       
  1087 are not set in the mask are not changed.
       
  1088 
       
  1089 The region affected consists of every paragraph containing one or more
       
  1090 characters in the range aPos to aPos+(aLength-1).
       
  1091 
       
  1092 @param aFormat Contains the paragraph format attribute values to apply.
       
  1093 @param aMask Specifies which paragraph format attributes should be affected.
       
  1094 @param aPos The document position of the start of the range.
       
  1095 @param aLength The number of characters in the range. */
       
  1096 	{
       
  1097 	// Applies the specified format attributes to the paragraphs covering
       
  1098 	// character position aPos to aPos+aLength-1.
       
  1099 	//
       
  1100 	__TEST_INVARIANT;
       
  1101 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1102 	__ASSERT_ALWAYS(aLength >= 0,Panic(EApplyParaFormatNegativeLength));
       
  1103 	__ASSERT_ALWAYS(aPos + (aLength - 1) <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1104 
       
  1105 	CreateAndGenerateMarkupComponentL();
       
  1106 	iIndex->ApplyParaFormatL(aFormat, aMask, aPos, aLength);
       
  1107 	SetHasChanged(ETrue);
       
  1108 
       
  1109 	__TEST_INVARIANT;
       
  1110 	}
       
  1111 
       
  1112 EXPORT_C void CRichText::ApplyCharFormatL(const TCharFormat& aFormat, const TCharFormatMask& aMask, TInt aPos, TInt aLength)
       
  1113 /** Applies character formatting to a range of characters. The attributes which
       
  1114 are set in the mask are read from aFormat and applied. The attributes which
       
  1115 are not set in the mask are not changed. The range of characters affected
       
  1116 is from aPos to aPos+(aLength-1) inclusive. The sum of aPos and aLength
       
  1117 must be less than or equal to the document length, or a panic occurs.
       
  1118 
       
  1119 @param aFormat Contains the character format attribute values to apply.
       
  1120 @param aMask Bitmask specifying which character format attributes should be
       
  1121 applied.
       
  1122 @param aPos Document position from which to apply the new character formatting.
       
  1123 Must be greater than or equal to zero, or a panic occurs.
       
  1124 @param aLength The number of characters to which the new formatting should
       
  1125 be applied. Must be greater than or equal to zero, or a panic occurs. If the
       
  1126 length is zero, the function has the same effect as SetInsertCharFormatL(). */
       
  1127 	{
       
  1128 	// Applies the specified character formatting to the characters conatined within the range
       
  1129 	// aPos to aPos+(aLength-1).
       
  1130 	// If aLength is zero, the SetInsertCharFormat state is called.
       
  1131 	//
       
  1132 	__ETEXT_WATCH(APPLY_CHAR_FORMAT);
       
  1133 	__TEST_INVARIANT;
       
  1134 	
       
  1135 	TInt document_length = DocumentLength();
       
  1136 	__ASSERT_ALWAYS(aPos >= 0,Panic(ECharPosBeyondDocument));
       
  1137 	__ASSERT_ALWAYS(aLength >= 0,Panic(EApplyCharFormatNegativeLength));
       
  1138 	__ASSERT_ALWAYS(aPos + aLength - 1 <= document_length,Panic(ECharPosBeyondDocument));
       
  1139 
       
  1140 	//If some characters are highlighted AND current position + highlighted txt = document length	
       
  1141 	// Fix for INC097216. Compensate for the changes introduced to Form in defect fix INC087637,
       
  1142 	// which now considers the height of the EOD character; meaning that this character now 
       
  1143 	// needs to be formatted along with rest of text.
       
  1144 	if ((aLength > 0) && (aPos + aLength == document_length))
       
  1145 		{
       
  1146 		aLength++;
       
  1147 		}
       
  1148 	
       
  1149 	DoApplyExtendedCharFormatL(aFormat, aMask, aPos, aLength);
       
  1150 	
       
  1151 	__TEST_INVARIANT;
       
  1152 	__ETEXT_WATCH_END(APPLY_CHAR_FORMAT);
       
  1153 	}
       
  1154 	
       
  1155 // This method is used internally only. It does not format the EOD character.
       
  1156 void CRichText::ApplyExtendedCharFormatL(const TCharFormatX& aFormat,const TCharFormatXMask& aMask,TInt aPos,TInt aLength)
       
  1157 	{
       
  1158 	TInt document_length = DocumentLength();
       
  1159 	__ASSERT_ALWAYS(aPos >= 0,Panic(ECharPosBeyondDocument));
       
  1160 	__ASSERT_ALWAYS(aLength >= 0,Panic(EApplyCharFormatNegativeLength));
       
  1161 	__ASSERT_ALWAYS(aPos + aLength - 1 <= document_length,Panic(ECharPosBeyondDocument));
       
  1162 	
       
  1163 	DoApplyExtendedCharFormatL(aFormat, aMask, aPos, aLength);
       
  1164 	}	
       
  1165 	
       
  1166 // Apply the extended character formatting.	
       
  1167 void CRichText::DoApplyExtendedCharFormatL(const TCharFormatX& aFormat,const TCharFormatXMask& aMask,TInt aPos,TInt aLength)
       
  1168 	{
       
  1169 	if (aLength > 0)
       
  1170 		{
       
  1171 		CreateAndGenerateMarkupComponentL();
       
  1172 		iIndex->ApplyCharFormatL(aFormat,aMask,aPos,aLength);
       
  1173 		SetHasChanged(ETrue);
       
  1174 		}
       
  1175 	else
       
  1176 		SetExtendedInsertCharFormatL(aFormat,aMask,aPos);
       
  1177 	}		
       
  1178 
       
  1179 EXPORT_C void CRichText::SetStyleListExternallyOwned(const CStyleList& aStyleList)
       
  1180 /** Assigns an externally owned style list to the rich text object.
       
  1181 Replaces any previous style list used by the object. Calls
       
  1182 SetStyleListExternallyOwned(ETrue).
       
  1183 
       
  1184 @param aExternallyOwned The style list to assign to this rich text object.
       
  1185 Not owned by the rich text object. */
       
  1186 	{
       
  1187 	CStyleList* styleList = CONST_CAST(CStyleList*, &aStyleList);
       
  1188 	iStyleList = styleList;
       
  1189 	SetStyleListExternallyOwned(ETrue);
       
  1190 	}
       
  1191 
       
  1192 EXPORT_C void CRichText::ApplyParagraphStyleL(const CParagraphStyle& aStyle, TInt aPos, TInt aLength, CParagraphStyle::TApplyParaStyleMode aMode)
       
  1193 /** Applies a specified paragraph style to a range of paragraphs. The region
       
  1194 affected consists of every paragraph containing one or more characters in the
       
  1195 range aPos to aPos+(aLength-1).
       
  1196 
       
  1197 A panic occurs if:
       
  1198 
       
  1199 aPos is invalid, or
       
  1200 
       
  1201 aLength is negative, or
       
  1202 
       
  1203 the range goes beyond the end of the document, or
       
  1204 
       
  1205 the rich text object has no style list
       
  1206 
       
  1207 @param aStyle The style to apply.
       
  1208 @param aPos The document position of the start of the range.
       
  1209 @param aLength The number of characters in the range.
       
  1210 @param aMode Controls what specific formatting, if any, should be preserved
       
  1211 when the style is applied. */
       
  1212 	{
       
  1213 	// Applies the specified paragraph style to the paragraphs covering
       
  1214 	// character positions aPos to aPos+aLength-1.
       
  1215 	//
       
  1216 	__TEST_INVARIANT;
       
  1217 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1218 	__ASSERT_ALWAYS(aLength >= 0, Panic(EApplyParaStyleNegativeLength));
       
  1219 	__ASSERT_ALWAYS(aPos + (aLength - 1) <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1220 	__ASSERT_ALWAYS(StyleListPresent(), Panic(ERichTextNotSetForUsingStyles));
       
  1221 
       
  1222 	CreateAndGenerateMarkupComponentL();
       
  1223 	iIndex->ApplyParagraphStyleL(aStyle, aPos, aLength, iGlobalCharFormatLayer, aMode);
       
  1224 	SetHasChanged(ETrue);
       
  1225 
       
  1226 	__TEST_INVARIANT;
       
  1227 	}
       
  1228 
       
  1229 EXPORT_C void CRichText::NotifyStyleChangedL(const CParagraphStyle* aTo, const CParagraphStyle* aFrom)
       
  1230 /** Removes a style from every paragraph in the document to which it applies,
       
  1231 and replaces it with another.
       
  1232 
       
  1233 If style aTo is NULL, aFrom is replaced by the global character and paragraph
       
  1234 format layers, so that in effect, style aFrom is removed. Any specific
       
  1235 formatting which has been applied to the paragraphs is retained.
       
  1236 
       
  1237 Notes:
       
  1238 
       
  1239 This function should be called on the text content object after changing a
       
  1240 style in the style list.
       
  1241 
       
  1242 A panic occurs if the rich text object does not use a style list (this can
       
  1243 be tested for using StyleListPresent()).
       
  1244 
       
  1245 @param aTo The new paragraph style to apply.
       
  1246 @param aFrom The paragraph style to remove. */
       
  1247 	{
       
  1248 	// Update the rich text index following the change of an applied paragraph style.
       
  1249 	//
       
  1250 	__TEST_INVARIANT;
       
  1251 	__ASSERT_ALWAYS(StyleListPresent(), Panic(ERichTextNotSetForUsingStyles));
       
  1252 
       
  1253 	CreateAndGenerateMarkupComponentL();
       
  1254 	iIndex->NotifyStyleChangedL(aTo, aFrom, *iGlobalParaFormatLayer, *iGlobalCharFormatLayer);
       
  1255 	SetHasChanged(ETrue);
       
  1256 
       
  1257 	__TEST_INVARIANT;
       
  1258 	}
       
  1259 
       
  1260 EXPORT_C const CParaFormatLayer* CRichText::ParagraphStyle(TBool& aStyleChangesOverRange, TInt aPos, TInt aLength) const
       
  1261 /** Gets a pointer to the first paragraph style encountered in the specified
       
  1262 range.
       
  1263 
       
  1264 @param aStyleChangesOverRange On return, set to ETrue if more than one paragraph
       
  1265 style is used over the specified range of characters. Otherwise EFalse
       
  1266 @param aPos The document position of the start of the range. Must be valid.
       
  1267 @param aLength The number of characters in the range. Must be greater than
       
  1268 or equal to zero.
       
  1269 @return Pointer to the paragraph style which applies to the paragraph containing
       
  1270 document position aPos. Its type (returned by CParaFormatLayer::Type())
       
  1271 indicates whether this object is a style, or just a paragraph format layer. */
       
  1272 	{
       
  1273 	__TEST_INVARIANT;
       
  1274 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1275 	__ASSERT_ALWAYS(aLength >= 0,Panic(EParagraphStyleNegativeLength));
       
  1276 	__ASSERT_ALWAYS(aPos + (aLength - 1) <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1277 
       
  1278 	if (IndexPresent())
       
  1279 		return iIndex->ParagraphStyle(aStyleChangesOverRange, aPos, aLength);
       
  1280 	else
       
  1281 		{
       
  1282 		aStyleChangesOverRange = EFalse;
       
  1283 		return iGlobalParaFormatLayer;
       
  1284 		}
       
  1285 	}
       
  1286 
       
  1287 EXPORT_C void CRichText::SetHasChanged(TBool aHasChanged)
       
  1288 /** Sets whether the document's content or formatting has changed. This function
       
  1289 is called with an value of ETrue by all functions which modify the text content
       
  1290 or formatting. Use CEditableText::HasChanged() to test whether the document
       
  1291 has changed.
       
  1292 
       
  1293 @param aHasChanged ETrue if the text object has been changed, EFalse if not. */
       
  1294 	{
       
  1295 	// Replaces the base class method of the same name.
       
  1296 	//
       
  1297 	if (aHasChanged && IndexPresent())
       
  1298 		iIndex->DocumentChanged();
       
  1299 	CGlobalText::SetHasChanged(aHasChanged);
       
  1300 	}
       
  1301 
       
  1302 EXPORT_C void CRichText::RemoveSpecificParaFormatL(TInt aPos, TInt aLength)
       
  1303 /** Removes all specific paragraph formatting from a range of paragraphs. This
       
  1304 does not remove formatting from the object's global paragraph format layer.
       
  1305 The region affected consists of every paragraph containing one or more
       
  1306 characters in the range covered by document position aPos to aPos+(aLength-1)
       
  1307 inclusive.
       
  1308 
       
  1309 A panic occurs in the following situations:
       
  1310 
       
  1311 the position is negative,
       
  1312 
       
  1313 the length is negative,
       
  1314 
       
  1315 the range goes beyond the end of the document
       
  1316 
       
  1317 @param aPos The document position of the start of the range.
       
  1318 @param aLength The number of characters in the range. */
       
  1319 	{
       
  1320 	// Removes all specific paragraph formatting from the selected region.
       
  1321 	//
       
  1322 	__ETEXT_WATCH(REMOVE_PARA_FORMAT);
       
  1323 
       
  1324 	__TEST_INVARIANT;
       
  1325 
       
  1326 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1327 	__ASSERT_ALWAYS(aLength >= 0, Panic(ERemoveSpecificParaFormatNegativeLength));
       
  1328 	__ASSERT_ALWAYS(aPos + (aLength - 1) <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1329 
       
  1330 	if (IndexPresent())
       
  1331 		{
       
  1332 		iIndex->RemoveSpecificParaFormatL(aPos, aLength);
       
  1333 		SetHasChanged(ETrue);
       
  1334 		}
       
  1335 
       
  1336 	__TEST_INVARIANT;
       
  1337 
       
  1338 	__ETEXT_WATCH_END(REMOVE_PARA_FORMAT);
       
  1339 	}
       
  1340 
       
  1341 EXPORT_C void CRichText::RemoveSpecificCharFormatL(TInt aPos, TInt aLength)
       
  1342 /** Removes all specific character formatting from a range of characters (does
       
  1343 not remove the formatting which has been taken from the object's global character
       
  1344 format layer). A panic occurs in the following situations:
       
  1345 
       
  1346 the position is negative,
       
  1347 
       
  1348 the length is negative,
       
  1349 
       
  1350 the range goes beyond the end of the document
       
  1351 
       
  1352 @param aPos The document position of the start of the region affected.
       
  1353 @param aLength The number of characters in the region affected. If zero, the
       
  1354 function has no effect. */
       
  1355 	{
       
  1356 	__TEST_INVARIANT;
       
  1357 	
       
  1358 	TInt document_length = DocumentLength();
       
  1359 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1360 	__ASSERT_ALWAYS(aLength >= 0, Panic(ERemoveSpecificParaFormatNegativeLength));
       
  1361 	__ASSERT_ALWAYS(aPos + (aLength - 1) <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1362 	
       
  1363 	// in correspondance to INC097216, character format removing considers the height of end of document
       
  1364     // character
       
  1365     if (aPos + aLength == document_length)
       
  1366    		{
       
  1367         aLength++;
       
  1368         }
       
  1369 
       
  1370 	if (aLength > 0 && IndexPresent())
       
  1371 		{
       
  1372 		iIndex->RemoveSpecificCharFormatL(aPos, aLength);
       
  1373 		SetHasChanged(ETrue);
       
  1374 		}
       
  1375 
       
  1376 	__TEST_INVARIANT;
       
  1377 	}
       
  1378 
       
  1379 EXPORT_C void CRichText::GetChars(TPtrC& aText, TCharFormat& aFormat, TInt aPos) const
       
  1380 /** Gets a constant pointer descriptor to a portion of the text object
       
  1381 with constant character formatting.
       
  1382 
       
  1383 The view starts at the document position specified, and ends at: the
       
  1384 last character which shares the same character formatting, orthe end
       
  1385 of the document, orthe end of the segment, if segmented storage is
       
  1386 being usedwhichever occurs first. Also fills a character format object
       
  1387 with the character formatting of the range of characters.
       
  1388 
       
  1389 @param aView On return, a constant pointer to a portion of the text.
       
  1390 @param aFormat On return, contains the character formatting of the text.
       
  1391 @param aPos The start position for the view. Must be a valid document
       
  1392 position, or a panic occurs. */
       
  1393 	{
       
  1394 	// Get a run of text and its format, starting at aPos.
       
  1395 	__ETEXT_WATCH(GET_CHARS)
       
  1396 	TCharFormatX format;
       
  1397 	GetTextAndExtendedFormat(aText, format, aPos);
       
  1398 	OverrideFormatForParsersIfApplicable(aText, format, aPos);
       
  1399 	aFormat = format.iCharFormat;
       
  1400 	OverrideFormatOfInlineTextIfApplicable(aText, aFormat, aPos);
       
  1401 	__ETEXT_WATCH_END(GET_CHARS)
       
  1402 	}
       
  1403 
       
  1404 
       
  1405 void CRichText::GetTextAndExtendedFormat(TPtrC& aText,TCharFormatX& aFormat,TInt aPos) const
       
  1406 	{
       
  1407 	__TEST_INVARIANT;
       
  1408 	TInt documentLength = DocumentLength();
       
  1409 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= documentLength, Panic(ECharPosBeyondDocument));
       
  1410 	if (!IndexPresent())
       
  1411 		{
       
  1412 		aText.Set(Read(aPos));
       
  1413 		iGlobalCharFormatLayer->SenseEffective(aFormat);
       
  1414 		}
       
  1415 	else
       
  1416 		{
       
  1417 		int phrase_length = iIndex->GetChars(aFormat,aPos);
       
  1418 		aText.Set(Read(aPos,phrase_length));
       
  1419 		}
       
  1420 	__TEST_INVARIANT;
       
  1421 	}
       
  1422 
       
  1423 EXPORT_C TInt CRichText::GetPictureSizeInTwips(TSize& aSize, TInt aPos) const
       
  1424 /** Gets the size of a picture located at a specified document position.
       
  1425 
       
  1426 @param aSize On return, contains the size of the picture located at aPos.
       
  1427 @param aPos Document position of the picture. Must be a valid position.
       
  1428 @return KErrNotFound if there is no picture at the specified document position,
       
  1429 KErrNone if there is. */
       
  1430 	{
       
  1431 	__TEST_INVARIANT;
       
  1432 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1433 
       
  1434 	if (IndexPresent())
       
  1435 		return iIndex->GetPictureSizeInTwips(aSize, aPos);
       
  1436 	else
       
  1437 		return KErrNotFound;
       
  1438 	}
       
  1439 
       
  1440 EXPORT_C CPicture* CRichText::PictureHandleL(TInt aPos, MLayDoc::TForcePictureLoad aForceLoad) const
       
  1441 /** Gets a pointer to the picture located at a specified document position, if
       
  1442 one exists. If the picture is not in memory, the function loads it (if the
       
  1443 second argument has a value of MLayDoc::EForceLoadTrue).
       
  1444 
       
  1445 Note:
       
  1446 
       
  1447 In order to load the picture, a picture factory and a store resolver must
       
  1448 have been set.
       
  1449 
       
  1450 @param aPos Document position of the picture character. Must be a valid position.
       
  1451 @param aForceLoad If the picture is not loaded into memory,
       
  1452 MLayDoc::EForceLoadTrue loads it using the picture factory;
       
  1453 MLayDoc::EForceLoadFalse does not, and in this case, the function returns NULL.
       
  1454 @return A pointer to the picture located at aPos. NULL if aPos does not specify
       
  1455 a picture character, or if there is a picture at aPos which is not in memory,
       
  1456 and the second argument is MLayDoc::EForceLoadFalse. */
       
  1457 	{
       
  1458 	__ETEXT_WATCH(PICTURE_HANDLE);
       
  1459 
       
  1460 	__TEST_INVARIANT;
       
  1461 	__ASSERT_ALWAYS(aPos>=0 && aPos<=DocumentLength(),Panic(ECharPosBeyondDocument));
       
  1462 
       
  1463 	if (IndexPresent())
       
  1464 		return iIndex->PictureHandleL(aPos, aForceLoad);
       
  1465 	else
       
  1466 		return NULL;
       
  1467 
       
  1468 	__ETEXT_WATCH_END(PICTURE_HANDLE);
       
  1469 	}
       
  1470 
       
  1471 EXPORT_C void CRichText::GetParagraphFormatL(CParaFormat* aFormat, TInt aPos) const
       
  1472 /** Gets the effective paragraph formatting which applies to the paragraph which
       
  1473 contains a specified document position. On return, aFormat is filled with
       
  1474 values for all paragraph format attributes.
       
  1475 
       
  1476 @param aFormat On return, filled with the paragraph's effective paragraph
       
  1477 formatting.
       
  1478 @param aPos Any document position within the paragraph of interest. */
       
  1479 	{
       
  1480 	__ETEXT_WATCH(GET_PARAGRAPH_FORMAT)
       
  1481 
       
  1482 	__TEST_INVARIANT;
       
  1483 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1484 
       
  1485 	if (!IndexPresent())
       
  1486 		CGlobalText::GetParagraphFormatL(aFormat, aPos);
       
  1487 	else
       
  1488 		{
       
  1489 		aFormat->Reset();
       
  1490 		iIndex->GetParagraphFormatL(aFormat, aPos);
       
  1491 		}
       
  1492 
       
  1493 	__ETEXT_WATCH_END(GET_PARAGRAPH_FORMAT)
       
  1494 	}
       
  1495 
       
  1496 EXPORT_C void CRichText::GetSpecificParagraphFormatL(CParaFormat* aFormat,
       
  1497 													 TParaFormatMask& aMask,
       
  1498 													 TInt aPos) const
       
  1499 // Fills aFormat with the effective Paragraph format attributes for the paragraph
       
  1500 // in which character position aPos is contained.
       
  1501 //
       
  1502 	{
       
  1503 	__ETEXT_WATCH(GET_PARAGRAPH_FORMAT)
       
  1504 
       
  1505 	__TEST_INVARIANT;
       
  1506 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1507 
       
  1508 	aFormat->Reset();
       
  1509 	aMask.ClearAll();
       
  1510 	if (IndexPresent())
       
  1511 		iIndex->GetSpecificParagraphFormatL(aFormat, aMask, aPos);
       
  1512 
       
  1513 	__ETEXT_WATCH_END(GET_PARAGRAPH_FORMAT)
       
  1514 	}
       
  1515 
       
  1516 EXPORT_C void CRichText::GetParaFormatL(CParaFormat* aFormat, TParaFormatMask& aVaries, TInt aPos, TInt aLength,
       
  1517 										CParaFormat::TParaFormatGetMode aMode) const
       
  1518 /** Gets the effective paragraph formatting which applies to a range of paragraphs.
       
  1519 The region involved is every paragraph containing one or more characters in
       
  1520 the range aPos to aPos+(aLength-1) inclusive. On return, aFormat is filled
       
  1521 with values for all paragraph format attributes and the mask indicates the
       
  1522 values that change over the region, and whose value is therefore indeterminate.
       
  1523 
       
  1524 Note:
       
  1525 
       
  1526 If aMode has a value of EFixedAttributes, the function cannot leave.
       
  1527 
       
  1528 @param aFormat Must not be NULL or a panic occurs. On return, contains the
       
  1529 effective paragraph formatting for the range of paragraphs.
       
  1530 @param aVaries On return, a bitmask indicating which paragraph format attributes
       
  1531 vary over the range of characters selected.
       
  1532 @param aPos The document position of the start of the range.
       
  1533 @param aLength The number of characters in the range.
       
  1534 @param aMode The default, EAllAttributes means that values for all paragraph
       
  1535 format attributes are written to aFormat. EFixedAttributes means that tabs,
       
  1536 bullets and borders are not written to aFormat. */
       
  1537 	{
       
  1538 	// Senses the paragraph format of para(s) covered by the region aPos to aPos+aLength-1.
       
  1539 	// aFormat takes the values of all attributes, and the mask aMask indicates those values that change
       
  1540 	// over the selected region, and are therefore *indeterminate*.
       
  1541 	// Application: seeding paragraph formatting dialogs.
       
  1542 	//
       
  1543 	__TEST_INVARIANT;
       
  1544 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1545 	__ASSERT_ALWAYS(aLength >= 0, Panic(EGetParaFormatNegativeLength));
       
  1546 	__ASSERT_ALWAYS(aPos + aLength <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1547 
       
  1548 	if (IndexPresent())
       
  1549 		iIndex->GetParaFormatL(aFormat, aVaries, aPos, aLength, aMode);
       
  1550 	else
       
  1551 		CGlobalText::GetParaFormatL(aFormat, aVaries, aPos, aLength, aMode);
       
  1552 	}
       
  1553 
       
  1554 EXPORT_C void CRichText::GetCharFormat(TCharFormat& aFormat, TCharFormatMask& aVaries, TInt aPos, TInt aLength) const
       
  1555 /** Gets the effective character formatting which applies to a range of
       
  1556 characters. The range of characters involved is from aPos to aPos+(aLength-1)
       
  1557 inclusive. On return, aFormat is filled with values for all character format
       
  1558 attributes, and on return, the mask indicates the values that change over the
       
  1559 region, and whose value is therefore indeterminate.
       
  1560 
       
  1561 The length value can be zero. In this case, the character formatting sensed
       
  1562 is that of the character immediately to the left of the position specified.
       
  1563 
       
  1564 @param aFormat On return, contains the character format values for the range
       
  1565 of characters.
       
  1566 @param aVaries On return, indicates which character format attributes vary
       
  1567 over the range.
       
  1568 @param aPos Document position of the start of the range. Must be valid or a
       
  1569 panic occurs.
       
  1570 @param aLength Number of characters in the range. Must be greater than or equal
       
  1571 to zero, or a panic occurs. */
       
  1572 	{
       
  1573 	// Senses the character formatting of the phrase(s) covered by the region aPos to aPos+aLength-1.
       
  1574 	// May be called with zero length.
       
  1575 	// aFormat takes the values of all character format attributes, and the mask aMask indicates those
       
  1576 	// values that change over the selected region, and are therefore *indeterminate*.
       
  1577 	// Application: seeding character formatting dialogs.
       
  1578 	//
       
  1579 	TCharFormatX format;
       
  1580 	TCharFormatXMask varies;
       
  1581 	GetExtendedCharFormat(format, varies, aPos, aLength);
       
  1582 	aFormat = format.iCharFormat;
       
  1583 	varies.ClearExtendedAttribs();
       
  1584 	aVaries = varies;
       
  1585 	}
       
  1586 
       
  1587 
       
  1588 void CRichText::GetExtendedCharFormat(TCharFormatX& aFormat, TCharFormatXMask& aVaries, TInt aPos, TInt aLength) const
       
  1589 	{
       
  1590 	__TEST_INVARIANT;
       
  1591 	int document_length = DocumentLength();
       
  1592 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= document_length, Panic(ECharPosBeyondDocument));
       
  1593 	__ASSERT_ALWAYS(aLength >= 0, Panic(EGetCharFormatNegativeLength));
       
  1594 	__ASSERT_ALWAYS(aPos + aLength - 1 <= document_length, Panic(ECharPosBeyondDocument));
       
  1595 
       
  1596 	if (IndexPresent())
       
  1597 		iIndex->GetCharFormat(aFormat, aVaries, aPos, aLength);
       
  1598 	else
       
  1599 		{
       
  1600 		iGlobalCharFormatLayer->SenseEffective(aFormat);
       
  1601 		aVaries.ClearAll();
       
  1602 		}
       
  1603 	}
       
  1604 
       
  1605 
       
  1606 void CRichText::GetSpecificCharFormatLeftRight(TCharFormat& aFormat,
       
  1607 									TCharFormatMask& aMask,
       
  1608 									TInt aPos,
       
  1609 									TBool aLeft) const
       
  1610 	{
       
  1611 	__ETEXT_WATCH(GET_SPECIFIC_CHARS);
       
  1612 
       
  1613 	__TEST_INVARIANT;
       
  1614 
       
  1615 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1616 
       
  1617 	if (IndexPresent())
       
  1618 		{
       
  1619 		TCharFormatX format;
       
  1620 		TCharFormatXMask mask;
       
  1621 		iIndex->GetSpecificCharFormatDirection(format, mask, aPos, aLeft);
       
  1622 		aFormat = format.iCharFormat;
       
  1623 		mask.ClearExtendedAttribs();
       
  1624 		aMask = mask;
       
  1625 		}
       
  1626 
       
  1627 	__ETEXT_WATCH_END(GET_SPECIFIC_CHARS);
       
  1628 	}
       
  1629 
       
  1630 EXPORT_C void CRichText::GetSpecificCharFormat(TCharFormat& aFormat, TCharFormatMask& aMask, TInt aPos) const
       
  1631 /** Gets the specific character formatting which applies to the character to the
       
  1632 left of a document position. Specific formatting is just the formatting which
       
  1633 has been applied over the object's global format layers - it is not the
       
  1634 same as the effective formatting.
       
  1635 
       
  1636 @param aFormat On return contains the specific character formatting which
       
  1637 applies to the character to the left of the document position.
       
  1638 @param aMask On return, indicates which character format attributes have been
       
  1639 applied specifically, (not taken from the global layers).
       
  1640 @param aPos The document position. Must be valid or a panic occurs. */
       
  1641 	{
       
  1642 	// Return the format attributes store in the specific layer only, for the specified document position.
       
  1643 	// THIS IS NOT THE EFFECTIVE FORMAT, BUT THE SPECIFIC FORMATTING ONLY.
       
  1644 	//
       
  1645 	GetSpecificCharFormatLeftRight(aFormat, aMask, aPos, ETrue);
       
  1646 	}
       
  1647 
       
  1648 EXPORT_C void CRichText::GetSpecificCharFormatRight(TCharFormat& aFormat, TCharFormatMask& aMask, TInt aPos) const
       
  1649 /** Gets the specific character formatting which applies to the character logically
       
  1650 after a document position. Note that this is not necessarily the character
       
  1651 to the right of the document position, because right to left text is supported.
       
  1652 
       
  1653 Specific formatting is just the formatting which has been applied over the
       
  1654 object's global format layers it is not the same as the effective formatting.
       
  1655 
       
  1656 @param aFormat On return, contains the specific character formatting which
       
  1657 applies to the character logically after the document position.
       
  1658 @param aMask On return, indicates which character format attributes have been
       
  1659 applied specifically, (not taken from the global layers).
       
  1660 @param aPos The document position. Must be valid or a panic occurs. */
       
  1661 	{
       
  1662 	GetSpecificCharFormatLeftRight(aFormat, aMask, aPos, EFalse);
       
  1663 	}
       
  1664 
       
  1665 TBool CRichText::IndexPresent()const
       
  1666 // Returns ETrue if the rich text index is present, otherwise
       
  1667 // returns EFalse.
       
  1668 //
       
  1669 	{
       
  1670 	return iIndex.IsPtr() && iIndex.AsPtr();
       
  1671 	}
       
  1672 
       
  1673 
       
  1674 EXPORT_C TInt CRichText::PictureCount() const
       
  1675 /** Gets a count of the number of pictures contained in the rich text object.
       
  1676 
       
  1677 @return The picture count. */
       
  1678 	{return (IndexPresent()) ? iIndex->iPictureCount : 0;}
       
  1679 
       
  1680 
       
  1681 void CRichText::SetParaTypeIsSingle(TBool aBool)
       
  1682 	{
       
  1683 	if (aBool)
       
  1684 		iFlags |= KParaTypeIsSingle;
       
  1685 	else
       
  1686 		iFlags &= ~KParaTypeIsSingle;
       
  1687 	}
       
  1688 
       
  1689 
       
  1690 TBool CRichText::ParaTypeIsSingle() const
       
  1691 	{return iFlags & KParaTypeIsSingle;}
       
  1692 
       
  1693 
       
  1694 EXPORT_C void CRichText::AppendTakingSolePictureOwnershipL(const CRichText& aSource)
       
  1695 /** Appends a rich text object to this one. The text is appended immediately after
       
  1696 the end-of-text paragraph delimiter. The incoming text's formatting is set
       
  1697 to be based on the global formatting of this rich text object.
       
  1698 
       
  1699 Notes:
       
  1700 
       
  1701 If this rich text object is empty (e.g. because it is newly initialised, or
       
  1702 has been reset), then the end-of-text delimiter of the incoming rich text
       
  1703 is not appended. This avoids the possibility of having a trailing paragraph
       
  1704 delimiter, giving one more empty line than would typically be desired.
       
  1705 
       
  1706 If the incoming rich text contains pictures which have been loaded into memory,
       
  1707 their sole ownership is transferred to the current rich text object. In aSource,
       
  1708 these picture handles are set to NULL.
       
  1709 
       
  1710 @param aSource The rich text object to append. */
       
  1711 	{
       
  1712 	// Appends the specified rich text object to this one.
       
  1713 	// If this rich text is empty or has been newly initialised or reset, then the final paragraph delimiter
       
  1714 	// of the incoming rich text is NOT appended, thus avoiding the prospect of having a trailing, empty
       
  1715 	// paragraph delimiter, giving one more empty line than would typically be desired.
       
  1716 	//
       
  1717 	__ETEXT_WATCH(APPEND_RICH_TEXT);
       
  1718 
       
  1719 	// Append the text
       
  1720 	const TInt thisDocumentLength = DocumentLength();
       
  1721 	MPictureFactory* factory = NULL;
       
  1722 	MRichTextStoreResolver* resolver = NULL;
       
  1723 	if (thisDocumentLength == 0)  // this is an empty document
       
  1724 		{
       
  1725 		factory = iPictureFactory;
       
  1726 		resolver = iStoreResolver;
       
  1727 		Reset();  // destroy the markup component if it exists.  Makes the job easier
       
  1728 		}
       
  1729 	//
       
  1730 	PrepareAppendMarkupL(aSource);  // requires no rollback - objects in a (bigger) stable state
       
  1731 	//
       
  1732 	TRAPD(ret, DoAppendTakingSolePictureOwnershipL(aSource));
       
  1733 	if (ret != KErrNone)
       
  1734 		{
       
  1735 		CPlainText::Delete(thisDocumentLength,DocumentLength() - thisDocumentLength);
       
  1736 		User::Leave(ret);
       
  1737 		}
       
  1738 	if (thisDocumentLength == 0)
       
  1739 		{
       
  1740 		DeleteParagraph(0, 1);   // remove excess first paragraph from empty documents
       
  1741 		SetPictureFactory(factory, resolver);
       
  1742 		}
       
  1743 	int new_length = DocumentLength() - thisDocumentLength;
       
  1744 	iParserData->MergeRange(thisDocumentLength,0,new_length);
       
  1745 	CallEditObserver(thisDocumentLength,new_length);
       
  1746 
       
  1747 	__TEST_INVARIANT;
       
  1748 
       
  1749 	__ETEXT_WATCH_END(APPEND_RICH_TEXT);
       
  1750 	}
       
  1751 
       
  1752 
       
  1753 void CRichText::DoAppendTakingSolePictureOwnershipL(const CRichText& aSource)
       
  1754 	{
       
  1755 	TInt lengthRemaining = aSource.DocumentLength() + 1;  // we want to append the para delimiters also!
       
  1756 	TInt consumed = 0;
       
  1757 	FOREVER
       
  1758 		{
       
  1759 		TPtrC view = aSource.Read(consumed);
       
  1760 		if (view.Length() > lengthRemaining)
       
  1761 			view.Set(view.Ptr(), lengthRemaining);
       
  1762 		CPlainText::DoPtInsertL(DocumentLength() + 1, view);  // insert AFTER the final paragraph delimiter
       
  1763 		TInt viewLength = view.Length();
       
  1764 		lengthRemaining -= viewLength;
       
  1765 		if (lengthRemaining == 0)
       
  1766 			break;
       
  1767 		consumed += viewLength;
       
  1768 		}
       
  1769 
       
  1770 	if (IndexPresent())
       
  1771 		{
       
  1772 		__ASSERT_DEBUG(aSource.IndexPresent(), User::Invariant());       // PrepareAppend should have sorted this
       
  1773 
       
  1774 		TGlobalLayerInfoAppend info(GlobalParaFormatLayer(), GlobalCharFormatLayer(), aSource.GlobalParaFormatLayer(), aSource.GlobalCharFormatLayer());
       
  1775 		iIndex->AppendTakingSolePictureOwnershipL(aSource.iIndex, info);
       
  1776 		}
       
  1777 
       
  1778 	__TEST_INVARIANT;
       
  1779 	}
       
  1780 
       
  1781 
       
  1782 void CRichText::PrepareAppendMarkupL(const CRichText& aSource)
       
  1783 // Guarantees that both the component and aggregate objects have a valid markup component.
       
  1784 //
       
  1785 	{
       
  1786 	if (aSource.HasMarkupData() && !HasMarkupData())
       
  1787 		CreateAndGenerateMarkupComponentL();
       
  1788 	else if (IndexPresent())
       
  1789 		CONST_CAST(CRichText&, aSource).CreateAndGenerateMarkupComponentL();
       
  1790 	}
       
  1791 
       
  1792 
       
  1793 EXPORT_C void CRichText::AppendParagraphL(TInt aReplicas)
       
  1794 /** Appends one or more empty paragraphs to the document. The new paragraphs take
       
  1795 on the formatting specified in the global format layers.
       
  1796 
       
  1797 @param aReplicas The number of empty paragraphs to append to the document.
       
  1798 By default, a single paragraph. */
       
  1799 	{
       
  1800 	// Inserts an empty paragraph at the end of the document.
       
  1801 	// The new paragraph takes on the format as described
       
  1802 	// by the global format layers.
       
  1803 	//
       
  1804 	__ETEXT_WATCH(APPEND_PARAGRAPH);
       
  1805 
       
  1806 	__TEST_INVARIANT;
       
  1807 
       
  1808 	TInt documentLength = DocumentLength();
       
  1809 	if (aReplicas == 1)
       
  1810 		CPlainText::InsertL(documentLength, CEditableText::EParagraphDelimiter);
       
  1811 	else
       
  1812 		{
       
  1813 		HBufC* bb = HBufC::NewLC(aReplicas);
       
  1814 		TPtr buf = bb->Des();
       
  1815 		buf.Fill(CEditableText::EParagraphDelimiter, aReplicas);
       
  1816 		CPlainText::InsertL(documentLength, buf);
       
  1817 		CleanupStack::PopAndDestroy();  // bb
       
  1818 		}
       
  1819 	//
       
  1820 	if (IndexPresent())
       
  1821 		{
       
  1822 		TRAPD(ret,
       
  1823 		iIndex->AppendParagraphL(iGlobalParaFormatLayer, iGlobalCharFormatLayer, aReplicas));
       
  1824 		if (ret != KErrNone)
       
  1825 			{
       
  1826 			CPlainText::Delete(DocumentLength() - aReplicas, aReplicas);
       
  1827 			User::Leave(ret);
       
  1828 			}
       
  1829 		SetHasChanged(ETrue);
       
  1830 		}
       
  1831 
       
  1832 	int new_length = DocumentLength() - documentLength;
       
  1833 	iParserData->MergeRange(documentLength,0,new_length);
       
  1834 	CallEditObserver(documentLength,new_length);
       
  1835 	__TEST_INVARIANT;
       
  1836 
       
  1837 	__ETEXT_WATCH_END(APPEND_PARAGRAPH);
       
  1838 	}