textrendering/texthandling/ttext/T_parse.cpp
changeset 0 1fb32624e06b
child 51 a7c938434754
equal deleted inserted replaced
-1:000000000000 0:1fb32624e06b
       
     1 /*
       
     2 * Copyright (c) 1999-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 * TPARSE.CPP
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 #include <e32test.h>
       
    21 #include <txtrich.h>
       
    22 #include <e32math.h>
       
    23 #include "T_parse.h"
       
    24 
       
    25 LOCAL_D CTrapCleanup* TrapCleanup;
       
    26 LOCAL_D RTest test(_L("Testing EText parser system"));
       
    27 LOCAL_D const TInt KTestCleanupStack=0x200;
       
    28 
       
    29 
       
    30 CTestParser* CTestParser::NewL()
       
    31 	{
       
    32 	CTestParser* self = new (ELeave) CTestParser;
       
    33 	CleanupStack::PushL(self);
       
    34 	self->iDoItText = HBufC::NewL(128);
       
    35 	*(self->iDoItText) = _L("Or is it just undead?");
       
    36 	CleanupStack::Pop();
       
    37 	return self;
       
    38 	}
       
    39 
       
    40 
       
    41 CTestParser::CTestParser()
       
    42 	{
       
    43 	}
       
    44 
       
    45 
       
    46 CTestParser::~CTestParser()
       
    47 	{
       
    48 	delete iDoItText;
       
    49 	}
       
    50 
       
    51 
       
    52 TBool CTestParser::ParseThisText(const CRichText& aTextObj, TBool aAllowBack,
       
    53 									TInt aStartScan, TInt aScanLength,
       
    54 									TInt& aStartTag, TInt& aTagLength)
       
    55 	{
       
    56 	// Very simple - looking for the phrase "the world"
       
    57 	_LIT(targetText, "TARGET");
       
    58 	TInt length = 6;
       
    59 	// Consider that the start of the scan may be part way through
       
    60 	// the item that we are looking for, so see if we need to move back
       
    61 	TInt start = aStartScan;
       
    62 	if (aAllowBack)
       
    63 		{
       
    64 		if (start >= length - 1)
       
    65 			start -= length - 1;
       
    66 		else
       
    67 			start = 0;
       
    68 		}
       
    69 	// And it might go beyond the end of the scan
       
    70 	TInt end = aStartScan + aScanLength;
       
    71 	if (end + length - 1 <= aTextObj.DocumentLength())
       
    72 		end += length - 1;
       
    73 	else
       
    74 		end = aTextObj.DocumentLength();
       
    75 	while (end - start >= length)
       
    76 		{
       
    77 		TPtrC buffer = aTextObj.Read(start, end - start);
       
    78 		TInt segmentLength= buffer.Length();
       
    79 
       
    80 		if (segmentLength >= length)	// There's enough text to bother searching
       
    81 			{
       
    82 			TInt result = buffer.FindF(targetText);
       
    83 			if (result != KErrNotFound)	// We found it
       
    84 				{
       
    85 				aStartTag = start + result;
       
    86 				aTagLength = length;
       
    87 				return ETrue;
       
    88 				}
       
    89 			}
       
    90 		if (end == start + segmentLength)	// There's no more text at all
       
    91 			break;
       
    92 		// The buffer is segmented and there's another segment 
       
    93 
       
    94 		// It could be over the segment boundary
       
    95 		TInt start2 = start + segmentLength;
       
    96 		TInt end2 = start2;
       
    97 		if (segmentLength >= length - 1)
       
    98 			start2 -= length - 1;
       
    99 		else start2 = start;
       
   100 		if (end >= end2 + length - 1)
       
   101 			end2 += length -1;
       
   102 		else
       
   103 			end2 = end;
       
   104 		if (end2 - start2 >= length)
       
   105 			{
       
   106 			// Create a buffer with the end of one and the start of the other
       
   107 			TBuf<10> bridgeBuffer;
       
   108 			aTextObj.Extract(bridgeBuffer, start2, end2 - start2);
       
   109 			TInt result = bridgeBuffer.FindF(targetText);
       
   110 			if (result != KErrNotFound)	// We found it
       
   111 				{
       
   112 				aStartTag = start2 + result;
       
   113 				aTagLength = length;
       
   114 				return ETrue;
       
   115 				}
       
   116 			}
       
   117 
       
   118 		// Move start up for next segment
       
   119 		start += segmentLength;
       
   120 		}
       
   121 		return EFalse;	// Not enough text left in buffer
       
   122 	}
       
   123 
       
   124 
       
   125 const TDesC& CTestParser::CreateDoItText(const CRichText& /* aTextObj */,
       
   126 							TInt /* aStartText */, TInt /* aLength */)
       
   127 	{
       
   128 	return *iDoItText;
       
   129 	}
       
   130 
       
   131 
       
   132 void CTestParser::ActivateThisTextL(const CRichText& /* aTextObj */,
       
   133 					  TInt /* aStartText */, TInt /* aLength */)
       
   134 	{
       
   135 	// Do something?
       
   136 
       
   137 	}
       
   138 
       
   139 
       
   140 void CTestParser::GetRecogniseFormat(TCharFormat& aFormat)
       
   141 	{
       
   142 	aFormat.iFontPresentation.iTextColor = KRgbRed;
       
   143 	aFormat.iFontPresentation.iUnderline = EUnderlineOn;
       
   144 	}
       
   145 
       
   146 
       
   147 void CTestParser::GetRolloverFormat(TCharFormat& aFormat)
       
   148 	{
       
   149 	aFormat.iFontPresentation.iTextColor = KRgbRed;
       
   150 	aFormat.iFontPresentation.iUnderline = EUnderlineOn;
       
   151 	aFormat.iFontPresentation.iHighlightColor = KRgbDarkRed;
       
   152 	aFormat.iFontPresentation.iHighlightStyle = TFontPresentation::EFontHighlightRounded;
       
   153 	}
       
   154 
       
   155 
       
   156 void CTestParser::Release()
       
   157 	{
       
   158 	delete this;
       
   159 	}
       
   160 
       
   161 //--------------------------------------------
       
   162 
       
   163 CTestParser2* CTestParser2::NewL()
       
   164 	{
       
   165 	CTestParser2* self = new (ELeave) CTestParser2;
       
   166 	CleanupStack::PushL(self);
       
   167 	self->iDoItText = HBufC::NewL(128);
       
   168 	*(self->iDoItText) = _L("Or is it just undead?");
       
   169 	CleanupStack::Pop();
       
   170 	return self;
       
   171 	}
       
   172 
       
   173 
       
   174 CTestParser2::CTestParser2()
       
   175 	{
       
   176 	}
       
   177 
       
   178 
       
   179 CTestParser2::~CTestParser2()
       
   180 	{
       
   181 	delete iDoItText;
       
   182 	}
       
   183 
       
   184 
       
   185 TBool CTestParser2::ParseThisText(const CRichText& aTextObj, TBool aAllowBack,
       
   186 									TInt aStartScan, TInt aScanLength,
       
   187 									TInt& aStartTag, TInt& aTagLength)
       
   188 	{
       
   189 	// Very simple - looking for the phrase "ARG"
       
   190 	_LIT(targetText, "ARG");
       
   191 	TInt length = 3;
       
   192 	// Consider that the start of the scan may be part way through
       
   193 	// the item that we are looking for, so see if we need to move back
       
   194 	TInt start = aStartScan;
       
   195 	if (aAllowBack)
       
   196 		{
       
   197 		if (start >= length - 1)
       
   198 			start -= length - 1;
       
   199 		else
       
   200 			start = 0;
       
   201 		}
       
   202 	// And it might go beyond the end of the scan
       
   203 	TInt end = aStartScan + aScanLength;
       
   204 	if (end + length - 1 <= aTextObj.DocumentLength())
       
   205 		end += length - 1;
       
   206 	else
       
   207 		end = aTextObj.DocumentLength();
       
   208 	while (end - start >= length)
       
   209 		{
       
   210 		TPtrC buffer = aTextObj.Read(start, end - start);
       
   211 		TInt segmentLength= buffer.Length();
       
   212 
       
   213 		if (segmentLength >= length)	// There's enough text to bother searching
       
   214 			{
       
   215 			TInt result = buffer.FindF(targetText);
       
   216 			if (result != KErrNotFound)	// We found it
       
   217 				{
       
   218 				aStartTag = start + result;
       
   219 				aTagLength = length;
       
   220 				return ETrue;
       
   221 				}
       
   222 			}
       
   223 		if (end == start + segmentLength)	// There's no more text at all
       
   224 			break;
       
   225 		// The buffer is segmented and there's another segment 
       
   226 
       
   227 		// It could be over the segment boundary
       
   228 		TInt start2 = start + segmentLength;
       
   229 		TInt end2 = start2;
       
   230 		if (segmentLength >= length - 1)
       
   231 			start2 -= length - 1;
       
   232 		else start2 = start;
       
   233 		if (end >= end2 + length - 1)
       
   234 			end2 += length -1;
       
   235 		else
       
   236 			end2 = end;
       
   237 		if (end2 - start2 >= length)
       
   238 			{
       
   239 			// Create a buffer with the end of one and the start of the other
       
   240 			TBuf<10> bridgeBuffer;
       
   241 			aTextObj.Extract(bridgeBuffer, start2, end2 - start2);
       
   242 			TInt result = bridgeBuffer.FindF(targetText);
       
   243 			if (result != KErrNotFound)	// We found it
       
   244 				{
       
   245 				aStartTag = start2 + result;
       
   246 				aTagLength = length;
       
   247 				return ETrue;
       
   248 				}
       
   249 			}
       
   250 
       
   251 		// Move start up for next segment
       
   252 		start += segmentLength;
       
   253 		}
       
   254 		return EFalse;	// Not enough text left in buffer
       
   255 	}
       
   256 
       
   257 
       
   258 const TDesC& CTestParser2::CreateDoItText(const CRichText& /* aTextObj */,
       
   259 							TInt /* aStartText */, TInt /* aLength */)
       
   260 	{
       
   261 	return *iDoItText;
       
   262 	}
       
   263 
       
   264 
       
   265 void CTestParser2::ActivateThisTextL(const CRichText& /* aTextObj */,
       
   266 					  TInt /* aStartText */, TInt /* aLength */)
       
   267 	{
       
   268 	// Do something?
       
   269 
       
   270 	}
       
   271 
       
   272 
       
   273 void CTestParser2::GetRecogniseFormat(TCharFormat& aFormat)
       
   274 	{
       
   275 	aFormat.iFontPresentation.iTextColor = KRgbRed;
       
   276 	aFormat.iFontPresentation.iUnderline = EUnderlineOn;
       
   277 	}
       
   278 
       
   279 
       
   280 void CTestParser2::GetRolloverFormat(TCharFormat& aFormat)
       
   281 	{
       
   282 	aFormat.iFontPresentation.iTextColor = KRgbRed;
       
   283 	aFormat.iFontPresentation.iUnderline = EUnderlineOn;
       
   284 	aFormat.iFontPresentation.iHighlightColor = KRgbDarkRed;
       
   285 	aFormat.iFontPresentation.iHighlightStyle = TFontPresentation::EFontHighlightRounded;
       
   286 	}
       
   287 
       
   288 
       
   289 void CTestParser2::Release()
       
   290 	{
       
   291 	delete this;
       
   292 	}
       
   293 
       
   294 
       
   295 //--------------------------------------------
       
   296 
       
   297 
       
   298 CEditObserver::CEditObserver()
       
   299 	{
       
   300 	iStart = 0;
       
   301 	iExtent = 0;
       
   302 	}
       
   303 
       
   304 
       
   305 CEditObserver::~CEditObserver()
       
   306 	{
       
   307 	}
       
   308 
       
   309 
       
   310 void CEditObserver::EditObserver(TInt aStart, TInt aExtent)
       
   311 	{
       
   312 	iStart = aStart;
       
   313 	iExtent = aExtent;
       
   314 	}
       
   315 
       
   316 
       
   317 void Test1()
       
   318 	{
       
   319 	test.Next(_L("Install 5, deinstall in reverse order"));
       
   320 	CTestParser* parser1 = CTestParser::NewL();
       
   321 	CTestParser* parser2 = CTestParser::NewL();
       
   322 	CTestParser* parser3 = CTestParser::NewL();
       
   323 	CTestParser* parser4 = CTestParser::NewL();
       
   324 	CTestParser* parser5 = CTestParser::NewL();
       
   325 	CRichText::ActivateParserL(parser1);	// List 1
       
   326 	CRichText::ActivateParserL(parser2);	// List 1, 2
       
   327 	CRichText::ActivateParserL(parser3);	// List 1, 2, 3
       
   328 	CRichText::ActivateParserL(parser4);	// List 1, 2, 3, 4
       
   329 	CRichText::ActivateParserL(parser5);	// List 1, 2, 3, 4, 5
       
   330 	CRichText::DeactivateParser(parser5);	// List 1, 2, 3, 4
       
   331 	CRichText::DeactivateParser(parser4);	// List 1, 2, 3
       
   332 	CRichText::DeactivateParser(parser3);	// List 1, 2
       
   333 	CRichText::DeactivateParser(parser2);	// List 1
       
   334 	CRichText::DeactivateParser(parser1);	// List empty
       
   335 	delete parser5;
       
   336 	delete parser4;
       
   337 	delete parser3;
       
   338 	delete parser2;
       
   339 	delete parser1;
       
   340 	CRichText::DeactivateParserDefaults();
       
   341 	}
       
   342 
       
   343 
       
   344 void Test2()
       
   345 	{
       
   346 	test.Next(_L("Install, deinstall in interleaved order"));
       
   347 	CTestParser* parser1 = CTestParser::NewL();
       
   348 	CRichText::ActivateParserL(parser1);	// List 1
       
   349 	CTestParser* parser2 = CTestParser::NewL();
       
   350 	CRichText::ActivateParserL(parser2);	// List 1, 2
       
   351 	// Remove first in list
       
   352 	CRichText::DeactivateParser(parser1);	// List 2
       
   353 	delete parser1;
       
   354 	CTestParser* parser3 = CTestParser::NewL();
       
   355 	CRichText::ActivateParserL(parser3);	// List 2, 3
       
   356 	// Remove last in list
       
   357 	CRichText::DeactivateParser(parser3);	// List 2
       
   358 	delete parser3;
       
   359 	CTestParser* parser4 = CTestParser::NewL();
       
   360 	CRichText::ActivateParserL(parser4);	// List 2, 4
       
   361 	CTestParser* parser5 = CTestParser::NewL();
       
   362 	CRichText::ActivateParserL(parser5);	// List 2, 4, 5
       
   363 	// Remove middle in list
       
   364 	CRichText::DeactivateParser(parser4);	// List 2, 5
       
   365 	delete parser4;
       
   366 	// Empty list
       
   367 	CRichText::DeactivateParser(parser5);	// List 2
       
   368 	delete parser5;
       
   369 	CRichText::DeactivateParser(parser2);	// List empty
       
   370 	delete parser2;
       
   371 	CRichText::DeactivateParserDefaults();
       
   372 	}
       
   373 
       
   374 
       
   375 void Test3()
       
   376 	{
       
   377 	test.Next(_L("Testing memory with OOM"));
       
   378 
       
   379 	TInt i;
       
   380 	TInt ret;
       
   381 	TInt count = 0;
       
   382 	TInt success = 0;
       
   383 
       
   384 	for (i = 0; i < 20; i++)
       
   385 		{
       
   386 		CTestParser* parser1 = NULL;
       
   387 		CTestParser* parser2 = NULL;
       
   388 		CTestParser* parser3 = NULL;
       
   389 		CTestParser* parser4 = NULL;
       
   390 		CTestParser* parser5 = NULL;
       
   391 		// Switch on memory problems, varying fail rate from 20 to 1
       
   392 		__UHEAP_SETFAIL(RHeap::EDeterministic, 20 - i);
       
   393 		__UHEAP_MARK;
       
   394 		count++;
       
   395 		TRAP(ret, parser1 = CTestParser::NewL());
       
   396 		if (ret != KErrNone)
       
   397 			{
       
   398 			parser1 = NULL;
       
   399 			}
       
   400 		else
       
   401 			{
       
   402 			TRAP(ret, CRichText::ActivateParserL(parser1));
       
   403 			if (ret != KErrNone)
       
   404 				{
       
   405 				delete parser1;
       
   406 				parser1 = NULL;
       
   407 				}
       
   408 			}
       
   409 		TRAP(ret, parser2 = CTestParser::NewL());
       
   410 		if (ret != KErrNone)
       
   411 			{
       
   412 			parser2 = NULL;
       
   413 			}
       
   414 		else
       
   415 			{
       
   416 			TRAP(ret, CRichText::ActivateParserL(parser2));
       
   417 			if (ret != KErrNone)
       
   418 				{
       
   419 				delete parser2;
       
   420 				parser2 = NULL;
       
   421 				}
       
   422 			}
       
   423 		TRAP(ret, parser3 = CTestParser::NewL());
       
   424 		if (ret != KErrNone)
       
   425 			{
       
   426 			parser3 = NULL;
       
   427 			}
       
   428 		else
       
   429 			{
       
   430 			TRAP(ret, CRichText::ActivateParserL(parser3));
       
   431 			if (ret != KErrNone)
       
   432 				{
       
   433 				delete parser3;
       
   434 				parser3 = NULL;
       
   435 				}
       
   436 			}
       
   437 		TRAP(ret, parser4 = CTestParser::NewL());
       
   438 		if (ret != KErrNone)
       
   439 			{
       
   440 			parser4 = NULL;
       
   441 			}
       
   442 		else
       
   443 			{
       
   444 			TRAP(ret, CRichText::ActivateParserL(parser4));
       
   445 			if (ret != KErrNone)
       
   446 				{
       
   447 				delete parser4;
       
   448 				parser4 = NULL;
       
   449 				}
       
   450 			}
       
   451 		TRAP(ret, parser5 = CTestParser::NewL());
       
   452 		if (ret != KErrNone)
       
   453 			{
       
   454 			parser5 = NULL;
       
   455 			}
       
   456 		else
       
   457 			{
       
   458 			TRAP(ret, CRichText::ActivateParserL(parser5));
       
   459 			if (ret != KErrNone)
       
   460 				{
       
   461 				delete parser5;
       
   462 				parser5 = NULL;
       
   463 				}
       
   464 			}
       
   465 		if (parser1)
       
   466 			{
       
   467 			success++;
       
   468 			CRichText::DeactivateParser(parser1);
       
   469 			delete parser1;
       
   470 			}
       
   471 		if (parser2)
       
   472 			{
       
   473 			success++;
       
   474 			CRichText::DeactivateParser(parser2);
       
   475 			delete parser2;
       
   476 			}
       
   477 		if (parser3)
       
   478 			{
       
   479 			success++;
       
   480 			CRichText::DeactivateParser(parser3);
       
   481 			delete parser3;
       
   482 			}
       
   483 		if (parser4)
       
   484 			{
       
   485 			success++;
       
   486 			CRichText::DeactivateParser(parser4);
       
   487 			delete parser4;
       
   488 			}
       
   489 		if (parser5)
       
   490 			{
       
   491 			success++;
       
   492 			CRichText::DeactivateParser(parser5);
       
   493 			delete parser5;
       
   494 			}
       
   495 		CRichText::DeactivateParserDefaults();
       
   496 		// Switch off memory problems
       
   497 		__UHEAP_MARKEND;
       
   498 		__UHEAP_RESET;
       
   499 		}
       
   500 
       
   501 	test.Printf(_L("%d attempted activations, %d successful\n"), 5 * count, success);
       
   502 	}
       
   503 
       
   504 
       
   505 void Test4()
       
   506 	{
       
   507 	// Create a block of 1000 chars
       
   508 	// Randomly insert a target string and check:
       
   509 	// - Can't find target that is not complete
       
   510 	// - Does find complete target in right place
       
   511 	// - Once target is removed, can't find it
       
   512 	// repeat x 100
       
   513 	test.Next(_L("Testing EText behaviour with active parsers and single target"));
       
   514 	// Create and activate a parser
       
   515 	CTestParser* parser1 = CTestParser::NewL();
       
   516 	CRichText::ActivateParserL(parser1);
       
   517 	// Create a CRichText
       
   518 	CParaFormatLayer* GlobalParaFormatLayer = CParaFormatLayer::NewL();
       
   519 	CCharFormatLayer* GlobalCharFormatLayer = CCharFormatLayer::NewL();
       
   520 	CRichText* richText = CRichText::NewL(GlobalParaFormatLayer, GlobalCharFormatLayer, CEditableText::ESegmentedStorage, CEditableText::EDefaultTextGranularity);
       
   521 	richText->SetPictureFactory(NULL, NULL);  // forces index generation
       
   522 	// Switch on parsers for this CRichText
       
   523 	CEditObserver* editObserver = new (ELeave) CEditObserver;
       
   524 	richText->SetEditObserver(editObserver);
       
   525 
       
   526 	// Insert 1000 chars (repeated string)
       
   527 	TInt i;
       
   528 	for (i = 0; i < 100; i++)
       
   529 		richText->InsertL(richText->DocumentLength(), _L("abcdefghij"));
       
   530 	TInt64 seed = 314159;
       
   531 	TInt startTags;
       
   532 	TInt lengthTags;
       
   533 	for (i = 0; i < 100; i++)
       
   534 		{
       
   535 		// Get a random in range 0-999
       
   536 		TInt random = Math::Rand(seed) % 1000;
       
   537 		// "Randomly" insert target string that is not complete
       
   538 		richText->InsertL(random, _L("TARGE"));
       
   539 		test(!richText->ParseText(startTags, lengthTags, EFalse));
       
   540 		test(!richText->ParseText(startTags, lengthTags, ETrue));
       
   541 		// Complete target string and check we find single target where we expect
       
   542 		richText->InsertL(random + 5, 'T');
       
   543 		test(richText->ParseText(startTags, lengthTags, EFalse));
       
   544 		test((startTags == random) && (lengthTags == 6));
       
   545 		test(richText->ParseText(startTags, lengthTags, ETrue));
       
   546 		test((startTags == random) && (lengthTags == 6));
       
   547 		// Completely remove target string
       
   548 		richText->DeleteL(random, 6);
       
   549 		test(!richText->ParseText(startTags, lengthTags, EFalse));
       
   550 		test(!richText->ParseText(startTags, lengthTags, ETrue));
       
   551 		}
       
   552 
       
   553 	// Clean up
       
   554 
       
   555 	delete richText;
       
   556 	delete GlobalCharFormatLayer;
       
   557 	delete GlobalParaFormatLayer;
       
   558 	CRichText::DeactivateParser(parser1);
       
   559 	delete parser1;
       
   560 	CRichText::DeactivateParserDefaults();
       
   561 	delete editObserver;
       
   562 	}
       
   563 
       
   564 
       
   565 void Test5()
       
   566 	{
       
   567 	// Create a block of 1000 chars
       
   568 	// Randomly insert two target strings and check:
       
   569 	// - Can't find targets that are not complete
       
   570 	// - Does find complete targets with exact range covered
       
   571 	// - Once targets are removed, can't find it
       
   572 	// repeat x 100
       
   573 	test.Next(_L("Testing EText behaviour with active parsers and double target"));
       
   574 	// Create and activate a parser
       
   575 	CTestParser* parser1 = CTestParser::NewL();
       
   576 	CRichText::ActivateParserL(parser1);
       
   577 	// Create a CRichText
       
   578 	CParaFormatLayer* GlobalParaFormatLayer = CParaFormatLayer::NewL();
       
   579 	CCharFormatLayer* GlobalCharFormatLayer = CCharFormatLayer::NewL();
       
   580 	CRichText* richText = CRichText::NewL(GlobalParaFormatLayer, GlobalCharFormatLayer, CEditableText::ESegmentedStorage, CEditableText::EDefaultTextGranularity);
       
   581 	richText->SetPictureFactory(NULL, NULL);  // forces index generation
       
   582 	// Switch on parsers for this CRichText
       
   583 	CEditObserver* editObserver = new (ELeave) CEditObserver;
       
   584 	richText->SetEditObserver(editObserver);
       
   585 
       
   586 	// Insert 1000 chars (repeated string)
       
   587 	TInt i;
       
   588 	for (i = 0; i < 100; i++)
       
   589 		richText->InsertL(richText->DocumentLength(), _L("abcdefghij"));
       
   590 	TInt64 seed1 = 314159;
       
   591 	TInt startTags;
       
   592 	TInt lengthTags;
       
   593 	for (i = 0; i < 100; i++)
       
   594 		{
       
   595 		// Get a random in range 0-999
       
   596 		TInt random1 = Math::Rand(seed1) % 1000;
       
   597 		TInt random2 = Math::Rand(seed1) % 1000;
       
   598 		TInt rlow = (random1 < random2) ? random1 : random2;
       
   599 		TInt rhigh = (random1 > random2) ? random1 : random2;
       
   600 		if (rlow + 7 > rhigh)
       
   601 			{ // Too close, spread them out
       
   602 			if (rhigh + 7 <= richText->DocumentLength())
       
   603 				rhigh += 7;
       
   604 			else
       
   605 				rlow -= 7;
       
   606 			}
       
   607 		// "Randomly" insert target strings that are not complete
       
   608 		richText->InsertL(rlow, _L("TARGE"));
       
   609 		richText->InsertL(rhigh - 1, _L("TARGE"));
       
   610 		test(!richText->ParseText(startTags, lengthTags, EFalse));
       
   611 		test(!richText->ParseText(startTags, lengthTags, ETrue));
       
   612 		// Complete target string and check we find single target where we expect
       
   613 		richText->InsertL(rlow + 5, 'T');
       
   614 		richText->InsertL(rhigh + 5, 'T');
       
   615 		test(richText->ParseText(startTags, lengthTags, EFalse));
       
   616 		test((startTags == rlow) && (lengthTags == rhigh + 6 - rlow));
       
   617 		test(richText->ParseText(startTags, lengthTags, ETrue));
       
   618 		test((startTags == rlow) && (lengthTags == rhigh + 6 - rlow));
       
   619 		// Completely remove target string
       
   620 		richText->DeleteL(rhigh, 6);
       
   621 		richText->DeleteL(rlow, 6);
       
   622 		test(!richText->ParseText(startTags, lengthTags, EFalse));
       
   623 		test(!richText->ParseText(startTags, lengthTags, ETrue));
       
   624 		}
       
   625 
       
   626 	// Clean up
       
   627 
       
   628 	delete richText;
       
   629 	delete GlobalCharFormatLayer;
       
   630 	delete GlobalParaFormatLayer;
       
   631 	CRichText::DeactivateParser(parser1);
       
   632 	delete parser1;
       
   633 	CRichText::DeactivateParserDefaults();
       
   634 	delete editObserver;
       
   635 	}
       
   636 
       
   637 /**
       
   638 @SYMTestCaseID          SYSLIB-ETEXT-UT-3405
       
   639 @SYMTestCaseDesc	    Test for the fix for when CRichText crashes when parsers are active
       
   640 @SYMTestPriority 	    Medium
       
   641 @SYMTestActions  	    Calls PositionOfNextTag on all available document positions to validate fix.
       
   642 @SYMTestExpectedResults Test must be able to call PositionOfNextTag on all document positions
       
   643 @SYMDEF                 PDEF102494
       
   644 */	
       
   645 
       
   646 void Test6()
       
   647 	{
       
   648 	test.Next(_L(" @SYMTestCaseID:SYSLIB-ETEXT-UT-3405 Calling PositionOfNextTag on an empty document "));
       
   649 	
       
   650 	// Create and activate a parser
       
   651 	CTestParser* parser1 = CTestParser::NewL();
       
   652 	CRichText::ActivateParserL(parser1);
       
   653 	// Create a CRichText
       
   654 	CParaFormatLayer* GlobalParaFormatLayer = CParaFormatLayer::NewL();
       
   655 	CCharFormatLayer* GlobalCharFormatLayer = CCharFormatLayer::NewL();
       
   656 	CRichText* richText = CRichText::NewL(GlobalParaFormatLayer, GlobalCharFormatLayer, CEditableText::ESegmentedStorage, CEditableText::EDefaultTextGranularity);
       
   657 	richText->SetPictureFactory(NULL, NULL);  // forces index generation
       
   658 	// Switch on parsers for this CRichText
       
   659 	CEditObserver* editObserver = new (ELeave) CEditObserver;
       
   660 	richText->SetEditObserver(editObserver);
       
   661 
       
   662 	//insert and format some text
       
   663 	richText->InsertL(richText->DocumentLength(), _L("abcdTARGET"));
       
   664 
       
   665 	TCharFormat charFormat;
       
   666 	TCharFormatMask charFormatMask;
       
   667 
       
   668 	richText->ApplyCharFormatL(charFormat, charFormatMask, 0, richText->DocumentLength());
       
   669 
       
   670 	TInt startTags;
       
   671 	TInt lengthTags;
       
   672 	richText->ParseText(startTags, lengthTags, ETrue);
       
   673 
       
   674     // Call position of next tag on all document positions
       
   675 	for (TInt i = 0; i <= richText->DocumentLength(); i++)
       
   676 		{
       
   677 		richText->PositionOfNextTag(i, parser1);
       
   678 		}
       
   679 	
       
   680 	// Clean up
       
   681 
       
   682 	delete richText;
       
   683 	delete GlobalCharFormatLayer;
       
   684 	delete GlobalParaFormatLayer;
       
   685 	CRichText::DeactivateParser(parser1);
       
   686 	delete parser1;
       
   687 	CRichText::DeactivateParserDefaults();
       
   688 	delete editObserver;
       
   689 	}
       
   690 
       
   691 /**
       
   692 @SYMTestCaseID          SYSLIB-ETEXT-UT-3406
       
   693 @SYMTestCaseDesc	    Test for the fix for when CRichText crashes when parsers are active
       
   694 @SYMTestPriority 	    Medium
       
   695 @SYMTestActions  	    Initialize two parsers. First parser has a target string of "TARGET",
       
   696                         and the second parser has a target string of "ARG". By parsing the
       
   697                         two overlapping (ARG is contained in TARGET) target strings, the changes
       
   698 						for this defect have full coverage.
       
   699 @SYMTestExpectedResults Test must be able to call PositionOfNextTag on the end of document positions
       
   700 @SYMDEF                 PDEF102494
       
   701 */
       
   702 void Test7()
       
   703 	{
       
   704 	test.Next(_L(" @SYMTestCaseID:SYSLIB-ETEXT-UT-3406 Testing EText behaviour with active parsers and single target "));
       
   705 	
       
   706 	// Create and activate a parser
       
   707 	CTestParser* parser1 = CTestParser::NewL();
       
   708 	CRichText::ActivateParserL(parser1);
       
   709 	CTestParser2* parser2 = CTestParser2::NewL();
       
   710 	CRichText::ActivateParserL(parser2);
       
   711 	// Create a CRichText
       
   712 	CParaFormatLayer* GlobalParaFormatLayer = CParaFormatLayer::NewL();
       
   713 	CCharFormatLayer* GlobalCharFormatLayer = CCharFormatLayer::NewL();
       
   714 	CRichText* richText = CRichText::NewL(GlobalParaFormatLayer, GlobalCharFormatLayer, CEditableText::ESegmentedStorage, CEditableText::EDefaultTextGranularity);
       
   715 	richText->SetPictureFactory(NULL, NULL);  // forces index generation
       
   716 	// Switch on parsers for this CRichText
       
   717 	CEditObserver* editObserver = new (ELeave) CEditObserver;
       
   718 	richText->SetEditObserver(editObserver);
       
   719 
       
   720 	// Insert 1000 chars (repeated string)
       
   721 	TInt i;
       
   722 	for (i = 0; i < 100; i++)
       
   723 		richText->InsertL(richText->DocumentLength(), _L("abcdefghij"));
       
   724 
       
   725 	TInt startTags;
       
   726 	TInt lengthTags;
       
   727 	TInt startPosition = 0;
       
   728 	
       
   729 	// Run test twice, once at start of string, once at end.
       
   730 	for (TInt i=0;i < 2;i++)
       
   731 		{
       
   732 		//Insert target string that is not complete (for code coverage purposes).
       
   733 		richText->InsertL(startPosition, _L("TARGE"));
       
   734 		// Parse range provided only. Parser two will set it's parser tags on "ARG".
       
   735 		test(richText->ParseText(startTags, lengthTags, EFalse));
       
   736 		// Ensure this call does not fail at end of document (anymore). This gets
       
   737 		// the position of the next tag at the end of document position. Should
       
   738 		// be none found at end of document.
       
   739 		test((richText->PositionOfNextTag(richText->DocumentLength(), parser1)) == -1);
       
   740 		
       
   741 		// Parse all text (for coverage purposes). This will first clear all tags,
       
   742 		// and then re-applies the tags again on "ARG"
       
   743 		test(richText->ParseText(startTags, lengthTags, ETrue));
       
   744 		test((richText->PositionOfNextTag(richText->DocumentLength(), parser1)) == -1);
       
   745 		
       
   746 		// Complete target string. The purpose of completing the target string
       
   747 		// here is for code coverage. The text has changed and the code path in 
       
   748 		// parselst.cpp will change.
       
   749 		richText->InsertL(startPosition + 5, 'T');
       
   750 
       
   751 		// Parse range provided only. The tags on "ARG" are considered
       
   752 		// lower precendence, so this will clear the parser tags on "ARG" and 
       
   753 		// will apply the parser tags on "TARGET". 
       
   754 		test(richText->ParseText(startTags, lengthTags, EFalse));
       
   755 		test((richText->PositionOfNextTag(richText->DocumentLength(), parser1)) == -1);
       
   756 				
       
   757 		// Completely remove target string
       
   758 		richText->DeleteL(startPosition, 6);
       
   759 		test(!richText->ParseText(startTags, lengthTags, EFalse));
       
   760 		test(!richText->ParseText(startTags, lengthTags, ETrue));
       
   761 		
       
   762 		startPosition = richText->DocumentLength();
       
   763 		}
       
   764 
       
   765 	// Clean up
       
   766 
       
   767 	delete richText;
       
   768 	delete GlobalCharFormatLayer;
       
   769 	delete GlobalParaFormatLayer;
       
   770 	CRichText::DeactivateParser(parser1);
       
   771 	delete parser1;
       
   772 	CRichText::DeactivateParser(parser2);
       
   773 	delete parser2;
       
   774 	CRichText::DeactivateParserDefaults();
       
   775 	delete editObserver;
       
   776 	}
       
   777 
       
   778 
       
   779 TInt E32Main()
       
   780 	{
       
   781 	TrapCleanup = CTrapCleanup::New();
       
   782 	TRAPD(r,\
       
   783 		{\
       
   784 		for (TInt i=KTestCleanupStack;i>0;i--)\
       
   785 			CleanupStack::PushL((TAny*)1);\
       
   786 		test(r==KErrNone);\
       
   787 		CleanupStack::Pop(KTestCleanupStack);\
       
   788 		});
       
   789     test(r == KErrNone);
       
   790 	test.Title();
       
   791 
       
   792 	test.Start(_L("Testing memory under normal conditions"));
       
   793 	TInt ret;
       
   794 
       
   795 	__UHEAP_MARK;
       
   796 	TRAP(ret, Test1());
       
   797     test(ret == KErrNone);
       
   798 	__UHEAP_MARKEND;
       
   799 
       
   800 	__UHEAP_MARK;
       
   801 	TRAP(ret, Test2());
       
   802     test(ret == KErrNone);
       
   803 	__UHEAP_MARKEND;
       
   804 
       
   805 	__UHEAP_MARK;
       
   806 	TRAP(ret, Test3());
       
   807     test(ret == KErrNone);
       
   808 	__UHEAP_MARKEND;
       
   809 
       
   810 	__UHEAP_MARK;
       
   811 	TRAP(ret, Test4());
       
   812     test(ret == KErrNone);
       
   813 	__UHEAP_MARKEND;
       
   814 
       
   815 	__UHEAP_MARK;
       
   816 	TRAP(ret, Test5());
       
   817     test(ret == KErrNone);
       
   818 	__UHEAP_MARKEND;
       
   819 
       
   820 	__UHEAP_MARK;
       
   821 	TRAP(ret, Test6());
       
   822     test(ret == KErrNone);
       
   823 	__UHEAP_MARKEND;
       
   824 	
       
   825 	__UHEAP_MARK;
       
   826 	TRAP(ret, Test7());
       
   827     test(ret == KErrNone);
       
   828 	__UHEAP_MARKEND;
       
   829 	
       
   830 	delete TrapCleanup;
       
   831 
       
   832 	test.End();
       
   833 	test.Close();
       
   834 	return 0;
       
   835 	}