Bug 1772588 [wpt PR 34302] - [wpt] Add test for block-in-inline offsetParent., a...
[gecko.git] / editor / libeditor / ReplaceTextTransaction.cpp
blobac1ed2b31d96220d5418c27b9b84b4e6cfafdb9e
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "ReplaceTextTransaction.h"
8 #include "HTMLEditUtils.h"
10 #include "mozilla/Logging.h"
11 #include "mozilla/OwningNonNull.h"
12 #include "mozilla/ToString.h"
14 namespace mozilla {
16 using namespace dom;
18 std::ostream& operator<<(std::ostream& aStream,
19 const ReplaceTextTransaction& aTransaction) {
20 aStream << "{ mTextNode=" << aTransaction.mTextNode.get();
21 if (aTransaction.mTextNode) {
22 aStream << " (" << *aTransaction.mTextNode << ")";
24 aStream << ", mStringToInsert=\""
25 << NS_ConvertUTF16toUTF8(aTransaction.mStringToInsert).get() << "\""
26 << ", mStringToBeReplaced=\""
27 << NS_ConvertUTF16toUTF8(aTransaction.mStringToBeReplaced).get()
28 << "\", mOffset=" << aTransaction.mOffset
29 << ", mEditorBase=" << aTransaction.mEditorBase.get() << " }";
30 return aStream;
33 NS_IMPL_CYCLE_COLLECTION_INHERITED(ReplaceTextTransaction, EditTransactionBase,
34 mEditorBase, mTextNode)
36 NS_IMPL_ADDREF_INHERITED(ReplaceTextTransaction, EditTransactionBase)
37 NS_IMPL_RELEASE_INHERITED(ReplaceTextTransaction, EditTransactionBase)
38 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ReplaceTextTransaction)
39 NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
41 NS_IMETHODIMP ReplaceTextTransaction::DoTransaction() {
42 MOZ_LOG(GetLogModule(), LogLevel::Info,
43 ("%p ReplaceTextTransaction::%s this=%s", this, __FUNCTION__,
44 ToString(*this).c_str()));
46 if (MOZ_UNLIKELY(
47 NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode) ||
48 NS_WARN_IF(!HTMLEditUtils::IsSimplyEditableNode(*mTextNode)))) {
49 return NS_ERROR_NOT_AVAILABLE;
52 OwningNonNull<EditorBase> editorBase = *mEditorBase;
53 OwningNonNull<Text> textNode = *mTextNode;
55 IgnoredErrorResult error;
56 editorBase->DoReplaceText(textNode, mOffset, mStringToBeReplaced.Length(),
57 mStringToInsert, error);
58 if (MOZ_UNLIKELY(error.Failed())) {
59 NS_WARNING("EditorBase::DoReplaceText() failed");
60 return error.StealNSResult();
62 // XXX What should we do if mutation event listener changed the node?
63 editorBase->RangeUpdaterRef().SelAdjReplaceText(textNode, mOffset,
64 mStringToBeReplaced.Length(),
65 mStringToInsert.Length());
67 if (!editorBase->AllowsTransactionsToChangeSelection()) {
68 return NS_OK;
71 // XXX Should we stop setting selection when mutation event listener
72 // modifies the text node?
73 editorBase->CollapseSelectionTo(
74 EditorRawDOMPoint(textNode, mOffset + mStringToInsert.Length()), error);
75 if (MOZ_UNLIKELY(error.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED))) {
76 NS_WARNING(
77 "EditorBase::CollapseSelectionTo() caused destroying the editor");
78 return NS_ERROR_EDITOR_DESTROYED;
80 NS_ASSERTION(!error.Failed(),
81 "EditorBase::CollapseSelectionTo() failed, but ignored");
82 return NS_OK;
85 NS_IMETHODIMP ReplaceTextTransaction::UndoTransaction() {
86 MOZ_LOG(GetLogModule(), LogLevel::Info,
87 ("%p ReplaceTextTransaction::%s this=%s", this, __FUNCTION__,
88 ToString(*this).c_str()));
90 if (MOZ_UNLIKELY(
91 NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode) ||
92 NS_WARN_IF(!HTMLEditUtils::IsSimplyEditableNode(*mTextNode)))) {
93 return NS_ERROR_NOT_AVAILABLE;
96 IgnoredErrorResult error;
97 nsAutoString insertedString;
98 mTextNode->SubstringData(mOffset, mStringToInsert.Length(), insertedString,
99 error);
100 if (MOZ_UNLIKELY(error.Failed())) {
101 NS_WARNING("CharacterData::SubstringData() failed");
102 return error.StealNSResult();
104 if (MOZ_UNLIKELY(insertedString != mStringToInsert)) {
105 NS_WARNING(
106 "ReplaceTextTransaction::UndoTransaction() did nothing due to "
107 "unexpected text");
108 return NS_OK;
111 OwningNonNull<EditorBase> editorBase = *mEditorBase;
112 OwningNonNull<Text> textNode = *mTextNode;
114 editorBase->DoReplaceText(textNode, mOffset, mStringToInsert.Length(),
115 mStringToBeReplaced, error);
116 if (MOZ_UNLIKELY(error.Failed())) {
117 NS_WARNING("EditorBase::DoReplaceText() failed");
118 return error.StealNSResult();
120 // XXX What should we do if mutation event listener changed the node?
121 editorBase->RangeUpdaterRef().SelAdjReplaceText(textNode, mOffset,
122 mStringToInsert.Length(),
123 mStringToBeReplaced.Length());
125 if (!editorBase->AllowsTransactionsToChangeSelection()) {
126 return NS_OK;
129 // XXX Should we stop setting selection when mutation event listener
130 // modifies the text node?
131 editorBase->CollapseSelectionTo(
132 EditorRawDOMPoint(textNode, mOffset + mStringToBeReplaced.Length()),
133 error);
134 if (MOZ_UNLIKELY(error.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED))) {
135 NS_WARNING(
136 "EditorBase::CollapseSelectionTo() caused destroying the editor");
137 return NS_ERROR_EDITOR_DESTROYED;
139 NS_ASSERTION(!error.Failed(),
140 "EditorBase::CollapseSelectionTo() failed, but ignored");
141 return NS_OK;
144 NS_IMETHODIMP ReplaceTextTransaction::RedoTransaction() {
145 MOZ_LOG(GetLogModule(), LogLevel::Info,
146 ("%p ReplaceTextTransaction::%s this=%s", this, __FUNCTION__,
147 ToString(*this).c_str()));
149 if (MOZ_UNLIKELY(
150 NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode) ||
151 NS_WARN_IF(!HTMLEditUtils::IsSimplyEditableNode(*mTextNode)))) {
152 return NS_ERROR_NOT_AVAILABLE;
155 IgnoredErrorResult error;
156 nsAutoString undoneString;
157 mTextNode->SubstringData(mOffset, mStringToBeReplaced.Length(), undoneString,
158 error);
159 if (MOZ_UNLIKELY(error.Failed())) {
160 NS_WARNING("CharacterData::SubstringData() failed");
161 return error.StealNSResult();
163 if (MOZ_UNLIKELY(undoneString != mStringToBeReplaced)) {
164 NS_WARNING(
165 "ReplaceTextTransaction::RedoTransaction() did nothing due to "
166 "unexpected text");
167 return NS_OK;
170 OwningNonNull<EditorBase> editorBase = *mEditorBase;
171 OwningNonNull<Text> textNode = *mTextNode;
173 editorBase->DoReplaceText(textNode, mOffset, mStringToBeReplaced.Length(),
174 mStringToInsert, error);
175 if (MOZ_UNLIKELY(error.Failed())) {
176 NS_WARNING("EditorBase::DoReplaceText() failed");
177 return error.StealNSResult();
179 // XXX What should we do if mutation event listener changed the node?
180 editorBase->RangeUpdaterRef().SelAdjReplaceText(textNode, mOffset,
181 mStringToBeReplaced.Length(),
182 mStringToInsert.Length());
184 if (!editorBase->AllowsTransactionsToChangeSelection()) {
185 return NS_OK;
188 // XXX Should we stop setting selection when mutation event listener
189 // modifies the text node?
190 editorBase->CollapseSelectionTo(
191 EditorRawDOMPoint(textNode, mOffset + mStringToInsert.Length()), error);
192 if (MOZ_UNLIKELY(error.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED))) {
193 NS_WARNING(
194 "EditorBase::CollapseSelectionTo() caused destroying the editor");
195 return NS_ERROR_EDITOR_DESTROYED;
197 NS_ASSERTION(!error.Failed(),
198 "EditorBase::CollapseSelectionTo() failed, but ignored");
199 return NS_OK;
202 } // namespace mozilla