Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
| 5 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. | 5 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. |
| 6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) | 6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) |
| 7 * | 7 * |
| 8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
| 9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
| 10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
| (...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 613 } | 613 } |
| 614 } | 614 } |
| 615 | 615 |
| 616 bool HTMLTextFormControlElement::lastChangeWasUserEdit() const | 616 bool HTMLTextFormControlElement::lastChangeWasUserEdit() const |
| 617 { | 617 { |
| 618 if (!isTextFormControl()) | 618 if (!isTextFormControl()) |
| 619 return false; | 619 return false; |
| 620 return m_lastChangeWasUserEdit; | 620 return m_lastChangeWasUserEdit; |
| 621 } | 621 } |
| 622 | 622 |
| 623 PassRefPtrWillBeRawPtr<Node> HTMLTextFormControlElement::createPlaceholderBreakE lement() const | |
| 624 { | |
| 625 return HTMLBRElement::create(document()); | |
| 626 } | |
| 627 | |
| 628 void HTMLTextFormControlElement::addPlaceholderBreakElementIfNecessary() | |
| 629 { | |
| 630 HTMLElement* innerEditor = innerEditorElement(); | |
| 631 ASSERT(innerEditor); | |
|
yosin_UTC9
2016/03/10 08:33:15
Q: do we need to have this assert? following line
tkent
2016/03/10 08:42:38
We may remove it. Removed.
| |
| 632 if (innerEditor->layoutObject() && !innerEditor->layoutObject()->style()->pr eserveNewline()) | |
| 633 return; | |
| 634 Node* lastChild = innerEditor->lastChild(); | |
| 635 if (!lastChild || !lastChild->isTextNode()) | |
| 636 return; | |
| 637 if (toText(lastChild)->data().endsWith('\n') || toText(lastChild)->data().en dsWith('\r')) | |
| 638 innerEditor->appendChild(createPlaceholderBreakElement()); | |
| 639 } | |
| 640 | |
| 623 void HTMLTextFormControlElement::setInnerEditorValue(const String& value) | 641 void HTMLTextFormControlElement::setInnerEditorValue(const String& value) |
| 624 { | 642 { |
| 625 ASSERT(!openShadowRoot()); | 643 ASSERT(!openShadowRoot()); |
| 626 if (!isTextFormControl() || openShadowRoot()) | 644 if (!isTextFormControl() || openShadowRoot()) |
| 627 return; | 645 return; |
| 628 | 646 |
| 629 bool textIsChanged = value != innerEditorValue(); | 647 bool textIsChanged = value != innerEditorValue(); |
| 630 HTMLElement* innerEditor = innerEditorElement(); | 648 HTMLElement* innerEditor = innerEditorElement(); |
| 631 if (!textIsChanged && innerEditor->hasChildren()) | 649 if (!textIsChanged && innerEditor->hasChildren()) |
| 632 return; | 650 return; |
| 633 | 651 |
| 634 // If the last child is a trailing <br> that's appended below, remove it | 652 // If the last child is a trailing <br> that's appended below, remove it |
| 635 // first so as to enable setInnerText() fast path of updating a text node. | 653 // first so as to enable setInnerText() fast path of updating a text node. |
| 636 if (isHTMLBRElement(innerEditor->lastChild())) | 654 if (isHTMLBRElement(innerEditor->lastChild())) |
| 637 innerEditor->removeChild(innerEditor->lastChild(), ASSERT_NO_EXCEPTION); | 655 innerEditor->removeChild(innerEditor->lastChild(), ASSERT_NO_EXCEPTION); |
| 638 | 656 |
| 639 // We don't use setTextContent. It triggers unnecessary paint. | 657 // We don't use setTextContent. It triggers unnecessary paint. |
| 640 if (value.isEmpty()) | 658 if (value.isEmpty()) |
| 641 innerEditor->removeChildren(); | 659 innerEditor->removeChildren(); |
| 642 else | 660 else |
| 643 replaceChildrenWithText(innerEditor, value, ASSERT_NO_EXCEPTION); | 661 replaceChildrenWithText(innerEditor, value, ASSERT_NO_EXCEPTION); |
| 644 | 662 |
| 645 if (value.endsWith('\n') || value.endsWith('\r')) | 663 // Add <br> so that we can put the caret at the next line of the last |
| 646 innerEditor->appendChild(HTMLBRElement::create(document())); | 664 // newline. |
| 665 addPlaceholderBreakElementIfNecessary(); | |
| 647 | 666 |
| 648 if (textIsChanged && layoutObject()) { | 667 if (textIsChanged && layoutObject()) { |
| 649 if (AXObjectCache* cache = document().existingAXObjectCache()) | 668 if (AXObjectCache* cache = document().existingAXObjectCache()) |
| 650 cache->handleTextFormControlChanged(this); | 669 cache->handleTextFormControlChanged(this); |
| 651 } | 670 } |
| 652 } | 671 } |
| 653 | 672 |
| 654 static String finishText(StringBuilder& result) | |
| 655 { | |
| 656 // Remove one trailing newline; there's always one that's collapsed out by l ayoutObject. | |
| 657 size_t size = result.length(); | |
| 658 if (size && result[size - 1] == '\n') | |
| 659 result.resize(--size); | |
| 660 return result.toString(); | |
| 661 } | |
| 662 | |
| 663 String HTMLTextFormControlElement::innerEditorValue() const | 673 String HTMLTextFormControlElement::innerEditorValue() const |
| 664 { | 674 { |
| 665 ASSERT(!openShadowRoot()); | 675 ASSERT(!openShadowRoot()); |
| 666 HTMLElement* innerEditor = innerEditorElement(); | 676 HTMLElement* innerEditor = innerEditorElement(); |
| 667 if (!innerEditor || !isTextFormControl()) | 677 if (!innerEditor || !isTextFormControl()) |
| 668 return emptyString(); | 678 return emptyString(); |
| 669 | 679 |
| 670 StringBuilder result; | 680 StringBuilder result; |
| 671 for (Node& node : NodeTraversal::inclusiveDescendantsOf(*innerEditor)) { | 681 for (Node& node : NodeTraversal::inclusiveDescendantsOf(*innerEditor)) { |
| 672 if (isHTMLBRElement(node)) | 682 if (isHTMLBRElement(node)) { |
| 673 result.append(newlineCharacter); | 683 ASSERT(&node == innerEditor->lastChild()); |
| 674 else if (node.isTextNode()) | 684 if (&node != innerEditor->lastChild()) |
| 685 result.append(newlineCharacter); | |
| 686 } else if (node.isTextNode()) { | |
| 675 result.append(toText(node).data()); | 687 result.append(toText(node).data()); |
| 688 } | |
| 676 } | 689 } |
| 677 return finishText(result); | 690 return result.toString(); |
| 678 } | 691 } |
| 679 | 692 |
| 680 static void getNextSoftBreak(RootInlineBox*& line, Node*& breakNode, unsigned& b reakOffset) | 693 static void getNextSoftBreak(RootInlineBox*& line, Node*& breakNode, unsigned& b reakOffset) |
| 681 { | 694 { |
| 682 RootInlineBox* next; | 695 RootInlineBox* next; |
| 683 for (; line; line = next) { | 696 for (; line; line = next) { |
| 684 next = line->nextRootBox(); | 697 next = line->nextRootBox(); |
| 685 if (next && !line->endsWithBreak()) { | 698 if (next && !line->endsWithBreak()) { |
| 686 ASSERT(line->lineBreakObj()); | 699 ASSERT(line->lineBreakObj()); |
| 687 breakNode = line->lineBreakObj().node(); | 700 breakNode = line->lineBreakObj().node(); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 710 unsigned breakOffset; | 723 unsigned breakOffset; |
| 711 RootInlineBox* line = layoutObject->firstRootBox(); | 724 RootInlineBox* line = layoutObject->firstRootBox(); |
| 712 if (!line) | 725 if (!line) |
| 713 return value(); | 726 return value(); |
| 714 | 727 |
| 715 getNextSoftBreak(line, breakNode, breakOffset); | 728 getNextSoftBreak(line, breakNode, breakOffset); |
| 716 | 729 |
| 717 StringBuilder result; | 730 StringBuilder result; |
| 718 for (Node& node : NodeTraversal::descendantsOf(*innerText)) { | 731 for (Node& node : NodeTraversal::descendantsOf(*innerText)) { |
| 719 if (isHTMLBRElement(node)) { | 732 if (isHTMLBRElement(node)) { |
| 720 result.append(newlineCharacter); | 733 ASSERT(&node == innerText->lastChild()); |
| 734 if (&node != innerText->lastChild()) | |
| 735 result.append(newlineCharacter); | |
| 721 } else if (node.isTextNode()) { | 736 } else if (node.isTextNode()) { |
| 722 String data = toText(node).data(); | 737 String data = toText(node).data(); |
| 723 unsigned length = data.length(); | 738 unsigned length = data.length(); |
| 724 unsigned position = 0; | 739 unsigned position = 0; |
| 725 while (breakNode == node && breakOffset <= length) { | 740 while (breakNode == node && breakOffset <= length) { |
| 726 if (breakOffset > position) { | 741 if (breakOffset > position) { |
| 727 result.append(data, position, breakOffset - position); | 742 result.append(data, position, breakOffset - position); |
| 728 position = breakOffset; | 743 position = breakOffset; |
| 729 result.append(newlineCharacter); | 744 result.append(newlineCharacter); |
| 730 } | 745 } |
| 731 getNextSoftBreak(line, breakNode, breakOffset); | 746 getNextSoftBreak(line, breakNode, breakOffset); |
| 732 } | 747 } |
| 733 result.append(data, position, length - position); | 748 result.append(data, position, length - position); |
| 734 } | 749 } |
| 735 while (breakNode == node) | 750 while (breakNode == node) |
| 736 getNextSoftBreak(line, breakNode, breakOffset); | 751 getNextSoftBreak(line, breakNode, breakOffset); |
| 737 } | 752 } |
| 738 return finishText(result); | 753 return result.toString(); |
| 739 } | 754 } |
| 740 | 755 |
| 741 HTMLTextFormControlElement* enclosingTextFormControl(const Position& position) | 756 HTMLTextFormControlElement* enclosingTextFormControl(const Position& position) |
| 742 { | 757 { |
| 743 ASSERT(position.isNull() || position.isOffsetInAnchor() | 758 ASSERT(position.isNull() || position.isOffsetInAnchor() |
| 744 || position.computeContainerNode() || !position.anchorNode()->shadowHost () | 759 || position.computeContainerNode() || !position.anchorNode()->shadowHost () |
| 745 || (position.anchorNode()->parentNode() && position.anchorNode()->parent Node()->isShadowRoot())); | 760 || (position.anchorNode()->parentNode() && position.anchorNode()->parent Node()->isShadowRoot())); |
| 746 return enclosingTextFormControl(position.computeContainerNode()); | 761 return enclosingTextFormControl(position.computeContainerNode()); |
| 747 } | 762 } |
| 748 | 763 |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1014 } | 1029 } |
| 1015 | 1030 |
| 1016 void HTMLTextFormControlElement::copyNonAttributePropertiesFromElement(const Ele ment& source) | 1031 void HTMLTextFormControlElement::copyNonAttributePropertiesFromElement(const Ele ment& source) |
| 1017 { | 1032 { |
| 1018 const HTMLTextFormControlElement& sourceElement = static_cast<const HTMLText FormControlElement&>(source); | 1033 const HTMLTextFormControlElement& sourceElement = static_cast<const HTMLText FormControlElement&>(source); |
| 1019 m_lastChangeWasUserEdit = sourceElement.m_lastChangeWasUserEdit; | 1034 m_lastChangeWasUserEdit = sourceElement.m_lastChangeWasUserEdit; |
| 1020 HTMLFormControlElement::copyNonAttributePropertiesFromElement(source); | 1035 HTMLFormControlElement::copyNonAttributePropertiesFromElement(source); |
| 1021 } | 1036 } |
| 1022 | 1037 |
| 1023 } // namespace blink | 1038 } // namespace blink |
| OLD | NEW |