Chromium Code Reviews| 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 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 523 // DeleteFromTextNodeCommand is never aborted. | 523 // DeleteFromTextNodeCommand is never aborted. |
| 524 applyCommandToComposite( | 524 applyCommandToComposite( |
| 525 DeleteFromTextNodeCommand::create(node, offset, count), | 525 DeleteFromTextNodeCommand::create(node, offset, count), |
| 526 ASSERT_NO_EDITING_ABORT); | 526 ASSERT_NO_EDITING_ABORT); |
| 527 } | 527 } |
| 528 | 528 |
| 529 void CompositeEditCommand::replaceTextInNode(Text* node, | 529 void CompositeEditCommand::replaceTextInNode(Text* node, |
| 530 unsigned offset, | 530 unsigned offset, |
| 531 unsigned count, | 531 unsigned count, |
| 532 const String& replacementText) { | 532 const String& replacementText) { |
| 533 // Notify listeners that a replacement has occurred rather than two separate | |
| 534 // insert + delete operations | |
| 535 SynchronousMutationNotifier::ScopedNotificationSuppressor suppressor( | |
| 536 &document()); | |
| 537 | |
| 533 // DeleteFromTextNodeCommand and InsertIntoTextNodeCommand are never | 538 // DeleteFromTextNodeCommand and InsertIntoTextNodeCommand are never |
| 534 // aborted. | 539 // aborted. |
| 535 applyCommandToComposite( | 540 applyCommandToComposite( |
| 536 DeleteFromTextNodeCommand::create(node, offset, count), | 541 DeleteFromTextNodeCommand::create(node, offset, count), |
| 537 ASSERT_NO_EDITING_ABORT); | 542 ASSERT_NO_EDITING_ABORT); |
| 538 if (!replacementText.isEmpty()) | 543 if (!replacementText.isEmpty()) |
| 539 applyCommandToComposite( | 544 applyCommandToComposite( |
| 540 InsertIntoTextNodeCommand::create(node, offset, replacementText), | 545 InsertIntoTextNodeCommand::create(node, offset, replacementText), |
| 541 ASSERT_NO_EDITING_ABORT); | 546 ASSERT_NO_EDITING_ABORT); |
| 542 } | 547 } |
| 543 | 548 |
| 544 Position CompositeEditCommand::replaceSelectedTextInNode(const String& text) { | 549 Position CompositeEditCommand::replaceSelectedTextInNode(const String& text) { |
| 545 Position start = endingSelection().start(); | 550 Position start = endingSelection().start(); |
| 546 Position end = endingSelection().end(); | 551 Position end = endingSelection().end(); |
| 547 if (start.computeContainerNode() != end.computeContainerNode() || | 552 if (start.computeContainerNode() != end.computeContainerNode() || |
| 548 !start.computeContainerNode()->isTextNode() || | 553 !start.computeContainerNode()->isTextNode() || |
| 549 isTabHTMLSpanElementTextNode(start.computeContainerNode())) | 554 isTabHTMLSpanElementTextNode(start.computeContainerNode())) |
| 550 return Position(); | 555 return Position(); |
| 551 | 556 |
| 552 Text* textNode = toText(start.computeContainerNode()); | 557 Text* textNode = toText(start.computeContainerNode()); |
| 553 replaceTextInNode(textNode, start.offsetInContainerNode(), | 558 replaceTextInNode(textNode, start.offsetInContainerNode(), |
| 554 end.offsetInContainerNode() - start.offsetInContainerNode(), | 559 end.offsetInContainerNode() - start.offsetInContainerNode(), |
| 555 text); | 560 text); |
| 556 | 561 |
| 557 return Position(textNode, start.offsetInContainerNode() + text.length()); | 562 return Position(textNode, start.offsetInContainerNode() + text.length()); |
| 558 } | 563 } |
| 559 | 564 |
| 560 static void copyMarkerTypesAndDescriptions( | |
| 561 const DocumentMarkerVector& markerPointers, | |
| 562 Vector<DocumentMarker::MarkerType>& types, | |
| 563 Vector<String>& descriptions) { | |
| 564 size_t arraySize = markerPointers.size(); | |
| 565 types.reserveCapacity(arraySize); | |
| 566 descriptions.reserveCapacity(arraySize); | |
| 567 for (const auto& markerPointer : markerPointers) { | |
| 568 types.push_back(markerPointer->type()); | |
| 569 descriptions.push_back(markerPointer->description()); | |
| 570 } | |
| 571 } | |
| 572 | |
| 573 void CompositeEditCommand::replaceTextInNodePreservingMarkers( | |
| 574 Text* node, | |
| 575 unsigned offset, | |
| 576 unsigned count, | |
| 577 const String& replacementText) { | |
| 578 DocumentMarkerController& markerController = document().markers(); | |
| 579 Vector<DocumentMarker::MarkerType> types; | |
| 580 Vector<String> descriptions; | |
| 581 copyMarkerTypesAndDescriptions( | |
| 582 markerController.markersInRange( | |
| 583 EphemeralRange(Position(node, offset), | |
| 584 Position(node, offset + count)), | |
| 585 DocumentMarker::AllMarkers()), | |
| 586 types, descriptions); | |
| 587 | |
| 588 replaceTextInNode(node, offset, count, replacementText); | |
| 589 | |
| 590 // Re-adding markers requires a clean tree. | |
| 591 document().updateStyleAndLayout(); | |
| 592 | |
| 593 DocumentLifecycle::DisallowTransitionScope disallowTransition( | |
| 594 document().lifecycle()); | |
| 595 Position startPosition(node, offset); | |
| 596 Position endPosition(node, offset + replacementText.length()); | |
| 597 DCHECK_EQ(types.size(), descriptions.size()); | |
| 598 | |
| 599 for (size_t i = 0; i < types.size(); ++i) | |
| 600 markerController.addMarker(startPosition, endPosition, types[i], | |
| 601 descriptions[i]); | |
| 602 } | |
| 603 | |
| 604 Position CompositeEditCommand::positionOutsideTabSpan(const Position& pos) { | 565 Position CompositeEditCommand::positionOutsideTabSpan(const Position& pos) { |
| 605 if (!isTabHTMLSpanElementTextNode(pos.anchorNode())) | 566 if (!isTabHTMLSpanElementTextNode(pos.anchorNode())) |
| 606 return pos; | 567 return pos; |
| 607 | 568 |
| 608 switch (pos.anchorType()) { | 569 switch (pos.anchorType()) { |
| 609 case PositionAnchorType::BeforeChildren: | 570 case PositionAnchorType::BeforeChildren: |
| 610 case PositionAnchorType::AfterChildren: | 571 case PositionAnchorType::AfterChildren: |
| 611 NOTREACHED(); | 572 NOTREACHED(); |
| 612 return pos; | 573 return pos; |
| 613 case PositionAnchorType::OffsetInAnchor: | 574 case PositionAnchorType::OffsetInAnchor: |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 766 !isWhitespace(toText(textNode->nextSibling())->data()[0]); | 727 !isWhitespace(toText(textNode->nextSibling())->data()[0]); |
| 767 const bool shouldEmitNBSPbeforeEnd = | 728 const bool shouldEmitNBSPbeforeEnd = |
| 768 (isEndOfParagraph(visibleDownstreamPos) || | 729 (isEndOfParagraph(visibleDownstreamPos) || |
| 769 (unsigned)downstream == text.length()) && | 730 (unsigned)downstream == text.length()) && |
| 770 !nextSiblingIsTextNode; | 731 !nextSiblingIsTextNode; |
| 771 String rebalancedString = stringWithRebalancedWhitespace( | 732 String rebalancedString = stringWithRebalancedWhitespace( |
| 772 string, isStartOfParagraph(visibleUpstreamPos) || !upstream, | 733 string, isStartOfParagraph(visibleUpstreamPos) || !upstream, |
| 773 shouldEmitNBSPbeforeEnd); | 734 shouldEmitNBSPbeforeEnd); |
| 774 | 735 |
| 775 if (string != rebalancedString) | 736 if (string != rebalancedString) |
| 776 replaceTextInNodePreservingMarkers(textNode, upstream, length, | 737 replaceTextInNode(textNode, upstream, length, rebalancedString); |
|
yosin_UTC9
2017/02/15 02:23:25
Let's make |replaceTextInNode()| to use |Character
| |
| 777 rebalancedString); | |
| 778 } | 738 } |
| 779 | 739 |
| 780 void CompositeEditCommand::prepareWhitespaceAtPositionForSplit( | 740 void CompositeEditCommand::prepareWhitespaceAtPositionForSplit( |
| 781 Position& position) { | 741 Position& position) { |
| 782 if (!isRichlyEditablePosition(position)) | 742 if (!isRichlyEditablePosition(position)) |
| 783 return; | 743 return; |
| 784 Node* node = position.anchorNode(); | 744 Node* node = position.anchorNode(); |
| 785 if (!node || !node->isTextNode()) | 745 if (!node || !node->isTextNode()) |
| 786 return; | 746 return; |
| 787 Text* textNode = toText(node); | 747 Text* textNode = toText(node); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 808 } | 768 } |
| 809 | 769 |
| 810 void CompositeEditCommand:: | 770 void CompositeEditCommand:: |
| 811 replaceCollapsibleWhitespaceWithNonBreakingSpaceIfNeeded( | 771 replaceCollapsibleWhitespaceWithNonBreakingSpaceIfNeeded( |
| 812 const VisiblePosition& visiblePosition) { | 772 const VisiblePosition& visiblePosition) { |
| 813 if (!isCollapsibleWhitespace(characterAfter(visiblePosition))) | 773 if (!isCollapsibleWhitespace(characterAfter(visiblePosition))) |
| 814 return; | 774 return; |
| 815 Position pos = mostForwardCaretPosition(visiblePosition.deepEquivalent()); | 775 Position pos = mostForwardCaretPosition(visiblePosition.deepEquivalent()); |
| 816 if (!pos.computeContainerNode() || !pos.computeContainerNode()->isTextNode()) | 776 if (!pos.computeContainerNode() || !pos.computeContainerNode()->isTextNode()) |
| 817 return; | 777 return; |
| 818 replaceTextInNodePreservingMarkers(toText(pos.computeContainerNode()), | 778 replaceTextInNode(toText(pos.computeContainerNode()), |
| 819 pos.offsetInContainerNode(), 1, | 779 pos.offsetInContainerNode(), 1, nonBreakingSpaceString()); |
| 820 nonBreakingSpaceString()); | |
| 821 } | 780 } |
| 822 | 781 |
| 823 void CompositeEditCommand::rebalanceWhitespace() { | 782 void CompositeEditCommand::rebalanceWhitespace() { |
| 824 VisibleSelection selection = endingSelection(); | 783 VisibleSelection selection = endingSelection(); |
| 825 if (selection.isNone()) | 784 if (selection.isNone()) |
| 826 return; | 785 return; |
| 827 | 786 |
| 828 rebalanceWhitespaceAt(selection.start()); | 787 rebalanceWhitespaceAt(selection.start()); |
| 829 if (selection.isRange()) | 788 if (selection.isRange()) |
| 830 rebalanceWhitespaceAt(selection.end()); | 789 rebalanceWhitespaceAt(selection.end()); |
| (...skipping 1140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1971 | 1930 |
| 1972 DEFINE_TRACE(CompositeEditCommand) { | 1931 DEFINE_TRACE(CompositeEditCommand) { |
| 1973 visitor->trace(m_commands); | 1932 visitor->trace(m_commands); |
| 1974 visitor->trace(m_startingSelection); | 1933 visitor->trace(m_startingSelection); |
| 1975 visitor->trace(m_endingSelection); | 1934 visitor->trace(m_endingSelection); |
| 1976 visitor->trace(m_undoStep); | 1935 visitor->trace(m_undoStep); |
| 1977 EditCommand::trace(visitor); | 1936 EditCommand::trace(visitor); |
| 1978 } | 1937 } |
| 1979 | 1938 |
| 1980 } // namespace blink | 1939 } // namespace blink |
| OLD | NEW |