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 |