os/textandloc/textrendering/textformatting/undo/EditorCommands.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 *
    16 */
    17 
    18 
    19 #include "EditorCommands.h"
    20 #include "AssertFileAndLine.h"
    21 #include <txtetext.h>
    22 #include <s32ucmp.h>
    23 
    24 using namespace UndoSystem;
    25 
    26 inline TBool IsSurrogate(TText a) { return 0xD800 == (a & 0xF800); }
    27 inline TBool IsHighSurrogate(TText a) { return 0xD800 == (a & 0xFC00); }
    28 inline TBool IsLowSurrogate(TText a) { return 0xDC00 == (a & 0xFC00); }
    29 inline TChar JoinSurrogates(TText aHigh, TText aLow)
    30 	{
    31 	return ((aHigh - 0xd7f7) << 10) + aLow;
    32 	}
    33 
    34 // These roughly mirror the prototype commands, but rather than
    35 // referencing externally-owned (and therefore temporary) objects,
    36 // they own objects. Typically these are unique instances.
    37 
    38 /**
    39  * Command for setting the base character and paragraph formats.
    40  *
    41  * @internalComponent
    42  * @since App-frameworks6.1
    43  */
    44 NONSHARABLE_CLASS(CEditorCommandSetBaseFormat) : public CEditorCommand
    45 	{
    46 	MUnifiedEditor&						iTarget;
    47 	RUniqueInstance<TTmCharFormat>	iChar;
    48 	RUniqueInstance<RTmParFormat>	iPar;
    49 
    50 	const TRepositories& iRepositories;
    51 
    52 	CEditorCommandSetBaseFormat(const TRepositories& aReps, MUnifiedEditor& aTarget);
    53 public:
    54 	~CEditorCommandSetBaseFormat();
    55 	static CEditorCommandSetBaseFormat* NewL(const TRepositories& aReps,
    56 		const TTmCharFormat& aCharFormat, const RTmParFormat& aParFormat,
    57 		MUnifiedEditor& aTarget);
    58 	static CEditorCommandSetBaseFormat* NewL(const TRepositories& aReps,
    59 		MUnifiedEditor& aTarget);
    60 
    61 	UndoSystem::CCommand* CreateInverseL() const;
    62 	TInt ExecuteL() const;
    63 	};
    64 
    65 /**
    66  * Command for renaming a style.
    67  *
    68  * @internalComponent
    69  * @since App-frameworks6.1
    70  */
    71 NONSHARABLE_CLASS(CEditorCommandRenameStyle) : public CEditorCommand
    72 	{
    73 	MUnifiedEditor&				iTarget;
    74 	RUniqueInstance<TDes>	iOldName;
    75 	RUniqueInstance<TDes>	iNewName;
    76 
    77 	const TRepositories& iRepositories;
    78 
    79 	CEditorCommandRenameStyle(const TRepositories& aReps, MUnifiedEditor& aTarget)
    80 		: iTarget(aTarget), iOldName(*aReps.iDes), iNewName(*aReps.iDes),
    81 		iRepositories(aReps) {}
    82 public:
    83 	~CEditorCommandRenameStyle();
    84 	static CEditorCommandRenameStyle* NewL(const TRepositories& aReps,
    85 		const TDesC& aOldName, const TDesC& aNewName, MUnifiedEditor& aTarget);
    86 
    87 	CCommand* CreateInverseL() const;
    88 	TInt ExecuteL() const;
    89 	};
    90 
    91 /**
    92  * Command for inserting a picture into the text.
    93  *
    94  * @internalComponent
    95  * @since App-frameworks6.1
    96  */
    97 NONSHARABLE_CLASS(CEditorCommandInsertPicture) : public CEditorCommand
    98 	{
    99 	MUnifiedEditor&				iTarget;
   100 	TInt					iPos;
   101 	mutable TPictureHeader	iPicture;
   102 	MPictureOwner*			iPictureOwner;
   103 	const TRepositories&	iRepositories;
   104 
   105 	CEditorCommandInsertPicture(const TRepositories& aReps, MUnifiedEditor& aTarget)
   106 		: iTarget(aTarget), iRepositories(aReps) {}
   107 public:
   108 	~CEditorCommandInsertPicture();
   109 	static CEditorCommandInsertPicture* NewL(const TRepositories& aReps,
   110 		TInt aPos, MPictureOwner& aPictureOwner, MUnifiedEditor& aTarget);
   111 	void TakePictureOwnership(TPictureHeader&);
   112 	void ForgetOwner(MPictureOwner*);
   113 
   114 	CCommand* CreateInverseL() const;
   115 	TInt ExecuteL() const;
   116 	};
   117 
   118 /**
   119  * Command for creating a new style.
   120  *
   121  * @internalComponent
   122  * @since App-frameworks6.1
   123  */
   124 NONSHARABLE_CLASS(CEditorCommandCreateStyle) : public CEditorCommand
   125 	{
   126 	MUnifiedEditor&					iTarget;
   127 	RUniqueInstance<TDes>			iName;
   128 	RUniqueInstance<TDes>			iNext;
   129 	RUniqueInstance<TTmCharFormat>	iChar;
   130 	TTmCharFormatMask				iCharMask;
   131 	RUniqueInstance<RTmParFormat>	iPar;
   132 	TTmParFormatMask				iParMask;
   133 	TInt							iLevel;
   134 
   135 	const TRepositories& iRepositories;
   136 
   137 	CEditorCommandCreateStyle(const TRepositories& aReps, MUnifiedEditor& aTarget)
   138 		: iTarget(aTarget), iName(*aReps.iDes), iNext(*aReps.iDes),
   139 		iChar(*aReps.iChar),
   140 		iPar(*aReps.iPar), iRepositories(aReps) {}
   141 public:
   142 	~CEditorCommandCreateStyle();
   143 	static CEditorCommandCreateStyle* NewL(const TRepositories& aReps,
   144 		const TDesC& aName, const TDesC& aNext,
   145 		TTmCharFormat& aChar, TTmCharFormatMask aCharMask,
   146 		RTmParFormat& aPar, TTmParFormatMask aParMask,
   147 		TInt aLevel, MUnifiedEditor& aTarget);
   148 	static CEditorCommandCreateStyle* NewL(const TRepositories& aReps,
   149 		const TDesC& aName, MUnifiedEditor& aTarget);
   150 	static CCommand* NewBatchL(const TRepositories& aReps,
   151 		const TDesC& aName, MUnifiedEditor& aTarget);
   152 
   153 	CCommand* CreateInverseL() const;
   154 	TInt ExecuteL() const;
   155 	};
   156 
   157 /**
   158  * Command for deleting a style, removing it from anywhere that it is applied.
   159  *
   160  * @internalComponent
   161  * @since App-frameworks6.1
   162  */
   163 NONSHARABLE_CLASS(CEditorCommandDeleteStyle) : public CEditorCommand
   164 	{
   165 	MUnifiedEditor&						iTarget;
   166 	RUniqueInstance<TDes>				iName;
   167 	const TRepositories& iRepositories;
   168 
   169 	CEditorCommandDeleteStyle(const TRepositories& aReps, MUnifiedEditor& aTarget)
   170 		: iTarget(aTarget), iName(*aReps.iDes), iRepositories(aReps) {}
   171 public:
   172 	~CEditorCommandDeleteStyle();
   173 	static CEditorCommandDeleteStyle* NewL(const TRepositories& aReps,
   174 		const TDesC& aName, MUnifiedEditor& aTarget);
   175 
   176 	CCommand* CreateInverseL() const;
   177 	TInt ExecuteL() const;
   178 	};
   179 
   180 /**
   181  * Command for altering the attributes of a style.
   182  *
   183  * @internalComponent
   184  * @since App-frameworks6.1
   185  */
   186 NONSHARABLE_CLASS(CEditorCommandAlterStyle) : public CEditorCommand
   187 	{
   188 	MUnifiedEditor&					iTarget;
   189 	RUniqueInstance<TDes>			iName;
   190 	RUniqueInstance<TDes>			iNext;
   191 	RUniqueInstance<TTmCharFormat>	iChar;
   192 	TTmCharFormatMask				iCharMask;
   193 	RUniqueInstance<RTmParFormat>	iPar;
   194 	TTmParFormatMask				iParMask;
   195 	TInt							iLevel;
   196 
   197 	const TRepositories& iRepositories;
   198 
   199 	CEditorCommandAlterStyle(const TRepositories& aReps, MUnifiedEditor& aTarget)
   200 		: iTarget(aTarget), iName(*aReps.iDes), iNext(*aReps.iDes),
   201 		iChar(*aReps.iChar), iPar(*aReps.iPar), iRepositories(aReps) {}
   202 public:
   203 	~CEditorCommandAlterStyle();
   204 	static CEditorCommandAlterStyle* NewL(const TRepositories& aReps,
   205 		const TDesC& aName, const TDesC& aNext,
   206 		TTmCharFormat& aChar, TTmCharFormatMask& aCharMask,
   207 		RTmParFormat& aPar, TTmParFormatMask& aParMask,
   208 		TInt aLevel, MUnifiedEditor& aTarget);
   209 	static CEditorCommandAlterStyle* NewL(const TRepositories& aReps,
   210 		const TDesC& aName, MUnifiedEditor& aTarget);
   211 
   212 	CCommand* CreateInverseL() const;
   213 	TInt ExecuteL() const;
   214 	};
   215 
   216 /**
   217  * Command for applying an existing style to text.
   218  *
   219  * @internalComponent
   220  * @since App-frameworks6.1
   221  */
   222 NONSHARABLE_CLASS(CEditorCommandSetStyle) : public CEditorCommand
   223 	{
   224 	MUnifiedEditor&			iTarget;
   225 	RUniqueInstance<TDes>	iName;
   226 	TInt					iPos;
   227 	TInt					iRunLength;
   228 
   229 	const TRepositories& iRepositories;
   230 
   231 	CEditorCommandSetStyle(const TRepositories& aReps, MUnifiedEditor& aTarget)
   232 		: iTarget(aTarget), iName(*aReps.iDes), iRepositories(aReps) {}
   233 public:
   234 	~CEditorCommandSetStyle();
   235 	static CEditorCommandSetStyle* NewL(const TRepositories& aReps,
   236 		const TDesC& aName, TInt aPos, TInt aRunLength,
   237 		MUnifiedEditor& aTarget);
   238 	static CCommand* NewL(const TRepositories& aReps,
   239 		TInt aPos, TInt aRunLength,
   240 		MUnifiedEditor& aTarget);
   241 
   242 	CCommand* CreateInverseL() const;
   243 	TInt ExecuteL() const;
   244 	};
   245 
   246 /**
   247  * Command for deleting text without pictures in it.
   248  *
   249  * @internalComponent
   250  * @since App-frameworks6.1
   251  */
   252 NONSHARABLE_CLASS(CEditorCommandDeleteText) : public CEditorCommand
   253 	{
   254 	TEditorDeletePlainTextImpl iImpl;
   255 	const TRepositories& iRepositories;		// only used in creating the inverse
   256 
   257 	CEditorCommandDeleteText*
   258 		CastToCEditorCommandDeleteText() { return this; }
   259 
   260 	CEditorCommandDeleteText(const TRepositories& aReps, MUnifiedEditor& aTarget,
   261 		TInt aPos, TInt aLength)
   262 		: iImpl(aTarget, aPos, aLength), iRepositories(aReps) {}
   263 public:
   264 	~CEditorCommandDeleteText();
   265 	static CEditorCommandDeleteText* NewL(const TRepositories& aReps,
   266 		TInt aPos, TInt aLength, MUnifiedEditor& aTarget);
   267 
   268 	CCommand* CreateInverseL() const;
   269 	TInt ExecuteL() const;
   270 
   271 	// This command can be coalesced with others of the same type
   272 	TBool CanAdd(TInt aPos, TInt aLength, MUnifiedEditor& aTarget) const;
   273 	void Add(TInt aLength);
   274 	};
   275 
   276 /**
   277  * Command for inserting text in a specified style and format.
   278  *
   279  * @internalComponent
   280  * @since App-frameworks6.1
   281  */
   282 NONSHARABLE_CLASS(CEditorCommandInsertTextAndFormat) : public CEditorCommand
   283 	{
   284 	TEditorInsertPlainTextImpl		iImpl;
   285 	// layer
   286 	RUniqueInstance<TTmCharFormat>	iChar;
   287 	TTmCharFormatMask				iCharMask;
   288 	RUniqueInstance<RTmParFormat>	iPar;
   289 	TTmParFormatMask				iParMask;
   290 	RUniqueInstance<TDes>			iStyle;
   291 
   292 	const TRepositories& iRepositories;
   293 
   294 	CEditorCommandInsertTextAndFormat*
   295 		CastToCEditorCommandInsertTextAndFormat() { return this; }
   296 	CEditorCommandInsertTextAndFormat(const TRepositories& aReps,
   297 		MUnifiedEditor& aTarget, TInt aPos, TDesC& aText)
   298 		: iImpl(aTarget, aPos, aText), iChar(*aReps.iChar), iPar(*aReps.iPar),
   299 		iStyle(*aReps.iDes), iRepositories(aReps) {}
   300 public:
   301 	struct RTextAndFormatParameters
   302 		{
   303 		TInt				iPos;
   304 		TPtrC				iText;
   305 		TPtrC				iStyleName;
   306 		TTmCharFormatLayer	iChar;
   307 		RTmParFormatLayer	iPar;
   308 
   309 		void Close();
   310 		void SetL(TInt aPos, TInt aMaxLength, MUnifiedEditor& aTarget);
   311 		};
   312 	~CEditorCommandInsertTextAndFormat();
   313 	static CEditorCommandInsertTextAndFormat* NewL(const TRepositories& aReps,
   314 		RTextAndFormatParameters& aParams, MUnifiedEditor& aTarget);
   315 
   316 	/**
   317 	 * Gets as much of a run as possible.
   318 	 */
   319 	static CEditorCommandInsertTextAndFormat* NewL(const TRepositories& aReps,
   320 		TInt aPos, TInt& aRemaining, TInt aOriginalPos, MUnifiedEditor& aTarget);
   321 
   322 	/**
   323 	 * Gets as many runs as necessary and returns a batch if necessary.
   324 	 */
   325 	static CCommand* NewBatchL(const TRepositories& aReps,
   326 		TInt aPos, TInt aLength, MUnifiedEditor& aTarget);
   327 
   328 	CCommand* CreateInverseL() const;
   329 	TInt ExecuteL() const;
   330 
   331 	// This command can be coalesced with others of the same type
   332 	TBool CanAdd(const RTextAndFormatParameters&, MUnifiedEditor& aTarget) const;
   333 	void Add(TInt aPos, const TDesC& aText);
   334 	};
   335 
   336 /**
   337  * Command for deleting the specific character format over a run of text.
   338  *
   339  * @internalComponent
   340  * @since App-frameworks6.1
   341  */
   342 NONSHARABLE_CLASS(CEditorCommandDeleteCharFormat) : public CEditorCommand
   343 	{
   344 	MUnifiedEditor&	iTarget;
   345 	TInt		iPos;
   346 	TInt		iLength;
   347 
   348 	const TRepositories& iRepositories;
   349 
   350 	CEditorCommandDeleteCharFormat*
   351 		CastToCEditorCommandDeleteCharFormat() { return this; }
   352 
   353 	CEditorCommandDeleteCharFormat(const TRepositories& aReps, MUnifiedEditor& aTarget)
   354 		: iTarget(aTarget), iRepositories(aReps) {}
   355 public:
   356 	~CEditorCommandDeleteCharFormat();
   357 	static CEditorCommandDeleteCharFormat* NewL(const TRepositories& aReps,
   358 		TInt aPos, TInt aLength,
   359 		MUnifiedEditor& aTarget);
   360 
   361 	CCommand* CreateInverseL() const;
   362 	TInt ExecuteL() const;
   363 
   364 	// This command can be coalesced with others of the same type
   365 	TBool CanAdd(TInt aPos, TInt aLength, MUnifiedEditor& aTarget) const;
   366 	void Add(TInt aPos, TInt aLength);
   367 	};
   368 
   369 /**
   370  * Command for deleting the specific paragraph format over a run of text.
   371  *
   372  * @internalComponent
   373  * @since App-frameworks6.1
   374  */
   375 NONSHARABLE_CLASS(CEditorCommandDeleteParFormat) : public CEditorCommand
   376 	{
   377 	MUnifiedEditor&	iTarget;
   378 	TInt		iPos;
   379 	TInt		iLength;
   380 
   381 	const TRepositories& iRepositories;
   382 
   383 	CEditorCommandDeleteParFormat*
   384 		CastToCEditorCommandDeleteParFormat() { return this; }
   385 
   386 	CEditorCommandDeleteParFormat(const TRepositories& aReps, MUnifiedEditor& aTarget)
   387 		: iTarget(aTarget), iRepositories(aReps) {}
   388 public:
   389 	~CEditorCommandDeleteParFormat();
   390 	static CEditorCommandDeleteParFormat* NewL(const TRepositories& aReps,
   391 		TInt aPos, TInt aLength,
   392 		MUnifiedEditor& aTarget);
   393 
   394 	CCommand* CreateInverseL() const;
   395 	TInt ExecuteL() const;
   396 
   397 	// This command can be coalesced with others of the same type
   398 	TBool CanAdd(TInt aPos, TInt aLength, MUnifiedEditor& aTarget) const;
   399 	void Add(TInt aPos, TInt aLength);
   400 	};
   401 
   402 /**
   403  * Command for applying a character format to a run of text that has no
   404  * existing specific character format.
   405  *
   406  * @internalComponent
   407  * @since App-frameworks6.1
   408  */
   409 NONSHARABLE_CLASS(CEditorCommandSetCharFormat) : public CEditorCommand
   410 	{
   411 	MUnifiedEditor&						iTarget;
   412 	TInt							iPos;
   413 	TInt							iLength;
   414 	// layer
   415 	RUniqueInstance<TTmCharFormat>	iChar;
   416 	TTmCharFormatMask				iCharMask;
   417 
   418 	const TRepositories& iRepositories;
   419 
   420 	CEditorCommandSetCharFormat(const TRepositories& aReps, MUnifiedEditor& aTarget)
   421 		: iTarget(aTarget), iChar(*aReps.iChar), iRepositories(aReps) {}
   422 public:
   423 	~CEditorCommandSetCharFormat();
   424 	static CEditorCommandSetCharFormat* NewL(const TRepositories& aReps,
   425 		TInt aPos, TInt aLength,
   426 		const TTmCharFormat* aChar, TTmCharFormatMask aCharMask,
   427 		MUnifiedEditor& aTarget);
   428 
   429 	// get as much of a run as possible.
   430 	static CEditorCommandSetCharFormat* NewL(const TRepositories& aReps,
   431 		TInt aPos, TInt& aRemaining, MUnifiedEditor& aTarget);
   432 
   433 	// get as many runs as necessary and return a batch if necessary.
   434 	static CCommand* NewBatchL(const TRepositories& aReps,
   435 		TInt aPos, TInt aLength, MUnifiedEditor& aTarget);
   436 
   437 	TBool PrepareToAddInverseToLastL(CSingleCommand& aLastCommand) const;
   438 	void AddInverseToLast(CSingleCommand& aLastCommand) const;
   439 	CCommand* CreateInverseL() const;
   440 	TInt ExecuteL() const;
   441 	};
   442 
   443 /**
   444  * Command for applying a paragraph format to a run of text that has no
   445  * existing specific paragraph format.
   446  *
   447  * @internalComponent
   448  * @since App-frameworks6.1
   449  */
   450 NONSHARABLE_CLASS(CEditorCommandSetParFormat) : public CEditorCommand
   451 	{
   452 	MUnifiedEditor&					iTarget;
   453 	TInt							iPos;
   454 	TInt							iLength;
   455 	// layer
   456 	RUniqueInstance<RTmParFormat>	iPar;
   457 	TTmParFormatMask				iParMask;
   458 
   459 	const TRepositories& iRepositories;
   460 
   461 	CEditorCommandSetParFormat(const TRepositories& aReps, MUnifiedEditor& aTarget)
   462 		: iTarget(aTarget), iPar(*aReps.iPar), iRepositories(aReps) {}
   463 public:
   464 	~CEditorCommandSetParFormat();
   465 	static CEditorCommandSetParFormat* NewL(const TRepositories& aReps,
   466 		TInt aPos, TInt aLength,
   467 		const RTmParFormat* aFormat, TTmParFormatMask aMask,
   468 		MUnifiedEditor& aTarget);
   469 
   470 	// get as much of a run as possible.
   471 	static CEditorCommandSetParFormat* NewL(const TRepositories& aReps,
   472 		TInt aPos, TInt& aRemaining, MUnifiedEditor& aTarget);
   473 
   474 	// get as many runs as necessary and return a batch if necessary.
   475 	static CCommand* NewBatchL(const TRepositories& aReps,
   476 		TInt aPos, TInt aLength, MUnifiedEditor& aTarget);
   477 
   478 	TBool PrepareToAddInverseToLastL(CSingleCommand& aLastCommand) const;
   479 	void AddInverseToLast(CSingleCommand& aLastCommand) const;
   480 	CCommand* CreateInverseL() const;
   481 	TInt ExecuteL() const;
   482 	};
   483 
   484 /**
   485  * Command for deleting a picture from the text. The picture is assumed
   486  * to be without significant formatting.
   487  *
   488  * @internalComponent
   489  * @since App-frameworks6.1
   490  */
   491 NONSHARABLE_CLASS(CEditorCommandDeletePicture) : public CEditorCommand,
   492 	private MPictureOwner
   493 	{
   494 	MUnifiedEditor&							iTarget;
   495 	TInt									iPos;
   496 	const TRepositories&					iRepositories;
   497 	/**
   498 	 * Will own picture after us.
   499 	 */
   500 	mutable CEditorCommandInsertPicture*	iPictureOwnerDelegate;
   501 
   502 	void ForgetDelegate();
   503 	CEditorCommandDeletePicture(const TRepositories& aReps, MUnifiedEditor& aTarget)
   504 		: iTarget(aTarget), iRepositories(aReps) {}
   505 public:
   506 	~CEditorCommandDeletePicture();
   507 	static CEditorCommandDeletePicture* NewL(const TRepositories& aReps,
   508 		TInt aPos, MUnifiedEditor& aTarget);
   509 
   510 	UndoSystem::CCommand* CreateInverseL() const;
   511 	TInt ExecuteL() const;
   512 	};
   513 
   514 ///////////////////////////////////
   515 //								 //
   516 //	CEditorCommandSetBaseFormat  //
   517 //								 //
   518 ///////////////////////////////////
   519 
   520 CEditorCommandSetBaseFormat::CEditorCommandSetBaseFormat(
   521 	const TRepositories& aReps, MUnifiedEditor& aTarget)
   522 	: iTarget(aTarget), iChar(*aReps.iChar), iPar(*aReps.iPar),
   523 	iRepositories(aReps)
   524 	{
   525 	}
   526 
   527 CEditorCommandSetBaseFormat::~CEditorCommandSetBaseFormat()
   528 	{
   529 	iChar.Close();
   530 	iPar.Close();
   531 	}
   532 
   533 CEditorCommandSetBaseFormat* CEditorCommandSetBaseFormat::NewL(
   534 	const TRepositories& aReps,
   535 	const TTmCharFormat& aCharFormat, const RTmParFormat& aParFormat,
   536 	MUnifiedEditor& aTarget)
   537 	{
   538 	CEditorCommandSetBaseFormat* r
   539 		= new(ELeave) CEditorCommandSetBaseFormat(aReps, aTarget);
   540 	CleanupStack::PushL(r);
   541 	r->iChar.TakeCopyL(&aCharFormat);
   542 	r->iPar.TakeCopyL(&aParFormat);
   543 	CleanupStack::Pop();
   544 	return r;
   545 	}
   546 
   547 CEditorCommandSetBaseFormat* CEditorCommandSetBaseFormat::NewL(
   548 	const TRepositories& aReps, MUnifiedEditor& aTarget)
   549 	{
   550 	TTmCharFormat c;
   551 	RTmParFormat p;
   552 	CleanupClosePushL(p);
   553 	aTarget.GetBaseFormatL(c, p);
   554 	CEditorCommandSetBaseFormat* r = NewL(aReps, c, p, aTarget);
   555 	CleanupStack::PopAndDestroy();
   556 	return r;
   557 	}
   558 
   559 CCommand* CEditorCommandSetBaseFormat::CreateInverseL() const
   560 	{
   561 	return NewL(iRepositories, iTarget);
   562 	}
   563 
   564 TInt CEditorCommandSetBaseFormat::ExecuteL() const
   565 	{
   566 	iTarget.SetBaseFormatL(*iChar.Peek(), *iPar.Peek());
   567 	return KErrNone;
   568 	}
   569 
   570 /////////////////////////////////
   571 //							   //
   572 //	CEditorCommandRenameStyle  //
   573 //							   //
   574 /////////////////////////////////
   575 
   576 CEditorCommandRenameStyle::~CEditorCommandRenameStyle()
   577 	{
   578 	iOldName.Close();
   579 	iNewName.Close();
   580 	}
   581 
   582 CEditorCommandRenameStyle* CEditorCommandRenameStyle::NewL(
   583 	const TRepositories& aReps,
   584 	const TDesC& aOldName, const TDesC& aNewName, MUnifiedEditor& aTarget)
   585 	{
   586 	CEditorCommandRenameStyle* r =
   587 		new(ELeave) CEditorCommandRenameStyle(aReps, aTarget);
   588 	CleanupStack::PushL(r);
   589 	r->iOldName.TakeCopyL(&aOldName);
   590 	r->iNewName.TakeCopyL(&aNewName);
   591 	CleanupStack::Pop(r);
   592 	return r;
   593 	}
   594 
   595 CCommand* CEditorCommandRenameStyle::CreateInverseL() const
   596 	{
   597 	return NewL(iRepositories, *iNewName.Peek(), *iOldName.Peek(), iTarget);
   598 	}
   599 
   600 TInt CEditorCommandRenameStyle::ExecuteL() const
   601 	{
   602 	MUnifiedEditor::MStyleSupport* si = iTarget.StyleSupport();
   603 	ASSERT(si);
   604 	return si->RenameStyleL(*iOldName.Peek(), *iNewName.Peek());
   605 	}
   606 
   607 ///////////////////////////////////
   608 //								 //
   609 //	CEditorCommandInsertPicture  //
   610 //								 //
   611 ///////////////////////////////////
   612 
   613 CEditorCommandInsertPicture::~CEditorCommandInsertPicture()
   614 	{
   615 	if (iPictureOwner)
   616 		iPictureOwner->ForgetDelegate();
   617 	iPicture.DeletePicture();
   618 	}
   619 
   620 CEditorCommandInsertPicture* CEditorCommandInsertPicture::NewL(
   621 	const TRepositories& aReps,
   622 	TInt aPos, MPictureOwner& aPictureOwner, MUnifiedEditor& aTarget)
   623 	{
   624 	CEditorCommandInsertPicture* r = new(ELeave)
   625 		CEditorCommandInsertPicture(aReps, aTarget);
   626 	r->iPictureOwner = &aPictureOwner;
   627 	r->iPos = aPos;
   628 	return r;
   629 	}
   630 
   631 void CEditorCommandInsertPicture::TakePictureOwnership(TPictureHeader& aPic)
   632 	{
   633 	iPicture = aPic;
   634 	iPictureOwner = 0;
   635 	}
   636 
   637 void CEditorCommandInsertPicture::ForgetOwner(MPictureOwner*
   638 #ifdef _DEBUG
   639 	aOwner
   640 #endif
   641 	)
   642 	{
   643 	ASSERT(aOwner == iPictureOwner);
   644 	iPictureOwner = 0;
   645 	}
   646 
   647 CCommand* CEditorCommandInsertPicture::CreateInverseL() const
   648 	{
   649 	return CEditorCommandDeletePicture::NewL(iRepositories, iPos, iTarget);
   650 	}
   651 
   652 TInt CEditorCommandInsertPicture::ExecuteL() const
   653 	{
   654 	ASSERT(iPictureOwner == 0);
   655 	MUnifiedEditor::MPictureSupport* pi = iTarget.PictureSupport();
   656 	ASSERT(pi);
   657 	pi->InsertPictureL(iPos, iPicture);
   658 	iPicture.iPicture = 0;
   659 	iPicture.iPictureType = KNullUid;
   660 	return KErrNone;
   661 	}
   662 
   663 
   664 ///////////////////////////////////
   665 //								 //
   666 //	CEditorCommandDeletePicture  //
   667 //								 //
   668 ///////////////////////////////////
   669 
   670 CEditorCommandDeletePicture::~CEditorCommandDeletePicture()
   671 	{
   672 	if (iPictureOwnerDelegate)
   673 		iPictureOwnerDelegate->ForgetOwner(this);
   674 	}
   675 
   676 void CEditorCommandDeletePicture::ForgetDelegate()
   677 	{
   678 	iPictureOwnerDelegate = 0;
   679 	}
   680 
   681 CEditorCommandDeletePicture* CEditorCommandDeletePicture::NewL(
   682 	const TRepositories& aReps, TInt aPos, MUnifiedEditor& aTarget)
   683 	{
   684 	CEditorCommandDeletePicture* r =
   685 		new(ELeave) CEditorCommandDeletePicture(aReps, aTarget);
   686 	r->iPos = aPos;
   687 	return r;
   688 	}
   689 
   690 CCommand* CEditorCommandDeletePicture::CreateInverseL() const
   691 	{
   692 	CEditorCommandDeletePicture* nonConstThis =
   693 		const_cast<CEditorCommandDeletePicture*>(this);	//yuck
   694 	CEditorCommandInsertPicture* inv =
   695 		CEditorCommandInsertPicture::NewL(iRepositories, iPos,
   696 		*nonConstThis, iTarget);
   697 	CleanupStack::PushL(inv);
   698 
   699 	if (iPictureOwnerDelegate)
   700 		iPictureOwnerDelegate->ForgetOwner(nonConstThis);
   701 
   702 	iPictureOwnerDelegate = inv;
   703 	CleanupStack::Pop(inv);
   704 
   705 	return inv;
   706 	}
   707 
   708 TInt CEditorCommandDeletePicture::ExecuteL() const
   709 	{
   710 	MUnifiedEditor::MPictureSupport* pi = iTarget.PictureSupport();
   711 	ASSERT(pi);
   712 	TPictureHeader pic;
   713 	pi->Picture(iPos, pic);
   714 	pi->DropPictureL(iPos);
   715 	if (iPictureOwnerDelegate)
   716 		{
   717 		iPictureOwnerDelegate->TakePictureOwnership(pic);
   718 		iPictureOwnerDelegate = 0;
   719 		}
   720 	else
   721 		pic.DeletePicture();
   722 	return KErrNone;
   723 	}
   724 
   725 /////////////////////////////////
   726 //							   //
   727 //	CEditorCommandCreateStyle  //
   728 //							   //
   729 /////////////////////////////////
   730 
   731 CEditorCommandCreateStyle* CEditorCommandCreateStyle::NewL(const TRepositories& aReps,
   732  		const TDesC& aName, const TDesC& aNext,
   733 		TTmCharFormat& aChar, TTmCharFormatMask aCharMask,
   734 		RTmParFormat& aPar, TTmParFormatMask aParMask,
   735 		TInt aLevel, MUnifiedEditor& aTarget)
   736 	{
   737 	CEditorCommandCreateStyle* p = new(ELeave) CEditorCommandCreateStyle(aReps, aTarget);
   738 	CleanupStack::PushL(p);
   739 	p->iName.TakeCopyL(&aName);
   740 	p->iNext.TakeCopyL(&aNext);
   741 	p->iChar.TakeCopyL(&aChar);
   742 	p->iCharMask = aCharMask;
   743 	p->iPar.TakeCopyL(&aPar);
   744 	p->iParMask = aParMask;
   745 	p->iLevel = aLevel;
   746 	CleanupStack::Pop(p);
   747 	return p;
   748 	}
   749 CEditorCommandCreateStyle* CEditorCommandCreateStyle::NewL(const TRepositories& aReps,
   750 	const TDesC& aName, MUnifiedEditor& aTarget)
   751 	{
   752 	RTmStyle style;
   753 	MUnifiedEditor::MStyleSupport* si = aTarget.StyleSupport();
   754 	ASSERT(si);
   755 	si->GetStyleByNameL(aName, style);
   756 	CleanupClosePushL(style);
   757 	CEditorCommandCreateStyle* p = NewL(aReps, aName, style.iNextStyleName,
   758 		style.iCharFormat.iFormat, style.iCharFormat.iMask,
   759 		style.iParFormat.iFormat, style.iParFormat.iMask,
   760 		style.iOutlineLevel, aTarget);
   761 	CleanupStack::PopAndDestroy();
   762 	return p;
   763 	}
   764 
   765 CCommand* CEditorCommandCreateStyle::NewBatchL(const TRepositories& aReps,
   766 											   const TDesC& aName,
   767 											   MUnifiedEditor& aTarget)
   768 	{
   769 	CCommand* inverse = 0;
   770 	MUnifiedEditor::MStyleSupport* si = aTarget.StyleSupport();
   771 	ASSERT(si);
   772 
   773 	TInt remainingLength = aTarget.DocumentLength();
   774 	TInt currentPosition = 0;
   775 	// got to be careful.. GetStyleL() can return KMaxTInt as the run length!
   776 	// luckily, any nonnegative TInt - KMaxTInt gives a negative TInt
   777 	while (0 < remainingLength)
   778 		{
   779 		TInt runLength;
   780 		TPtrC name;
   781 		si->GetStyle(currentPosition, name, runLength);
   782 		if (name == aName)
   783 			{
   784 			CleanupStack::PushL(inverse);
   785 	// coverity[double_free]
   786 			inverse = CoalesceL(inverse,
   787 				CEditorCommandSetStyle::NewL(aReps, aName,
   788 					currentPosition, runLength, aTarget));
   789 			CleanupStack::Pop();
   790 			}
   791 		currentPosition += runLength;
   792 		remainingLength -= runLength;
   793 		}
   794 
   795 	CleanupStack::PushL(inverse);
   796 	// coverity[double_free]
   797 	inverse = CoalesceL(inverse,
   798 		CEditorCommandCreateStyle::NewL(aReps, aName, aTarget));
   799 	CleanupStack::Pop();
   800 	return inverse;
   801 	}
   802 
   803 CEditorCommandCreateStyle::~CEditorCommandCreateStyle()
   804 	{
   805 	iName.Close();
   806 	iNext.Close();
   807 	iChar.Close();
   808 	iPar.Close();
   809 	}
   810 
   811 CCommand* CEditorCommandCreateStyle::CreateInverseL() const
   812 	{
   813 	return CEditorCommandDeleteStyle::NewL(iRepositories, *iName.Peek(), iTarget);
   814 	}
   815 
   816 TInt CEditorCommandCreateStyle::ExecuteL() const
   817 	{
   818 	RTmStyle style;
   819 	CleanupClosePushL(style);
   820 	style.iName = *iName.Peek();
   821 	style.iNextStyleName = *iNext.Peek();
   822 	style.iCharFormat.iFormat = *iChar.Peek();
   823 	style.iCharFormat.iMask = iCharMask;
   824 	style.iParFormat.iFormat.CopyL( *iPar.Peek() );
   825 	style.iParFormat.iMask.iFlags = iParMask.iFlags;
   826 	style.iOutlineLevel = iLevel;
   827 	MUnifiedEditor::MStyleSupport* si = iTarget.StyleSupport();
   828 	ASSERT(si);
   829 	TInt err = si->CreateStyleL(style);
   830 	CleanupStack::PopAndDestroy();
   831 	return err;
   832 	}
   833 
   834 /////////////////////////////////
   835 //							   //
   836 //	CEditorCommandDeleteStyle  //
   837 //							   //
   838 /////////////////////////////////
   839 
   840 CEditorCommandDeleteStyle* CEditorCommandDeleteStyle::NewL(const TRepositories& aReps,
   841  		const TDesC& aName, MUnifiedEditor& aTarget)
   842 	{
   843 	CEditorCommandDeleteStyle* p = new(ELeave) CEditorCommandDeleteStyle(aReps, aTarget);
   844 	CleanupStack::PushL(p);
   845 	p->iName.TakeCopyL(&aName);
   846 	CleanupStack::Pop(p);
   847 	return p;
   848 	}
   849 
   850 CEditorCommandDeleteStyle::~CEditorCommandDeleteStyle()
   851 	{
   852 	iName.Close();
   853 	}
   854 
   855 CCommand* CEditorCommandDeleteStyle::CreateInverseL() const
   856 	{
   857 	return CEditorCommandCreateStyle::NewBatchL(iRepositories, *iName.Peek(), iTarget);
   858 	}
   859 
   860 TInt CEditorCommandDeleteStyle::ExecuteL() const
   861 	{
   862 	MUnifiedEditor::MStyleSupport* si = iTarget.StyleSupport();
   863 	ASSERT(si);
   864 	return si->DeleteStyleL(*iName.Peek());
   865 	}
   866 
   867 ////////////////////////////////
   868 //							  //
   869 //	CEditorCommandAlterStyle  //
   870 //							  //
   871 ////////////////////////////////
   872 
   873 CEditorCommandAlterStyle* CEditorCommandAlterStyle::NewL(const TRepositories& aReps,
   874  		const TDesC& aName, const TDesC& aNext,
   875 		TTmCharFormat& aChar, TTmCharFormatMask& aCharMask,
   876 		RTmParFormat& aPar, TTmParFormatMask& aParMask,
   877 		TInt aLevel, MUnifiedEditor& aTarget)
   878 	{
   879 	CEditorCommandAlterStyle* p = new(ELeave) CEditorCommandAlterStyle(aReps, aTarget);
   880 	CleanupStack::PushL(p);
   881 	p->iName.TakeCopyL(&aName);
   882 	p->iNext.TakeCopyL(&aNext);
   883 	p->iChar.TakeCopyL(&aChar);
   884 	p->iCharMask = aCharMask;
   885 	p->iPar.TakeCopyL(&aPar);
   886 	p->iParMask = aParMask;
   887 	p->iLevel = aLevel;
   888 	CleanupStack::Pop(p);
   889 	return p;
   890 	}
   891 
   892 CEditorCommandAlterStyle* CEditorCommandAlterStyle::NewL(const TRepositories& aReps,
   893 	const TDesC& aName, MUnifiedEditor& aTarget)
   894 	{
   895 	RTmStyle style;
   896 	CleanupClosePushL(style);
   897 	MUnifiedEditor::MStyleSupport* si = aTarget.StyleSupport();
   898 	ASSERT(si);
   899 	si->GetStyleByNameL(aName, style);
   900 	CEditorCommandAlterStyle* p = NewL(aReps, aName, style.iNextStyleName,
   901 		style.iCharFormat.iFormat, style.iCharFormat.iMask,
   902 		style.iParFormat.iFormat, style.iParFormat.iMask,
   903 		style.iOutlineLevel, aTarget);
   904 	CleanupStack::PopAndDestroy();
   905 	return p;
   906 	}
   907 
   908 CEditorCommandAlterStyle::~CEditorCommandAlterStyle()
   909 	{
   910 	iName.Close();
   911 	iNext.Close();
   912 	iChar.Close();
   913 	iPar.Close();
   914 	}
   915 
   916 CCommand* CEditorCommandAlterStyle::CreateInverseL() const
   917 	{
   918 	return NewL(iRepositories, *iName.Peek(), iTarget);
   919 	}
   920 
   921 TInt CEditorCommandAlterStyle::ExecuteL() const
   922 	{
   923 	RTmStyle style;
   924 	CleanupClosePushL(style);
   925 	MUnifiedEditor::MStyleSupport* si = iTarget.StyleSupport();
   926 	ASSERT(si);
   927 	si->GetStyleByNameL(*iName.Peek(), style);
   928 	style.iCharFormat.iFormat	= *iChar.Peek();
   929 	style.iCharFormat.iMask		= iCharMask;
   930 	style.iParFormat.iFormat.CopyL( *iPar.Peek() );
   931 	style.iParFormat.iMask		= iParMask;
   932 	style.iOutlineLevel			= iLevel;
   933 	style.iName					= *iName.Peek();
   934 	style.iNextStyleName		= *iNext.Peek();
   935 	TInt err = si->ChangeStyleL(style);
   936 	CleanupStack::PopAndDestroy();
   937 	return err;
   938 	}
   939 
   940 //////////////////////////////
   941 //							//
   942 //	CEditorCommandSetStyle  //
   943 //							//
   944 //////////////////////////////
   945 
   946 CEditorCommandSetStyle::~CEditorCommandSetStyle()
   947 	{
   948 	iName.Close();
   949 	}
   950 
   951 CEditorCommandSetStyle* CEditorCommandSetStyle::NewL(const TRepositories& aReps,
   952 	const TDesC& aName, TInt aPos, TInt aRunLength, MUnifiedEditor& aTarget)
   953 	{
   954 	CEditorCommandSetStyle* r = new (ELeave) CEditorCommandSetStyle(aReps, aTarget);
   955 	CleanupStack::PushL(r);
   956 	r->iName.TakeCopyL(&aName);
   957 	r->iPos = aPos;
   958 	r->iRunLength = aRunLength;
   959 	CleanupStack::Pop(r);
   960 	return r;
   961 	}
   962 
   963 CCommand* CEditorCommandSetStyle::NewL(
   964 	const TRepositories& aReps, TInt aPos, TInt aRunLength, MUnifiedEditor& aTarget)
   965 	{
   966 	CCommand* inverse = 0;
   967 	MUnifiedEditor::MStyleSupport* si = aTarget.StyleSupport();
   968 	ASSERT(si);
   969 	while (0 < aRunLength)
   970 		{
   971 		TPtrC name;
   972 		TInt runLength;
   973 		si->GetStyle(aPos, name, runLength);
   974 		if (aRunLength < runLength)
   975 			runLength = aRunLength;
   976 		CleanupStack::PushL(inverse);
   977 		// coverity[double_free]
   978 		inverse = CoalesceL(inverse, NewL(aReps, name, aPos, runLength, aTarget));
   979 		CleanupStack::Pop();
   980 		aPos += runLength;
   981 		aRunLength -= runLength;
   982 		}
   983 	return inverse;
   984 	}
   985 
   986 CCommand* CEditorCommandSetStyle::CreateInverseL() const
   987 	{
   988 	return NewL(iRepositories, iPos, iRunLength, iTarget);
   989 	}
   990 
   991 TInt CEditorCommandSetStyle::ExecuteL() const
   992 	{
   993 	MUnifiedEditor::MStyleSupport* si = iTarget.StyleSupport();
   994 	ASSERT(si);
   995 	return si->SetStyleL(iPos, iRunLength, *iName.Peek());
   996 	}
   997 
   998 ////////////////////////////////
   999 //							  //
  1000 //	CEditorCommandDeleteText  //
  1001 //							  //
  1002 ////////////////////////////////
  1003 
  1004 CEditorCommandDeleteText::~CEditorCommandDeleteText() {}
  1005 
  1006 CEditorCommandDeleteText* CEditorCommandDeleteText::NewL(const TRepositories& aReps,
  1007 	TInt aPos, TInt aLength, MUnifiedEditor& aTarget)
  1008 	{
  1009 	return new(ELeave) CEditorCommandDeleteText(aReps,
  1010 		aTarget, aPos, aLength);
  1011 	}
  1012 
  1013 CCommand* CEditorCommandDeleteText::CreateInverseL() const
  1014 	{
  1015 	return CEditorCommandInsertTextAndFormat::NewBatchL(
  1016 		iRepositories, iImpl.Pos(), iImpl.Length(), iImpl.Target());
  1017 	}
  1018 
  1019 TInt CEditorCommandDeleteText::ExecuteL() const
  1020 	{
  1021 	return iImpl.ExecuteL();
  1022 	}
  1023 
  1024 TBool CEditorCommandDeleteText::CanAdd(TInt aPos, TInt aLength, MUnifiedEditor& aTarget) const
  1025 	{
  1026 	return iImpl.CanAdd(aPos, aLength, aTarget);
  1027 	}
  1028 
  1029 void CEditorCommandDeleteText::Add(TInt aLength)
  1030 	{
  1031 	iImpl.Add(aLength);
  1032 	}
  1033 
  1034 /////////////////////////////////////////
  1035 //									   //
  1036 //	CEditorCommandInsertTextAndFormat  //
  1037 //									   //
  1038 /////////////////////////////////////////
  1039 
  1040 CEditorCommandInsertTextAndFormat::~CEditorCommandInsertTextAndFormat()
  1041 	{
  1042 	iChar.Close();
  1043 	iPar.Close();
  1044 	iStyle.Close();
  1045 	}
  1046 
  1047 CEditorCommandInsertTextAndFormat* CEditorCommandInsertTextAndFormat::NewL(
  1048 	const TRepositories& aReps,
  1049 	CEditorCommandInsertTextAndFormat::RTextAndFormatParameters& aParams,
  1050 	MUnifiedEditor& aTarget)
  1051 	{
  1052 	ASSERT(aParams.iText.Length() <= KMaxCharsInSingleCommand);
  1053 	CEditorCommandInsertTextAndFormat* r = new(ELeave)
  1054 		CEditorCommandInsertTextAndFormat(aReps, aTarget, aParams.iPos, aParams.iText);
  1055 	CleanupStack::PushL(r);
  1056 	r->iChar.TakeCopyL(&aParams.iChar.iFormat);
  1057 	r->iCharMask = aParams.iChar.iMask;
  1058 	r->iPar.TakeCopyL(&aParams.iPar.iFormat);
  1059 	r->iParMask.iFlags = aParams.iPar.iMask.iFlags;
  1060 	r->iStyle.TakeCopyL(&aParams.iStyleName);
  1061 	CleanupStack::Pop(r);
  1062 	return r;
  1063 	}
  1064 
  1065 void CEditorCommandInsertTextAndFormat::RTextAndFormatParameters::Close()
  1066 	{
  1067 	iPar.Close();
  1068 	}
  1069 
  1070 void CEditorCommandInsertTextAndFormat::RTextAndFormatParameters::SetL(
  1071 	TInt aPos, TInt aMaxLength, MUnifiedEditor& aTarget)
  1072 	{
  1073 	iPos = aPos;
  1074 	aTarget.GetText(aPos, iText);
  1075 
  1076 	TInt length = iText.Length();
  1077 
  1078 	TInt charLength;
  1079 	aTarget.GetCharFormat(aPos, MUnifiedEditor::ESpecific, iChar, charLength);
  1080 
  1081 	TInt parLength;
  1082 	aTarget.GetParFormatL(aPos, MUnifiedEditor::ESpecific, iPar, parLength);
  1083 
  1084 	TInt styleLength = length;
  1085 	MUnifiedEditor::MStyleSupport* si = aTarget.StyleSupport();
  1086 	if (si)
  1087 		si->GetStyle(aPos, iStyleName, styleLength);
  1088 	else
  1089 		iStyleName.Set(TPtrC());
  1090 
  1091 	if (charLength < length)
  1092 		length = charLength;
  1093 	if (parLength < length)
  1094 		length = parLength;
  1095 	if (styleLength < length)
  1096 		length = styleLength;
  1097 	if (aMaxLength < length)
  1098 		length = aMaxLength;
  1099 	if (KMaxCharsInSingleCommand < length)
  1100 		length = KMaxCharsInSingleCommand;
  1101 	iText.Set(iText.Ptr(), length);
  1102 	}
  1103 
  1104 CEditorCommandInsertTextAndFormat* CEditorCommandInsertTextAndFormat::NewL(
  1105 	const TRepositories& aReps, TInt aPos, TInt& aRemaining,
  1106 	TInt aOriginalPos, MUnifiedEditor& aTarget)
  1107 	{
  1108 	RTextAndFormatParameters params;
  1109 	CleanupClosePushL(params);
  1110 	params.SetL(aPos, aRemaining, aTarget);
  1111 
  1112 	params.iPos = aOriginalPos;
  1113 	CEditorCommandInsertTextAndFormat* p = NewL(aReps, params, aTarget);
  1114 	aRemaining -= params.iText.Length();
  1115 
  1116 	CleanupStack::PopAndDestroy();
  1117 
  1118 	return p;
  1119 	}
  1120 
  1121 CCommand* CEditorCommandInsertTextAndFormat::NewBatchL(const TRepositories& aReps,
  1122 	TInt aPos, TInt aLength, MUnifiedEditor& aTarget)
  1123 	{
  1124 	CCommand* command = 0;
  1125 	TInt oldLength = aLength + 1;
  1126 	TInt end = aPos + aLength;
  1127 	// while there is still some length to go and there is still some
  1128 	// text to be got
  1129 	while (0 < aLength && aLength < oldLength)
  1130 		{
  1131 		oldLength = aLength;
  1132 		CleanupStack::PushL(command);
  1133 		// coverity[double_free]
  1134 		command = CoalesceL(command,
  1135 			NewL(aReps, end - aLength, aLength, aPos, aTarget));
  1136 		CleanupStack::Pop();
  1137 		}
  1138 
  1139 	return command;
  1140 	}
  1141 
  1142 CCommand* CEditorCommandInsertTextAndFormat::CreateInverseL() const
  1143 	{
  1144 	return CEditorCommandDeleteText::NewL(iRepositories,
  1145 		iImpl.Pos(), iImpl.Text().Length(), iImpl.Target());
  1146 	}
  1147 
  1148 TInt CEditorCommandInsertTextAndFormat::ExecuteL() const
  1149 	{
  1150 	TTmCharFormatLayer charLayer;
  1151 	RTmParFormatLayer parLayer;
  1152 
  1153 	TTmCharFormatLayer* pCharLayer = 0;
  1154 	RTmParFormatLayer* pParLayer = 0;
  1155 
  1156 	if (iChar.Peek())
  1157 		{
  1158 		charLayer.iFormat = *iChar.Peek();
  1159 		charLayer.iMask = iCharMask;
  1160 		pCharLayer = &charLayer;
  1161 		}
  1162 	if (iPar.Peek())
  1163 		{
  1164 		parLayer.iFormat.CopyL( *iPar.Peek() );
  1165 		parLayer.iMask = iParMask;
  1166 		pParLayer = &parLayer;
  1167 		CleanupClosePushL(parLayer);
  1168 		}
  1169 	TInt result = iImpl.ExecuteL(iStyle.Peek(), pCharLayer, pParLayer);
  1170 	if (pParLayer)
  1171 		CleanupStack::PopAndDestroy();
  1172 	return result;
  1173 	}
  1174 
  1175 TBool CEditorCommandInsertTextAndFormat::CanAdd(
  1176 	const CEditorCommandInsertTextAndFormat::RTextAndFormatParameters& aParams,
  1177 	MUnifiedEditor& aTarget) const
  1178 	{
  1179 	if (!iImpl.CanAdd(aParams.iPos, aParams.iText, aTarget))
  1180 		return EFalse;
  1181 	if (!iChar.Peek())
  1182 		return EFalse;
  1183 	if (!iPar.Peek())
  1184 		return EFalse;
  1185 	if (!iStyle.Peek())
  1186 		return EFalse;
  1187 	if (aParams.iStyleName != *iStyle.Peek())
  1188 		return EFalse;
  1189 	if (aParams.iPar.iMask.iFlags != iParMask.iFlags
  1190 		|| aParams.iPar.iFormat != *iPar.Peek())
  1191 		return EFalse;
  1192 	if (iCharMask.iFlags != aParams.iChar.iMask.iFlags
  1193 		|| aParams.iChar.iFormat != *iChar.Peek())
  1194 		return EFalse;
  1195 	// coalescence is not possible if the new text contains pictures.
  1196 	if (0 <= UndoSystem::FindPicture(aTarget, aParams.iPos, aParams.iText.Length()))
  1197 		return EFalse;
  1198 	return ETrue;
  1199 	}
  1200 
  1201 void CEditorCommandInsertTextAndFormat::Add(TInt aPos, const TDesC& aText)
  1202 	{
  1203 	iImpl.Add(aPos, aText);
  1204 	}
  1205 
  1206 ///////////////////////////////////
  1207 //								 //
  1208 //	CEditorCommandSetCharFormat  //
  1209 //								 //
  1210 ///////////////////////////////////
  1211 
  1212 CEditorCommandSetCharFormat::~CEditorCommandSetCharFormat()
  1213 	{
  1214 	iChar.Close();
  1215 	}
  1216 
  1217 CEditorCommandSetCharFormat* CEditorCommandSetCharFormat::NewL(
  1218 	const TRepositories& aReps, TInt aPos, TInt aLength,
  1219 	const TTmCharFormat* aChar, TTmCharFormatMask aCharMask,
  1220 	MUnifiedEditor& aTarget)
  1221 	{
  1222 	CEditorCommandSetCharFormat* r = new(ELeave) CEditorCommandSetCharFormat(aReps, aTarget);
  1223 	CleanupStack::PushL(r);
  1224 	r->iPos		= aPos;
  1225 	r->iLength	= aLength;
  1226 	r->iChar.TakeCopyL(aChar);
  1227 	r->iCharMask= aCharMask;
  1228 	CleanupStack::Pop(r);
  1229 	return r;
  1230 	}
  1231 
  1232 // get as much of a run as possible.
  1233 CEditorCommandSetCharFormat* CEditorCommandSetCharFormat::NewL(const TRepositories& aReps,
  1234 	TInt aPos, TInt& aRemaining, MUnifiedEditor& aTarget)
  1235 	{
  1236 	TTmCharFormatLayer format;
  1237 	TInt length;
  1238 	aTarget.GetCharFormat(aPos, MUnifiedEditor::ESpecific, format, length);
  1239 	if (aRemaining < length)
  1240 		length = aRemaining;
  1241 	CEditorCommandSetCharFormat* r =
  1242 		NewL(aReps, aPos, length, &format.iFormat, format.iMask, aTarget);
  1243 	aRemaining -= length;
  1244 	return r;
  1245 	}
  1246 
  1247 // get as many runs as necessary and return a batch if necessary.
  1248 CCommand* CEditorCommandSetCharFormat::NewBatchL(const TRepositories& aReps,
  1249 	TInt aPos, TInt aLength, MUnifiedEditor& aTarget)
  1250 	{
  1251 	CCommand* command = 0;
  1252 	TInt oldLength = aLength + 1;
  1253 	TInt end = aPos + aLength;
  1254 	while (0 < aLength && aLength < oldLength)
  1255 		{
  1256 		oldLength = aLength;
  1257 		CleanupStack::PushL(command);
  1258 		// coverity[double_free]
  1259 		command = CoalesceL(command, NewL(aReps, end - aLength, aLength, aTarget));
  1260 		CleanupStack::Pop();		// command, as was before call to CoalesceL
  1261 		}
  1262 	return command;
  1263 	}
  1264 
  1265 CCommand* CEditorCommandSetCharFormat::CreateInverseL() const
  1266 	{
  1267 	return CEditorCommandDeleteCharFormat::NewL(iRepositories, iPos, iLength, iTarget);
  1268 	}
  1269 
  1270 TInt CEditorCommandSetCharFormat::ExecuteL() const
  1271 	{
  1272 	TTmCharFormatLayer layer;
  1273 	layer.iFormat = *iChar.Peek();
  1274 	layer.iMask = iCharMask;
  1275 	iTarget.SetCharFormatL(iPos, iLength, layer);
  1276 	return 0;
  1277 	}
  1278 
  1279 TBool CEditorCommandSetCharFormat::PrepareToAddInverseToLastL(CSingleCommand& aLastCommand) const
  1280 	{
  1281 	if (aLastCommand.FamilyUid() != TUid::Uid(KUndoDllUid))
  1282 		return EFalse;
  1283 	CEditorCommandDeleteCharFormat* last =
  1284 		static_cast<CEditorCommand&>(aLastCommand).CastToCEditorCommandDeleteCharFormat();
  1285 	if (!last)
  1286 		return EFalse;
  1287 	return last->CanAdd(iPos, iLength, iTarget);
  1288 	}
  1289 
  1290 void CEditorCommandSetCharFormat::AddInverseToLast(CSingleCommand& aLastCommand) const
  1291 	{
  1292 	ASSERT(aLastCommand.FamilyUid() == TUid::Uid(KUndoDllUid));
  1293 	CEditorCommandDeleteCharFormat* last =
  1294 		static_cast<CEditorCommand&>(aLastCommand).CastToCEditorCommandDeleteCharFormat();
  1295 	ASSERT(last);
  1296 	last->Add(iPos, iLength);
  1297 	}
  1298 
  1299 //////////////////////////////////
  1300 //								//
  1301 //	CEditorCommandSetParFormat  //
  1302 //								//
  1303 //////////////////////////////////
  1304 
  1305 CEditorCommandSetParFormat::~CEditorCommandSetParFormat()
  1306 	{
  1307 	iPar.Close();
  1308 	}
  1309 
  1310 CEditorCommandSetParFormat* CEditorCommandSetParFormat::NewL(
  1311 	const TRepositories& aReps, TInt aPos, TInt aLength,
  1312 	const RTmParFormat* aFormat, TTmParFormatMask aMask,
  1313 	MUnifiedEditor& aTarget)
  1314 	{
  1315 	CEditorCommandSetParFormat* r = new(ELeave) CEditorCommandSetParFormat(aReps, aTarget);
  1316 	CleanupStack::PushL(r);
  1317 	r->iPos		= aPos;
  1318 	r->iLength	= aLength;
  1319 	r->iPar.TakeCopyL(aFormat);
  1320 	r->iParMask= aMask;
  1321 	CleanupStack::Pop(r);
  1322 	return r;
  1323 	}
  1324 
  1325 // get as much of a run as possible.
  1326 CEditorCommandSetParFormat* CEditorCommandSetParFormat::NewL(const TRepositories& aReps,
  1327 	TInt aPos, TInt& aRemaining, MUnifiedEditor& aTarget)
  1328 	{
  1329 	RTmParFormatLayer format;
  1330 	TInt length;
  1331 	CleanupClosePushL(format);
  1332 	aTarget.GetParFormatL(aPos, MUnifiedEditor::ESpecific, format, length);
  1333 	if (aRemaining < length)
  1334 		length = aRemaining;
  1335 	CEditorCommandSetParFormat* r =
  1336 		NewL(aReps, aPos, length, &format.iFormat, format.iMask, aTarget);
  1337 	aRemaining -= length;
  1338 	CleanupStack::PopAndDestroy();	// format
  1339 	return r;
  1340 	}
  1341 
  1342 // get as many runs as necessary and return a batch if necessary.
  1343 CCommand* CEditorCommandSetParFormat::NewBatchL(const TRepositories& aReps,
  1344 	TInt aPos, TInt aLength, MUnifiedEditor& aTarget)
  1345 	{
  1346 	CCommand* command = 0;
  1347 	TInt oldLength = aLength + 1;
  1348 	TInt end = aPos + aLength;
  1349 	while (0 < aLength && aLength < oldLength)
  1350 		{
  1351 		oldLength = aLength;
  1352 		CleanupStack::PushL(command);
  1353 		// coverity[double_free]
  1354 		command = CoalesceL(command, NewL(aReps, end - aLength, aLength, aTarget));
  1355 		CleanupStack::Pop();		// command, as was before call to CoalesceL
  1356 		}
  1357 	return command;
  1358 	}
  1359 
  1360 CCommand* CEditorCommandSetParFormat::CreateInverseL() const
  1361 	{
  1362 	return CEditorCommandDeleteParFormat::NewL(iRepositories, iPos, iLength, iTarget);
  1363 	}
  1364 
  1365 TInt CEditorCommandSetParFormat::ExecuteL() const
  1366 	{
  1367 	RTmParFormatLayer layer;
  1368 	CleanupClosePushL(layer);
  1369 	layer.iFormat.CopyL(*iPar.Peek());
  1370 	layer.iMask = iParMask;
  1371 	iTarget.SetParFormatL(iPos, iLength, layer);
  1372 	CleanupStack::PopAndDestroy();
  1373 	return 0;
  1374 	}
  1375 
  1376 TBool CEditorCommandSetParFormat::PrepareToAddInverseToLastL(CSingleCommand& aLastCommand) const
  1377 	{
  1378 	if (aLastCommand.FamilyUid() != TUid::Uid(KUndoDllUid))
  1379 		return EFalse;
  1380 	CEditorCommandDeleteParFormat* last =
  1381 		static_cast<CEditorCommand&>(aLastCommand).CastToCEditorCommandDeleteParFormat();
  1382 	if (!last)
  1383 		return EFalse;
  1384 	return last->CanAdd(iPos, iLength, iTarget);
  1385 	}
  1386 
  1387 void CEditorCommandSetParFormat::AddInverseToLast(CSingleCommand& aLastCommand) const
  1388 	{
  1389 	ASSERT(aLastCommand.FamilyUid() == TUid::Uid(KUndoDllUid));
  1390 	CEditorCommandDeleteParFormat* last =
  1391 		static_cast<CEditorCommand&>(aLastCommand).CastToCEditorCommandDeleteParFormat();
  1392 	ASSERT(last);
  1393 	last->Add(iPos, iLength);
  1394 	}
  1395 
  1396 //////////////////////////////////////
  1397 //									//
  1398 //	CEditorCommandDeleteCharFormat  //
  1399 //									//
  1400 //////////////////////////////////////
  1401 
  1402 CEditorCommandDeleteCharFormat::~CEditorCommandDeleteCharFormat() {}
  1403 
  1404 CEditorCommandDeleteCharFormat* CEditorCommandDeleteCharFormat::NewL(
  1405 	const TRepositories& aReps, TInt aPos, TInt aLength, MUnifiedEditor& aTarget)
  1406 	{
  1407 	CEditorCommandDeleteCharFormat* r =
  1408 		new(ELeave) CEditorCommandDeleteCharFormat(aReps, aTarget);
  1409 	r->iPos = aPos;
  1410 	r->iLength = aLength;
  1411 	return r;
  1412 	}
  1413 
  1414 CCommand* CEditorCommandDeleteCharFormat::CreateInverseL() const
  1415 	{
  1416 	return CEditorCommandSetCharFormat::NewBatchL(iRepositories, iPos, iLength, iTarget);
  1417 	}
  1418 
  1419 TInt CEditorCommandDeleteCharFormat::ExecuteL() const
  1420 	{
  1421 	iTarget.DeleteCharFormatL(iPos, iLength);
  1422 	return KErrNone;
  1423 	}
  1424 
  1425 TBool CEditorCommandDeleteCharFormat::CanAdd(TInt aPos, TInt aLength, MUnifiedEditor &aTarget) const
  1426 	{
  1427 	return &aTarget == &iTarget
  1428 		&& aPos <= iPos + iLength
  1429 		&& iPos <= aPos + aLength? ETrue : EFalse;
  1430 	}
  1431 
  1432 void CEditorCommandDeleteCharFormat::Add(TInt aPos, TInt aLength)
  1433 	{
  1434 	TInt min = aPos < iPos? aPos : iPos;
  1435 	TInt max = iPos + iLength;
  1436 	TInt max2= aPos + aLength;
  1437 	iPos = min;
  1438 	iLength = (max < max2? max2 : max) - min;
  1439 	}
  1440 
  1441 /////////////////////////////////////
  1442 //								   //
  1443 //	CEditorCommandDeleteParFormat  //
  1444 //								   //
  1445 /////////////////////////////////////
  1446 
  1447 CEditorCommandDeleteParFormat::~CEditorCommandDeleteParFormat() {}
  1448 
  1449 CEditorCommandDeleteParFormat* CEditorCommandDeleteParFormat::NewL(
  1450 	const TRepositories& aReps, TInt aPos, TInt aLength, MUnifiedEditor& aTarget)
  1451 	{
  1452 	CEditorCommandDeleteParFormat* r =
  1453 		new(ELeave) CEditorCommandDeleteParFormat(aReps, aTarget);
  1454 	r->iPos = aPos;
  1455 	r->iLength = aLength;
  1456 	return r;
  1457 	}
  1458 
  1459 CCommand* CEditorCommandDeleteParFormat::CreateInverseL() const
  1460 	{
  1461 	return CEditorCommandSetParFormat::NewBatchL(iRepositories, iPos, iLength, iTarget);
  1462 	}
  1463 
  1464 TInt CEditorCommandDeleteParFormat::ExecuteL() const
  1465 	{
  1466 	iTarget.DeleteParFormatL(iPos, iLength);
  1467 	return KErrNone;
  1468 	}
  1469 
  1470 TBool CEditorCommandDeleteParFormat::CanAdd(TInt aPos, TInt aLength, MUnifiedEditor& aTarget) const
  1471 	{
  1472 	return &aTarget == &iTarget
  1473 		&& aPos <= iPos + iLength
  1474 		&& iPos <= aPos + aLength? ETrue : EFalse;
  1475 	}
  1476 
  1477 void CEditorCommandDeleteParFormat::Add(TInt aPos, TInt aLength)
  1478 	{
  1479 	TInt min = aPos < iPos? aPos : iPos;
  1480 	TInt max = iPos + iLength;
  1481 	TInt max2= aPos + aLength;
  1482 	iPos = min;
  1483 	iLength = (max < max2? max2 : max) - min;
  1484 	}
  1485 
  1486 //////////////////////////
  1487 //						//
  1488 //	Command prototypes  //
  1489 //						//
  1490 //////////////////////////
  1491 
  1492 //
  1493 // Attribute setters
  1494 //
  1495 void CEditorCommandCreateStyleProto::Set(const RTmStyle& aStyle)
  1496 	{
  1497 	iStyle = &aStyle;
  1498 	}
  1499 
  1500 void CEditorCommandChangeStyleProto::Set(const RTmStyle& aStyle)
  1501 	{
  1502 	iStyle = &aStyle;
  1503 	}
  1504 
  1505 void CEditorCommandSetStyleProto::Set(TInt aPos,
  1506 	TInt aLength,
  1507 	const TDesC& aName)
  1508 	{
  1509 	iPos	= aPos;
  1510 	iLength	= aLength;
  1511 	iName	= &aName;
  1512 	}
  1513 
  1514 void CEditorCommandDeleteStyleProto::Set(const TDesC& aName)
  1515 	{
  1516 	iName	= &aName;
  1517 	}
  1518 
  1519 void CEditorCommandSetCharFormatProto::Set(TInt aPos,
  1520 	TInt aLength,
  1521 	const TTmCharFormatLayer& aFormat)
  1522 	{
  1523 	iPos	= aPos;
  1524 	iLength	= aLength;
  1525 	iFormat	= &aFormat;
  1526 	}
  1527 
  1528 void CEditorCommandSetParFormatProto::Set(TInt aPos,
  1529 	TInt aLength,
  1530 	const RTmParFormatLayer& aFormat)
  1531 	{
  1532 	iPos	= aPos;
  1533 	iLength	= aLength;
  1534 	iFormat	= &aFormat;
  1535 	}
  1536 
  1537 void CEditorCommandInsertProto::Set(TInt aPos,
  1538 	const TDesC& aText,
  1539 	const TDesC* aStyle,
  1540 	const TTmCharFormatLayer* aCharFormat,
  1541 	const RTmParFormatLayer* aParFormat)
  1542 	{
  1543 	iPos		= aPos;
  1544 	iText		= &aText;
  1545 	iStyle		= aStyle;
  1546 	iCharFormat	= aCharFormat;
  1547 	iParFormat	= aParFormat;
  1548 	}
  1549 
  1550 void CEditorCommandDeleteProto::Set(TInt aPos, TInt aLength)
  1551 	{
  1552 	iPos	= aPos;
  1553 	iLength	= aLength;
  1554 
  1555 	// adjust 'iPos' and 'iLength' to be surrogate aligned, if possible
  1556 	if (iPos >= 0 && iPos <= iTarget.DocumentLength())
  1557 		{
  1558 		// check the character at aPos
  1559 		TBuf<2> dest;
  1560 		iTarget.GetText(iPos, dest);
  1561 		if (dest.Length() > 0 && IsLowSurrogate(dest[0]))
  1562 			{
  1563 			// try to decrease aPos by 1
  1564 			if (iPos > 0)
  1565 				{
  1566 				iTarget.GetText(iPos-1, dest);
  1567 				if (dest.Length() > 0 && IsHighSurrogate(dest[0]))
  1568 					{
  1569 					iPos--;
  1570 					iLength++;
  1571 					}
  1572 				else
  1573 					{
  1574 					// do nothing, just delete the corrupt surrogate
  1575 					}
  1576 				}
  1577 			else
  1578 				{
  1579 				// do nothing
  1580 				}
  1581 			}
  1582 		}
  1583 	
  1584 	if (iLength > 0)
  1585 		{
  1586 		// check the character at aPos+aLength
  1587 		TBuf<2> dest;
  1588 		iTarget.GetText(iPos+iLength-1, dest);
  1589 		if (dest.Length() > 0 && IsHighSurrogate(dest[0]))
  1590 			{
  1591 			if (iPos + (iLength - 1) <= iTarget.DocumentLength())
  1592 				{
  1593 				// try to increase aLength by 1
  1594 				iTarget.GetText(iPos+iLength, dest);
  1595 				if (dest.Length() > 0 && IsLowSurrogate(dest[0]))
  1596 					{
  1597 					iLength++;
  1598 					}
  1599 				else
  1600 					{
  1601 					// do nothing
  1602 					}
  1603 				}
  1604 			else
  1605 				{
  1606 				// do nothing
  1607 				}
  1608 			}
  1609 		}
  1610  	}
  1611 
  1612 void CEditorCommandDeleteCharFormatProto::Set(TInt aPos, TInt aLength)
  1613 	{
  1614 	iPos	= aPos;
  1615 	iLength	= aLength;
  1616 	}
  1617 
  1618 void CEditorCommandDeleteParFormatProto::Set(TInt aPos, TInt aLength)
  1619 	{
  1620 	iPos	= aPos;
  1621 	iLength	= aLength;
  1622 	}
  1623 
  1624 void CEditorCommandDeletePictureProto::Set(TInt aPos)
  1625 	{
  1626 	iPos = aPos;
  1627 	}
  1628 
  1629 void CEditorCommandDestroyPictureProto::Set(TInt aPos)
  1630 	{
  1631 	if (iPictureOwnerDelegate)
  1632 		{
  1633 		iPictureOwnerDelegate->ForgetOwner(this);
  1634 		iPictureOwnerDelegate = 0;
  1635 		}
  1636 	iPos = aPos;
  1637 	}
  1638 
  1639 void CEditorCommandInsertPictureProto::Set(TInt aPos, const TPictureHeader& aPicture)
  1640 	{
  1641 	iPos		= aPos;
  1642 	iPicture	= &aPicture;
  1643 	}
  1644 
  1645 void CEditorCommandRenameStyleProto::Set(const TDesC& aOldName, const TDesC& aNewName)
  1646 	{
  1647 	iOldName	= &aOldName;
  1648 	iNewName	= &aNewName;
  1649 	}
  1650 
  1651 void CEditorCommandSetBaseFormatProto::Set(
  1652 	const TTmCharFormat* aCharFormat, const RTmParFormat* aParFormat)
  1653 	{
  1654 	iChar	= aCharFormat;
  1655 	iPar	= aParFormat;
  1656 	}
  1657 
  1658 void CEditorCommandPasteProto::Set(const CStreamStore& aStore,
  1659 	const CStreamDictionary& aStreamDictionary,	TInt aPos)
  1660 	{
  1661 	iImpl.Set(aStore, aStreamDictionary, aPos);
  1662 	}
  1663 
  1664 //
  1665 // execution and inversion
  1666 //
  1667 
  1668 // CEditorCommandCreateStyleProto
  1669 TInt CEditorCommandCreateStyleProto::ExecuteL() const
  1670 	{
  1671 	MUnifiedEditor::MStyleSupport* si = iTarget.StyleSupport();
  1672 	ASSERT(si);
  1673 	return si->CreateStyleL(*iStyle);
  1674 	}
  1675 
  1676 CCommand* CEditorCommandCreateStyleProto::CreateInverseL() const
  1677 	{
  1678 	return CEditorCommandDeleteStyle::NewL(Repositories(), iStyle->iName, iTarget);
  1679 	}
  1680 
  1681 
  1682 // CEditorCommandChangeStyleProto
  1683 TInt CEditorCommandChangeStyleProto::ExecuteL() const
  1684 	{
  1685 	MUnifiedEditor::MStyleSupport* si = iTarget.StyleSupport();
  1686 	ASSERT(si);
  1687 	return si->ChangeStyleL(*iStyle);
  1688 	}
  1689 
  1690 CCommand* CEditorCommandChangeStyleProto::CreateInverseL() const
  1691 	{
  1692 	return CEditorCommandAlterStyle::NewL(Repositories(), iStyle->iName, iTarget);
  1693 	}
  1694 
  1695 // CEditorCommandSetStyleProto
  1696 TInt CEditorCommandSetStyleProto::ExecuteL() const
  1697 	{
  1698 	MUnifiedEditor::MStyleSupport* si = iTarget.StyleSupport();
  1699 	ASSERT(si);
  1700 	return si->SetStyleL(iPos, iLength, *iName);
  1701 	}
  1702 
  1703 CCommand* CEditorCommandSetStyleProto::CreateInverseL() const
  1704 	{
  1705 	return CEditorCommandSetStyle::NewL(Repositories(), iPos, iLength, iTarget);
  1706 	}
  1707 
  1708 // CEditorCommandDeleteStyleProto
  1709 TInt CEditorCommandDeleteStyleProto::ExecuteL() const
  1710 	{
  1711 	MUnifiedEditor::MStyleSupport* si = iTarget.StyleSupport();
  1712 	ASSERT(si);
  1713 	return si->DeleteStyleL(*iName);
  1714 	}
  1715 
  1716 CCommand* CEditorCommandDeleteStyleProto::CreateInverseL() const
  1717 	{
  1718 	return CEditorCommandCreateStyle::NewBatchL(Repositories(), *iName, iTarget);
  1719 	}
  1720 
  1721 // CEditorCommandSetCharFormatProto
  1722 TInt CEditorCommandSetCharFormatProto::ExecuteL() const
  1723 	{
  1724 	iTarget.SetCharFormatL(iPos, iLength, *iFormat);
  1725 	return KErrNone;
  1726 	}
  1727 
  1728 CCommand* CEditorCommandSetCharFormatProto::CreateInverseL() const
  1729 	{
  1730 	// inverse is to remove formatting and re-apply the old
  1731 	CCommand* inverse =
  1732 		CEditorCommandSetCharFormat::NewBatchL(Repositories(),
  1733 			iPos, iLength, iTarget);
  1734 	CleanupStack::PushL(inverse);
  1735 	// coverity[double_free]
  1736 	inverse = CoalesceL(inverse,
  1737 		CEditorCommandDeleteCharFormat::NewL(Repositories(), iPos, iLength, iTarget));
  1738 	CleanupStack::Pop();
  1739 	return inverse;
  1740 	}
  1741 
  1742 // CEditorCommandSetParFormatProto
  1743 TInt CEditorCommandSetParFormatProto::ExecuteL() const
  1744 	{
  1745 	iTarget.SetParFormatL(iPos, iLength, *iFormat);
  1746 	return KErrNone;
  1747 	}
  1748 
  1749 CCommand* CEditorCommandSetParFormatProto::CreateInverseL() const
  1750 	{
  1751 	// inverse is to remove formatting and re-apply the old
  1752 	CCommand* inverse =
  1753 		CEditorCommandSetParFormat::NewBatchL(Repositories(), iPos, iLength, iTarget);
  1754 	CleanupStack::PushL(inverse);
  1755 	// coverity[double_free]
  1756 	inverse = CoalesceL(inverse,
  1757 		CEditorCommandDeleteParFormat::NewL(Repositories(), iPos, iLength, iTarget));
  1758 	CleanupStack::Pop();
  1759 	return inverse;
  1760 	}
  1761 
  1762 // CEditorCommandInsertProto
  1763 TInt CEditorCommandInsertProto::ExecuteL() const
  1764 	{
  1765 	iTarget.InsertTextL(iPos, *iText, iStyle, iCharFormat, iParFormat);
  1766 	return KErrNone;
  1767 	}
  1768 
  1769 CCommand* CEditorCommandInsertProto::CreateInverseL() const
  1770 	{
  1771 	return CEditorCommandDeleteText::NewL(Repositories(), iPos, iText->Length(), iTarget);
  1772 	}
  1773 
  1774 TBool CEditorCommandInsertProto::PrepareToAddInverseToLastL(CSingleCommand& aLastCommand) const
  1775 	{
  1776 	if (aLastCommand.FamilyUid() != TUid::Uid(KUndoDllUid))
  1777 		return EFalse;
  1778 	CEditorCommandDeleteText* last =
  1779 		static_cast<CEditorCommand&>(aLastCommand).CastToCEditorCommandDeleteText();
  1780 	if (!last)
  1781 		return EFalse;
  1782 	return last->CanAdd(iPos, iText->Length(), iTarget);
  1783 	}
  1784 
  1785 void CEditorCommandInsertProto::AddInverseToLast(CSingleCommand& aLastCommand) const
  1786 	{
  1787 	ASSERT(aLastCommand.FamilyUid() == TUid::Uid(KUndoDllUid));
  1788 	CEditorCommandDeleteText* last =
  1789 		static_cast<CEditorCommand&>(aLastCommand).CastToCEditorCommandDeleteText();
  1790 	ASSERT(last);
  1791 	last->Add(iText->Length());
  1792 	}
  1793 
  1794 // CEditorCommandDeleteProto
  1795 TInt CEditorCommandDeleteProto::ExecuteL() const
  1796 	{
  1797 	iTarget.DeleteTextL(iPos, iLength);
  1798 	return KErrNone;
  1799 	}
  1800 
  1801 CCommand* CEditorCommandDeleteProto::CreateInverseL() const
  1802 	{
  1803 	return CEditorCommandInsertTextAndFormat::NewBatchL(Repositories(),
  1804 		iPos, iLength, iTarget);
  1805 	}
  1806 
  1807 TBool CEditorCommandDeleteProto::PrepareToAddInverseToLastL(CSingleCommand& aLastCommand) const
  1808 	{
  1809 	if (iDeletedText.MaxLength() < iLength)
  1810 		return EFalse;
  1811 	if (aLastCommand.FamilyUid() != TUid::Uid(KUndoDllUid))
  1812 		return EFalse;
  1813 	CEditorCommandInsertTextAndFormat* last =
  1814 		static_cast<CEditorCommand&>(aLastCommand).CastToCEditorCommandInsertTextAndFormat();
  1815 	if (!last)
  1816 		return EFalse;
  1817 	CEditorCommandInsertTextAndFormat::RTextAndFormatParameters params;
  1818 	CleanupClosePushL(params);
  1819 	params.SetL(iPos, iLength, iTarget);
  1820 	TBool result = EFalse;
  1821 	if (params.iText.Length() == iLength)
  1822 		{
  1823 		result = last->CanAdd(params, iTarget);
  1824 		if (result)
  1825 			iDeletedText = params.iText;
  1826 		}
  1827 	CleanupStack::PopAndDestroy();
  1828 	return result;
  1829 	}
  1830 
  1831 void CEditorCommandDeleteProto::AddInverseToLast(CSingleCommand& aLastCommand) const
  1832 	{
  1833 	ASSERT(aLastCommand.FamilyUid() == TUid::Uid(KUndoDllUid));
  1834 	CEditorCommandInsertTextAndFormat* last =
  1835 		static_cast<CEditorCommand&>(aLastCommand).CastToCEditorCommandInsertTextAndFormat();
  1836 	ASSERT(last);
  1837 	last->Add(iPos, iDeletedText);
  1838 	}
  1839 
  1840 // CEditorCommandDeleteCharFormatProto
  1841 TInt CEditorCommandDeleteCharFormatProto::ExecuteL() const
  1842 	{
  1843 	iTarget.DeleteCharFormatL(iPos, iLength);
  1844 	return KErrNone;
  1845 	}
  1846 
  1847 CCommand* CEditorCommandDeleteCharFormatProto::CreateInverseL() const
  1848 	{
  1849 	return CEditorCommandSetCharFormat::NewBatchL(Repositories(),
  1850 		iPos, iLength, iTarget);
  1851 	}
  1852 
  1853 // CEditorCommandDeleteParFormatProto
  1854 TInt CEditorCommandDeleteParFormatProto::ExecuteL() const
  1855 	{
  1856 	iTarget.DeleteParFormatL(iPos, iLength);
  1857 	return KErrNone;
  1858 	}
  1859 
  1860 CCommand* CEditorCommandDeleteParFormatProto::CreateInverseL() const
  1861 	{
  1862 	return CEditorCommandSetParFormat::NewBatchL(Repositories(),
  1863 		iPos, iLength, iTarget);
  1864 	}
  1865 
  1866 // CEditorCommandDeletePictureProto
  1867 TInt CEditorCommandDeletePictureProto::ExecuteL() const
  1868 	{
  1869 	MUnifiedEditor::MPictureSupport* pi = iTarget.PictureSupport();
  1870 	ASSERT(pi);
  1871 	pi->DropPictureL(iPos);
  1872 	return KErrNone;
  1873 	}
  1874 
  1875 // CEditorCommandInsertPictureProto
  1876 TInt CEditorCommandInsertPictureProto::ExecuteL() const
  1877 	{
  1878 	MUnifiedEditor::MPictureSupport* pi = iTarget.PictureSupport();
  1879 	ASSERT(pi);
  1880 	pi->InsertPictureL(iPos, *iPicture);
  1881 	return KErrNone;
  1882 	}
  1883 
  1884 CCommand* CEditorCommandInsertPictureProto::CreateInverseL() const
  1885 	{
  1886 	return CEditorCommandDeletePicture::NewL(Repositories(), iPos, iTarget);
  1887 	}
  1888 
  1889 // CEditorCommandDestroyPictureProto
  1890 void CEditorCommandDestroyPictureProto::ForgetDelegate()
  1891 	{
  1892 	iPictureOwnerDelegate = 0;
  1893 	}
  1894 
  1895 CEditorCommandDestroyPictureProto::~CEditorCommandDestroyPictureProto()
  1896 	{
  1897 	if (iPictureOwnerDelegate)
  1898 		iPictureOwnerDelegate->ForgetOwner(this);
  1899 	}
  1900 
  1901 CCommand* CEditorCommandDestroyPictureProto::CreateInverseL() const
  1902 	{
  1903 	CEditorCommandDestroyPictureProto* nonConstThis =
  1904 		const_cast<CEditorCommandDestroyPictureProto*>(this);
  1905 	if (iPictureOwnerDelegate)
  1906 		{
  1907 		iPictureOwnerDelegate->ForgetOwner(nonConstThis);
  1908 		iPictureOwnerDelegate = 0;
  1909 		}
  1910 	CCommand* style =
  1911 		CEditorCommandSetStyle::NewL(Repositories(), iPos, 1, iTarget);
  1912 	CleanupStack::PushL(style);
  1913 	CCommand* charFormat =
  1914 		CEditorCommandSetCharFormat::NewBatchL(Repositories(), iPos, 1, iTarget);
  1915 	CleanupStack::PushL(charFormat);
  1916 	CCommand* parFormat =
  1917 		CEditorCommandSetParFormat::NewBatchL(Repositories(), iPos, 1, iTarget);
  1918 	CleanupStack::PushL(parFormat);
  1919 	iPictureOwnerDelegate =
  1920 		CEditorCommandInsertPicture::NewL(Repositories(), iPos,
  1921 		*const_cast<CEditorCommandDestroyPictureProto*>(nonConstThis), iTarget);
  1922 	// coverity[double_free]
  1923 	CCommand* command = CoalesceL(parFormat, iPictureOwnerDelegate);
  1924 	CleanupStack::Pop();	// parFormat, no longer owned
  1925 	// coverity[double_free]
  1926 	command = CoalesceL(charFormat, command);
  1927 	CleanupStack::Pop();	// charFormat, no longer owned
  1928 	// coverity[double_free]
  1929 	command = CoalesceL(style, command);
  1930 	CleanupStack::Pop();	// style, no longer owned
  1931 
  1932 	return command;
  1933 	}
  1934 
  1935 TInt CEditorCommandDestroyPictureProto::ExecuteL() const
  1936 	{
  1937 	MUnifiedEditor::MPictureSupport* pi = iTarget.PictureSupport();
  1938 	ASSERT(pi);
  1939 	TPictureHeader pic;
  1940 	pi->Picture(iPos, pic);
  1941 	pi->DropPictureL(iPos);
  1942 	if (iPictureOwnerDelegate)
  1943 		{
  1944 		iPictureOwnerDelegate->TakePictureOwnership(pic);
  1945 		iPictureOwnerDelegate = 0;
  1946 		}
  1947 	else
  1948 		pic.DeletePicture();
  1949 	return KErrNone;
  1950 	}
  1951 
  1952 // CEditorCommandRenameStyleProto
  1953 TInt CEditorCommandRenameStyleProto::ExecuteL() const
  1954 	{
  1955 	MUnifiedEditor::MStyleSupport* si = iTarget.StyleSupport();
  1956 	ASSERT(si);
  1957 	return si->RenameStyleL(*iOldName, *iNewName);
  1958 	}
  1959 
  1960 CCommand* CEditorCommandRenameStyleProto::CreateInverseL() const
  1961 	{
  1962 	return CEditorCommandRenameStyle::NewL(Repositories(),
  1963 		*iNewName, *iOldName, iTarget);
  1964 	}
  1965 
  1966 // CEditorCommandPasteProto
  1967 TInt CEditorCommandPasteProto::ExecuteL() const
  1968 	{
  1969 	return iImpl.ExecuteL();
  1970 	}
  1971 
  1972 UndoSystem::CCommand* CEditorCommandPasteProto::CreateInverseL() const
  1973 	{
  1974 	RStoreReadStream stream;
  1975 	iImpl.OpenPlainTextStreamLC(stream);
  1976 	TInt pos = iImpl.Pos();
  1977 	TInt length = stream.ReadInt32L();
  1978 	CCommand* command = 0;
  1979 	CBufSeg* buf = CBufSeg::NewL(200);
  1980 	CleanupStack::PushL(buf);
  1981 	TPtrC current;
  1982 
  1983 	if (length < 0)
  1984 		User::Leave(KErrNotSupported);	// don't know how to undo
  1985 
  1986 	RBufWriteStream bufferStream;
  1987 	bufferStream.Open(*buf);
  1988 	TMemoryStreamUnicodeSink sink(bufferStream);
  1989 	TUnicodeExpander e;
  1990 	e.ExpandL(sink, stream, length);
  1991 	bufferStream.CommitL();
  1992 	bufferStream.Close();
  1993 
  1994 	TInt end = pos + length;
  1995 	TInt bufferPos = 0;
  1996 
  1997 	while (pos != end)
  1998 		{
  1999 		ASSERT(pos < end);
  2000 		TInt lengthSearched = 0;
  2001 		TInt pic = KErrNotFound;
  2002 		while ((pic = current.Locate(CEditableText::EPictureCharacter)) < 0
  2003 			&& pos + lengthSearched < end)
  2004 			{
  2005 			lengthSearched += current.Length();
  2006 			TPtr8 seg(buf->Ptr(bufferPos));
  2007 			bufferPos += seg.Length();
  2008 			current.Set(reinterpret_cast<const TText*>(seg.Ptr()),
  2009 				seg.Length() / sizeof(TText));
  2010 			}
  2011 		TInt currentSearched = 0 <= pic? pic : current.Length();
  2012 		lengthSearched += currentSearched;
  2013 
  2014 		if (lengthSearched)
  2015 			{
  2016 			// we have some text to delete
  2017 			CleanupStack::PushL(command);
  2018 			// coverity[double_free]
  2019 			command = CoalesceL(command,
  2020 				CEditorCommandDeleteText::NewL(Repositories(), pos, lengthSearched,
  2021 					iImpl.Target()));
  2022 			CleanupStack::Pop();
  2023 			pos += lengthSearched;
  2024 			}
  2025 
  2026 		if (0 <= pic)
  2027 			{
  2028 			ASSERT(current.Length());
  2029 			// we have a picture to delete
  2030 			CleanupStack::PushL(command);
  2031 			command = CoalesceL(command,
  2032 				CEditorCommandDeletePicture::NewL(Repositories(), pos, iImpl.Target()));
  2033 			CleanupStack::Pop();
  2034 			currentSearched += 1;
  2035 			pos += 1;
  2036 			}
  2037 
  2038 		current.Set(current.Mid(currentSearched));
  2039 		}
  2040 
  2041 	CleanupStack::PopAndDestroy(buf);
  2042 	CleanupStack::PopAndDestroy();		// close stream
  2043 
  2044 	return command;
  2045 	}
  2046 
  2047 // CEditorCommandSetBaseFormatProto
  2048 TInt CEditorCommandSetBaseFormatProto::ExecuteL() const
  2049 	{
  2050 	iTarget.SetBaseFormatL(*iChar, *iPar);
  2051 	return KErrNone;
  2052 	}
  2053 
  2054 CCommand* CEditorCommandSetBaseFormatProto::CreateInverseL() const
  2055 	{
  2056 	return CEditorCommandSetBaseFormat::NewL(Repositories(),
  2057 		iTarget);
  2058 	}
  2059 
  2060 //////////////////////
  2061 //					//
  2062 //	free functions  //
  2063 //					//
  2064 //////////////////////
  2065 
  2066 TInt UndoSystem::FindPicture(const MUnifiedEditor& aTarget, TInt aPos, TInt aLength)
  2067 	{
  2068 	const MUnifiedEditor::MPictureSupport* pi =
  2069 		const_cast<MUnifiedEditor&>(aTarget).PictureSupport();
  2070 	if (!pi)
  2071 		return KErrNotFound;
  2072 	while (0 < aLength)
  2073 		{
  2074 		TPtrC text;
  2075 		aTarget.GetText(aPos, text);
  2076 		if (aLength < text.Length())
  2077 			text.Set(text.Ptr(), aLength);
  2078 		TInt result;
  2079 		while (0 <= (result = text.Locate(CEditableText::EPictureCharacter)))
  2080 			{
  2081 			TPictureHeader pic;
  2082 			pi->Picture(aPos + result, pic);
  2083 			if (pic.iPictureType != KNullUid)
  2084 				return aPos + result;
  2085 			++result;
  2086 			aPos += result;
  2087 			aLength -= result;
  2088 			TPtrC temp = text.Mid(result);
  2089 			text.Set(temp);
  2090 			}
  2091 		aPos += text.Length();
  2092 		aLength -= text.Length();
  2093 		}
  2094 	return KErrNotFound;
  2095 	}
  2096