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 |