--- /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 <txtetext.h>
+#include <txtclipboard.h>
+
+#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<CEditorCommand&>(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<CEditorCommand&>(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<CEditorCommand&>(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<CEditorCommand&>(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();
+ }