textrendering/texthandling/stext/TXTRICH.CPP
changeset 32 8b9155204a54
child 37 6be019398652
equal deleted inserted replaced
31:b9ad20498fb4 32:8b9155204a54
       
     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 	if (aChar < 0x10000)
       
   632 		{
       
   633 		TBuf<1> content;
       
   634 		content.Append(aChar);
       
   635 		RtInsertL(aPos, content);
       
   636 		}
       
   637 	else
       
   638 		{
       
   639 		TText16 high = TChar::GetHighSurrogate(aChar);
       
   640 		TText16 low = TChar::GetLowSurrogate(aChar);
       
   641 		RDebug::Print(_L("CRichText::InsertL(), %X expand to %X %X."), aChar, high, low);
       
   642 		
       
   643 		TBuf<2> content;
       
   644 		content.Append(high);
       
   645 		content.Append(low);
       
   646 		RtInsertL(aPos, content);
       
   647 		}
       
   648 
       
   649 	__TEST_INVARIANT;
       
   650 	}
       
   651 
       
   652 
       
   653 EXPORT_C void CRichText::InsertL(TInt aPos, const TDesC& aBuf)
       
   654 // Inserts the contents of aBuf into the text component at character position aPos.
       
   655 //
       
   656 	{
       
   657 	__ETEXT_WATCH(INSERT_DESC);
       
   658 
       
   659 	RtInsertL(aPos, aBuf);
       
   660 
       
   661 	__ETEXT_WATCH_END(INSERT_DESC);
       
   662 	}
       
   663 
       
   664 
       
   665 EXPORT_C void CRichText::RtInsertL(TInt aPos, const TDesC& aBuf)
       
   666 // Inserts the contents a aBuf into the text component at position aPos.
       
   667 // Updates the index accordingly, and accounts for all embedded paragraph delimiters
       
   668 // in the passed buffer aBuf.
       
   669 //
       
   670 	{
       
   671 	__TEST_INVARIANT;
       
   672 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
   673 
       
   674 	int length = aBuf.Length();
       
   675 	CPlainText::InsertL(aPos, aBuf);
       
   676 	if (IndexPresent())
       
   677 		{
       
   678 		TRAPD(ret, iIndex->InsertL(aPos, aBuf, *iGlobalParaFormatLayer));
       
   679 		if (ret != KErrNone)
       
   680 			{
       
   681 			CPlainText::Delete(aPos,length);
       
   682 			User::Leave(ret);
       
   683 			}
       
   684 		SetHasChanged(ETrue);
       
   685 		}
       
   686 
       
   687 	iParserData->MergeRange(aPos,0,length);
       
   688 	CallEditObserver(aPos,length);
       
   689 
       
   690 	__TEST_INVARIANT;
       
   691 	}
       
   692 
       
   693 
       
   694 EXPORT_C void CRichText::InsertL(TInt aPos,const TPictureHeader& aHeader)
       
   695 /**Inserts a picture header into the text object at a specified document
       
   696 position. The picture header specified must reference a valid picture, or
       
   697 a panic occurs.
       
   698 
       
   699 A panic also occurs if the text object is in an "insert pending" state
       
   700 (SetInsertCharFormatL() has been called and has not been cancelled using
       
   701 CancelInsertCharFormat()) and aPos is not the same as the insertion point.
       
   702 
       
   703 This method takes ownership of a picture referenced in aHeader.
       
   704 
       
   705 @param aPos The document position at which to insert the picture header. Must
       
   706 be valid, or a panic occurs.
       
   707 @param aHeader A picture header. This holds a pointer to the picture to insert,
       
   708 and information about the picture. */
       
   709 	{
       
   710 	__TEST_INVARIANT;
       
   711 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
   712 
       
   713 	CleanupStack::PushL(aHeader.iPicture);
       
   714 
       
   715 	if (!IndexPresent())
       
   716 		CreateAndGenerateMarkupComponentL();
       
   717 	TBuf<1> picture;
       
   718 	picture.Append(EPictureCharacter);
       
   719 	CPlainText::InsertL(aPos, picture);
       
   720 
       
   721     CleanupStack::Pop(aHeader.iPicture);
       
   722 
       
   723 	TBool pictureOwnershipTaken(EFalse);
       
   724 	TRAPD(ret, iIndex->InsertL(aPos, aHeader,pictureOwnershipTaken));
       
   725 	if (ret != KErrNone)
       
   726 		{
       
   727 		if(!pictureOwnershipTaken)
       
   728 		    {
       
   729 		    const_cast <TPictureHeader&> (aHeader).DeletePicture();
       
   730 		    }
       
   731 		CPlainText::Delete(aPos,picture.Length());  // remove the picture place-holder
       
   732     	User::Leave(ret);
       
   733 		}
       
   734 
       
   735 	SetHasChanged(ETrue);
       
   736 	iParserData->MergeRange(aPos,0,1);
       
   737 	CallEditObserver(aPos,1);
       
   738 	__TEST_INVARIANT;
       
   739 	}
       
   740 
       
   741 
       
   742 EXPORT_C TBool CRichText::DeleteL(TInt aPos, TInt aLength)
       
   743 /** Deletes one or more characters beginning at, and including, the character at
       
   744 a specified document position. Can leave because paragraphs may be merged
       
   745 and reformatted by the function.
       
   746 
       
   747 @param aPos The start of the range of characters to delete. Must be valid
       
   748 or a panic occurs.
       
   749 @param aLength The number of characters to delete. Must be positive or a panic
       
   750 occurs. The sum of aPos and aLength must be less than the document length,
       
   751 or a panic occurs.
       
   752 @return Indicates whether two paragraphs have been merged as a result of the
       
   753 delete, indicating that the formatting of part of the resulting paragraph
       
   754 may have changed. */
       
   755 	{
       
   756 	// Deletes aRange number of characters from the text component
       
   757 	// and the corresponding index data.
       
   758 	// Delete commences at, and includes, character position aPos.
       
   759 	__TEST_INVARIANT;
       
   760 
       
   761 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
   762 	__ASSERT_ALWAYS(aLength >= 0, Panic(EDebugDeleteZeroLength));
       
   763 	__ASSERT_ALWAYS(aPos + (aLength - 1) <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
   764 
       
   765 	TBool requireMerge = EFalse;
       
   766 	if (!IndexPresent())
       
   767 		CPlainText::Delete(aPos,aLength);
       
   768 	else
       
   769 		{
       
   770 		iIndex->CancelInsertCharFormat();
       
   771 		TIndexDeleteInfo info;
       
   772 		iIndex->SetForDeleteL(info, aPos, aLength);
       
   773 		CPlainText::Delete(aPos,aLength);
       
   774 		requireMerge = iIndex->DeleteNow(info);
       
   775 		}
       
   776 	iParserData->MergeRange(aPos,aLength,0);
       
   777 	CallEditObserver(aPos,-aLength);
       
   778 
       
   779 	__TEST_INVARIANT;
       
   780 	return requireMerge;
       
   781 	}
       
   782 
       
   783 EXPORT_C void CRichText::DeleteParagraph(TInt aPos, TInt aLength)
       
   784 /** Deletes one or more whole paragraphs of text. No paragraphs can be merged together
       
   785 by this function, so it cannot leave it must only be used to delete entire
       
   786 paragraphs.
       
   787 
       
   788 @param aPos The document position of the start of the first paragraph to delete.
       
   789 Must be a valid position or a panic occurs.
       
   790 @param aLength The number of characters to delete. */
       
   791 	{
       
   792 	// Use to remove entire paragraphs of text.
       
   793 	// Leave-safe if called in this context.
       
   794 	// MUST NOT CALL if not in this context.
       
   795 	__TEST_INVARIANT;
       
   796 
       
   797 	// Store the length of the text before we commence with deletions.
       
   798 	TInt initialDocLen=DocumentLength();
       
   799 
       
   800 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= initialDocLen, Panic(ECharPosBeyondDocument));
       
   801 	__ASSERT_ALWAYS(aPos + aLength <= initialDocLen + 1, Panic(ECharPosBeyondDocument));
       
   802 
       
   803 	if (aLength <= 0)
       
   804 		return;
       
   805 
       
   806 	if (IndexPresent())
       
   807 		iIndex->DeleteParagraph(aPos, aLength);
       
   808 	CPlainText::Delete(aPos,aLength);
       
   809 
       
   810 	// Change here for defect INC005336.
       
   811 	// Previously the MergeRange call (see else line) was incorrectly handling
       
   812 	// the scenario where all but the first paragraph was deleted e.g. pasting
       
   813 	// multi line buffer into a single line text control in a new email on Techview
       
   814 	// emulator.
       
   815 	// This was because the deletion in the two lines above would delete the
       
   816 	// 'end-of-text' maker causing the iEndParse member of CParserData to
       
   817 	// index the char right after the end of test marker. This would panic
       
   818 	// plugin parsers thatsubsquently executed.
       
   819 
       
   820 	if (aPos+aLength > initialDocLen)
       
   821 		// When deletion includes the end-of-text marker, adjust start
       
   822 		// supplied so that it appears to MergeRange that we are
       
   823 		// deleting the paragraph and CR just before it which belongs
       
   824 		// to the previous paragraph and not the end-of-text marker.
       
   825 		// This is actually the end result of the deletion anyway!
       
   826 		iParserData->MergeRange(initialDocLen-aLength,aLength,0);
       
   827 	else
       
   828 		// All other deletions which don't.
       
   829 		iParserData->MergeRange(aPos,aLength,0);
       
   830 
       
   831 	CallEditObserver(aPos,-aLength);
       
   832 
       
   833 	__TEST_INVARIANT;
       
   834 	}
       
   835 
       
   836 EXPORT_C void CRichText::DeleteFromParagraph(TInt aPos, TInt aLength)
       
   837 /** Removes a range of characters from within a single paragraph only. Should not
       
   838 be used for deleting an entire paragraph or paragraphs because this may cause
       
   839 it to leave. Otherwise, it is guaranteed not to leave.
       
   840 
       
   841 @param aPos The document position of the start of the range of characters
       
   842 to delete. Must be a valid document position, or a panic occurs.
       
   843 @param aLength The number of characters to delete. The sum of aPos and aLength
       
   844 must be less than the document length, or a panic occurs. */
       
   845 	{
       
   846 	// Removes aLength characters from *within* a single paragraph only.
       
   847 	// Guaranteed not to leave if this pre-condition holds true.
       
   848 	__TEST_INVARIANT;
       
   849 
       
   850 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
   851 	__ASSERT_ALWAYS(aPos + (aLength - 1) <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
   852 
       
   853 	if (aLength <= 0)
       
   854 		return;
       
   855 
       
   856 	if (IndexPresent())
       
   857 		iIndex->DeleteFromParagraph(aPos, aLength);
       
   858 	CPlainText::Delete(aPos,aLength);
       
   859 	iParserData->MergeRange(aPos,aLength,0);
       
   860 	CallEditObserver(aPos,-aLength);
       
   861 
       
   862 	__TEST_INVARIANT;
       
   863 	}
       
   864 
       
   865 EXPORT_C TInt CRichText::ParagraphCount()const
       
   866 /** Gets a count of the number of paragraphs in the text object.
       
   867 
       
   868 Note:
       
   869 
       
   870 The paragraph delimiter which terminates every text object means this function
       
   871 always returns a count of at least one.
       
   872 
       
   873 @return The number of paragraphs in the document. */
       
   874 	{
       
   875 	// Returns a count of the number of paragraphs
       
   876 	// in the document.
       
   877 	//
       
   878 	__TEST_INVARIANT;
       
   879 
       
   880 	if (IndexPresent())
       
   881 		return iIndex->ParagraphCount();
       
   882 	else
       
   883 		return CPlainText::ParagraphCount();
       
   884 	}
       
   885 
       
   886 
       
   887 EXPORT_C TEtextComponentInfo CRichText::ComponentInfo() const
       
   888 /** Gets information about the number of components contained in the text object
       
   889 (the field count, the picture count and the style count).
       
   890 
       
   891 @return Contains the component information. */
       
   892 	{
       
   893 	return TEtextComponentInfo(FieldCount(), PictureCount(), StyleCount());
       
   894 	}
       
   895 
       
   896 EXPORT_C TInt CRichText::CharPosOfParagraph(TInt& aLength, TInt aParaOffset) const
       
   897 /** Finds the length and the start position of a paragraph identified by its
       
   898 paragraph number. The first paragraph is numbered zero.
       
   899 
       
   900 Notes:
       
   901 
       
   902 if aParaOffset is invalid, (equal to or greater than the total number of
       
   903 paragraphs), the function's return value is EScanEndOfData (= -1)
       
   904 
       
   905 @param aLength On return contains the length of the specified paragraph.
       
   906 @param aParaOffset The paragraph number. The first paragraph is numbered zero.
       
   907 @return The document position of the first character in the paragraph. */
       
   908 	{
       
   909 	// Returns the character position of the first character of paragraph aParaOffset,
       
   910 	// where aParaOffset specifies the nth paragraph.
       
   911 	// The length of this nth paragraph is written to aLength.
       
   912 	//
       
   913 	// If aParaOffset specifies a paragraph that does not exist, EScanEndOfData is returned.
       
   914 	//
       
   915 	__TEST_INVARIANT;
       
   916 
       
   917 	if (IndexPresent())
       
   918 		return iIndex->CharPosOfParagraph(aLength, aParaOffset);
       
   919 	else
       
   920 		return CPlainText::CharPosOfParagraph(aLength, aParaOffset);
       
   921 	}
       
   922 
       
   923 EXPORT_C TInt CRichText::ParagraphNumberForPos(TInt& aPos) const
       
   924 /** Gets the number of the paragraph which contains a document position.
       
   925 Paragraph numbering begins at zero.
       
   926 
       
   927 @param aPos A document position. Must be valid or a panic occurs. On return,
       
   928 contains the document position of the first character in the paragraph in
       
   929 which it is located.
       
   930 @return The number of the paragraph containing the specified document position. */
       
   931 	{
       
   932 	// Returns the paragraph offset for the specified character position aPos.
       
   933 	// aPos is in turn modified to hold the character position of the first character
       
   934 	// of this paragraph.  If aPos is already on a paragraph boundary then do nothing.
       
   935 	//
       
   936 	__TEST_INVARIANT;
       
   937 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
   938 
       
   939 	if (IndexPresent())
       
   940 		return iIndex->ParagraphNumberForPos(aPos);
       
   941 	else
       
   942 		return CPlainText::ParagraphNumberForPos(aPos);
       
   943 	}
       
   944 
       
   945 /** Applies character formatting to a zero length selection, for example
       
   946 turning bold on. This has the effect that the formatting will be applied to
       
   947 text subsequently inserted at the position. This "insert pending" state is
       
   948 cancelled by calling CancelInsertCharFormat().
       
   949 
       
   950 Note 1: After calling this function, if text is inserted at a different
       
   951 position to aPos, a panic will occur, unless CancelInsertCharFormat() has been
       
   952 called before the insertion to cancel the "insert pending" state.
       
   953 
       
   954 Note 2: If the insert character format is being set for the end of the
       
   955 paragraph, the paragraph delimiter is set to that format as well. This helps
       
   956 end-of-paragraph behaviour be more similar to other places.
       
   957 
       
   958 @param aFormat The character format values to apply.
       
   959 @param aMask Character format mask specifying the attributes affected.
       
   960 @param aPos The document position at which to insert the character format.
       
   961 @pre aPos must be a valid position, or a panic will occur. */
       
   962 EXPORT_C void CRichText::SetInsertCharFormatL(const TCharFormat& aFormat,
       
   963 	const TCharFormatMask& aMask, TInt aPos)
       
   964 	{
       
   965 	SetExtendedInsertCharFormatL(aFormat, aMask,aPos);
       
   966 	}
       
   967 
       
   968 void CancelInsertCharFormat(TAny* aCRichTextIndex)
       
   969 	{
       
   970 	reinterpret_cast<CRichTextIndex*>(aCRichTextIndex)->CancelInsertCharFormat();
       
   971 	}
       
   972 
       
   973 void CRichText::SetExtendedInsertCharFormatL(const TCharFormatX& aFormat, const TCharFormatXMask& aMask, TInt aPos)
       
   974 	{
       
   975 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
   976 	CreateAndGenerateMarkupComponentL();
       
   977 	CRichTextIndex* index = iIndex.AsPtr();
       
   978 	if (index->InsertCharFormatIsActive())
       
   979 		{
       
   980 		TCharFormatX format = aFormat;
       
   981         TCharFormatXMask mask = aMask;
       
   982         CCharFormatLayer* currentLayer = index->GetCurrentInsertCharFormat();
       
   983         currentLayer->Sense(format,mask);
       
   984 		CCharFormatLayer* newLayer = CCharFormatLayer::NewCopyBaseL(currentLayer);
       
   985 		CleanupStack::PushL(newLayer);
       
   986         newLayer->SetL(format,mask);
       
   987 		if (Read(aPos, 1)[0] == EParagraphDelimiter)
       
   988 			index->ApplyCharFormatL(aFormat, aMask, aPos, 1, EFalse);
       
   989 		if (index->InsertCharFormatIsActive())
       
   990 			{
       
   991 			currentLayer = index->GetCurrentInsertCharFormat();
       
   992 			currentLayer->Swap(*newLayer);
       
   993 			}
       
   994 		CleanupStack::PopAndDestroy(newLayer);
       
   995 		}
       
   996 	else
       
   997 		{
       
   998 		TCleanupItem cleanup(::CancelInsertCharFormat, index);
       
   999 		CleanupStack::PushL(cleanup);
       
  1000 		index->NewInsertCharFormatL(aFormat, aMask, aPos);
       
  1001 		if (Read(aPos, 1)[0] == EParagraphDelimiter)
       
  1002 			index->ApplyCharFormatL(aFormat, aMask, aPos, 1, EFalse);
       
  1003 		CleanupStack::Pop();
       
  1004 		}
       
  1005 	SetHasChanged(TRUE);
       
  1006 	}
       
  1007 	
       
  1008 EXPORT_C void CRichText::ExtendedInterface(TAny*& aInterface, TUid aInterfaceId)
       
  1009 /**
       
  1010 Returns the interface corresponding to the specified UID if it exists, or 0 if not. 
       
  1011 Overridden versions should base call rather than returning 0.
       
  1012 For KUidRichText, CRichText will be returned if rich text is supported.
       
  1013 
       
  1014 @param aInterfaceId The UID indicating the interface to return
       
  1015 @param aInterface The interface corresponding to aInterfaceId
       
  1016 if it is supported, or 0 if it is not
       
  1017 */
       
  1018 	{ 
       
  1019 	if(KUidRichText == aInterfaceId) 
       
  1020 		{
       
  1021 		aInterface = REINTERPRET_CAST(TAny*, this);
       
  1022 		}
       
  1023 	else
       
  1024 		{
       
  1025 	    CGlobalText::ExtendedInterface(aInterface, aInterfaceId);
       
  1026 		}
       
  1027 	}
       
  1028 
       
  1029 EXPORT_C TBool CRichText::DelSetInsertCharFormatL(TInt aPos, TInt aLength)
       
  1030 /** Deletes a range of characters. The range affected is from aPos to
       
  1031 aPos+(aLength-1) inclusive. It differs from DeleteL() in that this function
       
  1032 preserves the formatting of the deleted character at position aPos, so that
       
  1033 any text subsequently inserted at aPos will have that formatting applied to it.
       
  1034 
       
  1035 A panic occurs if:
       
  1036 
       
  1037 after calling this function, text is inserted at a different position to aPos,
       
  1038 without calling CancelInsertCharFormat() before the insertion
       
  1039 
       
  1040 aPos is invalid
       
  1041 
       
  1042 aLength is negative
       
  1043 
       
  1044 the range goes beyond the end of the document
       
  1045 
       
  1046 @param aPos The document position of the first character to delete.
       
  1047 @param aLength The number of characters to delete.
       
  1048 @return ETrue if two paragraphs have been merged as a result of the deletion;
       
  1049 EFalse if there has been no paragraph merge. */
       
  1050 	{
       
  1051 	// Delete aLength characters, commencing at, and including, aPos.
       
  1052 	// If aPos is on a phrase boundary, and the whole phrase or more is deleted then
       
  1053 	// remember temporarily the phrase format.  This is applied to any content that is
       
  1054 	// immediately inserted.
       
  1055 	//
       
  1056 	__TEST_INVARIANT;
       
  1057 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1058 	__ASSERT_ALWAYS(aLength >= 0, Panic(EDebugDeleteZeroLength));
       
  1059 	__ASSERT_ALWAYS(aPos + (aLength - 1) <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1060 
       
  1061 	TBool parasMerged = EFalse;
       
  1062 	if (!IndexPresent())
       
  1063 		CPlainText::DeleteL(aPos, aLength);
       
  1064 	else
       
  1065 		{
       
  1066 		parasMerged = iIndex->DelSetInsertCharFormatL(aPos, aLength);
       
  1067 		CPlainText::Delete(aPos,aLength);
       
  1068 		SetHasChanged(ETrue);
       
  1069 		}
       
  1070 	iParserData->MergeRange(aPos,aLength,0);
       
  1071 	CallEditObserver(aPos,-aLength);
       
  1072 
       
  1073 	__TEST_INVARIANT;
       
  1074 	return parasMerged;
       
  1075 	}
       
  1076 
       
  1077 EXPORT_C void CRichText::CancelInsertCharFormat()
       
  1078 /** Cancels the "insert pending" state set by a call to SetInsertCharFormatL()
       
  1079 or DelSetInsertCharFormatL().
       
  1080 
       
  1081 This function removes the restriction on the text insertion position imposed
       
  1082 by these two functions. It is recommended that it is called before every cursor
       
  1083 movement, scroll, paste, etc. This call is a small overhead, and has no effect
       
  1084 if not applicable. */
       
  1085 	{
       
  1086 	// Cancels the transitory state where a specified character format
       
  1087 	// is applied *on top of* any inherited formatting.  eg, when bold is on.
       
  1088 	// Cancel when: (1) the text position is altered.  (2) the first character
       
  1089 	// has been inserted following the setting of this state.
       
  1090 	//
       
  1091 	if (IndexPresent() && iIndex->InsertCharFormatIsActive())
       
  1092 		{
       
  1093 		iIndex->CancelInsertCharFormat();
       
  1094 		SetHasChanged(ETrue);
       
  1095 		}
       
  1096 	}
       
  1097 
       
  1098 EXPORT_C void CRichText::ApplyParaFormatL(const CParaFormat* aFormat, const TParaFormatMask& aMask, TInt aPos, TInt aLength)
       
  1099 /** Applies paragraph formatting to a range of paragraphs. The attributes which
       
  1100 are set in the mask are taken from aFormat and applied. The attributes which
       
  1101 are not set in the mask are not changed.
       
  1102 
       
  1103 The region affected consists of every paragraph containing one or more
       
  1104 characters in the range aPos to aPos+(aLength-1).
       
  1105 
       
  1106 @param aFormat Contains the paragraph format attribute values to apply.
       
  1107 @param aMask Specifies which paragraph format attributes should be affected.
       
  1108 @param aPos The document position of the start of the range.
       
  1109 @param aLength The number of characters in the range. */
       
  1110 	{
       
  1111 	// Applies the specified format attributes to the paragraphs covering
       
  1112 	// character position aPos to aPos+aLength-1.
       
  1113 	//
       
  1114 	__TEST_INVARIANT;
       
  1115 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1116 	__ASSERT_ALWAYS(aLength >= 0,Panic(EApplyParaFormatNegativeLength));
       
  1117 	__ASSERT_ALWAYS(aPos + (aLength - 1) <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1118 
       
  1119 	CreateAndGenerateMarkupComponentL();
       
  1120 	iIndex->ApplyParaFormatL(aFormat, aMask, aPos, aLength);
       
  1121 	SetHasChanged(ETrue);
       
  1122 
       
  1123 	__TEST_INVARIANT;
       
  1124 	}
       
  1125 
       
  1126 EXPORT_C void CRichText::ApplyCharFormatL(const TCharFormat& aFormat, const TCharFormatMask& aMask, TInt aPos, TInt aLength)
       
  1127 /** Applies character formatting to a range of characters. The attributes which
       
  1128 are set in the mask are read from aFormat and applied. The attributes which
       
  1129 are not set in the mask are not changed. The range of characters affected
       
  1130 is from aPos to aPos+(aLength-1) inclusive. The sum of aPos and aLength
       
  1131 must be less than or equal to the document length, or a panic occurs.
       
  1132 
       
  1133 @param aFormat Contains the character format attribute values to apply.
       
  1134 @param aMask Bitmask specifying which character format attributes should be
       
  1135 applied.
       
  1136 @param aPos Document position from which to apply the new character formatting.
       
  1137 Must be greater than or equal to zero, or a panic occurs.
       
  1138 @param aLength The number of characters to which the new formatting should
       
  1139 be applied. Must be greater than or equal to zero, or a panic occurs. If the
       
  1140 length is zero, the function has the same effect as SetInsertCharFormatL(). */
       
  1141 	{
       
  1142 	// Applies the specified character formatting to the characters conatined within the range
       
  1143 	// aPos to aPos+(aLength-1).
       
  1144 	// If aLength is zero, the SetInsertCharFormat state is called.
       
  1145 	//
       
  1146 	__ETEXT_WATCH(APPLY_CHAR_FORMAT);
       
  1147 	__TEST_INVARIANT;
       
  1148 	
       
  1149 	TInt document_length = DocumentLength();
       
  1150 	__ASSERT_ALWAYS(aPos >= 0,Panic(ECharPosBeyondDocument));
       
  1151 	__ASSERT_ALWAYS(aLength >= 0,Panic(EApplyCharFormatNegativeLength));
       
  1152 	__ASSERT_ALWAYS(aPos + aLength - 1 <= document_length,Panic(ECharPosBeyondDocument));
       
  1153 
       
  1154 	//If some characters are highlighted AND current position + highlighted txt = document length	
       
  1155 	// Fix for INC097216. Compensate for the changes introduced to Form in defect fix INC087637,
       
  1156 	// which now considers the height of the EOD character; meaning that this character now 
       
  1157 	// needs to be formatted along with rest of text.
       
  1158 	if ((aLength > 0) && (aPos + aLength == document_length))
       
  1159 		{
       
  1160 		aLength++;
       
  1161 		}
       
  1162 	
       
  1163 	DoApplyExtendedCharFormatL(aFormat, aMask, aPos, aLength);
       
  1164 	
       
  1165 	__TEST_INVARIANT;
       
  1166 	__ETEXT_WATCH_END(APPLY_CHAR_FORMAT);
       
  1167 	}
       
  1168 	
       
  1169 // This method is used internally only. It does not format the EOD character.
       
  1170 void CRichText::ApplyExtendedCharFormatL(const TCharFormatX& aFormat,const TCharFormatXMask& aMask,TInt aPos,TInt aLength)
       
  1171 	{
       
  1172 	TInt document_length = DocumentLength();
       
  1173 	__ASSERT_ALWAYS(aPos >= 0,Panic(ECharPosBeyondDocument));
       
  1174 	__ASSERT_ALWAYS(aLength >= 0,Panic(EApplyCharFormatNegativeLength));
       
  1175 	__ASSERT_ALWAYS(aPos + aLength - 1 <= document_length,Panic(ECharPosBeyondDocument));
       
  1176 	
       
  1177 	DoApplyExtendedCharFormatL(aFormat, aMask, aPos, aLength);
       
  1178 	}	
       
  1179 	
       
  1180 // Apply the extended character formatting.	
       
  1181 void CRichText::DoApplyExtendedCharFormatL(const TCharFormatX& aFormat,const TCharFormatXMask& aMask,TInt aPos,TInt aLength)
       
  1182 	{
       
  1183 	if (aLength > 0)
       
  1184 		{
       
  1185 		CreateAndGenerateMarkupComponentL();
       
  1186 		iIndex->ApplyCharFormatL(aFormat,aMask,aPos,aLength);
       
  1187 		SetHasChanged(ETrue);
       
  1188 		}
       
  1189 	else
       
  1190 		SetExtendedInsertCharFormatL(aFormat,aMask,aPos);
       
  1191 	}		
       
  1192 
       
  1193 EXPORT_C void CRichText::SetStyleListExternallyOwned(const CStyleList& aStyleList)
       
  1194 /** Assigns an externally owned style list to the rich text object.
       
  1195 Replaces any previous style list used by the object. Calls
       
  1196 SetStyleListExternallyOwned(ETrue).
       
  1197 
       
  1198 @param aExternallyOwned The style list to assign to this rich text object.
       
  1199 Not owned by the rich text object. */
       
  1200 	{
       
  1201 	CStyleList* styleList = CONST_CAST(CStyleList*, &aStyleList);
       
  1202 	iStyleList = styleList;
       
  1203 	SetStyleListExternallyOwned(ETrue);
       
  1204 	}
       
  1205 
       
  1206 EXPORT_C void CRichText::ApplyParagraphStyleL(const CParagraphStyle& aStyle, TInt aPos, TInt aLength, CParagraphStyle::TApplyParaStyleMode aMode)
       
  1207 /** Applies a specified paragraph style to a range of paragraphs. The region
       
  1208 affected consists of every paragraph containing one or more characters in the
       
  1209 range aPos to aPos+(aLength-1).
       
  1210 
       
  1211 A panic occurs if:
       
  1212 
       
  1213 aPos is invalid, or
       
  1214 
       
  1215 aLength is negative, or
       
  1216 
       
  1217 the range goes beyond the end of the document, or
       
  1218 
       
  1219 the rich text object has no style list
       
  1220 
       
  1221 @param aStyle The style to apply.
       
  1222 @param aPos The document position of the start of the range.
       
  1223 @param aLength The number of characters in the range.
       
  1224 @param aMode Controls what specific formatting, if any, should be preserved
       
  1225 when the style is applied. */
       
  1226 	{
       
  1227 	// Applies the specified paragraph style to the paragraphs covering
       
  1228 	// character positions aPos to aPos+aLength-1.
       
  1229 	//
       
  1230 	__TEST_INVARIANT;
       
  1231 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1232 	__ASSERT_ALWAYS(aLength >= 0, Panic(EApplyParaStyleNegativeLength));
       
  1233 	__ASSERT_ALWAYS(aPos + (aLength - 1) <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1234 	__ASSERT_ALWAYS(StyleListPresent(), Panic(ERichTextNotSetForUsingStyles));
       
  1235 
       
  1236 	CreateAndGenerateMarkupComponentL();
       
  1237 	iIndex->ApplyParagraphStyleL(aStyle, aPos, aLength, iGlobalCharFormatLayer, aMode);
       
  1238 	SetHasChanged(ETrue);
       
  1239 
       
  1240 	__TEST_INVARIANT;
       
  1241 	}
       
  1242 
       
  1243 EXPORT_C void CRichText::NotifyStyleChangedL(const CParagraphStyle* aTo, const CParagraphStyle* aFrom)
       
  1244 /** Removes a style from every paragraph in the document to which it applies,
       
  1245 and replaces it with another.
       
  1246 
       
  1247 If style aTo is NULL, aFrom is replaced by the global character and paragraph
       
  1248 format layers, so that in effect, style aFrom is removed. Any specific
       
  1249 formatting which has been applied to the paragraphs is retained.
       
  1250 
       
  1251 Notes:
       
  1252 
       
  1253 This function should be called on the text content object after changing a
       
  1254 style in the style list.
       
  1255 
       
  1256 A panic occurs if the rich text object does not use a style list (this can
       
  1257 be tested for using StyleListPresent()).
       
  1258 
       
  1259 @param aTo The new paragraph style to apply.
       
  1260 @param aFrom The paragraph style to remove. */
       
  1261 	{
       
  1262 	// Update the rich text index following the change of an applied paragraph style.
       
  1263 	//
       
  1264 	__TEST_INVARIANT;
       
  1265 	__ASSERT_ALWAYS(StyleListPresent(), Panic(ERichTextNotSetForUsingStyles));
       
  1266 
       
  1267 	CreateAndGenerateMarkupComponentL();
       
  1268 	iIndex->NotifyStyleChangedL(aTo, aFrom, *iGlobalParaFormatLayer, *iGlobalCharFormatLayer);
       
  1269 	SetHasChanged(ETrue);
       
  1270 
       
  1271 	__TEST_INVARIANT;
       
  1272 	}
       
  1273 
       
  1274 EXPORT_C const CParaFormatLayer* CRichText::ParagraphStyle(TBool& aStyleChangesOverRange, TInt aPos, TInt aLength) const
       
  1275 /** Gets a pointer to the first paragraph style encountered in the specified
       
  1276 range.
       
  1277 
       
  1278 @param aStyleChangesOverRange On return, set to ETrue if more than one paragraph
       
  1279 style is used over the specified range of characters. Otherwise EFalse
       
  1280 @param aPos The document position of the start of the range. Must be valid.
       
  1281 @param aLength The number of characters in the range. Must be greater than
       
  1282 or equal to zero.
       
  1283 @return Pointer to the paragraph style which applies to the paragraph containing
       
  1284 document position aPos. Its type (returned by CParaFormatLayer::Type())
       
  1285 indicates whether this object is a style, or just a paragraph format layer. */
       
  1286 	{
       
  1287 	__TEST_INVARIANT;
       
  1288 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1289 	__ASSERT_ALWAYS(aLength >= 0,Panic(EParagraphStyleNegativeLength));
       
  1290 	__ASSERT_ALWAYS(aPos + (aLength - 1) <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1291 
       
  1292 	if (IndexPresent())
       
  1293 		return iIndex->ParagraphStyle(aStyleChangesOverRange, aPos, aLength);
       
  1294 	else
       
  1295 		{
       
  1296 		aStyleChangesOverRange = EFalse;
       
  1297 		return iGlobalParaFormatLayer;
       
  1298 		}
       
  1299 	}
       
  1300 
       
  1301 EXPORT_C void CRichText::SetHasChanged(TBool aHasChanged)
       
  1302 /** Sets whether the document's content or formatting has changed. This function
       
  1303 is called with an value of ETrue by all functions which modify the text content
       
  1304 or formatting. Use CEditableText::HasChanged() to test whether the document
       
  1305 has changed.
       
  1306 
       
  1307 @param aHasChanged ETrue if the text object has been changed, EFalse if not. */
       
  1308 	{
       
  1309 	// Replaces the base class method of the same name.
       
  1310 	//
       
  1311 	if (aHasChanged && IndexPresent())
       
  1312 		iIndex->DocumentChanged();
       
  1313 	CGlobalText::SetHasChanged(aHasChanged);
       
  1314 	}
       
  1315 
       
  1316 EXPORT_C void CRichText::RemoveSpecificParaFormatL(TInt aPos, TInt aLength)
       
  1317 /** Removes all specific paragraph formatting from a range of paragraphs. This
       
  1318 does not remove formatting from the object's global paragraph format layer.
       
  1319 The region affected consists of every paragraph containing one or more
       
  1320 characters in the range covered by document position aPos to aPos+(aLength-1)
       
  1321 inclusive.
       
  1322 
       
  1323 A panic occurs in the following situations:
       
  1324 
       
  1325 the position is negative,
       
  1326 
       
  1327 the length is negative,
       
  1328 
       
  1329 the range goes beyond the end of the document
       
  1330 
       
  1331 @param aPos The document position of the start of the range.
       
  1332 @param aLength The number of characters in the range. */
       
  1333 	{
       
  1334 	// Removes all specific paragraph formatting from the selected region.
       
  1335 	//
       
  1336 	__ETEXT_WATCH(REMOVE_PARA_FORMAT);
       
  1337 
       
  1338 	__TEST_INVARIANT;
       
  1339 
       
  1340 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1341 	__ASSERT_ALWAYS(aLength >= 0, Panic(ERemoveSpecificParaFormatNegativeLength));
       
  1342 	__ASSERT_ALWAYS(aPos + (aLength - 1) <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1343 
       
  1344 	if (IndexPresent())
       
  1345 		{
       
  1346 		iIndex->RemoveSpecificParaFormatL(aPos, aLength);
       
  1347 		SetHasChanged(ETrue);
       
  1348 		}
       
  1349 
       
  1350 	__TEST_INVARIANT;
       
  1351 
       
  1352 	__ETEXT_WATCH_END(REMOVE_PARA_FORMAT);
       
  1353 	}
       
  1354 
       
  1355 EXPORT_C void CRichText::RemoveSpecificCharFormatL(TInt aPos, TInt aLength)
       
  1356 /** Removes all specific character formatting from a range of characters (does
       
  1357 not remove the formatting which has been taken from the object's global character
       
  1358 format layer). A panic occurs in the following situations:
       
  1359 
       
  1360 the position is negative,
       
  1361 
       
  1362 the length is negative,
       
  1363 
       
  1364 the range goes beyond the end of the document
       
  1365 
       
  1366 @param aPos The document position of the start of the region affected.
       
  1367 @param aLength The number of characters in the region affected. If zero, the
       
  1368 function has no effect. */
       
  1369 	{
       
  1370 	__TEST_INVARIANT;
       
  1371 	
       
  1372 	TInt document_length = DocumentLength();
       
  1373 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1374 	__ASSERT_ALWAYS(aLength >= 0, Panic(ERemoveSpecificParaFormatNegativeLength));
       
  1375 	__ASSERT_ALWAYS(aPos + (aLength - 1) <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1376 	
       
  1377 	// in correspondance to INC097216, character format removing considers the height of end of document
       
  1378     // character
       
  1379     if (aPos + aLength == document_length)
       
  1380    		{
       
  1381         aLength++;
       
  1382         }
       
  1383 
       
  1384 	if (aLength > 0 && IndexPresent())
       
  1385 		{
       
  1386 		iIndex->RemoveSpecificCharFormatL(aPos, aLength);
       
  1387 		SetHasChanged(ETrue);
       
  1388 		}
       
  1389 
       
  1390 	__TEST_INVARIANT;
       
  1391 	}
       
  1392 
       
  1393 EXPORT_C void CRichText::GetChars(TPtrC& aText, TCharFormat& aFormat, TInt aPos) const
       
  1394 /** Gets a constant pointer descriptor to a portion of the text object
       
  1395 with constant character formatting.
       
  1396 
       
  1397 The view starts at the document position specified, and ends at: the
       
  1398 last character which shares the same character formatting, orthe end
       
  1399 of the document, orthe end of the segment, if segmented storage is
       
  1400 being usedwhichever occurs first. Also fills a character format object
       
  1401 with the character formatting of the range of characters.
       
  1402 
       
  1403 @param aView On return, a constant pointer to a portion of the text.
       
  1404 @param aFormat On return, contains the character formatting of the text.
       
  1405 @param aPos The start position for the view. Must be a valid document
       
  1406 position, or a panic occurs. */
       
  1407 	{
       
  1408 	// Get a run of text and its format, starting at aPos.
       
  1409 	__ETEXT_WATCH(GET_CHARS)
       
  1410 	TCharFormatX format;
       
  1411 	GetTextAndExtendedFormat(aText, format, aPos);
       
  1412 	OverrideFormatForParsersIfApplicable(aText, format, aPos);
       
  1413 	aFormat = format.iCharFormat;
       
  1414 	OverrideFormatOfInlineTextIfApplicable(aText, aFormat, aPos);
       
  1415 	__ETEXT_WATCH_END(GET_CHARS)
       
  1416 	}
       
  1417 
       
  1418 
       
  1419 void CRichText::GetTextAndExtendedFormat(TPtrC& aText,TCharFormatX& aFormat,TInt aPos) const
       
  1420 	{
       
  1421 	__TEST_INVARIANT;
       
  1422 	TInt documentLength = DocumentLength();
       
  1423 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= documentLength, Panic(ECharPosBeyondDocument));
       
  1424 	if (!IndexPresent())
       
  1425 		{
       
  1426 		aText.Set(Read(aPos));
       
  1427 		iGlobalCharFormatLayer->SenseEffective(aFormat);
       
  1428 		}
       
  1429 	else
       
  1430 		{
       
  1431 		int phrase_length = iIndex->GetChars(aFormat,aPos);
       
  1432 		aText.Set(Read(aPos,phrase_length));
       
  1433 		}
       
  1434 	__TEST_INVARIANT;
       
  1435 	}
       
  1436 
       
  1437 EXPORT_C TInt CRichText::GetPictureSizeInTwips(TSize& aSize, TInt aPos) const
       
  1438 /** Gets the size of a picture located at a specified document position.
       
  1439 
       
  1440 @param aSize On return, contains the size of the picture located at aPos.
       
  1441 @param aPos Document position of the picture. Must be a valid position.
       
  1442 @return KErrNotFound if there is no picture at the specified document position,
       
  1443 KErrNone if there is. */
       
  1444 	{
       
  1445 	__TEST_INVARIANT;
       
  1446 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1447 
       
  1448 	if (IndexPresent())
       
  1449 		return iIndex->GetPictureSizeInTwips(aSize, aPos);
       
  1450 	else
       
  1451 		return KErrNotFound;
       
  1452 	}
       
  1453 
       
  1454 EXPORT_C CPicture* CRichText::PictureHandleL(TInt aPos, MLayDoc::TForcePictureLoad aForceLoad) const
       
  1455 /** Gets a pointer to the picture located at a specified document position, if
       
  1456 one exists. If the picture is not in memory, the function loads it (if the
       
  1457 second argument has a value of MLayDoc::EForceLoadTrue).
       
  1458 
       
  1459 Note:
       
  1460 
       
  1461 In order to load the picture, a picture factory and a store resolver must
       
  1462 have been set.
       
  1463 
       
  1464 @param aPos Document position of the picture character. Must be a valid position.
       
  1465 @param aForceLoad If the picture is not loaded into memory,
       
  1466 MLayDoc::EForceLoadTrue loads it using the picture factory;
       
  1467 MLayDoc::EForceLoadFalse does not, and in this case, the function returns NULL.
       
  1468 @return A pointer to the picture located at aPos. NULL if aPos does not specify
       
  1469 a picture character, or if there is a picture at aPos which is not in memory,
       
  1470 and the second argument is MLayDoc::EForceLoadFalse. */
       
  1471 	{
       
  1472 	__ETEXT_WATCH(PICTURE_HANDLE);
       
  1473 
       
  1474 	__TEST_INVARIANT;
       
  1475 	__ASSERT_ALWAYS(aPos>=0 && aPos<=DocumentLength(),Panic(ECharPosBeyondDocument));
       
  1476 
       
  1477 	if (IndexPresent())
       
  1478 		return iIndex->PictureHandleL(aPos, aForceLoad);
       
  1479 	else
       
  1480 		return NULL;
       
  1481 
       
  1482 	__ETEXT_WATCH_END(PICTURE_HANDLE);
       
  1483 	}
       
  1484 
       
  1485 EXPORT_C void CRichText::GetParagraphFormatL(CParaFormat* aFormat, TInt aPos) const
       
  1486 /** Gets the effective paragraph formatting which applies to the paragraph which
       
  1487 contains a specified document position. On return, aFormat is filled with
       
  1488 values for all paragraph format attributes.
       
  1489 
       
  1490 @param aFormat On return, filled with the paragraph's effective paragraph
       
  1491 formatting.
       
  1492 @param aPos Any document position within the paragraph of interest. */
       
  1493 	{
       
  1494 	__ETEXT_WATCH(GET_PARAGRAPH_FORMAT)
       
  1495 
       
  1496 	__TEST_INVARIANT;
       
  1497 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1498 
       
  1499 	if (!IndexPresent())
       
  1500 		CGlobalText::GetParagraphFormatL(aFormat, aPos);
       
  1501 	else
       
  1502 		{
       
  1503 		aFormat->Reset();
       
  1504 		iIndex->GetParagraphFormatL(aFormat, aPos);
       
  1505 		}
       
  1506 
       
  1507 	__ETEXT_WATCH_END(GET_PARAGRAPH_FORMAT)
       
  1508 	}
       
  1509 
       
  1510 EXPORT_C void CRichText::GetSpecificParagraphFormatL(CParaFormat* aFormat,
       
  1511 													 TParaFormatMask& aMask,
       
  1512 													 TInt aPos) const
       
  1513 // Fills aFormat with the effective Paragraph format attributes for the paragraph
       
  1514 // in which character position aPos is contained.
       
  1515 //
       
  1516 	{
       
  1517 	__ETEXT_WATCH(GET_PARAGRAPH_FORMAT)
       
  1518 
       
  1519 	__TEST_INVARIANT;
       
  1520 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1521 
       
  1522 	aFormat->Reset();
       
  1523 	aMask.ClearAll();
       
  1524 	if (IndexPresent())
       
  1525 		iIndex->GetSpecificParagraphFormatL(aFormat, aMask, aPos);
       
  1526 
       
  1527 	__ETEXT_WATCH_END(GET_PARAGRAPH_FORMAT)
       
  1528 	}
       
  1529 
       
  1530 EXPORT_C void CRichText::GetParaFormatL(CParaFormat* aFormat, TParaFormatMask& aVaries, TInt aPos, TInt aLength,
       
  1531 										CParaFormat::TParaFormatGetMode aMode) const
       
  1532 /** Gets the effective paragraph formatting which applies to a range of paragraphs.
       
  1533 The region involved is every paragraph containing one or more characters in
       
  1534 the range aPos to aPos+(aLength-1) inclusive. On return, aFormat is filled
       
  1535 with values for all paragraph format attributes and the mask indicates the
       
  1536 values that change over the region, and whose value is therefore indeterminate.
       
  1537 
       
  1538 Note:
       
  1539 
       
  1540 If aMode has a value of EFixedAttributes, the function cannot leave.
       
  1541 
       
  1542 @param aFormat Must not be NULL or a panic occurs. On return, contains the
       
  1543 effective paragraph formatting for the range of paragraphs.
       
  1544 @param aVaries On return, a bitmask indicating which paragraph format attributes
       
  1545 vary over the range of characters selected.
       
  1546 @param aPos The document position of the start of the range.
       
  1547 @param aLength The number of characters in the range.
       
  1548 @param aMode The default, EAllAttributes means that values for all paragraph
       
  1549 format attributes are written to aFormat. EFixedAttributes means that tabs,
       
  1550 bullets and borders are not written to aFormat. */
       
  1551 	{
       
  1552 	// Senses the paragraph format of para(s) covered by the region aPos to aPos+aLength-1.
       
  1553 	// aFormat takes the values of all attributes, and the mask aMask indicates those values that change
       
  1554 	// over the selected region, and are therefore *indeterminate*.
       
  1555 	// Application: seeding paragraph formatting dialogs.
       
  1556 	//
       
  1557 	__TEST_INVARIANT;
       
  1558 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1559 	__ASSERT_ALWAYS(aLength >= 0, Panic(EGetParaFormatNegativeLength));
       
  1560 	__ASSERT_ALWAYS(aPos + aLength <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1561 
       
  1562 	if (IndexPresent())
       
  1563 		iIndex->GetParaFormatL(aFormat, aVaries, aPos, aLength, aMode);
       
  1564 	else
       
  1565 		CGlobalText::GetParaFormatL(aFormat, aVaries, aPos, aLength, aMode);
       
  1566 	}
       
  1567 
       
  1568 EXPORT_C void CRichText::GetCharFormat(TCharFormat& aFormat, TCharFormatMask& aVaries, TInt aPos, TInt aLength) const
       
  1569 /** Gets the effective character formatting which applies to a range of
       
  1570 characters. The range of characters involved is from aPos to aPos+(aLength-1)
       
  1571 inclusive. On return, aFormat is filled with values for all character format
       
  1572 attributes, and on return, the mask indicates the values that change over the
       
  1573 region, and whose value is therefore indeterminate.
       
  1574 
       
  1575 The length value can be zero. In this case, the character formatting sensed
       
  1576 is that of the character immediately to the left of the position specified.
       
  1577 
       
  1578 @param aFormat On return, contains the character format values for the range
       
  1579 of characters.
       
  1580 @param aVaries On return, indicates which character format attributes vary
       
  1581 over the range.
       
  1582 @param aPos Document position of the start of the range. Must be valid or a
       
  1583 panic occurs.
       
  1584 @param aLength Number of characters in the range. Must be greater than or equal
       
  1585 to zero, or a panic occurs. */
       
  1586 	{
       
  1587 	// Senses the character formatting of the phrase(s) covered by the region aPos to aPos+aLength-1.
       
  1588 	// May be called with zero length.
       
  1589 	// aFormat takes the values of all character format attributes, and the mask aMask indicates those
       
  1590 	// values that change over the selected region, and are therefore *indeterminate*.
       
  1591 	// Application: seeding character formatting dialogs.
       
  1592 	//
       
  1593 	TCharFormatX format;
       
  1594 	TCharFormatXMask varies;
       
  1595 	GetExtendedCharFormat(format, varies, aPos, aLength);
       
  1596 	aFormat = format.iCharFormat;
       
  1597 	varies.ClearExtendedAttribs();
       
  1598 	aVaries = varies;
       
  1599 	}
       
  1600 
       
  1601 
       
  1602 void CRichText::GetExtendedCharFormat(TCharFormatX& aFormat, TCharFormatXMask& aVaries, TInt aPos, TInt aLength) const
       
  1603 	{
       
  1604 	__TEST_INVARIANT;
       
  1605 	int document_length = DocumentLength();
       
  1606 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= document_length, Panic(ECharPosBeyondDocument));
       
  1607 	__ASSERT_ALWAYS(aLength >= 0, Panic(EGetCharFormatNegativeLength));
       
  1608 	__ASSERT_ALWAYS(aPos + aLength - 1 <= document_length, Panic(ECharPosBeyondDocument));
       
  1609 
       
  1610 	if (IndexPresent())
       
  1611 		iIndex->GetCharFormat(aFormat, aVaries, aPos, aLength);
       
  1612 	else
       
  1613 		{
       
  1614 		iGlobalCharFormatLayer->SenseEffective(aFormat);
       
  1615 		aVaries.ClearAll();
       
  1616 		}
       
  1617 	}
       
  1618 
       
  1619 
       
  1620 void CRichText::GetSpecificCharFormatLeftRight(TCharFormat& aFormat,
       
  1621 									TCharFormatMask& aMask,
       
  1622 									TInt aPos,
       
  1623 									TBool aLeft) const
       
  1624 	{
       
  1625 	__ETEXT_WATCH(GET_SPECIFIC_CHARS);
       
  1626 
       
  1627 	__TEST_INVARIANT;
       
  1628 
       
  1629 	__ASSERT_ALWAYS(aPos >= 0 && aPos <= DocumentLength(), Panic(ECharPosBeyondDocument));
       
  1630 
       
  1631 	if (IndexPresent())
       
  1632 		{
       
  1633 		TCharFormatX format;
       
  1634 		TCharFormatXMask mask;
       
  1635 		iIndex->GetSpecificCharFormatDirection(format, mask, aPos, aLeft);
       
  1636 		aFormat = format.iCharFormat;
       
  1637 		mask.ClearExtendedAttribs();
       
  1638 		aMask = mask;
       
  1639 		}
       
  1640 
       
  1641 	__ETEXT_WATCH_END(GET_SPECIFIC_CHARS);
       
  1642 	}
       
  1643 
       
  1644 EXPORT_C void CRichText::GetSpecificCharFormat(TCharFormat& aFormat, TCharFormatMask& aMask, TInt aPos) const
       
  1645 /** Gets the specific character formatting which applies to the character to the
       
  1646 left of a document position. Specific formatting is just the formatting which
       
  1647 has been applied over the object's global format layers - it is not the
       
  1648 same as the effective formatting.
       
  1649 
       
  1650 @param aFormat On return contains the specific character formatting which
       
  1651 applies to the character to the left of the document position.
       
  1652 @param aMask On return, indicates which character format attributes have been
       
  1653 applied specifically, (not taken from the global layers).
       
  1654 @param aPos The document position. Must be valid or a panic occurs. */
       
  1655 	{
       
  1656 	// Return the format attributes store in the specific layer only, for the specified document position.
       
  1657 	// THIS IS NOT THE EFFECTIVE FORMAT, BUT THE SPECIFIC FORMATTING ONLY.
       
  1658 	//
       
  1659 	GetSpecificCharFormatLeftRight(aFormat, aMask, aPos, ETrue);
       
  1660 	}
       
  1661 
       
  1662 EXPORT_C void CRichText::GetSpecificCharFormatRight(TCharFormat& aFormat, TCharFormatMask& aMask, TInt aPos) const
       
  1663 /** Gets the specific character formatting which applies to the character logically
       
  1664 after a document position. Note that this is not necessarily the character
       
  1665 to the right of the document position, because right to left text is supported.
       
  1666 
       
  1667 Specific formatting is just the formatting which has been applied over the
       
  1668 object's global format layers it is not the same as the effective formatting.
       
  1669 
       
  1670 @param aFormat On return, contains the specific character formatting which
       
  1671 applies to the character logically after the document position.
       
  1672 @param aMask On return, indicates which character format attributes have been
       
  1673 applied specifically, (not taken from the global layers).
       
  1674 @param aPos The document position. Must be valid or a panic occurs. */
       
  1675 	{
       
  1676 	GetSpecificCharFormatLeftRight(aFormat, aMask, aPos, EFalse);
       
  1677 	}
       
  1678 
       
  1679 TBool CRichText::IndexPresent()const
       
  1680 // Returns ETrue if the rich text index is present, otherwise
       
  1681 // returns EFalse.
       
  1682 //
       
  1683 	{
       
  1684 	return iIndex.IsPtr() && iIndex.AsPtr();
       
  1685 	}
       
  1686 
       
  1687 
       
  1688 EXPORT_C TInt CRichText::PictureCount() const
       
  1689 /** Gets a count of the number of pictures contained in the rich text object.
       
  1690 
       
  1691 @return The picture count. */
       
  1692 	{return (IndexPresent()) ? iIndex->iPictureCount : 0;}
       
  1693 
       
  1694 
       
  1695 void CRichText::SetParaTypeIsSingle(TBool aBool)
       
  1696 	{
       
  1697 	if (aBool)
       
  1698 		iFlags |= KParaTypeIsSingle;
       
  1699 	else
       
  1700 		iFlags &= ~KParaTypeIsSingle;
       
  1701 	}
       
  1702 
       
  1703 
       
  1704 TBool CRichText::ParaTypeIsSingle() const
       
  1705 	{return iFlags & KParaTypeIsSingle;}
       
  1706 
       
  1707 
       
  1708 EXPORT_C void CRichText::AppendTakingSolePictureOwnershipL(const CRichText& aSource)
       
  1709 /** Appends a rich text object to this one. The text is appended immediately after
       
  1710 the end-of-text paragraph delimiter. The incoming text's formatting is set
       
  1711 to be based on the global formatting of this rich text object.
       
  1712 
       
  1713 Notes:
       
  1714 
       
  1715 If this rich text object is empty (e.g. because it is newly initialised, or
       
  1716 has been reset), then the end-of-text delimiter of the incoming rich text
       
  1717 is not appended. This avoids the possibility of having a trailing paragraph
       
  1718 delimiter, giving one more empty line than would typically be desired.
       
  1719 
       
  1720 If the incoming rich text contains pictures which have been loaded into memory,
       
  1721 their sole ownership is transferred to the current rich text object. In aSource,
       
  1722 these picture handles are set to NULL.
       
  1723 
       
  1724 @param aSource The rich text object to append. */
       
  1725 	{
       
  1726 	// Appends the specified rich text object to this one.
       
  1727 	// If this rich text is empty or has been newly initialised or reset, then the final paragraph delimiter
       
  1728 	// of the incoming rich text is NOT appended, thus avoiding the prospect of having a trailing, empty
       
  1729 	// paragraph delimiter, giving one more empty line than would typically be desired.
       
  1730 	//
       
  1731 	__ETEXT_WATCH(APPEND_RICH_TEXT);
       
  1732 
       
  1733 	// Append the text
       
  1734 	const TInt thisDocumentLength = DocumentLength();
       
  1735 	MPictureFactory* factory = NULL;
       
  1736 	MRichTextStoreResolver* resolver = NULL;
       
  1737 	if (thisDocumentLength == 0)  // this is an empty document
       
  1738 		{
       
  1739 		factory = iPictureFactory;
       
  1740 		resolver = iStoreResolver;
       
  1741 		Reset();  // destroy the markup component if it exists.  Makes the job easier
       
  1742 		}
       
  1743 	//
       
  1744 	PrepareAppendMarkupL(aSource);  // requires no rollback - objects in a (bigger) stable state
       
  1745 	//
       
  1746 	TRAPD(ret, DoAppendTakingSolePictureOwnershipL(aSource));
       
  1747 	if (ret != KErrNone)
       
  1748 		{
       
  1749 		CPlainText::Delete(thisDocumentLength,DocumentLength() - thisDocumentLength);
       
  1750 		User::Leave(ret);
       
  1751 		}
       
  1752 	if (thisDocumentLength == 0)
       
  1753 		{
       
  1754 		DeleteParagraph(0, 1);   // remove excess first paragraph from empty documents
       
  1755 		SetPictureFactory(factory, resolver);
       
  1756 		}
       
  1757 	int new_length = DocumentLength() - thisDocumentLength;
       
  1758 	iParserData->MergeRange(thisDocumentLength,0,new_length);
       
  1759 	CallEditObserver(thisDocumentLength,new_length);
       
  1760 
       
  1761 	__TEST_INVARIANT;
       
  1762 
       
  1763 	__ETEXT_WATCH_END(APPEND_RICH_TEXT);
       
  1764 	}
       
  1765 
       
  1766 
       
  1767 void CRichText::DoAppendTakingSolePictureOwnershipL(const CRichText& aSource)
       
  1768 	{
       
  1769 	TInt lengthRemaining = aSource.DocumentLength() + 1;  // we want to append the para delimiters also!
       
  1770 	TInt consumed = 0;
       
  1771 	FOREVER
       
  1772 		{
       
  1773 		TPtrC view = aSource.Read(consumed);
       
  1774 		if (view.Length() > lengthRemaining)
       
  1775 			view.Set(view.Ptr(), lengthRemaining);
       
  1776 		CPlainText::DoPtInsertL(DocumentLength() + 1, view);  // insert AFTER the final paragraph delimiter
       
  1777 		TInt viewLength = view.Length();
       
  1778 		lengthRemaining -= viewLength;
       
  1779 		if (lengthRemaining == 0)
       
  1780 			break;
       
  1781 		consumed += viewLength;
       
  1782 		}
       
  1783 
       
  1784 	if (IndexPresent())
       
  1785 		{
       
  1786 		__ASSERT_DEBUG(aSource.IndexPresent(), User::Invariant());       // PrepareAppend should have sorted this
       
  1787 
       
  1788 		TGlobalLayerInfoAppend info(GlobalParaFormatLayer(), GlobalCharFormatLayer(), aSource.GlobalParaFormatLayer(), aSource.GlobalCharFormatLayer());
       
  1789 		iIndex->AppendTakingSolePictureOwnershipL(aSource.iIndex, info);
       
  1790 		}
       
  1791 
       
  1792 	__TEST_INVARIANT;
       
  1793 	}
       
  1794 
       
  1795 
       
  1796 void CRichText::PrepareAppendMarkupL(const CRichText& aSource)
       
  1797 // Guarantees that both the component and aggregate objects have a valid markup component.
       
  1798 //
       
  1799 	{
       
  1800 	if (aSource.HasMarkupData() && !HasMarkupData())
       
  1801 		CreateAndGenerateMarkupComponentL();
       
  1802 	else if (IndexPresent())
       
  1803 		CONST_CAST(CRichText&, aSource).CreateAndGenerateMarkupComponentL();
       
  1804 	}
       
  1805 
       
  1806 
       
  1807 EXPORT_C void CRichText::AppendParagraphL(TInt aReplicas)
       
  1808 /** Appends one or more empty paragraphs to the document. The new paragraphs take
       
  1809 on the formatting specified in the global format layers.
       
  1810 
       
  1811 @param aReplicas The number of empty paragraphs to append to the document.
       
  1812 By default, a single paragraph. */
       
  1813 	{
       
  1814 	// Inserts an empty paragraph at the end of the document.
       
  1815 	// The new paragraph takes on the format as described
       
  1816 	// by the global format layers.
       
  1817 	//
       
  1818 	__ETEXT_WATCH(APPEND_PARAGRAPH);
       
  1819 
       
  1820 	__TEST_INVARIANT;
       
  1821 
       
  1822 	TInt documentLength = DocumentLength();
       
  1823 	if (aReplicas == 1)
       
  1824 		CPlainText::InsertL(documentLength, CEditableText::EParagraphDelimiter);
       
  1825 	else
       
  1826 		{
       
  1827 		HBufC* bb = HBufC::NewLC(aReplicas);
       
  1828 		TPtr buf = bb->Des();
       
  1829 		buf.Fill(CEditableText::EParagraphDelimiter, aReplicas);
       
  1830 		CPlainText::InsertL(documentLength, buf);
       
  1831 		CleanupStack::PopAndDestroy();  // bb
       
  1832 		}
       
  1833 	//
       
  1834 	if (IndexPresent())
       
  1835 		{
       
  1836 		TRAPD(ret,
       
  1837 		iIndex->AppendParagraphL(iGlobalParaFormatLayer, iGlobalCharFormatLayer, aReplicas));
       
  1838 		if (ret != KErrNone)
       
  1839 			{
       
  1840 			CPlainText::Delete(DocumentLength() - aReplicas, aReplicas);
       
  1841 			User::Leave(ret);
       
  1842 			}
       
  1843 		SetHasChanged(ETrue);
       
  1844 		}
       
  1845 
       
  1846 	int new_length = DocumentLength() - documentLength;
       
  1847 	iParserData->MergeRange(documentLength,0,new_length);
       
  1848 	CallEditObserver(documentLength,new_length);
       
  1849 	__TEST_INVARIANT;
       
  1850 
       
  1851 	__ETEXT_WATCH_END(APPEND_PARAGRAPH);
       
  1852 	}