textrendering/texthandling/ttext/TRTCUSTM.CPP
changeset 0 1fb32624e06b
child 16 748ec5531811
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/textrendering/texthandling/ttext/TRTCUSTM.CPP	Tue Feb 02 02:02:46 2010 +0200
@@ -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 <txtrich.h>
+#include <txtstyle.h>
+#include "TXTMRTSR.H"
+#include <e32test.h>
+#include <gdi.h>
+#include <conpics.h>											   						 
+#include <s32mem.h>
+#include <s32file.h>
+#include <flddef.h>
+#include <fldbltin.h>
+#include <fldset.h>
+
+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;
+    }
+