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