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());
69 NS_IMETHODIMP
ReplaceTextTransaction::UndoTransaction() {
70 MOZ_LOG(GetLogModule(), LogLevel::Info
,
71 ("%p ReplaceTextTransaction::%s this=%s", this, __FUNCTION__
,
72 ToString(*this).c_str()));
75 NS_WARN_IF(!mEditorBase
) || NS_WARN_IF(!mTextNode
) ||
76 NS_WARN_IF(!HTMLEditUtils::IsSimplyEditableNode(*mTextNode
)))) {
77 return NS_ERROR_NOT_AVAILABLE
;
80 IgnoredErrorResult error
;
81 nsAutoString insertedString
;
82 mTextNode
->SubstringData(mOffset
, mStringToInsert
.Length(), insertedString
,
84 if (MOZ_UNLIKELY(error
.Failed())) {
85 NS_WARNING("CharacterData::SubstringData() failed");
86 return error
.StealNSResult();
88 if (MOZ_UNLIKELY(insertedString
!= mStringToInsert
)) {
90 "ReplaceTextTransaction::UndoTransaction() did nothing due to "
95 OwningNonNull
<EditorBase
> editorBase
= *mEditorBase
;
96 OwningNonNull
<Text
> textNode
= *mTextNode
;
98 editorBase
->DoReplaceText(textNode
, mOffset
, mStringToInsert
.Length(),
99 mStringToBeReplaced
, error
);
100 if (MOZ_UNLIKELY(error
.Failed())) {
101 NS_WARNING("EditorBase::DoReplaceText() failed");
102 return error
.StealNSResult();
104 // XXX What should we do if mutation event listener changed the node?
105 editorBase
->RangeUpdaterRef().SelAdjReplaceText(textNode
, mOffset
,
106 mStringToInsert
.Length(),
107 mStringToBeReplaced
.Length());
109 if (!editorBase
->AllowsTransactionsToChangeSelection()) {
113 // XXX Should we stop setting selection when mutation event listener
114 // modifies the text node?
115 editorBase
->CollapseSelectionTo(
116 EditorRawDOMPoint(textNode
, mOffset
+ mStringToBeReplaced
.Length()),
118 if (MOZ_UNLIKELY(error
.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED
))) {
120 "EditorBase::CollapseSelectionTo() caused destroying the editor");
121 return NS_ERROR_EDITOR_DESTROYED
;
123 NS_ASSERTION(!error
.Failed(),
124 "EditorBase::CollapseSelectionTo() failed, but ignored");
128 NS_IMETHODIMP
ReplaceTextTransaction::RedoTransaction() {
129 MOZ_LOG(GetLogModule(), LogLevel::Info
,
130 ("%p ReplaceTextTransaction::%s this=%s", this, __FUNCTION__
,
131 ToString(*this).c_str()));
134 NS_WARN_IF(!mEditorBase
) || NS_WARN_IF(!mTextNode
) ||
135 NS_WARN_IF(!HTMLEditUtils::IsSimplyEditableNode(*mTextNode
)))) {
136 return NS_ERROR_NOT_AVAILABLE
;
139 IgnoredErrorResult error
;
140 nsAutoString undoneString
;
141 mTextNode
->SubstringData(mOffset
, mStringToBeReplaced
.Length(), undoneString
,
143 if (MOZ_UNLIKELY(error
.Failed())) {
144 NS_WARNING("CharacterData::SubstringData() failed");
145 return error
.StealNSResult();
147 if (MOZ_UNLIKELY(undoneString
!= mStringToBeReplaced
)) {
149 "ReplaceTextTransaction::RedoTransaction() did nothing due to "
154 OwningNonNull
<EditorBase
> editorBase
= *mEditorBase
;
155 OwningNonNull
<Text
> textNode
= *mTextNode
;
157 editorBase
->DoReplaceText(textNode
, mOffset
, mStringToBeReplaced
.Length(),
158 mStringToInsert
, error
);
159 if (MOZ_UNLIKELY(error
.Failed())) {
160 NS_WARNING("EditorBase::DoReplaceText() failed");
161 return error
.StealNSResult();
163 // XXX What should we do if mutation event listener changed the node?
164 editorBase
->RangeUpdaterRef().SelAdjReplaceText(textNode
, mOffset
,
165 mStringToBeReplaced
.Length(),
166 mStringToInsert
.Length());
168 if (!editorBase
->AllowsTransactionsToChangeSelection()) {
172 // XXX Should we stop setting selection when mutation event listener
173 // modifies the text node?
174 editorBase
->CollapseSelectionTo(SuggestPointToPutCaret
<EditorRawDOMPoint
>(),
176 if (MOZ_UNLIKELY(error
.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED
))) {
178 "EditorBase::CollapseSelectionTo() caused destroying the editor");
179 return NS_ERROR_EDITOR_DESTROYED
;
181 NS_ASSERTION(!error
.Failed(),
182 "EditorBase::CollapseSelectionTo() failed, but ignored");
186 } // namespace mozilla