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