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 "DeleteTextTransaction.h"
8 #include "HTMLEditUtils.h"
9 #include "mozilla/Assertions.h"
10 #include "mozilla/EditorBase.h"
11 #include "mozilla/EditorDOMPoint.h"
12 #include "mozilla/SelectionState.h"
13 #include "mozilla/dom/Selection.h"
16 #include "nsISupportsImpl.h"
17 #include "nsAString.h"
24 already_AddRefed
<DeleteTextTransaction
> DeleteTextTransaction::MaybeCreate(
25 EditorBase
& aEditorBase
, Text
& aTextNode
, uint32_t aOffset
,
26 uint32_t aLengthToDelete
) {
27 RefPtr
<DeleteTextTransaction
> transaction
= new DeleteTextTransaction(
28 aEditorBase
, aTextNode
, aOffset
, aLengthToDelete
);
29 return transaction
.forget();
33 already_AddRefed
<DeleteTextTransaction
>
34 DeleteTextTransaction::MaybeCreateForPreviousCharacter(EditorBase
& aEditorBase
,
37 if (NS_WARN_IF(!aOffset
)) {
42 aTextNode
.GetData(data
);
43 if (NS_WARN_IF(data
.IsEmpty())) {
48 uint32_t offset
= aOffset
- 1;
49 if (offset
&& NS_IS_SURROGATE_PAIR(data
[offset
- 1], data
[offset
])) {
53 return DeleteTextTransaction::MaybeCreate(aEditorBase
, aTextNode
, offset
,
58 already_AddRefed
<DeleteTextTransaction
>
59 DeleteTextTransaction::MaybeCreateForNextCharacter(EditorBase
& aEditorBase
,
63 aTextNode
.GetData(data
);
64 if (NS_WARN_IF(aOffset
>= data
.Length()) || NS_WARN_IF(data
.IsEmpty())) {
69 if (aOffset
+ 1 < data
.Length() &&
70 NS_IS_SURROGATE_PAIR(data
[aOffset
], data
[aOffset
+ 1])) {
73 return DeleteTextTransaction::MaybeCreate(aEditorBase
, aTextNode
, aOffset
,
77 DeleteTextTransaction::DeleteTextTransaction(EditorBase
& aEditorBase
,
78 Text
& aTextNode
, uint32_t aOffset
,
79 uint32_t aLengthToDelete
)
80 : mEditorBase(&aEditorBase
),
81 mTextNode(&aTextNode
),
83 mLengthToDelete(aLengthToDelete
) {
84 NS_ASSERTION(mTextNode
->Length() >= aOffset
+ aLengthToDelete
,
85 "Trying to delete more characters than in node");
88 NS_IMPL_CYCLE_COLLECTION_INHERITED(DeleteTextTransaction
, EditTransactionBase
,
89 mEditorBase
, mTextNode
)
91 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DeleteTextTransaction
)
92 NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase
)
94 bool DeleteTextTransaction::CanDoIt() const {
95 if (NS_WARN_IF(!mTextNode
) || NS_WARN_IF(!mEditorBase
)) {
98 return mEditorBase
->IsTextEditor() ||
99 HTMLEditUtils::IsSimplyEditableNode(*mTextNode
);
102 NS_IMETHODIMP
DeleteTextTransaction::DoTransaction() {
103 if (NS_WARN_IF(!CanDoIt())) {
104 return NS_ERROR_NOT_AVAILABLE
;
107 // Get the text that we're about to delete
109 mTextNode
->SubstringData(mOffset
, mLengthToDelete
, mDeletedText
, error
);
110 if (error
.Failed()) {
111 NS_WARNING("Text::SubstringData() failed");
112 return error
.StealNSResult();
115 OwningNonNull
<EditorBase
> editorBase
= *mEditorBase
;
116 OwningNonNull
<Text
> textNode
= *mTextNode
;
117 editorBase
->DoDeleteText(textNode
, mOffset
, mLengthToDelete
, error
);
118 if (error
.Failed()) {
119 NS_WARNING("EditorBase::DoDeleteText() failed");
120 return error
.StealNSResult();
123 editorBase
->RangeUpdaterRef().SelAdjDeleteText(textNode
, mOffset
,
126 if (!editorBase
->AllowsTransactionsToChangeSelection()) {
130 RefPtr
<Selection
> selection
= editorBase
->GetSelection();
131 if (NS_WARN_IF(!selection
)) {
132 return NS_ERROR_FAILURE
;
134 selection
->CollapseInLimiter(EditorRawDOMPoint(textNode
, mOffset
), error
);
135 NS_WARNING_ASSERTION(!error
.Failed(),
136 "Selection::CollapseInLimiter() failed");
137 return error
.StealNSResult();
140 // XXX: We may want to store the selection state and restore it properly. Was
141 // it an insertion point or an extended selection?
142 NS_IMETHODIMP
DeleteTextTransaction::UndoTransaction() {
143 if (NS_WARN_IF(!CanDoIt())) {
144 return NS_ERROR_NOT_AVAILABLE
;
146 RefPtr
<EditorBase
> editorBase
= mEditorBase
;
147 RefPtr
<Text
> textNode
= mTextNode
;
149 editorBase
->DoInsertText(*textNode
, mOffset
, mDeletedText
, error
);
150 NS_WARNING_ASSERTION(!error
.Failed(), "EditorBase::DoInsertText() failed");
151 return error
.StealNSResult();
154 } // namespace mozilla