Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/editor/libeditor/DeleteTextTransaction.cpp
Line
Count
Source (jump to first uncovered line)
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/. */
5
6
#include "DeleteTextTransaction.h"
7
8
#include "mozilla/Assertions.h"
9
#include "mozilla/EditorBase.h"
10
#include "mozilla/EditorDOMPoint.h"
11
#include "mozilla/SelectionState.h"
12
#include "mozilla/dom/Selection.h"
13
#include "nsDebug.h"
14
#include "nsError.h"
15
#include "nsIEditor.h"
16
#include "nsISupportsImpl.h"
17
#include "nsAString.h"
18
19
namespace mozilla {
20
21
using namespace dom;
22
23
// static
24
already_AddRefed<DeleteTextTransaction>
25
DeleteTextTransaction::MaybeCreate(EditorBase& aEditorBase,
26
                                   CharacterData& aCharData,
27
                                   uint32_t aOffset,
28
                                   uint32_t aLengthToDelete)
29
0
{
30
0
  RefPtr<DeleteTextTransaction> transaction =
31
0
    new DeleteTextTransaction(aEditorBase, aCharData, aOffset, aLengthToDelete);
32
0
  return transaction.forget();
33
0
}
34
35
// static
36
already_AddRefed<DeleteTextTransaction>
37
DeleteTextTransaction::MaybeCreateForPreviousCharacter(
38
                         EditorBase& aEditorBase,
39
                         CharacterData& aCharData,
40
                         uint32_t aOffset)
41
0
{
42
0
  if (NS_WARN_IF(!aOffset)) {
43
0
    return nullptr;
44
0
  }
45
0
46
0
  nsAutoString data;
47
0
  aCharData.GetData(data);
48
0
  if (NS_WARN_IF(data.IsEmpty())) {
49
0
    return nullptr;
50
0
  }
51
0
52
0
  uint32_t length = 1;
53
0
  uint32_t offset = aOffset - 1;
54
0
  if (offset &&
55
0
      NS_IS_LOW_SURROGATE(data[offset]) &&
56
0
      NS_IS_HIGH_SURROGATE(data[offset - 1])) {
57
0
    ++length;
58
0
    --offset;
59
0
  }
60
0
  return DeleteTextTransaction::MaybeCreate(aEditorBase, aCharData,
61
0
                                            offset, length);
62
0
}
63
64
// static
65
already_AddRefed<DeleteTextTransaction>
66
DeleteTextTransaction::MaybeCreateForNextCharacter(
67
                         EditorBase& aEditorBase,
68
                         CharacterData& aCharData,
69
                         uint32_t aOffset)
70
0
{
71
0
  nsAutoString data;
72
0
  aCharData.GetData(data);
73
0
  if (NS_WARN_IF(aOffset >= data.Length()) ||
74
0
      NS_WARN_IF(data.IsEmpty())) {
75
0
    return nullptr;
76
0
  }
77
0
78
0
  uint32_t length = 1;
79
0
  if (aOffset + 1 < data.Length() &&
80
0
      NS_IS_HIGH_SURROGATE(data[aOffset]) &&
81
0
      NS_IS_LOW_SURROGATE(data[aOffset + 1])) {
82
0
    ++length;
83
0
  }
84
0
  return DeleteTextTransaction::MaybeCreate(aEditorBase, aCharData,
85
0
                                            aOffset, length);
86
0
}
87
88
DeleteTextTransaction::DeleteTextTransaction(
89
                         EditorBase& aEditorBase,
90
                         CharacterData& aCharData,
91
                         uint32_t aOffset,
92
                         uint32_t aLengthToDelete)
93
  : mEditorBase(&aEditorBase)
94
  , mCharData(&aCharData)
95
  , mOffset(aOffset)
96
  , mLengthToDelete(aLengthToDelete)
97
0
{
98
0
  NS_ASSERTION(mCharData->Length() >= aOffset + aLengthToDelete,
99
0
               "Trying to delete more characters than in node");
100
0
}
101
102
NS_IMPL_CYCLE_COLLECTION_INHERITED(DeleteTextTransaction, EditTransactionBase,
103
                                   mEditorBase,
104
                                   mCharData)
105
106
0
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DeleteTextTransaction)
107
0
NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
108
109
bool
110
DeleteTextTransaction::CanDoIt() const
111
0
{
112
0
  if (NS_WARN_IF(!mCharData) || NS_WARN_IF(!mEditorBase)) {
113
0
    return false;
114
0
  }
115
0
  return mEditorBase->IsModifiableNode(*mCharData);
116
0
}
117
118
NS_IMETHODIMP
119
DeleteTextTransaction::DoTransaction()
120
0
{
121
0
  if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mCharData)) {
122
0
    return NS_ERROR_NOT_AVAILABLE;
123
0
  }
124
0
125
0
  // Get the text that we're about to delete
126
0
  ErrorResult err;
127
0
  mCharData->SubstringData(mOffset, mLengthToDelete, mDeletedText, err);
128
0
  if (NS_WARN_IF(err.Failed())) {
129
0
    return err.StealNSResult();
130
0
  }
131
0
132
0
  mCharData->DeleteData(mOffset, mLengthToDelete, err);
133
0
  if (NS_WARN_IF(err.Failed())) {
134
0
    return err.StealNSResult();
135
0
  }
136
0
137
0
  mEditorBase->RangeUpdaterRef().
138
0
                 SelAdjDeleteText(mCharData, mOffset, mLengthToDelete);
139
0
140
0
  if (!mEditorBase->AllowsTransactionsToChangeSelection()) {
141
0
    return NS_OK;
142
0
  }
143
0
144
0
  RefPtr<Selection> selection = mEditorBase->GetSelection();
145
0
  if (NS_WARN_IF(!selection)) {
146
0
    return NS_ERROR_FAILURE;
147
0
  }
148
0
  ErrorResult error;
149
0
  selection->Collapse(EditorRawDOMPoint(mCharData, mOffset), error);
150
0
  if (NS_WARN_IF(error.Failed())) {
151
0
    return error.StealNSResult();
152
0
  }
153
0
  return NS_OK;
154
0
}
155
156
//XXX: We may want to store the selection state and restore it properly.  Was
157
//     it an insertion point or an extended selection?
158
NS_IMETHODIMP
159
DeleteTextTransaction::UndoTransaction()
160
0
{
161
0
  if (NS_WARN_IF(!mCharData)) {
162
0
    return NS_ERROR_NOT_INITIALIZED;
163
0
  }
164
0
  ErrorResult rv;
165
0
  mCharData->InsertData(mOffset, mDeletedText, rv);
166
0
  return rv.StealNSResult();
167
0
}
168
169
} // namespace mozilla