diff -r 000000000000 -r 1fb32624e06b textrendering/textformatting/undo/EditorCommands.cpp --- /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 +#include + +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 iChar; + RUniqueInstance 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 iOldName; + RUniqueInstance 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 iName; + RUniqueInstance iNext; + RUniqueInstance iChar; + TTmCharFormatMask iCharMask; + RUniqueInstance 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 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 iName; + RUniqueInstance iNext; + RUniqueInstance iChar; + TTmCharFormatMask iCharMask; + RUniqueInstance 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 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 iChar; + TTmCharFormatMask iCharMask; + RUniqueInstance iPar; + TTmParFormatMask iParMask; + RUniqueInstance 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 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 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(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(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(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(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(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(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(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(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(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(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(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(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(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; + } +