| 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 if (innerEditor->layoutObject() && !innerEditor->layoutObject()->style()->pr
eserveNewline()) |
| 632 return; |
| 633 Node* lastChild = innerEditor->lastChild(); |
| 634 if (!lastChild || !lastChild->isTextNode()) |
| 635 return; |
| 636 if (toText(lastChild)->data().endsWith('\n') || toText(lastChild)->data().en
dsWith('\r')) |
| 637 innerEditor->appendChild(createPlaceholderBreakElement()); |
| 638 } |
| 639 |
| 623 void HTMLTextFormControlElement::setInnerEditorValue(const String& value) | 640 void HTMLTextFormControlElement::setInnerEditorValue(const String& value) |
| 624 { | 641 { |
| 625 ASSERT(!openShadowRoot()); | 642 ASSERT(!openShadowRoot()); |
| 626 if (!isTextFormControl() || openShadowRoot()) | 643 if (!isTextFormControl() || openShadowRoot()) |
| 627 return; | 644 return; |
| 628 | 645 |
| 629 bool textIsChanged = value != innerEditorValue(); | 646 bool textIsChanged = value != innerEditorValue(); |
| 630 HTMLElement* innerEditor = innerEditorElement(); | 647 HTMLElement* innerEditor = innerEditorElement(); |
| 631 if (!textIsChanged && innerEditor->hasChildren()) | 648 if (!textIsChanged && innerEditor->hasChildren()) |
| 632 return; | 649 return; |
| 633 | 650 |
| 634 // If the last child is a trailing <br> that's appended below, remove it | 651 // 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. | 652 // first so as to enable setInnerText() fast path of updating a text node. |
| 636 if (isHTMLBRElement(innerEditor->lastChild())) | 653 if (isHTMLBRElement(innerEditor->lastChild())) |
| 637 innerEditor->removeChild(innerEditor->lastChild(), ASSERT_NO_EXCEPTION); | 654 innerEditor->removeChild(innerEditor->lastChild(), ASSERT_NO_EXCEPTION); |
| 638 | 655 |
| 639 // We don't use setTextContent. It triggers unnecessary paint. | 656 // We don't use setTextContent. It triggers unnecessary paint. |
| 640 if (value.isEmpty()) | 657 if (value.isEmpty()) |
| 641 innerEditor->removeChildren(); | 658 innerEditor->removeChildren(); |
| 642 else | 659 else |
| 643 replaceChildrenWithText(innerEditor, value, ASSERT_NO_EXCEPTION); | 660 replaceChildrenWithText(innerEditor, value, ASSERT_NO_EXCEPTION); |
| 644 | 661 |
| 645 if (value.endsWith('\n') || value.endsWith('\r')) | 662 // Add <br> so that we can put the caret at the next line of the last |
| 646 innerEditor->appendChild(HTMLBRElement::create(document())); | 663 // newline. |
| 664 addPlaceholderBreakElementIfNecessary(); |
| 647 | 665 |
| 648 if (textIsChanged && layoutObject()) { | 666 if (textIsChanged && layoutObject()) { |
| 649 if (AXObjectCache* cache = document().existingAXObjectCache()) | 667 if (AXObjectCache* cache = document().existingAXObjectCache()) |
| 650 cache->handleTextFormControlChanged(this); | 668 cache->handleTextFormControlChanged(this); |
| 651 } | 669 } |
| 652 } | 670 } |
| 653 | 671 |
| 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 | 672 String HTMLTextFormControlElement::innerEditorValue() const |
| 664 { | 673 { |
| 665 ASSERT(!openShadowRoot()); | 674 ASSERT(!openShadowRoot()); |
| 666 HTMLElement* innerEditor = innerEditorElement(); | 675 HTMLElement* innerEditor = innerEditorElement(); |
| 667 if (!innerEditor || !isTextFormControl()) | 676 if (!innerEditor || !isTextFormControl()) |
| 668 return emptyString(); | 677 return emptyString(); |
| 669 | 678 |
| 670 StringBuilder result; | 679 StringBuilder result; |
| 671 for (Node& node : NodeTraversal::inclusiveDescendantsOf(*innerEditor)) { | 680 for (Node& node : NodeTraversal::inclusiveDescendantsOf(*innerEditor)) { |
| 672 if (isHTMLBRElement(node)) | 681 if (isHTMLBRElement(node)) { |
| 673 result.append(newlineCharacter); | 682 ASSERT(&node == innerEditor->lastChild()); |
| 674 else if (node.isTextNode()) | 683 if (&node != innerEditor->lastChild()) |
| 684 result.append(newlineCharacter); |
| 685 } else if (node.isTextNode()) { |
| 675 result.append(toText(node).data()); | 686 result.append(toText(node).data()); |
| 687 } |
| 676 } | 688 } |
| 677 return finishText(result); | 689 return result.toString(); |
| 678 } | 690 } |
| 679 | 691 |
| 680 static void getNextSoftBreak(RootInlineBox*& line, Node*& breakNode, unsigned& b
reakOffset) | 692 static void getNextSoftBreak(RootInlineBox*& line, Node*& breakNode, unsigned& b
reakOffset) |
| 681 { | 693 { |
| 682 RootInlineBox* next; | 694 RootInlineBox* next; |
| 683 for (; line; line = next) { | 695 for (; line; line = next) { |
| 684 next = line->nextRootBox(); | 696 next = line->nextRootBox(); |
| 685 if (next && !line->endsWithBreak()) { | 697 if (next && !line->endsWithBreak()) { |
| 686 ASSERT(line->lineBreakObj()); | 698 ASSERT(line->lineBreakObj()); |
| 687 breakNode = line->lineBreakObj().node(); | 699 breakNode = line->lineBreakObj().node(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 710 unsigned breakOffset; | 722 unsigned breakOffset; |
| 711 RootInlineBox* line = layoutObject->firstRootBox(); | 723 RootInlineBox* line = layoutObject->firstRootBox(); |
| 712 if (!line) | 724 if (!line) |
| 713 return value(); | 725 return value(); |
| 714 | 726 |
| 715 getNextSoftBreak(line, breakNode, breakOffset); | 727 getNextSoftBreak(line, breakNode, breakOffset); |
| 716 | 728 |
| 717 StringBuilder result; | 729 StringBuilder result; |
| 718 for (Node& node : NodeTraversal::descendantsOf(*innerText)) { | 730 for (Node& node : NodeTraversal::descendantsOf(*innerText)) { |
| 719 if (isHTMLBRElement(node)) { | 731 if (isHTMLBRElement(node)) { |
| 720 result.append(newlineCharacter); | 732 ASSERT(&node == innerText->lastChild()); |
| 733 if (&node != innerText->lastChild()) |
| 734 result.append(newlineCharacter); |
| 721 } else if (node.isTextNode()) { | 735 } else if (node.isTextNode()) { |
| 722 String data = toText(node).data(); | 736 String data = toText(node).data(); |
| 723 unsigned length = data.length(); | 737 unsigned length = data.length(); |
| 724 unsigned position = 0; | 738 unsigned position = 0; |
| 725 while (breakNode == node && breakOffset <= length) { | 739 while (breakNode == node && breakOffset <= length) { |
| 726 if (breakOffset > position) { | 740 if (breakOffset > position) { |
| 727 result.append(data, position, breakOffset - position); | 741 result.append(data, position, breakOffset - position); |
| 728 position = breakOffset; | 742 position = breakOffset; |
| 729 result.append(newlineCharacter); | 743 result.append(newlineCharacter); |
| 730 } | 744 } |
| 731 getNextSoftBreak(line, breakNode, breakOffset); | 745 getNextSoftBreak(line, breakNode, breakOffset); |
| 732 } | 746 } |
| 733 result.append(data, position, length - position); | 747 result.append(data, position, length - position); |
| 734 } | 748 } |
| 735 while (breakNode == node) | 749 while (breakNode == node) |
| 736 getNextSoftBreak(line, breakNode, breakOffset); | 750 getNextSoftBreak(line, breakNode, breakOffset); |
| 737 } | 751 } |
| 738 return finishText(result); | 752 return result.toString(); |
| 739 } | 753 } |
| 740 | 754 |
| 741 HTMLTextFormControlElement* enclosingTextFormControl(const Position& position) | 755 HTMLTextFormControlElement* enclosingTextFormControl(const Position& position) |
| 742 { | 756 { |
| 743 ASSERT(position.isNull() || position.isOffsetInAnchor() | 757 ASSERT(position.isNull() || position.isOffsetInAnchor() |
| 744 || position.computeContainerNode() || !position.anchorNode()->shadowHost
() | 758 || position.computeContainerNode() || !position.anchorNode()->shadowHost
() |
| 745 || (position.anchorNode()->parentNode() && position.anchorNode()->parent
Node()->isShadowRoot())); | 759 || (position.anchorNode()->parentNode() && position.anchorNode()->parent
Node()->isShadowRoot())); |
| 746 return enclosingTextFormControl(position.computeContainerNode()); | 760 return enclosingTextFormControl(position.computeContainerNode()); |
| 747 } | 761 } |
| 748 | 762 |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1014 } | 1028 } |
| 1015 | 1029 |
| 1016 void HTMLTextFormControlElement::copyNonAttributePropertiesFromElement(const Ele
ment& source) | 1030 void HTMLTextFormControlElement::copyNonAttributePropertiesFromElement(const Ele
ment& source) |
| 1017 { | 1031 { |
| 1018 const HTMLTextFormControlElement& sourceElement = static_cast<const HTMLText
FormControlElement&>(source); | 1032 const HTMLTextFormControlElement& sourceElement = static_cast<const HTMLText
FormControlElement&>(source); |
| 1019 m_lastChangeWasUserEdit = sourceElement.m_lastChangeWasUserEdit; | 1033 m_lastChangeWasUserEdit = sourceElement.m_lastChangeWasUserEdit; |
| 1020 HTMLFormControlElement::copyNonAttributePropertiesFromElement(source); | 1034 HTMLFormControlElement::copyNonAttributePropertiesFromElement(source); |
| 1021 } | 1035 } |
| 1022 | 1036 |
| 1023 } // namespace blink | 1037 } // namespace blink |
| OLD | NEW |