| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. | 2 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 bool needsLayoutTreeUpdate(const Node& node) | 84 bool needsLayoutTreeUpdate(const Node& node) |
| 85 { | 85 { |
| 86 const Document& document = node.document(); | 86 const Document& document = node.document(); |
| 87 if (document.needsLayoutTreeUpdate()) | 87 if (document.needsLayoutTreeUpdate()) |
| 88 return true; | 88 return true; |
| 89 // TODO(yosin): We should make |document::needsLayoutTreeUpdate()| to | 89 // TODO(yosin): We should make |document::needsLayoutTreeUpdate()| to |
| 90 // check |LayoutView::needsLayout()|. | 90 // check |LayoutView::needsLayout()|. |
| 91 return document.view() && document.view()->needsLayout(); | 91 return document.view() && document.view()->needsLayout(); |
| 92 } | 92 } |
| 93 | 93 |
| 94 bool needsLayoutTreeUpdate(const Position& position) | 94 template <typename PositionType> |
| 95 static bool needsLayoutTreeUpdateAlgorithm(const PositionType& position) |
| 95 { | 96 { |
| 96 const Node* node = position.anchorNode(); | 97 const Node* node = position.anchorNode(); |
| 97 if (!node) | 98 if (!node) |
| 98 return false; | 99 return false; |
| 99 return needsLayoutTreeUpdate(*node); | 100 return needsLayoutTreeUpdate(*node); |
| 100 } | 101 } |
| 101 | 102 |
| 103 bool needsLayoutTreeUpdate(const Position& position) |
| 104 { |
| 105 return needsLayoutTreeUpdateAlgorithm<Position>(position); |
| 106 } |
| 107 |
| 108 bool needsLayoutTreeUpdate(const PositionInFlatTree& position) |
| 109 { |
| 110 return needsLayoutTreeUpdateAlgorithm<PositionInFlatTree>(position); |
| 111 } |
| 112 |
| 102 // Atomic means that the node has no children, or has children which are ignored
for the | 113 // Atomic means that the node has no children, or has children which are ignored
for the |
| 103 // purposes of editing. | 114 // purposes of editing. |
| 104 bool isAtomicNode(const Node *node) | 115 bool isAtomicNode(const Node *node) |
| 105 { | 116 { |
| 106 return node && (!node->hasChildren() || editingIgnoresContent(node)); | 117 return node && (!node->hasChildren() || editingIgnoresContent(node)); |
| 107 } | 118 } |
| 108 | 119 |
| 109 template <typename Traversal> | 120 template <typename Traversal> |
| 110 static int comparePositions(Node* containerA, int offsetA, Node* containerB, int
offsetB, bool* disconnected) | 121 static int comparePositions(Node* containerA, int offsetA, Node* containerB, int
offsetB, bool* disconnected) |
| 111 { | 122 { |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 526 return previousVisuallyDistinctCandidateAlgorithm<EditingStrategy>(position)
; | 537 return previousVisuallyDistinctCandidateAlgorithm<EditingStrategy>(position)
; |
| 527 } | 538 } |
| 528 | 539 |
| 529 PositionInFlatTree previousVisuallyDistinctCandidate(const PositionInFlatTree& p
osition) | 540 PositionInFlatTree previousVisuallyDistinctCandidate(const PositionInFlatTree& p
osition) |
| 530 { | 541 { |
| 531 return previousVisuallyDistinctCandidateAlgorithm<EditingInFlatTreeStrategy>
(position); | 542 return previousVisuallyDistinctCandidateAlgorithm<EditingInFlatTreeStrategy>
(position); |
| 532 } | 543 } |
| 533 | 544 |
| 534 VisiblePosition firstEditableVisiblePositionAfterPositionInRoot(const Position&
position, ContainerNode& highestRoot) | 545 VisiblePosition firstEditableVisiblePositionAfterPositionInRoot(const Position&
position, ContainerNode& highestRoot) |
| 535 { | 546 { |
| 536 return createVisiblePositionDeprecated(firstEditablePositionAfterPositionInR
oot(position, highestRoot)); | 547 DCHECK(!needsLayoutTreeUpdate(position)); |
| 548 return createVisiblePosition(firstEditablePositionAfterPositionInRoot(positi
on, highestRoot)); |
| 537 } | 549 } |
| 538 | 550 |
| 539 VisiblePositionInFlatTree firstEditableVisiblePositionAfterPositionInRoot(const
PositionInFlatTree& position, ContainerNode& highestRoot) | 551 VisiblePositionInFlatTree firstEditableVisiblePositionAfterPositionInRoot(const
PositionInFlatTree& position, ContainerNode& highestRoot) |
| 540 { | 552 { |
| 541 return createVisiblePositionDeprecated(firstEditablePositionAfterPositionInR
oot(position, highestRoot)); | 553 DCHECK(!needsLayoutTreeUpdate(position)); |
| 554 return createVisiblePosition(firstEditablePositionAfterPositionInRoot(positi
on, highestRoot)); |
| 542 } | 555 } |
| 543 | 556 |
| 544 template <typename Strategy> | 557 template <typename Strategy> |
| 545 PositionTemplate<Strategy> firstEditablePositionAfterPositionInRootAlgorithm(con
st PositionTemplate<Strategy>& position, Node& highestRoot) | 558 PositionTemplate<Strategy> firstEditablePositionAfterPositionInRootAlgorithm(con
st PositionTemplate<Strategy>& position, Node& highestRoot) |
| 546 { | 559 { |
| 547 DCHECK(!needsLayoutTreeUpdate(highestRoot)) << position << ' ' << highestRoo
t; | 560 DCHECK(!needsLayoutTreeUpdate(highestRoot)) << position << ' ' << highestRoo
t; |
| 548 // position falls before highestRoot. | 561 // position falls before highestRoot. |
| 549 if (position.compareTo(PositionTemplate<Strategy>::firstPositionInNode(&high
estRoot)) == -1 && hasEditableStyle(highestRoot)) | 562 if (position.compareTo(PositionTemplate<Strategy>::firstPositionInNode(&high
estRoot)) == -1 && hasEditableStyle(highestRoot)) |
| 550 return PositionTemplate<Strategy>::firstPositionInNode(&highestRoot); | 563 return PositionTemplate<Strategy>::firstPositionInNode(&highestRoot); |
| 551 | 564 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 581 return firstEditablePositionAfterPositionInRootAlgorithm<EditingStrategy>(po
sition, highestRoot); | 594 return firstEditablePositionAfterPositionInRootAlgorithm<EditingStrategy>(po
sition, highestRoot); |
| 582 } | 595 } |
| 583 | 596 |
| 584 PositionInFlatTree firstEditablePositionAfterPositionInRoot(const PositionInFlat
Tree& position, Node& highestRoot) | 597 PositionInFlatTree firstEditablePositionAfterPositionInRoot(const PositionInFlat
Tree& position, Node& highestRoot) |
| 585 { | 598 { |
| 586 return firstEditablePositionAfterPositionInRootAlgorithm<EditingInFlatTreeSt
rategy>(position, highestRoot); | 599 return firstEditablePositionAfterPositionInRootAlgorithm<EditingInFlatTreeSt
rategy>(position, highestRoot); |
| 587 } | 600 } |
| 588 | 601 |
| 589 VisiblePosition lastEditableVisiblePositionBeforePositionInRoot(const Position&
position, ContainerNode& highestRoot) | 602 VisiblePosition lastEditableVisiblePositionBeforePositionInRoot(const Position&
position, ContainerNode& highestRoot) |
| 590 { | 603 { |
| 591 return createVisiblePositionDeprecated(lastEditablePositionBeforePositionInR
oot(position, highestRoot)); | 604 DCHECK(!needsLayoutTreeUpdate(position)); |
| 605 return createVisiblePosition(lastEditablePositionBeforePositionInRoot(positi
on, highestRoot)); |
| 592 } | 606 } |
| 593 | 607 |
| 594 VisiblePositionInFlatTree lastEditableVisiblePositionBeforePositionInRoot(const
PositionInFlatTree& position, ContainerNode& highestRoot) | 608 VisiblePositionInFlatTree lastEditableVisiblePositionBeforePositionInRoot(const
PositionInFlatTree& position, ContainerNode& highestRoot) |
| 595 { | 609 { |
| 596 return createVisiblePositionDeprecated(lastEditablePositionBeforePositionInR
oot(position, highestRoot)); | 610 DCHECK(!needsLayoutTreeUpdate(position)); |
| 611 return createVisiblePosition(lastEditablePositionBeforePositionInRoot(positi
on, highestRoot)); |
| 597 } | 612 } |
| 598 | 613 |
| 599 template <typename Strategy> | 614 template <typename Strategy> |
| 600 PositionTemplate<Strategy> lastEditablePositionBeforePositionInRootAlgorithm(con
st PositionTemplate<Strategy>& position, Node& highestRoot) | 615 PositionTemplate<Strategy> lastEditablePositionBeforePositionInRootAlgorithm(con
st PositionTemplate<Strategy>& position, Node& highestRoot) |
| 601 { | 616 { |
| 602 DCHECK(!needsLayoutTreeUpdate(highestRoot)) << position << ' ' << highestRoo
t; | 617 DCHECK(!needsLayoutTreeUpdate(highestRoot)) << position << ' ' << highestRoo
t; |
| 603 // When position falls after highestRoot, the result is easy to compute. | 618 // When position falls after highestRoot, the result is easy to compute. |
| 604 if (position.compareTo(PositionTemplate<Strategy>::lastPositionInNode(&highe
stRoot)) == 1) | 619 if (position.compareTo(PositionTemplate<Strategy>::lastPositionInNode(&highe
stRoot)) == 1) |
| 605 return PositionTemplate<Strategy>::lastPositionInNode(&highestRoot); | 620 return PositionTemplate<Strategy>::lastPositionInNode(&highestRoot); |
| 606 | 621 |
| (...skipping 701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1308 if (n == root || isTableCell(n)) | 1323 if (n == root || isTableCell(n)) |
| 1309 return 0; | 1324 return 0; |
| 1310 } | 1325 } |
| 1311 | 1326 |
| 1312 return 0; | 1327 return 0; |
| 1313 } | 1328 } |
| 1314 | 1329 |
| 1315 // FIXME: This method should not need to call isStartOfParagraph/isEndOfParagrap
h | 1330 // FIXME: This method should not need to call isStartOfParagraph/isEndOfParagrap
h |
| 1316 Node* enclosingEmptyListItem(const VisiblePosition& visiblePos) | 1331 Node* enclosingEmptyListItem(const VisiblePosition& visiblePos) |
| 1317 { | 1332 { |
| 1333 DCHECK(visiblePos.isValid()); |
| 1334 |
| 1318 // Check that position is on a line by itself inside a list item | 1335 // Check that position is on a line by itself inside a list item |
| 1319 Node* listChildNode = enclosingListChild(visiblePos.deepEquivalent().anchorN
ode()); | 1336 Node* listChildNode = enclosingListChild(visiblePos.deepEquivalent().anchorN
ode()); |
| 1320 if (!listChildNode || !isStartOfParagraph(visiblePos) || !isEndOfParagraph(v
isiblePos)) | 1337 if (!listChildNode || !isStartOfParagraph(visiblePos) || !isEndOfParagraph(v
isiblePos)) |
| 1321 return 0; | 1338 return 0; |
| 1322 | 1339 |
| 1323 VisiblePosition firstInListChild = createVisiblePositionDeprecated(firstPosi
tionInOrBeforeNode(listChildNode)); | 1340 VisiblePosition firstInListChild = createVisiblePosition(firstPositionInOrBe
foreNode(listChildNode)); |
| 1324 VisiblePosition lastInListChild = createVisiblePositionDeprecated(lastPositi
onInOrAfterNode(listChildNode)); | 1341 VisiblePosition lastInListChild = createVisiblePosition(lastPositionInOrAfte
rNode(listChildNode)); |
| 1325 | 1342 |
| 1326 if (firstInListChild.deepEquivalent() != visiblePos.deepEquivalent() || last
InListChild.deepEquivalent() != visiblePos.deepEquivalent()) | 1343 if (firstInListChild.deepEquivalent() != visiblePos.deepEquivalent() || last
InListChild.deepEquivalent() != visiblePos.deepEquivalent()) |
| 1327 return 0; | 1344 return 0; |
| 1328 | 1345 |
| 1329 return listChildNode; | 1346 return listChildNode; |
| 1330 } | 1347 } |
| 1331 | 1348 |
| 1332 HTMLElement* outermostEnclosingList(Node* node, HTMLElement* rootList) | 1349 HTMLElement* outermostEnclosingList(Node* node, HTMLElement* rootList) |
| 1333 { | 1350 { |
| 1334 HTMLElement* list = enclosingList(node); | 1351 HTMLElement* list = enclosingList(node); |
| (...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1746 | 1763 |
| 1747 EphemeralRangeInFlatTree normalizeRange(const EphemeralRangeInFlatTree& range) | 1764 EphemeralRangeInFlatTree normalizeRange(const EphemeralRangeInFlatTree& range) |
| 1748 { | 1765 { |
| 1749 return normalizeRangeAlgorithm<EditingInFlatTreeStrategy>(range); | 1766 return normalizeRangeAlgorithm<EditingInFlatTreeStrategy>(range); |
| 1750 } | 1767 } |
| 1751 | 1768 |
| 1752 VisiblePosition visiblePositionForIndex(int index, ContainerNode* scope) | 1769 VisiblePosition visiblePositionForIndex(int index, ContainerNode* scope) |
| 1753 { | 1770 { |
| 1754 if (!scope) | 1771 if (!scope) |
| 1755 return VisiblePosition(); | 1772 return VisiblePosition(); |
| 1773 DCHECK(!scope->document().needsLayoutTreeUpdate()); |
| 1774 DocumentLifecycle::DisallowTransitionScope disallowTransition(scope->documen
t().lifecycle()); |
| 1775 |
| 1756 EphemeralRange range = PlainTextRange(index).createRangeForSelection(*scope)
; | 1776 EphemeralRange range = PlainTextRange(index).createRangeForSelection(*scope)
; |
| 1757 // Check for an invalid index. Certain editing operations invalidate indices | 1777 // Check for an invalid index. Certain editing operations invalidate indices |
| 1758 // because of problems with | 1778 // because of problems with |
| 1759 // TextIteratorEmitsCharactersBetweenAllVisiblePositions. | 1779 // TextIteratorEmitsCharactersBetweenAllVisiblePositions. |
| 1760 if (range.isNull()) | 1780 if (range.isNull()) |
| 1761 return VisiblePosition(); | 1781 return VisiblePosition(); |
| 1762 return createVisiblePositionDeprecated(range.startPosition()); | 1782 return createVisiblePosition(range.startPosition()); |
| 1763 } | 1783 } |
| 1764 | 1784 |
| 1765 // Determines whether a node is inside a range or visibly starts and ends at the
boundaries of the range. | 1785 // Determines whether a node is inside a range or visibly starts and ends at the
boundaries of the range. |
| 1766 // Call this function to determine whether a node is visibly fit inside selected
Range | 1786 // Call this function to determine whether a node is visibly fit inside selected
Range |
| 1767 bool isNodeVisiblyContainedWithin(Node& node, const Range& selectedRange) | 1787 bool isNodeVisiblyContainedWithin(Node& node, const Range& selectedRange) |
| 1768 { | 1788 { |
| 1769 if (selectedRange.isNodeFullyContained(node)) | 1789 if (selectedRange.isNodeFullyContained(node)) |
| 1770 return true; | 1790 return true; |
| 1771 | 1791 |
| 1772 bool startIsVisuallySame = visiblePositionBeforeNode(node).deepEquivalent()
== createVisiblePositionDeprecated(selectedRange.startPosition()).deepEquivalent
(); | 1792 bool startIsVisuallySame = visiblePositionBeforeNode(node).deepEquivalent()
== createVisiblePositionDeprecated(selectedRange.startPosition()).deepEquivalent
(); |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1918 return InputType::DeleteWordBackward; | 1938 return InputType::DeleteWordBackward; |
| 1919 if (granularity == LineBoundary) | 1939 if (granularity == LineBoundary) |
| 1920 return InputType::DeleteLineBackward; | 1940 return InputType::DeleteLineBackward; |
| 1921 return InputType::DeleteContentBackward; | 1941 return InputType::DeleteContentBackward; |
| 1922 default: | 1942 default: |
| 1923 return InputType::None; | 1943 return InputType::None; |
| 1924 } | 1944 } |
| 1925 } | 1945 } |
| 1926 | 1946 |
| 1927 } // namespace blink | 1947 } // namespace blink |
| OLD | NEW |