Bug 1842773 - Part 5: Add ArrayBuffer.prototype.{maxByteLength,resizable} getters...
[gecko.git] / dom / base / Text.cpp
bloba6cc317d4dca4e39acbaf18a6c0902d6c5319bca
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/. */
7 #include "mozilla/dom/Text.h"
8 #include "nsTextNode.h"
9 #include "mozAutoDocUpdate.h"
11 namespace mozilla::dom {
13 already_AddRefed<Text> Text::SplitText(uint32_t aOffset, ErrorResult& aRv) {
14 nsAutoString cutText;
15 const uint32_t length = TextLength();
17 if (aOffset > length) {
18 aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
19 return nullptr;
22 const uint32_t cutStartOffset = aOffset;
23 const uint32_t cutLength = length - aOffset;
24 SubstringData(cutStartOffset, cutLength, cutText, aRv);
25 if (aRv.Failed()) {
26 return nullptr;
29 Document* document = GetComposedDoc();
30 mozAutoDocUpdate updateBatch(document, true);
32 // Use Clone for creating the new node so that the new node is of same class
33 // as this node!
34 RefPtr<CharacterData> clone = CloneDataNode(mNodeInfo, false);
35 MOZ_ASSERT(clone && clone->IsText());
36 RefPtr<Text> newContent = static_cast<Text*>(clone.get());
38 // nsRange expects the CharacterDataChanged notification is followed
39 // by an insertion of |newContent|. If you change this code,
40 // make sure you make the appropriate changes in nsRange.
41 newContent->SetText(cutText, true); // XXX should be false?
43 CharacterDataChangeInfo::Details details = {
44 CharacterDataChangeInfo::Details::eSplit, newContent};
45 nsresult rv =
46 SetTextInternal(cutStartOffset, cutLength, nullptr, 0, true, &details);
47 if (NS_FAILED(rv)) {
48 aRv.Throw(rv);
49 return nullptr;
52 nsCOMPtr<nsINode> parent = GetParentNode();
53 if (parent) {
54 nsCOMPtr<nsIContent> beforeNode = GetNextSibling();
55 parent->InsertChildBefore(newContent, beforeNode, true, IgnoreErrors());
58 return newContent.forget();
61 static Text* FirstLogicallyAdjacentTextNode(Text* aNode) {
62 do {
63 nsIContent* sibling = aNode->GetPreviousSibling();
64 if (!sibling || !sibling->IsText()) {
65 return aNode;
67 aNode = static_cast<Text*>(sibling);
68 } while (1); // Must run out of previous siblings eventually!
71 static Text* LastLogicallyAdjacentTextNode(Text* aNode) {
72 do {
73 nsIContent* sibling = aNode->GetNextSibling();
74 if (!sibling || !sibling->IsText()) {
75 return aNode;
78 aNode = static_cast<Text*>(sibling);
79 } while (1); // Must run out of next siblings eventually!
82 void Text::GetWholeText(nsAString& aWholeText) {
83 nsIContent* parent = GetParent();
85 // Handle parent-less nodes
86 if (!parent) {
87 GetData(aWholeText);
88 return;
91 Text* first = FirstLogicallyAdjacentTextNode(this);
92 Text* last = LastLogicallyAdjacentTextNode(this);
94 aWholeText.Truncate();
96 nsAutoString tmp;
98 while (true) {
99 first->GetData(tmp);
100 aWholeText.Append(tmp);
102 if (first == last) {
103 break;
106 nsIContent* next = first->GetNextSibling();
107 MOZ_ASSERT(next && next->IsText(),
108 "How did we run out of text before hitting `last`?");
109 first = static_cast<Text*>(next);
113 /* static */
114 already_AddRefed<Text> Text::Constructor(const GlobalObject& aGlobal,
115 const nsAString& aData,
116 ErrorResult& aRv) {
117 nsCOMPtr<nsPIDOMWindowInner> window =
118 do_QueryInterface(aGlobal.GetAsSupports());
119 if (!window || !window->GetDoc()) {
120 aRv.Throw(NS_ERROR_FAILURE);
121 return nullptr;
124 return window->GetDoc()->CreateTextNode(aData);
127 bool Text::HasTextForTranslation() {
128 if (mText.Is2b()) {
129 // The fragment contains non-8bit characters which means there
130 // was at least one "interesting" character to trigger non-8bit.
131 return true;
134 if (HasFlag(NS_CACHED_TEXT_IS_ONLY_WHITESPACE) &&
135 HasFlag(NS_TEXT_IS_ONLY_WHITESPACE)) {
136 return false;
139 const char* cp = mText.Get1b();
140 const char* end = cp + mText.GetLength();
142 unsigned char ch;
143 for (; cp < end; cp++) {
144 ch = *cp;
146 // These are the characters that are letters
147 // in the first 256 UTF-8 codepoints.
148 if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
149 (ch >= 192 && ch <= 214) || (ch >= 216 && ch <= 246) || (ch >= 248)) {
150 return true;
154 return false;
157 } // namespace mozilla::dom