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
) {
15 const uint32_t length
= TextLength();
17 if (aOffset
> length
) {
18 aRv
.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR
);
22 const uint32_t cutStartOffset
= aOffset
;
23 const uint32_t cutLength
= length
- aOffset
;
24 SubstringData(cutStartOffset
, cutLength
, cutText
, aRv
);
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
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
};
46 SetTextInternal(cutStartOffset
, cutLength
, nullptr, 0, true, &details
);
52 nsCOMPtr
<nsINode
> parent
= GetParentNode();
54 nsCOMPtr
<nsIContent
> beforeNode
= GetNextSibling();
55 parent
->InsertChildBefore(newContent
, beforeNode
, true, IgnoreErrors());
58 return newContent
.forget();
61 static Text
* FirstLogicallyAdjacentTextNode(Text
* aNode
) {
63 nsIContent
* sibling
= aNode
->GetPreviousSibling();
64 if (!sibling
|| !sibling
->IsText()) {
67 aNode
= static_cast<Text
*>(sibling
);
68 } while (1); // Must run out of previous siblings eventually!
71 static Text
* LastLogicallyAdjacentTextNode(Text
* aNode
) {
73 nsIContent
* sibling
= aNode
->GetNextSibling();
74 if (!sibling
|| !sibling
->IsText()) {
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
91 Text
* first
= FirstLogicallyAdjacentTextNode(this);
92 Text
* last
= LastLogicallyAdjacentTextNode(this);
94 aWholeText
.Truncate();
100 aWholeText
.Append(tmp
);
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
);
114 already_AddRefed
<Text
> Text::Constructor(const GlobalObject
& aGlobal
,
115 const nsAString
& aData
,
117 nsCOMPtr
<nsPIDOMWindowInner
> window
=
118 do_QueryInterface(aGlobal
.GetAsSupports());
119 if (!window
|| !window
->GetDoc()) {
120 aRv
.Throw(NS_ERROR_FAILURE
);
124 return window
->GetDoc()->CreateTextNode(aData
);
127 bool Text::HasTextForTranslation() {
129 // The fragment contains non-8bit characters which means there
130 // was at least one "interesting" character to trigger non-8bit.
134 if (HasFlag(NS_CACHED_TEXT_IS_ONLY_WHITESPACE
) &&
135 HasFlag(NS_TEXT_IS_ONLY_WHITESPACE
)) {
139 const char* cp
= mText
.Get1b();
140 const char* end
= cp
+ mText
.GetLength();
143 for (; cp
< end
; 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)) {
157 } // namespace mozilla::dom