diff -r 000000000000 -r 1fb32624e06b textrendering/textformatting/undo/EditorPlainTextCommands.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/textrendering/textformatting/undo/EditorPlainTextCommands.cpp Tue Feb 02 02:02:46 2010 +0200 @@ -0,0 +1,428 @@ +/* +* 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 "EditorPlainTextCommands.h" +#include "AssertFileAndLine.h" +#include +#include + +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include "txtfmlyr_internal.h" +#endif +using namespace UndoSystem; + +///////////////////////// +// // +// Internal Commands // +// // +///////////////////////// + +TUid CEditorCommand::FamilyUid() const { return TUid::Uid(KUndoDllUid); } + +CEditorCommandInsertTextAndFormat* + CEditorCommand::CastToCEditorCommandInsertTextAndFormat() { return 0; } +CEditorCommandDeleteText* + CEditorCommand::CastToCEditorCommandDeleteText() { return 0; } +CEditorCommandInsertPlainText* + CEditorCommand::CastToCEditorCommandInsertPlainText() { return 0; } +CEditorCommandDeletePlainText* + CEditorCommand::CastToCEditorCommandDeletePlainText() { return 0; } +CEditorCommandDeleteCharFormat* + CEditorCommand::CastToCEditorCommandDeleteCharFormat() { return 0; } +CEditorCommandDeleteParFormat* + CEditorCommand::CastToCEditorCommandDeleteParFormat() { return 0; } + +///////////////////////////////// +// // +// Command coalesce function // +// // +///////////////////////////////// + +CCommand* UndoSystem::CoalesceL(CCommand* aLeft, CCommand* aRight) + { + if (!aRight) + return aLeft; + if (!aLeft) + return aRight; + + CleanupStack::PushL(aRight); + CBatchCommand* batch = aLeft->Batch(); + if (batch) + { + batch->PrepareToPushL(aRight); + batch->Push(aRight); + CleanupStack::Pop(aRight); + return batch; + } + ASSERT(aLeft->Single()); + batch = CBatchCommand::NewL(); + CleanupStack::PushL(batch); + batch->PrepareToPushL(aLeft); + batch->Push(aLeft); + batch->PrepareToPushL(aRight); + batch->Push(aRight); + CleanupStack::Pop(batch); + CleanupStack::Pop(aRight); + return batch; + } + +/** + * Command for deleting plain text. + * + * @internalComponent + * @since App-frameworks6.1 + */ +NONSHARABLE_CLASS(CEditorCommandDeletePlainText) : public CEditorCommand + { + TEditorDeletePlainTextImpl iImpl; + + CEditorCommandDeletePlainText* + CastToCEditorCommandDeletePlainText() { return this; } + + CEditorCommandDeletePlainText(MUnifiedEditor& aTarget, + TInt aPos, TInt aLength) + : iImpl(aTarget, aPos, aLength) {} +public: + static CEditorCommandDeletePlainText* NewL(TInt aPos, + TInt aLength, MUnifiedEditor& aTarget) + { + return new(ELeave) CEditorCommandDeletePlainText(aTarget, aPos, aLength); + } + + CCommand* CreateInverseL() const; + + TInt ExecuteL() const + { + return iImpl.ExecuteL(); + } + + // This command can be coalesced with others of the same type + TBool CanAdd(TInt aPos, TInt aLength, MUnifiedEditor& aTarget) const + { + return iImpl.CanAdd(aPos, aLength, aTarget); + } + + void Add(TInt aLength) + { + iImpl.Add(aLength); + } + }; + +/** + * Command for inserting text in a specified style and format. + * + * @internalComponent + * @since App-frameworks6.1 + */ +NONSHARABLE_CLASS(CEditorCommandInsertPlainText) : public CEditorCommand + { + TEditorInsertPlainTextImpl iImpl; + + CEditorCommandInsertPlainText* + CastToCEditorCommandInsertPlainText() { return this; } + CEditorCommandInsertPlainText(MUnifiedEditor& aTarget, TInt aPos, const TDesC& aText) + : iImpl(aTarget, aPos, aText) {} +public: + static CEditorCommandInsertPlainText* NewL(TInt aPos, const TDesC& aText, + MUnifiedEditor& aTarget) + { + return new(ELeave) CEditorCommandInsertPlainText(aTarget, aPos, aText); + } + /** + * Gets the length specified, but this might entail the use of more than + * one CCommand object. + */ + static CCommand* NewBatchL(TInt aPos, TInt aLength, MUnifiedEditor& aTarget); + + CCommand* CreateInverseL() const; + + TInt ExecuteL() const + { + return iImpl.ExecuteL(); + } + + TBool CanAdd(TInt aPos, const TDesC& aText, MUnifiedEditor& aTarget) const + { + return iImpl.CanAdd(aPos, aText, aTarget); + } + + void Add(TInt aPos, const TDesC& aText) + { + iImpl.Add(aPos, aText); + } + }; + +CCommand* CEditorCommandInsertPlainText::NewBatchL(TInt aPos, + TInt aLength, MUnifiedEditor& aTarget) + { + CCommand* command = 0; + TInt end = aPos + aLength; + while (aLength) + { + TPtrC textSegment; + aTarget.GetText(end - aLength, textSegment); + TInt segLength = textSegment.Length(); + if (aLength < segLength) + segLength = aLength; + if (KMaxCharsInSingleCommand < segLength) + segLength = KMaxCharsInSingleCommand; + CleanupStack::PushL(command); + // coverity[double_free] + command = CoalesceL(command, CEditorCommandInsertPlainText::NewL(aPos, + textSegment.Left(segLength), aTarget)); + CleanupStack::Pop(); + aLength -= segLength; + } + return command; + } + +CCommand* CEditorCommandInsertPlainText::CreateInverseL() const + { + return CEditorCommandDeletePlainText::NewL(iImpl.Pos(), iImpl.Text().Length(), + iImpl.Target()); + } + + +CCommand* CEditorCommandDeletePlainText::CreateInverseL() const + { + return CEditorCommandInsertPlainText::NewBatchL(iImpl.Pos(), iImpl.Length(), + iImpl.Target()); + } + +////////////////////////////////////////// +// // +// CEditorCommandInsertPlainTextProto // +// // +////////////////////////////////////////// + +void CEditorCommandInsertPlainTextProto::Set(TInt aPos, const TDesC& aText) + { + iPos = aPos; + iText = &aText; + } + +UndoSystem::CCommand* CEditorCommandInsertPlainTextProto::CreateInverseL() const + { + return CEditorCommandDeletePlainText::NewL(iPos, iText->Length(), iTarget); + } + +TInt CEditorCommandInsertPlainTextProto::ExecuteL() const + { + iTarget.InsertTextL(iPos, *iText); + return KErrNone; + } + +TBool CEditorCommandInsertPlainTextProto::PrepareToAddInverseToLastL( + CSingleCommand& aLastCommand) const + { + if (aLastCommand.FamilyUid() != TUid::Uid(KUndoDllUid)) + return EFalse; + CEditorCommandDeletePlainText* last = + static_cast(aLastCommand).CastToCEditorCommandDeletePlainText(); + if (!last) + return EFalse; + return last->CanAdd(iPos, iText->Length(), iTarget); + } + +void CEditorCommandInsertPlainTextProto::AddInverseToLast(CSingleCommand& aLastCommand) const + { + ASSERT(aLastCommand.FamilyUid() == TUid::Uid(KUndoDllUid)); + CEditorCommandDeletePlainText* last = + static_cast(aLastCommand).CastToCEditorCommandDeletePlainText(); + ASSERT(last); + last->Add(iText->Length()); + } + +////////////////////////////////////////// +// // +// CEditorCommandDeletePlainTextProto // +// // +////////////////////////////////////////// + +void CEditorCommandDeletePlainTextProto::Set(TInt aPos, TInt aLength) + { + iPos = aPos; + iLength = aLength; + } + +CCommand* CEditorCommandDeletePlainTextProto::CreateInverseL() const + { + return CEditorCommandInsertPlainText::NewBatchL(iPos, iLength, iTarget); + } + +TInt CEditorCommandDeletePlainTextProto::ExecuteL() const + { + iTarget.DeleteTextL(iPos, iLength); + return KErrNone; + } + +TBool CEditorCommandDeletePlainTextProto::PrepareToAddInverseToLastL( + CSingleCommand& aLastCommand) const + { + if (iDeletedText.MaxLength() < iLength) + return EFalse; + if (aLastCommand.FamilyUid() != TUid::Uid(KUndoDllUid)) + return EFalse; + CEditorCommandInsertPlainText* last = + static_cast(aLastCommand).CastToCEditorCommandInsertPlainText(); + if (!last) + return EFalse; + TBool result = EFalse; + TPtrC textSegment; + iTarget.GetText(iPos, textSegment); + if (iLength <= textSegment.Length()) + { + result = last->CanAdd(iPos, textSegment.Left(iLength), iTarget); + if (result) + iDeletedText = textSegment.Left(iLength); + } + return result; + } + +void CEditorCommandDeletePlainTextProto::AddInverseToLast(CSingleCommand& aLastCommand) const + { + ASSERT(aLastCommand.FamilyUid() == TUid::Uid(KUndoDllUid)); + CEditorCommandInsertPlainText* last = + static_cast(aLastCommand).CastToCEditorCommandInsertPlainText(); + ASSERT(last); + last->Add(iPos, iDeletedText); + } + +////////////////////////////////// +// // +// TEditorInsertPlainTextImpl // +// // +////////////////////////////////// + +TInt TEditorInsertPlainTextImpl::ExecuteL(const TDesC* aStyle, + const TTmCharFormatLayer* aChar, + const RTmParFormatLayer* aPar) const + { + iTarget.InsertTextL(iPos, iText, aStyle, aChar, aPar); + return KErrNone; + } + +TInt TEditorInsertPlainTextImpl::ExecuteL() const + { + return ExecuteL(0, 0, 0); + } + +TInt TEditorInsertPlainTextImpl::CanAdd(TInt aPos, const TDesC& aText, MUnifiedEditor& aTarget) const + { + if (&aTarget != &iTarget) + return EFalse; + TInt length = aText.Length(); + if (KMaxCharsInSingleCommand <= iText.Length() + length) + return EFalse; + return aPos <= iPos && iPos <= aPos + length; + } + +void TEditorInsertPlainTextImpl::Add(TInt aPos, const TDesC& aText) + { + TPtrC left = aText.Left(iPos - aPos); + TPtrC right = aText.Mid(iPos - aPos); + iText.Insert(0, left); + iText.Append(right); + iPos = aPos; + } + +////////////////////////////////// +// // +// TEditorDeletePlainTextImpl // +// // +////////////////////////////////// + +TInt TEditorDeletePlainTextImpl::ExecuteL() const + { + iTarget.DeleteTextL(iPos, iLength); + return KErrNone; + } + +TBool TEditorDeletePlainTextImpl::CanAdd(TInt aPos, TInt aLength, MUnifiedEditor& aTarget) const + { + return &aTarget == &iTarget && iPos <= aPos && aPos <= iLength + iPos + && aLength + iLength <= KMaxCharsInSingleCommand; + } + +void TEditorDeletePlainTextImpl::Add(TInt aLength) + { + iLength += aLength; + } + +///////////////////////////// +// // +// TEditorPasteProtoImpl // +// // +///////////////////////////// + +void TEditorPasteProtoImpl::Set(const CStreamStore& aStore, + const CStreamDictionary& aDict, + TInt aPos) + { + iStore = &aStore; + iStreamDictionary = &aDict; + iPos = aPos; + } + +void TEditorPasteProtoImpl::OpenPlainTextStreamLC(RStoreReadStream& aStream) const + { + TStreamId plainTextStream = iStreamDictionary->At(KClipboardUidTypePlainText); + if (plainTextStream == KNullStreamId) + User::Leave(KErrNotSupported); // don't know how to undo this + aStream.OpenLC(*iStore, plainTextStream); + } + +TInt TEditorPasteProtoImpl::LengthL() const + { + RStoreReadStream stream; + OpenPlainTextStreamLC(stream); + TInt length = stream.ReadInt32L(); + CleanupStack::PopAndDestroy(); + return length; + } + +TInt TEditorPasteProtoImpl::ExecuteL() const + { + MUnifiedEditor::MClipboardSupport* ci = iTarget.ClipboardSupport(); + ASSERT(ci); + ci->PasteFromStoreL(*iStore, *iStreamDictionary, iPos); + return KErrNone; + } + +///////////////////////////////////////// +// // +// CEditorCommandPastePlainTextProto // +// // +///////////////////////////////////////// + +void CEditorCommandPastePlainTextProto::Set(const CStreamStore& aStore, + const CStreamDictionary& aStreamDictionary, + TInt aPos) + { + iImpl.Set(aStore, aStreamDictionary, aPos); + } + +UndoSystem::CCommand* CEditorCommandPastePlainTextProto::CreateInverseL() const + { + return CEditorCommandDeletePlainText::NewL(iImpl.Pos(), iImpl.LengthL(), iImpl.Target()); + } + +TInt CEditorCommandPastePlainTextProto::ExecuteL() const + { + return iImpl.ExecuteL(); + }