tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Text.cpp (5009B)


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