| 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 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 349 | 349 |
| 350 void CompositeEditCommand::insertNodeAt(const Handle<Node>& insertChild, const P
osition& editingPosition) | 350 void CompositeEditCommand::insertNodeAt(const Handle<Node>& insertChild, const P
osition& editingPosition) |
| 351 { | 351 { |
| 352 ASSERT(isEditablePosition(editingPosition)); | 352 ASSERT(isEditablePosition(editingPosition)); |
| 353 // For editing positions like [table, 0], insert before the table, | 353 // For editing positions like [table, 0], insert before the table, |
| 354 // likewise for replaced elements, brs, etc. | 354 // likewise for replaced elements, brs, etc. |
| 355 Position p = editingPosition.parentAnchoredEquivalent(); | 355 Position p = editingPosition.parentAnchoredEquivalent(); |
| 356 Handle<Node> refChild = p.deprecatedNode(); | 356 Handle<Node> refChild = p.deprecatedNode(); |
| 357 int offset = p.deprecatedEditingOffset(); | 357 int offset = p.deprecatedEditingOffset(); |
| 358 | 358 |
| 359 if (canHaveChildrenForEditing(refChild.raw())) { | 359 if (canHaveChildrenForEditing(refChild)) { |
| 360 Handle<Node> child = refChild->firstChild(); | 360 Handle<Node> child = refChild->firstChild(); |
| 361 for (int i = 0; child && i < offset; i++) | 361 for (int i = 0; child && i < offset; i++) |
| 362 child = child->nextSibling(); | 362 child = child->nextSibling(); |
| 363 if (child) | 363 if (child) |
| 364 insertNodeBefore(insertChild, child); | 364 insertNodeBefore(insertChild, child); |
| 365 else | 365 else |
| 366 appendNode(insertChild, toContainerNode(refChild)); | 366 appendNode(insertChild, toContainerNode(refChild)); |
| 367 } else if (caretMinOffset(refChild.raw()) >= offset) | 367 } else if (caretMinOffset(refChild) >= offset) |
| 368 insertNodeBefore(insertChild, refChild); | 368 insertNodeBefore(insertChild, refChild); |
| 369 else if (refChild->isTextNode() && caretMaxOffset(refChild.raw()) > offset)
{ | 369 else if (refChild->isTextNode() && caretMaxOffset(refChild) > offset) { |
| 370 splitTextNode(toText(refChild.raw()), offset); | 370 splitTextNode(toText(refChild), offset); |
| 371 | 371 |
| 372 // Mutation events (bug 22634) from the text node insertion may have rem
oved the refChild | 372 // Mutation events (bug 22634) from the text node insertion may have rem
oved the refChild |
| 373 if (!refChild->inDocument()) | 373 if (!refChild->inDocument()) |
| 374 return; | 374 return; |
| 375 insertNodeBefore(insertChild, refChild); | 375 insertNodeBefore(insertChild, refChild); |
| 376 } else | 376 } else |
| 377 insertNodeAfter(insertChild, refChild); | 377 insertNodeAfter(insertChild, refChild); |
| 378 } | 378 } |
| 379 | 379 |
| 380 void CompositeEditCommand::appendNode(const Handle<Node>& node, const Handle<Con
tainerNode>& parent) | 380 void CompositeEditCommand::appendNode(const Handle<Node>& node, const Handle<Con
tainerNode>& parent) |
| 381 { | 381 { |
| 382 ASSERT(canHaveChildrenForEditing(parent.raw())); | 382 ASSERT(canHaveChildrenForEditing(parent)); |
| 383 applyCommandToComposite(AppendNodeCommand::create(parent, node)); | 383 applyCommandToComposite(AppendNodeCommand::create(parent, node)); |
| 384 } | 384 } |
| 385 | 385 |
| 386 void CompositeEditCommand::removeChildrenInRange(const Handle<Node>& node, unsig
ned from, unsigned to) | 386 void CompositeEditCommand::removeChildrenInRange(const Handle<Node>& node, unsig
ned from, unsigned to) |
| 387 { | 387 { |
| 388 CollectionRoot<Vector<Member<Node> > > children; | 388 CollectionRoot<Vector<Member<Node> > > children; |
| 389 Handle<Node> child = node->childNode(from); | 389 Handle<Node> child = node->childNode(from); |
| 390 for (unsigned i = from; child && i < to; i++, child = child->nextSibling())
{ | 390 for (unsigned i = from; child && i < to; i++, child = child->nextSibling())
{ |
| 391 NoHandleScope scope; | 391 NoHandleScope scope; |
| 392 children->append(child); | 392 children->append(child); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 for (unsigned i = 0; i < nodesToRemove->size(); i++) { | 433 for (unsigned i = 0; i < nodesToRemove->size(); i++) { |
| 434 HandleScope scope; | 434 HandleScope scope; |
| 435 removeNode(nodesToRemove[i]); | 435 removeNode(nodesToRemove[i]); |
| 436 appendNode(nodesToRemove[i], newParent); | 436 appendNode(nodesToRemove[i], newParent); |
| 437 } | 437 } |
| 438 } | 438 } |
| 439 | 439 |
| 440 void CompositeEditCommand::updatePositionForNodeRemovalPreservingChildren(Positi
on& position, const Handle<Node>& node) | 440 void CompositeEditCommand::updatePositionForNodeRemovalPreservingChildren(Positi
on& position, const Handle<Node>& node) |
| 441 { | 441 { |
| 442 int offset = (position.anchorType() == Position::PositionIsOffsetInAnchor) ?
position.offsetInContainerNode() : 0; | 442 int offset = (position.anchorType() == Position::PositionIsOffsetInAnchor) ?
position.offsetInContainerNode() : 0; |
| 443 updatePositionForNodeRemoval(position, node.raw()); | 443 updatePositionForNodeRemoval(position, node); |
| 444 if (offset) | 444 if (offset) |
| 445 position.moveToOffset(offset); | 445 position.moveToOffset(offset); |
| 446 } | 446 } |
| 447 | 447 |
| 448 Result<HTMLElement> CompositeEditCommand::replaceElementWithSpanPreservingChildr
enAndAttributes(const Handle<HTMLElement>& node) | 448 Result<HTMLElement> CompositeEditCommand::replaceElementWithSpanPreservingChildr
enAndAttributes(const Handle<HTMLElement>& node) |
| 449 { | 449 { |
| 450 // It would also be possible to implement all of ReplaceNodeWithSpanCommand | 450 // It would also be possible to implement all of ReplaceNodeWithSpanCommand |
| 451 // as a series of existing smaller edit commands. Someone who wanted to | 451 // as a series of existing smaller edit commands. Someone who wanted to |
| 452 // reduce the number of edit commands could do so here. | 452 // reduce the number of edit commands could do so here. |
| 453 RefPtr<ReplaceNodeWithSpanCommand> command = ReplaceNodeWithSpanCommand::cre
ate(node); | 453 RefPtr<ReplaceNodeWithSpanCommand> command = ReplaceNodeWithSpanCommand::cre
ate(node); |
| 454 applyCommandToComposite(command); | 454 applyCommandToComposite(command); |
| 455 // Returning a raw pointer here is OK because the command is retained by | 455 // Returning a raw pointer here is OK because the command is retained by |
| 456 // applyCommandToComposite (thus retaining the span), and the span is also | 456 // applyCommandToComposite (thus retaining the span), and the span is also |
| 457 // in the DOM tree, and thus alive whie it has a parent. | 457 // in the DOM tree, and thus alive whie it has a parent. |
| 458 ASSERT(command->spanElement()->inDocument()); | 458 ASSERT(command->spanElement()->inDocument()); |
| 459 return command->spanElement(); | 459 return command->spanElement(); |
| 460 } | 460 } |
| 461 | 461 |
| 462 void CompositeEditCommand::prune(const Handle<Node>& node) | 462 void CompositeEditCommand::prune(const Handle<Node>& node) |
| 463 { | 463 { |
| 464 if (Handle<Node> highestNodeToRemove = adoptRawResult(highestNodeToRemoveInP
runing(node.raw()))) | 464 if (Handle<Node> highestNodeToRemove = highestNodeToRemoveInPruning(node)) |
| 465 removeNode(highestNodeToRemove); | 465 removeNode(highestNodeToRemove); |
| 466 } | 466 } |
| 467 | 467 |
| 468 void CompositeEditCommand::splitTextNode(const Handle<Text>& node, unsigned offs
et) | 468 void CompositeEditCommand::splitTextNode(const Handle<Text>& node, unsigned offs
et) |
| 469 { | 469 { |
| 470 applyCommandToComposite(SplitTextNodeCommand::create(node, offset)); | 470 applyCommandToComposite(SplitTextNodeCommand::create(node, offset)); |
| 471 } | 471 } |
| 472 | 472 |
| 473 void CompositeEditCommand::splitElement(const Handle<Element>& element, const Ha
ndle<Node>& atChild) | 473 void CompositeEditCommand::splitElement(const Handle<Element>& element, const Ha
ndle<Node>& atChild) |
| 474 { | 474 { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 514 Handle<Text> node(prpNode); | 514 Handle<Text> node(prpNode); |
| 515 applyCommandToComposite(DeleteFromTextNodeCommand::create(node, offset, coun
t)); | 515 applyCommandToComposite(DeleteFromTextNodeCommand::create(node, offset, coun
t)); |
| 516 if (!replacementText.isEmpty()) | 516 if (!replacementText.isEmpty()) |
| 517 applyCommandToComposite(InsertIntoTextNodeCommand::create(node, offset,
replacementText)); | 517 applyCommandToComposite(InsertIntoTextNodeCommand::create(node, offset,
replacementText)); |
| 518 } | 518 } |
| 519 | 519 |
| 520 Position CompositeEditCommand::replaceSelectedTextInNode(const String& text) | 520 Position CompositeEditCommand::replaceSelectedTextInNode(const String& text) |
| 521 { | 521 { |
| 522 Position start = endingSelection().start(); | 522 Position start = endingSelection().start(); |
| 523 Position end = endingSelection().end(); | 523 Position end = endingSelection().end(); |
| 524 if (start.containerNode() != end.containerNode() || !start.containerNode()->
isTextNode() || isTabSpanTextNode(start.containerNode().handle().raw())) | 524 if (start.containerNode() != end.containerNode() || !start.containerNode()->
isTextNode() || isTabSpanTextNode(start.containerNode())) |
| 525 return Position(); | 525 return Position(); |
| 526 | 526 |
| 527 Handle<Text> textNode = start.containerText(); | 527 Handle<Text> textNode = start.containerText(); |
| 528 replaceTextInNode(textNode, start.offsetInContainerNode(), end.offsetInConta
inerNode() - start.offsetInContainerNode(), text); | 528 replaceTextInNode(textNode, start.offsetInContainerNode(), end.offsetInConta
inerNode() - start.offsetInContainerNode(), text); |
| 529 | 529 |
| 530 return Position(textNode, start.offsetInContainerNode() + text.length()); | 530 return Position(textNode, start.offsetInContainerNode() + text.length()); |
| 531 } | 531 } |
| 532 | 532 |
| 533 static void copyMarkers(const Vector<DocumentMarker*>& markerPointers, Vector<Do
cumentMarker>& markers) | 533 static void copyMarkers(const Vector<DocumentMarker*>& markerPointers, Vector<Do
cumentMarker>& markers) |
| 534 { | 534 { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 547 replaceTextInNode(node, offset, count, replacementText); | 547 replaceTextInNode(node, offset, count, replacementText); |
| 548 Handle<Range> newRange = Range::create(document(), node, offset, node, offse
t + replacementText.length()); | 548 Handle<Range> newRange = Range::create(document(), node, offset, node, offse
t + replacementText.length()); |
| 549 for (size_t i = 0; i < markers.size(); ++i) { | 549 for (size_t i = 0; i < markers.size(); ++i) { |
| 550 HandleScope scope; | 550 HandleScope scope; |
| 551 markerController->addMarker(newRange, markers[i].type(), markers[i].desc
ription()); | 551 markerController->addMarker(newRange, markers[i].type(), markers[i].desc
ription()); |
| 552 } | 552 } |
| 553 } | 553 } |
| 554 | 554 |
| 555 Position CompositeEditCommand::positionOutsideTabSpan(const Position& pos) | 555 Position CompositeEditCommand::positionOutsideTabSpan(const Position& pos) |
| 556 { | 556 { |
| 557 if (!isTabSpanTextNode(pos.anchorNode().handle().raw())) | 557 if (!isTabSpanTextNode(pos.anchorNode())) |
| 558 return pos; | 558 return pos; |
| 559 | 559 |
| 560 switch (pos.anchorType()) { | 560 switch (pos.anchorType()) { |
| 561 case Position::PositionIsBeforeChildren: | 561 case Position::PositionIsBeforeChildren: |
| 562 case Position::PositionIsAfterChildren: | 562 case Position::PositionIsAfterChildren: |
| 563 ASSERT_NOT_REACHED(); | 563 ASSERT_NOT_REACHED(); |
| 564 return pos; | 564 return pos; |
| 565 case Position::PositionIsOffsetInAnchor: | 565 case Position::PositionIsOffsetInAnchor: |
| 566 break; | 566 break; |
| 567 case Position::PositionIsBeforeAnchor: | 567 case Position::PositionIsBeforeAnchor: |
| 568 return positionInParentBeforeNode(pos.anchorNode()); | 568 return positionInParentBeforeNode(pos.anchorNode()); |
| 569 case Position::PositionIsAfterAnchor: | 569 case Position::PositionIsAfterAnchor: |
| 570 return positionInParentAfterNode(pos.anchorNode()); | 570 return positionInParentAfterNode(pos.anchorNode()); |
| 571 } | 571 } |
| 572 | 572 |
| 573 Handle<Node> tabSpan = adoptRawResult(tabSpanNode(pos.containerNode().handle
().raw())); | 573 Handle<Node> tabSpan = tabSpanNode(pos.containerNode()); |
| 574 | 574 |
| 575 if (pos.offsetInContainerNode() <= caretMinOffset(pos.containerNode().handle
().raw())) | 575 if (pos.offsetInContainerNode() <= caretMinOffset(pos.containerNode())) |
| 576 return positionInParentBeforeNode(tabSpan); | 576 return positionInParentBeforeNode(tabSpan); |
| 577 | 577 |
| 578 if (pos.offsetInContainerNode() >= caretMaxOffset(pos.containerNode().handle
().raw())) | 578 if (pos.offsetInContainerNode() >= caretMaxOffset(pos.containerNode())) |
| 579 return positionInParentAfterNode(tabSpan); | 579 return positionInParentAfterNode(tabSpan); |
| 580 | 580 |
| 581 splitTextNodeContainingElement(toText(pos.containerNode().handle().raw()), p
os.offsetInContainerNode()); | 581 splitTextNodeContainingElement(toText(pos.containerNode()), pos.offsetInCont
ainerNode()); |
| 582 return positionInParentBeforeNode(tabSpan); | 582 return positionInParentBeforeNode(tabSpan); |
| 583 } | 583 } |
| 584 | 584 |
| 585 void CompositeEditCommand::insertNodeAtTabSpanPosition(const Handle<Node>& node,
const Position& pos) | 585 void CompositeEditCommand::insertNodeAtTabSpanPosition(const Handle<Node>& node,
const Position& pos) |
| 586 { | 586 { |
| 587 // insert node before, after, or at split of tab span | 587 // insert node before, after, or at split of tab span |
| 588 insertNodeAt(node, positionOutsideTabSpan(pos)); | 588 insertNodeAt(node, positionOutsideTabSpan(pos)); |
| 589 } | 589 } |
| 590 | 590 |
| 591 void CompositeEditCommand::deleteSelection(bool smartDelete, bool mergeBlocksAft
erDelete, bool replace, bool expandForSpecialElements, bool sanitizeMarkup) | 591 void CompositeEditCommand::deleteSelection(bool smartDelete, bool mergeBlocksAft
erDelete, bool replace, bool expandForSpecialElements, bool sanitizeMarkup) |
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 940 | 940 |
| 941 Position upstreamStart = visibleParagraphStart.deepEquivalent().upstream(); | 941 Position upstreamStart = visibleParagraphStart.deepEquivalent().upstream(); |
| 942 Position upstreamEnd = visibleEnd.deepEquivalent().upstream(); | 942 Position upstreamEnd = visibleEnd.deepEquivalent().upstream(); |
| 943 | 943 |
| 944 // If there are no VisiblePositions in the same block as pos then | 944 // If there are no VisiblePositions in the same block as pos then |
| 945 // upstreamStart will be outside the paragraph | 945 // upstreamStart will be outside the paragraph |
| 946 if (comparePositions(pos, upstreamStart) < 0) | 946 if (comparePositions(pos, upstreamStart) < 0) |
| 947 return nullptr; | 947 return nullptr; |
| 948 | 948 |
| 949 // Perform some checks to see if we need to perform work in this function. | 949 // Perform some checks to see if we need to perform work in this function. |
| 950 if (isBlock(upstreamStart.deprecatedNode().handle().raw())) { | 950 if (isBlock(upstreamStart.deprecatedNode())) { |
| 951 // If the block is the root editable element, always move content to a n
ew block, | 951 // If the block is the root editable element, always move content to a n
ew block, |
| 952 // since it is illegal to modify attributes on the root editable element
for editing. | 952 // since it is illegal to modify attributes on the root editable element
for editing. |
| 953 if (upstreamStart.deprecatedNode() == editableRootForPosition(upstreamSt
art)) { | 953 if (upstreamStart.deprecatedNode() == editableRootForPosition(upstreamSt
art)) { |
| 954 // If the block is the root editable element and it contains no visi
ble content, create a new | 954 // If the block is the root editable element and it contains no visi
ble content, create a new |
| 955 // block but don't try and move content into it, since there's nothi
ng for moveParagraphs to move. | 955 // block but don't try and move content into it, since there's nothi
ng for moveParagraphs to move. |
| 956 if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(upstream
Start.deprecatedNode()->renderer())) | 956 if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(upstream
Start.deprecatedNode()->renderer())) |
| 957 return insertNewDefaultParagraphElementAt(upstreamStart); | 957 return insertNewDefaultParagraphElementAt(upstreamStart); |
| 958 } else if (isBlock(upstreamEnd.deprecatedNode().handle().raw())) { | 958 } else if (isBlock(upstreamEnd.deprecatedNode())) { |
| 959 if (!upstreamEnd.deprecatedNode()->isDescendantOf(upstreamStart.depr
ecatedNode().handle().raw())) { | 959 if (!upstreamEnd.deprecatedNode()->isDescendantOf(upstreamStart.depr
ecatedNode().handle().raw())) { |
| 960 // If the paragraph end is a descendant of paragraph start, then
we need to run | 960 // If the paragraph end is a descendant of paragraph start, then
we need to run |
| 961 // the rest of this function. If not, we can bail here. | 961 // the rest of this function. If not, we can bail here. |
| 962 return nullptr; | 962 return nullptr; |
| 963 } | 963 } |
| 964 } else if (enclosingBlock(upstreamEnd.deprecatedNode().handle().raw()) !
= upstreamStart.deprecatedNode().handle().raw()) { | 964 } else if (enclosingBlock(upstreamEnd.deprecatedNode()) != upstreamStart
.deprecatedNode()) { |
| 965 // The visibleEnd. It must be an ancestor of the paragraph start. | 965 // The visibleEnd. It must be an ancestor of the paragraph start. |
| 966 // We can bail as we have a full block to work with. | 966 // We can bail as we have a full block to work with. |
| 967 ASSERT(upstreamStart.deprecatedNode()->isDescendantOf(enclosingBlock
(upstreamEnd.deprecatedNode().handle().raw()).handle().raw())); | 967 ASSERT(upstreamStart.deprecatedNode()->isDescendantOf(enclosingBlock
(upstreamEnd.deprecatedNode()).handle().raw())); |
| 968 return nullptr; | 968 return nullptr; |
| 969 } else if (isEndOfEditableOrNonEditableContent(visibleEnd)) { | 969 } else if (isEndOfEditableOrNonEditableContent(visibleEnd)) { |
| 970 // At the end of the editable region. We can bail here as well. | 970 // At the end of the editable region. We can bail here as well. |
| 971 return nullptr; | 971 return nullptr; |
| 972 } | 972 } |
| 973 } | 973 } |
| 974 | 974 |
| 975 Handle<Node> newBlock = insertNewDefaultParagraphElementAt(upstreamStart); | 975 Handle<Node> newBlock = insertNewDefaultParagraphElementAt(upstreamStart); |
| 976 | 976 |
| 977 bool endWasBr = visibleParagraphEnd.deepEquivalent().deprecatedNode()->hasTa
gName(brTag); | 977 bool endWasBr = visibleParagraphEnd.deepEquivalent().deprecatedNode()->hasTa
gName(brTag); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1003 | 1003 |
| 1004 void CompositeEditCommand::cloneParagraphUnderNewElement(Position& start, Positi
on& end, const Handle<Node>& passedOuterNode, const Handle<Element>& blockElemen
t) | 1004 void CompositeEditCommand::cloneParagraphUnderNewElement(Position& start, Positi
on& end, const Handle<Node>& passedOuterNode, const Handle<Element>& blockElemen
t) |
| 1005 { | 1005 { |
| 1006 // First we clone the outerNode | 1006 // First we clone the outerNode |
| 1007 Handle<Node> lastNode; | 1007 Handle<Node> lastNode; |
| 1008 Handle<Node> outerNode = passedOuterNode; | 1008 Handle<Node> outerNode = passedOuterNode; |
| 1009 | 1009 |
| 1010 if (outerNode->isRootEditableElement()) { | 1010 if (outerNode->isRootEditableElement()) { |
| 1011 lastNode = blockElement; | 1011 lastNode = blockElement; |
| 1012 } else { | 1012 } else { |
| 1013 lastNode = outerNode->cloneNode(isTableElement(outerNode.raw())); | 1013 lastNode = outerNode->cloneNode(isTableElement(outerNode)); |
| 1014 appendNode(lastNode, blockElement); | 1014 appendNode(lastNode, blockElement); |
| 1015 } | 1015 } |
| 1016 | 1016 |
| 1017 if (start.deprecatedNode() != outerNode && lastNode->isElementNode()) { | 1017 if (start.deprecatedNode() != outerNode && lastNode->isElementNode()) { |
| 1018 CollectionRoot<Vector<Member<Node> > > ancestors; | 1018 CollectionRoot<Vector<Member<Node> > > ancestors; |
| 1019 | 1019 |
| 1020 // Insert each node from innerNode to outerNode (excluded) in a list. | 1020 // Insert each node from innerNode to outerNode (excluded) in a list. |
| 1021 for (Handle<Node> n = start.deprecatedNode(); n && n != outerNode; n = n
->parentNode()) { | 1021 for (Handle<Node> n = start.deprecatedNode(); n && n != outerNode; n = n
->parentNode()) { |
| 1022 NoHandleScope scope; | 1022 NoHandleScope scope; |
| 1023 ancestors->append(n); | 1023 ancestors->append(n); |
| 1024 } | 1024 } |
| 1025 | 1025 |
| 1026 // Clone every node between start.deprecatedNode() and outerBlock. | 1026 // Clone every node between start.deprecatedNode() and outerBlock. |
| 1027 | 1027 |
| 1028 for (size_t i = ancestors->size(); i != 0; --i) { | 1028 for (size_t i = ancestors->size(); i != 0; --i) { |
| 1029 HandleScope scope; | 1029 HandleScope scope; |
| 1030 Handle<Node> item = ancestors[i - 1]; | 1030 Handle<Node> item = ancestors[i - 1]; |
| 1031 Handle<Node> child = item->cloneNode(isTableElement(item.raw())); | 1031 Handle<Node> child = item->cloneNode(isTableElement(item)); |
| 1032 appendNode(child, Handle<Element>::cast(lastNode)); | 1032 appendNode(child, Handle<Element>::cast(lastNode)); |
| 1033 lastNode = child; | 1033 lastNode = child; |
| 1034 } | 1034 } |
| 1035 } | 1035 } |
| 1036 | 1036 |
| 1037 // Handle the case of paragraphs with more than one node, | 1037 // Handle the case of paragraphs with more than one node, |
| 1038 // cloning all the siblings until end.deprecatedNode() is reached. | 1038 // cloning all the siblings until end.deprecatedNode() is reached. |
| 1039 | 1039 |
| 1040 if (start.deprecatedNode() != end.deprecatedNode() && !start.deprecatedNode(
)->isDescendantOf(end.deprecatedNode().handle().raw())) { | 1040 if (start.deprecatedNode() != end.deprecatedNode() && !start.deprecatedNode(
)->isDescendantOf(end.deprecatedNode().handle().raw())) { |
| 1041 // If end is not a descendant of outerNode we need to | 1041 // If end is not a descendant of outerNode we need to |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1080 // Note: We want the rightmost candidate. | 1080 // Note: We want the rightmost candidate. |
| 1081 Position position = caretAfterDelete.deepEquivalent().downstream(); | 1081 Position position = caretAfterDelete.deepEquivalent().downstream(); |
| 1082 Handle<Node> node = position.deprecatedNode(); | 1082 Handle<Node> node = position.deprecatedNode(); |
| 1083 // Normally deletion will leave a br as a placeholder. | 1083 // Normally deletion will leave a br as a placeholder. |
| 1084 if (node->hasTagName(brTag)) | 1084 if (node->hasTagName(brTag)) |
| 1085 removeNodeAndPruneAncestors(node); | 1085 removeNodeAndPruneAncestors(node); |
| 1086 // If the selection to move was empty and in an empty block that | 1086 // If the selection to move was empty and in an empty block that |
| 1087 // doesn't require a placeholder to prop itself open (like a bordered | 1087 // doesn't require a placeholder to prop itself open (like a bordered |
| 1088 // div or an li), remove it during the move (the list removal code | 1088 // div or an li), remove it during the move (the list removal code |
| 1089 // expects this behavior). | 1089 // expects this behavior). |
| 1090 else if (isBlock(node.raw())) { | 1090 else if (isBlock(node)) { |
| 1091 // If caret position after deletion and destination position coincid
es, | 1091 // If caret position after deletion and destination position coincid
es, |
| 1092 // node should not be removed. | 1092 // node should not be removed. |
| 1093 if (!position.rendersInDifferentPosition(destination.deepEquivalent(
))) { | 1093 if (!position.rendersInDifferentPosition(destination.deepEquivalent(
))) { |
| 1094 prune(node); | 1094 prune(node); |
| 1095 return; | 1095 return; |
| 1096 } | 1096 } |
| 1097 removeNodeAndPruneAncestors(node); | 1097 removeNodeAndPruneAncestors(node); |
| 1098 } | 1098 } |
| 1099 else if (lineBreakExistsAtPosition(position)) { | 1099 else if (lineBreakExistsAtPosition(position)) { |
| 1100 // There is a preserved '\n' at caretAfterDelete. | 1100 // There is a preserved '\n' at caretAfterDelete. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1141 // Add a br if pruning an empty block level element caused a collapse. For
example: | 1141 // Add a br if pruning an empty block level element caused a collapse. For
example: |
| 1142 // foo^ | 1142 // foo^ |
| 1143 // <div>bar</div> | 1143 // <div>bar</div> |
| 1144 // baz | 1144 // baz |
| 1145 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. Th
at would | 1145 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. Th
at would |
| 1146 // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br
. | 1146 // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br
. |
| 1147 // Must recononicalize these two VisiblePositions after the pruning above. | 1147 // Must recononicalize these two VisiblePositions after the pruning above. |
| 1148 beforeParagraph = VisiblePosition(beforeParagraph.deepEquivalent()); | 1148 beforeParagraph = VisiblePosition(beforeParagraph.deepEquivalent()); |
| 1149 afterParagraph = VisiblePosition(afterParagraph.deepEquivalent()); | 1149 afterParagraph = VisiblePosition(afterParagraph.deepEquivalent()); |
| 1150 | 1150 |
| 1151 if (beforeParagraph.isNotNull() && !isTableElement(beforeParagraph.deepEquiv
alent().deprecatedNode().handle().raw()) | 1151 if (beforeParagraph.isNotNull() && !isTableElement(beforeParagraph.deepEquiv
alent().deprecatedNode()) |
| 1152 && ((!isEndOfParagraph(beforeParagraph) && !isStartOfParagraph(beforePar
agraph)) || beforeParagraph == afterParagraph)) { | 1152 && ((!isEndOfParagraph(beforeParagraph) && !isStartOfParagraph(beforePar
agraph)) || beforeParagraph == afterParagraph)) { |
| 1153 // FIXME: Trim text between beforeParagraph and afterParagraph if they a
ren't equal. | 1153 // FIXME: Trim text between beforeParagraph and afterParagraph if they a
ren't equal. |
| 1154 insertNodeAt(createBreakElement(document()), beforeParagraph.deepEquival
ent()); | 1154 insertNodeAt(createBreakElement(document()), beforeParagraph.deepEquival
ent()); |
| 1155 } | 1155 } |
| 1156 } | 1156 } |
| 1157 | 1157 |
| 1158 void CompositeEditCommand::moveParagraph(const VisiblePosition& startOfParagraph
ToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& dest
ination, bool preserveSelection, bool preserveStyle, const Handle<Node>& constra
iningAncestor) | 1158 void CompositeEditCommand::moveParagraph(const VisiblePosition& startOfParagraph
ToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& dest
ination, bool preserveSelection, bool preserveStyle, const Handle<Node>& constra
iningAncestor) |
| 1159 { | 1159 { |
| 1160 ASSERT(isStartOfParagraph(startOfParagraphToMove)); | 1160 ASSERT(isStartOfParagraph(startOfParagraphToMove)); |
| 1161 ASSERT(isEndOfParagraph(endOfParagraphToMove)); | 1161 ASSERT(isEndOfParagraph(endOfParagraphToMove)); |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1279 Handle<Range> start = TextIterator::rangeFromLocationAndLength(adoptRawR
esult(document()->documentElement().handle().raw()), destinationIndex + startInd
ex, 0, true); | 1279 Handle<Range> start = TextIterator::rangeFromLocationAndLength(adoptRawR
esult(document()->documentElement().handle().raw()), destinationIndex + startInd
ex, 0, true); |
| 1280 Handle<Range> end = TextIterator::rangeFromLocationAndLength(adoptRawRes
ult(document()->documentElement().handle().raw()), destinationIndex + endIndex,
0, true); | 1280 Handle<Range> end = TextIterator::rangeFromLocationAndLength(adoptRawRes
ult(document()->documentElement().handle().raw()), destinationIndex + endIndex,
0, true); |
| 1281 if (start && end) | 1281 if (start && end) |
| 1282 setEndingSelection(VisibleSelection(start->startPosition(), end->sta
rtPosition(), DOWNSTREAM, originalIsDirectional)); | 1282 setEndingSelection(VisibleSelection(start->startPosition(), end->sta
rtPosition(), DOWNSTREAM, originalIsDirectional)); |
| 1283 } | 1283 } |
| 1284 } | 1284 } |
| 1285 | 1285 |
| 1286 // FIXME: Send an appropriate shouldDeleteRange call. | 1286 // FIXME: Send an appropriate shouldDeleteRange call. |
| 1287 bool CompositeEditCommand::breakOutOfEmptyListItem() | 1287 bool CompositeEditCommand::breakOutOfEmptyListItem() |
| 1288 { | 1288 { |
| 1289 Handle<Node> emptyListItem = adoptRawResult(enclosingEmptyListItem(endingSel
ection().visibleStart())); | 1289 Handle<Node> emptyListItem = enclosingEmptyListItem(endingSelection().visibl
eStart()); |
| 1290 if (!emptyListItem) | 1290 if (!emptyListItem) |
| 1291 return false; | 1291 return false; |
| 1292 | 1292 |
| 1293 RefPtr<EditingStyle> style = EditingStyle::create(endingSelection().start())
; | 1293 RefPtr<EditingStyle> style = EditingStyle::create(endingSelection().start())
; |
| 1294 style->mergeTypingStyle(document()); | 1294 style->mergeTypingStyle(document()); |
| 1295 | 1295 |
| 1296 Handle<ContainerNode> listNode = emptyListItem->parentNode(); | 1296 Handle<ContainerNode> listNode = emptyListItem->parentNode(); |
| 1297 // FIXME: Can't we do something better when the immediate parent wasn't a li
st node? | 1297 // FIXME: Can't we do something better when the immediate parent wasn't a li
st node? |
| 1298 if (!listNode | 1298 if (!listNode |
| 1299 || (!listNode->hasTagName(ulTag) && !listNode->hasTagName(olTag)) | 1299 || (!listNode->hasTagName(ulTag) && !listNode->hasTagName(olTag)) |
| 1300 || !listNode->rendererIsEditable() | 1300 || !listNode->rendererIsEditable() |
| 1301 || listNode == emptyListItem->rootEditableElement()) | 1301 || listNode == emptyListItem->rootEditableElement()) |
| 1302 return false; | 1302 return false; |
| 1303 | 1303 |
| 1304 Handle<Element> newBlock; | 1304 Handle<Element> newBlock; |
| 1305 if (Handle<ContainerNode> blockEnclosingList = listNode->parentNode()) { | 1305 if (Handle<ContainerNode> blockEnclosingList = listNode->parentNode()) { |
| 1306 if (blockEnclosingList->hasTagName(liTag)) { // listNode is inside anoth
er list item | 1306 if (blockEnclosingList->hasTagName(liTag)) { // listNode is inside anoth
er list item |
| 1307 if (visiblePositionAfterNode(blockEnclosingList.raw()) == visiblePos
itionAfterNode(listNode.raw())) { | 1307 if (visiblePositionAfterNode(blockEnclosingList) == visiblePositionA
fterNode(listNode)) { |
| 1308 // If listNode appears at the end of the outer list item, then m
ove listNode outside of this list item | 1308 // If listNode appears at the end of the outer list item, then m
ove listNode outside of this list item |
| 1309 // 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 | 1309 // 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 |
| 1310 // If listNode does NOT appear at the end, then we should consid
er it as a regular paragraph. | 1310 // If listNode does NOT appear at the end, then we should consid
er it as a regular paragraph. |
| 1311 // 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 | 1311 // 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 |
| 1312 splitElement(toElement(blockEnclosingList), listNode); | 1312 splitElement(toElement(blockEnclosingList), listNode); |
| 1313 removeNodePreservingChildren(listNode->parentNode()); | 1313 removeNodePreservingChildren(listNode->parentNode()); |
| 1314 newBlock = createListItemElement(document()); | 1314 newBlock = createListItemElement(document()); |
| 1315 } | 1315 } |
| 1316 // If listNode does NOT appear at the end of the outer list item, th
en behave as if in a regular paragraph. | 1316 // If listNode does NOT appear at the end of the outer list item, th
en behave as if in a regular paragraph. |
| 1317 } else if (blockEnclosingList->hasTagName(olTag) || blockEnclosingList->
hasTagName(ulTag)) | 1317 } else if (blockEnclosingList->hasTagName(olTag) || blockEnclosingList->
hasTagName(ulTag)) |
| 1318 newBlock = createListItemElement(document()); | 1318 newBlock = createListItemElement(document()); |
| 1319 } | 1319 } |
| 1320 if (!newBlock) | 1320 if (!newBlock) |
| 1321 newBlock = createDefaultParagraphElement(document()); | 1321 newBlock = createDefaultParagraphElement(document()); |
| 1322 | 1322 |
| 1323 Handle<Node> previousListNode = emptyListItem->isElementNode() ? Result<Node
>(toElement(emptyListItem)->previousElementSibling()) : emptyListItem->previousS
ibling(); | 1323 Handle<Node> previousListNode = emptyListItem->isElementNode() ? Result<Node
>(toElement(emptyListItem)->previousElementSibling()) : emptyListItem->previousS
ibling(); |
| 1324 Handle<Node> nextListNode = emptyListItem->isElementNode() ? Result<Node>(to
Element(emptyListItem)->nextElementSibling()) : emptyListItem->nextSibling(); | 1324 Handle<Node> nextListNode = emptyListItem->isElementNode() ? Result<Node>(to
Element(emptyListItem)->nextElementSibling()) : emptyListItem->nextSibling(); |
| 1325 if (isListItem(nextListNode.raw()) || isListElement(nextListNode.raw())) { | 1325 if (isListItem(nextListNode) || isListElement(nextListNode)) { |
| 1326 // If emptyListItem follows another list item or nested list, split the
list node. | 1326 // If emptyListItem follows another list item or nested list, split the
list node. |
| 1327 if (isListItem(previousListNode.raw()) || isListElement(previousListNode
.raw())) | 1327 if (isListItem(previousListNode) || isListElement(previousListNode)) |
| 1328 splitElement(toElement(listNode), emptyListItem); | 1328 splitElement(toElement(listNode), emptyListItem); |
| 1329 | 1329 |
| 1330 // If emptyListItem is followed by other list item or nested list, then
insert newBlock before the list node. | 1330 // If emptyListItem is followed by other list item or nested list, then
insert newBlock before the list node. |
| 1331 // Because we have splitted the element, emptyListItem is the first elem
ent in the list node. | 1331 // Because we have splitted the element, emptyListItem is the first elem
ent in the list node. |
| 1332 // i.e. insert newBlock before ul or ol whose first element is emptyList
Item | 1332 // i.e. insert newBlock before ul or ol whose first element is emptyList
Item |
| 1333 insertNodeBefore(newBlock, listNode); | 1333 insertNodeBefore(newBlock, listNode); |
| 1334 removeNode(emptyListItem); | 1334 removeNode(emptyListItem); |
| 1335 } else { | 1335 } else { |
| 1336 // When emptyListItem does not follow any list item or nested list, inse
rt newBlock after the enclosing list node. | 1336 // When emptyListItem does not follow any list item or nested list, inse
rt newBlock after the enclosing list node. |
| 1337 // Remove the enclosing node if emptyListItem is the only child; otherwi
se just remove emptyListItem. | 1337 // Remove the enclosing node if emptyListItem is the only child; otherwi
se just remove emptyListItem. |
| 1338 insertNodeAfter(newBlock, listNode); | 1338 insertNodeAfter(newBlock, listNode); |
| 1339 removeNode(isListItem(previousListNode.raw()) || isListElement(previousL
istNode.raw()) ? emptyListItem : Handle<Node>(listNode)); | 1339 removeNode(isListItem(previousListNode) || isListElement(previousListNod
e) ? emptyListItem : Handle<Node>(listNode)); |
| 1340 } | 1340 } |
| 1341 | 1341 |
| 1342 appendBlockPlaceholder(newBlock); | 1342 appendBlockPlaceholder(newBlock); |
| 1343 setEndingSelection(VisibleSelection(firstPositionInNode(newBlock), DOWNSTREA
M, endingSelection().isDirectional())); | 1343 setEndingSelection(VisibleSelection(firstPositionInNode(newBlock), DOWNSTREA
M, endingSelection().isDirectional())); |
| 1344 | 1344 |
| 1345 style->prepareToApplyAt(endingSelection().start()); | 1345 style->prepareToApplyAt(endingSelection().start()); |
| 1346 if (!style->isEmpty()) | 1346 if (!style->isEmpty()) |
| 1347 applyStyle(style.get()); | 1347 applyStyle(style.get()); |
| 1348 | 1348 |
| 1349 return true; | 1349 return true; |
| 1350 } | 1350 } |
| 1351 | 1351 |
| 1352 // If the caret is in an empty quoted paragraph, and either there is nothing bef
ore that | 1352 // If the caret is in an empty quoted paragraph, and either there is nothing bef
ore that |
| 1353 // paragraph, or what is before is unquoted, and the user presses delete, unquot
e that paragraph. | 1353 // paragraph, or what is before is unquoted, and the user presses delete, unquot
e that paragraph. |
| 1354 bool CompositeEditCommand::breakOutOfEmptyMailBlockquotedParagraph() | 1354 bool CompositeEditCommand::breakOutOfEmptyMailBlockquotedParagraph() |
| 1355 { | 1355 { |
| 1356 if (!endingSelection().isCaret()) | 1356 if (!endingSelection().isCaret()) |
| 1357 return false; | 1357 return false; |
| 1358 | 1358 |
| 1359 VisiblePosition caret(endingSelection().visibleStart()); | 1359 VisiblePosition caret(endingSelection().visibleStart()); |
| 1360 Node* highestBlockquote = highestEnclosingNodeOfType(caret.deepEquivalent(),
&isMailBlockquote); | 1360 Handle<Node> highestBlockquote = highestEnclosingNodeOfType(caret.deepEquiva
lent(), &isMailBlockquote); |
| 1361 if (!highestBlockquote) | 1361 if (!highestBlockquote) |
| 1362 return false; | 1362 return false; |
| 1363 | 1363 |
| 1364 if (!isStartOfParagraph(caret) || !isEndOfParagraph(caret)) | 1364 if (!isStartOfParagraph(caret) || !isEndOfParagraph(caret)) |
| 1365 return false; | 1365 return false; |
| 1366 | 1366 |
| 1367 VisiblePosition previous(caret.previous(CannotCrossEditingBoundary)); | 1367 VisiblePosition previous(caret.previous(CannotCrossEditingBoundary)); |
| 1368 // Only move forward if there's nothing before the caret, or if there's unqu
oted content before it. | 1368 // Only move forward if there's nothing before the caret, or if there's unqu
oted content before it. |
| 1369 if (enclosingNodeOfType(previous.deepEquivalent(), &isMailBlockquote)) | 1369 if (enclosingNodeOfType(previous.deepEquivalent(), &isMailBlockquote)) |
| 1370 return false; | 1370 return false; |
| 1371 | 1371 |
| 1372 Handle<Node> br = createBreakElement(document()); | 1372 Handle<Node> br = createBreakElement(document()); |
| 1373 // We want to replace this quoted paragraph with an unquoted one, so insert
a br | 1373 // We want to replace this quoted paragraph with an unquoted one, so insert
a br |
| 1374 // to hold the caret before the highest blockquote. | 1374 // to hold the caret before the highest blockquote. |
| 1375 insertNodeBefore(br, adoptRawResult(highestBlockquote)); | 1375 insertNodeBefore(br, highestBlockquote); |
| 1376 VisiblePosition atBR(positionBeforeNode(br)); | 1376 VisiblePosition atBR(positionBeforeNode(br)); |
| 1377 // If the br we inserted collapsed, for example foo<br><blockquote>...</bloc
kquote>, insert | 1377 // If the br we inserted collapsed, for example foo<br><blockquote>...</bloc
kquote>, insert |
| 1378 // a second one. | 1378 // a second one. |
| 1379 if (!isStartOfParagraph(atBR)) | 1379 if (!isStartOfParagraph(atBR)) |
| 1380 insertNodeBefore(createBreakElement(document()), br); | 1380 insertNodeBefore(createBreakElement(document()), br); |
| 1381 setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional())
); | 1381 setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional())
); |
| 1382 | 1382 |
| 1383 // If this is an empty paragraph there must be a line break here. | 1383 // If this is an empty paragraph there must be a line break here. |
| 1384 if (!lineBreakExistsAtVisiblePosition(caret)) | 1384 if (!lineBreakExistsAtVisiblePosition(caret)) |
| 1385 return false; | 1385 return false; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1406 // Operations use this function to avoid inserting content into an anchor when a
t the start or the end of | 1406 // Operations use this function to avoid inserting content into an anchor when a
t the start or the end of |
| 1407 // that anchor, as in NSTextView. | 1407 // that anchor, as in NSTextView. |
| 1408 // FIXME: This is only an approximation of NSTextViews insertion behavior, which
varies depending on how | 1408 // FIXME: This is only an approximation of NSTextViews insertion behavior, which
varies depending on how |
| 1409 // the caret was made. | 1409 // the caret was made. |
| 1410 Position CompositeEditCommand::positionAvoidingSpecialElementBoundary(const Posi
tion& original) | 1410 Position CompositeEditCommand::positionAvoidingSpecialElementBoundary(const Posi
tion& original) |
| 1411 { | 1411 { |
| 1412 if (original.isNull()) | 1412 if (original.isNull()) |
| 1413 return original; | 1413 return original; |
| 1414 | 1414 |
| 1415 VisiblePosition visiblePos(original); | 1415 VisiblePosition visiblePos(original); |
| 1416 Handle<Node> enclosingAnchor = adoptRawResult(enclosingAnchorElement(origina
l)); | 1416 Handle<Node> enclosingAnchor = enclosingAnchorElement(original); |
| 1417 Position result = original; | 1417 Position result = original; |
| 1418 | 1418 |
| 1419 if (!enclosingAnchor) | 1419 if (!enclosingAnchor) |
| 1420 return result; | 1420 return result; |
| 1421 | 1421 |
| 1422 // Don't avoid block level anchors, because that would insert content into t
he wrong paragraph. | 1422 // Don't avoid block level anchors, because that would insert content into t
he wrong paragraph. |
| 1423 if (enclosingAnchor && !isBlock(enclosingAnchor.raw())) { | 1423 if (enclosingAnchor && !isBlock(enclosingAnchor)) { |
| 1424 VisiblePosition firstInAnchor(firstPositionInNode(enclosingAnchor)); | 1424 VisiblePosition firstInAnchor(firstPositionInNode(enclosingAnchor)); |
| 1425 VisiblePosition lastInAnchor(lastPositionInNode(enclosingAnchor)); | 1425 VisiblePosition lastInAnchor(lastPositionInNode(enclosingAnchor)); |
| 1426 // If visually just after the anchor, insert *inside* the anchor unless
it's the last | 1426 // If visually just after the anchor, insert *inside* the anchor unless
it's the last |
| 1427 // VisiblePosition in the document, to match NSTextView. | 1427 // VisiblePosition in the document, to match NSTextView. |
| 1428 if (visiblePos == lastInAnchor) { | 1428 if (visiblePos == lastInAnchor) { |
| 1429 // Make sure anchors are pushed down before avoiding them so that we
don't | 1429 // Make sure anchors are pushed down before avoiding them so that we
don't |
| 1430 // also avoid structural elements like lists and blocks (5142012). | 1430 // also avoid structural elements like lists and blocks (5142012). |
| 1431 if (original.deprecatedNode() != enclosingAnchor && original.depreca
tedNode()->parentNode() != enclosingAnchor) { | 1431 if (original.deprecatedNode() != enclosingAnchor && original.depreca
tedNode()->parentNode() != enclosingAnchor) { |
| 1432 pushAnchorElementDown(enclosingAnchor); | 1432 pushAnchorElementDown(enclosingAnchor); |
| 1433 enclosingAnchor = adoptRawResult(enclosingAnchorElement(original
)); | 1433 enclosingAnchor = enclosingAnchorElement(original); |
| 1434 if (!enclosingAnchor) | 1434 if (!enclosingAnchor) |
| 1435 return original; | 1435 return original; |
| 1436 } | 1436 } |
| 1437 // Don't insert outside an anchor if doing so would skip over a line
break. It would | 1437 // Don't insert outside an anchor if doing so would skip over a line
break. It would |
| 1438 // probably be safe to move the line break so that we could still av
oid the anchor here. | 1438 // probably be safe to move the line break so that we could still av
oid the anchor here. |
| 1439 Position downstream(visiblePos.deepEquivalent().downstream()); | 1439 Position downstream(visiblePos.deepEquivalent().downstream()); |
| 1440 if (lineBreakExistsAtVisiblePosition(visiblePos) && downstream.depre
catedNode()->isDescendantOf(enclosingAnchor.raw())) | 1440 if (lineBreakExistsAtVisiblePosition(visiblePos) && downstream.depre
catedNode()->isDescendantOf(enclosingAnchor.raw())) |
| 1441 return original; | 1441 return original; |
| 1442 | 1442 |
| 1443 result = positionInParentAfterNode(enclosingAnchor); | 1443 result = positionInParentAfterNode(enclosingAnchor); |
| 1444 } | 1444 } |
| 1445 // If visually just before an anchor, insert *outside* the anchor unless
it's the first | 1445 // If visually just before an anchor, insert *outside* the anchor unless
it's the first |
| 1446 // VisiblePosition in a paragraph, to match NSTextView. | 1446 // VisiblePosition in a paragraph, to match NSTextView. |
| 1447 if (visiblePos == firstInAnchor) { | 1447 if (visiblePos == firstInAnchor) { |
| 1448 // Make sure anchors are pushed down before avoiding them so that we
don't | 1448 // Make sure anchors are pushed down before avoiding them so that we
don't |
| 1449 // also avoid structural elements like lists and blocks (5142012). | 1449 // also avoid structural elements like lists and blocks (5142012). |
| 1450 if (original.deprecatedNode() != enclosingAnchor && original.depreca
tedNode()->parentNode() != enclosingAnchor) { | 1450 if (original.deprecatedNode() != enclosingAnchor && original.depreca
tedNode()->parentNode() != enclosingAnchor) { |
| 1451 pushAnchorElementDown(enclosingAnchor); | 1451 pushAnchorElementDown(enclosingAnchor); |
| 1452 enclosingAnchor = adoptRawResult(enclosingAnchorElement(original
)); | 1452 enclosingAnchor = enclosingAnchorElement(original); |
| 1453 } | 1453 } |
| 1454 if (!enclosingAnchor) | 1454 if (!enclosingAnchor) |
| 1455 return original; | 1455 return original; |
| 1456 | 1456 |
| 1457 result = positionInParentBeforeNode(enclosingAnchor); | 1457 result = positionInParentBeforeNode(enclosingAnchor); |
| 1458 } | 1458 } |
| 1459 } | 1459 } |
| 1460 | 1460 |
| 1461 if (result.isNull() || !editableRootForPosition(result)) | 1461 if (result.isNull() || !editableRootForPosition(result)) |
| 1462 result = original; | 1462 result = original; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1476 Handle<Node> endNode = end; | 1476 Handle<Node> endNode = end; |
| 1477 if (shouldSplitAncestor && endNode->parentNode()) | 1477 if (shouldSplitAncestor && endNode->parentNode()) |
| 1478 endNode = endNode->parentNode(); | 1478 endNode = endNode->parentNode(); |
| 1479 | 1479 |
| 1480 for (node = start; node && node->parentNode() != endNode; node = node->paren
tNode()) { | 1480 for (node = start; node && node->parentNode() != endNode; node = node->paren
tNode()) { |
| 1481 HandleScope scope; | 1481 HandleScope scope; |
| 1482 if (!node->parentNode()->isElementNode()) | 1482 if (!node->parentNode()->isElementNode()) |
| 1483 break; | 1483 break; |
| 1484 // Do not split a node when doing so introduces an empty node. | 1484 // Do not split a node when doing so introduces an empty node. |
| 1485 VisiblePosition positionInParent = firstPositionInNode(node->parentNode(
)); | 1485 VisiblePosition positionInParent = firstPositionInNode(node->parentNode(
)); |
| 1486 VisiblePosition positionInNode = firstPositionInOrBeforeNode(node.raw())
; | 1486 VisiblePosition positionInNode = firstPositionInOrBeforeNode(node); |
| 1487 if (positionInParent != positionInNode) | 1487 if (positionInParent != positionInNode) |
| 1488 splitElement(toElement(node->parentNode()), node); | 1488 splitElement(toElement(node->parentNode()), node); |
| 1489 } | 1489 } |
| 1490 | 1490 |
| 1491 return node; | 1491 return node; |
| 1492 } | 1492 } |
| 1493 | 1493 |
| 1494 Result<Element> createBlockPlaceholderElement(const Handle<Document>& document) | 1494 Result<Element> createBlockPlaceholderElement(const Handle<Document>& document) |
| 1495 { | 1495 { |
| 1496 return document->createElement(brTag, false); | 1496 return document->createElement(brTag, false); |
| 1497 } | 1497 } |
| 1498 | 1498 |
| 1499 } // namespace WebCore | 1499 } // namespace WebCore |
| OLD | NEW |