| 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 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 68 #include "core/rendering/RenderBlock.h" | 68 #include "core/rendering/RenderBlock.h" |
| 69 #include "core/rendering/RenderListItem.h" | 69 #include "core/rendering/RenderListItem.h" |
| 70 #include "core/rendering/RenderText.h" | 70 #include "core/rendering/RenderText.h" |
| 71 | 71 |
| 72 using namespace std; | 72 using namespace std; |
| 73 | 73 |
| 74 namespace WebCore { | 74 namespace WebCore { |
| 75 | 75 |
| 76 using namespace HTMLNames; | 76 using namespace HTMLNames; |
| 77 | 77 |
| 78 PassRefPtr<EditCommandComposition> EditCommandComposition::create(Document* docu
ment, | 78 PassRefPtrWillBeRawPtr<EditCommandComposition> EditCommandComposition::create(Do
cument* document, |
| 79 const VisibleSelection& startingSelection, const VisibleSelection& endingSel
ection, EditAction editAction) | 79 const VisibleSelection& startingSelection, const VisibleSelection& endingSel
ection, EditAction editAction) |
| 80 { | 80 { |
| 81 return adoptRef(new EditCommandComposition(document, startingSelection, endi
ngSelection, editAction)); | 81 return adoptRefWillBeNoop(new EditCommandComposition(document, startingSelec
tion, endingSelection, editAction)); |
| 82 } | 82 } |
| 83 | 83 |
| 84 EditCommandComposition::EditCommandComposition(Document* document, const Visible
Selection& startingSelection, const VisibleSelection& endingSelection, EditActio
n editAction) | 84 EditCommandComposition::EditCommandComposition(Document* document, const Visible
Selection& startingSelection, const VisibleSelection& endingSelection, EditActio
n editAction) |
| 85 : m_document(document) | 85 : m_document(document) |
| 86 , m_startingSelection(startingSelection) | 86 , m_startingSelection(startingSelection) |
| 87 , m_endingSelection(endingSelection) | 87 , m_endingSelection(endingSelection) |
| 88 , m_startingRootEditableElement(startingSelection.rootEditableElement()) | 88 , m_startingRootEditableElement(startingSelection.rootEditableElement()) |
| 89 , m_endingRootEditableElement(endingSelection.rootEditableElement()) | 89 , m_endingRootEditableElement(endingSelection.rootEditableElement()) |
| 90 , m_editAction(editAction) | 90 , m_editAction(editAction) |
| 91 { | 91 { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 m_startingSelection = selection; | 147 m_startingSelection = selection; |
| 148 m_startingRootEditableElement = selection.rootEditableElement(); | 148 m_startingRootEditableElement = selection.rootEditableElement(); |
| 149 } | 149 } |
| 150 | 150 |
| 151 void EditCommandComposition::setEndingSelection(const VisibleSelection& selectio
n) | 151 void EditCommandComposition::setEndingSelection(const VisibleSelection& selectio
n) |
| 152 { | 152 { |
| 153 m_endingSelection = selection; | 153 m_endingSelection = selection; |
| 154 m_endingRootEditableElement = selection.rootEditableElement(); | 154 m_endingRootEditableElement = selection.rootEditableElement(); |
| 155 } | 155 } |
| 156 | 156 |
| 157 void EditCommandComposition::trace(Visitor* visitor) |
| 158 { |
| 159 visitor->trace(m_document); |
| 160 visitor->trace(m_startingSelection); |
| 161 visitor->trace(m_endingSelection); |
| 162 visitor->trace(m_commands); |
| 163 visitor->trace(m_startingRootEditableElement); |
| 164 visitor->trace(m_endingRootEditableElement); |
| 165 UndoStep::trace(visitor); |
| 166 } |
| 167 |
| 157 CompositeEditCommand::CompositeEditCommand(Document& document) | 168 CompositeEditCommand::CompositeEditCommand(Document& document) |
| 158 : EditCommand(document) | 169 : EditCommand(document) |
| 159 { | 170 { |
| 160 } | 171 } |
| 161 | 172 |
| 162 CompositeEditCommand::~CompositeEditCommand() | 173 CompositeEditCommand::~CompositeEditCommand() |
| 163 { | 174 { |
| 164 ASSERT(isTopLevelCommand() || !m_composition); | 175 ASSERT(isTopLevelCommand() || !m_composition); |
| 165 } | 176 } |
| 166 | 177 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 return false; | 232 return false; |
| 222 } | 233 } |
| 223 | 234 |
| 224 void CompositeEditCommand::setShouldRetainAutocorrectionIndicator(bool) | 235 void CompositeEditCommand::setShouldRetainAutocorrectionIndicator(bool) |
| 225 { | 236 { |
| 226 } | 237 } |
| 227 | 238 |
| 228 // | 239 // |
| 229 // sugary-sweet convenience functions to help create and apply edit commands in
composite commands | 240 // sugary-sweet convenience functions to help create and apply edit commands in
composite commands |
| 230 // | 241 // |
| 231 void CompositeEditCommand::applyCommandToComposite(PassRefPtr<EditCommand> prpCo
mmand) | 242 void CompositeEditCommand::applyCommandToComposite(PassRefPtrWillBeRawPtr<EditCo
mmand> prpCommand) |
| 232 { | 243 { |
| 233 RefPtr<EditCommand> command = prpCommand; | 244 RefPtrWillBeRawPtr<EditCommand> command = prpCommand; |
| 234 command->setParent(this); | 245 command->setParent(this); |
| 235 command->doApply(); | 246 command->doApply(); |
| 236 if (command->isSimpleEditCommand()) { | 247 if (command->isSimpleEditCommand()) { |
| 237 command->setParent(0); | 248 command->setParent(0); |
| 238 ensureComposition()->append(toSimpleEditCommand(command.get())); | 249 ensureComposition()->append(toSimpleEditCommand(command.get())); |
| 239 } | 250 } |
| 240 m_commands.append(command.release()); | 251 m_commands.append(command.release()); |
| 241 } | 252 } |
| 242 | 253 |
| 243 void CompositeEditCommand::applyCommandToComposite(PassRefPtr<CompositeEditComma
nd> command, const VisibleSelection& selection) | 254 void CompositeEditCommand::applyCommandToComposite(PassRefPtrWillBeRawPtr<Compos
iteEditCommand> command, const VisibleSelection& selection) |
| 244 { | 255 { |
| 245 command->setParent(this); | 256 command->setParent(this); |
| 246 if (selection != command->endingSelection()) { | 257 if (selection != command->endingSelection()) { |
| 247 command->setStartingSelection(selection); | 258 command->setStartingSelection(selection); |
| 248 command->setEndingSelection(selection); | 259 command->setEndingSelection(selection); |
| 249 } | 260 } |
| 250 command->doApply(); | 261 command->doApply(); |
| 251 m_commands.append(command); | 262 m_commands.append(command); |
| 252 } | 263 } |
| 253 | 264 |
| 254 void CompositeEditCommand::applyStyle(const EditingStyle* style, EditAction edit
ingAction) | 265 void CompositeEditCommand::applyStyle(const EditingStyle* style, EditAction edit
ingAction) |
| 255 { | 266 { |
| 256 applyCommandToComposite(ApplyStyleCommand::create(document(), style, editing
Action)); | 267 applyCommandToComposite(ApplyStyleCommand::create(document(), style, editing
Action)); |
| 257 } | 268 } |
| 258 | 269 |
| 259 void CompositeEditCommand::applyStyle(const EditingStyle* style, const Position&
start, const Position& end, EditAction editingAction) | 270 void CompositeEditCommand::applyStyle(const EditingStyle* style, const Position&
start, const Position& end, EditAction editingAction) |
| 260 { | 271 { |
| 261 applyCommandToComposite(ApplyStyleCommand::create(document(), style, start,
end, editingAction)); | 272 applyCommandToComposite(ApplyStyleCommand::create(document(), style, start,
end, editingAction)); |
| 262 } | 273 } |
| 263 | 274 |
| 264 void CompositeEditCommand::applyStyledElement(PassRefPtr<Element> element) | 275 void CompositeEditCommand::applyStyledElement(PassRefPtrWillBeRawPtr<Element> el
ement) |
| 265 { | 276 { |
| 266 applyCommandToComposite(ApplyStyleCommand::create(element, false)); | 277 applyCommandToComposite(ApplyStyleCommand::create(element, false)); |
| 267 } | 278 } |
| 268 | 279 |
| 269 void CompositeEditCommand::removeStyledElement(PassRefPtr<Element> element) | 280 void CompositeEditCommand::removeStyledElement(PassRefPtrWillBeRawPtr<Element> e
lement) |
| 270 { | 281 { |
| 271 applyCommandToComposite(ApplyStyleCommand::create(element, true)); | 282 applyCommandToComposite(ApplyStyleCommand::create(element, true)); |
| 272 } | 283 } |
| 273 | 284 |
| 274 void CompositeEditCommand::insertParagraphSeparator(bool useDefaultParagraphElem
ent, bool pasteBlockqutoeIntoUnquotedArea) | 285 void CompositeEditCommand::insertParagraphSeparator(bool useDefaultParagraphElem
ent, bool pasteBlockqutoeIntoUnquotedArea) |
| 275 { | 286 { |
| 276 applyCommandToComposite(InsertParagraphSeparatorCommand::create(document(),
useDefaultParagraphElement, pasteBlockqutoeIntoUnquotedArea)); | 287 applyCommandToComposite(InsertParagraphSeparatorCommand::create(document(),
useDefaultParagraphElement, pasteBlockqutoeIntoUnquotedArea)); |
| 277 } | 288 } |
| 278 | 289 |
| 279 bool CompositeEditCommand::isRemovableBlock(const Node* node) | 290 bool CompositeEditCommand::isRemovableBlock(const Node* node) |
| 280 { | 291 { |
| 281 ASSERT(node); | 292 ASSERT(node); |
| 282 if (!isHTMLDivElement(*node)) | 293 if (!isHTMLDivElement(*node)) |
| 283 return false; | 294 return false; |
| 284 | 295 |
| 285 Node* parentNode = node->parentNode(); | 296 Node* parentNode = node->parentNode(); |
| 286 if (parentNode && parentNode->firstChild() != parentNode->lastChild()) | 297 if (parentNode && parentNode->firstChild() != parentNode->lastChild()) |
| 287 return false; | 298 return false; |
| 288 | 299 |
| 289 if (!toElement(node)->hasAttributes()) | 300 if (!toElement(node)->hasAttributes()) |
| 290 return true; | 301 return true; |
| 291 | 302 |
| 292 return false; | 303 return false; |
| 293 } | 304 } |
| 294 | 305 |
| 295 void CompositeEditCommand::insertNodeBefore(PassRefPtr<Node> insertChild, PassRe
fPtr<Node> refChild, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAl
waysEditable) | 306 void CompositeEditCommand::insertNodeBefore(PassRefPtrWillBeRawPtr<Node> insertC
hild, PassRefPtrWillBeRawPtr<Node> refChild, ShouldAssumeContentIsAlwaysEditable
shouldAssumeContentIsAlwaysEditable) |
| 296 { | 307 { |
| 297 ASSERT(!isHTMLBodyElement(*refChild)); | 308 ASSERT(!isHTMLBodyElement(*refChild)); |
| 298 applyCommandToComposite(InsertNodeBeforeCommand::create(insertChild, refChil
d, shouldAssumeContentIsAlwaysEditable)); | 309 applyCommandToComposite(InsertNodeBeforeCommand::create(insertChild, refChil
d, shouldAssumeContentIsAlwaysEditable)); |
| 299 } | 310 } |
| 300 | 311 |
| 301 void CompositeEditCommand::insertNodeAfter(PassRefPtr<Node> insertChild, PassRef
Ptr<Node> refChild) | 312 void CompositeEditCommand::insertNodeAfter(PassRefPtrWillBeRawPtr<Node> insertCh
ild, PassRefPtrWillBeRawPtr<Node> refChild) |
| 302 { | 313 { |
| 303 ASSERT(insertChild); | 314 ASSERT(insertChild); |
| 304 ASSERT(refChild); | 315 ASSERT(refChild); |
| 305 ASSERT(!isHTMLBodyElement(*refChild)); | 316 ASSERT(!isHTMLBodyElement(*refChild)); |
| 306 ContainerNode* parent = refChild->parentNode(); | 317 ContainerNode* parent = refChild->parentNode(); |
| 307 ASSERT(parent); | 318 ASSERT(parent); |
| 308 ASSERT(!parent->isShadowRoot()); | 319 ASSERT(!parent->isShadowRoot()); |
| 309 if (parent->lastChild() == refChild) | 320 if (parent->lastChild() == refChild) |
| 310 appendNode(insertChild, parent); | 321 appendNode(insertChild, parent); |
| 311 else { | 322 else { |
| 312 ASSERT(refChild->nextSibling()); | 323 ASSERT(refChild->nextSibling()); |
| 313 insertNodeBefore(insertChild, refChild->nextSibling()); | 324 insertNodeBefore(insertChild, refChild->nextSibling()); |
| 314 } | 325 } |
| 315 } | 326 } |
| 316 | 327 |
| 317 void CompositeEditCommand::insertNodeAt(PassRefPtr<Node> insertChild, const Posi
tion& editingPosition) | 328 void CompositeEditCommand::insertNodeAt(PassRefPtrWillBeRawPtr<Node> insertChild
, const Position& editingPosition) |
| 318 { | 329 { |
| 319 ASSERT(isEditablePosition(editingPosition, ContentIsEditable, DoNotUpdateSty
le)); | 330 ASSERT(isEditablePosition(editingPosition, ContentIsEditable, DoNotUpdateSty
le)); |
| 320 // For editing positions like [table, 0], insert before the table, | 331 // For editing positions like [table, 0], insert before the table, |
| 321 // likewise for replaced elements, brs, etc. | 332 // likewise for replaced elements, brs, etc. |
| 322 Position p = editingPosition.parentAnchoredEquivalent(); | 333 Position p = editingPosition.parentAnchoredEquivalent(); |
| 323 Node* refChild = p.deprecatedNode(); | 334 Node* refChild = p.deprecatedNode(); |
| 324 int offset = p.deprecatedEditingOffset(); | 335 int offset = p.deprecatedEditingOffset(); |
| 325 | 336 |
| 326 if (canHaveChildrenForEditing(refChild)) { | 337 if (canHaveChildrenForEditing(refChild)) { |
| 327 Node* child = refChild->firstChild(); | 338 Node* child = refChild->firstChild(); |
| 328 for (int i = 0; child && i < offset; i++) | 339 for (int i = 0; child && i < offset; i++) |
| 329 child = child->nextSibling(); | 340 child = child->nextSibling(); |
| 330 if (child) | 341 if (child) |
| 331 insertNodeBefore(insertChild, child); | 342 insertNodeBefore(insertChild, child); |
| 332 else | 343 else |
| 333 appendNode(insertChild, toContainerNode(refChild)); | 344 appendNode(insertChild, toContainerNode(refChild)); |
| 334 } else if (caretMinOffset(refChild) >= offset) | 345 } else if (caretMinOffset(refChild) >= offset) |
| 335 insertNodeBefore(insertChild, refChild); | 346 insertNodeBefore(insertChild, refChild); |
| 336 else if (refChild->isTextNode() && caretMaxOffset(refChild) > offset) { | 347 else if (refChild->isTextNode() && caretMaxOffset(refChild) > offset) { |
| 337 splitTextNode(toText(refChild), offset); | 348 splitTextNode(toText(refChild), offset); |
| 338 | 349 |
| 339 // Mutation events (bug 22634) from the text node insertion may have rem
oved the refChild | 350 // Mutation events (bug 22634) from the text node insertion may have rem
oved the refChild |
| 340 if (!refChild->inDocument()) | 351 if (!refChild->inDocument()) |
| 341 return; | 352 return; |
| 342 insertNodeBefore(insertChild, refChild); | 353 insertNodeBefore(insertChild, refChild); |
| 343 } else | 354 } else |
| 344 insertNodeAfter(insertChild, refChild); | 355 insertNodeAfter(insertChild, refChild); |
| 345 } | 356 } |
| 346 | 357 |
| 347 void CompositeEditCommand::appendNode(PassRefPtr<Node> node, PassRefPtr<Containe
rNode> parent) | 358 void CompositeEditCommand::appendNode(PassRefPtrWillBeRawPtr<Node> node, PassRef
PtrWillBeRawPtr<ContainerNode> parent) |
| 348 { | 359 { |
| 349 ASSERT(canHaveChildrenForEditing(parent.get())); | 360 ASSERT(canHaveChildrenForEditing(parent.get())); |
| 350 applyCommandToComposite(AppendNodeCommand::create(parent, node)); | 361 applyCommandToComposite(AppendNodeCommand::create(parent, node)); |
| 351 } | 362 } |
| 352 | 363 |
| 353 void CompositeEditCommand::removeChildrenInRange(PassRefPtr<Node> node, unsigned
from, unsigned to) | 364 void CompositeEditCommand::removeChildrenInRange(PassRefPtrWillBeRawPtr<Node> no
de, unsigned from, unsigned to) |
| 354 { | 365 { |
| 355 Vector<RefPtr<Node> > children; | 366 WillBeHeapVector<RefPtrWillBeMember<Node> > children; |
| 356 Node* child = node->traverseToChildAt(from); | 367 Node* child = node->traverseToChildAt(from); |
| 357 for (unsigned i = from; child && i < to; i++, child = child->nextSibling()) | 368 for (unsigned i = from; child && i < to; i++, child = child->nextSibling()) |
| 358 children.append(child); | 369 children.append(child); |
| 359 | 370 |
| 360 size_t size = children.size(); | 371 size_t size = children.size(); |
| 361 for (size_t i = 0; i < size; ++i) | 372 for (size_t i = 0; i < size; ++i) |
| 362 removeNode(children[i].release()); | 373 removeNode(children[i].release()); |
| 363 } | 374 } |
| 364 | 375 |
| 365 void CompositeEditCommand::removeNode(PassRefPtr<Node> node, ShouldAssumeContent
IsAlwaysEditable shouldAssumeContentIsAlwaysEditable) | 376 void CompositeEditCommand::removeNode(PassRefPtrWillBeRawPtr<Node> node, ShouldA
ssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable) |
| 366 { | 377 { |
| 367 if (!node || !node->nonShadowBoundaryParentNode()) | 378 if (!node || !node->nonShadowBoundaryParentNode()) |
| 368 return; | 379 return; |
| 369 applyCommandToComposite(RemoveNodeCommand::create(node, shouldAssumeContentI
sAlwaysEditable)); | 380 applyCommandToComposite(RemoveNodeCommand::create(node, shouldAssumeContentI
sAlwaysEditable)); |
| 370 } | 381 } |
| 371 | 382 |
| 372 void CompositeEditCommand::removeNodePreservingChildren(PassRefPtr<Node> node, S
houldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable) | 383 void CompositeEditCommand::removeNodePreservingChildren(PassRefPtrWillBeRawPtr<N
ode> node, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditab
le) |
| 373 { | 384 { |
| 374 applyCommandToComposite(RemoveNodePreservingChildrenCommand::create(node, sh
ouldAssumeContentIsAlwaysEditable)); | 385 applyCommandToComposite(RemoveNodePreservingChildrenCommand::create(node, sh
ouldAssumeContentIsAlwaysEditable)); |
| 375 } | 386 } |
| 376 | 387 |
| 377 void CompositeEditCommand::removeNodeAndPruneAncestors(PassRefPtr<Node> node, No
de* excludeNode) | 388 void CompositeEditCommand::removeNodeAndPruneAncestors(PassRefPtrWillBeRawPtr<No
de> node, Node* excludeNode) |
| 378 { | 389 { |
| 379 ASSERT(node.get() != excludeNode); | 390 ASSERT(node.get() != excludeNode); |
| 380 RefPtr<ContainerNode> parent = node->parentNode(); | 391 RefPtrWillBeRawPtr<ContainerNode> parent = node->parentNode(); |
| 381 removeNode(node); | 392 removeNode(node); |
| 382 prune(parent.release(), excludeNode); | 393 prune(parent.release(), excludeNode); |
| 383 } | 394 } |
| 384 | 395 |
| 385 void CompositeEditCommand::moveRemainingSiblingsToNewParent(Node* node, Node* pa
stLastNodeToMove, PassRefPtr<Element> prpNewParent) | 396 void CompositeEditCommand::moveRemainingSiblingsToNewParent(Node* node, Node* pa
stLastNodeToMove, PassRefPtrWillBeRawPtr<Element> prpNewParent) |
| 386 { | 397 { |
| 387 NodeVector nodesToRemove; | 398 NodeVector nodesToRemove; |
| 388 RefPtr<Element> newParent = prpNewParent; | 399 RefPtrWillBeRawPtr<Element> newParent = prpNewParent; |
| 389 | 400 |
| 390 for (; node && node != pastLastNodeToMove; node = node->nextSibling()) | 401 for (; node && node != pastLastNodeToMove; node = node->nextSibling()) |
| 391 nodesToRemove.append(node); | 402 nodesToRemove.append(node); |
| 392 | 403 |
| 393 for (unsigned i = 0; i < nodesToRemove.size(); i++) { | 404 for (unsigned i = 0; i < nodesToRemove.size(); i++) { |
| 394 removeNode(nodesToRemove[i]); | 405 removeNode(nodesToRemove[i]); |
| 395 appendNode(nodesToRemove[i], newParent); | 406 appendNode(nodesToRemove[i], newParent); |
| 396 } | 407 } |
| 397 } | 408 } |
| 398 | 409 |
| 399 void CompositeEditCommand::updatePositionForNodeRemovalPreservingChildren(Positi
on& position, Node& node) | 410 void CompositeEditCommand::updatePositionForNodeRemovalPreservingChildren(Positi
on& position, Node& node) |
| 400 { | 411 { |
| 401 int offset = (position.anchorType() == Position::PositionIsOffsetInAnchor) ?
position.offsetInContainerNode() : 0; | 412 int offset = (position.anchorType() == Position::PositionIsOffsetInAnchor) ?
position.offsetInContainerNode() : 0; |
| 402 updatePositionForNodeRemoval(position, node); | 413 updatePositionForNodeRemoval(position, node); |
| 403 if (offset) | 414 if (offset) |
| 404 position.moveToOffset(offset); | 415 position.moveToOffset(offset); |
| 405 } | 416 } |
| 406 | 417 |
| 407 HTMLElement* CompositeEditCommand::replaceElementWithSpanPreservingChildrenAndAt
tributes(PassRefPtrWillBeRawPtr<HTMLElement> node) | 418 HTMLElement* CompositeEditCommand::replaceElementWithSpanPreservingChildrenAndAt
tributes(PassRefPtrWillBeRawPtr<HTMLElement> node) |
| 408 { | 419 { |
| 409 // It would also be possible to implement all of ReplaceNodeWithSpanCommand | 420 // It would also be possible to implement all of ReplaceNodeWithSpanCommand |
| 410 // as a series of existing smaller edit commands. Someone who wanted to | 421 // as a series of existing smaller edit commands. Someone who wanted to |
| 411 // reduce the number of edit commands could do so here. | 422 // reduce the number of edit commands could do so here. |
| 412 RefPtr<ReplaceNodeWithSpanCommand> command = ReplaceNodeWithSpanCommand::cre
ate(node); | 423 RefPtrWillBeRawPtr<ReplaceNodeWithSpanCommand> command = ReplaceNodeWithSpan
Command::create(node); |
| 413 applyCommandToComposite(command); | 424 applyCommandToComposite(command); |
| 414 // Returning a raw pointer here is OK because the command is retained by | 425 // Returning a raw pointer here is OK because the command is retained by |
| 415 // applyCommandToComposite (thus retaining the span), and the span is also | 426 // applyCommandToComposite (thus retaining the span), and the span is also |
| 416 // in the DOM tree, and thus alive whie it has a parent. | 427 // in the DOM tree, and thus alive whie it has a parent. |
| 417 ASSERT(command->spanElement()->inDocument()); | 428 ASSERT(command->spanElement()->inDocument()); |
| 418 return command->spanElement(); | 429 return command->spanElement(); |
| 419 } | 430 } |
| 420 | 431 |
| 421 void CompositeEditCommand::prune(PassRefPtr<Node> node, Node* excludeNode) | 432 void CompositeEditCommand::prune(PassRefPtrWillBeRawPtr<Node> node, Node* exclud
eNode) |
| 422 { | 433 { |
| 423 if (RefPtr<Node> highestNodeToRemove = highestNodeToRemoveInPruning(node.get
(), excludeNode)) | 434 if (RefPtrWillBeRawPtr<Node> highestNodeToRemove = highestNodeToRemoveInPrun
ing(node.get(), excludeNode)) |
| 424 removeNode(highestNodeToRemove.release()); | 435 removeNode(highestNodeToRemove.release()); |
| 425 } | 436 } |
| 426 | 437 |
| 427 void CompositeEditCommand::splitTextNode(PassRefPtrWillBeRawPtr<Text> node, unsi
gned offset) | 438 void CompositeEditCommand::splitTextNode(PassRefPtrWillBeRawPtr<Text> node, unsi
gned offset) |
| 428 { | 439 { |
| 429 applyCommandToComposite(SplitTextNodeCommand::create(node, offset)); | 440 applyCommandToComposite(SplitTextNodeCommand::create(node, offset)); |
| 430 } | 441 } |
| 431 | 442 |
| 432 void CompositeEditCommand::splitElement(PassRefPtr<Element> element, PassRefPtr<
Node> atChild) | 443 void CompositeEditCommand::splitElement(PassRefPtrWillBeRawPtr<Element> element,
PassRefPtrWillBeRawPtr<Node> atChild) |
| 433 { | 444 { |
| 434 applyCommandToComposite(SplitElementCommand::create(element, atChild)); | 445 applyCommandToComposite(SplitElementCommand::create(element, atChild)); |
| 435 } | 446 } |
| 436 | 447 |
| 437 void CompositeEditCommand::mergeIdenticalElements(PassRefPtr<Element> prpFirst,
PassRefPtr<Element> prpSecond) | 448 void CompositeEditCommand::mergeIdenticalElements(PassRefPtrWillBeRawPtr<Element
> prpFirst, PassRefPtrWillBeRawPtr<Element> prpSecond) |
| 438 { | 449 { |
| 439 RefPtr<Element> first = prpFirst; | 450 RefPtrWillBeRawPtr<Element> first = prpFirst; |
| 440 RefPtr<Element> second = prpSecond; | 451 RefPtrWillBeRawPtr<Element> second = prpSecond; |
| 441 ASSERT(!first->isDescendantOf(second.get()) && second != first); | 452 ASSERT(!first->isDescendantOf(second.get()) && second != first); |
| 442 if (first->nextSibling() != second) { | 453 if (first->nextSibling() != second) { |
| 443 removeNode(second); | 454 removeNode(second); |
| 444 insertNodeAfter(second, first); | 455 insertNodeAfter(second, first); |
| 445 } | 456 } |
| 446 applyCommandToComposite(MergeIdenticalElementsCommand::create(first, second)
); | 457 applyCommandToComposite(MergeIdenticalElementsCommand::create(first, second)
); |
| 447 } | 458 } |
| 448 | 459 |
| 449 void CompositeEditCommand::wrapContentsInDummySpan(PassRefPtr<Element> element) | 460 void CompositeEditCommand::wrapContentsInDummySpan(PassRefPtrWillBeRawPtr<Elemen
t> element) |
| 450 { | 461 { |
| 451 applyCommandToComposite(WrapContentsInDummySpanCommand::create(element)); | 462 applyCommandToComposite(WrapContentsInDummySpanCommand::create(element)); |
| 452 } | 463 } |
| 453 | 464 |
| 454 void CompositeEditCommand::splitTextNodeContainingElement(PassRefPtrWillBeRawPtr
<Text> text, unsigned offset) | 465 void CompositeEditCommand::splitTextNodeContainingElement(PassRefPtrWillBeRawPtr
<Text> text, unsigned offset) |
| 455 { | 466 { |
| 456 applyCommandToComposite(SplitTextNodeContainingElementCommand::create(text,
offset)); | 467 applyCommandToComposite(SplitTextNodeContainingElementCommand::create(text,
offset)); |
| 457 } | 468 } |
| 458 | 469 |
| 459 void CompositeEditCommand::insertTextIntoNode(PassRefPtrWillBeRawPtr<Text> node,
unsigned offset, const String& text) | 470 void CompositeEditCommand::insertTextIntoNode(PassRefPtrWillBeRawPtr<Text> node,
unsigned offset, const String& text) |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 532 if (pos.offsetInContainerNode() <= caretMinOffset(pos.containerNode())) | 543 if (pos.offsetInContainerNode() <= caretMinOffset(pos.containerNode())) |
| 533 return positionInParentBeforeNode(*tabSpan); | 544 return positionInParentBeforeNode(*tabSpan); |
| 534 | 545 |
| 535 if (pos.offsetInContainerNode() >= caretMaxOffset(pos.containerNode())) | 546 if (pos.offsetInContainerNode() >= caretMaxOffset(pos.containerNode())) |
| 536 return positionInParentAfterNode(*tabSpan); | 547 return positionInParentAfterNode(*tabSpan); |
| 537 | 548 |
| 538 splitTextNodeContainingElement(toText(pos.containerNode()), pos.offsetInCont
ainerNode()); | 549 splitTextNodeContainingElement(toText(pos.containerNode()), pos.offsetInCont
ainerNode()); |
| 539 return positionInParentBeforeNode(*tabSpan); | 550 return positionInParentBeforeNode(*tabSpan); |
| 540 } | 551 } |
| 541 | 552 |
| 542 void CompositeEditCommand::insertNodeAtTabSpanPosition(PassRefPtr<Node> node, co
nst Position& pos) | 553 void CompositeEditCommand::insertNodeAtTabSpanPosition(PassRefPtrWillBeRawPtr<No
de> node, const Position& pos) |
| 543 { | 554 { |
| 544 // insert node before, after, or at split of tab span | 555 // insert node before, after, or at split of tab span |
| 545 insertNodeAt(node, positionOutsideTabSpan(pos)); | 556 insertNodeAt(node, positionOutsideTabSpan(pos)); |
| 546 } | 557 } |
| 547 | 558 |
| 548 void CompositeEditCommand::deleteSelection(bool smartDelete, bool mergeBlocksAft
erDelete, bool expandForSpecialElements, bool sanitizeMarkup) | 559 void CompositeEditCommand::deleteSelection(bool smartDelete, bool mergeBlocksAft
erDelete, bool expandForSpecialElements, bool sanitizeMarkup) |
| 549 { | 560 { |
| 550 if (endingSelection().isRange()) | 561 if (endingSelection().isRange()) |
| 551 applyCommandToComposite(DeleteSelectionCommand::create(document(), smart
Delete, mergeBlocksAfterDelete, expandForSpecialElements, sanitizeMarkup)); | 562 applyCommandToComposite(DeleteSelectionCommand::create(document(), smart
Delete, mergeBlocksAfterDelete, expandForSpecialElements, sanitizeMarkup)); |
| 552 } | 563 } |
| 553 | 564 |
| 554 void CompositeEditCommand::deleteSelection(const VisibleSelection &selection, bo
ol smartDelete, bool mergeBlocksAfterDelete, bool expandForSpecialElements, bool
sanitizeMarkup) | 565 void CompositeEditCommand::deleteSelection(const VisibleSelection &selection, bo
ol smartDelete, bool mergeBlocksAfterDelete, bool expandForSpecialElements, bool
sanitizeMarkup) |
| 555 { | 566 { |
| 556 if (selection.isRange()) | 567 if (selection.isRange()) |
| 557 applyCommandToComposite(DeleteSelectionCommand::create(selection, smartD
elete, mergeBlocksAfterDelete, expandForSpecialElements, sanitizeMarkup)); | 568 applyCommandToComposite(DeleteSelectionCommand::create(selection, smartD
elete, mergeBlocksAfterDelete, expandForSpecialElements, sanitizeMarkup)); |
| 558 } | 569 } |
| 559 | 570 |
| 560 void CompositeEditCommand::removeCSSProperty(PassRefPtr<Element> element, CSSPro
pertyID property) | 571 void CompositeEditCommand::removeCSSProperty(PassRefPtrWillBeRawPtr<Element> ele
ment, CSSPropertyID property) |
| 561 { | 572 { |
| 562 applyCommandToComposite(RemoveCSSPropertyCommand::create(document(), element
, property)); | 573 applyCommandToComposite(RemoveCSSPropertyCommand::create(document(), element
, property)); |
| 563 } | 574 } |
| 564 | 575 |
| 565 void CompositeEditCommand::removeNodeAttribute(PassRefPtr<Element> element, cons
t QualifiedName& attribute) | 576 void CompositeEditCommand::removeNodeAttribute(PassRefPtrWillBeRawPtr<Element> e
lement, const QualifiedName& attribute) |
| 566 { | 577 { |
| 567 setNodeAttribute(element, attribute, AtomicString()); | 578 setNodeAttribute(element, attribute, AtomicString()); |
| 568 } | 579 } |
| 569 | 580 |
| 570 void CompositeEditCommand::setNodeAttribute(PassRefPtr<Element> element, const Q
ualifiedName& attribute, const AtomicString& value) | 581 void CompositeEditCommand::setNodeAttribute(PassRefPtrWillBeRawPtr<Element> elem
ent, const QualifiedName& attribute, const AtomicString& value) |
| 571 { | 582 { |
| 572 applyCommandToComposite(SetNodeAttributeCommand::create(element, attribute,
value)); | 583 applyCommandToComposite(SetNodeAttributeCommand::create(element, attribute,
value)); |
| 573 } | 584 } |
| 574 | 585 |
| 575 static inline bool containsOnlyWhitespace(const String& text) | 586 static inline bool containsOnlyWhitespace(const String& text) |
| 576 { | 587 { |
| 577 for (unsigned i = 0; i < text.length(); ++i) { | 588 for (unsigned i = 0; i < text.length(); ++i) { |
| 578 if (!isWhitespace(text[i])) | 589 if (!isWhitespace(text[i])) |
| 579 return false; | 590 return false; |
| 580 } | 591 } |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 805 deleteInsignificantText(textNode, startOffset, endOffset); | 816 deleteInsignificantText(textNode, startOffset, endOffset); |
| 806 } | 817 } |
| 807 } | 818 } |
| 808 | 819 |
| 809 void CompositeEditCommand::deleteInsignificantTextDownstream(const Position& pos
) | 820 void CompositeEditCommand::deleteInsignificantTextDownstream(const Position& pos
) |
| 810 { | 821 { |
| 811 Position end = VisiblePosition(pos, VP_DEFAULT_AFFINITY).next().deepEquivale
nt().downstream(); | 822 Position end = VisiblePosition(pos, VP_DEFAULT_AFFINITY).next().deepEquivale
nt().downstream(); |
| 812 deleteInsignificantText(pos, end); | 823 deleteInsignificantText(pos, end); |
| 813 } | 824 } |
| 814 | 825 |
| 815 PassRefPtr<Node> CompositeEditCommand::appendBlockPlaceholder(PassRefPtr<Element
> container) | 826 PassRefPtrWillBeRawPtr<Node> CompositeEditCommand::appendBlockPlaceholder(PassRe
fPtrWillBeRawPtr<Element> container) |
| 816 { | 827 { |
| 817 if (!container) | 828 if (!container) |
| 818 return nullptr; | 829 return nullptr; |
| 819 | 830 |
| 820 document().updateLayoutIgnorePendingStylesheets(); | 831 document().updateLayoutIgnorePendingStylesheets(); |
| 821 | 832 |
| 822 // Should assert isRenderBlockFlow || isInlineFlow when deletion improves. S
ee 4244964. | 833 // Should assert isRenderBlockFlow || isInlineFlow when deletion improves. S
ee 4244964. |
| 823 ASSERT(container->renderer()); | 834 ASSERT(container->renderer()); |
| 824 | 835 |
| 825 RefPtr<Node> placeholder = createBlockPlaceholderElement(document()); | 836 RefPtrWillBeRawPtr<Node> placeholder = createBlockPlaceholderElement(documen
t()); |
| 826 appendNode(placeholder, container); | 837 appendNode(placeholder, container); |
| 827 return placeholder.release(); | 838 return placeholder.release(); |
| 828 } | 839 } |
| 829 | 840 |
| 830 PassRefPtr<Node> CompositeEditCommand::insertBlockPlaceholder(const Position& po
s) | 841 PassRefPtrWillBeRawPtr<Node> CompositeEditCommand::insertBlockPlaceholder(const
Position& pos) |
| 831 { | 842 { |
| 832 if (pos.isNull()) | 843 if (pos.isNull()) |
| 833 return nullptr; | 844 return nullptr; |
| 834 | 845 |
| 835 // Should assert isRenderBlockFlow || isInlineFlow when deletion improves. S
ee 4244964. | 846 // Should assert isRenderBlockFlow || isInlineFlow when deletion improves. S
ee 4244964. |
| 836 ASSERT(pos.deprecatedNode()->renderer()); | 847 ASSERT(pos.deprecatedNode()->renderer()); |
| 837 | 848 |
| 838 RefPtr<Node> placeholder = createBlockPlaceholderElement(document()); | 849 RefPtrWillBeRawPtr<Node> placeholder = createBlockPlaceholderElement(documen
t()); |
| 839 insertNodeAt(placeholder, pos); | 850 insertNodeAt(placeholder, pos); |
| 840 return placeholder.release(); | 851 return placeholder.release(); |
| 841 } | 852 } |
| 842 | 853 |
| 843 PassRefPtr<Node> CompositeEditCommand::addBlockPlaceholderIfNeeded(Element* cont
ainer) | 854 PassRefPtrWillBeRawPtr<Node> CompositeEditCommand::addBlockPlaceholderIfNeeded(E
lement* container) |
| 844 { | 855 { |
| 845 if (!container) | 856 if (!container) |
| 846 return nullptr; | 857 return nullptr; |
| 847 | 858 |
| 848 document().updateLayoutIgnorePendingStylesheets(); | 859 document().updateLayoutIgnorePendingStylesheets(); |
| 849 | 860 |
| 850 RenderObject* renderer = container->renderer(); | 861 RenderObject* renderer = container->renderer(); |
| 851 if (!renderer || !renderer->isRenderBlockFlow()) | 862 if (!renderer || !renderer->isRenderBlockFlow()) |
| 852 return nullptr; | 863 return nullptr; |
| 853 | 864 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 867 | 878 |
| 868 // We are certain that the position is at a line break, but it may be a br o
r a preserved newline. | 879 // We are certain that the position is at a line break, but it may be a br o
r a preserved newline. |
| 869 if (isHTMLBRElement(*p.anchorNode())) { | 880 if (isHTMLBRElement(*p.anchorNode())) { |
| 870 removeNode(p.anchorNode()); | 881 removeNode(p.anchorNode()); |
| 871 return; | 882 return; |
| 872 } | 883 } |
| 873 | 884 |
| 874 deleteTextFromNode(toText(p.anchorNode()), p.offsetInContainerNode(), 1); | 885 deleteTextFromNode(toText(p.anchorNode()), p.offsetInContainerNode(), 1); |
| 875 } | 886 } |
| 876 | 887 |
| 877 PassRefPtr<Node> CompositeEditCommand::insertNewDefaultParagraphElementAt(const
Position& position) | 888 PassRefPtrWillBeRawPtr<Node> CompositeEditCommand::insertNewDefaultParagraphElem
entAt(const Position& position) |
| 878 { | 889 { |
| 879 RefPtr<Element> paragraphElement = createDefaultParagraphElement(document())
; | 890 RefPtrWillBeRawPtr<Element> paragraphElement = createDefaultParagraphElement
(document()); |
| 880 paragraphElement->appendChild(createBreakElement(document())); | 891 paragraphElement->appendChild(createBreakElement(document())); |
| 881 insertNodeAt(paragraphElement, position); | 892 insertNodeAt(paragraphElement, position); |
| 882 return paragraphElement.release(); | 893 return paragraphElement.release(); |
| 883 } | 894 } |
| 884 | 895 |
| 885 // If the paragraph is not entirely within it's own block, create one and move t
he paragraph into | 896 // If the paragraph is not entirely within it's own block, create one and move t
he paragraph into |
| 886 // it, and return that block. Otherwise return 0. | 897 // it, and return that block. Otherwise return 0. |
| 887 PassRefPtr<Node> CompositeEditCommand::moveParagraphContentsToNewBlockIfNecessar
y(const Position& pos) | 898 PassRefPtrWillBeRawPtr<Node> CompositeEditCommand::moveParagraphContentsToNewBlo
ckIfNecessary(const Position& pos) |
| 888 { | 899 { |
| 889 if (pos.isNull()) | 900 if (pos.isNull()) |
| 890 return nullptr; | 901 return nullptr; |
| 891 | 902 |
| 892 document().updateLayoutIgnorePendingStylesheets(); | 903 document().updateLayoutIgnorePendingStylesheets(); |
| 893 | 904 |
| 894 // It's strange that this function is responsible for verifying that pos has
not been invalidated | 905 // It's strange that this function is responsible for verifying that pos has
not been invalidated |
| 895 // by an earlier call to this function. The caller, applyBlockStyle, should
do this. | 906 // by an earlier call to this function. The caller, applyBlockStyle, should
do this. |
| 896 VisiblePosition visiblePos(pos, VP_DEFAULT_AFFINITY); | 907 VisiblePosition visiblePos(pos, VP_DEFAULT_AFFINITY); |
| 897 VisiblePosition visibleParagraphStart(startOfParagraph(visiblePos)); | 908 VisiblePosition visibleParagraphStart(startOfParagraph(visiblePos)); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 929 return nullptr; | 940 return nullptr; |
| 930 } else if (isEndOfEditableOrNonEditableContent(visibleEnd)) { | 941 } else if (isEndOfEditableOrNonEditableContent(visibleEnd)) { |
| 931 // At the end of the editable region. We can bail here as well. | 942 // At the end of the editable region. We can bail here as well. |
| 932 return nullptr; | 943 return nullptr; |
| 933 } | 944 } |
| 934 } | 945 } |
| 935 | 946 |
| 936 if (visibleParagraphEnd.isNull()) | 947 if (visibleParagraphEnd.isNull()) |
| 937 return nullptr; | 948 return nullptr; |
| 938 | 949 |
| 939 RefPtr<Node> newBlock = insertNewDefaultParagraphElementAt(upstreamStart); | 950 RefPtrWillBeRawPtr<Node> newBlock = insertNewDefaultParagraphElementAt(upstr
eamStart); |
| 940 | 951 |
| 941 bool endWasBr = isHTMLBRElement(*visibleParagraphEnd.deepEquivalent().deprec
atedNode()); | 952 bool endWasBr = isHTMLBRElement(*visibleParagraphEnd.deepEquivalent().deprec
atedNode()); |
| 942 | 953 |
| 943 moveParagraphs(visibleParagraphStart, visibleParagraphEnd, VisiblePosition(f
irstPositionInNode(newBlock.get()))); | 954 moveParagraphs(visibleParagraphStart, visibleParagraphEnd, VisiblePosition(f
irstPositionInNode(newBlock.get()))); |
| 944 | 955 |
| 945 if (newBlock->lastChild() && isHTMLBRElement(*newBlock->lastChild()) && !end
WasBr) | 956 if (newBlock->lastChild() && isHTMLBRElement(*newBlock->lastChild()) && !end
WasBr) |
| 946 removeNode(newBlock->lastChild()); | 957 removeNode(newBlock->lastChild()); |
| 947 | 958 |
| 948 return newBlock.release(); | 959 return newBlock.release(); |
| 949 } | 960 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 965 // Clone the paragraph between start and end under blockElement, | 976 // Clone the paragraph between start and end under blockElement, |
| 966 // preserving the hierarchy up to outerNode. | 977 // preserving the hierarchy up to outerNode. |
| 967 | 978 |
| 968 void CompositeEditCommand::cloneParagraphUnderNewElement(const Position& start,
const Position& end, Node* passedOuterNode, Element* blockElement) | 979 void CompositeEditCommand::cloneParagraphUnderNewElement(const Position& start,
const Position& end, Node* passedOuterNode, Element* blockElement) |
| 969 { | 980 { |
| 970 ASSERT(comparePositions(start, end) <= 0); | 981 ASSERT(comparePositions(start, end) <= 0); |
| 971 ASSERT(passedOuterNode); | 982 ASSERT(passedOuterNode); |
| 972 ASSERT(blockElement); | 983 ASSERT(blockElement); |
| 973 | 984 |
| 974 // First we clone the outerNode | 985 // First we clone the outerNode |
| 975 RefPtr<Node> lastNode; | 986 RefPtrWillBeRawPtr<Node> lastNode = nullptr; |
| 976 RefPtr<Node> outerNode = passedOuterNode; | 987 RefPtrWillBeRawPtr<Node> outerNode = passedOuterNode; |
| 977 | 988 |
| 978 if (outerNode->isRootEditableElement()) { | 989 if (outerNode->isRootEditableElement()) { |
| 979 lastNode = blockElement; | 990 lastNode = blockElement; |
| 980 } else { | 991 } else { |
| 981 lastNode = outerNode->cloneNode(isRenderedTableElement(outerNode.get()))
; | 992 lastNode = outerNode->cloneNode(isRenderedTableElement(outerNode.get()))
; |
| 982 appendNode(lastNode, blockElement); | 993 appendNode(lastNode, blockElement); |
| 983 } | 994 } |
| 984 | 995 |
| 985 if (start.anchorNode() != outerNode && lastNode->isElementNode() && start.an
chorNode()->isDescendantOf(outerNode.get())) { | 996 if (start.anchorNode() != outerNode && lastNode->isElementNode() && start.an
chorNode()->isDescendantOf(outerNode.get())) { |
| 986 Vector<RefPtr<Node> > ancestors; | 997 WillBeHeapVector<RefPtrWillBeMember<Node> > ancestors; |
| 987 | 998 |
| 988 // Insert each node from innerNode to outerNode (excluded) in a list. | 999 // Insert each node from innerNode to outerNode (excluded) in a list. |
| 989 for (Node* n = start.deprecatedNode(); n && n != outerNode; n = n->paren
tNode()) | 1000 for (Node* n = start.deprecatedNode(); n && n != outerNode; n = n->paren
tNode()) |
| 990 ancestors.append(n); | 1001 ancestors.append(n); |
| 991 | 1002 |
| 992 // Clone every node between start.deprecatedNode() and outerBlock. | 1003 // Clone every node between start.deprecatedNode() and outerBlock. |
| 993 | 1004 |
| 994 for (size_t i = ancestors.size(); i != 0; --i) { | 1005 for (size_t i = ancestors.size(); i != 0; --i) { |
| 995 Node* item = ancestors[i - 1].get(); | 1006 Node* item = ancestors[i - 1].get(); |
| 996 RefPtr<Node> child = item->cloneNode(isRenderedTableElement(item)); | 1007 RefPtrWillBeRawPtr<Node> child = item->cloneNode(isRenderedTableElem
ent(item)); |
| 997 appendNode(child, toElement(lastNode)); | 1008 appendNode(child, toElement(lastNode)); |
| 998 lastNode = child.release(); | 1009 lastNode = child.release(); |
| 999 } | 1010 } |
| 1000 } | 1011 } |
| 1001 | 1012 |
| 1002 // Scripts specified in javascript protocol may remove |outerNode| | 1013 // Scripts specified in javascript protocol may remove |outerNode| |
| 1003 // during insertion, e.g. <iframe src="javascript:..."> | 1014 // during insertion, e.g. <iframe src="javascript:..."> |
| 1004 if (!outerNode->inDocument()) | 1015 if (!outerNode->inDocument()) |
| 1005 return; | 1016 return; |
| 1006 | 1017 |
| 1007 // Handle the case of paragraphs with more than one node, | 1018 // Handle the case of paragraphs with more than one node, |
| 1008 // cloning all the siblings until end.deprecatedNode() is reached. | 1019 // cloning all the siblings until end.deprecatedNode() is reached. |
| 1009 | 1020 |
| 1010 if (start.deprecatedNode() != end.deprecatedNode() && !start.deprecatedNode(
)->isDescendantOf(end.deprecatedNode())) { | 1021 if (start.deprecatedNode() != end.deprecatedNode() && !start.deprecatedNode(
)->isDescendantOf(end.deprecatedNode())) { |
| 1011 // If end is not a descendant of outerNode we need to | 1022 // If end is not a descendant of outerNode we need to |
| 1012 // find the first common ancestor to increase the scope | 1023 // find the first common ancestor to increase the scope |
| 1013 // of our nextSibling traversal. | 1024 // of our nextSibling traversal. |
| 1014 while (outerNode && !end.deprecatedNode()->isDescendantOf(outerNode.get(
))) { | 1025 while (outerNode && !end.deprecatedNode()->isDescendantOf(outerNode.get(
))) { |
| 1015 outerNode = outerNode->parentNode(); | 1026 outerNode = outerNode->parentNode(); |
| 1016 } | 1027 } |
| 1017 | 1028 |
| 1018 if (!outerNode) | 1029 if (!outerNode) |
| 1019 return; | 1030 return; |
| 1020 | 1031 |
| 1021 RefPtr<Node> startNode = start.deprecatedNode(); | 1032 RefPtrWillBeRawPtr<Node> startNode = start.deprecatedNode(); |
| 1022 for (RefPtr<Node> node = NodeTraversal::nextSkippingChildren(*startNode,
outerNode.get()); node; node = NodeTraversal::nextSkippingChildren(*node, outer
Node.get())) { | 1033 for (RefPtrWillBeRawPtr<Node> node = NodeTraversal::nextSkippingChildren
(*startNode, outerNode.get()); node; node = NodeTraversal::nextSkippingChildren(
*node, outerNode.get())) { |
| 1023 // Move lastNode up in the tree as much as node was moved up in the | 1034 // Move lastNode up in the tree as much as node was moved up in the |
| 1024 // tree by NodeTraversal::nextSkippingChildren, so that the relative
depth between | 1035 // tree by NodeTraversal::nextSkippingChildren, so that the relative
depth between |
| 1025 // node and the original start node is maintained in the clone. | 1036 // node and the original start node is maintained in the clone. |
| 1026 while (startNode && lastNode && startNode->parentNode() != node->par
entNode()) { | 1037 while (startNode && lastNode && startNode->parentNode() != node->par
entNode()) { |
| 1027 startNode = startNode->parentNode(); | 1038 startNode = startNode->parentNode(); |
| 1028 lastNode = lastNode->parentNode(); | 1039 lastNode = lastNode->parentNode(); |
| 1029 } | 1040 } |
| 1030 | 1041 |
| 1031 if (!lastNode || !lastNode->parentNode()) | 1042 if (!lastNode || !lastNode->parentNode()) |
| 1032 return; | 1043 return; |
| 1033 | 1044 |
| 1034 RefPtr<Node> clonedNode = node->cloneNode(true); | 1045 RefPtrWillBeRawPtr<Node> clonedNode = node->cloneNode(true); |
| 1035 insertNodeAfter(clonedNode, lastNode); | 1046 insertNodeAfter(clonedNode, lastNode); |
| 1036 lastNode = clonedNode.release(); | 1047 lastNode = clonedNode.release(); |
| 1037 if (node == end.deprecatedNode() || end.deprecatedNode()->isDescenda
ntOf(node.get())) | 1048 if (node == end.deprecatedNode() || end.deprecatedNode()->isDescenda
ntOf(node.get())) |
| 1038 break; | 1049 break; |
| 1039 } | 1050 } |
| 1040 } | 1051 } |
| 1041 } | 1052 } |
| 1042 | 1053 |
| 1043 | 1054 |
| 1044 // There are bugs in deletion when it removes a fully selected table/list. | 1055 // There are bugs in deletion when it removes a fully selected table/list. |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1193 RefPtrWillBeRawPtr<Range> range = Range::create(document(), startRangeCompli
ant.deprecatedNode(), startRangeCompliant.deprecatedEditingOffset(), endRangeCom
pliant.deprecatedNode(), endRangeCompliant.deprecatedEditingOffset()); | 1204 RefPtrWillBeRawPtr<Range> range = Range::create(document(), startRangeCompli
ant.deprecatedNode(), startRangeCompliant.deprecatedEditingOffset(), endRangeCom
pliant.deprecatedNode(), endRangeCompliant.deprecatedEditingOffset()); |
| 1194 | 1205 |
| 1195 // FIXME: This is an inefficient way to preserve style on nodes in the parag
raph to move. It | 1206 // FIXME: This is an inefficient way to preserve style on nodes in the parag
raph to move. It |
| 1196 // shouldn't matter though, since moved paragraphs will usually be quite sma
ll. | 1207 // shouldn't matter though, since moved paragraphs will usually be quite sma
ll. |
| 1197 RefPtrWillBeRawPtr<DocumentFragment> fragment = startOfParagraphToMove != en
dOfParagraphToMove ? | 1208 RefPtrWillBeRawPtr<DocumentFragment> fragment = startOfParagraphToMove != en
dOfParagraphToMove ? |
| 1198 createFragmentFromMarkup(document(), createMarkup(range.get(), 0, DoNotA
nnotateForInterchange, true, DoNotResolveURLs, constrainingAncestor), "") : null
ptr; | 1209 createFragmentFromMarkup(document(), createMarkup(range.get(), 0, DoNotA
nnotateForInterchange, true, DoNotResolveURLs, constrainingAncestor), "") : null
ptr; |
| 1199 | 1210 |
| 1200 // A non-empty paragraph's style is moved when we copy and move it. We don'
t move | 1211 // A non-empty paragraph's style is moved when we copy and move it. We don'
t move |
| 1201 // anything if we're given an empty paragraph, but an empty paragraph can ha
ve style | 1212 // anything if we're given an empty paragraph, but an empty paragraph can ha
ve style |
| 1202 // too, <div><b><br></b></div> for example. Save it so that we can preserve
it later. | 1213 // too, <div><b><br></b></div> for example. Save it so that we can preserve
it later. |
| 1203 RefPtr<EditingStyle> styleInEmptyParagraph; | 1214 RefPtrWillBeRawPtr<EditingStyle> styleInEmptyParagraph = nullptr; |
| 1204 if (startOfParagraphToMove == endOfParagraphToMove && preserveStyle) { | 1215 if (startOfParagraphToMove == endOfParagraphToMove && preserveStyle) { |
| 1205 styleInEmptyParagraph = EditingStyle::create(startOfParagraphToMove.deep
Equivalent()); | 1216 styleInEmptyParagraph = EditingStyle::create(startOfParagraphToMove.deep
Equivalent()); |
| 1206 styleInEmptyParagraph->mergeTypingStyle(&document()); | 1217 styleInEmptyParagraph->mergeTypingStyle(&document()); |
| 1207 // The moved paragraph should assume the block style of the destination. | 1218 // The moved paragraph should assume the block style of the destination. |
| 1208 styleInEmptyParagraph->removeBlockProperties(); | 1219 styleInEmptyParagraph->removeBlockProperties(); |
| 1209 } | 1220 } |
| 1210 | 1221 |
| 1211 // FIXME (5098931): We should add a new insert action "WebViewInsertActionMo
ved" and call shouldInsertFragment here. | 1222 // FIXME (5098931): We should add a new insert action "WebViewInsertActionMo
ved" and call shouldInsertFragment here. |
| 1212 | 1223 |
| 1213 setEndingSelection(VisibleSelection(start, end, DOWNSTREAM)); | 1224 setEndingSelection(VisibleSelection(start, end, DOWNSTREAM)); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1262 RefPtrWillBeRawPtr<Range> end = PlainTextRange(destinationIndex + en
dIndex).createRangeForSelection(*documentElement); | 1273 RefPtrWillBeRawPtr<Range> end = PlainTextRange(destinationIndex + en
dIndex).createRangeForSelection(*documentElement); |
| 1263 if (start && end) | 1274 if (start && end) |
| 1264 setEndingSelection(VisibleSelection(start->startPosition(), end-
>startPosition(), DOWNSTREAM, originalIsDirectional)); | 1275 setEndingSelection(VisibleSelection(start->startPosition(), end-
>startPosition(), DOWNSTREAM, originalIsDirectional)); |
| 1265 } | 1276 } |
| 1266 } | 1277 } |
| 1267 } | 1278 } |
| 1268 | 1279 |
| 1269 // FIXME: Send an appropriate shouldDeleteRange call. | 1280 // FIXME: Send an appropriate shouldDeleteRange call. |
| 1270 bool CompositeEditCommand::breakOutOfEmptyListItem() | 1281 bool CompositeEditCommand::breakOutOfEmptyListItem() |
| 1271 { | 1282 { |
| 1272 RefPtr<Node> emptyListItem = enclosingEmptyListItem(endingSelection().visibl
eStart()); | 1283 RefPtrWillBeRawPtr<Node> emptyListItem = enclosingEmptyListItem(endingSelect
ion().visibleStart()); |
| 1273 if (!emptyListItem) | 1284 if (!emptyListItem) |
| 1274 return false; | 1285 return false; |
| 1275 | 1286 |
| 1276 RefPtr<EditingStyle> style = EditingStyle::create(endingSelection().start())
; | 1287 RefPtrWillBeRawPtr<EditingStyle> style = EditingStyle::create(endingSelectio
n().start()); |
| 1277 style->mergeTypingStyle(&document()); | 1288 style->mergeTypingStyle(&document()); |
| 1278 | 1289 |
| 1279 RefPtr<ContainerNode> listNode = emptyListItem->parentNode(); | 1290 RefPtrWillBeRawPtr<ContainerNode> listNode = emptyListItem->parentNode(); |
| 1280 // FIXME: Can't we do something better when the immediate parent wasn't a li
st node? | 1291 // FIXME: Can't we do something better when the immediate parent wasn't a li
st node? |
| 1281 if (!listNode | 1292 if (!listNode |
| 1282 || (!isHTMLUListElement(*listNode) && !isHTMLOListElement(*listNode)) | 1293 || (!isHTMLUListElement(*listNode) && !isHTMLOListElement(*listNode)) |
| 1283 || !listNode->rendererIsEditable() | 1294 || !listNode->rendererIsEditable() |
| 1284 || listNode == emptyListItem->rootEditableElement()) | 1295 || listNode == emptyListItem->rootEditableElement()) |
| 1285 return false; | 1296 return false; |
| 1286 | 1297 |
| 1287 RefPtr<Element> newBlock = nullptr; | 1298 RefPtrWillBeRawPtr<Element> newBlock = nullptr; |
| 1288 if (ContainerNode* blockEnclosingList = listNode->parentNode()) { | 1299 if (ContainerNode* blockEnclosingList = listNode->parentNode()) { |
| 1289 if (isHTMLLIElement(*blockEnclosingList)) { // listNode is inside anothe
r list item | 1300 if (isHTMLLIElement(*blockEnclosingList)) { // listNode is inside anothe
r list item |
| 1290 if (visiblePositionAfterNode(*blockEnclosingList) == visiblePosition
AfterNode(*listNode)) { | 1301 if (visiblePositionAfterNode(*blockEnclosingList) == visiblePosition
AfterNode(*listNode)) { |
| 1291 // If listNode appears at the end of the outer list item, then m
ove listNode outside of this list item | 1302 // If listNode appears at the end of the outer list item, then m
ove listNode outside of this list item |
| 1292 // 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 | 1303 // 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 |
| 1293 // If listNode does NOT appear at the end, then we should consid
er it as a regular paragraph. | 1304 // If listNode does NOT appear at the end, then we should consid
er it as a regular paragraph. |
| 1294 // 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 | 1305 // 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 |
| 1295 splitElement(toElement(blockEnclosingList), listNode); | 1306 splitElement(toElement(blockEnclosingList), listNode); |
| 1296 removeNodePreservingChildren(listNode->parentNode()); | 1307 removeNodePreservingChildren(listNode->parentNode()); |
| 1297 newBlock = createListItemElement(document()); | 1308 newBlock = createListItemElement(document()); |
| 1298 } | 1309 } |
| 1299 // If listNode does NOT appear at the end of the outer list item, th
en behave as if in a regular paragraph. | 1310 // If listNode does NOT appear at the end of the outer list item, th
en behave as if in a regular paragraph. |
| 1300 } else if (isHTMLOListElement(*blockEnclosingList) || isHTMLUListElement
(*blockEnclosingList)) { | 1311 } else if (isHTMLOListElement(*blockEnclosingList) || isHTMLUListElement
(*blockEnclosingList)) { |
| 1301 newBlock = createListItemElement(document()); | 1312 newBlock = createListItemElement(document()); |
| 1302 } | 1313 } |
| 1303 } | 1314 } |
| 1304 if (!newBlock) | 1315 if (!newBlock) |
| 1305 newBlock = createDefaultParagraphElement(document()); | 1316 newBlock = createDefaultParagraphElement(document()); |
| 1306 | 1317 |
| 1307 RefPtr<Node> previousListNode = emptyListItem->isElementNode() ? ElementTrav
ersal::previousSibling(*emptyListItem): emptyListItem->previousSibling(); | 1318 RefPtrWillBeRawPtr<Node> previousListNode = emptyListItem->isElementNode() ?
ElementTraversal::previousSibling(*emptyListItem): emptyListItem->previousSibli
ng(); |
| 1308 RefPtr<Node> nextListNode = emptyListItem->isElementNode() ? ElementTraversa
l::nextSibling(*emptyListItem): emptyListItem->nextSibling(); | 1319 RefPtrWillBeRawPtr<Node> nextListNode = emptyListItem->isElementNode() ? Ele
mentTraversal::nextSibling(*emptyListItem): emptyListItem->nextSibling(); |
| 1309 if (isListItem(nextListNode.get()) || isListElement(nextListNode.get())) { | 1320 if (isListItem(nextListNode.get()) || isListElement(nextListNode.get())) { |
| 1310 // If emptyListItem follows another list item or nested list, split the
list node. | 1321 // If emptyListItem follows another list item or nested list, split the
list node. |
| 1311 if (isListItem(previousListNode.get()) || isListElement(previousListNode
.get())) | 1322 if (isListItem(previousListNode.get()) || isListElement(previousListNode
.get())) |
| 1312 splitElement(toElement(listNode), emptyListItem); | 1323 splitElement(toElement(listNode), emptyListItem); |
| 1313 | 1324 |
| 1314 // If emptyListItem is followed by other list item or nested list, then
insert newBlock before the list node. | 1325 // If emptyListItem is followed by other list item or nested list, then
insert newBlock before the list node. |
| 1315 // Because we have splitted the element, emptyListItem is the first elem
ent in the list node. | 1326 // Because we have splitted the element, emptyListItem is the first elem
ent in the list node. |
| 1316 // i.e. insert newBlock before ul or ol whose first element is emptyList
Item | 1327 // i.e. insert newBlock before ul or ol whose first element is emptyList
Item |
| 1317 insertNodeBefore(newBlock, listNode); | 1328 insertNodeBefore(newBlock, listNode); |
| 1318 removeNode(emptyListItem); | 1329 removeNode(emptyListItem); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1346 return false; | 1357 return false; |
| 1347 | 1358 |
| 1348 if (!isStartOfParagraph(caret) || !isEndOfParagraph(caret)) | 1359 if (!isStartOfParagraph(caret) || !isEndOfParagraph(caret)) |
| 1349 return false; | 1360 return false; |
| 1350 | 1361 |
| 1351 VisiblePosition previous(caret.previous(CannotCrossEditingBoundary)); | 1362 VisiblePosition previous(caret.previous(CannotCrossEditingBoundary)); |
| 1352 // Only move forward if there's nothing before the caret, or if there's unqu
oted content before it. | 1363 // Only move forward if there's nothing before the caret, or if there's unqu
oted content before it. |
| 1353 if (enclosingNodeOfType(previous.deepEquivalent(), &isMailBlockquote)) | 1364 if (enclosingNodeOfType(previous.deepEquivalent(), &isMailBlockquote)) |
| 1354 return false; | 1365 return false; |
| 1355 | 1366 |
| 1356 RefPtr<Node> br = createBreakElement(document()); | 1367 RefPtrWillBeRawPtr<Node> br = createBreakElement(document()); |
| 1357 // We want to replace this quoted paragraph with an unquoted one, so insert
a br | 1368 // We want to replace this quoted paragraph with an unquoted one, so insert
a br |
| 1358 // to hold the caret before the highest blockquote. | 1369 // to hold the caret before the highest blockquote. |
| 1359 insertNodeBefore(br, highestBlockquote); | 1370 insertNodeBefore(br, highestBlockquote); |
| 1360 VisiblePosition atBR(positionBeforeNode(br.get())); | 1371 VisiblePosition atBR(positionBeforeNode(br.get())); |
| 1361 // If the br we inserted collapsed, for example foo<br><blockquote>...</bloc
kquote>, insert | 1372 // If the br we inserted collapsed, for example foo<br><blockquote>...</bloc
kquote>, insert |
| 1362 // a second one. | 1373 // a second one. |
| 1363 if (!isStartOfParagraph(atBR)) | 1374 if (!isStartOfParagraph(atBR)) |
| 1364 insertNodeBefore(createBreakElement(document()), br); | 1375 insertNodeBefore(createBreakElement(document()), br); |
| 1365 setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional())
); | 1376 setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional())
); |
| 1366 | 1377 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1443 } | 1454 } |
| 1444 | 1455 |
| 1445 if (result.isNull() || !editableRootForPosition(result)) | 1456 if (result.isNull() || !editableRootForPosition(result)) |
| 1446 result = original; | 1457 result = original; |
| 1447 | 1458 |
| 1448 return result; | 1459 return result; |
| 1449 } | 1460 } |
| 1450 | 1461 |
| 1451 // Splits the tree parent by parent until we reach the specified ancestor. We us
e VisiblePositions | 1462 // Splits the tree parent by parent until we reach the specified ancestor. We us
e VisiblePositions |
| 1452 // to determine if the split is necessary. Returns the last split node. | 1463 // to determine if the split is necessary. Returns the last split node. |
| 1453 PassRefPtr<Node> CompositeEditCommand::splitTreeToNode(Node* start, Node* end, b
ool shouldSplitAncestor) | 1464 PassRefPtrWillBeRawPtr<Node> CompositeEditCommand::splitTreeToNode(Node* start,
Node* end, bool shouldSplitAncestor) |
| 1454 { | 1465 { |
| 1455 ASSERT(start); | 1466 ASSERT(start); |
| 1456 ASSERT(end); | 1467 ASSERT(end); |
| 1457 ASSERT(start != end); | 1468 ASSERT(start != end); |
| 1458 | 1469 |
| 1459 RefPtr<Node> node; | |
| 1460 if (shouldSplitAncestor && end->parentNode()) | 1470 if (shouldSplitAncestor && end->parentNode()) |
| 1461 end = end->parentNode(); | 1471 end = end->parentNode(); |
| 1462 | 1472 |
| 1463 RefPtr<Node> endNode = end; | 1473 RefPtrWillBeRawPtr<Node> endNode = end; |
| 1474 RefPtrWillBeRawPtr<Node> node = nullptr; |
| 1464 for (node = start; node && node->parentNode() != endNode; node = node->paren
tNode()) { | 1475 for (node = start; node && node->parentNode() != endNode; node = node->paren
tNode()) { |
| 1465 if (!node->parentNode()->isElementNode()) | 1476 if (!node->parentNode()->isElementNode()) |
| 1466 break; | 1477 break; |
| 1467 // Do not split a node when doing so introduces an empty node. | 1478 // Do not split a node when doing so introduces an empty node. |
| 1468 VisiblePosition positionInParent(firstPositionInNode(node->parentNode())
); | 1479 VisiblePosition positionInParent(firstPositionInNode(node->parentNode())
); |
| 1469 VisiblePosition positionInNode(firstPositionInOrBeforeNode(node.get())); | 1480 VisiblePosition positionInNode(firstPositionInOrBeforeNode(node.get())); |
| 1470 if (positionInParent != positionInNode) | 1481 if (positionInParent != positionInNode) |
| 1471 splitElement(toElement(node->parentNode()), node); | 1482 splitElement(toElement(node->parentNode()), node); |
| 1472 } | 1483 } |
| 1473 | 1484 |
| 1474 return node.release(); | 1485 return node.release(); |
| 1475 } | 1486 } |
| 1476 | 1487 |
| 1477 PassRefPtrWillBeRawPtr<Element> createBlockPlaceholderElement(Document& document
) | 1488 PassRefPtrWillBeRawPtr<Element> createBlockPlaceholderElement(Document& document
) |
| 1478 { | 1489 { |
| 1479 return document.createElement(brTag, false); | 1490 return document.createElement(brTag, false); |
| 1480 } | 1491 } |
| 1481 | 1492 |
| 1493 void CompositeEditCommand::trace(Visitor* visitor) |
| 1494 { |
| 1495 visitor->trace(m_commands); |
| 1496 visitor->trace(m_composition); |
| 1497 EditCommand::trace(visitor); |
| 1498 } |
| 1499 |
| 1482 } // namespace WebCore | 1500 } // namespace WebCore |
| OLD | NEW |