| 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 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 71 #include "core/layout/LayoutBlock.h" | 71 #include "core/layout/LayoutBlock.h" |
| 72 #include "core/layout/LayoutListItem.h" | 72 #include "core/layout/LayoutListItem.h" |
| 73 #include "core/layout/LayoutText.h" | 73 #include "core/layout/LayoutText.h" |
| 74 #include "core/layout/line/InlineTextBox.h" | 74 #include "core/layout/line/InlineTextBox.h" |
| 75 #include <algorithm> | 75 #include <algorithm> |
| 76 | 76 |
| 77 namespace blink { | 77 namespace blink { |
| 78 | 78 |
| 79 using namespace HTMLNames; | 79 using namespace HTMLNames; |
| 80 | 80 |
| 81 PassRefPtrWillBeRawPtr<EditCommandComposition> EditCommandComposition::create(Do
cument* document, | 81 RawPtr<EditCommandComposition> EditCommandComposition::create(Document* document
, |
| 82 const VisibleSelection& startingSelection, const VisibleSelection& endingSel
ection, EditAction editAction) | 82 const VisibleSelection& startingSelection, const VisibleSelection& endingSel
ection, EditAction editAction) |
| 83 { | 83 { |
| 84 return adoptRefWillBeNoop(new EditCommandComposition(document, startingSelec
tion, endingSelection, editAction)); | 84 return new EditCommandComposition(document, startingSelection, endingSelecti
on, editAction); |
| 85 } | 85 } |
| 86 | 86 |
| 87 EditCommandComposition::EditCommandComposition(Document* document, const Visible
Selection& startingSelection, const VisibleSelection& endingSelection, EditActio
n editAction) | 87 EditCommandComposition::EditCommandComposition(Document* document, const Visible
Selection& startingSelection, const VisibleSelection& endingSelection, EditActio
n editAction) |
| 88 : m_document(document) | 88 : m_document(document) |
| 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 ASSERT(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 ASSERT(m_document); |
| 106 RefPtrWillBeRawPtr<LocalFrame> frame = m_document->frame(); | 106 RawPtr<LocalFrame> frame = m_document->frame(); |
| 107 ASSERT(frame); | 107 ASSERT(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 ASSERT(m_document); |
| 126 RefPtrWillBeRawPtr<LocalFrame> frame = m_document->frame(); | 126 RawPtr<LocalFrame> frame = m_document->frame(); |
| 127 ASSERT(frame); | 127 ASSERT(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(); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 return false; | 241 return false; |
| 242 } | 242 } |
| 243 | 243 |
| 244 void CompositeEditCommand::setShouldRetainAutocorrectionIndicator(bool) | 244 void CompositeEditCommand::setShouldRetainAutocorrectionIndicator(bool) |
| 245 { | 245 { |
| 246 } | 246 } |
| 247 | 247 |
| 248 // | 248 // |
| 249 // sugary-sweet convenience functions to help create and apply edit commands in
composite commands | 249 // sugary-sweet convenience functions to help create and apply edit commands in
composite commands |
| 250 // | 250 // |
| 251 void CompositeEditCommand::applyCommandToComposite(PassRefPtrWillBeRawPtr<EditCo
mmand> prpCommand, EditingState* editingState) | 251 void CompositeEditCommand::applyCommandToComposite(RawPtr<EditCommand> prpComman
d, EditingState* editingState) |
| 252 { | 252 { |
| 253 RefPtrWillBeRawPtr<EditCommand> command = prpCommand; | 253 RawPtr<EditCommand> command = prpCommand; |
| 254 command->setParent(this); | 254 command->setParent(this); |
| 255 command->doApply(editingState); | 255 command->doApply(editingState); |
| 256 if (editingState->isAborted()) { | 256 if (editingState->isAborted()) { |
| 257 command->setParent(nullptr); | 257 command->setParent(nullptr); |
| 258 return; | 258 return; |
| 259 } | 259 } |
| 260 if (command->isSimpleEditCommand()) { | 260 if (command->isSimpleEditCommand()) { |
| 261 command->setParent(0); | 261 command->setParent(0); |
| 262 ensureComposition()->append(toSimpleEditCommand(command.get())); | 262 ensureComposition()->append(toSimpleEditCommand(command.get())); |
| 263 } | 263 } |
| 264 m_commands.append(command.release()); | 264 m_commands.append(command.release()); |
| 265 } | 265 } |
| 266 | 266 |
| 267 void CompositeEditCommand::applyCommandToComposite(PassRefPtrWillBeRawPtr<Compos
iteEditCommand> command, const VisibleSelection& selection, EditingState* editin
gState) | 267 void CompositeEditCommand::applyCommandToComposite(RawPtr<CompositeEditCommand>
command, const VisibleSelection& selection, EditingState* editingState) |
| 268 { | 268 { |
| 269 command->setParent(this); | 269 command->setParent(this); |
| 270 if (!equalSelectionsInDOMTree(selection, command->endingSelection())) { | 270 if (!equalSelectionsInDOMTree(selection, command->endingSelection())) { |
| 271 command->setStartingSelection(selection); | 271 command->setStartingSelection(selection); |
| 272 command->setEndingSelection(selection); | 272 command->setEndingSelection(selection); |
| 273 } | 273 } |
| 274 command->doApply(editingState); | 274 command->doApply(editingState); |
| 275 if (!editingState->isAborted()) | 275 if (!editingState->isAborted()) |
| 276 m_commands.append(command); | 276 m_commands.append(command); |
| 277 } | 277 } |
| 278 | 278 |
| 279 void CompositeEditCommand::applyStyle(const EditingStyle* style, EditingState* e
ditingState) | 279 void CompositeEditCommand::applyStyle(const EditingStyle* style, EditingState* e
ditingState) |
| 280 { | 280 { |
| 281 applyCommandToComposite(ApplyStyleCommand::create(document(), style, EditAct
ionChangeAttributes), editingState); | 281 applyCommandToComposite(ApplyStyleCommand::create(document(), style, EditAct
ionChangeAttributes), editingState); |
| 282 } | 282 } |
| 283 | 283 |
| 284 void CompositeEditCommand::applyStyle(const EditingStyle* style, const Position&
start, const Position& end, EditingState* editingState) | 284 void CompositeEditCommand::applyStyle(const EditingStyle* style, const Position&
start, const Position& end, EditingState* editingState) |
| 285 { | 285 { |
| 286 applyCommandToComposite(ApplyStyleCommand::create(document(), style, start,
end), editingState); | 286 applyCommandToComposite(ApplyStyleCommand::create(document(), style, start,
end), editingState); |
| 287 } | 287 } |
| 288 | 288 |
| 289 void CompositeEditCommand::applyStyledElement(PassRefPtrWillBeRawPtr<Element> el
ement, EditingState* editingState) | 289 void CompositeEditCommand::applyStyledElement(RawPtr<Element> element, EditingSt
ate* editingState) |
| 290 { | 290 { |
| 291 applyCommandToComposite(ApplyStyleCommand::create(element, false), editingSt
ate); | 291 applyCommandToComposite(ApplyStyleCommand::create(element, false), editingSt
ate); |
| 292 } | 292 } |
| 293 | 293 |
| 294 void CompositeEditCommand::removeStyledElement(PassRefPtrWillBeRawPtr<Element> e
lement, EditingState* editingState) | 294 void CompositeEditCommand::removeStyledElement(RawPtr<Element> element, EditingS
tate* editingState) |
| 295 { | 295 { |
| 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 ASSERT(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(PassRefPtrWillBeRawPtr<Node> insertC
hild, PassRefPtrWillBeRawPtr<Node> refChild, EditingState* editingState, ShouldA
ssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable) | 321 void CompositeEditCommand::insertNodeBefore(RawPtr<Node> insertChild, RawPtr<Nod
e> refChild, EditingState* editingState, ShouldAssumeContentIsAlwaysEditable sho
uldAssumeContentIsAlwaysEditable) |
| 322 { | 322 { |
| 323 ASSERT(document().body() != refChild); | 323 ASSERT(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(PassRefPtrWillBeRawPtr<Node> insertCh
ild, PassRefPtrWillBeRawPtr<Node> refChild, EditingState* editingState) | 328 void CompositeEditCommand::insertNodeAfter(RawPtr<Node> insertChild, RawPtr<Node
> refChild, EditingState* editingState) |
| 329 { | 329 { |
| 330 ASSERT(insertChild); | 330 ASSERT(insertChild); |
| 331 ASSERT(refChild); | 331 ASSERT(refChild); |
| 332 ASSERT(document().body() != refChild); | 332 ASSERT(document().body() != refChild); |
| 333 ContainerNode* parent = refChild->parentNode(); | 333 ContainerNode* parent = refChild->parentNode(); |
| 334 ASSERT(parent); | 334 ASSERT(parent); |
| 335 ASSERT(!parent->isShadowRoot()); | 335 ASSERT(!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 ASSERT(refChild->nextSibling()); |
| 340 insertNodeBefore(insertChild, refChild->nextSibling(), editingState); | 340 insertNodeBefore(insertChild, refChild->nextSibling(), editingState); |
| 341 } | 341 } |
| 342 } | 342 } |
| 343 | 343 |
| 344 void CompositeEditCommand::insertNodeAt(PassRefPtrWillBeRawPtr<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(); |
| 350 Node* refChild = p.anchorNode(); | 350 Node* refChild = p.anchorNode(); |
| 351 int offset = p.offsetInContainerNode(); | 351 int offset = p.offsetInContainerNode(); |
| 352 | 352 |
| 353 if (canHaveChildrenForEditing(refChild)) { | 353 if (canHaveChildrenForEditing(refChild)) { |
| 354 Node* child = refChild->firstChild(); | 354 Node* child = refChild->firstChild(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 365 | 365 |
| 366 // Mutation events (bug 22634) from the text node insertion may have rem
oved the refChild | 366 // Mutation events (bug 22634) from the text node insertion may have rem
oved the refChild |
| 367 if (!refChild->inDocument()) | 367 if (!refChild->inDocument()) |
| 368 return; | 368 return; |
| 369 insertNodeBefore(insertChild, refChild, editingState); | 369 insertNodeBefore(insertChild, refChild, editingState); |
| 370 } else { | 370 } else { |
| 371 insertNodeAfter(insertChild, refChild, editingState); | 371 insertNodeAfter(insertChild, refChild, editingState); |
| 372 } | 372 } |
| 373 } | 373 } |
| 374 | 374 |
| 375 void CompositeEditCommand::appendNode(PassRefPtrWillBeRawPtr<Node> node, PassRef
PtrWillBeRawPtr<ContainerNode> parent, EditingState* editingState) | 375 void CompositeEditCommand::appendNode(RawPtr<Node> node, RawPtr<ContainerNode> p
arent, EditingState* editingState) |
| 376 { | 376 { |
| 377 // When cloneParagraphUnderNewElement() clones the fallback content | 377 // When cloneParagraphUnderNewElement() clones the fallback content |
| 378 // of an OBJECT element, the ASSERT below may fire since the return | 378 // of an OBJECT element, the ASSERT below may fire since the return |
| 379 // value of canHaveChildrenForEditing is not reliable until the layout | 379 // value of canHaveChildrenForEditing is not reliable until the layout |
| 380 // object of the OBJECT is created. Hence we ignore this check for OBJECTs. | 380 // object of the OBJECT is created. Hence we ignore this check for OBJECTs. |
| 381 // TODO(yosin): We should move following |ABORT_EDITING_COMMAND_IF|s to | 381 // TODO(yosin): We should move following |ABORT_EDITING_COMMAND_IF|s to |
| 382 // |AppendNodeCommand|. | 382 // |AppendNodeCommand|. |
| 383 // TODO(yosin): We should get rid of |canHaveChildrenForEditing()|, since | 383 // TODO(yosin): We should get rid of |canHaveChildrenForEditing()|, since |
| 384 // |cloneParagraphUnderNewElement()| attempt to clone non-well-formed HTML, | 384 // |cloneParagraphUnderNewElement()| attempt to clone non-well-formed HTML, |
| 385 // produced by JavaScript. | 385 // produced by JavaScript. |
| 386 ABORT_EDITING_COMMAND_IF(!canHaveChildrenForEditing(parent.get()) | 386 ABORT_EDITING_COMMAND_IF(!canHaveChildrenForEditing(parent.get()) |
| 387 && !(parent->isElementNode() && toElement(parent.get())->tagQName() == o
bjectTag)); | 387 && !(parent->isElementNode() && toElement(parent.get())->tagQName() == o
bjectTag)); |
| 388 ABORT_EDITING_COMMAND_IF(!parent->hasEditableStyle() && parent->inActiveDocu
ment()); | 388 ABORT_EDITING_COMMAND_IF(!parent->hasEditableStyle() && parent->inActiveDocu
ment()); |
| 389 applyCommandToComposite(AppendNodeCommand::create(parent, node), editingStat
e); | 389 applyCommandToComposite(AppendNodeCommand::create(parent, node), editingStat
e); |
| 390 } | 390 } |
| 391 | 391 |
| 392 void CompositeEditCommand::removeChildrenInRange(PassRefPtrWillBeRawPtr<Node> no
de, unsigned from, unsigned to, EditingState* editingState) | 392 void CompositeEditCommand::removeChildrenInRange(RawPtr<Node> node, unsigned fro
m, unsigned to, EditingState* editingState) |
| 393 { | 393 { |
| 394 WillBeHeapVector<RefPtrWillBeMember<Node>> children; | 394 HeapVector<Member<Node>> children; |
| 395 Node* child = NodeTraversal::childAt(*node, from); | 395 Node* child = NodeTraversal::childAt(*node, from); |
| 396 for (unsigned i = from; child && i < to; i++, child = child->nextSibling()) | 396 for (unsigned i = from; child && i < to; i++, child = child->nextSibling()) |
| 397 children.append(child); | 397 children.append(child); |
| 398 | 398 |
| 399 size_t size = children.size(); | 399 size_t size = children.size(); |
| 400 for (size_t i = 0; i < size; ++i) { | 400 for (size_t i = 0; i < size; ++i) { |
| 401 removeNode(children[i].release(), editingState); | 401 removeNode(children[i].release(), editingState); |
| 402 if (editingState->isAborted()) | 402 if (editingState->isAborted()) |
| 403 return; | 403 return; |
| 404 } | 404 } |
| 405 } | 405 } |
| 406 | 406 |
| 407 void CompositeEditCommand::removeNode(PassRefPtrWillBeRawPtr<Node> node, Editing
State* editingState, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAl
waysEditable) | 407 void CompositeEditCommand::removeNode(RawPtr<Node> node, EditingState* editingSt
ate, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable) |
| 408 { | 408 { |
| 409 if (!node || !node->nonShadowBoundaryParentNode()) | 409 if (!node || !node->nonShadowBoundaryParentNode()) |
| 410 return; | 410 return; |
| 411 ABORT_EDITING_COMMAND_IF(!node->document().frame()); | 411 ABORT_EDITING_COMMAND_IF(!node->document().frame()); |
| 412 applyCommandToComposite(RemoveNodeCommand::create(node, shouldAssumeContentI
sAlwaysEditable), editingState); | 412 applyCommandToComposite(RemoveNodeCommand::create(node, shouldAssumeContentI
sAlwaysEditable), editingState); |
| 413 } | 413 } |
| 414 | 414 |
| 415 void CompositeEditCommand::removeNodePreservingChildren(PassRefPtrWillBeRawPtr<N
ode> node, EditingState* editingState, ShouldAssumeContentIsAlwaysEditable shoul
dAssumeContentIsAlwaysEditable) | 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(PassRefPtrWillBeRawPtr<No
de> node, EditingState* editingState, Node* excludeNode) | 421 void CompositeEditCommand::removeNodeAndPruneAncestors(RawPtr<Node> node, Editin
gState* editingState, Node* excludeNode) |
| 422 { | 422 { |
| 423 ASSERT(node.get() != excludeNode); | 423 ASSERT(node.get() != excludeNode); |
| 424 RefPtrWillBeRawPtr<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, PassRefPtrWillBeRawPtr<Element> prpNewParent, EditingState* ed
itingState) | 431 void CompositeEditCommand::moveRemainingSiblingsToNewParent(Node* node, Node* pa
stLastNodeToMove, RawPtr<Element> prpNewParent, EditingState* editingState) |
| 432 { | 432 { |
| 433 NodeVector nodesToRemove; | 433 NodeVector nodesToRemove; |
| 434 RefPtrWillBeRawPtr<Element> newParent = prpNewParent; | 434 RawPtr<Element> newParent = prpNewParent; |
| 435 | 435 |
| 436 for (; node && node != pastLastNodeToMove; node = node->nextSibling()) | 436 for (; node && node != pastLastNodeToMove; node = node->nextSibling()) |
| 437 nodesToRemove.append(node); | 437 nodesToRemove.append(node); |
| 438 | 438 |
| 439 for (unsigned i = 0; i < nodesToRemove.size(); i++) { | 439 for (unsigned i = 0; i < nodesToRemove.size(); i++) { |
| 440 removeNode(nodesToRemove[i], editingState); | 440 removeNode(nodesToRemove[i], editingState); |
| 441 if (editingState->isAborted()) | 441 if (editingState->isAborted()) |
| 442 return; | 442 return; |
| 443 appendNode(nodesToRemove[i], newParent, editingState); | 443 appendNode(nodesToRemove[i], newParent, editingState); |
| 444 if (editingState->isAborted()) | 444 if (editingState->isAborted()) |
| 445 return; | 445 return; |
| 446 } | 446 } |
| 447 } | 447 } |
| 448 | 448 |
| 449 void CompositeEditCommand::updatePositionForNodeRemovalPreservingChildren(Positi
on& position, Node& node) | 449 void CompositeEditCommand::updatePositionForNodeRemovalPreservingChildren(Positi
on& position, Node& node) |
| 450 { | 450 { |
| 451 int offset = position.isOffsetInAnchor() ? position.offsetInContainerNode()
: 0; | 451 int offset = position.isOffsetInAnchor() ? position.offsetInContainerNode()
: 0; |
| 452 updatePositionForNodeRemoval(position, node); | 452 updatePositionForNodeRemoval(position, node); |
| 453 if (offset == 0) | 453 if (offset == 0) |
| 454 return; | 454 return; |
| 455 position = Position(position.computeContainerNode(), offset); | 455 position = Position(position.computeContainerNode(), offset); |
| 456 } | 456 } |
| 457 | 457 |
| 458 HTMLSpanElement* CompositeEditCommand::replaceElementWithSpanPreservingChildrenA
ndAttributes(PassRefPtrWillBeRawPtr<HTMLElement> node) | 458 HTMLSpanElement* CompositeEditCommand::replaceElementWithSpanPreservingChildrenA
ndAttributes(RawPtr<HTMLElement> node) |
| 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 RefPtrWillBeRawPtr<ReplaceNodeWithSpanCommand> command = ReplaceNodeWithSpan
Command::create(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()->inDocument()); | 469 ASSERT(command->spanElement()->inDocument()); |
| 470 return command->spanElement(); | 470 return command->spanElement(); |
| 471 } | 471 } |
| 472 | 472 |
| 473 void CompositeEditCommand::prune(PassRefPtrWillBeRawPtr<Node> node, EditingState
* editingState, Node* excludeNode) | 473 void CompositeEditCommand::prune(RawPtr<Node> node, EditingState* editingState,
Node* excludeNode) |
| 474 { | 474 { |
| 475 if (RefPtrWillBeRawPtr<Node> highestNodeToRemove = highestNodeToRemoveInPrun
ing(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(PassRefPtrWillBeRawPtr<Text> node, unsi
gned 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(PassRefPtrWillBeRawPtr<Element> element,
PassRefPtrWillBeRawPtr<Node> atChild) | 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(PassRefPtrWillBeRawPtr<Element
> prpFirst, PassRefPtrWillBeRawPtr<Element> prpSecond, EditingState* editingStat
e) | 491 void CompositeEditCommand::mergeIdenticalElements(RawPtr<Element> prpFirst, RawP
tr<Element> prpSecond, EditingState* editingState) |
| 492 { | 492 { |
| 493 RefPtrWillBeRawPtr<Element> first = prpFirst; | 493 RawPtr<Element> first = prpFirst; |
| 494 RefPtrWillBeRawPtr<Element> second = prpSecond; | 494 RawPtr<Element> second = prpSecond; |
| 495 ASSERT(!first->isDescendantOf(second.get()) && second != first); | 495 ASSERT(!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 } |
| 506 | 506 |
| 507 void CompositeEditCommand::wrapContentsInDummySpan(PassRefPtrWillBeRawPtr<Elemen
t> element) | 507 void CompositeEditCommand::wrapContentsInDummySpan(RawPtr<Element> element) |
| 508 { | 508 { |
| 509 // WrapContentsInDummySpanCommand is never aborted. | 509 // WrapContentsInDummySpanCommand is never aborted. |
| 510 applyCommandToComposite(WrapContentsInDummySpanCommand::create(element), ASS
ERT_NO_EDITING_ABORT); | 510 applyCommandToComposite(WrapContentsInDummySpanCommand::create(element), ASS
ERT_NO_EDITING_ABORT); |
| 511 } | 511 } |
| 512 | 512 |
| 513 void CompositeEditCommand::splitTextNodeContainingElement(PassRefPtrWillBeRawPtr
<Text> text, unsigned offset) | 513 void CompositeEditCommand::splitTextNodeContainingElement(RawPtr<Text> text, uns
igned offset) |
| 514 { | 514 { |
| 515 // SplitTextNodeContainingElementCommand is never aborted. | 515 // SplitTextNodeContainingElementCommand is never aborted. |
| 516 applyCommandToComposite(SplitTextNodeContainingElementCommand::create(text,
offset), ASSERT_NO_EDITING_ABORT); | 516 applyCommandToComposite(SplitTextNodeContainingElementCommand::create(text,
offset), ASSERT_NO_EDITING_ABORT); |
| 517 } | 517 } |
| 518 | 518 |
| 519 void CompositeEditCommand::insertTextIntoNode(PassRefPtrWillBeRawPtr<Text> node,
unsigned offset, const String& text) | 519 void CompositeEditCommand::insertTextIntoNode(RawPtr<Text> node, unsigned offset
, const String& text) |
| 520 { | 520 { |
| 521 // InsertIntoTextNodeCommand is never aborted. | 521 // InsertIntoTextNodeCommand is never aborted. |
| 522 if (!text.isEmpty()) | 522 if (!text.isEmpty()) |
| 523 applyCommandToComposite(InsertIntoTextNodeCommand::create(node, offset,
text), ASSERT_NO_EDITING_ABORT); | 523 applyCommandToComposite(InsertIntoTextNodeCommand::create(node, offset,
text), ASSERT_NO_EDITING_ABORT); |
| 524 } | 524 } |
| 525 | 525 |
| 526 void CompositeEditCommand::deleteTextFromNode(PassRefPtrWillBeRawPtr<Text> node,
unsigned offset, unsigned count) | 526 void CompositeEditCommand::deleteTextFromNode(RawPtr<Text> node, unsigned offset
, unsigned count) |
| 527 { | 527 { |
| 528 // DeleteFromTextNodeCommand is never aborted. | 528 // DeleteFromTextNodeCommand is never aborted. |
| 529 applyCommandToComposite(DeleteFromTextNodeCommand::create(node, offset, coun
t), ASSERT_NO_EDITING_ABORT); | 529 applyCommandToComposite(DeleteFromTextNodeCommand::create(node, offset, coun
t), ASSERT_NO_EDITING_ABORT); |
| 530 } | 530 } |
| 531 | 531 |
| 532 void CompositeEditCommand::replaceTextInNode(PassRefPtrWillBeRawPtr<Text> prpNod
e, unsigned offset, unsigned count, const String& replacementText) | 532 void CompositeEditCommand::replaceTextInNode(RawPtr<Text> prpNode, unsigned offs
et, unsigned count, const String& replacementText) |
| 533 { | 533 { |
| 534 RefPtrWillBeRawPtr<Text> node(prpNode); | 534 RawPtr<Text> node(prpNode); |
| 535 // DeleteFromTextNodeCommand and InsertIntoTextNodeCommand are never | 535 // DeleteFromTextNodeCommand and InsertIntoTextNodeCommand are never |
| 536 // aborted. | 536 // aborted. |
| 537 applyCommandToComposite(DeleteFromTextNodeCommand::create(node, offset, coun
t), ASSERT_NO_EDITING_ABORT); | 537 applyCommandToComposite(DeleteFromTextNodeCommand::create(node, offset, coun
t), ASSERT_NO_EDITING_ABORT); |
| 538 if (!replacementText.isEmpty()) | 538 if (!replacementText.isEmpty()) |
| 539 applyCommandToComposite(InsertIntoTextNodeCommand::create(node, offset,
replacementText), ASSERT_NO_EDITING_ABORT); | 539 applyCommandToComposite(InsertIntoTextNodeCommand::create(node, offset,
replacementText), ASSERT_NO_EDITING_ABORT); |
| 540 } | 540 } |
| 541 | 541 |
| 542 Position CompositeEditCommand::replaceSelectedTextInNode(const String& text) | 542 Position CompositeEditCommand::replaceSelectedTextInNode(const String& text) |
| 543 { | 543 { |
| 544 Position start = endingSelection().start(); | 544 Position start = endingSelection().start(); |
| 545 Position end = endingSelection().end(); | 545 Position end = endingSelection().end(); |
| 546 if (start.computeContainerNode() != end.computeContainerNode() || !start.com
puteContainerNode()->isTextNode() || isTabHTMLSpanElementTextNode(start.computeC
ontainerNode())) | 546 if (start.computeContainerNode() != end.computeContainerNode() || !start.com
puteContainerNode()->isTextNode() || isTabHTMLSpanElementTextNode(start.computeC
ontainerNode())) |
| 547 return Position(); | 547 return Position(); |
| 548 | 548 |
| 549 RefPtrWillBeRawPtr<Text> textNode = toText(start.computeContainerNode()); | 549 RawPtr<Text> textNode = toText(start.computeContainerNode()); |
| 550 replaceTextInNode(textNode, start.offsetInContainerNode(), end.offsetInConta
inerNode() - start.offsetInContainerNode(), text); | 550 replaceTextInNode(textNode, start.offsetInContainerNode(), end.offsetInConta
inerNode() - start.offsetInContainerNode(), text); |
| 551 | 551 |
| 552 return Position(textNode.release(), start.offsetInContainerNode() + text.len
gth()); | 552 return Position(textNode.release(), start.offsetInContainerNode() + text.len
gth()); |
| 553 } | 553 } |
| 554 | 554 |
| 555 static void copyMarkerTypesAndDescriptions(const DocumentMarkerVector& markerPoi
nters, Vector<DocumentMarker::MarkerType>& types, Vector<String>& descriptions) | 555 static void copyMarkerTypesAndDescriptions(const DocumentMarkerVector& markerPoi
nters, Vector<DocumentMarker::MarkerType>& types, Vector<String>& descriptions) |
| 556 { | 556 { |
| 557 size_t arraySize = markerPointers.size(); | 557 size_t arraySize = markerPointers.size(); |
| 558 types.reserveCapacity(arraySize); | 558 types.reserveCapacity(arraySize); |
| 559 descriptions.reserveCapacity(arraySize); | 559 descriptions.reserveCapacity(arraySize); |
| 560 for (const auto& markerPointer : markerPointers) { | 560 for (const auto& markerPointer : markerPointers) { |
| 561 types.append(markerPointer->type()); | 561 types.append(markerPointer->type()); |
| 562 descriptions.append(markerPointer->description()); | 562 descriptions.append(markerPointer->description()); |
| 563 } | 563 } |
| 564 } | 564 } |
| 565 | 565 |
| 566 void CompositeEditCommand::replaceTextInNodePreservingMarkers(PassRefPtrWillBeRa
wPtr<Text> prpNode, unsigned offset, unsigned count, const String& replacementTe
xt) | 566 void CompositeEditCommand::replaceTextInNodePreservingMarkers(RawPtr<Text> prpNo
de, unsigned offset, unsigned count, const String& replacementText) |
| 567 { | 567 { |
| 568 RefPtrWillBeRawPtr<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 ASSERT(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]); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 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 } |
| 611 | 611 |
| 612 void CompositeEditCommand::insertNodeAtTabSpanPosition(PassRefPtrWillBeRawPtr<No
de> node, const Position& pos, EditingState* editingState) | 612 void CompositeEditCommand::insertNodeAtTabSpanPosition(RawPtr<Node> node, const
Position& pos, EditingState* editingState) |
| 613 { | 613 { |
| 614 // insert node before, after, or at split of tab span | 614 // insert node before, after, or at split of tab span |
| 615 insertNodeAt(node, positionOutsideTabSpan(pos), editingState); | 615 insertNodeAt(node, positionOutsideTabSpan(pos), editingState); |
| 616 } | 616 } |
| 617 | 617 |
| 618 void CompositeEditCommand::deleteSelection(EditingState* editingState, bool smar
tDelete, bool mergeBlocksAfterDelete, bool expandForSpecialElements, bool saniti
zeMarkup) | 618 void CompositeEditCommand::deleteSelection(EditingState* editingState, bool smar
tDelete, bool mergeBlocksAfterDelete, bool expandForSpecialElements, bool saniti
zeMarkup) |
| 619 { | 619 { |
| 620 if (endingSelection().isRange()) | 620 if (endingSelection().isRange()) |
| 621 applyCommandToComposite(DeleteSelectionCommand::create(document(), smart
Delete, mergeBlocksAfterDelete, expandForSpecialElements, sanitizeMarkup), editi
ngState); | 621 applyCommandToComposite(DeleteSelectionCommand::create(document(), smart
Delete, mergeBlocksAfterDelete, expandForSpecialElements, sanitizeMarkup), editi
ngState); |
| 622 } | 622 } |
| 623 | 623 |
| 624 void CompositeEditCommand::deleteSelection(const VisibleSelection &selection, Ed
itingState* editingState, bool smartDelete, bool mergeBlocksAfterDelete, bool ex
pandForSpecialElements, bool sanitizeMarkup) | 624 void CompositeEditCommand::deleteSelection(const VisibleSelection &selection, Ed
itingState* editingState, bool smartDelete, bool mergeBlocksAfterDelete, bool ex
pandForSpecialElements, bool sanitizeMarkup) |
| 625 { | 625 { |
| 626 if (selection.isRange()) | 626 if (selection.isRange()) |
| 627 applyCommandToComposite(DeleteSelectionCommand::create(selection, smartD
elete, mergeBlocksAfterDelete, expandForSpecialElements, sanitizeMarkup), editin
gState); | 627 applyCommandToComposite(DeleteSelectionCommand::create(selection, smartD
elete, mergeBlocksAfterDelete, expandForSpecialElements, sanitizeMarkup), editin
gState); |
| 628 } | 628 } |
| 629 | 629 |
| 630 void CompositeEditCommand::removeCSSProperty(PassRefPtrWillBeRawPtr<Element> ele
ment, CSSPropertyID property) | 630 void CompositeEditCommand::removeCSSProperty(RawPtr<Element> element, CSSPropert
yID property) |
| 631 { | 631 { |
| 632 // RemoveCSSPropertyCommand is never aborted. | 632 // RemoveCSSPropertyCommand is never aborted. |
| 633 applyCommandToComposite(RemoveCSSPropertyCommand::create(document(), element
, property), ASSERT_NO_EDITING_ABORT); | 633 applyCommandToComposite(RemoveCSSPropertyCommand::create(document(), element
, property), ASSERT_NO_EDITING_ABORT); |
| 634 } | 634 } |
| 635 | 635 |
| 636 void CompositeEditCommand::removeElementAttribute(PassRefPtrWillBeRawPtr<Element
> element, const QualifiedName& attribute) | 636 void CompositeEditCommand::removeElementAttribute(RawPtr<Element> element, const
QualifiedName& attribute) |
| 637 { | 637 { |
| 638 setNodeAttribute(element, attribute, AtomicString()); | 638 setNodeAttribute(element, attribute, AtomicString()); |
| 639 } | 639 } |
| 640 | 640 |
| 641 void CompositeEditCommand::setNodeAttribute(PassRefPtrWillBeRawPtr<Element> elem
ent, const QualifiedName& attribute, const AtomicString& value) | 641 void CompositeEditCommand::setNodeAttribute(RawPtr<Element> element, const Quali
fiedName& attribute, const AtomicString& value) |
| 642 { | 642 { |
| 643 // SetNodeAttributeCommand is never aborted. | 643 // SetNodeAttributeCommand is never aborted. |
| 644 applyCommandToComposite(SetNodeAttributeCommand::create(element, attribute,
value), ASSERT_NO_EDITING_ABORT); | 644 applyCommandToComposite(SetNodeAttributeCommand::create(element, attribute,
value), ASSERT_NO_EDITING_ABORT); |
| 645 } | 645 } |
| 646 | 646 |
| 647 static inline bool containsOnlyWhitespace(const String& text) | 647 static inline bool containsOnlyWhitespace(const String& text) |
| 648 { | 648 { |
| 649 for (unsigned i = 0; i < text.length(); ++i) { | 649 for (unsigned i = 0; i < text.length(); ++i) { |
| 650 if (!isWhitespace(text[i])) | 650 if (!isWhitespace(text[i])) |
| 651 return false; | 651 return false; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 688 String text = toText(node)->data(); | 688 String text = toText(node)->data(); |
| 689 if (!isWhitespace(text[offset])) { | 689 if (!isWhitespace(text[offset])) { |
| 690 offset--; | 690 offset--; |
| 691 if (offset < 0 || !isWhitespace(text[offset])) | 691 if (offset < 0 || !isWhitespace(text[offset])) |
| 692 return; | 692 return; |
| 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(PassRefPtrWillBeRa
wPtr<Text> prpTextNode, int startOffset, int endOffset) | 698 void CompositeEditCommand::rebalanceWhitespaceOnTextSubstring(RawPtr<Text> prpTe
xtNode, int startOffset, int endOffset) |
| 699 { | 699 { |
| 700 RefPtrWillBeRawPtr<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 ASSERT(!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; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 771 { | 771 { |
| 772 VisibleSelection selection = endingSelection(); | 772 VisibleSelection selection = endingSelection(); |
| 773 if (selection.isNone()) | 773 if (selection.isNone()) |
| 774 return; | 774 return; |
| 775 | 775 |
| 776 rebalanceWhitespaceAt(selection.start()); | 776 rebalanceWhitespaceAt(selection.start()); |
| 777 if (selection.isRange()) | 777 if (selection.isRange()) |
| 778 rebalanceWhitespaceAt(selection.end()); | 778 rebalanceWhitespaceAt(selection.end()); |
| 779 } | 779 } |
| 780 | 780 |
| 781 void CompositeEditCommand::deleteInsignificantText(PassRefPtrWillBeRawPtr<Text>
textNode, unsigned start, unsigned end) | 781 void CompositeEditCommand::deleteInsignificantText(RawPtr<Text> textNode, unsign
ed start, unsigned end) |
| 782 { | 782 { |
| 783 if (!textNode || start >= end) | 783 if (!textNode || start >= end) |
| 784 return; | 784 return; |
| 785 | 785 |
| 786 document().updateLayout(); | 786 document().updateLayout(); |
| 787 | 787 |
| 788 LayoutText* textLayoutObject = textNode->layoutObject(); | 788 LayoutText* textLayoutObject = textNode->layoutObject(); |
| 789 if (!textLayoutObject) | 789 if (!textLayoutObject) |
| 790 return; | 790 return; |
| 791 | 791 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 |
| 868 if (comparePositions(start, end) >= 0) | 868 if (comparePositions(start, end) >= 0) |
| 869 return; | 869 return; |
| 870 | 870 |
| 871 WillBeHeapVector<RefPtrWillBeMember<Text>> nodes; | 871 HeapVector<Member<Text>> nodes; |
| 872 for (Node& node : NodeTraversal::startsAt(start.anchorNode())) { | 872 for (Node& node : NodeTraversal::startsAt(start.anchorNode())) { |
| 873 if (node.isTextNode()) | 873 if (node.isTextNode()) |
| 874 nodes.append(toText(&node)); | 874 nodes.append(toText(&node)); |
| 875 if (&node == end.anchorNode()) | 875 if (&node == end.anchorNode()) |
| 876 break; | 876 break; |
| 877 } | 877 } |
| 878 | 878 |
| 879 for (const auto& node : nodes) { | 879 for (const auto& node : nodes) { |
| 880 Text* textNode = node.get(); | 880 Text* textNode = node.get(); |
| 881 int startOffset = textNode == start.anchorNode() ? start.computeOffsetIn
ContainerNode() : 0; | 881 int startOffset = textNode == start.anchorNode() ? start.computeOffsetIn
ContainerNode() : 0; |
| 882 int endOffset = textNode == end.anchorNode() ? end.computeOffsetInContai
nerNode() : static_cast<int>(textNode->length()); | 882 int endOffset = textNode == end.anchorNode() ? end.computeOffsetInContai
nerNode() : static_cast<int>(textNode->length()); |
| 883 deleteInsignificantText(textNode, startOffset, endOffset); | 883 deleteInsignificantText(textNode, startOffset, endOffset); |
| 884 } | 884 } |
| 885 } | 885 } |
| 886 | 886 |
| 887 void CompositeEditCommand::deleteInsignificantTextDownstream(const Position& pos
) | 887 void CompositeEditCommand::deleteInsignificantTextDownstream(const Position& pos
) |
| 888 { | 888 { |
| 889 Position end = mostForwardCaretPosition(nextPositionOf(createVisiblePosition
(pos, VP_DEFAULT_AFFINITY)).deepEquivalent()); | 889 Position end = mostForwardCaretPosition(nextPositionOf(createVisiblePosition
(pos, VP_DEFAULT_AFFINITY)).deepEquivalent()); |
| 890 deleteInsignificantText(pos, end); | 890 deleteInsignificantText(pos, end); |
| 891 } | 891 } |
| 892 | 892 |
| 893 PassRefPtrWillBeRawPtr<HTMLBRElement> CompositeEditCommand::appendBlockPlacehold
er(PassRefPtrWillBeRawPtr<Element> 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 ASSERT(container->layoutObject()); |
| 902 | 902 |
| 903 RefPtrWillBeRawPtr<HTMLBRElement> placeholder = HTMLBRElement::create(docume
nt()); | 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 PassRefPtrWillBeRawPtr<HTMLBRElement> CompositeEditCommand::insertBlockPlacehold
er(const Position& 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 ASSERT(pos.anchorNode()->layoutObject()); |
| 917 | 917 |
| 918 RefPtrWillBeRawPtr<HTMLBRElement> placeholder = HTMLBRElement::create(docume
nt()); | 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 PassRefPtrWillBeRawPtr<HTMLBRElement> CompositeEditCommand::addBlockPlaceholderI
fNeeded(Element* container, EditingState* editingState) | 925 RawPtr<HTMLBRElement> CompositeEditCommand::addBlockPlaceholderIfNeeded(Element*
container, EditingState* editingState) |
| 926 { | 926 { |
| 927 if (!container) | 927 if (!container) |
| 928 return nullptr; | 928 return nullptr; |
| 929 | 929 |
| 930 document().updateLayoutIgnorePendingStylesheets(); | 930 document().updateLayoutIgnorePendingStylesheets(); |
| 931 | 931 |
| 932 LayoutObject* layoutObject = container->layoutObject(); | 932 LayoutObject* layoutObject = container->layoutObject(); |
| 933 if (!layoutObject || !layoutObject->isLayoutBlockFlow()) | 933 if (!layoutObject || !layoutObject->isLayoutBlockFlow()) |
| 934 return nullptr; | 934 return nullptr; |
| 935 | 935 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 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 PassRefPtrWillBeRawPtr<HTMLElement> CompositeEditCommand::insertNewDefaultParagr
aphElementAt(const Position& position, EditingState* editingState) | 960 RawPtr<HTMLElement> CompositeEditCommand::insertNewDefaultParagraphElementAt(con
st Position& position, EditingState* editingState) |
| 961 { | 961 { |
| 962 RefPtrWillBeRawPtr<HTMLElement> paragraphElement = createDefaultParagraphEle
ment(document()); | 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 PassRefPtrWillBeRawPtr<HTMLElement> CompositeEditCommand::moveParagraphContentsT
oNewBlockIfNecessary(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 ASSERT(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; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1010 return nullptr; | 1010 return nullptr; |
| 1011 } else if (isEndOfEditableOrNonEditableContent(visibleEnd)) { | 1011 } else if (isEndOfEditableOrNonEditableContent(visibleEnd)) { |
| 1012 // At the end of the editable region. We can bail here as well. | 1012 // At the end of the editable region. We can bail here as well. |
| 1013 return nullptr; | 1013 return nullptr; |
| 1014 } | 1014 } |
| 1015 } | 1015 } |
| 1016 | 1016 |
| 1017 if (visibleParagraphEnd.isNull()) | 1017 if (visibleParagraphEnd.isNull()) |
| 1018 return nullptr; | 1018 return nullptr; |
| 1019 | 1019 |
| 1020 RefPtrWillBeRawPtr<HTMLElement> newBlock = insertNewDefaultParagraphElementA
t(upstreamStart, editingState); | 1020 RawPtr<HTMLElement> newBlock = insertNewDefaultParagraphElementAt(upstreamSt
art, editingState); |
| 1021 if (editingState->isAborted()) | 1021 if (editingState->isAborted()) |
| 1022 return nullptr; | 1022 return nullptr; |
| 1023 | 1023 |
| 1024 bool endWasBr = isHTMLBRElement(*visibleParagraphEnd.deepEquivalent().anchor
Node()); | 1024 bool endWasBr = isHTMLBRElement(*visibleParagraphEnd.deepEquivalent().anchor
Node()); |
| 1025 | 1025 |
| 1026 // Inserting default paragraph element can change visible position. We | 1026 // Inserting default paragraph element can change visible position. We |
| 1027 // should update visible positions before use them. | 1027 // should update visible positions before use them. |
| 1028 visiblePos = createVisiblePosition(pos, VP_DEFAULT_AFFINITY); | 1028 visiblePos = createVisiblePosition(pos, VP_DEFAULT_AFFINITY); |
| 1029 visibleParagraphStart = startOfParagraph(visiblePos); | 1029 visibleParagraphStart = startOfParagraph(visiblePos); |
| 1030 visibleParagraphEnd = endOfParagraph(visiblePos); | 1030 visibleParagraphEnd = endOfParagraph(visiblePos); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 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 ASSERT(comparePositions(start, end) <= 0); |
| 1066 ASSERT(passedOuterNode); | 1066 ASSERT(passedOuterNode); |
| 1067 ASSERT(blockElement); | 1067 ASSERT(blockElement); |
| 1068 | 1068 |
| 1069 // First we clone the outerNode | 1069 // First we clone the outerNode |
| 1070 RefPtrWillBeRawPtr<Node> lastNode = nullptr; | 1070 RawPtr<Node> lastNode = nullptr; |
| 1071 RefPtrWillBeRawPtr<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); |
| 1078 if (editingState->isAborted()) | 1078 if (editingState->isAborted()) |
| 1079 return; | 1079 return; |
| 1080 } | 1080 } |
| 1081 | 1081 |
| 1082 if (start.anchorNode() != outerNode && lastNode->isElementNode() && start.an
chorNode()->isDescendantOf(outerNode.get())) { | 1082 if (start.anchorNode() != outerNode && lastNode->isElementNode() && start.an
chorNode()->isDescendantOf(outerNode.get())) { |
| 1083 WillBeHeapVector<RefPtrWillBeMember<Node>> ancestors; | 1083 HeapVector<Member<Node>> ancestors; |
| 1084 | 1084 |
| 1085 // Insert each node from innerNode to outerNode (excluded) in a list. | 1085 // Insert each node from innerNode to outerNode (excluded) in a list. |
| 1086 for (Node* n = start.anchorNode(); n && n != outerNode; n = n->parentNod
e()) | 1086 for (Node* n = start.anchorNode(); n && n != outerNode; n = n->parentNod
e()) |
| 1087 ancestors.append(n); | 1087 ancestors.append(n); |
| 1088 | 1088 |
| 1089 // Clone every node between start.anchorNode() and outerBlock. | 1089 // Clone every node between start.anchorNode() and outerBlock. |
| 1090 | 1090 |
| 1091 for (size_t i = ancestors.size(); i != 0; --i) { | 1091 for (size_t i = ancestors.size(); i != 0; --i) { |
| 1092 Node* item = ancestors[i - 1].get(); | 1092 Node* item = ancestors[i - 1].get(); |
| 1093 RefPtrWillBeRawPtr<Node> child = item->cloneNode(isDisplayInsideTabl
e(item)); | 1093 RawPtr<Node> child = item->cloneNode(isDisplayInsideTable(item)); |
| 1094 appendNode(child, toElement(lastNode), editingState); | 1094 appendNode(child, toElement(lastNode), editingState); |
| 1095 if (editingState->isAborted()) | 1095 if (editingState->isAborted()) |
| 1096 return; | 1096 return; |
| 1097 lastNode = child.release(); | 1097 lastNode = child.release(); |
| 1098 } | 1098 } |
| 1099 } | 1099 } |
| 1100 | 1100 |
| 1101 // Scripts specified in javascript protocol may remove |outerNode| | 1101 // Scripts specified in javascript protocol may remove |outerNode| |
| 1102 // during insertion, e.g. <iframe src="javascript:..."> | 1102 // during insertion, e.g. <iframe src="javascript:..."> |
| 1103 if (!outerNode->inDocument()) | 1103 if (!outerNode->inDocument()) |
| 1104 return; | 1104 return; |
| 1105 | 1105 |
| 1106 // Handle the case of paragraphs with more than one node, | 1106 // Handle the case of paragraphs with more than one node, |
| 1107 // cloning all the siblings until end.anchorNode() is reached. | 1107 // cloning all the siblings until end.anchorNode() is reached. |
| 1108 | 1108 |
| 1109 if (start.anchorNode() != end.anchorNode() && !start.anchorNode()->isDescend
antOf(end.anchorNode())) { | 1109 if (start.anchorNode() != end.anchorNode() && !start.anchorNode()->isDescend
antOf(end.anchorNode())) { |
| 1110 // If end is not a descendant of outerNode we need to | 1110 // If end is not a descendant of outerNode we need to |
| 1111 // find the first common ancestor to increase the scope | 1111 // find the first common ancestor to increase the scope |
| 1112 // of our nextSibling traversal. | 1112 // of our nextSibling traversal. |
| 1113 while (outerNode && !end.anchorNode()->isDescendantOf(outerNode.get()))
{ | 1113 while (outerNode && !end.anchorNode()->isDescendantOf(outerNode.get()))
{ |
| 1114 outerNode = outerNode->parentNode(); | 1114 outerNode = outerNode->parentNode(); |
| 1115 } | 1115 } |
| 1116 | 1116 |
| 1117 if (!outerNode) | 1117 if (!outerNode) |
| 1118 return; | 1118 return; |
| 1119 | 1119 |
| 1120 RefPtrWillBeRawPtr<Node> startNode = start.anchorNode(); | 1120 RawPtr<Node> startNode = start.anchorNode(); |
| 1121 for (RefPtrWillBeRawPtr<Node> node = NodeTraversal::nextSkippingChildren
(*startNode, outerNode.get()); node; node = NodeTraversal::nextSkippingChildren(
*node, outerNode.get())) { | 1121 for (RawPtr<Node> node = NodeTraversal::nextSkippingChildren(*startNode,
outerNode.get()); node; node = NodeTraversal::nextSkippingChildren(*node, outer
Node.get())) { |
| 1122 // Move lastNode up in the tree as much as node was moved up in the | 1122 // Move lastNode up in the tree as much as node was moved up in the |
| 1123 // tree by NodeTraversal::nextSkippingChildren, so that the relative
depth between | 1123 // tree by NodeTraversal::nextSkippingChildren, so that the relative
depth between |
| 1124 // node and the original start node is maintained in the clone. | 1124 // node and the original start node is maintained in the clone. |
| 1125 while (startNode && lastNode && startNode->parentNode() != node->par
entNode()) { | 1125 while (startNode && lastNode && startNode->parentNode() != node->par
entNode()) { |
| 1126 startNode = startNode->parentNode(); | 1126 startNode = startNode->parentNode(); |
| 1127 lastNode = lastNode->parentNode(); | 1127 lastNode = lastNode->parentNode(); |
| 1128 } | 1128 } |
| 1129 | 1129 |
| 1130 if (!lastNode || !lastNode->parentNode()) | 1130 if (!lastNode || !lastNode->parentNode()) |
| 1131 return; | 1131 return; |
| 1132 | 1132 |
| 1133 RefPtrWillBeRawPtr<Node> clonedNode = node->cloneNode(true); | 1133 RawPtr<Node> clonedNode = node->cloneNode(true); |
| 1134 insertNodeAfter(clonedNode, lastNode, editingState); | 1134 insertNodeAfter(clonedNode, lastNode, editingState); |
| 1135 if (editingState->isAborted()) | 1135 if (editingState->isAborted()) |
| 1136 return; | 1136 return; |
| 1137 lastNode = clonedNode.release(); | 1137 lastNode = clonedNode.release(); |
| 1138 if (node == end.anchorNode() || end.anchorNode()->isDescendantOf(nod
e.get())) | 1138 if (node == end.anchorNode() || end.anchorNode()->isDescendantOf(nod
e.get())) |
| 1139 break; | 1139 break; |
| 1140 } | 1140 } |
| 1141 } | 1141 } |
| 1142 } | 1142 } |
| 1143 | 1143 |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1282 VisiblePosition beforeParagraph = previousPositionOf(startOfParagraphToMove,
CannotCrossEditingBoundary); | 1282 VisiblePosition beforeParagraph = previousPositionOf(startOfParagraphToMove,
CannotCrossEditingBoundary); |
| 1283 VisiblePosition afterParagraph = nextPositionOf(endOfParagraphToMove, Cannot
CrossEditingBoundary); | 1283 VisiblePosition afterParagraph = nextPositionOf(endOfParagraphToMove, Cannot
CrossEditingBoundary); |
| 1284 | 1284 |
| 1285 // We upstream() the end and downstream() the start so that we don't include
collapsed whitespace in the move. | 1285 // We upstream() the end and downstream() the start so that we don't include
collapsed whitespace in the move. |
| 1286 // When we paste a fragment, spaces after the end and before the start are t
reated as though they were rendered. | 1286 // When we paste a fragment, spaces after the end and before the start are t
reated as though they were rendered. |
| 1287 Position start = mostForwardCaretPosition(startOfParagraphToMove.deepEquival
ent()); | 1287 Position start = mostForwardCaretPosition(startOfParagraphToMove.deepEquival
ent()); |
| 1288 Position end = mostBackwardCaretPosition(endOfParagraphToMove.deepEquivalent
()); | 1288 Position end = mostBackwardCaretPosition(endOfParagraphToMove.deepEquivalent
()); |
| 1289 | 1289 |
| 1290 // FIXME: This is an inefficient way to preserve style on nodes in the parag
raph to move. It | 1290 // FIXME: This is an inefficient way to preserve style on nodes in the parag
raph to move. It |
| 1291 // shouldn't matter though, since moved paragraphs will usually be quite sma
ll. | 1291 // shouldn't matter though, since moved paragraphs will usually be quite sma
ll. |
| 1292 RefPtrWillBeRawPtr<DocumentFragment> fragment = startOfParagraphToMove.deepE
quivalent() != endOfParagraphToMove.deepEquivalent() ? | 1292 RawPtr<DocumentFragment> fragment = startOfParagraphToMove.deepEquivalent()
!= endOfParagraphToMove.deepEquivalent() ? |
| 1293 createFragmentFromMarkup(document(), createMarkup(start.parentAnchoredEq
uivalent(), end.parentAnchoredEquivalent(), DoNotAnnotateForInterchange, Convert
BlocksToInlines::Convert, DoNotResolveURLs, constrainingAncestor), "") : nullptr
; | 1293 createFragmentFromMarkup(document(), createMarkup(start.parentAnchoredEq
uivalent(), end.parentAnchoredEquivalent(), DoNotAnnotateForInterchange, Convert
BlocksToInlines::Convert, DoNotResolveURLs, constrainingAncestor), "") : nullptr
; |
| 1294 | 1294 |
| 1295 // A non-empty paragraph's style is moved when we copy and move it. We don'
t move | 1295 // A non-empty paragraph's style is moved when we copy and move it. We don'
t move |
| 1296 // anything if we're given an empty paragraph, but an empty paragraph can ha
ve style | 1296 // anything if we're given an empty paragraph, but an empty paragraph can ha
ve style |
| 1297 // too, <div><b><br></b></div> for example. Save it so that we can preserve
it later. | 1297 // too, <div><b><br></b></div> for example. Save it so that we can preserve
it later. |
| 1298 RefPtrWillBeRawPtr<EditingStyle> styleInEmptyParagraph = nullptr; | 1298 RawPtr<EditingStyle> styleInEmptyParagraph = nullptr; |
| 1299 if (startOfParagraphToMove.deepEquivalent() == endOfParagraphToMove.deepEqui
valent() && preserveStyle) { | 1299 if (startOfParagraphToMove.deepEquivalent() == endOfParagraphToMove.deepEqui
valent() && preserveStyle) { |
| 1300 styleInEmptyParagraph = EditingStyle::create(startOfParagraphToMove.deep
Equivalent()); | 1300 styleInEmptyParagraph = EditingStyle::create(startOfParagraphToMove.deep
Equivalent()); |
| 1301 styleInEmptyParagraph->mergeTypingStyle(&document()); | 1301 styleInEmptyParagraph->mergeTypingStyle(&document()); |
| 1302 // The moved paragraph should assume the block style of the destination. | 1302 // The moved paragraph should assume the block style of the destination. |
| 1303 styleInEmptyParagraph->removeBlockProperties(); | 1303 styleInEmptyParagraph->removeBlockProperties(); |
| 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)); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1371 return; | 1371 return; |
| 1372 EphemeralRange endRange = PlainTextRange(destinationIndex + endIndex).create
RangeForSelection(*documentElement); | 1372 EphemeralRange endRange = PlainTextRange(destinationIndex + endIndex).create
RangeForSelection(*documentElement); |
| 1373 if (endRange.isNull()) | 1373 if (endRange.isNull()) |
| 1374 return; | 1374 return; |
| 1375 setEndingSelection(VisibleSelection(startRange.startPosition(), endRange.sta
rtPosition(), TextAffinity::Downstream, originalIsDirectional)); | 1375 setEndingSelection(VisibleSelection(startRange.startPosition(), endRange.sta
rtPosition(), TextAffinity::Downstream, originalIsDirectional)); |
| 1376 } | 1376 } |
| 1377 | 1377 |
| 1378 // FIXME: Send an appropriate shouldDeleteRange call. | 1378 // FIXME: Send an appropriate shouldDeleteRange call. |
| 1379 bool CompositeEditCommand::breakOutOfEmptyListItem(EditingState* editingState) | 1379 bool CompositeEditCommand::breakOutOfEmptyListItem(EditingState* editingState) |
| 1380 { | 1380 { |
| 1381 RefPtrWillBeRawPtr<Node> emptyListItem = enclosingEmptyListItem(endingSelect
ion().visibleStart()); | 1381 RawPtr<Node> emptyListItem = enclosingEmptyListItem(endingSelection().visibl
eStart()); |
| 1382 if (!emptyListItem) | 1382 if (!emptyListItem) |
| 1383 return false; | 1383 return false; |
| 1384 | 1384 |
| 1385 RefPtrWillBeRawPtr<EditingStyle> style = EditingStyle::create(endingSelectio
n().start()); | 1385 RawPtr<EditingStyle> style = EditingStyle::create(endingSelection().start())
; |
| 1386 style->mergeTypingStyle(&document()); | 1386 style->mergeTypingStyle(&document()); |
| 1387 | 1387 |
| 1388 RefPtrWillBeRawPtr<ContainerNode> listNode = emptyListItem->parentNode(); | 1388 RawPtr<ContainerNode> listNode = emptyListItem->parentNode(); |
| 1389 // FIXME: Can't we do something better when the immediate parent wasn't a li
st node? | 1389 // FIXME: Can't we do something better when the immediate parent wasn't a li
st node? |
| 1390 if (!listNode | 1390 if (!listNode |
| 1391 || (!isHTMLUListElement(*listNode) && !isHTMLOListElement(*listNode)) | 1391 || (!isHTMLUListElement(*listNode) && !isHTMLOListElement(*listNode)) |
| 1392 || !listNode->hasEditableStyle() | 1392 || !listNode->hasEditableStyle() |
| 1393 || listNode == emptyListItem->rootEditableElement()) | 1393 || listNode == emptyListItem->rootEditableElement()) |
| 1394 return false; | 1394 return false; |
| 1395 | 1395 |
| 1396 RefPtrWillBeRawPtr<HTMLElement> newBlock = nullptr; | 1396 RawPtr<HTMLElement> newBlock = nullptr; |
| 1397 if (ContainerNode* blockEnclosingList = listNode->parentNode()) { | 1397 if (ContainerNode* blockEnclosingList = listNode->parentNode()) { |
| 1398 if (isHTMLLIElement(*blockEnclosingList)) { // listNode is inside anothe
r list item | 1398 if (isHTMLLIElement(*blockEnclosingList)) { // listNode is inside anothe
r list item |
| 1399 if (visiblePositionAfterNode(*blockEnclosingList).deepEquivalent() =
= visiblePositionAfterNode(*listNode).deepEquivalent()) { | 1399 if (visiblePositionAfterNode(*blockEnclosingList).deepEquivalent() =
= visiblePositionAfterNode(*listNode).deepEquivalent()) { |
| 1400 // If listNode appears at the end of the outer list item, then m
ove listNode outside of this list item | 1400 // If listNode appears at the end of the outer list item, then m
ove listNode outside of this list item |
| 1401 // e.g. <ul><li>hello <ul><li><br></li></ul> </li></ul> should b
ecome <ul><li>hello</li> <ul><li><br></li></ul> </ul> after this section | 1401 // e.g. <ul><li>hello <ul><li><br></li></ul> </li></ul> should b
ecome <ul><li>hello</li> <ul><li><br></li></ul> </ul> after this section |
| 1402 // If listNode does NOT appear at the end, then we should consid
er it as a regular paragraph. | 1402 // If listNode does NOT appear at the end, then we should consid
er it as a regular paragraph. |
| 1403 // e.g. <ul><li> <ul><li><br></li></ul> hello</li></ul> should b
ecome <ul><li> <div><br></div> hello</li></ul> at the end | 1403 // e.g. <ul><li> <ul><li><br></li></ul> hello</li></ul> should b
ecome <ul><li> <div><br></div> hello</li></ul> at the end |
| 1404 splitElement(toElement(blockEnclosingList), listNode); | 1404 splitElement(toElement(blockEnclosingList), listNode); |
| 1405 removeNodePreservingChildren(listNode->parentNode(), editingStat
e); | 1405 removeNodePreservingChildren(listNode->parentNode(), editingStat
e); |
| 1406 if (editingState->isAborted()) | 1406 if (editingState->isAborted()) |
| 1407 return false; | 1407 return false; |
| 1408 newBlock = HTMLLIElement::create(document()); | 1408 newBlock = HTMLLIElement::create(document()); |
| 1409 } | 1409 } |
| 1410 // If listNode does NOT appear at the end of the outer list item, th
en behave as if in a regular paragraph. | 1410 // If listNode does NOT appear at the end of the outer list item, th
en behave as if in a regular paragraph. |
| 1411 } else if (isHTMLOListElement(*blockEnclosingList) || isHTMLUListElement
(*blockEnclosingList)) { | 1411 } else if (isHTMLOListElement(*blockEnclosingList) || isHTMLUListElement
(*blockEnclosingList)) { |
| 1412 newBlock = HTMLLIElement::create(document()); | 1412 newBlock = HTMLLIElement::create(document()); |
| 1413 } | 1413 } |
| 1414 } | 1414 } |
| 1415 if (!newBlock) | 1415 if (!newBlock) |
| 1416 newBlock = createDefaultParagraphElement(document()); | 1416 newBlock = createDefaultParagraphElement(document()); |
| 1417 | 1417 |
| 1418 RefPtrWillBeRawPtr<Node> previousListNode = emptyListItem->isElementNode() ?
ElementTraversal::previousSibling(*emptyListItem): emptyListItem->previousSibli
ng(); | 1418 RawPtr<Node> previousListNode = emptyListItem->isElementNode() ? ElementTrav
ersal::previousSibling(*emptyListItem): emptyListItem->previousSibling(); |
| 1419 RefPtrWillBeRawPtr<Node> nextListNode = emptyListItem->isElementNode() ? Ele
mentTraversal::nextSibling(*emptyListItem): emptyListItem->nextSibling(); | 1419 RawPtr<Node> nextListNode = emptyListItem->isElementNode() ? ElementTraversa
l::nextSibling(*emptyListItem): emptyListItem->nextSibling(); |
| 1420 if (isListItem(nextListNode.get()) || isHTMLListElement(nextListNode.get()))
{ | 1420 if (isListItem(nextListNode.get()) || isHTMLListElement(nextListNode.get()))
{ |
| 1421 // If emptyListItem follows another list item or nested list, split the
list node. | 1421 // If emptyListItem follows another list item or nested list, split the
list node. |
| 1422 if (isListItem(previousListNode.get()) || isHTMLListElement(previousList
Node.get())) | 1422 if (isListItem(previousListNode.get()) || isHTMLListElement(previousList
Node.get())) |
| 1423 splitElement(toElement(listNode), emptyListItem); | 1423 splitElement(toElement(listNode), emptyListItem); |
| 1424 | 1424 |
| 1425 // If emptyListItem is followed by other list item or nested list, then
insert newBlock before the list node. | 1425 // If emptyListItem is followed by other list item or nested list, then
insert newBlock before the list node. |
| 1426 // Because we have splitted the element, emptyListItem is the first elem
ent in the list node. | 1426 // Because we have splitted the element, emptyListItem is the first elem
ent in the list node. |
| 1427 // i.e. insert newBlock before ul or ol whose first element is emptyList
Item | 1427 // i.e. insert newBlock before ul or ol whose first element is emptyList
Item |
| 1428 insertNodeBefore(newBlock, listNode, editingState); | 1428 insertNodeBefore(newBlock, listNode, editingState); |
| 1429 if (editingState->isAborted()) | 1429 if (editingState->isAborted()) |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1470 return false; | 1470 return false; |
| 1471 | 1471 |
| 1472 if (!isStartOfParagraph(caret) || !isEndOfParagraph(caret)) | 1472 if (!isStartOfParagraph(caret) || !isEndOfParagraph(caret)) |
| 1473 return false; | 1473 return false; |
| 1474 | 1474 |
| 1475 VisiblePosition previous = previousPositionOf(caret, CannotCrossEditingBound
ary); | 1475 VisiblePosition previous = previousPositionOf(caret, CannotCrossEditingBound
ary); |
| 1476 // Only move forward if there's nothing before the caret, or if there's unqu
oted content before it. | 1476 // Only move forward if there's nothing before the caret, or if there's unqu
oted content before it. |
| 1477 if (enclosingNodeOfType(previous.deepEquivalent(), &isMailHTMLBlockquoteElem
ent)) | 1477 if (enclosingNodeOfType(previous.deepEquivalent(), &isMailHTMLBlockquoteElem
ent)) |
| 1478 return false; | 1478 return false; |
| 1479 | 1479 |
| 1480 RefPtrWillBeRawPtr<HTMLBRElement> br = HTMLBRElement::create(document()); | 1480 RawPtr<HTMLBRElement> br = HTMLBRElement::create(document()); |
| 1481 // We want to replace this quoted paragraph with an unquoted one, so insert
a br | 1481 // We want to replace this quoted paragraph with an unquoted one, so insert
a br |
| 1482 // to hold the caret before the highest blockquote. | 1482 // to hold the caret before the highest blockquote. |
| 1483 insertNodeBefore(br, highestBlockquote, editingState); | 1483 insertNodeBefore(br, highestBlockquote, editingState); |
| 1484 if (editingState->isAborted()) | 1484 if (editingState->isAborted()) |
| 1485 return false; | 1485 return false; |
| 1486 VisiblePosition atBR = createVisiblePosition(positionBeforeNode(br.get())); | 1486 VisiblePosition atBR = createVisiblePosition(positionBeforeNode(br.get())); |
| 1487 // If the br we inserted collapsed, for example foo<br><blockquote>...</bloc
kquote>, insert | 1487 // If the br we inserted collapsed, for example foo<br><blockquote>...</bloc
kquote>, insert |
| 1488 // a second one. | 1488 // a second one. |
| 1489 if (!isStartOfParagraph(atBR)) { | 1489 if (!isStartOfParagraph(atBR)) { |
| 1490 insertNodeBefore(HTMLBRElement::create(document()), br, editingState); | 1490 insertNodeBefore(HTMLBRElement::create(document()), br, editingState); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1580 } | 1580 } |
| 1581 | 1581 |
| 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 PassRefPtrWillBeRawPtr<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 ASSERT(start); |
| 1593 ASSERT(end); | 1593 ASSERT(end); |
| 1594 ASSERT(start != end); | 1594 ASSERT(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 RefPtrWillBeRawPtr<Node> endNode = end; | 1601 RawPtr<Node> endNode = end; |
| 1602 RefPtrWillBeRawPtr<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(); |
| 1605 if (!parentElement) | 1605 if (!parentElement) |
| 1606 break; | 1606 break; |
| 1607 // Do not split a node when doing so introduces an empty node. | 1607 // Do not split a node when doing so introduces an empty node. |
| 1608 VisiblePosition positionInParent = createVisiblePosition(firstPositionIn
Node(parentElement)); | 1608 VisiblePosition positionInParent = createVisiblePosition(firstPositionIn
Node(parentElement)); |
| 1609 VisiblePosition positionInNode = createVisiblePosition(firstPositionInOr
BeforeNode(node.get())); | 1609 VisiblePosition positionInNode = createVisiblePosition(firstPositionInOr
BeforeNode(node.get())); |
| 1610 if (positionInParent.deepEquivalent() != positionInNode.deepEquivalent()
) | 1610 if (positionInParent.deepEquivalent() != positionInNode.deepEquivalent()
) |
| 1611 splitElement(parentElement, node); | 1611 splitElement(parentElement, node); |
| 1612 } | 1612 } |
| 1613 | 1613 |
| 1614 return node.release(); | 1614 return node.release(); |
| 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 |