| 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 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 | 331 |
| 332 static Position firstEditablePositionInNode(Node* node) | 332 static Position firstEditablePositionInNode(Node* node) |
| 333 { | 333 { |
| 334 ASSERT(node); | 334 ASSERT(node); |
| 335 Node* next = node; | 335 Node* next = node; |
| 336 while (next && !next->hasEditableStyle()) | 336 while (next && !next->hasEditableStyle()) |
| 337 next = NodeTraversal::next(*next, node); | 337 next = NodeTraversal::next(*next, node); |
| 338 return next ? firstPositionInOrBeforeNode(next) : Position(); | 338 return next ? firstPositionInOrBeforeNode(next) : Position(); |
| 339 } | 339 } |
| 340 | 340 |
| 341 void DeleteSelectionCommand::removeNode(PassRefPtrWillBeRawPtr<Node> node, Shoul
dAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable) | 341 void DeleteSelectionCommand::removeNode(RawPtr<Node> node, ShouldAssumeContentIs
AlwaysEditable shouldAssumeContentIsAlwaysEditable) |
| 342 { | 342 { |
| 343 if (!node) | 343 if (!node) |
| 344 return; | 344 return; |
| 345 | 345 |
| 346 if (m_startRoot != m_endRoot && !(node->isDescendantOf(m_startRoot.get()) &&
node->isDescendantOf(m_endRoot.get()))) { | 346 if (m_startRoot != m_endRoot && !(node->isDescendantOf(m_startRoot.get()) &&
node->isDescendantOf(m_endRoot.get()))) { |
| 347 // If a node is not in both the start and end editable roots, remove it
only if its inside an editable region. | 347 // If a node is not in both the start and end editable roots, remove it
only if its inside an editable region. |
| 348 if (!node->parentNode()->hasEditableStyle()) { | 348 if (!node->parentNode()->hasEditableStyle()) { |
| 349 // Don't remove non-editable atomic nodes. | 349 // Don't remove non-editable atomic nodes. |
| 350 if (!node->hasChildren()) | 350 if (!node->hasChildren()) |
| 351 return; | 351 return; |
| 352 // Search this non-editable region for editable regions to empty. | 352 // Search this non-editable region for editable regions to empty. |
| 353 RefPtrWillBeRawPtr<Node> child = node->firstChild(); | 353 RawPtr<Node> child = node->firstChild(); |
| 354 while (child) { | 354 while (child) { |
| 355 RefPtrWillBeRawPtr<Node> nextChild = child->nextSibling(); | 355 RawPtr<Node> nextChild = child->nextSibling(); |
| 356 removeNode(child.get(), shouldAssumeContentIsAlwaysEditable); | 356 removeNode(child.get(), shouldAssumeContentIsAlwaysEditable); |
| 357 // Bail if nextChild is no longer node's child. | 357 // Bail if nextChild is no longer node's child. |
| 358 if (nextChild && nextChild->parentNode() != node) | 358 if (nextChild && nextChild->parentNode() != node) |
| 359 return; | 359 return; |
| 360 child = nextChild; | 360 child = nextChild; |
| 361 } | 361 } |
| 362 | 362 |
| 363 // Don't remove editable regions that are inside non-editable ones,
just clear them. | 363 // Don't remove editable regions that are inside non-editable ones,
just clear them. |
| 364 return; | 364 return; |
| 365 } | 365 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 { | 409 { |
| 410 if (!position.isOffsetInAnchor() || position.computeContainerNode() != node) | 410 if (!position.isOffsetInAnchor() || position.computeContainerNode() != node) |
| 411 return; | 411 return; |
| 412 | 412 |
| 413 if (position.offsetInContainerNode() > offset + count) | 413 if (position.offsetInContainerNode() > offset + count) |
| 414 position = Position(position.computeContainerNode(), position.offsetInCo
ntainerNode() - count); | 414 position = Position(position.computeContainerNode(), position.offsetInCo
ntainerNode() - count); |
| 415 else if (position.offsetInContainerNode() > offset) | 415 else if (position.offsetInContainerNode() > offset) |
| 416 position = Position(position.computeContainerNode(), offset); | 416 position = Position(position.computeContainerNode(), offset); |
| 417 } | 417 } |
| 418 | 418 |
| 419 void DeleteSelectionCommand::deleteTextFromNode(PassRefPtrWillBeRawPtr<Text> nod
e, unsigned offset, unsigned count) | 419 void DeleteSelectionCommand::deleteTextFromNode(RawPtr<Text> node, unsigned offs
et, unsigned count) |
| 420 { | 420 { |
| 421 // FIXME: Update the endpoints of the range being deleted. | 421 // FIXME: Update the endpoints of the range being deleted. |
| 422 updatePositionForTextRemoval(node.get(), offset, count, m_endingPosition); | 422 updatePositionForTextRemoval(node.get(), offset, count, m_endingPosition); |
| 423 updatePositionForTextRemoval(node.get(), offset, count, m_leadingWhitespace)
; | 423 updatePositionForTextRemoval(node.get(), offset, count, m_leadingWhitespace)
; |
| 424 updatePositionForTextRemoval(node.get(), offset, count, m_trailingWhitespace
); | 424 updatePositionForTextRemoval(node.get(), offset, count, m_trailingWhitespace
); |
| 425 updatePositionForTextRemoval(node.get(), offset, count, m_downstreamEnd); | 425 updatePositionForTextRemoval(node.get(), offset, count, m_downstreamEnd); |
| 426 | 426 |
| 427 CompositeEditCommand::deleteTextFromNode(node, offset, count); | 427 CompositeEditCommand::deleteTextFromNode(node, offset, count); |
| 428 } | 428 } |
| 429 | 429 |
| 430 void DeleteSelectionCommand::makeStylingElementsDirectChildrenOfEditableRootToPr
eventStyleLoss() | 430 void DeleteSelectionCommand::makeStylingElementsDirectChildrenOfEditableRootToPr
eventStyleLoss() |
| 431 { | 431 { |
| 432 RefPtrWillBeRawPtr<Range> range = createRange(m_selectionToDelete.toNormaliz
edEphemeralRange()); | 432 RawPtr<Range> range = createRange(m_selectionToDelete.toNormalizedEphemeralR
ange()); |
| 433 RefPtrWillBeRawPtr<Node> node = range->firstNode(); | 433 RawPtr<Node> node = range->firstNode(); |
| 434 while (node && node != range->pastLastNode()) { | 434 while (node && node != range->pastLastNode()) { |
| 435 RefPtrWillBeRawPtr<Node> nextNode = NodeTraversal::next(*node); | 435 RawPtr<Node> nextNode = NodeTraversal::next(*node); |
| 436 if (isHTMLStyleElement(*node) || isHTMLLinkElement(*node)) { | 436 if (isHTMLStyleElement(*node) || isHTMLLinkElement(*node)) { |
| 437 nextNode = NodeTraversal::nextSkippingChildren(*node); | 437 nextNode = NodeTraversal::nextSkippingChildren(*node); |
| 438 RefPtrWillBeRawPtr<Element> rootEditableElement = node->rootEditable
Element(); | 438 RawPtr<Element> rootEditableElement = node->rootEditableElement(); |
| 439 if (rootEditableElement.get()) { | 439 if (rootEditableElement.get()) { |
| 440 removeNode(node); | 440 removeNode(node); |
| 441 appendNode(node, rootEditableElement); | 441 appendNode(node, rootEditableElement); |
| 442 } | 442 } |
| 443 } | 443 } |
| 444 node = nextNode; | 444 node = nextNode; |
| 445 } | 445 } |
| 446 } | 446 } |
| 447 | 447 |
| 448 void DeleteSelectionCommand::handleGeneralDelete() | 448 void DeleteSelectionCommand::handleGeneralDelete() |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 490 m_endingPosition = m_upstreamStart; | 490 m_endingPosition = m_upstreamStart; |
| 491 } | 491 } |
| 492 } | 492 } |
| 493 | 493 |
| 494 // The selection to delete is all in one node. | 494 // The selection to delete is all in one node. |
| 495 if (!startNode->layoutObject() || (!startOffset && m_downstreamEnd.atLas
tEditingPositionForNode())) | 495 if (!startNode->layoutObject() || (!startOffset && m_downstreamEnd.atLas
tEditingPositionForNode())) |
| 496 removeNode(startNode); | 496 removeNode(startNode); |
| 497 } else { | 497 } else { |
| 498 bool startNodeWasDescendantOfEndNode = m_upstreamStart.anchorNode()->isD
escendantOf(m_downstreamEnd.anchorNode()); | 498 bool startNodeWasDescendantOfEndNode = m_upstreamStart.anchorNode()->isD
escendantOf(m_downstreamEnd.anchorNode()); |
| 499 // The selection to delete spans more than one node. | 499 // The selection to delete spans more than one node. |
| 500 RefPtrWillBeRawPtr<Node> node(startNode); | 500 RawPtr<Node> node(startNode); |
| 501 | 501 |
| 502 if (startOffset > 0) { | 502 if (startOffset > 0) { |
| 503 if (startNode->isTextNode()) { | 503 if (startNode->isTextNode()) { |
| 504 // in a text node that needs to be trimmed | 504 // in a text node that needs to be trimmed |
| 505 Text* text = toText(node); | 505 Text* text = toText(node); |
| 506 deleteTextFromNode(text, startOffset, text->length() - startOffs
et); | 506 deleteTextFromNode(text, startOffset, text->length() - startOffs
et); |
| 507 node = NodeTraversal::next(*node); | 507 node = NodeTraversal::next(*node); |
| 508 } else { | 508 } else { |
| 509 node = NodeTraversal::childAt(*startNode, startOffset); | 509 node = NodeTraversal::childAt(*startNode, startOffset); |
| 510 } | 510 } |
| 511 } else if (startNode == m_upstreamEnd.anchorNode() && startNode->isTextN
ode()) { | 511 } else if (startNode == m_upstreamEnd.anchorNode() && startNode->isTextN
ode()) { |
| 512 Text* text = toText(m_upstreamEnd.anchorNode()); | 512 Text* text = toText(m_upstreamEnd.anchorNode()); |
| 513 deleteTextFromNode(text, 0, m_upstreamEnd.computeOffsetInContainerNo
de()); | 513 deleteTextFromNode(text, 0, m_upstreamEnd.computeOffsetInContainerNo
de()); |
| 514 } | 514 } |
| 515 | 515 |
| 516 // handle deleting all nodes that are completely selected | 516 // handle deleting all nodes that are completely selected |
| 517 while (node && node != m_downstreamEnd.anchorNode()) { | 517 while (node && node != m_downstreamEnd.anchorNode()) { |
| 518 if (comparePositions(firstPositionInOrBeforeNode(node.get()), m_down
streamEnd) >= 0) { | 518 if (comparePositions(firstPositionInOrBeforeNode(node.get()), m_down
streamEnd) >= 0) { |
| 519 // NodeTraversal::nextSkippingChildren just blew past the end po
sition, so stop deleting | 519 // NodeTraversal::nextSkippingChildren just blew past the end po
sition, so stop deleting |
| 520 node = nullptr; | 520 node = nullptr; |
| 521 } else if (!m_downstreamEnd.anchorNode()->isDescendantOf(node.get())
) { | 521 } else if (!m_downstreamEnd.anchorNode()->isDescendantOf(node.get())
) { |
| 522 RefPtrWillBeRawPtr<Node> nextNode = NodeTraversal::nextSkippingC
hildren(*node); | 522 RawPtr<Node> nextNode = NodeTraversal::nextSkippingChildren(*nod
e); |
| 523 // if we just removed a node from the end container, update end
position so the | 523 // if we just removed a node from the end container, update end
position so the |
| 524 // check above will work | 524 // check above will work |
| 525 updatePositionForNodeRemoval(m_downstreamEnd, *node); | 525 updatePositionForNodeRemoval(m_downstreamEnd, *node); |
| 526 removeNode(node.get()); | 526 removeNode(node.get()); |
| 527 node = nextNode.get(); | 527 node = nextNode.get(); |
| 528 } else { | 528 } else { |
| 529 Node& n = NodeTraversal::lastWithinOrSelf(*node); | 529 Node& n = NodeTraversal::lastWithinOrSelf(*node); |
| 530 if (m_downstreamEnd.anchorNode() == n && m_downstreamEnd.compute
EditingOffset() >= caretMaxOffset(&n)) { | 530 if (m_downstreamEnd.anchorNode() == n && m_downstreamEnd.compute
EditingOffset() >= caretMaxOffset(&n)) { |
| 531 removeNode(node.get()); | 531 removeNode(node.get()); |
| 532 node = nullptr; | 532 node = nullptr; |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 680 m_needPlaceholder = needPlaceholder; | 680 m_needPlaceholder = needPlaceholder; |
| 681 // The endingPosition was likely clobbered by the move, so recompute it (mov
eParagraph selects the moved paragraph). | 681 // The endingPosition was likely clobbered by the move, so recompute it (mov
eParagraph selects the moved paragraph). |
| 682 m_endingPosition = endingSelection().start(); | 682 m_endingPosition = endingSelection().start(); |
| 683 } | 683 } |
| 684 | 684 |
| 685 void DeleteSelectionCommand::removePreviouslySelectedEmptyTableRows() | 685 void DeleteSelectionCommand::removePreviouslySelectedEmptyTableRows() |
| 686 { | 686 { |
| 687 if (m_endTableRow && m_endTableRow->inDocument() && m_endTableRow != m_start
TableRow) { | 687 if (m_endTableRow && m_endTableRow->inDocument() && m_endTableRow != m_start
TableRow) { |
| 688 Node* row = m_endTableRow->previousSibling(); | 688 Node* row = m_endTableRow->previousSibling(); |
| 689 while (row && row != m_startTableRow) { | 689 while (row && row != m_startTableRow) { |
| 690 RefPtrWillBeRawPtr<Node> previousRow = row->previousSibling(); | 690 RawPtr<Node> previousRow = row->previousSibling(); |
| 691 if (isTableRowEmpty(row)) { | 691 if (isTableRowEmpty(row)) { |
| 692 // Use a raw removeNode, instead of DeleteSelectionCommand's, | 692 // Use a raw removeNode, instead of DeleteSelectionCommand's, |
| 693 // because that won't remove rows, it only empties them in | 693 // because that won't remove rows, it only empties them in |
| 694 // preparation for this function. | 694 // preparation for this function. |
| 695 CompositeEditCommand::removeNode(row); | 695 CompositeEditCommand::removeNode(row); |
| 696 } | 696 } |
| 697 row = previousRow.get(); | 697 row = previousRow.get(); |
| 698 } | 698 } |
| 699 } | 699 } |
| 700 | 700 |
| 701 // Remove empty rows after the start row. | 701 // Remove empty rows after the start row. |
| 702 if (m_startTableRow && m_startTableRow->inDocument() && m_startTableRow != m
_endTableRow) { | 702 if (m_startTableRow && m_startTableRow->inDocument() && m_startTableRow != m
_endTableRow) { |
| 703 Node* row = m_startTableRow->nextSibling(); | 703 Node* row = m_startTableRow->nextSibling(); |
| 704 while (row && row != m_endTableRow) { | 704 while (row && row != m_endTableRow) { |
| 705 RefPtrWillBeRawPtr<Node> nextRow = row->nextSibling(); | 705 RawPtr<Node> nextRow = row->nextSibling(); |
| 706 if (isTableRowEmpty(row)) | 706 if (isTableRowEmpty(row)) |
| 707 CompositeEditCommand::removeNode(row); | 707 CompositeEditCommand::removeNode(row); |
| 708 row = nextRow.get(); | 708 row = nextRow.get(); |
| 709 } | 709 } |
| 710 } | 710 } |
| 711 | 711 |
| 712 if (m_endTableRow && m_endTableRow->inDocument() && m_endTableRow != m_start
TableRow) { | 712 if (m_endTableRow && m_endTableRow->inDocument() && m_endTableRow != m_start
TableRow) { |
| 713 if (isTableRowEmpty(m_endTableRow.get())) { | 713 if (isTableRowEmpty(m_endTableRow.get())) { |
| 714 // Don't remove m_endTableRow if it's where we're putting the ending | 714 // Don't remove m_endTableRow if it's where we're putting the ending |
| 715 // selection. | 715 // selection. |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 845 | 845 |
| 846 removePreviouslySelectedEmptyTableRows(); | 846 removePreviouslySelectedEmptyTableRows(); |
| 847 | 847 |
| 848 if (!m_needPlaceholder && rootWillStayOpenWithoutPlaceholder) { | 848 if (!m_needPlaceholder && rootWillStayOpenWithoutPlaceholder) { |
| 849 VisiblePosition visualEnding = createVisiblePosition(m_endingPosition); | 849 VisiblePosition visualEnding = createVisiblePosition(m_endingPosition); |
| 850 bool hasPlaceholder = lineBreakExistsAtVisiblePosition(visualEnding) | 850 bool hasPlaceholder = lineBreakExistsAtVisiblePosition(visualEnding) |
| 851 && nextPositionOf(visualEnding, CannotCrossEditingBoundary).isNull()
; | 851 && nextPositionOf(visualEnding, CannotCrossEditingBoundary).isNull()
; |
| 852 m_needPlaceholder = hasPlaceholder && lineBreakBeforeStart && !lineBreak
AtEndOfSelectionToDelete; | 852 m_needPlaceholder = hasPlaceholder && lineBreakBeforeStart && !lineBreak
AtEndOfSelectionToDelete; |
| 853 } | 853 } |
| 854 | 854 |
| 855 RefPtrWillBeRawPtr<HTMLBRElement> placeholder = m_needPlaceholder ? HTMLBREl
ement::create(document()) : nullptr; | 855 RawPtr<HTMLBRElement> placeholder = m_needPlaceholder ? HTMLBRElement::creat
e(document()) : nullptr; |
| 856 | 856 |
| 857 if (placeholder) { | 857 if (placeholder) { |
| 858 if (m_sanitizeMarkup) | 858 if (m_sanitizeMarkup) |
| 859 removeRedundantBlocks(); | 859 removeRedundantBlocks(); |
| 860 // handleGeneralDelete cause DOM mutation events so |m_endingPosition| | 860 // handleGeneralDelete cause DOM mutation events so |m_endingPosition| |
| 861 // can be out of document. | 861 // can be out of document. |
| 862 if (m_endingPosition.inDocument()) | 862 if (m_endingPosition.inDocument()) |
| 863 insertNodeAt(placeholder.get(), m_endingPosition); | 863 insertNodeAt(placeholder.get(), m_endingPosition); |
| 864 } | 864 } |
| 865 | 865 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 903 visitor->trace(m_deleteIntoBlockquoteStyle); | 903 visitor->trace(m_deleteIntoBlockquoteStyle); |
| 904 visitor->trace(m_startRoot); | 904 visitor->trace(m_startRoot); |
| 905 visitor->trace(m_endRoot); | 905 visitor->trace(m_endRoot); |
| 906 visitor->trace(m_startTableRow); | 906 visitor->trace(m_startTableRow); |
| 907 visitor->trace(m_endTableRow); | 907 visitor->trace(m_endTableRow); |
| 908 visitor->trace(m_temporaryPlaceholder); | 908 visitor->trace(m_temporaryPlaceholder); |
| 909 CompositeEditCommand::trace(visitor); | 909 CompositeEditCommand::trace(visitor); |
| 910 } | 910 } |
| 911 | 911 |
| 912 } // namespace blink | 912 } // namespace blink |
| OLD | NEW |