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) |
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 |