textrendering/texthandling/stext/TXTINDEX.CPP
branchRCL_3
changeset 55 336bee5c2d35
parent 54 748ec5531811
equal deleted inserted replaced
54:748ec5531811 55:336bee5c2d35
    25 #include "TXTETEXT.H"
    25 #include "TXTETEXT.H"
    26 #include "TXTLAYDC.H"
    26 #include "TXTLAYDC.H"
    27 #include "TXTSTYLE.H"
    27 #include "TXTSTYLE.H"
    28 #include "TXTINDEX.H"
    28 #include "TXTINDEX.H"
    29 
    29 
    30 #include "OstTraceDefinitions.h"
       
    31 #ifdef OST_TRACE_COMPILER_IN_USE
       
    32 #include "TXTINDEXTraces.h"
       
    33 #endif
       
    34 
       
    35 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
    30 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
    36 #include "TXTFMLYR_INTERNAL.H"
    31 #include "TXTFMLYR_INTERNAL.H"
    37 #include "TXTSTYLE_INTERNAL.H"
    32 #include "TXTSTYLE_INTERNAL.H"
    38 #endif
    33 #endif
    39 
    34 
    73 	for (TInt para=0;para<maxPara;para++)
    68 	for (TInt para=0;para<maxPara;para++)
    74 		{
    69 		{
    75 		// ASSERT: The basedOn link is valid.
    70 		// ASSERT: The basedOn link is valid.
    76 		CFormatLayer* thisLayer=(*iParaIx)[para].iParaAttribs->iParaFormat;
    71 		CFormatLayer* thisLayer=(*iParaIx)[para].iParaAttribs->iParaFormat;
    77 		CFormatLayer* base=CONST_CAST(CFormatLayer*,thisLayer->SenseBase());
    72 		CFormatLayer* base=CONST_CAST(CFormatLayer*,thisLayer->SenseBase());
    78 		if (base==NULL)
       
    79 		    {
       
    80 		    OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_DBGTESTINVARIANT, "base==NULL" );
       
    81 		    }
       
    82 		__ASSERT_DEBUG(base!=NULL,User::Invariant());
    73 		__ASSERT_DEBUG(base!=NULL,User::Invariant());
    83 		if ((*iParaIx)[para].iParaAttribs->iRefCount>0)
    74 		if ((*iParaIx)[para].iParaAttribs->iRefCount>0)
    84 			numberOfReferencesToSharedList++;
    75 			numberOfReferencesToSharedList++;
    85 		TInt paragraphLength=(*iParaIx)[para].iLength;
    76 		TInt paragraphLength=(*iParaIx)[para].iLength;
    86 		TInt sumOfPhraseLengths=0;
    77 		TInt sumOfPhraseLengths=0;
    90 			if (maxPhrase>1)
    81 			if (maxPhrase>1)
    91 				{
    82 				{
    92 				const RPhraseAttribsEntry* phrase=&(*iPhraseIx)[currentPhraseElement];
    83 				const RPhraseAttribsEntry* phrase=&(*iPhraseIx)[currentPhraseElement];
    93 				CCharFormatLayer* charFormatLayer=phrase->CharFormat();
    84 				CCharFormatLayer* charFormatLayer=phrase->CharFormat();
    94 				// ASSERT: The basedOn link is valid.
    85 				// ASSERT: The basedOn link is valid.
    95 				if (charFormatLayer->SenseBase()==NULL)
       
    96 				    {
       
    97 				    OstTrace0( TRACE_DUMP, DUP1_CRICHTEXTINDEX_DBGTESTINVARIANT, "charFormatLayer->SenseBase()==NULL" );
       
    98 				    }
       
    99 				__ASSERT_DEBUG(charFormatLayer->SenseBase()!=NULL,User::Invariant());
    86 				__ASSERT_DEBUG(charFormatLayer->SenseBase()!=NULL,User::Invariant());
   100 				if (TInt(charFormatLayer->SenseBase())<=0x1000)
       
   101 				    {
       
   102 				    OstTrace0( TRACE_DUMP, DUP2_CRICHTEXTINDEX_DBGTESTINVARIANT, "TInt(charFormatLayer->SenseBase())<=0x1000" );
       
   103 				    }
       
   104 				__ASSERT_DEBUG(TInt(charFormatLayer->SenseBase())>0x1000,User::Invariant());
    87 				__ASSERT_DEBUG(TInt(charFormatLayer->SenseBase())>0x1000,User::Invariant());
   105 				sumOfPhraseLengths+=(*iPhraseIx)[currentPhraseElement].Length();
    88 				sumOfPhraseLengths+=(*iPhraseIx)[currentPhraseElement].Length();
   106 				if ((*iPhraseIx)[currentPhraseElement].Length()==0)
    89 				if ((*iPhraseIx)[currentPhraseElement].Length()==0)
   107 					zeroLengthPhraseCount++;
    90 					zeroLengthPhraseCount++;
   108 				currentPhraseElement++;
    91 				currentPhraseElement++;
   109 				}
    92 				}
   110 			else
    93 			else
   111 				{
    94 				{
   112 				CCharFormatLayer* charFormatLayer=(*iParaIx)[para].iParaAttribs->iCharFormat;
    95 				CCharFormatLayer* charFormatLayer=(*iParaIx)[para].iParaAttribs->iCharFormat;
   113 				// ASSERT: The basedOn link is valid.
    96 				// ASSERT: The basedOn link is valid.
   114 				if (charFormatLayer->SenseBase()==NULL)
       
   115 				    {
       
   116 				    OstTrace0( TRACE_DUMP, DUP3_CRICHTEXTINDEX_DBGTESTINVARIANT, "charFormatLayer->SenseBase()==NULL" );
       
   117 				    }
       
   118 				__ASSERT_DEBUG(charFormatLayer->SenseBase()!=NULL,User::Invariant());
    97 				__ASSERT_DEBUG(charFormatLayer->SenseBase()!=NULL,User::Invariant());
   119 				sumOfPhraseLengths+=(*iParaIx)[para].iLength;
    98 				sumOfPhraseLengths+=(*iParaIx)[para].iLength;
   120 				}
    99 				}
   121 			}
   100 			}
   122 		if (sumOfPhraseLengths!=paragraphLength)
       
   123 		    {
       
   124 		    OstTrace0( TRACE_DUMP, DUP4_CRICHTEXTINDEX_DBGTESTINVARIANT, "sumOfPhraseLengths!=paragraphLength" );
       
   125 		    }
       
   126 		__ASSERT_DEBUG(sumOfPhraseLengths==paragraphLength,User::Invariant());
   101 		__ASSERT_DEBUG(sumOfPhraseLengths==paragraphLength,User::Invariant());
   127 		}
   102 		}
   128 // ASSERT: We have no unexpected phrases left over
   103 // ASSERT: We have no unexpected phrases left over
   129 	if (currentPhraseElement!=-1 &&
       
   130             currentPhraseElement!=iPhraseIx->Count())
       
   131 	    {
       
   132 	    OstTrace0( TRACE_DUMP, DUP5_CRICHTEXTINDEX_DBGTESTINVARIANT, "We have no unexpected phrases left over" );
       
   133 	    }
       
   134 	__ASSERT_DEBUG(currentPhraseElement==-1 ||
   104 	__ASSERT_DEBUG(currentPhraseElement==-1 ||
   135 					currentPhraseElement==iPhraseIx->Count(),User::Invariant());
   105 					currentPhraseElement==iPhraseIx->Count(),User::Invariant());
   136 // ASSERT: There is either zero(0) or one(1) zero length phrase in the whole index
   106 // ASSERT: There is either zero(0) or one(1) zero length phrase in the whole index
   137 	if (!((zeroLengthPhraseCount==0) ||
       
   138             (zeroLengthPhraseCount==1 && iPendingNewPhrasePos!=EInsertCharFormatReset)))
       
   139 	    {
       
   140 	    OstTrace0( TRACE_DUMP, DUP6_CRICHTEXTINDEX_DBGTESTINVARIANT, "There is either zero(0) or one(1) zero length phrase in the whole index" );
       
   141 	    }
       
   142 	__ASSERT_DEBUG( (zeroLengthPhraseCount==0) ||
   107 	__ASSERT_DEBUG( (zeroLengthPhraseCount==0) ||
   143 					(zeroLengthPhraseCount==1 && iPendingNewPhrasePos!=EInsertCharFormatReset),
   108 					(zeroLengthPhraseCount==1 && iPendingNewPhrasePos!=EInsertCharFormatReset),
   144 					User::Invariant());
   109 					User::Invariant());
   145 // ASSERT: the number of paraEntries with paraAttribs of refCount>0 == the sum of refCounts in the shared list.
   110 // ASSERT: the number of paraEntries with paraAttribs of refCount>0 == the sum of refCounts in the shared list.
   146 //			or is only one less - as is set when SetInsertCharFormat is called on a shared paraAttribs.
   111 //			or is only one less - as is set when SetInsertCharFormat is called on a shared paraAttribs.
   150 		CParaAttribs* currentSharedPara;
   115 		CParaAttribs* currentSharedPara;
   151 		TDblQueIter<CParaAttribs> iterator(((CRichTextIndex*)this)->iSharedParaQueHead);
   116 		TDblQueIter<CParaAttribs> iterator(((CRichTextIndex*)this)->iSharedParaQueHead);
   152 		while ((currentSharedPara=iterator++)!=NULL)
   117 		while ((currentSharedPara=iterator++)!=NULL)
   153 			totalReferenceCount+=currentSharedPara->iRefCount;
   118 			totalReferenceCount+=currentSharedPara->iRefCount;
   154 		}
   119 		}
   155 	if ((numberOfReferencesToSharedList!=totalReferenceCount) &&
       
   156             (numberOfReferencesToSharedList!=totalReferenceCount-1))
       
   157 	    {
       
   158 	    OstTrace0( TRACE_DUMP, DUP7_CRICHTEXTINDEX_DBGTESTINVARIANT, "Invariant" );
       
   159 	    }
       
   160 	__ASSERT_DEBUG((numberOfReferencesToSharedList==totalReferenceCount) ||
   120 	__ASSERT_DEBUG((numberOfReferencesToSharedList==totalReferenceCount) ||
   161 				   (numberOfReferencesToSharedList==totalReferenceCount-1),User::Invariant());
   121 				   (numberOfReferencesToSharedList==totalReferenceCount-1),User::Invariant());
   162 // ASSERT: iPictureCount corresponds to the number of pictures in the stored in the index.
   122 // ASSERT: iPictureCount corresponds to the number of pictures in the stored in the index.
   163 	TInt picCount=0;
   123 	TInt picCount=0;
   164 	TInt phraseCount=(iPhraseIx) ? iPhraseIx->Count() : 0;
   124 	TInt phraseCount=(iPhraseIx) ? iPhraseIx->Count() : 0;
   165 	for (TInt item=0;item<phraseCount;item++)
   125 	for (TInt item=0;item<phraseCount;item++)
   166 		picCount+=((*iPhraseIx)[item].IsPicturePhrase())
   126 		picCount+=((*iPhraseIx)[item].IsPicturePhrase())
   167 					? 1
   127 					? 1
   168 					: 0;
   128 					: 0;
   169 	if (iPictureCount!=picCount)
       
   170 	    {
       
   171 	    OstTrace0( TRACE_DUMP, DUP8_CRICHTEXTINDEX_DBGTESTINVARIANT, "Invariant" );
       
   172 	    }
       
   173 	__ASSERT_DEBUG(iPictureCount==picCount,User::Invariant());
   129 	__ASSERT_DEBUG(iPictureCount==picCount,User::Invariant());
   174 #endif
   130 #endif
   175 	}
   131 	}
   176 
   132 
   177 
   133 
   228 //
   184 //
   229 	{
   185 	{
   230 	TInt count;
   186 	TInt count;
   231 	if (iPhraseIx)
   187 	if (iPhraseIx)
   232 		{// Destroy the phrase index and its contents.
   188 		{// Destroy the phrase index and its contents.
   233 		if (!iParaIx)
       
   234 		    {
       
   235 		    OstTrace0( TRACE_FATAL, CRICHTEXTINDEX_CRICHTEXTINDEX, "EPhraseIxPresentWithNoParaIx" );
       
   236 		    }
       
   237 		__ASSERT_ALWAYS(iParaIx,Panic(EPhraseIxPresentWithNoParaIx));
   189 		__ASSERT_ALWAYS(iParaIx,Panic(EPhraseIxPresentWithNoParaIx));
   238 		count=iPhraseIx->Count();
   190 		count=iPhraseIx->Count();
   239 		for (TInt offset=0;offset<count;offset++)
   191 		for (TInt offset=0;offset<count;offset++)
   240 			(*iPhraseIx)[offset].Discard();
   192 			(*iPhraseIx)[offset].Discard();
   241 		}
   193 		}
   257 	// unless internalize failed after getting shared list & before getting all para data.
   209 	// unless internalize failed after getting shared list & before getting all para data.
   258 	CParaAttribs* currentSharedPara;
   210 	CParaAttribs* currentSharedPara;
   259 	TDblQueIter<CParaAttribs> iterator(iSharedParaQueHead);
   211 	TDblQueIter<CParaAttribs> iterator(iSharedParaQueHead);
   260 	while ((currentSharedPara=iterator++)!=NULL)
   212 	while ((currentSharedPara=iterator++)!=NULL)
   261 		currentSharedPara->Release(currentSharedPara->iRefCount);
   213 		currentSharedPara->Release(currentSharedPara->iRefCount);
   262 	if (!iSharedParaQueHead.IsEmpty())
       
   263 	    {
       
   264 	    OstTrace0( TRACE_FATAL, DUP1_CRICHTEXTINDEX_CRICHTEXTINDEX, "ERichTextIndexIntegrityErr" );
       
   265 	    }
       
   266 	__ASSERT_ALWAYS(iSharedParaQueHead.IsEmpty(),Panic(ERichTextIndexIntegrityErr));
   214 	__ASSERT_ALWAYS(iSharedParaQueHead.IsEmpty(),Panic(ERichTextIndexIntegrityErr));
   267 	}
   215 	}
   268 
   216 
   269 
   217 
   270 TInt CRichTextIndex::CharPosOfParagraph(TInt& aLength,TInt aParaOffset)const
   218 TInt CRichTextIndex::CharPosOfParagraph(TInt& aLength,TInt aParaOffset)const
   447 		}
   395 		}
   448 	for (TInt paraItem=1;paraItem<paragraphCount;paraItem++)
   396 	for (TInt paraItem=1;paraItem<paragraphCount;paraItem++)
   449 		{// For each para inserted between the fist and last
   397 		{// For each para inserted between the fist and last
   450 		TParaAttribsEntry& para=(*iParaIx)[pastePos.iParaElement+paraItem];
   398 		TParaAttribsEntry& para=(*iParaIx)[pastePos.iParaElement+paraItem];
   451 		TInt length=ParaLengthFromBuffer(buf)+1;
   399 		TInt length=ParaLengthFromBuffer(buf)+1;
   452 		if (length==KErrNotFound)
       
   453 		    {
       
   454 		    OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_INSERTL, "EInsertEmbeddedParaErr" );
       
   455 		    }
       
   456 		__ASSERT_DEBUG(length!=KErrNotFound,Panic(EInsertEmbeddedParaErr));
   400 		__ASSERT_DEBUG(length!=KErrNotFound,Panic(EInsertEmbeddedParaErr));
   457 		para.iLength=length;
   401 		para.iLength=length;
   458 		buf.Set(buf.Right(buf.Length()-length));
   402 		buf.Set(buf.Right(buf.Length()-length));
   459 		}
   403 		}
   460 	// For final paragrph
   404 	// For final paragrph
   506 		if (current.iPhrase)
   450 		if (current.iPhrase)
   507 			{
   451 			{
   508 			current.iPhrase->AdjustLength(-1);  // collapse phrase by right amount
   452 			current.iPhrase->AdjustLength(-1);  // collapse phrase by right amount
   509 			if (insertPendingPos!=EInsertCharFormatReset)
   453 			if (insertPendingPos!=EInsertCharFormatReset)
   510 				{
   454 				{
   511 				if (current.iPhrase->Length()!=0)
       
   512 				    {
       
   513 				    OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_SPLITPARAGRAPHATPASTEPOSL, "Invariant" );
       
   514 				    }
       
   515 				__ASSERT_DEBUG(current.iPhrase->Length()==0,User::Invariant());
   455 				__ASSERT_DEBUG(current.iPhrase->Length()==0,User::Invariant());
   516 				iPendingNewPhrasePos=insertPendingPos;
   456 				iPendingNewPhrasePos=insertPendingPos;
   517 				}
   457 				}
   518 			else if (current.iPhrase->Length()==0)
   458 			else if (current.iPhrase->Length()==0)
   519 				{
   459 				{
   520 				RemoveFromPhraseIx(iPos.iPhraseElement,1);
   460 				RemoveFromPhraseIx(iPos.iPhraseElement,1);
   521 				current.iParaAttribs->iPhraseCount--;
   461 				current.iParaAttribs->iPhraseCount--;
   522 				if (current.iParaAttribs->PhraseCount()<=1)
       
   523 				    {
       
   524 				    OstTrace0( TRACE_DUMP, DUP1_CRICHTEXTINDEX_SPLITPARAGRAPHATPASTEPOSL, "Invariant" );
       
   525 				    }
       
   526 				__ASSERT_DEBUG(current.iParaAttribs->PhraseCount()>1,User::Invariant());
   462 				__ASSERT_DEBUG(current.iParaAttribs->PhraseCount()>1,User::Invariant());
   527 				}
   463 				}
   528 			}
   464 			}
   529 		OstTrace1( TRACE_DUMP, DUP2_CRICHTEXTINDEX_SPLITPARAGRAPHATPASTEPOSL, "Leave code=%d", ret );
       
   530 		User::Leave(ret);
   465 		User::Leave(ret);
   531 		}
   466 		}
   532 	if (insertPendingPos != EInsertCharFormatReset)
   467 	if (insertPendingPos != EInsertCharFormatReset)
   533 		ConsolidateAt(insertPendingPos, insertCharFormatDeleted?
   468 		ConsolidateAt(insertPendingPos, insertCharFormatDeleted?
   534 			EPositionOnly : EFollowingPhrase);
   469 			EPositionOnly : EFollowingPhrase);
   553 	{
   488 	{
   554 	__TEST_INVARIANT;
   489 	__TEST_INVARIANT;
   555 
   490 
   556 	RebalanceIndex();
   491 	RebalanceIndex();
   557 // ASSERT: A valid picture header, referencing a valid picture has been inserted.
   492 // ASSERT: A valid picture header, referencing a valid picture has been inserted.
   558 	if (!aPicHdr.iPicture.IsPtr() || aPicHdr.iPicture.AsPtr()==NULL)
       
   559 	    {
       
   560 	    OstTrace0( TRACE_FATAL, DUP1_CRICHTEXTINDEX_INSERTL, "EInsertNullPicHdrData" );
       
   561 	    }
       
   562 	__ASSERT_ALWAYS(aPicHdr.iPicture.IsPtr() && aPicHdr.iPicture.AsPtr()!=NULL,Panic(EInsertNullPicHdrData));
   493 	__ASSERT_ALWAYS(aPicHdr.iPicture.IsPtr() && aPicHdr.iPicture.AsPtr()!=NULL,Panic(EInsertNullPicHdrData));
   563 // ASSERT: The current insert pos hasn't been changed without cancelling SetInsertCharFormat.
   494 // ASSERT: The current insert pos hasn't been changed without cancelling SetInsertCharFormat.
   564 	if ((iPendingNewPhrasePos!=EInsertCharFormatReset) && (aPos!=iPendingNewPhrasePos))
       
   565 	    {
       
   566 	    OstTrace0( TRACE_FATAL, DUP2_CRICHTEXTINDEX_INSERTL, "ESetInsertCharFormatIntegrityErr" );
       
   567 	    }
       
   568 	__ASSERT_ALWAYS((iPendingNewPhrasePos==EInsertCharFormatReset) || (aPos==iPendingNewPhrasePos),
   495 	__ASSERT_ALWAYS((iPendingNewPhrasePos==EInsertCharFormatReset) || (aPos==iPendingNewPhrasePos),
   569 					Panic(ESetInsertCharFormatIntegrityErr));
   496 					Panic(ESetInsertCharFormatIntegrityErr));
   570 	if (iPendingNewPhrasePos!=EInsertCharFormatReset)
   497 	if (iPendingNewPhrasePos!=EInsertCharFormatReset)
   571 		CancelInsertCharFormat();  // Cancel this state before inserting picture. Rebalances the index.
   498 		CancelInsertCharFormat();  // Cancel this state before inserting picture. Rebalances the index.
   572 	ScanToPosition(aPos,EScanToPositionMatchLeft);
   499 	ScanToPosition(aPos,EScanToPositionMatchLeft);
   587 		CleanupStack::PushL(TCleanupItem(ReleaseOnCleanup,reclaimed));
   514 		CleanupStack::PushL(TCleanupItem(ReleaseOnCleanup,reclaimed));
   588 		current.iParaEntry->iParaAttribs=reclaimed;  // Use this reclaimed para attribs (the new CParaAttribs instance)
   515 		current.iParaEntry->iParaAttribs=reclaimed;  // Use this reclaimed para attribs (the new CParaAttribs instance)
   589 		}
   516 		}
   590 	GetCurrentRecords(current);
   517 	GetCurrentRecords(current);
   591 //	ASSERT: The reclaim succeeded.  We must always end up with a PhraseIx-not constant char format.
   518 //	ASSERT: The reclaim succeeded.  We must always end up with a PhraseIx-not constant char format.
   592 	if (current.iPhrase==NULL)
       
   593 	    {
       
   594 	    OstTrace0( TRACE_DUMP, DUP3_CRICHTEXTINDEX_INSERTL, "EReclaimShareError" );
       
   595 	    }
       
   596 	__ASSERT_DEBUG(current.iPhrase!=NULL,Panic(EReclaimShareError));
   519 	__ASSERT_DEBUG(current.iPhrase!=NULL,Panic(EReclaimShareError));
   597 	TRAPD(ret1,
   520 	TRAPD(ret1,
   598 	SplitPhraseL(aPos));  // Phrase may not be split if at boundary.
   521 	SplitPhraseL(aPos));  // Phrase may not be split if at boundary.
   599 
   522 
   600     if (ret1!=KErrNone)
   523     if (ret1!=KErrNone)
   846 	__TEST_INVARIANT;  // Do not need to RebalanceIndex(); part of defined behaviour for delete.
   769 	__TEST_INVARIANT;  // Do not need to RebalanceIndex(); part of defined behaviour for delete.
   847 
   770 
   848 	CancelInsertCharFormat();
   771 	CancelInsertCharFormat();
   849 	ScanToPosition(aPos,EScanToPositionAbsolute,&iLastUsed);
   772 	ScanToPosition(aPos,EScanToPositionAbsolute,&iLastUsed);
   850 
   773 
   851 	if (iPos.iParaElementOffset!=0)
       
   852 	    {
       
   853 	    OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_DELETEPARAGRAPH, "EDeleteParagraphInvalidStartValue" );
       
   854 	    }
       
   855 	__ASSERT_DEBUG(iPos.iParaElementOffset==0,Panic(EDeleteParagraphInvalidStartValue));
   774 	__ASSERT_DEBUG(iPos.iParaElementOffset==0,Panic(EDeleteParagraphInvalidStartValue));
   856 
   775 
   857 	TIndexDeleteInfo info;
   776 	TIndexDeleteInfo info;
   858 	info.iDeleteType=TIndexDeleteInfo::EDeleteParagraph;
   777 	info.iDeleteType=TIndexDeleteInfo::EDeleteParagraph;
   859 	info.iDeletePos=iPos;
   778 	info.iDeletePos=iPos;
   892 	TCurrentIndexRecords current;
   811 	TCurrentIndexRecords current;
   893 	GetCurrentRecords(current);
   812 	GetCurrentRecords(current);
   894 	TInt startParaLength=current.iParaEntry->iLength;
   813 	TInt startParaLength=current.iParaEntry->iLength;
   895 	TInt lengthRemainingInPara=startParaLength-iPos.iParaElementOffset;
   814 	TInt lengthRemainingInPara=startParaLength-iPos.iParaElementOffset;
   896 
   815 
   897 	if (aLength>=lengthRemainingInPara)
       
   898 	    {
       
   899 	    OstTrace0( TRACE_FATAL, CRICHTEXTINDEX_DELETEFROMPARAGRAPH, "EDeleteFromParagraphInvalidRange" );
       
   900 	    }
       
   901 	__ASSERT_ALWAYS(aLength<lengthRemainingInPara,Panic(EDeleteFromParagraphInvalidRange));
   816 	__ASSERT_ALWAYS(aLength<lengthRemainingInPara,Panic(EDeleteFromParagraphInvalidRange));
   902 	}
   817 	}
   903 #endif
   818 #endif
   904 
   819 
   905 	TIndexDeleteInfo info;
   820 	TIndexDeleteInfo info;
  1111 movement etc. Split the current phrase at aPos (if necessary) and insert a zero
  1026 movement etc. Split the current phrase at aPos (if necessary) and insert a zero
  1112 length phrase, ready to accept the pending content of the specified format.
  1027 length phrase, ready to accept the pending content of the specified format.
  1113 */
  1028 */
  1114 void CRichTextIndex::SetInsertCharFormatL(const TCharFormatX& aFormat,const TCharFormatXMask& aMask,TInt aPos)
  1029 void CRichTextIndex::SetInsertCharFormatL(const TCharFormatX& aFormat,const TCharFormatXMask& aMask,TInt aPos)
  1115 	{
  1030 	{
  1116 	if (InsertCharFormatIsActive() && aPos!=iPendingNewPhrasePos)
       
  1117 	    {
       
  1118 	    OstTrace0( TRACE_FATAL, CRICHTEXTINDEX_SETINSERTCHARFORMATL, "ESetInsertCharFormatIntegrityErr" );
       
  1119 	    }
       
  1120 	__ASSERT_ALWAYS(!InsertCharFormatIsActive() || aPos==iPendingNewPhrasePos,
  1031 	__ASSERT_ALWAYS(!InsertCharFormatIsActive() || aPos==iPendingNewPhrasePos,
  1121 					Panic(ESetInsertCharFormatIntegrityErr));
  1032 					Panic(ESetInsertCharFormatIntegrityErr));
  1122 	if (InsertCharFormatIsActive())
  1033 	if (InsertCharFormatIsActive())
  1123 		UpdateInsertCharFormatL(aFormat, aMask);
  1034 		UpdateInsertCharFormatL(aFormat, aMask);
  1124 	else
  1035 	else
  1126 	}
  1037 	}
  1127 
  1038 
  1128 void CRichTextIndex::NewInsertCharFormatL(const TCharFormatX& aFormat,
  1039 void CRichTextIndex::NewInsertCharFormatL(const TCharFormatX& aFormat,
  1129 	const TCharFormatXMask& aMask, TInt aPos)
  1040 	const TCharFormatXMask& aMask, TInt aPos)
  1130 	{
  1041 	{
  1131 	if (InsertCharFormatIsActive())
       
  1132 	    {
       
  1133 	    OstTrace0( TRACE_FATAL, CRICHTEXTINDEX_NEWINSERTCHARFORMATL, "ESetInsertCharFormatIntegrityErr" );
       
  1134 	    }
       
  1135 	__ASSERT_ALWAYS(!InsertCharFormatIsActive(),
  1042 	__ASSERT_ALWAYS(!InsertCharFormatIsActive(),
  1136 		Panic(ESetInsertCharFormatIntegrityErr));
  1043 		Panic(ESetInsertCharFormatIntegrityErr));
  1137 	ScanToPosition(aPos,EScanToPositionMatchLeft);
  1044 	ScanToPosition(aPos,EScanToPositionMatchLeft);
  1138 	TCurrentIndexRecords current;
  1045 	TCurrentIndexRecords current;
  1139 	GetCurrentRecords(current);
  1046 	GetCurrentRecords(current);
  1162 		else
  1069 		else
  1163 			{// Restore the original phrase index.
  1070 			{// Restore the original phrase index.
  1164 			if (PhraseSplit())
  1071 			if (PhraseSplit())
  1165 				MergePhrases(aPos);
  1072 				MergePhrases(aPos);
  1166 			}
  1073 			}
  1167 		OstTrace0( TRACE_FATAL, DUP1_CRICHTEXTINDEX_NEWINSERTCHARFORMATL, "LeaveNoMemory" );
       
  1168 		User::LeaveNoMemory();
  1074 		User::LeaveNoMemory();
  1169 		}
  1075 		}
  1170 	iPendingNewPhrasePos=aPos;
  1076 	iPendingNewPhrasePos=aPos;
  1171 	}
  1077 	}
  1172 
  1078 
  1181 	CleanupStack::PopAndDestroy(newLayer);
  1087 	CleanupStack::PopAndDestroy(newLayer);
  1182 	}
  1088 	}
  1183 
  1089 
  1184 CCharFormatLayer* CRichTextIndex::GetCurrentInsertCharFormat()
  1090 CCharFormatLayer* CRichTextIndex::GetCurrentInsertCharFormat()
  1185 	{
  1091 	{
  1186 	if (!InsertCharFormatIsActive())
       
  1187 	    {
       
  1188 	    OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_GETCURRENTINSERTCHARFORMAT, "ESetInsertCharFormatIntegrityErr" );
       
  1189 	    }
       
  1190 	__ASSERT_DEBUG(InsertCharFormatIsActive(),
  1092 	__ASSERT_DEBUG(InsertCharFormatIsActive(),
  1191 		Panic(ESetInsertCharFormatIntegrityErr));
  1093 		Panic(ESetInsertCharFormatIntegrityErr));
  1192 	ScanToPosition(iPendingNewPhrasePos,EScanToPositionMatchLeft);
  1094 	ScanToPosition(iPendingNewPhrasePos,EScanToPositionMatchLeft);
  1193 	TCurrentIndexRecords current;
  1095 	TCurrentIndexRecords current;
  1194 	GetCurrentRecords(current);
  1096 	GetCurrentRecords(current);
  1195 	if ((*iPhraseIx)[iPos.iPhraseElement].Length() != 0)
       
  1196 	    {
       
  1197 	    OstTrace0( TRACE_DUMP, DUP1_CRICHTEXTINDEX_GETCURRENTINSERTCHARFORMAT, "ESetInsertCharFormatIntegrityErr" );
       
  1198 	    }
       
  1199 	__ASSERT_DEBUG((*iPhraseIx)[iPos.iPhraseElement].Length() == 0,
  1097 	__ASSERT_DEBUG((*iPhraseIx)[iPos.iPhraseElement].Length() == 0,
  1200 		Panic(ESetInsertCharFormatIntegrityErr));
  1098 		Panic(ESetInsertCharFormatIntegrityErr));
  1201 	return (*iPhraseIx)[iPos.iPhraseElement].CharFormat();
  1099 	return (*iPhraseIx)[iPos.iPhraseElement].CharFormat();
  1202 	}
  1100 	}
  1203 
  1101 
  1223 //
  1121 //
  1224 	{
  1122 	{
  1225 	if (iRollbackParaAttribsHandle)
  1123 	if (iRollbackParaAttribsHandle)
  1226 		{
  1124 		{
  1227 		// ASSERT: The specified para attribs is indeed in the share list.
  1125 		// ASSERT: The specified para attribs is indeed in the share list.
  1228 		if (!iRollbackParaAttribsHandle->IsShared())
       
  1229 		    {
       
  1230 		    OstTrace0( TRACE_FATAL, CRICHTEXTINDEX_REBALANCEINDEX, "EParaAttribsNotInSharedList" );
       
  1231 		    }
       
  1232 		__ASSERT_ALWAYS(iRollbackParaAttribsHandle->IsShared(),Panic(EParaAttribsNotInSharedList));
  1126 		__ASSERT_ALWAYS(iRollbackParaAttribsHandle->IsShared(),Panic(EParaAttribsNotInSharedList));
  1233 		iRollbackParaAttribsHandle->Release();
  1127 		iRollbackParaAttribsHandle->Release();
  1234 		iRollbackParaAttribsHandle=NULL;
  1128 		iRollbackParaAttribsHandle=NULL;
  1235 		}
  1129 		}
  1236 	}
  1130 	}
  1258 @pre The insert character format must be active
  1152 @pre The insert character format must be active
  1259 @return ETrue if a zero-length phrase was deleted.
  1153 @return ETrue if a zero-length phrase was deleted.
  1260 */
  1154 */
  1261 TBool CRichTextIndex::DeleteInsertCharFormat()
  1155 TBool CRichTextIndex::DeleteInsertCharFormat()
  1262 	{
  1156 	{
  1263 	if (!InsertCharFormatIsActive())
       
  1264 	    {
       
  1265 	    OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_DELETEINSERTCHARFORMAT, "Invariant" );
       
  1266 	    }
       
  1267 	__ASSERT_DEBUG(InsertCharFormatIsActive(), User::Invariant());
  1157 	__ASSERT_DEBUG(InsertCharFormatIsActive(), User::Invariant());
  1268 	ScanToPosition(iPendingNewPhrasePos,EScanToPositionMatchLeft);
  1158 	ScanToPosition(iPendingNewPhrasePos,EScanToPositionMatchLeft);
  1269 	TCurrentIndexRecords current;
  1159 	TCurrentIndexRecords current;
  1270 	GetCurrentRecords(current);
  1160 	GetCurrentRecords(current);
  1271 	if (current.iPhrase && current.iPhrase->Length() == 0)
  1161 	if (current.iPhrase && current.iPhrase->Length() == 0)
  1563 	}
  1453 	}
  1564 
  1454 
  1565 
  1455 
  1566 void CRichTextIndex::SplitPhraseL(TInt aPhrase,TInt anOffset,RPhraseAttribsEntry& aPhraseAttribs,CParaAttribs& aParaAttribs)
  1456 void CRichTextIndex::SplitPhraseL(TInt aPhrase,TInt anOffset,RPhraseAttribsEntry& aPhraseAttribs,CParaAttribs& aParaAttribs)
  1567 	{
  1457 	{
  1568 	if (anOffset<=0 || anOffset>=aPhraseAttribs.Length())
       
  1569 	    {
       
  1570 	    OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_SPLITPHRASEL, "Invariant" );
       
  1571 	    }
       
  1572 	__ASSERT_DEBUG(anOffset>0 && anOffset<aPhraseAttribs.Length(),User::Invariant());
  1458 	__ASSERT_DEBUG(anOffset>0 && anOffset<aPhraseAttribs.Length(),User::Invariant());
  1573 //
  1459 //
  1574 	CCharFormatLayer* charLayer=CCharFormatLayer::NewCopyBaseL(aPhraseAttribs.CharFormat());
  1460 	CCharFormatLayer* charLayer=CCharFormatLayer::NewCopyBaseL(aPhraseAttribs.CharFormat());
  1575 	CleanupStack::PushL(charLayer);
  1461 	CleanupStack::PushL(charLayer);
  1576 	iPhraseIx->InsertL(aPhrase+1,RPhraseAttribsEntry(charLayer,aPhraseAttribs.Length()-anOffset));
  1462 	iPhraseIx->InsertL(aPhrase+1,RPhraseAttribsEntry(charLayer,aPhraseAttribs.Length()-anOffset));
  1599 //
  1485 //
  1600 // aParaEntry is not shared and can be (phrase count 1), aPhrase is the single phrase element
  1486 // aParaEntry is not shared and can be (phrase count 1), aPhrase is the single phrase element
  1601 //
  1487 //
  1602 	{
  1488 	{
  1603 	CParaAttribs* paraAttribs=aParaEntry.iParaAttribs;
  1489 	CParaAttribs* paraAttribs=aParaEntry.iParaAttribs;
  1604 	if (paraAttribs->iPhraseCount!=1)
       
  1605 	    {
       
  1606 	    OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_SHARE, "Invariant" );
       
  1607 	    }
       
  1608 	__ASSERT_DEBUG(paraAttribs->iPhraseCount==1,User::Invariant());
  1490 	__ASSERT_DEBUG(paraAttribs->iPhraseCount==1,User::Invariant());
  1609 
  1491 
  1610 	RPhraseAttribsEntry& phraseAttribs=iPhraseIx->At(aPhrase);
  1492 	RPhraseAttribsEntry& phraseAttribs=iPhraseIx->At(aPhrase);
  1611 	if (phraseAttribs.IsPicturePhrase())
       
  1612 	    {
       
  1613 	    OstTrace0( TRACE_DUMP, DUP1_CRICHTEXTINDEX_SHARE, "Invariant" );
       
  1614 	    }
       
  1615 	__ASSERT_DEBUG(!phraseAttribs.IsPicturePhrase(),User::Invariant());
  1493 	__ASSERT_DEBUG(!phraseAttribs.IsPicturePhrase(),User::Invariant());
  1616 
  1494 
  1617 	CParaAttribs* share=GetParaAttribs(paraAttribs,*phraseAttribs.CharFormat());
  1495 	CParaAttribs* share=GetParaAttribs(paraAttribs,*phraseAttribs.CharFormat());
  1618 	if (share!=paraAttribs)
  1496 	if (share!=paraAttribs)
  1619 		{	// re-use an existing share, so release the current attribs
  1497 		{	// re-use an existing share, so release the current attribs
  1642 	if (paraAttribs->IsShared())
  1520 	if (paraAttribs->IsShared())
  1643 		return;
  1521 		return;
  1644 
  1522 
  1645 	TInt phrase=iPos.iPhraseElement;
  1523 	TInt phrase=iPos.iPhraseElement;
  1646 	TInt base=iPos.iParaBasePhraseElement;
  1524 	TInt base=iPos.iParaBasePhraseElement;
  1647 	if (phrase<base || phrase>=base+paraAttribs->iPhraseCount)
       
  1648 	    {
       
  1649 	    OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_APPLYCHARFORMATROLLBACK, "Invariant" );
       
  1650 	    }
       
  1651 	__ASSERT_DEBUG(phrase>=base && phrase<base+paraAttribs->iPhraseCount,User::Invariant());
  1525 	__ASSERT_DEBUG(phrase>=base && phrase<base+paraAttribs->iPhraseCount,User::Invariant());
  1652 	if (phrase<base+paraAttribs->iPhraseCount-1)	// merge to the right
  1526 	if (phrase<base+paraAttribs->iPhraseCount-1)	// merge to the right
  1653 		MergePhrases(phrase+1,iPhraseIx->At(phrase+1),*paraAttribs);
  1527 		MergePhrases(phrase+1,iPhraseIx->At(phrase+1),*paraAttribs);
  1654 	if (phrase>base)								// merge to the left
  1528 	if (phrase>base)								// merge to the left
  1655 		MergePhrases(phrase,iPhraseIx->At(phrase),*paraAttribs);
  1529 		MergePhrases(phrase,iPhraseIx->At(phrase),*paraAttribs);
  1661 void CRichTextIndex::ApplyCharFormatL(const TCharFormatX& aFormat,const TCharFormatXMask& aMask,TInt aPos,TInt aLength,TBool aRemoveSpecific)
  1535 void CRichTextIndex::ApplyCharFormatL(const TCharFormatX& aFormat,const TCharFormatXMask& aMask,TInt aPos,TInt aLength,TBool aRemoveSpecific)
  1662 // Applies the specified character formatting to the characters contained within the range
  1536 // Applies the specified character formatting to the characters contained within the range
  1663 // aPos to aPos+(aLength-1).
  1537 // aPos to aPos+(aLength-1).
  1664 //
  1538 //
  1665 	{
  1539 	{
  1666 	if (aLength<0)
       
  1667 	    {
       
  1668 	    OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_APPLYCHARFORMATL, "Invariant" );
       
  1669 	    }
       
  1670 	__ASSERT_DEBUG(aLength>=0,User::Invariant());
  1540 	__ASSERT_DEBUG(aLength>=0,User::Invariant());
  1671 	__TEST_INVARIANT;
  1541 	__TEST_INVARIANT;
  1672 
  1542 
  1673 	ScanToPosition(aPos,EScanToPositionAbsolute);
  1543 	ScanToPosition(aPos,EScanToPositionAbsolute);
  1674 	TInt paraOffset=iPos.iParaElementOffset;
  1544 	TInt paraOffset=iPos.iParaElementOffset;
  1718 // STEP 2.	Walk through all affected phrases in this paragraph
  1588 // STEP 2.	Walk through all affected phrases in this paragraph
  1719 //			For each one, we may need to split it, and then apply the new format
  1589 //			For each one, we may need to split it, and then apply the new format
  1720 
  1590 
  1721 		do
  1591 		do
  1722 			{
  1592 			{
  1723 			if (phrase>=iPos.iParaBasePhraseElement+paraAttribs->iPhraseCount)
       
  1724 			    {
       
  1725 			    OstTrace0( TRACE_DUMP, DUP1_CRICHTEXTINDEX_APPLYCHARFORMATL, "Invariant" );
       
  1726 			    }
       
  1727 			__ASSERT_DEBUG(phrase<iPos.iParaBasePhraseElement+paraAttribs->iPhraseCount,User::Invariant());
  1593 			__ASSERT_DEBUG(phrase<iPos.iParaBasePhraseElement+paraAttribs->iPhraseCount,User::Invariant());
  1728 //
  1594 //
  1729 			RPhraseAttribsEntry* phraseAttribs=&iPhraseIx->At(phrase);
  1595 			RPhraseAttribsEntry* phraseAttribs=&iPhraseIx->At(phrase);
  1730 			TInt len=phraseAttribs->Length();
  1596 			TInt len=phraseAttribs->Length();
  1731 
  1597 
  1759 				SplitPhraseL(phrase,charsToFormat,*phraseAttribs,*paraAttribs);
  1625 				SplitPhraseL(phrase,charsToFormat,*phraseAttribs,*paraAttribs);
  1760 				len=charsToFormat;
  1626 				len=charsToFormat;
  1761 				phraseAttribs=&iPhraseIx->At(phrase);		// SplitPhraseL modifies the index array, we must do this!
  1627 				phraseAttribs=&iPhraseIx->At(phrase);		// SplitPhraseL modifies the index array, we must do this!
  1762 				}
  1628 				}
  1763 
  1629 
  1764 			if (phraseAttribs->Length()!=len)
       
  1765 			    {
       
  1766 			    OstTrace0( TRACE_DUMP, DUP2_CRICHTEXTINDEX_APPLYCHARFORMATL, "Invariant" );
       
  1767 			    }
       
  1768 			__ASSERT_DEBUG(phraseAttribs->Length()==len,User::Invariant());
  1630 			__ASSERT_DEBUG(phraseAttribs->Length()==len,User::Invariant());
  1769 
  1631 
  1770 // STEP 2.3	Change the format of the current phrase layer
  1632 // STEP 2.3	Change the format of the current phrase layer
  1771 
  1633 
  1772 			TCharFormatX format=aFormat;
  1634 			TCharFormatX format=aFormat;
  1783 				iPos.iPhraseElement=++phrase;
  1645 				iPos.iPhraseElement=++phrase;
  1784 
  1646 
  1785 			charsToFormat-=len;
  1647 			charsToFormat-=len;
  1786 			} while (charsToFormat);
  1648 			} while (charsToFormat);
  1787 
  1649 
  1788 		if (phrase!=iPos.iParaBasePhraseElement+paraAttribs->iPhraseCount && aLength!=0)
       
  1789 		    {
       
  1790 		    OstTrace0( TRACE_DUMP, DUP3_CRICHTEXTINDEX_APPLYCHARFORMATL, "Invariant" );
       
  1791 		    }
       
  1792 		__ASSERT_DEBUG(phrase==iPos.iParaBasePhraseElement+paraAttribs->iPhraseCount || aLength==0,User::Invariant());
  1650 		__ASSERT_DEBUG(phrase==iPos.iParaBasePhraseElement+paraAttribs->iPhraseCount || aLength==0,User::Invariant());
  1793 
  1651 
  1794 // STEP 3	Reduce the paragraph attributes back to canonical form
  1652 // STEP 3	Reduce the paragraph attributes back to canonical form
  1795 
  1653 
  1796 // STEP 3.1	Check for merging at the end of the changes
  1654 // STEP 3.1	Check for merging at the end of the changes
  1812 		iPos.iParaElement++;
  1670 		iPos.iParaElement++;
  1813 		paraOffset=0;
  1671 		paraOffset=0;
  1814 		iPos.iParaBasePhraseElement=phrase;
  1672 		iPos.iParaBasePhraseElement=phrase;
  1815 #ifdef _DEBUG
  1673 #ifdef _DEBUG
  1816 		ScanToPosition(aPos,EScanToPositionAbsolute);
  1674 		ScanToPosition(aPos,EScanToPositionAbsolute);
  1817 		if (iPos.iDocPos!=aPos)
       
  1818 		    {
       
  1819 		    OstTrace0( TRACE_DUMP, DUP4_CRICHTEXTINDEX_APPLYCHARFORMATL, "Invariant" );
       
  1820 		    }
       
  1821 		__ASSERT_DEBUG(iPos.iDocPos==aPos,User::Invariant());
  1675 		__ASSERT_DEBUG(iPos.iDocPos==aPos,User::Invariant());
  1822 		if (iPos.iPhraseElement!=phrase)
       
  1823 		    {
       
  1824 		    OstTrace0( TRACE_DUMP, DUP5_CRICHTEXTINDEX_APPLYCHARFORMATL, "Invariant" );
       
  1825 		    }
       
  1826 		__ASSERT_DEBUG(iPos.iPhraseElement==phrase,User::Invariant());
  1676 		__ASSERT_DEBUG(iPos.iPhraseElement==phrase,User::Invariant());
  1827 		if (iPos.iParaElementOffset!=paraOffset)
       
  1828 		    {
       
  1829 		    OstTrace0( TRACE_DUMP, DUP6_CRICHTEXTINDEX_APPLYCHARFORMATL, "Invariant" );
       
  1830 		    }
       
  1831 		__ASSERT_DEBUG(iPos.iParaElementOffset==paraOffset,User::Invariant());
  1677 		__ASSERT_DEBUG(iPos.iParaElementOffset==paraOffset,User::Invariant());
  1832 		if (iPos.iPhraseElementOffset!=phraseOffset)
       
  1833 		    {
       
  1834 		    OstTrace0( TRACE_DUMP, DUP7_CRICHTEXTINDEX_APPLYCHARFORMATL, "Invariant" );
       
  1835 		    }
       
  1836 		__ASSERT_DEBUG(iPos.iPhraseElementOffset==phraseOffset,User::Invariant());
  1678 		__ASSERT_DEBUG(iPos.iPhraseElementOffset==phraseOffset,User::Invariant());
  1837 		__TEST_INVARIANT;
  1679 		__TEST_INVARIANT;
  1838 #endif
  1680 #endif
  1839 		}
  1681 		}
  1840 
  1682 
  2383 	if (handle)
  2225 	if (handle)
  2384 		return handle;
  2226 		return handle;
  2385 	else
  2227 	else
  2386 		{// No match, so piece together new shared paraAttribs and add to shared para list
  2228 		{// No match, so piece together new shared paraAttribs and add to shared para list
  2387 		sourceParaAttribs->iRefCount=1;
  2229 		sourceParaAttribs->iRefCount=1;
  2388 		if (sourcePhrase->IsPicturePhrase())
       
  2389 		    {
       
  2390 		    OstTrace0( TRACE_FATAL, CRICHTEXTINDEX_GETPARAATTRIBS, "EReleasCharFormatLayerOwnershipCalledOnPicturePhrase" );
       
  2391 		    }
       
  2392 		__ASSERT_ALWAYS(!sourcePhrase->IsPicturePhrase(),Panic(EReleasCharFormatLayerOwnershipCalledOnPicturePhrase));
  2230 		__ASSERT_ALWAYS(!sourcePhrase->IsPicturePhrase(),Panic(EReleasCharFormatLayerOwnershipCalledOnPicturePhrase));
  2393 		sourceParaAttribs->iCharFormat=sourcePhrase->ReleaseCharFormatLayerOwnership();
  2231 		sourceParaAttribs->iCharFormat=sourcePhrase->ReleaseCharFormatLayerOwnership();
  2394 		sourcePhrase->Discard();
  2232 		sourcePhrase->Discard();
  2395 		iPhraseIx->Delete(aLogicalPosition.iPhraseElement);  // remove the deleted phrase from the phrase index.
  2233 		iPhraseIx->Delete(aLogicalPosition.iPhraseElement);  // remove the deleted phrase from the phrase index.
  2396 		iSharedParaQueHead.AddLast(*sourceParaAttribs);
  2234 		iSharedParaQueHead.AddLast(*sourceParaAttribs);
  2516 		else
  2354 		else
  2517 			iPos.iPhraseElementOffset=paraElementOffset-startOfPhrase;
  2355 			iPos.iPhraseElementOffset=paraElementOffset-startOfPhrase;
  2518 		}
  2356 		}
  2519 	else
  2357 	else
  2520 		{
  2358 		{
  2521 		if (iPos.iParaBasePhraseElement!=phraseElement)
       
  2522 		    {
       
  2523 		    OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_SCANTOPOSITION, "EDebug" );
       
  2524 		    }
       
  2525 		__ASSERT_DEBUG(iPos.iParaBasePhraseElement==phraseElement,Panic(EDebug));
  2359 		__ASSERT_DEBUG(iPos.iParaBasePhraseElement==phraseElement,Panic(EDebug));
  2526 		}
  2360 		}
  2527 	iPos.iPhraseElement=phraseElement;
  2361 	iPos.iPhraseElement=phraseElement;
  2528 	iPos.iDocPos=aCharPos;
  2362 	iPos.iDocPos=aCharPos;
  2529 	if (aLastUsed)
  2363 	if (aLastUsed)
  2624 	ScanToPosition(aSplitPos,EScanToPositionAbsolute);
  2458 	ScanToPosition(aSplitPos,EScanToPositionAbsolute);
  2625 	if (iPos.iPhraseElementOffset==0)
  2459 	if (iPos.iPhraseElementOffset==0)
  2626 		return;  // aSplitPos on a phrase boundary; urgo no split.
  2460 		return;  // aSplitPos on a phrase boundary; urgo no split.
  2627 	TCurrentIndexRecords current; GetCurrentRecords(current);
  2461 	TCurrentIndexRecords current; GetCurrentRecords(current);
  2628 // ASSERT: This function set can only be called on CParaAttribs that specific char format.
  2462 // ASSERT: This function set can only be called on CParaAttribs that specific char format.
  2629 	if (current.iPhrase==NULL)
       
  2630 	    {
       
  2631 	    OstTrace0( TRACE_FATAL, DUP1_CRICHTEXTINDEX_SPLITPHRASEL, "ESplitPhraseCalledOnSharedPara" );
       
  2632 	    }
       
  2633 	__ASSERT_ALWAYS(current.iPhrase!=NULL,Panic(ESplitPhraseCalledOnSharedPara));
  2463 	__ASSERT_ALWAYS(current.iPhrase!=NULL,Panic(ESplitPhraseCalledOnSharedPara));
  2634 	DoSplitPhraseL(*current.iPhrase,iPos.iPhraseElementOffset,current.iParaAttribs);
  2464 	DoSplitPhraseL(*current.iPhrase,iPos.iPhraseElementOffset,current.iParaAttribs);
  2635 	}
  2465 	}
  2636 
  2466 
  2637 
  2467 
  2657 // Splits the specified phrase, creating a new phrase of the same character format.
  2487 // Splits the specified phrase, creating a new phrase of the same character format.
  2658 // This new phrase is inserted into the phrase index immediately following the current one.
  2488 // This new phrase is inserted into the phrase index immediately following the current one.
  2659 //
  2489 //
  2660 	{
  2490 	{
  2661 // ASSERT: Cannot split a picture phrase.
  2491 // ASSERT: Cannot split a picture phrase.
  2662 	if (aCurrentPhrase.IsPicturePhrase())
       
  2663 	    {
       
  2664 	    OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_DOSPLITPHRASEL, "ESplitPhraseCalledOnPicturePhrase" );
       
  2665 	    }
       
  2666 	__ASSERT_DEBUG(!aCurrentPhrase.IsPicturePhrase(),Panic(ESplitPhraseCalledOnPicturePhrase));
  2492 	__ASSERT_DEBUG(!aCurrentPhrase.IsPicturePhrase(),Panic(ESplitPhraseCalledOnPicturePhrase));
  2667 	CCharFormatLayer* layer=CCharFormatLayer::NewCopyBaseL(aCurrentPhrase.CharFormat());
  2493 	CCharFormatLayer* layer=CCharFormatLayer::NewCopyBaseL(aCurrentPhrase.CharFormat());
  2668 	CleanupStack::PushL(layer);
  2494 	CleanupStack::PushL(layer);
  2669 	RPhraseAttribsEntry newPhrase(layer,aCurrentPhrase.Length()-aPhraseOffset);
  2495 	RPhraseAttribsEntry newPhrase(layer,aCurrentPhrase.Length()-aPhraseOffset);
  2670 	iPhraseIx->InsertL(iPos.iPhraseElement+1,newPhrase);
  2496 	iPhraseIx->InsertL(iPos.iPhraseElement+1,newPhrase);
  2692 	TInt phraseCount=PhraseCount();
  2518 	TInt phraseCount=PhraseCount();
  2693 	if (phraseCount>0)
  2519 	if (phraseCount>0)
  2694 		return ETrue;
  2520 		return ETrue;
  2695 	//
  2521 	//
  2696 	TInt sharedParaCount=SharedParaCount(this);
  2522 	TInt sharedParaCount=SharedParaCount(this);
  2697 	if (sharedParaCount<1 && (sharedParaCount!=0 || phraseCount<=0))
       
  2698 	    {
       
  2699 	    OstTrace0( TRACE_FATAL, CRICHTEXTINDEX_HASMARKUPDATA, "ERichTextIndexIntegrityErr" );
       
  2700 	    }
       
  2701 	__ASSERT_ALWAYS(sharedParaCount>=1 || (sharedParaCount==0 && phraseCount>0),Panic(ERichTextIndexIntegrityErr));
  2523 	__ASSERT_ALWAYS(sharedParaCount>=1 || (sharedParaCount==0 && phraseCount>0),Panic(ERichTextIndexIntegrityErr));
  2702 	if (sharedParaCount>1)
  2524 	if (sharedParaCount>1)
  2703 		return ETrue;
  2525 		return ETrue;
  2704 	const CParaAttribs* paraAttribs=iSharedParaQueHead.First();
  2526 	const CParaAttribs* paraAttribs=iSharedParaQueHead.First();
  2705 	if (!paraAttribs->iParaFormat->IsEmpty())
  2527 	if (!paraAttribs->iParaFormat->IsEmpty())
  2768 		const CParaAttribs* sParaAttribs=sParaEntry.iParaAttribs;
  2590 		const CParaAttribs* sParaAttribs=sParaEntry.iParaAttribs;
  2769 		CParaAttribs* tParaAttribs;
  2591 		CParaAttribs* tParaAttribs;
  2770 		if (sParaAttribs->IsShared())
  2592 		if (sParaAttribs->IsShared())
  2771 			{
  2593 			{
  2772 			tParaAttribs=map->Item(sParaAttribs);
  2594 			tParaAttribs=map->Item(sParaAttribs);
  2773 			if (tParaAttribs==NULL)
       
  2774 			    {
       
  2775 			    OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_APPENDPARAINDEXL, "ESharedFormatsMapIntegrityError" );
       
  2776 			    }
       
  2777 			__ASSERT_DEBUG(tParaAttribs!=NULL,Panic(ESharedFormatsMapIntegrityError));
  2595 			__ASSERT_DEBUG(tParaAttribs!=NULL,Panic(ESharedFormatsMapIntegrityError));
  2778 			tParaAttribs->iRefCount++;
  2596 			tParaAttribs->iRefCount++;
  2779 			}
  2597 			}
  2780 		else
  2598 		else
  2781 			{// Have to build up the specific para attribs
  2599 			{// Have to build up the specific para attribs
  2805 	{
  2623 	{
  2806 	TDblQueIter<CParaAttribs> iterator(MUTABLE_CAST(TDblQue<CParaAttribs>&,aSource->iSharedParaQueHead));
  2624 	TDblQueIter<CParaAttribs> iterator(MUTABLE_CAST(TDblQue<CParaAttribs>&,aSource->iSharedParaQueHead));
  2807 	CParaAttribs* currentSharedPara;
  2625 	CParaAttribs* currentSharedPara;
  2808 	while ((currentSharedPara=iterator++)!=NULL)
  2626 	while ((currentSharedPara=iterator++)!=NULL)
  2809 		{
  2627 		{
  2810 		if (!currentSharedPara->IsShared())
       
  2811 		    {
       
  2812 		    OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_APPENDSHAREDFORMATSL, "Invariant" );
       
  2813 		    }
       
  2814 		__ASSERT_DEBUG(currentSharedPara->IsShared(),User::Invariant());
  2628 		__ASSERT_DEBUG(currentSharedPara->IsShared(),User::Invariant());
  2815 
  2629 
  2816 		CParaFormatLayer* sPl=currentSharedPara->iParaFormat;
  2630 		CParaFormatLayer* sPl=currentSharedPara->iParaFormat;
  2817 		CCharFormatLayer* sCl=currentSharedPara->iCharFormat;
  2631 		CCharFormatLayer* sCl=currentSharedPara->iCharFormat;
  2818 		sPl->SetBase(aGlobalLayerInfo.iAggParaFormatLayer);  // alter the original so that the following GetParaAttribsL() call will
  2632 		sPl->SetBase(aGlobalLayerInfo.iAggParaFormatLayer);  // alter the original so that the following GetParaAttribsL() call will
  2873 	// transfer pictures now
  2687 	// transfer pictures now
  2874 	for (TInt kk=pictureMap->Count();--kk>=0;)
  2688 	for (TInt kk=pictureMap->Count();--kk>=0;)
  2875 		{
  2689 		{
  2876 		TInt jj=pictureMap->At(kk);
  2690 		TInt jj=pictureMap->At(kk);
  2877 		TPictureHeader* sHeader=(*aSource->iPhraseIx)[jj].PictureHeaderPtr();
  2691 		TPictureHeader* sHeader=(*aSource->iPhraseIx)[jj].PictureHeaderPtr();
  2878 		if (!sHeader)
       
  2879 		    {
       
  2880 		    OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_APPENDPHRASEINDEXL, "Invariant" );
       
  2881 		    }
       
  2882 		__ASSERT_DEBUG(sHeader,User::Invariant());
  2692 		__ASSERT_DEBUG(sHeader,User::Invariant());
  2883 		if (sHeader->iPicture.IsPtr())
  2693 		if (sHeader->iPicture.IsPtr())
  2884 			{	// transfer picture to us
  2694 			{	// transfer picture to us
  2885 			TPictureHeader* tHeader=(*iPhraseIx)[jj+originalPhraseCount].PictureHeaderPtr();
  2695 			TPictureHeader* tHeader=(*iPhraseIx)[jj+originalPhraseCount].PictureHeaderPtr();
  2886 			if (!tHeader)
       
  2887 			    {
       
  2888 			    OstTrace0( TRACE_DUMP, DUP1_CRICHTEXTINDEX_APPENDPHRASEINDEXL, "Invariant" );
       
  2889 			    }
       
  2890 			__ASSERT_DEBUG(tHeader,User::Invariant());
  2696 			__ASSERT_DEBUG(tHeader,User::Invariant());
  2891 			tHeader->iPicture=sHeader->iPicture.AsPtr();
  2697 			tHeader->iPicture=sHeader->iPicture.AsPtr();
  2892 			sHeader->iPicture=NULL;
  2698 			sHeader->iPicture=NULL;
  2893 			}
  2699 			}
  2894 		}
  2700 		}
  3034 // Class invariants.
  2840 // Class invariants.
  3035 //
  2841 //
  3036 	{
  2842 	{
  3037 #ifdef _DEBUG
  2843 #ifdef _DEBUG
  3038 // ASSERT: iLength is +ve (applying to character formatting, or	is set to indicate a picture phrase.
  2844 // ASSERT: iLength is +ve (applying to character formatting, or	is set to indicate a picture phrase.
  3039 	if (iLength<0 && !IsPicturePhrase())
       
  3040 	    {
       
  3041 	    OstTrace0( TRACE_DUMP, RPHRASEATTRIBSENTRY_DBGTESTINVARIANT, "Invariant" );
       
  3042 	    }
       
  3043 	__ASSERT_DEBUG(iLength>=0 || IsPicturePhrase(),User::Invariant());
  2845 	__ASSERT_DEBUG(iLength>=0 || IsPicturePhrase(),User::Invariant());
  3044 #endif
  2846 #endif
  3045 	}
  2847 	}
  3046 
  2848 
  3047 
  2849 
  3121 // Adjusts the length of the phrase by the signed value aIncrement.
  2923 // Adjusts the length of the phrase by the signed value aIncrement.
  3122 //
  2924 //
  3123 	{
  2925 	{
  3124 // ASSERT: The length of a picture phrase may only be altered by deleting it, in which case
  2926 // ASSERT: The length of a picture phrase may only be altered by deleting it, in which case
  3125 //			the only adjustment made will be an increment of -1 (EPictureIndicator).
  2927 //			the only adjustment made will be an increment of -1 (EPictureIndicator).
  3126 	if (IsPicturePhrase() && (!IsPicturePhrase() || aIncrement!=EPictureIndicator)
       
  3127                                       && (!IsPicturePhrase() || aIncrement!=0) )
       
  3128 	    {
       
  3129 	    OstTrace0( TRACE_DUMP, RPHRASEATTRIBSENTRY_ADJUSTLENGTH, "EModifiedPicturePhraseLength" );
       
  3130 	    }
       
  3131 	__ASSERT_DEBUG(!IsPicturePhrase() || (IsPicturePhrase() && aIncrement==EPictureIndicator)
  2928 	__ASSERT_DEBUG(!IsPicturePhrase() || (IsPicturePhrase() && aIncrement==EPictureIndicator)
  3132 									  || (IsPicturePhrase() && aIncrement==0)
  2929 									  || (IsPicturePhrase() && aIncrement==0)
  3133 									  ,Panic(EModifiedPicturePhraseLength));
  2930 									  ,Panic(EModifiedPicturePhraseLength));
  3134 	TInt len=iLength;
  2931 	TInt len=iLength;
  3135 	iLength=(len==EPictureIndicator)
  2932 	iLength=(len==EPictureIndicator)