diff -r b9ad20498fb4 -r 8b9155204a54 textrendering/texthandling/ttext/TRTCUSTM.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/textrendering/texthandling/ttext/TRTCUSTM.CPP Fri Jun 04 10:37:54 2010 +0100 @@ -0,0 +1,903 @@ +/* +* Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + + +#include +#include +#include "TXTMRTSR.H" +#include +#include +#include +#include +#include +#include +#include +#include + +GLDEF_C RTest test(_L("TRTCUSTM")); +LOCAL_D RFs theFs; +LOCAL_D CFileStore* TheStore; +LOCAL_D CParaFormatLayer* GlobalParaFormatLayer; +LOCAL_D CCharFormatLayer* GlobalCharFormatLayer; +LOCAL_D CTrapCleanup* TheTrapCleanup; +const TInt KTestCleanupStack=0x500; + + +class TStoreResolver : public MRichTextStoreResolver + { +public: + virtual const CStreamStore& StreamStoreL(TInt /*aPos*/)const {return *iStore;} +public: + CStreamStore* iStore; + }; + + +//////////////////////////////////////////////////////////////////////////////////////////// +class TTestFieldFactory : public MTextFieldFactory + { +public: + // from MTextFieldFactory + virtual CTextField* NewFieldL(TUid aFieldType); + // Creates a field of the type specified + // Returns NULL if it does not recognise/support the field type + }; + +CTextField* TTestFieldFactory::NewFieldL(TUid aFieldType) +// Creates a field (in aHeader) of the type specified in aHeader +// + { + CTextField* field=NULL; + if (aFieldType==KDateTimeFieldUid) + field = (CTextField*)new(ELeave) CDateTimeField(); + return field; + } +///////////////////////////////////////////////////////////////////////////////////////////// + +LOCAL_D void WriteInlineL(RWriteStream& aStream,CRichText* aRichText) + { + aRichText->CancelInsertCharFormat(); + aRichText->ExternalizeFieldDataL(aStream); + aRichText->ExternalizeStyleDataL(aStream); + TBool hasMarkupData=aRichText->HasMarkupData(); + aStream.WriteUint8L((TUint8)hasMarkupData!=EFalse); + if (hasMarkupData) + aRichText->ExternalizeMarkupDataL(aStream); + aRichText->ExternalizePlainTextL(aStream); + } + +LOCAL_D void ReadInlineL(RReadStream& aStream,CRichText* aRichText) + { + aRichText->InternalizeFieldDataL(aStream); + aRichText->InternalizeStyleDataL(aStream); + TBool hasMarkupData=(TBool)aStream.ReadUint8L(); + if (hasMarkupData) + aRichText->InternalizeMarkupDataL(aStream); + aRichText->InternalizePlainTextL(aStream); + } + + +LOCAL_D TStreamId PerformSaveL(CRichText* aRichText) +// + { + RStoreWriteStream out; + TStreamId id1=out.CreateLC(*TheStore); + WriteInlineL(out,aRichText); + delete aRichText; + out.CommitL(); + CleanupStack::PopAndDestroy(); // out + TheStore->CommitL(); + return id1; + } + + +LOCAL_C CRichText* PerformLoadL(TStreamId aId) +// + { + CRichText* text=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer); + RStoreReadStream in; + in.OpenLC(*TheStore,aId); + TRAPD(ret, + ReadInlineL(in,text)); + test(ret==KErrNone); + CleanupStack::PopAndDestroy(); // in + return text; + } + + +LOCAL_C CStyleList* CreatePopulatedStyleList() +// + { + // + // Create style aswell. + CStyleList* list=CStyleList::NewL(); + CParagraphStyle* style1=CParagraphStyle::NewL(*GlobalParaFormatLayer,*GlobalCharFormatLayer); + CParagraphStyle* style2=CParagraphStyle::NewL(*GlobalParaFormatLayer,*GlobalCharFormatLayer); + CParagraphStyle* style3=CParagraphStyle::NewL(*GlobalParaFormatLayer,*GlobalCharFormatLayer); + RParagraphStyleInfo info1(style1); + RParagraphStyleInfo info2(style2); + RParagraphStyleInfo info3(style3); + list->AppendL(&info1); + list->AppendL(&info2); + list->AppendL(&info3); + return list; + } + +_LIT(KTRtCustOutputFile,"c:\\etext\\TRTCUSTM.DAT"); + +LOCAL_C void CustomLoadSave() + { +// Set up the framework + theFs.Delete(KTRtCustOutputFile); + theFs.MkDirAll(KTRtCustOutputFile); + TheStore=CPermanentFileStore::CreateLC(theFs,KTRtCustOutputFile,EFileRead|EFileWrite); + TheStore->SetTypeL(TheStore->Layout()); + +// +// Case (1) Rich text with owned style list. - no markup data +// + test.Start(_L("RT + no markup + style list owned")); + // + // Setup the rich text + CStyleList* list=CreatePopulatedStyleList(); + CRichText* richText1=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer,*list); + TBool hasMarkupData=richText1->HasMarkupData(); + test(hasMarkupData); + richText1->InsertL(0,_L("hello")); + richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter); + richText1->InsertL(richText1->DocumentLength(),_L("there")); + // + // Save the rich text + TStreamId id1=PerformSaveL(richText1); + // + // Load the rich text + CRichText* empty=NULL; + TRAPD(ret, + empty=PerformLoadL(id1)); + test(ret==KErrNone); + hasMarkupData=empty->HasMarkupData(); + test(hasMarkupData); + delete empty; + empty=NULL; +// +// Case (2) Rich text with referenced style list. - no markup data +// + test.Next(_L("RT + no markup + style list externally owned")); + // + // Setup the rich text + list=CreatePopulatedStyleList(); + richText1=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer,*list,CEditableText::ESegmentedStorage,2); + richText1->SetStyleListExternallyOwned(ETrue); + hasMarkupData=richText1->HasMarkupData(); + test(!hasMarkupData); + richText1->InsertL(0,_L("hello")); + richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter); + richText1->InsertL(richText1->DocumentLength(),_L("there")); + richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter); + hasMarkupData=richText1->HasMarkupData(); + test(!hasMarkupData); + // + // Save the rich text + id1=PerformSaveL(richText1); + // + // Load the rich text + empty=PerformLoadL(id1); + hasMarkupData=empty->HasMarkupData(); + test(!hasMarkupData); + TInt paragraphCount=empty->ParagraphCount(); + test(paragraphCount==3); + test(list->Count()==3); // the style list is now externally owned. + delete empty; + test(list->Count()==3); // the style list should not have been destroyed by the rich text + delete list; + empty=NULL; +// +// Case (3) Rich text with referenced style list. - with markup +// + test.Next(_L("RT + markup + style list externally owned")); + // Setup the rich text + list=CreatePopulatedStyleList(); + richText1=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer,*list); + richText1->SetStyleListExternallyOwned(ETrue); + hasMarkupData=richText1->HasMarkupData(); + test(!hasMarkupData); + richText1->InsertL(0,_L("hello")); + richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter); + richText1->InsertL(richText1->DocumentLength(),_L("there")); + richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter); + CParaFormat* paraFormat=CParaFormat::NewLC(); + TParaFormatMask paraMask; + paraFormat->iHorizontalAlignment=CParaFormat::ERightAlign; + paraMask.SetAttrib(EAttAlignment); + richText1->ApplyParaFormatL(paraFormat,paraMask,8,0); + CleanupStack::PopAndDestroy(); // paraFormat + hasMarkupData=richText1->HasMarkupData(); + test(hasMarkupData); + // + // Save the rich text + id1=PerformSaveL(richText1); + // + // Load the rich text + empty=PerformLoadL(id1); + hasMarkupData=empty->HasMarkupData(); + test(hasMarkupData); + paragraphCount=empty->ParagraphCount(); + test(paragraphCount==3); + test(list->Count()==3); // the style list is now externally owned. + delete empty; + test(list->Count()==3); // the style list should not have been destroyed by the rich text + delete list; + empty=NULL; +// +// Case (4) Rich text with no style list. - no effective markup +// + test.Next(_L("RT + delete picture + no style list")); + // Setup the rich text + richText1=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer); + hasMarkupData=richText1->HasMarkupData(); + test(!hasMarkupData); + richText1->InsertL(0,_L("hello")); + richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter); + richText1->InsertL(richText1->DocumentLength(),_L("there")); + richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter); + // + // Create & insert a picture + CXzePicture* pic1=CXzePicture::NewL('o'); + TPictureHeader header1; + TSize size; + pic1->GetSizeInTwips(size); + header1.iPictureType=KUidXzePictureType; + header1.iPicture=pic1; + header1.iSize=size; + richText1->InsertL(3,header1); + hasMarkupData=richText1->HasMarkupData(); + test(hasMarkupData); + richText1->DeleteL(3,1); + hasMarkupData=richText1->HasMarkupData(); + test(!hasMarkupData); + // + // Save the rich text + id1=PerformSaveL(richText1); + // + // Load the rich text + empty=PerformLoadL(id1); + hasMarkupData=empty->HasMarkupData(); + test(!hasMarkupData); + paragraphCount=empty->ParagraphCount(); + test(paragraphCount==3); + delete empty; + empty=NULL; +// +// Case (5) Rich text with SetInsertCharFormat() +// + test.Next(_L("RT + SetInsertCharFormatL()")); + // Setup the rich text + richText1=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer); + hasMarkupData=richText1->HasMarkupData(); + test(!hasMarkupData); + richText1->InsertL(0,_L("hello")); + richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter); + richText1->InsertL(richText1->DocumentLength(),_L("there")); + richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter); + TCharFormat charFormat; + TCharFormatMask charMask; + charFormat.iFontPresentation.iStrikethrough=EStrikethroughOn; + charMask.SetAttrib(EAttFontStrikethrough); + richText1->SetInsertCharFormatL(charFormat,charMask,3); + hasMarkupData=richText1->HasMarkupData(); + test(hasMarkupData); + // + // Save the rich text + id1=PerformSaveL(richText1); + // + // Load the rich text + empty=PerformLoadL(id1); + hasMarkupData=empty->HasMarkupData(); + test(!hasMarkupData); + paragraphCount=empty->ParagraphCount(); + test(paragraphCount==3); + delete empty; + empty=NULL; +// +// Case (6) Rich text with components - default re/store used. +// + + test.Next(_L("RT + components")); + // Setup the rich text + richText1=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer); + hasMarkupData=richText1->HasMarkupData(); + test(!hasMarkupData); + richText1->InsertL(0,_L("hello")); + richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter); + richText1->InsertL(richText1->DocumentLength(),_L("there")); + richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter); + // + // Create & insert some fields + TTestFieldFactory factory; + richText1->SetFieldFactory(&factory); + CTextField* field=NULL; + CTextField* field2=NULL; + TRAP(ret, + field=factory.NewFieldL(KDateTimeFieldUid)); test(ret==KErrNone); + TRAP(ret, + field2=factory.NewFieldL(KDateTimeFieldUid)); test(ret==KErrNone); + TRAP(ret, + richText1->InsertFieldL(0,field,KDateTimeFieldUid)); test(ret==KErrNone); + TRAP(ret, + richText1->UpdateFieldL(0)); + test(ret==KErrNone); + TRAP(ret, + richText1->InsertFieldL(0,field2,KDateTimeFieldUid)); + test(ret==KErrNone); + TRAP(ret, + richText1->UpdateFieldL(0)); + test(ret==KErrNone); + // + // Create & insert a picture + pic1=CXzePicture::NewL('o'); + pic1->GetSizeInTwips(size); + header1.iPictureType=KUidXzePictureType; + header1.iPicture=pic1; + header1.iSize=size; + richText1->InsertL(0,header1); + hasMarkupData=richText1->HasMarkupData(); + test(hasMarkupData); + // + // Save the rich text + TStreamId head=richText1->StoreL(*TheStore); + delete richText1; + // + // Load the rich text + empty=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer); + empty->SetFieldFactory(&factory); + empty->RestoreL(*TheStore,head); + // + // Create the correct factories + TStoreResolver storeResolver; + storeResolver.iStore=TheStore; + MDemPictureFactory* pictureFactory=new(ELeave) MDemPictureFactory; + + empty->SetPictureFactory(pictureFactory,&storeResolver); + CXzePicture* rPic=(CXzePicture*)empty->PictureHandleL(0); + test(rPic->iLabel=='o'); + // + hasMarkupData=empty->HasMarkupData(); + test(hasMarkupData); + paragraphCount=empty->ParagraphCount(); + test(paragraphCount==3); + delete empty; + empty=NULL; + delete pictureFactory; +// +// Case (7) Rich text with fields with referenced style list with markup +// + test.Next(_L("RT + fields + markup + style list")); + // Setup the rich text + list=CreatePopulatedStyleList(); + richText1=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer,*list); + hasMarkupData=richText1->HasMarkupData(); + test(hasMarkupData); + richText1->InsertL(0,_L("hello")); + richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter); + richText1->InsertL(richText1->DocumentLength(),_L("there")); + richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter); + paraFormat=CParaFormat::NewLC(); + paraMask.ClearAll(); + paraFormat->iHorizontalAlignment=CParaFormat::ERightAlign; + paraMask.SetAttrib(EAttAlignment); + richText1->ApplyParaFormatL(paraFormat,paraMask,8,0); + CleanupStack::PopAndDestroy(); // paraFormat + hasMarkupData=richText1->HasMarkupData(); + test(hasMarkupData); + // + // Now add a text field to this. + richText1->SetFieldFactory(&factory); + field=NULL; + TRAP(ret, + field=factory.NewFieldL(KDateTimeFieldUid)); + test(ret==KErrNone); + TRAP(ret, + richText1->InsertFieldL(0,field,KDateTimeFieldUid)); + test(ret==KErrNone); + TRAP(ret, + richText1->UpdateFieldL(0)); + test(ret==KErrNone); + // + // Save the rich text + // + // 1st the components. + CStoreMap* map=CStoreMap::NewLC(*TheStore); + richText1->StoreFieldComponentsL(*TheStore,*map); + // + RStoreWriteStream out(*map); + id1=out.CreateLC(*TheStore); + // + richText1->CancelInsertCharFormat(); + richText1->ExternalizeFieldDataL(out); + richText1->ExternalizeStyleDataL(out); + hasMarkupData=richText1->HasMarkupData(); + out.WriteUint8L((TUint8)hasMarkupData!=EFalse); + if (hasMarkupData) + richText1->ExternalizeMarkupDataL(out); + richText1->ExternalizePlainTextL(out); + // + delete richText1; + out.CommitL(); + // + map->Reset(); + CleanupStack::PopAndDestroy(2); // map,out + TheStore->CommitL(); + // + // Load the rich text + empty=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer); + empty->SetFieldFactory(&factory); + RStoreReadStream in; + in.OpenLC(*TheStore,id1); + empty->InternalizeFieldDataL(in); + empty->InternalizeStyleDataL(in); + hasMarkupData=(TBool)in.ReadUint8L(); + if (hasMarkupData) + empty->InternalizeMarkupDataL(in); + empty->InternalizePlainTextL(in); + CleanupStack::PopAndDestroy(); // in + // + empty->RestoreFieldComponentsL(*TheStore); + hasMarkupData=empty->HasMarkupData(); + test(hasMarkupData); + paragraphCount=empty->ParagraphCount(); + test(paragraphCount==3); + test(empty->StyleList()->Count()==3); // the style list is now externally owned. + delete empty; + empty=NULL; +// +// Case (8) Rich text with fields with referenced style list with markup - default store +// + test.Next(_L("RT + fields + markup + style list - default store")); + // Setup the rich text + list=CreatePopulatedStyleList(); + richText1=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer,*list); + hasMarkupData=richText1->HasMarkupData(); + test(hasMarkupData); + richText1->InsertL(0,_L("hello")); + richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter); + richText1->InsertL(richText1->DocumentLength(),_L("there")); + richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter); + paraFormat=CParaFormat::NewLC(); + paraMask.ClearAll(); + paraFormat->iHorizontalAlignment=CParaFormat::ERightAlign; + paraMask.SetAttrib(EAttAlignment); + richText1->ApplyParaFormatL(paraFormat,paraMask,8,0); + CleanupStack::PopAndDestroy(); // paraFormat + hasMarkupData=richText1->HasMarkupData(); + test(hasMarkupData); + // + // Now add a text field to this. + richText1->SetFieldFactory(&factory); + field=NULL; + TRAP(ret, + field=factory.NewFieldL(KDateTimeFieldUid)); + test(ret==KErrNone); + TRAP(ret, + richText1->InsertFieldL(0,field,KDateTimeFieldUid)); + test(ret==KErrNone); + TRAP(ret, + richText1->UpdateFieldL(0)); + test(ret==KErrNone); + // + // Save the rich text + id1=richText1->StoreL(*TheStore); + delete richText1; + // + // Load the rich text + empty=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer); + empty->SetFieldFactory(&factory); + empty->RestoreL(*TheStore,id1); + // + hasMarkupData=empty->HasMarkupData(); + test(hasMarkupData); + paragraphCount=empty->ParagraphCount(); + test(paragraphCount==3); + TEtextComponentInfo ci=empty->ComponentInfo(); + test(ci.iFieldCount==1); + test(ci.iStyleCount==3); + delete empty; + empty=NULL; // +// +// Case (9) Rich text with no components whatsoever - default store +// + test.Next(_L("RT + no markup whatsoever - default store")); + richText1=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer); + hasMarkupData=richText1->HasMarkupData(); + test(!hasMarkupData); + richText1->InsertL(0,_L("hello")); + richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter); + richText1->InsertL(richText1->DocumentLength(),_L("there")); + richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter); + // + // Save the rich text + id1=richText1->StoreL(*TheStore); + delete richText1; + // + // Load the rich text + empty=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer); + empty->RestoreL(*TheStore,id1); + // + hasMarkupData=empty->HasMarkupData(); + test(!hasMarkupData); + paragraphCount=empty->ParagraphCount(); + test(paragraphCount==3); + ci=empty->ComponentInfo(); + test(ci.iFieldCount==0); + test(ci.iStyleCount==0); + test(ci.iPictureCount==0); + delete empty; + empty=NULL; + // + // + CleanupStack::PopAndDestroy(); // TheStore + test.End(); + } + +/** +@SYMTestCaseID SYSLIB-ETEXT-CT-3380 +@SYMTestCaseDesc Inserting and deleting rich text and verify behaviours of DeleteParagraph(), Delete() and NotifyDelete(); + ie. when encounter paragraph delimiter and hidden character +@SYMTestPriority High +@SYMTestActions 1. Insert and delete a whole paragraph of rich text + 2. Insert a paragraph and delete some text + 3. Insert 2nd paragraph and DeleteParagraph() both + 4. Insert field to rich text object and delete field + 5. Insert field to rich text object after some plain text and delete it + 6. Insert field to rich text object in between two plain texts then delete the field to merge the texts + 7. Insert plain text in between two fields to rich text object then delete plain text to merge two fields +@SYMTestExpectedResults CTextFieldSet, CPlainText, CRichText's APIs for performing various types of deletion function properly when + dealing with paragraph delimiter and hidden characters in a paragraph +@SYMDEF PDEF101757 +*/ +LOCAL_C void TestDEF101757() + { + TFindFieldInfo info; + TTestFieldFactory factory; + CTextField* field=NULL; + CTextField* field1=NULL; + CTextField* field2=NULL; + CTextField* field3=NULL; + CTextField* field4=NULL; + + _LIT(KSample1, "Hello"); // length:5 + _LIT(KSample2, "How are you"); // length:11 + + test.Start(_L(" @SYMTestCaseID:SYSLIB-ETEXT-CT-3380 Insertion and deletion to rich text object ")); + + CRichText* richText=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer); + CleanupStack::PushL(richText); + + // Case1 + // Insert and delete a whole paragraph of rich text + richText->InsertL(0, KSample1); + richText->InsertL(richText->DocumentLength(),CEditableText::EParagraphDelimiter); + test(richText->DocumentLength()==6); + + richText->DeleteParagraph(0, 5); //do not delete para delimiter + + richText->InsertL(0, KSample1); + richText->InsertL(richText->DocumentLength(),CEditableText::EParagraphDelimiter); + test(richText->DocumentLength()==7); + + richText->DeleteParagraph(0, 7); //delete para delimiter + + test(richText->DocumentLength()==0); + test(richText->ParagraphCount()==1); + + // Case2 + // Insert a paragraph and delete some text + richText->InsertL(0, KSample2); + richText->InsertL(richText->DocumentLength(),CEditableText::EParagraphDelimiter); + test(richText->DocumentLength()==12); + + richText->DeleteParagraph(10, 1); //delete last char 'u' and not para delimter + test(richText->DocumentLength()==11); + + richText->DeleteParagraph(9, 2); //delete last char 'o' and also para delimter + test(richText->DocumentLength()==9); + //should not panic due to fix for PDEF101757 + + test(richText->ParagraphCount()==1); + + // Case3 + // Insert 2nd paragraph and DeleteParagraph() both + richText->InsertL(richText->DocumentLength(),CEditableText::EParagraphDelimiter); + test(richText->ParagraphCount()==2); + richText->InsertL(richText->DocumentLength(),KSample1); + richText->InsertL(richText->DocumentLength(),CEditableText::EParagraphDelimiter); + test(richText->DocumentLength()==16); + test(richText->ParagraphCount()==3); //2 paragraph delimiters including EOD delimiter (always there) + + richText->DeleteParagraph(0, 16); + test(richText->DocumentLength()==0); + test(richText->ParagraphCount()==1); //2 paragrsphs deleted + + // Case4 + // Insert field to rich text object and delete field + richText->SetFieldFactory(&factory); + field=factory.NewFieldL(KDateTimeFieldUid); // TUid KDateTimeFieldUid: length:10 + CleanupStack::PushL(field); + richText->InsertFieldL(0,field,KDateTimeFieldUid); + CleanupStack::Pop(field);//richtext has taken ownership successfully + + richText->UpdateFieldL(0); + test(richText->FieldCount()==1); + richText->DeleteParagraph(0, 10); + richText->UpdateFieldL(0); + test(richText->FieldCount()==0); + + // Case5 + // Insert field to rich text object after some plain text and delete it + richText->InsertL(0, KSample1); + field1=factory.NewFieldL(KDateTimeFieldUid); + CleanupStack::PushL(field1); + richText->InsertFieldL(5, field1, KDateTimeFieldUid); + CleanupStack::Pop(field1); + richText->UpdateFieldL(5); + test(richText->FieldCount()==1); + richText->DeleteParagraph(5, 10); + test(richText->FieldCount()==0); + + // Case6 + // Insert field to rich text object in between two plain texts then delete the field to merge the texts + field2=factory.NewFieldL(KDateTimeFieldUid); + CleanupStack::PushL(field2); + richText->InsertFieldL(5, field2, KDateTimeFieldUid); + CleanupStack::Pop(field2); + richText->UpdateFieldL(5); + richText->InsertL(14, KSample1); + richText->DeleteParagraph(5, 10); + test(richText->DocumentLength()==10); //two plain texts merged + richText->DeleteParagraph(0, 10); + test(richText->FieldCount()==0); + test(richText->DocumentLength()==0); + + // Case7 + // Insert plain text in between two fields to rich text object then delete plain text to merge two fields + field3=factory.NewFieldL(KDateTimeFieldUid); + field4=factory.NewFieldL(KDateTimeFieldUid); + + CleanupStack::PushL(field3); + richText->InsertFieldL(0, field3, KDateTimeFieldUid); + CleanupStack::Pop(field3); + richText->UpdateFieldL(0); + + richText->InsertL(10, KSample1); + + CleanupStack::PushL(field4); + richText->InsertFieldL(15, field4, KDateTimeFieldUid); + CleanupStack::Pop(field4); + richText->UpdateFieldL(15); + richText->DeleteParagraph(10, 5); + + richText->FindFields(info,5); + test(info.iFirstFieldLen==10); + test(info.iFirstFieldPos==0); + richText->FindFields(info,15); + test(info.iFirstFieldLen==10); + test(info.iFirstFieldPos==10); + test(richText->FieldCount()==2); + + CleanupStack::PopAndDestroy(richText); + test.End(); + } + + +//Testcode for INC054540 +LOCAL_C void TestINC054540() + { + theFs.Delete(KTRtCustOutputFile); + theFs.MkDirAll(KTRtCustOutputFile); + TheStore=CPermanentFileStore::CreateLC(theFs,KTRtCustOutputFile,EFileRead|EFileWrite); + TheStore->SetTypeL(TheStore->Layout()); +// +//test 1: Test INC054540 fix for 255 fields +// + test.Start(_L("test")); + + CRichText* richText1=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer); + // + // Now add a text field to this. + TTestFieldFactory factory; + richText1->SetFieldFactory(&factory); + CTextField* field=NULL; + TInt x=0; + //add 255 fields + while(x<255) + { + TRAPD(ret,field=factory.NewFieldL(KDateTimeFieldUid)); + test(ret==KErrNone); + TRAP(ret,richText1->InsertFieldL(0,field,KDateTimeFieldUid)); + test(ret==KErrNone); + TRAP(ret,richText1->UpdateFieldL(0)); + test(ret==KErrNone); + x++; + } + // Save the rich text + // + CStoreMap* map=CStoreMap::NewLC(*TheStore); + richText1->StoreFieldComponentsL(*TheStore,*map); + // + RStoreWriteStream out1(*map); + TStreamId id1=out1.CreateLC(*TheStore); + // + richText1->ExternalizeFieldDataL(out1); + // + delete richText1; + out1.CommitL(); + // + map->Reset(); + CleanupStack::PopAndDestroy(2); // map,out1 + TheStore->CommitL(); + // + // Load the rich text + CRichText* empty=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer); + empty->SetFieldFactory(&factory); + RStoreReadStream in; + in.OpenLC(*TheStore,id1); + empty->InternalizeFieldDataL(in); + CleanupStack::PopAndDestroy(); // in + // + empty->RestoreFieldComponentsL(*TheStore); + test(empty->FieldCount()==255); + delete empty; + empty=NULL; + +// +//test 2: Test INC054540 fix for more than 255 fields +// + test.Next(_L("test for more than 255 fields")); + richText1=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer); + // Add the text fields + richText1->SetFieldFactory(&factory); + field=NULL; + x=0; + //add 256 fields + while(x<256) + { + TRAPD(ret,field=factory.NewFieldL(KDateTimeFieldUid)); + test(ret==KErrNone); + TRAP(ret,richText1->InsertFieldL(0,field,KDateTimeFieldUid)); + test(ret==KErrNone); + TRAP(ret,richText1->UpdateFieldL(0)); + test(ret==KErrNone); + x++; + } + // Save the rich text + // + map=CStoreMap::NewLC(*TheStore); + richText1->StoreFieldComponentsL(*TheStore,*map); + // + RStoreWriteStream out2(*map); + id1=out2.CreateLC(*TheStore); + // + richText1->ExternalizeFieldDataL(out2); + // + delete richText1; + out2.CommitL(); + // + map->Reset(); + CleanupStack::PopAndDestroy(2); // map,out2 + TheStore->CommitL(); + // + // Load the rich text + empty=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer); + empty->SetFieldFactory(&factory); + in.OpenLC(*TheStore,id1); + empty->InternalizeFieldDataL(in); + CleanupStack::PopAndDestroy(); // in + // + empty->RestoreFieldComponentsL(*TheStore); + test(empty->FieldCount()==256); + delete empty; + empty=NULL; + // + // + CleanupStack::PopAndDestroy(); // TheStore + test.End(); + } + + +LOCAL_C void doMainL() + { + GlobalParaFormatLayer=CParaFormatLayer::NewL(); + GlobalCharFormatLayer=CCharFormatLayer::NewL(); + theFs.Connect(); + // + CustomLoadSave(); + TestDEF101757(); + TestINC054540(); + // + delete GlobalParaFormatLayer; + delete GlobalCharFormatLayer; + theFs.Close(); + } + + +LOCAL_C void setupCleanup() +// +// Initialise the cleanup stack. +// + { + TheTrapCleanup=CTrapCleanup::New(); + test(TheTrapCleanup!=NULL); + TRAPD(r,\ + {\ + for (TInt i=KTestCleanupStack;i>0;i--)\ + CleanupStack::PushL((TAny*)0);\ + CleanupStack::Pop(KTestCleanupStack);\ + }); + test(r==KErrNone); + } + + +LOCAL_C void DeleteDataFile(const TDesC& aFullName) + { + RFs fsSession; + TInt err = fsSession.Connect(); + if(err == KErrNone) + { + TEntry entry; + if(fsSession.Entry(aFullName, entry) == KErrNone) + { + RDebug::Print(_L("Deleting \"%S\" file.\n"), &aFullName); + err = fsSession.SetAtt(aFullName, 0, KEntryAttReadOnly); + if(err != KErrNone) + { + RDebug::Print(_L("Error %d changing \"%S\" file attributes.\n"), err, &aFullName); + } + err = fsSession.Delete(aFullName); + if(err != KErrNone) + { + RDebug::Print(_L("Error %d deleting \"%S\" file.\n"), err, &aFullName); + } + } + fsSession.Close(); + } + else + { + RDebug::Print(_L("Error %d connecting file session. File: %S.\n"), err, &aFullName); + } + } + +GLDEF_C TInt E32Main() +// +// Test permanent file TheStore. +// + { + test.Title(); + setupCleanup(); + __UHEAP_MARK; +// + test.Start(_L("Testing custom save/load optimization")); + TRAPD(ret,doMainL()); + test(ret==KErrNone); + + ::DeleteDataFile(KTRtCustOutputFile); //deletion of data files must be before call to End() - DEF047652 + test.End(); +// + __UHEAP_MARKEND; + delete TheTrapCleanup; + test.Close(); + + return KErrNone; + } +