os/textandloc/textrendering/textformatting/test/src/TUndo.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /*
     2 * Copyright (c) 2000-2010 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 * TUndo.cpp test file for UndoSystem classes
    16 *
    17 */
    18 
    19 
    20 #include <e32test.h>
    21 
    22 #include "UndoSystem.h"
    23 #include "UndoSystemImpl.h"
    24 #include "EditorUndo.h"
    25 #include "EditorPlainTextUndo.h"
    26 #include <txtetext.h>
    27 #include <conpics.h>
    28 #include <s32mem.h>
    29 #include <s32ucmp.h>
    30 #include "TGraphicsContext.h"
    31 #include "form_and_etext_editor.h"
    32 
    33 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
    34 #include <txtclipboard.h>
    35 #include "txtfmlyr_internal.h"
    36 #endif
    37 
    38 #include "tundo.h"
    39 
    40 #define UNUSED_VAR(a) a = a
    41 
    42 using namespace UndoSystem;
    43 
    44 namespace
    45 {
    46 CTUndoStep* TestStep = NULL;
    47 #define TESTPOINT(p) TestStep->testpoint(p,(TText8*)__FILE__,__LINE__)
    48 #define TESTPRINT(p) TestStep->print(p,(TText8*)__FILE__,__LINE__)
    49 }
    50 
    51 //
    52 //
    53 //  logger
    54 //
    55 //
    56 
    57 class CLogger : public CBase
    58 	{
    59 public:
    60 	virtual void Output(const TDesC& aText) = 0;
    61 	void Output(TInt a)
    62 		{
    63 		TBuf<16> num(_L("<"));
    64 		num.AppendNum(a);
    65 		num.Append(_L(">"));
    66 		Output(num);
    67 		}
    68 	};
    69 
    70 namespace
    71 {
    72 CLogger& operator<<(CLogger& aLog, const TDesC& aText)
    73 	{
    74 	aLog.Output(aText);
    75 	return aLog;
    76 	}
    77 CLogger& operator<<(CLogger& aLog, TInt aVal)
    78 	{
    79 	aLog.Output(aVal);
    80 	return aLog;
    81 	}
    82 }
    83 
    84 class CCheckingLogger : public CLogger
    85 	{
    86 	const TDesC*	iCheck;
    87 	TInt			iPos;
    88 	TBool			iFailed;
    89 public:
    90 	void SetCheckString(const TDesC& aCheck) { iCheck = &aCheck; iPos = 0; iFailed = EFalse; }
    91 	TBool Failed() { return iFailed; }
    92 	TBool Passed() { return !iFailed && iCheck && iCheck->Length() == iPos; }
    93 	void Output(const TDesC& aText)
    94 		{
    95 		if (!iCheck || iFailed)
    96 			return;
    97 		TInt length = aText.Length();
    98 		TInt maxLength = iCheck->Length() - iPos;
    99 		TPtrC mid = iCheck->Mid(iPos, length < maxLength? length : maxLength);
   100 		if (aText.Compare(mid) != 0)
   101 			iFailed = ETrue;
   102 		else
   103 			iPos += aText.Length();
   104 		}
   105 	};
   106 
   107 class CStoringLogger : public CLogger
   108 	{
   109 	HBufC*	iStore;
   110 	TInt	iMaxLength;
   111 public:
   112 	~CStoringLogger() { delete iStore; }
   113 	HBufC* GetStore() { HBufC* r = iStore; iStore = 0; iMaxLength = 0; return r; }
   114 	void Output(const TDesC& aText)
   115 		{
   116 		if (!iStore)
   117 			{
   118 			iStore = HBufC::NewL(50);
   119 			iMaxLength = 50;
   120 			}
   121 		while (iMaxLength < aText.Length() + iStore->Length())
   122 			{
   123 			iMaxLength *= 2;
   124 			iStore = iStore->ReAllocL(iMaxLength);
   125 			}
   126 		iStore->Des().Append(aText);
   127 		};
   128 	};
   129 
   130 //
   131 //
   132 //  commands
   133 //
   134 //
   135 
   136 // internal commands
   137 class CCommandOffset;
   138 class CCommandToggle;
   139 class CTestCommand : public CSingleCommand
   140 	{
   141 public:
   142 	TUid FamilyUid() const
   143 		{
   144 		return TUid::Uid(12345);
   145 		}
   146 	virtual CCommandOffset* CastToCCommandOffset() { return 0; }
   147 	virtual CCommandToggle* CastToCCommandToggle() { return 0; }
   148 	};
   149 
   150 // Offset
   151 class CCommandOffset : public CTestCommand
   152 	{
   153 	TInt	iOffset;
   154 	TInt*	iTarget;
   155 	CLogger* iLogger;
   156 	CCommandOffset() {}
   157 public:
   158 	static CCommandOffset* NewL(TInt aOffset, TInt* aTarget, CLogger* aLogger = 0)
   159 		{
   160 		CCommandOffset* r = new(ELeave) CCommandOffset;
   161 		r->iOffset = aOffset;
   162 		r->iTarget = aTarget;
   163 		r->iLogger = aLogger;
   164 		return r;
   165 		}
   166 	void SetLogger(CLogger* aLogger) { iLogger = aLogger; }
   167 	TInt ExecuteL() const
   168 		{
   169 		if (iLogger)
   170 			(*iLogger) << _L("offset") << iOffset;
   171 		*iTarget += iOffset;
   172 		return KErrNone;
   173 		}
   174 	CCommand* CreateInverseL() const
   175 		{
   176 		return NewL(-iOffset, iTarget, iLogger);
   177 		}
   178 	void Add(TInt aOffset) { iOffset += aOffset; }
   179 	CCommandOffset* CastToCCommandOffset() { return this; }
   180 	};
   181 
   182 // Negate (only if iTog is ETrue!)
   183 class CCommandToggle : public CTestCommand
   184 	{
   185 	TBool iTog;
   186 	TInt* iTarget;
   187 	CLogger* iLogger;
   188 	CCommandToggle() {}
   189 public:
   190 	static CCommandToggle* NewL(TBool aTog, TInt* aTarget, CLogger* aLogger = 0)
   191 		{
   192 		CCommandToggle* r = new(ELeave) CCommandToggle;
   193 		r->iTog = aTog;
   194 		r->iTarget = aTarget;
   195 		r->iLogger = aLogger;
   196 		return r;
   197 		}
   198 	void SetLogger(CLogger* aLogger) { iLogger = aLogger; }
   199 	TInt ExecuteL() const
   200 		{
   201 		if (iLogger)
   202 			{
   203 			(*iLogger) << _L("negate") << (iTog? 1:0);
   204 			}
   205 		if (iTog)
   206 			*iTarget = -*iTarget;
   207 		return KErrNone;
   208 		}
   209 	CCommand* CreateInverseL() const
   210 		{
   211 		return NewL(iTog, iTarget, iLogger);
   212 		}
   213 	void Add(TBool aTog)
   214 		{
   215 		if (aTog)
   216 			iTog = !iTog;
   217 		}
   218 	CCommandToggle* CastToCCommandToggle() { return this; }
   219 	};
   220 
   221 // command prototypes
   222 class CCommandIncProto : public CTestCommand
   223 	{
   224 	TInt*		iTarget;
   225 	CLogger*	iLogger;
   226 	CCommandIncProto() {}
   227 public:
   228 	static CCommandIncProto* NewL(TInt* aTarget, CLogger* aLogger = 0)
   229 		{
   230 		CCommandIncProto* r = new(ELeave) CCommandIncProto;
   231 		r->iTarget = aTarget;
   232 		r->iLogger = aLogger;
   233 		return r;
   234 		}
   235 	TInt ExecuteL() const
   236 		{
   237 		if (iLogger)
   238 			(*iLogger) << _L("inc<>");
   239 		++*iTarget;
   240 		return KErrNone;
   241 		}
   242 	CCommand* CreateInverseL() const
   243 		{
   244 		return CCommandOffset::NewL(-1, iTarget, iLogger);
   245 		}
   246 	TBool PrepareToAddInverseToLastL(CSingleCommand& aLastCommand) const
   247 		{
   248 		if (aLastCommand.FamilyUid() != TUid::Uid(12345))
   249 			return EFalse;
   250 		return !!static_cast<CTestCommand&>(aLastCommand).CastToCCommandOffset();
   251 		}
   252 	void AddInverseToLast(CSingleCommand& aLastCommand) const
   253 		{
   254 		CCommandOffset* c =
   255 			static_cast<CTestCommand&>(aLastCommand).CastToCCommandOffset();
   256 		ASSERT(c);
   257 		c->Add(-1);
   258 		}
   259 	};
   260 
   261 class CCommandDecProto : public CTestCommand
   262 	{
   263 	TInt*		iTarget;
   264 	CLogger*	iLogger;
   265 	CCommandDecProto() {}
   266 public:
   267 	static CCommandDecProto* NewL(TInt* aTarget, CLogger* aLogger = 0)
   268 		{
   269 		CCommandDecProto* r = new(ELeave) CCommandDecProto;
   270 		r->iTarget = aTarget;
   271 		r->iLogger = aLogger;
   272 		return r;
   273 		}
   274 	TInt ExecuteL() const
   275 		{
   276 		if (iLogger)
   277 			(*iLogger) << _L("dec<>");
   278 		--*iTarget;
   279 		return KErrNone;
   280 		}
   281 	CCommand* CreateInverseL() const
   282 		{
   283 		return CCommandOffset::NewL(1, iTarget, iLogger);
   284 		}
   285 	TBool PrepareToAddInverseToLastL(CSingleCommand& aLastCommand) const
   286 		{
   287 		if (aLastCommand.FamilyUid() != TUid::Uid(12345))
   288 			return EFalse;
   289 		return !!static_cast<CTestCommand&>(aLastCommand).CastToCCommandOffset();
   290 		}
   291 	void AddInverseToLast(CSingleCommand& aLastCommand) const
   292 		{
   293 		CCommandOffset* c =
   294 			static_cast<CTestCommand&>(aLastCommand).CastToCCommandOffset();
   295 		ASSERT(c);
   296 		c->Add(1);
   297 		}
   298 	};
   299 
   300 class CCommandNegProto : public CTestCommand
   301 	{
   302 	TInt*		iTarget;
   303 	CLogger*	iLogger;
   304 	CCommandNegProto() {}
   305 public:
   306 	static CCommandNegProto* NewL(TInt* aTarget, CLogger* aLogger = 0)
   307 		{
   308 		CCommandNegProto* r = new(ELeave) CCommandNegProto;
   309 		r->iTarget = aTarget;
   310 		r->iLogger = aLogger;
   311 		return r;
   312 		}
   313 	TInt ExecuteL() const
   314 		{
   315 		if (iLogger)
   316 			(*iLogger) << _L("neg<>");
   317 		*iTarget = -*iTarget;
   318 		return KErrNone;
   319 		}
   320 	CCommand* CreateInverseL() const
   321 		{
   322 		return CCommandToggle::NewL(ETrue, iTarget, iLogger);
   323 		}
   324 	TBool PrepareToAddInverseToLastL(CSingleCommand& aLastCommand) const
   325 		{
   326 		if (aLastCommand.FamilyUid() != TUid::Uid(12345))
   327 			return EFalse;
   328 		return !!static_cast<CTestCommand&>(aLastCommand).CastToCCommandToggle();
   329 		}
   330 	void AddInverseToLast(CSingleCommand& aLastCommand) const
   331 		{
   332 		CCommandToggle* c =
   333 			static_cast<CTestCommand&>(aLastCommand).CastToCCommandToggle();
   334 		ASSERT(c);
   335 		c->Add(ETrue);
   336 		}
   337 	};
   338 
   339 // command whose inverse is a batch command
   340 class CCommandDecThenNegProto : public CTestCommand
   341 	{
   342 	TInt*		iTarget;
   343 	CLogger*	iLogger;
   344 	CCommandDecThenNegProto() {}
   345 public:
   346 	static CCommandDecThenNegProto* NewL(TInt* aTarget, CLogger* aLogger = 0)
   347 		{
   348 		CCommandDecThenNegProto* r = new(ELeave) CCommandDecThenNegProto;
   349 		r->iTarget = aTarget;
   350 		r->iLogger = aLogger;
   351 		return r;
   352 		}
   353 	TInt ExecuteL() const
   354 		{
   355 		if (iLogger)
   356 			(*iLogger) << _L("decneg<>");
   357 		*iTarget = -(*iTarget - 1);
   358 		return KErrNone;
   359 		}
   360 	CCommand* CreateInverseL() const
   361 		{
   362 		CBatchCommand* batch = CBatchCommand::NewLC();
   363 		batch->PushL(CCommandOffset::NewL(1, iTarget, iLogger));
   364 		batch->PushL(CCommandToggle::NewL(ETrue, iTarget, iLogger));
   365 		CleanupStack::Pop(batch);
   366 		return batch;
   367 		}
   368 	};
   369 
   370 class CCommandCannotDo : public CTestCommand
   371 	{
   372 	CLogger*	iLogger;
   373 public:
   374 	static CCommandCannotDo* NewL(CLogger* aLogger)
   375 		{
   376 		CCommandCannotDo* r = new(ELeave) CCommandCannotDo;
   377 		r->iLogger = aLogger;
   378 		return r;
   379 		}
   380 	TInt ExecuteL() const
   381 		{
   382 		if (iLogger)
   383 			(*iLogger) << _L("nodo<>");
   384 		return KErrNotSupported;
   385 		}
   386 	CCommand* CreateInverseL() const
   387 		{
   388 		return 0;
   389 		}
   390 	};
   391 
   392 class CCommandCannotInvert : public CTestCommand
   393 	{
   394 	CLogger*	iLogger;
   395 public:
   396 	static CCommandCannotInvert* NewL(CLogger* aLogger)
   397 		{
   398 		CCommandCannotInvert* r = new(ELeave) CCommandCannotInvert;
   399 		r->iLogger = aLogger;
   400 		return r;
   401 		}
   402 	TInt ExecuteL() const
   403 		{
   404 		if (iLogger)
   405 			(*iLogger) << _L("noinv<>");
   406 		return KErrNone;
   407 		}
   408 	CCommand* CreateInverseL() const
   409 		{
   410 		if (iLogger)
   411 			(*iLogger) << _L("noinvfail.");
   412 		User::Leave(KErrNotSupported);
   413 		return 0;
   414 		}
   415 	};
   416 
   417 class CCommandLeavesInvert : public CTestCommand
   418 	{
   419 	CLogger*	iLogger;
   420 public:
   421 	mutable TBool iFail;
   422 	static CCommandLeavesInvert* NewL(CLogger* aLogger)
   423 		{
   424 		CCommandLeavesInvert* r = new(ELeave) CCommandLeavesInvert;
   425 		r->iLogger = aLogger;
   426 		r->iFail = ETrue;
   427 		return r;
   428 		}
   429 	TInt ExecuteL() const
   430 		{
   431 		if (iLogger)
   432 			(*iLogger) << _L("leaveinv<>");
   433 		return KErrNone;
   434 		}
   435 	CCommand* CreateInverseL() const
   436 		{
   437 		if (iFail)
   438 			{
   439 			iFail = EFalse;
   440 			if (iLogger)
   441 				(*iLogger) << _L("noinvfail.");
   442 			User::Leave(KErrNotFound);
   443 			}
   444 		return 0;
   445 		}
   446 	};
   447 
   448 class CCommandNoMemory : public CTestCommand
   449 	{
   450 	CLogger*	iLogger;
   451 public:
   452 	TBool iFailInvert;
   453 	TBool iFailAddToLast;
   454 	TBool iFailExecute;
   455 	mutable TBool iLogExecuteFailed;
   456 
   457 	static CCommandNoMemory* NewL(CLogger* aLogger)
   458 		{
   459 		CCommandNoMemory* r = new(ELeave) CCommandNoMemory;
   460 		r->iLogger = aLogger;
   461 		r->iFailInvert		= ETrue;
   462 		r->iFailAddToLast	= ETrue;
   463 		r->iFailExecute		= ETrue;
   464 		r->iLogExecuteFailed= ETrue;
   465 		return r;
   466 		}
   467 	TInt ExecuteL() const
   468 		{
   469 		if (iFailExecute)
   470 			{
   471 			if (iLogger && iLogExecuteFailed)
   472 				(*iLogger) << _L("nomemfailexe.");
   473 			iLogExecuteFailed = EFalse;
   474 			User::Leave(KErrNoMemory);
   475 			}
   476 		if (iLogger)
   477 			(*iLogger) << _L("nomem<>");
   478 		return KErrNone;
   479 		}
   480 	CCommand* CreateInverseL() const
   481 		{
   482 		if (iFailInvert)
   483 			{
   484 			if (iLogger)
   485 				(*iLogger) << _L("nomemfailinv.");
   486 			User::Leave(KErrNoMemory);
   487 			}
   488 		return 0;
   489 		}
   490 	TBool PrepareToAddInverseToLastL(CSingleCommand&) const
   491 		{
   492 		if (iFailAddToLast)
   493 			{
   494 			if (iLogger)
   495 				(*iLogger) << _L("nomemfailadd.");
   496 			User::Leave(KErrNoMemory);
   497 			}
   498 		return EFalse;
   499 		}
   500 	};
   501 
   502 // this gatekeeper refuses non-undoable requests
   503 class CRefuserGatekeeper : public CBase, public MNotUndoableGatekeeper
   504 	{
   505 public:
   506 	TBool RetryOutOfMemoryL(TInt)
   507 		{
   508 		return EFalse;
   509 		}
   510 	TBool AllowNotUndoableL(TInt)
   511 		{
   512 		return EFalse;
   513 		}
   514 	};
   515 
   516 // this gatekeeper permits all non-undoable requests
   517 // (not just KErrNotSupported and KErrNoMemory)
   518 class CPermitterGatekeeper : public CBase, public MNotUndoableGatekeeper
   519 	{
   520 public:
   521 	TBool RetryOutOfMemoryL(TInt)
   522 		{
   523 		return EFalse;
   524 		}
   525 	TBool AllowNotUndoableL(TInt)
   526 		{
   527 		return ETrue;
   528 		}
   529 	};
   530 
   531 // this gatekeeper makes the CCommandNoMemory fail less the more times it is called
   532 class CMemoryReclaimGatekeeper : public CRefuserGatekeeper
   533 	{
   534 public:
   535 	CCommandNoMemory* iTarget;
   536 	CMemoryReclaimGatekeeper(CCommandNoMemory* aTarget = 0) : iTarget(aTarget) {}
   537 	TBool RetryOutOfMemoryL(TInt aNumRetries)
   538 		{
   539 		if (aNumRetries == 0)
   540 			{
   541 			iTarget->iFailAddToLast = EFalse;
   542 			return ETrue;
   543 			}
   544 		if (aNumRetries == 1)
   545 			{
   546 			iTarget->iFailInvert = EFalse;
   547 			return ETrue;
   548 			}
   549 		if (aNumRetries == 2)
   550 			{
   551 			iTarget->iFailExecute = EFalse;
   552 			return ETrue;
   553 			}
   554 		return EFalse;
   555 		}
   556 	};
   557 
   558 
   559 //
   560 //
   561 //	Editor
   562 //
   563 //
   564 
   565 // a cut-down set of attributes for testing purposes
   566 class CUndoTestPicture : public CPicture
   567 	{
   568 	TBuf<1> iDesc;
   569 public:
   570 	CUndoTestPicture(TInt aChar) : iDesc(1) { iDesc[0] = static_cast<TText>(aChar); }
   571 	void Draw(CGraphicsContext&, const TPoint&, const TRect&, MGraphicsDeviceMap*) const {}
   572 	void ExternalizeL(RWriteStream&) const {}
   573 	void GetOriginalSizeInTwips(TSize&) const {}
   574 	TPtrC Description() const { return iDesc; }
   575 	};
   576 
   577 struct TTestAttributes
   578 	{
   579 	TInt8 iCharFlags;
   580 	TInt8 iParFlags;
   581 	TInt8 iStyle;
   582 	TTestAttributes() : iCharFlags(0), iParFlags(0), iStyle(-1) {}
   583 	TBool operator==(TTestAttributes& a)
   584 		{
   585 		return iCharFlags == a.iCharFlags && iParFlags == a.iParFlags && iStyle == a.iStyle;
   586 		}
   587 	};
   588 CLogger& operator<<(CLogger& log, TTestAttributes& at)
   589 	{
   590 	TBuf<3> buf(_L("Aa0"));
   591 	buf[0] = (TText)(buf[0] + (at.iCharFlags & 15));
   592 	buf[1] = (TText)(buf[1] + (at.iParFlags & 15));
   593 	buf[2] = (TText)(buf[2] + at.iStyle);
   594 	return log << buf;
   595 	}
   596 // Test editor, badly behaved if something leaves.
   597 // The only formats supported are bold, italic, keep together and keep with next.
   598 class CTestEditor : public CBase, public MUnifiedEditor,
   599 	public MUnifiedEditor::MStyleSupport,
   600 	public MUnifiedEditor::MPictureSupport,
   601 	public MUnifiedEditor::MClipboardSupport
   602 	{
   603 	TTestAttributes iBase;
   604 	TTestAttributes iStyles[10];
   605 	TBuf<KMaxParagraphStyleName> iStyleNames[10];
   606 	TInt iNumStyles;
   607 	CArrayFix<TTestAttributes>* iAttrs;
   608 	CBufSeg* iText;
   609 	CArrayFix<CUndoTestPicture*>* iPics;
   610 
   611 	CTestEditor* ConstructL()
   612 		{
   613 		iText = CBufSeg::NewL(5 * sizeof(TText));
   614 		iAttrs = new(ELeave) CArrayFixFlat<TTestAttributes>(5);
   615 		iPics = new(ELeave) CArrayFixFlat<CUndoTestPicture*>(5);
   616 		return this;
   617 		}
   618 	TInt Style(const TDesC& aName) const
   619 		{
   620 		for (int i = 0; i != iNumStyles; ++i)
   621 			if (aName == iStyleNames[i])
   622 				return i;
   623 		return -1;
   624 		}
   625 	TInt InsertStylePos(const TDesC& aName) const
   626 		{
   627 		int i;
   628 		for (i = 0; i != iNumStyles; ++i)
   629 			if (aName.Compare(iStyleNames[i]) <= 0)
   630 				return i;
   631 		return i;
   632 		}
   633 	void ReassignStyles(TInt aFrom, TInt aTo)
   634 		{
   635 		ASSERT(-1 <= aTo && aTo < iNumStyles);
   636 		ASSERT(0 <= aFrom && aFrom < iNumStyles);
   637 		if (aTo == aFrom)
   638 			return;
   639 		TInt setTo	= aTo;
   640 		if (aTo == -1)
   641 			aTo = iNumStyles - 1;
   642 		TInt low	= aFrom;
   643 		TInt high	= aTo;
   644 		TInt delta	= -1;
   645 		if (aTo < aFrom)
   646 			{
   647 			low		= aTo;
   648 			high	= aFrom;
   649 			delta	= 1;
   650 			}
   651 		TInt len = DocumentLength();
   652 
   653 		int i;
   654 		for (i = 0; i != len; ++i)
   655 			{
   656 			TTestAttributes* attr = &iAttrs->At(i);
   657 			if (aFrom == attr->iStyle)
   658 				attr->iStyle = static_cast<TInt8>(setTo);
   659 			else if (low <= attr->iStyle && attr->iStyle <= high)
   660 				attr->iStyle = static_cast<TInt8>(attr->iStyle + delta);
   661 			}
   662 		for (i = aFrom; i != aTo; i -= delta)
   663 			{
   664 			iStyles[i] = iStyles[i - delta];
   665 			iStyleNames[i] = iStyleNames[i - delta];
   666 			}
   667 		}
   668 	void DoDeleteStyle(TInt aForDeletion)
   669 		{
   670 		ASSERT(aForDeletion < iNumStyles);
   671 		ReassignStyles(aForDeletion, -1);
   672 		--iNumStyles;
   673 		}
   674 	void DoAddStyle(const TDesC& aNewName, const TTestAttributes& aAttr)
   675 		{
   676 		ASSERT(iNumStyles < 10);
   677 		TInt pos = InsertStylePos(aNewName);
   678 		++iNumStyles;
   679 		ReassignStyles(iNumStyles - 1, pos);
   680 		iStyles[pos] = aAttr;
   681 		iStyleNames[pos] = aNewName;
   682 		}
   683 	static void BoldToAttr(TTestAttributes& aAttr, const TTmCharFormat& aCFormat)
   684 		{
   685 		if (aCFormat.iFontSpec.IsBold())
   686 			aAttr.iCharFlags |= 1;
   687 		else
   688 			aAttr.iCharFlags &= ~1;
   689 		}
   690 	static void ItalicToAttr(TTestAttributes& aAttr, const TTmCharFormat& aCFormat)
   691 		{
   692 		if (aCFormat.iFontSpec.IsItalic())
   693 			aAttr.iCharFlags |= 2;
   694 		else
   695 			aAttr.iCharFlags &= ~2;
   696 		}
   697 	static void CharFormatToAttr(TTestAttributes& aAttr, const TTmCharFormat& aCFormat)
   698 		{
   699 		aAttr.iCharFlags = 0;
   700 		BoldToAttr(aAttr, aCFormat);
   701 		ItalicToAttr(aAttr, aCFormat);
   702 		}
   703 	static void CharLayerToAttr(TTestAttributes& aAttr, const TTmCharFormatLayer& aCLayer)
   704 		{
   705 		if (aCLayer.iMask.iFlags & TTmCharFormatMask::EBold)
   706 			{
   707 			aAttr.iCharFlags |= 4;
   708 			BoldToAttr(aAttr, aCLayer.iFormat);
   709 			}
   710 		if (aCLayer.iMask.iFlags & TTmCharFormatMask::EItalic)
   711 			{
   712 			aAttr.iCharFlags |= 8;
   713 			ItalicToAttr(aAttr, aCLayer.iFormat);
   714 			}
   715 		}
   716 	static void KeepTogetherToAttr(TTestAttributes& aAttr, const RTmParFormat& aPFormat)
   717 		{
   718 		if (aPFormat.iFlags & RTmParFormat::EKeepTogether)
   719 			aAttr.iParFlags |= 1;
   720 		else
   721 			aAttr.iParFlags &= ~1;
   722 		}
   723 	static void KeepWithNextToAttr(TTestAttributes& aAttr, const RTmParFormat& aPFormat)
   724 		{
   725 		if (aPFormat.iFlags & RTmParFormat::EKeepWithNext)
   726 			aAttr.iParFlags |= 2;
   727 		else
   728 			aAttr.iParFlags &= ~2;
   729 		}
   730 	static void ParFormatToAttr(TTestAttributes& aAttr, const RTmParFormat& aPFormat)
   731 		{
   732 		aAttr.iParFlags = 0;
   733 		KeepTogetherToAttr(aAttr, aPFormat);
   734 		KeepWithNextToAttr(aAttr, aPFormat);
   735 		}
   736 	static void ParLayerToAttr(TTestAttributes& aAttr, const RTmParFormatLayer& aPLayer)
   737 		{
   738 		if (aPLayer.iMask.iFlags & TTmParFormatMask::EKeepTogether)
   739 			{
   740 			aAttr.iParFlags |= 4;
   741 			KeepTogetherToAttr(aAttr, aPLayer.iFormat);
   742 			}
   743 		if (aPLayer.iMask.iFlags & TTmParFormatMask::EKeepWithNext)
   744 			{
   745 			aAttr.iParFlags |= 8;
   746 			KeepWithNextToAttr(aAttr, aPLayer.iFormat);
   747 			}
   748 		}
   749 	static void BoldAttrToCharFormat(TTmCharFormat& aCFormat, const TTestAttributes& aAttr)
   750 		{
   751 		if (aAttr.iCharFlags & 1)
   752 			aCFormat.iFontSpec.SetBold(ETrue);
   753 		}
   754 	static void ItalicAttrToCharFormat(TTmCharFormat& aCFormat, const TTestAttributes& aAttr)
   755 		{
   756 		if (aAttr.iCharFlags & 2)
   757 			aCFormat.iFontSpec.SetItalic(ETrue);
   758 		}
   759 	static void ResetCharFormat(TTmCharFormat& aCFormat)
   760 		{
   761 		TTmCharFormat c;
   762 		aCFormat = c;
   763 		}
   764 	static void AttrToCharFormat(TTmCharFormat& aCFormat, const TTestAttributes& aAttr)
   765 		{
   766 		ResetCharFormat(aCFormat);
   767 		BoldAttrToCharFormat(aCFormat, aAttr);
   768 		ItalicAttrToCharFormat(aCFormat, aAttr);
   769 		}
   770 	static void MergeAttrToCharLayer(TTmCharFormatLayer& aCLayer, const TTestAttributes& aAttr)
   771 		{
   772 		if (aAttr.iCharFlags & 4)
   773 			{
   774 			aCLayer.iMask.iFlags |= TTmCharFormatMask::EBold;
   775 			BoldAttrToCharFormat(aCLayer.iFormat, aAttr);
   776 			}
   777 		if (aAttr.iCharFlags & 8)
   778 			{
   779 			aCLayer.iMask.iFlags |= TTmCharFormatMask::EItalic;
   780 			ItalicAttrToCharFormat(aCLayer.iFormat, aAttr);
   781 			}
   782 		}
   783 	static void AttrToCharLayer(TTmCharFormatLayer& aCLayer, const TTestAttributes& aAttr)
   784 		{
   785 		ResetCharFormat(aCLayer.iFormat);
   786 		aCLayer.iMask.iFlags = 0;
   787 		MergeAttrToCharLayer(aCLayer, aAttr);
   788 		}
   789 	static void ResetParFormat(RTmParFormat& aPFormat)
   790 		{
   791 		RTmParFormat p;
   792 		CleanupClosePushL(p);
   793 		aPFormat.CopyL(p);
   794 		CleanupStack::PopAndDestroy();
   795 		}
   796 	static void KeepTogetherAttrToParFormat(RTmParFormat& aPFormat, const TTestAttributes& aAttr)
   797 		{
   798 		if (aAttr.iParFlags & 1)
   799 			aPFormat.iFlags |= RTmParFormat::EKeepTogether;
   800 		}
   801 	static void KeepWithNextAttrToParFormat(RTmParFormat& aPFormat, const TTestAttributes& aAttr)
   802 		{
   803 		if (aAttr.iParFlags & 2)
   804 			aPFormat.iFlags |= RTmParFormat::EKeepWithNext;
   805 		}
   806 	static void AttrToParFormat(RTmParFormat& aPFormat, const TTestAttributes& aAttr)
   807 		{
   808 		ResetParFormat(aPFormat);
   809 		KeepTogetherAttrToParFormat(aPFormat, aAttr);
   810 		KeepWithNextAttrToParFormat(aPFormat, aAttr);
   811 		}
   812 	static void MergeAttrToParLayer(RTmParFormatLayer& aPLayer, const TTestAttributes& aAttr)
   813 		{
   814 		if (aAttr.iParFlags & 4)
   815 			{
   816 			aPLayer.iMask.iFlags |= TTmParFormatMask::EKeepTogether;
   817 			KeepTogetherAttrToParFormat(aPLayer.iFormat, aAttr);
   818 			}
   819 		if (aAttr.iParFlags & 8)
   820 			{
   821 			aPLayer.iMask.iFlags |= TTmParFormatMask::EKeepWithNext;
   822 			KeepWithNextAttrToParFormat(aPLayer.iFormat, aAttr);
   823 			}
   824 		}
   825 	static void AttrToParLayer(RTmParFormatLayer& aPLayer, const TTestAttributes& aAttr)
   826 		{
   827 		ResetParFormat(aPLayer.iFormat);
   828 		aPLayer.iMask.iFlags = 0;
   829 		MergeAttrToParLayer(aPLayer, aAttr);
   830 		}
   831 public:
   832 	~CTestEditor()
   833 		{
   834 		delete iAttrs;
   835 		// workaround for CBufSeg bug
   836 		if (0 < iText->Size())
   837 			iText->Delete(iText->Size() - 1, 1);
   838 		delete iText;
   839 		delete iPics;
   840 		}
   841 	static CTestEditor* NewL()	{ return (new(ELeave) CTestEditor)->ConstructL(); }
   842 	void Reset()
   843 		{
   844 		iAttrs->Reset();
   845 		iText->Reset();
   846 		iPics->Reset();
   847 		iNumStyles = 0;
   848 		}
   849 	void AlterGranularityL(TInt aNewGranularity)
   850 		{
   851 		CBufSeg* newIText = CBufSeg::NewL(aNewGranularity * sizeof(TText));
   852 		CleanupStack::PushL(newIText);
   853 		TBuf8<32> transfer;
   854 		TInt pos = 0;
   855 		while (pos < iText->Size())
   856 			{
   857 			TInt length = transfer.MaxLength();
   858 			if (iText->Size() - pos < length)
   859 				length = iText->Size() - pos;
   860 			iText->Read(pos, transfer, length);
   861 			newIText->InsertL(pos, transfer, length);
   862 			pos += transfer.Length();
   863 			}
   864 		CleanupStack::Pop(newIText);
   865 		// workaround for CBufSeg bug
   866 		if (0 < iText->Size())
   867 			iText->Delete(iText->Size() - 1, 1);
   868 		delete iText;
   869 		iText = newIText;
   870 		}
   871 	void Print(CLogger& log)
   872 		{
   873 		TInt length = DocumentLength();
   874 		int i;
   875 		log << _L("text{");
   876 		for (i = 0; i < length;)
   877 			{
   878 			TPtrC seg;
   879 			GetText(i, seg);
   880 			TInt picPos = seg.Locate(CEditableText::EPictureCharacter);
   881 			if (0 < picPos)
   882 				{
   883 				// shorten seg to just before the picture character
   884 				TPtrC temp(seg.Ptr(), picPos);
   885 				seg.Set(temp);
   886 				}
   887 			if (0 == picPos)
   888 				{
   889 				CUndoTestPicture* pic = iPics->At(i);
   890 				if (pic)
   891 					log << _L("{pic:") << pic->Description() << _L("}");
   892 				else
   893 					log << _L("{nopic}");
   894 				++i;
   895 				}
   896 			else
   897 				{
   898 				log << seg;
   899 				i += seg.Length();
   900 				}
   901 			}
   902 		log << _L("} styles{");
   903 		for(i = 0; i != iNumStyles; ++i)
   904 			{
   905 			if (i)
   906 				log << _L(", ");
   907 			log << iStyleNames[i] << _L(":") << iStyles[i];
   908 			}
   909 		log << _L("} attr{");
   910 		for (i = 0; i != length; ++i)
   911 			log << iAttrs->At(i);
   912 		log << _L("} ");
   913 		}
   914 	MTmOptionalInterface* Interface(TUint aId)
   915 		{
   916 		if (aId == KUidMUnifiedEditorStyleSupport)
   917 			return static_cast<MUnifiedEditor::MStyleSupport*>(this);
   918 		if (aId == KUidMUnifiedEditorPictureSupport)
   919 			return static_cast<MUnifiedEditor::MPictureSupport*>(this);
   920 		if (aId == KUidMUnifiedEditorClipboardSupport)
   921 			return static_cast<MUnifiedEditor::MClipboardSupport*>(this);
   922 		return 0;
   923 		}
   924 
   925 	void InsertTextL(TInt aPos, const TDesC& aText,
   926 					 const TDesC* aStyle,
   927 					 const TTmCharFormatLayer* aCharFormat,
   928 					 const RTmParFormatLayer* aParFormat)
   929 		{
   930 		TTestAttributes attr;
   931 		attr.iStyle = aStyle? (TInt8)Style(*aStyle) : (TInt8)-1;
   932 		if (aCharFormat)
   933 			CharLayerToAttr(attr, *aCharFormat);
   934 		if (aParFormat)
   935 			ParLayerToAttr(attr, *aParFormat);
   936 		iText->InsertL(aPos * sizeof(TText), aText.Ptr(), aText.Length() * sizeof(TText));
   937 		iAttrs->InsertL(aPos, attr, aText.Length());
   938 		CUndoTestPicture* nullPic = 0;
   939 		iPics->InsertL(aPos, nullPic, aText.Length());
   940 		}
   941 	void DeleteTextL(TInt aPos, TInt aLength)
   942 		{
   943 		iText->Delete(aPos * sizeof(TText), aLength * sizeof(TText));
   944 		iAttrs->Delete(aPos, aLength);
   945 		for (int i = aPos; i != aPos + aLength; ++i)
   946 			delete iPics->At(i);
   947 		iPics->Delete(aPos, aLength);
   948 		}
   949 	void SetBaseFormatL(const TTmCharFormat& aCharFormat,const RTmParFormat& aParFormat)
   950 		{
   951 		CharFormatToAttr(iBase, aCharFormat);
   952 		ParFormatToAttr(iBase, aParFormat);
   953 		}
   954 	void SetCharFormatL(TInt aPos,TInt aLength,const TTmCharFormatLayer& aFormat)
   955 		{
   956 		TInt end = aPos + aLength;
   957 		if (DocumentLength() < end)
   958 			end = DocumentLength();
   959 		for (; aPos < end; ++aPos)
   960 			CharLayerToAttr(iAttrs->At(aPos), aFormat);
   961 		}
   962 	void SetParFormatL(TInt aPos,TInt aLength,const RTmParFormatLayer& aFormat)
   963 		{
   964 		TInt end = aPos + aLength;
   965 		if (DocumentLength() < end)
   966 			end = DocumentLength();
   967 		for (; aPos < end; ++aPos)
   968 			ParLayerToAttr(iAttrs->At(aPos), aFormat);
   969 		}
   970 	void DeleteCharFormatL(TInt aPos,TInt aLength)
   971 		{
   972 		TInt end = aPos + aLength;
   973 		if (DocumentLength() < end)
   974 			end = DocumentLength();
   975 		for (; aPos < end; ++aPos)
   976 			iAttrs->At(aPos).iCharFlags = 0;
   977 		}
   978 	void DeleteParFormatL(TInt aPos,TInt aLength)
   979 		{
   980 		TInt end = aPos + aLength;
   981 		if (DocumentLength() < end)
   982 			end = DocumentLength();
   983 		for (; aPos < end; ++aPos)
   984 			iAttrs->At(aPos).iParFlags = 0;
   985 		}
   986 	TInt CreateStyleL(const RTmStyle& aStyle)
   987 		{
   988 		TInt styleNo = Style(aStyle.iName);
   989 		if (0 <= styleNo)
   990 			return KErrAlreadyExists;
   991 		TTestAttributes newAttr;
   992 		CharLayerToAttr(newAttr, aStyle.iCharFormat);
   993 		ParLayerToAttr(newAttr, aStyle.iParFormat);
   994 		DoAddStyle(aStyle.iName, newAttr);
   995 		return KErrNone;
   996 		}
   997 	TInt ChangeStyleL(const RTmStyle& aStyle)
   998 		{
   999 		TInt styleNo = Style(aStyle.iName);
  1000 		if (styleNo < 0)
  1001 			return KErrNotFound;
  1002 		iStyles[styleNo] = TTestAttributes();
  1003 		CharLayerToAttr(iStyles[styleNo], aStyle.iCharFormat);
  1004 		ParLayerToAttr(iStyles[styleNo], aStyle.iParFormat);
  1005 		return KErrNone;
  1006 		}
  1007 	TInt SetStyleL(TInt aPos, TInt aLength, const TDesC& aName)
  1008 		{
  1009 		TInt styleNo(-1);
  1010 		if (aName.Length())
  1011 			{
  1012 			styleNo = Style(aName);
  1013 			if (styleNo < 0)
  1014 				return KErrNotFound;
  1015 			}
  1016 		TInt end = aPos + aLength;
  1017 		for (; aPos < end; ++aPos)
  1018 			iAttrs->At(aPos).iStyle = (TInt8)styleNo;
  1019 		return KErrNone;
  1020 		}
  1021 	TInt RenameStyleL(const TDesC& aOldName, const TDesC& aNewName)
  1022 		{
  1023 		TInt oldNo = Style(aOldName);
  1024 		if (oldNo < 0)
  1025 			return KErrNotFound;
  1026 		TTestAttributes temp = iStyles[oldNo];
  1027 		TInt newNo = InsertStylePos(aNewName);
  1028 		if (oldNo < newNo)
  1029 			--newNo;
  1030 		ReassignStyles(oldNo, newNo);
  1031 		iStyles[newNo] = temp;
  1032 		iStyleNames[newNo] = aNewName;
  1033 		return KErrNone;
  1034 		}
  1035 	TInt DeleteStyleL(const TDesC& aName)
  1036 		{
  1037 		TInt n = Style(aName);
  1038 		if (n < 0)
  1039 			return KErrNotFound;
  1040 		DoDeleteStyle(n);
  1041 		return KErrNone;
  1042 		}
  1043 	void InsertPictureL(TInt aPos, const TPictureHeader& aPictureIn)
  1044 		{
  1045 		TBuf<1> picChar(1);
  1046 		picChar[0] = CEditableText::EPictureCharacter;
  1047 		InsertTextL(aPos, picChar, 0, 0, 0);
  1048 		iPics->At(aPos) = static_cast<CUndoTestPicture*>(aPictureIn.iPicture.AsPtr());
  1049 		}
  1050 	void DropPictureL(TInt aPos)
  1051 		{
  1052 		TPtrC ptr;
  1053 		GetText(aPos, ptr);
  1054 		if (ptr[0] == CEditableText::EPictureCharacter)
  1055 			{
  1056 			iPics->At(aPos) = 0;
  1057 			DeleteTextL(aPos, 1);
  1058 			}
  1059 		}
  1060 	void Picture(TInt aPos, TPictureHeader& aPictureOut) const
  1061 		{
  1062 		CPicture* pic = iPics->At(aPos);
  1063 		aPictureOut.iPictureType = KUidXzePictureType;
  1064 		aPictureOut.iPicture = pic;
  1065 		}
  1066 	TInt DocumentLength() const
  1067 		{
  1068 		return iText->Size() / sizeof(TText);
  1069 		}
  1070 	void GetText(TInt aPos, TPtrC& aText) const
  1071 		{
  1072 		iText->Compress();
  1073 		if (DocumentLength() <= aPos)
  1074 			aPos = DocumentLength();
  1075 		TPtr8 ptr = iText->Ptr(aPos * sizeof(TText));
  1076 		aText.Set((TText*)ptr.Ptr(), ptr.Length()/sizeof(TText));
  1077 		}
  1078 	void GetBaseFormatL(TTmCharFormat& aCharFormat, RTmParFormat& aParFormat) const
  1079 		{
  1080 		AttrToCharFormat(aCharFormat, iBase);
  1081 		AttrToParFormat(aParFormat, iBase);
  1082 		}
  1083 	void GetCharFormat(TInt aPos, TFormatLevel aLevel,
  1084 					   TTmCharFormatLayer& aFormat, TInt& aRunLength) const
  1085 		{
  1086 		TInt length = DocumentLength();
  1087 		if (length <= aPos)
  1088 			{
  1089 			aRunLength = 0;
  1090 			return;
  1091 			}
  1092 		TTestAttributes attr = iAttrs->At(aPos);
  1093 		if (aLevel == ESpecific)
  1094 			{
  1095 			AttrToCharLayer(aFormat, attr);
  1096 			}
  1097 		else
  1098 			{
  1099 			AttrToCharLayer(aFormat, iBase);
  1100 			MergeAttrToCharLayer(aFormat, attr);
  1101 			}
  1102 		TInt pos = aPos + 1;
  1103 		while (pos < length && attr == iAttrs->At(pos))
  1104 			++pos;
  1105 		aRunLength = pos - aPos;
  1106 		}
  1107 	void GetParFormatL(TInt aPos, TFormatLevel aLevel,
  1108 					   RTmParFormatLayer& aFormat, TInt& aRunLength) const
  1109 		{
  1110 		TInt length = DocumentLength();
  1111 		if (length <= aPos)
  1112 			{
  1113 			aRunLength = 0;
  1114 			return;
  1115 			}
  1116 		TTestAttributes attr = iAttrs->At(aPos);
  1117 		if (aLevel == ESpecific)
  1118 			{
  1119 			AttrToParLayer(aFormat, attr);
  1120 			}
  1121 		else
  1122 			{
  1123 			AttrToParLayer(aFormat, iBase);
  1124 			MergeAttrToParLayer(aFormat, attr);
  1125 			}
  1126 		TInt pos = aPos + 1;
  1127 		while (pos < length && attr == iAttrs->At(pos))
  1128 			++pos;
  1129 		aRunLength = pos - aPos;
  1130 		}
  1131 	TInt StyleCount() const { return iNumStyles; }
  1132 	void GetStyle(TInt aPos, TPtrC& aName, TInt& aRunLength) const
  1133 		{
  1134 		TInt length = DocumentLength();
  1135 		if (aPos < 0 || length <= aPos)
  1136 			{
  1137 			aName.Set(iStyleNames[0].Ptr(), 0);
  1138 			aRunLength = 0;
  1139 			return;
  1140 			}
  1141 		TInt styleNo = iAttrs->At(aPos).iStyle;
  1142 		if (styleNo < 0)
  1143 			aName.Set(iStyleNames[0].Ptr(), 0);
  1144 		else
  1145 			aName.Set(iStyleNames[styleNo]);
  1146 		TInt pos = aPos + 1;
  1147 		while (pos < length && iAttrs->At(pos).iStyle == styleNo)
  1148 			++pos;
  1149 		aRunLength = pos - aPos;
  1150 		return;
  1151 		}
  1152 	TInt GetStyleByNameL(const TDesC& aName, RTmStyle& aStyle) const
  1153 		{
  1154 		return GetStyleByIndexL(Style(aName), aStyle);
  1155 		}
  1156 	TInt GetStyleByIndexL(TInt aIndex, RTmStyle& aStyle) const
  1157 		{
  1158 		if (aIndex < 0 || iNumStyles <= aIndex)
  1159 			return KErrNotFound;
  1160 		aStyle.iName = iStyleNames[aIndex];
  1161 		AttrToParLayer(aStyle.iParFormat, iStyles[aIndex]);
  1162 		AttrToCharLayer(aStyle.iCharFormat, iStyles[aIndex]);
  1163 		return KErrNone;
  1164 		}
  1165 	void CopyToStoreL(CStreamStore& aStore, CStreamDictionary& aDictionary,
  1166 		TInt aPos, TInt aLength) const
  1167 		{
  1168 		ASSERT(aPos + aLength <= DocumentLength());
  1169 		if (aLength <= 0)
  1170 			return;
  1171 		RStoreWriteStream stream;
  1172 		TStreamId id = stream.CreateLC(aStore);
  1173 		stream.WriteInt32L(aLength);
  1174 		RBufReadStream input_stream(*iText, aPos * sizeof(TText));
  1175 		TMemoryStreamUnicodeSource source(input_stream);
  1176 		TUnicodeCompressor c;
  1177 		c.CompressL(stream, source, KMaxTInt, aLength);
  1178 		input_stream.Close();
  1179 		stream.CommitL();
  1180 		aDictionary.AssignL(KClipboardUidTypePlainText, id);
  1181 		CleanupStack::PopAndDestroy();		// close stream
  1182 
  1183 		// now write out formatting in our own bizarre format
  1184 		//...
  1185 		// in actual fact this probably wouldn't test that much, so I won't
  1186 		// bother right now.
  1187 		}
  1188 	void PasteFromStoreL(const CStreamStore& aStore,
  1189 		const CStreamDictionary& aDictionary, TInt aPos)
  1190 		{
  1191 		ASSERT(aPos <= DocumentLength());
  1192 		TStreamId id = aDictionary.At(KClipboardUidTypePlainText);
  1193 		RStoreReadStream stream;
  1194 		stream.OpenLC(aStore, id);
  1195 		TInt length = stream.ReadInt32L();
  1196 		RBufWriteStream bufferStream;
  1197 		bufferStream.Insert(*iText, aPos * sizeof(TText));
  1198 		TMemoryStreamUnicodeSink sink(bufferStream);
  1199 		TUnicodeExpander e;
  1200 		e.ExpandL(sink, stream, length);
  1201 		bufferStream.CommitL();
  1202 		bufferStream.Close();
  1203 		CleanupStack::PopAndDestroy();	// close stream
  1204 
  1205 		// and if we get round to adding some formatting to the copy method,
  1206 		// then we should deal with it here also
  1207 		//...
  1208 		// but not today. Just add the appropriate spaces into all the structures.
  1209 		TTestAttributes attr;
  1210 		iAttrs->InsertL(aPos, attr, length);
  1211 		CUndoTestPicture* nullPic = 0;
  1212 		iPics->InsertL(aPos, nullPic, length);
  1213 		}
  1214 	};
  1215 
  1216 CLogger& operator<<(CLogger& log, CTestEditor& ed) { ed.Print(log); return log; }
  1217 
  1218 // 1 - CCommandStack test
  1219 TInt ExecuteStackL(CCommandStack& a)
  1220 	{
  1221 	while (a.Top())
  1222 		{
  1223 		CSingleCommand* single = a.Top()->Single();
  1224 		if (!single)
  1225 			{
  1226             TESTPRINT(_L("CCommandStack : stack unexpectedly contained batches"));
  1227 			a.Reset();
  1228 			return 1;
  1229 			}
  1230 		single->ExecuteL();
  1231 		delete single;
  1232 		a.Pop();
  1233 		}
  1234 	return 0;
  1235 	}
  1236 TInt CheckLog(CCheckingLogger& a)
  1237 	{
  1238 	if (a.Passed())
  1239 		return 0;
  1240 	TESTPRINT(_L("CCommandStack... : log failed"));
  1241 	return 1;
  1242 	}
  1243 TInt CheckTop(CCommandStack& aStack, CCommand* aTop)
  1244 	{
  1245 	if (aStack.Top() != aTop)
  1246 		{
  1247         TESTPRINT(_L("CCommandStack : unexpected item at top of stack"));
  1248 		return 1;
  1249 		}
  1250 	return 0;
  1251 	}
  1252 TInt CheckCount(CCommandStack& aStack, TInt aExpectedCount)
  1253 	{
  1254 	if (aStack.Count() != aExpectedCount)
  1255 		{
  1256 	    TESTPRINT(_L("CCommandStack : stack an unexpected size"));
  1257 		return 1;
  1258 		}
  1259 	return 0;
  1260 	}
  1261 TInt CheckPop(CCommandStack& aStack)
  1262 	{
  1263 	CCommand* check = aStack.Top();
  1264 	if (aStack.Pop() != check)
  1265 		{
  1266         TESTPRINT(_L("CCommandStack : Pop() does not match Top()"));
  1267 		return 1;
  1268 		}
  1269 	return 0;
  1270 	}
  1271 void AddStuffL(CCommandStack& aStack, TInt* aTarget, CLogger* aLog)
  1272 	{
  1273 	TInt startCount = aStack.Count();
  1274 	CheckTop(aStack, 0);
  1275 	aStack.PrepareToPushL(1);
  1276 	CheckCount(aStack, startCount);
  1277 	CheckTop(aStack, 0);
  1278 	CheckCount(aStack, startCount);
  1279 	CCommand* temp = CCommandIncProto::NewL(aTarget, aLog);
  1280 	aStack.Push(temp);
  1281 	CheckCount(aStack, startCount + 1);
  1282 	CheckTop(aStack, temp);
  1283 	aStack.PrepareToPushL(2);
  1284 	CheckCount(aStack, startCount + 1);
  1285 	CheckTop(aStack, temp);
  1286 	CheckCount(aStack, startCount + 1);
  1287 	CheckTop(aStack, temp);
  1288 	aStack.PrepareToPushL(1);
  1289 	aStack.PrepareToPushL(3);
  1290 	CheckCount(aStack, startCount + 1);
  1291 	CheckTop(aStack, temp);
  1292 	temp = CCommandDecProto::NewL(aTarget, aLog);
  1293 	CheckCount(aStack, startCount + 1);
  1294 	aStack.Push(temp);
  1295 	CheckCount(aStack, startCount + 2);
  1296 	CheckTop(aStack, temp);
  1297 	CheckTop(aStack, temp);
  1298 	CheckCount(aStack, startCount + 2);
  1299 	CheckTop(aStack, temp);
  1300 	temp = CCommandIncProto::NewL(aTarget, aLog);
  1301 	aStack.Push(temp);
  1302 	CheckTop(aStack, temp);
  1303 	CheckCount(aStack, startCount + 3);
  1304 	aStack.PrepareToPushL(1);
  1305 	CheckTop(aStack, temp);
  1306 	aStack.PrepareToPushL(2);
  1307 	CheckTop(aStack, temp);
  1308 	temp = CCommandNegProto::NewL(aTarget, aLog);
  1309 	CheckCount(aStack, startCount + 3);
  1310 	aStack.Push(temp);
  1311 	CheckCount(aStack, startCount + 4);
  1312 	CheckTop(aStack, temp);
  1313 	CheckCount(aStack, startCount + 4);
  1314 	CheckTop(aStack, temp);
  1315 	temp = CCommandIncProto::NewL(aTarget, aLog);
  1316 	CheckCount(aStack, startCount + 4);
  1317 	aStack.Push(temp);
  1318 	CheckTop(aStack, temp);
  1319 	CheckCount(aStack, startCount + 5);
  1320 	}
  1321 void TestCCommandStackL()
  1322 	{
  1323 	__UHEAP_MARK;
  1324 	TInt target;
  1325 	CCheckingLogger* log = new(ELeave) CCheckingLogger;
  1326 
  1327 	CCommandStack* stack = CCommandStack::NewL();
  1328 
  1329 	AddStuffL(*stack, &target, log);
  1330 
  1331 	log->SetCheckString(_L("inc<>neg<>inc<>dec<>inc<>"));
  1332 	ExecuteStackL(*stack);
  1333 	CheckLog(*log);
  1334 
  1335 	CheckCount(*stack, 0);
  1336 	CCommand* temp = CCommandIncProto::NewL(&target, log);
  1337 	CheckTop(*stack, 0);
  1338 	stack->PrepareToPushL(1);
  1339 	CheckCount(*stack, 0);
  1340 	CheckTop(*stack, 0);
  1341 	CheckCount(*stack, 0);
  1342 	stack->Push(temp);
  1343 	CheckCount(*stack, 1);
  1344 	stack->PrepareToPushL(1);
  1345 	CheckCount(*stack, 1);
  1346 	CCommand* next = CCommandDecProto::NewL(&target, log);
  1347 	stack->Push(next);
  1348 	CheckCount(*stack, 2);
  1349 	stack->PrepareToPushL(1);
  1350 	CheckPop(*stack);
  1351 	stack->PrepareToPushL(1);
  1352 	CheckCount(*stack, 1);
  1353 	CheckTop(*stack, temp);
  1354 	CheckCount(*stack, 1);
  1355 	stack->Push(next);
  1356 	stack->PrepareToPushL(1);
  1357 	CheckCount(*stack, 2);
  1358 	CheckCount(*stack, 2);
  1359 	CheckPop(*stack);
  1360 	CheckCount(*stack, 1);
  1361 	CheckTop(*stack, temp);
  1362 	delete next;
  1363 
  1364 	stack->Reset();
  1365 	CheckCount(*stack, 0);
  1366 
  1367 	AddStuffL(*stack, &target, log);
  1368 	stack->PruneTo(3);
  1369 	CheckCount(*stack, 3);
  1370 	log->SetCheckString(_L("inc<>neg<>inc<>"));
  1371 	ExecuteStackL(*stack);
  1372 	CheckLog(*log);
  1373 
  1374 	AddStuffL(*stack, &target, log);
  1375 	stack->PrepareToPushL(1);
  1376 	CheckCount(*stack, 5);
  1377 	stack->PruneTo(2);
  1378 	CheckCount(*stack, 2);
  1379 	log->SetCheckString(_L("inc<>neg<>"));
  1380 	ExecuteStackL(*stack);
  1381 	CheckLog(*log);
  1382 
  1383 	delete stack;
  1384 	delete log;
  1385 
  1386 	__UHEAP_MARKENDC(0);
  1387 	}
  1388 
  1389 // 2 - CBatchCommand test
  1390 void ExecuteBatchL(CBatchCommand& a)
  1391 	{
  1392 	while (a.Top())
  1393 		{
  1394 		CSingleCommand* single = a.Top();
  1395 		single->ExecuteL();
  1396 		if (a.Pop() != single)
  1397 			{
  1398             TESTPRINT(_L("CBatchCommand : Pop() didn't match Top()"));
  1399             TESTPOINT(0);
  1400 			}
  1401 		delete single;
  1402 		}
  1403 	TESTPOINT(1);
  1404 	}
  1405 void CheckTop(CBatchCommand& aBatch, CCommand* aTop)
  1406 	{
  1407 	if (aBatch.Top() != aTop)
  1408 		{
  1409         TESTPRINT(_L("CCommandBatch : unexpected item at top of stack"));
  1410         TESTPOINT(0);
  1411 		}
  1412 	TESTPOINT(1);
  1413 	}
  1414 void TestCBatchCommandL()
  1415 	{
  1416 	__UHEAP_MARK;
  1417 	TInt target = 0;
  1418 	CCheckingLogger* log = new(ELeave) CCheckingLogger;
  1419 
  1420 	CBatchCommand* batch = CBatchCommand::NewL();
  1421 
  1422 	CBatchCommand* b1 = CBatchCommand::NewL();
  1423 	CBatchCommand* b2 = CBatchCommand::NewL();
  1424 	CBatchCommand* b3 = CBatchCommand::NewL();
  1425 
  1426 	CCommand* s1 = CCommandIncProto::NewL(&target, log);
  1427 	CCommand* s2 = CCommandDecProto::NewL(&target, log);
  1428 	CCommand* s3 = CCommandNegProto::NewL(&target, log);
  1429 	CCommand* s4 = CCommandIncProto::NewL(&target, log);
  1430 	CCommand* s5 = CCommandDecProto::NewL(&target, log);
  1431 	CCommand* s6 = CCommandNegProto::NewL(&target, log);
  1432 	CCommand* s7 = CCommandIncProto::NewL(&target, log);
  1433 	CCommand* s8 = CCommandDecProto::NewL(&target, log);
  1434 	CCommand* s9 = CCommandNegProto::NewL(&target, log);
  1435 
  1436 	b2->PrepareToPushL(s4);
  1437 	b2->Push(s4);
  1438 	b2->PrepareToPushL(s8);
  1439 	b2->Push(s8);
  1440 	b2->PrepareToPushL(s2);
  1441 	b2->PrepareToPushL(s2);
  1442 	b2->Push(s2);
  1443 
  1444 	b3->PrepareToPushL(s3);
  1445 	b3->PrepareToPushL(s9);
  1446 	b3->Push(s9);
  1447 	b3->PrepareToPushL(s3);
  1448 	b3->Push(s3);
  1449 	b3->PrepareToPushL(s7);
  1450 	b3->Push(s7);
  1451 
  1452 	b1->PrepareToPushL(s6);
  1453 	b1->Push(s6);
  1454 	b1->PrepareToPushL(s5);
  1455 	b1->Push(s5);
  1456 	b1->PrepareToPushL(b3);
  1457 	b1->Push(b3);
  1458 	b1->PrepareToPushL(b1);
  1459 	b1->PrepareToPushL(s1);
  1460 	b1->PrepareToPushL(s1);
  1461 	b1->PrepareToPushL(b2);
  1462 
  1463 	batch->PrepareToPushL(b2);
  1464 	batch->Push(b2);
  1465 	batch->PrepareToPushL(s1);
  1466 	batch->PrepareToPushL(s1);
  1467 	batch->PrepareToPushL(b1);
  1468 	batch->Push(b1);
  1469 	batch->PrepareToPushL(s1);
  1470 	batch->Push(s1);
  1471 
  1472 	CheckTop(*batch, s1);
  1473 	batch->Pop();
  1474 	CheckTop(*batch, s7);
  1475 	batch->PrepareToPushL(s1);
  1476 	CheckTop(*batch, s7);
  1477 	batch->Push(s1);
  1478 	CheckTop(*batch, s1);
  1479 	batch->PrepareToPushL(s1);
  1480 	CheckTop(*batch, s1);
  1481 	batch->Pop();
  1482 	CheckTop(*batch, s7);
  1483 	batch->Pop();
  1484 	CheckTop(*batch, s3);
  1485 	batch->Pop();
  1486 	CheckTop(*batch, s9);
  1487 	batch->Pop();
  1488 	CheckTop(*batch, s5);
  1489 	batch->Pop();
  1490 	CheckTop(*batch, s6);
  1491 	batch->PrepareToPushL(s5);
  1492 	CheckTop(*batch, s6);
  1493 	batch->Push(s5);
  1494 	CheckTop(*batch, s5);
  1495 	b3 = CBatchCommand::NewL();
  1496 	b3->PrepareToPushL(s9);
  1497 	CheckTop(*b3, 0);
  1498 	b3->Push(s9);
  1499 	CheckTop(*b3, s9);
  1500 	b3->PrepareToPushL(s3);
  1501 	CheckTop(*b3, s9);
  1502 	b3->Push(s3);
  1503 	CheckTop(*b3, s3);
  1504 	b3->PrepareToPushL(s7);
  1505 	CheckTop(*b3, s3);
  1506 	b3->Push(s7);
  1507 	CheckTop(*b3, s7);
  1508 	batch->PrepareToPushL(b3);
  1509 	CheckTop(*batch, s5);
  1510 	batch->Push(b3);
  1511 	CheckTop(*batch, s7);
  1512 	batch->PrepareToPushL(s1);
  1513 	batch->Push(s1);
  1514 
  1515 	log->SetCheckString(_L("inc<>inc<>neg<>neg<>dec<>neg<>dec<>dec<>inc<>"));
  1516 	ExecuteBatchL(*batch);
  1517 	CheckLog(*log);
  1518 
  1519 	delete log;
  1520 	delete batch;
  1521 
  1522 	__UHEAP_MARKENDC(0);
  1523 	}
  1524 
  1525 // 3 - CCommandHistory test
  1526 void ExecuteHistoryL(CCommandHistory& aHistory, CLogger& aLog)
  1527 	{
  1528 	while (aHistory.Top())
  1529 		{
  1530 		if (aHistory.Top()->Single())
  1531 			{
  1532 			aHistory.Top()->Single()->ExecuteL();
  1533 			}
  1534 		else
  1535 			{
  1536 			CBatchCommand* batch = aHistory.Top()->Batch();
  1537 			TESTPOINT(batch != 0);
  1538 			aLog << _L("batch{");
  1539 			ExecuteBatchL(*batch);
  1540 			aLog << _L("}");
  1541 			}
  1542 		delete aHistory.Pop();
  1543 		}
  1544 	}
  1545 void TestCCommandHistoryL()
  1546 	{
  1547 	__UHEAP_MARK;
  1548 
  1549 	CCommandHistory* history = CCommandHistory::NewL();
  1550 	CCheckingLogger* log = new(ELeave) CCheckingLogger;
  1551 	TInt target;
  1552 
  1553 	CCommand* p;
  1554 	history->SetMaxItems(5);
  1555 	p = CCommandDecProto::NewL(&target, log);
  1556 	history->PrepareToAddCommandL(p);
  1557 	history->AddCommand(p);
  1558 	p = CCommandIncProto::NewL(&target, log);
  1559 	history->PrepareToAddCommandL(p);
  1560 	history->AddCommand(p);
  1561 	p = CCommandDecProto::NewL(&target, log);
  1562 	history->PrepareToAddCommandL(p);
  1563 	history->AddCommand(p);
  1564 	p = CCommandNegProto::NewL(&target, log);
  1565 	history->PrepareToAddCommandL(p);
  1566 	history->AddCommand(p);
  1567 	history->BeginBatchLC();
  1568 	p = CCommandIncProto::NewL(&target, log);
  1569 	history->PrepareToAddCommandL(p);
  1570 	history->AddCommand(p);
  1571 	p = CCommandDecProto::NewL(&target, log);
  1572 	history->PrepareToAddCommandL(p);
  1573 	history->AddCommand(p);
  1574 	p = CCommandNegProto::NewL(&target, log);
  1575 	history->PrepareToAddCommandL(p);
  1576 	history->AddCommand(p);
  1577 	CleanupStack::PopAndDestroy();
  1578 	p = CCommandDecProto::NewL(&target, log);
  1579 	history->PrepareToAddCommandL(p);
  1580 	history->AddCommand(p);
  1581 	CBatchCommand* batch = CBatchCommand::NewL();
  1582 	p = CCommandDecProto::NewL(&target, log);
  1583 	batch->PrepareToPushL(p);
  1584 	batch->Push(p);
  1585 	p = CCommandNegProto::NewL(&target, log);
  1586 	batch->PrepareToPushL(p);
  1587 	batch->Push(p);
  1588 	p = CCommandIncProto::NewL(&target, log);
  1589 	batch->PrepareToPushL(p);
  1590 	batch->Push(p);
  1591 	history->PrepareToAddCommandL(batch);
  1592 	history->AddCommand(batch);
  1593 	p = CCommandNegProto::NewL(&target, log);
  1594 	history->PrepareToAddCommandL(p);
  1595 	history->AddCommand(p);
  1596 
  1597 	log->SetCheckString(_L("neg<>batch{inc<>neg<>dec<>}dec<>batch{neg<>dec<>inc<>}neg<>"));
  1598 	ExecuteHistoryL(*history, *log);
  1599 	CheckLog(*log);
  1600 
  1601 	delete log;
  1602 	delete history;
  1603 
  1604 	__UHEAP_MARKENDC(0);
  1605 	}
  1606 
  1607 // 4 - CCommandManager test
  1608 void TestCanUndo(const CCommandManager& aMan)
  1609 	{
  1610 	if (aMan.CanUndo())
  1611 		{
  1612         TESTPOINT(1);
  1613 		return;
  1614 		}
  1615 	TESTPRINT(_L("CCommandManager : unexpectedly could not undo"));
  1616 	TESTPOINT(0);
  1617 	}
  1618 void TestCanRedo(const CCommandManager& aMan)
  1619 	{
  1620 	if (aMan.CanRedo())
  1621 		{
  1622         TESTPOINT(1);
  1623 		return;
  1624 		}
  1625 	TESTPRINT(_L("CCommandManager : unexpectedly could not redo"));
  1626 	TESTPOINT(0);
  1627 	}
  1628 void TestCannotUndo(const CCommandManager& aMan)
  1629 	{
  1630 	if (!aMan.CanUndo())
  1631 		{
  1632         TESTPOINT(1);
  1633 		return;
  1634 		}
  1635 	TESTPRINT(_L("CCommandManager : unexpectedly could undo"));
  1636 	TESTPOINT(0);
  1637 	}
  1638 void TestCannotRedo(const CCommandManager& aMan)
  1639 	{
  1640 	if (!aMan.CanRedo())
  1641 		{
  1642         TESTPOINT(1);
  1643 		return;
  1644 		}
  1645 	TESTPRINT(_L("CCommandManager : unexpectedly could undo"));
  1646 	TESTPOINT(0);
  1647 	}
  1648 void SetUpTestL(CCommandManager& aMan, CSingleCommand& aCommand, TInt* aTarget, CLogger* aLogger)
  1649 	{
  1650 	CCommandIncProto* inc = CCommandIncProto::NewL(aTarget, aLogger);
  1651 	CleanupStack::PushL(inc);
  1652 	CCommandNegProto* neg = CCommandNegProto::NewL(aTarget, aLogger);
  1653 	CleanupStack::PushL(neg);
  1654 	CCommandDecProto* dec = CCommandDecProto::NewL(aTarget, aLogger);
  1655 	CleanupStack::PushL(dec);
  1656 
  1657 	aMan.ExecuteL(*inc);
  1658 	aMan.BeginBatchLC();
  1659 	aMan.ExecuteL(*neg);
  1660 	aMan.ExecuteL(aCommand);
  1661 	aMan.ExecuteL(*dec);
  1662 	CleanupStack::PopAndDestroy();		// close batch
  1663 	aMan.ExecuteL(*neg);
  1664 	aMan.UndoL();
  1665 
  1666 	CleanupStack::PopAndDestroy(dec);
  1667 	CleanupStack::PopAndDestroy(neg);
  1668 	CleanupStack::PopAndDestroy(inc);
  1669 	}
  1670 TInt CheckErrorCode(TInt aErr, TInt aExpected)
  1671 	{
  1672 	if (aErr == aExpected)
  1673 		return 0;
  1674 	if (aErr == KErrNone)
  1675 	    TESTPRINT(_L("CCommandManager : no leave where one was expected"));
  1676 	else
  1677 	    TESTPRINT(_L("CCommandManager : unexpected leave code"));
  1678 	return 1;
  1679 	}
  1680 void TestCCommandManagerL()
  1681 	{
  1682 	__UHEAP_MARK;
  1683 
  1684 	CCommandManager* manager = CCommandManager::NewL();
  1685 	CCheckingLogger* log = new(ELeave) CCheckingLogger;
  1686 	TInt target = 0;
  1687 	CRefuserGatekeeper* refuser = new(ELeave) CRefuserGatekeeper;
  1688 	CPermitterGatekeeper* permitter = new(ELeave) CPermitterGatekeeper;
  1689 	CMemoryReclaimGatekeeper* reclaimer = new(ELeave) CMemoryReclaimGatekeeper;
  1690 
  1691 	TestCannotUndo(*manager);
  1692 	TestCannotRedo(*manager);
  1693 
  1694 	CCommandIncProto* inc = CCommandIncProto::NewL(&target, log);
  1695 	CCommandDecProto* dec = CCommandDecProto::NewL(&target, log);
  1696 	CCommandNegProto* neg = CCommandNegProto::NewL(&target, log);
  1697 
  1698 	log->SetCheckString(_L("inc<>neg<>inc<>dec<>neg<>negate<1>"));
  1699 	SetUpTestL(*manager, *inc, &target, log);
  1700 	CheckLog(*log);
  1701 	TestCanUndo(*manager);
  1702 	TestCanRedo(*manager);
  1703 	log->SetCheckString(_L("offset<0>negate<1>"));
  1704 	manager->UndoL();
  1705 	CheckLog(*log);
  1706 	TestCanUndo(*manager);
  1707 	TestCanRedo(*manager);
  1708 	log->SetCheckString(_L("offset<-1>"));
  1709 	manager->UndoL();
  1710 	CheckLog(*log);
  1711 	TestCannotUndo(*manager);
  1712 	TestCanRedo(*manager);
  1713 	log->SetCheckString(_L("offset<1>"));
  1714 	manager->RedoL();
  1715 	CheckLog(*log);
  1716 	TestCanUndo(*manager);
  1717 	TestCanRedo(*manager);
  1718 	log->SetCheckString(_L("negate<1>offset<0>"));
  1719 	manager->RedoL();
  1720 	CheckLog(*log);
  1721 	TestCanUndo(*manager);
  1722 	TestCanRedo(*manager);
  1723 	log->SetCheckString(_L("negate<1>"));
  1724 	manager->RedoL();
  1725 	CheckLog(*log);
  1726 	TestCanUndo(*manager);
  1727 	TestCannotRedo(*manager);
  1728 	log->SetCheckString(_L("negate<1>"));
  1729 	manager->UndoL();
  1730 	CheckLog(*log);
  1731 	TestCanUndo(*manager);
  1732 	TestCanRedo(*manager);
  1733 	log->SetCheckString(_L("inc<>"));
  1734 	manager->ExecuteL(*inc);
  1735 	CheckLog(*log);
  1736 	TestCanUndo(*manager);
  1737 	TestCannotRedo(*manager);
  1738 	log->SetCheckString(_L("offset<-1>negate<1>"));
  1739 	manager->UndoL();
  1740 	CheckLog(*log);
  1741 	TestCanUndo(*manager);
  1742 	TestCanRedo(*manager);
  1743 	log->SetCheckString(_L("negate<1>offset<1>"));
  1744 	manager->RedoL();
  1745 	CheckLog(*log);
  1746 	TestCanUndo(*manager);
  1747 	TestCannotRedo(*manager);
  1748 
  1749 	manager->ResetUndo();
  1750 	TestCannotUndo(*manager);
  1751 	TestCannotRedo(*manager);
  1752 
  1753 	// test coalescence
  1754 
  1755 	log->SetCheckString(_L("inc<>inc<>inc<>inc<>inc<>inc<>"));
  1756 
  1757 	manager->ExecuteL(*inc);
  1758 	manager->ExecuteL(*inc);
  1759 	manager->BeginBatchLC();
  1760 	manager->ExecuteL(*inc);
  1761 	manager->ExecuteL(*inc);
  1762 	CleanupStack::PopAndDestroy();		// close batch
  1763 	manager->ExecuteL(*inc);
  1764 	manager->ExecuteL(*inc);
  1765 	CheckLog(*log);
  1766 
  1767 	log->SetCheckString(_L("offset<-4>offset<-2>"));
  1768 	manager->UndoL();
  1769 	manager->UndoL();
  1770 	CheckLog(*log);
  1771 
  1772 	log->SetCheckString(_L("offset<2>offset<4>"));
  1773 	manager->RedoL();
  1774 	manager->RedoL();
  1775 	TestCannotRedo(*manager);
  1776 	CheckLog(*log);
  1777 
  1778 	manager->ResetUndo();
  1779 	TestCannotUndo(*manager);
  1780 	TestCannotRedo(*manager);
  1781 
  1782 	// test command with batch inverse
  1783 	log->SetCheckString(_L("inc<>decneg<>inc<>"));
  1784 	CCommandDecThenNegProto* dnp = CCommandDecThenNegProto::NewL(&target, log);
  1785 	manager->ExecuteL(*inc);
  1786 	manager->ExecuteL(*dnp);
  1787 	manager->ExecuteL(*inc);
  1788 	CheckLog(*log);
  1789 	delete dnp;
  1790 	log->SetCheckString(_L("offset<-1>"));
  1791 	manager->UndoL();
  1792 	CheckLog(*log);
  1793 	log->SetCheckString(_L("negate<1>offset<1>"));
  1794 	manager->UndoL();
  1795 	CheckLog(*log);
  1796 	log->SetCheckString(_L("offset<-1>"));
  1797 	manager->UndoL();
  1798 	CheckLog(*log);
  1799 	manager->ResetUndo();
  1800 
  1801 	// Test case when undo is not supported
  1802 	// 1. execution is permitted
  1803 	log->SetCheckString(_L("inc<>neg<>noinvfail.noinv<>dec<>neg<>negate<1>"));
  1804 	CCommandCannotInvert* noInv = CCommandCannotInvert::NewL(log);
  1805 	SetUpTestL(*manager, *noInv, &target, log);
  1806 	CheckLog(*log);
  1807 	TestCannotUndo(*manager);
  1808 	log->SetCheckString(_L("negate<1>"));
  1809 	manager->RedoL();
  1810 	CheckLog(*log);
  1811 	TestCannotRedo(*manager);
  1812 	manager->ResetUndo();
  1813 
  1814 	//2. execution is supressed
  1815 	manager->SetGatekeeper(refuser);
  1816 	log->SetCheckString(_L("inc<>neg<>noinvfail.dec<>neg<>negate<1>"));
  1817 	SetUpTestL(*manager, *noInv, &target, log);
  1818 	CheckLog(*log);
  1819 	delete noInv;
  1820 	log->SetCheckString(_L("offset<1>negate<1>"));
  1821 	manager->UndoL();
  1822 	CheckLog(*log);
  1823 	log->SetCheckString(_L("offset<-1>"));
  1824 	manager->UndoL();
  1825 	CheckLog(*log);
  1826 	TestCannotUndo(*manager);
  1827 	manager->ResetUndo();
  1828 	manager->SetGatekeeper(0);
  1829 
  1830 	// Test case when execution fails (with returned error code)
  1831 	CCommandCannotDo* noDo = CCommandCannotDo::NewL(log);
  1832 	log->SetCheckString(_L("inc<>neg<>nodo<>dec<>neg<>negate<1>"));
  1833 	SetUpTestL(*manager, *noDo, &target, log);
  1834 	delete noDo;
  1835 	log->SetCheckString(_L("offset<1>negate<1>"));
  1836 	manager->UndoL();
  1837 	CheckLog(*log);
  1838 	log->SetCheckString(_L("offset<-1>"));
  1839 	manager->UndoL();
  1840 	CheckLog(*log);
  1841 	TestCannotUndo(*manager);
  1842 	manager->ResetUndo();
  1843 
  1844 	// Test case when inversion fails (not inversion is reported as impossible)
  1845 	// 1. when execution is permitted
  1846 	manager->SetGatekeeper(permitter);
  1847 	log->SetCheckString(_L("inc<>neg<>noinvfail.leaveinv<>dec<>neg<>negate<1>"));
  1848 	CCommandLeavesInvert* leaveInv = CCommandLeavesInvert::NewL(log);
  1849 	SetUpTestL(*manager, *leaveInv, &target, log);
  1850 	CheckLog(*log);
  1851 	TestCannotUndo(*manager);
  1852 	log->SetCheckString(_L("negate<1>"));
  1853 	manager->RedoL();
  1854 	CheckLog(*log);
  1855 	TestCannotRedo(*manager);
  1856 	manager->ResetUndo();
  1857 
  1858 	// 2. when execution is supressed
  1859 	manager->SetGatekeeper(refuser);
  1860 	log->SetCheckString(_L("inc<>neg<>noinvfail.dec<>neg<>negate<1>"));
  1861 	leaveInv->iFail = ETrue;
  1862 	TRAPD(err, SetUpTestL(*manager, *leaveInv, &target, log));
  1863 	CheckErrorCode(err, KErrNone);
  1864 	CheckLog(*log);
  1865 	log->SetCheckString(_L("offset<1>negate<1>"));
  1866 	manager->UndoL();
  1867 	CheckLog(*log);
  1868 	log->SetCheckString(_L("offset<-1>"));
  1869 	manager->UndoL();
  1870 	CheckLog(*log);
  1871 	TestCannotUndo(*manager);
  1872 	manager->ResetUndo();
  1873 
  1874 	// 3. when execution is terminated by leaving
  1875 	manager->SetGatekeeper(0);
  1876 	log->SetCheckString(_L("inc<>neg<>noinvfail."));
  1877 	leaveInv->iFail = ETrue;
  1878 	TRAP(err, SetUpTestL(*manager, *leaveInv, &target, log));
  1879 	CheckErrorCode(err, KErrNotFound);
  1880 	CheckLog(*log);
  1881 	delete leaveInv;
  1882 	log->SetCheckString(_L("negate<1>"));
  1883 	manager->UndoL();
  1884 	CheckLog(*log);
  1885 	log->SetCheckString(_L("offset<-1>"));
  1886 	manager->UndoL();
  1887 	CheckLog(*log);
  1888 	TestCannotUndo(*manager);
  1889 	manager->ResetUndo();
  1890 
  1891 	// Test case when inversion runs out of memory
  1892 	// 1. when execution is permitted with no undo
  1893 	manager->SetGatekeeper(permitter);
  1894 	log->SetCheckString(_L("inc<>neg<>nomemfailadd.nomem<>dec<>neg<>negate<1>"));
  1895 	CCommandNoMemory* noMem = CCommandNoMemory::NewL(log);
  1896 	noMem->iFailExecute = EFalse;
  1897 	SetUpTestL(*manager, *noMem, &target, log);
  1898 	CheckLog(*log);
  1899 	TestCannotUndo(*manager);
  1900 	log->SetCheckString(_L("negate<1>"));
  1901 	manager->RedoL();
  1902 	CheckLog(*log);
  1903 	TestCannotRedo(*manager);
  1904 	manager->ResetUndo();
  1905 
  1906 	// 2. when execution is supressed
  1907 	manager->SetGatekeeper(refuser);
  1908 	log->SetCheckString(_L("inc<>neg<>nomemfailadd.dec<>neg<>negate<1>"));
  1909 	TRAP(err, SetUpTestL(*manager, *noMem, &target, log));
  1910 	CheckErrorCode(err, KErrNone);
  1911 	CheckLog(*log);
  1912 	log->SetCheckString(_L("offset<1>negate<1>"));
  1913 	manager->UndoL();
  1914 	CheckLog(*log);
  1915 	log->SetCheckString(_L("offset<-1>"));
  1916 	manager->UndoL();
  1917 	CheckLog(*log);
  1918 	TestCannotUndo(*manager);
  1919 	manager->ResetUndo();
  1920 	manager->SetGatekeeper(0);
  1921 
  1922 	// 3. when memory is reclaimed
  1923 	reclaimer->iTarget = noMem;
  1924 	manager->SetGatekeeper(reclaimer);
  1925 	log->SetCheckString(_L("inc<>neg<>nomemfailadd.nomemfailinv.nomem<>dec<>neg<>negate<1>"));
  1926 	TRAP(err, SetUpTestL(*manager, *noMem, &target, log));
  1927 	CheckErrorCode(err, KErrNone);
  1928 	CheckLog(*log);
  1929 	log->SetCheckString(_L("offset<1>negate<1>"));
  1930 	manager->UndoL();
  1931 	CheckLog(*log);
  1932 	log->SetCheckString(_L("offset<-1>"));
  1933 	manager->UndoL();
  1934 	CheckLog(*log);
  1935 	TestCannotUndo(*manager);
  1936 	manager->ResetUndo();
  1937 	manager->SetGatekeeper(0);
  1938 
  1939 	// Test when execution runs out of memory
  1940 	// 1. with no reclaimation
  1941 	noMem->iFailAddToLast	= EFalse;
  1942 	noMem->iFailInvert		= EFalse;
  1943 	noMem->iFailExecute		= ETrue;
  1944 	noMem->iLogExecuteFailed= ETrue;
  1945 	log->SetCheckString(_L("inc<>neg<>nomemfailexe."));
  1946 	TRAP(err, SetUpTestL(*manager, *noMem, &target, log));
  1947 	CheckErrorCode(err, KErrNoMemory);
  1948 	CheckLog(*log);
  1949 	TestCannotRedo(*manager);
  1950 	log->SetCheckString(_L("negate<1>"));
  1951 	manager->UndoL();
  1952 	CheckLog(*log);
  1953 	log->SetCheckString(_L("offset<-1>"));
  1954 	manager->UndoL();
  1955 	CheckLog(*log);
  1956 	TestCannotUndo(*manager);
  1957 	manager->ResetUndo();
  1958 	// 2. with reclaimation
  1959 	noMem->iFailAddToLast	= EFalse;
  1960 	noMem->iFailInvert		= EFalse;
  1961 	noMem->iFailExecute		= ETrue;
  1962 	noMem->iLogExecuteFailed= ETrue;
  1963 	reclaimer->iTarget = noMem;
  1964 	manager->SetGatekeeper(reclaimer);
  1965 	log->SetCheckString(_L("inc<>neg<>nomemfailexe.nomem<>dec<>neg<>negate<1>"));
  1966 	TRAP(err, SetUpTestL(*manager, *noMem, &target, log));
  1967 	CheckErrorCode(err, KErrNone);
  1968 	CheckLog(*log);
  1969 	log->SetCheckString(_L("offset<1>negate<1>"));
  1970 	manager->UndoL();
  1971 	CheckLog(*log);
  1972 	log->SetCheckString(_L("offset<-1>"));
  1973 	manager->UndoL();
  1974 	CheckLog(*log);
  1975 	TestCannotUndo(*manager);
  1976 	manager->ResetUndo();
  1977 	manager->SetGatekeeper(0);
  1978 	delete noMem;
  1979 
  1980 	delete inc;
  1981 	delete dec;
  1982 	delete neg;
  1983 	delete reclaimer;
  1984 	delete refuser;
  1985 	delete permitter;
  1986 	delete log;
  1987 	manager->Release();
  1988 
  1989 	__UHEAP_MARKENDC(0);
  1990 	}
  1991 
  1992 //
  1993 //
  1994 //	Tests involving CTestEditor
  1995 //
  1996 //
  1997 
  1998 void CheckEditorLog(CCheckingLogger& a)
  1999 	{
  2000 	if (a.Passed())
  2001 		{
  2002 	    TESTPOINT(1);
  2003 		return;
  2004 		}
  2005 	TESTPRINT(_L("EditorUndo : log failed"));
  2006 	TESTPOINT(0);
  2007 	}
  2008 
  2009 void TestPlainText(CTestEditor& aTestEditor, MUnifiedEditor& aUndoEditor,
  2010 				   CCommandManager& aCommandManager)
  2011 	{
  2012 	CCheckingLogger* check = new(ELeave) CCheckingLogger;
  2013 	CStoringLogger* log = new(ELeave) CStoringLogger;
  2014 
  2015 	//
  2016 	// general inserting and deleting text
  2017 	//
  2018 	aUndoEditor.InsertTextL(0, _L("Hello world!"), 0, 0, 0);
  2019 
  2020 	aCommandManager.ResetUndo();
  2021 
  2022 	aTestEditor.Print(*log);
  2023 	HBufC* helloWorldLog = log->GetStore();
  2024 
  2025 	check->SetCheckString(*helloWorldLog);
  2026 	aTestEditor.Print(*check);
  2027 	CheckEditorLog(*check);
  2028 	aUndoEditor.InsertTextL(5, _L(" lovely"), 0, 0, 0);
  2029 	aTestEditor.Print(*log);
  2030 	HBufC* helloLovelyWorldLog = log->GetStore();
  2031 	aUndoEditor.DeleteTextL(10, 8);
  2032 	aTestEditor.Print(*log);
  2033 	HBufC* helloLoveLog = log->GetStore();
  2034 	aCommandManager.UndoL();
  2035 	check->SetCheckString(*helloLovelyWorldLog);
  2036 	aTestEditor.Print(*check);
  2037 	CheckEditorLog(*check);
  2038 	aCommandManager.UndoL();
  2039 	check->SetCheckString(*helloWorldLog);
  2040 	aTestEditor.Print(*check);
  2041 	CheckEditorLog(*check);
  2042 	aCommandManager.RedoL();
  2043 	check->SetCheckString(*helloLovelyWorldLog);
  2044 	aTestEditor.Print(*check);
  2045 	CheckEditorLog(*check);
  2046 	aCommandManager.RedoL();
  2047 	check->SetCheckString(*helloLoveLog);
  2048 	aTestEditor.Print(*check);
  2049 	CheckEditorLog(*check);
  2050 	aCommandManager.UndoL();
  2051 	check->SetCheckString(*helloLovelyWorldLog);
  2052 	aTestEditor.Print(*check);
  2053 	CheckEditorLog(*check);
  2054 	aCommandManager.UndoL();
  2055 	check->SetCheckString(*helloWorldLog);
  2056 	aTestEditor.Print(*check);
  2057 	CheckEditorLog(*check);
  2058 
  2059 	aUndoEditor.InsertTextL(6, _L("w"), 0, 0, 0);
  2060 	aUndoEditor.InsertTextL(7, _L("h"), 0, 0, 0);
  2061 	aUndoEditor.InsertTextL(8, _L("at's"), 0, 0, 0);
  2062 	aUndoEditor.InsertTextL(12, _L(" "), 0, 0, 0);
  2063 	aUndoEditor.InsertTextL(13, _L("w"), 0, 0, 0);
  2064 	aUndoEditor.InsertTextL(14, _L("i"), 0, 0, 0);
  2065 	aUndoEditor.InsertTextL(6, _L("there "), 0, 0, 0);
  2066 	aUndoEditor.InsertTextL(21, _L("t"), 0, 0, 0);
  2067 	aUndoEditor.InsertTextL(22, _L("h"), 0, 0, 0);
  2068 	aUndoEditor.InsertTextL(23, _L(" "), 0, 0, 0);
  2069 	aTestEditor.Print(*log);
  2070 	HBufC* textLog0 = log->GetStore();
  2071 	aUndoEditor.InsertTextL(24, _L("the"), 0, 0, 0);	// first of next
  2072 	aUndoEditor.InsertTextL(27, _L(" "), 0, 0, 0);
  2073 	aUndoEditor.InsertTextL(28, _L("d "), 0, 0, 0);
  2074 	aUndoEditor.InsertTextL(28, _L("ol"), 0, 0, 0);
  2075 	aTestEditor.Print(*log);
  2076 	HBufC* textLog1 = log->GetStore();
  2077 
  2078 	aCommandManager.UndoL();
  2079 	check->SetCheckString(*textLog0);
  2080 	aTestEditor.Print(*check);
  2081 	CheckEditorLog(*check);
  2082 
  2083 	aCommandManager.UndoL();
  2084 	check->SetCheckString(*helloWorldLog);
  2085 	aTestEditor.Print(*check);
  2086 	CheckEditorLog(*check);
  2087 
  2088 	aCommandManager.RedoL();
  2089 	check->SetCheckString(*textLog0);
  2090 	aTestEditor.Print(*check);
  2091 	CheckEditorLog(*check);
  2092 
  2093 	aCommandManager.RedoL();
  2094 	check->SetCheckString(*textLog1);
  2095 	aTestEditor.Print(*check);
  2096 	CheckEditorLog(*check);
  2097 
  2098 	// check coalescence of insertions
  2099 	aTestEditor.AlterGranularityL(5);
  2100 	aUndoEditor.DeleteTextL(22, 1);
  2101 	aUndoEditor.DeleteTextL(21, 1);
  2102 	aUndoEditor.DeleteTextL(20, 1);
  2103 	aUndoEditor.DeleteTextL(19, 1);
  2104 	aUndoEditor.DeleteTextL(18, 1);
  2105 	aUndoEditor.DeleteTextL(18, 1);
  2106 	aUndoEditor.DeleteTextL(15, 3);		// this will coalesce
  2107 	aUndoEditor.DeleteTextL(6, 9);		// this won't, as it does not fit in one command
  2108 	aTestEditor.Print(*log);
  2109 	HBufC* delLog0 = log->GetStore();
  2110 	aUndoEditor.DeleteTextL(4, 1);
  2111 	aTestEditor.Print(*log);
  2112 	HBufC* delLog1 = log->GetStore();
  2113 	aUndoEditor.DeleteTextL(8, 2);
  2114 	aUndoEditor.DeleteTextL(8, 1);	// should coalesce
  2115 	aUndoEditor.DeleteTextL(8, 1);	// should coalesce
  2116 	aTestEditor.Print(*log);
  2117 	HBufC* delLog3 = log->GetStore();
  2118 
  2119 	aCommandManager.UndoL();
  2120 	check->SetCheckString(*delLog1);
  2121 	aTestEditor.Print(*check);
  2122 	CheckEditorLog(*check);
  2123 
  2124 	aCommandManager.UndoL();
  2125 	check->SetCheckString(*delLog0);
  2126 	aTestEditor.Print(*check);
  2127 	CheckEditorLog(*check);
  2128 
  2129 	aCommandManager.UndoL();
  2130 	aCommandManager.UndoL();
  2131 	check->SetCheckString(*textLog1);
  2132 	aTestEditor.Print(*check);
  2133 	CheckEditorLog(*check);
  2134 
  2135 	aCommandManager.RedoL();
  2136 	aCommandManager.RedoL();
  2137 	check->SetCheckString(*delLog0);
  2138 	aTestEditor.Print(*check);
  2139 	CheckEditorLog(*check);
  2140 
  2141 	aCommandManager.RedoL();
  2142 	check->SetCheckString(*delLog1);
  2143 	aTestEditor.Print(*check);
  2144 	CheckEditorLog(*check);
  2145 
  2146 	aCommandManager.RedoL();
  2147 	check->SetCheckString(*delLog3);
  2148 	aTestEditor.Print(*check);
  2149 	CheckEditorLog(*check);
  2150 
  2151 	aCommandManager.UndoL();
  2152 	check->SetCheckString(*delLog1);
  2153 	aTestEditor.Print(*check);
  2154 	CheckEditorLog(*check);
  2155 
  2156 	aCommandManager.UndoL();
  2157 	check->SetCheckString(*delLog0);
  2158 	aTestEditor.Print(*check);
  2159 	CheckEditorLog(*check);
  2160 
  2161 	aCommandManager.UndoL();
  2162 	aCommandManager.UndoL();
  2163 	check->SetCheckString(*textLog1);
  2164 	aTestEditor.Print(*check);
  2165 	CheckEditorLog(*check);
  2166 
  2167 	aCommandManager.UndoL();
  2168 	aCommandManager.UndoL();
  2169 	check->SetCheckString(*helloWorldLog);
  2170 	aTestEditor.Print(*check);
  2171 	CheckEditorLog(*check);
  2172 
  2173 	aCommandManager.ResetUndo();
  2174 	delete delLog0;
  2175 	delete delLog1;
  2176 	delete delLog3;
  2177 
  2178 	// Check adding large amounts of text
  2179 	aTestEditor.AlterGranularityL(32);
  2180 	aUndoEditor.InsertTextL(0, _L("123456789"), 0, 0, 0);
  2181 	aUndoEditor.InsertTextL(0, _L("223456789"), 0, 0, 0);
  2182 	aTestEditor.Print(*log);
  2183 	HBufC* largeLog0 = log->GetStore();
  2184 	aUndoEditor.InsertTextL(0, _L("3234567890"), 0, 0, 0);
  2185 	aUndoEditor.InsertTextL(0, _L("4234567890"), 0, 0, 0);
  2186 	aTestEditor.Print(*log);
  2187 	HBufC* largeLog1 = log->GetStore();
  2188 	aUndoEditor.InsertTextL(0, _L("523456789"), 0, 0, 0);
  2189 	aTestEditor.Print(*log);
  2190 	HBufC* largeLog2 = log->GetStore();
  2191 
  2192 	aCommandManager.UndoL();
  2193 	check->SetCheckString(*largeLog1);
  2194 	aTestEditor.Print(*check);
  2195 	CheckEditorLog(*check);
  2196 
  2197 	aCommandManager.UndoL();
  2198 	check->SetCheckString(*largeLog0);
  2199 	aTestEditor.Print(*check);
  2200 	CheckEditorLog(*check);
  2201 
  2202 	aCommandManager.UndoL();
  2203 	check->SetCheckString(*helloWorldLog);
  2204 	aTestEditor.Print(*check);
  2205 	CheckEditorLog(*check);
  2206 
  2207 	aCommandManager.RedoL();
  2208 	check->SetCheckString(*largeLog0);
  2209 	aTestEditor.Print(*check);
  2210 	CheckEditorLog(*check);
  2211 
  2212 	aCommandManager.RedoL();
  2213 	check->SetCheckString(*largeLog1);
  2214 	aTestEditor.Print(*check);
  2215 	CheckEditorLog(*check);
  2216 
  2217 	aCommandManager.RedoL();
  2218 	check->SetCheckString(*largeLog2);
  2219 	aTestEditor.Print(*check);
  2220 	CheckEditorLog(*check);
  2221 
  2222 	aCommandManager.UndoL();
  2223 	check->SetCheckString(*largeLog1);
  2224 	aTestEditor.Print(*check);
  2225 	CheckEditorLog(*check);
  2226 
  2227 	aCommandManager.UndoL();
  2228 	check->SetCheckString(*largeLog0);
  2229 	aTestEditor.Print(*check);
  2230 	CheckEditorLog(*check);
  2231 
  2232 	aCommandManager.UndoL();
  2233 	check->SetCheckString(*helloWorldLog);
  2234  	aTestEditor.Print(*check);
  2235 	CheckEditorLog(*check);
  2236 
  2237 	aCommandManager.RedoL();
  2238 	aCommandManager.RedoL();
  2239 	aCommandManager.RedoL();
  2240 
  2241 	// test copy and paste
  2242 	MUnifiedEditor::MClipboardSupport* ci = aUndoEditor.ClipboardSupport();
  2243 	ASSERT(ci);
  2244 
  2245 	CBufStore* clipboardBuffer = CBufStore::NewL(100);
  2246 	CStreamDictionary* clipboardDictionary = CStreamDictionary::NewL();
  2247 
  2248 	ci->CopyToStoreL(*clipboardBuffer, *clipboardDictionary, 5, 40);
  2249 	aTestEditor.Print(*log);
  2250 	HBufC* clipLog0 = log->GetStore();
  2251 	ci->PasteFromStoreL(*clipboardBuffer, *clipboardDictionary, 2);
  2252 	aTestEditor.Print(*log);
  2253 	HBufC* clipLog1 = log->GetStore();
  2254 	ci->PasteFromStoreL(*clipboardBuffer, *clipboardDictionary, 55);
  2255 	aTestEditor.Print(*log);
  2256 	HBufC* clipLog2 = log->GetStore();
  2257 	ci->PasteFromStoreL(*clipboardBuffer, *clipboardDictionary, 23);
  2258 	aTestEditor.Print(*log);
  2259 	HBufC* clipLog3 = log->GetStore();
  2260 
  2261 	aCommandManager.UndoL();
  2262 	check->SetCheckString(*clipLog2);
  2263 	aTestEditor.Print(*check);
  2264 	CheckEditorLog(*check);
  2265 
  2266 	aCommandManager.UndoL();
  2267 	check->SetCheckString(*clipLog1);
  2268 	aTestEditor.Print(*check);
  2269 	CheckEditorLog(*check);
  2270 
  2271 	aCommandManager.UndoL();
  2272 	check->SetCheckString(*clipLog0);
  2273 	aTestEditor.Print(*check);
  2274 	CheckEditorLog(*check);
  2275 
  2276 	aCommandManager.RedoL();
  2277 	check->SetCheckString(*clipLog1);
  2278 	aTestEditor.Print(*check);
  2279 	CheckEditorLog(*check);
  2280 
  2281 	aCommandManager.RedoL();
  2282 	check->SetCheckString(*clipLog2);
  2283 	aTestEditor.Print(*check);
  2284 	CheckEditorLog(*check);
  2285 
  2286 	aCommandManager.RedoL();
  2287 	check->SetCheckString(*clipLog3);
  2288 	aTestEditor.Print(*check);
  2289 	CheckEditorLog(*check);
  2290 
  2291 	aCommandManager.UndoL();
  2292 	check->SetCheckString(*clipLog2);
  2293 	aTestEditor.Print(*check);
  2294 	CheckEditorLog(*check);
  2295 
  2296 	aCommandManager.UndoL();
  2297 	check->SetCheckString(*clipLog1);
  2298 	aTestEditor.Print(*check);
  2299 	CheckEditorLog(*check);
  2300 
  2301 	aCommandManager.UndoL();
  2302 	check->SetCheckString(*clipLog0);
  2303 	aTestEditor.Print(*check);
  2304 	CheckEditorLog(*check);
  2305 
  2306 	delete clipLog0;
  2307 	delete clipLog1;
  2308 	delete clipLog2;
  2309 	delete clipLog3;
  2310 	delete clipboardDictionary;
  2311 	delete clipboardBuffer;
  2312 
  2313 	delete textLog0;
  2314 	delete textLog1;
  2315 
  2316 	delete largeLog0;
  2317 	delete largeLog1;
  2318 	delete largeLog2;
  2319 
  2320 	delete helloWorldLog;
  2321 	delete helloLovelyWorldLog;
  2322 	delete helloLoveLog;
  2323 	delete log;
  2324 	delete check;
  2325 	}
  2326 
  2327 // This class merely splits the test function into little functions
  2328 // to help out the MW compiler
  2329 class TestEditorUndo
  2330 	{
  2331 	CCheckingLogger* check;
  2332 	CStoringLogger* log;
  2333 	CTestEditor* testEd;
  2334 	CCommandManager* manager;
  2335 	CEditorPlainTextWithUndo* plainEd;
  2336 	CEditorWithUndo* ed;
  2337 	TTmCharFormatMask charBMask;
  2338 	TTmCharFormatMask charIMask;
  2339 	TTmCharFormatMask charBIMask;
  2340 	TOpenFontFaceAttribBase attrib;
  2341 	TTmCharFormat charB;
  2342 	TTmCharFormat charIB;
  2343 	TTmCharFormat charI;
  2344 	TTmParFormatMask parTMask;
  2345 	TTmParFormatMask parNMask;
  2346 	TTmParFormatMask parTNMask;
  2347 	RTmParFormat par0;
  2348 	RTmParFormat parT;
  2349 	RTmParFormat parN;
  2350 	RTmParFormat parTN;
  2351 	TTmCharFormatLayer charLayer;
  2352 	RTmParFormatLayer parLayer;
  2353 	RTmStyle style1;
  2354 	RTmStyle style2;
  2355 	HBufC* charLog0;
  2356 	HBufC* charLog1;
  2357 	HBufC* charLog2;
  2358 	HBufC* charLog3;
  2359 	HBufC* textLog0;
  2360 	HBufC* textLog1;
  2361 	HBufC* textLog2;
  2362 	HBufC* textLog3;
  2363 	HBufC* parLog0;
  2364 	HBufC* parLog1;
  2365 	HBufC* parLog2;
  2366 	HBufC* parLog3;
  2367 	HBufC* delLog0;
  2368 	HBufC* delLog1;
  2369 	HBufC* delLog2;
  2370 	HBufC* delLog3;
  2371 	HBufC* styleLog1;
  2372 	HBufC* styleLog2;
  2373 	HBufC* styleLog3;
  2374 	HBufC* styleLog4;
  2375 	HBufC* styleLog5;
  2376 	HBufC* styleLog6;
  2377 	HBufC* styleLog7;
  2378 	HBufC* styleLog8;
  2379 	HBufC* styleLog9;
  2380 	HBufC* styleLog10;
  2381 	HBufC* styleLog11;
  2382 	HBufC* styleLog12;
  2383 	HBufC* styleLog13;
  2384 	HBufC* picLog0;
  2385 	HBufC* picLog1;
  2386 	HBufC* picLog2;
  2387 	HBufC* picLog3;
  2388 	HBufC* picLog4;
  2389 	HBufC* picLog5;
  2390 	HBufC* bookMarkLog0;
  2391 	HBufC* bookMarkLog1;
  2392 	HBufC* bookMarkLog2;
  2393 	HBufC* bookMarkLog3;
  2394 	HBufC* bookMarkLog4;
  2395 	HBufC* bookMarkLog5;
  2396 public:
  2397 	void Test1L();
  2398 	void Test2L();
  2399 	void Test3L();
  2400 	void Test4L();
  2401 	void Test5L();
  2402 	void Test6L();
  2403 	void Test7L();
  2404 	void Test8L();
  2405 	};
  2406 
  2407 void TestEditorUndo::Test1L()
  2408 	{
  2409 	check = new(ELeave) CCheckingLogger;
  2410 	log = new(ELeave) CStoringLogger;
  2411 	testEd = CTestEditor::NewL();
  2412 	manager = CCommandManager::NewL();
  2413 	plainEd = CEditorPlainTextWithUndo::NewL(*testEd, manager);
  2414 
  2415 	TestPlainText(*testEd, *plainEd, *manager);
  2416 	ed = CEditorWithUndo::NewL(*testEd, manager);
  2417 	testEd->DeleteTextL(0, testEd->DocumentLength());
  2418 	manager->ResetUndo();
  2419 
  2420 	delete plainEd;
  2421 	plainEd = 0;
  2422 
  2423 	TestPlainText(*testEd, *ed, *manager);
  2424 	manager->Release();
  2425 	}
  2426 
  2427 void TestEditorUndo::Test2L()
  2428 	{
  2429 	// char and par formats
  2430 	charBMask.iFlags = TTmCharFormatMask::EBold;
  2431 	charIMask.iFlags = TTmCharFormatMask::EItalic;
  2432 	charBIMask.iFlags = TTmCharFormatMask::EItalic | TTmCharFormatMask::EBold;
  2433 	attrib.SetBold(ETrue);
  2434 	charB.iFontSpec.SetAttrib(attrib);
  2435 	attrib.SetItalic(ETrue);
  2436 	charIB.iFontSpec.SetAttrib(attrib);
  2437 	attrib.SetBold(EFalse);
  2438 	charI.iFontSpec.SetAttrib(attrib);
  2439 
  2440 	parTMask.iFlags = TTmParFormatMask::EKeepTogether;
  2441 	parNMask.iFlags = TTmParFormatMask::EKeepWithNext;
  2442 	parTNMask.iFlags = TTmParFormatMask::EKeepTogether | TTmParFormatMask::EKeepWithNext;
  2443 	parT.iFlags = RTmParFormat::EKeepTogether;
  2444 	parN.iFlags = RTmParFormat::EKeepWithNext;
  2445 	parTN.iFlags = RTmParFormat::EKeepWithNext | RTmParFormat::EKeepTogether;
  2446 
  2447 	charLayer.iFormat = charB;
  2448 	charLayer.iMask = charBMask;
  2449 	ed->SetCharFormatL(0, 5, charLayer);
  2450 	testEd->Print(*log);
  2451 	charLog0 = log->GetStore();
  2452 
  2453 	charLayer.iFormat = charI;
  2454 	charLayer.iMask = charIMask;
  2455 	ed->SetCharFormatL(3, 9, charLayer);
  2456 	testEd->Print(*log);
  2457 	charLog1 = log->GetStore();
  2458 
  2459 	charLayer.iFormat = charB;
  2460 	charLayer.iMask = charBIMask;
  2461 	ed->SetCharFormatL(2, 5, charLayer);
  2462 	testEd->Print(*log);
  2463 	charLog2 = log->GetStore();
  2464 
  2465 	ed->DeleteCharFormatL(1, 10);
  2466 	testEd->Print(*log);
  2467 	charLog3 = log->GetStore();
  2468 
  2469 	ed->UndoL();
  2470 	check->SetCheckString(*charLog2);
  2471 	testEd->Print(*check);
  2472 	CheckEditorLog(*check);
  2473 
  2474 	ed->UndoL();
  2475 	check->SetCheckString(*charLog1);
  2476 	testEd->Print(*check);
  2477 	CheckEditorLog(*check);
  2478 
  2479 	ed->UndoL();
  2480 	check->SetCheckString(*charLog0);
  2481 	testEd->Print(*check);
  2482 	CheckEditorLog(*check);
  2483 
  2484 	ed->RedoL();
  2485 	check->SetCheckString(*charLog1);
  2486 	testEd->Print(*check);
  2487 	CheckEditorLog(*check);
  2488 
  2489 	ed->RedoL();
  2490 	check->SetCheckString(*charLog2);
  2491 	testEd->Print(*check);
  2492 	CheckEditorLog(*check);
  2493 
  2494 	ed->RedoL();
  2495 	check->SetCheckString(*charLog3);
  2496 	testEd->Print(*check);
  2497 	CheckEditorLog(*check);
  2498 
  2499 	parLayer.iMask = parTMask;
  2500 	parLayer.iFormat.CopyL(parT);
  2501 	ed->SetParFormatL(5, 7, parLayer);
  2502 	testEd->Print(*log);
  2503 	parLog0 = log->GetStore();
  2504 
  2505 	parLayer.iMask = parTNMask;
  2506 	parLayer.iFormat.CopyL(parN);
  2507 	ed->SetParFormatL(0, 7, parLayer);
  2508 	testEd->Print(*log);
  2509 	parLog1 = log->GetStore();
  2510 
  2511 	ed->DeleteParFormatL(4, 4);
  2512 	testEd->Print(*log);
  2513 	parLog2 = log->GetStore();
  2514 
  2515 	parLayer.iMask = parNMask;
  2516 	parLayer.iFormat.CopyL(parN);
  2517 	ed->SetParFormatL(3, 6, parLayer);
  2518 	testEd->Print(*log);
  2519 	parLog3 = log->GetStore();
  2520 
  2521 	ed->UndoL();
  2522 	check->SetCheckString(*parLog2);
  2523 	testEd->Print(*check);
  2524 	CheckEditorLog(*check);
  2525 
  2526 	ed->UndoL();
  2527 	check->SetCheckString(*parLog1);
  2528 	testEd->Print(*check);
  2529 	CheckEditorLog(*check);
  2530 
  2531 	ed->UndoL();
  2532 	check->SetCheckString(*parLog0);
  2533 	testEd->Print(*check);
  2534 	CheckEditorLog(*check);
  2535 
  2536 	ed->UndoL();
  2537 	check->SetCheckString(*charLog3);
  2538 	testEd->Print(*check);
  2539 	CheckEditorLog(*check);
  2540 
  2541 	ed->RedoL();
  2542 	check->SetCheckString(*parLog0);
  2543 	testEd->Print(*check);
  2544 	CheckEditorLog(*check);
  2545 
  2546 	ed->RedoL();
  2547 	check->SetCheckString(*parLog1);
  2548 	testEd->Print(*check);
  2549 	CheckEditorLog(*check);
  2550 
  2551 	ed->RedoL();
  2552 	check->SetCheckString(*parLog2);
  2553 	testEd->Print(*check);
  2554 	CheckEditorLog(*check);
  2555 
  2556 	ed->RedoL();
  2557 	check->SetCheckString(*parLog3);
  2558 	testEd->Print(*check);
  2559 	CheckEditorLog(*check);
  2560 	}
  2561 
  2562 void TestEditorUndo::Test3L()
  2563 	{
  2564 	// check coalescence of deletions
  2565 	charLayer.iMask = charIMask;
  2566 	charLayer.iFormat = charI;
  2567 	parLayer.iMask = parNMask;
  2568 	parLayer.iFormat.CopyL(parN);
  2569 	ed->InsertTextL(6, _L("w"), 0, &charLayer, &parLayer);
  2570 	ed->InsertTextL(7, _L("h"), 0, &charLayer, &parLayer);
  2571 	ed->InsertTextL(8, _L("at's"), 0, &charLayer, &parLayer);
  2572 	ed->InsertTextL(12, _L(" "), 0, &charLayer, &parLayer);
  2573 	ed->InsertTextL(13, _L("w"), 0, &charLayer, &parLayer);
  2574 	ed->InsertTextL(14, _L("i"), 0, &charLayer, &parLayer);
  2575 	ed->InsertTextL(6, _L("there "), 0, &charLayer, &parLayer);
  2576 	ed->InsertTextL(21, _L("t"), 0, &charLayer, &parLayer);
  2577 	ed->InsertTextL(22, _L("h"), 0, &charLayer, &parLayer);
  2578 	ed->InsertTextL(23, _L(" "), 0, &charLayer, &parLayer);
  2579 	testEd->Print(*log);
  2580 	textLog0 = log->GetStore();
  2581 	ed->InsertTextL(24, _L("the"), 0, &charLayer, &parLayer);	// first of next?
  2582 	ed->InsertTextL(27, _L(" "), 0, &charLayer, &parLayer);
  2583 	testEd->Print(*log);
  2584 	textLog1 = log->GetStore();
  2585 	charLayer.iMask = charBIMask;
  2586 	ed->InsertTextL(28, _L("ol"), 0, &charLayer, &parLayer);
  2587 	testEd->Print(*log);
  2588 	textLog2 = log->GetStore();
  2589 	parLayer.iMask = parTNMask;
  2590 	ed->InsertTextL(30, _L("d "), 0, &charLayer, &parLayer);
  2591 	testEd->Print(*log);
  2592 	textLog3 = log->GetStore();
  2593 
  2594 	ed->UndoL();
  2595 	check->SetCheckString(*textLog0);
  2596 	testEd->Print(*check);
  2597 	CheckEditorLog(*check);
  2598 
  2599 	ed->UndoL();
  2600 	check->SetCheckString(*parLog3);
  2601 	testEd->Print(*check);
  2602 	CheckEditorLog(*check);
  2603 
  2604 	ed->RedoL();
  2605 	check->SetCheckString(*textLog0);
  2606 	testEd->Print(*check);
  2607 	CheckEditorLog(*check);
  2608 
  2609 	ed->RedoL();
  2610 	check->SetCheckString(*textLog3);
  2611 	testEd->Print(*check);
  2612 	CheckEditorLog(*check);
  2613 	ed->ResetUndo();
  2614 	}
  2615 
  2616 void TestEditorUndo::Test4L()
  2617 	{
  2618 	// check coalescence of insertions
  2619 	testEd->AlterGranularityL(5);
  2620 	ed->DeleteTextL(22, 1);
  2621 	ed->DeleteTextL(21, 1);
  2622 	ed->DeleteTextL(20, 1);
  2623 	ed->DeleteTextL(19, 1);
  2624 	ed->DeleteTextL(18, 1);
  2625 	ed->DeleteTextL(18, 1);
  2626 	ed->DeleteTextL(15, 3);		// this will coalesce
  2627 	ed->DeleteTextL(6, 9);		// this won't, as it does not fit in one command
  2628 	testEd->Print(*log);
  2629 	delLog0 = log->GetStore();
  2630 	ed->DeleteTextL(4, 1);
  2631 	testEd->Print(*log);
  2632 	delLog1 = log->GetStore();
  2633 	ed->DeleteTextL(8, 2);
  2634 	ed->DeleteTextL(8, 1);	// should coalesce
  2635 	testEd->Print(*log);
  2636 	delLog2 = log->GetStore();
  2637 	ed->DeleteTextL(8, 1);	// should fail to coalesce
  2638 	testEd->Print(*log);
  2639 	delLog3 = log->GetStore();
  2640 
  2641 	ed->UndoL();
  2642 	check->SetCheckString(*delLog2);
  2643 	testEd->Print(*check);
  2644 	CheckEditorLog(*check);
  2645 
  2646 	ed->UndoL();
  2647 	check->SetCheckString(*delLog1);
  2648 	testEd->Print(*check);
  2649 	CheckEditorLog(*check);
  2650 
  2651 	ed->UndoL();
  2652 	check->SetCheckString(*delLog0);
  2653 	testEd->Print(*check);
  2654 	CheckEditorLog(*check);
  2655 
  2656 	ed->UndoL();
  2657 	ed->UndoL();
  2658 	check->SetCheckString(*textLog3);
  2659 	testEd->Print(*check);
  2660 	CheckEditorLog(*check);
  2661 
  2662 	ed->RedoL();
  2663 	ed->RedoL();
  2664 	check->SetCheckString(*delLog0);
  2665 	testEd->Print(*check);
  2666 	CheckEditorLog(*check);
  2667 
  2668 	ed->RedoL();
  2669 	check->SetCheckString(*delLog1);
  2670 	testEd->Print(*check);
  2671 	CheckEditorLog(*check);
  2672 
  2673 	ed->RedoL();
  2674 	check->SetCheckString(*delLog2);
  2675 	testEd->Print(*check);
  2676 	CheckEditorLog(*check);
  2677 
  2678 	ed->RedoL();
  2679 	check->SetCheckString(*delLog3);
  2680 	testEd->Print(*check);
  2681 	CheckEditorLog(*check);
  2682 
  2683 	ed->UndoL();
  2684 	check->SetCheckString(*delLog2);
  2685 	testEd->Print(*check);
  2686 	CheckEditorLog(*check);
  2687 
  2688 	ed->UndoL();
  2689 	check->SetCheckString(*delLog1);
  2690 	testEd->Print(*check);
  2691 	CheckEditorLog(*check);
  2692 
  2693 	ed->UndoL();
  2694 	check->SetCheckString(*delLog0);
  2695 	testEd->Print(*check);
  2696 	CheckEditorLog(*check);
  2697 
  2698 	ed->UndoL();
  2699 	ed->UndoL();
  2700 	check->SetCheckString(*textLog3);
  2701 	testEd->Print(*check);
  2702 	CheckEditorLog(*check);
  2703 	ed->ResetUndo();
  2704 	delete delLog0;
  2705 	delete delLog1;
  2706 	delete delLog2;
  2707 	delete delLog3;
  2708 	}
  2709 
  2710 void TestEditorUndo::Test5L()
  2711 	{
  2712 	// Check adding large amounts of text
  2713 	testEd->AlterGranularityL(32);
  2714 	ed->InsertTextL(0, _L("123456789"), 0, 0, 0);
  2715 	ed->InsertTextL(0, _L("223456789"), 0, 0, 0);
  2716 	testEd->Print(*log);
  2717 	delete textLog0;
  2718 	textLog0 = log->GetStore();
  2719 	ed->InsertTextL(0, _L("3234567890"), 0, 0, 0);
  2720 	ed->InsertTextL(0, _L("4234567890"), 0, 0, 0);
  2721 	testEd->Print(*log);
  2722 	delete textLog1;
  2723 	textLog1 = log->GetStore();
  2724 	ed->InsertTextL(0, _L("523456789"), 0, 0, 0);
  2725 	testEd->Print(*log);
  2726 	delete textLog2;
  2727 	textLog2 = log->GetStore();
  2728 
  2729 	ed->UndoL();
  2730 	check->SetCheckString(*textLog1);
  2731 	testEd->Print(*check);
  2732 	CheckEditorLog(*check);
  2733 
  2734 	ed->UndoL();
  2735 	check->SetCheckString(*textLog0);
  2736 	testEd->Print(*check);
  2737 	CheckEditorLog(*check);
  2738 
  2739 	ed->UndoL();
  2740 	check->SetCheckString(*textLog3);
  2741 	testEd->Print(*check);
  2742 	CheckEditorLog(*check);
  2743 
  2744 	ed->RedoL();
  2745 	check->SetCheckString(*textLog0);
  2746 	testEd->Print(*check);
  2747 	CheckEditorLog(*check);
  2748 
  2749 	ed->RedoL();
  2750 	check->SetCheckString(*textLog1);
  2751 	testEd->Print(*check);
  2752 	CheckEditorLog(*check);
  2753 
  2754 	ed->RedoL();
  2755 	check->SetCheckString(*textLog2);
  2756 	testEd->Print(*check);
  2757 	CheckEditorLog(*check);
  2758 
  2759 	ed->UndoL();
  2760 	check->SetCheckString(*textLog1);
  2761 	testEd->Print(*check);
  2762 	CheckEditorLog(*check);
  2763 
  2764 	ed->UndoL();
  2765 	check->SetCheckString(*textLog0);
  2766 	testEd->Print(*check);
  2767 	CheckEditorLog(*check);
  2768 
  2769 	ed->UndoL();
  2770 	check->SetCheckString(*textLog3);
  2771 	testEd->Print(*check);
  2772 	CheckEditorLog(*check);
  2773 	}
  2774 
  2775 void TestEditorUndo::Test6L()
  2776 	{
  2777 	// test style manipulation
  2778 	style1.iName = _L("author");
  2779 	style2.iName = _L("title");
  2780 	style2.iNextStyleName = _L("author");
  2781 	style1.iCharFormat.iFormat = charI;
  2782 	style1.iCharFormat.iMask = charIMask;
  2783 	style1.iParFormat.iFormat.CopyL(parT);
  2784 	style1.iParFormat.iMask = parTNMask;
  2785 	style2.iCharFormat.iFormat = charB;
  2786 	style2.iCharFormat.iMask = charBIMask;
  2787 	style2.iParFormat.iFormat.CopyL(parN);
  2788 	style2.iParFormat.iMask = parNMask;
  2789 
  2790 	ed->StyleSupport()->CreateStyleL(style1);
  2791 	testEd->Print(*log);
  2792 	styleLog1 = log->GetStore();
  2793 	TInt retval = ed->StyleSupport()->SetStyleL(1, 3, _L("author"));
  2794 	testEd->Print(*log);
  2795 	styleLog2 = log->GetStore();
  2796 	if (retval != KErrNone)
  2797 		{
  2798         TESTPRINT(_L("EditorUndo : apply style failed"));
  2799         TESTPOINT(0);
  2800 		}
  2801 	TPtrC testStyleName;
  2802 	TInt testStyleRunLength;
  2803 	ed->StyleSupport()->GetStyle(1, testStyleName, testStyleRunLength);
  2804 	if (testStyleRunLength != 3 || testStyleName != style1.iName)
  2805 		{
  2806         TESTPRINT(_L("EditorUndo : apply style failed"));
  2807 		TESTPOINT(0);
  2808 		}
  2809 	ed->InsertTextL(5, _L(","), &style1.iName, 0, 0);
  2810 	testEd->Print(*log);
  2811 	styleLog3 = log->GetStore();
  2812 	ed->StyleSupport()->CreateStyleL(style2);
  2813 	testEd->Print(*log);
  2814 	styleLog4 = log->GetStore();
  2815 	ed->StyleSupport()->SetStyleL(2, 7, _L("title"));
  2816 	testEd->Print(*log);
  2817 	styleLog5 = log->GetStore();
  2818 	ed->StyleSupport()->SetStyleL(10, 4, _L("title"));
  2819 	testEd->Print(*log);
  2820 	styleLog6 = log->GetStore();
  2821 	ed->StyleSupport()->SetStyleL(8, 4, _L("author"));
  2822 	testEd->Print(*log);
  2823 	styleLog7 = log->GetStore();
  2824 	style1.iCharFormat.iFormat = charB;
  2825 	style1.iCharFormat.iMask = charBMask;
  2826 	ed->StyleSupport()->ChangeStyleL(style1);
  2827 	testEd->Print(*log);
  2828 	styleLog8 = log->GetStore();
  2829  	ed->StyleSupport()->RenameStyleL(_L("author"), _L("version"));
  2830 	style1.iName = _L("version");
  2831 	testEd->Print(*log);
  2832 	styleLog9 = log->GetStore();
  2833 	retval = ed->StyleSupport()->SetStyleL(10, 1, _L("version"));
  2834 	testEd->Print(*log);
  2835 	styleLog10 = log->GetStore();
  2836 	if (retval != KErrNone)
  2837 		{
  2838         TESTPRINT(_L("EditorUndo : rename style failed"));
  2839 		TESTPOINT(0);
  2840 		}
  2841 	ed->StyleSupport()->GetStyle(1, testStyleName, testStyleRunLength);
  2842 	if (testStyleRunLength != 1 || testStyleName != style1.iName)
  2843 		{
  2844         TESTPRINT(_L("EditorUndo : rename or apply style failed"));
  2845 		TESTPOINT(0);
  2846 		}
  2847 	ed->StyleSupport()->RenameStyleL(_L("title"), _L("zip"));
  2848 	style2.iName = _L("zip");
  2849 	testEd->Print(*log);
  2850 	styleLog11 = log->GetStore();
  2851 	ed->StyleSupport()->SetStyleL(0, 6, _L("zip"));
  2852 	testEd->Print(*log);
  2853 	styleLog12 = log->GetStore();
  2854 	ed->StyleSupport()->DeleteStyleL(_L("zip"));
  2855 	testEd->Print(*log);
  2856 	styleLog13 = log->GetStore();
  2857 	ed->InsertTextL(0, _L("Well "), &style1.iName, 0, 0);
  2858 
  2859 	ed->UndoL();
  2860 	check->SetCheckString(*styleLog13);
  2861 	testEd->Print(*check);
  2862 	CheckEditorLog(*check);
  2863 
  2864 	ed->UndoL();
  2865 	check->SetCheckString(*styleLog12);
  2866 	testEd->Print(*check);
  2867 	CheckEditorLog(*check);
  2868 
  2869 	ed->UndoL();
  2870 	check->SetCheckString(*styleLog11);
  2871 	testEd->Print(*check);
  2872 	CheckEditorLog(*check);
  2873 
  2874 	ed->UndoL();
  2875 	check->SetCheckString(*styleLog10);
  2876 	testEd->Print(*check);
  2877 	CheckEditorLog(*check);
  2878 
  2879 	ed->UndoL();
  2880 	check->SetCheckString(*styleLog9);
  2881 	testEd->Print(*check);
  2882 	CheckEditorLog(*check);
  2883 
  2884 	ed->UndoL();
  2885 	check->SetCheckString(*styleLog8);
  2886 	testEd->Print(*check);
  2887 	CheckEditorLog(*check);
  2888 
  2889 	ed->UndoL();
  2890 	check->SetCheckString(*styleLog7);
  2891 	testEd->Print(*check);
  2892 	CheckEditorLog(*check);
  2893 
  2894 	ed->UndoL();
  2895 	check->SetCheckString(*styleLog6);
  2896 	testEd->Print(*check);
  2897 	CheckEditorLog(*check);
  2898 
  2899 	ed->UndoL();
  2900 	check->SetCheckString(*styleLog5);
  2901 	testEd->Print(*check);
  2902 	CheckEditorLog(*check);
  2903 
  2904 	ed->UndoL();
  2905 	check->SetCheckString(*styleLog4);
  2906 	testEd->Print(*check);
  2907 	CheckEditorLog(*check);
  2908 
  2909 	ed->UndoL();
  2910 	check->SetCheckString(*styleLog3);
  2911 	testEd->Print(*check);
  2912 	CheckEditorLog(*check);
  2913 
  2914 	ed->UndoL();
  2915 	check->SetCheckString(*styleLog2);
  2916 	testEd->Print(*check);
  2917 	CheckEditorLog(*check);
  2918 
  2919 	ed->UndoL();
  2920 	check->SetCheckString(*styleLog1);
  2921 	testEd->Print(*check);
  2922 	CheckEditorLog(*check);
  2923 
  2924 	ed->UndoL();
  2925 	check->SetCheckString(*textLog3);
  2926 	testEd->Print(*check);
  2927 	CheckEditorLog(*check);
  2928 
  2929 	ed->RedoL();
  2930 	check->SetCheckString(*styleLog1);
  2931 	testEd->Print(*check);
  2932 	CheckEditorLog(*check);
  2933 
  2934 	ed->RedoL();
  2935 	check->SetCheckString(*styleLog2);
  2936 	testEd->Print(*check);
  2937 	CheckEditorLog(*check);
  2938 
  2939 	ed->RedoL();
  2940 	check->SetCheckString(*styleLog3);
  2941 	testEd->Print(*check);
  2942 	CheckEditorLog(*check);
  2943 
  2944 	ed->RedoL();
  2945 	check->SetCheckString(*styleLog4);
  2946 	testEd->Print(*check);
  2947 	CheckEditorLog(*check);
  2948 
  2949 	ed->RedoL();
  2950 	check->SetCheckString(*styleLog5);
  2951 	testEd->Print(*check);
  2952 	CheckEditorLog(*check);
  2953 
  2954 	ed->RedoL();
  2955 	check->SetCheckString(*styleLog6);
  2956 	testEd->Print(*check);
  2957 	CheckEditorLog(*check);
  2958 
  2959 	ed->RedoL();
  2960 	check->SetCheckString(*styleLog7);
  2961 	testEd->Print(*check);
  2962 	CheckEditorLog(*check);
  2963 
  2964 	ed->RedoL();
  2965 	check->SetCheckString(*styleLog8);
  2966 	testEd->Print(*check);
  2967 	CheckEditorLog(*check);
  2968 
  2969 	ed->RedoL();
  2970 	check->SetCheckString(*styleLog9);
  2971 	testEd->Print(*check);
  2972 	CheckEditorLog(*check);
  2973 
  2974 	ed->RedoL();
  2975 	check->SetCheckString(*styleLog10);
  2976 	testEd->Print(*check);
  2977 	CheckEditorLog(*check);
  2978 
  2979 	ed->RedoL();
  2980 	check->SetCheckString(*styleLog11);
  2981 	testEd->Print(*check);
  2982 	CheckEditorLog(*check);
  2983 
  2984 	ed->RedoL();
  2985 	check->SetCheckString(*styleLog12);
  2986 	testEd->Print(*check);
  2987 	CheckEditorLog(*check);
  2988 
  2989 	ed->RedoL();
  2990 	check->SetCheckString(*styleLog13);
  2991 	testEd->Print(*check);
  2992 	CheckEditorLog(*check);
  2993 
  2994 	// probably need some more style tests that test the full range of
  2995 	// attributes that a style may have.
  2996 	//...
  2997 
  2998 	delete textLog0;
  2999 	delete textLog1;
  3000 	delete textLog2;
  3001 	delete parLog0;
  3002 	delete parLog1;
  3003 	delete parLog2;
  3004 	delete parLog3;
  3005 	delete charLog0;
  3006 	delete charLog1;
  3007 	delete charLog2;
  3008 	delete charLog3;
  3009 	delete styleLog1;
  3010 	delete styleLog2;
  3011 	delete styleLog3;
  3012 	delete styleLog4;
  3013 	delete styleLog5;
  3014 	delete styleLog6;
  3015 	delete styleLog7;
  3016 	delete styleLog8;
  3017 	delete styleLog9;
  3018 	delete styleLog10;
  3019 	delete styleLog11;
  3020 	delete styleLog12;
  3021 	delete styleLog13;
  3022 
  3023 	delete textLog3;
  3024 	}
  3025 
  3026 void TestEditorUndo::Test7L()
  3027 	{
  3028 	// test picture manipulation
  3029 	TPictureHeader pic;
  3030 	pic.iPictureType = KUidXzePictureType;
  3031 	testEd->Print(*log);
  3032 	picLog0 = log->GetStore();
  3033 	pic.iPicture = new (ELeave) CUndoTestPicture('A');
  3034 	ed->PictureSupport()->InsertPictureL(5, pic);
  3035 	testEd->Print(*log);
  3036 	picLog1 = log->GetStore();
  3037 	pic.iPicture = new (ELeave) CUndoTestPicture('B');
  3038 	ed->PictureSupport()->InsertPictureL(8, pic);
  3039 	testEd->Print(*log);
  3040 	picLog2 = log->GetStore();
  3041 	pic.iPicture = new (ELeave) CUndoTestPicture('C');
  3042 	ed->PictureSupport()->InsertPictureL(9, pic);
  3043 	testEd->Print(*log);
  3044 	picLog3 = log->GetStore();
  3045 	pic.iPicture = new (ELeave) CUndoTestPicture('D');
  3046 	ed->PictureSupport()->InsertPictureL(12, pic);
  3047 	ed->StyleSupport()->SetStyleL(6, 2, style1.iName);
  3048 	ed->SetCharFormatL(8, 3, charLayer);
  3049 	ed->SetParFormatL(7, 7, parLayer);
  3050 	testEd->Print(*log);
  3051 	picLog4 = log->GetStore();
  3052 	ed->DeleteTextL(5, 8);
  3053 	testEd->Print(*log);
  3054 	picLog5 = log->GetStore();
  3055 
  3056 	ed->UndoL();
  3057 	check->SetCheckString(*picLog4);
  3058 	testEd->Print(*check);
  3059 	CheckEditorLog(*check);
  3060 
  3061 	ed->UndoL();
  3062 	ed->UndoL();
  3063 	ed->UndoL();
  3064 	ed->UndoL();
  3065 	check->SetCheckString(*picLog3);
  3066 	testEd->Print(*check);
  3067 	CheckEditorLog(*check);
  3068 
  3069 	ed->UndoL();
  3070 	check->SetCheckString(*picLog2);
  3071 	testEd->Print(*check);
  3072 	CheckEditorLog(*check);
  3073 
  3074 	ed->UndoL();
  3075 	check->SetCheckString(*picLog1);
  3076 	testEd->Print(*check);
  3077 	CheckEditorLog(*check);
  3078 
  3079 	ed->UndoL();
  3080 	check->SetCheckString(*picLog0);
  3081 	testEd->Print(*check);
  3082 	CheckEditorLog(*check);
  3083 
  3084 	ed->RedoL();
  3085 	check->SetCheckString(*picLog1);
  3086 	testEd->Print(*check);
  3087 	CheckEditorLog(*check);
  3088 
  3089 	ed->RedoL();
  3090 	check->SetCheckString(*picLog2);
  3091 	testEd->Print(*check);
  3092 	CheckEditorLog(*check);
  3093 
  3094 	ed->RedoL();
  3095 	check->SetCheckString(*picLog3);
  3096 	testEd->Print(*check);
  3097 	CheckEditorLog(*check);
  3098 
  3099 	ed->RedoL();
  3100 	ed->RedoL();
  3101 	ed->RedoL();
  3102 	ed->RedoL();
  3103 	check->SetCheckString(*picLog4);
  3104 	testEd->Print(*check);
  3105 	CheckEditorLog(*check);
  3106 
  3107 	ed->RedoL();
  3108 	check->SetCheckString(*picLog5);
  3109 	testEd->Print(*check);
  3110 	CheckEditorLog(*check);
  3111 
  3112 	style1.Close();
  3113 	style2.Close();
  3114 	parLayer.Close();
  3115 	par0.Close();
  3116 	parT.Close();
  3117 	parN.Close();
  3118 	parTN.Close();
  3119 	delete picLog0;
  3120 	delete picLog1;
  3121 	delete picLog2;
  3122 	delete picLog3;
  3123 	delete picLog4;
  3124 	delete picLog5;
  3125 	}
  3126 
  3127 void TestEditorUndo::Test8L()
  3128 	{
  3129 	// test bookmarking
  3130 	for (TInt i = 0; i != 7; ++i)
  3131 		{
  3132 		testEd->Reset();
  3133 		ed->ResetUndo();
  3134 		if (i == 0)
  3135 			manager->SetBookmark();
  3136 		testEd->Print(*log);
  3137 		bookMarkLog0 = log->GetStore();
  3138 		ed->InsertTextL(0, _L("Hallo"), 0, 0, 0);	// hallo
  3139 		if (i == 1)
  3140 			manager->SetBookmark();
  3141 		testEd->Print(*log);
  3142 		bookMarkLog1 = log->GetStore();
  3143 		ed->DeleteTextL(2, 1);	// halo
  3144 		if (i == 2)
  3145 			manager->SetBookmark();
  3146 		testEd->Print(*log);
  3147 		bookMarkLog2 = log->GetStore();
  3148 		manager->BeginBatchLC();
  3149 		ed->DeleteTextL(3, 1);	// hal
  3150 		ed->InsertTextL(3, _L("t, who goes there?"), 0, 0, 0);	// halt, who goes there?
  3151 		if (i == 3)
  3152 			manager->SetBookmark();		// should not get set
  3153 		ed->DeleteTextL(9, 5);		// halt, who there?
  3154 		CleanupStack::PopAndDestroy();
  3155 		if (i == 4)
  3156 			manager->SetBookmark();
  3157 		testEd->Print(*log);
  3158 		bookMarkLog3 = log->GetStore();
  3159 		ed->InsertTextL(0, _L("Oi"), 0, 0, 0);
  3160 		if (i == 5)
  3161 			manager->SetBookmark();
  3162 		testEd->Print(*log);
  3163 		bookMarkLog4 = log->GetStore();
  3164 		ed->InsertTextL(2, _L("! "), 0, 0, 0);
  3165 		testEd->Print(*log);
  3166 		bookMarkLog5 = log->GetStore();
  3167 		if (i == 6)
  3168 			manager->SetBookmark();
  3169 
  3170 		ed->UndoL();
  3171 		// coalescence should have happenned unless there is a bookmark
  3172 		// in the way.
  3173 		if (i == 5)
  3174 			{
  3175             TESTPOINT(manager->IsAtBookmark());
  3176 			check->SetCheckString(*bookMarkLog4);
  3177 			testEd->Print(*check);
  3178 			CheckEditorLog(*check);
  3179 			ed->UndoL();
  3180 			}
  3181 		if (i == 4)
  3182 		    TESTPOINT(manager->IsAtBookmark());
  3183 		else
  3184 		    TESTPOINT(!manager->IsAtBookmark());
  3185 		check->SetCheckString(*bookMarkLog3);
  3186 		testEd->Print(*check);
  3187 		CheckEditorLog(*check);
  3188 		ed->UndoL();
  3189 		if (i == 2)
  3190 		    TESTPOINT(manager->IsAtBookmark());
  3191 		else
  3192 		    TESTPOINT(!manager->IsAtBookmark());
  3193 		check->SetCheckString(*bookMarkLog2);
  3194 		testEd->Print(*check);
  3195 		CheckEditorLog(*check);
  3196 		ed->UndoL();
  3197 		if (i == 1)
  3198 		    TESTPOINT(manager->IsAtBookmark());
  3199 		else
  3200 		    TESTPOINT(!manager->IsAtBookmark());
  3201 		check->SetCheckString(*bookMarkLog1);
  3202 		testEd->Print(*check);
  3203 		CheckEditorLog(*check);
  3204 		ed->UndoL();
  3205 		if (i == 0)
  3206 		    TESTPOINT(manager->IsAtBookmark());
  3207 		else
  3208 		    TESTPOINT(!manager->IsAtBookmark());
  3209 		check->SetCheckString(*bookMarkLog0);
  3210 		testEd->Print(*check);
  3211 		CheckEditorLog(*check);
  3212 		TESTPOINT(!ed->CanUndo());
  3213 		ed->RedoL();
  3214 		if (i == 1)
  3215 		    TESTPOINT(manager->IsAtBookmark());
  3216 		else
  3217 		    TESTPOINT(!manager->IsAtBookmark());
  3218 		check->SetCheckString(*bookMarkLog1);
  3219 		testEd->Print(*check);
  3220 		CheckEditorLog(*check);
  3221 		ed->RedoL();
  3222 		if (i == 2)
  3223 		    TESTPOINT(manager->IsAtBookmark());
  3224 		else
  3225 		    TESTPOINT(!manager->IsAtBookmark());
  3226 		check->SetCheckString(*bookMarkLog2);
  3227 		testEd->Print(*check);
  3228 		CheckEditorLog(*check);
  3229 		ed->RedoL();
  3230 		if (i == 4)
  3231 		    TESTPOINT(manager->IsAtBookmark());
  3232 		else
  3233 		    TESTPOINT(!manager->IsAtBookmark());
  3234 		check->SetCheckString(*bookMarkLog3);
  3235 		testEd->Print(*check);
  3236 		CheckEditorLog(*check);
  3237 		ed->RedoL();
  3238 		if (i == 5)
  3239 			{
  3240             TESTPOINT(manager->IsAtBookmark());
  3241 			check->SetCheckString(*bookMarkLog4);
  3242 			testEd->Print(*check);
  3243 			CheckEditorLog(*check);
  3244 			ed->RedoL();
  3245 			}
  3246 		TESTPOINT(!ed->CanRedo());
  3247 		if (i == 6)
  3248 		    TESTPOINT(manager->IsAtBookmark());
  3249 		else
  3250 		    TESTPOINT(!manager->IsAtBookmark());
  3251 
  3252 		delete bookMarkLog0;
  3253 		delete bookMarkLog1;
  3254 		delete bookMarkLog2;
  3255 		delete bookMarkLog3;
  3256 		delete bookMarkLog4;
  3257 		delete bookMarkLog5;
  3258 		}
  3259 
  3260 	delete ed;
  3261 	delete testEd;
  3262 	delete log;
  3263 	delete check;
  3264 	}
  3265 
  3266 void TestEditorUndoL()
  3267 	{
  3268 	__UHEAP_MARK;
  3269 
  3270 	TestEditorUndo t;
  3271 	t.Test1L();
  3272 	t.Test2L();
  3273 	t.Test3L();
  3274 	t.Test4L();
  3275 	t.Test5L();
  3276 	t.Test6L();
  3277 	t.Test7L();
  3278 	t.Test8L();
  3279 
  3280 	__UHEAP_MARKENDC(0);
  3281 	}
  3282 // integration of command manager with multiple editors
  3283 void TestMultipleEditorsL()
  3284 	{
  3285 	__UHEAP_MARK;
  3286 
  3287 	CCheckingLogger* check = new(ELeave) CCheckingLogger;
  3288 	CStoringLogger* log = new(ELeave) CStoringLogger;
  3289 
  3290 	CTestEditor* testEd0 = CTestEditor::NewL();
  3291 	CTestEditor* testEd1 = CTestEditor::NewL();
  3292 	CTestEditor* testEd2 = CTestEditor::NewL();
  3293 	CTestEditor* testEd3 = CTestEditor::NewL();
  3294 	CCommandManager* manager = CCommandManager::NewL();
  3295 
  3296 	CEditorPlainTextWithUndo* ed0 =
  3297 		CEditorPlainTextWithUndo::NewL(*testEd0, manager);
  3298 	CEditorWithUndo* ed1 = CEditorWithUndo::NewL(*testEd1, manager);
  3299 	CEditorPlainTextWithUndo* ed2 =
  3300 		CEditorPlainTextWithUndo::NewL(*testEd2, manager);
  3301 	CEditorWithUndo* ed3 = CEditorWithUndo::NewL(*testEd3, manager);
  3302 	manager->Release();
  3303 
  3304 	// Testing the API's of CEditorPlainTextWithUndo
  3305 	TTmCharFormatMask charBIMask;
  3306 	charBIMask.iFlags = TTmCharFormatMask::EItalic | TTmCharFormatMask::EBold;
  3307 	TOpenFontFaceAttribBase attrib;
  3308 	TTmCharFormat charB;
  3309 	attrib.SetBold(ETrue);
  3310 	charB.iFontSpec.SetAttrib(attrib);
  3311 	TTmCharFormatLayer charLayer;
  3312 	charLayer.iFormat = charB;
  3313 	charLayer.iMask = charBIMask;
  3314 	TTmParFormatMask parTMask;
  3315 	parTMask.iFlags = TTmParFormatMask::EKeepTogether;
  3316 	RTmParFormat parT;
  3317 	parT.iFlags = RTmParFormat::EKeepTogether;
  3318 	RTmParFormatLayer parLayer;
  3319 	parLayer.iMask = parTMask;
  3320 
  3321 	//Setting the base, character and paragraph format and then inserting the text
  3322 	ed0->SetBaseFormatL(charB,parT);
  3323 	ed0->SetCharFormatL(0, 1, charLayer);
  3324 	ed0->SetParFormatL(0, 1, parLayer);
  3325 
  3326 	// The main thing to check is that no commands coalesce that have
  3327 	// different targets which would if their targets matched. The
  3328 	// commands that can coalesce are Delete Text, Delete Plain Text,
  3329 	// Insert Text, Insert Plain Text, Delete Character Format, Delete
  3330 	// Paragraph Format.
  3331 	ed0->InsertTextL(0, _L("ab"), 0, 0, 0);
  3332 	testEd0->Print(*log);
  3333 	HBufC* log00 = log->GetStore();
  3334 	ed2->InsertTextL(0, _L("cd"), 0, 0, 0);
  3335 	testEd2->Print(*log);
  3336 	HBufC* log20 = log->GetStore();
  3337 	ed1->InsertTextL(0, _L("ef"), 0, 0, 0);
  3338 	testEd1->Print(*log);
  3339 	HBufC* log10 = log->GetStore();
  3340 	ed3->InsertTextL(0, _L("gh"), 0, 0, 0);
  3341 	testEd3->Print(*log);
  3342 	HBufC* log30 = log->GetStore();
  3343 
  3344 	manager->UndoL();
  3345 	check->SetCheckString(*log10);
  3346 	testEd1->Print(*check);
  3347 	CheckEditorLog(*check);
  3348 
  3349 	manager->UndoL();
  3350 	check->SetCheckString(*log20);
  3351 	testEd2->Print(*check);
  3352 	CheckEditorLog(*check);
  3353 
  3354 	manager->UndoL();
  3355 	check->SetCheckString(*log00);
  3356 	testEd0->Print(*check);
  3357 	CheckEditorLog(*check);
  3358 
  3359 	manager->UndoL();
  3360 	TestCannotUndo(*manager);
  3361 
  3362 	manager->RedoL();
  3363 	check->SetCheckString(*log00);
  3364 	testEd0->Print(*check);
  3365 	CheckEditorLog(*check);
  3366 
  3367 	manager->RedoL();
  3368 	check->SetCheckString(*log20);
  3369 	testEd2->Print(*check);
  3370 	CheckEditorLog(*check);
  3371 
  3372 	manager->RedoL();
  3373 	check->SetCheckString(*log10);
  3374 	testEd1->Print(*check);
  3375 	CheckEditorLog(*check);
  3376 
  3377 	manager->RedoL();
  3378 	check->SetCheckString(*log30);
  3379 	testEd3->Print(*check);
  3380 	CheckEditorLog(*check);
  3381 	TestCannotRedo(*manager);
  3382 
  3383 	ed0->DeleteTextL(1, 1);
  3384 	testEd0->Print(*log);
  3385 	HBufC* log01 = log->GetStore();
  3386 	ed2->DeleteTextL(0, 1);
  3387 	testEd2->Print(*log);
  3388 	HBufC* log21 = log->GetStore();
  3389 	ed3->DeleteTextL(0, 1);
  3390 	testEd3->Print(*log);
  3391 	HBufC* log31 = log->GetStore();
  3392 	ed1->DeleteTextL(0, 1);
  3393 	testEd1->Print(*log);
  3394 	HBufC* log11 = log->GetStore();
  3395 
  3396 	manager->UndoL();
  3397 	check->SetCheckString(*log31);
  3398 	testEd3->Print(*check);
  3399 	CheckEditorLog(*check);
  3400 
  3401 	manager->UndoL();
  3402 	check->SetCheckString(*log21);
  3403 	testEd2->Print(*check);
  3404 	CheckEditorLog(*check);
  3405 
  3406 	manager->UndoL();
  3407 	check->SetCheckString(*log01);
  3408 	testEd0->Print(*check);
  3409 	CheckEditorLog(*check);
  3410 
  3411 	manager->UndoL();
  3412 	check->SetCheckString(*log30);
  3413 	testEd3->Print(*check);
  3414 	CheckEditorLog(*check);
  3415 
  3416 	manager->RedoL();
  3417 	check->SetCheckString(*log01);
  3418 	testEd0->Print(*check);
  3419 	CheckEditorLog(*check);
  3420 
  3421 	manager->RedoL();
  3422 	check->SetCheckString(*log21);
  3423 	testEd2->Print(*check);
  3424 	CheckEditorLog(*check);
  3425 
  3426 	manager->RedoL();
  3427 	check->SetCheckString(*log31);
  3428 	testEd3->Print(*check);
  3429 	CheckEditorLog(*check);
  3430 
  3431 	manager->RedoL();
  3432 	check->SetCheckString(*log11);
  3433 	testEd1->Print(*check);
  3434 	CheckEditorLog(*check);
  3435 	TestCannotRedo(*manager);
  3436 
  3437 	parLayer.iFormat.CopyL(parT);
  3438 
  3439 	//Getting the base format to check if it is set accordingly
  3440 	TTmCharFormat charB1;
  3441 	RTmParFormat parT1;
  3442 	ed0->GetBaseFormatL(charB1,parT1);
  3443 	TESTPOINT(charB1==charB);
  3444 	TESTPOINT(parT1==parT);
  3445 
  3446 	//Getting the character format
  3447 	TTmCharFormatLayer charLayer1;
  3448 	MUnifiedEditor::TFormatLevel level=MUnifiedEditor::EEffective;
  3449 	TInt runLen=10;
  3450 	ed0->GetCharFormat(0,level,charLayer1,runLen);
  3451 
  3452 	//Getting the paragraph format
  3453 	RTmParFormatLayer parLayer1;
  3454 	ed0->GetParFormatL(0,level,parLayer1,runLen);
  3455 
  3456 	//Getting the text
  3457 	TPtrC text;
  3458 	ed0->GetText(0,text);
  3459 	TESTPOINT(text==_L("a"));
  3460 
  3461 	//Deleting the formating
  3462 	ed0->DeleteCharFormatL(0,1);
  3463 	ed0->DeleteParFormatL(0,1);
  3464 
  3465 	// To test CEditorCommandSetBaseFormat class
  3466 	// SetBaseFormatL calls CEditorCommandSetBaseFormatProto::CreateInverseL() which in turn calls CEditorCommandSetBaseFormat::NewL().
  3467 	ed1->SetBaseFormatL(charB,parT);
  3468 	ed1->SetCharFormatL(0, 1, charLayer);
  3469 
  3470 	testEd1->Print(*log);
  3471 	HBufC* log12 = log->GetStore();
  3472 	ed3->SetCharFormatL(0, 1 ,charLayer);
  3473 	testEd3->Print(*log);
  3474 	HBufC* log32 = log->GetStore();
  3475 	ed3->SetParFormatL(0, 1, parLayer);
  3476 	testEd3->Print(*log);
  3477 	HBufC* log33 = log->GetStore();
  3478 	ed1->SetParFormatL(0, 1, parLayer);
  3479 	testEd1->Print(*log);
  3480 	HBufC* log13 = log->GetStore();
  3481 
  3482 	manager->UndoL();
  3483 	check->SetCheckString(*log33);
  3484 	testEd3->Print(*check);
  3485 	CheckEditorLog(*check);
  3486 
  3487 	manager->UndoL();
  3488 	check->SetCheckString(*log32);
  3489 	testEd3->Print(*check);
  3490 	CheckEditorLog(*check);
  3491 
  3492 	manager->UndoL();
  3493 	check->SetCheckString(*log12);
  3494 	testEd1->Print(*check);
  3495 	CheckEditorLog(*check);
  3496 
  3497 	manager->RedoL();
  3498 	check->SetCheckString(*log32);
  3499 	testEd3->Print(*check);
  3500 	CheckEditorLog(*check);
  3501 
  3502 	manager->RedoL();
  3503 	check->SetCheckString(*log33);
  3504 	testEd3->Print(*check);
  3505 	CheckEditorLog(*check);
  3506 
  3507 	manager->RedoL();
  3508 	check->SetCheckString(*log13);
  3509 	testEd1->Print(*check);
  3510 	CheckEditorLog(*check);
  3511 
  3512 	parLayer.Close();
  3513 	parT.Close();
  3514 	delete log00;
  3515 	delete log10;
  3516 	delete log20;
  3517 	delete log30;
  3518 	delete log01;
  3519 	delete log11;
  3520 	delete log21;
  3521 	delete log31;
  3522 	delete log12;
  3523 	delete log13;
  3524 	delete log32;
  3525 	delete log33;
  3526 	manager->ResetUndo();
  3527 	delete ed0;
  3528 	delete ed1;
  3529 	delete ed2;
  3530 	delete ed3;
  3531 	delete testEd0;
  3532 	delete testEd1;
  3533 	delete testEd2;
  3534 	delete testEd3;
  3535 	delete log;
  3536 	delete check;
  3537 
  3538 	__UHEAP_MARKENDC(0);
  3539 	}
  3540 
  3541 //
  3542 //
  3543 //  Main
  3544 //
  3545 //
  3546 
  3547 TVerdict CTUndoStep::doTestStepL()
  3548 	{
  3549     SetTestStepResult(EPass);
  3550     TestStep = this;
  3551     TESTPRINT(_L("TUndo - Undo system"));
  3552     
  3553     __UHEAP_MARK;
  3554     TESTPRINT(_L("@SYMTestCaseID:SYSLIB-FORM-LEGACY-UNDO-0001 Undo System Tests: "));
  3555 	
  3556 	// test of general undo system components
  3557 	TestCCommandStackL();
  3558 	TestCBatchCommandL();
  3559 	TestCCommandHistoryL();
  3560 	TestCCommandManagerL();
  3561 
  3562 	// test of editor undo components
  3563 	TestEditorUndoL();
  3564 
  3565 	// test that command manager and multiple editors integrate correctly
  3566 	TestMultipleEditorsL();
  3567 
  3568 	__UHEAP_MARKENDC(0);
  3569 	
  3570 	return TestStepResult();
  3571 	}
  3572