| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. | 2 * Copyright (C) 2005 Apple Computer, 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 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 | 320 |
| 321 static Position firstEditablePositionInNode(Node* node) | 321 static Position firstEditablePositionInNode(Node* node) |
| 322 { | 322 { |
| 323 ASSERT(node); | 323 ASSERT(node); |
| 324 Node* next = node; | 324 Node* next = node; |
| 325 while (next && !next->rendererIsEditable()) | 325 while (next && !next->rendererIsEditable()) |
| 326 next = NodeTraversal::next(*next, node); | 326 next = NodeTraversal::next(*next, node); |
| 327 return next ? firstPositionInOrBeforeNode(next) : Position(); | 327 return next ? firstPositionInOrBeforeNode(next) : Position(); |
| 328 } | 328 } |
| 329 | 329 |
| 330 void DeleteSelectionCommand::removeNode(PassRefPtr<Node> node, ShouldAssumeConte
ntIsAlwaysEditable shouldAssumeContentIsAlwaysEditable) | 330 void DeleteSelectionCommand::removeNode(PassRefPtrWillBeRawPtr<Node> node, Shoul
dAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable) |
| 331 { | 331 { |
| 332 if (!node) | 332 if (!node) |
| 333 return; | 333 return; |
| 334 | 334 |
| 335 if (m_startRoot != m_endRoot && !(node->isDescendantOf(m_startRoot.get()) &&
node->isDescendantOf(m_endRoot.get()))) { | 335 if (m_startRoot != m_endRoot && !(node->isDescendantOf(m_startRoot.get()) &&
node->isDescendantOf(m_endRoot.get()))) { |
| 336 // If a node is not in both the start and end editable roots, remove it
only if its inside an editable region. | 336 // If a node is not in both the start and end editable roots, remove it
only if its inside an editable region. |
| 337 if (!node->parentNode()->rendererIsEditable()) { | 337 if (!node->parentNode()->rendererIsEditable()) { |
| 338 // Don't remove non-editable atomic nodes. | 338 // Don't remove non-editable atomic nodes. |
| 339 if (!node->firstChild()) | 339 if (!node->firstChild()) |
| 340 return; | 340 return; |
| 341 // Search this non-editable region for editable regions to empty. | 341 // Search this non-editable region for editable regions to empty. |
| 342 RefPtr<Node> child = node->firstChild(); | 342 RefPtrWillBeRawPtr<Node> child = node->firstChild(); |
| 343 while (child) { | 343 while (child) { |
| 344 RefPtr<Node> nextChild = child->nextSibling(); | 344 RefPtrWillBeRawPtr<Node> nextChild = child->nextSibling(); |
| 345 removeNode(child.get(), shouldAssumeContentIsAlwaysEditable); | 345 removeNode(child.get(), shouldAssumeContentIsAlwaysEditable); |
| 346 // Bail if nextChild is no longer node's child. | 346 // Bail if nextChild is no longer node's child. |
| 347 if (nextChild && nextChild->parentNode() != node) | 347 if (nextChild && nextChild->parentNode() != node) |
| 348 return; | 348 return; |
| 349 child = nextChild; | 349 child = nextChild; |
| 350 } | 350 } |
| 351 | 351 |
| 352 // Don't remove editable regions that are inside non-editable ones,
just clear them. | 352 // Don't remove editable regions that are inside non-editable ones,
just clear them. |
| 353 return; | 353 return; |
| 354 } | 354 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 412 updatePositionForTextRemoval(node.get(), offset, count, m_leadingWhitespace)
; | 412 updatePositionForTextRemoval(node.get(), offset, count, m_leadingWhitespace)
; |
| 413 updatePositionForTextRemoval(node.get(), offset, count, m_trailingWhitespace
); | 413 updatePositionForTextRemoval(node.get(), offset, count, m_trailingWhitespace
); |
| 414 updatePositionForTextRemoval(node.get(), offset, count, m_downstreamEnd); | 414 updatePositionForTextRemoval(node.get(), offset, count, m_downstreamEnd); |
| 415 | 415 |
| 416 CompositeEditCommand::deleteTextFromNode(node, offset, count); | 416 CompositeEditCommand::deleteTextFromNode(node, offset, count); |
| 417 } | 417 } |
| 418 | 418 |
| 419 void DeleteSelectionCommand::makeStylingElementsDirectChildrenOfEditableRootToPr
eventStyleLoss() | 419 void DeleteSelectionCommand::makeStylingElementsDirectChildrenOfEditableRootToPr
eventStyleLoss() |
| 420 { | 420 { |
| 421 RefPtrWillBeRawPtr<Range> range = m_selectionToDelete.toNormalizedRange(); | 421 RefPtrWillBeRawPtr<Range> range = m_selectionToDelete.toNormalizedRange(); |
| 422 RefPtr<Node> node = range->firstNode(); | 422 RefPtrWillBeRawPtr<Node> node = range->firstNode(); |
| 423 while (node && node != range->pastLastNode()) { | 423 while (node && node != range->pastLastNode()) { |
| 424 RefPtr<Node> nextNode = NodeTraversal::next(*node); | 424 RefPtrWillBeRawPtr<Node> nextNode = NodeTraversal::next(*node); |
| 425 if ((isHTMLStyleElement(*node) && !(toElement(node)->hasAttribute(scoped
Attr))) || isHTMLLinkElement(*node)) { | 425 if ((isHTMLStyleElement(*node) && !(toElement(node)->hasAttribute(scoped
Attr))) || isHTMLLinkElement(*node)) { |
| 426 nextNode = NodeTraversal::nextSkippingChildren(*node); | 426 nextNode = NodeTraversal::nextSkippingChildren(*node); |
| 427 RefPtr<ContainerNode> rootEditableElement = node->rootEditableElemen
t(); | 427 RefPtrWillBeRawPtr<ContainerNode> rootEditableElement = node->rootEd
itableElement(); |
| 428 if (rootEditableElement.get()) { | 428 if (rootEditableElement.get()) { |
| 429 removeNode(node); | 429 removeNode(node); |
| 430 appendNode(node, rootEditableElement); | 430 appendNode(node, rootEditableElement); |
| 431 } | 431 } |
| 432 } | 432 } |
| 433 node = nextNode; | 433 node = nextNode; |
| 434 } | 434 } |
| 435 } | 435 } |
| 436 | 436 |
| 437 void DeleteSelectionCommand::handleGeneralDelete() | 437 void DeleteSelectionCommand::handleGeneralDelete() |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 480 } | 480 } |
| 481 } | 481 } |
| 482 | 482 |
| 483 // The selection to delete is all in one node. | 483 // The selection to delete is all in one node. |
| 484 if (!startNode->renderer() || (!startOffset && m_downstreamEnd.atLastEdi
tingPositionForNode())) | 484 if (!startNode->renderer() || (!startOffset && m_downstreamEnd.atLastEdi
tingPositionForNode())) |
| 485 removeNode(startNode); | 485 removeNode(startNode); |
| 486 } | 486 } |
| 487 else { | 487 else { |
| 488 bool startNodeWasDescendantOfEndNode = m_upstreamStart.deprecatedNode()-
>isDescendantOf(m_downstreamEnd.deprecatedNode()); | 488 bool startNodeWasDescendantOfEndNode = m_upstreamStart.deprecatedNode()-
>isDescendantOf(m_downstreamEnd.deprecatedNode()); |
| 489 // The selection to delete spans more than one node. | 489 // The selection to delete spans more than one node. |
| 490 RefPtr<Node> node(startNode); | 490 RefPtrWillBeRawPtr<Node> node(startNode); |
| 491 | 491 |
| 492 if (startOffset > 0) { | 492 if (startOffset > 0) { |
| 493 if (startNode->isTextNode()) { | 493 if (startNode->isTextNode()) { |
| 494 // in a text node that needs to be trimmed | 494 // in a text node that needs to be trimmed |
| 495 Text* text = toText(node); | 495 Text* text = toText(node); |
| 496 deleteTextFromNode(text, startOffset, text->length() - startOffs
et); | 496 deleteTextFromNode(text, startOffset, text->length() - startOffs
et); |
| 497 node = NodeTraversal::next(*node); | 497 node = NodeTraversal::next(*node); |
| 498 } else { | 498 } else { |
| 499 node = startNode->traverseToChildAt(startOffset); | 499 node = startNode->traverseToChildAt(startOffset); |
| 500 } | 500 } |
| 501 } else if (startNode == m_upstreamEnd.deprecatedNode() && startNode->isT
extNode()) { | 501 } else if (startNode == m_upstreamEnd.deprecatedNode() && startNode->isT
extNode()) { |
| 502 Text* text = toText(m_upstreamEnd.deprecatedNode()); | 502 Text* text = toText(m_upstreamEnd.deprecatedNode()); |
| 503 deleteTextFromNode(text, 0, m_upstreamEnd.deprecatedEditingOffset())
; | 503 deleteTextFromNode(text, 0, m_upstreamEnd.deprecatedEditingOffset())
; |
| 504 } | 504 } |
| 505 | 505 |
| 506 // handle deleting all nodes that are completely selected | 506 // handle deleting all nodes that are completely selected |
| 507 while (node && node != m_downstreamEnd.deprecatedNode()) { | 507 while (node && node != m_downstreamEnd.deprecatedNode()) { |
| 508 if (comparePositions(firstPositionInOrBeforeNode(node.get()), m_down
streamEnd) >= 0) { | 508 if (comparePositions(firstPositionInOrBeforeNode(node.get()), m_down
streamEnd) >= 0) { |
| 509 // NodeTraversal::nextSkippingChildren just blew past the end po
sition, so stop deleting | 509 // NodeTraversal::nextSkippingChildren just blew past the end po
sition, so stop deleting |
| 510 node = nullptr; | 510 node = nullptr; |
| 511 } else if (!m_downstreamEnd.deprecatedNode()->isDescendantOf(node.ge
t())) { | 511 } else if (!m_downstreamEnd.deprecatedNode()->isDescendantOf(node.ge
t())) { |
| 512 RefPtr<Node> nextNode = NodeTraversal::nextSkippingChildren(*nod
e); | 512 RefPtrWillBeRawPtr<Node> nextNode = NodeTraversal::nextSkippingC
hildren(*node); |
| 513 // if we just removed a node from the end container, update end
position so the | 513 // if we just removed a node from the end container, update end
position so the |
| 514 // check above will work | 514 // check above will work |
| 515 updatePositionForNodeRemoval(m_downstreamEnd, *node); | 515 updatePositionForNodeRemoval(m_downstreamEnd, *node); |
| 516 removeNode(node.get()); | 516 removeNode(node.get()); |
| 517 node = nextNode.get(); | 517 node = nextNode.get(); |
| 518 } else { | 518 } else { |
| 519 Node& n = node->lastDescendantOrSelf(); | 519 Node& n = node->lastDescendantOrSelf(); |
| 520 if (m_downstreamEnd.deprecatedNode() == n && m_downstreamEnd.dep
recatedEditingOffset() >= caretMaxOffset(&n)) { | 520 if (m_downstreamEnd.deprecatedNode() == n && m_downstreamEnd.dep
recatedEditingOffset() >= caretMaxOffset(&n)) { |
| 521 removeNode(node.get()); | 521 removeNode(node.get()); |
| 522 node = nullptr; | 522 node = nullptr; |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 m_needPlaceholder = needPlaceholder; | 668 m_needPlaceholder = needPlaceholder; |
| 669 // The endingPosition was likely clobbered by the move, so recompute it (mov
eParagraph selects the moved paragraph). | 669 // The endingPosition was likely clobbered by the move, so recompute it (mov
eParagraph selects the moved paragraph). |
| 670 m_endingPosition = endingSelection().start(); | 670 m_endingPosition = endingSelection().start(); |
| 671 } | 671 } |
| 672 | 672 |
| 673 void DeleteSelectionCommand::removePreviouslySelectedEmptyTableRows() | 673 void DeleteSelectionCommand::removePreviouslySelectedEmptyTableRows() |
| 674 { | 674 { |
| 675 if (m_endTableRow && m_endTableRow->inDocument() && m_endTableRow != m_start
TableRow) { | 675 if (m_endTableRow && m_endTableRow->inDocument() && m_endTableRow != m_start
TableRow) { |
| 676 Node* row = m_endTableRow->previousSibling(); | 676 Node* row = m_endTableRow->previousSibling(); |
| 677 while (row && row != m_startTableRow) { | 677 while (row && row != m_startTableRow) { |
| 678 RefPtr<Node> previousRow = row->previousSibling(); | 678 RefPtrWillBeRawPtr<Node> previousRow = row->previousSibling(); |
| 679 if (isTableRowEmpty(row)) | 679 if (isTableRowEmpty(row)) |
| 680 // Use a raw removeNode, instead of DeleteSelectionCommand's, be
cause | 680 // Use a raw removeNode, instead of DeleteSelectionCommand's, be
cause |
| 681 // that won't remove rows, it only empties them in preparation f
or this function. | 681 // that won't remove rows, it only empties them in preparation f
or this function. |
| 682 CompositeEditCommand::removeNode(row); | 682 CompositeEditCommand::removeNode(row); |
| 683 row = previousRow.get(); | 683 row = previousRow.get(); |
| 684 } | 684 } |
| 685 } | 685 } |
| 686 | 686 |
| 687 // Remove empty rows after the start row. | 687 // Remove empty rows after the start row. |
| 688 if (m_startTableRow && m_startTableRow->inDocument() && m_startTableRow != m
_endTableRow) { | 688 if (m_startTableRow && m_startTableRow->inDocument() && m_startTableRow != m
_endTableRow) { |
| 689 Node* row = m_startTableRow->nextSibling(); | 689 Node* row = m_startTableRow->nextSibling(); |
| 690 while (row && row != m_endTableRow) { | 690 while (row && row != m_endTableRow) { |
| 691 RefPtr<Node> nextRow = row->nextSibling(); | 691 RefPtrWillBeRawPtr<Node> nextRow = row->nextSibling(); |
| 692 if (isTableRowEmpty(row)) | 692 if (isTableRowEmpty(row)) |
| 693 CompositeEditCommand::removeNode(row); | 693 CompositeEditCommand::removeNode(row); |
| 694 row = nextRow.get(); | 694 row = nextRow.get(); |
| 695 } | 695 } |
| 696 } | 696 } |
| 697 | 697 |
| 698 if (m_endTableRow && m_endTableRow->inDocument() && m_endTableRow != m_start
TableRow) | 698 if (m_endTableRow && m_endTableRow->inDocument() && m_endTableRow != m_start
TableRow) |
| 699 if (isTableRowEmpty(m_endTableRow.get())) { | 699 if (isTableRowEmpty(m_endTableRow.get())) { |
| 700 // Don't remove m_endTableRow if it's where we're putting the ending
selection. | 700 // Don't remove m_endTableRow if it's where we're putting the ending
selection. |
| 701 if (!m_endingPosition.deprecatedNode()->isDescendantOf(m_endTableRow
.get())) { | 701 if (!m_endingPosition.deprecatedNode()->isDescendantOf(m_endTableRow
.get())) { |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 825 | 825 |
| 826 removePreviouslySelectedEmptyTableRows(); | 826 removePreviouslySelectedEmptyTableRows(); |
| 827 | 827 |
| 828 if (!m_needPlaceholder && rootWillStayOpenWithoutPlaceholder) { | 828 if (!m_needPlaceholder && rootWillStayOpenWithoutPlaceholder) { |
| 829 VisiblePosition visualEnding(m_endingPosition); | 829 VisiblePosition visualEnding(m_endingPosition); |
| 830 bool hasPlaceholder = lineBreakExistsAtVisiblePosition(visualEnding) | 830 bool hasPlaceholder = lineBreakExistsAtVisiblePosition(visualEnding) |
| 831 && visualEnding.next(CannotCrossEditingBoundary).isNull(); | 831 && visualEnding.next(CannotCrossEditingBoundary).isNull(); |
| 832 m_needPlaceholder = hasPlaceholder && lineBreakBeforeStart && !lineBreak
AtEndOfSelectionToDelete; | 832 m_needPlaceholder = hasPlaceholder && lineBreakBeforeStart && !lineBreak
AtEndOfSelectionToDelete; |
| 833 } | 833 } |
| 834 | 834 |
| 835 RefPtr<Node> placeholder = m_needPlaceholder ? createBreakElement(document()
).get() : 0; | 835 RefPtrWillBeRawPtr<Node> placeholder = m_needPlaceholder ? createBreakElemen
t(document()) : nullptr; |
| 836 | 836 |
| 837 if (placeholder) { | 837 if (placeholder) { |
| 838 if (m_sanitizeMarkup) | 838 if (m_sanitizeMarkup) |
| 839 removeRedundantBlocks(); | 839 removeRedundantBlocks(); |
| 840 insertNodeAt(placeholder.get(), m_endingPosition); | 840 insertNodeAt(placeholder.get(), m_endingPosition); |
| 841 } | 841 } |
| 842 | 842 |
| 843 rebalanceWhitespaceAt(m_endingPosition); | 843 rebalanceWhitespaceAt(m_endingPosition); |
| 844 | 844 |
| 845 calculateTypingStyleAfterDelete(); | 845 calculateTypingStyleAfterDelete(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 857 } | 857 } |
| 858 | 858 |
| 859 // Normally deletion doesn't preserve the typing style that was present before i
t. For example, | 859 // Normally deletion doesn't preserve the typing style that was present before i
t. For example, |
| 860 // type a character, Bold, then delete the character and start typing. The Bold
typing style shouldn't | 860 // type a character, Bold, then delete the character and start typing. The Bold
typing style shouldn't |
| 861 // stick around. Deletion should preserve a typing style that *it* sets, howeve
r. | 861 // stick around. Deletion should preserve a typing style that *it* sets, howeve
r. |
| 862 bool DeleteSelectionCommand::preservesTypingStyle() const | 862 bool DeleteSelectionCommand::preservesTypingStyle() const |
| 863 { | 863 { |
| 864 return m_typingStyle; | 864 return m_typingStyle; |
| 865 } | 865 } |
| 866 | 866 |
| 867 void DeleteSelectionCommand::trace(Visitor* visitor) |
| 868 { |
| 869 visitor->trace(m_selectionToDelete); |
| 870 visitor->trace(m_upstreamStart); |
| 871 visitor->trace(m_downstreamStart); |
| 872 visitor->trace(m_upstreamEnd); |
| 873 visitor->trace(m_downstreamEnd); |
| 874 visitor->trace(m_endingPosition); |
| 875 visitor->trace(m_leadingWhitespace); |
| 876 visitor->trace(m_trailingWhitespace); |
| 877 visitor->trace(m_startBlock); |
| 878 visitor->trace(m_endBlock); |
| 879 visitor->trace(m_typingStyle); |
| 880 visitor->trace(m_deleteIntoBlockquoteStyle); |
| 881 visitor->trace(m_startRoot); |
| 882 visitor->trace(m_endRoot); |
| 883 visitor->trace(m_startTableRow); |
| 884 visitor->trace(m_endTableRow); |
| 885 visitor->trace(m_temporaryPlaceholder); |
| 886 CompositeEditCommand::trace(visitor); |
| 887 } |
| 888 |
| 867 } // namespace WebCore | 889 } // namespace WebCore |
| OLD | NEW |