Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. | 2 * Copyright (C) 2004, 2005, 2006, 2007 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 30 matching lines...) Expand all Loading... | |
| 41 #include "core/editing/PlainTextRange.h" | 41 #include "core/editing/PlainTextRange.h" |
| 42 #include "core/editing/TextIterator.h" | 42 #include "core/editing/TextIterator.h" |
| 43 #include "core/editing/VisiblePosition.h" | 43 #include "core/editing/VisiblePosition.h" |
| 44 #include "core/editing/VisibleSelection.h" | 44 #include "core/editing/VisibleSelection.h" |
| 45 #include "core/editing/VisibleUnits.h" | 45 #include "core/editing/VisibleUnits.h" |
| 46 #include "core/frame/LocalFrame.h" | 46 #include "core/frame/LocalFrame.h" |
| 47 #include "core/frame/UseCounter.h" | 47 #include "core/frame/UseCounter.h" |
| 48 #include "core/html/HTMLBRElement.h" | 48 #include "core/html/HTMLBRElement.h" |
| 49 #include "core/html/HTMLDivElement.h" | 49 #include "core/html/HTMLDivElement.h" |
| 50 #include "core/html/HTMLLIElement.h" | 50 #include "core/html/HTMLLIElement.h" |
| 51 #include "core/html/HTMLOListElement.h" | |
| 52 #include "core/html/HTMLParagraphElement.h" | 51 #include "core/html/HTMLParagraphElement.h" |
| 53 #include "core/html/HTMLSpanElement.h" | 52 #include "core/html/HTMLSpanElement.h" |
| 54 #include "core/html/HTMLTableCellElement.h" | 53 #include "core/html/HTMLTableCellElement.h" |
| 55 #include "core/html/HTMLUListElement.h" | 54 #include "core/html/HTMLUListElement.h" |
| 56 #include "core/rendering/RenderObject.h" | 55 #include "core/rendering/RenderObject.h" |
| 57 #include "core/rendering/RenderTableCell.h" | 56 #include "core/rendering/RenderTableCell.h" |
| 58 #include "wtf/Assertions.h" | 57 #include "wtf/Assertions.h" |
| 59 #include "wtf/StdLibExtras.h" | 58 #include "wtf/StdLibExtras.h" |
| 60 #include "wtf/text/StringBuilder.h" | 59 #include "wtf/text/StringBuilder.h" |
| 61 | 60 |
| (...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 537 // Returns the visible position at the ending of a node | 536 // Returns the visible position at the ending of a node |
| 538 VisiblePosition visiblePositionAfterNode(Node& node) | 537 VisiblePosition visiblePositionAfterNode(Node& node) |
| 539 { | 538 { |
| 540 if (node.hasChildren()) | 539 if (node.hasChildren()) |
| 541 return VisiblePosition(lastPositionInOrAfterNode(&node), DOWNSTREAM); | 540 return VisiblePosition(lastPositionInOrAfterNode(&node), DOWNSTREAM); |
| 542 ASSERT(node.parentNode()); | 541 ASSERT(node.parentNode()); |
| 543 ASSERT(!node.parentNode()->isShadowRoot()); | 542 ASSERT(!node.parentNode()->isShadowRoot()); |
| 544 return VisiblePosition(positionInParentAfterNode(node)); | 543 return VisiblePosition(positionInParentAfterNode(node)); |
| 545 } | 544 } |
| 546 | 545 |
| 547 // Create a range object with two visible positions, start and end. | |
| 548 // create(Document*, const Position&, const Position&); will use deprecatedEditi ngOffset | |
| 549 // Use this function instead of create a regular range object (avoiding editing offset). | |
| 550 PassRefPtrWillBeRawPtr<Range> createRange(Document& document, const VisiblePosit ion& start, const VisiblePosition& end, ExceptionState& exceptionState) | |
| 551 { | |
| 552 RefPtrWillBeRawPtr<Range> selectedRange = Range::create(document); | |
| 553 selectedRange->setStart(start.deepEquivalent().containerNode(), start.deepEq uivalent().computeOffsetInContainerNode(), exceptionState); | |
| 554 if (!exceptionState.hadException()) | |
| 555 selectedRange->setEnd(end.deepEquivalent().containerNode(), end.deepEqui valent().computeOffsetInContainerNode(), exceptionState); | |
| 556 return selectedRange.release(); | |
| 557 } | |
| 558 | |
| 559 bool isHTMLListElement(Node* n) | 546 bool isHTMLListElement(Node* n) |
| 560 { | 547 { |
| 561 return (n && (isHTMLUListElement(*n) || isHTMLOListElement(*n) || isHTMLDLis tElement(*n))); | 548 return (n && (isHTMLUListElement(*n) || isHTMLOListElement(*n) || isHTMLDLis tElement(*n))); |
| 562 } | 549 } |
| 563 | 550 |
| 564 bool isListItem(const Node* n) | 551 bool isListItem(const Node* n) |
| 565 { | 552 { |
| 566 return n && n->renderer() && n->renderer()->isListItem(); | 553 return n && n->renderer() && n->renderer()->isListItem(); |
| 567 } | 554 } |
| 568 | 555 |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 729 | 716 |
| 730 while (HTMLElement* nextList = enclosingList(list)) { | 717 while (HTMLElement* nextList = enclosingList(list)) { |
| 731 if (nextList == rootList) | 718 if (nextList == rootList) |
| 732 break; | 719 break; |
| 733 list = nextList; | 720 list = nextList; |
| 734 } | 721 } |
| 735 | 722 |
| 736 return list; | 723 return list; |
| 737 } | 724 } |
| 738 | 725 |
| 726 // Determines whether two positions are visibly next to each other (first then s econd) | |
| 727 // while ignoring whitespaces and unrendered nodes | |
| 728 static bool isVisiblyAdjacent(const Position& first, const Position& second) | |
| 729 { | |
| 730 return VisiblePosition(first) == VisiblePosition(second.upstream()); | |
| 731 } | |
| 732 | |
| 739 bool canMergeLists(Element* firstList, Element* secondList) | 733 bool canMergeLists(Element* firstList, Element* secondList) |
| 740 { | 734 { |
| 741 if (!firstList || !secondList || !firstList->isHTMLElement() || !secondList- >isHTMLElement()) | 735 if (!firstList || !secondList || !firstList->isHTMLElement() || !secondList- >isHTMLElement()) |
| 742 return false; | 736 return false; |
| 743 | 737 |
| 744 return firstList->hasTagName(secondList->tagQName()) // make sure the list t ypes match (ol vs. ul) | 738 return firstList->hasTagName(secondList->tagQName()) // make sure the list t ypes match (ol vs. ul) |
| 745 && firstList->hasEditableStyle() && secondList->hasEditableStyle() // both l ists are editable | 739 && firstList->hasEditableStyle() && secondList->hasEditableStyle() // both l ists are editable |
| 746 && firstList->rootEditableElement() == secondList->rootEditableElement() // don't cross editing boundaries | 740 && firstList->rootEditableElement() == secondList->rootEditableElement() // don't cross editing boundaries |
| 747 && isVisiblyAdjacent(positionInParentAfterNode(*firstList), positionInParent BeforeNode(*secondList)); | 741 && isVisiblyAdjacent(positionInParentAfterNode(*firstList), positionInParent BeforeNode(*secondList)); |
| 748 // Make sure there is no visible content between this li and the previous li st | 742 // Make sure there is no visible content between this li and the previous li st |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 813 | 807 |
| 814 ASSERT_NOT_REACHED(); | 808 ASSERT_NOT_REACHED(); |
| 815 return nullptr; | 809 return nullptr; |
| 816 } | 810 } |
| 817 | 811 |
| 818 PassRefPtrWillBeRawPtr<HTMLBRElement> createBreakElement(Document& document) | 812 PassRefPtrWillBeRawPtr<HTMLBRElement> createBreakElement(Document& document) |
| 819 { | 813 { |
| 820 return HTMLBRElement::create(document); | 814 return HTMLBRElement::create(document); |
| 821 } | 815 } |
| 822 | 816 |
| 823 PassRefPtrWillBeRawPtr<HTMLOListElement> createOrderedListElement(Document& docu ment) | |
| 824 { | |
| 825 return HTMLOListElement::create(document); | |
| 826 } | |
| 827 | |
| 828 PassRefPtrWillBeRawPtr<HTMLUListElement> createUnorderedListElement(Document& do cument) | 817 PassRefPtrWillBeRawPtr<HTMLUListElement> createUnorderedListElement(Document& do cument) |
| 829 { | 818 { |
| 830 return HTMLUListElement::create(document); | 819 return HTMLUListElement::create(document); |
| 831 } | 820 } |
| 832 | 821 |
| 833 PassRefPtrWillBeRawPtr<HTMLLIElement> createListItemElement(Document& document) | 822 PassRefPtrWillBeRawPtr<HTMLLIElement> createListItemElement(Document& document) |
| 834 { | 823 { |
| 835 return HTMLLIElement::create(document); | 824 return HTMLLIElement::create(document); |
| 836 } | 825 } |
| 837 | 826 |
| 838 PassRefPtrWillBeRawPtr<HTMLElement> createHTMLElement(Document& document, const QualifiedName& name) | 827 PassRefPtrWillBeRawPtr<HTMLElement> createHTMLElement(Document& document, const QualifiedName& name) |
| 839 { | 828 { |
| 840 return createHTMLElement(document, name.localName()); | 829 return HTMLElementFactory::createHTMLElement(name.localName(), document, 0, false); |
| 841 } | |
| 842 | |
| 843 PassRefPtrWillBeRawPtr<HTMLElement> createHTMLElement(Document& document, const AtomicString& tagName) | |
| 844 { | |
| 845 return HTMLElementFactory::createHTMLElement(tagName, document, 0, false); | |
| 846 } | 830 } |
| 847 | 831 |
| 848 bool isTabHTMLSpanElement(const Node* node) | 832 bool isTabHTMLSpanElement(const Node* node) |
| 849 { | 833 { |
| 850 if (!isHTMLSpanElement(node) || toHTMLSpanElement(node)->getAttribute(classA ttr) != AppleTabSpanClass) | 834 if (!isHTMLSpanElement(node) || toHTMLSpanElement(node)->getAttribute(classA ttr) != AppleTabSpanClass) |
| 851 return false; | 835 return false; |
| 852 UseCounter::count(node->document(), UseCounter::EditingAppleTabSpanClass); | 836 UseCounter::count(node->document(), UseCounter::EditingAppleTabSpanClass); |
| 853 return true; | 837 return true; |
| 854 } | 838 } |
| 855 | 839 |
| 856 bool isTabHTMLSpanElementTextNode(const Node* node) | 840 bool isTabHTMLSpanElementTextNode(const Node* node) |
| 857 { | 841 { |
| 858 return node && node->isTextNode() && node->parentNode() && isTabHTMLSpanElem ent(node->parentNode()); | 842 return node && node->isTextNode() && node->parentNode() && isTabHTMLSpanElem ent(node->parentNode()); |
| 859 } | 843 } |
| 860 | 844 |
| 861 HTMLSpanElement* tabSpanElement(const Node* node) | 845 HTMLSpanElement* tabSpanElement(const Node* node) |
| 862 { | 846 { |
| 863 return isTabHTMLSpanElementTextNode(node) ? toHTMLSpanElement(node->parentNo de()) : 0; | 847 return isTabHTMLSpanElementTextNode(node) ? toHTMLSpanElement(node->parentNo de()) : 0; |
| 864 } | 848 } |
| 865 | 849 |
| 866 PassRefPtrWillBeRawPtr<HTMLSpanElement> createTabSpanElement(Document& document, PassRefPtrWillBeRawPtr<Text> prpTabTextNode) | 850 static PassRefPtrWillBeRawPtr<HTMLSpanElement> createTabSpanElement(Document& do cument, PassRefPtrWillBeRawPtr<Text> prpTabTextNode) |
| 867 { | 851 { |
| 868 RefPtrWillBeRawPtr<Text> tabTextNode = prpTabTextNode; | 852 RefPtrWillBeRawPtr<Text> tabTextNode = prpTabTextNode; |
| 869 | 853 |
| 870 // Make the span to hold the tab. | 854 // Make the span to hold the tab. |
| 871 RefPtrWillBeRawPtr<HTMLSpanElement> spanElement = toHTMLSpanElement(document .createElement(spanTag, false).get()); | 855 RefPtrWillBeRawPtr<HTMLSpanElement> spanElement = toHTMLSpanElement(document .createElement(spanTag, false).get()); |
| 872 spanElement->setAttribute(classAttr, AppleTabSpanClass); | 856 spanElement->setAttribute(classAttr, AppleTabSpanClass); |
| 873 spanElement->setAttribute(styleAttr, "white-space:pre"); | 857 spanElement->setAttribute(styleAttr, "white-space:pre"); |
| 874 | 858 |
| 875 // Add tab text to that span. | 859 // Add tab text to that span. |
| 876 if (!tabTextNode) | 860 if (!tabTextNode) |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 889 PassRefPtrWillBeRawPtr<HTMLSpanElement> createTabSpanElement(Document& document) | 873 PassRefPtrWillBeRawPtr<HTMLSpanElement> createTabSpanElement(Document& document) |
| 890 { | 874 { |
| 891 return createTabSpanElement(document, PassRefPtrWillBeRawPtr<Text>(nullptr)) ; | 875 return createTabSpanElement(document, PassRefPtrWillBeRawPtr<Text>(nullptr)) ; |
| 892 } | 876 } |
| 893 | 877 |
| 894 PassRefPtrWillBeRawPtr<HTMLBRElement> createBlockPlaceholderElement(Document& do cument) | 878 PassRefPtrWillBeRawPtr<HTMLBRElement> createBlockPlaceholderElement(Document& do cument) |
| 895 { | 879 { |
| 896 return toHTMLBRElement(document.createElement(brTag, false).get()); | 880 return toHTMLBRElement(document.createElement(brTag, false).get()); |
| 897 } | 881 } |
| 898 | 882 |
| 899 bool isNodeRendered(const Node *node) | 883 bool isNodeRendered(const Node &node) |
|
Yuta Kitamura
2014/11/27 08:38:39
Plaese attach "&" to the type name, not the argume
| |
| 900 { | 884 { |
| 901 if (!node) | 885 RenderObject* renderer = node.renderer(); |
| 902 return false; | |
| 903 | |
| 904 RenderObject* renderer = node->renderer(); | |
| 905 if (!renderer) | 886 if (!renderer) |
| 906 return false; | 887 return false; |
| 907 | 888 |
| 908 return renderer->style()->visibility() == VISIBLE; | 889 return renderer->style()->visibility() == VISIBLE; |
| 909 } | 890 } |
| 910 | 891 |
| 911 // return first preceding DOM position rendered at a different location, or "thi s" | 892 // return first preceding DOM position rendered at a different location, or "thi s" |
| 912 static Position previousCharacterPosition(const Position& position, EAffinity af finity) | 893 static Position previousCharacterPosition(const Position& position, EAffinity af finity) |
| 913 { | 894 { |
| 914 if (position.isNull()) | 895 if (position.isNull()) |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1124 if (!scope) | 1105 if (!scope) |
| 1125 return VisiblePosition(); | 1106 return VisiblePosition(); |
| 1126 RefPtrWillBeRawPtr<Range> range = PlainTextRange(index).createRangeForSelect ion(*scope); | 1107 RefPtrWillBeRawPtr<Range> range = PlainTextRange(index).createRangeForSelect ion(*scope); |
| 1127 // Check for an invalid index. Certain editing operations invalidate indices because | 1108 // Check for an invalid index. Certain editing operations invalidate indices because |
| 1128 // of problems with TextIteratorEmitsCharactersBetweenAllVisiblePositions. | 1109 // of problems with TextIteratorEmitsCharactersBetweenAllVisiblePositions. |
| 1129 if (!range) | 1110 if (!range) |
| 1130 return VisiblePosition(); | 1111 return VisiblePosition(); |
| 1131 return VisiblePosition(range->startPosition()); | 1112 return VisiblePosition(range->startPosition()); |
| 1132 } | 1113 } |
| 1133 | 1114 |
| 1134 // Determines whether two positions are visibly next to each other (first then s econd) | |
| 1135 // while ignoring whitespaces and unrendered nodes | |
| 1136 bool isVisiblyAdjacent(const Position& first, const Position& second) | |
| 1137 { | |
| 1138 return VisiblePosition(first) == VisiblePosition(second.upstream()); | |
| 1139 } | |
| 1140 | |
| 1141 // Determines whether a node is inside a range or visibly starts and ends at the boundaries of the range. | 1115 // Determines whether a node is inside a range or visibly starts and ends at the boundaries of the range. |
| 1142 // Call this function to determine whether a node is visibly fit inside selected Range | 1116 // Call this function to determine whether a node is visibly fit inside selected Range |
| 1143 bool isNodeVisiblyContainedWithin(Node& node, const Range& selectedRange) | 1117 bool isNodeVisiblyContainedWithin(Node& node, const Range& selectedRange) |
| 1144 { | 1118 { |
| 1145 // If the node is inside the range, then it surely is contained within | 1119 // If the node is inside the range, then it surely is contained within |
| 1146 if (selectedRange.compareNode(&node, IGNORE_EXCEPTION) == Range::NODE_INSIDE ) | 1120 if (selectedRange.compareNode(&node, IGNORE_EXCEPTION) == Range::NODE_INSIDE ) |
| 1147 return true; | 1121 return true; |
| 1148 | 1122 |
| 1149 bool startIsVisuallySame = visiblePositionBeforeNode(node) == VisiblePositio n(selectedRange.startPosition()); | 1123 bool startIsVisuallySame = visiblePositionBeforeNode(node) == VisiblePositio n(selectedRange.startPosition()); |
| 1150 if (startIsVisuallySame && comparePositions(positionInParentAfterNode(node), selectedRange.endPosition()) < 0) | 1124 if (startIsVisuallySame && comparePositions(positionInParentAfterNode(node), selectedRange.endPosition()) < 0) |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1222 // if the selection starts just before a paragraph break, skip over it | 1196 // if the selection starts just before a paragraph break, skip over it |
| 1223 if (isEndOfParagraph(visiblePosition)) | 1197 if (isEndOfParagraph(visiblePosition)) |
| 1224 return visiblePosition.next().deepEquivalent().downstream(); | 1198 return visiblePosition.next().deepEquivalent().downstream(); |
| 1225 | 1199 |
| 1226 // otherwise, make sure to be at the start of the first selected node, | 1200 // otherwise, make sure to be at the start of the first selected node, |
| 1227 // instead of possibly at the end of the last node before the selection | 1201 // instead of possibly at the end of the last node before the selection |
| 1228 return visiblePosition.deepEquivalent().downstream(); | 1202 return visiblePosition.deepEquivalent().downstream(); |
| 1229 } | 1203 } |
| 1230 | 1204 |
| 1231 } // namespace blink | 1205 } // namespace blink |
| OLD | NEW |