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 |