tor-browser

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

CaretAssociationHint.cpp (2994B)


      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 "CaretAssociationHint.h"
      8 
      9 #include "mozilla/RangeBoundary.h"            // for RangeBoundaryBase
     10 #include "mozilla/SelectionMovementUtils.h"   // for CaretFrameData
     11 #include "mozilla/intl/BidiEmbeddingLevel.h"  // for BidiEmbeddingLevel
     12 #include "nsCaret.h"                          // for nsCaret
     13 #include "nsIContent.h"                       // for nsIContent
     14 #include "nsIFrame.h"                         // for nsIFrame
     15 #include "nsTextFrame.h"                      // for nsTextFrame
     16 
     17 namespace mozilla {
     18 
     19 template CaretAssociationHint ComputeCaretAssociationHint(
     20    CaretAssociationHint aDefault, intl::BidiEmbeddingLevel aBidiLevel,
     21    const RangeBoundary& aCaretPoint);
     22 template CaretAssociationHint ComputeCaretAssociationHint(
     23    CaretAssociationHint aDefault, intl::BidiEmbeddingLevel aBidiLevel,
     24    const RawRangeBoundary& aCaretPoint);
     25 
     26 template <typename PT, typename CT>
     27 CaretAssociationHint ComputeCaretAssociationHint(
     28    CaretAssociationHint aDefault, intl::BidiEmbeddingLevel aBidiLevel,
     29    const RangeBoundaryBase<PT, CT>& aCaretPoint) {
     30  MOZ_ASSERT(aCaretPoint.IsSetAndValid());
     31  if (aDefault != CaretAssociationHint::Before ||
     32      !aCaretPoint.GetContainer()->IsContent()) {
     33    return aDefault;
     34  }
     35  const nsCaret::CaretPosition pos{
     36      aCaretPoint.GetContainer(),
     37      static_cast<int32_t>(*aCaretPoint.Offset(
     38          RangeBoundaryBase<PT, CT>::OffsetFilter::kValidOffsets)),
     39      aDefault, aBidiLevel};
     40  CaretFrameData frameData = nsCaret::GetFrameAndOffset(pos);
     41  nsTextFrame* f = do_QueryFrame(frameData.mFrame);
     42  if (f && f->IsAtEndOfLine() && f->HasSignificantTerminalNewline()) {
     43    // RangeBoundaryBase<PT, CT>::Offset() causes computing offset if it's not
     44    // been done yet.  However, it's called only when the container is a text
     45    // node.  In such case, offset has always been set since it cannot have
     46    // any children.  So, this doesn't cause computing offset with expensive
     47    // method, nsINode::ComputeIndexOf().
     48    const bool caretPointIsAtEndOfFrame =
     49        aCaretPoint.GetContainer() == f->GetContent() &&
     50        f->GetContentEnd() ==
     51            static_cast<int32_t>(*aCaretPoint.Offset(
     52                RangeBoundaryBase<PT, CT>::OffsetFilter::kValidOffsets));
     53    const bool caretPointIsImmediatelyAfterFrameContent =
     54        aCaretPoint.GetContainer() == f->GetContent()->GetParentNode() &&
     55        f->GetContent() == aCaretPoint.GetPreviousSiblingOfChildAtOffset();
     56    if (caretPointIsAtEndOfFrame || caretPointIsImmediatelyAfterFrameContent) {
     57      return CaretAssociationHint::After;
     58    }
     59  }
     60  return frameData ? frameData.mHint : aDefault;
     61 }
     62 
     63 }  // namespace mozilla