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