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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 if (!isTableRow(row)) | 60 if (!isTableRow(row)) |
61 return false; | 61 return false; |
62 | 62 |
63 for (Node* child = row->firstChild(); child; child = child->nextSibling()) | 63 for (Node* child = row->firstChild(); child; child = child->nextSibling()) |
64 if (isTableCell(child) && !isTableCellEmpty(child)) | 64 if (isTableCell(child) && !isTableCellEmpty(child)) |
65 return false; | 65 return false; |
66 | 66 |
67 return true; | 67 return true; |
68 } | 68 } |
69 | 69 |
70 DeleteSelectionCommand::DeleteSelectionCommand(Document *document, bool smartDel
ete, bool mergeBlocksAfterDelete, bool replace, bool expandForSpecialElements, b
ool sanitizeMarkup) | 70 DeleteSelectionCommand::DeleteSelectionCommand(Document& document, bool smartDel
ete, bool mergeBlocksAfterDelete, bool replace, bool expandForSpecialElements, b
ool sanitizeMarkup) |
71 : CompositeEditCommand(document) | 71 : CompositeEditCommand(document) |
72 , m_hasSelectionToDelete(false) | 72 , m_hasSelectionToDelete(false) |
73 , m_smartDelete(smartDelete) | 73 , m_smartDelete(smartDelete) |
74 , m_mergeBlocksAfterDelete(mergeBlocksAfterDelete) | 74 , m_mergeBlocksAfterDelete(mergeBlocksAfterDelete) |
75 , m_needPlaceholder(false) | 75 , m_needPlaceholder(false) |
76 , m_replace(replace) | 76 , m_replace(replace) |
77 , m_expandForSpecialElements(expandForSpecialElements) | 77 , m_expandForSpecialElements(expandForSpecialElements) |
78 , m_pruneStartBlockIfNecessary(false) | 78 , m_pruneStartBlockIfNecessary(false) |
79 , m_startsAtEmptyLine(false) | 79 , m_startsAtEmptyLine(false) |
80 , m_sanitizeMarkup(sanitizeMarkup) | 80 , m_sanitizeMarkup(sanitizeMarkup) |
81 , m_startBlock(0) | 81 , m_startBlock(0) |
82 , m_endBlock(0) | 82 , m_endBlock(0) |
83 , m_typingStyle(0) | 83 , m_typingStyle(0) |
84 , m_deleteIntoBlockquoteStyle(0) | 84 , m_deleteIntoBlockquoteStyle(0) |
85 { | 85 { |
86 } | 86 } |
87 | 87 |
88 DeleteSelectionCommand::DeleteSelectionCommand(const VisibleSelection& selection
, bool smartDelete, bool mergeBlocksAfterDelete, bool replace, bool expandForSpe
cialElements, bool sanitizeMarkup) | 88 DeleteSelectionCommand::DeleteSelectionCommand(const VisibleSelection& selection
, bool smartDelete, bool mergeBlocksAfterDelete, bool replace, bool expandForSpe
cialElements, bool sanitizeMarkup) |
89 : CompositeEditCommand(&selection.start().anchorNode()->document()) | 89 : CompositeEditCommand(selection.start().anchorNode()->document()) |
90 , m_hasSelectionToDelete(true) | 90 , m_hasSelectionToDelete(true) |
91 , m_smartDelete(smartDelete) | 91 , m_smartDelete(smartDelete) |
92 , m_mergeBlocksAfterDelete(mergeBlocksAfterDelete) | 92 , m_mergeBlocksAfterDelete(mergeBlocksAfterDelete) |
93 , m_needPlaceholder(false) | 93 , m_needPlaceholder(false) |
94 , m_replace(replace) | 94 , m_replace(replace) |
95 , m_expandForSpecialElements(expandForSpecialElements) | 95 , m_expandForSpecialElements(expandForSpecialElements) |
96 , m_pruneStartBlockIfNecessary(false) | 96 , m_pruneStartBlockIfNecessary(false) |
97 , m_startsAtEmptyLine(false) | 97 , m_startsAtEmptyLine(false) |
98 , m_sanitizeMarkup(sanitizeMarkup) | 98 , m_sanitizeMarkup(sanitizeMarkup) |
99 , m_selectionToDelete(selection) | 99 , m_selectionToDelete(selection) |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 // Do not remove an element of table structure; remove its contents. | 372 // Do not remove an element of table structure; remove its contents. |
373 // Likewise for the root editable element. | 373 // Likewise for the root editable element. |
374 Node* child = node->firstChild(); | 374 Node* child = node->firstChild(); |
375 while (child) { | 375 while (child) { |
376 Node* remove = child; | 376 Node* remove = child; |
377 child = child->nextSibling(); | 377 child = child->nextSibling(); |
378 removeNode(remove, shouldAssumeContentIsAlwaysEditable); | 378 removeNode(remove, shouldAssumeContentIsAlwaysEditable); |
379 } | 379 } |
380 | 380 |
381 // Make sure empty cell has some height, if a placeholder can be inserte
d. | 381 // Make sure empty cell has some height, if a placeholder can be inserte
d. |
382 document()->updateLayoutIgnorePendingStylesheets(); | 382 document().updateLayoutIgnorePendingStylesheets(); |
383 RenderObject *r = node->renderer(); | 383 RenderObject *r = node->renderer(); |
384 if (r && r->isTableCell() && toRenderTableCell(r)->contentHeight() <= 0)
{ | 384 if (r && r->isTableCell() && toRenderTableCell(r)->contentHeight() <= 0)
{ |
385 Position firstEditablePosition = firstEditablePositionInNode(node.ge
t()); | 385 Position firstEditablePosition = firstEditablePositionInNode(node.ge
t()); |
386 if (firstEditablePosition.isNotNull()) | 386 if (firstEditablePosition.isNotNull()) |
387 insertBlockPlaceholder(firstEditablePosition); | 387 insertBlockPlaceholder(firstEditablePosition); |
388 } | 388 } |
389 return; | 389 return; |
390 } | 390 } |
391 | 391 |
392 if (node == m_startBlock && !isEndOfBlock(VisiblePosition(firstPositionInNod
e(m_startBlock.get())).previous())) | 392 if (node == m_startBlock && !isEndOfBlock(VisiblePosition(firstPositionInNod
e(m_startBlock.get())).previous())) |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
561 removeChildrenInRange(m_downstreamEnd.deprecatedNode(), offs
et, m_downstreamEnd.deprecatedEditingOffset()); | 561 removeChildrenInRange(m_downstreamEnd.deprecatedNode(), offs
et, m_downstreamEnd.deprecatedEditingOffset()); |
562 m_downstreamEnd = createLegacyEditingPosition(m_downstreamEn
d.deprecatedNode(), offset); | 562 m_downstreamEnd = createLegacyEditingPosition(m_downstreamEn
d.deprecatedNode(), offset); |
563 } | 563 } |
564 } | 564 } |
565 } | 565 } |
566 } | 566 } |
567 } | 567 } |
568 | 568 |
569 void DeleteSelectionCommand::fixupWhitespace() | 569 void DeleteSelectionCommand::fixupWhitespace() |
570 { | 570 { |
571 document()->updateLayoutIgnorePendingStylesheets(); | 571 document().updateLayoutIgnorePendingStylesheets(); |
572 // FIXME: isRenderedCharacter should be removed, and we should use VisiblePo
sition::characterAfter and VisiblePosition::characterBefore | 572 // FIXME: isRenderedCharacter should be removed, and we should use VisiblePo
sition::characterAfter and VisiblePosition::characterBefore |
573 if (m_leadingWhitespace.isNotNull() && !m_leadingWhitespace.isRenderedCharac
ter() && m_leadingWhitespace.deprecatedNode()->isTextNode()) { | 573 if (m_leadingWhitespace.isNotNull() && !m_leadingWhitespace.isRenderedCharac
ter() && m_leadingWhitespace.deprecatedNode()->isTextNode()) { |
574 Text* textNode = toText(m_leadingWhitespace.deprecatedNode()); | 574 Text* textNode = toText(m_leadingWhitespace.deprecatedNode()); |
575 ASSERT(!textNode->renderer() || textNode->renderer()->style()->collapseW
hiteSpace()); | 575 ASSERT(!textNode->renderer() || textNode->renderer()->style()->collapseW
hiteSpace()); |
576 replaceTextInNodePreservingMarkers(textNode, m_leadingWhitespace.depreca
tedEditingOffset(), 1, nonBreakingSpaceString()); | 576 replaceTextInNodePreservingMarkers(textNode, m_leadingWhitespace.depreca
tedEditingOffset(), 1, nonBreakingSpaceString()); |
577 } | 577 } |
578 if (m_trailingWhitespace.isNotNull() && !m_trailingWhitespace.isRenderedChar
acter() && m_trailingWhitespace.deprecatedNode()->isTextNode()) { | 578 if (m_trailingWhitespace.isNotNull() && !m_trailingWhitespace.isRenderedChar
acter() && m_trailingWhitespace.deprecatedNode()->isTextNode()) { |
579 Text* textNode = toText(m_trailingWhitespace.deprecatedNode()); | 579 Text* textNode = toText(m_trailingWhitespace.deprecatedNode()); |
580 ASSERT(!textNode->renderer() ||textNode->renderer()->style()->collapseWh
iteSpace()); | 580 ASSERT(!textNode->renderer() ||textNode->renderer()->style()->collapseWh
iteSpace()); |
581 replaceTextInNodePreservingMarkers(textNode, m_trailingWhitespace.deprec
atedEditingOffset(), 1, nonBreakingSpaceString()); | 581 replaceTextInNodePreservingMarkers(textNode, m_trailingWhitespace.deprec
atedEditingOffset(), 1, nonBreakingSpaceString()); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
618 // m_downstreamEnd's block has been emptied out by deletion. There is no co
ntent inside of it to | 618 // m_downstreamEnd's block has been emptied out by deletion. There is no co
ntent inside of it to |
619 // move, so just remove it. | 619 // move, so just remove it. |
620 Element* endBlock = enclosingBlock(m_downstreamEnd.deprecatedNode()); | 620 Element* endBlock = enclosingBlock(m_downstreamEnd.deprecatedNode()); |
621 if (!endBlock || !endBlock->contains(startOfParagraphToMove.deepEquivalent()
.deprecatedNode()) || !startOfParagraphToMove.deepEquivalent().deprecatedNode())
{ | 621 if (!endBlock || !endBlock->contains(startOfParagraphToMove.deepEquivalent()
.deprecatedNode()) || !startOfParagraphToMove.deepEquivalent().deprecatedNode())
{ |
622 removeNode(enclosingBlock(m_downstreamEnd.deprecatedNode())); | 622 removeNode(enclosingBlock(m_downstreamEnd.deprecatedNode())); |
623 return; | 623 return; |
624 } | 624 } |
625 | 625 |
626 // We need to merge into m_upstreamStart's block, but it's been emptied out
and collapsed by deletion. | 626 // We need to merge into m_upstreamStart's block, but it's been emptied out
and collapsed by deletion. |
627 if (!mergeDestination.deepEquivalent().deprecatedNode() || !mergeDestination
.deepEquivalent().deprecatedNode()->isDescendantOf(enclosingBlock(m_upstreamStar
t.containerNode())) || m_startsAtEmptyLine) { | 627 if (!mergeDestination.deepEquivalent().deprecatedNode() || !mergeDestination
.deepEquivalent().deprecatedNode()->isDescendantOf(enclosingBlock(m_upstreamStar
t.containerNode())) || m_startsAtEmptyLine) { |
628 insertNodeAt(createBreakElement(document()).get(), m_upstreamStart); | 628 insertNodeAt(createBreakElement(&document()).get(), m_upstreamStart); |
629 mergeDestination = VisiblePosition(m_upstreamStart); | 629 mergeDestination = VisiblePosition(m_upstreamStart); |
630 } | 630 } |
631 | 631 |
632 if (mergeDestination == startOfParagraphToMove) | 632 if (mergeDestination == startOfParagraphToMove) |
633 return; | 633 return; |
634 | 634 |
635 VisiblePosition endOfParagraphToMove = endOfParagraph(startOfParagraphToMove
); | 635 VisiblePosition endOfParagraphToMove = endOfParagraph(startOfParagraphToMove
); |
636 | 636 |
637 if (mergeDestination == endOfParagraphToMove) | 637 if (mergeDestination == endOfParagraphToMove) |
638 return; | 638 return; |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
718 m_typingStyle = m_deleteIntoBlockquoteStyle; | 718 m_typingStyle = m_deleteIntoBlockquoteStyle; |
719 m_deleteIntoBlockquoteStyle = 0; | 719 m_deleteIntoBlockquoteStyle = 0; |
720 | 720 |
721 m_typingStyle->prepareToApplyAt(m_endingPosition); | 721 m_typingStyle->prepareToApplyAt(m_endingPosition); |
722 if (m_typingStyle->isEmpty()) | 722 if (m_typingStyle->isEmpty()) |
723 m_typingStyle = 0; | 723 m_typingStyle = 0; |
724 // This is where we've deleted all traces of a style but not a whole paragra
ph (that's handled above). | 724 // This is where we've deleted all traces of a style but not a whole paragra
ph (that's handled above). |
725 // In this case if we start typing, the new characters should have the same
style as the just deleted ones, | 725 // In this case if we start typing, the new characters should have the same
style as the just deleted ones, |
726 // but, if we change the selection, come back and start typing that style sh
ould be lost. Also see | 726 // but, if we change the selection, come back and start typing that style sh
ould be lost. Also see |
727 // preserveTypingStyle() below. | 727 // preserveTypingStyle() below. |
728 document()->frame()->selection()->setTypingStyle(m_typingStyle); | 728 document().frame()->selection()->setTypingStyle(m_typingStyle); |
729 } | 729 } |
730 | 730 |
731 void DeleteSelectionCommand::clearTransientState() | 731 void DeleteSelectionCommand::clearTransientState() |
732 { | 732 { |
733 m_selectionToDelete = VisibleSelection(); | 733 m_selectionToDelete = VisibleSelection(); |
734 m_upstreamStart.clear(); | 734 m_upstreamStart.clear(); |
735 m_downstreamStart.clear(); | 735 m_downstreamStart.clear(); |
736 m_upstreamEnd.clear(); | 736 m_upstreamEnd.clear(); |
737 m_downstreamEnd.clear(); | 737 m_downstreamEnd.clear(); |
738 m_endingPosition.clear(); | 738 m_endingPosition.clear(); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
818 | 818 |
819 if (!m_needPlaceholder && rootWillStayOpenWithoutPlaceholder) { | 819 if (!m_needPlaceholder && rootWillStayOpenWithoutPlaceholder) { |
820 VisiblePosition visualEnding(m_endingPosition); | 820 VisiblePosition visualEnding(m_endingPosition); |
821 m_needPlaceholder = !isStartOfParagraph(visualEnding, CanCrossEditingBou
ndary) | 821 m_needPlaceholder = !isStartOfParagraph(visualEnding, CanCrossEditingBou
ndary) |
822 && isEndOfParagraph(visualEnding, CanCrossEditingBoundary) | 822 && isEndOfParagraph(visualEnding, CanCrossEditingBoundary) |
823 && lineBreakExistsAtVisiblePosition(visualEnding) | 823 && lineBreakExistsAtVisiblePosition(visualEnding) |
824 && visualEnding.next(CannotCrossEditingBoundary).isNull() | 824 && visualEnding.next(CannotCrossEditingBoundary).isNull() |
825 && lineBreakBeforeStart; | 825 && lineBreakBeforeStart; |
826 } | 826 } |
827 | 827 |
828 RefPtr<Node> placeholder = m_needPlaceholder ? createBreakElement(document()
).get() : 0; | 828 RefPtr<Node> placeholder = m_needPlaceholder ? createBreakElement(&document(
)).get() : 0; |
829 | 829 |
830 if (placeholder) { | 830 if (placeholder) { |
831 if (m_sanitizeMarkup) | 831 if (m_sanitizeMarkup) |
832 removeRedundantBlocks(); | 832 removeRedundantBlocks(); |
833 insertNodeAt(placeholder.get(), m_endingPosition); | 833 insertNodeAt(placeholder.get(), m_endingPosition); |
834 } | 834 } |
835 | 835 |
836 rebalanceWhitespaceAt(m_endingPosition); | 836 rebalanceWhitespaceAt(m_endingPosition); |
837 | 837 |
838 calculateTypingStyleAfterDelete(); | 838 calculateTypingStyleAfterDelete(); |
(...skipping 12 matching lines...) Expand all Loading... |
851 | 851 |
852 // Normally deletion doesn't preserve the typing style that was present before i
t. For example, | 852 // Normally deletion doesn't preserve the typing style that was present before i
t. For example, |
853 // type a character, Bold, then delete the character and start typing. The Bold
typing style shouldn't | 853 // type a character, Bold, then delete the character and start typing. The Bold
typing style shouldn't |
854 // stick around. Deletion should preserve a typing style that *it* sets, howeve
r. | 854 // stick around. Deletion should preserve a typing style that *it* sets, howeve
r. |
855 bool DeleteSelectionCommand::preservesTypingStyle() const | 855 bool DeleteSelectionCommand::preservesTypingStyle() const |
856 { | 856 { |
857 return m_typingStyle; | 857 return m_typingStyle; |
858 } | 858 } |
859 | 859 |
860 } // namespace WebCore | 860 } // namespace WebCore |
OLD | NEW |