diff options
Diffstat (limited to 'dom/base/Text.cpp')
-rw-r--r-- | dom/base/Text.cpp | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/dom/base/Text.cpp b/dom/base/Text.cpp new file mode 100644 index 0000000000..a6cc317d4d --- /dev/null +++ b/dom/base/Text.cpp @@ -0,0 +1,157 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/Text.h" +#include "nsTextNode.h" +#include "mozAutoDocUpdate.h" + +namespace mozilla::dom { + +already_AddRefed<Text> Text::SplitText(uint32_t aOffset, ErrorResult& aRv) { + nsAutoString cutText; + const uint32_t length = TextLength(); + + if (aOffset > length) { + aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); + return nullptr; + } + + const uint32_t cutStartOffset = aOffset; + const uint32_t cutLength = length - aOffset; + SubstringData(cutStartOffset, cutLength, cutText, aRv); + if (aRv.Failed()) { + return nullptr; + } + + Document* document = GetComposedDoc(); + mozAutoDocUpdate updateBatch(document, true); + + // Use Clone for creating the new node so that the new node is of same class + // as this node! + RefPtr<CharacterData> clone = CloneDataNode(mNodeInfo, false); + MOZ_ASSERT(clone && clone->IsText()); + RefPtr<Text> newContent = static_cast<Text*>(clone.get()); + + // nsRange expects the CharacterDataChanged notification is followed + // by an insertion of |newContent|. If you change this code, + // make sure you make the appropriate changes in nsRange. + newContent->SetText(cutText, true); // XXX should be false? + + CharacterDataChangeInfo::Details details = { + CharacterDataChangeInfo::Details::eSplit, newContent}; + nsresult rv = + SetTextInternal(cutStartOffset, cutLength, nullptr, 0, true, &details); + if (NS_FAILED(rv)) { + aRv.Throw(rv); + return nullptr; + } + + nsCOMPtr<nsINode> parent = GetParentNode(); + if (parent) { + nsCOMPtr<nsIContent> beforeNode = GetNextSibling(); + parent->InsertChildBefore(newContent, beforeNode, true, IgnoreErrors()); + } + + return newContent.forget(); +} + +static Text* FirstLogicallyAdjacentTextNode(Text* aNode) { + do { + nsIContent* sibling = aNode->GetPreviousSibling(); + if (!sibling || !sibling->IsText()) { + return aNode; + } + aNode = static_cast<Text*>(sibling); + } while (1); // Must run out of previous siblings eventually! +} + +static Text* LastLogicallyAdjacentTextNode(Text* aNode) { + do { + nsIContent* sibling = aNode->GetNextSibling(); + if (!sibling || !sibling->IsText()) { + return aNode; + } + + aNode = static_cast<Text*>(sibling); + } while (1); // Must run out of next siblings eventually! +} + +void Text::GetWholeText(nsAString& aWholeText) { + nsIContent* parent = GetParent(); + + // Handle parent-less nodes + if (!parent) { + GetData(aWholeText); + return; + } + + Text* first = FirstLogicallyAdjacentTextNode(this); + Text* last = LastLogicallyAdjacentTextNode(this); + + aWholeText.Truncate(); + + nsAutoString tmp; + + while (true) { + first->GetData(tmp); + aWholeText.Append(tmp); + + if (first == last) { + break; + } + + nsIContent* next = first->GetNextSibling(); + MOZ_ASSERT(next && next->IsText(), + "How did we run out of text before hitting `last`?"); + first = static_cast<Text*>(next); + } +} + +/* static */ +already_AddRefed<Text> Text::Constructor(const GlobalObject& aGlobal, + const nsAString& aData, + ErrorResult& aRv) { + nsCOMPtr<nsPIDOMWindowInner> window = + do_QueryInterface(aGlobal.GetAsSupports()); + if (!window || !window->GetDoc()) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + return window->GetDoc()->CreateTextNode(aData); +} + +bool Text::HasTextForTranslation() { + if (mText.Is2b()) { + // The fragment contains non-8bit characters which means there + // was at least one "interesting" character to trigger non-8bit. + return true; + } + + if (HasFlag(NS_CACHED_TEXT_IS_ONLY_WHITESPACE) && + HasFlag(NS_TEXT_IS_ONLY_WHITESPACE)) { + return false; + } + + const char* cp = mText.Get1b(); + const char* end = cp + mText.GetLength(); + + unsigned char ch; + for (; cp < end; cp++) { + ch = *cp; + + // These are the characters that are letters + // in the first 256 UTF-8 codepoints. + if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || + (ch >= 192 && ch <= 214) || (ch >= 216 && ch <= 246) || (ch >= 248)) { + return true; + } + } + + return false; +} + +} // namespace mozilla::dom |