Backed out changeset b71c8c052463 (bug 1943846) for causing mass failures. CLOSED...
[gecko.git] / editor / libeditor / InsertTextTransaction.cpp
blob3a308dd4878f5ba7f40e541e7a6e209fbce419cd
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 "InsertTextTransaction.h"
8 #include "ErrorList.h"
9 #include "mozilla/EditorBase.h" // mEditorBase
10 #include "mozilla/Logging.h"
11 #include "mozilla/SelectionState.h" // RangeUpdater
12 #include "mozilla/ToString.h"
13 #include "mozilla/dom/Selection.h" // Selection local var
14 #include "mozilla/dom/Text.h" // mTextNode
16 #include "nsAString.h" // nsAString parameter
17 #include "nsDebug.h" // for NS_ASSERTION, etc.
18 #include "nsError.h" // for NS_OK, etc.
19 #include "nsQueryObject.h" // for do_QueryObject
21 namespace mozilla {
23 using namespace dom;
25 // static
26 already_AddRefed<InsertTextTransaction> InsertTextTransaction::Create(
27 EditorBase& aEditorBase, const nsAString& aStringToInsert,
28 const EditorDOMPointInText& aPointToInsert) {
29 MOZ_ASSERT(aPointToInsert.IsSetAndValid());
30 RefPtr<InsertTextTransaction> transaction =
31 new InsertTextTransaction(aEditorBase, aStringToInsert, aPointToInsert);
32 return transaction.forget();
35 InsertTextTransaction::InsertTextTransaction(
36 EditorBase& aEditorBase, const nsAString& aStringToInsert,
37 const EditorDOMPointInText& aPointToInsert)
38 : mTextNode(aPointToInsert.ContainerAs<Text>()),
39 mOffset(aPointToInsert.Offset()),
40 mStringToInsert(aStringToInsert),
41 mEditorBase(&aEditorBase) {}
43 std::ostream& operator<<(std::ostream& aStream,
44 const InsertTextTransaction& aTransaction) {
45 aStream << "{ mTextNode=" << aTransaction.mTextNode.get();
46 if (aTransaction.mTextNode) {
47 aStream << " (" << *aTransaction.mTextNode << ")";
49 aStream << ", mOffset=" << aTransaction.mOffset << ", mStringToInsert=\""
50 << NS_ConvertUTF16toUTF8(aTransaction.mStringToInsert).get() << "\""
51 << ", mEditorBase=" << aTransaction.mEditorBase.get() << " }";
52 return aStream;
55 NS_IMPL_CYCLE_COLLECTION_INHERITED(InsertTextTransaction, EditTransactionBase,
56 mEditorBase, mTextNode)
58 NS_IMPL_ADDREF_INHERITED(InsertTextTransaction, EditTransactionBase)
59 NS_IMPL_RELEASE_INHERITED(InsertTextTransaction, EditTransactionBase)
60 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(InsertTextTransaction)
61 NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
63 NS_IMETHODIMP InsertTextTransaction::DoTransaction() {
64 MOZ_LOG(GetLogModule(), LogLevel::Info,
65 ("%p InsertTextTransaction::%s this=%s", this, __FUNCTION__,
66 ToString(*this).c_str()));
68 if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode)) {
69 return NS_ERROR_NOT_AVAILABLE;
72 OwningNonNull<EditorBase> editorBase = *mEditorBase;
73 OwningNonNull<Text> textNode = *mTextNode;
75 ErrorResult error;
76 editorBase->DoInsertText(textNode, mOffset, mStringToInsert, error);
77 if (error.Failed()) {
78 NS_WARNING("EditorBase::DoInsertText() failed");
79 return error.StealNSResult();
82 editorBase->RangeUpdaterRef().SelAdjInsertText(textNode, mOffset,
83 mStringToInsert.Length());
84 return NS_OK;
87 NS_IMETHODIMP InsertTextTransaction::UndoTransaction() {
88 MOZ_LOG(GetLogModule(), LogLevel::Info,
89 ("%p InsertTextTransaction::%s this=%s", this, __FUNCTION__,
90 ToString(*this).c_str()));
92 if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode)) {
93 return NS_ERROR_NOT_INITIALIZED;
95 OwningNonNull<EditorBase> editorBase = *mEditorBase;
96 OwningNonNull<Text> textNode = *mTextNode;
97 ErrorResult error;
98 editorBase->DoDeleteText(textNode, mOffset, mStringToInsert.Length(), error);
99 NS_WARNING_ASSERTION(!error.Failed(), "EditorBase::DoDeleteText() failed");
100 return error.StealNSResult();
103 NS_IMETHODIMP InsertTextTransaction::RedoTransaction() {
104 MOZ_LOG(GetLogModule(), LogLevel::Info,
105 ("%p InsertTextTransaction::%s this=%s", this, __FUNCTION__,
106 ToString(*this).c_str()));
107 nsresult rv = DoTransaction();
108 if (NS_FAILED(rv)) {
109 NS_WARNING("InsertTextTransaction::DoTransaction() failed");
110 return rv;
112 if (RefPtr<EditorBase> editorBase = mEditorBase) {
113 nsresult rv = editorBase->CollapseSelectionTo(
114 SuggestPointToPutCaret<EditorRawDOMPoint>());
115 if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {
116 return NS_ERROR_EDITOR_DESTROYED;
118 NS_WARNING_ASSERTION(
119 NS_SUCCEEDED(rv),
120 "EditorBase::CollapseSelectionTo() failed, but ignored");
122 return NS_OK;
125 NS_IMETHODIMP InsertTextTransaction::Merge(nsITransaction* aOtherTransaction,
126 bool* aDidMerge) {
127 MOZ_LOG(GetLogModule(), LogLevel::Debug,
128 ("%p InsertTextTransaction::%s(aOtherTransaction=%p) this=%s", this,
129 __FUNCTION__, aOtherTransaction, ToString(*this).c_str()));
131 if (NS_WARN_IF(!aOtherTransaction) || NS_WARN_IF(!aDidMerge)) {
132 return NS_ERROR_INVALID_ARG;
134 // Set out param default value
135 *aDidMerge = false;
137 RefPtr<EditTransactionBase> otherTransactionBase =
138 aOtherTransaction->GetAsEditTransactionBase();
139 if (!otherTransactionBase) {
140 MOZ_LOG(
141 GetLogModule(), LogLevel::Debug,
142 ("%p InsertTextTransaction::%s(aOtherTransaction=%p) returned false",
143 this, __FUNCTION__, aOtherTransaction));
144 return NS_OK;
147 // If aTransaction is a InsertTextTransaction, and if the selection hasn't
148 // changed, then absorb it.
149 InsertTextTransaction* otherInsertTextTransaction =
150 otherTransactionBase->GetAsInsertTextTransaction();
151 if (!otherInsertTextTransaction ||
152 !IsSequentialInsert(*otherInsertTextTransaction)) {
153 MOZ_LOG(
154 GetLogModule(), LogLevel::Debug,
155 ("%p InsertTextTransaction::%s(aOtherTransaction=%p) returned false",
156 this, __FUNCTION__, aOtherTransaction));
157 return NS_OK;
160 mStringToInsert += otherInsertTextTransaction->GetData();
161 *aDidMerge = true;
162 MOZ_LOG(GetLogModule(), LogLevel::Debug,
163 ("%p InsertTextTransaction::%s(aOtherTransaction=%p) returned true",
164 this, __FUNCTION__, aOtherTransaction));
165 return NS_OK;
168 /* ============ private methods ================== */
170 bool InsertTextTransaction::IsSequentialInsert(
171 InsertTextTransaction& aOtherTransaction) const {
172 return aOtherTransaction.mTextNode == mTextNode &&
173 aOtherTransaction.mOffset == mOffset + mStringToInsert.Length();
176 } // namespace mozilla