--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/textrendering/textformatting/undo/EditorCommands.cpp Tue Feb 02 02:02:46 2010 +0200
@@ -0,0 +1,2096 @@
+/*
+* Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+#include "EditorCommands.h"
+#include "AssertFileAndLine.h"
+#include <txtetext.h>
+#include <s32ucmp.h>
+
+using namespace UndoSystem;
+
+inline TBool IsSurrogate(TText a) { return 0xD800 == (a & 0xF800); }
+inline TBool IsHighSurrogate(TText a) { return 0xD800 == (a & 0xFC00); }
+inline TBool IsLowSurrogate(TText a) { return 0xDC00 == (a & 0xFC00); }
+inline TChar JoinSurrogates(TText aHigh, TText aLow)
+ {
+ return ((aHigh - 0xd7f7) << 10) + aLow;
+ }
+
+// These roughly mirror the prototype commands, but rather than
+// referencing externally-owned (and therefore temporary) objects,
+// they own objects. Typically these are unique instances.
+
+/**
+ * Command for setting the base character and paragraph formats.
+ *
+ * @internalComponent
+ * @since App-frameworks6.1
+ */
+NONSHARABLE_CLASS(CEditorCommandSetBaseFormat) : public CEditorCommand
+ {
+ MUnifiedEditor& iTarget;
+ RUniqueInstance<TTmCharFormat> iChar;
+ RUniqueInstance<RTmParFormat> iPar;
+
+ const TRepositories& iRepositories;
+
+ CEditorCommandSetBaseFormat(const TRepositories& aReps, MUnifiedEditor& aTarget);
+public:
+ ~CEditorCommandSetBaseFormat();
+ static CEditorCommandSetBaseFormat* NewL(const TRepositories& aReps,
+ const TTmCharFormat& aCharFormat, const RTmParFormat& aParFormat,
+ MUnifiedEditor& aTarget);
+ static CEditorCommandSetBaseFormat* NewL(const TRepositories& aReps,
+ MUnifiedEditor& aTarget);
+
+ UndoSystem::CCommand* CreateInverseL() const;
+ TInt ExecuteL() const;
+ };
+
+/**
+ * Command for renaming a style.
+ *
+ * @internalComponent
+ * @since App-frameworks6.1
+ */
+NONSHARABLE_CLASS(CEditorCommandRenameStyle) : public CEditorCommand
+ {
+ MUnifiedEditor& iTarget;
+ RUniqueInstance<TDes> iOldName;
+ RUniqueInstance<TDes> iNewName;
+
+ const TRepositories& iRepositories;
+
+ CEditorCommandRenameStyle(const TRepositories& aReps, MUnifiedEditor& aTarget)
+ : iTarget(aTarget), iOldName(*aReps.iDes), iNewName(*aReps.iDes),
+ iRepositories(aReps) {}
+public:
+ ~CEditorCommandRenameStyle();
+ static CEditorCommandRenameStyle* NewL(const TRepositories& aReps,
+ const TDesC& aOldName, const TDesC& aNewName, MUnifiedEditor& aTarget);
+
+ CCommand* CreateInverseL() const;
+ TInt ExecuteL() const;
+ };
+
+/**
+ * Command for inserting a picture into the text.
+ *
+ * @internalComponent
+ * @since App-frameworks6.1
+ */
+NONSHARABLE_CLASS(CEditorCommandInsertPicture) : public CEditorCommand
+ {
+ MUnifiedEditor& iTarget;
+ TInt iPos;
+ mutable TPictureHeader iPicture;
+ MPictureOwner* iPictureOwner;
+ const TRepositories& iRepositories;
+
+ CEditorCommandInsertPicture(const TRepositories& aReps, MUnifiedEditor& aTarget)
+ : iTarget(aTarget), iRepositories(aReps) {}
+public:
+ ~CEditorCommandInsertPicture();
+ static CEditorCommandInsertPicture* NewL(const TRepositories& aReps,
+ TInt aPos, MPictureOwner& aPictureOwner, MUnifiedEditor& aTarget);
+ void TakePictureOwnership(TPictureHeader&);
+ void ForgetOwner(MPictureOwner*);
+
+ CCommand* CreateInverseL() const;
+ TInt ExecuteL() const;
+ };
+
+/**
+ * Command for creating a new style.
+ *
+ * @internalComponent
+ * @since App-frameworks6.1
+ */
+NONSHARABLE_CLASS(CEditorCommandCreateStyle) : public CEditorCommand
+ {
+ MUnifiedEditor& iTarget;
+ RUniqueInstance<TDes> iName;
+ RUniqueInstance<TDes> iNext;
+ RUniqueInstance<TTmCharFormat> iChar;
+ TTmCharFormatMask iCharMask;
+ RUniqueInstance<RTmParFormat> iPar;
+ TTmParFormatMask iParMask;
+ TInt iLevel;
+
+ const TRepositories& iRepositories;
+
+ CEditorCommandCreateStyle(const TRepositories& aReps, MUnifiedEditor& aTarget)
+ : iTarget(aTarget), iName(*aReps.iDes), iNext(*aReps.iDes),
+ iChar(*aReps.iChar),
+ iPar(*aReps.iPar), iRepositories(aReps) {}
+public:
+ ~CEditorCommandCreateStyle();
+ static CEditorCommandCreateStyle* NewL(const TRepositories& aReps,
+ const TDesC& aName, const TDesC& aNext,
+ TTmCharFormat& aChar, TTmCharFormatMask aCharMask,
+ RTmParFormat& aPar, TTmParFormatMask aParMask,
+ TInt aLevel, MUnifiedEditor& aTarget);
+ static CEditorCommandCreateStyle* NewL(const TRepositories& aReps,
+ const TDesC& aName, MUnifiedEditor& aTarget);
+ static CCommand* NewBatchL(const TRepositories& aReps,
+ const TDesC& aName, MUnifiedEditor& aTarget);
+
+ CCommand* CreateInverseL() const;
+ TInt ExecuteL() const;
+ };
+
+/**
+ * Command for deleting a style, removing it from anywhere that it is applied.
+ *
+ * @internalComponent
+ * @since App-frameworks6.1
+ */
+NONSHARABLE_CLASS(CEditorCommandDeleteStyle) : public CEditorCommand
+ {
+ MUnifiedEditor& iTarget;
+ RUniqueInstance<TDes> iName;
+ const TRepositories& iRepositories;
+
+ CEditorCommandDeleteStyle(const TRepositories& aReps, MUnifiedEditor& aTarget)
+ : iTarget(aTarget), iName(*aReps.iDes), iRepositories(aReps) {}
+public:
+ ~CEditorCommandDeleteStyle();
+ static CEditorCommandDeleteStyle* NewL(const TRepositories& aReps,
+ const TDesC& aName, MUnifiedEditor& aTarget);
+
+ CCommand* CreateInverseL() const;
+ TInt ExecuteL() const;
+ };
+
+/**
+ * Command for altering the attributes of a style.
+ *
+ * @internalComponent
+ * @since App-frameworks6.1
+ */
+NONSHARABLE_CLASS(CEditorCommandAlterStyle) : public CEditorCommand
+ {
+ MUnifiedEditor& iTarget;
+ RUniqueInstance<TDes> iName;
+ RUniqueInstance<TDes> iNext;
+ RUniqueInstance<TTmCharFormat> iChar;
+ TTmCharFormatMask iCharMask;
+ RUniqueInstance<RTmParFormat> iPar;
+ TTmParFormatMask iParMask;
+ TInt iLevel;
+
+ const TRepositories& iRepositories;
+
+ CEditorCommandAlterStyle(const TRepositories& aReps, MUnifiedEditor& aTarget)
+ : iTarget(aTarget), iName(*aReps.iDes), iNext(*aReps.iDes),
+ iChar(*aReps.iChar), iPar(*aReps.iPar), iRepositories(aReps) {}
+public:
+ ~CEditorCommandAlterStyle();
+ static CEditorCommandAlterStyle* NewL(const TRepositories& aReps,
+ const TDesC& aName, const TDesC& aNext,
+ TTmCharFormat& aChar, TTmCharFormatMask& aCharMask,
+ RTmParFormat& aPar, TTmParFormatMask& aParMask,
+ TInt aLevel, MUnifiedEditor& aTarget);
+ static CEditorCommandAlterStyle* NewL(const TRepositories& aReps,
+ const TDesC& aName, MUnifiedEditor& aTarget);
+
+ CCommand* CreateInverseL() const;
+ TInt ExecuteL() const;
+ };
+
+/**
+ * Command for applying an existing style to text.
+ *
+ * @internalComponent
+ * @since App-frameworks6.1
+ */
+NONSHARABLE_CLASS(CEditorCommandSetStyle) : public CEditorCommand
+ {
+ MUnifiedEditor& iTarget;
+ RUniqueInstance<TDes> iName;
+ TInt iPos;
+ TInt iRunLength;
+
+ const TRepositories& iRepositories;
+
+ CEditorCommandSetStyle(const TRepositories& aReps, MUnifiedEditor& aTarget)
+ : iTarget(aTarget), iName(*aReps.iDes), iRepositories(aReps) {}
+public:
+ ~CEditorCommandSetStyle();
+ static CEditorCommandSetStyle* NewL(const TRepositories& aReps,
+ const TDesC& aName, TInt aPos, TInt aRunLength,
+ MUnifiedEditor& aTarget);
+ static CCommand* NewL(const TRepositories& aReps,
+ TInt aPos, TInt aRunLength,
+ MUnifiedEditor& aTarget);
+
+ CCommand* CreateInverseL() const;
+ TInt ExecuteL() const;
+ };
+
+/**
+ * Command for deleting text without pictures in it.
+ *
+ * @internalComponent
+ * @since App-frameworks6.1
+ */
+NONSHARABLE_CLASS(CEditorCommandDeleteText) : public CEditorCommand
+ {
+ TEditorDeletePlainTextImpl iImpl;
+ const TRepositories& iRepositories; // only used in creating the inverse
+
+ CEditorCommandDeleteText*
+ CastToCEditorCommandDeleteText() { return this; }
+
+ CEditorCommandDeleteText(const TRepositories& aReps, MUnifiedEditor& aTarget,
+ TInt aPos, TInt aLength)
+ : iImpl(aTarget, aPos, aLength), iRepositories(aReps) {}
+public:
+ ~CEditorCommandDeleteText();
+ static CEditorCommandDeleteText* NewL(const TRepositories& aReps,
+ TInt aPos, TInt aLength, MUnifiedEditor& aTarget);
+
+ CCommand* CreateInverseL() const;
+ TInt ExecuteL() const;
+
+ // This command can be coalesced with others of the same type
+ TBool CanAdd(TInt aPos, TInt aLength, MUnifiedEditor& aTarget) const;
+ void Add(TInt aLength);
+ };
+
+/**
+ * Command for inserting text in a specified style and format.
+ *
+ * @internalComponent
+ * @since App-frameworks6.1
+ */
+NONSHARABLE_CLASS(CEditorCommandInsertTextAndFormat) : public CEditorCommand
+ {
+ TEditorInsertPlainTextImpl iImpl;
+ // layer
+ RUniqueInstance<TTmCharFormat> iChar;
+ TTmCharFormatMask iCharMask;
+ RUniqueInstance<RTmParFormat> iPar;
+ TTmParFormatMask iParMask;
+ RUniqueInstance<TDes> iStyle;
+
+ const TRepositories& iRepositories;
+
+ CEditorCommandInsertTextAndFormat*
+ CastToCEditorCommandInsertTextAndFormat() { return this; }
+ CEditorCommandInsertTextAndFormat(const TRepositories& aReps,
+ MUnifiedEditor& aTarget, TInt aPos, TDesC& aText)
+ : iImpl(aTarget, aPos, aText), iChar(*aReps.iChar), iPar(*aReps.iPar),
+ iStyle(*aReps.iDes), iRepositories(aReps) {}
+public:
+ struct RTextAndFormatParameters
+ {
+ TInt iPos;
+ TPtrC iText;
+ TPtrC iStyleName;
+ TTmCharFormatLayer iChar;
+ RTmParFormatLayer iPar;
+
+ void Close();
+ void SetL(TInt aPos, TInt aMaxLength, MUnifiedEditor& aTarget);
+ };
+ ~CEditorCommandInsertTextAndFormat();
+ static CEditorCommandInsertTextAndFormat* NewL(const TRepositories& aReps,
+ RTextAndFormatParameters& aParams, MUnifiedEditor& aTarget);
+
+ /**
+ * Gets as much of a run as possible.
+ */
+ static CEditorCommandInsertTextAndFormat* NewL(const TRepositories& aReps,
+ TInt aPos, TInt& aRemaining, TInt aOriginalPos, MUnifiedEditor& aTarget);
+
+ /**
+ * Gets as many runs as necessary and returns a batch if necessary.
+ */
+ static CCommand* NewBatchL(const TRepositories& aReps,
+ TInt aPos, TInt aLength, MUnifiedEditor& aTarget);
+
+ CCommand* CreateInverseL() const;
+ TInt ExecuteL() const;
+
+ // This command can be coalesced with others of the same type
+ TBool CanAdd(const RTextAndFormatParameters&, MUnifiedEditor& aTarget) const;
+ void Add(TInt aPos, const TDesC& aText);
+ };
+
+/**
+ * Command for deleting the specific character format over a run of text.
+ *
+ * @internalComponent
+ * @since App-frameworks6.1
+ */
+NONSHARABLE_CLASS(CEditorCommandDeleteCharFormat) : public CEditorCommand
+ {
+ MUnifiedEditor& iTarget;
+ TInt iPos;
+ TInt iLength;
+
+ const TRepositories& iRepositories;
+
+ CEditorCommandDeleteCharFormat*
+ CastToCEditorCommandDeleteCharFormat() { return this; }
+
+ CEditorCommandDeleteCharFormat(const TRepositories& aReps, MUnifiedEditor& aTarget)
+ : iTarget(aTarget), iRepositories(aReps) {}
+public:
+ ~CEditorCommandDeleteCharFormat();
+ static CEditorCommandDeleteCharFormat* NewL(const TRepositories& aReps,
+ TInt aPos, TInt aLength,
+ MUnifiedEditor& aTarget);
+
+ CCommand* CreateInverseL() const;
+ TInt ExecuteL() const;
+
+ // This command can be coalesced with others of the same type
+ TBool CanAdd(TInt aPos, TInt aLength, MUnifiedEditor& aTarget) const;
+ void Add(TInt aPos, TInt aLength);
+ };
+
+/**
+ * Command for deleting the specific paragraph format over a run of text.
+ *
+ * @internalComponent
+ * @since App-frameworks6.1
+ */
+NONSHARABLE_CLASS(CEditorCommandDeleteParFormat) : public CEditorCommand
+ {
+ MUnifiedEditor& iTarget;
+ TInt iPos;
+ TInt iLength;
+
+ const TRepositories& iRepositories;
+
+ CEditorCommandDeleteParFormat*
+ CastToCEditorCommandDeleteParFormat() { return this; }
+
+ CEditorCommandDeleteParFormat(const TRepositories& aReps, MUnifiedEditor& aTarget)
+ : iTarget(aTarget), iRepositories(aReps) {}
+public:
+ ~CEditorCommandDeleteParFormat();
+ static CEditorCommandDeleteParFormat* NewL(const TRepositories& aReps,
+ TInt aPos, TInt aLength,
+ MUnifiedEditor& aTarget);
+
+ CCommand* CreateInverseL() const;
+ TInt ExecuteL() const;
+
+ // This command can be coalesced with others of the same type
+ TBool CanAdd(TInt aPos, TInt aLength, MUnifiedEditor& aTarget) const;
+ void Add(TInt aPos, TInt aLength);
+ };
+
+/**
+ * Command for applying a character format to a run of text that has no
+ * existing specific character format.
+ *
+ * @internalComponent
+ * @since App-frameworks6.1
+ */
+NONSHARABLE_CLASS(CEditorCommandSetCharFormat) : public CEditorCommand
+ {
+ MUnifiedEditor& iTarget;
+ TInt iPos;
+ TInt iLength;
+ // layer
+ RUniqueInstance<TTmCharFormat> iChar;
+ TTmCharFormatMask iCharMask;
+
+ const TRepositories& iRepositories;
+
+ CEditorCommandSetCharFormat(const TRepositories& aReps, MUnifiedEditor& aTarget)
+ : iTarget(aTarget), iChar(*aReps.iChar), iRepositories(aReps) {}
+public:
+ ~CEditorCommandSetCharFormat();
+ static CEditorCommandSetCharFormat* NewL(const TRepositories& aReps,
+ TInt aPos, TInt aLength,
+ const TTmCharFormat* aChar, TTmCharFormatMask aCharMask,
+ MUnifiedEditor& aTarget);
+
+ // get as much of a run as possible.
+ static CEditorCommandSetCharFormat* NewL(const TRepositories& aReps,
+ TInt aPos, TInt& aRemaining, MUnifiedEditor& aTarget);
+
+ // get as many runs as necessary and return a batch if necessary.
+ static CCommand* NewBatchL(const TRepositories& aReps,
+ TInt aPos, TInt aLength, MUnifiedEditor& aTarget);
+
+ TBool PrepareToAddInverseToLastL(CSingleCommand& aLastCommand) const;
+ void AddInverseToLast(CSingleCommand& aLastCommand) const;
+ CCommand* CreateInverseL() const;
+ TInt ExecuteL() const;
+ };
+
+/**
+ * Command for applying a paragraph format to a run of text that has no
+ * existing specific paragraph format.
+ *
+ * @internalComponent
+ * @since App-frameworks6.1
+ */
+NONSHARABLE_CLASS(CEditorCommandSetParFormat) : public CEditorCommand
+ {
+ MUnifiedEditor& iTarget;
+ TInt iPos;
+ TInt iLength;
+ // layer
+ RUniqueInstance<RTmParFormat> iPar;
+ TTmParFormatMask iParMask;
+
+ const TRepositories& iRepositories;
+
+ CEditorCommandSetParFormat(const TRepositories& aReps, MUnifiedEditor& aTarget)
+ : iTarget(aTarget), iPar(*aReps.iPar), iRepositories(aReps) {}
+public:
+ ~CEditorCommandSetParFormat();
+ static CEditorCommandSetParFormat* NewL(const TRepositories& aReps,
+ TInt aPos, TInt aLength,
+ const RTmParFormat* aFormat, TTmParFormatMask aMask,
+ MUnifiedEditor& aTarget);
+
+ // get as much of a run as possible.
+ static CEditorCommandSetParFormat* NewL(const TRepositories& aReps,
+ TInt aPos, TInt& aRemaining, MUnifiedEditor& aTarget);
+
+ // get as many runs as necessary and return a batch if necessary.
+ static CCommand* NewBatchL(const TRepositories& aReps,
+ TInt aPos, TInt aLength, MUnifiedEditor& aTarget);
+
+ TBool PrepareToAddInverseToLastL(CSingleCommand& aLastCommand) const;
+ void AddInverseToLast(CSingleCommand& aLastCommand) const;
+ CCommand* CreateInverseL() const;
+ TInt ExecuteL() const;
+ };
+
+/**
+ * Command for deleting a picture from the text. The picture is assumed
+ * to be without significant formatting.
+ *
+ * @internalComponent
+ * @since App-frameworks6.1
+ */
+NONSHARABLE_CLASS(CEditorCommandDeletePicture) : public CEditorCommand,
+ private MPictureOwner
+ {
+ MUnifiedEditor& iTarget;
+ TInt iPos;
+ const TRepositories& iRepositories;
+ /**
+ * Will own picture after us.
+ */
+ mutable CEditorCommandInsertPicture* iPictureOwnerDelegate;
+
+ void ForgetDelegate();
+ CEditorCommandDeletePicture(const TRepositories& aReps, MUnifiedEditor& aTarget)
+ : iTarget(aTarget), iRepositories(aReps) {}
+public:
+ ~CEditorCommandDeletePicture();
+ static CEditorCommandDeletePicture* NewL(const TRepositories& aReps,
+ TInt aPos, MUnifiedEditor& aTarget);
+
+ UndoSystem::CCommand* CreateInverseL() const;
+ TInt ExecuteL() const;
+ };
+
+///////////////////////////////////
+// //
+// CEditorCommandSetBaseFormat //
+// //
+///////////////////////////////////
+
+CEditorCommandSetBaseFormat::CEditorCommandSetBaseFormat(
+ const TRepositories& aReps, MUnifiedEditor& aTarget)
+ : iTarget(aTarget), iChar(*aReps.iChar), iPar(*aReps.iPar),
+ iRepositories(aReps)
+ {
+ }
+
+CEditorCommandSetBaseFormat::~CEditorCommandSetBaseFormat()
+ {
+ iChar.Close();
+ iPar.Close();
+ }
+
+CEditorCommandSetBaseFormat* CEditorCommandSetBaseFormat::NewL(
+ const TRepositories& aReps,
+ const TTmCharFormat& aCharFormat, const RTmParFormat& aParFormat,
+ MUnifiedEditor& aTarget)
+ {
+ CEditorCommandSetBaseFormat* r
+ = new(ELeave) CEditorCommandSetBaseFormat(aReps, aTarget);
+ CleanupStack::PushL(r);
+ r->iChar.TakeCopyL(&aCharFormat);
+ r->iPar.TakeCopyL(&aParFormat);
+ CleanupStack::Pop();
+ return r;
+ }
+
+CEditorCommandSetBaseFormat* CEditorCommandSetBaseFormat::NewL(
+ const TRepositories& aReps, MUnifiedEditor& aTarget)
+ {
+ TTmCharFormat c;
+ RTmParFormat p;
+ CleanupClosePushL(p);
+ aTarget.GetBaseFormatL(c, p);
+ CEditorCommandSetBaseFormat* r = NewL(aReps, c, p, aTarget);
+ CleanupStack::PopAndDestroy();
+ return r;
+ }
+
+CCommand* CEditorCommandSetBaseFormat::CreateInverseL() const
+ {
+ return NewL(iRepositories, iTarget);
+ }
+
+TInt CEditorCommandSetBaseFormat::ExecuteL() const
+ {
+ iTarget.SetBaseFormatL(*iChar.Peek(), *iPar.Peek());
+ return KErrNone;
+ }
+
+/////////////////////////////////
+// //
+// CEditorCommandRenameStyle //
+// //
+/////////////////////////////////
+
+CEditorCommandRenameStyle::~CEditorCommandRenameStyle()
+ {
+ iOldName.Close();
+ iNewName.Close();
+ }
+
+CEditorCommandRenameStyle* CEditorCommandRenameStyle::NewL(
+ const TRepositories& aReps,
+ const TDesC& aOldName, const TDesC& aNewName, MUnifiedEditor& aTarget)
+ {
+ CEditorCommandRenameStyle* r =
+ new(ELeave) CEditorCommandRenameStyle(aReps, aTarget);
+ CleanupStack::PushL(r);
+ r->iOldName.TakeCopyL(&aOldName);
+ r->iNewName.TakeCopyL(&aNewName);
+ CleanupStack::Pop(r);
+ return r;
+ }
+
+CCommand* CEditorCommandRenameStyle::CreateInverseL() const
+ {
+ return NewL(iRepositories, *iNewName.Peek(), *iOldName.Peek(), iTarget);
+ }
+
+TInt CEditorCommandRenameStyle::ExecuteL() const
+ {
+ MUnifiedEditor::MStyleSupport* si = iTarget.StyleSupport();
+ ASSERT(si);
+ return si->RenameStyleL(*iOldName.Peek(), *iNewName.Peek());
+ }
+
+///////////////////////////////////
+// //
+// CEditorCommandInsertPicture //
+// //
+///////////////////////////////////
+
+CEditorCommandInsertPicture::~CEditorCommandInsertPicture()
+ {
+ if (iPictureOwner)
+ iPictureOwner->ForgetDelegate();
+ iPicture.DeletePicture();
+ }
+
+CEditorCommandInsertPicture* CEditorCommandInsertPicture::NewL(
+ const TRepositories& aReps,
+ TInt aPos, MPictureOwner& aPictureOwner, MUnifiedEditor& aTarget)
+ {
+ CEditorCommandInsertPicture* r = new(ELeave)
+ CEditorCommandInsertPicture(aReps, aTarget);
+ r->iPictureOwner = &aPictureOwner;
+ r->iPos = aPos;
+ return r;
+ }
+
+void CEditorCommandInsertPicture::TakePictureOwnership(TPictureHeader& aPic)
+ {
+ iPicture = aPic;
+ iPictureOwner = 0;
+ }
+
+void CEditorCommandInsertPicture::ForgetOwner(MPictureOwner*
+#ifdef _DEBUG
+ aOwner
+#endif
+ )
+ {
+ ASSERT(aOwner == iPictureOwner);
+ iPictureOwner = 0;
+ }
+
+CCommand* CEditorCommandInsertPicture::CreateInverseL() const
+ {
+ return CEditorCommandDeletePicture::NewL(iRepositories, iPos, iTarget);
+ }
+
+TInt CEditorCommandInsertPicture::ExecuteL() const
+ {
+ ASSERT(iPictureOwner == 0);
+ MUnifiedEditor::MPictureSupport* pi = iTarget.PictureSupport();
+ ASSERT(pi);
+ pi->InsertPictureL(iPos, iPicture);
+ iPicture.iPicture = 0;
+ iPicture.iPictureType = KNullUid;
+ return KErrNone;
+ }
+
+
+///////////////////////////////////
+// //
+// CEditorCommandDeletePicture //
+// //
+///////////////////////////////////
+
+CEditorCommandDeletePicture::~CEditorCommandDeletePicture()
+ {
+ if (iPictureOwnerDelegate)
+ iPictureOwnerDelegate->ForgetOwner(this);
+ }
+
+void CEditorCommandDeletePicture::ForgetDelegate()
+ {
+ iPictureOwnerDelegate = 0;
+ }
+
+CEditorCommandDeletePicture* CEditorCommandDeletePicture::NewL(
+ const TRepositories& aReps, TInt aPos, MUnifiedEditor& aTarget)
+ {
+ CEditorCommandDeletePicture* r =
+ new(ELeave) CEditorCommandDeletePicture(aReps, aTarget);
+ r->iPos = aPos;
+ return r;
+ }
+
+CCommand* CEditorCommandDeletePicture::CreateInverseL() const
+ {
+ CEditorCommandDeletePicture* nonConstThis =
+ const_cast<CEditorCommandDeletePicture*>(this); //yuck
+ CEditorCommandInsertPicture* inv =
+ CEditorCommandInsertPicture::NewL(iRepositories, iPos,
+ *nonConstThis, iTarget);
+ CleanupStack::PushL(inv);
+
+ if (iPictureOwnerDelegate)
+ iPictureOwnerDelegate->ForgetOwner(nonConstThis);
+
+ iPictureOwnerDelegate = inv;
+ CleanupStack::Pop(inv);
+
+ return inv;
+ }
+
+TInt CEditorCommandDeletePicture::ExecuteL() const
+ {
+ MUnifiedEditor::MPictureSupport* pi = iTarget.PictureSupport();
+ ASSERT(pi);
+ TPictureHeader pic;
+ pi->Picture(iPos, pic);
+ pi->DropPictureL(iPos);
+ if (iPictureOwnerDelegate)
+ {
+ iPictureOwnerDelegate->TakePictureOwnership(pic);
+ iPictureOwnerDelegate = 0;
+ }
+ else
+ pic.DeletePicture();
+ return KErrNone;
+ }
+
+/////////////////////////////////
+// //
+// CEditorCommandCreateStyle //
+// //
+/////////////////////////////////
+
+CEditorCommandCreateStyle* CEditorCommandCreateStyle::NewL(const TRepositories& aReps,
+ const TDesC& aName, const TDesC& aNext,
+ TTmCharFormat& aChar, TTmCharFormatMask aCharMask,
+ RTmParFormat& aPar, TTmParFormatMask aParMask,
+ TInt aLevel, MUnifiedEditor& aTarget)
+ {
+ CEditorCommandCreateStyle* p = new(ELeave) CEditorCommandCreateStyle(aReps, aTarget);
+ CleanupStack::PushL(p);
+ p->iName.TakeCopyL(&aName);
+ p->iNext.TakeCopyL(&aNext);
+ p->iChar.TakeCopyL(&aChar);
+ p->iCharMask = aCharMask;
+ p->iPar.TakeCopyL(&aPar);
+ p->iParMask = aParMask;
+ p->iLevel = aLevel;
+ CleanupStack::Pop(p);
+ return p;
+ }
+CEditorCommandCreateStyle* CEditorCommandCreateStyle::NewL(const TRepositories& aReps,
+ const TDesC& aName, MUnifiedEditor& aTarget)
+ {
+ RTmStyle style;
+ MUnifiedEditor::MStyleSupport* si = aTarget.StyleSupport();
+ ASSERT(si);
+ si->GetStyleByNameL(aName, style);
+ CleanupClosePushL(style);
+ CEditorCommandCreateStyle* p = NewL(aReps, aName, style.iNextStyleName,
+ style.iCharFormat.iFormat, style.iCharFormat.iMask,
+ style.iParFormat.iFormat, style.iParFormat.iMask,
+ style.iOutlineLevel, aTarget);
+ CleanupStack::PopAndDestroy();
+ return p;
+ }
+
+CCommand* CEditorCommandCreateStyle::NewBatchL(const TRepositories& aReps,
+ const TDesC& aName,
+ MUnifiedEditor& aTarget)
+ {
+ CCommand* inverse = 0;
+ MUnifiedEditor::MStyleSupport* si = aTarget.StyleSupport();
+ ASSERT(si);
+
+ TInt remainingLength = aTarget.DocumentLength();
+ TInt currentPosition = 0;
+ // got to be careful.. GetStyleL() can return KMaxTInt as the run length!
+ // luckily, any nonnegative TInt - KMaxTInt gives a negative TInt
+ while (0 < remainingLength)
+ {
+ TInt runLength;
+ TPtrC name;
+ si->GetStyle(currentPosition, name, runLength);
+ if (name == aName)
+ {
+ CleanupStack::PushL(inverse);
+ // coverity[double_free]
+ inverse = CoalesceL(inverse,
+ CEditorCommandSetStyle::NewL(aReps, aName,
+ currentPosition, runLength, aTarget));
+ CleanupStack::Pop();
+ }
+ currentPosition += runLength;
+ remainingLength -= runLength;
+ }
+
+ CleanupStack::PushL(inverse);
+ // coverity[double_free]
+ inverse = CoalesceL(inverse,
+ CEditorCommandCreateStyle::NewL(aReps, aName, aTarget));
+ CleanupStack::Pop();
+ return inverse;
+ }
+
+CEditorCommandCreateStyle::~CEditorCommandCreateStyle()
+ {
+ iName.Close();
+ iNext.Close();
+ iChar.Close();
+ iPar.Close();
+ }
+
+CCommand* CEditorCommandCreateStyle::CreateInverseL() const
+ {
+ return CEditorCommandDeleteStyle::NewL(iRepositories, *iName.Peek(), iTarget);
+ }
+
+TInt CEditorCommandCreateStyle::ExecuteL() const
+ {
+ RTmStyle style;
+ CleanupClosePushL(style);
+ style.iName = *iName.Peek();
+ style.iNextStyleName = *iNext.Peek();
+ style.iCharFormat.iFormat = *iChar.Peek();
+ style.iCharFormat.iMask = iCharMask;
+ style.iParFormat.iFormat.CopyL( *iPar.Peek() );
+ style.iParFormat.iMask.iFlags = iParMask.iFlags;
+ style.iOutlineLevel = iLevel;
+ MUnifiedEditor::MStyleSupport* si = iTarget.StyleSupport();
+ ASSERT(si);
+ TInt err = si->CreateStyleL(style);
+ CleanupStack::PopAndDestroy();
+ return err;
+ }
+
+/////////////////////////////////
+// //
+// CEditorCommandDeleteStyle //
+// //
+/////////////////////////////////
+
+CEditorCommandDeleteStyle* CEditorCommandDeleteStyle::NewL(const TRepositories& aReps,
+ const TDesC& aName, MUnifiedEditor& aTarget)
+ {
+ CEditorCommandDeleteStyle* p = new(ELeave) CEditorCommandDeleteStyle(aReps, aTarget);
+ CleanupStack::PushL(p);
+ p->iName.TakeCopyL(&aName);
+ CleanupStack::Pop(p);
+ return p;
+ }
+
+CEditorCommandDeleteStyle::~CEditorCommandDeleteStyle()
+ {
+ iName.Close();
+ }
+
+CCommand* CEditorCommandDeleteStyle::CreateInverseL() const
+ {
+ return CEditorCommandCreateStyle::NewBatchL(iRepositories, *iName.Peek(), iTarget);
+ }
+
+TInt CEditorCommandDeleteStyle::ExecuteL() const
+ {
+ MUnifiedEditor::MStyleSupport* si = iTarget.StyleSupport();
+ ASSERT(si);
+ return si->DeleteStyleL(*iName.Peek());
+ }
+
+////////////////////////////////
+// //
+// CEditorCommandAlterStyle //
+// //
+////////////////////////////////
+
+CEditorCommandAlterStyle* CEditorCommandAlterStyle::NewL(const TRepositories& aReps,
+ const TDesC& aName, const TDesC& aNext,
+ TTmCharFormat& aChar, TTmCharFormatMask& aCharMask,
+ RTmParFormat& aPar, TTmParFormatMask& aParMask,
+ TInt aLevel, MUnifiedEditor& aTarget)
+ {
+ CEditorCommandAlterStyle* p = new(ELeave) CEditorCommandAlterStyle(aReps, aTarget);
+ CleanupStack::PushL(p);
+ p->iName.TakeCopyL(&aName);
+ p->iNext.TakeCopyL(&aNext);
+ p->iChar.TakeCopyL(&aChar);
+ p->iCharMask = aCharMask;
+ p->iPar.TakeCopyL(&aPar);
+ p->iParMask = aParMask;
+ p->iLevel = aLevel;
+ CleanupStack::Pop(p);
+ return p;
+ }
+
+CEditorCommandAlterStyle* CEditorCommandAlterStyle::NewL(const TRepositories& aReps,
+ const TDesC& aName, MUnifiedEditor& aTarget)
+ {
+ RTmStyle style;
+ CleanupClosePushL(style);
+ MUnifiedEditor::MStyleSupport* si = aTarget.StyleSupport();
+ ASSERT(si);
+ si->GetStyleByNameL(aName, style);
+ CEditorCommandAlterStyle* p = NewL(aReps, aName, style.iNextStyleName,
+ style.iCharFormat.iFormat, style.iCharFormat.iMask,
+ style.iParFormat.iFormat, style.iParFormat.iMask,
+ style.iOutlineLevel, aTarget);
+ CleanupStack::PopAndDestroy();
+ return p;
+ }
+
+CEditorCommandAlterStyle::~CEditorCommandAlterStyle()
+ {
+ iName.Close();
+ iNext.Close();
+ iChar.Close();
+ iPar.Close();
+ }
+
+CCommand* CEditorCommandAlterStyle::CreateInverseL() const
+ {
+ return NewL(iRepositories, *iName.Peek(), iTarget);
+ }
+
+TInt CEditorCommandAlterStyle::ExecuteL() const
+ {
+ RTmStyle style;
+ CleanupClosePushL(style);
+ MUnifiedEditor::MStyleSupport* si = iTarget.StyleSupport();
+ ASSERT(si);
+ si->GetStyleByNameL(*iName.Peek(), style);
+ style.iCharFormat.iFormat = *iChar.Peek();
+ style.iCharFormat.iMask = iCharMask;
+ style.iParFormat.iFormat.CopyL( *iPar.Peek() );
+ style.iParFormat.iMask = iParMask;
+ style.iOutlineLevel = iLevel;
+ style.iName = *iName.Peek();
+ style.iNextStyleName = *iNext.Peek();
+ TInt err = si->ChangeStyleL(style);
+ CleanupStack::PopAndDestroy();
+ return err;
+ }
+
+//////////////////////////////
+// //
+// CEditorCommandSetStyle //
+// //
+//////////////////////////////
+
+CEditorCommandSetStyle::~CEditorCommandSetStyle()
+ {
+ iName.Close();
+ }
+
+CEditorCommandSetStyle* CEditorCommandSetStyle::NewL(const TRepositories& aReps,
+ const TDesC& aName, TInt aPos, TInt aRunLength, MUnifiedEditor& aTarget)
+ {
+ CEditorCommandSetStyle* r = new (ELeave) CEditorCommandSetStyle(aReps, aTarget);
+ CleanupStack::PushL(r);
+ r->iName.TakeCopyL(&aName);
+ r->iPos = aPos;
+ r->iRunLength = aRunLength;
+ CleanupStack::Pop(r);
+ return r;
+ }
+
+CCommand* CEditorCommandSetStyle::NewL(
+ const TRepositories& aReps, TInt aPos, TInt aRunLength, MUnifiedEditor& aTarget)
+ {
+ CCommand* inverse = 0;
+ MUnifiedEditor::MStyleSupport* si = aTarget.StyleSupport();
+ ASSERT(si);
+ while (0 < aRunLength)
+ {
+ TPtrC name;
+ TInt runLength;
+ si->GetStyle(aPos, name, runLength);
+ if (aRunLength < runLength)
+ runLength = aRunLength;
+ CleanupStack::PushL(inverse);
+ // coverity[double_free]
+ inverse = CoalesceL(inverse, NewL(aReps, name, aPos, runLength, aTarget));
+ CleanupStack::Pop();
+ aPos += runLength;
+ aRunLength -= runLength;
+ }
+ return inverse;
+ }
+
+CCommand* CEditorCommandSetStyle::CreateInverseL() const
+ {
+ return NewL(iRepositories, iPos, iRunLength, iTarget);
+ }
+
+TInt CEditorCommandSetStyle::ExecuteL() const
+ {
+ MUnifiedEditor::MStyleSupport* si = iTarget.StyleSupport();
+ ASSERT(si);
+ return si->SetStyleL(iPos, iRunLength, *iName.Peek());
+ }
+
+////////////////////////////////
+// //
+// CEditorCommandDeleteText //
+// //
+////////////////////////////////
+
+CEditorCommandDeleteText::~CEditorCommandDeleteText() {}
+
+CEditorCommandDeleteText* CEditorCommandDeleteText::NewL(const TRepositories& aReps,
+ TInt aPos, TInt aLength, MUnifiedEditor& aTarget)
+ {
+ return new(ELeave) CEditorCommandDeleteText(aReps,
+ aTarget, aPos, aLength);
+ }
+
+CCommand* CEditorCommandDeleteText::CreateInverseL() const
+ {
+ return CEditorCommandInsertTextAndFormat::NewBatchL(
+ iRepositories, iImpl.Pos(), iImpl.Length(), iImpl.Target());
+ }
+
+TInt CEditorCommandDeleteText::ExecuteL() const
+ {
+ return iImpl.ExecuteL();
+ }
+
+TBool CEditorCommandDeleteText::CanAdd(TInt aPos, TInt aLength, MUnifiedEditor& aTarget) const
+ {
+ return iImpl.CanAdd(aPos, aLength, aTarget);
+ }
+
+void CEditorCommandDeleteText::Add(TInt aLength)
+ {
+ iImpl.Add(aLength);
+ }
+
+/////////////////////////////////////////
+// //
+// CEditorCommandInsertTextAndFormat //
+// //
+/////////////////////////////////////////
+
+CEditorCommandInsertTextAndFormat::~CEditorCommandInsertTextAndFormat()
+ {
+ iChar.Close();
+ iPar.Close();
+ iStyle.Close();
+ }
+
+CEditorCommandInsertTextAndFormat* CEditorCommandInsertTextAndFormat::NewL(
+ const TRepositories& aReps,
+ CEditorCommandInsertTextAndFormat::RTextAndFormatParameters& aParams,
+ MUnifiedEditor& aTarget)
+ {
+ ASSERT(aParams.iText.Length() <= KMaxCharsInSingleCommand);
+ CEditorCommandInsertTextAndFormat* r = new(ELeave)
+ CEditorCommandInsertTextAndFormat(aReps, aTarget, aParams.iPos, aParams.iText);
+ CleanupStack::PushL(r);
+ r->iChar.TakeCopyL(&aParams.iChar.iFormat);
+ r->iCharMask = aParams.iChar.iMask;
+ r->iPar.TakeCopyL(&aParams.iPar.iFormat);
+ r->iParMask.iFlags = aParams.iPar.iMask.iFlags;
+ r->iStyle.TakeCopyL(&aParams.iStyleName);
+ CleanupStack::Pop(r);
+ return r;
+ }
+
+void CEditorCommandInsertTextAndFormat::RTextAndFormatParameters::Close()
+ {
+ iPar.Close();
+ }
+
+void CEditorCommandInsertTextAndFormat::RTextAndFormatParameters::SetL(
+ TInt aPos, TInt aMaxLength, MUnifiedEditor& aTarget)
+ {
+ iPos = aPos;
+ aTarget.GetText(aPos, iText);
+
+ TInt length = iText.Length();
+
+ TInt charLength;
+ aTarget.GetCharFormat(aPos, MUnifiedEditor::ESpecific, iChar, charLength);
+
+ TInt parLength;
+ aTarget.GetParFormatL(aPos, MUnifiedEditor::ESpecific, iPar, parLength);
+
+ TInt styleLength = length;
+ MUnifiedEditor::MStyleSupport* si = aTarget.StyleSupport();
+ if (si)
+ si->GetStyle(aPos, iStyleName, styleLength);
+ else
+ iStyleName.Set(TPtrC());
+
+ if (charLength < length)
+ length = charLength;
+ if (parLength < length)
+ length = parLength;
+ if (styleLength < length)
+ length = styleLength;
+ if (aMaxLength < length)
+ length = aMaxLength;
+ if (KMaxCharsInSingleCommand < length)
+ length = KMaxCharsInSingleCommand;
+ iText.Set(iText.Ptr(), length);
+ }
+
+CEditorCommandInsertTextAndFormat* CEditorCommandInsertTextAndFormat::NewL(
+ const TRepositories& aReps, TInt aPos, TInt& aRemaining,
+ TInt aOriginalPos, MUnifiedEditor& aTarget)
+ {
+ RTextAndFormatParameters params;
+ CleanupClosePushL(params);
+ params.SetL(aPos, aRemaining, aTarget);
+
+ params.iPos = aOriginalPos;
+ CEditorCommandInsertTextAndFormat* p = NewL(aReps, params, aTarget);
+ aRemaining -= params.iText.Length();
+
+ CleanupStack::PopAndDestroy();
+
+ return p;
+ }
+
+CCommand* CEditorCommandInsertTextAndFormat::NewBatchL(const TRepositories& aReps,
+ TInt aPos, TInt aLength, MUnifiedEditor& aTarget)
+ {
+ CCommand* command = 0;
+ TInt oldLength = aLength + 1;
+ TInt end = aPos + aLength;
+ // while there is still some length to go and there is still some
+ // text to be got
+ while (0 < aLength && aLength < oldLength)
+ {
+ oldLength = aLength;
+ CleanupStack::PushL(command);
+ // coverity[double_free]
+ command = CoalesceL(command,
+ NewL(aReps, end - aLength, aLength, aPos, aTarget));
+ CleanupStack::Pop();
+ }
+
+ return command;
+ }
+
+CCommand* CEditorCommandInsertTextAndFormat::CreateInverseL() const
+ {
+ return CEditorCommandDeleteText::NewL(iRepositories,
+ iImpl.Pos(), iImpl.Text().Length(), iImpl.Target());
+ }
+
+TInt CEditorCommandInsertTextAndFormat::ExecuteL() const
+ {
+ TTmCharFormatLayer charLayer;
+ RTmParFormatLayer parLayer;
+
+ TTmCharFormatLayer* pCharLayer = 0;
+ RTmParFormatLayer* pParLayer = 0;
+
+ if (iChar.Peek())
+ {
+ charLayer.iFormat = *iChar.Peek();
+ charLayer.iMask = iCharMask;
+ pCharLayer = &charLayer;
+ }
+ if (iPar.Peek())
+ {
+ parLayer.iFormat.CopyL( *iPar.Peek() );
+ parLayer.iMask = iParMask;
+ pParLayer = &parLayer;
+ CleanupClosePushL(parLayer);
+ }
+ TInt result = iImpl.ExecuteL(iStyle.Peek(), pCharLayer, pParLayer);
+ if (pParLayer)
+ CleanupStack::PopAndDestroy();
+ return result;
+ }
+
+TBool CEditorCommandInsertTextAndFormat::CanAdd(
+ const CEditorCommandInsertTextAndFormat::RTextAndFormatParameters& aParams,
+ MUnifiedEditor& aTarget) const
+ {
+ if (!iImpl.CanAdd(aParams.iPos, aParams.iText, aTarget))
+ return EFalse;
+ if (!iChar.Peek())
+ return EFalse;
+ if (!iPar.Peek())
+ return EFalse;
+ if (!iStyle.Peek())
+ return EFalse;
+ if (aParams.iStyleName != *iStyle.Peek())
+ return EFalse;
+ if (aParams.iPar.iMask.iFlags != iParMask.iFlags
+ || aParams.iPar.iFormat != *iPar.Peek())
+ return EFalse;
+ if (iCharMask.iFlags != aParams.iChar.iMask.iFlags
+ || aParams.iChar.iFormat != *iChar.Peek())
+ return EFalse;
+ // coalescence is not possible if the new text contains pictures.
+ if (0 <= UndoSystem::FindPicture(aTarget, aParams.iPos, aParams.iText.Length()))
+ return EFalse;
+ return ETrue;
+ }
+
+void CEditorCommandInsertTextAndFormat::Add(TInt aPos, const TDesC& aText)
+ {
+ iImpl.Add(aPos, aText);
+ }
+
+///////////////////////////////////
+// //
+// CEditorCommandSetCharFormat //
+// //
+///////////////////////////////////
+
+CEditorCommandSetCharFormat::~CEditorCommandSetCharFormat()
+ {
+ iChar.Close();
+ }
+
+CEditorCommandSetCharFormat* CEditorCommandSetCharFormat::NewL(
+ const TRepositories& aReps, TInt aPos, TInt aLength,
+ const TTmCharFormat* aChar, TTmCharFormatMask aCharMask,
+ MUnifiedEditor& aTarget)
+ {
+ CEditorCommandSetCharFormat* r = new(ELeave) CEditorCommandSetCharFormat(aReps, aTarget);
+ CleanupStack::PushL(r);
+ r->iPos = aPos;
+ r->iLength = aLength;
+ r->iChar.TakeCopyL(aChar);
+ r->iCharMask= aCharMask;
+ CleanupStack::Pop(r);
+ return r;
+ }
+
+// get as much of a run as possible.
+CEditorCommandSetCharFormat* CEditorCommandSetCharFormat::NewL(const TRepositories& aReps,
+ TInt aPos, TInt& aRemaining, MUnifiedEditor& aTarget)
+ {
+ TTmCharFormatLayer format;
+ TInt length;
+ aTarget.GetCharFormat(aPos, MUnifiedEditor::ESpecific, format, length);
+ if (aRemaining < length)
+ length = aRemaining;
+ CEditorCommandSetCharFormat* r =
+ NewL(aReps, aPos, length, &format.iFormat, format.iMask, aTarget);
+ aRemaining -= length;
+ return r;
+ }
+
+// get as many runs as necessary and return a batch if necessary.
+CCommand* CEditorCommandSetCharFormat::NewBatchL(const TRepositories& aReps,
+ TInt aPos, TInt aLength, MUnifiedEditor& aTarget)
+ {
+ CCommand* command = 0;
+ TInt oldLength = aLength + 1;
+ TInt end = aPos + aLength;
+ while (0 < aLength && aLength < oldLength)
+ {
+ oldLength = aLength;
+ CleanupStack::PushL(command);
+ // coverity[double_free]
+ command = CoalesceL(command, NewL(aReps, end - aLength, aLength, aTarget));
+ CleanupStack::Pop(); // command, as was before call to CoalesceL
+ }
+ return command;
+ }
+
+CCommand* CEditorCommandSetCharFormat::CreateInverseL() const
+ {
+ return CEditorCommandDeleteCharFormat::NewL(iRepositories, iPos, iLength, iTarget);
+ }
+
+TInt CEditorCommandSetCharFormat::ExecuteL() const
+ {
+ TTmCharFormatLayer layer;
+ layer.iFormat = *iChar.Peek();
+ layer.iMask = iCharMask;
+ iTarget.SetCharFormatL(iPos, iLength, layer);
+ return 0;
+ }
+
+TBool CEditorCommandSetCharFormat::PrepareToAddInverseToLastL(CSingleCommand& aLastCommand) const
+ {
+ if (aLastCommand.FamilyUid() != TUid::Uid(KUndoDllUid))
+ return EFalse;
+ CEditorCommandDeleteCharFormat* last =
+ static_cast<CEditorCommand&>(aLastCommand).CastToCEditorCommandDeleteCharFormat();
+ if (!last)
+ return EFalse;
+ return last->CanAdd(iPos, iLength, iTarget);
+ }
+
+void CEditorCommandSetCharFormat::AddInverseToLast(CSingleCommand& aLastCommand) const
+ {
+ ASSERT(aLastCommand.FamilyUid() == TUid::Uid(KUndoDllUid));
+ CEditorCommandDeleteCharFormat* last =
+ static_cast<CEditorCommand&>(aLastCommand).CastToCEditorCommandDeleteCharFormat();
+ ASSERT(last);
+ last->Add(iPos, iLength);
+ }
+
+//////////////////////////////////
+// //
+// CEditorCommandSetParFormat //
+// //
+//////////////////////////////////
+
+CEditorCommandSetParFormat::~CEditorCommandSetParFormat()
+ {
+ iPar.Close();
+ }
+
+CEditorCommandSetParFormat* CEditorCommandSetParFormat::NewL(
+ const TRepositories& aReps, TInt aPos, TInt aLength,
+ const RTmParFormat* aFormat, TTmParFormatMask aMask,
+ MUnifiedEditor& aTarget)
+ {
+ CEditorCommandSetParFormat* r = new(ELeave) CEditorCommandSetParFormat(aReps, aTarget);
+ CleanupStack::PushL(r);
+ r->iPos = aPos;
+ r->iLength = aLength;
+ r->iPar.TakeCopyL(aFormat);
+ r->iParMask= aMask;
+ CleanupStack::Pop(r);
+ return r;
+ }
+
+// get as much of a run as possible.
+CEditorCommandSetParFormat* CEditorCommandSetParFormat::NewL(const TRepositories& aReps,
+ TInt aPos, TInt& aRemaining, MUnifiedEditor& aTarget)
+ {
+ RTmParFormatLayer format;
+ TInt length;
+ CleanupClosePushL(format);
+ aTarget.GetParFormatL(aPos, MUnifiedEditor::ESpecific, format, length);
+ if (aRemaining < length)
+ length = aRemaining;
+ CEditorCommandSetParFormat* r =
+ NewL(aReps, aPos, length, &format.iFormat, format.iMask, aTarget);
+ aRemaining -= length;
+ CleanupStack::PopAndDestroy(); // format
+ return r;
+ }
+
+// get as many runs as necessary and return a batch if necessary.
+CCommand* CEditorCommandSetParFormat::NewBatchL(const TRepositories& aReps,
+ TInt aPos, TInt aLength, MUnifiedEditor& aTarget)
+ {
+ CCommand* command = 0;
+ TInt oldLength = aLength + 1;
+ TInt end = aPos + aLength;
+ while (0 < aLength && aLength < oldLength)
+ {
+ oldLength = aLength;
+ CleanupStack::PushL(command);
+ // coverity[double_free]
+ command = CoalesceL(command, NewL(aReps, end - aLength, aLength, aTarget));
+ CleanupStack::Pop(); // command, as was before call to CoalesceL
+ }
+ return command;
+ }
+
+CCommand* CEditorCommandSetParFormat::CreateInverseL() const
+ {
+ return CEditorCommandDeleteParFormat::NewL(iRepositories, iPos, iLength, iTarget);
+ }
+
+TInt CEditorCommandSetParFormat::ExecuteL() const
+ {
+ RTmParFormatLayer layer;
+ CleanupClosePushL(layer);
+ layer.iFormat.CopyL(*iPar.Peek());
+ layer.iMask = iParMask;
+ iTarget.SetParFormatL(iPos, iLength, layer);
+ CleanupStack::PopAndDestroy();
+ return 0;
+ }
+
+TBool CEditorCommandSetParFormat::PrepareToAddInverseToLastL(CSingleCommand& aLastCommand) const
+ {
+ if (aLastCommand.FamilyUid() != TUid::Uid(KUndoDllUid))
+ return EFalse;
+ CEditorCommandDeleteParFormat* last =
+ static_cast<CEditorCommand&>(aLastCommand).CastToCEditorCommandDeleteParFormat();
+ if (!last)
+ return EFalse;
+ return last->CanAdd(iPos, iLength, iTarget);
+ }
+
+void CEditorCommandSetParFormat::AddInverseToLast(CSingleCommand& aLastCommand) const
+ {
+ ASSERT(aLastCommand.FamilyUid() == TUid::Uid(KUndoDllUid));
+ CEditorCommandDeleteParFormat* last =
+ static_cast<CEditorCommand&>(aLastCommand).CastToCEditorCommandDeleteParFormat();
+ ASSERT(last);
+ last->Add(iPos, iLength);
+ }
+
+//////////////////////////////////////
+// //
+// CEditorCommandDeleteCharFormat //
+// //
+//////////////////////////////////////
+
+CEditorCommandDeleteCharFormat::~CEditorCommandDeleteCharFormat() {}
+
+CEditorCommandDeleteCharFormat* CEditorCommandDeleteCharFormat::NewL(
+ const TRepositories& aReps, TInt aPos, TInt aLength, MUnifiedEditor& aTarget)
+ {
+ CEditorCommandDeleteCharFormat* r =
+ new(ELeave) CEditorCommandDeleteCharFormat(aReps, aTarget);
+ r->iPos = aPos;
+ r->iLength = aLength;
+ return r;
+ }
+
+CCommand* CEditorCommandDeleteCharFormat::CreateInverseL() const
+ {
+ return CEditorCommandSetCharFormat::NewBatchL(iRepositories, iPos, iLength, iTarget);
+ }
+
+TInt CEditorCommandDeleteCharFormat::ExecuteL() const
+ {
+ iTarget.DeleteCharFormatL(iPos, iLength);
+ return KErrNone;
+ }
+
+TBool CEditorCommandDeleteCharFormat::CanAdd(TInt aPos, TInt aLength, MUnifiedEditor &aTarget) const
+ {
+ return &aTarget == &iTarget
+ && aPos <= iPos + iLength
+ && iPos <= aPos + aLength? ETrue : EFalse;
+ }
+
+void CEditorCommandDeleteCharFormat::Add(TInt aPos, TInt aLength)
+ {
+ TInt min = aPos < iPos? aPos : iPos;
+ TInt max = iPos + iLength;
+ TInt max2= aPos + aLength;
+ iPos = min;
+ iLength = (max < max2? max2 : max) - min;
+ }
+
+/////////////////////////////////////
+// //
+// CEditorCommandDeleteParFormat //
+// //
+/////////////////////////////////////
+
+CEditorCommandDeleteParFormat::~CEditorCommandDeleteParFormat() {}
+
+CEditorCommandDeleteParFormat* CEditorCommandDeleteParFormat::NewL(
+ const TRepositories& aReps, TInt aPos, TInt aLength, MUnifiedEditor& aTarget)
+ {
+ CEditorCommandDeleteParFormat* r =
+ new(ELeave) CEditorCommandDeleteParFormat(aReps, aTarget);
+ r->iPos = aPos;
+ r->iLength = aLength;
+ return r;
+ }
+
+CCommand* CEditorCommandDeleteParFormat::CreateInverseL() const
+ {
+ return CEditorCommandSetParFormat::NewBatchL(iRepositories, iPos, iLength, iTarget);
+ }
+
+TInt CEditorCommandDeleteParFormat::ExecuteL() const
+ {
+ iTarget.DeleteParFormatL(iPos, iLength);
+ return KErrNone;
+ }
+
+TBool CEditorCommandDeleteParFormat::CanAdd(TInt aPos, TInt aLength, MUnifiedEditor& aTarget) const
+ {
+ return &aTarget == &iTarget
+ && aPos <= iPos + iLength
+ && iPos <= aPos + aLength? ETrue : EFalse;
+ }
+
+void CEditorCommandDeleteParFormat::Add(TInt aPos, TInt aLength)
+ {
+ TInt min = aPos < iPos? aPos : iPos;
+ TInt max = iPos + iLength;
+ TInt max2= aPos + aLength;
+ iPos = min;
+ iLength = (max < max2? max2 : max) - min;
+ }
+
+//////////////////////////
+// //
+// Command prototypes //
+// //
+//////////////////////////
+
+//
+// Attribute setters
+//
+void CEditorCommandCreateStyleProto::Set(const RTmStyle& aStyle)
+ {
+ iStyle = &aStyle;
+ }
+
+void CEditorCommandChangeStyleProto::Set(const RTmStyle& aStyle)
+ {
+ iStyle = &aStyle;
+ }
+
+void CEditorCommandSetStyleProto::Set(TInt aPos,
+ TInt aLength,
+ const TDesC& aName)
+ {
+ iPos = aPos;
+ iLength = aLength;
+ iName = &aName;
+ }
+
+void CEditorCommandDeleteStyleProto::Set(const TDesC& aName)
+ {
+ iName = &aName;
+ }
+
+void CEditorCommandSetCharFormatProto::Set(TInt aPos,
+ TInt aLength,
+ const TTmCharFormatLayer& aFormat)
+ {
+ iPos = aPos;
+ iLength = aLength;
+ iFormat = &aFormat;
+ }
+
+void CEditorCommandSetParFormatProto::Set(TInt aPos,
+ TInt aLength,
+ const RTmParFormatLayer& aFormat)
+ {
+ iPos = aPos;
+ iLength = aLength;
+ iFormat = &aFormat;
+ }
+
+void CEditorCommandInsertProto::Set(TInt aPos,
+ const TDesC& aText,
+ const TDesC* aStyle,
+ const TTmCharFormatLayer* aCharFormat,
+ const RTmParFormatLayer* aParFormat)
+ {
+ iPos = aPos;
+ iText = &aText;
+ iStyle = aStyle;
+ iCharFormat = aCharFormat;
+ iParFormat = aParFormat;
+ }
+
+void CEditorCommandDeleteProto::Set(TInt aPos, TInt aLength)
+ {
+ iPos = aPos;
+ iLength = aLength;
+
+ // adjust 'iPos' and 'iLength' to be surrogate aligned, if possible
+ if (iPos >= 0 && iPos <= iTarget.DocumentLength())
+ {
+ // check the character at aPos
+ TBuf<2> dest;
+ iTarget.GetText(iPos, dest);
+ if (dest.Length() > 0 && IsLowSurrogate(dest[0]))
+ {
+ // try to decrease aPos by 1
+ if (iPos > 0)
+ {
+ iTarget.GetText(iPos-1, dest);
+ if (dest.Length() > 0 && IsHighSurrogate(dest[0]))
+ {
+ iPos--;
+ iLength++;
+ }
+ else
+ {
+ // do nothing, just delete the corrupt surrogate
+ }
+ }
+ else
+ {
+ // do nothing
+ }
+ }
+ }
+
+ if (iLength > 0)
+ {
+ // check the character at aPos+aLength
+ TBuf<2> dest;
+ iTarget.GetText(iPos+iLength-1, dest);
+ if (dest.Length() > 0 && IsHighSurrogate(dest[0]))
+ {
+ if (iPos + (iLength - 1) <= iTarget.DocumentLength())
+ {
+ // try to increase aLength by 1
+ iTarget.GetText(iPos+iLength, dest);
+ if (dest.Length() > 0 && IsLowSurrogate(dest[0]))
+ {
+ iLength++;
+ }
+ else
+ {
+ // do nothing
+ }
+ }
+ else
+ {
+ // do nothing
+ }
+ }
+ }
+ }
+
+void CEditorCommandDeleteCharFormatProto::Set(TInt aPos, TInt aLength)
+ {
+ iPos = aPos;
+ iLength = aLength;
+ }
+
+void CEditorCommandDeleteParFormatProto::Set(TInt aPos, TInt aLength)
+ {
+ iPos = aPos;
+ iLength = aLength;
+ }
+
+void CEditorCommandDeletePictureProto::Set(TInt aPos)
+ {
+ iPos = aPos;
+ }
+
+void CEditorCommandDestroyPictureProto::Set(TInt aPos)
+ {
+ if (iPictureOwnerDelegate)
+ {
+ iPictureOwnerDelegate->ForgetOwner(this);
+ iPictureOwnerDelegate = 0;
+ }
+ iPos = aPos;
+ }
+
+void CEditorCommandInsertPictureProto::Set(TInt aPos, const TPictureHeader& aPicture)
+ {
+ iPos = aPos;
+ iPicture = &aPicture;
+ }
+
+void CEditorCommandRenameStyleProto::Set(const TDesC& aOldName, const TDesC& aNewName)
+ {
+ iOldName = &aOldName;
+ iNewName = &aNewName;
+ }
+
+void CEditorCommandSetBaseFormatProto::Set(
+ const TTmCharFormat* aCharFormat, const RTmParFormat* aParFormat)
+ {
+ iChar = aCharFormat;
+ iPar = aParFormat;
+ }
+
+void CEditorCommandPasteProto::Set(const CStreamStore& aStore,
+ const CStreamDictionary& aStreamDictionary, TInt aPos)
+ {
+ iImpl.Set(aStore, aStreamDictionary, aPos);
+ }
+
+//
+// execution and inversion
+//
+
+// CEditorCommandCreateStyleProto
+TInt CEditorCommandCreateStyleProto::ExecuteL() const
+ {
+ MUnifiedEditor::MStyleSupport* si = iTarget.StyleSupport();
+ ASSERT(si);
+ return si->CreateStyleL(*iStyle);
+ }
+
+CCommand* CEditorCommandCreateStyleProto::CreateInverseL() const
+ {
+ return CEditorCommandDeleteStyle::NewL(Repositories(), iStyle->iName, iTarget);
+ }
+
+
+// CEditorCommandChangeStyleProto
+TInt CEditorCommandChangeStyleProto::ExecuteL() const
+ {
+ MUnifiedEditor::MStyleSupport* si = iTarget.StyleSupport();
+ ASSERT(si);
+ return si->ChangeStyleL(*iStyle);
+ }
+
+CCommand* CEditorCommandChangeStyleProto::CreateInverseL() const
+ {
+ return CEditorCommandAlterStyle::NewL(Repositories(), iStyle->iName, iTarget);
+ }
+
+// CEditorCommandSetStyleProto
+TInt CEditorCommandSetStyleProto::ExecuteL() const
+ {
+ MUnifiedEditor::MStyleSupport* si = iTarget.StyleSupport();
+ ASSERT(si);
+ return si->SetStyleL(iPos, iLength, *iName);
+ }
+
+CCommand* CEditorCommandSetStyleProto::CreateInverseL() const
+ {
+ return CEditorCommandSetStyle::NewL(Repositories(), iPos, iLength, iTarget);
+ }
+
+// CEditorCommandDeleteStyleProto
+TInt CEditorCommandDeleteStyleProto::ExecuteL() const
+ {
+ MUnifiedEditor::MStyleSupport* si = iTarget.StyleSupport();
+ ASSERT(si);
+ return si->DeleteStyleL(*iName);
+ }
+
+CCommand* CEditorCommandDeleteStyleProto::CreateInverseL() const
+ {
+ return CEditorCommandCreateStyle::NewBatchL(Repositories(), *iName, iTarget);
+ }
+
+// CEditorCommandSetCharFormatProto
+TInt CEditorCommandSetCharFormatProto::ExecuteL() const
+ {
+ iTarget.SetCharFormatL(iPos, iLength, *iFormat);
+ return KErrNone;
+ }
+
+CCommand* CEditorCommandSetCharFormatProto::CreateInverseL() const
+ {
+ // inverse is to remove formatting and re-apply the old
+ CCommand* inverse =
+ CEditorCommandSetCharFormat::NewBatchL(Repositories(),
+ iPos, iLength, iTarget);
+ CleanupStack::PushL(inverse);
+ // coverity[double_free]
+ inverse = CoalesceL(inverse,
+ CEditorCommandDeleteCharFormat::NewL(Repositories(), iPos, iLength, iTarget));
+ CleanupStack::Pop();
+ return inverse;
+ }
+
+// CEditorCommandSetParFormatProto
+TInt CEditorCommandSetParFormatProto::ExecuteL() const
+ {
+ iTarget.SetParFormatL(iPos, iLength, *iFormat);
+ return KErrNone;
+ }
+
+CCommand* CEditorCommandSetParFormatProto::CreateInverseL() const
+ {
+ // inverse is to remove formatting and re-apply the old
+ CCommand* inverse =
+ CEditorCommandSetParFormat::NewBatchL(Repositories(), iPos, iLength, iTarget);
+ CleanupStack::PushL(inverse);
+ // coverity[double_free]
+ inverse = CoalesceL(inverse,
+ CEditorCommandDeleteParFormat::NewL(Repositories(), iPos, iLength, iTarget));
+ CleanupStack::Pop();
+ return inverse;
+ }
+
+// CEditorCommandInsertProto
+TInt CEditorCommandInsertProto::ExecuteL() const
+ {
+ iTarget.InsertTextL(iPos, *iText, iStyle, iCharFormat, iParFormat);
+ return KErrNone;
+ }
+
+CCommand* CEditorCommandInsertProto::CreateInverseL() const
+ {
+ return CEditorCommandDeleteText::NewL(Repositories(), iPos, iText->Length(), iTarget);
+ }
+
+TBool CEditorCommandInsertProto::PrepareToAddInverseToLastL(CSingleCommand& aLastCommand) const
+ {
+ if (aLastCommand.FamilyUid() != TUid::Uid(KUndoDllUid))
+ return EFalse;
+ CEditorCommandDeleteText* last =
+ static_cast<CEditorCommand&>(aLastCommand).CastToCEditorCommandDeleteText();
+ if (!last)
+ return EFalse;
+ return last->CanAdd(iPos, iText->Length(), iTarget);
+ }
+
+void CEditorCommandInsertProto::AddInverseToLast(CSingleCommand& aLastCommand) const
+ {
+ ASSERT(aLastCommand.FamilyUid() == TUid::Uid(KUndoDllUid));
+ CEditorCommandDeleteText* last =
+ static_cast<CEditorCommand&>(aLastCommand).CastToCEditorCommandDeleteText();
+ ASSERT(last);
+ last->Add(iText->Length());
+ }
+
+// CEditorCommandDeleteProto
+TInt CEditorCommandDeleteProto::ExecuteL() const
+ {
+ iTarget.DeleteTextL(iPos, iLength);
+ return KErrNone;
+ }
+
+CCommand* CEditorCommandDeleteProto::CreateInverseL() const
+ {
+ return CEditorCommandInsertTextAndFormat::NewBatchL(Repositories(),
+ iPos, iLength, iTarget);
+ }
+
+TBool CEditorCommandDeleteProto::PrepareToAddInverseToLastL(CSingleCommand& aLastCommand) const
+ {
+ if (iDeletedText.MaxLength() < iLength)
+ return EFalse;
+ if (aLastCommand.FamilyUid() != TUid::Uid(KUndoDllUid))
+ return EFalse;
+ CEditorCommandInsertTextAndFormat* last =
+ static_cast<CEditorCommand&>(aLastCommand).CastToCEditorCommandInsertTextAndFormat();
+ if (!last)
+ return EFalse;
+ CEditorCommandInsertTextAndFormat::RTextAndFormatParameters params;
+ CleanupClosePushL(params);
+ params.SetL(iPos, iLength, iTarget);
+ TBool result = EFalse;
+ if (params.iText.Length() == iLength)
+ {
+ result = last->CanAdd(params, iTarget);
+ if (result)
+ iDeletedText = params.iText;
+ }
+ CleanupStack::PopAndDestroy();
+ return result;
+ }
+
+void CEditorCommandDeleteProto::AddInverseToLast(CSingleCommand& aLastCommand) const
+ {
+ ASSERT(aLastCommand.FamilyUid() == TUid::Uid(KUndoDllUid));
+ CEditorCommandInsertTextAndFormat* last =
+ static_cast<CEditorCommand&>(aLastCommand).CastToCEditorCommandInsertTextAndFormat();
+ ASSERT(last);
+ last->Add(iPos, iDeletedText);
+ }
+
+// CEditorCommandDeleteCharFormatProto
+TInt CEditorCommandDeleteCharFormatProto::ExecuteL() const
+ {
+ iTarget.DeleteCharFormatL(iPos, iLength);
+ return KErrNone;
+ }
+
+CCommand* CEditorCommandDeleteCharFormatProto::CreateInverseL() const
+ {
+ return CEditorCommandSetCharFormat::NewBatchL(Repositories(),
+ iPos, iLength, iTarget);
+ }
+
+// CEditorCommandDeleteParFormatProto
+TInt CEditorCommandDeleteParFormatProto::ExecuteL() const
+ {
+ iTarget.DeleteParFormatL(iPos, iLength);
+ return KErrNone;
+ }
+
+CCommand* CEditorCommandDeleteParFormatProto::CreateInverseL() const
+ {
+ return CEditorCommandSetParFormat::NewBatchL(Repositories(),
+ iPos, iLength, iTarget);
+ }
+
+// CEditorCommandDeletePictureProto
+TInt CEditorCommandDeletePictureProto::ExecuteL() const
+ {
+ MUnifiedEditor::MPictureSupport* pi = iTarget.PictureSupport();
+ ASSERT(pi);
+ pi->DropPictureL(iPos);
+ return KErrNone;
+ }
+
+// CEditorCommandInsertPictureProto
+TInt CEditorCommandInsertPictureProto::ExecuteL() const
+ {
+ MUnifiedEditor::MPictureSupport* pi = iTarget.PictureSupport();
+ ASSERT(pi);
+ pi->InsertPictureL(iPos, *iPicture);
+ return KErrNone;
+ }
+
+CCommand* CEditorCommandInsertPictureProto::CreateInverseL() const
+ {
+ return CEditorCommandDeletePicture::NewL(Repositories(), iPos, iTarget);
+ }
+
+// CEditorCommandDestroyPictureProto
+void CEditorCommandDestroyPictureProto::ForgetDelegate()
+ {
+ iPictureOwnerDelegate = 0;
+ }
+
+CEditorCommandDestroyPictureProto::~CEditorCommandDestroyPictureProto()
+ {
+ if (iPictureOwnerDelegate)
+ iPictureOwnerDelegate->ForgetOwner(this);
+ }
+
+CCommand* CEditorCommandDestroyPictureProto::CreateInverseL() const
+ {
+ CEditorCommandDestroyPictureProto* nonConstThis =
+ const_cast<CEditorCommandDestroyPictureProto*>(this);
+ if (iPictureOwnerDelegate)
+ {
+ iPictureOwnerDelegate->ForgetOwner(nonConstThis);
+ iPictureOwnerDelegate = 0;
+ }
+ CCommand* style =
+ CEditorCommandSetStyle::NewL(Repositories(), iPos, 1, iTarget);
+ CleanupStack::PushL(style);
+ CCommand* charFormat =
+ CEditorCommandSetCharFormat::NewBatchL(Repositories(), iPos, 1, iTarget);
+ CleanupStack::PushL(charFormat);
+ CCommand* parFormat =
+ CEditorCommandSetParFormat::NewBatchL(Repositories(), iPos, 1, iTarget);
+ CleanupStack::PushL(parFormat);
+ iPictureOwnerDelegate =
+ CEditorCommandInsertPicture::NewL(Repositories(), iPos,
+ *const_cast<CEditorCommandDestroyPictureProto*>(nonConstThis), iTarget);
+ // coverity[double_free]
+ CCommand* command = CoalesceL(parFormat, iPictureOwnerDelegate);
+ CleanupStack::Pop(); // parFormat, no longer owned
+ // coverity[double_free]
+ command = CoalesceL(charFormat, command);
+ CleanupStack::Pop(); // charFormat, no longer owned
+ // coverity[double_free]
+ command = CoalesceL(style, command);
+ CleanupStack::Pop(); // style, no longer owned
+
+ return command;
+ }
+
+TInt CEditorCommandDestroyPictureProto::ExecuteL() const
+ {
+ MUnifiedEditor::MPictureSupport* pi = iTarget.PictureSupport();
+ ASSERT(pi);
+ TPictureHeader pic;
+ pi->Picture(iPos, pic);
+ pi->DropPictureL(iPos);
+ if (iPictureOwnerDelegate)
+ {
+ iPictureOwnerDelegate->TakePictureOwnership(pic);
+ iPictureOwnerDelegate = 0;
+ }
+ else
+ pic.DeletePicture();
+ return KErrNone;
+ }
+
+// CEditorCommandRenameStyleProto
+TInt CEditorCommandRenameStyleProto::ExecuteL() const
+ {
+ MUnifiedEditor::MStyleSupport* si = iTarget.StyleSupport();
+ ASSERT(si);
+ return si->RenameStyleL(*iOldName, *iNewName);
+ }
+
+CCommand* CEditorCommandRenameStyleProto::CreateInverseL() const
+ {
+ return CEditorCommandRenameStyle::NewL(Repositories(),
+ *iNewName, *iOldName, iTarget);
+ }
+
+// CEditorCommandPasteProto
+TInt CEditorCommandPasteProto::ExecuteL() const
+ {
+ return iImpl.ExecuteL();
+ }
+
+UndoSystem::CCommand* CEditorCommandPasteProto::CreateInverseL() const
+ {
+ RStoreReadStream stream;
+ iImpl.OpenPlainTextStreamLC(stream);
+ TInt pos = iImpl.Pos();
+ TInt length = stream.ReadInt32L();
+ CCommand* command = 0;
+ CBufSeg* buf = CBufSeg::NewL(200);
+ CleanupStack::PushL(buf);
+ TPtrC current;
+
+ if (length < 0)
+ User::Leave(KErrNotSupported); // don't know how to undo
+
+ RBufWriteStream bufferStream;
+ bufferStream.Open(*buf);
+ TMemoryStreamUnicodeSink sink(bufferStream);
+ TUnicodeExpander e;
+ e.ExpandL(sink, stream, length);
+ bufferStream.CommitL();
+ bufferStream.Close();
+
+ TInt end = pos + length;
+ TInt bufferPos = 0;
+
+ while (pos != end)
+ {
+ ASSERT(pos < end);
+ TInt lengthSearched = 0;
+ TInt pic = KErrNotFound;
+ while ((pic = current.Locate(CEditableText::EPictureCharacter)) < 0
+ && pos + lengthSearched < end)
+ {
+ lengthSearched += current.Length();
+ TPtr8 seg(buf->Ptr(bufferPos));
+ bufferPos += seg.Length();
+ current.Set(reinterpret_cast<const TText*>(seg.Ptr()),
+ seg.Length() / sizeof(TText));
+ }
+ TInt currentSearched = 0 <= pic? pic : current.Length();
+ lengthSearched += currentSearched;
+
+ if (lengthSearched)
+ {
+ // we have some text to delete
+ CleanupStack::PushL(command);
+ // coverity[double_free]
+ command = CoalesceL(command,
+ CEditorCommandDeleteText::NewL(Repositories(), pos, lengthSearched,
+ iImpl.Target()));
+ CleanupStack::Pop();
+ pos += lengthSearched;
+ }
+
+ if (0 <= pic)
+ {
+ ASSERT(current.Length());
+ // we have a picture to delete
+ CleanupStack::PushL(command);
+ command = CoalesceL(command,
+ CEditorCommandDeletePicture::NewL(Repositories(), pos, iImpl.Target()));
+ CleanupStack::Pop();
+ currentSearched += 1;
+ pos += 1;
+ }
+
+ current.Set(current.Mid(currentSearched));
+ }
+
+ CleanupStack::PopAndDestroy(buf);
+ CleanupStack::PopAndDestroy(); // close stream
+
+ return command;
+ }
+
+// CEditorCommandSetBaseFormatProto
+TInt CEditorCommandSetBaseFormatProto::ExecuteL() const
+ {
+ iTarget.SetBaseFormatL(*iChar, *iPar);
+ return KErrNone;
+ }
+
+CCommand* CEditorCommandSetBaseFormatProto::CreateInverseL() const
+ {
+ return CEditorCommandSetBaseFormat::NewL(Repositories(),
+ iTarget);
+ }
+
+//////////////////////
+// //
+// free functions //
+// //
+//////////////////////
+
+TInt UndoSystem::FindPicture(const MUnifiedEditor& aTarget, TInt aPos, TInt aLength)
+ {
+ const MUnifiedEditor::MPictureSupport* pi =
+ const_cast<MUnifiedEditor&>(aTarget).PictureSupport();
+ if (!pi)
+ return KErrNotFound;
+ while (0 < aLength)
+ {
+ TPtrC text;
+ aTarget.GetText(aPos, text);
+ if (aLength < text.Length())
+ text.Set(text.Ptr(), aLength);
+ TInt result;
+ while (0 <= (result = text.Locate(CEditableText::EPictureCharacter)))
+ {
+ TPictureHeader pic;
+ pi->Picture(aPos + result, pic);
+ if (pic.iPictureType != KNullUid)
+ return aPos + result;
+ ++result;
+ aPos += result;
+ aLength -= result;
+ TPtrC temp = text.Mid(result);
+ text.Set(temp);
+ }
+ aPos += text.Length();
+ aLength -= text.Length();
+ }
+ return KErrNotFound;
+ }
+