os/textandloc/textrendering/texthandling/stext/TXTIXSTR.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/*
sl@0
     2
* Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     3
* All rights reserved.
sl@0
     4
* This component and the accompanying materials are made available
sl@0
     5
* under the terms of "Eclipse Public License v1.0"
sl@0
     6
* which accompanies this distribution, and is available
sl@0
     7
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     8
*
sl@0
     9
* Initial Contributors:
sl@0
    10
* Nokia Corporation - initial contribution.
sl@0
    11
*
sl@0
    12
* Contributors:
sl@0
    13
*
sl@0
    14
* Description: 
sl@0
    15
*
sl@0
    16
*/
sl@0
    17
sl@0
    18
sl@0
    19
#include <e32std.h>
sl@0
    20
#include <e32base.h>
sl@0
    21
sl@0
    22
#include <gdi.h>
sl@0
    23
sl@0
    24
#include "TXTFMLYR.H"
sl@0
    25
#include "TXTMRTSR.H"
sl@0
    26
#include "TXTRICH.H"
sl@0
    27
#include "TXTINDEX.H"
sl@0
    28
#include "TXTSTD.H"
sl@0
    29
sl@0
    30
#include "OstTraceDefinitions.h"
sl@0
    31
#ifdef OST_TRACE_COMPILER_IN_USE
sl@0
    32
#include "TXTIXSTRTraces.h"
sl@0
    33
#endif
sl@0
    34
sl@0
    35
#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
sl@0
    36
#include "TXTFMLYR_INTERNAL.H"
sl@0
    37
#endif
sl@0
    38
sl@0
    39
const TUint8 KRegisterItemPresent=1;
sl@0
    40
sl@0
    41
sl@0
    42
GLDEF_C void DiscardPhraseOnCleanup(TAny* aPhrase)
sl@0
    43
// Allows RPhraseAttribsEntry on the CleanupStack to be destroyed correctly,
sl@0
    44
// when included as a PushL(TCleanupItem).
sl@0
    45
//
sl@0
    46
	{
sl@0
    47
	((RPhraseAttribsEntry*)aPhrase)->Discard();
sl@0
    48
	User::Free(aPhrase);
sl@0
    49
	}
sl@0
    50
sl@0
    51
sl@0
    52
TRtPasteContext::TRtPasteContext(const CStreamStore* aStore,const CParaFormatLayer* aGlobalParaLayer,const CCharFormatLayer* aGlobalCharLayer,const CStyleList* aStyleList)
sl@0
    53
//
sl@0
    54
	:iStore(aStore),
sl@0
    55
	iGlobalParaLayer(aGlobalParaLayer),iGlobalCharLayer(aGlobalCharLayer),iStyleList(aStyleList),
sl@0
    56
	iParagraphStylesFlag(EFalse),iIncompleteParaFlag(ETrue),iPastePos(),iParasPasted(0)
sl@0
    57
	{}
sl@0
    58
sl@0
    59
//////////////////////////////////////////////////////////////////////////////////////
sl@0
    60
sl@0
    61
sl@0
    62
CRichTextIndex* CRichTextIndex::NewL(const CStreamStore& aStore,TStreamId aId,
sl@0
    63
//										MPictureFactory* aPictureFactory,MRichTextStoreResolver* aStoreResolver,
sl@0
    64
										const CParaFormatLayer* aGlobalParaLayer,
sl@0
    65
										const CCharFormatLayer* aGlobalCharLayer,
sl@0
    66
										const CRichText& aText)
sl@0
    67
//										const CStyleList* aStyleList)
sl@0
    68
//
sl@0
    69
	{
sl@0
    70
	CRichTextIndex* self=new(ELeave) CRichTextIndex(aText);
sl@0
    71
	CleanupStack::PushL(self);
sl@0
    72
	self->ConstructL(aGlobalParaLayer,aGlobalCharLayer,KMultiParaGranularity,KLargePhraseGranularity);
sl@0
    73
	self->RestoreL(aStore,aId,aGlobalParaLayer,aGlobalCharLayer,aText.StyleList());
sl@0
    74
//	self->SetPictureFactory(aPictureFactory,aStoreResolver);
sl@0
    75
	CleanupStack::Pop();
sl@0
    76
	return self;
sl@0
    77
	}
sl@0
    78
sl@0
    79
sl@0
    80
void CRichTextIndex::RestoreL(const CStreamStore& aStore,TStreamId aId,
sl@0
    81
									   const CParaFormatLayer* aGlobalParaLayer,
sl@0
    82
									   const CCharFormatLayer* aGlobalCharLayer,
sl@0
    83
									   const CStyleList* aStyleList)
sl@0
    84
//
sl@0
    85
	{
sl@0
    86
	RStoreReadStream stream;
sl@0
    87
	stream.OpenLC(aStore,aId);
sl@0
    88
	//
sl@0
    89
	InternalizeL(stream,aGlobalParaLayer,aGlobalCharLayer,aStyleList);
sl@0
    90
	CleanupStack::PopAndDestroy();  // stream
sl@0
    91
	}
sl@0
    92
sl@0
    93
sl@0
    94
TStreamId CRichTextIndex::StoreMarkupL(CStreamStore& aStore,const CStyleList* /*aStyleList*/) const
sl@0
    95
// Store this rich text markup out-of-line along with its components.
sl@0
    96
//
sl@0
    97
	{
sl@0
    98
	CStoreMap* map=CStoreMap::NewLC(aStore);
sl@0
    99
	StorePicturesL(aStore,*map);
sl@0
   100
//
sl@0
   101
	RStoreWriteStream stream(*map);
sl@0
   102
	TStreamId id=stream.CreateLC(aStore);
sl@0
   103
//	CONST_CAST(CRichTextIndex*,this)->iStyleList=CONST_CAST(CStyleList*,aStyleList);
sl@0
   104
	ExternalizeL(stream);
sl@0
   105
	stream.CommitL();
sl@0
   106
//
sl@0
   107
	map->Reset();
sl@0
   108
	CleanupStack::PopAndDestroy(2);  // map,stream
sl@0
   109
	return id;
sl@0
   110
	}
sl@0
   111
sl@0
   112
sl@0
   113
void CRichTextIndex::StorePicturesL(CStreamStore& aStore,CStoreMap& aMap) const
sl@0
   114
// Store any picture components in the specified store.
sl@0
   115
// Due to deferred loading, any pictures that are not in memory at this point are loaded,
sl@0
   116
// and then saved.
sl@0
   117
//
sl@0
   118
	{
sl@0
   119
	__TEST_INVARIANT;
sl@0
   120
sl@0
   121
	StorePicturesL(aStore,aMap,0,iText.DocumentLength()+1);
sl@0
   122
	}
sl@0
   123
sl@0
   124
sl@0
   125
void CRichTextIndex::StorePicturesL(CStreamStore& aStore,CStoreMap& aMap,TInt aPos,TInt aLength) const
sl@0
   126
// Store all picture components that are contained within the specified range (inclusive), in the store provided.
sl@0
   127
// Prior to storing the picture, its size is written to its picture header which is stored in-line in 
sl@0
   128
// the markup.
sl@0
   129
// Any pictures that are not in memory are now deleted, as a previous call to LoadAllPicturesNowL()
sl@0
   130
// should have been made.
sl@0
   131
// We are guaranteed that all pictures that are in memory are fully restored & detached from their store
sl@0
   132
//
sl@0
   133
	{
sl@0
   134
	__TEST_INVARIANT;
sl@0
   135
sl@0
   136
	if (iPictureCount==0)
sl@0
   137
		return;
sl@0
   138
	CONST_CAST(CRichTextIndex*,this)->DetachFromStoreL(CPicture::EDetachFull,aPos,aLength);	// ensure all pictures have been loaded
sl@0
   139
	TInt currentPos=aPos;
sl@0
   140
	DocumentChanged();  // reset the cache logical position
sl@0
   141
	while (currentPos<aPos+aLength)
sl@0
   142
		{// Store next picture & increment pos.
sl@0
   143
		CONST_CAST(CRichTextIndex*,this)->ScanToPosition(currentPos,EScanToPositionAbsolute,&MUTABLE_CAST(TLogicalPosition&,iLastUsed));
sl@0
   144
		TCurrentIndexRecords current;
sl@0
   145
		GetCurrentRecords(current);
sl@0
   146
		if (current.iPhrase && current.iPhrase->IsPicturePhrase())
sl@0
   147
			{
sl@0
   148
			RPhraseAttribsEntry& phrase=*current.iPhrase;
sl@0
   149
			TPictureHeader* hdr=phrase.PictureHeaderPtr();
sl@0
   150
			if (!hdr)
sl@0
   151
			    {
sl@0
   152
			    OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_STOREPICTURESL, "ERichTextStorePictureIntegrityError" );
sl@0
   153
			    }
sl@0
   154
			__ASSERT_DEBUG(hdr,Panic(ERichTextStorePictureIntegrityError));
sl@0
   155
			TBool pictureInMemory=(hdr->iPicture.IsPtr() && hdr->iPicture.AsPtr());
sl@0
   156
			if (pictureInMemory)
sl@0
   157
				{// Store the picture
sl@0
   158
				CPicture& picture=*hdr->iPicture;
sl@0
   159
				picture.GetSizeInTwips(hdr->iSize);  //  write picture size to picture header.
sl@0
   160
				TStreamId id=picture.StoreL(aStore);
sl@0
   161
				aMap.BindL(hdr->iPicture,id);
sl@0
   162
				}
sl@0
   163
			else
sl@0
   164
				{// Replace the picture phrase with a simple text equivalent.
sl@0
   165
				CCharFormatLayer* charLayer=phrase.ReleaseCharFormatLayerOwnership();
sl@0
   166
				phrase.Discard();  // destroy the redundant picture phrase
sl@0
   167
				RPhraseAttribsEntry newTextPhrase(charLayer,1);
sl@0
   168
				(*iPhraseIx)[iPos.iPhraseElement]=newTextPhrase;
sl@0
   169
				CONST_CAST(CRichTextIndex*,this)->iPictureCount--;  // the picture has now been removed
sl@0
   170
				// I do not bother tidying up the phrase index here,
sl@0
   171
				// since the benefit does not currently match the cost involved.
sl@0
   172
				//
sl@0
   173
				}
sl@0
   174
			}
sl@0
   175
		//
sl@0
   176
		// increment the current position to the *start* of the next phrase/paragraph
sl@0
   177
		TInt offsetIntoUnit=(current.iPhrase)?iPos.iPhraseElementOffset:iPos.iParaElementOffset;
sl@0
   178
		currentPos+=CurrentPhraseLength()-offsetIntoUnit;
sl@0
   179
		}
sl@0
   180
	}
sl@0
   181
sl@0
   182
sl@0
   183
void CRichTextIndex::DetachFromStoreL(CPicture::TDetach aDegree,TInt aPos,TInt aLength)
sl@0
   184
// Attempts to restore all pictures not already present in memory.
sl@0
   185
// A deep (door+document) or shallow (door only) restoration may occur, depending
sl@0
   186
// on the value of detach.
sl@0
   187
//
sl@0
   188
	{
sl@0
   189
	__TEST_INVARIANT;
sl@0
   190
sl@0
   191
	if (iPictureCount==0)
sl@0
   192
		return;
sl@0
   193
	DocumentChanged();  // reset the cache logical position
sl@0
   194
	TInt currentPos=aPos;
sl@0
   195
	while (currentPos<aPos+aLength)
sl@0
   196
		{
sl@0
   197
		CONST_CAST(CRichTextIndex*,this)->ScanToPosition(currentPos,EScanToPositionAbsolute,&iLastUsed);
sl@0
   198
		TCurrentIndexRecords current;
sl@0
   199
		GetCurrentRecords(current);
sl@0
   200
		if (current.iPhrase)
sl@0
   201
			{
sl@0
   202
			RPhraseAttribsEntry& phrase=*current.iPhrase;
sl@0
   203
			if (phrase.IsPicturePhrase())
sl@0
   204
				{
sl@0
   205
				TPictureHeader* hdr=phrase.PictureHeaderPtr();
sl@0
   206
				if (!hdr)
sl@0
   207
				    {
sl@0
   208
				    OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_DETACHFROMSTOREL, "ERichTextStorePictureIntegrityError" );
sl@0
   209
				    }
sl@0
   210
				__ASSERT_DEBUG(hdr,Panic(ERichTextStorePictureIntegrityError));
sl@0
   211
				//
sl@0
   212
				if (hdr->iPicture.IsId())
sl@0
   213
					{
sl@0
   214
					TRAPD(r,
sl@0
   215
					phrase.PictureHandleL(iText.PictureFactory(),iText.StoreResolver(),iPos.iDocPos,MLayDoc::EForceLoadTrue));  // swizzles
sl@0
   216
					if (r!=KErrNone && !hdr->iPicture.IsId())
sl@0
   217
					    {
sl@0
   218
					    OstTrace0( TRACE_DUMP, DUP1_CRICHTEXTINDEX_DETACHFROMSTOREL, "ERichTextStorePictureIntegrityError" );    
sl@0
   219
					    }
sl@0
   220
					__ASSERT_DEBUG(r==KErrNone || hdr->iPicture.IsId(),Panic(ERichTextStorePictureIntegrityError));
sl@0
   221
					if (r==KErrNotSupported)  // we don't recognise the picture type
sl@0
   222
						{
sl@0
   223
						TInt offsetIntoUnit=(current.iPhrase)?iPos.iPhraseElementOffset:iPos.iParaElementOffset;
sl@0
   224
						currentPos+=CurrentPhraseLength()-offsetIntoUnit;
sl@0
   225
						continue;
sl@0
   226
						}
sl@0
   227
					
sl@0
   228
					OstTrace1( TRACE_FATAL, DUP3_CRICHTEXTINDEX_DETACHFROMSTOREL, "Leave code=%d", r );
sl@0
   229
					User::LeaveIfError(r);
sl@0
   230
					}
sl@0
   231
				//
sl@0
   232
				// recurse the call to detach the picture from the store
sl@0
   233
				if (!hdr->iPicture.IsPtr())
sl@0
   234
				    {
sl@0
   235
				    OstTrace0( TRACE_DUMP, DUP2_CRICHTEXTINDEX_DETACHFROMSTOREL, "ERichTextStorePictureIntegrityError" );
sl@0
   236
				    }
sl@0
   237
				__ASSERT_DEBUG(hdr->iPicture.IsPtr(),Panic(ERichTextStorePictureIntegrityError));
sl@0
   238
				hdr->iPicture->DetachFromStoreL(aDegree);
sl@0
   239
				}
sl@0
   240
			}
sl@0
   241
		//
sl@0
   242
		// increment the current position to the *start* of the next phrase/paragraph
sl@0
   243
		TInt offsetIntoUnit=(current.iPhrase)?iPos.iPhraseElementOffset:iPos.iParaElementOffset;
sl@0
   244
		currentPos+=CurrentPhraseLength()-offsetIntoUnit;
sl@0
   245
		}
sl@0
   246
	__TEST_INVARIANT;
sl@0
   247
	}
sl@0
   248
sl@0
   249
//////////////////////////////////////////////////////////////////////////////////////
sl@0
   250
sl@0
   251
void CRichTextIndex::ExternalizeL(RWriteStream& aStream)const
sl@0
   252
// Persist the current state of this object in the specified stream.
sl@0
   253
// Saved records include the terminating paragraph delimiter. 
sl@0
   254
//
sl@0
   255
//
sl@0
   256
	{
sl@0
   257
	__TEST_INVARIANT;
sl@0
   258
sl@0
   259
	CONST_CAST(CRichTextIndex*,this)->CancelInsertCharFormat();  // cancel any insert-pending state.
sl@0
   260
	TInt charCount=iText.DocumentLength()+1;  // includes the end of document character
sl@0
   261
	((CRichTextIndex*)this)->ScanToPosition(0,EScanToPositionAbsolute);
sl@0
   262
	TLogicalPosition startPos=iPos;
sl@0
   263
	((CRichTextIndex*)this)->ScanToPosition(charCount-1,EScanToPositionMatchLeft);
sl@0
   264
	TLogicalPosition endPos=iPos;
sl@0
   265
	CStyleList* styleList=iText.StyleList();
sl@0
   266
	ExternalizeRtiHeaderL(aStream,endPos,styleList);
sl@0
   267
	ExternalizeSharedFormatsL(aStream,startPos,endPos,styleList);
sl@0
   268
	// DEF126934 begin: memory leak
sl@0
   269
	RPhraseAttribsEntry *pForRelease = ExternalizeParaIxL(aStream,startPos,endPos,styleList);
sl@0
   270
	if (pForRelease)
sl@0
   271
		delete pForRelease;
sl@0
   272
	// DEF126934 end
sl@0
   273
	ExternalizePhraseIxL(aStream);
sl@0
   274
	}
sl@0
   275
sl@0
   276
sl@0
   277
void CRichTextIndex::InternalizeL(RReadStream& aStream,const CParaFormatLayer* aGlobalParaLayer,const CCharFormatLayer* aGlobalCharLayer,const CStyleList* aStyleList)
sl@0
   278
// Load a rich text index.  Has construct semantics only!
sl@0
   279
// Restores this object from the specified stream.  As specific format layers are restored, they are based
sl@0
   280
// on the specified global format layers. 
sl@0
   281
//
sl@0
   282
	{
sl@0
   283
	if (iParaIx->Count()!=1 || (*iParaIx)[0].iLength!=1)
sl@0
   284
	    {
sl@0
   285
	    OstTrace0( TRACE_FATAL, CRICHTEXTINDEX_INTERNALIZEL, "ERtIndexInternalizeCalledOnNonEmptySource" );
sl@0
   286
	    }
sl@0
   287
	__ASSERT_ALWAYS(iParaIx->Count()==1 && (*iParaIx)[0].iLength==1,Panic(ERtIndexInternalizeCalledOnNonEmptySource));
sl@0
   288
	TRtPasteContext context(NULL,aGlobalParaLayer,aGlobalCharLayer,aStyleList);
sl@0
   289
	InternalizeRtiHeaderL(aStream,context);
sl@0
   290
	InternalizeSharedFormatsL(aStream,context);
sl@0
   291
	InternalizeParaIxL(aStream,context);
sl@0
   292
	InternalizePhraseIxL(aStream,aGlobalCharLayer);
sl@0
   293
	if (context.iParagraphStylesFlag)
sl@0
   294
		GenerateAllPhraseLinksL();
sl@0
   295
	SetSpecificMarkupInternalized(ETrue);
sl@0
   296
sl@0
   297
	__TEST_INVARIANT;
sl@0
   298
	}
sl@0
   299
sl@0
   300
//////////////////////////////////////////////////////////////////////////////////////
sl@0
   301
sl@0
   302
sl@0
   303
void CRichTextIndex::GenerateAllPhraseLinksL()
sl@0
   304
// Go through the index, and for each specific character format layer (shared or otherwise), regenerate
sl@0
   305
// the appropriate based-on link, (normal or style).
sl@0
   306
// 
sl@0
   307
	{
sl@0
   308
	TInt count=ParagraphCount();
sl@0
   309
	TInt phraseElement=0;
sl@0
   310
	for (TInt ii=0; ii<count; ii++)
sl@0
   311
		{
sl@0
   312
		const CParaAttribs& paraAttribs=*(*iParaIx)[ii].iParaAttribs;
sl@0
   313
		const CParaFormatLayer* base=STATIC_CAST(const CParaFormatLayer*,paraAttribs.iParaFormat->SenseBase());
sl@0
   314
		TInt phraseCount=paraAttribs.PhraseCount();
sl@0
   315
		if (phraseCount==1)
sl@0
   316
			{
sl@0
   317
			// If the reference count is zero, iCharFormat cannot be valid, so the CParaAttribs object is corrupt.
sl@0
   318
			if (paraAttribs.iRefCount == 0)
sl@0
   319
				User::Leave(KErrCorrupt);
sl@0
   320
sl@0
   321
			GeneratePhraseLink(paraAttribs.iCharFormat,base);  // constant character formatting
sl@0
   322
			}
sl@0
   323
		else
sl@0
   324
			{
sl@0
   325
			if (phraseCount<=1)
sl@0
   326
			    {
sl@0
   327
			    OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_GENERATEALLPHRASELINKSL, "EDebug" );
sl@0
   328
			    }
sl@0
   329
			 __ASSERT_DEBUG(phraseCount>1,Panic(EDebug));
sl@0
   330
sl@0
   331
			// If the phrase count is too great the CParaAttribs object is corrupt.
sl@0
   332
			if (phraseElement + phraseCount > iPhraseIx->Count())
sl@0
   333
				User::Leave(KErrCorrupt);
sl@0
   334
sl@0
   335
			for (TInt nn=0; nn<phraseCount; nn++)
sl@0
   336
				GeneratePhraseLink((*iPhraseIx)[phraseElement+nn].CharFormat(),base);
sl@0
   337
			phraseElement+=phraseCount;
sl@0
   338
			}
sl@0
   339
		}
sl@0
   340
	}
sl@0
   341
sl@0
   342
sl@0
   343
void CRichTextIndex::GeneratePhraseLink(CCharFormatLayer* aPhraseCharFormatLayer,const CParaFormatLayer* aBase)
sl@0
   344
// Set the based on link for this character format layer appropriately.
sl@0
   345
// By default, all specific character format layers are based on the global default.
sl@0
   346
//
sl@0
   347
	{
sl@0
   348
	TUid type=aBase->Type();
sl@0
   349
	if (type!=KNormalParagraphStyleUid)
sl@0
   350
		aPhraseCharFormatLayer->SetBase(((CParagraphStyle*)aBase)->CharFormatLayer());
sl@0
   351
	}
sl@0
   352
sl@0
   353
sl@0
   354
//////////////////////////////////////////////////////////////////////////////////////
sl@0
   355
sl@0
   356
void CRichTextIndex::CopyToStreamL(RWriteStream& aStream,TInt aPos,TInt aLength, TBool aCopyStyles)const
sl@0
   357
// Copies the markup corresponding to the specified rich text region to the specified write stream.
sl@0
   358
// aPos/aLength has already been validated in RichText
sl@0
   359
// Saved records can NOT include the terminating paragraph delimiter.
sl@0
   360
//
sl@0
   361
	{
sl@0
   362
	__TEST_INVARIANT;
sl@0
   363
sl@0
   364
	((CRichTextIndex*)this)->ScanToPosition(aPos,EScanToPositionAbsolute);
sl@0
   365
	TLogicalPosition startPos=iPos;
sl@0
   366
	((CRichTextIndex*)this)->ScanToPosition((aPos+aLength)-1,EScanToPositionAbsolute);
sl@0
   367
	TLogicalPosition endPos=iPos;
sl@0
   368
sl@0
   369
	CStyleList* docStyleList = NULL;
sl@0
   370
	if (aCopyStyles)
sl@0
   371
		docStyleList = (CStyleList*)iText.StyleList();
sl@0
   372
sl@0
   373
	ExternalizeRtiHeaderL(aStream,endPos,docStyleList);
sl@0
   374
	
sl@0
   375
	if (docStyleList)
sl@0
   376
		ExternalizeReferencedStylesL(aStream,startPos,endPos);
sl@0
   377
	
sl@0
   378
	ExternalizeSharedFormatsL(aStream,startPos,endPos,docStyleList); 
sl@0
   379
	RPhraseAttribsEntry* virtualTrailingText=ExternalizeParaIxL(aStream,startPos,endPos,docStyleList);
sl@0
   380
	if (virtualTrailingText)
sl@0
   381
	    CleanupStack::PushL(virtualTrailingText);
sl@0
   382
	ExternalizePhraseIxL(aStream,startPos,endPos,virtualTrailingText);
sl@0
   383
	if (virtualTrailingText)
sl@0
   384
	    CleanupStack::PopAndDestroy(virtualTrailingText);
sl@0
   385
	}
sl@0
   386
sl@0
   387
//////////////////////////////////////////////////////////////////////////////////////
sl@0
   388
sl@0
   389
sl@0
   390
void CRichTextIndex::ExternalizeRtiHeaderL(RWriteStream& aStream,const TLogicalPosition& aEnd,const CStyleList* aStyleList)const
sl@0
   391
// Stores index specific information.
sl@0
   392
//
sl@0
   393
	{
sl@0
   394
	TBool incompleteParaFlag=((*iParaIx)[aEnd.iParaElement].iLength>(aEnd.iParaElementOffset+1));
sl@0
   395
	aStream.WriteUint8L((TUint8)(aStyleList!=NULL));  // flags the presence of paragraph styles.
sl@0
   396
	aStream.WriteUint8L((TUint8)(incompleteParaFlag!=EFalse)); // the last para has no paragraph delimiter
sl@0
   397
	if(incompleteParaFlag)
sl@0
   398
		{//apply paragraph format to final text fragment if logical end is at document end
sl@0
   399
		aStream.WriteUint8L((TUint8)(aEnd.iDocPos+1 == iText.DocumentLength()));
sl@0
   400
		}
sl@0
   401
	}
sl@0
   402
sl@0
   403
sl@0
   404
void CRichTextIndex::InternalizeRtiHeaderL(RReadStream& aStream,TRtPasteContext& aContext)
sl@0
   405
// Load index specific information.
sl@0
   406
//
sl@0
   407
	{
sl@0
   408
	TUint8 flag=0;
sl@0
   409
	aStream>> flag;
sl@0
   410
	aContext.iParagraphStylesFlag=(TBool)flag;
sl@0
   411
	aStream>> flag;
sl@0
   412
	aContext.iIncompleteParaFlag=(TBool)flag;
sl@0
   413
	aContext.iApplyFormatToLastFlag=EFalse;
sl@0
   414
	if(aContext.iIncompleteParaFlag)
sl@0
   415
		{
sl@0
   416
		aStream>> flag;
sl@0
   417
		aContext.iApplyFormatToLastFlag=(TBool)flag;
sl@0
   418
		}
sl@0
   419
	}
sl@0
   420
sl@0
   421
//////////////////////////////////////////////////////////////////////////////////////
sl@0
   422
                                                                                                                     
sl@0
   423
void CRichTextIndex::ExternalizeReferencedStylesL(RWriteStream& aStream,const TLogicalPosition& aStart,
sl@0
   424
												  const TLogicalPosition& aEnd) const
sl@0
   425
// Write those styles that are referenced by the paragraphs in the range aStart to aEnd.
sl@0
   426
//
sl@0
   427
	{
sl@0
   428
	CStyleList* list = iText.StyleList();
sl@0
   429
	if (!list)
sl@0
   430
	    {
sl@0
   431
	    OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_EXTERNALIZEREFERENCEDSTYLESL, "EStyleClipboardIntegrityError" );
sl@0
   432
	    }
sl@0
   433
	__ASSERT_DEBUG(list,Panic(EStyleClipboardIntegrityError));
sl@0
   434
	if (aStart.iParaElement > aEnd.iParaElement)
sl@0
   435
	    {
sl@0
   436
	    OstTrace0( TRACE_DUMP, DUP1_CRICHTEXTINDEX_EXTERNALIZEREFERENCEDSTYLESL, "EStyleClipboardIntegrityError" );
sl@0
   437
	    }
sl@0
   438
	__ASSERT_DEBUG(aStart.iParaElement <= aEnd.iParaElement,Panic(EStyleClipboardIntegrityError));
sl@0
   439
sl@0
   440
	TUint8 numStyles = 0;
sl@0
   441
	if (list) 
sl@0
   442
		numStyles = (TUint8)list->Count();
sl@0
   443
sl@0
   444
	HBufC8* buf=HBufC8::NewL(numStyles);
sl@0
   445
	TPtr8 paraRegister=buf->Des();
sl@0
   446
	paraRegister.FillZ(numStyles);
sl@0
   447
	TInt refCount=MarkStyleRegister(paraRegister,aStart.iParaElement,aEnd.iParaElement);
sl@0
   448
	CleanupStack::PushL(buf);
sl@0
   449
	ExternalizeItemsPresentInStyleRegisterL(aStream,refCount,paraRegister);
sl@0
   450
	CleanupStack::PopAndDestroy();
sl@0
   451
	}
sl@0
   452
sl@0
   453
sl@0
   454
void CRichTextIndex::InternalizeSharedFormatsL(RReadStream& aStream, const TRtPasteContext& aContext)
sl@0
   455
// Restores the list of shared para attribs.
sl@0
   456
// All existing CParaAttribs on the shared list are removed.
sl@0
   457
// The reference counts are not restored, but modified dynamically as the para index is loaded.
sl@0
   458
//
sl@0
   459
	{
sl@0
   460
	iParaIx->Reset();  // stops paraIx referencing shared paraAttribs that are about to be released.
sl@0
   461
	CParaAttribs* currentSharedPara;
sl@0
   462
	TDblQueIter<CParaAttribs> iterator(iSharedParaQueHead);
sl@0
   463
	while ( (currentSharedPara = iterator++) != NULL )
sl@0
   464
		currentSharedPara->Release(currentSharedPara->iRefCount);
sl@0
   465
	TUint8 sharedParaCount = ReadTUint8CountL(aStream);
sl@0
   466
	for (TUint8 paraItem = 0; paraItem < sharedParaCount; paraItem++)
sl@0
   467
		{
sl@0
   468
		(void)aStream.ReadInt32L();  // consume the data.
sl@0
   469
		CParaFormatLayer* paraLayer = InternalizeParagraphFormatL(aStream, aContext);
sl@0
   470
		CleanupStack::PushL(paraLayer);
sl@0
   471
sl@0
   472
		CCharFormatLayer* charLayer = CCharFormatLayer::NewL(aStream);  // Does not restore based on link.
sl@0
   473
		charLayer->SetBase(aContext.iGlobalCharLayer);  // base on 'Normal' global char format
sl@0
   474
		CleanupStack::PushL(charLayer);
sl@0
   475
		CParaAttribs* paraAttribs = CParaAttribs::NewL(paraLayer, charLayer);
sl@0
   476
		CleanupStack::PopAndDestroy(2);
sl@0
   477
		paraAttribs->iRefCount = 0;  // Otherwise recalculating reference counts on internalization of paraIx will result in 1 too many.
sl@0
   478
		iSharedParaQueHead.AddLast(*paraAttribs);
sl@0
   479
		}
sl@0
   480
	}
sl@0
   481
sl@0
   482
sl@0
   483
void CRichTextIndex::ExternalizeSharedFormatsL(RWriteStream& aStream,const TLogicalPosition& aStart,const TLogicalPosition& aEnd,const CStyleList* aStyleList)const
sl@0
   484
// Persist those items in the shared list that are referenced by the paragraphs in the 
sl@0
   485
// range aStart para to aEnd para.
sl@0
   486
//
sl@0
   487
	{
sl@0
   488
	TUint8 sharedParaCount=SharedParaAttribsEntryCountL();
sl@0
   489
	// Some paras coverd, so take register
sl@0
   490
	HBufC8* buf=HBufC8::NewL(sharedParaCount);
sl@0
   491
	TPtr8 sharedAttribsRegister=buf->Des();
sl@0
   492
	sharedAttribsRegister.FillZ(sharedParaCount);
sl@0
   493
	TInt sharedCount=MarkRegister(sharedAttribsRegister,aStart.iParaElement,aEnd.iParaElement);
sl@0
   494
	CleanupStack::PushL(buf);
sl@0
   495
	ExternalizeItemsPresentInRegisterL(aStream,sharedCount,sharedAttribsRegister,aStyleList);
sl@0
   496
	CleanupStack::PopAndDestroy();
sl@0
   497
	}
sl@0
   498
sl@0
   499
sl@0
   500
TUint8 CRichTextIndex::SharedParaAttribsEntryCountL()const
sl@0
   501
// Return a count of the number of items currently
sl@0
   502
// in the sharedParaFormats list.
sl@0
   503
//
sl@0
   504
// This will leave if more than 255 found, as this is not supported
sl@0
   505
	{
sl@0
   506
	TDblQueIter<CParaAttribs> iterator(((CRichTextIndex*)this)->iSharedParaQueHead);
sl@0
   507
	TUint16 sharedParaCount = 0;
sl@0
   508
	while (iterator++ != NULL)
sl@0
   509
		sharedParaCount++;
sl@0
   510
		
sl@0
   511
	// Currently more than 255 paragraph formats are not supported 
sl@0
   512
	// If the current document has more, leave with KErrNotSupported
sl@0
   513
	if (sharedParaCount > 255)
sl@0
   514
		User::Leave(KErrNotSupported);
sl@0
   515
	
sl@0
   516
	return (TUint8)sharedParaCount;
sl@0
   517
	}
sl@0
   518
sl@0
   519
sl@0
   520
TInt CRichTextIndex::MarkRegister(TDes8& aBuf,TInt aStartPara,TInt aEndPara)const
sl@0
   521
// Indicate in the register, aBuf, once and once only, each paraAttribs that is
sl@0
   522
// referenced by each of the paragraphs in the specified range.
sl@0
   523
// Return the number of shared para formats referenced.
sl@0
   524
//
sl@0
   525
	{
sl@0
   526
	TInt parasReferenced=0;
sl@0
   527
	for (TInt item=aStartPara;item<=aEndPara;item++)
sl@0
   528
		{
sl@0
   529
		CParaAttribs* paraAttribs=(*iParaIx)[item].iParaAttribs;
sl@0
   530
		TInt offset=RefNum(paraAttribs);  // 0 return shows para attribs not in shared list
sl@0
   531
		if (offset>0)
sl@0
   532
			{// para entry references a shared para attribs
sl@0
   533
			if (aBuf[offset-1]==0)
sl@0
   534
				{
sl@0
   535
				aBuf[offset-1]=KRegisterItemPresent;  // mark item as needing to be stored
sl@0
   536
				parasReferenced++;
sl@0
   537
				}
sl@0
   538
			}
sl@0
   539
		}
sl@0
   540
	return parasReferenced;
sl@0
   541
	}
sl@0
   542
sl@0
   543
sl@0
   544
TInt CRichTextIndex::MarkStyleRegister(TDes8& aBuf,TInt aStartPara,TInt aEndPara)const
sl@0
   545
// Indicate in the register, aBuf, once and once only, each paragraph style thar is
sl@0
   546
// referenced by each of the paragraphs in the speciifed range.
sl@0
   547
// Return the umber of paragraph styles referenced.
sl@0
   548
//
sl@0
   549
	{
sl@0
   550
	TInt stylesReferenced=0;
sl@0
   551
	const CParaAttribs* para=NULL;
sl@0
   552
	for (TInt item=aStartPara;item<=aEndPara;item++)
sl@0
   553
		{
sl@0
   554
		para=(*iParaIx)[item].iParaAttribs;
sl@0
   555
		TInt index=iText.StyleList()->IndexByPtr(STATIC_CAST(const CParaFormatLayer*,para->iParaFormat->SenseBase()));
sl@0
   556
		if (index!=KErrNotFound)
sl@0
   557
			{
sl@0
   558
			if (index>=aBuf.Length())
sl@0
   559
			    {
sl@0
   560
			    OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_MARKSTYLEREGISTER, "EStyleClipboardIntegrityError" );
sl@0
   561
			    }
sl@0
   562
			__ASSERT_DEBUG(index<aBuf.Length(),Panic(EStyleClipboardIntegrityError));
sl@0
   563
			if (aBuf[index]!=KRegisterItemPresent)
sl@0
   564
				{
sl@0
   565
				aBuf[index]=KRegisterItemPresent;  // mark item as needing to be stored
sl@0
   566
		
sl@0
   567
				stylesReferenced++;
sl@0
   568
				}
sl@0
   569
			}
sl@0
   570
		}
sl@0
   571
	return stylesReferenced;
sl@0
   572
	}
sl@0
   573
sl@0
   574
sl@0
   575
void CRichTextIndex::ExternalizeItemsPresentInRegisterL(RWriteStream& aStream,TInt aSharedCount,const TDes8& aBuf,const CStyleList* aStyleList)const
sl@0
   576
// Externalize each object from the shared list that has a corresponding mark in the
sl@0
   577
// register, aBuf.
sl@0
   578
//
sl@0
   579
	{
sl@0
   580
	if (aSharedCount>(TInt)KMaxTUint8)
sl@0
   581
	    {
sl@0
   582
	    OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_EXTERNALIZEITEMSPRESENTINREGISTERL, "ESharedParaCountStreamOverflow" );
sl@0
   583
	    }
sl@0
   584
	__ASSERT_DEBUG(aSharedCount<=(TInt)KMaxTUint8,Panic(ESharedParaCountStreamOverflow));
sl@0
   585
	aStream.WriteUint8L(aSharedCount);
sl@0
   586
	CParaAttribs* currentSharedPara=NULL;
sl@0
   587
	TDblQueIter<CParaAttribs> iterator(((CRichTextIndex*)this)->iSharedParaQueHead);
sl@0
   588
	TInt offset=0;
sl@0
   589
	while ((currentSharedPara=iterator++)!=NULL)
sl@0
   590
		{
sl@0
   591
		if (aBuf[offset]==KRegisterItemPresent)
sl@0
   592
			{
sl@0
   593
			aStream.WriteInt32L(offset+1);  // the ref-no of the shared para - so it can be spotted in the paste.
sl@0
   594
			ExternalizeParagraphFormatL(aStream,*currentSharedPara->iParaFormat,aStyleList);
sl@0
   595
			aStream<< *currentSharedPara->iCharFormat;
sl@0
   596
			}
sl@0
   597
		offset++;
sl@0
   598
		}
sl@0
   599
	}
sl@0
   600
sl@0
   601
sl@0
   602
void CRichTextIndex::ExternalizeItemsPresentInStyleRegisterL(RWriteStream& aStream,TInt aRefStyleCount,
sl@0
   603
															 const TDes8& aBuf) const
sl@0
   604
// Externalize each object from the paragraph style list that has a corresponding mark in the register aBuf.
sl@0
   605
//
sl@0
   606
	{
sl@0
   607
	if (aRefStyleCount > (TInt)KMaxTUint8)
sl@0
   608
	    {
sl@0
   609
	    OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_EXTERNALIZEITEMSPRESENTINSTYLEREGISTERL, "EStyleClipboardIntegrityError" );
sl@0
   610
	    }
sl@0
   611
	__ASSERT_DEBUG(aRefStyleCount <= (TInt)KMaxTUint8,Panic(EStyleClipboardIntegrityError));
sl@0
   612
	aStream.WriteUint8L(aRefStyleCount);
sl@0
   613
	TInt count=aBuf.Length();
sl@0
   614
sl@0
   615
	for (TInt ii=0;ii<count;ii++)
sl@0
   616
		{
sl@0
   617
		if (aBuf[ii]==KRegisterItemPresent)
sl@0
   618
			{
sl@0
   619
			aStream.WriteInt8L(ii+1);  // cannot use 0 index as this represents an absence.
sl@0
   620
			iText.StyleList()->At(ii).iStyle->ExternalizeL(aStream);
sl@0
   621
			}
sl@0
   622
		}
sl@0
   623
  }
sl@0
   624
sl@0
   625
sl@0
   626
RPhraseAttribsEntry* CRichTextIndex::ExternalizeParaIxL(RWriteStream& aStream,
sl@0
   627
										const TLogicalPosition& aStart,
sl@0
   628
										const TLogicalPosition& aEnd,
sl@0
   629
										const CStyleList* aStyleList)const
sl@0
   630
// Externalize each para entry from the para index that falls between 
sl@0
   631
// aStart paragraph and aEnd paragraph inclusive.
sl@0
   632
// Any specific paraAttribs (ie not on the shared list) are also externalized.
sl@0
   633
// * paragraph count
sl@0
   634
// * 	paragraph length
sl@0
   635
// *	ref no.  (ref no. 0 means specific/non-shared one)
sl@0
   636
// *	[specific paragraph format layer - including based-on link]
sl@0
   637
// *	[specific phrase count]
sl@0
   638
//
sl@0
   639
	{
sl@0
   640
	TParaAttribsEntry lastParaEntry=(*iParaIx)[aEnd.iParaElement];
sl@0
   641
	TBool incompleteParaFlag=(lastParaEntry.iLength>(aEnd.iParaElementOffset+1));
sl@0
   642
	aStream.WriteInt32L(1+aEnd.iParaElement-aStart.iParaElement);  // paragraph count
sl@0
   643
	for (TInt paraItem=aStart.iParaElement;paraItem<aEnd.iParaElement;paraItem++)
sl@0
   644
		{// Externalize all but last TParaAttribsEntrys from the para index
sl@0
   645
		TParaAttribsEntry paraEntry=(*iParaIx)[paraItem];
sl@0
   646
		TInt phraseCount=(paraEntry.iParaAttribs->IsShared()) 
sl@0
   647
			? 0 
sl@0
   648
			: paraEntry.iParaAttribs->iPhraseCount;
sl@0
   649
		if (paraItem==aStart.iParaElement)
sl@0
   650
			{// Fix & write length & phrase count of the first paragraph.
sl@0
   651
			paraEntry.iLength=(paraEntry.iLength-aStart.iParaElementOffset);  // fix 1st para length
sl@0
   652
			if (phraseCount>0)
sl@0
   653
				phraseCount=phraseCount-(aStart.iPhraseElement-aStart.iParaBasePhraseElement);
sl@0
   654
			}
sl@0
   655
		aStream.WriteInt32L(paraEntry.iLength);
sl@0
   656
		CParaAttribs* paraAttribs=paraEntry.iParaAttribs;
sl@0
   657
		TUint8 refNo=RefNum(paraAttribs);
sl@0
   658
		aStream.WriteUint8L(refNo);
sl@0
   659
		if (refNo==0)
sl@0
   660
			{// Write specific para layer & phrase count
sl@0
   661
			ExternalizeParagraphFormatL(aStream,*paraAttribs->iParaFormat,aStyleList);
sl@0
   662
			aStream.WriteInt32L(phraseCount);
sl@0
   663
			}
sl@0
   664
		}
sl@0
   665
	// Fix & write the length of the last paragraph.
sl@0
   666
	if (aStart.iParaElement==aEnd.iParaElement)
sl@0
   667
		lastParaEntry.iLength=(aEnd.iParaElementOffset-aStart.iParaElementOffset)+1;  // copied text contained within 1 para
sl@0
   668
	else
sl@0
   669
		lastParaEntry.iLength-=(lastParaEntry.iLength-aEnd.iParaElementOffset)-1;
sl@0
   670
	aStream.WriteInt32L(lastParaEntry.iLength);
sl@0
   671
	// Fix & write the phrase count of the last paragraph if it has specific char format
sl@0
   672
	CParaAttribs* lastParaAttribs=lastParaEntry.iParaAttribs;
sl@0
   673
	TUint8 refNo=RefNum(lastParaAttribs);
sl@0
   674
	RPhraseAttribsEntry* virtualTextPhrase=NULL;
sl@0
   675
	if (incompleteParaFlag)
sl@0
   676
		{// Adjust the phrase count for this paragraph that is not complete
sl@0
   677
		TInt phraseCount=0;
sl@0
   678
		if (aStart.iParaElement==aEnd.iParaElement)
sl@0
   679
			phraseCount=(aEnd.iPhraseElement-aStart.iPhraseElement)+1;  // copied text contained within 1 para
sl@0
   680
		else
sl@0
   681
			phraseCount=(aEnd.iPhraseElement-aEnd.iParaBasePhraseElement)+1;
sl@0
   682
		if (phraseCount>lastParaAttribs->iPhraseCount)
sl@0
   683
		    {
sl@0
   684
		    OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_EXTERNALIZEPARAIXL, "ERtExternalizeParaIx" );
sl@0
   685
		    }
sl@0
   686
		__ASSERT_DEBUG(phraseCount<=lastParaAttribs->iPhraseCount,Panic(ERtExternalizeParaIx));
sl@0
   687
		aStream.WriteInt32L(phraseCount);
sl@0
   688
		if (refNo>0)
sl@0
   689
			{// Set the virtual phrase representing the trailing text from the shared paragraph.
sl@0
   690
			virtualTextPhrase=new(ELeave) RPhraseAttribsEntry(lastParaAttribs->iCharFormat,lastParaEntry.iLength);
sl@0
   691
			CleanupStack::PushL(virtualTextPhrase);
sl@0
   692
			}
sl@0
   693
sl@0
   694
		// Write out the paragraph format for the paragraph that is not complete
sl@0
   695
		// - necessary since we need to patch up the style character formatting
sl@0
   696
		if (aStyleList || aEnd.iDocPos+1 == iText.DocumentLength())
sl@0
   697
			ExternalizeParagraphFormatL(aStream, *lastParaAttribs->iParaFormat, aStyleList);
sl@0
   698
		}
sl@0
   699
	else
sl@0
   700
		{// This is a complete para - copy region ends on a paragraph delimiter.
sl@0
   701
		aStream.WriteUint8L(refNo);
sl@0
   702
		if (refNo==0)
sl@0
   703
			{// Write specific para layer & phrase count
sl@0
   704
			ExternalizeParagraphFormatL(aStream,*lastParaAttribs->iParaFormat,aStyleList);
sl@0
   705
			TInt phraseCount=lastParaAttribs->iPhraseCount;
sl@0
   706
			if (aStart.iParaElement==aEnd.iParaElement && aStart.iParaElementOffset && aStart.iParaElementOffset>0)
sl@0
   707
				phraseCount=(aEnd.iPhraseElement-aStart.iPhraseElement)+1;  // copied text contained within 1 para
sl@0
   708
			aStream.WriteInt32L(phraseCount);
sl@0
   709
			}
sl@0
   710
		}
sl@0
   711
	if (virtualTextPhrase)
sl@0
   712
	    CleanupStack::Pop(virtualTextPhrase);
sl@0
   713
	return virtualTextPhrase;
sl@0
   714
	}
sl@0
   715
sl@0
   716
sl@0
   717
void CRichTextIndex::ExternalizeParagraphFormatL(RWriteStream& aStream,const CParaFormatLayer& aLayer,const CStyleList* aStyleList)const
sl@0
   718
// If a style list is present, write out the based-on links for every paragraph format layer,
sl@0
   719
// in order to reconnect each paragraph to the right style on loading.
sl@0
   720
//
sl@0
   721
	{
sl@0
   722
	aStream<< aLayer;
sl@0
   723
	if (aStyleList)
sl@0
   724
		{
sl@0
   725
		TInt refNo=0;
sl@0
   726
		refNo=aStyleList->IndexByPtr(((CParaFormatLayer*)aLayer.SenseBase()));
sl@0
   727
		// returns the offset in the style list, or a negative error.
sl@0
   728
		//
sl@0
   729
		refNo=(refNo!=KErrNotFound)
sl@0
   730
			? refNo+1  // the nth style where 1st item is offset 1.
sl@0
   731
			: 0;  // An error value was returned so this thing has no paragraph style as its base
sl@0
   732
		aStream.WriteInt8L((TInt8)-refNo);
sl@0
   733
		}
sl@0
   734
 	}
sl@0
   735
sl@0
   736
sl@0
   737
CParaFormatLayer* CRichTextIndex::InternalizeParagraphFormatL(RReadStream& aStream,const TRtPasteContext& aContext)
sl@0
   738
// 
sl@0
   739
	{
sl@0
   740
	CParaFormatLayer* paraLayer=CParaFormatLayer::NewL(aStream);  // specific paragraph format layer
sl@0
   741
	TUint index=0;
sl@0
   742
	if (aContext.iParagraphStylesFlag)
sl@0
   743
		{
sl@0
   744
		CleanupStack::PushL(paraLayer);
sl@0
   745
		TInt refNo=aStream.ReadInt8L();  // Read in the based on link to fix up to the style table
sl@0
   746
		CleanupStack::Pop();
sl@0
   747
		index=Abs(refNo);
sl@0
   748
		}
sl@0
   749
	if (index>0 && aContext.iStyleList)
sl@0
   750
		paraLayer->SetBase(aContext.iStyleList->At(index-1).iStyle);
sl@0
   751
	else
sl@0
   752
		paraLayer->SetBase(aContext.iGlobalParaLayer);
sl@0
   753
	return paraLayer;
sl@0
   754
	}
sl@0
   755
sl@0
   756
sl@0
   757
CParaFormatLayer* CRichTextIndex::PasteParagraphFormatL(RReadStream& aStream,const TRtPasteContext& aContext,CStyleMap* aStyleMap)
sl@0
   758
// 
sl@0
   759
	{
sl@0
   760
	CParaFormatLayer* paraLayer=CParaFormatLayer::NewL(aStream);  // specific paragraph format layer
sl@0
   761
 
sl@0
   762
	TUint index=0;
sl@0
   763
	if (aContext.iParagraphStylesFlag)
sl@0
   764
		{
sl@0
   765
		CleanupStack::PushL(paraLayer);
sl@0
   766
		TInt refNo=aStream.ReadInt8L();  // Read in the based on link to fix up to the style table
sl@0
   767
		CleanupStack::Pop(paraLayer);	// paraLayer
sl@0
   768
		index=Abs(refNo);
sl@0
   769
		}
sl@0
   770
sl@0
   771
	// If a style exists for this paragraph, set it as the base.
sl@0
   772
	// If a style list doesn't exist, the base paragraph style will be set instead.
sl@0
   773
	
sl@0
   774
	if (index>0 && aContext.iStylePasteMode != CParagraphStyle::EIgnoreNewStyles)
sl@0
   775
	{
sl@0
   776
		if (!aContext.iStyleList || (aContext.iStyleList && aContext.iStylePasteMode == CParagraphStyle::EConvertNewStyles))
sl@0
   777
		{
sl@0
   778
			CleanupStack::PushL(paraLayer);
sl@0
   779
			iLastCharacterStyle = (aStyleMap->Item(index))->iCharFormatLayer;
sl@0
   780
sl@0
   781
			// If the application doesn't have a style list, 
sl@0
   782
			// the new paragraph style has to be enforced by merging the old
sl@0
   783
			// paralayer with the style paralayer
sl@0
   784
			CParaFormat* MergedParaFormat = CParaFormat::NewLC();
sl@0
   785
			TParaFormatMask MergedParaFormatMask;
sl@0
   786
sl@0
   787
			CParaFormatLayer* newParaLayer;
sl@0
   788
sl@0
   789
			// Extract the masks from both layers
sl@0
   790
			paraLayer->SenseL(MergedParaFormat, MergedParaFormatMask);
sl@0
   791
			(aStyleMap->Item(index))->SenseL(MergedParaFormat, MergedParaFormatMask);
sl@0
   792
sl@0
   793
			newParaLayer = CParaFormatLayer::NewL(MergedParaFormat, MergedParaFormatMask);
sl@0
   794
sl@0
   795
			// Now on stack: MergedParaFormat, paraLayer, ...
sl@0
   796
			CleanupStack::PopAndDestroy();	// delete MergedParaFormat
sl@0
   797
sl@0
   798
			// Now on stack: paraLayer, ...
sl@0
   799
			CleanupStack::PopAndDestroy();	// paraLayer
sl@0
   800
			paraLayer = newParaLayer;
sl@0
   801
sl@0
   802
			paraLayer->SetBase(aContext.iGlobalParaLayer);
sl@0
   803
sl@0
   804
		}
sl@0
   805
		else 
sl@0
   806
		{
sl@0
   807
			paraLayer->SetBase(aStyleMap->Item(index));		
sl@0
   808
			iLastCharacterStyle = NULL;
sl@0
   809
		}
sl@0
   810
	}
sl@0
   811
	else 
sl@0
   812
	// Otherwise set the character style to NULL, which will set the global
sl@0
   813
	// character style (see line 983 approx)
sl@0
   814
	{
sl@0
   815
		iLastCharacterStyle = NULL;
sl@0
   816
		paraLayer->SetBase(aContext.iGlobalParaLayer);
sl@0
   817
	}
sl@0
   818
		
sl@0
   819
	return paraLayer;
sl@0
   820
	}
sl@0
   821
sl@0
   822
sl@0
   823
void CRichTextIndex::InternalizeParaIxL(RReadStream& aStream,const TRtPasteContext& aContext)
sl@0
   824
// Restore the paragraph index & all associated specific para formats,
sl@0
   825
// All existing index data is lost.
sl@0
   826
//
sl@0
   827
	{
sl@0
   828
	// The para index has been reset at the start of internalize shared formats.
sl@0
   829
	TInt paraIxCount=aStream.ReadInt32L();  // paragraph count
sl@0
   830
	for (TInt currentPara=0;currentPara<paraIxCount;currentPara++)
sl@0
   831
		{// Restore each paragraph
sl@0
   832
		TParaAttribsEntry para;
sl@0
   833
		para.iLength=aStream.ReadInt32L();  // paragraph length
sl@0
   834
		TUint8 refNo=aStream.ReadUint8L();  // ref no
sl@0
   835
		if (refNo>0)
sl@0
   836
			{// Link to para attribs in shared list & up its reference count
sl@0
   837
			para.iParaAttribs=SharedParaAttribs(refNo);
sl@0
   838
			para.iParaAttribs->iRefCount++;
sl@0
   839
			iParaIx->AppendL(para);
sl@0
   840
			}
sl@0
   841
		else
sl@0
   842
			{// Have to build up the specific para attribs
sl@0
   843
			CParaFormatLayer* paraLayer=InternalizeParagraphFormatL(aStream,aContext);
sl@0
   844
			CleanupStack::PushL(paraLayer);
sl@0
   845
			CParaAttribs* specificParaAttribs=CParaAttribs::NewL(paraLayer);
sl@0
   846
				CleanupStack::PushL(TCleanupItem(ReleaseOnCleanup,specificParaAttribs));
sl@0
   847
			specificParaAttribs->iPhraseCount=aStream.ReadInt32L();  // specific phrase count
sl@0
   848
				CleanupStack::Pop();	// specificParaAttribs
sl@0
   849
			CleanupStack::PopAndDestroy(); // paraLayer
sl@0
   850
			para.iParaAttribs=specificParaAttribs;
sl@0
   851
			CleanupStack::PushL(TCleanupItem(ReleaseOnCleanup,specificParaAttribs));
sl@0
   852
			iParaIx->AppendL(para);
sl@0
   853
			CleanupStack::Pop();  // specificParaAttribs
sl@0
   854
			}
sl@0
   855
		}
sl@0
   856
	}
sl@0
   857
sl@0
   858
void CRichTextIndex::ExternalizePhraseIxL(RWriteStream& aStream)const
sl@0
   859
// Called from an Externalize.
sl@0
   860
// All phrases must be saved.
sl@0
   861
//
sl@0
   862
	{ExternalizePhrasesL(aStream,0,PhraseCount());}
sl@0
   863
sl@0
   864
sl@0
   865
void CRichTextIndex::ExternalizePhraseIxL(RWriteStream& aStream,
sl@0
   866
										  const TLogicalPosition& aStart,
sl@0
   867
										  TLogicalPosition& aEnd,
sl@0
   868
										  const RPhraseAttribsEntry* aVirtualTrailingText)const
sl@0
   869
// Called from CopyToStream.
sl@0
   870
// Here, a text fragment only, is to be saved.
sl@0
   871
// The last argument may be NULL.  If it is other than NULL, it represents trailing text
sl@0
   872
// that has no paragraph delimiter, which was part of a shared paragraph.  This must be presented as
sl@0
   873
// a distinct phrase, since this is the context in which it is pasted back into a document.
sl@0
   874
//
sl@0
   875
	{
sl@0
   876
	TInt phraseCount=PhraseCount();
sl@0
   877
	phraseCount+=(aVirtualTrailingText) ? 1 : 0;
sl@0
   878
	TBool noRealPhrasesInRegion=ETrue;
sl@0
   879
	TInt nn=aStart.iParaElement;
sl@0
   880
	while (nn<=aEnd.iParaElement && noRealPhrasesInRegion)
sl@0
   881
		{
sl@0
   882
		if (!(*iParaIx)[nn].iParaAttribs->IsShared())
sl@0
   883
			noRealPhrasesInRegion=EFalse;
sl@0
   884
		nn++;
sl@0
   885
		}
sl@0
   886
	//
sl@0
   887
	if (phraseCount==0 || (phraseCount==1 && aVirtualTrailingText || noRealPhrasesInRegion))  // save this phrase count
sl@0
   888
		ExternalizePhrasesL(aStream,aStart.iPhraseElement,0,aVirtualTrailingText);
sl@0
   889
	else
sl@0
   890
		{
sl@0
   891
		TBool endParaShared=(*iParaIx)[aEnd.iParaElement].iParaAttribs->IsShared();
sl@0
   892
		if (endParaShared && aEnd.iPhraseElement>0)
sl@0
   893
			aEnd.iPhraseElement--;  // Due to action of ScanToPosition
sl@0
   894
		//
sl@0
   895
		RPhraseAttribsEntry* backPhrase=&(*iPhraseIx)[aEnd.iPhraseElement];
sl@0
   896
		TInt backLength=backPhrase->Length();
sl@0
   897
		if (!(endParaShared || backPhrase->IsPicturePhrase()))
sl@0
   898
			backPhrase->SetLength(aEnd.iPhraseElementOffset+1);
sl@0
   899
		//
sl@0
   900
		RPhraseAttribsEntry* frontPhrase=&(*iPhraseIx)[aStart.iPhraseElement];
sl@0
   901
		TInt frontLength=frontPhrase->Length();
sl@0
   902
		if (!frontPhrase->IsPicturePhrase())  // Fix length of first phrase.
sl@0
   903
			frontPhrase->SetLength(frontLength-aStart.iPhraseElementOffset);
sl@0
   904
		TRAPD(ret,
sl@0
   905
			ExternalizePhrasesL(aStream,aStart.iPhraseElement,aEnd.iPhraseElement-aStart.iPhraseElement+1,aVirtualTrailingText));
sl@0
   906
		//
sl@0
   907
		// Now fix the altered phrase lengths.
sl@0
   908
		if (!frontPhrase->IsPicturePhrase())
sl@0
   909
			frontPhrase->SetLength(frontLength);
sl@0
   910
		if (!(endParaShared || backPhrase->IsPicturePhrase()))
sl@0
   911
			backPhrase->SetLength(backLength);
sl@0
   912
sl@0
   913
		__TEST_INVARIANT;	// we lied about being const
sl@0
   914
sl@0
   915
		User::LeaveIfError(ret);
sl@0
   916
		}
sl@0
   917
	}
sl@0
   918
sl@0
   919
sl@0
   920
void CRichTextIndex::ExternalizePhrasesL(RWriteStream& aStream,TInt aStart,TInt aPhraseCount,
sl@0
   921
										 const RPhraseAttribsEntry* aVirtualPhrase)const
sl@0
   922
// Save the specified number of phrases present in the phrase index,
sl@0
   923
// starting from phrase offset aStart.
sl@0
   924
//
sl@0
   925
	{
sl@0
   926
	ExternalizePhraseCountL(aStream,aPhraseCount+ ((aVirtualPhrase)?1:0) );
sl@0
   927
	for (TInt phraseItem=aStart;phraseItem<aStart+aPhraseCount;phraseItem++)
sl@0
   928
		{
sl@0
   929
		RPhraseAttribsEntry& phraseEntry=(*iPhraseIx)[phraseItem];
sl@0
   930
		aStream<< phraseEntry;
sl@0
   931
		}
sl@0
   932
	if (aVirtualPhrase)
sl@0
   933
		aStream<< *aVirtualPhrase;
sl@0
   934
	}
sl@0
   935
sl@0
   936
sl@0
   937
void CRichTextIndex::InternalizePhraseIxL(RReadStream& aStream,const CCharFormatLayer* aGlobalCharFormat)
sl@0
   938
// Load all the phrases from the stream, and insert them into the phrase index
sl@0
   939
//
sl@0
   940
	{
sl@0
   941
	iPhraseIx->Reset();
sl@0
   942
	TInt phraseCount=aStream.ReadInt32L();
sl@0
   943
sl@0
   944
	// Extend phrase index by required amount
sl@0
   945
	iPhraseIx->AppendL(RPhraseAttribsEntry(),phraseCount);
sl@0
   946
	
sl@0
   947
	for (TInt phraseItem=0;phraseItem<phraseCount;phraseItem++)
sl@0
   948
		{// Restore each phrase & insert into the phrase index.
sl@0
   949
		TBool isPicture=(TBool)aStream.ReadUint8L();
sl@0
   950
		TInt phraseLength=aStream.ReadInt32L();
sl@0
   951
		CCharFormatLayer* charLayer=CCharFormatLayer::NewL(aStream);
sl@0
   952
		charLayer->SetBase(aGlobalCharFormat);
sl@0
   953
		RPhraseAttribsEntry& tPhrase=iPhraseIx->At(phraseItem);
sl@0
   954
		if (!isPicture)
sl@0
   955
			new(&tPhrase) RPhraseAttribsEntry(charLayer,phraseLength);
sl@0
   956
		else
sl@0
   957
			{// Manufacture new picture header & set its picture store
sl@0
   958
			CleanupStack::PushL(charLayer);
sl@0
   959
			TPictureHeader hdr;
sl@0
   960
			aStream>> hdr;
sl@0
   961
			TBool ownershipTaken(EFalse);
sl@0
   962
			CPicturePhrase* picPhrase=CPicturePhrase::NewL(hdr,charLayer,ownershipTaken);
sl@0
   963
			CleanupStack::Pop();  // char layer
sl@0
   964
			new(&tPhrase) RPhraseAttribsEntry(picPhrase);
sl@0
   965
			iPictureCount++;
sl@0
   966
			}
sl@0
   967
		}
sl@0
   968
	}
sl@0
   969
sl@0
   970
sl@0
   971
CParaAttribs* CRichTextIndex::SharedParaAttribs(TUint8 aOrdinal)
sl@0
   972
// Return the handle of the para attribs in the shared para attribs list,
sl@0
   973
// whose position in the list is specified by the argument aOrdinal.
sl@0
   974
//
sl@0
   975
	{
sl@0
   976
	CParaAttribs* currentSharedPara;
sl@0
   977
	TDblQueIter<CParaAttribs> iterator(iSharedParaQueHead);
sl@0
   978
	TInt match=1;
sl@0
   979
	while ((currentSharedPara=iterator++)!=NULL && aOrdinal!=match)
sl@0
   980
		match++;
sl@0
   981
	if (currentSharedPara==NULL)
sl@0
   982
	    {
sl@0
   983
	    OstTrace0( TRACE_FATAL, CRICHTEXTINDEX_SHAREDPARAATTRIBS, "EEndOfSharedParaListEncountered" );
sl@0
   984
	    }
sl@0
   985
	__ASSERT_ALWAYS(currentSharedPara!=NULL,Panic(EEndOfSharedParaListEncountered));
sl@0
   986
	return currentSharedPara;
sl@0
   987
	}
sl@0
   988
sl@0
   989
sl@0
   990
TUint8 CRichTextIndex::RefNum(const CParaAttribs* aParaAttribs)const
sl@0
   991
// If the para attribs argument is present in the shared list, return a 
sl@0
   992
// reference to it; otherwise return zero as the reference.
sl@0
   993
//
sl@0
   994
	{
sl@0
   995
	CParaAttribs* currentSharedPara;
sl@0
   996
	TDblQueIter<CParaAttribs> iterator(((CRichTextIndex*)this)->iSharedParaQueHead);
sl@0
   997
	TUint8	 refNo=1;
sl@0
   998
	while ((currentSharedPara=iterator++)!=NULL)
sl@0
   999
		{
sl@0
  1000
		if (currentSharedPara==aParaAttribs)
sl@0
  1001
			return refNo;
sl@0
  1002
		refNo++;
sl@0
  1003
		}
sl@0
  1004
	return 0;
sl@0
  1005
	}
sl@0
  1006
sl@0
  1007
//////////////////////////////////////////////////
sl@0
  1008
//////////////////////////////////////////////////
sl@0
  1009
//////////////////////////////////////////////////
sl@0
  1010
sl@0
  1011
void CRichTextIndex::PasteFromStreamL(const CStreamStore& aStore,RReadStream& aStream,TInt aPos,CParagraphStyle::TStylePasteMode aStylePasteMode,const CParaFormatLayer* aGlobalParaLayer,const CCharFormatLayer* aGlobalCharLayer)
sl@0
  1012
//
sl@0
  1013
	{
sl@0
  1014
	__TEST_INVARIANT;
sl@0
  1015
	
sl@0
  1016
	CancelInsertCharFormat();
sl@0
  1017
	ScanToPosition(aPos,EScanToPositionAbsolute);
sl@0
  1018
sl@0
  1019
	//
sl@0
  1020
	//  Get the header
sl@0
  1021
	TRtPasteContext context(&aStore,aGlobalParaLayer,aGlobalCharLayer,iText.StyleList());
sl@0
  1022
	context.iPastePos=iPos;
sl@0
  1023
	context.iStylePasteMode = aStylePasteMode;
sl@0
  1024
sl@0
  1025
	InternalizeRtiHeaderL(aStream,context);  // no rollback required on the header.  Does not alter iPos.
sl@0
  1026
	//
sl@0
  1027
	// Get the pargraph styles
sl@0
  1028
sl@0
  1029
	CStyleMap* styleMap = NULL;
sl@0
  1030
	if (context.iParagraphStylesFlag)
sl@0
  1031
	{
sl@0
  1032
		TUint8 styleCount=ReadTUint8CountL(aStream);
sl@0
  1033
		styleMap=CStyleMap::NewLC(styleCount);
sl@0
  1034
		TRAPD(ret,
sl@0
  1035
		PasteStylesL(aStream,*styleMap,context));  // Does not alter iPos.
sl@0
  1036
		if (ret!=KErrNone) {RbPasteSharedFormatsL(ret);}
sl@0
  1037
	}
sl@0
  1038
	//
sl@0
  1039
	// Get the shared formats
sl@0
  1040
	TUint8 sharedParaCount=ReadTUint8CountL(aStream);
sl@0
  1041
	CParaAttribsMap* paraMap=CParaAttribsMap::NewLC(sharedParaCount);
sl@0
  1042
	TRAPD(ret,
sl@0
  1043
	PasteSharedFormatsL(aStream,*paraMap,context,styleMap));  // Does not alter iPos.
sl@0
  1044
	if (ret!=KErrNone)
sl@0
  1045
		{
sl@0
  1046
		// beginning of fixing DEF 126651 (1/2)
sl@0
  1047
		// free orphan object before leave.
sl@0
  1048
		if (context.iParagraphStylesFlag)
sl@0
  1049
		{
sl@0
  1050
			if (!context.iStyleList || context.iStylePasteMode == CParagraphStyle::EConvertNewStyles)
sl@0
  1051
			{
sl@0
  1052
			TInt maxSize = styleMap->Count();
sl@0
  1053
			for (TInt count=0; count<maxSize; count++)
sl@0
  1054
				{
sl@0
  1055
				delete (CParagraphStyle*)styleMap->At(count).iT;	
sl@0
  1056
				}
sl@0
  1057
			}
sl@0
  1058
			CleanupStack::PopAndDestroy();	// cleanup styleMap
sl@0
  1059
		}
sl@0
  1060
		CleanupStack::PopAndDestroy();  // cleanup paraMap
sl@0
  1061
		// end of fixing DEF 126651 (1/2)
sl@0
  1062
		RbPasteSharedFormatsL(ret);
sl@0
  1063
		}
sl@0
  1064
	//
sl@0
  1065
	// Get the markup
sl@0
  1066
	TRAP(ret,
sl@0
  1067
	PasteIxL(aStream,context,*paraMap, styleMap));  // context now has both global layers & pastePos
sl@0
  1068
	if (ret!=KErrNone)
sl@0
  1069
		{
sl@0
  1070
		// beginning of fixing DEF 126651 (2/2)
sl@0
  1071
		// free orphan object before leave.
sl@0
  1072
		if (context.iParagraphStylesFlag)
sl@0
  1073
		{
sl@0
  1074
			if (!context.iStyleList || context.iStylePasteMode == CParagraphStyle::EConvertNewStyles)
sl@0
  1075
			{
sl@0
  1076
			TInt maxSize = styleMap->Count();
sl@0
  1077
			for (TInt count=0; count<maxSize; count++)
sl@0
  1078
				{
sl@0
  1079
				delete (CParagraphStyle*)styleMap->At(count).iT;	
sl@0
  1080
				}
sl@0
  1081
			}
sl@0
  1082
			CleanupStack::PopAndDestroy();	// cleanup styleMap
sl@0
  1083
		}
sl@0
  1084
		CleanupStack::PopAndDestroy();  // cleanup paraMap
sl@0
  1085
		// end of fixing DEF 126651 (2/2)
sl@0
  1086
		RbPasteSharedFormatsL(ret);
sl@0
  1087
		}
sl@0
  1088
sl@0
  1089
sl@0
  1090
	if (context.iParagraphStylesFlag)
sl@0
  1091
	{
sl@0
  1092
		TRAP(ret,GenerateAllPhraseLinksL());
sl@0
  1093
		if (ret != KErrNone)
sl@0
  1094
			RbPasteSharedFormatsL(ret);
sl@0
  1095
sl@0
  1096
		if (!context.iStyleList || context.iStylePasteMode == CParagraphStyle::EConvertNewStyles)
sl@0
  1097
		{
sl@0
  1098
		TInt maxSize = styleMap->Count();
sl@0
  1099
		for (TInt count=0; count<maxSize; count++)
sl@0
  1100
			{
sl@0
  1101
			delete (CParagraphStyle*)styleMap->At(count).iT;	
sl@0
  1102
			}
sl@0
  1103
		}
sl@0
  1104
		CleanupStack::PopAndDestroy();	// cleanup styleMap
sl@0
  1105
	}
sl@0
  1106
sl@0
  1107
	CleanupStack::PopAndDestroy();  // cleanup paraMap
sl@0
  1108
sl@0
  1109
	__TEST_INVARIANT;
sl@0
  1110
	}
sl@0
  1111
sl@0
  1112
sl@0
  1113
void CRichTextIndex::PasteStylesL(RReadStream& aStream,CStyleMap& aMap,const TRtPasteContext& aContext)
sl@0
  1114
// Restore the paragraph styles from the specified stream.
sl@0
  1115
// Restoration is controlled by the flag TStylePasteMode.
sl@0
  1116
//
sl@0
  1117
	{
sl@0
  1118
	
sl@0
  1119
	TInt styleCount=aMap.iCapacity;
sl@0
  1120
//	TBool docSupportsStyles = iText.StyleListPresent();	// detect if document has style list
sl@0
  1121
	CParagraphStyle* style=NULL;
sl@0
  1122
	for(TUint8 ii=0; ii<styleCount; ii++)
sl@0
  1123
	{
sl@0
  1124
		TInt refNo=aStream.ReadInt8L();
sl@0
  1125
		style=CParagraphStyle::NewL(aStream,*aContext.iGlobalParaLayer,*aContext.iGlobalCharLayer);
sl@0
  1126
sl@0
  1127
		// Now attempt to map this style to one in the document we are adding it to
sl@0
  1128
		// refNo contains the style number when the selection was cut, which
sl@0
  1129
		//   is needed to map to the reference no's coming in with the paragraph
sl@0
  1130
		//   format info
sl@0
  1131
sl@0
  1132
		if (aContext.iStylePasteMode == CParagraphStyle::EIgnoreNewStyles)
sl@0
  1133
			// We're ignoring all style info, so delete it now
sl@0
  1134
			delete style;
sl@0
  1135
		else
sl@0
  1136
		{
sl@0
  1137
sl@0
  1138
		if (aContext.iStyleList && aContext.iStylePasteMode == CParagraphStyle::EAddNewStyles)
sl@0
  1139
		{
sl@0
  1140
			TInt docStyle = iText.StyleList()->IndexByName(style->iName);
sl@0
  1141
			if (docStyle!=KErrNotFound)
sl@0
  1142
			{
sl@0
  1143
				/* Add the existing style into the stylemap */
sl@0
  1144
				aMap.Bind(refNo,iText.StyleList()->PtrByName(style->iName)->iStyle);
sl@0
  1145
sl@0
  1146
				/* Since this style exists, we can safely delete this copy */
sl@0
  1147
				delete style;
sl@0
  1148
sl@0
  1149
			}
sl@0
  1150
			else
sl@0
  1151
			{
sl@0
  1152
				// Ok, the document doesn't have this style in it.
sl@0
  1153
				// So let's add it in, and put a reference in the stylemap
sl@0
  1154
sl@0
  1155
				RParagraphStyleInfo newStyle(style);
sl@0
  1156
sl@0
  1157
				iText.StyleList()->AppendL(&newStyle);
sl@0
  1158
sl@0
  1159
				aMap.Bind(refNo,style);
sl@0
  1160
sl@0
  1161
				// the StyeList takes care of style destruction, so no deletion
sl@0
  1162
				// is necessary here
sl@0
  1163
			}
sl@0
  1164
		}
sl@0
  1165
		else
sl@0
  1166
		{
sl@0
  1167
			// Document doesn't support styles, so save them so they can
sl@0
  1168
			// be converted to character specific formatting later on
sl@0
  1169
			aMap.Bind(refNo, style);
sl@0
  1170
		}
sl@0
  1171
		}
sl@0
  1172
sl@0
  1173
	}
sl@0
  1174
}
sl@0
  1175
sl@0
  1176
sl@0
  1177
void CRichTextIndex::ImposeCharacterStyleL(CCharFormatLayer** aCharLayer)
sl@0
  1178
{
sl@0
  1179
	// This function is used to impose the current character style onto
sl@0
  1180
	// the character layer for this paragraph. It's used when translating
sl@0
  1181
	// style information into specific formatting when pasting text containing
sl@0
  1182
	// styles into text without styles.
sl@0
  1183
sl@0
  1184
	TCharFormatX MergedCharFormat;
sl@0
  1185
	TCharFormatXMask MergedCharFormatMask;
sl@0
  1186
			
sl@0
  1187
	CCharFormatLayer* newCharLayer;
sl@0
  1188
sl@0
  1189
	// Extract the masks from both layers.
sl@0
  1190
	// use MergedCharFormat to hold the char info which we don't want yet
sl@0
  1191
sl@0
  1192
	(*aCharLayer)->Sense(MergedCharFormat, MergedCharFormatMask);
sl@0
  1193
	iLastCharacterStyle->Sense(MergedCharFormat, MergedCharFormatMask);
sl@0
  1194
			
sl@0
  1195
	// Re-build charLayer;
sl@0
  1196
	CleanupStack::PushL(*aCharLayer);
sl@0
  1197
	newCharLayer = CCharFormatLayer::NewL(MergedCharFormat,MergedCharFormatMask);
sl@0
  1198
	CleanupStack::Pop(*aCharLayer);
sl@0
  1199
sl@0
  1200
	delete (*aCharLayer);
sl@0
  1201
	(*aCharLayer) = newCharLayer;
sl@0
  1202
}
sl@0
  1203
sl@0
  1204
sl@0
  1205
void CRichTextIndex::PasteSharedFormatsL(RReadStream& aStream,CParaAttribsMap& aMap,const TRtPasteContext& aContext,CStyleMap* aStyleMap)
sl@0
  1206
// Load shared formats from the specified stream.
sl@0
  1207
// Only adds the loaded shared format to the list of shared formats
sl@0
  1208
// if it does not already exist in that list.
sl@0
  1209
// A map is kept, that for each loaded format specifies its offset within
sl@0
  1210
// the shared list.
sl@0
  1211
//
sl@0
  1212
sl@0
  1213
	{
sl@0
  1214
	TInt mapCount=aMap.iCapacity;
sl@0
  1215
	for (TUint8 paraItem=0;paraItem<mapCount;paraItem++)
sl@0
  1216
		{
sl@0
  1217
		TInt refNo=aStream.ReadInt32L();
sl@0
  1218
		CParaFormatLayer* paraLayer=PasteParagraphFormatL(aStream,aContext,aStyleMap);
sl@0
  1219
		CleanupStack::PushL(paraLayer);
sl@0
  1220
sl@0
  1221
		CCharFormatLayer* charLayer=CCharFormatLayer::NewL(aStream);  // Does not restore based on link.
sl@0
  1222
//// Change specific formatting for this paragraph
sl@0
  1223
sl@0
  1224
		if (iLastCharacterStyle != NULL)
sl@0
  1225
			ImposeCharacterStyleL(&charLayer);
sl@0
  1226
		
sl@0
  1227
		charLayer->SetBase(aContext.iGlobalCharLayer);
sl@0
  1228
sl@0
  1229
		CleanupStack::PushL(charLayer);
sl@0
  1230
		CParaAttribs* paraAttribs=GetParaAttribsL(paraLayer,charLayer);
sl@0
  1231
		CleanupStack::PopAndDestroy(2);  // charLayer & paraLayer
sl@0
  1232
		aMap.Bind(refNo,paraAttribs);
sl@0
  1233
		paraAttribs->iRefCount--;
sl@0
  1234
		}
sl@0
  1235
	}
sl@0
  1236
sl@0
  1237
sl@0
  1238
void CRichTextIndex::PasteIxL(RReadStream& aStream,TRtPasteContext& aContext,const CParaAttribsMap& aMap,CStyleMap* aStyleMap/*,CParaAttribs* aSecondReserved*/)
sl@0
  1239
//
sl@0
  1240
	{
sl@0
  1241
	TInt completeParaCount=aStream.ReadInt32L();
sl@0
  1242
	completeParaCount-=(aContext.iIncompleteParaFlag)? 1 : 0;
sl@0
  1243
//	Create rollback states
sl@0
  1244
	TParaAttribsEntry para=(*iParaIx)[aContext.iPastePos.iParaElement];
sl@0
  1245
	CParaAttribs* reclaimed=RequestReclaimShareL(para.iParaAttribs,&para);  // does not release share
sl@0
  1246
	iRollbackParaAttribsHandle=NULL;
sl@0
  1247
	if (reclaimed)
sl@0
  1248
		{
sl@0
  1249
		iRollbackParaAttribsHandle=para.iParaAttribs;
sl@0
  1250
		CleanupStack::PushL(TCleanupItem(ReleaseOnCleanup,reclaimed));
sl@0
  1251
		(*iParaIx)[aContext.iPastePos.iParaElement].iParaAttribs=reclaimed;  // Use this reclaimed para attribs
sl@0
  1252
		}
sl@0
  1253
//	Split the phrase at the paste position, ready to insert clipboard content
sl@0
  1254
	TRAPD(ret,
sl@0
  1255
	SplitPhraseL(aContext.iPastePos.iDocPos));
sl@0
  1256
		if (ret!=KErrNone) {RbPasteParaIxL(aContext.iPastePos,aContext.iParasPasted,ret);}
sl@0
  1257
	ScanToPosition(aContext.iPastePos.iDocPos,EScanToPositionAbsolute);  // pick up the changes
sl@0
  1258
	aContext.iPastePos=iPos;
sl@0
  1259
//	Paste all complete paragraphs from the clipboard
sl@0
  1260
	TInt characterCount=0;
sl@0
  1261
	RPhraseAttribsEntry* firstParaVirtualPhrase=NULL;
sl@0
  1262
	TRAP(ret,
sl@0
  1263
	characterCount=PasteParaIxL(aStream,aContext,completeParaCount,aMap,firstParaVirtualPhrase,aStyleMap));
sl@0
  1264
		if (ret!=KErrNone) {RbPasteParaIxL(aContext.iPastePos,aContext.iParasPasted,ret);}
sl@0
  1265
	CleanupStack::PushL(firstParaVirtualPhrase);
sl@0
  1266
//	Paste any remaining text fragment.
sl@0
  1267
	TTextFragment textFragment;
sl@0
  1268
	if (aContext.iIncompleteParaFlag)
sl@0
  1269
		{
sl@0
  1270
		TRAPD(ret,
sl@0
  1271
		textFragment=GetTextFragmentL(aStream));
sl@0
  1272
			if (ret!=KErrNone) {RbPasteParaIxL(aContext.iPastePos,aContext.iParasPasted,ret);}			
sl@0
  1273
		characterCount+=textFragment.iLength;
sl@0
  1274
sl@0
  1275
		// Restore the character stle info for the final text fragment
sl@0
  1276
		if (aContext.iParagraphStylesFlag || aContext.iApplyFormatToLastFlag)
sl@0
  1277
			{
sl@0
  1278
			CParaFormatLayer* paraLayer = PasteParagraphFormatL(aStream, aContext, aStyleMap);
sl@0
  1279
			CleanupStack::PushL(paraLayer);
sl@0
  1280
			//Restore the paragraph formatting for the final text fragment
sl@0
  1281
			if (aContext.iApplyFormatToLastFlag)
sl@0
  1282
				{
sl@0
  1283
				CParaFormat* paraFormat = CParaFormat::NewLC();
sl@0
  1284
				TParaFormatMask mask;
sl@0
  1285
				paraLayer->SenseL(paraFormat,mask);
sl@0
  1286
				(*iParaIx)[completeParaCount].iParaAttribs->iParaFormat->SetL(paraFormat,mask);
sl@0
  1287
				CleanupStack::PopAndDestroy(paraFormat);
sl@0
  1288
				}
sl@0
  1289
			// We can now discard the format layer, but the character format has been safely
sl@0
  1290
			// patched to the style character format
sl@0
  1291
			CleanupStack::PopAndDestroy(paraLayer);
sl@0
  1292
			}
sl@0
  1293
		}
sl@0
  1294
//
sl@0
  1295
	TRAP(ret,
sl@0
  1296
	PastePhraseIxL(aStream,aContext,firstParaVirtualPhrase));
sl@0
  1297
		if (ret!=KErrNone) {RbPasteParaIxL(aContext.iPastePos,aContext.iParasPasted,ret);}
sl@0
  1298
	CleanupStack::PopAndDestroy();  // firstParaVirtualPhrase / shallow destroy only - deep copy in phraseIx
sl@0
  1299
sl@0
  1300
//	ScanToPosition(aContext.iPastePos.iDocPos,EScanToPositionAbsolute);  // phraseIx not pasted at this point
sl@0
  1301
//	TLogicalPosition headParaNormalizePos=iPos;
sl@0
  1302
	
sl@0
  1303
	
sl@0
  1304
	if (completeParaCount==0)
sl@0
  1305
		{// Adjust paragraph length & phrase count
sl@0
  1306
		TParaAttribsEntry* para=&(*iParaIx)[aContext.iPastePos.iParaElement];
sl@0
  1307
		para->iLength+=textFragment.iLength;
sl@0
  1308
		para->iParaAttribs->iPhraseCount+=textFragment.iPhraseCount;
sl@0
  1309
		ScanToPosition(aContext.iPastePos.iDocPos,EScanToPositionAbsolute);
sl@0
  1310
		TLogicalPosition headParaNormalizePos=iPos;
sl@0
  1311
		MergePhrases(headParaNormalizePos);
sl@0
  1312
		MergePhrases(aContext.iPastePos.iDocPos+characterCount);
sl@0
  1313
		DoPasteCleanup(headParaNormalizePos,reclaimed);
sl@0
  1314
		}
sl@0
  1315
	else
sl@0
  1316
		{// Adjust paragraph lengths & phrase counts	
sl@0
  1317
		TParaAttribsEntry* firstPara=&(*iParaIx)[aContext.iPastePos.iParaElement];
sl@0
  1318
		firstPara->iLength+=aContext.iPastePos.iParaElementOffset;  // Update length of the first para
sl@0
  1319
		firstPara->iParaAttribs->iPhraseCount+=(aContext.iPastePos.iPhraseElement-aContext.iPastePos.iParaBasePhraseElement);  // Update the phrase count of the first para attribs
sl@0
  1320
		ScanToPosition(aContext.iPastePos.iDocPos,EScanToPositionAbsolute);
sl@0
  1321
		TLogicalPosition headParaNormalizePos=iPos;
sl@0
  1322
		MergePhrases(headParaNormalizePos);
sl@0
  1323
		DoPasteCleanup(headParaNormalizePos,reclaimed);
sl@0
  1324
		//
sl@0
  1325
		// Adjust the length & phrase count of the new final paragraph
sl@0
  1326
		TParaAttribsEntry* lastPara=&(*iParaIx)[aContext.iPastePos.iParaElement+completeParaCount];
sl@0
  1327
		lastPara->iLength=(lastPara->iLength-aContext.iPastePos.iParaElementOffset)+textFragment.iLength;
sl@0
  1328
		lastPara->iParaAttribs->iPhraseCount-=(aContext.iPastePos.iPhraseElement-aContext.iPastePos.iParaBasePhraseElement);
sl@0
  1329
		// phrase count may be wrong - since the added phrase may have been merged into the current one.
sl@0
  1330
		// Cant just add these phrases.
sl@0
  1331
		lastPara->iParaAttribs->iPhraseCount+=textFragment.iPhraseCount;
sl@0
  1332
		ScanToPosition(aContext.iPastePos.iDocPos+characterCount,EScanToPositionAbsolute);
sl@0
  1333
		MergePhrases(iPos);
sl@0
  1334
		DoPasteCleanup(iPos,(CParaAttribs*)NULL);
sl@0
  1335
		}
sl@0
  1336
	RebalanceIndex();
sl@0
  1337
	NormalizeSharedList();
sl@0
  1338
	}
sl@0
  1339
sl@0
  1340
sl@0
  1341
void CRichTextIndex::DoPasteCleanup(TLogicalPosition& aNormalizePos,CParaAttribs* aReclaimed)
sl@0
  1342
//
sl@0
  1343
	{
sl@0
  1344
	NormalizeNow(aNormalizePos);
sl@0
  1345
	if (aReclaimed)
sl@0
  1346
		CleanupStack::Pop();
sl@0
  1347
	}
sl@0
  1348
sl@0
  1349
sl@0
  1350
TInt CRichTextIndex::PasteParaIxL(RReadStream& aStream,TRtPasteContext& aContext,TInt aCompleteParaCount,const CParaAttribsMap& aMap,RPhraseAttribsEntry*& aFirstParaVirtualPhrase, CStyleMap* aStyleMap)
sl@0
  1351
//
sl@0
  1352
	{
sl@0
  1353
	TParaAttribsEntry para;
sl@0
  1354
	iParaIx->InsertL(aContext.iPastePos.iParaElement,para,aCompleteParaCount);	
sl@0
  1355
	aContext.iParasPasted=aCompleteParaCount;
sl@0
  1356
	TInt characterCount=0;
sl@0
  1357
	if (aCompleteParaCount>0)
sl@0
  1358
		{
sl@0
  1359
		para=DoPasteFirstIntoParaL(aStream,aMap,aContext,aFirstParaVirtualPhrase, aStyleMap);
sl@0
  1360
		TInt paraItem=0;
sl@0
  1361
		(*iParaIx)[aContext.iPastePos.iParaElement+paraItem]=para;
sl@0
  1362
		characterCount+=para.iLength;
sl@0
  1363
		}
sl@0
  1364
	CleanupStack::PushL(TCleanupItem(DiscardPhraseOnCleanup,aFirstParaVirtualPhrase));
sl@0
  1365
	for (TInt paraItem=1;paraItem<aCompleteParaCount;paraItem++)
sl@0
  1366
		{// Paste all the paras that have paragraph delimiters.
sl@0
  1367
		para=DoPasteIntoParaL(aStream,aMap,aContext,aStyleMap);
sl@0
  1368
		(*iParaIx)[aContext.iPastePos.iParaElement+paraItem]=para;
sl@0
  1369
		characterCount+=para.iLength;
sl@0
  1370
		}
sl@0
  1371
	CleanupStack::Pop();  // firstParaVirtualPhrase
sl@0
  1372
// ASSERT: At this point we have pasted all paras that were in the stream.
sl@0
  1373
	if (aContext.iParasPasted!=aCompleteParaCount)
sl@0
  1374
	    {
sl@0
  1375
	    OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_PASTEPARAIXL, "EPasteParaIxError" );
sl@0
  1376
	    }
sl@0
  1377
	__ASSERT_DEBUG(aContext.iParasPasted==aCompleteParaCount,Panic(EPasteParaIxError));
sl@0
  1378
	return characterCount;
sl@0
  1379
	}
sl@0
  1380
			
sl@0
  1381
			
sl@0
  1382
TParaAttribsEntry CRichTextIndex::DoPasteFirstIntoParaL(RReadStream& aStream,const CParaAttribsMap& aMap,const TRtPasteContext& aContext,RPhraseAttribsEntry*& aFirstParaVirtualPhrase,CStyleMap* aStyleMap)
sl@0
  1383
//
sl@0
  1384
	{
sl@0
  1385
	TParaAttribsEntry para;
sl@0
  1386
	para.iLength=aStream.ReadInt32L();
sl@0
  1387
	TUint8 refNo=aStream.ReadUint8L();
sl@0
  1388
	if (refNo>0)
sl@0
  1389
		{// This is the first pasted para, so if shared, must convert to phrase on the fly.
sl@0
  1390
		CParaAttribs* paraAttribs=aMap.Item(refNo);
sl@0
  1391
		CParaAttribs* specificParaAttribs=CParaAttribs::NewL(paraAttribs->iParaFormat);
sl@0
  1392
		CleanupStack::PushL(TCleanupItem(ReleaseOnCleanup,specificParaAttribs));
sl@0
  1393
		//
sl@0
  1394
		CCharFormatLayer* layer=CCharFormatLayer::NewCopyBaseL(paraAttribs->iCharFormat);
sl@0
  1395
		CleanupStack::PushL(layer);
sl@0
  1396
		aFirstParaVirtualPhrase=new(ELeave) RPhraseAttribsEntry(layer,para.iLength);
sl@0
  1397
		CleanupStack::Pop(2);  // layer & specificParaAttribs
sl@0
  1398
		//
sl@0
  1399
		para.iParaAttribs=specificParaAttribs;
sl@0
  1400
		if (para.iParaAttribs==NULL)
sl@0
  1401
		    {
sl@0
  1402
		    OstTrace0( TRACE_FATAL, CRICHTEXTINDEX_DOPASTEFIRSTINTOPARAL, "ESharedFormatsMapIntegrityError" );
sl@0
  1403
		    }
sl@0
  1404
		__ASSERT_ALWAYS(para.iParaAttribs!=NULL,Panic(ESharedFormatsMapIntegrityError));
sl@0
  1405
		}
sl@0
  1406
	else
sl@0
  1407
		{// Have to build up the specific para attribs
sl@0
  1408
		CParaFormatLayer* paraLayer=PasteParagraphFormatL(aStream,aContext,aStyleMap);
sl@0
  1409
		CleanupStack::PushL(paraLayer);
sl@0
  1410
		TInt phraseCount=aStream.ReadInt32L();  // specific phrase count
sl@0
  1411
		CParaAttribs* specificParaAttribs=CParaAttribs::NewL(paraLayer);
sl@0
  1412
		specificParaAttribs->iPhraseCount=phraseCount;
sl@0
  1413
		para.iParaAttribs=specificParaAttribs;
sl@0
  1414
		CleanupStack::PopAndDestroy();  // a copy of paraLayer is taken!
sl@0
  1415
		}
sl@0
  1416
	return para;
sl@0
  1417
	}
sl@0
  1418
sl@0
  1419
sl@0
  1420
TParaAttribsEntry CRichTextIndex::DoPasteIntoParaL(RReadStream& aStream,const CParaAttribsMap& aMap,const TRtPasteContext& aContext,CStyleMap* aStyleMap)
sl@0
  1421
//
sl@0
  1422
	{
sl@0
  1423
	TParaAttribsEntry para;
sl@0
  1424
	para.iLength=aStream.ReadInt32L();
sl@0
  1425
	TUint8 refNo=aStream.ReadUint8L();
sl@0
  1426
	if (refNo>0)
sl@0
  1427
		{// Link to para attribs in shared list & up its reference count
sl@0
  1428
		para.iParaAttribs=aMap.Item(refNo);
sl@0
  1429
		if (para.iParaAttribs==NULL)
sl@0
  1430
		    {
sl@0
  1431
		    OstTrace0( TRACE_FATAL, CRICHTEXTINDEX_DOPASTEINTOPARAL, "ESharedFormatsMapIntegrityError" );
sl@0
  1432
		    }
sl@0
  1433
		__ASSERT_ALWAYS(para.iParaAttribs!=NULL,Panic(ESharedFormatsMapIntegrityError));
sl@0
  1434
		para.iParaAttribs->iRefCount++;
sl@0
  1435
		}
sl@0
  1436
	else
sl@0
  1437
		{// Have to build up the specific para attribs
sl@0
  1438
		CParaFormatLayer* paraLayer=PasteParagraphFormatL(aStream,aContext,aStyleMap);
sl@0
  1439
		CleanupStack::PushL(paraLayer);
sl@0
  1440
		TInt phraseCount=aStream.ReadInt32L();  // specific phrase count
sl@0
  1441
		CParaAttribs* specificParaAttribs=CParaAttribs::NewL(paraLayer);
sl@0
  1442
		specificParaAttribs->iPhraseCount=phraseCount;
sl@0
  1443
		para.iParaAttribs=specificParaAttribs;
sl@0
  1444
		CleanupStack::PopAndDestroy();  // a copy of paraLayer is taken!
sl@0
  1445
		}
sl@0
  1446
	return para;
sl@0
  1447
	}
sl@0
  1448
sl@0
  1449
sl@0
  1450
TTextFragment CRichTextIndex::GetTextFragmentL(RReadStream& aStream)
sl@0
  1451
//
sl@0
  1452
	{
sl@0
  1453
	TTextFragment textFragment;
sl@0
  1454
	textFragment.iLength=aStream.ReadInt32L();
sl@0
  1455
	textFragment.iPhraseCount=aStream.ReadInt32L();
sl@0
  1456
	return textFragment;
sl@0
  1457
	}
sl@0
  1458
sl@0
  1459
sl@0
  1460
void CRichTextIndex::PastePhraseIxL(RReadStream& aStream,TRtPasteContext& aContext,const RPhraseAttribsEntry* aFirstParaVirtualPhrase)
sl@0
  1461
// The character position to paste at should now fall on a phrase boundary.
sl@0
  1462
//
sl@0
  1463
	{
sl@0
  1464
// ASSERT: Having pasted the paraIx, the para containig pastePos has had the containing phrase split at that point.
sl@0
  1465
	if (aContext.iPastePos.iPhraseElementOffset!=0)
sl@0
  1466
	    {
sl@0
  1467
	    OstTrace0( TRACE_FATAL, CRICHTEXTINDEX_PASTEPHRASEIXL, "EPastePhraseIxErr" );
sl@0
  1468
	    }
sl@0
  1469
	__ASSERT_ALWAYS(aContext.iPastePos.iPhraseElementOffset==0,Panic(EPastePhraseIxErr));
sl@0
  1470
sl@0
  1471
	TInt offset=0;
sl@0
  1472
	TInt phraseCount=aStream.ReadInt32L();  // leave caught by calling function.  No state change yet.
sl@0
  1473
	if (aFirstParaVirtualPhrase)
sl@0
  1474
		{
sl@0
  1475
		iPhraseIx->InsertL(aContext.iPastePos.iPhraseElement,*aFirstParaVirtualPhrase);
sl@0
  1476
		offset++;
sl@0
  1477
		}
sl@0
  1478
	RPhraseAttribsEntry holdingPhrase;
sl@0
  1479
	iPhraseIx->InsertL(aContext.iPastePos.iPhraseElement+offset,holdingPhrase,phraseCount);
sl@0
  1480
	for (TInt phraseItem=0;phraseItem<phraseCount;phraseItem++)
sl@0
  1481
		{// Restore each phrase & insert into the phrase index.
sl@0
  1482
		RPhraseAttribsEntry phrase;
sl@0
  1483
		TRAPD(ret,
sl@0
  1484
//		phrase=DoPastePhraseL(aStream,aContext));  // !! delete this if the code works
sl@0
  1485
		DoPastePhraseL(aStream,aContext,phrase));
sl@0
  1486
			if (ret!=KErrNone) {RbPastePhraseIxL(aContext.iPastePos,phraseCount+offset,ret);}
sl@0
  1487
		(*iPhraseIx)[aContext.iPastePos.iPhraseElement+phraseItem+offset]=phrase;
sl@0
  1488
		if (phrase.IsPicturePhrase() && iText.PictureFactory())
sl@0
  1489
			iPictureCount++;
sl@0
  1490
		}
sl@0
  1491
	}
sl@0
  1492
sl@0
  1493
sl@0
  1494
void CRichTextIndex::DoPastePhraseL(RReadStream& aStream,const TRtPasteContext& aContext,RPhraseAttribsEntry& aPhrase)
sl@0
  1495
//
sl@0
  1496
	{
sl@0
  1497
	TBool isPicture=(TBool)aStream.ReadUint8L();
sl@0
  1498
	TInt phraseLength=aStream.ReadInt32L();
sl@0
  1499
sl@0
  1500
	if (!(isPicture && phraseLength==1 || !isPicture))
sl@0
  1501
	    {
sl@0
  1502
	    OstTrace0( TRACE_FATAL, CRICHTEXTINDEX_DOPASTEPHRASEL, "KErrCorrupt" );
sl@0
  1503
	    }
sl@0
  1504
	__ASSERT_ALWAYS(isPicture && phraseLength==1 || !isPicture,User::Leave(KErrCorrupt));
sl@0
  1505
	
sl@0
  1506
	CCharFormatLayer* charLayer=CCharFormatLayer::NewL(aStream);
sl@0
  1507
/// Change this character format if style formatting is to be applied
sl@0
  1508
sl@0
  1509
// Paste style for the trailing text
sl@0
  1510
	if (iLastCharacterStyle != NULL)
sl@0
  1511
			ImposeCharacterStyleL(&charLayer);
sl@0
  1512
	
sl@0
  1513
		charLayer->SetBase(aContext.iGlobalCharLayer);
sl@0
  1514
sl@0
  1515
	CPicturePhrase* picPhrase=NULL;
sl@0
  1516
	const MPictureFactory* factory=iText.PictureFactory();
sl@0
  1517
	TBool pictureLoadError=EFalse;
sl@0
  1518
	if (isPicture)
sl@0
  1519
		{
sl@0
  1520
		TPictureHeader hdr;
sl@0
  1521
		aStream>> hdr;  // hdr.iPicture always references a picture in the deferred store.
sl@0
  1522
		if (isPicture && factory)
sl@0
  1523
			{// Manufacture new picture phrase & set its picture store
sl@0
  1524
			CleanupStack::PushL(charLayer);
sl@0
  1525
			TBool ownershipTaken(EFalse);
sl@0
  1526
			picPhrase=CPicturePhrase::NewL(hdr,charLayer,ownershipTaken);
sl@0
  1527
			CleanupStack::Pop();  // charLayer - picPhrase takes ownership
sl@0
  1528
			CleanupStack::PushL(picPhrase);
sl@0
  1529
			TRAPD(r,factory->NewPictureL(hdr,*aContext.iStore));  // load picture since clipboard store is transient.
sl@0
  1530
			// r=KErrNotSupported  // we don't recognise the picture type
sl@0
  1531
			if (r==KErrNone)
sl@0
  1532
				{
sl@0
  1533
				picPhrase->iPicHdr.iPicture=hdr.iPicture;  // make picPhrase point at the restored picture object.
sl@0
  1534
				TRAP(r,
sl@0
  1535
				hdr.iPicture->DetachFromStoreL(CPicture::EDetachFull));  // recurse the call to detach the picture from the store
sl@0
  1536
				}
sl@0
  1537
			switch (r)
sl@0
  1538
				{
sl@0
  1539
				case(KErrNone):
sl@0
  1540
					break;
sl@0
  1541
				default:
sl@0
  1542
					pictureLoadError=ETrue;
sl@0
  1543
					picPhrase->iCharFormat=NULL;
sl@0
  1544
					CleanupStack::PopAndDestroy(picPhrase);
sl@0
  1545
					if (r!=KErrNotSupported)
sl@0
  1546
					    {
sl@0
  1547
						OstTrace1( TRACE_FATAL, DUP2_CRICHTEXTINDEX_DOPASTEPHRASEL, "Leave code=%d", r );
sl@0
  1548
					    User::Leave(r);
sl@0
  1549
					    }
sl@0
  1550
				}
sl@0
  1551
			}
sl@0
  1552
		}
sl@0
  1553
	if (isPicture && factory && !pictureLoadError)
sl@0
  1554
		new(&aPhrase) RPhraseAttribsEntry(picPhrase);
sl@0
  1555
	else
sl@0
  1556
		new(&aPhrase) RPhraseAttribsEntry(charLayer,phraseLength);
sl@0
  1557
	
sl@0
  1558
	// The ownership has been transfered to RPhraseAttribsEntry
sl@0
  1559
	if(picPhrase)
sl@0
  1560
	    CleanupStack::Pop(picPhrase);
sl@0
  1561
	}
sl@0
  1562
sl@0
  1563
sl@0
  1564
TUint8 CRichTextIndex::ReadTUint8CountL(RReadStream& aStream)const
sl@0
  1565
	{return aStream.ReadUint8L();}
sl@0
  1566
sl@0
  1567
sl@0
  1568
void CRichTextIndex::RbPasteSharedFormatsL(TInt aRet)
sl@0
  1569
// For each para attribs that has been read in, release all shares on it, if it
sl@0
  1570
// does not already exist in shared list.
sl@0
  1571
//
sl@0
  1572
	{
sl@0
  1573
	NormalizeSharedList();
sl@0
  1574
	OstTrace1( TRACE_FATAL, CRICHTEXTINDEX_RBPASTESHAREDFORMATSL, "Leave code=%d", aRet );
sl@0
  1575
	User::Leave(aRet);
sl@0
  1576
	}
sl@0
  1577
		
sl@0
  1578
	
sl@0
  1579
void CRichTextIndex::NormalizeSharedList()
sl@0
  1580
// Removes unreferenced (non-shared) shared paras from the shared list.
sl@0
  1581
// Called in rollback situations.
sl@0
  1582
// Also called naturally following a paste, since an incoming shared para
sl@0
  1583
// may be pasted into an existing para, making it non-shared.
sl@0
  1584
//
sl@0
  1585
	{
sl@0
  1586
	CParaAttribs* currentSharedPara=NULL;
sl@0
  1587
	TDblQueIter<CParaAttribs> iterator(iSharedParaQueHead);
sl@0
  1588
	while ((currentSharedPara=iterator++)!=NULL)
sl@0
  1589
		{// Rollback the shared list.
sl@0
  1590
		if (currentSharedPara->iRefCount==0)
sl@0
  1591
			{// Remove this unreferenced item from the shared list.
sl@0
  1592
			currentSharedPara->iRefCount=1;
sl@0
  1593
			currentSharedPara->Release();
sl@0
  1594
			}
sl@0
  1595
		}
sl@0
  1596
	}
sl@0
  1597
sl@0
  1598
sl@0
  1599
void CRichTextIndex::RbRemoveInsertedParaAttribsEntries(TInt aFirstParaInsertPos,TInt aInsertedParaCount)
sl@0
  1600
// Rollback on leaving part way through inserting paragraph records into the para index.
sl@0
  1601
// For all pasted paragraph records, release their share on their paraAttribs if present.
sl@0
  1602
//
sl@0
  1603
	{
sl@0
  1604
	for (TInt ii=0;ii<aInsertedParaCount;ii++)
sl@0
  1605
		{
sl@0
  1606
		CParaAttribs* paraAttribs=(*iParaIx)[aFirstParaInsertPos+ii].iParaAttribs;
sl@0
  1607
		if (paraAttribs)
sl@0
  1608
			paraAttribs->Release();
sl@0
  1609
		}
sl@0
  1610
	iParaIx->Delete(aFirstParaInsertPos,aInsertedParaCount);
sl@0
  1611
	}
sl@0
  1612
sl@0
  1613
sl@0
  1614
void CRichTextIndex::RbPasteParaIxL(const TLogicalPosition& aPos,TInt aParasPasted,TInt aRet)
sl@0
  1615
// Rollback on leaving part way through the pasting of the para index.
sl@0
  1616
// For all pasted paras, release their share on their paraAttribs.
sl@0
  1617
//
sl@0
  1618
	{
sl@0
  1619
	RbRemoveInsertedParaAttribsEntries(aPos.iParaElement,aParasPasted);
sl@0
  1620
	MergePhrases(aPos.iDocPos);  // updates iPos to paste pos.
sl@0
  1621
	// 
sl@0
  1622
	//
sl@0
  1623
	if (iRollbackParaAttribsHandle)
sl@0
  1624
		{
sl@0
  1625
		RemoveFromPhraseIx(iPos.iPhraseElement,1);  // Removes the phrase created from ResquestReclaim on para
sl@0
  1626
		(*iParaIx)[aPos.iParaElement].iParaAttribs=iRollbackParaAttribsHandle;
sl@0
  1627
		iRollbackParaAttribsHandle=NULL;
sl@0
  1628
		}
sl@0
  1629
	OstTrace1( TRACE_FATAL, CRICHTEXTINDEX_RBPASTEPARAIXL, "Leave code=%d", aRet );
sl@0
  1630
	User::Leave(aRet);
sl@0
  1631
	}
sl@0
  1632
sl@0
  1633
sl@0
  1634
void CRichTextIndex::RbRemoveInsertedPhraseAttribsEntries(TInt aFirstPhraseInsertPos,TInt aInsertedPhraseCount)
sl@0
  1635
// Rollback on leaving part way through the pasting of the phrase index.
sl@0
  1636
// For all pasted phrases, discard their components.
sl@0
  1637
//
sl@0
  1638
	{
sl@0
  1639
	for (TInt ii=0;ii<aInsertedPhraseCount;ii++)
sl@0
  1640
		{
sl@0
  1641
		RPhraseAttribsEntry& phrase=(*iPhraseIx)[aFirstPhraseInsertPos+ii];
sl@0
  1642
		if (phrase.IsPicturePhrase())
sl@0
  1643
			iPictureCount--;
sl@0
  1644
		if (phrase.CharFormat())
sl@0
  1645
			phrase.Discard();
sl@0
  1646
		}
sl@0
  1647
	iPhraseIx->Delete(aFirstPhraseInsertPos,aInsertedPhraseCount);
sl@0
  1648
	}
sl@0
  1649
sl@0
  1650
sl@0
  1651
void CRichTextIndex::RbPastePhraseIxL(const TLogicalPosition& aPos,TInt aPhraseCount,TInt aRet)
sl@0
  1652
// Rollback on leaving part way through the pasting of the phrase index.
sl@0
  1653
// For all pasted phrases, discard their components.
sl@0
  1654
//
sl@0
  1655
	{
sl@0
  1656
	RbRemoveInsertedPhraseAttribsEntries(aPos.iPhraseElement,aPhraseCount);
sl@0
  1657
	OstTrace1( TRACE_FATAL, CRICHTEXTINDEX_RBPASTEPHRASEIXL, "Leave code=%d", aRet );
sl@0
  1658
	User::Leave(aRet);
sl@0
  1659
	}