| 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, endingSelect
ion, 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 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 return false; | 239 return false; |
| 240 } | 240 } |
| 241 | 241 |
| 242 void CompositeEditCommand::setShouldRetainAutocorrectionIndicator(bool) | 242 void CompositeEditCommand::setShouldRetainAutocorrectionIndicator(bool) |
| 243 { | 243 { |
| 244 } | 244 } |
| 245 | 245 |
| 246 // | 246 // |
| 247 // sugary-sweet convenience functions to help create and apply edit commands in
composite commands | 247 // sugary-sweet convenience functions to help create and apply edit commands in
composite commands |
| 248 // | 248 // |
| 249 void CompositeEditCommand::applyCommandToComposite(PassRefPtrWillBeRawPtr<EditCo
mmand> prpCommand) | 249 void CompositeEditCommand::applyCommandToComposite(RawPtr<EditCommand> prpComman
d) |
| 250 { | 250 { |
| 251 RefPtrWillBeRawPtr<EditCommand> command = prpCommand; | 251 RawPtr<EditCommand> command = prpCommand; |
| 252 command->setParent(this); | 252 command->setParent(this); |
| 253 command->doApply(); | 253 command->doApply(); |
| 254 if (command->isSimpleEditCommand()) { | 254 if (command->isSimpleEditCommand()) { |
| 255 command->setParent(0); | 255 command->setParent(0); |
| 256 ensureComposition()->append(toSimpleEditCommand(command.get())); | 256 ensureComposition()->append(toSimpleEditCommand(command.get())); |
| 257 } | 257 } |
| 258 m_commands.append(command.release()); | 258 m_commands.append(command.release()); |
| 259 } | 259 } |
| 260 | 260 |
| 261 void CompositeEditCommand::applyCommandToComposite(PassRefPtrWillBeRawPtr<Compos
iteEditCommand> command, const VisibleSelection& selection) | 261 void CompositeEditCommand::applyCommandToComposite(RawPtr<CompositeEditCommand>
command, const VisibleSelection& selection) |
| 262 { | 262 { |
| 263 command->setParent(this); | 263 command->setParent(this); |
| 264 if (!equalSelectionsInDOMTree(selection, command->endingSelection())) { | 264 if (!equalSelectionsInDOMTree(selection, command->endingSelection())) { |
| 265 command->setStartingSelection(selection); | 265 command->setStartingSelection(selection); |
| 266 command->setEndingSelection(selection); | 266 command->setEndingSelection(selection); |
| 267 } | 267 } |
| 268 command->doApply(); | 268 command->doApply(); |
| 269 m_commands.append(command); | 269 m_commands.append(command); |
| 270 } | 270 } |
| 271 | 271 |
| 272 void CompositeEditCommand::applyStyle(const EditingStyle* style, EditAction edit
ingAction) | 272 void CompositeEditCommand::applyStyle(const EditingStyle* style, EditAction edit
ingAction) |
| 273 { | 273 { |
| 274 applyCommandToComposite(ApplyStyleCommand::create(document(), style, editing
Action)); | 274 applyCommandToComposite(ApplyStyleCommand::create(document(), style, editing
Action)); |
| 275 } | 275 } |
| 276 | 276 |
| 277 void CompositeEditCommand::applyStyle(const EditingStyle* style, const Position&
start, const Position& end, EditAction editingAction) | 277 void CompositeEditCommand::applyStyle(const EditingStyle* style, const Position&
start, const Position& end, EditAction editingAction) |
| 278 { | 278 { |
| 279 applyCommandToComposite(ApplyStyleCommand::create(document(), style, start,
end, editingAction)); | 279 applyCommandToComposite(ApplyStyleCommand::create(document(), style, start,
end, editingAction)); |
| 280 } | 280 } |
| 281 | 281 |
| 282 void CompositeEditCommand::applyStyledElement(PassRefPtrWillBeRawPtr<Element> el
ement) | 282 void CompositeEditCommand::applyStyledElement(RawPtr<Element> element) |
| 283 { | 283 { |
| 284 applyCommandToComposite(ApplyStyleCommand::create(element, false)); | 284 applyCommandToComposite(ApplyStyleCommand::create(element, false)); |
| 285 } | 285 } |
| 286 | 286 |
| 287 void CompositeEditCommand::removeStyledElement(PassRefPtrWillBeRawPtr<Element> e
lement) | 287 void CompositeEditCommand::removeStyledElement(RawPtr<Element> element) |
| 288 { | 288 { |
| 289 applyCommandToComposite(ApplyStyleCommand::create(element, true)); | 289 applyCommandToComposite(ApplyStyleCommand::create(element, true)); |
| 290 } | 290 } |
| 291 | 291 |
| 292 void CompositeEditCommand::insertParagraphSeparator(bool useDefaultParagraphElem
ent, bool pasteBlockqutoeIntoUnquotedArea) | 292 void CompositeEditCommand::insertParagraphSeparator(bool useDefaultParagraphElem
ent, bool pasteBlockqutoeIntoUnquotedArea) |
| 293 { | 293 { |
| 294 applyCommandToComposite(InsertParagraphSeparatorCommand::create(document(),
useDefaultParagraphElement, pasteBlockqutoeIntoUnquotedArea)); | 294 applyCommandToComposite(InsertParagraphSeparatorCommand::create(document(),
useDefaultParagraphElement, pasteBlockqutoeIntoUnquotedArea)); |
| 295 } | 295 } |
| 296 | 296 |
| 297 bool CompositeEditCommand::isRemovableBlock(const Node* node) | 297 bool CompositeEditCommand::isRemovableBlock(const Node* node) |
| 298 { | 298 { |
| 299 ASSERT(node); | 299 ASSERT(node); |
| 300 if (!isHTMLDivElement(*node)) | 300 if (!isHTMLDivElement(*node)) |
| 301 return false; | 301 return false; |
| 302 | 302 |
| 303 const HTMLDivElement& element = toHTMLDivElement(*node); | 303 const HTMLDivElement& element = toHTMLDivElement(*node); |
| 304 ContainerNode* parentNode = element.parentNode(); | 304 ContainerNode* parentNode = element.parentNode(); |
| 305 if (parentNode && parentNode->firstChild() != parentNode->lastChild()) | 305 if (parentNode && parentNode->firstChild() != parentNode->lastChild()) |
| 306 return false; | 306 return false; |
| 307 | 307 |
| 308 if (!element.hasAttributes()) | 308 if (!element.hasAttributes()) |
| 309 return true; | 309 return true; |
| 310 | 310 |
| 311 return false; | 311 return false; |
| 312 } | 312 } |
| 313 | 313 |
| 314 void CompositeEditCommand::insertNodeBefore(PassRefPtrWillBeRawPtr<Node> insertC
hild, PassRefPtrWillBeRawPtr<Node> refChild, ShouldAssumeContentIsAlwaysEditable
shouldAssumeContentIsAlwaysEditable) | 314 void CompositeEditCommand::insertNodeBefore(RawPtr<Node> insertChild, RawPtr<Nod
e> refChild, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEdit
able) |
| 315 { | 315 { |
| 316 ASSERT(document().body() != refChild); | 316 ASSERT(document().body() != refChild); |
| 317 applyCommandToComposite(InsertNodeBeforeCommand::create(insertChild, refChil
d, shouldAssumeContentIsAlwaysEditable)); | 317 applyCommandToComposite(InsertNodeBeforeCommand::create(insertChild, refChil
d, shouldAssumeContentIsAlwaysEditable)); |
| 318 } | 318 } |
| 319 | 319 |
| 320 void CompositeEditCommand::insertNodeAfter(PassRefPtrWillBeRawPtr<Node> insertCh
ild, PassRefPtrWillBeRawPtr<Node> refChild) | 320 void CompositeEditCommand::insertNodeAfter(RawPtr<Node> insertChild, RawPtr<Node
> refChild) |
| 321 { | 321 { |
| 322 ASSERT(insertChild); | 322 ASSERT(insertChild); |
| 323 ASSERT(refChild); | 323 ASSERT(refChild); |
| 324 ASSERT(document().body() != refChild); | 324 ASSERT(document().body() != refChild); |
| 325 ContainerNode* parent = refChild->parentNode(); | 325 ContainerNode* parent = refChild->parentNode(); |
| 326 ASSERT(parent); | 326 ASSERT(parent); |
| 327 ASSERT(!parent->isShadowRoot()); | 327 ASSERT(!parent->isShadowRoot()); |
| 328 if (parent->lastChild() == refChild) { | 328 if (parent->lastChild() == refChild) { |
| 329 appendNode(insertChild, parent); | 329 appendNode(insertChild, parent); |
| 330 } else { | 330 } else { |
| 331 ASSERT(refChild->nextSibling()); | 331 ASSERT(refChild->nextSibling()); |
| 332 insertNodeBefore(insertChild, refChild->nextSibling()); | 332 insertNodeBefore(insertChild, refChild->nextSibling()); |
| 333 } | 333 } |
| 334 } | 334 } |
| 335 | 335 |
| 336 void CompositeEditCommand::insertNodeAt(PassRefPtrWillBeRawPtr<Node> insertChild
, const Position& editingPosition) | 336 void CompositeEditCommand::insertNodeAt(RawPtr<Node> insertChild, const Position
& editingPosition) |
| 337 { | 337 { |
| 338 ASSERT(isEditablePosition(editingPosition, ContentIsEditable, DoNotUpdateSty
le)); | 338 ASSERT(isEditablePosition(editingPosition, ContentIsEditable, DoNotUpdateSty
le)); |
| 339 // For editing positions like [table, 0], insert before the table, | 339 // For editing positions like [table, 0], insert before the table, |
| 340 // likewise for replaced elements, brs, etc. | 340 // likewise for replaced elements, brs, etc. |
| 341 Position p = editingPosition.parentAnchoredEquivalent(); | 341 Position p = editingPosition.parentAnchoredEquivalent(); |
| 342 Node* refChild = p.anchorNode(); | 342 Node* refChild = p.anchorNode(); |
| 343 int offset = p.offsetInContainerNode(); | 343 int offset = p.offsetInContainerNode(); |
| 344 | 344 |
| 345 if (canHaveChildrenForEditing(refChild)) { | 345 if (canHaveChildrenForEditing(refChild)) { |
| 346 Node* child = refChild->firstChild(); | 346 Node* child = refChild->firstChild(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 357 | 357 |
| 358 // Mutation events (bug 22634) from the text node insertion may have rem
oved the refChild | 358 // Mutation events (bug 22634) from the text node insertion may have rem
oved the refChild |
| 359 if (!refChild->inDocument()) | 359 if (!refChild->inDocument()) |
| 360 return; | 360 return; |
| 361 insertNodeBefore(insertChild, refChild); | 361 insertNodeBefore(insertChild, refChild); |
| 362 } else { | 362 } else { |
| 363 insertNodeAfter(insertChild, refChild); | 363 insertNodeAfter(insertChild, refChild); |
| 364 } | 364 } |
| 365 } | 365 } |
| 366 | 366 |
| 367 void CompositeEditCommand::appendNode(PassRefPtrWillBeRawPtr<Node> node, PassRef
PtrWillBeRawPtr<ContainerNode> parent) | 367 void CompositeEditCommand::appendNode(RawPtr<Node> node, RawPtr<ContainerNode> p
arent) |
| 368 { | 368 { |
| 369 // When cloneParagraphUnderNewElement() clones the fallback content | 369 // When cloneParagraphUnderNewElement() clones the fallback content |
| 370 // of an OBJECT element, the ASSERT below may fire since the return | 370 // of an OBJECT element, the ASSERT below may fire since the return |
| 371 // value of canHaveChildrenForEditing is not reliable until the layout | 371 // value of canHaveChildrenForEditing is not reliable until the layout |
| 372 // object of the OBJECT is created. Hence we ignore this check for OBJECTs. | 372 // object of the OBJECT is created. Hence we ignore this check for OBJECTs. |
| 373 ASSERT(canHaveChildrenForEditing(parent.get()) | 373 ASSERT(canHaveChildrenForEditing(parent.get()) |
| 374 || (parent->isElementNode() && toElement(parent.get())->tagQName() == ob
jectTag)); | 374 || (parent->isElementNode() && toElement(parent.get())->tagQName() == ob
jectTag)); |
| 375 applyCommandToComposite(AppendNodeCommand::create(parent, node)); | 375 applyCommandToComposite(AppendNodeCommand::create(parent, node)); |
| 376 } | 376 } |
| 377 | 377 |
| 378 void CompositeEditCommand::removeChildrenInRange(PassRefPtrWillBeRawPtr<Node> no
de, unsigned from, unsigned to) | 378 void CompositeEditCommand::removeChildrenInRange(RawPtr<Node> node, unsigned fro
m, unsigned to) |
| 379 { | 379 { |
| 380 WillBeHeapVector<RefPtrWillBeMember<Node>> children; | 380 HeapVector<Member<Node>> children; |
| 381 Node* child = NodeTraversal::childAt(*node, from); | 381 Node* child = NodeTraversal::childAt(*node, from); |
| 382 for (unsigned i = from; child && i < to; i++, child = child->nextSibling()) | 382 for (unsigned i = from; child && i < to; i++, child = child->nextSibling()) |
| 383 children.append(child); | 383 children.append(child); |
| 384 | 384 |
| 385 size_t size = children.size(); | 385 size_t size = children.size(); |
| 386 for (size_t i = 0; i < size; ++i) | 386 for (size_t i = 0; i < size; ++i) |
| 387 removeNode(children[i].release()); | 387 removeNode(children[i].release()); |
| 388 } | 388 } |
| 389 | 389 |
| 390 void CompositeEditCommand::removeNode(PassRefPtrWillBeRawPtr<Node> node, ShouldA
ssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable) | 390 void CompositeEditCommand::removeNode(RawPtr<Node> node, ShouldAssumeContentIsAl
waysEditable shouldAssumeContentIsAlwaysEditable) |
| 391 { | 391 { |
| 392 if (!node || !node->nonShadowBoundaryParentNode()) | 392 if (!node || !node->nonShadowBoundaryParentNode()) |
| 393 return; | 393 return; |
| 394 applyCommandToComposite(RemoveNodeCommand::create(node, shouldAssumeContentI
sAlwaysEditable)); | 394 applyCommandToComposite(RemoveNodeCommand::create(node, shouldAssumeContentI
sAlwaysEditable)); |
| 395 } | 395 } |
| 396 | 396 |
| 397 void CompositeEditCommand::removeNodePreservingChildren(PassRefPtrWillBeRawPtr<N
ode> node, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditab
le) | 397 void CompositeEditCommand::removeNodePreservingChildren(RawPtr<Node> node, Shoul
dAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable) |
| 398 { | 398 { |
| 399 applyCommandToComposite(RemoveNodePreservingChildrenCommand::create(node, sh
ouldAssumeContentIsAlwaysEditable)); | 399 applyCommandToComposite(RemoveNodePreservingChildrenCommand::create(node, sh
ouldAssumeContentIsAlwaysEditable)); |
| 400 } | 400 } |
| 401 | 401 |
| 402 void CompositeEditCommand::removeNodeAndPruneAncestors(PassRefPtrWillBeRawPtr<No
de> node, Node* excludeNode) | 402 void CompositeEditCommand::removeNodeAndPruneAncestors(RawPtr<Node> node, Node*
excludeNode) |
| 403 { | 403 { |
| 404 ASSERT(node.get() != excludeNode); | 404 ASSERT(node.get() != excludeNode); |
| 405 RefPtrWillBeRawPtr<ContainerNode> parent = node->parentNode(); | 405 RawPtr<ContainerNode> parent = node->parentNode(); |
| 406 removeNode(node); | 406 removeNode(node); |
| 407 prune(parent.release(), excludeNode); | 407 prune(parent.release(), excludeNode); |
| 408 } | 408 } |
| 409 | 409 |
| 410 void CompositeEditCommand::moveRemainingSiblingsToNewParent(Node* node, Node* pa
stLastNodeToMove, PassRefPtrWillBeRawPtr<Element> prpNewParent) | 410 void CompositeEditCommand::moveRemainingSiblingsToNewParent(Node* node, Node* pa
stLastNodeToMove, RawPtr<Element> prpNewParent) |
| 411 { | 411 { |
| 412 NodeVector nodesToRemove; | 412 NodeVector nodesToRemove; |
| 413 RefPtrWillBeRawPtr<Element> newParent = prpNewParent; | 413 RawPtr<Element> newParent = prpNewParent; |
| 414 | 414 |
| 415 for (; node && node != pastLastNodeToMove; node = node->nextSibling()) | 415 for (; node && node != pastLastNodeToMove; node = node->nextSibling()) |
| 416 nodesToRemove.append(node); | 416 nodesToRemove.append(node); |
| 417 | 417 |
| 418 for (unsigned i = 0; i < nodesToRemove.size(); i++) { | 418 for (unsigned i = 0; i < nodesToRemove.size(); i++) { |
| 419 removeNode(nodesToRemove[i]); | 419 removeNode(nodesToRemove[i]); |
| 420 appendNode(nodesToRemove[i], newParent); | 420 appendNode(nodesToRemove[i], newParent); |
| 421 } | 421 } |
| 422 } | 422 } |
| 423 | 423 |
| 424 void CompositeEditCommand::updatePositionForNodeRemovalPreservingChildren(Positi
on& position, Node& node) | 424 void CompositeEditCommand::updatePositionForNodeRemovalPreservingChildren(Positi
on& position, Node& node) |
| 425 { | 425 { |
| 426 int offset = position.isOffsetInAnchor() ? position.offsetInContainerNode()
: 0; | 426 int offset = position.isOffsetInAnchor() ? position.offsetInContainerNode()
: 0; |
| 427 updatePositionForNodeRemoval(position, node); | 427 updatePositionForNodeRemoval(position, node); |
| 428 if (offset == 0) | 428 if (offset == 0) |
| 429 return; | 429 return; |
| 430 position = Position(position.computeContainerNode(), offset); | 430 position = Position(position.computeContainerNode(), offset); |
| 431 } | 431 } |
| 432 | 432 |
| 433 HTMLSpanElement* CompositeEditCommand::replaceElementWithSpanPreservingChildrenA
ndAttributes(PassRefPtrWillBeRawPtr<HTMLElement> node) | 433 HTMLSpanElement* CompositeEditCommand::replaceElementWithSpanPreservingChildrenA
ndAttributes(RawPtr<HTMLElement> node) |
| 434 { | 434 { |
| 435 // It would also be possible to implement all of ReplaceNodeWithSpanCommand | 435 // It would also be possible to implement all of ReplaceNodeWithSpanCommand |
| 436 // as a series of existing smaller edit commands. Someone who wanted to | 436 // as a series of existing smaller edit commands. Someone who wanted to |
| 437 // reduce the number of edit commands could do so here. | 437 // reduce the number of edit commands could do so here. |
| 438 RefPtrWillBeRawPtr<ReplaceNodeWithSpanCommand> command = ReplaceNodeWithSpan
Command::create(node); | 438 RawPtr<ReplaceNodeWithSpanCommand> command = ReplaceNodeWithSpanCommand::cre
ate(node); |
| 439 applyCommandToComposite(command); | 439 applyCommandToComposite(command); |
| 440 // Returning a raw pointer here is OK because the command is retained by | 440 // Returning a raw pointer here is OK because the command is retained by |
| 441 // applyCommandToComposite (thus retaining the span), and the span is also | 441 // applyCommandToComposite (thus retaining the span), and the span is also |
| 442 // in the DOM tree, and thus alive whie it has a parent. | 442 // in the DOM tree, and thus alive whie it has a parent. |
| 443 ASSERT(command->spanElement()->inDocument()); | 443 ASSERT(command->spanElement()->inDocument()); |
| 444 return command->spanElement(); | 444 return command->spanElement(); |
| 445 } | 445 } |
| 446 | 446 |
| 447 void CompositeEditCommand::prune(PassRefPtrWillBeRawPtr<Node> node, Node* exclud
eNode) | 447 void CompositeEditCommand::prune(RawPtr<Node> node, Node* excludeNode) |
| 448 { | 448 { |
| 449 if (RefPtrWillBeRawPtr<Node> highestNodeToRemove = highestNodeToRemoveInPrun
ing(node.get(), excludeNode)) | 449 if (RawPtr<Node> highestNodeToRemove = highestNodeToRemoveInPruning(node.get
(), excludeNode)) |
| 450 removeNode(highestNodeToRemove.release()); | 450 removeNode(highestNodeToRemove.release()); |
| 451 } | 451 } |
| 452 | 452 |
| 453 void CompositeEditCommand::splitTextNode(PassRefPtrWillBeRawPtr<Text> node, unsi
gned offset) | 453 void CompositeEditCommand::splitTextNode(RawPtr<Text> node, unsigned offset) |
| 454 { | 454 { |
| 455 applyCommandToComposite(SplitTextNodeCommand::create(node, offset)); | 455 applyCommandToComposite(SplitTextNodeCommand::create(node, offset)); |
| 456 } | 456 } |
| 457 | 457 |
| 458 void CompositeEditCommand::splitElement(PassRefPtrWillBeRawPtr<Element> element,
PassRefPtrWillBeRawPtr<Node> atChild) | 458 void CompositeEditCommand::splitElement(RawPtr<Element> element, RawPtr<Node> at
Child) |
| 459 { | 459 { |
| 460 applyCommandToComposite(SplitElementCommand::create(element, atChild)); | 460 applyCommandToComposite(SplitElementCommand::create(element, atChild)); |
| 461 } | 461 } |
| 462 | 462 |
| 463 void CompositeEditCommand::mergeIdenticalElements(PassRefPtrWillBeRawPtr<Element
> prpFirst, PassRefPtrWillBeRawPtr<Element> prpSecond) | 463 void CompositeEditCommand::mergeIdenticalElements(RawPtr<Element> prpFirst, RawP
tr<Element> prpSecond) |
| 464 { | 464 { |
| 465 RefPtrWillBeRawPtr<Element> first = prpFirst; | 465 RawPtr<Element> first = prpFirst; |
| 466 RefPtrWillBeRawPtr<Element> second = prpSecond; | 466 RawPtr<Element> second = prpSecond; |
| 467 ASSERT(!first->isDescendantOf(second.get()) && second != first); | 467 ASSERT(!first->isDescendantOf(second.get()) && second != first); |
| 468 if (first->nextSibling() != second) { | 468 if (first->nextSibling() != second) { |
| 469 removeNode(second); | 469 removeNode(second); |
| 470 insertNodeAfter(second, first); | 470 insertNodeAfter(second, first); |
| 471 } | 471 } |
| 472 applyCommandToComposite(MergeIdenticalElementsCommand::create(first, second)
); | 472 applyCommandToComposite(MergeIdenticalElementsCommand::create(first, second)
); |
| 473 } | 473 } |
| 474 | 474 |
| 475 void CompositeEditCommand::wrapContentsInDummySpan(PassRefPtrWillBeRawPtr<Elemen
t> element) | 475 void CompositeEditCommand::wrapContentsInDummySpan(RawPtr<Element> element) |
| 476 { | 476 { |
| 477 applyCommandToComposite(WrapContentsInDummySpanCommand::create(element)); | 477 applyCommandToComposite(WrapContentsInDummySpanCommand::create(element)); |
| 478 } | 478 } |
| 479 | 479 |
| 480 void CompositeEditCommand::splitTextNodeContainingElement(PassRefPtrWillBeRawPtr
<Text> text, unsigned offset) | 480 void CompositeEditCommand::splitTextNodeContainingElement(RawPtr<Text> text, uns
igned offset) |
| 481 { | 481 { |
| 482 applyCommandToComposite(SplitTextNodeContainingElementCommand::create(text,
offset)); | 482 applyCommandToComposite(SplitTextNodeContainingElementCommand::create(text,
offset)); |
| 483 } | 483 } |
| 484 | 484 |
| 485 void CompositeEditCommand::insertTextIntoNode(PassRefPtrWillBeRawPtr<Text> node,
unsigned offset, const String& text) | 485 void CompositeEditCommand::insertTextIntoNode(RawPtr<Text> node, unsigned offset
, const String& text) |
| 486 { | 486 { |
| 487 if (!text.isEmpty()) | 487 if (!text.isEmpty()) |
| 488 applyCommandToComposite(InsertIntoTextNodeCommand::create(node, offset,
text)); | 488 applyCommandToComposite(InsertIntoTextNodeCommand::create(node, offset,
text)); |
| 489 } | 489 } |
| 490 | 490 |
| 491 void CompositeEditCommand::deleteTextFromNode(PassRefPtrWillBeRawPtr<Text> node,
unsigned offset, unsigned count) | 491 void CompositeEditCommand::deleteTextFromNode(RawPtr<Text> node, unsigned offset
, unsigned count) |
| 492 { | 492 { |
| 493 applyCommandToComposite(DeleteFromTextNodeCommand::create(node, offset, coun
t)); | 493 applyCommandToComposite(DeleteFromTextNodeCommand::create(node, offset, coun
t)); |
| 494 } | 494 } |
| 495 | 495 |
| 496 void CompositeEditCommand::replaceTextInNode(PassRefPtrWillBeRawPtr<Text> prpNod
e, unsigned offset, unsigned count, const String& replacementText) | 496 void CompositeEditCommand::replaceTextInNode(RawPtr<Text> prpNode, unsigned offs
et, unsigned count, const String& replacementText) |
| 497 { | 497 { |
| 498 RefPtrWillBeRawPtr<Text> node(prpNode); | 498 RawPtr<Text> node(prpNode); |
| 499 applyCommandToComposite(DeleteFromTextNodeCommand::create(node, offset, coun
t)); | 499 applyCommandToComposite(DeleteFromTextNodeCommand::create(node, offset, coun
t)); |
| 500 if (!replacementText.isEmpty()) | 500 if (!replacementText.isEmpty()) |
| 501 applyCommandToComposite(InsertIntoTextNodeCommand::create(node, offset,
replacementText)); | 501 applyCommandToComposite(InsertIntoTextNodeCommand::create(node, offset,
replacementText)); |
| 502 } | 502 } |
| 503 | 503 |
| 504 Position CompositeEditCommand::replaceSelectedTextInNode(const String& text) | 504 Position CompositeEditCommand::replaceSelectedTextInNode(const String& text) |
| 505 { | 505 { |
| 506 Position start = endingSelection().start(); | 506 Position start = endingSelection().start(); |
| 507 Position end = endingSelection().end(); | 507 Position end = endingSelection().end(); |
| 508 if (start.computeContainerNode() != end.computeContainerNode() || !start.com
puteContainerNode()->isTextNode() || isTabHTMLSpanElementTextNode(start.computeC
ontainerNode())) | 508 if (start.computeContainerNode() != end.computeContainerNode() || !start.com
puteContainerNode()->isTextNode() || isTabHTMLSpanElementTextNode(start.computeC
ontainerNode())) |
| 509 return Position(); | 509 return Position(); |
| 510 | 510 |
| 511 RefPtrWillBeRawPtr<Text> textNode = toText(start.computeContainerNode()); | 511 RawPtr<Text> textNode = toText(start.computeContainerNode()); |
| 512 replaceTextInNode(textNode, start.offsetInContainerNode(), end.offsetInConta
inerNode() - start.offsetInContainerNode(), text); | 512 replaceTextInNode(textNode, start.offsetInContainerNode(), end.offsetInConta
inerNode() - start.offsetInContainerNode(), text); |
| 513 | 513 |
| 514 return Position(textNode.release(), start.offsetInContainerNode() + text.len
gth()); | 514 return Position(textNode.release(), start.offsetInContainerNode() + text.len
gth()); |
| 515 } | 515 } |
| 516 | 516 |
| 517 static void copyMarkerTypesAndDescriptions(const DocumentMarkerVector& markerPoi
nters, Vector<DocumentMarker::MarkerType>& types, Vector<String>& descriptions) | 517 static void copyMarkerTypesAndDescriptions(const DocumentMarkerVector& markerPoi
nters, Vector<DocumentMarker::MarkerType>& types, Vector<String>& descriptions) |
| 518 { | 518 { |
| 519 size_t arraySize = markerPointers.size(); | 519 size_t arraySize = markerPointers.size(); |
| 520 types.reserveCapacity(arraySize); | 520 types.reserveCapacity(arraySize); |
| 521 descriptions.reserveCapacity(arraySize); | 521 descriptions.reserveCapacity(arraySize); |
| 522 for (const auto& markerPointer : markerPointers) { | 522 for (const auto& markerPointer : markerPointers) { |
| 523 types.append(markerPointer->type()); | 523 types.append(markerPointer->type()); |
| 524 descriptions.append(markerPointer->description()); | 524 descriptions.append(markerPointer->description()); |
| 525 } | 525 } |
| 526 } | 526 } |
| 527 | 527 |
| 528 void CompositeEditCommand::replaceTextInNodePreservingMarkers(PassRefPtrWillBeRa
wPtr<Text> prpNode, unsigned offset, unsigned count, const String& replacementTe
xt) | 528 void CompositeEditCommand::replaceTextInNodePreservingMarkers(RawPtr<Text> prpNo
de, unsigned offset, unsigned count, const String& replacementText) |
| 529 { | 529 { |
| 530 RefPtrWillBeRawPtr<Text> node(prpNode); | 530 RawPtr<Text> node(prpNode); |
| 531 DocumentMarkerController& markerController = document().markers(); | 531 DocumentMarkerController& markerController = document().markers(); |
| 532 Vector<DocumentMarker::MarkerType> types; | 532 Vector<DocumentMarker::MarkerType> types; |
| 533 Vector<String> descriptions; | 533 Vector<String> descriptions; |
| 534 copyMarkerTypesAndDescriptions(markerController.markersInRange(EphemeralRang
e(Position(node.get(), offset), Position(node.get(), offset + count)), DocumentM
arker::AllMarkers()), types, descriptions); | 534 copyMarkerTypesAndDescriptions(markerController.markersInRange(EphemeralRang
e(Position(node.get(), offset), Position(node.get(), offset + count)), DocumentM
arker::AllMarkers()), types, descriptions); |
| 535 replaceTextInNode(node, offset, count, replacementText); | 535 replaceTextInNode(node, offset, count, replacementText); |
| 536 Position startPosition(node.get(), offset); | 536 Position startPosition(node.get(), offset); |
| 537 Position endPosition(node.get(), offset + replacementText.length()); | 537 Position endPosition(node.get(), offset + replacementText.length()); |
| 538 ASSERT(types.size() == descriptions.size()); | 538 ASSERT(types.size() == descriptions.size()); |
| 539 for (size_t i = 0; i < types.size(); ++i) | 539 for (size_t i = 0; i < types.size(); ++i) |
| 540 markerController.addMarker(startPosition, endPosition, types[i], descrip
tions[i]); | 540 markerController.addMarker(startPosition, endPosition, types[i], descrip
tions[i]); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 564 if (pos.offsetInContainerNode() <= caretMinOffset(pos.computeContainerNode()
)) | 564 if (pos.offsetInContainerNode() <= caretMinOffset(pos.computeContainerNode()
)) |
| 565 return positionInParentBeforeNode(*tabSpan); | 565 return positionInParentBeforeNode(*tabSpan); |
| 566 | 566 |
| 567 if (pos.offsetInContainerNode() >= caretMaxOffset(pos.computeContainerNode()
)) | 567 if (pos.offsetInContainerNode() >= caretMaxOffset(pos.computeContainerNode()
)) |
| 568 return positionInParentAfterNode(*tabSpan); | 568 return positionInParentAfterNode(*tabSpan); |
| 569 | 569 |
| 570 splitTextNodeContainingElement(toText(pos.computeContainerNode()), pos.offse
tInContainerNode()); | 570 splitTextNodeContainingElement(toText(pos.computeContainerNode()), pos.offse
tInContainerNode()); |
| 571 return positionInParentBeforeNode(*tabSpan); | 571 return positionInParentBeforeNode(*tabSpan); |
| 572 } | 572 } |
| 573 | 573 |
| 574 void CompositeEditCommand::insertNodeAtTabSpanPosition(PassRefPtrWillBeRawPtr<No
de> node, const Position& pos) | 574 void CompositeEditCommand::insertNodeAtTabSpanPosition(RawPtr<Node> node, const
Position& pos) |
| 575 { | 575 { |
| 576 // insert node before, after, or at split of tab span | 576 // insert node before, after, or at split of tab span |
| 577 insertNodeAt(node, positionOutsideTabSpan(pos)); | 577 insertNodeAt(node, positionOutsideTabSpan(pos)); |
| 578 } | 578 } |
| 579 | 579 |
| 580 void CompositeEditCommand::deleteSelection(bool smartDelete, bool mergeBlocksAft
erDelete, bool expandForSpecialElements, bool sanitizeMarkup) | 580 void CompositeEditCommand::deleteSelection(bool smartDelete, bool mergeBlocksAft
erDelete, bool expandForSpecialElements, bool sanitizeMarkup) |
| 581 { | 581 { |
| 582 if (endingSelection().isRange()) | 582 if (endingSelection().isRange()) |
| 583 applyCommandToComposite(DeleteSelectionCommand::create(document(), smart
Delete, mergeBlocksAfterDelete, expandForSpecialElements, sanitizeMarkup)); | 583 applyCommandToComposite(DeleteSelectionCommand::create(document(), smart
Delete, mergeBlocksAfterDelete, expandForSpecialElements, sanitizeMarkup)); |
| 584 } | 584 } |
| 585 | 585 |
| 586 void CompositeEditCommand::deleteSelection(const VisibleSelection &selection, bo
ol smartDelete, bool mergeBlocksAfterDelete, bool expandForSpecialElements, bool
sanitizeMarkup) | 586 void CompositeEditCommand::deleteSelection(const VisibleSelection &selection, bo
ol smartDelete, bool mergeBlocksAfterDelete, bool expandForSpecialElements, bool
sanitizeMarkup) |
| 587 { | 587 { |
| 588 if (selection.isRange()) | 588 if (selection.isRange()) |
| 589 applyCommandToComposite(DeleteSelectionCommand::create(selection, smartD
elete, mergeBlocksAfterDelete, expandForSpecialElements, sanitizeMarkup)); | 589 applyCommandToComposite(DeleteSelectionCommand::create(selection, smartD
elete, mergeBlocksAfterDelete, expandForSpecialElements, sanitizeMarkup)); |
| 590 } | 590 } |
| 591 | 591 |
| 592 void CompositeEditCommand::removeCSSProperty(PassRefPtrWillBeRawPtr<Element> ele
ment, CSSPropertyID property) | 592 void CompositeEditCommand::removeCSSProperty(RawPtr<Element> element, CSSPropert
yID property) |
| 593 { | 593 { |
| 594 applyCommandToComposite(RemoveCSSPropertyCommand::create(document(), element
, property)); | 594 applyCommandToComposite(RemoveCSSPropertyCommand::create(document(), element
, property)); |
| 595 } | 595 } |
| 596 | 596 |
| 597 void CompositeEditCommand::removeElementAttribute(PassRefPtrWillBeRawPtr<Element
> element, const QualifiedName& attribute) | 597 void CompositeEditCommand::removeElementAttribute(RawPtr<Element> element, const
QualifiedName& attribute) |
| 598 { | 598 { |
| 599 setNodeAttribute(element, attribute, AtomicString()); | 599 setNodeAttribute(element, attribute, AtomicString()); |
| 600 } | 600 } |
| 601 | 601 |
| 602 void CompositeEditCommand::setNodeAttribute(PassRefPtrWillBeRawPtr<Element> elem
ent, const QualifiedName& attribute, const AtomicString& value) | 602 void CompositeEditCommand::setNodeAttribute(RawPtr<Element> element, const Quali
fiedName& attribute, const AtomicString& value) |
| 603 { | 603 { |
| 604 applyCommandToComposite(SetNodeAttributeCommand::create(element, attribute,
value)); | 604 applyCommandToComposite(SetNodeAttributeCommand::create(element, attribute,
value)); |
| 605 } | 605 } |
| 606 | 606 |
| 607 static inline bool containsOnlyWhitespace(const String& text) | 607 static inline bool containsOnlyWhitespace(const String& text) |
| 608 { | 608 { |
| 609 for (unsigned i = 0; i < text.length(); ++i) { | 609 for (unsigned i = 0; i < text.length(); ++i) { |
| 610 if (!isWhitespace(text[i])) | 610 if (!isWhitespace(text[i])) |
| 611 return false; | 611 return false; |
| 612 } | 612 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 648 String text = toText(node)->data(); | 648 String text = toText(node)->data(); |
| 649 if (!isWhitespace(text[offset])) { | 649 if (!isWhitespace(text[offset])) { |
| 650 offset--; | 650 offset--; |
| 651 if (offset < 0 || !isWhitespace(text[offset])) | 651 if (offset < 0 || !isWhitespace(text[offset])) |
| 652 return; | 652 return; |
| 653 } | 653 } |
| 654 | 654 |
| 655 rebalanceWhitespaceOnTextSubstring(toText(node), position.offsetInContainerN
ode(), position.offsetInContainerNode()); | 655 rebalanceWhitespaceOnTextSubstring(toText(node), position.offsetInContainerN
ode(), position.offsetInContainerNode()); |
| 656 } | 656 } |
| 657 | 657 |
| 658 void CompositeEditCommand::rebalanceWhitespaceOnTextSubstring(PassRefPtrWillBeRa
wPtr<Text> prpTextNode, int startOffset, int endOffset) | 658 void CompositeEditCommand::rebalanceWhitespaceOnTextSubstring(RawPtr<Text> prpTe
xtNode, int startOffset, int endOffset) |
| 659 { | 659 { |
| 660 RefPtrWillBeRawPtr<Text> textNode = prpTextNode; | 660 RawPtr<Text> textNode = prpTextNode; |
| 661 | 661 |
| 662 String text = textNode->data(); | 662 String text = textNode->data(); |
| 663 ASSERT(!text.isEmpty()); | 663 ASSERT(!text.isEmpty()); |
| 664 | 664 |
| 665 // Set upstream and downstream to define the extent of the whitespace surrou
nding text[offset]. | 665 // Set upstream and downstream to define the extent of the whitespace surrou
nding text[offset]. |
| 666 int upstream = startOffset; | 666 int upstream = startOffset; |
| 667 while (upstream > 0 && isWhitespace(text[upstream - 1])) | 667 while (upstream > 0 && isWhitespace(text[upstream - 1])) |
| 668 upstream--; | 668 upstream--; |
| 669 | 669 |
| 670 int downstream = endOffset; | 670 int downstream = endOffset; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 729 { | 729 { |
| 730 VisibleSelection selection = endingSelection(); | 730 VisibleSelection selection = endingSelection(); |
| 731 if (selection.isNone()) | 731 if (selection.isNone()) |
| 732 return; | 732 return; |
| 733 | 733 |
| 734 rebalanceWhitespaceAt(selection.start()); | 734 rebalanceWhitespaceAt(selection.start()); |
| 735 if (selection.isRange()) | 735 if (selection.isRange()) |
| 736 rebalanceWhitespaceAt(selection.end()); | 736 rebalanceWhitespaceAt(selection.end()); |
| 737 } | 737 } |
| 738 | 738 |
| 739 void CompositeEditCommand::deleteInsignificantText(PassRefPtrWillBeRawPtr<Text>
textNode, unsigned start, unsigned end) | 739 void CompositeEditCommand::deleteInsignificantText(RawPtr<Text> textNode, unsign
ed start, unsigned end) |
| 740 { | 740 { |
| 741 if (!textNode || start >= end) | 741 if (!textNode || start >= end) |
| 742 return; | 742 return; |
| 743 | 743 |
| 744 document().updateLayout(); | 744 document().updateLayout(); |
| 745 | 745 |
| 746 LayoutText* textLayoutObject = textNode->layoutObject(); | 746 LayoutText* textLayoutObject = textNode->layoutObject(); |
| 747 if (!textLayoutObject) | 747 if (!textLayoutObject) |
| 748 return; | 748 return; |
| 749 | 749 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 818 } | 818 } |
| 819 | 819 |
| 820 void CompositeEditCommand::deleteInsignificantText(const Position& start, const
Position& end) | 820 void CompositeEditCommand::deleteInsignificantText(const Position& start, const
Position& end) |
| 821 { | 821 { |
| 822 if (start.isNull() || end.isNull()) | 822 if (start.isNull() || end.isNull()) |
| 823 return; | 823 return; |
| 824 | 824 |
| 825 if (comparePositions(start, end) >= 0) | 825 if (comparePositions(start, end) >= 0) |
| 826 return; | 826 return; |
| 827 | 827 |
| 828 WillBeHeapVector<RefPtrWillBeMember<Text>> nodes; | 828 HeapVector<Member<Text>> nodes; |
| 829 for (Node& node : NodeTraversal::startsAt(start.anchorNode())) { | 829 for (Node& node : NodeTraversal::startsAt(start.anchorNode())) { |
| 830 if (node.isTextNode()) | 830 if (node.isTextNode()) |
| 831 nodes.append(toText(&node)); | 831 nodes.append(toText(&node)); |
| 832 if (&node == end.anchorNode()) | 832 if (&node == end.anchorNode()) |
| 833 break; | 833 break; |
| 834 } | 834 } |
| 835 | 835 |
| 836 for (const auto& node : nodes) { | 836 for (const auto& node : nodes) { |
| 837 Text* textNode = node.get(); | 837 Text* textNode = node.get(); |
| 838 int startOffset = textNode == start.anchorNode() ? start.computeOffsetIn
ContainerNode() : 0; | 838 int startOffset = textNode == start.anchorNode() ? start.computeOffsetIn
ContainerNode() : 0; |
| 839 int endOffset = textNode == end.anchorNode() ? end.computeOffsetInContai
nerNode() : static_cast<int>(textNode->length()); | 839 int endOffset = textNode == end.anchorNode() ? end.computeOffsetInContai
nerNode() : static_cast<int>(textNode->length()); |
| 840 deleteInsignificantText(textNode, startOffset, endOffset); | 840 deleteInsignificantText(textNode, startOffset, endOffset); |
| 841 } | 841 } |
| 842 } | 842 } |
| 843 | 843 |
| 844 void CompositeEditCommand::deleteInsignificantTextDownstream(const Position& pos
) | 844 void CompositeEditCommand::deleteInsignificantTextDownstream(const Position& pos
) |
| 845 { | 845 { |
| 846 Position end = mostForwardCaretPosition(nextPositionOf(createVisiblePosition
(pos, VP_DEFAULT_AFFINITY)).deepEquivalent()); | 846 Position end = mostForwardCaretPosition(nextPositionOf(createVisiblePosition
(pos, VP_DEFAULT_AFFINITY)).deepEquivalent()); |
| 847 deleteInsignificantText(pos, end); | 847 deleteInsignificantText(pos, end); |
| 848 } | 848 } |
| 849 | 849 |
| 850 PassRefPtrWillBeRawPtr<HTMLBRElement> CompositeEditCommand::appendBlockPlacehold
er(PassRefPtrWillBeRawPtr<Element> container) | 850 RawPtr<HTMLBRElement> CompositeEditCommand::appendBlockPlaceholder(RawPtr<Elemen
t> container) |
| 851 { | 851 { |
| 852 if (!container) | 852 if (!container) |
| 853 return nullptr; | 853 return nullptr; |
| 854 | 854 |
| 855 document().updateLayoutIgnorePendingStylesheets(); | 855 document().updateLayoutIgnorePendingStylesheets(); |
| 856 | 856 |
| 857 // Should assert isLayoutBlockFlow || isInlineFlow when deletion improves. S
ee 4244964. | 857 // Should assert isLayoutBlockFlow || isInlineFlow when deletion improves. S
ee 4244964. |
| 858 ASSERT(container->layoutObject()); | 858 ASSERT(container->layoutObject()); |
| 859 | 859 |
| 860 RefPtrWillBeRawPtr<HTMLBRElement> placeholder = HTMLBRElement::create(docume
nt()); | 860 RawPtr<HTMLBRElement> placeholder = HTMLBRElement::create(document()); |
| 861 appendNode(placeholder, container); | 861 appendNode(placeholder, container); |
| 862 return placeholder.release(); | 862 return placeholder.release(); |
| 863 } | 863 } |
| 864 | 864 |
| 865 PassRefPtrWillBeRawPtr<HTMLBRElement> CompositeEditCommand::insertBlockPlacehold
er(const Position& pos) | 865 RawPtr<HTMLBRElement> CompositeEditCommand::insertBlockPlaceholder(const Positio
n& pos) |
| 866 { | 866 { |
| 867 if (pos.isNull()) | 867 if (pos.isNull()) |
| 868 return nullptr; | 868 return nullptr; |
| 869 | 869 |
| 870 // Should assert isLayoutBlockFlow || isInlineFlow when deletion improves. S
ee 4244964. | 870 // Should assert isLayoutBlockFlow || isInlineFlow when deletion improves. S
ee 4244964. |
| 871 ASSERT(pos.anchorNode()->layoutObject()); | 871 ASSERT(pos.anchorNode()->layoutObject()); |
| 872 | 872 |
| 873 RefPtrWillBeRawPtr<HTMLBRElement> placeholder = HTMLBRElement::create(docume
nt()); | 873 RawPtr<HTMLBRElement> placeholder = HTMLBRElement::create(document()); |
| 874 insertNodeAt(placeholder, pos); | 874 insertNodeAt(placeholder, pos); |
| 875 return placeholder.release(); | 875 return placeholder.release(); |
| 876 } | 876 } |
| 877 | 877 |
| 878 PassRefPtrWillBeRawPtr<HTMLBRElement> CompositeEditCommand::addBlockPlaceholderI
fNeeded(Element* container) | 878 RawPtr<HTMLBRElement> CompositeEditCommand::addBlockPlaceholderIfNeeded(Element*
container) |
| 879 { | 879 { |
| 880 if (!container) | 880 if (!container) |
| 881 return nullptr; | 881 return nullptr; |
| 882 | 882 |
| 883 document().updateLayoutIgnorePendingStylesheets(); | 883 document().updateLayoutIgnorePendingStylesheets(); |
| 884 | 884 |
| 885 LayoutObject* layoutObject = container->layoutObject(); | 885 LayoutObject* layoutObject = container->layoutObject(); |
| 886 if (!layoutObject || !layoutObject->isLayoutBlockFlow()) | 886 if (!layoutObject || !layoutObject->isLayoutBlockFlow()) |
| 887 return nullptr; | 887 return nullptr; |
| 888 | 888 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 902 | 902 |
| 903 // We are certain that the position is at a line break, but it may be a br o
r a preserved newline. | 903 // We are certain that the position is at a line break, but it may be a br o
r a preserved newline. |
| 904 if (isHTMLBRElement(*p.anchorNode())) { | 904 if (isHTMLBRElement(*p.anchorNode())) { |
| 905 removeNode(p.anchorNode()); | 905 removeNode(p.anchorNode()); |
| 906 return; | 906 return; |
| 907 } | 907 } |
| 908 | 908 |
| 909 deleteTextFromNode(toText(p.anchorNode()), p.offsetInContainerNode(), 1); | 909 deleteTextFromNode(toText(p.anchorNode()), p.offsetInContainerNode(), 1); |
| 910 } | 910 } |
| 911 | 911 |
| 912 PassRefPtrWillBeRawPtr<HTMLElement> CompositeEditCommand::insertNewDefaultParagr
aphElementAt(const Position& position) | 912 RawPtr<HTMLElement> CompositeEditCommand::insertNewDefaultParagraphElementAt(con
st Position& position) |
| 913 { | 913 { |
| 914 RefPtrWillBeRawPtr<HTMLElement> paragraphElement = createDefaultParagraphEle
ment(document()); | 914 RawPtr<HTMLElement> paragraphElement = createDefaultParagraphElement(documen
t()); |
| 915 paragraphElement->appendChild(HTMLBRElement::create(document())); | 915 paragraphElement->appendChild(HTMLBRElement::create(document())); |
| 916 insertNodeAt(paragraphElement, position); | 916 insertNodeAt(paragraphElement, position); |
| 917 return paragraphElement.release(); | 917 return paragraphElement.release(); |
| 918 } | 918 } |
| 919 | 919 |
| 920 // If the paragraph is not entirely within it's own block, create one and move t
he paragraph into | 920 // If the paragraph is not entirely within it's own block, create one and move t
he paragraph into |
| 921 // it, and return that block. Otherwise return 0. | 921 // it, and return that block. Otherwise return 0. |
| 922 PassRefPtrWillBeRawPtr<HTMLElement> CompositeEditCommand::moveParagraphContentsT
oNewBlockIfNecessary(const Position& pos) | 922 RawPtr<HTMLElement> CompositeEditCommand::moveParagraphContentsToNewBlockIfNeces
sary(const Position& pos) |
| 923 { | 923 { |
| 924 ASSERT(isEditablePosition(pos, ContentIsEditable, DoNotUpdateStyle)); | 924 ASSERT(isEditablePosition(pos, ContentIsEditable, DoNotUpdateStyle)); |
| 925 | 925 |
| 926 // It's strange that this function is responsible for verifying that pos has
not been invalidated | 926 // It's strange that this function is responsible for verifying that pos has
not been invalidated |
| 927 // by an earlier call to this function. The caller, applyBlockStyle, should
do this. | 927 // by an earlier call to this function. The caller, applyBlockStyle, should
do this. |
| 928 VisiblePosition visiblePos = createVisiblePosition(pos, VP_DEFAULT_AFFINITY)
; | 928 VisiblePosition visiblePos = createVisiblePosition(pos, VP_DEFAULT_AFFINITY)
; |
| 929 VisiblePosition visibleParagraphStart = startOfParagraph(visiblePos); | 929 VisiblePosition visibleParagraphStart = startOfParagraph(visiblePos); |
| 930 VisiblePosition visibleParagraphEnd = endOfParagraph(visiblePos); | 930 VisiblePosition visibleParagraphEnd = endOfParagraph(visiblePos); |
| 931 VisiblePosition next = nextPositionOf(visibleParagraphEnd); | 931 VisiblePosition next = nextPositionOf(visibleParagraphEnd); |
| 932 VisiblePosition visibleEnd = next.isNotNull() ? next : visibleParagraphEnd; | 932 VisiblePosition visibleEnd = next.isNotNull() ? next : visibleParagraphEnd; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 960 return nullptr; | 960 return nullptr; |
| 961 } else if (isEndOfEditableOrNonEditableContent(visibleEnd)) { | 961 } else if (isEndOfEditableOrNonEditableContent(visibleEnd)) { |
| 962 // At the end of the editable region. We can bail here as well. | 962 // At the end of the editable region. We can bail here as well. |
| 963 return nullptr; | 963 return nullptr; |
| 964 } | 964 } |
| 965 } | 965 } |
| 966 | 966 |
| 967 if (visibleParagraphEnd.isNull()) | 967 if (visibleParagraphEnd.isNull()) |
| 968 return nullptr; | 968 return nullptr; |
| 969 | 969 |
| 970 RefPtrWillBeRawPtr<HTMLElement> newBlock = insertNewDefaultParagraphElementA
t(upstreamStart); | 970 RawPtr<HTMLElement> newBlock = insertNewDefaultParagraphElementAt(upstreamSt
art); |
| 971 | 971 |
| 972 bool endWasBr = isHTMLBRElement(*visibleParagraphEnd.deepEquivalent().anchor
Node()); | 972 bool endWasBr = isHTMLBRElement(*visibleParagraphEnd.deepEquivalent().anchor
Node()); |
| 973 | 973 |
| 974 // Inserting default paragraph element can change visible position. We | 974 // Inserting default paragraph element can change visible position. We |
| 975 // should update visible positions before use them. | 975 // should update visible positions before use them. |
| 976 visiblePos = createVisiblePosition(pos, VP_DEFAULT_AFFINITY); | 976 visiblePos = createVisiblePosition(pos, VP_DEFAULT_AFFINITY); |
| 977 visibleParagraphStart = startOfParagraph(visiblePos); | 977 visibleParagraphStart = startOfParagraph(visiblePos); |
| 978 visibleParagraphEnd = endOfParagraph(visiblePos); | 978 visibleParagraphEnd = endOfParagraph(visiblePos); |
| 979 moveParagraphs(visibleParagraphStart, visibleParagraphEnd, createVisiblePosi
tion(firstPositionInNode(newBlock.get()))); | 979 moveParagraphs(visibleParagraphStart, visibleParagraphEnd, createVisiblePosi
tion(firstPositionInNode(newBlock.get()))); |
| 980 | 980 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1001 // Clone the paragraph between start and end under blockElement, | 1001 // Clone the paragraph between start and end under blockElement, |
| 1002 // preserving the hierarchy up to outerNode. | 1002 // preserving the hierarchy up to outerNode. |
| 1003 | 1003 |
| 1004 void CompositeEditCommand::cloneParagraphUnderNewElement(const Position& start,
const Position& end, Node* passedOuterNode, Element* blockElement) | 1004 void CompositeEditCommand::cloneParagraphUnderNewElement(const Position& start,
const Position& end, Node* passedOuterNode, Element* blockElement) |
| 1005 { | 1005 { |
| 1006 ASSERT(comparePositions(start, end) <= 0); | 1006 ASSERT(comparePositions(start, end) <= 0); |
| 1007 ASSERT(passedOuterNode); | 1007 ASSERT(passedOuterNode); |
| 1008 ASSERT(blockElement); | 1008 ASSERT(blockElement); |
| 1009 | 1009 |
| 1010 // First we clone the outerNode | 1010 // First we clone the outerNode |
| 1011 RefPtrWillBeRawPtr<Node> lastNode = nullptr; | 1011 RawPtr<Node> lastNode = nullptr; |
| 1012 RefPtrWillBeRawPtr<Node> outerNode = passedOuterNode; | 1012 RawPtr<Node> outerNode = passedOuterNode; |
| 1013 | 1013 |
| 1014 if (outerNode->isRootEditableElement()) { | 1014 if (outerNode->isRootEditableElement()) { |
| 1015 lastNode = blockElement; | 1015 lastNode = blockElement; |
| 1016 } else { | 1016 } else { |
| 1017 lastNode = outerNode->cloneNode(isDisplayInsideTable(outerNode.get())); | 1017 lastNode = outerNode->cloneNode(isDisplayInsideTable(outerNode.get())); |
| 1018 appendNode(lastNode, blockElement); | 1018 appendNode(lastNode, blockElement); |
| 1019 } | 1019 } |
| 1020 | 1020 |
| 1021 if (start.anchorNode() != outerNode && lastNode->isElementNode() && start.an
chorNode()->isDescendantOf(outerNode.get())) { | 1021 if (start.anchorNode() != outerNode && lastNode->isElementNode() && start.an
chorNode()->isDescendantOf(outerNode.get())) { |
| 1022 WillBeHeapVector<RefPtrWillBeMember<Node>> ancestors; | 1022 HeapVector<Member<Node>> ancestors; |
| 1023 | 1023 |
| 1024 // Insert each node from innerNode to outerNode (excluded) in a list. | 1024 // Insert each node from innerNode to outerNode (excluded) in a list. |
| 1025 for (Node* n = start.anchorNode(); n && n != outerNode; n = n->parentNod
e()) | 1025 for (Node* n = start.anchorNode(); n && n != outerNode; n = n->parentNod
e()) |
| 1026 ancestors.append(n); | 1026 ancestors.append(n); |
| 1027 | 1027 |
| 1028 // Clone every node between start.anchorNode() and outerBlock. | 1028 // Clone every node between start.anchorNode() and outerBlock. |
| 1029 | 1029 |
| 1030 for (size_t i = ancestors.size(); i != 0; --i) { | 1030 for (size_t i = ancestors.size(); i != 0; --i) { |
| 1031 Node* item = ancestors[i - 1].get(); | 1031 Node* item = ancestors[i - 1].get(); |
| 1032 RefPtrWillBeRawPtr<Node> child = item->cloneNode(isDisplayInsideTabl
e(item)); | 1032 RawPtr<Node> child = item->cloneNode(isDisplayInsideTable(item)); |
| 1033 appendNode(child, toElement(lastNode)); | 1033 appendNode(child, toElement(lastNode)); |
| 1034 lastNode = child.release(); | 1034 lastNode = child.release(); |
| 1035 } | 1035 } |
| 1036 } | 1036 } |
| 1037 | 1037 |
| 1038 // Scripts specified in javascript protocol may remove |outerNode| | 1038 // Scripts specified in javascript protocol may remove |outerNode| |
| 1039 // during insertion, e.g. <iframe src="javascript:..."> | 1039 // during insertion, e.g. <iframe src="javascript:..."> |
| 1040 if (!outerNode->inDocument()) | 1040 if (!outerNode->inDocument()) |
| 1041 return; | 1041 return; |
| 1042 | 1042 |
| 1043 // Handle the case of paragraphs with more than one node, | 1043 // Handle the case of paragraphs with more than one node, |
| 1044 // cloning all the siblings until end.anchorNode() is reached. | 1044 // cloning all the siblings until end.anchorNode() is reached. |
| 1045 | 1045 |
| 1046 if (start.anchorNode() != end.anchorNode() && !start.anchorNode()->isDescend
antOf(end.anchorNode())) { | 1046 if (start.anchorNode() != end.anchorNode() && !start.anchorNode()->isDescend
antOf(end.anchorNode())) { |
| 1047 // If end is not a descendant of outerNode we need to | 1047 // If end is not a descendant of outerNode we need to |
| 1048 // find the first common ancestor to increase the scope | 1048 // find the first common ancestor to increase the scope |
| 1049 // of our nextSibling traversal. | 1049 // of our nextSibling traversal. |
| 1050 while (outerNode && !end.anchorNode()->isDescendantOf(outerNode.get()))
{ | 1050 while (outerNode && !end.anchorNode()->isDescendantOf(outerNode.get()))
{ |
| 1051 outerNode = outerNode->parentNode(); | 1051 outerNode = outerNode->parentNode(); |
| 1052 } | 1052 } |
| 1053 | 1053 |
| 1054 if (!outerNode) | 1054 if (!outerNode) |
| 1055 return; | 1055 return; |
| 1056 | 1056 |
| 1057 RefPtrWillBeRawPtr<Node> startNode = start.anchorNode(); | 1057 RawPtr<Node> startNode = start.anchorNode(); |
| 1058 for (RefPtrWillBeRawPtr<Node> node = NodeTraversal::nextSkippingChildren
(*startNode, outerNode.get()); node; node = NodeTraversal::nextSkippingChildren(
*node, outerNode.get())) { | 1058 for (RawPtr<Node> node = NodeTraversal::nextSkippingChildren(*startNode,
outerNode.get()); node; node = NodeTraversal::nextSkippingChildren(*node, outer
Node.get())) { |
| 1059 // Move lastNode up in the tree as much as node was moved up in the | 1059 // Move lastNode up in the tree as much as node was moved up in the |
| 1060 // tree by NodeTraversal::nextSkippingChildren, so that the relative
depth between | 1060 // tree by NodeTraversal::nextSkippingChildren, so that the relative
depth between |
| 1061 // node and the original start node is maintained in the clone. | 1061 // node and the original start node is maintained in the clone. |
| 1062 while (startNode && lastNode && startNode->parentNode() != node->par
entNode()) { | 1062 while (startNode && lastNode && startNode->parentNode() != node->par
entNode()) { |
| 1063 startNode = startNode->parentNode(); | 1063 startNode = startNode->parentNode(); |
| 1064 lastNode = lastNode->parentNode(); | 1064 lastNode = lastNode->parentNode(); |
| 1065 } | 1065 } |
| 1066 | 1066 |
| 1067 if (!lastNode || !lastNode->parentNode()) | 1067 if (!lastNode || !lastNode->parentNode()) |
| 1068 return; | 1068 return; |
| 1069 | 1069 |
| 1070 RefPtrWillBeRawPtr<Node> clonedNode = node->cloneNode(true); | 1070 RawPtr<Node> clonedNode = node->cloneNode(true); |
| 1071 insertNodeAfter(clonedNode, lastNode); | 1071 insertNodeAfter(clonedNode, lastNode); |
| 1072 lastNode = clonedNode.release(); | 1072 lastNode = clonedNode.release(); |
| 1073 if (node == end.anchorNode() || end.anchorNode()->isDescendantOf(nod
e.get())) | 1073 if (node == end.anchorNode() || end.anchorNode()->isDescendantOf(nod
e.get())) |
| 1074 break; | 1074 break; |
| 1075 } | 1075 } |
| 1076 } | 1076 } |
| 1077 } | 1077 } |
| 1078 | 1078 |
| 1079 | 1079 |
| 1080 // There are bugs in deletion when it removes a fully selected table/list. | 1080 // There are bugs in deletion when it removes a fully selected table/list. |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1213 VisiblePosition beforeParagraph = previousPositionOf(startOfParagraphToMove,
CannotCrossEditingBoundary); | 1213 VisiblePosition beforeParagraph = previousPositionOf(startOfParagraphToMove,
CannotCrossEditingBoundary); |
| 1214 VisiblePosition afterParagraph = nextPositionOf(endOfParagraphToMove, Cannot
CrossEditingBoundary); | 1214 VisiblePosition afterParagraph = nextPositionOf(endOfParagraphToMove, Cannot
CrossEditingBoundary); |
| 1215 | 1215 |
| 1216 // We upstream() the end and downstream() the start so that we don't include
collapsed whitespace in the move. | 1216 // We upstream() the end and downstream() the start so that we don't include
collapsed whitespace in the move. |
| 1217 // When we paste a fragment, spaces after the end and before the start are t
reated as though they were rendered. | 1217 // When we paste a fragment, spaces after the end and before the start are t
reated as though they were rendered. |
| 1218 Position start = mostForwardCaretPosition(startOfParagraphToMove.deepEquival
ent()); | 1218 Position start = mostForwardCaretPosition(startOfParagraphToMove.deepEquival
ent()); |
| 1219 Position end = mostBackwardCaretPosition(endOfParagraphToMove.deepEquivalent
()); | 1219 Position end = mostBackwardCaretPosition(endOfParagraphToMove.deepEquivalent
()); |
| 1220 | 1220 |
| 1221 // FIXME: This is an inefficient way to preserve style on nodes in the parag
raph to move. It | 1221 // FIXME: This is an inefficient way to preserve style on nodes in the parag
raph to move. It |
| 1222 // shouldn't matter though, since moved paragraphs will usually be quite sma
ll. | 1222 // shouldn't matter though, since moved paragraphs will usually be quite sma
ll. |
| 1223 RefPtrWillBeRawPtr<DocumentFragment> fragment = startOfParagraphToMove.deepE
quivalent() != endOfParagraphToMove.deepEquivalent() ? | 1223 RawPtr<DocumentFragment> fragment = startOfParagraphToMove.deepEquivalent()
!= endOfParagraphToMove.deepEquivalent() ? |
| 1224 createFragmentFromMarkup(document(), createMarkup(start.parentAnchoredEq
uivalent(), end.parentAnchoredEquivalent(), DoNotAnnotateForInterchange, Convert
BlocksToInlines::Convert, DoNotResolveURLs, constrainingAncestor), "") : nullptr
; | 1224 createFragmentFromMarkup(document(), createMarkup(start.parentAnchoredEq
uivalent(), end.parentAnchoredEquivalent(), DoNotAnnotateForInterchange, Convert
BlocksToInlines::Convert, DoNotResolveURLs, constrainingAncestor), "") : nullptr
; |
| 1225 | 1225 |
| 1226 // A non-empty paragraph's style is moved when we copy and move it. We don'
t move | 1226 // A non-empty paragraph's style is moved when we copy and move it. We don'
t move |
| 1227 // anything if we're given an empty paragraph, but an empty paragraph can ha
ve style | 1227 // anything if we're given an empty paragraph, but an empty paragraph can ha
ve style |
| 1228 // too, <div><b><br></b></div> for example. Save it so that we can preserve
it later. | 1228 // too, <div><b><br></b></div> for example. Save it so that we can preserve
it later. |
| 1229 RefPtrWillBeRawPtr<EditingStyle> styleInEmptyParagraph = nullptr; | 1229 RawPtr<EditingStyle> styleInEmptyParagraph = nullptr; |
| 1230 if (startOfParagraphToMove.deepEquivalent() == endOfParagraphToMove.deepEqui
valent() && preserveStyle) { | 1230 if (startOfParagraphToMove.deepEquivalent() == endOfParagraphToMove.deepEqui
valent() && preserveStyle) { |
| 1231 styleInEmptyParagraph = EditingStyle::create(startOfParagraphToMove.deep
Equivalent()); | 1231 styleInEmptyParagraph = EditingStyle::create(startOfParagraphToMove.deep
Equivalent()); |
| 1232 styleInEmptyParagraph->mergeTypingStyle(&document()); | 1232 styleInEmptyParagraph->mergeTypingStyle(&document()); |
| 1233 // The moved paragraph should assume the block style of the destination. | 1233 // The moved paragraph should assume the block style of the destination. |
| 1234 styleInEmptyParagraph->removeBlockProperties(); | 1234 styleInEmptyParagraph->removeBlockProperties(); |
| 1235 } | 1235 } |
| 1236 | 1236 |
| 1237 // FIXME (5098931): We should add a new insert action "WebViewInsertActionMo
ved" and call shouldInsertFragment here. | 1237 // FIXME (5098931): We should add a new insert action "WebViewInsertActionMo
ved" and call shouldInsertFragment here. |
| 1238 | 1238 |
| 1239 setEndingSelection(VisibleSelection(start, end)); | 1239 setEndingSelection(VisibleSelection(start, end)); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1291 return; | 1291 return; |
| 1292 EphemeralRange endRange = PlainTextRange(destinationIndex + endIndex).create
RangeForSelection(*documentElement); | 1292 EphemeralRange endRange = PlainTextRange(destinationIndex + endIndex).create
RangeForSelection(*documentElement); |
| 1293 if (endRange.isNull()) | 1293 if (endRange.isNull()) |
| 1294 return; | 1294 return; |
| 1295 setEndingSelection(VisibleSelection(startRange.startPosition(), endRange.sta
rtPosition(), TextAffinity::Downstream, originalIsDirectional)); | 1295 setEndingSelection(VisibleSelection(startRange.startPosition(), endRange.sta
rtPosition(), TextAffinity::Downstream, originalIsDirectional)); |
| 1296 } | 1296 } |
| 1297 | 1297 |
| 1298 // FIXME: Send an appropriate shouldDeleteRange call. | 1298 // FIXME: Send an appropriate shouldDeleteRange call. |
| 1299 bool CompositeEditCommand::breakOutOfEmptyListItem() | 1299 bool CompositeEditCommand::breakOutOfEmptyListItem() |
| 1300 { | 1300 { |
| 1301 RefPtrWillBeRawPtr<Node> emptyListItem = enclosingEmptyListItem(endingSelect
ion().visibleStart()); | 1301 RawPtr<Node> emptyListItem = enclosingEmptyListItem(endingSelection().visibl
eStart()); |
| 1302 if (!emptyListItem) | 1302 if (!emptyListItem) |
| 1303 return false; | 1303 return false; |
| 1304 | 1304 |
| 1305 RefPtrWillBeRawPtr<EditingStyle> style = EditingStyle::create(endingSelectio
n().start()); | 1305 RawPtr<EditingStyle> style = EditingStyle::create(endingSelection().start())
; |
| 1306 style->mergeTypingStyle(&document()); | 1306 style->mergeTypingStyle(&document()); |
| 1307 | 1307 |
| 1308 RefPtrWillBeRawPtr<ContainerNode> listNode = emptyListItem->parentNode(); | 1308 RawPtr<ContainerNode> listNode = emptyListItem->parentNode(); |
| 1309 // FIXME: Can't we do something better when the immediate parent wasn't a li
st node? | 1309 // FIXME: Can't we do something better when the immediate parent wasn't a li
st node? |
| 1310 if (!listNode | 1310 if (!listNode |
| 1311 || (!isHTMLUListElement(*listNode) && !isHTMLOListElement(*listNode)) | 1311 || (!isHTMLUListElement(*listNode) && !isHTMLOListElement(*listNode)) |
| 1312 || !listNode->hasEditableStyle() | 1312 || !listNode->hasEditableStyle() |
| 1313 || listNode == emptyListItem->rootEditableElement()) | 1313 || listNode == emptyListItem->rootEditableElement()) |
| 1314 return false; | 1314 return false; |
| 1315 | 1315 |
| 1316 RefPtrWillBeRawPtr<HTMLElement> newBlock = nullptr; | 1316 RawPtr<HTMLElement> newBlock = nullptr; |
| 1317 if (ContainerNode* blockEnclosingList = listNode->parentNode()) { | 1317 if (ContainerNode* blockEnclosingList = listNode->parentNode()) { |
| 1318 if (isHTMLLIElement(*blockEnclosingList)) { // listNode is inside anothe
r list item | 1318 if (isHTMLLIElement(*blockEnclosingList)) { // listNode is inside anothe
r list item |
| 1319 if (visiblePositionAfterNode(*blockEnclosingList).deepEquivalent() =
= visiblePositionAfterNode(*listNode).deepEquivalent()) { | 1319 if (visiblePositionAfterNode(*blockEnclosingList).deepEquivalent() =
= visiblePositionAfterNode(*listNode).deepEquivalent()) { |
| 1320 // If listNode appears at the end of the outer list item, then m
ove listNode outside of this list item | 1320 // If listNode appears at the end of the outer list item, then m
ove listNode outside of this list item |
| 1321 // 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 | 1321 // 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 |
| 1322 // If listNode does NOT appear at the end, then we should consid
er it as a regular paragraph. | 1322 // If listNode does NOT appear at the end, then we should consid
er it as a regular paragraph. |
| 1323 // 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 | 1323 // 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 |
| 1324 splitElement(toElement(blockEnclosingList), listNode); | 1324 splitElement(toElement(blockEnclosingList), listNode); |
| 1325 removeNodePreservingChildren(listNode->parentNode()); | 1325 removeNodePreservingChildren(listNode->parentNode()); |
| 1326 newBlock = HTMLLIElement::create(document()); | 1326 newBlock = HTMLLIElement::create(document()); |
| 1327 } | 1327 } |
| 1328 // If listNode does NOT appear at the end of the outer list item, th
en behave as if in a regular paragraph. | 1328 // If listNode does NOT appear at the end of the outer list item, th
en behave as if in a regular paragraph. |
| 1329 } else if (isHTMLOListElement(*blockEnclosingList) || isHTMLUListElement
(*blockEnclosingList)) { | 1329 } else if (isHTMLOListElement(*blockEnclosingList) || isHTMLUListElement
(*blockEnclosingList)) { |
| 1330 newBlock = HTMLLIElement::create(document()); | 1330 newBlock = HTMLLIElement::create(document()); |
| 1331 } | 1331 } |
| 1332 } | 1332 } |
| 1333 if (!newBlock) | 1333 if (!newBlock) |
| 1334 newBlock = createDefaultParagraphElement(document()); | 1334 newBlock = createDefaultParagraphElement(document()); |
| 1335 | 1335 |
| 1336 RefPtrWillBeRawPtr<Node> previousListNode = emptyListItem->isElementNode() ?
ElementTraversal::previousSibling(*emptyListItem): emptyListItem->previousSibli
ng(); | 1336 RawPtr<Node> previousListNode = emptyListItem->isElementNode() ? ElementTrav
ersal::previousSibling(*emptyListItem): emptyListItem->previousSibling(); |
| 1337 RefPtrWillBeRawPtr<Node> nextListNode = emptyListItem->isElementNode() ? Ele
mentTraversal::nextSibling(*emptyListItem): emptyListItem->nextSibling(); | 1337 RawPtr<Node> nextListNode = emptyListItem->isElementNode() ? ElementTraversa
l::nextSibling(*emptyListItem): emptyListItem->nextSibling(); |
| 1338 if (isListItem(nextListNode.get()) || isHTMLListElement(nextListNode.get()))
{ | 1338 if (isListItem(nextListNode.get()) || isHTMLListElement(nextListNode.get()))
{ |
| 1339 // If emptyListItem follows another list item or nested list, split the
list node. | 1339 // If emptyListItem follows another list item or nested list, split the
list node. |
| 1340 if (isListItem(previousListNode.get()) || isHTMLListElement(previousList
Node.get())) | 1340 if (isListItem(previousListNode.get()) || isHTMLListElement(previousList
Node.get())) |
| 1341 splitElement(toElement(listNode), emptyListItem); | 1341 splitElement(toElement(listNode), emptyListItem); |
| 1342 | 1342 |
| 1343 // If emptyListItem is followed by other list item or nested list, then
insert newBlock before the list node. | 1343 // If emptyListItem is followed by other list item or nested list, then
insert newBlock before the list node. |
| 1344 // Because we have splitted the element, emptyListItem is the first elem
ent in the list node. | 1344 // Because we have splitted the element, emptyListItem is the first elem
ent in the list node. |
| 1345 // i.e. insert newBlock before ul or ol whose first element is emptyList
Item | 1345 // i.e. insert newBlock before ul or ol whose first element is emptyList
Item |
| 1346 insertNodeBefore(newBlock, listNode); | 1346 insertNodeBefore(newBlock, listNode); |
| 1347 removeNode(emptyListItem); | 1347 removeNode(emptyListItem); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1375 return false; | 1375 return false; |
| 1376 | 1376 |
| 1377 if (!isStartOfParagraph(caret) || !isEndOfParagraph(caret)) | 1377 if (!isStartOfParagraph(caret) || !isEndOfParagraph(caret)) |
| 1378 return false; | 1378 return false; |
| 1379 | 1379 |
| 1380 VisiblePosition previous = previousPositionOf(caret, CannotCrossEditingBound
ary); | 1380 VisiblePosition previous = previousPositionOf(caret, CannotCrossEditingBound
ary); |
| 1381 // Only move forward if there's nothing before the caret, or if there's unqu
oted content before it. | 1381 // Only move forward if there's nothing before the caret, or if there's unqu
oted content before it. |
| 1382 if (enclosingNodeOfType(previous.deepEquivalent(), &isMailHTMLBlockquoteElem
ent)) | 1382 if (enclosingNodeOfType(previous.deepEquivalent(), &isMailHTMLBlockquoteElem
ent)) |
| 1383 return false; | 1383 return false; |
| 1384 | 1384 |
| 1385 RefPtrWillBeRawPtr<HTMLBRElement> br = HTMLBRElement::create(document()); | 1385 RawPtr<HTMLBRElement> br = HTMLBRElement::create(document()); |
| 1386 // We want to replace this quoted paragraph with an unquoted one, so insert
a br | 1386 // We want to replace this quoted paragraph with an unquoted one, so insert
a br |
| 1387 // to hold the caret before the highest blockquote. | 1387 // to hold the caret before the highest blockquote. |
| 1388 insertNodeBefore(br, highestBlockquote); | 1388 insertNodeBefore(br, highestBlockquote); |
| 1389 VisiblePosition atBR = createVisiblePosition(positionBeforeNode(br.get())); | 1389 VisiblePosition atBR = createVisiblePosition(positionBeforeNode(br.get())); |
| 1390 // If the br we inserted collapsed, for example foo<br><blockquote>...</bloc
kquote>, insert | 1390 // If the br we inserted collapsed, for example foo<br><blockquote>...</bloc
kquote>, insert |
| 1391 // a second one. | 1391 // a second one. |
| 1392 if (!isStartOfParagraph(atBR)) | 1392 if (!isStartOfParagraph(atBR)) |
| 1393 insertNodeBefore(HTMLBRElement::create(document()), br); | 1393 insertNodeBefore(HTMLBRElement::create(document()), br); |
| 1394 setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional())
); | 1394 setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional())
); |
| 1395 | 1395 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1472 } | 1472 } |
| 1473 | 1473 |
| 1474 if (result.isNull() || !rootEditableElementOf(result)) | 1474 if (result.isNull() || !rootEditableElementOf(result)) |
| 1475 result = original; | 1475 result = original; |
| 1476 | 1476 |
| 1477 return result; | 1477 return result; |
| 1478 } | 1478 } |
| 1479 | 1479 |
| 1480 // Splits the tree parent by parent until we reach the specified ancestor. We us
e VisiblePositions | 1480 // Splits the tree parent by parent until we reach the specified ancestor. We us
e VisiblePositions |
| 1481 // to determine if the split is necessary. Returns the last split node. | 1481 // to determine if the split is necessary. Returns the last split node. |
| 1482 PassRefPtrWillBeRawPtr<Node> CompositeEditCommand::splitTreeToNode(Node* start,
Node* end, bool shouldSplitAncestor) | 1482 RawPtr<Node> CompositeEditCommand::splitTreeToNode(Node* start, Node* end, bool
shouldSplitAncestor) |
| 1483 { | 1483 { |
| 1484 ASSERT(start); | 1484 ASSERT(start); |
| 1485 ASSERT(end); | 1485 ASSERT(end); |
| 1486 ASSERT(start != end); | 1486 ASSERT(start != end); |
| 1487 | 1487 |
| 1488 if (shouldSplitAncestor && end->parentNode()) | 1488 if (shouldSplitAncestor && end->parentNode()) |
| 1489 end = end->parentNode(); | 1489 end = end->parentNode(); |
| 1490 if (!start->isDescendantOf(end)) | 1490 if (!start->isDescendantOf(end)) |
| 1491 return end; | 1491 return end; |
| 1492 | 1492 |
| 1493 RefPtrWillBeRawPtr<Node> endNode = end; | 1493 RawPtr<Node> endNode = end; |
| 1494 RefPtrWillBeRawPtr<Node> node = nullptr; | 1494 RawPtr<Node> node = nullptr; |
| 1495 for (node = start; node->parentNode() != endNode; node = node->parentNode())
{ | 1495 for (node = start; node->parentNode() != endNode; node = node->parentNode())
{ |
| 1496 Element* parentElement = node->parentElement(); | 1496 Element* parentElement = node->parentElement(); |
| 1497 if (!parentElement) | 1497 if (!parentElement) |
| 1498 break; | 1498 break; |
| 1499 // Do not split a node when doing so introduces an empty node. | 1499 // Do not split a node when doing so introduces an empty node. |
| 1500 VisiblePosition positionInParent = createVisiblePosition(firstPositionIn
Node(parentElement)); | 1500 VisiblePosition positionInParent = createVisiblePosition(firstPositionIn
Node(parentElement)); |
| 1501 VisiblePosition positionInNode = createVisiblePosition(firstPositionInOr
BeforeNode(node.get())); | 1501 VisiblePosition positionInNode = createVisiblePosition(firstPositionInOr
BeforeNode(node.get())); |
| 1502 if (positionInParent.deepEquivalent() != positionInNode.deepEquivalent()
) | 1502 if (positionInParent.deepEquivalent() != positionInNode.deepEquivalent()
) |
| 1503 splitElement(parentElement, node); | 1503 splitElement(parentElement, node); |
| 1504 } | 1504 } |
| 1505 | 1505 |
| 1506 return node.release(); | 1506 return node.release(); |
| 1507 } | 1507 } |
| 1508 | 1508 |
| 1509 DEFINE_TRACE(CompositeEditCommand) | 1509 DEFINE_TRACE(CompositeEditCommand) |
| 1510 { | 1510 { |
| 1511 visitor->trace(m_commands); | 1511 visitor->trace(m_commands); |
| 1512 visitor->trace(m_composition); | 1512 visitor->trace(m_composition); |
| 1513 EditCommand::trace(visitor); | 1513 EditCommand::trace(visitor); |
| 1514 } | 1514 } |
| 1515 | 1515 |
| 1516 } // namespace blink | 1516 } // namespace blink |
| OLD | NEW |