Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(33)

Side by Side Diff: third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp

Issue 1695153002: Editing: Make the |EditingState*| argument of CompositeEditCommand::removeNode mandatory. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: ; Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. 2 * Copyright (C) 2005 Apple Computer, 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 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
293 m_typingStyle->removeStyleAddedByElement(enclosingAnchorElement(m_selectionT oDelete.start())); 293 m_typingStyle->removeStyleAddedByElement(enclosingAnchorElement(m_selectionT oDelete.start()));
294 294
295 // If we're deleting into a Mail blockquote, save the style at end() instead of start() 295 // If we're deleting into a Mail blockquote, save the style at end() instead of start()
296 // We'll use this later in computeTypingStyleAfterDelete if we end up outsid e of a Mail blockquote 296 // We'll use this later in computeTypingStyleAfterDelete if we end up outsid e of a Mail blockquote
297 if (enclosingNodeOfType(m_selectionToDelete.start(), isMailHTMLBlockquoteEle ment)) 297 if (enclosingNodeOfType(m_selectionToDelete.start(), isMailHTMLBlockquoteEle ment))
298 m_deleteIntoBlockquoteStyle = EditingStyle::create(m_selectionToDelete.e nd()); 298 m_deleteIntoBlockquoteStyle = EditingStyle::create(m_selectionToDelete.e nd());
299 else 299 else
300 m_deleteIntoBlockquoteStyle = nullptr; 300 m_deleteIntoBlockquoteStyle = nullptr;
301 } 301 }
302 302
303 bool DeleteSelectionCommand::handleSpecialCaseBRDelete() 303 bool DeleteSelectionCommand::handleSpecialCaseBRDelete(EditingState* editingStat e)
304 { 304 {
305 Node* nodeAfterUpstreamStart = m_upstreamStart.computeNodeAfterPosition(); 305 Node* nodeAfterUpstreamStart = m_upstreamStart.computeNodeAfterPosition();
306 Node* nodeAfterDownstreamStart = m_downstreamStart.computeNodeAfterPosition( ); 306 Node* nodeAfterDownstreamStart = m_downstreamStart.computeNodeAfterPosition( );
307 // Upstream end will appear before BR due to canonicalization 307 // Upstream end will appear before BR due to canonicalization
308 Node* nodeAfterUpstreamEnd = m_upstreamEnd.computeNodeAfterPosition(); 308 Node* nodeAfterUpstreamEnd = m_upstreamEnd.computeNodeAfterPosition();
309 309
310 if (!nodeAfterUpstreamStart || !nodeAfterDownstreamStart) 310 if (!nodeAfterUpstreamStart || !nodeAfterDownstreamStart)
311 return false; 311 return false;
312 312
313 // Check for special-case where the selection contains only a BR on a line b y itself after another BR. 313 // Check for special-case where the selection contains only a BR on a line b y itself after another BR.
314 bool upstreamStartIsBR = isHTMLBRElement(*nodeAfterUpstreamStart); 314 bool upstreamStartIsBR = isHTMLBRElement(*nodeAfterUpstreamStart);
315 bool downstreamStartIsBR = isHTMLBRElement(*nodeAfterDownstreamStart); 315 bool downstreamStartIsBR = isHTMLBRElement(*nodeAfterDownstreamStart);
316 bool isBROnLineByItself = upstreamStartIsBR && downstreamStartIsBR && nodeAf terDownstreamStart == nodeAfterUpstreamEnd; 316 bool isBROnLineByItself = upstreamStartIsBR && downstreamStartIsBR && nodeAf terDownstreamStart == nodeAfterUpstreamEnd;
317 if (isBROnLineByItself) { 317 if (isBROnLineByItself) {
318 removeNode(nodeAfterDownstreamStart); 318 removeNode(nodeAfterDownstreamStart, editingState);
319 return true; 319 return true;
320 } 320 }
321 321
322 // FIXME: This code doesn't belong in here. 322 // FIXME: This code doesn't belong in here.
323 // We detect the case where the start is an empty line consisting of BR not wrapped in a block element. 323 // We detect the case where the start is an empty line consisting of BR not wrapped in a block element.
324 if (upstreamStartIsBR && downstreamStartIsBR && !(isStartOfBlock(createVisib lePosition(positionBeforeNode(nodeAfterUpstreamStart))) && isEndOfBlock(createVi siblePosition(positionAfterNode(nodeAfterUpstreamStart))))) { 324 if (upstreamStartIsBR && downstreamStartIsBR && !(isStartOfBlock(createVisib lePosition(positionBeforeNode(nodeAfterUpstreamStart))) && isEndOfBlock(createVi siblePosition(positionAfterNode(nodeAfterUpstreamStart))))) {
325 m_startsAtEmptyLine = true; 325 m_startsAtEmptyLine = true;
326 m_endingPosition = m_downstreamEnd; 326 m_endingPosition = m_downstreamEnd;
327 } 327 }
328 328
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 { 424 {
425 // FIXME: Update the endpoints of the range being deleted. 425 // FIXME: Update the endpoints of the range being deleted.
426 updatePositionForTextRemoval(node.get(), offset, count, m_endingPosition); 426 updatePositionForTextRemoval(node.get(), offset, count, m_endingPosition);
427 updatePositionForTextRemoval(node.get(), offset, count, m_leadingWhitespace) ; 427 updatePositionForTextRemoval(node.get(), offset, count, m_leadingWhitespace) ;
428 updatePositionForTextRemoval(node.get(), offset, count, m_trailingWhitespace ); 428 updatePositionForTextRemoval(node.get(), offset, count, m_trailingWhitespace );
429 updatePositionForTextRemoval(node.get(), offset, count, m_downstreamEnd); 429 updatePositionForTextRemoval(node.get(), offset, count, m_downstreamEnd);
430 430
431 CompositeEditCommand::deleteTextFromNode(node, offset, count); 431 CompositeEditCommand::deleteTextFromNode(node, offset, count);
432 } 432 }
433 433
434 void DeleteSelectionCommand::makeStylingElementsDirectChildrenOfEditableRootToPr eventStyleLoss() 434 void DeleteSelectionCommand::makeStylingElementsDirectChildrenOfEditableRootToPr eventStyleLoss(EditingState* editingState)
435 { 435 {
436 RefPtrWillBeRawPtr<Range> range = createRange(m_selectionToDelete.toNormaliz edEphemeralRange()); 436 RefPtrWillBeRawPtr<Range> range = createRange(m_selectionToDelete.toNormaliz edEphemeralRange());
437 RefPtrWillBeRawPtr<Node> node = range->firstNode(); 437 RefPtrWillBeRawPtr<Node> node = range->firstNode();
438 while (node && node != range->pastLastNode()) { 438 while (node && node != range->pastLastNode()) {
439 RefPtrWillBeRawPtr<Node> nextNode = NodeTraversal::next(*node); 439 RefPtrWillBeRawPtr<Node> nextNode = NodeTraversal::next(*node);
440 if (isHTMLStyleElement(*node) || isHTMLLinkElement(*node)) { 440 if (isHTMLStyleElement(*node) || isHTMLLinkElement(*node)) {
441 nextNode = NodeTraversal::nextSkippingChildren(*node); 441 nextNode = NodeTraversal::nextSkippingChildren(*node);
442 RefPtrWillBeRawPtr<Element> rootEditableElement = node->rootEditable Element(); 442 RefPtrWillBeRawPtr<Element> rootEditableElement = node->rootEditable Element();
443 if (rootEditableElement.get()) { 443 if (rootEditableElement.get()) {
444 removeNode(node); 444 removeNode(node, editingState);
445 appendNode(node, rootEditableElement); 445 if (editingState->isAborted())
446 return;
447 appendNode(node, rootEditableElement, editingState);
448 if (editingState->isAborted())
449 return;
446 } 450 }
447 } 451 }
448 node = nextNode; 452 node = nextNode;
449 } 453 }
450 } 454 }
451 455
452 void DeleteSelectionCommand::handleGeneralDelete(EditingState* editingState) 456 void DeleteSelectionCommand::handleGeneralDelete(EditingState* editingState)
453 { 457 {
454 if (m_upstreamStart.isNull()) 458 if (m_upstreamStart.isNull())
455 return; 459 return;
456 460
457 int startOffset = m_upstreamStart.computeEditingOffset(); 461 int startOffset = m_upstreamStart.computeEditingOffset();
458 Node* startNode = m_upstreamStart.anchorNode(); 462 Node* startNode = m_upstreamStart.anchorNode();
459 ASSERT(startNode); 463 ASSERT(startNode);
460 464
461 makeStylingElementsDirectChildrenOfEditableRootToPreventStyleLoss(); 465 makeStylingElementsDirectChildrenOfEditableRootToPreventStyleLoss(editingSta te);
466 if (editingState->isAborted())
467 return;
462 468
463 // Never remove the start block unless it's a table, in which case we won't merge content in. 469 // Never remove the start block unless it's a table, in which case we won't merge content in.
464 if (startNode->isSameNode(m_startBlock.get()) && !startOffset && canHaveChil drenForEditing(startNode) && !isHTMLTableElement(*startNode)) { 470 if (startNode->isSameNode(m_startBlock.get()) && !startOffset && canHaveChil drenForEditing(startNode) && !isHTMLTableElement(*startNode)) {
465 startOffset = 0; 471 startOffset = 0;
466 startNode = NodeTraversal::next(*startNode); 472 startNode = NodeTraversal::next(*startNode);
467 if (!startNode) 473 if (!startNode)
468 return; 474 return;
469 } 475 }
470 476
471 if (startOffset >= caretMaxOffset(startNode) && startNode->isTextNode()) { 477 if (startOffset >= caretMaxOffset(startNode) && startNode->isTextNode()) {
(...skipping 11 matching lines...) Expand all
483 if (!startNode) 489 if (!startNode)
484 return; 490 return;
485 491
486 if (startNode == m_downstreamEnd.anchorNode()) { 492 if (startNode == m_downstreamEnd.anchorNode()) {
487 if (m_downstreamEnd.computeEditingOffset() - startOffset > 0) { 493 if (m_downstreamEnd.computeEditingOffset() - startOffset > 0) {
488 if (startNode->isTextNode()) { 494 if (startNode->isTextNode()) {
489 // in a text node that needs to be trimmed 495 // in a text node that needs to be trimmed
490 Text* text = toText(startNode); 496 Text* text = toText(startNode);
491 deleteTextFromNode(text, startOffset, m_downstreamEnd.computeOff setInContainerNode() - startOffset); 497 deleteTextFromNode(text, startOffset, m_downstreamEnd.computeOff setInContainerNode() - startOffset);
492 } else { 498 } else {
493 removeChildrenInRange(startNode, startOffset, m_downstreamEnd.co mputeEditingOffset()); 499 removeChildrenInRange(startNode, startOffset, m_downstreamEnd.co mputeEditingOffset(), editingState);
500 if (editingState->isAborted())
501 return;
494 m_endingPosition = m_upstreamStart; 502 m_endingPosition = m_upstreamStart;
495 } 503 }
496 } 504 }
497 505
498 // The selection to delete is all in one node. 506 // The selection to delete is all in one node.
499 if (!startNode->layoutObject() || (!startOffset && m_downstreamEnd.atLas tEditingPositionForNode())) { 507 if (!startNode->layoutObject() || (!startOffset && m_downstreamEnd.atLas tEditingPositionForNode())) {
500 removeNode(startNode, editingState); 508 removeNode(startNode, editingState);
501 if (editingState->isAborted()) 509 if (editingState->isAborted())
502 return; 510 return;
503 } 511 }
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
566 // always know which children to remove. 574 // always know which children to remove.
567 } else if (!(startNodeWasDescendantOfEndNode && !m_upstreamStart .inDocument())) { 575 } else if (!(startNodeWasDescendantOfEndNode && !m_upstreamStart .inDocument())) {
568 int offset = 0; 576 int offset = 0;
569 if (m_upstreamStart.anchorNode()->isDescendantOf(m_downstrea mEnd.anchorNode())) { 577 if (m_upstreamStart.anchorNode()->isDescendantOf(m_downstrea mEnd.anchorNode())) {
570 Node* n = m_upstreamStart.anchorNode(); 578 Node* n = m_upstreamStart.anchorNode();
571 while (n && n->parentNode() != m_downstreamEnd.anchorNod e()) 579 while (n && n->parentNode() != m_downstreamEnd.anchorNod e())
572 n = n->parentNode(); 580 n = n->parentNode();
573 if (n) 581 if (n)
574 offset = n->nodeIndex() + 1; 582 offset = n->nodeIndex() + 1;
575 } 583 }
576 removeChildrenInRange(m_downstreamEnd.anchorNode(), offset, m_downstreamEnd.computeEditingOffset()); 584 removeChildrenInRange(m_downstreamEnd.anchorNode(), offset, m_downstreamEnd.computeEditingOffset(), editingState);
585 if (editingState->isAborted())
586 return;
577 m_downstreamEnd = Position::editingPositionOf(m_downstreamEn d.anchorNode(), offset); 587 m_downstreamEnd = Position::editingPositionOf(m_downstreamEn d.anchorNode(), offset);
578 } 588 }
579 } 589 }
580 } 590 }
581 } 591 }
582 } 592 }
583 593
584 void DeleteSelectionCommand::fixupWhitespace() 594 void DeleteSelectionCommand::fixupWhitespace()
585 { 595 {
586 document().updateLayoutIgnorePendingStylesheets(); 596 document().updateLayoutIgnorePendingStylesheets();
587 // TODO(yosin) |isRenderedCharacter()| should be removed, and we should use 597 // TODO(yosin) |isRenderedCharacter()| should be removed, and we should use
588 // |VisiblePosition::characterAfter()| and 598 // |VisiblePosition::characterAfter()| and
589 // |VisiblePosition::characterBefore()| 599 // |VisiblePosition::characterBefore()|
590 if (m_leadingWhitespace.isNotNull() && !isRenderedCharacter(m_leadingWhitesp ace) && m_leadingWhitespace.anchorNode()->isTextNode()) { 600 if (m_leadingWhitespace.isNotNull() && !isRenderedCharacter(m_leadingWhitesp ace) && m_leadingWhitespace.anchorNode()->isTextNode()) {
591 Text* textNode = toText(m_leadingWhitespace.anchorNode()); 601 Text* textNode = toText(m_leadingWhitespace.anchorNode());
592 ASSERT(!textNode->layoutObject() || textNode->layoutObject()->style()->c ollapseWhiteSpace()); 602 ASSERT(!textNode->layoutObject() || textNode->layoutObject()->style()->c ollapseWhiteSpace());
593 replaceTextInNodePreservingMarkers(textNode, m_leadingWhitespace.compute OffsetInContainerNode(), 1, nonBreakingSpaceString()); 603 replaceTextInNodePreservingMarkers(textNode, m_leadingWhitespace.compute OffsetInContainerNode(), 1, nonBreakingSpaceString());
594 } 604 }
595 if (m_trailingWhitespace.isNotNull() && !isRenderedCharacter(m_trailingWhite space) && m_trailingWhitespace.anchorNode()->isTextNode()) { 605 if (m_trailingWhitespace.isNotNull() && !isRenderedCharacter(m_trailingWhite space) && m_trailingWhitespace.anchorNode()->isTextNode()) {
596 Text* textNode = toText(m_trailingWhitespace.anchorNode()); 606 Text* textNode = toText(m_trailingWhitespace.anchorNode());
597 ASSERT(!textNode->layoutObject() || textNode->layoutObject()->style()->c ollapseWhiteSpace()); 607 ASSERT(!textNode->layoutObject() || textNode->layoutObject()->style()->c ollapseWhiteSpace());
598 replaceTextInNodePreservingMarkers(textNode, m_trailingWhitespace.comput eOffsetInContainerNode(), 1, nonBreakingSpaceString()); 608 replaceTextInNodePreservingMarkers(textNode, m_trailingWhitespace.comput eOffsetInContainerNode(), 1, nonBreakingSpaceString());
599 } 609 }
600 } 610 }
601 611
602 // If a selection starts in one block and ends in another, we have to merge to b ring content before the 612 // If a selection starts in one block and ends in another, we have to merge to b ring content before the
603 // start together with content after the end. 613 // start together with content after the end.
604 void DeleteSelectionCommand::mergeParagraphs() 614 void DeleteSelectionCommand::mergeParagraphs(EditingState* editingState)
605 { 615 {
606 if (!m_mergeBlocksAfterDelete) { 616 if (!m_mergeBlocksAfterDelete) {
607 if (m_pruneStartBlockIfNecessary) { 617 if (m_pruneStartBlockIfNecessary) {
608 // We aren't going to merge into the start block, so remove it if it 's empty. 618 // We aren't going to merge into the start block, so remove it if it 's empty.
609 prune(m_startBlock); 619 prune(m_startBlock, editingState);
620 if (editingState->isAborted())
621 return;
610 // Removing the start block during a deletion is usually an indicati on that we need 622 // Removing the start block during a deletion is usually an indicati on that we need
611 // a placeholder, but not in this case. 623 // a placeholder, but not in this case.
612 m_needPlaceholder = false; 624 m_needPlaceholder = false;
613 } 625 }
614 return; 626 return;
615 } 627 }
616 628
617 // It shouldn't have been asked to both try and merge content into the start block and prune it. 629 // It shouldn't have been asked to both try and merge content into the start block and prune it.
618 ASSERT(!m_pruneStartBlockIfNecessary); 630 ASSERT(!m_pruneStartBlockIfNecessary);
619 631
620 // FIXME: Deletion should adjust selection endpoints as it removes nodes so that we never get into this state (4099839). 632 // FIXME: Deletion should adjust selection endpoints as it removes nodes so that we never get into this state (4099839).
621 if (!m_downstreamEnd.inDocument() || !m_upstreamStart.inDocument()) 633 if (!m_downstreamEnd.inDocument() || !m_upstreamStart.inDocument())
622 return; 634 return;
623 635
624 // FIXME: The deletion algorithm shouldn't let this happen. 636 // FIXME: The deletion algorithm shouldn't let this happen.
625 if (comparePositions(m_upstreamStart, m_downstreamEnd) > 0) 637 if (comparePositions(m_upstreamStart, m_downstreamEnd) > 0)
626 return; 638 return;
627 639
628 // There's nothing to merge. 640 // There's nothing to merge.
629 if (m_upstreamStart == m_downstreamEnd) 641 if (m_upstreamStart == m_downstreamEnd)
630 return; 642 return;
631 643
632 VisiblePosition startOfParagraphToMove = createVisiblePosition(m_downstreamE nd); 644 VisiblePosition startOfParagraphToMove = createVisiblePosition(m_downstreamE nd);
633 VisiblePosition mergeDestination = createVisiblePosition(m_upstreamStart); 645 VisiblePosition mergeDestination = createVisiblePosition(m_upstreamStart);
634 646
635 // m_downstreamEnd's block has been emptied out by deletion. There is no co ntent inside of it to 647 // m_downstreamEnd's block has been emptied out by deletion. There is no co ntent inside of it to
636 // move, so just remove it. 648 // move, so just remove it.
637 Element* endBlock = enclosingBlock(m_downstreamEnd.anchorNode()); 649 Element* endBlock = enclosingBlock(m_downstreamEnd.anchorNode());
638 if (!endBlock || !endBlock->contains(startOfParagraphToMove.deepEquivalent() .anchorNode()) || !startOfParagraphToMove.deepEquivalent().anchorNode()) { 650 if (!endBlock || !endBlock->contains(startOfParagraphToMove.deepEquivalent() .anchorNode()) || !startOfParagraphToMove.deepEquivalent().anchorNode()) {
639 removeNode(enclosingBlock(m_downstreamEnd.anchorNode())); 651 removeNode(enclosingBlock(m_downstreamEnd.anchorNode()), editingState);
640 return; 652 return;
641 } 653 }
642 654
643 // We need to merge into m_upstreamStart's block, but it's been emptied out and collapsed by deletion. 655 // We need to merge into m_upstreamStart's block, but it's been emptied out and collapsed by deletion.
644 if (!mergeDestination.deepEquivalent().anchorNode() || (!mergeDestination.de epEquivalent().anchorNode()->isDescendantOf(enclosingBlock(m_upstreamStart.compu teContainerNode())) && (!mergeDestination.deepEquivalent().anchorNode()->hasChil dren() || !m_upstreamStart.computeContainerNode()->hasChildren())) || (m_startsA tEmptyLine && mergeDestination.deepEquivalent() != startOfParagraphToMove.deepEq uivalent())) { 656 if (!mergeDestination.deepEquivalent().anchorNode() || (!mergeDestination.de epEquivalent().anchorNode()->isDescendantOf(enclosingBlock(m_upstreamStart.compu teContainerNode())) && (!mergeDestination.deepEquivalent().anchorNode()->hasChil dren() || !m_upstreamStart.computeContainerNode()->hasChildren())) || (m_startsA tEmptyLine && mergeDestination.deepEquivalent() != startOfParagraphToMove.deepEq uivalent())) {
645 insertNodeAt(HTMLBRElement::create(document()).get(), m_upstreamStart); 657 insertNodeAt(HTMLBRElement::create(document()).get(), m_upstreamStart, e ditingState);
658 if (editingState->isAborted())
659 return;
646 mergeDestination = createVisiblePosition(m_upstreamStart); 660 mergeDestination = createVisiblePosition(m_upstreamStart);
647 } 661 }
648 662
649 if (mergeDestination.deepEquivalent() == startOfParagraphToMove.deepEquivale nt()) 663 if (mergeDestination.deepEquivalent() == startOfParagraphToMove.deepEquivale nt())
650 return; 664 return;
651 665
652 VisiblePosition endOfParagraphToMove = endOfParagraph(startOfParagraphToMove , CanSkipOverEditingBoundary); 666 VisiblePosition endOfParagraphToMove = endOfParagraph(startOfParagraphToMove , CanSkipOverEditingBoundary);
653 667
654 if (mergeDestination.deepEquivalent() == endOfParagraphToMove.deepEquivalent ()) 668 if (mergeDestination.deepEquivalent() == endOfParagraphToMove.deepEquivalent ())
655 return; 669 return;
656 670
657 // If the merge destination and source to be moved are both list items of di fferent lists, merge them into single list. 671 // If the merge destination and source to be moved are both list items of di fferent lists, merge them into single list.
658 Node* listItemInFirstParagraph = enclosingNodeOfType(m_upstreamStart, isList Item); 672 Node* listItemInFirstParagraph = enclosingNodeOfType(m_upstreamStart, isList Item);
659 Node* listItemInSecondParagraph = enclosingNodeOfType(m_downstreamEnd, isLis tItem); 673 Node* listItemInSecondParagraph = enclosingNodeOfType(m_downstreamEnd, isLis tItem);
660 if (listItemInFirstParagraph && listItemInSecondParagraph 674 if (listItemInFirstParagraph && listItemInSecondParagraph
661 && listItemInFirstParagraph->parentElement() != listItemInSecondParagrap h->parentElement() 675 && listItemInFirstParagraph->parentElement() != listItemInSecondParagrap h->parentElement()
662 && canMergeLists(listItemInFirstParagraph->parentElement(), listItemInSe condParagraph->parentElement())) { 676 && canMergeLists(listItemInFirstParagraph->parentElement(), listItemInSe condParagraph->parentElement())) {
663 mergeIdenticalElements(listItemInFirstParagraph->parentElement(), listIt emInSecondParagraph->parentElement()); 677 mergeIdenticalElements(listItemInFirstParagraph->parentElement(), listIt emInSecondParagraph->parentElement(), editingState);
678 if (editingState->isAborted())
679 return;
664 m_endingPosition = mergeDestination.deepEquivalent(); 680 m_endingPosition = mergeDestination.deepEquivalent();
665 return; 681 return;
666 } 682 }
667 683
668 // The rule for merging into an empty block is: only do so if its farther to the right. 684 // The rule for merging into an empty block is: only do so if its farther to the right.
669 // FIXME: Consider RTL. 685 // FIXME: Consider RTL.
670 if (!m_startsAtEmptyLine && isStartOfParagraph(mergeDestination) && absolute CaretBoundsOf(startOfParagraphToMove).x() > absoluteCaretBoundsOf(mergeDestinati on).x()) { 686 if (!m_startsAtEmptyLine && isStartOfParagraph(mergeDestination) && absolute CaretBoundsOf(startOfParagraphToMove).x() > absoluteCaretBoundsOf(mergeDestinati on).x()) {
671 if (isHTMLBRElement(*mostForwardCaretPosition(mergeDestination.deepEquiv alent()).anchorNode())) { 687 if (isHTMLBRElement(*mostForwardCaretPosition(mergeDestination.deepEquiv alent()).anchorNode())) {
672 removeNodeAndPruneAncestors(mostForwardCaretPosition(mergeDestinatio n.deepEquivalent()).anchorNode()); 688 removeNodeAndPruneAncestors(mostForwardCaretPosition(mergeDestinatio n.deepEquivalent()).anchorNode(), editingState);
689 if (editingState->isAborted())
690 return;
673 m_endingPosition = startOfParagraphToMove.deepEquivalent(); 691 m_endingPosition = startOfParagraphToMove.deepEquivalent();
674 return; 692 return;
675 } 693 }
676 } 694 }
677 695
678 // Block images, tables and horizontal rules cannot be made inline with cont ent at mergeDestination. If there is 696 // Block images, tables and horizontal rules cannot be made inline with cont ent at mergeDestination. If there is
679 // any (!isStartOfParagraph(mergeDestination)), don't merge, just move the c aret to just before the selection we deleted. 697 // any (!isStartOfParagraph(mergeDestination)), don't merge, just move the c aret to just before the selection we deleted.
680 // See https://bugs.webkit.org/show_bug.cgi?id=25439 698 // See https://bugs.webkit.org/show_bug.cgi?id=25439
681 if (isRenderedAsNonInlineTableImageOrHR(startOfParagraphToMove.deepEquivalen t().anchorNode()) && !isStartOfParagraph(mergeDestination)) { 699 if (isRenderedAsNonInlineTableImageOrHR(startOfParagraphToMove.deepEquivalen t().anchorNode()) && !isStartOfParagraph(mergeDestination)) {
682 m_endingPosition = m_upstreamStart; 700 m_endingPosition = m_upstreamStart;
683 return; 701 return;
684 } 702 }
685 703
686 // moveParagraphs will insert placeholders if it removes blocks that would r equire their use, don't let block 704 // moveParagraphs will insert placeholders if it removes blocks that would r equire their use, don't let block
687 // removals that it does cause the insertion of *another* placeholder. 705 // removals that it does cause the insertion of *another* placeholder.
688 bool needPlaceholder = m_needPlaceholder; 706 bool needPlaceholder = m_needPlaceholder;
689 bool paragraphToMergeIsEmpty = startOfParagraphToMove.deepEquivalent() == en dOfParagraphToMove.deepEquivalent(); 707 bool paragraphToMergeIsEmpty = startOfParagraphToMove.deepEquivalent() == en dOfParagraphToMove.deepEquivalent();
690 moveParagraph(startOfParagraphToMove, endOfParagraphToMove, mergeDestination , ASSERT_NO_EDITING_ABORT, false, !paragraphToMergeIsEmpty); 708 moveParagraph(startOfParagraphToMove, endOfParagraphToMove, mergeDestination , editingState, false, !paragraphToMergeIsEmpty);
709 if (editingState->isAborted())
710 return;
691 m_needPlaceholder = needPlaceholder; 711 m_needPlaceholder = needPlaceholder;
692 // The endingPosition was likely clobbered by the move, so recompute it (mov eParagraph selects the moved paragraph). 712 // The endingPosition was likely clobbered by the move, so recompute it (mov eParagraph selects the moved paragraph).
693 m_endingPosition = endingSelection().start(); 713 m_endingPosition = endingSelection().start();
694 } 714 }
695 715
696 void DeleteSelectionCommand::removePreviouslySelectedEmptyTableRows() 716 void DeleteSelectionCommand::removePreviouslySelectedEmptyTableRows(EditingState * editingState)
697 { 717 {
698 if (m_endTableRow && m_endTableRow->inDocument() && m_endTableRow != m_start TableRow) { 718 if (m_endTableRow && m_endTableRow->inDocument() && m_endTableRow != m_start TableRow) {
699 Node* row = m_endTableRow->previousSibling(); 719 Node* row = m_endTableRow->previousSibling();
700 while (row && row != m_startTableRow) { 720 while (row && row != m_startTableRow) {
701 RefPtrWillBeRawPtr<Node> previousRow = row->previousSibling(); 721 RefPtrWillBeRawPtr<Node> previousRow = row->previousSibling();
702 if (isTableRowEmpty(row)) { 722 if (isTableRowEmpty(row)) {
703 // Use a raw removeNode, instead of DeleteSelectionCommand's, 723 // Use a raw removeNode, instead of DeleteSelectionCommand's,
704 // because that won't remove rows, it only empties them in 724 // because that won't remove rows, it only empties them in
705 // preparation for this function. 725 // preparation for this function.
706 CompositeEditCommand::removeNode(row); 726 CompositeEditCommand::removeNode(row, editingState);
727 if (editingState->isAborted())
728 return;
707 } 729 }
708 row = previousRow.get(); 730 row = previousRow.get();
709 } 731 }
710 } 732 }
711 733
712 // Remove empty rows after the start row. 734 // Remove empty rows after the start row.
713 if (m_startTableRow && m_startTableRow->inDocument() && m_startTableRow != m _endTableRow) { 735 if (m_startTableRow && m_startTableRow->inDocument() && m_startTableRow != m _endTableRow) {
714 Node* row = m_startTableRow->nextSibling(); 736 Node* row = m_startTableRow->nextSibling();
715 while (row && row != m_endTableRow) { 737 while (row && row != m_endTableRow) {
716 RefPtrWillBeRawPtr<Node> nextRow = row->nextSibling(); 738 RefPtrWillBeRawPtr<Node> nextRow = row->nextSibling();
717 if (isTableRowEmpty(row)) 739 if (isTableRowEmpty(row)) {
718 CompositeEditCommand::removeNode(row); 740 CompositeEditCommand::removeNode(row, editingState);
741 if (editingState->isAborted())
742 return;
743 }
719 row = nextRow.get(); 744 row = nextRow.get();
720 } 745 }
721 } 746 }
722 747
723 if (m_endTableRow && m_endTableRow->inDocument() && m_endTableRow != m_start TableRow) { 748 if (m_endTableRow && m_endTableRow->inDocument() && m_endTableRow != m_start TableRow) {
724 if (isTableRowEmpty(m_endTableRow.get())) { 749 if (isTableRowEmpty(m_endTableRow.get())) {
725 // Don't remove m_endTableRow if it's where we're putting the ending 750 // Don't remove m_endTableRow if it's where we're putting the ending
726 // selection. 751 // selection.
727 if (!m_endingPosition.anchorNode()->isDescendantOf(m_endTableRow.get ())) { 752 if (!m_endingPosition.anchorNode()->isDescendantOf(m_endTableRow.get ())) {
728 // FIXME: We probably shouldn't remove m_endTableRow unless it's 753 // FIXME: We probably shouldn't remove m_endTableRow unless it's
729 // fully selected, even if it is empty. We'll need to start 754 // fully selected, even if it is empty. We'll need to start
730 // adjusting the selection endpoints during deletion to know 755 // adjusting the selection endpoints during deletion to know
731 // whether or not m_endTableRow was fully selected here. 756 // whether or not m_endTableRow was fully selected here.
732 CompositeEditCommand::removeNode(m_endTableRow.get()); 757 CompositeEditCommand::removeNode(m_endTableRow.get(), editingSta te);
758 if (editingState->isAborted())
759 return;
733 } 760 }
734 } 761 }
735 } 762 }
736 } 763 }
737 764
738 void DeleteSelectionCommand::calculateTypingStyleAfterDelete() 765 void DeleteSelectionCommand::calculateTypingStyleAfterDelete()
739 { 766 {
740 // Clearing any previously set typing style and doing an early return. 767 // Clearing any previously set typing style and doing an early return.
741 if (!m_typingStyle) { 768 if (!m_typingStyle) {
742 document().frame()->selection().clearTypingStyle(); 769 document().frame()->selection().clearTypingStyle();
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
835 bool lineBreakBeforeStart = lineBreakExistsAtVisiblePosition(previousPositio nOf(createVisiblePosition(m_upstreamStart))); 862 bool lineBreakBeforeStart = lineBreakExistsAtVisiblePosition(previousPositio nOf(createVisiblePosition(m_upstreamStart)));
836 863
837 // Delete any text that may hinder our ability to fixup whitespace after the 864 // Delete any text that may hinder our ability to fixup whitespace after the
838 // delete 865 // delete
839 deleteInsignificantTextDownstream(m_trailingWhitespace); 866 deleteInsignificantTextDownstream(m_trailingWhitespace);
840 867
841 saveTypingStyleState(); 868 saveTypingStyleState();
842 869
843 // deleting just a BR is handled specially, at least because we do not 870 // deleting just a BR is handled specially, at least because we do not
844 // want to replace it with a placeholder BR! 871 // want to replace it with a placeholder BR!
845 if (handleSpecialCaseBRDelete()) { 872 bool brResult = handleSpecialCaseBRDelete(editingState);
873 if (editingState->isAborted())
874 return;
875 if (brResult) {
846 calculateTypingStyleAfterDelete(); 876 calculateTypingStyleAfterDelete();
847 setEndingSelection(VisibleSelection(m_endingPosition, affinity, endingSe lection().isDirectional())); 877 setEndingSelection(VisibleSelection(m_endingPosition, affinity, endingSe lection().isDirectional()));
848 clearTransientState(); 878 clearTransientState();
849 rebalanceWhitespace(); 879 rebalanceWhitespace();
850 return; 880 return;
851 } 881 }
852 882
853 handleGeneralDelete(editingState); 883 handleGeneralDelete(editingState);
854 if (editingState->isAborted()) 884 if (editingState->isAborted())
855 return; 885 return;
856 886
857 fixupWhitespace(); 887 fixupWhitespace();
858 888
859 mergeParagraphs(); 889 mergeParagraphs(editingState);
890 if (editingState->isAborted())
891 return;
860 892
861 removePreviouslySelectedEmptyTableRows(); 893 removePreviouslySelectedEmptyTableRows(editingState);
894 if (editingState->isAborted())
895 return;
862 896
863 if (!m_needPlaceholder && rootWillStayOpenWithoutPlaceholder) { 897 if (!m_needPlaceholder && rootWillStayOpenWithoutPlaceholder) {
864 VisiblePosition visualEnding = createVisiblePosition(m_endingPosition); 898 VisiblePosition visualEnding = createVisiblePosition(m_endingPosition);
865 bool hasPlaceholder = lineBreakExistsAtVisiblePosition(visualEnding) 899 bool hasPlaceholder = lineBreakExistsAtVisiblePosition(visualEnding)
866 && nextPositionOf(visualEnding, CannotCrossEditingBoundary).isNull() ; 900 && nextPositionOf(visualEnding, CannotCrossEditingBoundary).isNull() ;
867 m_needPlaceholder = hasPlaceholder && lineBreakBeforeStart && !lineBreak AtEndOfSelectionToDelete; 901 m_needPlaceholder = hasPlaceholder && lineBreakBeforeStart && !lineBreak AtEndOfSelectionToDelete;
868 } 902 }
869 903
870 RefPtrWillBeRawPtr<HTMLBRElement> placeholder = m_needPlaceholder ? HTMLBREl ement::create(document()) : nullptr; 904 RefPtrWillBeRawPtr<HTMLBRElement> placeholder = m_needPlaceholder ? HTMLBREl ement::create(document()) : nullptr;
871 905
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
921 visitor->trace(m_deleteIntoBlockquoteStyle); 955 visitor->trace(m_deleteIntoBlockquoteStyle);
922 visitor->trace(m_startRoot); 956 visitor->trace(m_startRoot);
923 visitor->trace(m_endRoot); 957 visitor->trace(m_endRoot);
924 visitor->trace(m_startTableRow); 958 visitor->trace(m_startTableRow);
925 visitor->trace(m_endTableRow); 959 visitor->trace(m_endTableRow);
926 visitor->trace(m_temporaryPlaceholder); 960 visitor->trace(m_temporaryPlaceholder);
927 CompositeEditCommand::trace(visitor); 961 CompositeEditCommand::trace(visitor);
928 } 962 }
929 963
930 } // namespace blink 964 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698