/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ReplaceTextTransaction.h" #include "HTMLEditUtils.h" #include "mozilla/OwningNonNull.h" namespace mozilla { using namespace dom; NS_IMPL_CYCLE_COLLECTION_INHERITED(ReplaceTextTransaction, EditTransactionBase, mEditorBase, mTextNode) NS_IMPL_ADDREF_INHERITED(ReplaceTextTransaction, EditTransactionBase) NS_IMPL_RELEASE_INHERITED(ReplaceTextTransaction, EditTransactionBase) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ReplaceTextTransaction) NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase) NS_IMETHODIMP ReplaceTextTransaction::DoTransaction() { if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode) || NS_WARN_IF(!HTMLEditUtils::IsSimplyEditableNode(*mTextNode))) { return NS_ERROR_NOT_AVAILABLE; } OwningNonNull editorBase = *mEditorBase; OwningNonNull textNode = *mTextNode; ErrorResult error; editorBase->DoReplaceText(textNode, mOffset, mStringToBeReplaced.Length(), mStringToInsert, error); if (error.Failed()) { NS_WARNING("EditorBase::DoReplaceText() failed"); return error.StealNSResult(); } // XXX What should we do if mutation event listener changed the node? editorBase->RangeUpdaterRef().SelAdjReplaceText(textNode, mOffset, mStringToBeReplaced.Length(), mStringToInsert.Length()); if (!editorBase->AllowsTransactionsToChangeSelection()) { return NS_OK; } // XXX Should we stop setting selection when mutation event listener // modifies the text node? RefPtr selection = editorBase->GetSelection(); if (NS_WARN_IF(!selection)) { return NS_ERROR_FAILURE; } DebugOnly rvIgnored = selection->CollapseInLimiter( textNode, mOffset + mStringToInsert.Length()); if (NS_WARN_IF(editorBase->Destroyed())) { return NS_ERROR_EDITOR_DESTROYED; } NS_ASSERTION(NS_SUCCEEDED(rvIgnored), "Selection::CollapseInLimiter() failed, but ignored"); return NS_OK; } NS_IMETHODIMP ReplaceTextTransaction::UndoTransaction() { if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode) || NS_WARN_IF(!HTMLEditUtils::IsSimplyEditableNode(*mTextNode))) { return NS_ERROR_NOT_AVAILABLE; } ErrorResult error; nsAutoString insertedString; mTextNode->SubstringData(mOffset, mStringToInsert.Length(), insertedString, error); if (error.Failed()) { NS_WARNING("CharacterData::SubstringData() failed"); return error.StealNSResult(); } if (insertedString != mStringToInsert) { NS_WARNING( "ReplaceTextTransaction::UndoTransaction() did nothing due to " "unexpected text"); return NS_OK; } OwningNonNull editorBase = *mEditorBase; OwningNonNull textNode = *mTextNode; editorBase->DoReplaceText(textNode, mOffset, mStringToInsert.Length(), mStringToBeReplaced, error); if (error.Failed()) { NS_WARNING("EditorBase::DoReplaceText() failed"); return error.StealNSResult(); } // XXX What should we do if mutation event listener changed the node? editorBase->RangeUpdaterRef().SelAdjReplaceText(textNode, mOffset, mStringToInsert.Length(), mStringToBeReplaced.Length()); if (!editorBase->AllowsTransactionsToChangeSelection()) { return NS_OK; } // XXX Should we stop setting selection when mutation event listener // modifies the text node? RefPtr selection = editorBase->GetSelection(); if (NS_WARN_IF(!selection)) { return NS_ERROR_FAILURE; } DebugOnly rvIgnored = selection->CollapseInLimiter( textNode, mOffset + mStringToBeReplaced.Length()); if (NS_WARN_IF(editorBase->Destroyed())) { return NS_ERROR_EDITOR_DESTROYED; } NS_ASSERTION(NS_SUCCEEDED(rvIgnored), "Selection::CollapseInLimiter() failed, but ignored"); return NS_OK; } NS_IMETHODIMP ReplaceTextTransaction::RedoTransaction() { if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode) || NS_WARN_IF(!HTMLEditUtils::IsSimplyEditableNode(*mTextNode))) { return NS_ERROR_NOT_AVAILABLE; } ErrorResult error; nsAutoString undoneString; mTextNode->SubstringData(mOffset, mStringToBeReplaced.Length(), undoneString, error); if (error.Failed()) { NS_WARNING("CharacterData::SubstringData() failed"); return error.StealNSResult(); } if (undoneString != mStringToBeReplaced) { NS_WARNING( "ReplaceTextTransaction::RedoTransaction() did nothing due to " "unexpected text"); return NS_OK; } OwningNonNull editorBase = *mEditorBase; OwningNonNull textNode = *mTextNode; editorBase->DoReplaceText(textNode, mOffset, mStringToBeReplaced.Length(), mStringToInsert, error); if (error.Failed()) { NS_WARNING("EditorBase::DoReplaceText() failed"); return error.StealNSResult(); } // XXX What should we do if mutation event listener changed the node? editorBase->RangeUpdaterRef().SelAdjReplaceText(textNode, mOffset, mStringToBeReplaced.Length(), mStringToInsert.Length()); if (!editorBase->AllowsTransactionsToChangeSelection()) { return NS_OK; } // XXX Should we stop setting selection when mutation event listener // modifies the text node? RefPtr selection = editorBase->GetSelection(); if (NS_WARN_IF(!selection)) { return NS_ERROR_FAILURE; } DebugOnly rvIgnored = selection->CollapseInLimiter( textNode, mOffset + mStringToInsert.Length()); if (NS_WARN_IF(editorBase->Destroyed())) { return NS_ERROR_EDITOR_DESTROYED; } NS_ASSERTION(NS_SUCCEEDED(rvIgnored), "Selection::CollapseInLimiter() failed, but ignored"); return NS_OK; } } // namespace mozilla