textrendering/texthandling/ttext/TRTCUSTM.CPP
changeset 32 8b9155204a54
parent 0 1fb32624e06b
child 51 a7c938434754
equal deleted inserted replaced
31:b9ad20498fb4 32:8b9155204a54
       
     1 /*
       
     2 * Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <txtrich.h>
       
    20 #include <txtstyle.h>
       
    21 #include "TXTMRTSR.H"
       
    22 #include <e32test.h>
       
    23 #include <gdi.h>
       
    24 #include <conpics.h>											   						 
       
    25 #include <s32mem.h>
       
    26 #include <s32file.h>
       
    27 #include <flddef.h>
       
    28 #include <fldbltin.h>
       
    29 #include <fldset.h>
       
    30 
       
    31 GLDEF_C RTest test(_L("TRTCUSTM"));
       
    32 LOCAL_D RFs theFs;
       
    33 LOCAL_D CFileStore* TheStore;
       
    34 LOCAL_D CParaFormatLayer* GlobalParaFormatLayer;
       
    35 LOCAL_D CCharFormatLayer* GlobalCharFormatLayer;
       
    36 LOCAL_D CTrapCleanup* TheTrapCleanup;
       
    37 const TInt KTestCleanupStack=0x500;
       
    38 
       
    39 
       
    40 class TStoreResolver : public MRichTextStoreResolver
       
    41 	{
       
    42 public:
       
    43 	virtual const CStreamStore& StreamStoreL(TInt /*aPos*/)const {return *iStore;}
       
    44 public:
       
    45 	CStreamStore* iStore;
       
    46 	};
       
    47 
       
    48 
       
    49 ////////////////////////////////////////////////////////////////////////////////////////////
       
    50 class TTestFieldFactory : public MTextFieldFactory
       
    51 	{
       
    52 public:
       
    53 	// from MTextFieldFactory
       
    54 	virtual CTextField* NewFieldL(TUid aFieldType); 
       
    55 	// Creates a field of the type specified
       
    56 	// Returns NULL if it does not recognise/support the field type
       
    57 	};
       
    58 
       
    59 CTextField* TTestFieldFactory::NewFieldL(TUid aFieldType)
       
    60 // Creates a field (in aHeader) of the type specified in aHeader
       
    61 // 
       
    62 	{
       
    63 	CTextField* field=NULL;
       
    64 	if (aFieldType==KDateTimeFieldUid)
       
    65 		field = (CTextField*)new(ELeave) CDateTimeField();
       
    66 	return field;
       
    67 	}
       
    68 /////////////////////////////////////////////////////////////////////////////////////////////
       
    69 
       
    70 LOCAL_D void WriteInlineL(RWriteStream& aStream,CRichText* aRichText)
       
    71 	{
       
    72 	aRichText->CancelInsertCharFormat();
       
    73 	aRichText->ExternalizeFieldDataL(aStream);
       
    74 	aRichText->ExternalizeStyleDataL(aStream);
       
    75 	TBool hasMarkupData=aRichText->HasMarkupData();
       
    76 	aStream.WriteUint8L((TUint8)hasMarkupData!=EFalse);
       
    77 	if (hasMarkupData)
       
    78 		aRichText->ExternalizeMarkupDataL(aStream);	
       
    79 	aRichText->ExternalizePlainTextL(aStream);
       
    80 	}
       
    81 
       
    82 LOCAL_D void ReadInlineL(RReadStream& aStream,CRichText* aRichText)
       
    83 	{
       
    84 	aRichText->InternalizeFieldDataL(aStream);
       
    85 	aRichText->InternalizeStyleDataL(aStream);
       
    86 	TBool hasMarkupData=(TBool)aStream.ReadUint8L();
       
    87 	if (hasMarkupData)
       
    88 		aRichText->InternalizeMarkupDataL(aStream);	
       
    89 	aRichText->InternalizePlainTextL(aStream);
       
    90 	}
       
    91 
       
    92 
       
    93 LOCAL_D TStreamId PerformSaveL(CRichText* aRichText)
       
    94 //
       
    95 	{
       
    96 	RStoreWriteStream out;
       
    97 	TStreamId id1=out.CreateLC(*TheStore);
       
    98 	WriteInlineL(out,aRichText);
       
    99 	delete aRichText;
       
   100 	out.CommitL();
       
   101 	CleanupStack::PopAndDestroy();  // out
       
   102 	TheStore->CommitL();
       
   103 	return id1;
       
   104 	}
       
   105 
       
   106 
       
   107 LOCAL_C CRichText* PerformLoadL(TStreamId aId)
       
   108 //
       
   109 	{
       
   110 	CRichText* text=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer);
       
   111 	RStoreReadStream in;
       
   112 	in.OpenLC(*TheStore,aId);
       
   113 	TRAPD(ret,
       
   114 	ReadInlineL(in,text));
       
   115 	test(ret==KErrNone);
       
   116 	CleanupStack::PopAndDestroy();  // in
       
   117 	return text;
       
   118 	}
       
   119 
       
   120 
       
   121 LOCAL_C CStyleList* CreatePopulatedStyleList()
       
   122 //
       
   123 	{
       
   124 	//
       
   125 	// Create style aswell.
       
   126 	CStyleList* list=CStyleList::NewL();
       
   127 	CParagraphStyle* style1=CParagraphStyle::NewL(*GlobalParaFormatLayer,*GlobalCharFormatLayer);
       
   128 	CParagraphStyle* style2=CParagraphStyle::NewL(*GlobalParaFormatLayer,*GlobalCharFormatLayer);
       
   129 	CParagraphStyle* style3=CParagraphStyle::NewL(*GlobalParaFormatLayer,*GlobalCharFormatLayer);
       
   130 	RParagraphStyleInfo info1(style1);
       
   131 	RParagraphStyleInfo info2(style2);
       
   132 	RParagraphStyleInfo info3(style3);
       
   133 	list->AppendL(&info1);
       
   134 	list->AppendL(&info2);
       
   135 	list->AppendL(&info3);
       
   136 	return list;
       
   137 	}
       
   138 
       
   139 _LIT(KTRtCustOutputFile,"c:\\etext\\TRTCUSTM.DAT");
       
   140 
       
   141 LOCAL_C void CustomLoadSave()
       
   142 	{
       
   143 // Set up the framework
       
   144 	theFs.Delete(KTRtCustOutputFile);
       
   145 	theFs.MkDirAll(KTRtCustOutputFile);
       
   146 	TheStore=CPermanentFileStore::CreateLC(theFs,KTRtCustOutputFile,EFileRead|EFileWrite);
       
   147 	TheStore->SetTypeL(TheStore->Layout());
       
   148 
       
   149 //
       
   150 // Case (1) Rich text with owned style list. - no markup data
       
   151 //
       
   152 	test.Start(_L("RT + no markup + style list owned"));
       
   153 	//
       
   154 	// Setup the rich text
       
   155 	CStyleList* list=CreatePopulatedStyleList();
       
   156 	CRichText* richText1=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer,*list);
       
   157 	TBool hasMarkupData=richText1->HasMarkupData();
       
   158 	test(hasMarkupData);
       
   159 	richText1->InsertL(0,_L("hello"));
       
   160 	richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter);
       
   161 	richText1->InsertL(richText1->DocumentLength(),_L("there"));
       
   162 	//
       
   163 	// Save the rich text
       
   164 	TStreamId id1=PerformSaveL(richText1);
       
   165 	//
       
   166 	// Load the rich text
       
   167 	CRichText* empty=NULL;
       
   168 	TRAPD(ret,
       
   169 	empty=PerformLoadL(id1));
       
   170 	test(ret==KErrNone);
       
   171 	hasMarkupData=empty->HasMarkupData();
       
   172 	test(hasMarkupData);
       
   173 	delete empty;
       
   174 	empty=NULL;
       
   175 //
       
   176 // Case (2) Rich text with referenced style list. - no markup data
       
   177 //
       
   178 	test.Next(_L("RT + no markup + style list externally owned"));
       
   179 	//
       
   180 	// Setup the rich text
       
   181 	list=CreatePopulatedStyleList();
       
   182 	richText1=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer,*list,CEditableText::ESegmentedStorage,2);
       
   183 	richText1->SetStyleListExternallyOwned(ETrue);
       
   184 	hasMarkupData=richText1->HasMarkupData();
       
   185 	test(!hasMarkupData);
       
   186 	richText1->InsertL(0,_L("hello"));
       
   187 	richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter);
       
   188 	richText1->InsertL(richText1->DocumentLength(),_L("there"));
       
   189 	richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter);
       
   190 	hasMarkupData=richText1->HasMarkupData();
       
   191 	test(!hasMarkupData);
       
   192 	//
       
   193 	// Save the rich text
       
   194 	id1=PerformSaveL(richText1);
       
   195 	//
       
   196 	// Load the rich text
       
   197 	empty=PerformLoadL(id1);
       
   198 	hasMarkupData=empty->HasMarkupData();
       
   199 	test(!hasMarkupData);
       
   200 	TInt paragraphCount=empty->ParagraphCount();
       
   201 	test(paragraphCount==3);
       
   202 	test(list->Count()==3);  // the style list is now externally owned.
       
   203 	delete empty;
       
   204 	test(list->Count()==3);  // the style list should not have been destroyed by the rich text
       
   205 	delete list;
       
   206 	empty=NULL;
       
   207 //
       
   208 // Case (3) Rich text with referenced style list. - with markup
       
   209 //
       
   210 	test.Next(_L("RT + markup + style list externally owned"));
       
   211 	// Setup the rich text
       
   212 	list=CreatePopulatedStyleList();
       
   213 	richText1=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer,*list);
       
   214 	richText1->SetStyleListExternallyOwned(ETrue);
       
   215 	hasMarkupData=richText1->HasMarkupData();
       
   216 	test(!hasMarkupData);
       
   217 	richText1->InsertL(0,_L("hello"));
       
   218 	richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter);
       
   219 	richText1->InsertL(richText1->DocumentLength(),_L("there"));
       
   220 	richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter);
       
   221 	CParaFormat* paraFormat=CParaFormat::NewLC();
       
   222 	TParaFormatMask paraMask;
       
   223 	paraFormat->iHorizontalAlignment=CParaFormat::ERightAlign;
       
   224 	paraMask.SetAttrib(EAttAlignment);
       
   225 	richText1->ApplyParaFormatL(paraFormat,paraMask,8,0);
       
   226 	CleanupStack::PopAndDestroy();  // paraFormat
       
   227 	hasMarkupData=richText1->HasMarkupData();
       
   228 	test(hasMarkupData);
       
   229 	//
       
   230 	// Save the rich text
       
   231 	id1=PerformSaveL(richText1);
       
   232 	//
       
   233 	// Load the rich text
       
   234 	empty=PerformLoadL(id1);
       
   235 	hasMarkupData=empty->HasMarkupData();
       
   236 	test(hasMarkupData);
       
   237 	paragraphCount=empty->ParagraphCount();
       
   238 	test(paragraphCount==3);
       
   239 	test(list->Count()==3);  // the style list is now externally owned.
       
   240 	delete empty;
       
   241 	test(list->Count()==3);  // the style list should not have been destroyed by the rich text
       
   242 	delete list;
       
   243 	empty=NULL;
       
   244 //
       
   245 // Case (4) Rich text with no style list. - no effective markup
       
   246 //
       
   247 	test.Next(_L("RT + delete picture + no style list"));
       
   248 	// Setup the rich text
       
   249 	richText1=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer);
       
   250 	hasMarkupData=richText1->HasMarkupData();
       
   251 	test(!hasMarkupData);
       
   252 	richText1->InsertL(0,_L("hello"));
       
   253 	richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter);
       
   254 	richText1->InsertL(richText1->DocumentLength(),_L("there"));
       
   255 	richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter);
       
   256 	//
       
   257 	// Create & insert a picture
       
   258 	CXzePicture* pic1=CXzePicture::NewL('o');
       
   259 	TPictureHeader header1;
       
   260 	TSize size;
       
   261 	pic1->GetSizeInTwips(size);
       
   262 	header1.iPictureType=KUidXzePictureType;
       
   263 	header1.iPicture=pic1;
       
   264 	header1.iSize=size;
       
   265 	richText1->InsertL(3,header1);
       
   266 	hasMarkupData=richText1->HasMarkupData();
       
   267 	test(hasMarkupData);
       
   268 	richText1->DeleteL(3,1);
       
   269 	hasMarkupData=richText1->HasMarkupData();
       
   270 	test(!hasMarkupData);
       
   271 	//
       
   272 	// Save the rich text
       
   273 	id1=PerformSaveL(richText1);
       
   274 	//
       
   275 	// Load the rich text
       
   276 	empty=PerformLoadL(id1);
       
   277 	hasMarkupData=empty->HasMarkupData();
       
   278 	test(!hasMarkupData);
       
   279 	paragraphCount=empty->ParagraphCount();
       
   280 	test(paragraphCount==3);
       
   281 	delete empty;
       
   282 	empty=NULL;
       
   283 //
       
   284 // Case (5) Rich text with SetInsertCharFormat()
       
   285 //
       
   286 	test.Next(_L("RT + SetInsertCharFormatL()"));
       
   287 	// Setup the rich text
       
   288 	richText1=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer);
       
   289 	hasMarkupData=richText1->HasMarkupData();
       
   290 	test(!hasMarkupData);
       
   291 	richText1->InsertL(0,_L("hello"));
       
   292 	richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter);
       
   293 	richText1->InsertL(richText1->DocumentLength(),_L("there"));
       
   294 	richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter);
       
   295 	TCharFormat charFormat;
       
   296 	TCharFormatMask charMask;
       
   297 	charFormat.iFontPresentation.iStrikethrough=EStrikethroughOn;
       
   298 	charMask.SetAttrib(EAttFontStrikethrough);
       
   299 	richText1->SetInsertCharFormatL(charFormat,charMask,3);
       
   300 	hasMarkupData=richText1->HasMarkupData();
       
   301 	test(hasMarkupData);
       
   302 	//
       
   303 	// Save the rich text
       
   304 	id1=PerformSaveL(richText1);
       
   305 	//
       
   306 	// Load the rich text
       
   307 	empty=PerformLoadL(id1);
       
   308 	hasMarkupData=empty->HasMarkupData();
       
   309 	test(!hasMarkupData);
       
   310 	paragraphCount=empty->ParagraphCount();
       
   311 	test(paragraphCount==3);
       
   312 	delete empty;
       
   313 	empty=NULL;
       
   314 //
       
   315 // Case (6) Rich text with components - default re/store used.
       
   316 //
       
   317 
       
   318 	test.Next(_L("RT + components"));
       
   319 	// Setup the rich text
       
   320 	richText1=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer);
       
   321 	hasMarkupData=richText1->HasMarkupData();
       
   322 	test(!hasMarkupData);
       
   323 	richText1->InsertL(0,_L("hello"));
       
   324 	richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter);
       
   325 	richText1->InsertL(richText1->DocumentLength(),_L("there"));
       
   326 	richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter);
       
   327 	//
       
   328 	// Create & insert some fields
       
   329 	TTestFieldFactory factory;
       
   330 	richText1->SetFieldFactory(&factory);
       
   331 	CTextField* field=NULL;
       
   332 	CTextField* field2=NULL;
       
   333 	TRAP(ret,
       
   334 	field=factory.NewFieldL(KDateTimeFieldUid));	test(ret==KErrNone);
       
   335 	TRAP(ret,
       
   336 	field2=factory.NewFieldL(KDateTimeFieldUid));    test(ret==KErrNone);
       
   337 	TRAP(ret,
       
   338 	richText1->InsertFieldL(0,field,KDateTimeFieldUid));  test(ret==KErrNone);
       
   339 	TRAP(ret,
       
   340 	richText1->UpdateFieldL(0));
       
   341 	test(ret==KErrNone);
       
   342 	TRAP(ret,
       
   343 	richText1->InsertFieldL(0,field2,KDateTimeFieldUid));
       
   344 	test(ret==KErrNone);
       
   345 	TRAP(ret,
       
   346 	richText1->UpdateFieldL(0));
       
   347 	test(ret==KErrNone);
       
   348 	//
       
   349 	// Create & insert a picture
       
   350 	pic1=CXzePicture::NewL('o');
       
   351 	pic1->GetSizeInTwips(size);
       
   352 	header1.iPictureType=KUidXzePictureType;
       
   353 	header1.iPicture=pic1;
       
   354 	header1.iSize=size;
       
   355 	richText1->InsertL(0,header1);
       
   356 	hasMarkupData=richText1->HasMarkupData();
       
   357 	test(hasMarkupData);
       
   358 	//
       
   359 	// Save the rich text
       
   360 	TStreamId head=richText1->StoreL(*TheStore);
       
   361 	delete richText1;
       
   362 	//
       
   363 	// Load the rich text
       
   364 	empty=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer);
       
   365 	empty->SetFieldFactory(&factory);
       
   366 	empty->RestoreL(*TheStore,head);
       
   367 	//
       
   368 	// Create the correct factories
       
   369 	TStoreResolver storeResolver;
       
   370 	storeResolver.iStore=TheStore;
       
   371 	MDemPictureFactory* pictureFactory=new(ELeave) MDemPictureFactory;
       
   372 
       
   373 	empty->SetPictureFactory(pictureFactory,&storeResolver);
       
   374 	CXzePicture* rPic=(CXzePicture*)empty->PictureHandleL(0);
       
   375 	test(rPic->iLabel=='o');
       
   376 	//
       
   377 	hasMarkupData=empty->HasMarkupData();
       
   378 	test(hasMarkupData);
       
   379 	paragraphCount=empty->ParagraphCount();
       
   380 	test(paragraphCount==3);
       
   381 	delete empty;
       
   382 	empty=NULL;
       
   383 	delete pictureFactory;
       
   384 //
       
   385 // Case (7) Rich text with fields with referenced style list with markup
       
   386 //
       
   387 	test.Next(_L("RT + fields + markup + style list"));
       
   388 	// Setup the rich text
       
   389 	list=CreatePopulatedStyleList();
       
   390 	richText1=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer,*list);
       
   391 	hasMarkupData=richText1->HasMarkupData();
       
   392 	test(hasMarkupData);
       
   393 	richText1->InsertL(0,_L("hello"));
       
   394 	richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter);
       
   395 	richText1->InsertL(richText1->DocumentLength(),_L("there"));
       
   396 	richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter);
       
   397 	paraFormat=CParaFormat::NewLC();
       
   398 	paraMask.ClearAll();
       
   399 	paraFormat->iHorizontalAlignment=CParaFormat::ERightAlign;
       
   400 	paraMask.SetAttrib(EAttAlignment);
       
   401 	richText1->ApplyParaFormatL(paraFormat,paraMask,8,0);
       
   402 	CleanupStack::PopAndDestroy();  // paraFormat
       
   403 	hasMarkupData=richText1->HasMarkupData();
       
   404 	test(hasMarkupData);
       
   405 	//
       
   406 	// Now add a text field to this.
       
   407 	richText1->SetFieldFactory(&factory);
       
   408 	field=NULL;
       
   409 	TRAP(ret,
       
   410 	field=factory.NewFieldL(KDateTimeFieldUid));
       
   411 	test(ret==KErrNone);
       
   412 	TRAP(ret,
       
   413 	richText1->InsertFieldL(0,field,KDateTimeFieldUid));
       
   414 	test(ret==KErrNone);
       
   415 	TRAP(ret,
       
   416 	richText1->UpdateFieldL(0));
       
   417 	test(ret==KErrNone);
       
   418 	//
       
   419 	// Save the rich text
       
   420 	//
       
   421 	// 1st the components.
       
   422 	CStoreMap* map=CStoreMap::NewLC(*TheStore);
       
   423 	richText1->StoreFieldComponentsL(*TheStore,*map);
       
   424 	//
       
   425 	RStoreWriteStream out(*map);
       
   426 	id1=out.CreateLC(*TheStore);
       
   427 	//
       
   428 	richText1->CancelInsertCharFormat();
       
   429 	richText1->ExternalizeFieldDataL(out);
       
   430 	richText1->ExternalizeStyleDataL(out);
       
   431 	hasMarkupData=richText1->HasMarkupData();
       
   432 	out.WriteUint8L((TUint8)hasMarkupData!=EFalse);
       
   433 	if (hasMarkupData)
       
   434 		richText1->ExternalizeMarkupDataL(out);	
       
   435 	richText1->ExternalizePlainTextL(out);
       
   436 	//
       
   437 	delete richText1;
       
   438 	out.CommitL();
       
   439 	//
       
   440 	map->Reset();
       
   441 	CleanupStack::PopAndDestroy(2);  // map,out
       
   442 	TheStore->CommitL();
       
   443 	//
       
   444 	// Load the rich text
       
   445 	empty=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer);
       
   446 	empty->SetFieldFactory(&factory);
       
   447 	RStoreReadStream in;
       
   448 	in.OpenLC(*TheStore,id1);
       
   449 	empty->InternalizeFieldDataL(in);
       
   450 	empty->InternalizeStyleDataL(in);
       
   451 	hasMarkupData=(TBool)in.ReadUint8L();
       
   452 	if (hasMarkupData)
       
   453 		empty->InternalizeMarkupDataL(in);	
       
   454 	empty->InternalizePlainTextL(in);
       
   455 	CleanupStack::PopAndDestroy();  // in
       
   456 	//	
       
   457 	empty->RestoreFieldComponentsL(*TheStore);
       
   458 	hasMarkupData=empty->HasMarkupData();
       
   459 	test(hasMarkupData);
       
   460 	paragraphCount=empty->ParagraphCount();
       
   461 	test(paragraphCount==3);
       
   462 	test(empty->StyleList()->Count()==3);  // the style list is now externally owned.
       
   463 	delete empty;
       
   464 	empty=NULL;
       
   465 //
       
   466 // Case (8) Rich text with fields with referenced style list with markup - default store
       
   467 //
       
   468 	test.Next(_L("RT + fields + markup + style list - default store"));
       
   469 	// Setup the rich text
       
   470 	list=CreatePopulatedStyleList();
       
   471 	richText1=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer,*list);
       
   472 	hasMarkupData=richText1->HasMarkupData();
       
   473 	test(hasMarkupData);
       
   474 	richText1->InsertL(0,_L("hello"));
       
   475 	richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter);
       
   476 	richText1->InsertL(richText1->DocumentLength(),_L("there"));
       
   477 	richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter);
       
   478 	paraFormat=CParaFormat::NewLC();
       
   479 	paraMask.ClearAll();
       
   480 	paraFormat->iHorizontalAlignment=CParaFormat::ERightAlign;
       
   481 	paraMask.SetAttrib(EAttAlignment);
       
   482 	richText1->ApplyParaFormatL(paraFormat,paraMask,8,0);
       
   483 	CleanupStack::PopAndDestroy();  // paraFormat
       
   484 	hasMarkupData=richText1->HasMarkupData();
       
   485 	test(hasMarkupData);
       
   486 	//
       
   487 	// Now add a text field to this.
       
   488 	richText1->SetFieldFactory(&factory);
       
   489 	field=NULL;
       
   490 	TRAP(ret,
       
   491 	field=factory.NewFieldL(KDateTimeFieldUid));
       
   492 	test(ret==KErrNone);
       
   493 	TRAP(ret,
       
   494 	richText1->InsertFieldL(0,field,KDateTimeFieldUid));
       
   495 	test(ret==KErrNone);
       
   496 	TRAP(ret,
       
   497 	richText1->UpdateFieldL(0));
       
   498 	test(ret==KErrNone);
       
   499 	//
       
   500 	// Save the rich text
       
   501 	id1=richText1->StoreL(*TheStore);
       
   502 	delete richText1;
       
   503 	//
       
   504 	// Load the rich text
       
   505 	empty=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer);
       
   506 	empty->SetFieldFactory(&factory);
       
   507 	empty->RestoreL(*TheStore,id1);
       
   508 	//
       
   509 	hasMarkupData=empty->HasMarkupData();
       
   510 	test(hasMarkupData);
       
   511 	paragraphCount=empty->ParagraphCount();
       
   512 	test(paragraphCount==3);
       
   513 	TEtextComponentInfo ci=empty->ComponentInfo();	
       
   514 	test(ci.iFieldCount==1);
       
   515 	test(ci.iStyleCount==3);
       
   516 	delete empty;
       
   517 	empty=NULL;	//
       
   518 //
       
   519 // Case (9) Rich text with no components whatsoever - default store
       
   520 //
       
   521 	test.Next(_L("RT + no markup whatsoever - default store"));
       
   522 	richText1=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer);
       
   523 	hasMarkupData=richText1->HasMarkupData();
       
   524 	test(!hasMarkupData);
       
   525 	richText1->InsertL(0,_L("hello"));
       
   526 	richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter);
       
   527 	richText1->InsertL(richText1->DocumentLength(),_L("there"));
       
   528 	richText1->InsertL(richText1->DocumentLength(),CEditableText::EParagraphDelimiter);
       
   529 	//
       
   530 	// Save the rich text
       
   531 	id1=richText1->StoreL(*TheStore);
       
   532 	delete richText1;
       
   533 	//
       
   534 	// Load the rich text
       
   535 	empty=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer);
       
   536 	empty->RestoreL(*TheStore,id1);
       
   537 	//
       
   538 	hasMarkupData=empty->HasMarkupData();
       
   539 	test(!hasMarkupData);
       
   540 	paragraphCount=empty->ParagraphCount();
       
   541 	test(paragraphCount==3);
       
   542 	ci=empty->ComponentInfo();
       
   543 	test(ci.iFieldCount==0);
       
   544 	test(ci.iStyleCount==0);
       
   545 	test(ci.iPictureCount==0);
       
   546 	delete empty;
       
   547 	empty=NULL;
       
   548 	//
       
   549 	//
       
   550 	CleanupStack::PopAndDestroy();  // TheStore
       
   551 	test.End();
       
   552 	}
       
   553 	
       
   554 /**
       
   555 @SYMTestCaseID 			SYSLIB-ETEXT-CT-3380
       
   556 @SYMTestCaseDesc  		Inserting and deleting rich text and verify behaviours of DeleteParagraph(), Delete() and NotifyDelete(); 
       
   557   ie. when encounter paragraph delimiter and hidden character
       
   558 @SYMTestPriority  		High
       
   559 @SYMTestActions 		1. Insert and delete a whole paragraph of rich text
       
   560 						2. Insert a paragraph and delete some text
       
   561 						3. Insert 2nd paragraph and DeleteParagraph() both
       
   562 						4. Insert field to rich text object and delete field
       
   563 						5. Insert field to rich text object after some plain text and delete it 
       
   564 						6. Insert field to rich text object in between two plain texts then delete the field to merge the texts
       
   565 						7. Insert plain text in between two fields to rich text object then delete plain text to merge two fields
       
   566 @SYMTestExpectedResults	CTextFieldSet, CPlainText, CRichText's APIs for performing various types of deletion function properly when 
       
   567   dealing with paragraph delimiter and hidden characters in a paragraph
       
   568 @SYMDEF					PDEF101757
       
   569 */
       
   570 LOCAL_C void TestDEF101757()
       
   571 	{	
       
   572 	TFindFieldInfo info;
       
   573 	TTestFieldFactory factory;
       
   574 	CTextField* field=NULL;
       
   575 	CTextField* field1=NULL;
       
   576 	CTextField* field2=NULL;
       
   577 	CTextField* field3=NULL;
       
   578 	CTextField* field4=NULL;
       
   579 	
       
   580 	_LIT(KSample1, "Hello"); // length:5
       
   581 	_LIT(KSample2, "How are you"); // length:11
       
   582 	
       
   583 	test.Start(_L(" @SYMTestCaseID:SYSLIB-ETEXT-CT-3380 Insertion and deletion to rich text object "));
       
   584 	
       
   585 	CRichText* richText=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer);
       
   586 	CleanupStack::PushL(richText);
       
   587 	
       
   588 	// Case1
       
   589 	// Insert and delete a whole paragraph of rich text
       
   590 	richText->InsertL(0, KSample1);
       
   591 	richText->InsertL(richText->DocumentLength(),CEditableText::EParagraphDelimiter);
       
   592 	test(richText->DocumentLength()==6);
       
   593 	
       
   594 	richText->DeleteParagraph(0, 5); //do not delete para delimiter
       
   595 	
       
   596 	richText->InsertL(0, KSample1);
       
   597 	richText->InsertL(richText->DocumentLength(),CEditableText::EParagraphDelimiter);
       
   598 	test(richText->DocumentLength()==7);
       
   599 	
       
   600 	richText->DeleteParagraph(0, 7); //delete para delimiter
       
   601 	
       
   602 	test(richText->DocumentLength()==0);
       
   603 	test(richText->ParagraphCount()==1); 
       
   604 	
       
   605 	// Case2
       
   606 	// Insert a paragraph and delete some text
       
   607 	richText->InsertL(0, KSample2);
       
   608 	richText->InsertL(richText->DocumentLength(),CEditableText::EParagraphDelimiter);
       
   609 	test(richText->DocumentLength()==12);
       
   610 	
       
   611 	richText->DeleteParagraph(10, 1); //delete last char 'u' and not para delimter
       
   612 	test(richText->DocumentLength()==11);
       
   613 	
       
   614 	richText->DeleteParagraph(9, 2); //delete last char 'o' and also para delimter
       
   615 	test(richText->DocumentLength()==9);
       
   616 	//should not panic due to fix for PDEF101757
       
   617 	
       
   618 	test(richText->ParagraphCount()==1);
       
   619 	
       
   620 	// Case3
       
   621 	// Insert 2nd paragraph and DeleteParagraph() both
       
   622 	richText->InsertL(richText->DocumentLength(),CEditableText::EParagraphDelimiter);
       
   623 	test(richText->ParagraphCount()==2);
       
   624 	richText->InsertL(richText->DocumentLength(),KSample1);
       
   625 	richText->InsertL(richText->DocumentLength(),CEditableText::EParagraphDelimiter);
       
   626 	test(richText->DocumentLength()==16);
       
   627 	test(richText->ParagraphCount()==3); //2 paragraph delimiters including EOD delimiter (always there)
       
   628 
       
   629 	richText->DeleteParagraph(0, 16);
       
   630 	test(richText->DocumentLength()==0);
       
   631 	test(richText->ParagraphCount()==1); //2 paragrsphs deleted
       
   632 	
       
   633 	// Case4
       
   634 	// Insert field to rich text object and delete field
       
   635 	richText->SetFieldFactory(&factory);
       
   636 	field=factory.NewFieldL(KDateTimeFieldUid); // TUid KDateTimeFieldUid: length:10
       
   637 	CleanupStack::PushL(field);
       
   638 	richText->InsertFieldL(0,field,KDateTimeFieldUid);
       
   639 	CleanupStack::Pop(field);//richtext has taken ownership successfully
       
   640 	
       
   641 	richText->UpdateFieldL(0);
       
   642 	test(richText->FieldCount()==1);
       
   643 	richText->DeleteParagraph(0, 10);
       
   644 	richText->UpdateFieldL(0);
       
   645 	test(richText->FieldCount()==0);
       
   646 	
       
   647 	// Case5
       
   648 	// Insert field to rich text object after some plain text and delete it 
       
   649 	richText->InsertL(0, KSample1); 
       
   650 	field1=factory.NewFieldL(KDateTimeFieldUid);
       
   651 	CleanupStack::PushL(field1);
       
   652 	richText->InsertFieldL(5, field1, KDateTimeFieldUid);
       
   653 	CleanupStack::Pop(field1);
       
   654 	richText->UpdateFieldL(5);
       
   655 	test(richText->FieldCount()==1);
       
   656 	richText->DeleteParagraph(5, 10);
       
   657 	test(richText->FieldCount()==0);
       
   658 	
       
   659 	// Case6
       
   660 	// Insert field to rich text object in between two plain texts then delete the field to merge the texts
       
   661 	field2=factory.NewFieldL(KDateTimeFieldUid);
       
   662 	CleanupStack::PushL(field2);
       
   663 	richText->InsertFieldL(5, field2, KDateTimeFieldUid);
       
   664 	CleanupStack::Pop(field2);
       
   665 	richText->UpdateFieldL(5);
       
   666 	richText->InsertL(14, KSample1);
       
   667 	richText->DeleteParagraph(5, 10);
       
   668 	test(richText->DocumentLength()==10); //two plain texts merged 
       
   669 	richText->DeleteParagraph(0, 10);
       
   670 	test(richText->FieldCount()==0);
       
   671 	test(richText->DocumentLength()==0);
       
   672 	
       
   673 	// Case7
       
   674 	// Insert plain text in between two fields to rich text object then delete plain text to merge two fields
       
   675 	field3=factory.NewFieldL(KDateTimeFieldUid);
       
   676 	field4=factory.NewFieldL(KDateTimeFieldUid);
       
   677 	
       
   678 	CleanupStack::PushL(field3);
       
   679 	richText->InsertFieldL(0, field3, KDateTimeFieldUid);
       
   680 	CleanupStack::Pop(field3);
       
   681 	richText->UpdateFieldL(0);
       
   682 	
       
   683 	richText->InsertL(10, KSample1);
       
   684 	
       
   685 	CleanupStack::PushL(field4);
       
   686 	richText->InsertFieldL(15, field4, KDateTimeFieldUid);
       
   687 	CleanupStack::Pop(field4);
       
   688 	richText->UpdateFieldL(15);
       
   689 	richText->DeleteParagraph(10, 5);
       
   690 	
       
   691 	richText->FindFields(info,5);
       
   692 	test(info.iFirstFieldLen==10);
       
   693 	test(info.iFirstFieldPos==0);
       
   694 	richText->FindFields(info,15);
       
   695 	test(info.iFirstFieldLen==10);
       
   696 	test(info.iFirstFieldPos==10);
       
   697 	test(richText->FieldCount()==2);
       
   698 	
       
   699 	CleanupStack::PopAndDestroy(richText);
       
   700 	test.End();
       
   701 	}
       
   702 	
       
   703 
       
   704 //Testcode for INC054540
       
   705 LOCAL_C void TestINC054540()
       
   706 	{
       
   707 	theFs.Delete(KTRtCustOutputFile);
       
   708 	theFs.MkDirAll(KTRtCustOutputFile);
       
   709 	TheStore=CPermanentFileStore::CreateLC(theFs,KTRtCustOutputFile,EFileRead|EFileWrite);
       
   710 	TheStore->SetTypeL(TheStore->Layout());
       
   711 //
       
   712 //test 1: Test INC054540 fix for 255 fields
       
   713 //	
       
   714 	test.Start(_L("test"));
       
   715 	
       
   716 	CRichText* richText1=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer);
       
   717 	//
       
   718 	// Now add a text field to this.
       
   719 	TTestFieldFactory factory;
       
   720 	richText1->SetFieldFactory(&factory);
       
   721 	CTextField* field=NULL;
       
   722 	TInt x=0;
       
   723 	//add 255 fields
       
   724 	while(x<255)
       
   725 		{
       
   726 		TRAPD(ret,field=factory.NewFieldL(KDateTimeFieldUid));
       
   727 		test(ret==KErrNone);
       
   728 		TRAP(ret,richText1->InsertFieldL(0,field,KDateTimeFieldUid));
       
   729 		test(ret==KErrNone);
       
   730 		TRAP(ret,richText1->UpdateFieldL(0));
       
   731 		test(ret==KErrNone);
       
   732 		x++;
       
   733 		}
       
   734 	// Save the rich text
       
   735 	//
       
   736 	CStoreMap* map=CStoreMap::NewLC(*TheStore);
       
   737 	richText1->StoreFieldComponentsL(*TheStore,*map);
       
   738 	//
       
   739 	RStoreWriteStream out1(*map);
       
   740 	TStreamId id1=out1.CreateLC(*TheStore);
       
   741 	//
       
   742 	richText1->ExternalizeFieldDataL(out1);
       
   743 	//
       
   744 	delete richText1;
       
   745 	out1.CommitL();
       
   746 	//
       
   747 	map->Reset();
       
   748 	CleanupStack::PopAndDestroy(2);  // map,out1
       
   749 	TheStore->CommitL();
       
   750 	//
       
   751 	// Load the rich text
       
   752 	CRichText* empty=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer);
       
   753 	empty->SetFieldFactory(&factory);
       
   754 	RStoreReadStream in;
       
   755 	in.OpenLC(*TheStore,id1);
       
   756 	empty->InternalizeFieldDataL(in);
       
   757 	CleanupStack::PopAndDestroy();  // in
       
   758 	//	
       
   759 	empty->RestoreFieldComponentsL(*TheStore);
       
   760 	test(empty->FieldCount()==255);
       
   761 	delete empty;
       
   762 	empty=NULL;
       
   763 	
       
   764 //
       
   765 //test 2: Test INC054540 fix for more than 255 fields
       
   766 //	
       
   767 	test.Next(_L("test for more than 255 fields"));
       
   768 	richText1=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer);
       
   769 	// Add the text fields
       
   770 	richText1->SetFieldFactory(&factory);
       
   771 	field=NULL;
       
   772 	x=0;
       
   773 	//add 256 fields
       
   774 	while(x<256)
       
   775 		{
       
   776 		TRAPD(ret,field=factory.NewFieldL(KDateTimeFieldUid));
       
   777 		test(ret==KErrNone);
       
   778 		TRAP(ret,richText1->InsertFieldL(0,field,KDateTimeFieldUid));
       
   779 		test(ret==KErrNone);
       
   780 		TRAP(ret,richText1->UpdateFieldL(0));
       
   781 		test(ret==KErrNone);
       
   782 		x++;
       
   783 		}
       
   784 	// Save the rich text
       
   785 	//
       
   786 	map=CStoreMap::NewLC(*TheStore);
       
   787 	richText1->StoreFieldComponentsL(*TheStore,*map);
       
   788 	//
       
   789 	RStoreWriteStream out2(*map);
       
   790 	id1=out2.CreateLC(*TheStore);
       
   791 	//
       
   792 	richText1->ExternalizeFieldDataL(out2);
       
   793 	//
       
   794 	delete richText1;
       
   795 	out2.CommitL();
       
   796 	//
       
   797 	map->Reset();	
       
   798 	CleanupStack::PopAndDestroy(2);  // map,out2
       
   799 	TheStore->CommitL();
       
   800 	//
       
   801 	// Load the rich text
       
   802 	empty=CRichText::NewL(GlobalParaFormatLayer,GlobalCharFormatLayer);
       
   803 	empty->SetFieldFactory(&factory);
       
   804 	in.OpenLC(*TheStore,id1);
       
   805 	empty->InternalizeFieldDataL(in);
       
   806 	CleanupStack::PopAndDestroy();  // in
       
   807 	//	
       
   808 	empty->RestoreFieldComponentsL(*TheStore);
       
   809 	test(empty->FieldCount()==256);
       
   810 	delete empty;
       
   811 	empty=NULL;
       
   812 	//
       
   813 	//
       
   814 	CleanupStack::PopAndDestroy();  // TheStore
       
   815 	test.End();
       
   816 	}
       
   817 
       
   818 
       
   819 LOCAL_C void doMainL()
       
   820 	{
       
   821 	GlobalParaFormatLayer=CParaFormatLayer::NewL();
       
   822 	GlobalCharFormatLayer=CCharFormatLayer::NewL();
       
   823 	theFs.Connect();
       
   824 	//
       
   825 	CustomLoadSave();
       
   826 	TestDEF101757();
       
   827 	TestINC054540();
       
   828 	//
       
   829 	delete GlobalParaFormatLayer;
       
   830 	delete GlobalCharFormatLayer;
       
   831 	theFs.Close();
       
   832 	}
       
   833 
       
   834 
       
   835 LOCAL_C void setupCleanup()
       
   836 //
       
   837 // Initialise the cleanup stack.
       
   838 //
       
   839     {
       
   840 	TheTrapCleanup=CTrapCleanup::New();
       
   841 	test(TheTrapCleanup!=NULL);
       
   842 	TRAPD(r,\
       
   843 		{\
       
   844 		for (TInt i=KTestCleanupStack;i>0;i--)\
       
   845 			CleanupStack::PushL((TAny*)0);\
       
   846 		CleanupStack::Pop(KTestCleanupStack);\
       
   847 		});
       
   848 	test(r==KErrNone);
       
   849 	}
       
   850 
       
   851 
       
   852 LOCAL_C void DeleteDataFile(const TDesC& aFullName)
       
   853 	{
       
   854 	RFs fsSession;
       
   855 	TInt err = fsSession.Connect();
       
   856 	if(err == KErrNone)
       
   857 		{
       
   858 		TEntry entry;
       
   859 		if(fsSession.Entry(aFullName, entry) == KErrNone)
       
   860 			{
       
   861 			RDebug::Print(_L("Deleting \"%S\" file.\n"), &aFullName);
       
   862 			err = fsSession.SetAtt(aFullName, 0, KEntryAttReadOnly);
       
   863 			if(err != KErrNone) 
       
   864 				{
       
   865 				RDebug::Print(_L("Error %d changing \"%S\" file attributes.\n"), err, &aFullName);
       
   866 				}
       
   867 			err = fsSession.Delete(aFullName);
       
   868 			if(err != KErrNone) 
       
   869 				{
       
   870 				RDebug::Print(_L("Error %d deleting \"%S\" file.\n"), err, &aFullName);
       
   871 				}
       
   872 			}
       
   873 		fsSession.Close();
       
   874 		}
       
   875 	else
       
   876 		{
       
   877 		RDebug::Print(_L("Error %d connecting file session. File: %S.\n"), err, &aFullName);
       
   878 		}
       
   879 	}
       
   880 
       
   881 GLDEF_C TInt E32Main()
       
   882 //
       
   883 // Test permanent file TheStore.
       
   884 //
       
   885     {
       
   886 	test.Title();
       
   887 	setupCleanup();
       
   888 	__UHEAP_MARK;
       
   889 //
       
   890 	test.Start(_L("Testing custom save/load optimization"));
       
   891 	TRAPD(ret,doMainL());	
       
   892 	test(ret==KErrNone);
       
   893 	
       
   894 	::DeleteDataFile(KTRtCustOutputFile); 	//deletion of data files must be before call to End() - DEF047652
       
   895 	test.End();
       
   896 //
       
   897 	__UHEAP_MARKEND;
       
   898 	delete TheTrapCleanup;
       
   899 	test.Close();
       
   900 
       
   901 	return KErrNone;
       
   902     }
       
   903