|
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 |