| Index: third_party/WebKit/Source/core/editing/VisibleUnits.cpp
|
| diff --git a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
|
| index 674ec43e7e6de1391063bda523020869fc8d9982..f182fe1893e69cbeaba72b4522b6729fb8001fab 100644
|
| --- a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
|
| +++ b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
|
| @@ -816,363 +816,6 @@ EphemeralRange ExpandRangeToSentenceBoundary(const EphemeralRange& range) {
|
| range.EndPosition()));
|
| }
|
|
|
| -static bool NodeIsUserSelectAll(const Node* node) {
|
| - return node && node->GetLayoutObject() &&
|
| - node->GetLayoutObject()->Style()->UserSelect() == EUserSelect::kAll;
|
| -}
|
| -
|
| -template <typename Strategy>
|
| -PositionTemplate<Strategy> StartOfParagraphAlgorithm(
|
| - const PositionTemplate<Strategy>& position,
|
| - EditingBoundaryCrossingRule boundary_crossing_rule) {
|
| - Node* const start_node = position.AnchorNode();
|
| -
|
| - if (!start_node)
|
| - return PositionTemplate<Strategy>();
|
| -
|
| - if (IsRenderedAsNonInlineTableImageOrHR(start_node))
|
| - return PositionTemplate<Strategy>::BeforeNode(start_node);
|
| -
|
| - Element* const start_block = EnclosingBlock(
|
| - PositionTemplate<Strategy>::FirstPositionInOrBeforeNode(start_node),
|
| - kCannotCrossEditingBoundary);
|
| - ContainerNode* const highest_root = HighestEditableRoot(position);
|
| - const bool start_node_is_editable = HasEditableStyle(*start_node);
|
| -
|
| - Node* candidate_node = start_node;
|
| - PositionAnchorType candidate_type = position.AnchorType();
|
| - int candidate_offset = position.ComputeEditingOffset();
|
| -
|
| - Node* previous_node_iterator = start_node;
|
| - while (previous_node_iterator) {
|
| - if (boundary_crossing_rule == kCannotCrossEditingBoundary &&
|
| - !NodeIsUserSelectAll(previous_node_iterator) &&
|
| - HasEditableStyle(*previous_node_iterator) != start_node_is_editable)
|
| - break;
|
| - if (boundary_crossing_rule == kCanSkipOverEditingBoundary) {
|
| - while (previous_node_iterator &&
|
| - HasEditableStyle(*previous_node_iterator) !=
|
| - start_node_is_editable) {
|
| - previous_node_iterator =
|
| - Strategy::PreviousPostOrder(*previous_node_iterator, start_block);
|
| - }
|
| - if (!previous_node_iterator ||
|
| - !previous_node_iterator->IsDescendantOf(highest_root))
|
| - break;
|
| - }
|
| -
|
| - const LayoutItem layout_item =
|
| - LayoutItem(previous_node_iterator->GetLayoutObject());
|
| - if (layout_item.IsNull()) {
|
| - previous_node_iterator =
|
| - Strategy::PreviousPostOrder(*previous_node_iterator, start_block);
|
| - continue;
|
| - }
|
| - const ComputedStyle& style = layout_item.StyleRef();
|
| - if (style.Visibility() != EVisibility::kVisible) {
|
| - previous_node_iterator =
|
| - Strategy::PreviousPostOrder(*previous_node_iterator, start_block);
|
| - continue;
|
| - }
|
| -
|
| - if (layout_item.IsBR() || IsEnclosingBlock(previous_node_iterator))
|
| - break;
|
| -
|
| - if (layout_item.IsText() &&
|
| - ToLayoutText(previous_node_iterator->GetLayoutObject())
|
| - ->ResolvedTextLength()) {
|
| - SECURITY_DCHECK(previous_node_iterator->IsTextNode());
|
| - if (style.PreserveNewline()) {
|
| - LayoutText* text =
|
| - ToLayoutText(previous_node_iterator->GetLayoutObject());
|
| - int index = text->TextLength();
|
| - if (previous_node_iterator == start_node && candidate_offset < index)
|
| - index = max(0, candidate_offset);
|
| - while (--index >= 0) {
|
| - if ((*text)[index] == '\n')
|
| - return PositionTemplate<Strategy>(ToText(previous_node_iterator),
|
| - index + 1);
|
| - }
|
| - }
|
| - candidate_node = previous_node_iterator;
|
| - candidate_type = PositionAnchorType::kOffsetInAnchor;
|
| - candidate_offset = 0;
|
| - previous_node_iterator =
|
| - Strategy::PreviousPostOrder(*previous_node_iterator, start_block);
|
| - } else if (EditingIgnoresContent(*previous_node_iterator) ||
|
| - IsDisplayInsideTable(previous_node_iterator)) {
|
| - candidate_node = previous_node_iterator;
|
| - candidate_type = PositionAnchorType::kBeforeAnchor;
|
| - previous_node_iterator = previous_node_iterator->previousSibling()
|
| - ? previous_node_iterator->previousSibling()
|
| - : Strategy::PreviousPostOrder(
|
| - *previous_node_iterator, start_block);
|
| - } else {
|
| - previous_node_iterator =
|
| - Strategy::PreviousPostOrder(*previous_node_iterator, start_block);
|
| - }
|
| - }
|
| -
|
| - if (candidate_type == PositionAnchorType::kOffsetInAnchor)
|
| - return PositionTemplate<Strategy>(candidate_node, candidate_offset);
|
| -
|
| - return PositionTemplate<Strategy>(candidate_node, candidate_type);
|
| -}
|
| -
|
| -template <typename Strategy>
|
| -VisiblePositionTemplate<Strategy> StartOfParagraphAlgorithm(
|
| - const VisiblePositionTemplate<Strategy>& visible_position,
|
| - EditingBoundaryCrossingRule boundary_crossing_rule) {
|
| - DCHECK(visible_position.IsValid()) << visible_position;
|
| - return CreateVisiblePosition(StartOfParagraphAlgorithm(
|
| - visible_position.DeepEquivalent(), boundary_crossing_rule));
|
| -}
|
| -
|
| -VisiblePosition StartOfParagraph(
|
| - const VisiblePosition& c,
|
| - EditingBoundaryCrossingRule boundary_crossing_rule) {
|
| - return StartOfParagraphAlgorithm<EditingStrategy>(c, boundary_crossing_rule);
|
| -}
|
| -
|
| -VisiblePositionInFlatTree StartOfParagraph(
|
| - const VisiblePositionInFlatTree& c,
|
| - EditingBoundaryCrossingRule boundary_crossing_rule) {
|
| - return StartOfParagraphAlgorithm<EditingInFlatTreeStrategy>(
|
| - c, boundary_crossing_rule);
|
| -}
|
| -
|
| -template <typename Strategy>
|
| -static PositionTemplate<Strategy> EndOfParagraphAlgorithm(
|
| - const PositionTemplate<Strategy>& position,
|
| - EditingBoundaryCrossingRule boundary_crossing_rule) {
|
| - Node* const start_node = position.AnchorNode();
|
| -
|
| - if (!start_node)
|
| - return PositionTemplate<Strategy>();
|
| -
|
| - if (IsRenderedAsNonInlineTableImageOrHR(start_node))
|
| - return PositionTemplate<Strategy>::AfterNode(start_node);
|
| -
|
| - Element* const start_block = EnclosingBlock(
|
| - PositionTemplate<Strategy>::FirstPositionInOrBeforeNode(start_node),
|
| - kCannotCrossEditingBoundary);
|
| - ContainerNode* const highest_root = HighestEditableRoot(position);
|
| - const bool start_node_is_editable = HasEditableStyle(*start_node);
|
| -
|
| - Node* candidate_node = start_node;
|
| - PositionAnchorType candidate_type = position.AnchorType();
|
| - int candidate_offset = position.ComputeEditingOffset();
|
| -
|
| - Node* next_node_iterator = start_node;
|
| - while (next_node_iterator) {
|
| - if (boundary_crossing_rule == kCannotCrossEditingBoundary &&
|
| - !NodeIsUserSelectAll(next_node_iterator) &&
|
| - HasEditableStyle(*next_node_iterator) != start_node_is_editable)
|
| - break;
|
| - if (boundary_crossing_rule == kCanSkipOverEditingBoundary) {
|
| - while (next_node_iterator &&
|
| - HasEditableStyle(*next_node_iterator) != start_node_is_editable)
|
| - next_node_iterator = Strategy::Next(*next_node_iterator, start_block);
|
| - if (!next_node_iterator ||
|
| - !next_node_iterator->IsDescendantOf(highest_root))
|
| - break;
|
| - }
|
| -
|
| - LayoutObject* const layout_object = next_node_iterator->GetLayoutObject();
|
| - if (!layout_object) {
|
| - next_node_iterator = Strategy::Next(*next_node_iterator, start_block);
|
| - continue;
|
| - }
|
| - const ComputedStyle& style = layout_object->StyleRef();
|
| - if (style.Visibility() != EVisibility::kVisible) {
|
| - next_node_iterator = Strategy::Next(*next_node_iterator, start_block);
|
| - continue;
|
| - }
|
| -
|
| - if (layout_object->IsBR() || IsEnclosingBlock(next_node_iterator))
|
| - break;
|
| -
|
| - // FIXME: We avoid returning a position where the layoutObject can't accept
|
| - // the caret.
|
| - if (layout_object->IsText() &&
|
| - ToLayoutText(layout_object)->ResolvedTextLength()) {
|
| - SECURITY_DCHECK(next_node_iterator->IsTextNode());
|
| - LayoutText* const text = ToLayoutText(layout_object);
|
| - if (style.PreserveNewline()) {
|
| - const int length = ToLayoutText(layout_object)->TextLength();
|
| - for (int i = (next_node_iterator == start_node ? candidate_offset : 0);
|
| - i < length; ++i) {
|
| - if ((*text)[i] == '\n')
|
| - return PositionTemplate<Strategy>(ToText(next_node_iterator),
|
| - i + text->TextStartOffset());
|
| - }
|
| - }
|
| -
|
| - candidate_node = next_node_iterator;
|
| - candidate_type = PositionAnchorType::kOffsetInAnchor;
|
| - candidate_offset =
|
| - layout_object->CaretMaxOffset() + text->TextStartOffset();
|
| - next_node_iterator = Strategy::Next(*next_node_iterator, start_block);
|
| - } else if (EditingIgnoresContent(*next_node_iterator) ||
|
| - IsDisplayInsideTable(next_node_iterator)) {
|
| - candidate_node = next_node_iterator;
|
| - candidate_type = PositionAnchorType::kAfterAnchor;
|
| - next_node_iterator =
|
| - Strategy::NextSkippingChildren(*next_node_iterator, start_block);
|
| - } else {
|
| - next_node_iterator = Strategy::Next(*next_node_iterator, start_block);
|
| - }
|
| - }
|
| -
|
| - if (candidate_type == PositionAnchorType::kOffsetInAnchor)
|
| - return PositionTemplate<Strategy>(candidate_node, candidate_offset);
|
| -
|
| - return PositionTemplate<Strategy>(candidate_node, candidate_type);
|
| -}
|
| -
|
| -template <typename Strategy>
|
| -static VisiblePositionTemplate<Strategy> EndOfParagraphAlgorithm(
|
| - const VisiblePositionTemplate<Strategy>& visible_position,
|
| - EditingBoundaryCrossingRule boundary_crossing_rule) {
|
| - DCHECK(visible_position.IsValid()) << visible_position;
|
| - return CreateVisiblePosition(EndOfParagraphAlgorithm(
|
| - visible_position.DeepEquivalent(), boundary_crossing_rule));
|
| -}
|
| -
|
| -VisiblePosition EndOfParagraph(
|
| - const VisiblePosition& c,
|
| - EditingBoundaryCrossingRule boundary_crossing_rule) {
|
| - return EndOfParagraphAlgorithm<EditingStrategy>(c, boundary_crossing_rule);
|
| -}
|
| -
|
| -VisiblePositionInFlatTree EndOfParagraph(
|
| - const VisiblePositionInFlatTree& c,
|
| - EditingBoundaryCrossingRule boundary_crossing_rule) {
|
| - return EndOfParagraphAlgorithm<EditingInFlatTreeStrategy>(
|
| - c, boundary_crossing_rule);
|
| -}
|
| -
|
| -// FIXME: isStartOfParagraph(startOfNextParagraph(pos)) is not always true
|
| -VisiblePosition StartOfNextParagraph(const VisiblePosition& visible_position) {
|
| - DCHECK(visible_position.IsValid()) << visible_position;
|
| - VisiblePosition paragraph_end(
|
| - EndOfParagraph(visible_position, kCanSkipOverEditingBoundary));
|
| - VisiblePosition after_paragraph_end(
|
| - NextPositionOf(paragraph_end, kCannotCrossEditingBoundary));
|
| - // The position after the last position in the last cell of a table
|
| - // is not the start of the next paragraph.
|
| - if (TableElementJustBefore(after_paragraph_end))
|
| - return NextPositionOf(after_paragraph_end, kCannotCrossEditingBoundary);
|
| - return after_paragraph_end;
|
| -}
|
| -
|
| -// FIXME: isStartOfParagraph(startOfNextParagraph(pos)) is not always true
|
| -bool InSameParagraph(const VisiblePosition& a,
|
| - const VisiblePosition& b,
|
| - EditingBoundaryCrossingRule boundary_crossing_rule) {
|
| - DCHECK(a.IsValid()) << a;
|
| - DCHECK(b.IsValid()) << b;
|
| - return a.IsNotNull() &&
|
| - StartOfParagraph(a, boundary_crossing_rule).DeepEquivalent() ==
|
| - StartOfParagraph(b, boundary_crossing_rule).DeepEquivalent();
|
| -}
|
| -
|
| -template <typename Strategy>
|
| -static bool IsStartOfParagraphAlgorithm(
|
| - const VisiblePositionTemplate<Strategy>& pos,
|
| - EditingBoundaryCrossingRule boundary_crossing_rule) {
|
| - DCHECK(pos.IsValid()) << pos;
|
| - return pos.IsNotNull() &&
|
| - pos.DeepEquivalent() ==
|
| - StartOfParagraph(pos, boundary_crossing_rule).DeepEquivalent();
|
| -}
|
| -
|
| -bool IsStartOfParagraph(const VisiblePosition& pos,
|
| - EditingBoundaryCrossingRule boundary_crossing_rule) {
|
| - return IsStartOfParagraphAlgorithm<EditingStrategy>(pos,
|
| - boundary_crossing_rule);
|
| -}
|
| -
|
| -bool IsStartOfParagraph(const VisiblePositionInFlatTree& pos,
|
| - EditingBoundaryCrossingRule boundary_crossing_rule) {
|
| - return IsStartOfParagraphAlgorithm<EditingInFlatTreeStrategy>(
|
| - pos, boundary_crossing_rule);
|
| -}
|
| -
|
| -template <typename Strategy>
|
| -static bool IsEndOfParagraphAlgorithm(
|
| - const VisiblePositionTemplate<Strategy>& pos,
|
| - EditingBoundaryCrossingRule boundary_crossing_rule) {
|
| - DCHECK(pos.IsValid()) << pos;
|
| - return pos.IsNotNull() &&
|
| - pos.DeepEquivalent() ==
|
| - EndOfParagraph(pos, boundary_crossing_rule).DeepEquivalent();
|
| -}
|
| -
|
| -bool IsEndOfParagraph(const VisiblePosition& pos,
|
| - EditingBoundaryCrossingRule boundary_crossing_rule) {
|
| - return IsEndOfParagraphAlgorithm<EditingStrategy>(pos,
|
| - boundary_crossing_rule);
|
| -}
|
| -
|
| -bool IsEndOfParagraph(const VisiblePositionInFlatTree& pos,
|
| - EditingBoundaryCrossingRule boundary_crossing_rule) {
|
| - return IsEndOfParagraphAlgorithm<EditingInFlatTreeStrategy>(
|
| - pos, boundary_crossing_rule);
|
| -}
|
| -
|
| -VisiblePosition PreviousParagraphPosition(const VisiblePosition& p,
|
| - LayoutUnit x) {
|
| - DCHECK(p.IsValid()) << p;
|
| - VisiblePosition pos = p;
|
| - do {
|
| - VisiblePosition n = PreviousLinePosition(pos, x);
|
| - if (n.IsNull() || n.DeepEquivalent() == pos.DeepEquivalent())
|
| - break;
|
| - pos = n;
|
| - } while (InSameParagraph(p, pos));
|
| - return pos;
|
| -}
|
| -
|
| -VisiblePosition NextParagraphPosition(const VisiblePosition& p, LayoutUnit x) {
|
| - DCHECK(p.IsValid()) << p;
|
| - VisiblePosition pos = p;
|
| - do {
|
| - VisiblePosition n = NextLinePosition(pos, x);
|
| - if (n.IsNull() || n.DeepEquivalent() == pos.DeepEquivalent())
|
| - break;
|
| - pos = n;
|
| - } while (InSameParagraph(p, pos));
|
| - return pos;
|
| -}
|
| -
|
| -EphemeralRange ExpandToParagraphBoundary(const EphemeralRange& range) {
|
| - const VisiblePosition& start = CreateVisiblePosition(range.StartPosition());
|
| - DCHECK(start.IsNotNull()) << range.StartPosition();
|
| - const Position& paragraph_start = StartOfParagraph(start).DeepEquivalent();
|
| - DCHECK(paragraph_start.IsNotNull()) << range.StartPosition();
|
| -
|
| - const VisiblePosition& end = CreateVisiblePosition(range.EndPosition());
|
| - DCHECK(end.IsNotNull()) << range.EndPosition();
|
| - const Position& paragraph_end = EndOfParagraph(end).DeepEquivalent();
|
| - DCHECK(paragraph_end.IsNotNull()) << range.EndPosition();
|
| -
|
| - // TODO(xiaochengh): There are some cases (crbug.com/640112) where we get
|
| - // |paragraphStart > paragraphEnd|, which is the reason we cannot directly
|
| - // return |EphemeralRange(paragraphStart, paragraphEnd)|. This is not
|
| - // desired, though. We should do more investigation to ensure that why
|
| - // |paragraphStart <= paragraphEnd| is violated.
|
| - const Position& result_start =
|
| - paragraph_start.IsNotNull() && paragraph_start <= range.StartPosition()
|
| - ? paragraph_start
|
| - : range.StartPosition();
|
| - const Position& result_end =
|
| - paragraph_end.IsNotNull() && paragraph_end >= range.EndPosition()
|
| - ? paragraph_end
|
| - : range.EndPosition();
|
| - return EphemeralRange(result_start, result_end);
|
| -}
|
| -
|
| // ---------
|
|
|
| VisiblePosition StartOfBlock(const VisiblePosition& visible_position,
|
|
|