| 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 RawPtr<LocalFrame> frame = m_document->frame(); | 106 RawPtr<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 RawPtr<LocalFrame> frame = m_document->frame(); | 126 RawPtr<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 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 applyCommandToComposite(ApplyStyleCommand::create(element, true), editingSta
te); | 296 applyCommandToComposite(ApplyStyleCommand::create(element, true), editingSta
te); |
| 297 } | 297 } |
| 298 | 298 |
| 299 void CompositeEditCommand::insertParagraphSeparator(EditingState* editingState,
bool useDefaultParagraphElement, bool pasteBlockqutoeIntoUnquotedArea) | 299 void CompositeEditCommand::insertParagraphSeparator(EditingState* editingState,
bool useDefaultParagraphElement, bool pasteBlockqutoeIntoUnquotedArea) |
| 300 { | 300 { |
| 301 applyCommandToComposite(InsertParagraphSeparatorCommand::create(document(),
useDefaultParagraphElement, pasteBlockqutoeIntoUnquotedArea), editingState); | 301 applyCommandToComposite(InsertParagraphSeparatorCommand::create(document(),
useDefaultParagraphElement, pasteBlockqutoeIntoUnquotedArea), editingState); |
| 302 } | 302 } |
| 303 | 303 |
| 304 bool CompositeEditCommand::isRemovableBlock(const Node* node) | 304 bool CompositeEditCommand::isRemovableBlock(const Node* node) |
| 305 { | 305 { |
| 306 ASSERT(node); | 306 DCHECK(node); |
| 307 if (!isHTMLDivElement(*node)) | 307 if (!isHTMLDivElement(*node)) |
| 308 return false; | 308 return false; |
| 309 | 309 |
| 310 const HTMLDivElement& element = toHTMLDivElement(*node); | 310 const HTMLDivElement& element = toHTMLDivElement(*node); |
| 311 ContainerNode* parentNode = element.parentNode(); | 311 ContainerNode* parentNode = element.parentNode(); |
| 312 if (parentNode && parentNode->firstChild() != parentNode->lastChild()) | 312 if (parentNode && parentNode->firstChild() != parentNode->lastChild()) |
| 313 return false; | 313 return false; |
| 314 | 314 |
| 315 if (!element.hasAttributes()) | 315 if (!element.hasAttributes()) |
| 316 return true; | 316 return true; |
| 317 | 317 |
| 318 return false; | 318 return false; |
| 319 } | 319 } |
| 320 | 320 |
| 321 void CompositeEditCommand::insertNodeBefore(RawPtr<Node> insertChild, RawPtr<Nod
e> refChild, EditingState* editingState, ShouldAssumeContentIsAlwaysEditable sho
uldAssumeContentIsAlwaysEditable) | 321 void CompositeEditCommand::insertNodeBefore(RawPtr<Node> insertChild, RawPtr<Nod
e> refChild, EditingState* editingState, ShouldAssumeContentIsAlwaysEditable sho
uldAssumeContentIsAlwaysEditable) |
| 322 { | 322 { |
| 323 ASSERT(document().body() != refChild); | 323 DCHECK_NE(document().body(), refChild); |
| 324 ABORT_EDITING_COMMAND_IF(!refChild->parentNode()->hasEditableStyle() && refC
hild->parentNode()->inActiveDocument()); | 324 ABORT_EDITING_COMMAND_IF(!refChild->parentNode()->hasEditableStyle() && refC
hild->parentNode()->inActiveDocument()); |
| 325 applyCommandToComposite(InsertNodeBeforeCommand::create(insertChild, refChil
d, shouldAssumeContentIsAlwaysEditable), editingState); | 325 applyCommandToComposite(InsertNodeBeforeCommand::create(insertChild, refChil
d, shouldAssumeContentIsAlwaysEditable), editingState); |
| 326 } | 326 } |
| 327 | 327 |
| 328 void CompositeEditCommand::insertNodeAfter(RawPtr<Node> insertChild, RawPtr<Node
> refChild, EditingState* editingState) | 328 void CompositeEditCommand::insertNodeAfter(RawPtr<Node> insertChild, RawPtr<Node
> refChild, EditingState* editingState) |
| 329 { | 329 { |
| 330 ASSERT(insertChild); | 330 DCHECK(insertChild); |
| 331 ASSERT(refChild); | 331 DCHECK(refChild); |
| 332 ASSERT(document().body() != refChild); | 332 DCHECK_NE(document().body(), refChild); |
| 333 ContainerNode* parent = refChild->parentNode(); | 333 ContainerNode* parent = refChild->parentNode(); |
| 334 ASSERT(parent); | 334 DCHECK(parent); |
| 335 ASSERT(!parent->isShadowRoot()); | 335 DCHECK(!parent->isShadowRoot()); |
| 336 if (parent->lastChild() == refChild) { | 336 if (parent->lastChild() == refChild) { |
| 337 appendNode(insertChild, parent, editingState); | 337 appendNode(insertChild, parent, editingState); |
| 338 } else { | 338 } else { |
| 339 ASSERT(refChild->nextSibling()); | 339 DCHECK(refChild->nextSibling()); |
| 340 insertNodeBefore(insertChild, refChild->nextSibling(), editingState); | 340 insertNodeBefore(insertChild, refChild->nextSibling(), editingState); |
| 341 } | 341 } |
| 342 } | 342 } |
| 343 | 343 |
| 344 void CompositeEditCommand::insertNodeAt(RawPtr<Node> insertChild, const Position
& editingPosition, EditingState* editingState) | 344 void CompositeEditCommand::insertNodeAt(RawPtr<Node> insertChild, const Position
& editingPosition, EditingState* editingState) |
| 345 { | 345 { |
| 346 ABORT_EDITING_COMMAND_IF(!isEditablePosition(editingPosition, ContentIsEdita
ble, DoNotUpdateStyle)); | 346 ABORT_EDITING_COMMAND_IF(!isEditablePosition(editingPosition, ContentIsEdita
ble, DoNotUpdateStyle)); |
| 347 // For editing positions like [table, 0], insert before the table, | 347 // For editing positions like [table, 0], insert before the table, |
| 348 // likewise for replaced elements, brs, etc. | 348 // likewise for replaced elements, brs, etc. |
| 349 Position p = editingPosition.parentAnchoredEquivalent(); | 349 Position p = editingPosition.parentAnchoredEquivalent(); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 413 } | 413 } |
| 414 | 414 |
| 415 void CompositeEditCommand::removeNodePreservingChildren(RawPtr<Node> node, Editi
ngState* editingState, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIs
AlwaysEditable) | 415 void CompositeEditCommand::removeNodePreservingChildren(RawPtr<Node> node, Editi
ngState* editingState, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIs
AlwaysEditable) |
| 416 { | 416 { |
| 417 ABORT_EDITING_COMMAND_IF(!node->document().frame()); | 417 ABORT_EDITING_COMMAND_IF(!node->document().frame()); |
| 418 applyCommandToComposite(RemoveNodePreservingChildrenCommand::create(node, sh
ouldAssumeContentIsAlwaysEditable), editingState); | 418 applyCommandToComposite(RemoveNodePreservingChildrenCommand::create(node, sh
ouldAssumeContentIsAlwaysEditable), editingState); |
| 419 } | 419 } |
| 420 | 420 |
| 421 void CompositeEditCommand::removeNodeAndPruneAncestors(RawPtr<Node> node, Editin
gState* editingState, Node* excludeNode) | 421 void CompositeEditCommand::removeNodeAndPruneAncestors(RawPtr<Node> node, Editin
gState* editingState, Node* excludeNode) |
| 422 { | 422 { |
| 423 ASSERT(node.get() != excludeNode); | 423 DCHECK_NE(node.get(), excludeNode); |
| 424 RawPtr<ContainerNode> parent = node->parentNode(); | 424 RawPtr<ContainerNode> parent = node->parentNode(); |
| 425 removeNode(node, editingState); | 425 removeNode(node, editingState); |
| 426 if (editingState->isAborted()) | 426 if (editingState->isAborted()) |
| 427 return; | 427 return; |
| 428 prune(parent.release(), editingState, excludeNode); | 428 prune(parent.release(), editingState, excludeNode); |
| 429 } | 429 } |
| 430 | 430 |
| 431 void CompositeEditCommand::moveRemainingSiblingsToNewParent(Node* node, Node* pa
stLastNodeToMove, RawPtr<Element> prpNewParent, EditingState* editingState) | 431 void CompositeEditCommand::moveRemainingSiblingsToNewParent(Node* node, Node* pa
stLastNodeToMove, RawPtr<Element> prpNewParent, EditingState* editingState) |
| 432 { | 432 { |
| 433 NodeVector nodesToRemove; | 433 NodeVector nodesToRemove; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 459 { | 459 { |
| 460 // It would also be possible to implement all of ReplaceNodeWithSpanCommand | 460 // It would also be possible to implement all of ReplaceNodeWithSpanCommand |
| 461 // as a series of existing smaller edit commands. Someone who wanted to | 461 // as a series of existing smaller edit commands. Someone who wanted to |
| 462 // reduce the number of edit commands could do so here. | 462 // reduce the number of edit commands could do so here. |
| 463 RawPtr<ReplaceNodeWithSpanCommand> command = ReplaceNodeWithSpanCommand::cre
ate(node); | 463 RawPtr<ReplaceNodeWithSpanCommand> command = ReplaceNodeWithSpanCommand::cre
ate(node); |
| 464 // ReplaceNodeWithSpanCommand is never aborted. | 464 // ReplaceNodeWithSpanCommand is never aborted. |
| 465 applyCommandToComposite(command, ASSERT_NO_EDITING_ABORT); | 465 applyCommandToComposite(command, ASSERT_NO_EDITING_ABORT); |
| 466 // Returning a raw pointer here is OK because the command is retained by | 466 // Returning a raw pointer here is OK because the command is retained by |
| 467 // applyCommandToComposite (thus retaining the span), and the span is also | 467 // applyCommandToComposite (thus retaining the span), and the span is also |
| 468 // in the DOM tree, and thus alive whie it has a parent. | 468 // in the DOM tree, and thus alive whie it has a parent. |
| 469 ASSERT(command->spanElement()->inShadowIncludingDocument()); | 469 DCHECK(command->spanElement()->inShadowIncludingDocument()); |
| 470 return command->spanElement(); | 470 return command->spanElement(); |
| 471 } | 471 } |
| 472 | 472 |
| 473 void CompositeEditCommand::prune(RawPtr<Node> node, EditingState* editingState,
Node* excludeNode) | 473 void CompositeEditCommand::prune(RawPtr<Node> node, EditingState* editingState,
Node* excludeNode) |
| 474 { | 474 { |
| 475 if (RawPtr<Node> highestNodeToRemove = highestNodeToRemoveInPruning(node.get
(), excludeNode)) | 475 if (RawPtr<Node> highestNodeToRemove = highestNodeToRemoveInPruning(node.get
(), excludeNode)) |
| 476 removeNode(highestNodeToRemove.release(), editingState); | 476 removeNode(highestNodeToRemove.release(), editingState); |
| 477 } | 477 } |
| 478 | 478 |
| 479 void CompositeEditCommand::splitTextNode(RawPtr<Text> node, unsigned offset) | 479 void CompositeEditCommand::splitTextNode(RawPtr<Text> node, unsigned offset) |
| 480 { | 480 { |
| 481 // SplitTextNodeCommand is never aborted. | 481 // SplitTextNodeCommand is never aborted. |
| 482 applyCommandToComposite(SplitTextNodeCommand::create(node, offset), ASSERT_N
O_EDITING_ABORT); | 482 applyCommandToComposite(SplitTextNodeCommand::create(node, offset), ASSERT_N
O_EDITING_ABORT); |
| 483 } | 483 } |
| 484 | 484 |
| 485 void CompositeEditCommand::splitElement(RawPtr<Element> element, RawPtr<Node> at
Child) | 485 void CompositeEditCommand::splitElement(RawPtr<Element> element, RawPtr<Node> at
Child) |
| 486 { | 486 { |
| 487 // SplitElementCommand is never aborted. | 487 // SplitElementCommand is never aborted. |
| 488 applyCommandToComposite(SplitElementCommand::create(element, atChild), ASSER
T_NO_EDITING_ABORT); | 488 applyCommandToComposite(SplitElementCommand::create(element, atChild), ASSER
T_NO_EDITING_ABORT); |
| 489 } | 489 } |
| 490 | 490 |
| 491 void CompositeEditCommand::mergeIdenticalElements(RawPtr<Element> prpFirst, RawP
tr<Element> prpSecond, EditingState* editingState) | 491 void CompositeEditCommand::mergeIdenticalElements(RawPtr<Element> prpFirst, RawP
tr<Element> prpSecond, EditingState* editingState) |
| 492 { | 492 { |
| 493 RawPtr<Element> first = prpFirst; | 493 RawPtr<Element> first = prpFirst; |
| 494 RawPtr<Element> second = prpSecond; | 494 RawPtr<Element> second = prpSecond; |
| 495 ASSERT(!first->isDescendantOf(second.get()) && second != first); | 495 DCHECK(!first->isDescendantOf(second.get()) && second != first); |
| 496 if (first->nextSibling() != second) { | 496 if (first->nextSibling() != second) { |
| 497 removeNode(second, editingState); | 497 removeNode(second, editingState); |
| 498 if (editingState->isAborted()) | 498 if (editingState->isAborted()) |
| 499 return; | 499 return; |
| 500 insertNodeAfter(second, first, editingState); | 500 insertNodeAfter(second, first, editingState); |
| 501 if (editingState->isAborted()) | 501 if (editingState->isAborted()) |
| 502 return; | 502 return; |
| 503 } | 503 } |
| 504 applyCommandToComposite(MergeIdenticalElementsCommand::create(first, second)
, editingState); | 504 applyCommandToComposite(MergeIdenticalElementsCommand::create(first, second)
, editingState); |
| 505 } | 505 } |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 566 void CompositeEditCommand::replaceTextInNodePreservingMarkers(RawPtr<Text> prpNo
de, unsigned offset, unsigned count, const String& replacementText) | 566 void CompositeEditCommand::replaceTextInNodePreservingMarkers(RawPtr<Text> prpNo
de, unsigned offset, unsigned count, const String& replacementText) |
| 567 { | 567 { |
| 568 RawPtr<Text> node(prpNode); | 568 RawPtr<Text> node(prpNode); |
| 569 DocumentMarkerController& markerController = document().markers(); | 569 DocumentMarkerController& markerController = document().markers(); |
| 570 Vector<DocumentMarker::MarkerType> types; | 570 Vector<DocumentMarker::MarkerType> types; |
| 571 Vector<String> descriptions; | 571 Vector<String> descriptions; |
| 572 copyMarkerTypesAndDescriptions(markerController.markersInRange(EphemeralRang
e(Position(node.get(), offset), Position(node.get(), offset + count)), DocumentM
arker::AllMarkers()), types, descriptions); | 572 copyMarkerTypesAndDescriptions(markerController.markersInRange(EphemeralRang
e(Position(node.get(), offset), Position(node.get(), offset + count)), DocumentM
arker::AllMarkers()), types, descriptions); |
| 573 replaceTextInNode(node, offset, count, replacementText); | 573 replaceTextInNode(node, offset, count, replacementText); |
| 574 Position startPosition(node.get(), offset); | 574 Position startPosition(node.get(), offset); |
| 575 Position endPosition(node.get(), offset + replacementText.length()); | 575 Position endPosition(node.get(), offset + replacementText.length()); |
| 576 ASSERT(types.size() == descriptions.size()); | 576 DCHECK_EQ(types.size(), descriptions.size()); |
| 577 for (size_t i = 0; i < types.size(); ++i) | 577 for (size_t i = 0; i < types.size(); ++i) |
| 578 markerController.addMarker(startPosition, endPosition, types[i], descrip
tions[i]); | 578 markerController.addMarker(startPosition, endPosition, types[i], descrip
tions[i]); |
| 579 } | 579 } |
| 580 | 580 |
| 581 Position CompositeEditCommand::positionOutsideTabSpan(const Position& pos) | 581 Position CompositeEditCommand::positionOutsideTabSpan(const Position& pos) |
| 582 { | 582 { |
| 583 if (!isTabHTMLSpanElementTextNode(pos.anchorNode())) | 583 if (!isTabHTMLSpanElementTextNode(pos.anchorNode())) |
| 584 return pos; | 584 return pos; |
| 585 | 585 |
| 586 switch (pos.anchorType()) { | 586 switch (pos.anchorType()) { |
| 587 case PositionAnchorType::BeforeChildren: | 587 case PositionAnchorType::BeforeChildren: |
| 588 case PositionAnchorType::AfterChildren: | 588 case PositionAnchorType::AfterChildren: |
| 589 ASSERT_NOT_REACHED(); | 589 ASSERT_NOT_REACHED(); |
| 590 return pos; | 590 return pos; |
| 591 case PositionAnchorType::OffsetInAnchor: | 591 case PositionAnchorType::OffsetInAnchor: |
| 592 break; | 592 break; |
| 593 case PositionAnchorType::BeforeAnchor: | 593 case PositionAnchorType::BeforeAnchor: |
| 594 return positionInParentBeforeNode(*pos.anchorNode()); | 594 return positionInParentBeforeNode(*pos.anchorNode()); |
| 595 case PositionAnchorType::AfterAnchor: | 595 case PositionAnchorType::AfterAnchor: |
| 596 return positionInParentAfterNode(*pos.anchorNode()); | 596 return positionInParentAfterNode(*pos.anchorNode()); |
| 597 } | 597 } |
| 598 | 598 |
| 599 HTMLSpanElement* tabSpan = tabSpanElement(pos.computeContainerNode()); | 599 HTMLSpanElement* tabSpan = tabSpanElement(pos.computeContainerNode()); |
| 600 ASSERT(tabSpan); | 600 DCHECK(tabSpan); |
| 601 | 601 |
| 602 if (pos.offsetInContainerNode() <= caretMinOffset(pos.computeContainerNode()
)) | 602 if (pos.offsetInContainerNode() <= caretMinOffset(pos.computeContainerNode()
)) |
| 603 return positionInParentBeforeNode(*tabSpan); | 603 return positionInParentBeforeNode(*tabSpan); |
| 604 | 604 |
| 605 if (pos.offsetInContainerNode() >= caretMaxOffset(pos.computeContainerNode()
)) | 605 if (pos.offsetInContainerNode() >= caretMaxOffset(pos.computeContainerNode()
)) |
| 606 return positionInParentAfterNode(*tabSpan); | 606 return positionInParentAfterNode(*tabSpan); |
| 607 | 607 |
| 608 splitTextNodeContainingElement(toText(pos.computeContainerNode()), pos.offse
tInContainerNode()); | 608 splitTextNodeContainingElement(toText(pos.computeContainerNode()), pos.offse
tInContainerNode()); |
| 609 return positionInParentBeforeNode(*tabSpan); | 609 return positionInParentBeforeNode(*tabSpan); |
| 610 } | 610 } |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 693 } | 693 } |
| 694 | 694 |
| 695 rebalanceWhitespaceOnTextSubstring(toText(node), position.offsetInContainerN
ode(), position.offsetInContainerNode()); | 695 rebalanceWhitespaceOnTextSubstring(toText(node), position.offsetInContainerN
ode(), position.offsetInContainerNode()); |
| 696 } | 696 } |
| 697 | 697 |
| 698 void CompositeEditCommand::rebalanceWhitespaceOnTextSubstring(RawPtr<Text> prpTe
xtNode, int startOffset, int endOffset) | 698 void CompositeEditCommand::rebalanceWhitespaceOnTextSubstring(RawPtr<Text> prpTe
xtNode, int startOffset, int endOffset) |
| 699 { | 699 { |
| 700 RawPtr<Text> textNode = prpTextNode; | 700 RawPtr<Text> textNode = prpTextNode; |
| 701 | 701 |
| 702 String text = textNode->data(); | 702 String text = textNode->data(); |
| 703 ASSERT(!text.isEmpty()); | 703 DCHECK(!text.isEmpty()); |
| 704 | 704 |
| 705 // Set upstream and downstream to define the extent of the whitespace surrou
nding text[offset]. | 705 // Set upstream and downstream to define the extent of the whitespace surrou
nding text[offset]. |
| 706 int upstream = startOffset; | 706 int upstream = startOffset; |
| 707 while (upstream > 0 && isWhitespace(text[upstream - 1])) | 707 while (upstream > 0 && isWhitespace(text[upstream - 1])) |
| 708 upstream--; | 708 upstream--; |
| 709 | 709 |
| 710 int downstream = endOffset; | 710 int downstream = endOffset; |
| 711 while ((unsigned)downstream < text.length() && isWhitespace(text[downstream]
)) | 711 while ((unsigned)downstream < text.length() && isWhitespace(text[downstream]
)) |
| 712 downstream++; | 712 downstream++; |
| 713 | 713 |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 847 } | 847 } |
| 848 | 848 |
| 849 if (!str.isNull()) { | 849 if (!str.isNull()) { |
| 850 // Replace the text between start and end with our pruned version. | 850 // Replace the text between start and end with our pruned version. |
| 851 if (!str.isEmpty()) { | 851 if (!str.isEmpty()) { |
| 852 replaceTextInNode(textNode, start, end - start, str); | 852 replaceTextInNode(textNode, start, end - start, str); |
| 853 } else { | 853 } else { |
| 854 // Assert that we are not going to delete all of the text in the nod
e. | 854 // Assert that we are not going to delete all of the text in the nod
e. |
| 855 // If we were, that should have been done above with the call to | 855 // If we were, that should have been done above with the call to |
| 856 // removeNode and return. | 856 // removeNode and return. |
| 857 ASSERT(start > 0 || end - start < textNode->length()); | 857 DCHECK(start > 0 || end - start < textNode->length()); |
| 858 deleteTextFromNode(textNode, start, end - start); | 858 deleteTextFromNode(textNode, start, end - start); |
| 859 } | 859 } |
| 860 } | 860 } |
| 861 } | 861 } |
| 862 | 862 |
| 863 void CompositeEditCommand::deleteInsignificantText(const Position& start, const
Position& end) | 863 void CompositeEditCommand::deleteInsignificantText(const Position& start, const
Position& end) |
| 864 { | 864 { |
| 865 if (start.isNull() || end.isNull()) | 865 if (start.isNull() || end.isNull()) |
| 866 return; | 866 return; |
| 867 | 867 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 891 } | 891 } |
| 892 | 892 |
| 893 RawPtr<HTMLBRElement> CompositeEditCommand::appendBlockPlaceholder(RawPtr<Elemen
t> container, EditingState* editingState) | 893 RawPtr<HTMLBRElement> CompositeEditCommand::appendBlockPlaceholder(RawPtr<Elemen
t> container, EditingState* editingState) |
| 894 { | 894 { |
| 895 if (!container) | 895 if (!container) |
| 896 return nullptr; | 896 return nullptr; |
| 897 | 897 |
| 898 document().updateLayoutIgnorePendingStylesheets(); | 898 document().updateLayoutIgnorePendingStylesheets(); |
| 899 | 899 |
| 900 // Should assert isLayoutBlockFlow || isInlineFlow when deletion improves. S
ee 4244964. | 900 // Should assert isLayoutBlockFlow || isInlineFlow when deletion improves. S
ee 4244964. |
| 901 ASSERT(container->layoutObject()); | 901 DCHECK(container->layoutObject()); |
| 902 | 902 |
| 903 RawPtr<HTMLBRElement> placeholder = HTMLBRElement::create(document()); | 903 RawPtr<HTMLBRElement> placeholder = HTMLBRElement::create(document()); |
| 904 appendNode(placeholder, container, editingState); | 904 appendNode(placeholder, container, editingState); |
| 905 if (editingState->isAborted()) | 905 if (editingState->isAborted()) |
| 906 return nullptr; | 906 return nullptr; |
| 907 return placeholder.release(); | 907 return placeholder.release(); |
| 908 } | 908 } |
| 909 | 909 |
| 910 RawPtr<HTMLBRElement> CompositeEditCommand::insertBlockPlaceholder(const Positio
n& pos, EditingState* editingState) | 910 RawPtr<HTMLBRElement> CompositeEditCommand::insertBlockPlaceholder(const Positio
n& pos, EditingState* editingState) |
| 911 { | 911 { |
| 912 if (pos.isNull()) | 912 if (pos.isNull()) |
| 913 return nullptr; | 913 return nullptr; |
| 914 | 914 |
| 915 // Should assert isLayoutBlockFlow || isInlineFlow when deletion improves. S
ee 4244964. | 915 // Should assert isLayoutBlockFlow || isInlineFlow when deletion improves. S
ee 4244964. |
| 916 ASSERT(pos.anchorNode()->layoutObject()); | 916 DCHECK(pos.anchorNode()->layoutObject()); |
| 917 | 917 |
| 918 RawPtr<HTMLBRElement> placeholder = HTMLBRElement::create(document()); | 918 RawPtr<HTMLBRElement> placeholder = HTMLBRElement::create(document()); |
| 919 insertNodeAt(placeholder, pos, editingState); | 919 insertNodeAt(placeholder, pos, editingState); |
| 920 if (editingState->isAborted()) | 920 if (editingState->isAborted()) |
| 921 return nullptr; | 921 return nullptr; |
| 922 return placeholder.release(); | 922 return placeholder.release(); |
| 923 } | 923 } |
| 924 | 924 |
| 925 RawPtr<HTMLBRElement> CompositeEditCommand::addBlockPlaceholderIfNeeded(Element*
container, EditingState* editingState) | 925 RawPtr<HTMLBRElement> CompositeEditCommand::addBlockPlaceholderIfNeeded(Element*
container, EditingState* editingState) |
| 926 { | 926 { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 938 LayoutBlockFlow* block = toLayoutBlockFlow(layoutObject); | 938 LayoutBlockFlow* block = toLayoutBlockFlow(layoutObject); |
| 939 if (block->size().height() == 0 || (block->isListItem() && toLayoutListItem(
block)->isEmpty())) | 939 if (block->size().height() == 0 || (block->isListItem() && toLayoutListItem(
block)->isEmpty())) |
| 940 return appendBlockPlaceholder(container, editingState); | 940 return appendBlockPlaceholder(container, editingState); |
| 941 | 941 |
| 942 return nullptr; | 942 return nullptr; |
| 943 } | 943 } |
| 944 | 944 |
| 945 // Assumes that the position is at a placeholder and does the removal without mu
ch checking. | 945 // Assumes that the position is at a placeholder and does the removal without mu
ch checking. |
| 946 void CompositeEditCommand::removePlaceholderAt(const Position& p) | 946 void CompositeEditCommand::removePlaceholderAt(const Position& p) |
| 947 { | 947 { |
| 948 ASSERT(lineBreakExistsAtPosition(p)); | 948 DCHECK(lineBreakExistsAtPosition(p)); |
| 949 | 949 |
| 950 // We are certain that the position is at a line break, but it may be a br o
r a preserved newline. | 950 // We are certain that the position is at a line break, but it may be a br o
r a preserved newline. |
| 951 if (isHTMLBRElement(*p.anchorNode())) { | 951 if (isHTMLBRElement(*p.anchorNode())) { |
| 952 // Removing a BR element won't dispatch synchronous events. | 952 // Removing a BR element won't dispatch synchronous events. |
| 953 removeNode(p.anchorNode(), ASSERT_NO_EDITING_ABORT); | 953 removeNode(p.anchorNode(), ASSERT_NO_EDITING_ABORT); |
| 954 return; | 954 return; |
| 955 } | 955 } |
| 956 | 956 |
| 957 deleteTextFromNode(toText(p.anchorNode()), p.offsetInContainerNode(), 1); | 957 deleteTextFromNode(toText(p.anchorNode()), p.offsetInContainerNode(), 1); |
| 958 } | 958 } |
| 959 | 959 |
| 960 RawPtr<HTMLElement> CompositeEditCommand::insertNewDefaultParagraphElementAt(con
st Position& position, EditingState* editingState) | 960 RawPtr<HTMLElement> CompositeEditCommand::insertNewDefaultParagraphElementAt(con
st Position& position, EditingState* editingState) |
| 961 { | 961 { |
| 962 RawPtr<HTMLElement> paragraphElement = createDefaultParagraphElement(documen
t()); | 962 RawPtr<HTMLElement> paragraphElement = createDefaultParagraphElement(documen
t()); |
| 963 paragraphElement->appendChild(HTMLBRElement::create(document())); | 963 paragraphElement->appendChild(HTMLBRElement::create(document())); |
| 964 insertNodeAt(paragraphElement, position, editingState); | 964 insertNodeAt(paragraphElement, position, editingState); |
| 965 if (editingState->isAborted()) | 965 if (editingState->isAborted()) |
| 966 return nullptr; | 966 return nullptr; |
| 967 return paragraphElement.release(); | 967 return paragraphElement.release(); |
| 968 } | 968 } |
| 969 | 969 |
| 970 // If the paragraph is not entirely within it's own block, create one and move t
he paragraph into | 970 // If the paragraph is not entirely within it's own block, create one and move t
he paragraph into |
| 971 // it, and return that block. Otherwise return 0. | 971 // it, and return that block. Otherwise return 0. |
| 972 RawPtr<HTMLElement> CompositeEditCommand::moveParagraphContentsToNewBlockIfNeces
sary(const Position& pos, EditingState* editingState) | 972 RawPtr<HTMLElement> CompositeEditCommand::moveParagraphContentsToNewBlockIfNeces
sary(const Position& pos, EditingState* editingState) |
| 973 { | 973 { |
| 974 ASSERT(isEditablePosition(pos, ContentIsEditable, DoNotUpdateStyle)); | 974 DCHECK(isEditablePosition(pos, ContentIsEditable, DoNotUpdateStyle)); |
| 975 | 975 |
| 976 // It's strange that this function is responsible for verifying that pos has
not been invalidated | 976 // It's strange that this function is responsible for verifying that pos has
not been invalidated |
| 977 // by an earlier call to this function. The caller, applyBlockStyle, should
do this. | 977 // by an earlier call to this function. The caller, applyBlockStyle, should
do this. |
| 978 VisiblePosition visiblePos = createVisiblePosition(pos, VP_DEFAULT_AFFINITY)
; | 978 VisiblePosition visiblePos = createVisiblePosition(pos, VP_DEFAULT_AFFINITY)
; |
| 979 VisiblePosition visibleParagraphStart = startOfParagraph(visiblePos); | 979 VisiblePosition visibleParagraphStart = startOfParagraph(visiblePos); |
| 980 VisiblePosition visibleParagraphEnd = endOfParagraph(visiblePos); | 980 VisiblePosition visibleParagraphEnd = endOfParagraph(visiblePos); |
| 981 VisiblePosition next = nextPositionOf(visibleParagraphEnd); | 981 VisiblePosition next = nextPositionOf(visibleParagraphEnd); |
| 982 VisiblePosition visibleEnd = next.isNotNull() ? next : visibleParagraphEnd; | 982 VisiblePosition visibleEnd = next.isNotNull() ? next : visibleParagraphEnd; |
| 983 | 983 |
| 984 Position upstreamStart = mostBackwardCaretPosition(visibleParagraphStart.dee
pEquivalent()); | 984 Position upstreamStart = mostBackwardCaretPosition(visibleParagraphStart.dee
pEquivalent()); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1039 } | 1039 } |
| 1040 | 1040 |
| 1041 return newBlock.release(); | 1041 return newBlock.release(); |
| 1042 } | 1042 } |
| 1043 | 1043 |
| 1044 void CompositeEditCommand::pushAnchorElementDown(Element* anchorNode, EditingSta
te* editingState) | 1044 void CompositeEditCommand::pushAnchorElementDown(Element* anchorNode, EditingSta
te* editingState) |
| 1045 { | 1045 { |
| 1046 if (!anchorNode) | 1046 if (!anchorNode) |
| 1047 return; | 1047 return; |
| 1048 | 1048 |
| 1049 ASSERT(anchorNode->isLink()); | 1049 DCHECK(anchorNode->isLink()); |
| 1050 | 1050 |
| 1051 setEndingSelection(VisibleSelection::selectionFromContentsOfNode(anchorNode)
); | 1051 setEndingSelection(VisibleSelection::selectionFromContentsOfNode(anchorNode)
); |
| 1052 applyStyledElement(anchorNode, editingState); | 1052 applyStyledElement(anchorNode, editingState); |
| 1053 if (editingState->isAborted()) | 1053 if (editingState->isAborted()) |
| 1054 return; | 1054 return; |
| 1055 // Clones of anchorNode have been pushed down, now remove it. | 1055 // Clones of anchorNode have been pushed down, now remove it. |
| 1056 if (anchorNode->inShadowIncludingDocument()) | 1056 if (anchorNode->inShadowIncludingDocument()) |
| 1057 removeNodePreservingChildren(anchorNode, editingState); | 1057 removeNodePreservingChildren(anchorNode, editingState); |
| 1058 } | 1058 } |
| 1059 | 1059 |
| 1060 // Clone the paragraph between start and end under blockElement, | 1060 // Clone the paragraph between start and end under blockElement, |
| 1061 // preserving the hierarchy up to outerNode. | 1061 // preserving the hierarchy up to outerNode. |
| 1062 | 1062 |
| 1063 void CompositeEditCommand::cloneParagraphUnderNewElement(const Position& start,
const Position& end, Node* passedOuterNode, Element* blockElement, EditingState*
editingState) | 1063 void CompositeEditCommand::cloneParagraphUnderNewElement(const Position& start,
const Position& end, Node* passedOuterNode, Element* blockElement, EditingState*
editingState) |
| 1064 { | 1064 { |
| 1065 ASSERT(comparePositions(start, end) <= 0); | 1065 DCHECK_LE(comparePositions(start, end), 0); |
| 1066 ASSERT(passedOuterNode); | 1066 DCHECK(passedOuterNode); |
| 1067 ASSERT(blockElement); | 1067 DCHECK(blockElement); |
| 1068 | 1068 |
| 1069 // First we clone the outerNode | 1069 // First we clone the outerNode |
| 1070 RawPtr<Node> lastNode = nullptr; | 1070 RawPtr<Node> lastNode = nullptr; |
| 1071 RawPtr<Node> outerNode = passedOuterNode; | 1071 RawPtr<Node> outerNode = passedOuterNode; |
| 1072 | 1072 |
| 1073 if (outerNode->isRootEditableElement()) { | 1073 if (outerNode->isRootEditableElement()) { |
| 1074 lastNode = blockElement; | 1074 lastNode = blockElement; |
| 1075 } else { | 1075 } else { |
| 1076 lastNode = outerNode->cloneNode(isDisplayInsideTable(outerNode.get())); | 1076 lastNode = outerNode->cloneNode(isDisplayInsideTable(outerNode.get())); |
| 1077 appendNode(lastNode, blockElement, editingState); | 1077 appendNode(lastNode, blockElement, editingState); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1190 } | 1190 } |
| 1191 | 1191 |
| 1192 // This is a version of moveParagraph that preserves style by keeping the origin
al markup | 1192 // This is a version of moveParagraph that preserves style by keeping the origin
al markup |
| 1193 // It is currently used only by IndentOutdentCommand but it is meant to be used
in the | 1193 // It is currently used only by IndentOutdentCommand but it is meant to be used
in the |
| 1194 // future by several other commands such as InsertList and the align commands. | 1194 // future by several other commands such as InsertList and the align commands. |
| 1195 // The blockElement parameter is the element to move the paragraph to, | 1195 // The blockElement parameter is the element to move the paragraph to, |
| 1196 // outerNode is the top element of the paragraph hierarchy. | 1196 // outerNode is the top element of the paragraph hierarchy. |
| 1197 | 1197 |
| 1198 void CompositeEditCommand::moveParagraphWithClones(const VisiblePosition& startO
fParagraphToMove, const VisiblePosition& endOfParagraphToMove, HTMLElement* bloc
kElement, Node* outerNode, EditingState* editingState) | 1198 void CompositeEditCommand::moveParagraphWithClones(const VisiblePosition& startO
fParagraphToMove, const VisiblePosition& endOfParagraphToMove, HTMLElement* bloc
kElement, Node* outerNode, EditingState* editingState) |
| 1199 { | 1199 { |
| 1200 ASSERT(outerNode); | 1200 DCHECK(outerNode); |
| 1201 ASSERT(blockElement); | 1201 DCHECK(blockElement); |
| 1202 | 1202 |
| 1203 VisiblePosition beforeParagraph = previousPositionOf(startOfParagraphToMove)
; | 1203 VisiblePosition beforeParagraph = previousPositionOf(startOfParagraphToMove)
; |
| 1204 VisiblePosition afterParagraph = nextPositionOf(endOfParagraphToMove); | 1204 VisiblePosition afterParagraph = nextPositionOf(endOfParagraphToMove); |
| 1205 | 1205 |
| 1206 // We upstream() the end and downstream() the start so that we don't include
collapsed whitespace in the move. | 1206 // We upstream() the end and downstream() the start so that we don't include
collapsed whitespace in the move. |
| 1207 // When we paste a fragment, spaces after the end and before the start are t
reated as though they were rendered. | 1207 // When we paste a fragment, spaces after the end and before the start are t
reated as though they were rendered. |
| 1208 Position start = mostForwardCaretPosition(startOfParagraphToMove.deepEquival
ent()); | 1208 Position start = mostForwardCaretPosition(startOfParagraphToMove.deepEquival
ent()); |
| 1209 Position end = startOfParagraphToMove.deepEquivalent() == endOfParagraphToMo
ve.deepEquivalent() ? start : mostBackwardCaretPosition(endOfParagraphToMove.dee
pEquivalent()); | 1209 Position end = startOfParagraphToMove.deepEquivalent() == endOfParagraphToMo
ve.deepEquivalent() ? start : mostBackwardCaretPosition(endOfParagraphToMove.dee
pEquivalent()); |
| 1210 if (comparePositions(start, end) > 0) | 1210 if (comparePositions(start, end) > 0) |
| 1211 end = start; | 1211 end = start; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1237 | 1237 |
| 1238 if (beforeParagraph.isNotNull() && !isDisplayInsideTable(beforeParagraph.dee
pEquivalent().anchorNode()) | 1238 if (beforeParagraph.isNotNull() && !isDisplayInsideTable(beforeParagraph.dee
pEquivalent().anchorNode()) |
| 1239 && ((!isEndOfParagraph(beforeParagraph) && !isStartOfParagraph(beforePar
agraph)) || beforeParagraph.deepEquivalent() == afterParagraph.deepEquivalent())
) { | 1239 && ((!isEndOfParagraph(beforeParagraph) && !isStartOfParagraph(beforePar
agraph)) || beforeParagraph.deepEquivalent() == afterParagraph.deepEquivalent())
) { |
| 1240 // FIXME: Trim text between beforeParagraph and afterParagraph if they a
ren't equal. | 1240 // FIXME: Trim text between beforeParagraph and afterParagraph if they a
ren't equal. |
| 1241 insertNodeAt(HTMLBRElement::create(document()), beforeParagraph.deepEqui
valent(), editingState); | 1241 insertNodeAt(HTMLBRElement::create(document()), beforeParagraph.deepEqui
valent(), editingState); |
| 1242 } | 1242 } |
| 1243 } | 1243 } |
| 1244 | 1244 |
| 1245 void CompositeEditCommand::moveParagraph(const VisiblePosition& startOfParagraph
ToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& dest
ination, EditingState* editingState, bool preserveSelection, bool preserveStyle,
Node* constrainingAncestor) | 1245 void CompositeEditCommand::moveParagraph(const VisiblePosition& startOfParagraph
ToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& dest
ination, EditingState* editingState, bool preserveSelection, bool preserveStyle,
Node* constrainingAncestor) |
| 1246 { | 1246 { |
| 1247 ASSERT(isStartOfParagraph(startOfParagraphToMove)); | 1247 DCHECK(isStartOfParagraph(startOfParagraphToMove)); |
| 1248 ASSERT(isEndOfParagraph(endOfParagraphToMove)); | 1248 DCHECK(isEndOfParagraph(endOfParagraphToMove)); |
| 1249 moveParagraphs(startOfParagraphToMove, endOfParagraphToMove, destination, ed
itingState, preserveSelection, preserveStyle, constrainingAncestor); | 1249 moveParagraphs(startOfParagraphToMove, endOfParagraphToMove, destination, ed
itingState, preserveSelection, preserveStyle, constrainingAncestor); |
| 1250 } | 1250 } |
| 1251 | 1251 |
| 1252 void CompositeEditCommand::moveParagraphs(const VisiblePosition& startOfParagrap
hToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& des
tination, EditingState* editingState, bool preserveSelection, bool preserveStyle
, Node* constrainingAncestor) | 1252 void CompositeEditCommand::moveParagraphs(const VisiblePosition& startOfParagrap
hToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& des
tination, EditingState* editingState, bool preserveSelection, bool preserveStyle
, Node* constrainingAncestor) |
| 1253 { | 1253 { |
| 1254 if (startOfParagraphToMove.deepEquivalent() == destination.deepEquivalent()
|| startOfParagraphToMove.isNull()) | 1254 if (startOfParagraphToMove.deepEquivalent() == destination.deepEquivalent()
|| startOfParagraphToMove.isNull()) |
| 1255 return; | 1255 return; |
| 1256 | 1256 |
| 1257 int startIndex = -1; | 1257 int startIndex = -1; |
| 1258 int endIndex = -1; | 1258 int endIndex = -1; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1304 } | 1304 } |
| 1305 | 1305 |
| 1306 // FIXME (5098931): We should add a new insert action "WebViewInsertActionMo
ved" and call shouldInsertFragment here. | 1306 // FIXME (5098931): We should add a new insert action "WebViewInsertActionMo
ved" and call shouldInsertFragment here. |
| 1307 | 1307 |
| 1308 setEndingSelection(VisibleSelection(start, end)); | 1308 setEndingSelection(VisibleSelection(start, end)); |
| 1309 document().frame()->spellChecker().clearMisspellingsAndBadGrammar(endingSele
ction()); | 1309 document().frame()->spellChecker().clearMisspellingsAndBadGrammar(endingSele
ction()); |
| 1310 deleteSelection(editingState, false, false, false); | 1310 deleteSelection(editingState, false, false, false); |
| 1311 if (editingState->isAborted()) | 1311 if (editingState->isAborted()) |
| 1312 return; | 1312 return; |
| 1313 | 1313 |
| 1314 ASSERT(destination.deepEquivalent().inShadowIncludingDocument()); | 1314 DCHECK(destination.deepEquivalent().inShadowIncludingDocument()); |
| 1315 cleanupAfterDeletion(editingState, destination); | 1315 cleanupAfterDeletion(editingState, destination); |
| 1316 if (editingState->isAborted()) | 1316 if (editingState->isAborted()) |
| 1317 return; | 1317 return; |
| 1318 ASSERT(destination.deepEquivalent().inShadowIncludingDocument()); | 1318 DCHECK(destination.deepEquivalent().inShadowIncludingDocument()); |
| 1319 | 1319 |
| 1320 // Add a br if pruning an empty block level element caused a collapse. For e
xample: | 1320 // Add a br if pruning an empty block level element caused a collapse. For e
xample: |
| 1321 // foo^ | 1321 // foo^ |
| 1322 // <div>bar</div> | 1322 // <div>bar</div> |
| 1323 // baz | 1323 // baz |
| 1324 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. That
would | 1324 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. That
would |
| 1325 // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br
. | 1325 // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br
. |
| 1326 // Must recononicalize these two VisiblePositions after the pruning above. | 1326 // Must recononicalize these two VisiblePositions after the pruning above. |
| 1327 beforeParagraph = createVisiblePosition(beforeParagraph.deepEquivalent()); | 1327 beforeParagraph = createVisiblePosition(beforeParagraph.deepEquivalent()); |
| 1328 afterParagraph = createVisiblePosition(afterParagraph.deepEquivalent()); | 1328 afterParagraph = createVisiblePosition(afterParagraph.deepEquivalent()); |
| 1329 if (beforeParagraph.isNotNull() && (!isEndOfParagraph(beforeParagraph) || be
foreParagraph.deepEquivalent() == afterParagraph.deepEquivalent())) { | 1329 if (beforeParagraph.isNotNull() && (!isEndOfParagraph(beforeParagraph) || be
foreParagraph.deepEquivalent() == afterParagraph.deepEquivalent())) { |
| 1330 // FIXME: Trim text between beforeParagraph and afterParagraph if they a
ren't equal. | 1330 // FIXME: Trim text between beforeParagraph and afterParagraph if they a
ren't equal. |
| 1331 insertNodeAt(HTMLBRElement::create(document()), beforeParagraph.deepEqui
valent(), editingState); | 1331 insertNodeAt(HTMLBRElement::create(document()), beforeParagraph.deepEqui
valent(), editingState); |
| 1332 if (editingState->isAborted()) | 1332 if (editingState->isAborted()) |
| 1333 return; | 1333 return; |
| 1334 // Need an updateLayout here in case inserting the br has split a text n
ode. | 1334 // Need an updateLayout here in case inserting the br has split a text n
ode. |
| 1335 document().updateLayoutIgnorePendingStylesheets(); | 1335 document().updateLayoutIgnorePendingStylesheets(); |
| 1336 } | 1336 } |
| 1337 | 1337 |
| 1338 destinationIndex = TextIterator::rangeLength(firstPositionInNode(document().
documentElement()), destination.toParentAnchoredPosition(), true); | 1338 destinationIndex = TextIterator::rangeLength(firstPositionInNode(document().
documentElement()), destination.toParentAnchoredPosition(), true); |
| 1339 | 1339 |
| 1340 setEndingSelection(VisibleSelection(destination, originalIsDirectional)); | 1340 setEndingSelection(VisibleSelection(destination, originalIsDirectional)); |
| 1341 ASSERT(endingSelection().isCaretOrRange()); | 1341 DCHECK(endingSelection().isCaretOrRange()); |
| 1342 ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::S
electReplacement | ReplaceSelectionCommand::MovingParagraph; | 1342 ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::S
electReplacement | ReplaceSelectionCommand::MovingParagraph; |
| 1343 if (!preserveStyle) | 1343 if (!preserveStyle) |
| 1344 options |= ReplaceSelectionCommand::MatchStyle; | 1344 options |= ReplaceSelectionCommand::MatchStyle; |
| 1345 applyCommandToComposite(ReplaceSelectionCommand::create(document(), fragment
, options), editingState); | 1345 applyCommandToComposite(ReplaceSelectionCommand::create(document(), fragment
, options), editingState); |
| 1346 if (editingState->isAborted()) | 1346 if (editingState->isAborted()) |
| 1347 return; | 1347 return; |
| 1348 | 1348 |
| 1349 document().frame()->spellChecker().markMisspellingsAndBadGrammar(endingSelec
tion()); | 1349 document().frame()->spellChecker().markMisspellingsAndBadGrammar(endingSelec
tion()); |
| 1350 | 1350 |
| 1351 // If the selection is in an empty paragraph, restore styles from the old em
pty paragraph to the new empty paragraph. | 1351 // 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... |
| 1492 return false; | 1492 return false; |
| 1493 } | 1493 } |
| 1494 setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional())
); | 1494 setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional())
); |
| 1495 | 1495 |
| 1496 // If this is an empty paragraph there must be a line break here. | 1496 // If this is an empty paragraph there must be a line break here. |
| 1497 if (!lineBreakExistsAtVisiblePosition(caret)) | 1497 if (!lineBreakExistsAtVisiblePosition(caret)) |
| 1498 return false; | 1498 return false; |
| 1499 | 1499 |
| 1500 Position caretPos(mostForwardCaretPosition(caret.deepEquivalent())); | 1500 Position caretPos(mostForwardCaretPosition(caret.deepEquivalent())); |
| 1501 // A line break is either a br or a preserved newline. | 1501 // A line break is either a br or a preserved newline. |
| 1502 ASSERT(isHTMLBRElement(caretPos.anchorNode()) || (caretPos.anchorNode()->isT
extNode() && caretPos.anchorNode()->layoutObject()->style()->preserveNewline()))
; | 1502 DCHECK(isHTMLBRElement(caretPos.anchorNode()) || (caretPos.anchorNode()->isT
extNode() && caretPos.anchorNode()->layoutObject()->style()->preserveNewline()))
; |
| 1503 | 1503 |
| 1504 if (isHTMLBRElement(*caretPos.anchorNode())) { | 1504 if (isHTMLBRElement(*caretPos.anchorNode())) { |
| 1505 removeNodeAndPruneAncestors(caretPos.anchorNode(), editingState); | 1505 removeNodeAndPruneAncestors(caretPos.anchorNode(), editingState); |
| 1506 if (editingState->isAborted()) | 1506 if (editingState->isAborted()) |
| 1507 return false; | 1507 return false; |
| 1508 } else if (caretPos.anchorNode()->isTextNode()) { | 1508 } else if (caretPos.anchorNode()->isTextNode()) { |
| 1509 ASSERT(caretPos.computeOffsetInContainerNode() == 0); | 1509 DCHECK_EQ(caretPos.computeOffsetInContainerNode(), 0); |
| 1510 Text* textNode = toText(caretPos.anchorNode()); | 1510 Text* textNode = toText(caretPos.anchorNode()); |
| 1511 ContainerNode* parentNode = textNode->parentNode(); | 1511 ContainerNode* parentNode = textNode->parentNode(); |
| 1512 // The preserved newline must be the first thing in the node, since othe
rwise the previous | 1512 // The preserved newline must be the first thing in the node, since othe
rwise the previous |
| 1513 // paragraph would be quoted, and we verified that it wasn't above. | 1513 // paragraph would be quoted, and we verified that it wasn't above. |
| 1514 deleteTextFromNode(textNode, 0, 1); | 1514 deleteTextFromNode(textNode, 0, 1); |
| 1515 prune(parentNode, editingState); | 1515 prune(parentNode, editingState); |
| 1516 if (editingState->isAborted()) | 1516 if (editingState->isAborted()) |
| 1517 return false; | 1517 return false; |
| 1518 } | 1518 } |
| 1519 | 1519 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1582 if (result.isNull() || !rootEditableElementOf(result)) | 1582 if (result.isNull() || !rootEditableElementOf(result)) |
| 1583 result = original; | 1583 result = original; |
| 1584 | 1584 |
| 1585 return result; | 1585 return result; |
| 1586 } | 1586 } |
| 1587 | 1587 |
| 1588 // Splits the tree parent by parent until we reach the specified ancestor. We us
e VisiblePositions | 1588 // Splits the tree parent by parent until we reach the specified ancestor. We us
e VisiblePositions |
| 1589 // to determine if the split is necessary. Returns the last split node. | 1589 // to determine if the split is necessary. Returns the last split node. |
| 1590 RawPtr<Node> CompositeEditCommand::splitTreeToNode(Node* start, Node* end, bool
shouldSplitAncestor) | 1590 RawPtr<Node> CompositeEditCommand::splitTreeToNode(Node* start, Node* end, bool
shouldSplitAncestor) |
| 1591 { | 1591 { |
| 1592 ASSERT(start); | 1592 DCHECK(start); |
| 1593 ASSERT(end); | 1593 DCHECK(end); |
| 1594 ASSERT(start != end); | 1594 DCHECK_NE(start, end); |
| 1595 | 1595 |
| 1596 if (shouldSplitAncestor && end->parentNode()) | 1596 if (shouldSplitAncestor && end->parentNode()) |
| 1597 end = end->parentNode(); | 1597 end = end->parentNode(); |
| 1598 if (!start->isDescendantOf(end)) | 1598 if (!start->isDescendantOf(end)) |
| 1599 return end; | 1599 return end; |
| 1600 | 1600 |
| 1601 RawPtr<Node> endNode = end; | 1601 RawPtr<Node> endNode = end; |
| 1602 RawPtr<Node> node = nullptr; | 1602 RawPtr<Node> node = nullptr; |
| 1603 for (node = start; node->parentNode() != endNode; node = node->parentNode())
{ | 1603 for (node = start; node->parentNode() != endNode; node = node->parentNode())
{ |
| 1604 Element* parentElement = node->parentElement(); | 1604 Element* parentElement = node->parentElement(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1615 } | 1615 } |
| 1616 | 1616 |
| 1617 DEFINE_TRACE(CompositeEditCommand) | 1617 DEFINE_TRACE(CompositeEditCommand) |
| 1618 { | 1618 { |
| 1619 visitor->trace(m_commands); | 1619 visitor->trace(m_commands); |
| 1620 visitor->trace(m_composition); | 1620 visitor->trace(m_composition); |
| 1621 EditCommand::trace(visitor); | 1621 EditCommand::trace(visitor); |
| 1622 } | 1622 } |
| 1623 | 1623 |
| 1624 } // namespace blink | 1624 } // namespace blink |
| OLD | NEW |