| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2005, 2006, 2007, 2008 Apple 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 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 , m_startingSelection(startingSelection) | 89 , m_startingSelection(startingSelection) |
| 90 , m_endingSelection(endingSelection) | 90 , m_endingSelection(endingSelection) |
| 91 , m_startingRootEditableElement(startingSelection.rootEditableElement()) | 91 , m_startingRootEditableElement(startingSelection.rootEditableElement()) |
| 92 , m_endingRootEditableElement(endingSelection.rootEditableElement()) | 92 , m_endingRootEditableElement(endingSelection.rootEditableElement()) |
| 93 , m_editAction(editAction) | 93 , m_editAction(editAction) |
| 94 { | 94 { |
| 95 } | 95 } |
| 96 | 96 |
| 97 bool EditCommandComposition::belongsTo(const LocalFrame& frame) const | 97 bool EditCommandComposition::belongsTo(const LocalFrame& frame) const |
| 98 { | 98 { |
| 99 ASSERT(m_document); | 99 DCHECK(m_document); |
| 100 return m_document->frame() == &frame; | 100 return m_document->frame() == &frame; |
| 101 } | 101 } |
| 102 | 102 |
| 103 void EditCommandComposition::unapply() | 103 void EditCommandComposition::unapply() |
| 104 { | 104 { |
| 105 ASSERT(m_document); | 105 DCHECK(m_document); |
| 106 LocalFrame* frame = m_document->frame(); | 106 LocalFrame* frame = m_document->frame(); |
| 107 ASSERT(frame); | 107 DCHECK(frame); |
| 108 | 108 |
| 109 // Changes to the document may have been made since the last editing operati
on that require a layout, as in <rdar://problem/5658603>. | 109 // Changes to the document may have been made since the last editing operati
on that require a layout, as in <rdar://problem/5658603>. |
| 110 // Low level operations, like RemoveNodeCommand, don't require a layout beca
use the high level operations that use them perform one | 110 // Low level operations, like RemoveNodeCommand, don't require a layout beca
use the high level operations that use them perform one |
| 111 // if one is necessary (like for the creation of VisiblePositions). | 111 // if one is necessary (like for the creation of VisiblePositions). |
| 112 m_document->updateLayoutIgnorePendingStylesheets(); | 112 m_document->updateLayoutIgnorePendingStylesheets(); |
| 113 | 113 |
| 114 { | 114 { |
| 115 size_t size = m_commands.size(); | 115 size_t size = m_commands.size(); |
| 116 for (size_t i = size; i; --i) | 116 for (size_t i = size; i; --i) |
| 117 m_commands[i - 1]->doUnapply(); | 117 m_commands[i - 1]->doUnapply(); |
| 118 } | 118 } |
| 119 | 119 |
| 120 frame->editor().unappliedEditing(this); | 120 frame->editor().unappliedEditing(this); |
| 121 } | 121 } |
| 122 | 122 |
| 123 void EditCommandComposition::reapply() | 123 void EditCommandComposition::reapply() |
| 124 { | 124 { |
| 125 ASSERT(m_document); | 125 DCHECK(m_document); |
| 126 LocalFrame* frame = m_document->frame(); | 126 LocalFrame* frame = m_document->frame(); |
| 127 ASSERT(frame); | 127 DCHECK(frame); |
| 128 | 128 |
| 129 // Changes to the document may have been made since the last editing operati
on that require a layout, as in <rdar://problem/5658603>. | 129 // Changes to the document may have been made since the last editing operati
on that require a layout, as in <rdar://problem/5658603>. |
| 130 // Low level operations, like RemoveNodeCommand, don't require a layout beca
use the high level operations that use them perform one | 130 // Low level operations, like RemoveNodeCommand, don't require a layout beca
use the high level operations that use them perform one |
| 131 // if one is necessary (like for the creation of VisiblePositions). | 131 // if one is necessary (like for the creation of VisiblePositions). |
| 132 m_document->updateLayoutIgnorePendingStylesheets(); | 132 m_document->updateLayoutIgnorePendingStylesheets(); |
| 133 | 133 |
| 134 { | 134 { |
| 135 for (const auto& command : m_commands) | 135 for (const auto& command : m_commands) |
| 136 command->doReapply(); | 136 command->doReapply(); |
| 137 } | 137 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 167 UndoStep::trace(visitor); | 167 UndoStep::trace(visitor); |
| 168 } | 168 } |
| 169 | 169 |
| 170 CompositeEditCommand::CompositeEditCommand(Document& document) | 170 CompositeEditCommand::CompositeEditCommand(Document& document) |
| 171 : EditCommand(document) | 171 : EditCommand(document) |
| 172 { | 172 { |
| 173 } | 173 } |
| 174 | 174 |
| 175 CompositeEditCommand::~CompositeEditCommand() | 175 CompositeEditCommand::~CompositeEditCommand() |
| 176 { | 176 { |
| 177 ASSERT(isTopLevelCommand() || !m_composition); | 177 DCHECK(isTopLevelCommand() || !m_composition); |
| 178 } | 178 } |
| 179 | 179 |
| 180 bool CompositeEditCommand::apply() | 180 bool CompositeEditCommand::apply() |
| 181 { | 181 { |
| 182 if (!endingSelection().isContentRichlyEditable()) { | 182 if (!endingSelection().isContentRichlyEditable()) { |
| 183 switch (editingAction()) { | 183 switch (editingAction()) { |
| 184 case EditActionTyping: | 184 case EditActionTyping: |
| 185 case EditActionPaste: | 185 case EditActionPaste: |
| 186 case EditActionDrag: | 186 case EditActionDrag: |
| 187 case EditActionSetWritingDirection: | 187 case EditActionSetWritingDirection: |
| 188 case EditActionCut: | 188 case EditActionCut: |
| 189 case EditActionUnspecified: | 189 case EditActionUnspecified: |
| 190 break; | 190 break; |
| 191 default: | 191 default: |
| 192 ASSERT_NOT_REACHED(); | 192 ASSERT_NOT_REACHED(); |
| 193 return false; | 193 return false; |
| 194 } | 194 } |
| 195 } | 195 } |
| 196 ensureComposition(); | 196 ensureComposition(); |
| 197 | 197 |
| 198 // Changes to the document may have been made since the last editing operati
on that require a layout, as in <rdar://problem/5658603>. | 198 // Changes to the document may have been made since the last editing operati
on that require a layout, as in <rdar://problem/5658603>. |
| 199 // Low level operations, like RemoveNodeCommand, don't require a layout beca
use the high level operations that use them perform one | 199 // Low level operations, like RemoveNodeCommand, don't require a layout beca
use the high level operations that use them perform one |
| 200 // if one is necessary (like for the creation of VisiblePositions). | 200 // if one is necessary (like for the creation of VisiblePositions). |
| 201 document().updateLayoutIgnorePendingStylesheets(); | 201 document().updateLayoutIgnorePendingStylesheets(); |
| 202 | 202 |
| 203 LocalFrame* frame = document().frame(); | 203 LocalFrame* frame = document().frame(); |
| 204 ASSERT(frame); | 204 DCHECK(frame); |
| 205 EditingState editingState; | 205 EditingState editingState; |
| 206 { | 206 { |
| 207 EventQueueScope eventQueueScope; | 207 EventQueueScope eventQueueScope; |
| 208 doApply(&editingState); | 208 doApply(&editingState); |
| 209 } | 209 } |
| 210 | 210 |
| 211 // Only need to call appliedEditing for top-level commands, | 211 // Only need to call appliedEditing for top-level commands, |
| 212 // and TypingCommands do it on their own (see TypingCommand::typingAddedToOp
enCommand). | 212 // and TypingCommands do it on their own (see TypingCommand::typingAddedToOp
enCommand). |
| 213 if (!isTypingCommand()) | 213 if (!isTypingCommand()) |
| 214 frame->editor().appliedEditing(this); | 214 frame->editor().appliedEditing(this); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 applyCommandToComposite(ApplyStyleCommand::create(element, true), editingSta
te); | 295 applyCommandToComposite(ApplyStyleCommand::create(element, true), editingSta
te); |
| 296 } | 296 } |
| 297 | 297 |
| 298 void CompositeEditCommand::insertParagraphSeparator(EditingState* editingState,
bool useDefaultParagraphElement, bool pasteBlockqutoeIntoUnquotedArea) | 298 void CompositeEditCommand::insertParagraphSeparator(EditingState* editingState,
bool useDefaultParagraphElement, bool pasteBlockqutoeIntoUnquotedArea) |
| 299 { | 299 { |
| 300 applyCommandToComposite(InsertParagraphSeparatorCommand::create(document(),
useDefaultParagraphElement, pasteBlockqutoeIntoUnquotedArea), editingState); | 300 applyCommandToComposite(InsertParagraphSeparatorCommand::create(document(),
useDefaultParagraphElement, pasteBlockqutoeIntoUnquotedArea), editingState); |
| 301 } | 301 } |
| 302 | 302 |
| 303 bool CompositeEditCommand::isRemovableBlock(const Node* node) | 303 bool CompositeEditCommand::isRemovableBlock(const Node* node) |
| 304 { | 304 { |
| 305 ASSERT(node); | 305 DCHECK(node); |
| 306 if (!isHTMLDivElement(*node)) | 306 if (!isHTMLDivElement(*node)) |
| 307 return false; | 307 return false; |
| 308 | 308 |
| 309 const HTMLDivElement& element = toHTMLDivElement(*node); | 309 const HTMLDivElement& element = toHTMLDivElement(*node); |
| 310 ContainerNode* parentNode = element.parentNode(); | 310 ContainerNode* parentNode = element.parentNode(); |
| 311 if (parentNode && parentNode->firstChild() != parentNode->lastChild()) | 311 if (parentNode && parentNode->firstChild() != parentNode->lastChild()) |
| 312 return false; | 312 return false; |
| 313 | 313 |
| 314 if (!element.hasAttributes()) | 314 if (!element.hasAttributes()) |
| 315 return true; | 315 return true; |
| 316 | 316 |
| 317 return false; | 317 return false; |
| 318 } | 318 } |
| 319 | 319 |
| 320 void CompositeEditCommand::insertNodeBefore(Node* insertChild, Node* refChild, E
ditingState* editingState, ShouldAssumeContentIsAlwaysEditable shouldAssumeConte
ntIsAlwaysEditable) | 320 void CompositeEditCommand::insertNodeBefore(Node* insertChild, Node* refChild, E
ditingState* editingState, ShouldAssumeContentIsAlwaysEditable shouldAssumeConte
ntIsAlwaysEditable) |
| 321 { | 321 { |
| 322 ASSERT(document().body() != refChild); | 322 DCHECK_NE(document().body(), refChild); |
| 323 ABORT_EDITING_COMMAND_IF(!refChild->parentNode()->hasEditableStyle() && refC
hild->parentNode()->inActiveDocument()); | 323 ABORT_EDITING_COMMAND_IF(!refChild->parentNode()->hasEditableStyle() && refC
hild->parentNode()->inActiveDocument()); |
| 324 applyCommandToComposite(InsertNodeBeforeCommand::create(insertChild, refChil
d, shouldAssumeContentIsAlwaysEditable), editingState); | 324 applyCommandToComposite(InsertNodeBeforeCommand::create(insertChild, refChil
d, shouldAssumeContentIsAlwaysEditable), editingState); |
| 325 } | 325 } |
| 326 | 326 |
| 327 void CompositeEditCommand::insertNodeAfter(Node* insertChild, Node* refChild, Ed
itingState* editingState) | 327 void CompositeEditCommand::insertNodeAfter(Node* insertChild, Node* refChild, Ed
itingState* editingState) |
| 328 { | 328 { |
| 329 ASSERT(insertChild); | 329 DCHECK(insertChild); |
| 330 ASSERT(refChild); | 330 DCHECK(refChild); |
| 331 ASSERT(document().body() != refChild); | 331 DCHECK_NE(document().body(), refChild); |
| 332 ContainerNode* parent = refChild->parentNode(); | 332 ContainerNode* parent = refChild->parentNode(); |
| 333 ASSERT(parent); | 333 DCHECK(parent); |
| 334 ASSERT(!parent->isShadowRoot()); | 334 DCHECK(!parent->isShadowRoot()) << parent; |
| 335 if (parent->lastChild() == refChild) { | 335 if (parent->lastChild() == refChild) { |
| 336 appendNode(insertChild, parent, editingState); | 336 appendNode(insertChild, parent, editingState); |
| 337 } else { | 337 } else { |
| 338 ASSERT(refChild->nextSibling()); | 338 DCHECK(refChild->nextSibling()) << refChild; |
| 339 insertNodeBefore(insertChild, refChild->nextSibling(), editingState); | 339 insertNodeBefore(insertChild, refChild->nextSibling(), editingState); |
| 340 } | 340 } |
| 341 } | 341 } |
| 342 | 342 |
| 343 void CompositeEditCommand::insertNodeAt(Node* insertChild, const Position& editi
ngPosition, EditingState* editingState) | 343 void CompositeEditCommand::insertNodeAt(Node* insertChild, const Position& editi
ngPosition, EditingState* editingState) |
| 344 { | 344 { |
| 345 ABORT_EDITING_COMMAND_IF(!isEditablePosition(editingPosition, ContentIsEdita
ble, DoNotUpdateStyle)); | 345 ABORT_EDITING_COMMAND_IF(!isEditablePosition(editingPosition, ContentIsEdita
ble, DoNotUpdateStyle)); |
| 346 // For editing positions like [table, 0], insert before the table, | 346 // For editing positions like [table, 0], insert before the table, |
| 347 // likewise for replaced elements, brs, etc. | 347 // likewise for replaced elements, brs, etc. |
| 348 Position p = editingPosition.parentAnchoredEquivalent(); | 348 Position p = editingPosition.parentAnchoredEquivalent(); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 412 } | 412 } |
| 413 | 413 |
| 414 void CompositeEditCommand::removeNodePreservingChildren(Node* node, EditingState
* editingState, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysE
ditable) | 414 void CompositeEditCommand::removeNodePreservingChildren(Node* node, EditingState
* editingState, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysE
ditable) |
| 415 { | 415 { |
| 416 ABORT_EDITING_COMMAND_IF(!node->document().frame()); | 416 ABORT_EDITING_COMMAND_IF(!node->document().frame()); |
| 417 applyCommandToComposite(RemoveNodePreservingChildrenCommand::create(node, sh
ouldAssumeContentIsAlwaysEditable), editingState); | 417 applyCommandToComposite(RemoveNodePreservingChildrenCommand::create(node, sh
ouldAssumeContentIsAlwaysEditable), editingState); |
| 418 } | 418 } |
| 419 | 419 |
| 420 void CompositeEditCommand::removeNodeAndPruneAncestors(Node* node, EditingState*
editingState, Node* excludeNode) | 420 void CompositeEditCommand::removeNodeAndPruneAncestors(Node* node, EditingState*
editingState, Node* excludeNode) |
| 421 { | 421 { |
| 422 ASSERT(node != excludeNode); | 422 DCHECK_NE(node, excludeNode); |
| 423 ContainerNode* parent = node->parentNode(); | 423 ContainerNode* parent = node->parentNode(); |
| 424 removeNode(node, editingState); | 424 removeNode(node, editingState); |
| 425 if (editingState->isAborted()) | 425 if (editingState->isAborted()) |
| 426 return; | 426 return; |
| 427 prune(parent, editingState, excludeNode); | 427 prune(parent, editingState, excludeNode); |
| 428 } | 428 } |
| 429 | 429 |
| 430 void CompositeEditCommand::moveRemainingSiblingsToNewParent(Node* node, Node* pa
stLastNodeToMove, Element* newParent, EditingState* editingState) | 430 void CompositeEditCommand::moveRemainingSiblingsToNewParent(Node* node, Node* pa
stLastNodeToMove, Element* newParent, EditingState* editingState) |
| 431 { | 431 { |
| 432 NodeVector nodesToRemove; | 432 NodeVector nodesToRemove; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 457 { | 457 { |
| 458 // It would also be possible to implement all of ReplaceNodeWithSpanCommand | 458 // It would also be possible to implement all of ReplaceNodeWithSpanCommand |
| 459 // as a series of existing smaller edit commands. Someone who wanted to | 459 // as a series of existing smaller edit commands. Someone who wanted to |
| 460 // reduce the number of edit commands could do so here. | 460 // reduce the number of edit commands could do so here. |
| 461 ReplaceNodeWithSpanCommand* command = ReplaceNodeWithSpanCommand::create(nod
e); | 461 ReplaceNodeWithSpanCommand* command = ReplaceNodeWithSpanCommand::create(nod
e); |
| 462 // ReplaceNodeWithSpanCommand is never aborted. | 462 // ReplaceNodeWithSpanCommand is never aborted. |
| 463 applyCommandToComposite(command, ASSERT_NO_EDITING_ABORT); | 463 applyCommandToComposite(command, ASSERT_NO_EDITING_ABORT); |
| 464 // Returning a raw pointer here is OK because the command is retained by | 464 // Returning a raw pointer here is OK because the command is retained by |
| 465 // applyCommandToComposite (thus retaining the span), and the span is also | 465 // applyCommandToComposite (thus retaining the span), and the span is also |
| 466 // in the DOM tree, and thus alive whie it has a parent. | 466 // in the DOM tree, and thus alive whie it has a parent. |
| 467 ASSERT(command->spanElement()->inShadowIncludingDocument()); | 467 DCHECK(command->spanElement()->inShadowIncludingDocument()) << command->span
Element(); |
| 468 return command->spanElement(); | 468 return command->spanElement(); |
| 469 } | 469 } |
| 470 | 470 |
| 471 void CompositeEditCommand::prune(Node* node, EditingState* editingState, Node* e
xcludeNode) | 471 void CompositeEditCommand::prune(Node* node, EditingState* editingState, Node* e
xcludeNode) |
| 472 { | 472 { |
| 473 if (Node* highestNodeToRemove = highestNodeToRemoveInPruning(node, excludeNo
de)) | 473 if (Node* highestNodeToRemove = highestNodeToRemoveInPruning(node, excludeNo
de)) |
| 474 removeNode(highestNodeToRemove, editingState); | 474 removeNode(highestNodeToRemove, editingState); |
| 475 } | 475 } |
| 476 | 476 |
| 477 void CompositeEditCommand::splitTextNode(Text* node, unsigned offset) | 477 void CompositeEditCommand::splitTextNode(Text* node, unsigned offset) |
| 478 { | 478 { |
| 479 // SplitTextNodeCommand is never aborted. | 479 // SplitTextNodeCommand is never aborted. |
| 480 applyCommandToComposite(SplitTextNodeCommand::create(node, offset), ASSERT_N
O_EDITING_ABORT); | 480 applyCommandToComposite(SplitTextNodeCommand::create(node, offset), ASSERT_N
O_EDITING_ABORT); |
| 481 } | 481 } |
| 482 | 482 |
| 483 void CompositeEditCommand::splitElement(Element* element, Node* atChild) | 483 void CompositeEditCommand::splitElement(Element* element, Node* atChild) |
| 484 { | 484 { |
| 485 // SplitElementCommand is never aborted. | 485 // SplitElementCommand is never aborted. |
| 486 applyCommandToComposite(SplitElementCommand::create(element, atChild), ASSER
T_NO_EDITING_ABORT); | 486 applyCommandToComposite(SplitElementCommand::create(element, atChild), ASSER
T_NO_EDITING_ABORT); |
| 487 } | 487 } |
| 488 | 488 |
| 489 void CompositeEditCommand::mergeIdenticalElements(Element* first, Element* secon
d, EditingState* editingState) | 489 void CompositeEditCommand::mergeIdenticalElements(Element* first, Element* secon
d, EditingState* editingState) |
| 490 { | 490 { |
| 491 ASSERT(!first->isDescendantOf(second) && second != first); | 491 DCHECK(!first->isDescendantOf(second)) << first << " " << second; |
| 492 DCHECK_NE(second, first); |
| 492 if (first->nextSibling() != second) { | 493 if (first->nextSibling() != second) { |
| 493 removeNode(second, editingState); | 494 removeNode(second, editingState); |
| 494 if (editingState->isAborted()) | 495 if (editingState->isAborted()) |
| 495 return; | 496 return; |
| 496 insertNodeAfter(second, first, editingState); | 497 insertNodeAfter(second, first, editingState); |
| 497 if (editingState->isAborted()) | 498 if (editingState->isAborted()) |
| 498 return; | 499 return; |
| 499 } | 500 } |
| 500 applyCommandToComposite(MergeIdenticalElementsCommand::create(first, second)
, editingState); | 501 applyCommandToComposite(MergeIdenticalElementsCommand::create(first, second)
, editingState); |
| 501 } | 502 } |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 | 561 |
| 561 void CompositeEditCommand::replaceTextInNodePreservingMarkers(Text* node, unsign
ed offset, unsigned count, const String& replacementText) | 562 void CompositeEditCommand::replaceTextInNodePreservingMarkers(Text* node, unsign
ed offset, unsigned count, const String& replacementText) |
| 562 { | 563 { |
| 563 DocumentMarkerController& markerController = document().markers(); | 564 DocumentMarkerController& markerController = document().markers(); |
| 564 Vector<DocumentMarker::MarkerType> types; | 565 Vector<DocumentMarker::MarkerType> types; |
| 565 Vector<String> descriptions; | 566 Vector<String> descriptions; |
| 566 copyMarkerTypesAndDescriptions(markerController.markersInRange(EphemeralRang
e(Position(node, offset), Position(node, offset + count)), DocumentMarker::AllMa
rkers()), types, descriptions); | 567 copyMarkerTypesAndDescriptions(markerController.markersInRange(EphemeralRang
e(Position(node, offset), Position(node, offset + count)), DocumentMarker::AllMa
rkers()), types, descriptions); |
| 567 replaceTextInNode(node, offset, count, replacementText); | 568 replaceTextInNode(node, offset, count, replacementText); |
| 568 Position startPosition(node, offset); | 569 Position startPosition(node, offset); |
| 569 Position endPosition(node, offset + replacementText.length()); | 570 Position endPosition(node, offset + replacementText.length()); |
| 570 ASSERT(types.size() == descriptions.size()); | 571 DCHECK_EQ(types.size(), descriptions.size()); |
| 571 for (size_t i = 0; i < types.size(); ++i) | 572 for (size_t i = 0; i < types.size(); ++i) |
| 572 markerController.addMarker(startPosition, endPosition, types[i], descrip
tions[i]); | 573 markerController.addMarker(startPosition, endPosition, types[i], descrip
tions[i]); |
| 573 } | 574 } |
| 574 | 575 |
| 575 Position CompositeEditCommand::positionOutsideTabSpan(const Position& pos) | 576 Position CompositeEditCommand::positionOutsideTabSpan(const Position& pos) |
| 576 { | 577 { |
| 577 if (!isTabHTMLSpanElementTextNode(pos.anchorNode())) | 578 if (!isTabHTMLSpanElementTextNode(pos.anchorNode())) |
| 578 return pos; | 579 return pos; |
| 579 | 580 |
| 580 switch (pos.anchorType()) { | 581 switch (pos.anchorType()) { |
| 581 case PositionAnchorType::BeforeChildren: | 582 case PositionAnchorType::BeforeChildren: |
| 582 case PositionAnchorType::AfterChildren: | 583 case PositionAnchorType::AfterChildren: |
| 583 ASSERT_NOT_REACHED(); | 584 ASSERT_NOT_REACHED(); |
| 584 return pos; | 585 return pos; |
| 585 case PositionAnchorType::OffsetInAnchor: | 586 case PositionAnchorType::OffsetInAnchor: |
| 586 break; | 587 break; |
| 587 case PositionAnchorType::BeforeAnchor: | 588 case PositionAnchorType::BeforeAnchor: |
| 588 return positionInParentBeforeNode(*pos.anchorNode()); | 589 return positionInParentBeforeNode(*pos.anchorNode()); |
| 589 case PositionAnchorType::AfterAnchor: | 590 case PositionAnchorType::AfterAnchor: |
| 590 return positionInParentAfterNode(*pos.anchorNode()); | 591 return positionInParentAfterNode(*pos.anchorNode()); |
| 591 } | 592 } |
| 592 | 593 |
| 593 HTMLSpanElement* tabSpan = tabSpanElement(pos.computeContainerNode()); | 594 HTMLSpanElement* tabSpan = tabSpanElement(pos.computeContainerNode()); |
| 594 ASSERT(tabSpan); | 595 DCHECK(tabSpan); |
| 595 | 596 |
| 596 if (pos.offsetInContainerNode() <= caretMinOffset(pos.computeContainerNode()
)) | 597 if (pos.offsetInContainerNode() <= caretMinOffset(pos.computeContainerNode()
)) |
| 597 return positionInParentBeforeNode(*tabSpan); | 598 return positionInParentBeforeNode(*tabSpan); |
| 598 | 599 |
| 599 if (pos.offsetInContainerNode() >= caretMaxOffset(pos.computeContainerNode()
)) | 600 if (pos.offsetInContainerNode() >= caretMaxOffset(pos.computeContainerNode()
)) |
| 600 return positionInParentAfterNode(*tabSpan); | 601 return positionInParentAfterNode(*tabSpan); |
| 601 | 602 |
| 602 splitTextNodeContainingElement(toText(pos.computeContainerNode()), pos.offse
tInContainerNode()); | 603 splitTextNodeContainingElement(toText(pos.computeContainerNode()), pos.offse
tInContainerNode()); |
| 603 return positionInParentBeforeNode(*tabSpan); | 604 return positionInParentBeforeNode(*tabSpan); |
| 604 } | 605 } |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 685 if (offset < 0 || !isWhitespace(text[offset])) | 686 if (offset < 0 || !isWhitespace(text[offset])) |
| 686 return; | 687 return; |
| 687 } | 688 } |
| 688 | 689 |
| 689 rebalanceWhitespaceOnTextSubstring(toText(node), position.offsetInContainerN
ode(), position.offsetInContainerNode()); | 690 rebalanceWhitespaceOnTextSubstring(toText(node), position.offsetInContainerN
ode(), position.offsetInContainerNode()); |
| 690 } | 691 } |
| 691 | 692 |
| 692 void CompositeEditCommand::rebalanceWhitespaceOnTextSubstring(Text* textNode, in
t startOffset, int endOffset) | 693 void CompositeEditCommand::rebalanceWhitespaceOnTextSubstring(Text* textNode, in
t startOffset, int endOffset) |
| 693 { | 694 { |
| 694 String text = textNode->data(); | 695 String text = textNode->data(); |
| 695 ASSERT(!text.isEmpty()); | 696 DCHECK(!text.isEmpty()); |
| 696 | 697 |
| 697 // Set upstream and downstream to define the extent of the whitespace surrou
nding text[offset]. | 698 // Set upstream and downstream to define the extent of the whitespace surrou
nding text[offset]. |
| 698 int upstream = startOffset; | 699 int upstream = startOffset; |
| 699 while (upstream > 0 && isWhitespace(text[upstream - 1])) | 700 while (upstream > 0 && isWhitespace(text[upstream - 1])) |
| 700 upstream--; | 701 upstream--; |
| 701 | 702 |
| 702 int downstream = endOffset; | 703 int downstream = endOffset; |
| 703 while ((unsigned)downstream < text.length() && isWhitespace(text[downstream]
)) | 704 while ((unsigned)downstream < text.length() && isWhitespace(text[downstream]
)) |
| 704 downstream++; | 705 downstream++; |
| 705 | 706 |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 839 } | 840 } |
| 840 | 841 |
| 841 if (!str.isNull()) { | 842 if (!str.isNull()) { |
| 842 // Replace the text between start and end with our pruned version. | 843 // Replace the text between start and end with our pruned version. |
| 843 if (!str.isEmpty()) { | 844 if (!str.isEmpty()) { |
| 844 replaceTextInNode(textNode, start, end - start, str); | 845 replaceTextInNode(textNode, start, end - start, str); |
| 845 } else { | 846 } else { |
| 846 // Assert that we are not going to delete all of the text in the nod
e. | 847 // Assert that we are not going to delete all of the text in the nod
e. |
| 847 // If we were, that should have been done above with the call to | 848 // If we were, that should have been done above with the call to |
| 848 // removeNode and return. | 849 // removeNode and return. |
| 849 ASSERT(start > 0 || end - start < textNode->length()); | 850 DCHECK(start > 0 || end - start < textNode->length()); |
| 850 deleteTextFromNode(textNode, start, end - start); | 851 deleteTextFromNode(textNode, start, end - start); |
| 851 } | 852 } |
| 852 } | 853 } |
| 853 } | 854 } |
| 854 | 855 |
| 855 void CompositeEditCommand::deleteInsignificantText(const Position& start, const
Position& end) | 856 void CompositeEditCommand::deleteInsignificantText(const Position& start, const
Position& end) |
| 856 { | 857 { |
| 857 if (start.isNull() || end.isNull()) | 858 if (start.isNull() || end.isNull()) |
| 858 return; | 859 return; |
| 859 | 860 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 883 } | 884 } |
| 884 | 885 |
| 885 HTMLBRElement* CompositeEditCommand::appendBlockPlaceholder(Element* container,
EditingState* editingState) | 886 HTMLBRElement* CompositeEditCommand::appendBlockPlaceholder(Element* container,
EditingState* editingState) |
| 886 { | 887 { |
| 887 if (!container) | 888 if (!container) |
| 888 return nullptr; | 889 return nullptr; |
| 889 | 890 |
| 890 document().updateLayoutIgnorePendingStylesheets(); | 891 document().updateLayoutIgnorePendingStylesheets(); |
| 891 | 892 |
| 892 // Should assert isLayoutBlockFlow || isInlineFlow when deletion improves. S
ee 4244964. | 893 // Should assert isLayoutBlockFlow || isInlineFlow when deletion improves. S
ee 4244964. |
| 893 ASSERT(container->layoutObject()); | 894 DCHECK(container->layoutObject()) << container; |
| 894 | 895 |
| 895 HTMLBRElement* placeholder = HTMLBRElement::create(document()); | 896 HTMLBRElement* placeholder = HTMLBRElement::create(document()); |
| 896 appendNode(placeholder, container, editingState); | 897 appendNode(placeholder, container, editingState); |
| 897 if (editingState->isAborted()) | 898 if (editingState->isAborted()) |
| 898 return nullptr; | 899 return nullptr; |
| 899 return placeholder; | 900 return placeholder; |
| 900 } | 901 } |
| 901 | 902 |
| 902 HTMLBRElement* CompositeEditCommand::insertBlockPlaceholder(const Position& pos,
EditingState* editingState) | 903 HTMLBRElement* CompositeEditCommand::insertBlockPlaceholder(const Position& pos,
EditingState* editingState) |
| 903 { | 904 { |
| 904 if (pos.isNull()) | 905 if (pos.isNull()) |
| 905 return nullptr; | 906 return nullptr; |
| 906 | 907 |
| 907 // Should assert isLayoutBlockFlow || isInlineFlow when deletion improves. S
ee 4244964. | 908 // Should assert isLayoutBlockFlow || isInlineFlow when deletion improves. S
ee 4244964. |
| 908 ASSERT(pos.anchorNode()->layoutObject()); | 909 DCHECK(pos.anchorNode()->layoutObject()) << pos; |
| 909 | 910 |
| 910 HTMLBRElement* placeholder = HTMLBRElement::create(document()); | 911 HTMLBRElement* placeholder = HTMLBRElement::create(document()); |
| 911 insertNodeAt(placeholder, pos, editingState); | 912 insertNodeAt(placeholder, pos, editingState); |
| 912 if (editingState->isAborted()) | 913 if (editingState->isAborted()) |
| 913 return nullptr; | 914 return nullptr; |
| 914 return placeholder; | 915 return placeholder; |
| 915 } | 916 } |
| 916 | 917 |
| 917 HTMLBRElement* CompositeEditCommand::addBlockPlaceholderIfNeeded(Element* contai
ner, EditingState* editingState) | 918 HTMLBRElement* CompositeEditCommand::addBlockPlaceholderIfNeeded(Element* contai
ner, EditingState* editingState) |
| 918 { | 919 { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 930 LayoutBlockFlow* block = toLayoutBlockFlow(layoutObject); | 931 LayoutBlockFlow* block = toLayoutBlockFlow(layoutObject); |
| 931 if (block->size().height() == 0 || (block->isListItem() && toLayoutListItem(
block)->isEmpty())) | 932 if (block->size().height() == 0 || (block->isListItem() && toLayoutListItem(
block)->isEmpty())) |
| 932 return appendBlockPlaceholder(container, editingState); | 933 return appendBlockPlaceholder(container, editingState); |
| 933 | 934 |
| 934 return nullptr; | 935 return nullptr; |
| 935 } | 936 } |
| 936 | 937 |
| 937 // Assumes that the position is at a placeholder and does the removal without mu
ch checking. | 938 // Assumes that the position is at a placeholder and does the removal without mu
ch checking. |
| 938 void CompositeEditCommand::removePlaceholderAt(const Position& p) | 939 void CompositeEditCommand::removePlaceholderAt(const Position& p) |
| 939 { | 940 { |
| 940 ASSERT(lineBreakExistsAtPosition(p)); | 941 DCHECK(lineBreakExistsAtPosition(p)) << p; |
| 941 | 942 |
| 942 // We are certain that the position is at a line break, but it may be a br o
r a preserved newline. | 943 // We are certain that the position is at a line break, but it may be a br o
r a preserved newline. |
| 943 if (isHTMLBRElement(*p.anchorNode())) { | 944 if (isHTMLBRElement(*p.anchorNode())) { |
| 944 // Removing a BR element won't dispatch synchronous events. | 945 // Removing a BR element won't dispatch synchronous events. |
| 945 removeNode(p.anchorNode(), ASSERT_NO_EDITING_ABORT); | 946 removeNode(p.anchorNode(), ASSERT_NO_EDITING_ABORT); |
| 946 return; | 947 return; |
| 947 } | 948 } |
| 948 | 949 |
| 949 deleteTextFromNode(toText(p.anchorNode()), p.offsetInContainerNode(), 1); | 950 deleteTextFromNode(toText(p.anchorNode()), p.offsetInContainerNode(), 1); |
| 950 } | 951 } |
| 951 | 952 |
| 952 HTMLElement* CompositeEditCommand::insertNewDefaultParagraphElementAt(const Posi
tion& position, EditingState* editingState) | 953 HTMLElement* CompositeEditCommand::insertNewDefaultParagraphElementAt(const Posi
tion& position, EditingState* editingState) |
| 953 { | 954 { |
| 954 HTMLElement* paragraphElement = createDefaultParagraphElement(document()); | 955 HTMLElement* paragraphElement = createDefaultParagraphElement(document()); |
| 955 paragraphElement->appendChild(HTMLBRElement::create(document())); | 956 paragraphElement->appendChild(HTMLBRElement::create(document())); |
| 956 insertNodeAt(paragraphElement, position, editingState); | 957 insertNodeAt(paragraphElement, position, editingState); |
| 957 if (editingState->isAborted()) | 958 if (editingState->isAborted()) |
| 958 return nullptr; | 959 return nullptr; |
| 959 return paragraphElement; | 960 return paragraphElement; |
| 960 } | 961 } |
| 961 | 962 |
| 962 // If the paragraph is not entirely within it's own block, create one and move t
he paragraph into | 963 // If the paragraph is not entirely within it's own block, create one and move t
he paragraph into |
| 963 // it, and return that block. Otherwise return 0. | 964 // it, and return that block. Otherwise return 0. |
| 964 HTMLElement* CompositeEditCommand::moveParagraphContentsToNewBlockIfNecessary(co
nst Position& pos, EditingState* editingState) | 965 HTMLElement* CompositeEditCommand::moveParagraphContentsToNewBlockIfNecessary(co
nst Position& pos, EditingState* editingState) |
| 965 { | 966 { |
| 966 ASSERT(isEditablePosition(pos, ContentIsEditable, DoNotUpdateStyle)); | 967 DCHECK(isEditablePosition(pos, ContentIsEditable, DoNotUpdateStyle)) << pos; |
| 967 | 968 |
| 968 // It's strange that this function is responsible for verifying that pos has
not been invalidated | 969 // It's strange that this function is responsible for verifying that pos has
not been invalidated |
| 969 // by an earlier call to this function. The caller, applyBlockStyle, should
do this. | 970 // by an earlier call to this function. The caller, applyBlockStyle, should
do this. |
| 970 VisiblePosition visiblePos = createVisiblePosition(pos, VP_DEFAULT_AFFINITY)
; | 971 VisiblePosition visiblePos = createVisiblePosition(pos, VP_DEFAULT_AFFINITY)
; |
| 971 VisiblePosition visibleParagraphStart = startOfParagraph(visiblePos); | 972 VisiblePosition visibleParagraphStart = startOfParagraph(visiblePos); |
| 972 VisiblePosition visibleParagraphEnd = endOfParagraph(visiblePos); | 973 VisiblePosition visibleParagraphEnd = endOfParagraph(visiblePos); |
| 973 VisiblePosition next = nextPositionOf(visibleParagraphEnd); | 974 VisiblePosition next = nextPositionOf(visibleParagraphEnd); |
| 974 VisiblePosition visibleEnd = next.isNotNull() ? next : visibleParagraphEnd; | 975 VisiblePosition visibleEnd = next.isNotNull() ? next : visibleParagraphEnd; |
| 975 | 976 |
| 976 Position upstreamStart = mostBackwardCaretPosition(visibleParagraphStart.dee
pEquivalent()); | 977 Position upstreamStart = mostBackwardCaretPosition(visibleParagraphStart.dee
pEquivalent()); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1031 } | 1032 } |
| 1032 | 1033 |
| 1033 return newBlock; | 1034 return newBlock; |
| 1034 } | 1035 } |
| 1035 | 1036 |
| 1036 void CompositeEditCommand::pushAnchorElementDown(Element* anchorNode, EditingSta
te* editingState) | 1037 void CompositeEditCommand::pushAnchorElementDown(Element* anchorNode, EditingSta
te* editingState) |
| 1037 { | 1038 { |
| 1038 if (!anchorNode) | 1039 if (!anchorNode) |
| 1039 return; | 1040 return; |
| 1040 | 1041 |
| 1041 ASSERT(anchorNode->isLink()); | 1042 DCHECK(anchorNode->isLink()) << anchorNode; |
| 1042 | 1043 |
| 1043 setEndingSelection(VisibleSelection::selectionFromContentsOfNode(anchorNode)
); | 1044 setEndingSelection(VisibleSelection::selectionFromContentsOfNode(anchorNode)
); |
| 1044 applyStyledElement(anchorNode, editingState); | 1045 applyStyledElement(anchorNode, editingState); |
| 1045 if (editingState->isAborted()) | 1046 if (editingState->isAborted()) |
| 1046 return; | 1047 return; |
| 1047 // Clones of anchorNode have been pushed down, now remove it. | 1048 // Clones of anchorNode have been pushed down, now remove it. |
| 1048 if (anchorNode->inShadowIncludingDocument()) | 1049 if (anchorNode->inShadowIncludingDocument()) |
| 1049 removeNodePreservingChildren(anchorNode, editingState); | 1050 removeNodePreservingChildren(anchorNode, editingState); |
| 1050 } | 1051 } |
| 1051 | 1052 |
| 1052 // Clone the paragraph between start and end under blockElement, | 1053 // Clone the paragraph between start and end under blockElement, |
| 1053 // preserving the hierarchy up to outerNode. | 1054 // preserving the hierarchy up to outerNode. |
| 1054 | 1055 |
| 1055 void CompositeEditCommand::cloneParagraphUnderNewElement(const Position& start,
const Position& end, Node* passedOuterNode, Element* blockElement, EditingState*
editingState) | 1056 void CompositeEditCommand::cloneParagraphUnderNewElement(const Position& start,
const Position& end, Node* passedOuterNode, Element* blockElement, EditingState*
editingState) |
| 1056 { | 1057 { |
| 1057 DCHECK_LE(start, end); | 1058 DCHECK_LE(start, end); |
| 1058 ASSERT(passedOuterNode); | 1059 DCHECK(passedOuterNode); |
| 1059 ASSERT(blockElement); | 1060 DCHECK(blockElement); |
| 1060 | 1061 |
| 1061 // First we clone the outerNode | 1062 // First we clone the outerNode |
| 1062 Node* lastNode = nullptr; | 1063 Node* lastNode = nullptr; |
| 1063 Node* outerNode = passedOuterNode; | 1064 Node* outerNode = passedOuterNode; |
| 1064 | 1065 |
| 1065 if (outerNode->isRootEditableElement()) { | 1066 if (outerNode->isRootEditableElement()) { |
| 1066 lastNode = blockElement; | 1067 lastNode = blockElement; |
| 1067 } else { | 1068 } else { |
| 1068 lastNode = outerNode->cloneNode(isDisplayInsideTable(outerNode)); | 1069 lastNode = outerNode->cloneNode(isDisplayInsideTable(outerNode)); |
| 1069 appendNode(lastNode, blockElement, editingState); | 1070 appendNode(lastNode, blockElement, editingState); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1182 } | 1183 } |
| 1183 | 1184 |
| 1184 // This is a version of moveParagraph that preserves style by keeping the origin
al markup | 1185 // This is a version of moveParagraph that preserves style by keeping the origin
al markup |
| 1185 // It is currently used only by IndentOutdentCommand but it is meant to be used
in the | 1186 // It is currently used only by IndentOutdentCommand but it is meant to be used
in the |
| 1186 // future by several other commands such as InsertList and the align commands. | 1187 // future by several other commands such as InsertList and the align commands. |
| 1187 // The blockElement parameter is the element to move the paragraph to, | 1188 // The blockElement parameter is the element to move the paragraph to, |
| 1188 // outerNode is the top element of the paragraph hierarchy. | 1189 // outerNode is the top element of the paragraph hierarchy. |
| 1189 | 1190 |
| 1190 void CompositeEditCommand::moveParagraphWithClones(const VisiblePosition& startO
fParagraphToMove, const VisiblePosition& endOfParagraphToMove, HTMLElement* bloc
kElement, Node* outerNode, EditingState* editingState) | 1191 void CompositeEditCommand::moveParagraphWithClones(const VisiblePosition& startO
fParagraphToMove, const VisiblePosition& endOfParagraphToMove, HTMLElement* bloc
kElement, Node* outerNode, EditingState* editingState) |
| 1191 { | 1192 { |
| 1192 ASSERT(outerNode); | 1193 DCHECK(outerNode); |
| 1193 ASSERT(blockElement); | 1194 DCHECK(blockElement); |
| 1194 | 1195 |
| 1195 VisiblePosition beforeParagraph = previousPositionOf(startOfParagraphToMove)
; | 1196 VisiblePosition beforeParagraph = previousPositionOf(startOfParagraphToMove)
; |
| 1196 VisiblePosition afterParagraph = nextPositionOf(endOfParagraphToMove); | 1197 VisiblePosition afterParagraph = nextPositionOf(endOfParagraphToMove); |
| 1197 | 1198 |
| 1198 // We upstream() the end and downstream() the start so that we don't include
collapsed whitespace in the move. | 1199 // We upstream() the end and downstream() the start so that we don't include
collapsed whitespace in the move. |
| 1199 // When we paste a fragment, spaces after the end and before the start are t
reated as though they were rendered. | 1200 // When we paste a fragment, spaces after the end and before the start are t
reated as though they were rendered. |
| 1200 Position start = mostForwardCaretPosition(startOfParagraphToMove.deepEquival
ent()); | 1201 Position start = mostForwardCaretPosition(startOfParagraphToMove.deepEquival
ent()); |
| 1201 Position end = startOfParagraphToMove.deepEquivalent() == endOfParagraphToMo
ve.deepEquivalent() ? start : mostBackwardCaretPosition(endOfParagraphToMove.dee
pEquivalent()); | 1202 Position end = startOfParagraphToMove.deepEquivalent() == endOfParagraphToMo
ve.deepEquivalent() ? start : mostBackwardCaretPosition(endOfParagraphToMove.dee
pEquivalent()); |
| 1202 if (comparePositions(start, end) > 0) | 1203 if (comparePositions(start, end) > 0) |
| 1203 end = start; | 1204 end = start; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1229 | 1230 |
| 1230 if (beforeParagraph.isNotNull() && !isDisplayInsideTable(beforeParagraph.dee
pEquivalent().anchorNode()) | 1231 if (beforeParagraph.isNotNull() && !isDisplayInsideTable(beforeParagraph.dee
pEquivalent().anchorNode()) |
| 1231 && ((!isEndOfParagraph(beforeParagraph) && !isStartOfParagraph(beforePar
agraph)) || beforeParagraph.deepEquivalent() == afterParagraph.deepEquivalent())
) { | 1232 && ((!isEndOfParagraph(beforeParagraph) && !isStartOfParagraph(beforePar
agraph)) || beforeParagraph.deepEquivalent() == afterParagraph.deepEquivalent())
) { |
| 1232 // FIXME: Trim text between beforeParagraph and afterParagraph if they a
ren't equal. | 1233 // FIXME: Trim text between beforeParagraph and afterParagraph if they a
ren't equal. |
| 1233 insertNodeAt(HTMLBRElement::create(document()), beforeParagraph.deepEqui
valent(), editingState); | 1234 insertNodeAt(HTMLBRElement::create(document()), beforeParagraph.deepEqui
valent(), editingState); |
| 1234 } | 1235 } |
| 1235 } | 1236 } |
| 1236 | 1237 |
| 1237 void CompositeEditCommand::moveParagraph(const VisiblePosition& startOfParagraph
ToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& dest
ination, EditingState* editingState, bool preserveSelection, bool preserveStyle,
Node* constrainingAncestor) | 1238 void CompositeEditCommand::moveParagraph(const VisiblePosition& startOfParagraph
ToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& dest
ination, EditingState* editingState, bool preserveSelection, bool preserveStyle,
Node* constrainingAncestor) |
| 1238 { | 1239 { |
| 1239 ASSERT(isStartOfParagraph(startOfParagraphToMove)); | 1240 DCHECK(isStartOfParagraph(startOfParagraphToMove)) << startOfParagraphToMove
; |
| 1240 ASSERT(isEndOfParagraph(endOfParagraphToMove)); | 1241 DCHECK(isEndOfParagraph(endOfParagraphToMove)) << endOfParagraphToMove; |
| 1241 moveParagraphs(startOfParagraphToMove, endOfParagraphToMove, destination, ed
itingState, preserveSelection, preserveStyle, constrainingAncestor); | 1242 moveParagraphs(startOfParagraphToMove, endOfParagraphToMove, destination, ed
itingState, preserveSelection, preserveStyle, constrainingAncestor); |
| 1242 } | 1243 } |
| 1243 | 1244 |
| 1244 void CompositeEditCommand::moveParagraphs(const VisiblePosition& startOfParagrap
hToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& des
tination, EditingState* editingState, bool preserveSelection, bool preserveStyle
, Node* constrainingAncestor) | 1245 void CompositeEditCommand::moveParagraphs(const VisiblePosition& startOfParagrap
hToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& des
tination, EditingState* editingState, bool preserveSelection, bool preserveStyle
, Node* constrainingAncestor) |
| 1245 { | 1246 { |
| 1246 if (startOfParagraphToMove.deepEquivalent() == destination.deepEquivalent()
|| startOfParagraphToMove.isNull()) | 1247 if (startOfParagraphToMove.deepEquivalent() == destination.deepEquivalent()
|| startOfParagraphToMove.isNull()) |
| 1247 return; | 1248 return; |
| 1248 | 1249 |
| 1249 int startIndex = -1; | 1250 int startIndex = -1; |
| 1250 int endIndex = -1; | 1251 int endIndex = -1; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1296 } | 1297 } |
| 1297 | 1298 |
| 1298 // FIXME (5098931): We should add a new insert action "WebViewInsertActionMo
ved" and call shouldInsertFragment here. | 1299 // FIXME (5098931): We should add a new insert action "WebViewInsertActionMo
ved" and call shouldInsertFragment here. |
| 1299 | 1300 |
| 1300 setEndingSelection(VisibleSelection(start, end)); | 1301 setEndingSelection(VisibleSelection(start, end)); |
| 1301 document().frame()->spellChecker().clearMisspellingsAndBadGrammar(endingSele
ction()); | 1302 document().frame()->spellChecker().clearMisspellingsAndBadGrammar(endingSele
ction()); |
| 1302 deleteSelection(editingState, false, false, false); | 1303 deleteSelection(editingState, false, false, false); |
| 1303 if (editingState->isAborted()) | 1304 if (editingState->isAborted()) |
| 1304 return; | 1305 return; |
| 1305 | 1306 |
| 1306 ASSERT(destination.deepEquivalent().inShadowIncludingDocument()); | 1307 DCHECK(destination.deepEquivalent().inShadowIncludingDocument()) << destinat
ion; |
| 1307 cleanupAfterDeletion(editingState, destination); | 1308 cleanupAfterDeletion(editingState, destination); |
| 1308 if (editingState->isAborted()) | 1309 if (editingState->isAborted()) |
| 1309 return; | 1310 return; |
| 1310 ASSERT(destination.deepEquivalent().inShadowIncludingDocument()); | 1311 DCHECK(destination.deepEquivalent().inShadowIncludingDocument()) << destinat
ion; |
| 1311 | 1312 |
| 1312 // Add a br if pruning an empty block level element caused a collapse. For e
xample: | 1313 // Add a br if pruning an empty block level element caused a collapse. For e
xample: |
| 1313 // foo^ | 1314 // foo^ |
| 1314 // <div>bar</div> | 1315 // <div>bar</div> |
| 1315 // baz | 1316 // baz |
| 1316 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. That
would | 1317 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. That
would |
| 1317 // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br
. | 1318 // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br
. |
| 1318 // Must recononicalize these two VisiblePositions after the pruning above. | 1319 // Must recononicalize these two VisiblePositions after the pruning above. |
| 1319 beforeParagraph = createVisiblePosition(beforeParagraph.deepEquivalent()); | 1320 beforeParagraph = createVisiblePosition(beforeParagraph.deepEquivalent()); |
| 1320 afterParagraph = createVisiblePosition(afterParagraph.deepEquivalent()); | 1321 afterParagraph = createVisiblePosition(afterParagraph.deepEquivalent()); |
| 1321 if (beforeParagraph.isNotNull() && (!isEndOfParagraph(beforeParagraph) || be
foreParagraph.deepEquivalent() == afterParagraph.deepEquivalent())) { | 1322 if (beforeParagraph.isNotNull() && (!isEndOfParagraph(beforeParagraph) || be
foreParagraph.deepEquivalent() == afterParagraph.deepEquivalent())) { |
| 1322 // FIXME: Trim text between beforeParagraph and afterParagraph if they a
ren't equal. | 1323 // FIXME: Trim text between beforeParagraph and afterParagraph if they a
ren't equal. |
| 1323 insertNodeAt(HTMLBRElement::create(document()), beforeParagraph.deepEqui
valent(), editingState); | 1324 insertNodeAt(HTMLBRElement::create(document()), beforeParagraph.deepEqui
valent(), editingState); |
| 1324 if (editingState->isAborted()) | 1325 if (editingState->isAborted()) |
| 1325 return; | 1326 return; |
| 1326 // Need an updateLayout here in case inserting the br has split a text n
ode. | 1327 // Need an updateLayout here in case inserting the br has split a text n
ode. |
| 1327 document().updateLayoutIgnorePendingStylesheets(); | 1328 document().updateLayoutIgnorePendingStylesheets(); |
| 1328 } | 1329 } |
| 1329 | 1330 |
| 1330 destinationIndex = TextIterator::rangeLength(firstPositionInNode(document().
documentElement()), destination.toParentAnchoredPosition(), true); | 1331 destinationIndex = TextIterator::rangeLength(firstPositionInNode(document().
documentElement()), destination.toParentAnchoredPosition(), true); |
| 1331 | 1332 |
| 1332 setEndingSelection(VisibleSelection(destination, originalIsDirectional)); | 1333 setEndingSelection(VisibleSelection(destination, originalIsDirectional)); |
| 1333 ASSERT(endingSelection().isCaretOrRange()); | 1334 DCHECK(endingSelection().isCaretOrRange()); |
| 1334 ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::S
electReplacement | ReplaceSelectionCommand::MovingParagraph; | 1335 ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::S
electReplacement | ReplaceSelectionCommand::MovingParagraph; |
| 1335 if (!preserveStyle) | 1336 if (!preserveStyle) |
| 1336 options |= ReplaceSelectionCommand::MatchStyle; | 1337 options |= ReplaceSelectionCommand::MatchStyle; |
| 1337 applyCommandToComposite(ReplaceSelectionCommand::create(document(), fragment
, options), editingState); | 1338 applyCommandToComposite(ReplaceSelectionCommand::create(document(), fragment
, options), editingState); |
| 1338 if (editingState->isAborted()) | 1339 if (editingState->isAborted()) |
| 1339 return; | 1340 return; |
| 1340 | 1341 |
| 1341 document().frame()->spellChecker().markMisspellingsAndBadGrammar(endingSelec
tion()); | 1342 document().frame()->spellChecker().markMisspellingsAndBadGrammar(endingSelec
tion()); |
| 1342 | 1343 |
| 1343 // If the selection is in an empty paragraph, restore styles from the old em
pty paragraph to the new empty paragraph. | 1344 // If the selection is in an empty paragraph, restore styles from the old em
pty paragraph to the new empty paragraph. |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1484 return false; | 1485 return false; |
| 1485 } | 1486 } |
| 1486 setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional())
); | 1487 setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional())
); |
| 1487 | 1488 |
| 1488 // If this is an empty paragraph there must be a line break here. | 1489 // If this is an empty paragraph there must be a line break here. |
| 1489 if (!lineBreakExistsAtVisiblePosition(caret)) | 1490 if (!lineBreakExistsAtVisiblePosition(caret)) |
| 1490 return false; | 1491 return false; |
| 1491 | 1492 |
| 1492 Position caretPos(mostForwardCaretPosition(caret.deepEquivalent())); | 1493 Position caretPos(mostForwardCaretPosition(caret.deepEquivalent())); |
| 1493 // A line break is either a br or a preserved newline. | 1494 // A line break is either a br or a preserved newline. |
| 1494 ASSERT(isHTMLBRElement(caretPos.anchorNode()) || (caretPos.anchorNode()->isT
extNode() && caretPos.anchorNode()->layoutObject()->style()->preserveNewline()))
; | 1495 DCHECK(isHTMLBRElement(caretPos.anchorNode()) || (caretPos.anchorNode()->isT
extNode() && caretPos.anchorNode()->layoutObject()->style()->preserveNewline()))
<< caretPos; |
| 1495 | 1496 |
| 1496 if (isHTMLBRElement(*caretPos.anchorNode())) { | 1497 if (isHTMLBRElement(*caretPos.anchorNode())) { |
| 1497 removeNodeAndPruneAncestors(caretPos.anchorNode(), editingState); | 1498 removeNodeAndPruneAncestors(caretPos.anchorNode(), editingState); |
| 1498 if (editingState->isAborted()) | 1499 if (editingState->isAborted()) |
| 1499 return false; | 1500 return false; |
| 1500 } else if (caretPos.anchorNode()->isTextNode()) { | 1501 } else if (caretPos.anchorNode()->isTextNode()) { |
| 1501 ASSERT(caretPos.computeOffsetInContainerNode() == 0); | 1502 DCHECK_EQ(caretPos.computeOffsetInContainerNode(), 0); |
| 1502 Text* textNode = toText(caretPos.anchorNode()); | 1503 Text* textNode = toText(caretPos.anchorNode()); |
| 1503 ContainerNode* parentNode = textNode->parentNode(); | 1504 ContainerNode* parentNode = textNode->parentNode(); |
| 1504 // The preserved newline must be the first thing in the node, since othe
rwise the previous | 1505 // The preserved newline must be the first thing in the node, since othe
rwise the previous |
| 1505 // paragraph would be quoted, and we verified that it wasn't above. | 1506 // paragraph would be quoted, and we verified that it wasn't above. |
| 1506 deleteTextFromNode(textNode, 0, 1); | 1507 deleteTextFromNode(textNode, 0, 1); |
| 1507 prune(parentNode, editingState); | 1508 prune(parentNode, editingState); |
| 1508 if (editingState->isAborted()) | 1509 if (editingState->isAborted()) |
| 1509 return false; | 1510 return false; |
| 1510 } | 1511 } |
| 1511 | 1512 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1574 if (result.isNull() || !rootEditableElementOf(result)) | 1575 if (result.isNull() || !rootEditableElementOf(result)) |
| 1575 result = original; | 1576 result = original; |
| 1576 | 1577 |
| 1577 return result; | 1578 return result; |
| 1578 } | 1579 } |
| 1579 | 1580 |
| 1580 // Splits the tree parent by parent until we reach the specified ancestor. We us
e VisiblePositions | 1581 // Splits the tree parent by parent until we reach the specified ancestor. We us
e VisiblePositions |
| 1581 // to determine if the split is necessary. Returns the last split node. | 1582 // to determine if the split is necessary. Returns the last split node. |
| 1582 Node* CompositeEditCommand::splitTreeToNode(Node* start, Node* end, bool shouldS
plitAncestor) | 1583 Node* CompositeEditCommand::splitTreeToNode(Node* start, Node* end, bool shouldS
plitAncestor) |
| 1583 { | 1584 { |
| 1584 ASSERT(start); | 1585 DCHECK(start); |
| 1585 ASSERT(end); | 1586 DCHECK(end); |
| 1586 ASSERT(start != end); | 1587 DCHECK_NE(start, end); |
| 1587 | 1588 |
| 1588 if (shouldSplitAncestor && end->parentNode()) | 1589 if (shouldSplitAncestor && end->parentNode()) |
| 1589 end = end->parentNode(); | 1590 end = end->parentNode(); |
| 1590 if (!start->isDescendantOf(end)) | 1591 if (!start->isDescendantOf(end)) |
| 1591 return end; | 1592 return end; |
| 1592 | 1593 |
| 1593 Node* endNode = end; | 1594 Node* endNode = end; |
| 1594 Node* node = nullptr; | 1595 Node* node = nullptr; |
| 1595 for (node = start; node->parentNode() != endNode; node = node->parentNode())
{ | 1596 for (node = start; node->parentNode() != endNode; node = node->parentNode())
{ |
| 1596 Element* parentElement = node->parentElement(); | 1597 Element* parentElement = node->parentElement(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1607 } | 1608 } |
| 1608 | 1609 |
| 1609 DEFINE_TRACE(CompositeEditCommand) | 1610 DEFINE_TRACE(CompositeEditCommand) |
| 1610 { | 1611 { |
| 1611 visitor->trace(m_commands); | 1612 visitor->trace(m_commands); |
| 1612 visitor->trace(m_composition); | 1613 visitor->trace(m_composition); |
| 1613 EditCommand::trace(visitor); | 1614 EditCommand::trace(visitor); |
| 1614 } | 1615 } |
| 1615 | 1616 |
| 1616 } // namespace blink | 1617 } // namespace blink |
| OLD | NEW |