| 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 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 265 | 265 |
| 266 if (position.deprecatedNode()->treeScope() != highestRoot->treeScope()) { | 266 if (position.deprecatedNode()->treeScope() != highestRoot->treeScope()) { |
| 267 Node* shadowAncestor = highestRoot->treeScope().ancestorInThisScope(p.de
precatedNode()); | 267 Node* shadowAncestor = highestRoot->treeScope().ancestorInThisScope(p.de
precatedNode()); |
| 268 if (!shadowAncestor) | 268 if (!shadowAncestor) |
| 269 return VisiblePosition(); | 269 return VisiblePosition(); |
| 270 | 270 |
| 271 p = positionAfterNode(shadowAncestor); | 271 p = positionAfterNode(shadowAncestor); |
| 272 } | 272 } |
| 273 | 273 |
| 274 while (p.deprecatedNode() && !isEditablePosition(p) && p.deprecatedNode()->i
sDescendantOf(highestRoot)) | 274 while (p.deprecatedNode() && !isEditablePosition(p) && p.deprecatedNode()->i
sDescendantOf(highestRoot)) |
| 275 p = isAtomicNode(p.deprecatedNode()) ? positionInParentAfterNode(p.depre
catedNode()) : nextVisuallyDistinctCandidate(p); | 275 p = isAtomicNode(p.deprecatedNode()) ? positionInParentAfterNode(*p.depr
ecatedNode()) : nextVisuallyDistinctCandidate(p); |
| 276 | 276 |
| 277 if (p.deprecatedNode() && p.deprecatedNode() != highestRoot && !p.deprecated
Node()->isDescendantOf(highestRoot)) | 277 if (p.deprecatedNode() && p.deprecatedNode() != highestRoot && !p.deprecated
Node()->isDescendantOf(highestRoot)) |
| 278 return VisiblePosition(); | 278 return VisiblePosition(); |
| 279 | 279 |
| 280 return VisiblePosition(p); | 280 return VisiblePosition(p); |
| 281 } | 281 } |
| 282 | 282 |
| 283 VisiblePosition lastEditablePositionBeforePositionInRoot(const Position& positio
n, Node* highestRoot) | 283 VisiblePosition lastEditablePositionBeforePositionInRoot(const Position& positio
n, Node* highestRoot) |
| 284 { | 284 { |
| 285 // When position falls after highestRoot, the result is easy to compute. | 285 // When position falls after highestRoot, the result is easy to compute. |
| 286 if (comparePositions(position, lastPositionInNode(highestRoot)) == 1) | 286 if (comparePositions(position, lastPositionInNode(highestRoot)) == 1) |
| 287 return VisiblePosition(lastPositionInNode(highestRoot)); | 287 return VisiblePosition(lastPositionInNode(highestRoot)); |
| 288 | 288 |
| 289 Position p = position; | 289 Position p = position; |
| 290 | 290 |
| 291 if (position.deprecatedNode()->treeScope() != highestRoot->treeScope()) { | 291 if (position.deprecatedNode()->treeScope() != highestRoot->treeScope()) { |
| 292 Node* shadowAncestor = highestRoot->treeScope().ancestorInThisScope(p.de
precatedNode()); | 292 Node* shadowAncestor = highestRoot->treeScope().ancestorInThisScope(p.de
precatedNode()); |
| 293 if (!shadowAncestor) | 293 if (!shadowAncestor) |
| 294 return VisiblePosition(); | 294 return VisiblePosition(); |
| 295 | 295 |
| 296 p = firstPositionInOrBeforeNode(shadowAncestor); | 296 p = firstPositionInOrBeforeNode(shadowAncestor); |
| 297 } | 297 } |
| 298 | 298 |
| 299 while (p.deprecatedNode() && !isEditablePosition(p) && p.deprecatedNode()->i
sDescendantOf(highestRoot)) | 299 while (p.deprecatedNode() && !isEditablePosition(p) && p.deprecatedNode()->i
sDescendantOf(highestRoot)) |
| 300 p = isAtomicNode(p.deprecatedNode()) ? positionInParentBeforeNode(p.depr
ecatedNode()) : previousVisuallyDistinctCandidate(p); | 300 p = isAtomicNode(p.deprecatedNode()) ? positionInParentBeforeNode(*p.dep
recatedNode()) : previousVisuallyDistinctCandidate(p); |
| 301 | 301 |
| 302 if (p.deprecatedNode() && p.deprecatedNode() != highestRoot && !p.deprecated
Node()->isDescendantOf(highestRoot)) | 302 if (p.deprecatedNode() && p.deprecatedNode() != highestRoot && !p.deprecated
Node()->isDescendantOf(highestRoot)) |
| 303 return VisiblePosition(); | 303 return VisiblePosition(); |
| 304 | 304 |
| 305 return VisiblePosition(p); | 305 return VisiblePosition(p); |
| 306 } | 306 } |
| 307 | 307 |
| 308 // FIXME: The method name, comment, and code say three different things here! | 308 // FIXME: The method name, comment, and code say three different things here! |
| 309 // Whether or not content before and after this node will collapse onto the same
line as it. | 309 // Whether or not content before and after this node will collapse onto the same
line as it. |
| 310 bool isBlock(const Node* node) | 310 bool isBlock(const Node* node) |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 453 return n; | 453 return n; |
| 454 } | 454 } |
| 455 return 0; | 455 return 0; |
| 456 } | 456 } |
| 457 | 457 |
| 458 Position positionBeforeContainingSpecialElement(const Position& pos, Node** cont
ainingSpecialElement) | 458 Position positionBeforeContainingSpecialElement(const Position& pos, Node** cont
ainingSpecialElement) |
| 459 { | 459 { |
| 460 Node* n = firstInSpecialElement(pos); | 460 Node* n = firstInSpecialElement(pos); |
| 461 if (!n) | 461 if (!n) |
| 462 return pos; | 462 return pos; |
| 463 Position result = positionInParentBeforeNode(n); | 463 Position result = positionInParentBeforeNode(*n); |
| 464 if (result.isNull() || result.deprecatedNode()->rootEditableElement() != pos
.deprecatedNode()->rootEditableElement()) | 464 if (result.isNull() || result.deprecatedNode()->rootEditableElement() != pos
.deprecatedNode()->rootEditableElement()) |
| 465 return pos; | 465 return pos; |
| 466 if (containingSpecialElement) | 466 if (containingSpecialElement) |
| 467 *containingSpecialElement = n; | 467 *containingSpecialElement = n; |
| 468 return result; | 468 return result; |
| 469 } | 469 } |
| 470 | 470 |
| 471 Position positionAfterContainingSpecialElement(const Position& pos, Node **conta
iningSpecialElement) | 471 Position positionAfterContainingSpecialElement(const Position& pos, Node **conta
iningSpecialElement) |
| 472 { | 472 { |
| 473 Node* n = lastInSpecialElement(pos); | 473 Node* n = lastInSpecialElement(pos); |
| 474 if (!n) | 474 if (!n) |
| 475 return pos; | 475 return pos; |
| 476 Position result = positionInParentAfterNode(n); | 476 Position result = positionInParentAfterNode(*n); |
| 477 if (result.isNull() || result.deprecatedNode()->rootEditableElement() != pos
.deprecatedNode()->rootEditableElement()) | 477 if (result.isNull() || result.deprecatedNode()->rootEditableElement() != pos
.deprecatedNode()->rootEditableElement()) |
| 478 return pos; | 478 return pos; |
| 479 if (containingSpecialElement) | 479 if (containingSpecialElement) |
| 480 *containingSpecialElement = n; | 480 *containingSpecialElement = n; |
| 481 return result; | 481 return result; |
| 482 } | 482 } |
| 483 | 483 |
| 484 Node* isFirstPositionAfterTable(const VisiblePosition& visiblePosition) | 484 Node* isFirstPositionAfterTable(const VisiblePosition& visiblePosition) |
| 485 { | 485 { |
| 486 Position upstream(visiblePosition.deepEquivalent().upstream()); | 486 Position upstream(visiblePosition.deepEquivalent().upstream()); |
| 487 if (isRenderedTable(upstream.deprecatedNode()) && upstream.atLastEditingPosi
tionForNode()) | 487 if (isRenderedTable(upstream.deprecatedNode()) && upstream.atLastEditingPosi
tionForNode()) |
| 488 return upstream.deprecatedNode(); | 488 return upstream.deprecatedNode(); |
| 489 | 489 |
| 490 return 0; | 490 return 0; |
| 491 } | 491 } |
| 492 | 492 |
| 493 Node* isLastPositionBeforeTable(const VisiblePosition& visiblePosition) | 493 Node* isLastPositionBeforeTable(const VisiblePosition& visiblePosition) |
| 494 { | 494 { |
| 495 Position downstream(visiblePosition.deepEquivalent().downstream()); | 495 Position downstream(visiblePosition.deepEquivalent().downstream()); |
| 496 if (isRenderedTable(downstream.deprecatedNode()) && downstream.atFirstEditin
gPositionForNode()) | 496 if (isRenderedTable(downstream.deprecatedNode()) && downstream.atFirstEditin
gPositionForNode()) |
| 497 return downstream.deprecatedNode(); | 497 return downstream.deprecatedNode(); |
| 498 | 498 |
| 499 return 0; | 499 return 0; |
| 500 } | 500 } |
| 501 | 501 |
| 502 // Returns the visible position at the beginning of a node | 502 // Returns the visible position at the beginning of a node |
| 503 VisiblePosition visiblePositionBeforeNode(Node* node) | 503 VisiblePosition visiblePositionBeforeNode(Node& node) |
| 504 { | 504 { |
| 505 ASSERT(node); | 505 if (node.hasChildren()) |
| 506 if (node->hasChildren()) | 506 return VisiblePosition(firstPositionInOrBeforeNode(&node), DOWNSTREAM); |
| 507 return VisiblePosition(firstPositionInOrBeforeNode(node), DOWNSTREAM); | 507 ASSERT(node.parentNode()); |
| 508 ASSERT(node->parentNode()); | 508 ASSERT(!node.parentNode()->isShadowRoot()); |
| 509 ASSERT(!node->parentNode()->isShadowRoot()); | |
| 510 return VisiblePosition(positionInParentBeforeNode(node)); | 509 return VisiblePosition(positionInParentBeforeNode(node)); |
| 511 } | 510 } |
| 512 | 511 |
| 513 // Returns the visible position at the ending of a node | 512 // Returns the visible position at the ending of a node |
| 514 VisiblePosition visiblePositionAfterNode(Node* node) | 513 VisiblePosition visiblePositionAfterNode(Node& node) |
| 515 { | 514 { |
| 516 ASSERT(node); | 515 if (node.hasChildren()) |
| 517 if (node->hasChildren()) | 516 return VisiblePosition(lastPositionInOrAfterNode(&node), DOWNSTREAM); |
| 518 return VisiblePosition(lastPositionInOrAfterNode(node), DOWNSTREAM); | 517 ASSERT(node.parentNode()); |
| 519 ASSERT(node->parentNode()); | 518 ASSERT(!node.parentNode()->isShadowRoot()); |
| 520 ASSERT(!node->parentNode()->isShadowRoot()); | |
| 521 return VisiblePosition(positionInParentAfterNode(node)); | 519 return VisiblePosition(positionInParentAfterNode(node)); |
| 522 } | 520 } |
| 523 | 521 |
| 524 // Create a range object with two visible positions, start and end. | 522 // Create a range object with two visible positions, start and end. |
| 525 // create(Document*, const Position&, const Position&); will use deprecatedEditi
ngOffset | 523 // create(Document*, const Position&, const Position&); will use deprecatedEditi
ngOffset |
| 526 // Use this function instead of create a regular range object (avoiding editing
offset). | 524 // Use this function instead of create a regular range object (avoiding editing
offset). |
| 527 PassRefPtr<Range> createRange(Document& document, const VisiblePosition& start,
const VisiblePosition& end, ExceptionState& exceptionState) | 525 PassRefPtr<Range> createRange(Document& document, const VisiblePosition& start,
const VisiblePosition& end, ExceptionState& exceptionState) |
| 528 { | 526 { |
| 529 RefPtr<Range> selectedRange = Range::create(document); | 527 RefPtr<Range> selectedRange = Range::create(document); |
| 530 selectedRange->setStart(start.deepEquivalent().containerNode(), start.deepEq
uivalent().computeOffsetInContainerNode(), exceptionState); | 528 selectedRange->setStart(start.deepEquivalent().containerNode(), start.deepEq
uivalent().computeOffsetInContainerNode(), exceptionState); |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 712 } | 710 } |
| 713 | 711 |
| 714 bool canMergeLists(Element* firstList, Element* secondList) | 712 bool canMergeLists(Element* firstList, Element* secondList) |
| 715 { | 713 { |
| 716 if (!firstList || !secondList || !firstList->isHTMLElement() || !secondList-
>isHTMLElement()) | 714 if (!firstList || !secondList || !firstList->isHTMLElement() || !secondList-
>isHTMLElement()) |
| 717 return false; | 715 return false; |
| 718 | 716 |
| 719 return firstList->hasTagName(secondList->tagQName()) // make sure the list t
ypes match (ol vs. ul) | 717 return firstList->hasTagName(secondList->tagQName()) // make sure the list t
ypes match (ol vs. ul) |
| 720 && firstList->rendererIsEditable() && secondList->rendererIsEditable() // bo
th lists are editable | 718 && firstList->rendererIsEditable() && secondList->rendererIsEditable() // bo
th lists are editable |
| 721 && firstList->rootEditableElement() == secondList->rootEditableElement() //
don't cross editing boundaries | 719 && firstList->rootEditableElement() == secondList->rootEditableElement() //
don't cross editing boundaries |
| 722 && isVisiblyAdjacent(positionInParentAfterNode(firstList), positionInParentB
eforeNode(secondList)); | 720 && isVisiblyAdjacent(positionInParentAfterNode(*firstList), positionInParent
BeforeNode(*secondList)); |
| 723 // Make sure there is no visible content between this li and the previous li
st | 721 // Make sure there is no visible content between this li and the previous li
st |
| 724 } | 722 } |
| 725 | 723 |
| 726 bool isRenderedTableElement(const Node* node) | 724 bool isRenderedTableElement(const Node* node) |
| 727 { | 725 { |
| 728 if (!node || !node->isElementNode()) | 726 if (!node || !node->isElementNode()) |
| 729 return false; | 727 return false; |
| 730 | 728 |
| 731 return node->renderer() && node->hasTagName(tableTag); | 729 return node->renderer() && node->hasTagName(tableTag); |
| 732 } | 730 } |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 883 unsigned numEnclosingMailBlockquotes(const Position& p) | 881 unsigned numEnclosingMailBlockquotes(const Position& p) |
| 884 { | 882 { |
| 885 unsigned num = 0; | 883 unsigned num = 0; |
| 886 for (Node* n = p.deprecatedNode(); n; n = n->parentNode()) | 884 for (Node* n = p.deprecatedNode(); n; n = n->parentNode()) |
| 887 if (isMailBlockquote(n)) | 885 if (isMailBlockquote(n)) |
| 888 num++; | 886 num++; |
| 889 | 887 |
| 890 return num; | 888 return num; |
| 891 } | 889 } |
| 892 | 890 |
| 893 void updatePositionForNodeRemoval(Position& position, Node* node) | 891 void updatePositionForNodeRemoval(Position& position, Node& node) |
| 894 { | 892 { |
| 895 if (position.isNull()) | 893 if (position.isNull()) |
| 896 return; | 894 return; |
| 897 switch (position.anchorType()) { | 895 switch (position.anchorType()) { |
| 898 case Position::PositionIsBeforeChildren: | 896 case Position::PositionIsBeforeChildren: |
| 899 if (position.containerNode() == node) | 897 if (position.containerNode() == node) |
| 900 position = positionInParentBeforeNode(node); | 898 position = positionInParentBeforeNode(node); |
| 901 break; | 899 break; |
| 902 case Position::PositionIsAfterChildren: | 900 case Position::PositionIsAfterChildren: |
| 903 if (position.containerNode() == node) | 901 if (position.containerNode() == node) |
| 904 position = positionInParentAfterNode(node); | 902 position = positionInParentAfterNode(node); |
| 905 break; | 903 break; |
| 906 case Position::PositionIsOffsetInAnchor: | 904 case Position::PositionIsOffsetInAnchor: |
| 907 if (position.containerNode() == node->parentNode() && static_cast<unsign
ed>(position.offsetInContainerNode()) > node->nodeIndex()) | 905 if (position.containerNode() == node.parentNode() && static_cast<unsigne
d>(position.offsetInContainerNode()) > node.nodeIndex()) |
| 908 position.moveToOffset(position.offsetInContainerNode() - 1); | 906 position.moveToOffset(position.offsetInContainerNode() - 1); |
| 909 else if (node->containsIncludingShadowDOM(position.containerNode())) | 907 else if (node.containsIncludingShadowDOM(position.containerNode())) |
| 910 position = positionInParentBeforeNode(node); | 908 position = positionInParentBeforeNode(node); |
| 911 break; | 909 break; |
| 912 case Position::PositionIsAfterAnchor: | 910 case Position::PositionIsAfterAnchor: |
| 913 if (node->containsIncludingShadowDOM(position.anchorNode())) | 911 if (node.containsIncludingShadowDOM(position.anchorNode())) |
| 914 position = positionInParentAfterNode(node); | 912 position = positionInParentAfterNode(node); |
| 915 break; | 913 break; |
| 916 case Position::PositionIsBeforeAnchor: | 914 case Position::PositionIsBeforeAnchor: |
| 917 if (node->containsIncludingShadowDOM(position.anchorNode())) | 915 if (node.containsIncludingShadowDOM(position.anchorNode())) |
| 918 position = positionInParentBeforeNode(node); | 916 position = positionInParentBeforeNode(node); |
| 919 break; | 917 break; |
| 920 } | 918 } |
| 921 } | 919 } |
| 922 | 920 |
| 923 bool isMailBlockquote(const Node *node) | 921 bool isMailBlockquote(const Node *node) |
| 924 { | 922 { |
| 925 if (!node || !node->hasTagName(blockquoteTag)) | 923 if (!node || !node->hasTagName(blockquoteTag)) |
| 926 return false; | 924 return false; |
| 927 | 925 |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1037 | 1035 |
| 1038 // Determines whether two positions are visibly next to each other (first then s
econd) | 1036 // Determines whether two positions are visibly next to each other (first then s
econd) |
| 1039 // while ignoring whitespaces and unrendered nodes | 1037 // while ignoring whitespaces and unrendered nodes |
| 1040 bool isVisiblyAdjacent(const Position& first, const Position& second) | 1038 bool isVisiblyAdjacent(const Position& first, const Position& second) |
| 1041 { | 1039 { |
| 1042 return VisiblePosition(first) == VisiblePosition(second.upstream()); | 1040 return VisiblePosition(first) == VisiblePosition(second.upstream()); |
| 1043 } | 1041 } |
| 1044 | 1042 |
| 1045 // Determines whether a node is inside a range or visibly starts and ends at the
boundaries of the range. | 1043 // Determines whether a node is inside a range or visibly starts and ends at the
boundaries of the range. |
| 1046 // Call this function to determine whether a node is visibly fit inside selected
Range | 1044 // Call this function to determine whether a node is visibly fit inside selected
Range |
| 1047 bool isNodeVisiblyContainedWithin(Node* node, const Range* selectedRange) | 1045 bool isNodeVisiblyContainedWithin(Node& node, const Range& selectedRange) |
| 1048 { | 1046 { |
| 1049 ASSERT(node); | |
| 1050 ASSERT(selectedRange); | |
| 1051 // If the node is inside the range, then it surely is contained within | 1047 // If the node is inside the range, then it surely is contained within |
| 1052 if (selectedRange->compareNode(node, IGNORE_EXCEPTION) == Range::NODE_INSIDE
) | 1048 if (selectedRange.compareNode(&node, IGNORE_EXCEPTION) == Range::NODE_INSIDE
) |
| 1053 return true; | 1049 return true; |
| 1054 | 1050 |
| 1055 bool startIsVisuallySame = visiblePositionBeforeNode(node) == VisiblePositio
n(selectedRange->startPosition()); | 1051 bool startIsVisuallySame = visiblePositionBeforeNode(node) == VisiblePositio
n(selectedRange.startPosition()); |
| 1056 if (startIsVisuallySame && comparePositions(positionInParentAfterNode(node),
selectedRange->endPosition()) < 0) | 1052 if (startIsVisuallySame && comparePositions(positionInParentAfterNode(node),
selectedRange.endPosition()) < 0) |
| 1057 return true; | 1053 return true; |
| 1058 | 1054 |
| 1059 bool endIsVisuallySame = visiblePositionAfterNode(node) == VisiblePosition(s
electedRange->endPosition()); | 1055 bool endIsVisuallySame = visiblePositionAfterNode(node) == VisiblePosition(s
electedRange.endPosition()); |
| 1060 if (endIsVisuallySame && comparePositions(selectedRange->startPosition(), po
sitionInParentBeforeNode(node)) < 0) | 1056 if (endIsVisuallySame && comparePositions(selectedRange.startPosition(), pos
itionInParentBeforeNode(node)) < 0) |
| 1061 return true; | 1057 return true; |
| 1062 | 1058 |
| 1063 return startIsVisuallySame && endIsVisuallySame; | 1059 return startIsVisuallySame && endIsVisuallySame; |
| 1064 } | 1060 } |
| 1065 | 1061 |
| 1066 bool isRenderedAsNonInlineTableImageOrHR(const Node* node) | 1062 bool isRenderedAsNonInlineTableImageOrHR(const Node* node) |
| 1067 { | 1063 { |
| 1068 if (!node) | 1064 if (!node) |
| 1069 return false; | 1065 return false; |
| 1070 RenderObject* renderer = node->renderer(); | 1066 RenderObject* renderer = node->renderer(); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1118 // if the selection starts just before a paragraph break, skip over it | 1114 // if the selection starts just before a paragraph break, skip over it |
| 1119 if (isEndOfParagraph(visiblePosition)) | 1115 if (isEndOfParagraph(visiblePosition)) |
| 1120 return visiblePosition.next().deepEquivalent().downstream(); | 1116 return visiblePosition.next().deepEquivalent().downstream(); |
| 1121 | 1117 |
| 1122 // otherwise, make sure to be at the start of the first selected node, | 1118 // otherwise, make sure to be at the start of the first selected node, |
| 1123 // instead of possibly at the end of the last node before the selection | 1119 // instead of possibly at the end of the last node before the selection |
| 1124 return visiblePosition.deepEquivalent().downstream(); | 1120 return visiblePosition.deepEquivalent().downstream(); |
| 1125 } | 1121 } |
| 1126 | 1122 |
| 1127 } // namespace WebCore | 1123 } // namespace WebCore |
| OLD | NEW |