| 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 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 return true; | 72 return true; |
| 73 } | 73 } |
| 74 | 74 |
| 75 DeleteSelectionCommand::DeleteSelectionCommand(Document *document, bool smartDel
ete, bool mergeBlocksAfterDelete, bool replace, bool expandForSpecialElements) | 75 DeleteSelectionCommand::DeleteSelectionCommand(Document *document, bool smartDel
ete, bool mergeBlocksAfterDelete, bool replace, bool expandForSpecialElements) |
| 76 : CompositeEditCommand(document), | 76 : CompositeEditCommand(document), |
| 77 m_hasSelectionToDelete(false), | 77 m_hasSelectionToDelete(false), |
| 78 m_smartDelete(smartDelete), | 78 m_smartDelete(smartDelete), |
| 79 m_mergeBlocksAfterDelete(mergeBlocksAfterDelete), | 79 m_mergeBlocksAfterDelete(mergeBlocksAfterDelete), |
| 80 m_replace(replace), | 80 m_replace(replace), |
| 81 m_expandForSpecialElements(expandForSpecialElements), | 81 m_expandForSpecialElements(expandForSpecialElements), |
| 82 m_pruneStartBlockIfNecessary(false), |
| 82 m_startBlock(0), | 83 m_startBlock(0), |
| 83 m_endBlock(0), | 84 m_endBlock(0), |
| 84 m_typingStyle(0), | 85 m_typingStyle(0), |
| 85 m_deleteIntoBlockquoteStyle(0) | 86 m_deleteIntoBlockquoteStyle(0) |
| 86 { | 87 { |
| 87 } | 88 } |
| 88 | 89 |
| 89 DeleteSelectionCommand::DeleteSelectionCommand(const Selection& selection, bool
smartDelete, bool mergeBlocksAfterDelete, bool replace, bool expandForSpecialEle
ments) | 90 DeleteSelectionCommand::DeleteSelectionCommand(const Selection& selection, bool
smartDelete, bool mergeBlocksAfterDelete, bool replace, bool expandForSpecialEle
ments) |
| 90 : CompositeEditCommand(selection.start().node()->document()), | 91 : CompositeEditCommand(selection.start().node()->document()), |
| 91 m_hasSelectionToDelete(true), | 92 m_hasSelectionToDelete(true), |
| 92 m_smartDelete(smartDelete), | 93 m_smartDelete(smartDelete), |
| 93 m_mergeBlocksAfterDelete(mergeBlocksAfterDelete), | 94 m_mergeBlocksAfterDelete(mergeBlocksAfterDelete), |
| 94 m_replace(replace), | 95 m_replace(replace), |
| 95 m_expandForSpecialElements(expandForSpecialElements), | 96 m_expandForSpecialElements(expandForSpecialElements), |
| 97 m_pruneStartBlockIfNecessary(false), |
| 96 m_selectionToDelete(selection), | 98 m_selectionToDelete(selection), |
| 97 m_startBlock(0), | 99 m_startBlock(0), |
| 98 m_endBlock(0), | 100 m_endBlock(0), |
| 99 m_typingStyle(0), | 101 m_typingStyle(0), |
| 100 m_deleteIntoBlockquoteStyle(0) | 102 m_deleteIntoBlockquoteStyle(0) |
| 101 { | 103 { |
| 102 } | 104 } |
| 103 | 105 |
| 104 void DeleteSelectionCommand::initializeStartEnd(Position& start, Position& end) | 106 void DeleteSelectionCommand::initializeStartEnd(Position& start, Position& end) |
| 105 { | 107 { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 m_mergeBlocksAfterDelete = false; | 184 m_mergeBlocksAfterDelete = false; |
| 183 | 185 |
| 184 // Usually the start and the end of the selection to delete are pulled toget
her as a result of the deletion. | 186 // Usually the start and the end of the selection to delete are pulled toget
her as a result of the deletion. |
| 185 // Sometimes they aren't (like when no merge is requested), so we must choos
e one position to hold the caret | 187 // Sometimes they aren't (like when no merge is requested), so we must choos
e one position to hold the caret |
| 186 // and receive the placeholder after deletion. | 188 // and receive the placeholder after deletion. |
| 187 VisiblePosition visibleEnd(m_downstreamEnd); | 189 VisiblePosition visibleEnd(m_downstreamEnd); |
| 188 if (m_mergeBlocksAfterDelete && !isEndOfParagraph(visibleEnd)) | 190 if (m_mergeBlocksAfterDelete && !isEndOfParagraph(visibleEnd)) |
| 189 m_endingPosition = m_downstreamEnd; | 191 m_endingPosition = m_downstreamEnd; |
| 190 else | 192 else |
| 191 m_endingPosition = m_downstreamStart; | 193 m_endingPosition = m_downstreamStart; |
| 194 |
| 195 // We don't want to merge into a block if it will mean changing the quote le
vel of content after deleting |
| 196 // selections that contain a whole number paragraphs plus a line break, sinc
e it is unclear to most users |
| 197 // that such a selection actually ends at the start of the next paragraph. T
his matches TextEdit behavior |
| 198 // for indented paragraphs. |
| 199 if (numEnclosingMailBlockquotes(start) != numEnclosingMailBlockquotes(end) &
& isStartOfParagraph(visibleEnd) && isStartOfParagraph(VisiblePosition(start)))
{ |
| 200 m_mergeBlocksAfterDelete = false; |
| 201 m_pruneStartBlockIfNecessary = true; |
| 202 } |
| 192 | 203 |
| 193 // Handle leading and trailing whitespace, as well as smart delete adjustmen
ts to the selection | 204 // Handle leading and trailing whitespace, as well as smart delete adjustmen
ts to the selection |
| 194 m_leadingWhitespace = m_upstreamStart.leadingWhitespacePosition(m_selectionT
oDelete.affinity()); | 205 m_leadingWhitespace = m_upstreamStart.leadingWhitespacePosition(m_selectionT
oDelete.affinity()); |
| 195 m_trailingWhitespace = m_downstreamEnd.trailingWhitespacePosition(VP_DEFAULT
_AFFINITY); | 206 m_trailingWhitespace = m_downstreamEnd.trailingWhitespacePosition(VP_DEFAULT
_AFFINITY); |
| 196 | 207 |
| 197 if (m_smartDelete) { | 208 if (m_smartDelete) { |
| 198 | 209 |
| 199 // skip smart delete if the selection to delete already starts or ends w
ith whitespace | 210 // skip smart delete if the selection to delete already starts or ends w
ith whitespace |
| 200 Position pos = VisiblePosition(m_upstreamStart, m_selectionToDelete.affi
nity()).deepEquivalent(); | 211 Position pos = VisiblePosition(m_upstreamStart, m_selectionToDelete.affi
nity()).deepEquivalent(); |
| 201 bool skipSmartDelete = pos.trailingWhitespacePosition(VP_DEFAULT_AFFINIT
Y, true).isNotNull(); | 212 bool skipSmartDelete = pos.trailingWhitespacePosition(VP_DEFAULT_AFFINIT
Y, true).isNotNull(); |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 503 Text* textNode = static_cast<Text*>(m_trailingWhitespace.node()); | 514 Text* textNode = static_cast<Text*>(m_trailingWhitespace.node()); |
| 504 ASSERT(!textNode->renderer() ||textNode->renderer()->style()->collapseWh
iteSpace()); | 515 ASSERT(!textNode->renderer() ||textNode->renderer()->style()->collapseWh
iteSpace()); |
| 505 replaceTextInNode(textNode, m_trailingWhitespace.offset(), 1, nonBreakin
gSpaceString()); | 516 replaceTextInNode(textNode, m_trailingWhitespace.offset(), 1, nonBreakin
gSpaceString()); |
| 506 } | 517 } |
| 507 } | 518 } |
| 508 | 519 |
| 509 // If a selection starts in one block and ends in another, we have to merge to b
ring content before the | 520 // If a selection starts in one block and ends in another, we have to merge to b
ring content before the |
| 510 // start together with content after the end. | 521 // start together with content after the end. |
| 511 void DeleteSelectionCommand::mergeParagraphs() | 522 void DeleteSelectionCommand::mergeParagraphs() |
| 512 { | 523 { |
| 513 if (!m_mergeBlocksAfterDelete) | 524 if (!m_mergeBlocksAfterDelete) { |
| 525 if (m_pruneStartBlockIfNecessary) { |
| 526 // Make sure that the ending position isn't inside the block we're a
bout to prune. |
| 527 m_endingPosition = m_downstreamEnd; |
| 528 // We aren't going to merge into the start block, so remove it if it
's empty. |
| 529 prune(m_upstreamStart.node()); |
| 530 // Removing the start block during a deletion is usually an indicati
on that we need |
| 531 // a placeholder, but not in this case. |
| 532 m_needPlaceholder = false; |
| 533 } |
| 514 return; | 534 return; |
| 535 } |
| 536 |
| 537 // It shouldn't have been asked to both try and merge content into the start
block and prune it. |
| 538 ASSERT(!m_pruneStartBlockIfNecessary); |
| 515 | 539 |
| 516 // FIXME: Deletion should adjust selection endpoints as it removes nodes so
that we never get into this state (4099839). | 540 // FIXME: Deletion should adjust selection endpoints as it removes nodes so
that we never get into this state (4099839). |
| 517 if (!m_downstreamEnd.node()->inDocument() || !m_upstreamStart.node()->inDocu
ment()) | 541 if (!m_downstreamEnd.node()->inDocument() || !m_upstreamStart.node()->inDocu
ment()) |
| 518 return; | 542 return; |
| 519 | 543 |
| 520 // FIXME: The deletion algorithm shouldn't let this happen. | 544 // FIXME: The deletion algorithm shouldn't let this happen. |
| 521 if (Range::compareBoundaryPoints(m_upstreamStart, m_downstreamEnd) > 0) | 545 if (Range::compareBoundaryPoints(m_upstreamStart, m_downstreamEnd) > 0) |
| 522 return; | 546 return; |
| 523 | 547 |
| 524 // FIXME: Merging will always be unnecessary in this case, but we really bai
l here because this is a case where | 548 // FIXME: Merging will always be unnecessary in this case, but we really bai
l here because this is a case where |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 781 | 805 |
| 782 // Normally deletion doesn't preserve the typing style that was present before i
t. For example, | 806 // Normally deletion doesn't preserve the typing style that was present before i
t. For example, |
| 783 // type a character, Bold, then delete the character and start typing. The Bold
typing style shouldn't | 807 // type a character, Bold, then delete the character and start typing. The Bold
typing style shouldn't |
| 784 // stick around. Deletion should preserve a typing style that *it* sets, howeve
r. | 808 // stick around. Deletion should preserve a typing style that *it* sets, howeve
r. |
| 785 bool DeleteSelectionCommand::preservesTypingStyle() const | 809 bool DeleteSelectionCommand::preservesTypingStyle() const |
| 786 { | 810 { |
| 787 return m_typingStyle; | 811 return m_typingStyle; |
| 788 } | 812 } |
| 789 | 813 |
| 790 } // namespace WebCore | 814 } // namespace WebCore |
| OLD | NEW |