Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/base/Text.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "mozilla/dom/Text.h"
8
#include "nsTextNode.h"
9
#include "mozAutoDocUpdate.h"
10
11
namespace mozilla {
12
namespace dom {
13
14
already_AddRefed<Text>
15
Text::SplitText(uint32_t aOffset, ErrorResult& aRv)
16
0
{
17
0
  nsAutoString cutText;
18
0
  uint32_t length = TextLength();
19
0
20
0
  if (aOffset > length) {
21
0
    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
22
0
    return nullptr;
23
0
  }
24
0
25
0
  uint32_t cutStartOffset = aOffset;
26
0
  uint32_t cutLength = length - aOffset;
27
0
  SubstringData(cutStartOffset, cutLength, cutText, aRv);
28
0
  if (aRv.Failed()) {
29
0
    return nullptr;
30
0
  }
31
0
32
0
  nsIDocument* document = GetComposedDoc();
33
0
  mozAutoDocUpdate updateBatch(document, true);
34
0
35
0
  // Use Clone for creating the new node so that the new node is of same class
36
0
  // as this node!
37
0
  RefPtr<CharacterData> clone = CloneDataNode(mNodeInfo, false);
38
0
  MOZ_ASSERT(clone && clone->IsText());
39
0
  RefPtr<Text> newContent = static_cast<Text*>(clone.get());
40
0
41
0
  // nsRange expects the CharacterDataChanged notification is followed
42
0
  // by an insertion of |newContent|. If you change this code,
43
0
  // make sure you make the appropriate changes in nsRange.
44
0
  newContent->SetText(cutText, true); // XXX should be false?
45
0
46
0
  CharacterDataChangeInfo::Details details = {
47
0
    CharacterDataChangeInfo::Details::eSplit, newContent
48
0
  };
49
0
  nsresult rv = SetTextInternal(cutStartOffset, cutLength, nullptr, 0, true,
50
0
                                &details);
51
0
  if (NS_FAILED(rv)) {
52
0
    aRv.Throw(rv);
53
0
    return nullptr;
54
0
  }
55
0
56
0
  nsCOMPtr<nsINode> parent = GetParentNode();
57
0
  if (parent) {
58
0
    nsCOMPtr<nsIContent> beforeNode = GetNextSibling();
59
0
    parent->InsertChildBefore(newContent, beforeNode, true);
60
0
  }
61
0
62
0
  return newContent.forget();
63
0
}
64
65
static Text*
66
FirstLogicallyAdjacentTextNode(Text* aNode)
67
0
{
68
0
  do {
69
0
    nsIContent* sibling = aNode->GetPreviousSibling();
70
0
    if (!sibling || !sibling->IsText()) {
71
0
      return aNode;
72
0
    }
73
0
    aNode = static_cast<Text*>(sibling);
74
0
  } while (1);  // Must run out of previous siblings eventually!
75
0
}
76
77
static Text*
78
LastLogicallyAdjacentTextNode(Text* aNode)
79
0
{
80
0
  do {
81
0
    nsIContent* sibling = aNode->GetNextSibling();
82
0
    if (!sibling || !sibling->IsText()) {
83
0
      return aNode;
84
0
    }
85
0
86
0
    aNode = static_cast<Text*>(sibling);
87
0
  } while (1); // Must run out of next siblings eventually!
88
0
}
89
90
void
91
Text::GetWholeText(nsAString& aWholeText,
92
                   ErrorResult& aRv)
93
0
{
94
0
  nsIContent* parent = GetParent();
95
0
96
0
  // Handle parent-less nodes
97
0
  if (!parent) {
98
0
    GetData(aWholeText);
99
0
    return;
100
0
  }
101
0
102
0
  int32_t index = parent->ComputeIndexOf(this);
103
0
  NS_WARNING_ASSERTION(index >= 0,
104
0
                       "Trying to use .wholeText with an anonymous"
105
0
                       "text node child of a binding parent?");
106
0
  if (NS_WARN_IF(index < 0)) {
107
0
    aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
108
0
    return;
109
0
  }
110
0
111
0
  Text* first = FirstLogicallyAdjacentTextNode(this);
112
0
  Text* last = LastLogicallyAdjacentTextNode(this);
113
0
114
0
  aWholeText.Truncate();
115
0
116
0
  nsAutoString tmp;
117
0
118
0
  while (true) {
119
0
    first->GetData(tmp);
120
0
    aWholeText.Append(tmp);
121
0
122
0
    if (first == last) {
123
0
      break;
124
0
    }
125
0
126
0
    nsIContent* next = first->GetNextSibling();
127
0
    MOZ_ASSERT(next && next->IsText(),
128
0
               "How did we run out of text before hitting `last`?");
129
0
    first = static_cast<Text*>(next);
130
0
  }
131
0
}
132
133
/* static */ already_AddRefed<Text>
134
Text::Constructor(const GlobalObject& aGlobal,
135
                  const nsAString& aData, ErrorResult& aRv)
136
0
{
137
0
  nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports());
138
0
  if (!window || !window->GetDoc()) {
139
0
    aRv.Throw(NS_ERROR_FAILURE);
140
0
    return nullptr;
141
0
  }
142
0
143
0
  return window->GetDoc()->CreateTextNode(aData);
144
0
}
145
146
bool
147
Text::HasTextForTranslation()
148
0
{
149
0
  if (mText.Is2b()) {
150
0
    // The fragment contains non-8bit characters which means there
151
0
    // was at least one "interesting" character to trigger non-8bit.
152
0
    return true;
153
0
  }
154
0
155
0
  if (HasFlag(NS_CACHED_TEXT_IS_ONLY_WHITESPACE) &&
156
0
      HasFlag(NS_TEXT_IS_ONLY_WHITESPACE)) {
157
0
    return false;
158
0
  }
159
0
160
0
  const char* cp = mText.Get1b();
161
0
  const char* end = cp + mText.GetLength();
162
0
163
0
  unsigned char ch;
164
0
  for (; cp < end; cp++) {
165
0
    ch = *cp;
166
0
167
0
    // These are the characters that are letters
168
0
    // in the first 256 UTF-8 codepoints.
169
0
    if ((ch >= 'a' && ch <= 'z') ||
170
0
       (ch >= 'A' && ch <= 'Z') ||
171
0
       (ch >= 192 && ch <= 214) ||
172
0
       (ch >= 216 && ch <= 246) ||
173
0
       (ch >= 248)) {
174
0
      return true;
175
0
    }
176
0
  }
177
0
178
0
  return false;
179
0
}
180
181
} // namespace dom
182
} // namespace mozilla