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"
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() << " }";
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()));
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()) {
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
))) {
77 "EditorBase::CollapseSelectionTo() caused destroying the editor");
78 return NS_ERROR_EDITOR_DESTROYED
;
80 NS_ASSERTION(!error
.Failed(),
81 "EditorBase::CollapseSelectionTo() failed, but ignored");
85 NS_IMETHODIMP
ReplaceTextTransaction::UndoTransaction() {
86 MOZ_LOG(GetLogModule(), LogLevel::Info
,
87 ("%p ReplaceTextTransaction::%s this=%s", this, __FUNCTION__
,
88 ToString(*this).c_str()));
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
,
100 if (MOZ_UNLIKELY(error
.Failed())) {
101 NS_WARNING("CharacterData::SubstringData() failed");
102 return error
.StealNSResult();
104 if (MOZ_UNLIKELY(insertedString
!= mStringToInsert
)) {
106 "ReplaceTextTransaction::UndoTransaction() did nothing due to "
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()) {
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()),
134 if (MOZ_UNLIKELY(error
.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED
))) {
136 "EditorBase::CollapseSelectionTo() caused destroying the editor");
137 return NS_ERROR_EDITOR_DESTROYED
;
139 NS_ASSERTION(!error
.Failed(),
140 "EditorBase::CollapseSelectionTo() failed, but ignored");
144 NS_IMETHODIMP
ReplaceTextTransaction::RedoTransaction() {
145 MOZ_LOG(GetLogModule(), LogLevel::Info
,
146 ("%p ReplaceTextTransaction::%s this=%s", this, __FUNCTION__
,
147 ToString(*this).c_str()));
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
,
159 if (MOZ_UNLIKELY(error
.Failed())) {
160 NS_WARNING("CharacterData::SubstringData() failed");
161 return error
.StealNSResult();
163 if (MOZ_UNLIKELY(undoneString
!= mStringToBeReplaced
)) {
165 "ReplaceTextTransaction::RedoTransaction() did nothing due to "
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()) {
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
))) {
194 "EditorBase::CollapseSelectionTo() caused destroying the editor");
195 return NS_ERROR_EDITOR_DESTROYED
;
197 NS_ASSERTION(!error
.Failed(),
198 "EditorBase::CollapseSelectionTo() failed, but ignored");
202 } // namespace mozilla