1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/textandloc/textrendering/texthandling/stext/TXTIXSTR.CPP Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1659 @@
1.4 +/*
1.5 +* Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description:
1.18 +*
1.19 +*/
1.20 +
1.21 +
1.22 +#include <e32std.h>
1.23 +#include <e32base.h>
1.24 +
1.25 +#include <gdi.h>
1.26 +
1.27 +#include "TXTFMLYR.H"
1.28 +#include "TXTMRTSR.H"
1.29 +#include "TXTRICH.H"
1.30 +#include "TXTINDEX.H"
1.31 +#include "TXTSTD.H"
1.32 +
1.33 +#include "OstTraceDefinitions.h"
1.34 +#ifdef OST_TRACE_COMPILER_IN_USE
1.35 +#include "TXTIXSTRTraces.h"
1.36 +#endif
1.37 +
1.38 +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
1.39 +#include "TXTFMLYR_INTERNAL.H"
1.40 +#endif
1.41 +
1.42 +const TUint8 KRegisterItemPresent=1;
1.43 +
1.44 +
1.45 +GLDEF_C void DiscardPhraseOnCleanup(TAny* aPhrase)
1.46 +// Allows RPhraseAttribsEntry on the CleanupStack to be destroyed correctly,
1.47 +// when included as a PushL(TCleanupItem).
1.48 +//
1.49 + {
1.50 + ((RPhraseAttribsEntry*)aPhrase)->Discard();
1.51 + User::Free(aPhrase);
1.52 + }
1.53 +
1.54 +
1.55 +TRtPasteContext::TRtPasteContext(const CStreamStore* aStore,const CParaFormatLayer* aGlobalParaLayer,const CCharFormatLayer* aGlobalCharLayer,const CStyleList* aStyleList)
1.56 +//
1.57 + :iStore(aStore),
1.58 + iGlobalParaLayer(aGlobalParaLayer),iGlobalCharLayer(aGlobalCharLayer),iStyleList(aStyleList),
1.59 + iParagraphStylesFlag(EFalse),iIncompleteParaFlag(ETrue),iPastePos(),iParasPasted(0)
1.60 + {}
1.61 +
1.62 +//////////////////////////////////////////////////////////////////////////////////////
1.63 +
1.64 +
1.65 +CRichTextIndex* CRichTextIndex::NewL(const CStreamStore& aStore,TStreamId aId,
1.66 +// MPictureFactory* aPictureFactory,MRichTextStoreResolver* aStoreResolver,
1.67 + const CParaFormatLayer* aGlobalParaLayer,
1.68 + const CCharFormatLayer* aGlobalCharLayer,
1.69 + const CRichText& aText)
1.70 +// const CStyleList* aStyleList)
1.71 +//
1.72 + {
1.73 + CRichTextIndex* self=new(ELeave) CRichTextIndex(aText);
1.74 + CleanupStack::PushL(self);
1.75 + self->ConstructL(aGlobalParaLayer,aGlobalCharLayer,KMultiParaGranularity,KLargePhraseGranularity);
1.76 + self->RestoreL(aStore,aId,aGlobalParaLayer,aGlobalCharLayer,aText.StyleList());
1.77 +// self->SetPictureFactory(aPictureFactory,aStoreResolver);
1.78 + CleanupStack::Pop();
1.79 + return self;
1.80 + }
1.81 +
1.82 +
1.83 +void CRichTextIndex::RestoreL(const CStreamStore& aStore,TStreamId aId,
1.84 + const CParaFormatLayer* aGlobalParaLayer,
1.85 + const CCharFormatLayer* aGlobalCharLayer,
1.86 + const CStyleList* aStyleList)
1.87 +//
1.88 + {
1.89 + RStoreReadStream stream;
1.90 + stream.OpenLC(aStore,aId);
1.91 + //
1.92 + InternalizeL(stream,aGlobalParaLayer,aGlobalCharLayer,aStyleList);
1.93 + CleanupStack::PopAndDestroy(); // stream
1.94 + }
1.95 +
1.96 +
1.97 +TStreamId CRichTextIndex::StoreMarkupL(CStreamStore& aStore,const CStyleList* /*aStyleList*/) const
1.98 +// Store this rich text markup out-of-line along with its components.
1.99 +//
1.100 + {
1.101 + CStoreMap* map=CStoreMap::NewLC(aStore);
1.102 + StorePicturesL(aStore,*map);
1.103 +//
1.104 + RStoreWriteStream stream(*map);
1.105 + TStreamId id=stream.CreateLC(aStore);
1.106 +// CONST_CAST(CRichTextIndex*,this)->iStyleList=CONST_CAST(CStyleList*,aStyleList);
1.107 + ExternalizeL(stream);
1.108 + stream.CommitL();
1.109 +//
1.110 + map->Reset();
1.111 + CleanupStack::PopAndDestroy(2); // map,stream
1.112 + return id;
1.113 + }
1.114 +
1.115 +
1.116 +void CRichTextIndex::StorePicturesL(CStreamStore& aStore,CStoreMap& aMap) const
1.117 +// Store any picture components in the specified store.
1.118 +// Due to deferred loading, any pictures that are not in memory at this point are loaded,
1.119 +// and then saved.
1.120 +//
1.121 + {
1.122 + __TEST_INVARIANT;
1.123 +
1.124 + StorePicturesL(aStore,aMap,0,iText.DocumentLength()+1);
1.125 + }
1.126 +
1.127 +
1.128 +void CRichTextIndex::StorePicturesL(CStreamStore& aStore,CStoreMap& aMap,TInt aPos,TInt aLength) const
1.129 +// Store all picture components that are contained within the specified range (inclusive), in the store provided.
1.130 +// Prior to storing the picture, its size is written to its picture header which is stored in-line in
1.131 +// the markup.
1.132 +// Any pictures that are not in memory are now deleted, as a previous call to LoadAllPicturesNowL()
1.133 +// should have been made.
1.134 +// We are guaranteed that all pictures that are in memory are fully restored & detached from their store
1.135 +//
1.136 + {
1.137 + __TEST_INVARIANT;
1.138 +
1.139 + if (iPictureCount==0)
1.140 + return;
1.141 + CONST_CAST(CRichTextIndex*,this)->DetachFromStoreL(CPicture::EDetachFull,aPos,aLength); // ensure all pictures have been loaded
1.142 + TInt currentPos=aPos;
1.143 + DocumentChanged(); // reset the cache logical position
1.144 + while (currentPos<aPos+aLength)
1.145 + {// Store next picture & increment pos.
1.146 + CONST_CAST(CRichTextIndex*,this)->ScanToPosition(currentPos,EScanToPositionAbsolute,&MUTABLE_CAST(TLogicalPosition&,iLastUsed));
1.147 + TCurrentIndexRecords current;
1.148 + GetCurrentRecords(current);
1.149 + if (current.iPhrase && current.iPhrase->IsPicturePhrase())
1.150 + {
1.151 + RPhraseAttribsEntry& phrase=*current.iPhrase;
1.152 + TPictureHeader* hdr=phrase.PictureHeaderPtr();
1.153 + if (!hdr)
1.154 + {
1.155 + OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_STOREPICTURESL, "ERichTextStorePictureIntegrityError" );
1.156 + }
1.157 + __ASSERT_DEBUG(hdr,Panic(ERichTextStorePictureIntegrityError));
1.158 + TBool pictureInMemory=(hdr->iPicture.IsPtr() && hdr->iPicture.AsPtr());
1.159 + if (pictureInMemory)
1.160 + {// Store the picture
1.161 + CPicture& picture=*hdr->iPicture;
1.162 + picture.GetSizeInTwips(hdr->iSize); // write picture size to picture header.
1.163 + TStreamId id=picture.StoreL(aStore);
1.164 + aMap.BindL(hdr->iPicture,id);
1.165 + }
1.166 + else
1.167 + {// Replace the picture phrase with a simple text equivalent.
1.168 + CCharFormatLayer* charLayer=phrase.ReleaseCharFormatLayerOwnership();
1.169 + phrase.Discard(); // destroy the redundant picture phrase
1.170 + RPhraseAttribsEntry newTextPhrase(charLayer,1);
1.171 + (*iPhraseIx)[iPos.iPhraseElement]=newTextPhrase;
1.172 + CONST_CAST(CRichTextIndex*,this)->iPictureCount--; // the picture has now been removed
1.173 + // I do not bother tidying up the phrase index here,
1.174 + // since the benefit does not currently match the cost involved.
1.175 + //
1.176 + }
1.177 + }
1.178 + //
1.179 + // increment the current position to the *start* of the next phrase/paragraph
1.180 + TInt offsetIntoUnit=(current.iPhrase)?iPos.iPhraseElementOffset:iPos.iParaElementOffset;
1.181 + currentPos+=CurrentPhraseLength()-offsetIntoUnit;
1.182 + }
1.183 + }
1.184 +
1.185 +
1.186 +void CRichTextIndex::DetachFromStoreL(CPicture::TDetach aDegree,TInt aPos,TInt aLength)
1.187 +// Attempts to restore all pictures not already present in memory.
1.188 +// A deep (door+document) or shallow (door only) restoration may occur, depending
1.189 +// on the value of detach.
1.190 +//
1.191 + {
1.192 + __TEST_INVARIANT;
1.193 +
1.194 + if (iPictureCount==0)
1.195 + return;
1.196 + DocumentChanged(); // reset the cache logical position
1.197 + TInt currentPos=aPos;
1.198 + while (currentPos<aPos+aLength)
1.199 + {
1.200 + CONST_CAST(CRichTextIndex*,this)->ScanToPosition(currentPos,EScanToPositionAbsolute,&iLastUsed);
1.201 + TCurrentIndexRecords current;
1.202 + GetCurrentRecords(current);
1.203 + if (current.iPhrase)
1.204 + {
1.205 + RPhraseAttribsEntry& phrase=*current.iPhrase;
1.206 + if (phrase.IsPicturePhrase())
1.207 + {
1.208 + TPictureHeader* hdr=phrase.PictureHeaderPtr();
1.209 + if (!hdr)
1.210 + {
1.211 + OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_DETACHFROMSTOREL, "ERichTextStorePictureIntegrityError" );
1.212 + }
1.213 + __ASSERT_DEBUG(hdr,Panic(ERichTextStorePictureIntegrityError));
1.214 + //
1.215 + if (hdr->iPicture.IsId())
1.216 + {
1.217 + TRAPD(r,
1.218 + phrase.PictureHandleL(iText.PictureFactory(),iText.StoreResolver(),iPos.iDocPos,MLayDoc::EForceLoadTrue)); // swizzles
1.219 + if (r!=KErrNone && !hdr->iPicture.IsId())
1.220 + {
1.221 + OstTrace0( TRACE_DUMP, DUP1_CRICHTEXTINDEX_DETACHFROMSTOREL, "ERichTextStorePictureIntegrityError" );
1.222 + }
1.223 + __ASSERT_DEBUG(r==KErrNone || hdr->iPicture.IsId(),Panic(ERichTextStorePictureIntegrityError));
1.224 + if (r==KErrNotSupported) // we don't recognise the picture type
1.225 + {
1.226 + TInt offsetIntoUnit=(current.iPhrase)?iPos.iPhraseElementOffset:iPos.iParaElementOffset;
1.227 + currentPos+=CurrentPhraseLength()-offsetIntoUnit;
1.228 + continue;
1.229 + }
1.230 +
1.231 + OstTrace1( TRACE_FATAL, DUP3_CRICHTEXTINDEX_DETACHFROMSTOREL, "Leave code=%d", r );
1.232 + User::LeaveIfError(r);
1.233 + }
1.234 + //
1.235 + // recurse the call to detach the picture from the store
1.236 + if (!hdr->iPicture.IsPtr())
1.237 + {
1.238 + OstTrace0( TRACE_DUMP, DUP2_CRICHTEXTINDEX_DETACHFROMSTOREL, "ERichTextStorePictureIntegrityError" );
1.239 + }
1.240 + __ASSERT_DEBUG(hdr->iPicture.IsPtr(),Panic(ERichTextStorePictureIntegrityError));
1.241 + hdr->iPicture->DetachFromStoreL(aDegree);
1.242 + }
1.243 + }
1.244 + //
1.245 + // increment the current position to the *start* of the next phrase/paragraph
1.246 + TInt offsetIntoUnit=(current.iPhrase)?iPos.iPhraseElementOffset:iPos.iParaElementOffset;
1.247 + currentPos+=CurrentPhraseLength()-offsetIntoUnit;
1.248 + }
1.249 + __TEST_INVARIANT;
1.250 + }
1.251 +
1.252 +//////////////////////////////////////////////////////////////////////////////////////
1.253 +
1.254 +void CRichTextIndex::ExternalizeL(RWriteStream& aStream)const
1.255 +// Persist the current state of this object in the specified stream.
1.256 +// Saved records include the terminating paragraph delimiter.
1.257 +//
1.258 +//
1.259 + {
1.260 + __TEST_INVARIANT;
1.261 +
1.262 + CONST_CAST(CRichTextIndex*,this)->CancelInsertCharFormat(); // cancel any insert-pending state.
1.263 + TInt charCount=iText.DocumentLength()+1; // includes the end of document character
1.264 + ((CRichTextIndex*)this)->ScanToPosition(0,EScanToPositionAbsolute);
1.265 + TLogicalPosition startPos=iPos;
1.266 + ((CRichTextIndex*)this)->ScanToPosition(charCount-1,EScanToPositionMatchLeft);
1.267 + TLogicalPosition endPos=iPos;
1.268 + CStyleList* styleList=iText.StyleList();
1.269 + ExternalizeRtiHeaderL(aStream,endPos,styleList);
1.270 + ExternalizeSharedFormatsL(aStream,startPos,endPos,styleList);
1.271 + // DEF126934 begin: memory leak
1.272 + RPhraseAttribsEntry *pForRelease = ExternalizeParaIxL(aStream,startPos,endPos,styleList);
1.273 + if (pForRelease)
1.274 + delete pForRelease;
1.275 + // DEF126934 end
1.276 + ExternalizePhraseIxL(aStream);
1.277 + }
1.278 +
1.279 +
1.280 +void CRichTextIndex::InternalizeL(RReadStream& aStream,const CParaFormatLayer* aGlobalParaLayer,const CCharFormatLayer* aGlobalCharLayer,const CStyleList* aStyleList)
1.281 +// Load a rich text index. Has construct semantics only!
1.282 +// Restores this object from the specified stream. As specific format layers are restored, they are based
1.283 +// on the specified global format layers.
1.284 +//
1.285 + {
1.286 + if (iParaIx->Count()!=1 || (*iParaIx)[0].iLength!=1)
1.287 + {
1.288 + OstTrace0( TRACE_FATAL, CRICHTEXTINDEX_INTERNALIZEL, "ERtIndexInternalizeCalledOnNonEmptySource" );
1.289 + }
1.290 + __ASSERT_ALWAYS(iParaIx->Count()==1 && (*iParaIx)[0].iLength==1,Panic(ERtIndexInternalizeCalledOnNonEmptySource));
1.291 + TRtPasteContext context(NULL,aGlobalParaLayer,aGlobalCharLayer,aStyleList);
1.292 + InternalizeRtiHeaderL(aStream,context);
1.293 + InternalizeSharedFormatsL(aStream,context);
1.294 + InternalizeParaIxL(aStream,context);
1.295 + InternalizePhraseIxL(aStream,aGlobalCharLayer);
1.296 + if (context.iParagraphStylesFlag)
1.297 + GenerateAllPhraseLinksL();
1.298 + SetSpecificMarkupInternalized(ETrue);
1.299 +
1.300 + __TEST_INVARIANT;
1.301 + }
1.302 +
1.303 +//////////////////////////////////////////////////////////////////////////////////////
1.304 +
1.305 +
1.306 +void CRichTextIndex::GenerateAllPhraseLinksL()
1.307 +// Go through the index, and for each specific character format layer (shared or otherwise), regenerate
1.308 +// the appropriate based-on link, (normal or style).
1.309 +//
1.310 + {
1.311 + TInt count=ParagraphCount();
1.312 + TInt phraseElement=0;
1.313 + for (TInt ii=0; ii<count; ii++)
1.314 + {
1.315 + const CParaAttribs& paraAttribs=*(*iParaIx)[ii].iParaAttribs;
1.316 + const CParaFormatLayer* base=STATIC_CAST(const CParaFormatLayer*,paraAttribs.iParaFormat->SenseBase());
1.317 + TInt phraseCount=paraAttribs.PhraseCount();
1.318 + if (phraseCount==1)
1.319 + {
1.320 + // If the reference count is zero, iCharFormat cannot be valid, so the CParaAttribs object is corrupt.
1.321 + if (paraAttribs.iRefCount == 0)
1.322 + User::Leave(KErrCorrupt);
1.323 +
1.324 + GeneratePhraseLink(paraAttribs.iCharFormat,base); // constant character formatting
1.325 + }
1.326 + else
1.327 + {
1.328 + if (phraseCount<=1)
1.329 + {
1.330 + OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_GENERATEALLPHRASELINKSL, "EDebug" );
1.331 + }
1.332 + __ASSERT_DEBUG(phraseCount>1,Panic(EDebug));
1.333 +
1.334 + // If the phrase count is too great the CParaAttribs object is corrupt.
1.335 + if (phraseElement + phraseCount > iPhraseIx->Count())
1.336 + User::Leave(KErrCorrupt);
1.337 +
1.338 + for (TInt nn=0; nn<phraseCount; nn++)
1.339 + GeneratePhraseLink((*iPhraseIx)[phraseElement+nn].CharFormat(),base);
1.340 + phraseElement+=phraseCount;
1.341 + }
1.342 + }
1.343 + }
1.344 +
1.345 +
1.346 +void CRichTextIndex::GeneratePhraseLink(CCharFormatLayer* aPhraseCharFormatLayer,const CParaFormatLayer* aBase)
1.347 +// Set the based on link for this character format layer appropriately.
1.348 +// By default, all specific character format layers are based on the global default.
1.349 +//
1.350 + {
1.351 + TUid type=aBase->Type();
1.352 + if (type!=KNormalParagraphStyleUid)
1.353 + aPhraseCharFormatLayer->SetBase(((CParagraphStyle*)aBase)->CharFormatLayer());
1.354 + }
1.355 +
1.356 +
1.357 +//////////////////////////////////////////////////////////////////////////////////////
1.358 +
1.359 +void CRichTextIndex::CopyToStreamL(RWriteStream& aStream,TInt aPos,TInt aLength, TBool aCopyStyles)const
1.360 +// Copies the markup corresponding to the specified rich text region to the specified write stream.
1.361 +// aPos/aLength has already been validated in RichText
1.362 +// Saved records can NOT include the terminating paragraph delimiter.
1.363 +//
1.364 + {
1.365 + __TEST_INVARIANT;
1.366 +
1.367 + ((CRichTextIndex*)this)->ScanToPosition(aPos,EScanToPositionAbsolute);
1.368 + TLogicalPosition startPos=iPos;
1.369 + ((CRichTextIndex*)this)->ScanToPosition((aPos+aLength)-1,EScanToPositionAbsolute);
1.370 + TLogicalPosition endPos=iPos;
1.371 +
1.372 + CStyleList* docStyleList = NULL;
1.373 + if (aCopyStyles)
1.374 + docStyleList = (CStyleList*)iText.StyleList();
1.375 +
1.376 + ExternalizeRtiHeaderL(aStream,endPos,docStyleList);
1.377 +
1.378 + if (docStyleList)
1.379 + ExternalizeReferencedStylesL(aStream,startPos,endPos);
1.380 +
1.381 + ExternalizeSharedFormatsL(aStream,startPos,endPos,docStyleList);
1.382 + RPhraseAttribsEntry* virtualTrailingText=ExternalizeParaIxL(aStream,startPos,endPos,docStyleList);
1.383 + if (virtualTrailingText)
1.384 + CleanupStack::PushL(virtualTrailingText);
1.385 + ExternalizePhraseIxL(aStream,startPos,endPos,virtualTrailingText);
1.386 + if (virtualTrailingText)
1.387 + CleanupStack::PopAndDestroy(virtualTrailingText);
1.388 + }
1.389 +
1.390 +//////////////////////////////////////////////////////////////////////////////////////
1.391 +
1.392 +
1.393 +void CRichTextIndex::ExternalizeRtiHeaderL(RWriteStream& aStream,const TLogicalPosition& aEnd,const CStyleList* aStyleList)const
1.394 +// Stores index specific information.
1.395 +//
1.396 + {
1.397 + TBool incompleteParaFlag=((*iParaIx)[aEnd.iParaElement].iLength>(aEnd.iParaElementOffset+1));
1.398 + aStream.WriteUint8L((TUint8)(aStyleList!=NULL)); // flags the presence of paragraph styles.
1.399 + aStream.WriteUint8L((TUint8)(incompleteParaFlag!=EFalse)); // the last para has no paragraph delimiter
1.400 + if(incompleteParaFlag)
1.401 + {//apply paragraph format to final text fragment if logical end is at document end
1.402 + aStream.WriteUint8L((TUint8)(aEnd.iDocPos+1 == iText.DocumentLength()));
1.403 + }
1.404 + }
1.405 +
1.406 +
1.407 +void CRichTextIndex::InternalizeRtiHeaderL(RReadStream& aStream,TRtPasteContext& aContext)
1.408 +// Load index specific information.
1.409 +//
1.410 + {
1.411 + TUint8 flag=0;
1.412 + aStream>> flag;
1.413 + aContext.iParagraphStylesFlag=(TBool)flag;
1.414 + aStream>> flag;
1.415 + aContext.iIncompleteParaFlag=(TBool)flag;
1.416 + aContext.iApplyFormatToLastFlag=EFalse;
1.417 + if(aContext.iIncompleteParaFlag)
1.418 + {
1.419 + aStream>> flag;
1.420 + aContext.iApplyFormatToLastFlag=(TBool)flag;
1.421 + }
1.422 + }
1.423 +
1.424 +//////////////////////////////////////////////////////////////////////////////////////
1.425 +
1.426 +void CRichTextIndex::ExternalizeReferencedStylesL(RWriteStream& aStream,const TLogicalPosition& aStart,
1.427 + const TLogicalPosition& aEnd) const
1.428 +// Write those styles that are referenced by the paragraphs in the range aStart to aEnd.
1.429 +//
1.430 + {
1.431 + CStyleList* list = iText.StyleList();
1.432 + if (!list)
1.433 + {
1.434 + OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_EXTERNALIZEREFERENCEDSTYLESL, "EStyleClipboardIntegrityError" );
1.435 + }
1.436 + __ASSERT_DEBUG(list,Panic(EStyleClipboardIntegrityError));
1.437 + if (aStart.iParaElement > aEnd.iParaElement)
1.438 + {
1.439 + OstTrace0( TRACE_DUMP, DUP1_CRICHTEXTINDEX_EXTERNALIZEREFERENCEDSTYLESL, "EStyleClipboardIntegrityError" );
1.440 + }
1.441 + __ASSERT_DEBUG(aStart.iParaElement <= aEnd.iParaElement,Panic(EStyleClipboardIntegrityError));
1.442 +
1.443 + TUint8 numStyles = 0;
1.444 + if (list)
1.445 + numStyles = (TUint8)list->Count();
1.446 +
1.447 + HBufC8* buf=HBufC8::NewL(numStyles);
1.448 + TPtr8 paraRegister=buf->Des();
1.449 + paraRegister.FillZ(numStyles);
1.450 + TInt refCount=MarkStyleRegister(paraRegister,aStart.iParaElement,aEnd.iParaElement);
1.451 + CleanupStack::PushL(buf);
1.452 + ExternalizeItemsPresentInStyleRegisterL(aStream,refCount,paraRegister);
1.453 + CleanupStack::PopAndDestroy();
1.454 + }
1.455 +
1.456 +
1.457 +void CRichTextIndex::InternalizeSharedFormatsL(RReadStream& aStream, const TRtPasteContext& aContext)
1.458 +// Restores the list of shared para attribs.
1.459 +// All existing CParaAttribs on the shared list are removed.
1.460 +// The reference counts are not restored, but modified dynamically as the para index is loaded.
1.461 +//
1.462 + {
1.463 + iParaIx->Reset(); // stops paraIx referencing shared paraAttribs that are about to be released.
1.464 + CParaAttribs* currentSharedPara;
1.465 + TDblQueIter<CParaAttribs> iterator(iSharedParaQueHead);
1.466 + while ( (currentSharedPara = iterator++) != NULL )
1.467 + currentSharedPara->Release(currentSharedPara->iRefCount);
1.468 + TUint8 sharedParaCount = ReadTUint8CountL(aStream);
1.469 + for (TUint8 paraItem = 0; paraItem < sharedParaCount; paraItem++)
1.470 + {
1.471 + (void)aStream.ReadInt32L(); // consume the data.
1.472 + CParaFormatLayer* paraLayer = InternalizeParagraphFormatL(aStream, aContext);
1.473 + CleanupStack::PushL(paraLayer);
1.474 +
1.475 + CCharFormatLayer* charLayer = CCharFormatLayer::NewL(aStream); // Does not restore based on link.
1.476 + charLayer->SetBase(aContext.iGlobalCharLayer); // base on 'Normal' global char format
1.477 + CleanupStack::PushL(charLayer);
1.478 + CParaAttribs* paraAttribs = CParaAttribs::NewL(paraLayer, charLayer);
1.479 + CleanupStack::PopAndDestroy(2);
1.480 + paraAttribs->iRefCount = 0; // Otherwise recalculating reference counts on internalization of paraIx will result in 1 too many.
1.481 + iSharedParaQueHead.AddLast(*paraAttribs);
1.482 + }
1.483 + }
1.484 +
1.485 +
1.486 +void CRichTextIndex::ExternalizeSharedFormatsL(RWriteStream& aStream,const TLogicalPosition& aStart,const TLogicalPosition& aEnd,const CStyleList* aStyleList)const
1.487 +// Persist those items in the shared list that are referenced by the paragraphs in the
1.488 +// range aStart para to aEnd para.
1.489 +//
1.490 + {
1.491 + TUint8 sharedParaCount=SharedParaAttribsEntryCountL();
1.492 + // Some paras coverd, so take register
1.493 + HBufC8* buf=HBufC8::NewL(sharedParaCount);
1.494 + TPtr8 sharedAttribsRegister=buf->Des();
1.495 + sharedAttribsRegister.FillZ(sharedParaCount);
1.496 + TInt sharedCount=MarkRegister(sharedAttribsRegister,aStart.iParaElement,aEnd.iParaElement);
1.497 + CleanupStack::PushL(buf);
1.498 + ExternalizeItemsPresentInRegisterL(aStream,sharedCount,sharedAttribsRegister,aStyleList);
1.499 + CleanupStack::PopAndDestroy();
1.500 + }
1.501 +
1.502 +
1.503 +TUint8 CRichTextIndex::SharedParaAttribsEntryCountL()const
1.504 +// Return a count of the number of items currently
1.505 +// in the sharedParaFormats list.
1.506 +//
1.507 +// This will leave if more than 255 found, as this is not supported
1.508 + {
1.509 + TDblQueIter<CParaAttribs> iterator(((CRichTextIndex*)this)->iSharedParaQueHead);
1.510 + TUint16 sharedParaCount = 0;
1.511 + while (iterator++ != NULL)
1.512 + sharedParaCount++;
1.513 +
1.514 + // Currently more than 255 paragraph formats are not supported
1.515 + // If the current document has more, leave with KErrNotSupported
1.516 + if (sharedParaCount > 255)
1.517 + User::Leave(KErrNotSupported);
1.518 +
1.519 + return (TUint8)sharedParaCount;
1.520 + }
1.521 +
1.522 +
1.523 +TInt CRichTextIndex::MarkRegister(TDes8& aBuf,TInt aStartPara,TInt aEndPara)const
1.524 +// Indicate in the register, aBuf, once and once only, each paraAttribs that is
1.525 +// referenced by each of the paragraphs in the specified range.
1.526 +// Return the number of shared para formats referenced.
1.527 +//
1.528 + {
1.529 + TInt parasReferenced=0;
1.530 + for (TInt item=aStartPara;item<=aEndPara;item++)
1.531 + {
1.532 + CParaAttribs* paraAttribs=(*iParaIx)[item].iParaAttribs;
1.533 + TInt offset=RefNum(paraAttribs); // 0 return shows para attribs not in shared list
1.534 + if (offset>0)
1.535 + {// para entry references a shared para attribs
1.536 + if (aBuf[offset-1]==0)
1.537 + {
1.538 + aBuf[offset-1]=KRegisterItemPresent; // mark item as needing to be stored
1.539 + parasReferenced++;
1.540 + }
1.541 + }
1.542 + }
1.543 + return parasReferenced;
1.544 + }
1.545 +
1.546 +
1.547 +TInt CRichTextIndex::MarkStyleRegister(TDes8& aBuf,TInt aStartPara,TInt aEndPara)const
1.548 +// Indicate in the register, aBuf, once and once only, each paragraph style thar is
1.549 +// referenced by each of the paragraphs in the speciifed range.
1.550 +// Return the umber of paragraph styles referenced.
1.551 +//
1.552 + {
1.553 + TInt stylesReferenced=0;
1.554 + const CParaAttribs* para=NULL;
1.555 + for (TInt item=aStartPara;item<=aEndPara;item++)
1.556 + {
1.557 + para=(*iParaIx)[item].iParaAttribs;
1.558 + TInt index=iText.StyleList()->IndexByPtr(STATIC_CAST(const CParaFormatLayer*,para->iParaFormat->SenseBase()));
1.559 + if (index!=KErrNotFound)
1.560 + {
1.561 + if (index>=aBuf.Length())
1.562 + {
1.563 + OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_MARKSTYLEREGISTER, "EStyleClipboardIntegrityError" );
1.564 + }
1.565 + __ASSERT_DEBUG(index<aBuf.Length(),Panic(EStyleClipboardIntegrityError));
1.566 + if (aBuf[index]!=KRegisterItemPresent)
1.567 + {
1.568 + aBuf[index]=KRegisterItemPresent; // mark item as needing to be stored
1.569 +
1.570 + stylesReferenced++;
1.571 + }
1.572 + }
1.573 + }
1.574 + return stylesReferenced;
1.575 + }
1.576 +
1.577 +
1.578 +void CRichTextIndex::ExternalizeItemsPresentInRegisterL(RWriteStream& aStream,TInt aSharedCount,const TDes8& aBuf,const CStyleList* aStyleList)const
1.579 +// Externalize each object from the shared list that has a corresponding mark in the
1.580 +// register, aBuf.
1.581 +//
1.582 + {
1.583 + if (aSharedCount>(TInt)KMaxTUint8)
1.584 + {
1.585 + OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_EXTERNALIZEITEMSPRESENTINREGISTERL, "ESharedParaCountStreamOverflow" );
1.586 + }
1.587 + __ASSERT_DEBUG(aSharedCount<=(TInt)KMaxTUint8,Panic(ESharedParaCountStreamOverflow));
1.588 + aStream.WriteUint8L(aSharedCount);
1.589 + CParaAttribs* currentSharedPara=NULL;
1.590 + TDblQueIter<CParaAttribs> iterator(((CRichTextIndex*)this)->iSharedParaQueHead);
1.591 + TInt offset=0;
1.592 + while ((currentSharedPara=iterator++)!=NULL)
1.593 + {
1.594 + if (aBuf[offset]==KRegisterItemPresent)
1.595 + {
1.596 + aStream.WriteInt32L(offset+1); // the ref-no of the shared para - so it can be spotted in the paste.
1.597 + ExternalizeParagraphFormatL(aStream,*currentSharedPara->iParaFormat,aStyleList);
1.598 + aStream<< *currentSharedPara->iCharFormat;
1.599 + }
1.600 + offset++;
1.601 + }
1.602 + }
1.603 +
1.604 +
1.605 +void CRichTextIndex::ExternalizeItemsPresentInStyleRegisterL(RWriteStream& aStream,TInt aRefStyleCount,
1.606 + const TDes8& aBuf) const
1.607 +// Externalize each object from the paragraph style list that has a corresponding mark in the register aBuf.
1.608 +//
1.609 + {
1.610 + if (aRefStyleCount > (TInt)KMaxTUint8)
1.611 + {
1.612 + OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_EXTERNALIZEITEMSPRESENTINSTYLEREGISTERL, "EStyleClipboardIntegrityError" );
1.613 + }
1.614 + __ASSERT_DEBUG(aRefStyleCount <= (TInt)KMaxTUint8,Panic(EStyleClipboardIntegrityError));
1.615 + aStream.WriteUint8L(aRefStyleCount);
1.616 + TInt count=aBuf.Length();
1.617 +
1.618 + for (TInt ii=0;ii<count;ii++)
1.619 + {
1.620 + if (aBuf[ii]==KRegisterItemPresent)
1.621 + {
1.622 + aStream.WriteInt8L(ii+1); // cannot use 0 index as this represents an absence.
1.623 + iText.StyleList()->At(ii).iStyle->ExternalizeL(aStream);
1.624 + }
1.625 + }
1.626 + }
1.627 +
1.628 +
1.629 +RPhraseAttribsEntry* CRichTextIndex::ExternalizeParaIxL(RWriteStream& aStream,
1.630 + const TLogicalPosition& aStart,
1.631 + const TLogicalPosition& aEnd,
1.632 + const CStyleList* aStyleList)const
1.633 +// Externalize each para entry from the para index that falls between
1.634 +// aStart paragraph and aEnd paragraph inclusive.
1.635 +// Any specific paraAttribs (ie not on the shared list) are also externalized.
1.636 +// * paragraph count
1.637 +// * paragraph length
1.638 +// * ref no. (ref no. 0 means specific/non-shared one)
1.639 +// * [specific paragraph format layer - including based-on link]
1.640 +// * [specific phrase count]
1.641 +//
1.642 + {
1.643 + TParaAttribsEntry lastParaEntry=(*iParaIx)[aEnd.iParaElement];
1.644 + TBool incompleteParaFlag=(lastParaEntry.iLength>(aEnd.iParaElementOffset+1));
1.645 + aStream.WriteInt32L(1+aEnd.iParaElement-aStart.iParaElement); // paragraph count
1.646 + for (TInt paraItem=aStart.iParaElement;paraItem<aEnd.iParaElement;paraItem++)
1.647 + {// Externalize all but last TParaAttribsEntrys from the para index
1.648 + TParaAttribsEntry paraEntry=(*iParaIx)[paraItem];
1.649 + TInt phraseCount=(paraEntry.iParaAttribs->IsShared())
1.650 + ? 0
1.651 + : paraEntry.iParaAttribs->iPhraseCount;
1.652 + if (paraItem==aStart.iParaElement)
1.653 + {// Fix & write length & phrase count of the first paragraph.
1.654 + paraEntry.iLength=(paraEntry.iLength-aStart.iParaElementOffset); // fix 1st para length
1.655 + if (phraseCount>0)
1.656 + phraseCount=phraseCount-(aStart.iPhraseElement-aStart.iParaBasePhraseElement);
1.657 + }
1.658 + aStream.WriteInt32L(paraEntry.iLength);
1.659 + CParaAttribs* paraAttribs=paraEntry.iParaAttribs;
1.660 + TUint8 refNo=RefNum(paraAttribs);
1.661 + aStream.WriteUint8L(refNo);
1.662 + if (refNo==0)
1.663 + {// Write specific para layer & phrase count
1.664 + ExternalizeParagraphFormatL(aStream,*paraAttribs->iParaFormat,aStyleList);
1.665 + aStream.WriteInt32L(phraseCount);
1.666 + }
1.667 + }
1.668 + // Fix & write the length of the last paragraph.
1.669 + if (aStart.iParaElement==aEnd.iParaElement)
1.670 + lastParaEntry.iLength=(aEnd.iParaElementOffset-aStart.iParaElementOffset)+1; // copied text contained within 1 para
1.671 + else
1.672 + lastParaEntry.iLength-=(lastParaEntry.iLength-aEnd.iParaElementOffset)-1;
1.673 + aStream.WriteInt32L(lastParaEntry.iLength);
1.674 + // Fix & write the phrase count of the last paragraph if it has specific char format
1.675 + CParaAttribs* lastParaAttribs=lastParaEntry.iParaAttribs;
1.676 + TUint8 refNo=RefNum(lastParaAttribs);
1.677 + RPhraseAttribsEntry* virtualTextPhrase=NULL;
1.678 + if (incompleteParaFlag)
1.679 + {// Adjust the phrase count for this paragraph that is not complete
1.680 + TInt phraseCount=0;
1.681 + if (aStart.iParaElement==aEnd.iParaElement)
1.682 + phraseCount=(aEnd.iPhraseElement-aStart.iPhraseElement)+1; // copied text contained within 1 para
1.683 + else
1.684 + phraseCount=(aEnd.iPhraseElement-aEnd.iParaBasePhraseElement)+1;
1.685 + if (phraseCount>lastParaAttribs->iPhraseCount)
1.686 + {
1.687 + OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_EXTERNALIZEPARAIXL, "ERtExternalizeParaIx" );
1.688 + }
1.689 + __ASSERT_DEBUG(phraseCount<=lastParaAttribs->iPhraseCount,Panic(ERtExternalizeParaIx));
1.690 + aStream.WriteInt32L(phraseCount);
1.691 + if (refNo>0)
1.692 + {// Set the virtual phrase representing the trailing text from the shared paragraph.
1.693 + virtualTextPhrase=new(ELeave) RPhraseAttribsEntry(lastParaAttribs->iCharFormat,lastParaEntry.iLength);
1.694 + CleanupStack::PushL(virtualTextPhrase);
1.695 + }
1.696 +
1.697 + // Write out the paragraph format for the paragraph that is not complete
1.698 + // - necessary since we need to patch up the style character formatting
1.699 + if (aStyleList || aEnd.iDocPos+1 == iText.DocumentLength())
1.700 + ExternalizeParagraphFormatL(aStream, *lastParaAttribs->iParaFormat, aStyleList);
1.701 + }
1.702 + else
1.703 + {// This is a complete para - copy region ends on a paragraph delimiter.
1.704 + aStream.WriteUint8L(refNo);
1.705 + if (refNo==0)
1.706 + {// Write specific para layer & phrase count
1.707 + ExternalizeParagraphFormatL(aStream,*lastParaAttribs->iParaFormat,aStyleList);
1.708 + TInt phraseCount=lastParaAttribs->iPhraseCount;
1.709 + if (aStart.iParaElement==aEnd.iParaElement && aStart.iParaElementOffset && aStart.iParaElementOffset>0)
1.710 + phraseCount=(aEnd.iPhraseElement-aStart.iPhraseElement)+1; // copied text contained within 1 para
1.711 + aStream.WriteInt32L(phraseCount);
1.712 + }
1.713 + }
1.714 + if (virtualTextPhrase)
1.715 + CleanupStack::Pop(virtualTextPhrase);
1.716 + return virtualTextPhrase;
1.717 + }
1.718 +
1.719 +
1.720 +void CRichTextIndex::ExternalizeParagraphFormatL(RWriteStream& aStream,const CParaFormatLayer& aLayer,const CStyleList* aStyleList)const
1.721 +// If a style list is present, write out the based-on links for every paragraph format layer,
1.722 +// in order to reconnect each paragraph to the right style on loading.
1.723 +//
1.724 + {
1.725 + aStream<< aLayer;
1.726 + if (aStyleList)
1.727 + {
1.728 + TInt refNo=0;
1.729 + refNo=aStyleList->IndexByPtr(((CParaFormatLayer*)aLayer.SenseBase()));
1.730 + // returns the offset in the style list, or a negative error.
1.731 + //
1.732 + refNo=(refNo!=KErrNotFound)
1.733 + ? refNo+1 // the nth style where 1st item is offset 1.
1.734 + : 0; // An error value was returned so this thing has no paragraph style as its base
1.735 + aStream.WriteInt8L((TInt8)-refNo);
1.736 + }
1.737 + }
1.738 +
1.739 +
1.740 +CParaFormatLayer* CRichTextIndex::InternalizeParagraphFormatL(RReadStream& aStream,const TRtPasteContext& aContext)
1.741 +//
1.742 + {
1.743 + CParaFormatLayer* paraLayer=CParaFormatLayer::NewL(aStream); // specific paragraph format layer
1.744 + TUint index=0;
1.745 + if (aContext.iParagraphStylesFlag)
1.746 + {
1.747 + CleanupStack::PushL(paraLayer);
1.748 + TInt refNo=aStream.ReadInt8L(); // Read in the based on link to fix up to the style table
1.749 + CleanupStack::Pop();
1.750 + index=Abs(refNo);
1.751 + }
1.752 + if (index>0 && aContext.iStyleList)
1.753 + paraLayer->SetBase(aContext.iStyleList->At(index-1).iStyle);
1.754 + else
1.755 + paraLayer->SetBase(aContext.iGlobalParaLayer);
1.756 + return paraLayer;
1.757 + }
1.758 +
1.759 +
1.760 +CParaFormatLayer* CRichTextIndex::PasteParagraphFormatL(RReadStream& aStream,const TRtPasteContext& aContext,CStyleMap* aStyleMap)
1.761 +//
1.762 + {
1.763 + CParaFormatLayer* paraLayer=CParaFormatLayer::NewL(aStream); // specific paragraph format layer
1.764 +
1.765 + TUint index=0;
1.766 + if (aContext.iParagraphStylesFlag)
1.767 + {
1.768 + CleanupStack::PushL(paraLayer);
1.769 + TInt refNo=aStream.ReadInt8L(); // Read in the based on link to fix up to the style table
1.770 + CleanupStack::Pop(paraLayer); // paraLayer
1.771 + index=Abs(refNo);
1.772 + }
1.773 +
1.774 + // If a style exists for this paragraph, set it as the base.
1.775 + // If a style list doesn't exist, the base paragraph style will be set instead.
1.776 +
1.777 + if (index>0 && aContext.iStylePasteMode != CParagraphStyle::EIgnoreNewStyles)
1.778 + {
1.779 + if (!aContext.iStyleList || (aContext.iStyleList && aContext.iStylePasteMode == CParagraphStyle::EConvertNewStyles))
1.780 + {
1.781 + CleanupStack::PushL(paraLayer);
1.782 + iLastCharacterStyle = (aStyleMap->Item(index))->iCharFormatLayer;
1.783 +
1.784 + // If the application doesn't have a style list,
1.785 + // the new paragraph style has to be enforced by merging the old
1.786 + // paralayer with the style paralayer
1.787 + CParaFormat* MergedParaFormat = CParaFormat::NewLC();
1.788 + TParaFormatMask MergedParaFormatMask;
1.789 +
1.790 + CParaFormatLayer* newParaLayer;
1.791 +
1.792 + // Extract the masks from both layers
1.793 + paraLayer->SenseL(MergedParaFormat, MergedParaFormatMask);
1.794 + (aStyleMap->Item(index))->SenseL(MergedParaFormat, MergedParaFormatMask);
1.795 +
1.796 + newParaLayer = CParaFormatLayer::NewL(MergedParaFormat, MergedParaFormatMask);
1.797 +
1.798 + // Now on stack: MergedParaFormat, paraLayer, ...
1.799 + CleanupStack::PopAndDestroy(); // delete MergedParaFormat
1.800 +
1.801 + // Now on stack: paraLayer, ...
1.802 + CleanupStack::PopAndDestroy(); // paraLayer
1.803 + paraLayer = newParaLayer;
1.804 +
1.805 + paraLayer->SetBase(aContext.iGlobalParaLayer);
1.806 +
1.807 + }
1.808 + else
1.809 + {
1.810 + paraLayer->SetBase(aStyleMap->Item(index));
1.811 + iLastCharacterStyle = NULL;
1.812 + }
1.813 + }
1.814 + else
1.815 + // Otherwise set the character style to NULL, which will set the global
1.816 + // character style (see line 983 approx)
1.817 + {
1.818 + iLastCharacterStyle = NULL;
1.819 + paraLayer->SetBase(aContext.iGlobalParaLayer);
1.820 + }
1.821 +
1.822 + return paraLayer;
1.823 + }
1.824 +
1.825 +
1.826 +void CRichTextIndex::InternalizeParaIxL(RReadStream& aStream,const TRtPasteContext& aContext)
1.827 +// Restore the paragraph index & all associated specific para formats,
1.828 +// All existing index data is lost.
1.829 +//
1.830 + {
1.831 + // The para index has been reset at the start of internalize shared formats.
1.832 + TInt paraIxCount=aStream.ReadInt32L(); // paragraph count
1.833 + for (TInt currentPara=0;currentPara<paraIxCount;currentPara++)
1.834 + {// Restore each paragraph
1.835 + TParaAttribsEntry para;
1.836 + para.iLength=aStream.ReadInt32L(); // paragraph length
1.837 + TUint8 refNo=aStream.ReadUint8L(); // ref no
1.838 + if (refNo>0)
1.839 + {// Link to para attribs in shared list & up its reference count
1.840 + para.iParaAttribs=SharedParaAttribs(refNo);
1.841 + para.iParaAttribs->iRefCount++;
1.842 + iParaIx->AppendL(para);
1.843 + }
1.844 + else
1.845 + {// Have to build up the specific para attribs
1.846 + CParaFormatLayer* paraLayer=InternalizeParagraphFormatL(aStream,aContext);
1.847 + CleanupStack::PushL(paraLayer);
1.848 + CParaAttribs* specificParaAttribs=CParaAttribs::NewL(paraLayer);
1.849 + CleanupStack::PushL(TCleanupItem(ReleaseOnCleanup,specificParaAttribs));
1.850 + specificParaAttribs->iPhraseCount=aStream.ReadInt32L(); // specific phrase count
1.851 + CleanupStack::Pop(); // specificParaAttribs
1.852 + CleanupStack::PopAndDestroy(); // paraLayer
1.853 + para.iParaAttribs=specificParaAttribs;
1.854 + CleanupStack::PushL(TCleanupItem(ReleaseOnCleanup,specificParaAttribs));
1.855 + iParaIx->AppendL(para);
1.856 + CleanupStack::Pop(); // specificParaAttribs
1.857 + }
1.858 + }
1.859 + }
1.860 +
1.861 +void CRichTextIndex::ExternalizePhraseIxL(RWriteStream& aStream)const
1.862 +// Called from an Externalize.
1.863 +// All phrases must be saved.
1.864 +//
1.865 + {ExternalizePhrasesL(aStream,0,PhraseCount());}
1.866 +
1.867 +
1.868 +void CRichTextIndex::ExternalizePhraseIxL(RWriteStream& aStream,
1.869 + const TLogicalPosition& aStart,
1.870 + TLogicalPosition& aEnd,
1.871 + const RPhraseAttribsEntry* aVirtualTrailingText)const
1.872 +// Called from CopyToStream.
1.873 +// Here, a text fragment only, is to be saved.
1.874 +// The last argument may be NULL. If it is other than NULL, it represents trailing text
1.875 +// that has no paragraph delimiter, which was part of a shared paragraph. This must be presented as
1.876 +// a distinct phrase, since this is the context in which it is pasted back into a document.
1.877 +//
1.878 + {
1.879 + TInt phraseCount=PhraseCount();
1.880 + phraseCount+=(aVirtualTrailingText) ? 1 : 0;
1.881 + TBool noRealPhrasesInRegion=ETrue;
1.882 + TInt nn=aStart.iParaElement;
1.883 + while (nn<=aEnd.iParaElement && noRealPhrasesInRegion)
1.884 + {
1.885 + if (!(*iParaIx)[nn].iParaAttribs->IsShared())
1.886 + noRealPhrasesInRegion=EFalse;
1.887 + nn++;
1.888 + }
1.889 + //
1.890 + if (phraseCount==0 || (phraseCount==1 && aVirtualTrailingText || noRealPhrasesInRegion)) // save this phrase count
1.891 + ExternalizePhrasesL(aStream,aStart.iPhraseElement,0,aVirtualTrailingText);
1.892 + else
1.893 + {
1.894 + TBool endParaShared=(*iParaIx)[aEnd.iParaElement].iParaAttribs->IsShared();
1.895 + if (endParaShared && aEnd.iPhraseElement>0)
1.896 + aEnd.iPhraseElement--; // Due to action of ScanToPosition
1.897 + //
1.898 + RPhraseAttribsEntry* backPhrase=&(*iPhraseIx)[aEnd.iPhraseElement];
1.899 + TInt backLength=backPhrase->Length();
1.900 + if (!(endParaShared || backPhrase->IsPicturePhrase()))
1.901 + backPhrase->SetLength(aEnd.iPhraseElementOffset+1);
1.902 + //
1.903 + RPhraseAttribsEntry* frontPhrase=&(*iPhraseIx)[aStart.iPhraseElement];
1.904 + TInt frontLength=frontPhrase->Length();
1.905 + if (!frontPhrase->IsPicturePhrase()) // Fix length of first phrase.
1.906 + frontPhrase->SetLength(frontLength-aStart.iPhraseElementOffset);
1.907 + TRAPD(ret,
1.908 + ExternalizePhrasesL(aStream,aStart.iPhraseElement,aEnd.iPhraseElement-aStart.iPhraseElement+1,aVirtualTrailingText));
1.909 + //
1.910 + // Now fix the altered phrase lengths.
1.911 + if (!frontPhrase->IsPicturePhrase())
1.912 + frontPhrase->SetLength(frontLength);
1.913 + if (!(endParaShared || backPhrase->IsPicturePhrase()))
1.914 + backPhrase->SetLength(backLength);
1.915 +
1.916 + __TEST_INVARIANT; // we lied about being const
1.917 +
1.918 + User::LeaveIfError(ret);
1.919 + }
1.920 + }
1.921 +
1.922 +
1.923 +void CRichTextIndex::ExternalizePhrasesL(RWriteStream& aStream,TInt aStart,TInt aPhraseCount,
1.924 + const RPhraseAttribsEntry* aVirtualPhrase)const
1.925 +// Save the specified number of phrases present in the phrase index,
1.926 +// starting from phrase offset aStart.
1.927 +//
1.928 + {
1.929 + ExternalizePhraseCountL(aStream,aPhraseCount+ ((aVirtualPhrase)?1:0) );
1.930 + for (TInt phraseItem=aStart;phraseItem<aStart+aPhraseCount;phraseItem++)
1.931 + {
1.932 + RPhraseAttribsEntry& phraseEntry=(*iPhraseIx)[phraseItem];
1.933 + aStream<< phraseEntry;
1.934 + }
1.935 + if (aVirtualPhrase)
1.936 + aStream<< *aVirtualPhrase;
1.937 + }
1.938 +
1.939 +
1.940 +void CRichTextIndex::InternalizePhraseIxL(RReadStream& aStream,const CCharFormatLayer* aGlobalCharFormat)
1.941 +// Load all the phrases from the stream, and insert them into the phrase index
1.942 +//
1.943 + {
1.944 + iPhraseIx->Reset();
1.945 + TInt phraseCount=aStream.ReadInt32L();
1.946 +
1.947 + // Extend phrase index by required amount
1.948 + iPhraseIx->AppendL(RPhraseAttribsEntry(),phraseCount);
1.949 +
1.950 + for (TInt phraseItem=0;phraseItem<phraseCount;phraseItem++)
1.951 + {// Restore each phrase & insert into the phrase index.
1.952 + TBool isPicture=(TBool)aStream.ReadUint8L();
1.953 + TInt phraseLength=aStream.ReadInt32L();
1.954 + CCharFormatLayer* charLayer=CCharFormatLayer::NewL(aStream);
1.955 + charLayer->SetBase(aGlobalCharFormat);
1.956 + RPhraseAttribsEntry& tPhrase=iPhraseIx->At(phraseItem);
1.957 + if (!isPicture)
1.958 + new(&tPhrase) RPhraseAttribsEntry(charLayer,phraseLength);
1.959 + else
1.960 + {// Manufacture new picture header & set its picture store
1.961 + CleanupStack::PushL(charLayer);
1.962 + TPictureHeader hdr;
1.963 + aStream>> hdr;
1.964 + TBool ownershipTaken(EFalse);
1.965 + CPicturePhrase* picPhrase=CPicturePhrase::NewL(hdr,charLayer,ownershipTaken);
1.966 + CleanupStack::Pop(); // char layer
1.967 + new(&tPhrase) RPhraseAttribsEntry(picPhrase);
1.968 + iPictureCount++;
1.969 + }
1.970 + }
1.971 + }
1.972 +
1.973 +
1.974 +CParaAttribs* CRichTextIndex::SharedParaAttribs(TUint8 aOrdinal)
1.975 +// Return the handle of the para attribs in the shared para attribs list,
1.976 +// whose position in the list is specified by the argument aOrdinal.
1.977 +//
1.978 + {
1.979 + CParaAttribs* currentSharedPara;
1.980 + TDblQueIter<CParaAttribs> iterator(iSharedParaQueHead);
1.981 + TInt match=1;
1.982 + while ((currentSharedPara=iterator++)!=NULL && aOrdinal!=match)
1.983 + match++;
1.984 + if (currentSharedPara==NULL)
1.985 + {
1.986 + OstTrace0( TRACE_FATAL, CRICHTEXTINDEX_SHAREDPARAATTRIBS, "EEndOfSharedParaListEncountered" );
1.987 + }
1.988 + __ASSERT_ALWAYS(currentSharedPara!=NULL,Panic(EEndOfSharedParaListEncountered));
1.989 + return currentSharedPara;
1.990 + }
1.991 +
1.992 +
1.993 +TUint8 CRichTextIndex::RefNum(const CParaAttribs* aParaAttribs)const
1.994 +// If the para attribs argument is present in the shared list, return a
1.995 +// reference to it; otherwise return zero as the reference.
1.996 +//
1.997 + {
1.998 + CParaAttribs* currentSharedPara;
1.999 + TDblQueIter<CParaAttribs> iterator(((CRichTextIndex*)this)->iSharedParaQueHead);
1.1000 + TUint8 refNo=1;
1.1001 + while ((currentSharedPara=iterator++)!=NULL)
1.1002 + {
1.1003 + if (currentSharedPara==aParaAttribs)
1.1004 + return refNo;
1.1005 + refNo++;
1.1006 + }
1.1007 + return 0;
1.1008 + }
1.1009 +
1.1010 +//////////////////////////////////////////////////
1.1011 +//////////////////////////////////////////////////
1.1012 +//////////////////////////////////////////////////
1.1013 +
1.1014 +void CRichTextIndex::PasteFromStreamL(const CStreamStore& aStore,RReadStream& aStream,TInt aPos,CParagraphStyle::TStylePasteMode aStylePasteMode,const CParaFormatLayer* aGlobalParaLayer,const CCharFormatLayer* aGlobalCharLayer)
1.1015 +//
1.1016 + {
1.1017 + __TEST_INVARIANT;
1.1018 +
1.1019 + CancelInsertCharFormat();
1.1020 + ScanToPosition(aPos,EScanToPositionAbsolute);
1.1021 +
1.1022 + //
1.1023 + // Get the header
1.1024 + TRtPasteContext context(&aStore,aGlobalParaLayer,aGlobalCharLayer,iText.StyleList());
1.1025 + context.iPastePos=iPos;
1.1026 + context.iStylePasteMode = aStylePasteMode;
1.1027 +
1.1028 + InternalizeRtiHeaderL(aStream,context); // no rollback required on the header. Does not alter iPos.
1.1029 + //
1.1030 + // Get the pargraph styles
1.1031 +
1.1032 + CStyleMap* styleMap = NULL;
1.1033 + if (context.iParagraphStylesFlag)
1.1034 + {
1.1035 + TUint8 styleCount=ReadTUint8CountL(aStream);
1.1036 + styleMap=CStyleMap::NewLC(styleCount);
1.1037 + TRAPD(ret,
1.1038 + PasteStylesL(aStream,*styleMap,context)); // Does not alter iPos.
1.1039 + if (ret!=KErrNone) {RbPasteSharedFormatsL(ret);}
1.1040 + }
1.1041 + //
1.1042 + // Get the shared formats
1.1043 + TUint8 sharedParaCount=ReadTUint8CountL(aStream);
1.1044 + CParaAttribsMap* paraMap=CParaAttribsMap::NewLC(sharedParaCount);
1.1045 + TRAPD(ret,
1.1046 + PasteSharedFormatsL(aStream,*paraMap,context,styleMap)); // Does not alter iPos.
1.1047 + if (ret!=KErrNone)
1.1048 + {
1.1049 + // beginning of fixing DEF 126651 (1/2)
1.1050 + // free orphan object before leave.
1.1051 + if (context.iParagraphStylesFlag)
1.1052 + {
1.1053 + if (!context.iStyleList || context.iStylePasteMode == CParagraphStyle::EConvertNewStyles)
1.1054 + {
1.1055 + TInt maxSize = styleMap->Count();
1.1056 + for (TInt count=0; count<maxSize; count++)
1.1057 + {
1.1058 + delete (CParagraphStyle*)styleMap->At(count).iT;
1.1059 + }
1.1060 + }
1.1061 + CleanupStack::PopAndDestroy(); // cleanup styleMap
1.1062 + }
1.1063 + CleanupStack::PopAndDestroy(); // cleanup paraMap
1.1064 + // end of fixing DEF 126651 (1/2)
1.1065 + RbPasteSharedFormatsL(ret);
1.1066 + }
1.1067 + //
1.1068 + // Get the markup
1.1069 + TRAP(ret,
1.1070 + PasteIxL(aStream,context,*paraMap, styleMap)); // context now has both global layers & pastePos
1.1071 + if (ret!=KErrNone)
1.1072 + {
1.1073 + // beginning of fixing DEF 126651 (2/2)
1.1074 + // free orphan object before leave.
1.1075 + if (context.iParagraphStylesFlag)
1.1076 + {
1.1077 + if (!context.iStyleList || context.iStylePasteMode == CParagraphStyle::EConvertNewStyles)
1.1078 + {
1.1079 + TInt maxSize = styleMap->Count();
1.1080 + for (TInt count=0; count<maxSize; count++)
1.1081 + {
1.1082 + delete (CParagraphStyle*)styleMap->At(count).iT;
1.1083 + }
1.1084 + }
1.1085 + CleanupStack::PopAndDestroy(); // cleanup styleMap
1.1086 + }
1.1087 + CleanupStack::PopAndDestroy(); // cleanup paraMap
1.1088 + // end of fixing DEF 126651 (2/2)
1.1089 + RbPasteSharedFormatsL(ret);
1.1090 + }
1.1091 +
1.1092 +
1.1093 + if (context.iParagraphStylesFlag)
1.1094 + {
1.1095 + TRAP(ret,GenerateAllPhraseLinksL());
1.1096 + if (ret != KErrNone)
1.1097 + RbPasteSharedFormatsL(ret);
1.1098 +
1.1099 + if (!context.iStyleList || context.iStylePasteMode == CParagraphStyle::EConvertNewStyles)
1.1100 + {
1.1101 + TInt maxSize = styleMap->Count();
1.1102 + for (TInt count=0; count<maxSize; count++)
1.1103 + {
1.1104 + delete (CParagraphStyle*)styleMap->At(count).iT;
1.1105 + }
1.1106 + }
1.1107 + CleanupStack::PopAndDestroy(); // cleanup styleMap
1.1108 + }
1.1109 +
1.1110 + CleanupStack::PopAndDestroy(); // cleanup paraMap
1.1111 +
1.1112 + __TEST_INVARIANT;
1.1113 + }
1.1114 +
1.1115 +
1.1116 +void CRichTextIndex::PasteStylesL(RReadStream& aStream,CStyleMap& aMap,const TRtPasteContext& aContext)
1.1117 +// Restore the paragraph styles from the specified stream.
1.1118 +// Restoration is controlled by the flag TStylePasteMode.
1.1119 +//
1.1120 + {
1.1121 +
1.1122 + TInt styleCount=aMap.iCapacity;
1.1123 +// TBool docSupportsStyles = iText.StyleListPresent(); // detect if document has style list
1.1124 + CParagraphStyle* style=NULL;
1.1125 + for(TUint8 ii=0; ii<styleCount; ii++)
1.1126 + {
1.1127 + TInt refNo=aStream.ReadInt8L();
1.1128 + style=CParagraphStyle::NewL(aStream,*aContext.iGlobalParaLayer,*aContext.iGlobalCharLayer);
1.1129 +
1.1130 + // Now attempt to map this style to one in the document we are adding it to
1.1131 + // refNo contains the style number when the selection was cut, which
1.1132 + // is needed to map to the reference no's coming in with the paragraph
1.1133 + // format info
1.1134 +
1.1135 + if (aContext.iStylePasteMode == CParagraphStyle::EIgnoreNewStyles)
1.1136 + // We're ignoring all style info, so delete it now
1.1137 + delete style;
1.1138 + else
1.1139 + {
1.1140 +
1.1141 + if (aContext.iStyleList && aContext.iStylePasteMode == CParagraphStyle::EAddNewStyles)
1.1142 + {
1.1143 + TInt docStyle = iText.StyleList()->IndexByName(style->iName);
1.1144 + if (docStyle!=KErrNotFound)
1.1145 + {
1.1146 + /* Add the existing style into the stylemap */
1.1147 + aMap.Bind(refNo,iText.StyleList()->PtrByName(style->iName)->iStyle);
1.1148 +
1.1149 + /* Since this style exists, we can safely delete this copy */
1.1150 + delete style;
1.1151 +
1.1152 + }
1.1153 + else
1.1154 + {
1.1155 + // Ok, the document doesn't have this style in it.
1.1156 + // So let's add it in, and put a reference in the stylemap
1.1157 +
1.1158 + RParagraphStyleInfo newStyle(style);
1.1159 +
1.1160 + iText.StyleList()->AppendL(&newStyle);
1.1161 +
1.1162 + aMap.Bind(refNo,style);
1.1163 +
1.1164 + // the StyeList takes care of style destruction, so no deletion
1.1165 + // is necessary here
1.1166 + }
1.1167 + }
1.1168 + else
1.1169 + {
1.1170 + // Document doesn't support styles, so save them so they can
1.1171 + // be converted to character specific formatting later on
1.1172 + aMap.Bind(refNo, style);
1.1173 + }
1.1174 + }
1.1175 +
1.1176 + }
1.1177 +}
1.1178 +
1.1179 +
1.1180 +void CRichTextIndex::ImposeCharacterStyleL(CCharFormatLayer** aCharLayer)
1.1181 +{
1.1182 + // This function is used to impose the current character style onto
1.1183 + // the character layer for this paragraph. It's used when translating
1.1184 + // style information into specific formatting when pasting text containing
1.1185 + // styles into text without styles.
1.1186 +
1.1187 + TCharFormatX MergedCharFormat;
1.1188 + TCharFormatXMask MergedCharFormatMask;
1.1189 +
1.1190 + CCharFormatLayer* newCharLayer;
1.1191 +
1.1192 + // Extract the masks from both layers.
1.1193 + // use MergedCharFormat to hold the char info which we don't want yet
1.1194 +
1.1195 + (*aCharLayer)->Sense(MergedCharFormat, MergedCharFormatMask);
1.1196 + iLastCharacterStyle->Sense(MergedCharFormat, MergedCharFormatMask);
1.1197 +
1.1198 + // Re-build charLayer;
1.1199 + CleanupStack::PushL(*aCharLayer);
1.1200 + newCharLayer = CCharFormatLayer::NewL(MergedCharFormat,MergedCharFormatMask);
1.1201 + CleanupStack::Pop(*aCharLayer);
1.1202 +
1.1203 + delete (*aCharLayer);
1.1204 + (*aCharLayer) = newCharLayer;
1.1205 +}
1.1206 +
1.1207 +
1.1208 +void CRichTextIndex::PasteSharedFormatsL(RReadStream& aStream,CParaAttribsMap& aMap,const TRtPasteContext& aContext,CStyleMap* aStyleMap)
1.1209 +// Load shared formats from the specified stream.
1.1210 +// Only adds the loaded shared format to the list of shared formats
1.1211 +// if it does not already exist in that list.
1.1212 +// A map is kept, that for each loaded format specifies its offset within
1.1213 +// the shared list.
1.1214 +//
1.1215 +
1.1216 + {
1.1217 + TInt mapCount=aMap.iCapacity;
1.1218 + for (TUint8 paraItem=0;paraItem<mapCount;paraItem++)
1.1219 + {
1.1220 + TInt refNo=aStream.ReadInt32L();
1.1221 + CParaFormatLayer* paraLayer=PasteParagraphFormatL(aStream,aContext,aStyleMap);
1.1222 + CleanupStack::PushL(paraLayer);
1.1223 +
1.1224 + CCharFormatLayer* charLayer=CCharFormatLayer::NewL(aStream); // Does not restore based on link.
1.1225 +//// Change specific formatting for this paragraph
1.1226 +
1.1227 + if (iLastCharacterStyle != NULL)
1.1228 + ImposeCharacterStyleL(&charLayer);
1.1229 +
1.1230 + charLayer->SetBase(aContext.iGlobalCharLayer);
1.1231 +
1.1232 + CleanupStack::PushL(charLayer);
1.1233 + CParaAttribs* paraAttribs=GetParaAttribsL(paraLayer,charLayer);
1.1234 + CleanupStack::PopAndDestroy(2); // charLayer & paraLayer
1.1235 + aMap.Bind(refNo,paraAttribs);
1.1236 + paraAttribs->iRefCount--;
1.1237 + }
1.1238 + }
1.1239 +
1.1240 +
1.1241 +void CRichTextIndex::PasteIxL(RReadStream& aStream,TRtPasteContext& aContext,const CParaAttribsMap& aMap,CStyleMap* aStyleMap/*,CParaAttribs* aSecondReserved*/)
1.1242 +//
1.1243 + {
1.1244 + TInt completeParaCount=aStream.ReadInt32L();
1.1245 + completeParaCount-=(aContext.iIncompleteParaFlag)? 1 : 0;
1.1246 +// Create rollback states
1.1247 + TParaAttribsEntry para=(*iParaIx)[aContext.iPastePos.iParaElement];
1.1248 + CParaAttribs* reclaimed=RequestReclaimShareL(para.iParaAttribs,¶); // does not release share
1.1249 + iRollbackParaAttribsHandle=NULL;
1.1250 + if (reclaimed)
1.1251 + {
1.1252 + iRollbackParaAttribsHandle=para.iParaAttribs;
1.1253 + CleanupStack::PushL(TCleanupItem(ReleaseOnCleanup,reclaimed));
1.1254 + (*iParaIx)[aContext.iPastePos.iParaElement].iParaAttribs=reclaimed; // Use this reclaimed para attribs
1.1255 + }
1.1256 +// Split the phrase at the paste position, ready to insert clipboard content
1.1257 + TRAPD(ret,
1.1258 + SplitPhraseL(aContext.iPastePos.iDocPos));
1.1259 + if (ret!=KErrNone) {RbPasteParaIxL(aContext.iPastePos,aContext.iParasPasted,ret);}
1.1260 + ScanToPosition(aContext.iPastePos.iDocPos,EScanToPositionAbsolute); // pick up the changes
1.1261 + aContext.iPastePos=iPos;
1.1262 +// Paste all complete paragraphs from the clipboard
1.1263 + TInt characterCount=0;
1.1264 + RPhraseAttribsEntry* firstParaVirtualPhrase=NULL;
1.1265 + TRAP(ret,
1.1266 + characterCount=PasteParaIxL(aStream,aContext,completeParaCount,aMap,firstParaVirtualPhrase,aStyleMap));
1.1267 + if (ret!=KErrNone) {RbPasteParaIxL(aContext.iPastePos,aContext.iParasPasted,ret);}
1.1268 + CleanupStack::PushL(firstParaVirtualPhrase);
1.1269 +// Paste any remaining text fragment.
1.1270 + TTextFragment textFragment;
1.1271 + if (aContext.iIncompleteParaFlag)
1.1272 + {
1.1273 + TRAPD(ret,
1.1274 + textFragment=GetTextFragmentL(aStream));
1.1275 + if (ret!=KErrNone) {RbPasteParaIxL(aContext.iPastePos,aContext.iParasPasted,ret);}
1.1276 + characterCount+=textFragment.iLength;
1.1277 +
1.1278 + // Restore the character stle info for the final text fragment
1.1279 + if (aContext.iParagraphStylesFlag || aContext.iApplyFormatToLastFlag)
1.1280 + {
1.1281 + CParaFormatLayer* paraLayer = PasteParagraphFormatL(aStream, aContext, aStyleMap);
1.1282 + CleanupStack::PushL(paraLayer);
1.1283 + //Restore the paragraph formatting for the final text fragment
1.1284 + if (aContext.iApplyFormatToLastFlag)
1.1285 + {
1.1286 + CParaFormat* paraFormat = CParaFormat::NewLC();
1.1287 + TParaFormatMask mask;
1.1288 + paraLayer->SenseL(paraFormat,mask);
1.1289 + (*iParaIx)[completeParaCount].iParaAttribs->iParaFormat->SetL(paraFormat,mask);
1.1290 + CleanupStack::PopAndDestroy(paraFormat);
1.1291 + }
1.1292 + // We can now discard the format layer, but the character format has been safely
1.1293 + // patched to the style character format
1.1294 + CleanupStack::PopAndDestroy(paraLayer);
1.1295 + }
1.1296 + }
1.1297 +//
1.1298 + TRAP(ret,
1.1299 + PastePhraseIxL(aStream,aContext,firstParaVirtualPhrase));
1.1300 + if (ret!=KErrNone) {RbPasteParaIxL(aContext.iPastePos,aContext.iParasPasted,ret);}
1.1301 + CleanupStack::PopAndDestroy(); // firstParaVirtualPhrase / shallow destroy only - deep copy in phraseIx
1.1302 +
1.1303 +// ScanToPosition(aContext.iPastePos.iDocPos,EScanToPositionAbsolute); // phraseIx not pasted at this point
1.1304 +// TLogicalPosition headParaNormalizePos=iPos;
1.1305 +
1.1306 +
1.1307 + if (completeParaCount==0)
1.1308 + {// Adjust paragraph length & phrase count
1.1309 + TParaAttribsEntry* para=&(*iParaIx)[aContext.iPastePos.iParaElement];
1.1310 + para->iLength+=textFragment.iLength;
1.1311 + para->iParaAttribs->iPhraseCount+=textFragment.iPhraseCount;
1.1312 + ScanToPosition(aContext.iPastePos.iDocPos,EScanToPositionAbsolute);
1.1313 + TLogicalPosition headParaNormalizePos=iPos;
1.1314 + MergePhrases(headParaNormalizePos);
1.1315 + MergePhrases(aContext.iPastePos.iDocPos+characterCount);
1.1316 + DoPasteCleanup(headParaNormalizePos,reclaimed);
1.1317 + }
1.1318 + else
1.1319 + {// Adjust paragraph lengths & phrase counts
1.1320 + TParaAttribsEntry* firstPara=&(*iParaIx)[aContext.iPastePos.iParaElement];
1.1321 + firstPara->iLength+=aContext.iPastePos.iParaElementOffset; // Update length of the first para
1.1322 + firstPara->iParaAttribs->iPhraseCount+=(aContext.iPastePos.iPhraseElement-aContext.iPastePos.iParaBasePhraseElement); // Update the phrase count of the first para attribs
1.1323 + ScanToPosition(aContext.iPastePos.iDocPos,EScanToPositionAbsolute);
1.1324 + TLogicalPosition headParaNormalizePos=iPos;
1.1325 + MergePhrases(headParaNormalizePos);
1.1326 + DoPasteCleanup(headParaNormalizePos,reclaimed);
1.1327 + //
1.1328 + // Adjust the length & phrase count of the new final paragraph
1.1329 + TParaAttribsEntry* lastPara=&(*iParaIx)[aContext.iPastePos.iParaElement+completeParaCount];
1.1330 + lastPara->iLength=(lastPara->iLength-aContext.iPastePos.iParaElementOffset)+textFragment.iLength;
1.1331 + lastPara->iParaAttribs->iPhraseCount-=(aContext.iPastePos.iPhraseElement-aContext.iPastePos.iParaBasePhraseElement);
1.1332 + // phrase count may be wrong - since the added phrase may have been merged into the current one.
1.1333 + // Cant just add these phrases.
1.1334 + lastPara->iParaAttribs->iPhraseCount+=textFragment.iPhraseCount;
1.1335 + ScanToPosition(aContext.iPastePos.iDocPos+characterCount,EScanToPositionAbsolute);
1.1336 + MergePhrases(iPos);
1.1337 + DoPasteCleanup(iPos,(CParaAttribs*)NULL);
1.1338 + }
1.1339 + RebalanceIndex();
1.1340 + NormalizeSharedList();
1.1341 + }
1.1342 +
1.1343 +
1.1344 +void CRichTextIndex::DoPasteCleanup(TLogicalPosition& aNormalizePos,CParaAttribs* aReclaimed)
1.1345 +//
1.1346 + {
1.1347 + NormalizeNow(aNormalizePos);
1.1348 + if (aReclaimed)
1.1349 + CleanupStack::Pop();
1.1350 + }
1.1351 +
1.1352 +
1.1353 +TInt CRichTextIndex::PasteParaIxL(RReadStream& aStream,TRtPasteContext& aContext,TInt aCompleteParaCount,const CParaAttribsMap& aMap,RPhraseAttribsEntry*& aFirstParaVirtualPhrase, CStyleMap* aStyleMap)
1.1354 +//
1.1355 + {
1.1356 + TParaAttribsEntry para;
1.1357 + iParaIx->InsertL(aContext.iPastePos.iParaElement,para,aCompleteParaCount);
1.1358 + aContext.iParasPasted=aCompleteParaCount;
1.1359 + TInt characterCount=0;
1.1360 + if (aCompleteParaCount>0)
1.1361 + {
1.1362 + para=DoPasteFirstIntoParaL(aStream,aMap,aContext,aFirstParaVirtualPhrase, aStyleMap);
1.1363 + TInt paraItem=0;
1.1364 + (*iParaIx)[aContext.iPastePos.iParaElement+paraItem]=para;
1.1365 + characterCount+=para.iLength;
1.1366 + }
1.1367 + CleanupStack::PushL(TCleanupItem(DiscardPhraseOnCleanup,aFirstParaVirtualPhrase));
1.1368 + for (TInt paraItem=1;paraItem<aCompleteParaCount;paraItem++)
1.1369 + {// Paste all the paras that have paragraph delimiters.
1.1370 + para=DoPasteIntoParaL(aStream,aMap,aContext,aStyleMap);
1.1371 + (*iParaIx)[aContext.iPastePos.iParaElement+paraItem]=para;
1.1372 + characterCount+=para.iLength;
1.1373 + }
1.1374 + CleanupStack::Pop(); // firstParaVirtualPhrase
1.1375 +// ASSERT: At this point we have pasted all paras that were in the stream.
1.1376 + if (aContext.iParasPasted!=aCompleteParaCount)
1.1377 + {
1.1378 + OstTrace0( TRACE_DUMP, CRICHTEXTINDEX_PASTEPARAIXL, "EPasteParaIxError" );
1.1379 + }
1.1380 + __ASSERT_DEBUG(aContext.iParasPasted==aCompleteParaCount,Panic(EPasteParaIxError));
1.1381 + return characterCount;
1.1382 + }
1.1383 +
1.1384 +
1.1385 +TParaAttribsEntry CRichTextIndex::DoPasteFirstIntoParaL(RReadStream& aStream,const CParaAttribsMap& aMap,const TRtPasteContext& aContext,RPhraseAttribsEntry*& aFirstParaVirtualPhrase,CStyleMap* aStyleMap)
1.1386 +//
1.1387 + {
1.1388 + TParaAttribsEntry para;
1.1389 + para.iLength=aStream.ReadInt32L();
1.1390 + TUint8 refNo=aStream.ReadUint8L();
1.1391 + if (refNo>0)
1.1392 + {// This is the first pasted para, so if shared, must convert to phrase on the fly.
1.1393 + CParaAttribs* paraAttribs=aMap.Item(refNo);
1.1394 + CParaAttribs* specificParaAttribs=CParaAttribs::NewL(paraAttribs->iParaFormat);
1.1395 + CleanupStack::PushL(TCleanupItem(ReleaseOnCleanup,specificParaAttribs));
1.1396 + //
1.1397 + CCharFormatLayer* layer=CCharFormatLayer::NewCopyBaseL(paraAttribs->iCharFormat);
1.1398 + CleanupStack::PushL(layer);
1.1399 + aFirstParaVirtualPhrase=new(ELeave) RPhraseAttribsEntry(layer,para.iLength);
1.1400 + CleanupStack::Pop(2); // layer & specificParaAttribs
1.1401 + //
1.1402 + para.iParaAttribs=specificParaAttribs;
1.1403 + if (para.iParaAttribs==NULL)
1.1404 + {
1.1405 + OstTrace0( TRACE_FATAL, CRICHTEXTINDEX_DOPASTEFIRSTINTOPARAL, "ESharedFormatsMapIntegrityError" );
1.1406 + }
1.1407 + __ASSERT_ALWAYS(para.iParaAttribs!=NULL,Panic(ESharedFormatsMapIntegrityError));
1.1408 + }
1.1409 + else
1.1410 + {// Have to build up the specific para attribs
1.1411 + CParaFormatLayer* paraLayer=PasteParagraphFormatL(aStream,aContext,aStyleMap);
1.1412 + CleanupStack::PushL(paraLayer);
1.1413 + TInt phraseCount=aStream.ReadInt32L(); // specific phrase count
1.1414 + CParaAttribs* specificParaAttribs=CParaAttribs::NewL(paraLayer);
1.1415 + specificParaAttribs->iPhraseCount=phraseCount;
1.1416 + para.iParaAttribs=specificParaAttribs;
1.1417 + CleanupStack::PopAndDestroy(); // a copy of paraLayer is taken!
1.1418 + }
1.1419 + return para;
1.1420 + }
1.1421 +
1.1422 +
1.1423 +TParaAttribsEntry CRichTextIndex::DoPasteIntoParaL(RReadStream& aStream,const CParaAttribsMap& aMap,const TRtPasteContext& aContext,CStyleMap* aStyleMap)
1.1424 +//
1.1425 + {
1.1426 + TParaAttribsEntry para;
1.1427 + para.iLength=aStream.ReadInt32L();
1.1428 + TUint8 refNo=aStream.ReadUint8L();
1.1429 + if (refNo>0)
1.1430 + {// Link to para attribs in shared list & up its reference count
1.1431 + para.iParaAttribs=aMap.Item(refNo);
1.1432 + if (para.iParaAttribs==NULL)
1.1433 + {
1.1434 + OstTrace0( TRACE_FATAL, CRICHTEXTINDEX_DOPASTEINTOPARAL, "ESharedFormatsMapIntegrityError" );
1.1435 + }
1.1436 + __ASSERT_ALWAYS(para.iParaAttribs!=NULL,Panic(ESharedFormatsMapIntegrityError));
1.1437 + para.iParaAttribs->iRefCount++;
1.1438 + }
1.1439 + else
1.1440 + {// Have to build up the specific para attribs
1.1441 + CParaFormatLayer* paraLayer=PasteParagraphFormatL(aStream,aContext,aStyleMap);
1.1442 + CleanupStack::PushL(paraLayer);
1.1443 + TInt phraseCount=aStream.ReadInt32L(); // specific phrase count
1.1444 + CParaAttribs* specificParaAttribs=CParaAttribs::NewL(paraLayer);
1.1445 + specificParaAttribs->iPhraseCount=phraseCount;
1.1446 + para.iParaAttribs=specificParaAttribs;
1.1447 + CleanupStack::PopAndDestroy(); // a copy of paraLayer is taken!
1.1448 + }
1.1449 + return para;
1.1450 + }
1.1451 +
1.1452 +
1.1453 +TTextFragment CRichTextIndex::GetTextFragmentL(RReadStream& aStream)
1.1454 +//
1.1455 + {
1.1456 + TTextFragment textFragment;
1.1457 + textFragment.iLength=aStream.ReadInt32L();
1.1458 + textFragment.iPhraseCount=aStream.ReadInt32L();
1.1459 + return textFragment;
1.1460 + }
1.1461 +
1.1462 +
1.1463 +void CRichTextIndex::PastePhraseIxL(RReadStream& aStream,TRtPasteContext& aContext,const RPhraseAttribsEntry* aFirstParaVirtualPhrase)
1.1464 +// The character position to paste at should now fall on a phrase boundary.
1.1465 +//
1.1466 + {
1.1467 +// ASSERT: Having pasted the paraIx, the para containig pastePos has had the containing phrase split at that point.
1.1468 + if (aContext.iPastePos.iPhraseElementOffset!=0)
1.1469 + {
1.1470 + OstTrace0( TRACE_FATAL, CRICHTEXTINDEX_PASTEPHRASEIXL, "EPastePhraseIxErr" );
1.1471 + }
1.1472 + __ASSERT_ALWAYS(aContext.iPastePos.iPhraseElementOffset==0,Panic(EPastePhraseIxErr));
1.1473 +
1.1474 + TInt offset=0;
1.1475 + TInt phraseCount=aStream.ReadInt32L(); // leave caught by calling function. No state change yet.
1.1476 + if (aFirstParaVirtualPhrase)
1.1477 + {
1.1478 + iPhraseIx->InsertL(aContext.iPastePos.iPhraseElement,*aFirstParaVirtualPhrase);
1.1479 + offset++;
1.1480 + }
1.1481 + RPhraseAttribsEntry holdingPhrase;
1.1482 + iPhraseIx->InsertL(aContext.iPastePos.iPhraseElement+offset,holdingPhrase,phraseCount);
1.1483 + for (TInt phraseItem=0;phraseItem<phraseCount;phraseItem++)
1.1484 + {// Restore each phrase & insert into the phrase index.
1.1485 + RPhraseAttribsEntry phrase;
1.1486 + TRAPD(ret,
1.1487 +// phrase=DoPastePhraseL(aStream,aContext)); // !! delete this if the code works
1.1488 + DoPastePhraseL(aStream,aContext,phrase));
1.1489 + if (ret!=KErrNone) {RbPastePhraseIxL(aContext.iPastePos,phraseCount+offset,ret);}
1.1490 + (*iPhraseIx)[aContext.iPastePos.iPhraseElement+phraseItem+offset]=phrase;
1.1491 + if (phrase.IsPicturePhrase() && iText.PictureFactory())
1.1492 + iPictureCount++;
1.1493 + }
1.1494 + }
1.1495 +
1.1496 +
1.1497 +void CRichTextIndex::DoPastePhraseL(RReadStream& aStream,const TRtPasteContext& aContext,RPhraseAttribsEntry& aPhrase)
1.1498 +//
1.1499 + {
1.1500 + TBool isPicture=(TBool)aStream.ReadUint8L();
1.1501 + TInt phraseLength=aStream.ReadInt32L();
1.1502 +
1.1503 + if (!(isPicture && phraseLength==1 || !isPicture))
1.1504 + {
1.1505 + OstTrace0( TRACE_FATAL, CRICHTEXTINDEX_DOPASTEPHRASEL, "KErrCorrupt" );
1.1506 + }
1.1507 + __ASSERT_ALWAYS(isPicture && phraseLength==1 || !isPicture,User::Leave(KErrCorrupt));
1.1508 +
1.1509 + CCharFormatLayer* charLayer=CCharFormatLayer::NewL(aStream);
1.1510 +/// Change this character format if style formatting is to be applied
1.1511 +
1.1512 +// Paste style for the trailing text
1.1513 + if (iLastCharacterStyle != NULL)
1.1514 + ImposeCharacterStyleL(&charLayer);
1.1515 +
1.1516 + charLayer->SetBase(aContext.iGlobalCharLayer);
1.1517 +
1.1518 + CPicturePhrase* picPhrase=NULL;
1.1519 + const MPictureFactory* factory=iText.PictureFactory();
1.1520 + TBool pictureLoadError=EFalse;
1.1521 + if (isPicture)
1.1522 + {
1.1523 + TPictureHeader hdr;
1.1524 + aStream>> hdr; // hdr.iPicture always references a picture in the deferred store.
1.1525 + if (isPicture && factory)
1.1526 + {// Manufacture new picture phrase & set its picture store
1.1527 + CleanupStack::PushL(charLayer);
1.1528 + TBool ownershipTaken(EFalse);
1.1529 + picPhrase=CPicturePhrase::NewL(hdr,charLayer,ownershipTaken);
1.1530 + CleanupStack::Pop(); // charLayer - picPhrase takes ownership
1.1531 + CleanupStack::PushL(picPhrase);
1.1532 + TRAPD(r,factory->NewPictureL(hdr,*aContext.iStore)); // load picture since clipboard store is transient.
1.1533 + // r=KErrNotSupported // we don't recognise the picture type
1.1534 + if (r==KErrNone)
1.1535 + {
1.1536 + picPhrase->iPicHdr.iPicture=hdr.iPicture; // make picPhrase point at the restored picture object.
1.1537 + TRAP(r,
1.1538 + hdr.iPicture->DetachFromStoreL(CPicture::EDetachFull)); // recurse the call to detach the picture from the store
1.1539 + }
1.1540 + switch (r)
1.1541 + {
1.1542 + case(KErrNone):
1.1543 + break;
1.1544 + default:
1.1545 + pictureLoadError=ETrue;
1.1546 + picPhrase->iCharFormat=NULL;
1.1547 + CleanupStack::PopAndDestroy(picPhrase);
1.1548 + if (r!=KErrNotSupported)
1.1549 + {
1.1550 + OstTrace1( TRACE_FATAL, DUP2_CRICHTEXTINDEX_DOPASTEPHRASEL, "Leave code=%d", r );
1.1551 + User::Leave(r);
1.1552 + }
1.1553 + }
1.1554 + }
1.1555 + }
1.1556 + if (isPicture && factory && !pictureLoadError)
1.1557 + new(&aPhrase) RPhraseAttribsEntry(picPhrase);
1.1558 + else
1.1559 + new(&aPhrase) RPhraseAttribsEntry(charLayer,phraseLength);
1.1560 +
1.1561 + // The ownership has been transfered to RPhraseAttribsEntry
1.1562 + if(picPhrase)
1.1563 + CleanupStack::Pop(picPhrase);
1.1564 + }
1.1565 +
1.1566 +
1.1567 +TUint8 CRichTextIndex::ReadTUint8CountL(RReadStream& aStream)const
1.1568 + {return aStream.ReadUint8L();}
1.1569 +
1.1570 +
1.1571 +void CRichTextIndex::RbPasteSharedFormatsL(TInt aRet)
1.1572 +// For each para attribs that has been read in, release all shares on it, if it
1.1573 +// does not already exist in shared list.
1.1574 +//
1.1575 + {
1.1576 + NormalizeSharedList();
1.1577 + OstTrace1( TRACE_FATAL, CRICHTEXTINDEX_RBPASTESHAREDFORMATSL, "Leave code=%d", aRet );
1.1578 + User::Leave(aRet);
1.1579 + }
1.1580 +
1.1581 +
1.1582 +void CRichTextIndex::NormalizeSharedList()
1.1583 +// Removes unreferenced (non-shared) shared paras from the shared list.
1.1584 +// Called in rollback situations.
1.1585 +// Also called naturally following a paste, since an incoming shared para
1.1586 +// may be pasted into an existing para, making it non-shared.
1.1587 +//
1.1588 + {
1.1589 + CParaAttribs* currentSharedPara=NULL;
1.1590 + TDblQueIter<CParaAttribs> iterator(iSharedParaQueHead);
1.1591 + while ((currentSharedPara=iterator++)!=NULL)
1.1592 + {// Rollback the shared list.
1.1593 + if (currentSharedPara->iRefCount==0)
1.1594 + {// Remove this unreferenced item from the shared list.
1.1595 + currentSharedPara->iRefCount=1;
1.1596 + currentSharedPara->Release();
1.1597 + }
1.1598 + }
1.1599 + }
1.1600 +
1.1601 +
1.1602 +void CRichTextIndex::RbRemoveInsertedParaAttribsEntries(TInt aFirstParaInsertPos,TInt aInsertedParaCount)
1.1603 +// Rollback on leaving part way through inserting paragraph records into the para index.
1.1604 +// For all pasted paragraph records, release their share on their paraAttribs if present.
1.1605 +//
1.1606 + {
1.1607 + for (TInt ii=0;ii<aInsertedParaCount;ii++)
1.1608 + {
1.1609 + CParaAttribs* paraAttribs=(*iParaIx)[aFirstParaInsertPos+ii].iParaAttribs;
1.1610 + if (paraAttribs)
1.1611 + paraAttribs->Release();
1.1612 + }
1.1613 + iParaIx->Delete(aFirstParaInsertPos,aInsertedParaCount);
1.1614 + }
1.1615 +
1.1616 +
1.1617 +void CRichTextIndex::RbPasteParaIxL(const TLogicalPosition& aPos,TInt aParasPasted,TInt aRet)
1.1618 +// Rollback on leaving part way through the pasting of the para index.
1.1619 +// For all pasted paras, release their share on their paraAttribs.
1.1620 +//
1.1621 + {
1.1622 + RbRemoveInsertedParaAttribsEntries(aPos.iParaElement,aParasPasted);
1.1623 + MergePhrases(aPos.iDocPos); // updates iPos to paste pos.
1.1624 + //
1.1625 + //
1.1626 + if (iRollbackParaAttribsHandle)
1.1627 + {
1.1628 + RemoveFromPhraseIx(iPos.iPhraseElement,1); // Removes the phrase created from ResquestReclaim on para
1.1629 + (*iParaIx)[aPos.iParaElement].iParaAttribs=iRollbackParaAttribsHandle;
1.1630 + iRollbackParaAttribsHandle=NULL;
1.1631 + }
1.1632 + OstTrace1( TRACE_FATAL, CRICHTEXTINDEX_RBPASTEPARAIXL, "Leave code=%d", aRet );
1.1633 + User::Leave(aRet);
1.1634 + }
1.1635 +
1.1636 +
1.1637 +void CRichTextIndex::RbRemoveInsertedPhraseAttribsEntries(TInt aFirstPhraseInsertPos,TInt aInsertedPhraseCount)
1.1638 +// Rollback on leaving part way through the pasting of the phrase index.
1.1639 +// For all pasted phrases, discard their components.
1.1640 +//
1.1641 + {
1.1642 + for (TInt ii=0;ii<aInsertedPhraseCount;ii++)
1.1643 + {
1.1644 + RPhraseAttribsEntry& phrase=(*iPhraseIx)[aFirstPhraseInsertPos+ii];
1.1645 + if (phrase.IsPicturePhrase())
1.1646 + iPictureCount--;
1.1647 + if (phrase.CharFormat())
1.1648 + phrase.Discard();
1.1649 + }
1.1650 + iPhraseIx->Delete(aFirstPhraseInsertPos,aInsertedPhraseCount);
1.1651 + }
1.1652 +
1.1653 +
1.1654 +void CRichTextIndex::RbPastePhraseIxL(const TLogicalPosition& aPos,TInt aPhraseCount,TInt aRet)
1.1655 +// Rollback on leaving part way through the pasting of the phrase index.
1.1656 +// For all pasted phrases, discard their components.
1.1657 +//
1.1658 + {
1.1659 + RbRemoveInsertedPhraseAttribsEntries(aPos.iPhraseElement,aPhraseCount);
1.1660 + OstTrace1( TRACE_FATAL, CRICHTEXTINDEX_RBPASTEPHRASEIXL, "Leave code=%d", aRet );
1.1661 + User::Leave(aRet);
1.1662 + }