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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 #include "core/layout/LayoutTableCell.h" | 43 #include "core/layout/LayoutTableCell.h" |
44 #include "core/layout/LayoutText.h" | 44 #include "core/layout/LayoutText.h" |
45 | 45 |
46 namespace blink { | 46 namespace blink { |
47 | 47 |
48 using namespace HTMLNames; | 48 using namespace HTMLNames; |
49 | 49 |
50 static bool isTableCellEmpty(Node* cell) | 50 static bool isTableCellEmpty(Node* cell) |
51 { | 51 { |
52 ASSERT(isTableCell(cell)); | 52 ASSERT(isTableCell(cell)); |
53 return VisiblePosition(firstPositionInNode(cell)).deepEquivalent() == Visibl
ePosition(lastPositionInNode(cell)).deepEquivalent(); | 53 return createVisiblePosition(firstPositionInNode(cell)).deepEquivalent() ==
createVisiblePosition(lastPositionInNode(cell)).deepEquivalent(); |
54 } | 54 } |
55 | 55 |
56 static bool isTableRowEmpty(Node* row) | 56 static bool isTableRowEmpty(Node* row) |
57 { | 57 { |
58 if (!isHTMLTableRowElement(row)) | 58 if (!isHTMLTableRowElement(row)) |
59 return false; | 59 return false; |
60 | 60 |
61 for (Node* child = row->firstChild(); child; child = child->nextSibling()) { | 61 for (Node* child = row->firstChild(); child; child = child->nextSibling()) { |
62 if (isTableCell(child) && !isTableCellEmpty(child)) | 62 if (isTableCell(child) && !isTableCellEmpty(child)) |
63 return false; | 63 return false; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 while (1) { | 122 while (1) { |
123 startSpecialContainer = 0; | 123 startSpecialContainer = 0; |
124 endSpecialContainer = 0; | 124 endSpecialContainer = 0; |
125 | 125 |
126 Position s = positionBeforeContainingSpecialElement(start, &startSpecial
Container); | 126 Position s = positionBeforeContainingSpecialElement(start, &startSpecial
Container); |
127 Position e = positionAfterContainingSpecialElement(end, &endSpecialConta
iner); | 127 Position e = positionAfterContainingSpecialElement(end, &endSpecialConta
iner); |
128 | 128 |
129 if (!startSpecialContainer && !endSpecialContainer) | 129 if (!startSpecialContainer && !endSpecialContainer) |
130 break; | 130 break; |
131 | 131 |
132 if (VisiblePosition(start).deepEquivalent() != m_selectionToDelete.visib
leStart().deepEquivalent() || VisiblePosition(end).deepEquivalent() != m_selecti
onToDelete.visibleEnd().deepEquivalent()) | 132 if (createVisiblePosition(start).deepEquivalent() != m_selectionToDelete
.visibleStart().deepEquivalent() || createVisiblePosition(end).deepEquivalent()
!= m_selectionToDelete.visibleEnd().deepEquivalent()) |
133 break; | 133 break; |
134 | 134 |
135 // If we're going to expand to include the startSpecialContainer, it mus
t be fully selected. | 135 // If we're going to expand to include the startSpecialContainer, it mus
t be fully selected. |
136 if (startSpecialContainer && !endSpecialContainer && comparePositions(po
sitionInParentAfterNode(*startSpecialContainer), end) > -1) | 136 if (startSpecialContainer && !endSpecialContainer && comparePositions(po
sitionInParentAfterNode(*startSpecialContainer), end) > -1) |
137 break; | 137 break; |
138 | 138 |
139 // If we're going to expand to include the endSpecialContainer, it must
be fully selected. | 139 // If we're going to expand to include the endSpecialContainer, it must
be fully selected. |
140 if (endSpecialContainer && !startSpecialContainer && comparePositions(st
art, positionInParentBeforeNode(*endSpecialContainer)) > -1) | 140 if (endSpecialContainer && !startSpecialContainer && comparePositions(st
art, positionInParentBeforeNode(*endSpecialContainer)) > -1) |
141 break; | 141 break; |
142 | 142 |
143 if (startSpecialContainer && startSpecialContainer->isDescendantOf(endSp
ecialContainer)) { | 143 if (startSpecialContainer && startSpecialContainer->isDescendantOf(endSp
ecialContainer)) { |
144 // Don't adjust the end yet, it is the end of a special element that
contains the start | 144 // Don't adjust the end yet, it is the end of a special element that
contains the start |
145 // special element (which may or may not be fully selected). | 145 // special element (which may or may not be fully selected). |
146 start = s; | 146 start = s; |
147 } else if (endSpecialContainer && endSpecialContainer->isDescendantOf(st
artSpecialContainer)) { | 147 } else if (endSpecialContainer && endSpecialContainer->isDescendantOf(st
artSpecialContainer)) { |
148 // Don't adjust the start yet, it is the start of a special element
that contains the end | 148 // Don't adjust the start yet, it is the start of a special element
that contains the end |
149 // special element (which may or may not be fully selected). | 149 // special element (which may or may not be fully selected). |
150 end = e; | 150 end = e; |
151 } else { | 151 } else { |
152 start = s; | 152 start = s; |
153 end = e; | 153 end = e; |
154 } | 154 } |
155 } | 155 } |
156 } | 156 } |
157 | 157 |
158 void DeleteSelectionCommand::setStartingSelectionOnSmartDelete(const Position& s
tart, const Position& end) | 158 void DeleteSelectionCommand::setStartingSelectionOnSmartDelete(const Position& s
tart, const Position& end) |
159 { | 159 { |
160 bool isBaseFirst = startingSelection().isBaseFirst(); | 160 bool isBaseFirst = startingSelection().isBaseFirst(); |
161 VisiblePosition newBase(isBaseFirst ? start : end); | 161 VisiblePosition newBase = createVisiblePosition(isBaseFirst ? start : end); |
162 VisiblePosition newExtent(isBaseFirst ? end : start); | 162 VisiblePosition newExtent = createVisiblePosition(isBaseFirst ? end : start)
; |
163 setStartingSelection(VisibleSelection(newBase, newExtent, startingSelection(
).isDirectional())); | 163 setStartingSelection(VisibleSelection(newBase, newExtent, startingSelection(
).isDirectional())); |
164 } | 164 } |
165 | 165 |
166 void DeleteSelectionCommand::initializePositionData() | 166 void DeleteSelectionCommand::initializePositionData() |
167 { | 167 { |
168 Position start, end; | 168 Position start, end; |
169 initializeStartEnd(start, end); | 169 initializeStartEnd(start, end); |
170 | 170 |
171 ASSERT(isEditablePosition(start, ContentIsEditable, DoNotUpdateStyle)); | 171 ASSERT(isEditablePosition(start, ContentIsEditable, DoNotUpdateStyle)); |
172 if (!isEditablePosition(end, ContentIsEditable, DoNotUpdateStyle)) | 172 if (!isEditablePosition(end, ContentIsEditable, DoNotUpdateStyle)) |
(...skipping 15 matching lines...) Expand all Loading... |
188 // tell that function that we don't care if it returns non-editable nodes. | 188 // tell that function that we don't care if it returns non-editable nodes. |
189 Node* startCell = enclosingNodeOfType(m_upstreamStart, &isTableCell, CanCros
sEditingBoundary); | 189 Node* startCell = enclosingNodeOfType(m_upstreamStart, &isTableCell, CanCros
sEditingBoundary); |
190 Node* endCell = enclosingNodeOfType(m_downstreamEnd, &isTableCell, CanCrossE
ditingBoundary); | 190 Node* endCell = enclosingNodeOfType(m_downstreamEnd, &isTableCell, CanCrossE
ditingBoundary); |
191 // FIXME: This isn't right. A borderless table with two rows and a single c
olumn would appear as two paragraphs. | 191 // FIXME: This isn't right. A borderless table with two rows and a single c
olumn would appear as two paragraphs. |
192 if (endCell && endCell != startCell) | 192 if (endCell && endCell != startCell) |
193 m_mergeBlocksAfterDelete = false; | 193 m_mergeBlocksAfterDelete = false; |
194 | 194 |
195 // Usually the start and the end of the selection to delete are pulled toget
her as a result of the deletion. | 195 // Usually the start and the end of the selection to delete are pulled toget
her as a result of the deletion. |
196 // Sometimes they aren't (like when no merge is requested), so we must choos
e one position to hold the caret | 196 // Sometimes they aren't (like when no merge is requested), so we must choos
e one position to hold the caret |
197 // and receive the placeholder after deletion. | 197 // and receive the placeholder after deletion. |
198 VisiblePosition visibleEnd(m_downstreamEnd); | 198 VisiblePosition visibleEnd = createVisiblePosition(m_downstreamEnd); |
199 if (m_mergeBlocksAfterDelete && !isEndOfParagraph(visibleEnd)) | 199 if (m_mergeBlocksAfterDelete && !isEndOfParagraph(visibleEnd)) |
200 m_endingPosition = m_downstreamEnd; | 200 m_endingPosition = m_downstreamEnd; |
201 else | 201 else |
202 m_endingPosition = m_downstreamStart; | 202 m_endingPosition = m_downstreamStart; |
203 | 203 |
204 // We don't want to merge into a block if it will mean changing the quote le
vel of content after deleting | 204 // We don't want to merge into a block if it will mean changing the quote le
vel of content after deleting |
205 // selections that contain a whole number paragraphs plus a line break, sinc
e it is unclear to most users | 205 // selections that contain a whole number paragraphs plus a line break, sinc
e it is unclear to most users |
206 // that such a selection actually ends at the start of the next paragraph. T
his matches TextEdit behavior | 206 // that such a selection actually ends at the start of the next paragraph. T
his matches TextEdit behavior |
207 // for indented paragraphs. | 207 // for indented paragraphs. |
208 // Only apply this rule if the endingSelection is a range selection. If it
is a caret, then other operations have created | 208 // Only apply this rule if the endingSelection is a range selection. If it
is a caret, then other operations have created |
209 // the selection we're deleting (like the process of creating a selection to
delete during a backspace), and the user isn't in the situation described above
. | 209 // the selection we're deleting (like the process of creating a selection to
delete during a backspace), and the user isn't in the situation described above
. |
210 if (numEnclosingMailBlockquotes(start) != numEnclosingMailBlockquotes(end) | 210 if (numEnclosingMailBlockquotes(start) != numEnclosingMailBlockquotes(end) |
211 && isStartOfParagraph(visibleEnd) && isStartOfParagraph(VisiblePosition(
start)) | 211 && isStartOfParagraph(visibleEnd) && isStartOfParagraph(createVisiblePos
ition(start)) |
212 && endingSelection().isRange()) { | 212 && endingSelection().isRange()) { |
213 m_mergeBlocksAfterDelete = false; | 213 m_mergeBlocksAfterDelete = false; |
214 m_pruneStartBlockIfNecessary = true; | 214 m_pruneStartBlockIfNecessary = true; |
215 } | 215 } |
216 | 216 |
217 // Handle leading and trailing whitespace, as well as smart delete adjustmen
ts to the selection | 217 // Handle leading and trailing whitespace, as well as smart delete adjustmen
ts to the selection |
218 m_leadingWhitespace = leadingWhitespacePosition(m_upstreamStart, m_selection
ToDelete.affinity()); | 218 m_leadingWhitespace = leadingWhitespacePosition(m_upstreamStart, m_selection
ToDelete.affinity()); |
219 m_trailingWhitespace = trailingWhitespacePosition(m_downstreamEnd, VP_DEFAUL
T_AFFINITY); | 219 m_trailingWhitespace = trailingWhitespacePosition(m_downstreamEnd, VP_DEFAUL
T_AFFINITY); |
220 | 220 |
221 if (m_smartDelete) { | 221 if (m_smartDelete) { |
222 | 222 |
223 // skip smart delete if the selection to delete already starts or ends w
ith whitespace | 223 // skip smart delete if the selection to delete already starts or ends w
ith whitespace |
224 Position pos = VisiblePosition(m_upstreamStart, m_selectionToDelete.affi
nity()).deepEquivalent(); | 224 Position pos = createVisiblePosition(m_upstreamStart, m_selectionToDelet
e.affinity()).deepEquivalent(); |
225 bool skipSmartDelete = trailingWhitespacePosition(pos, VP_DEFAULT_AFFINI
TY, ConsiderNonCollapsibleWhitespace).isNotNull(); | 225 bool skipSmartDelete = trailingWhitespacePosition(pos, VP_DEFAULT_AFFINI
TY, ConsiderNonCollapsibleWhitespace).isNotNull(); |
226 if (!skipSmartDelete) | 226 if (!skipSmartDelete) |
227 skipSmartDelete = leadingWhitespacePosition(m_downstreamEnd, VP_DEFA
ULT_AFFINITY, ConsiderNonCollapsibleWhitespace).isNotNull(); | 227 skipSmartDelete = leadingWhitespacePosition(m_downstreamEnd, VP_DEFA
ULT_AFFINITY, ConsiderNonCollapsibleWhitespace).isNotNull(); |
228 | 228 |
229 // extend selection upstream if there is whitespace there | 229 // extend selection upstream if there is whitespace there |
230 bool hasLeadingWhitespaceBeforeAdjustment = leadingWhitespacePosition(m_
upstreamStart, m_selectionToDelete.affinity(), ConsiderNonCollapsibleWhitespace)
.isNotNull(); | 230 bool hasLeadingWhitespaceBeforeAdjustment = leadingWhitespacePosition(m_
upstreamStart, m_selectionToDelete.affinity(), ConsiderNonCollapsibleWhitespace)
.isNotNull(); |
231 if (!skipSmartDelete && hasLeadingWhitespaceBeforeAdjustment) { | 231 if (!skipSmartDelete && hasLeadingWhitespaceBeforeAdjustment) { |
232 VisiblePosition visiblePos = previousPositionOf(VisiblePosition(m_up
streamStart, VP_DEFAULT_AFFINITY)); | 232 VisiblePosition visiblePos = previousPositionOf(createVisiblePositio
n(m_upstreamStart, VP_DEFAULT_AFFINITY)); |
233 pos = visiblePos.deepEquivalent(); | 233 pos = visiblePos.deepEquivalent(); |
234 // Expand out one character upstream for smart delete and recalculat
e | 234 // Expand out one character upstream for smart delete and recalculat
e |
235 // positions based on this change. | 235 // positions based on this change. |
236 m_upstreamStart = mostBackwardCaretPosition(pos); | 236 m_upstreamStart = mostBackwardCaretPosition(pos); |
237 m_downstreamStart = mostForwardCaretPosition(pos); | 237 m_downstreamStart = mostForwardCaretPosition(pos); |
238 m_leadingWhitespace = leadingWhitespacePosition(m_upstreamStart, vis
iblePos.affinity()); | 238 m_leadingWhitespace = leadingWhitespacePosition(m_upstreamStart, vis
iblePos.affinity()); |
239 | 239 |
240 setStartingSelectionOnSmartDelete(m_upstreamStart, m_upstreamEnd); | 240 setStartingSelectionOnSmartDelete(m_upstreamStart, m_upstreamEnd); |
241 } | 241 } |
242 | 242 |
243 // trailing whitespace is only considered for smart delete if there is n
o leading | 243 // trailing whitespace is only considered for smart delete if there is n
o leading |
244 // whitespace, as in the case where you double-click the first word of a
paragraph. | 244 // whitespace, as in the case where you double-click the first word of a
paragraph. |
245 if (!skipSmartDelete && !hasLeadingWhitespaceBeforeAdjustment && trailin
gWhitespacePosition(m_downstreamEnd, VP_DEFAULT_AFFINITY, ConsiderNonCollapsible
Whitespace).isNotNull()) { | 245 if (!skipSmartDelete && !hasLeadingWhitespaceBeforeAdjustment && trailin
gWhitespacePosition(m_downstreamEnd, VP_DEFAULT_AFFINITY, ConsiderNonCollapsible
Whitespace).isNotNull()) { |
246 // Expand out one character downstream for smart delete and recalcul
ate | 246 // Expand out one character downstream for smart delete and recalcul
ate |
247 // positions based on this change. | 247 // positions based on this change. |
248 pos = nextPositionOf(VisiblePosition(m_downstreamEnd, VP_DEFAULT_AFF
INITY)).deepEquivalent(); | 248 pos = nextPositionOf(createVisiblePosition(m_downstreamEnd, VP_DEFAU
LT_AFFINITY)).deepEquivalent(); |
249 m_upstreamEnd = mostBackwardCaretPosition(pos); | 249 m_upstreamEnd = mostBackwardCaretPosition(pos); |
250 m_downstreamEnd = mostForwardCaretPosition(pos); | 250 m_downstreamEnd = mostForwardCaretPosition(pos); |
251 m_trailingWhitespace = trailingWhitespacePosition(m_downstreamEnd, V
P_DEFAULT_AFFINITY); | 251 m_trailingWhitespace = trailingWhitespacePosition(m_downstreamEnd, V
P_DEFAULT_AFFINITY); |
252 | 252 |
253 setStartingSelectionOnSmartDelete(m_downstreamStart, m_downstreamEnd
); | 253 setStartingSelectionOnSmartDelete(m_downstreamStart, m_downstreamEnd
); |
254 } | 254 } |
255 } | 255 } |
256 | 256 |
257 // We must pass call parentAnchoredEquivalent on the positions since some ed
iting positions | 257 // We must pass call parentAnchoredEquivalent on the positions since some ed
iting positions |
258 // that appear inside their nodes aren't really inside them. [hr, 0] is one
example. | 258 // that appear inside their nodes aren't really inside them. [hr, 0] is one
example. |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 bool upstreamStartIsBR = isHTMLBRElement(*nodeAfterUpstreamStart); | 311 bool upstreamStartIsBR = isHTMLBRElement(*nodeAfterUpstreamStart); |
312 bool downstreamStartIsBR = isHTMLBRElement(*nodeAfterDownstreamStart); | 312 bool downstreamStartIsBR = isHTMLBRElement(*nodeAfterDownstreamStart); |
313 bool isBROnLineByItself = upstreamStartIsBR && downstreamStartIsBR && nodeAf
terDownstreamStart == nodeAfterUpstreamEnd; | 313 bool isBROnLineByItself = upstreamStartIsBR && downstreamStartIsBR && nodeAf
terDownstreamStart == nodeAfterUpstreamEnd; |
314 if (isBROnLineByItself) { | 314 if (isBROnLineByItself) { |
315 removeNode(nodeAfterDownstreamStart); | 315 removeNode(nodeAfterDownstreamStart); |
316 return true; | 316 return true; |
317 } | 317 } |
318 | 318 |
319 // FIXME: This code doesn't belong in here. | 319 // FIXME: This code doesn't belong in here. |
320 // We detect the case where the start is an empty line consisting of BR not
wrapped in a block element. | 320 // We detect the case where the start is an empty line consisting of BR not
wrapped in a block element. |
321 if (upstreamStartIsBR && downstreamStartIsBR && !(isStartOfBlock(VisiblePosi
tion(positionBeforeNode(nodeAfterUpstreamStart))) && isEndOfBlock(VisiblePositio
n(positionAfterNode(nodeAfterUpstreamStart))))) { | 321 if (upstreamStartIsBR && downstreamStartIsBR && !(isStartOfBlock(createVisib
lePosition(positionBeforeNode(nodeAfterUpstreamStart))) && isEndOfBlock(createVi
siblePosition(positionAfterNode(nodeAfterUpstreamStart))))) { |
322 m_startsAtEmptyLine = true; | 322 m_startsAtEmptyLine = true; |
323 m_endingPosition = m_downstreamEnd; | 323 m_endingPosition = m_downstreamEnd; |
324 } | 324 } |
325 | 325 |
326 return false; | 326 return false; |
327 } | 327 } |
328 | 328 |
329 static Position firstEditablePositionInNode(Node* node) | 329 static Position firstEditablePositionInNode(Node* node) |
330 { | 330 { |
331 ASSERT(node); | 331 ASSERT(node); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
377 LayoutObject* r = node->layoutObject(); | 377 LayoutObject* r = node->layoutObject(); |
378 if (r && r->isTableCell() && toLayoutTableCell(r)->contentHeight() <= 0)
{ | 378 if (r && r->isTableCell() && toLayoutTableCell(r)->contentHeight() <= 0)
{ |
379 Position firstEditablePosition = firstEditablePositionInNode(node.ge
t()); | 379 Position firstEditablePosition = firstEditablePositionInNode(node.ge
t()); |
380 if (firstEditablePosition.isNotNull()) | 380 if (firstEditablePosition.isNotNull()) |
381 insertBlockPlaceholder(firstEditablePosition); | 381 insertBlockPlaceholder(firstEditablePosition); |
382 } | 382 } |
383 return; | 383 return; |
384 } | 384 } |
385 | 385 |
386 if (node == m_startBlock) { | 386 if (node == m_startBlock) { |
387 VisiblePosition previous = previousPositionOf(VisiblePosition(firstPosit
ionInNode(m_startBlock.get()))); | 387 VisiblePosition previous = previousPositionOf(createVisiblePosition(firs
tPositionInNode(m_startBlock.get()))); |
388 if (previous.isNotNull() && !isEndOfBlock(previous)) | 388 if (previous.isNotNull() && !isEndOfBlock(previous)) |
389 m_needPlaceholder = true; | 389 m_needPlaceholder = true; |
390 } | 390 } |
391 if (node == m_endBlock) { | 391 if (node == m_endBlock) { |
392 VisiblePosition next = nextPositionOf(VisiblePosition(lastPositionInNode
(m_endBlock.get()))); | 392 VisiblePosition next = nextPositionOf(createVisiblePosition(lastPosition
InNode(m_endBlock.get()))); |
393 if (next.isNotNull() && !isStartOfBlock(next)) | 393 if (next.isNotNull() && !isStartOfBlock(next)) |
394 m_needPlaceholder = true; | 394 m_needPlaceholder = true; |
395 } | 395 } |
396 | 396 |
397 // FIXME: Update the endpoints of the range being deleted. | 397 // FIXME: Update the endpoints of the range being deleted. |
398 updatePositionForNodeRemoval(m_endingPosition, *node); | 398 updatePositionForNodeRemoval(m_endingPosition, *node); |
399 updatePositionForNodeRemoval(m_leadingWhitespace, *node); | 399 updatePositionForNodeRemoval(m_leadingWhitespace, *node); |
400 updatePositionForNodeRemoval(m_trailingWhitespace, *node); | 400 updatePositionForNodeRemoval(m_trailingWhitespace, *node); |
401 | 401 |
402 CompositeEditCommand::removeNode(node, shouldAssumeContentIsAlwaysEditable); | 402 CompositeEditCommand::removeNode(node, shouldAssumeContentIsAlwaysEditable); |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
608 return; | 608 return; |
609 | 609 |
610 // FIXME: The deletion algorithm shouldn't let this happen. | 610 // FIXME: The deletion algorithm shouldn't let this happen. |
611 if (comparePositions(m_upstreamStart, m_downstreamEnd) > 0) | 611 if (comparePositions(m_upstreamStart, m_downstreamEnd) > 0) |
612 return; | 612 return; |
613 | 613 |
614 // There's nothing to merge. | 614 // There's nothing to merge. |
615 if (m_upstreamStart == m_downstreamEnd) | 615 if (m_upstreamStart == m_downstreamEnd) |
616 return; | 616 return; |
617 | 617 |
618 VisiblePosition startOfParagraphToMove(m_downstreamEnd); | 618 VisiblePosition startOfParagraphToMove = createVisiblePosition(m_downstreamE
nd); |
619 VisiblePosition mergeDestination(m_upstreamStart); | 619 VisiblePosition mergeDestination = createVisiblePosition(m_upstreamStart); |
620 | 620 |
621 // m_downstreamEnd's block has been emptied out by deletion. There is no co
ntent inside of it to | 621 // m_downstreamEnd's block has been emptied out by deletion. There is no co
ntent inside of it to |
622 // move, so just remove it. | 622 // move, so just remove it. |
623 Element* endBlock = enclosingBlock(m_downstreamEnd.anchorNode()); | 623 Element* endBlock = enclosingBlock(m_downstreamEnd.anchorNode()); |
624 if (!endBlock || !endBlock->contains(startOfParagraphToMove.deepEquivalent()
.anchorNode()) || !startOfParagraphToMove.deepEquivalent().anchorNode()) { | 624 if (!endBlock || !endBlock->contains(startOfParagraphToMove.deepEquivalent()
.anchorNode()) || !startOfParagraphToMove.deepEquivalent().anchorNode()) { |
625 removeNode(enclosingBlock(m_downstreamEnd.anchorNode())); | 625 removeNode(enclosingBlock(m_downstreamEnd.anchorNode())); |
626 return; | 626 return; |
627 } | 627 } |
628 | 628 |
629 // We need to merge into m_upstreamStart's block, but it's been emptied out
and collapsed by deletion. | 629 // We need to merge into m_upstreamStart's block, but it's been emptied out
and collapsed by deletion. |
630 if (!mergeDestination.deepEquivalent().anchorNode() || (!mergeDestination.de
epEquivalent().anchorNode()->isDescendantOf(enclosingBlock(m_upstreamStart.compu
teContainerNode())) && (!mergeDestination.deepEquivalent().anchorNode()->hasChil
dren() || !m_upstreamStart.computeContainerNode()->hasChildren())) || (m_startsA
tEmptyLine && mergeDestination.deepEquivalent() != startOfParagraphToMove.deepEq
uivalent())) { | 630 if (!mergeDestination.deepEquivalent().anchorNode() || (!mergeDestination.de
epEquivalent().anchorNode()->isDescendantOf(enclosingBlock(m_upstreamStart.compu
teContainerNode())) && (!mergeDestination.deepEquivalent().anchorNode()->hasChil
dren() || !m_upstreamStart.computeContainerNode()->hasChildren())) || (m_startsA
tEmptyLine && mergeDestination.deepEquivalent() != startOfParagraphToMove.deepEq
uivalent())) { |
631 insertNodeAt(createBreakElement(document()).get(), m_upstreamStart); | 631 insertNodeAt(createBreakElement(document()).get(), m_upstreamStart); |
632 mergeDestination = VisiblePosition(m_upstreamStart); | 632 mergeDestination = createVisiblePosition(m_upstreamStart); |
633 } | 633 } |
634 | 634 |
635 if (mergeDestination.deepEquivalent() == startOfParagraphToMove.deepEquivale
nt()) | 635 if (mergeDestination.deepEquivalent() == startOfParagraphToMove.deepEquivale
nt()) |
636 return; | 636 return; |
637 | 637 |
638 VisiblePosition endOfParagraphToMove = endOfParagraph(startOfParagraphToMove
, CanSkipOverEditingBoundary); | 638 VisiblePosition endOfParagraphToMove = endOfParagraph(startOfParagraphToMove
, CanSkipOverEditingBoundary); |
639 | 639 |
640 if (mergeDestination.deepEquivalent() == endOfParagraphToMove.deepEquivalent
()) | 640 if (mergeDestination.deepEquivalent() == endOfParagraphToMove.deepEquivalent
()) |
641 return; | 641 return; |
642 | 642 |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
809 if (Element* table = isLastPositionBeforeTable(m_selectionToDelete.visib
leStart())) { | 809 if (Element* table = isLastPositionBeforeTable(m_selectionToDelete.visib
leStart())) { |
810 if (m_selectionToDelete.end().anchorNode()->isDescendantOf(table)) | 810 if (m_selectionToDelete.end().anchorNode()->isDescendantOf(table)) |
811 m_needPlaceholder = false; | 811 m_needPlaceholder = false; |
812 } | 812 } |
813 } | 813 } |
814 | 814 |
815 | 815 |
816 // set up our state | 816 // set up our state |
817 initializePositionData(); | 817 initializePositionData(); |
818 | 818 |
819 bool lineBreakBeforeStart = lineBreakExistsAtVisiblePosition(previousPositio
nOf(VisiblePosition(m_upstreamStart))); | 819 bool lineBreakBeforeStart = lineBreakExistsAtVisiblePosition(previousPositio
nOf(createVisiblePosition(m_upstreamStart))); |
820 | 820 |
821 // Delete any text that may hinder our ability to fixup whitespace after the | 821 // Delete any text that may hinder our ability to fixup whitespace after the |
822 // delete | 822 // delete |
823 deleteInsignificantTextDownstream(m_trailingWhitespace); | 823 deleteInsignificantTextDownstream(m_trailingWhitespace); |
824 | 824 |
825 saveTypingStyleState(); | 825 saveTypingStyleState(); |
826 | 826 |
827 // deleting just a BR is handled specially, at least because we do not | 827 // deleting just a BR is handled specially, at least because we do not |
828 // want to replace it with a placeholder BR! | 828 // want to replace it with a placeholder BR! |
829 if (handleSpecialCaseBRDelete()) { | 829 if (handleSpecialCaseBRDelete()) { |
830 calculateTypingStyleAfterDelete(); | 830 calculateTypingStyleAfterDelete(); |
831 setEndingSelection(VisibleSelection(m_endingPosition, affinity, endingSe
lection().isDirectional())); | 831 setEndingSelection(VisibleSelection(m_endingPosition, affinity, endingSe
lection().isDirectional())); |
832 clearTransientState(); | 832 clearTransientState(); |
833 rebalanceWhitespace(); | 833 rebalanceWhitespace(); |
834 return; | 834 return; |
835 } | 835 } |
836 | 836 |
837 handleGeneralDelete(); | 837 handleGeneralDelete(); |
838 | 838 |
839 fixupWhitespace(); | 839 fixupWhitespace(); |
840 | 840 |
841 mergeParagraphs(); | 841 mergeParagraphs(); |
842 | 842 |
843 removePreviouslySelectedEmptyTableRows(); | 843 removePreviouslySelectedEmptyTableRows(); |
844 | 844 |
845 if (!m_needPlaceholder && rootWillStayOpenWithoutPlaceholder) { | 845 if (!m_needPlaceholder && rootWillStayOpenWithoutPlaceholder) { |
846 VisiblePosition visualEnding(m_endingPosition); | 846 VisiblePosition visualEnding = createVisiblePosition(m_endingPosition); |
847 bool hasPlaceholder = lineBreakExistsAtVisiblePosition(visualEnding) | 847 bool hasPlaceholder = lineBreakExistsAtVisiblePosition(visualEnding) |
848 && nextPositionOf(visualEnding, CannotCrossEditingBoundary).isNull()
; | 848 && nextPositionOf(visualEnding, CannotCrossEditingBoundary).isNull()
; |
849 m_needPlaceholder = hasPlaceholder && lineBreakBeforeStart && !lineBreak
AtEndOfSelectionToDelete; | 849 m_needPlaceholder = hasPlaceholder && lineBreakBeforeStart && !lineBreak
AtEndOfSelectionToDelete; |
850 } | 850 } |
851 | 851 |
852 RefPtrWillBeRawPtr<HTMLBRElement> placeholder = m_needPlaceholder ? createBr
eakElement(document()) : nullptr; | 852 RefPtrWillBeRawPtr<HTMLBRElement> placeholder = m_needPlaceholder ? createBr
eakElement(document()) : nullptr; |
853 | 853 |
854 if (placeholder) { | 854 if (placeholder) { |
855 if (m_sanitizeMarkup) | 855 if (m_sanitizeMarkup) |
856 removeRedundantBlocks(); | 856 removeRedundantBlocks(); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
900 visitor->trace(m_deleteIntoBlockquoteStyle); | 900 visitor->trace(m_deleteIntoBlockquoteStyle); |
901 visitor->trace(m_startRoot); | 901 visitor->trace(m_startRoot); |
902 visitor->trace(m_endRoot); | 902 visitor->trace(m_endRoot); |
903 visitor->trace(m_startTableRow); | 903 visitor->trace(m_startTableRow); |
904 visitor->trace(m_endTableRow); | 904 visitor->trace(m_endTableRow); |
905 visitor->trace(m_temporaryPlaceholder); | 905 visitor->trace(m_temporaryPlaceholder); |
906 CompositeEditCommand::trace(visitor); | 906 CompositeEditCommand::trace(visitor); |
907 } | 907 } |
908 | 908 |
909 } // namespace blink | 909 } // namespace blink |
OLD | NEW |