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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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/html/HTMLBRElement.h" | 47 #include "core/html/HTMLBRElement.h" |
48 #include "core/html/HTMLDivElement.h" | 48 #include "core/html/HTMLDivElement.h" |
49 #include "core/html/HTMLLIElement.h" | 49 #include "core/html/HTMLLIElement.h" |
50 #include "core/html/HTMLOListElement.h" | 50 #include "core/html/HTMLOListElement.h" |
51 #include "core/html/HTMLParagraphElement.h" | 51 #include "core/html/HTMLParagraphElement.h" |
| 52 #include "core/html/HTMLTableCellElement.h" |
52 #include "core/html/HTMLUListElement.h" | 53 #include "core/html/HTMLUListElement.h" |
53 #include "core/rendering/RenderObject.h" | 54 #include "core/rendering/RenderObject.h" |
54 #include "wtf/Assertions.h" | 55 #include "wtf/Assertions.h" |
55 #include "wtf/StdLibExtras.h" | 56 #include "wtf/StdLibExtras.h" |
56 #include "wtf/text/StringBuilder.h" | 57 #include "wtf/text/StringBuilder.h" |
57 | 58 |
58 using namespace std; | 59 using namespace std; |
59 | 60 |
60 namespace WebCore { | 61 namespace WebCore { |
61 | 62 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 Node* highestEditableRoot(const Position& position, EditableType editableType) | 116 Node* highestEditableRoot(const Position& position, EditableType editableType) |
116 { | 117 { |
117 Node* node = position.deprecatedNode(); | 118 Node* node = position.deprecatedNode(); |
118 if (!node) | 119 if (!node) |
119 return 0; | 120 return 0; |
120 | 121 |
121 Node* highestRoot = editableRootForPosition(position, editableType); | 122 Node* highestRoot = editableRootForPosition(position, editableType); |
122 if (!highestRoot) | 123 if (!highestRoot) |
123 return 0; | 124 return 0; |
124 | 125 |
125 if (highestRoot->hasTagName(bodyTag)) | 126 if (isHTMLBodyElement(*highestRoot)) |
126 return highestRoot; | 127 return highestRoot; |
127 | 128 |
128 node = highestRoot->parentNode(); | 129 node = highestRoot->parentNode(); |
129 while (node) { | 130 while (node) { |
130 if (node->rendererIsEditable(editableType)) | 131 if (node->rendererIsEditable(editableType)) |
131 highestRoot = node; | 132 highestRoot = node; |
132 if (node->hasTagName(bodyTag)) | 133 if (isHTMLBodyElement(*node)) |
133 break; | 134 break; |
134 node = node->parentNode(); | 135 node = node->parentNode(); |
135 } | 136 } |
136 | 137 |
137 return highestRoot; | 138 return highestRoot; |
138 } | 139 } |
139 | 140 |
140 Node* lowestEditableAncestor(Node* node) | 141 Node* lowestEditableAncestor(Node* node) |
141 { | 142 { |
142 while (node) { | 143 while (node) { |
143 if (node->rendererIsEditable()) | 144 if (node->rendererIsEditable()) |
144 return node->rootEditableElement(); | 145 return node->rootEditableElement(); |
145 if (node->hasTagName(bodyTag)) | 146 if (isHTMLBodyElement(*node)) |
146 break; | 147 break; |
147 node = node->parentNode(); | 148 node = node->parentNode(); |
148 } | 149 } |
149 | 150 |
150 return 0; | 151 return 0; |
151 } | 152 } |
152 | 153 |
153 bool isEditablePosition(const Position& p, EditableType editableType, EUpdateSty
le updateStyle) | 154 bool isEditablePosition(const Position& p, EditableType editableType, EUpdateSty
le updateStyle) |
154 { | 155 { |
155 Node* node = p.deprecatedNode(); | 156 Node* node = p.deprecatedNode(); |
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
526 // Use this function instead of create a regular range object (avoiding editing
offset). | 527 // Use this function instead of create a regular range object (avoiding editing
offset). |
527 PassRefPtr<Range> createRange(Document& document, const VisiblePosition& start,
const VisiblePosition& end, ExceptionState& exceptionState) | 528 PassRefPtr<Range> createRange(Document& document, const VisiblePosition& start,
const VisiblePosition& end, ExceptionState& exceptionState) |
528 { | 529 { |
529 RefPtr<Range> selectedRange = Range::create(document); | 530 RefPtr<Range> selectedRange = Range::create(document); |
530 selectedRange->setStart(start.deepEquivalent().containerNode(), start.deepEq
uivalent().computeOffsetInContainerNode(), exceptionState); | 531 selectedRange->setStart(start.deepEquivalent().containerNode(), start.deepEq
uivalent().computeOffsetInContainerNode(), exceptionState); |
531 if (!exceptionState.hadException()) | 532 if (!exceptionState.hadException()) |
532 selectedRange->setEnd(end.deepEquivalent().containerNode(), end.deepEqui
valent().computeOffsetInContainerNode(), exceptionState); | 533 selectedRange->setEnd(end.deepEquivalent().containerNode(), end.deepEqui
valent().computeOffsetInContainerNode(), exceptionState); |
533 return selectedRange.release(); | 534 return selectedRange.release(); |
534 } | 535 } |
535 | 536 |
536 bool isListElement(Node *n) | 537 bool isListElement(Node* n) |
537 { | 538 { |
538 return (n && (n->hasTagName(ulTag) || n->hasTagName(olTag) || n->hasTagName(
dlTag))); | 539 return (n && (isHTMLUListElement(*n) || isHTMLOListElement(*n) || isHTMLDLis
tElement(*n))); |
539 } | 540 } |
540 | 541 |
541 bool isListItem(const Node *n) | 542 bool isListItem(const Node* n) |
542 { | 543 { |
543 return n && n->renderer() && n->renderer()->isListItem(); | 544 return n && n->renderer() && n->renderer()->isListItem(); |
544 } | 545 } |
545 | 546 |
546 Node* enclosingNodeWithTag(const Position& p, const QualifiedName& tagName) | 547 Node* enclosingNodeWithTag(const Position& p, const QualifiedName& tagName) |
547 { | 548 { |
548 if (p.isNull()) | 549 if (p.isNull()) |
549 return 0; | 550 return 0; |
550 | 551 |
551 Node* root = highestEditableRoot(p); | 552 Node* root = highestEditableRoot(p); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
644 } | 645 } |
645 | 646 |
646 HTMLElement* enclosingList(Node* node) | 647 HTMLElement* enclosingList(Node* node) |
647 { | 648 { |
648 if (!node) | 649 if (!node) |
649 return 0; | 650 return 0; |
650 | 651 |
651 Node* root = highestEditableRoot(firstPositionInOrBeforeNode(node)); | 652 Node* root = highestEditableRoot(firstPositionInOrBeforeNode(node)); |
652 | 653 |
653 for (ContainerNode* n = node->parentNode(); n; n = n->parentNode()) { | 654 for (ContainerNode* n = node->parentNode(); n; n = n->parentNode()) { |
654 if (n->hasTagName(ulTag) || n->hasTagName(olTag)) | 655 if (isHTMLUListElement(*n) || isHTMLOListElement(*n)) |
655 return toHTMLElement(n); | 656 return toHTMLElement(n); |
656 if (n == root) | 657 if (n == root) |
657 return 0; | 658 return 0; |
658 } | 659 } |
659 | 660 |
660 return 0; | 661 return 0; |
661 } | 662 } |
662 | 663 |
663 Node* enclosingListChild(Node *node) | 664 Node* enclosingListChild(Node *node) |
664 { | 665 { |
665 if (!node) | 666 if (!node) |
666 return 0; | 667 return 0; |
667 // Check for a list item element, or for a node whose parent is a list eleme
nt. Such a node | 668 // Check for a list item element, or for a node whose parent is a list eleme
nt. Such a node |
668 // will appear visually as a list item (but without a list marker) | 669 // will appear visually as a list item (but without a list marker) |
669 Node* root = highestEditableRoot(firstPositionInOrBeforeNode(node)); | 670 Node* root = highestEditableRoot(firstPositionInOrBeforeNode(node)); |
670 | 671 |
671 // FIXME: This function is inappropriately named if it starts with node inst
ead of node->parentNode() | 672 // FIXME: This function is inappropriately named if it starts with node inst
ead of node->parentNode() |
672 for (Node* n = node; n && n->parentNode(); n = n->parentNode()) { | 673 for (Node* n = node; n && n->parentNode(); n = n->parentNode()) { |
673 if (n->hasTagName(liTag) || (isListElement(n->parentNode()) && n != root
)) | 674 if (isHTMLLIElement(*n) || (isListElement(n->parentNode()) && n != root)
) |
674 return n; | 675 return n; |
675 if (n == root || isTableCell(n)) | 676 if (n == root || isTableCell(n)) |
676 return 0; | 677 return 0; |
677 } | 678 } |
678 | 679 |
679 return 0; | 680 return 0; |
680 } | 681 } |
681 | 682 |
682 // FIXME: This method should not need to call isStartOfParagraph/isEndOfParagrap
h | 683 // FIXME: This method should not need to call isStartOfParagraph/isEndOfParagrap
h |
683 Node* enclosingEmptyListItem(const VisiblePosition& visiblePos) | 684 Node* enclosingEmptyListItem(const VisiblePosition& visiblePos) |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
718 | 719 |
719 return firstList->hasTagName(secondList->tagQName()) // make sure the list t
ypes match (ol vs. ul) | 720 return firstList->hasTagName(secondList->tagQName()) // make sure the list t
ypes match (ol vs. ul) |
720 && firstList->rendererIsEditable() && secondList->rendererIsEditable() // bo
th lists are editable | 721 && firstList->rendererIsEditable() && secondList->rendererIsEditable() // bo
th lists are editable |
721 && firstList->rootEditableElement() == secondList->rootEditableElement() //
don't cross editing boundaries | 722 && firstList->rootEditableElement() == secondList->rootEditableElement() //
don't cross editing boundaries |
722 && isVisiblyAdjacent(positionInParentAfterNode(*firstList), positionInParent
BeforeNode(*secondList)); | 723 && isVisiblyAdjacent(positionInParentAfterNode(*firstList), positionInParent
BeforeNode(*secondList)); |
723 // Make sure there is no visible content between this li and the previous li
st | 724 // Make sure there is no visible content between this li and the previous li
st |
724 } | 725 } |
725 | 726 |
726 bool isRenderedTableElement(const Node* node) | 727 bool isRenderedTableElement(const Node* node) |
727 { | 728 { |
728 if (!node || !node->isElementNode()) | 729 return isHTMLTableElement(*node) && node->renderer(); |
729 return false; | |
730 | |
731 return node->renderer() && node->hasTagName(tableTag); | |
732 } | 730 } |
733 | 731 |
734 bool isRenderedTable(const Node* node) | 732 bool isRenderedTable(const Node* node) |
735 { | 733 { |
736 if (!node || !node->isElementNode()) | 734 if (!node || !node->isElementNode()) |
737 return false; | 735 return false; |
738 | 736 |
739 RenderObject* renderer = node->renderer(); | 737 RenderObject* renderer = node->renderer(); |
740 return (renderer && renderer->isTable()); | 738 return (renderer && renderer->isTable()); |
741 } | 739 } |
742 | 740 |
743 bool isTableCell(const Node* node) | 741 bool isTableCell(const Node* node) |
744 { | 742 { |
| 743 ASSERT(node); |
745 RenderObject* r = node->renderer(); | 744 RenderObject* r = node->renderer(); |
746 if (!r) | 745 return r ? r->isTableCell() : isHTMLTableCellElement(*node); |
747 return node->hasTagName(tdTag) || node->hasTagName(thTag); | |
748 | |
749 return r->isTableCell(); | |
750 } | 746 } |
751 | 747 |
752 bool isEmptyTableCell(const Node* node) | 748 bool isEmptyTableCell(const Node* node) |
753 { | 749 { |
754 // Returns true IFF the passed in node is one of: | 750 // Returns true IFF the passed in node is one of: |
755 // .) a table cell with no children, | 751 // .) a table cell with no children, |
756 // .) a table cell with a single BR child, and which has no other child re
nderers, including :before and :after renderers | 752 // .) a table cell with a single BR child, and which has no other child re
nderers, including :before and :after renderers |
757 // .) the BR child of such a table cell | 753 // .) the BR child of such a table cell |
758 | 754 |
759 // Find rendered node | 755 // Find rendered node |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
818 PassRefPtr<HTMLElement> createHTMLElement(Document& document, const QualifiedNam
e& name) | 814 PassRefPtr<HTMLElement> createHTMLElement(Document& document, const QualifiedNam
e& name) |
819 { | 815 { |
820 return createHTMLElement(document, name.localName()); | 816 return createHTMLElement(document, name.localName()); |
821 } | 817 } |
822 | 818 |
823 PassRefPtr<HTMLElement> createHTMLElement(Document& document, const AtomicString
& tagName) | 819 PassRefPtr<HTMLElement> createHTMLElement(Document& document, const AtomicString
& tagName) |
824 { | 820 { |
825 return HTMLElementFactory::createHTMLElement(tagName, document, 0, false); | 821 return HTMLElementFactory::createHTMLElement(tagName, document, 0, false); |
826 } | 822 } |
827 | 823 |
828 bool isTabSpanNode(const Node *node) | 824 bool isTabSpanNode(const Node* node) |
829 { | 825 { |
830 return node && node->hasTagName(spanTag) && node->isElementNode() && toEleme
nt(node)->getAttribute(classAttr) == AppleTabSpanClass; | 826 return isHTMLSpanElement(node) && toElement(node)->getAttribute(classAttr) =
= AppleTabSpanClass; |
831 } | 827 } |
832 | 828 |
833 bool isTabSpanTextNode(const Node *node) | 829 bool isTabSpanTextNode(const Node* node) |
834 { | 830 { |
835 return node && node->isTextNode() && node->parentNode() && isTabSpanNode(nod
e->parentNode()); | 831 return node && node->isTextNode() && node->parentNode() && isTabSpanNode(nod
e->parentNode()); |
836 } | 832 } |
837 | 833 |
838 Node* tabSpanNode(const Node *node) | 834 Node* tabSpanNode(const Node* node) |
839 { | 835 { |
840 return isTabSpanTextNode(node) ? node->parentNode() : 0; | 836 return isTabSpanTextNode(node) ? node->parentNode() : 0; |
841 } | 837 } |
842 | 838 |
843 PassRefPtr<Element> createTabSpanElement(Document& document, PassRefPtr<Node> pr
pTabTextNode) | 839 PassRefPtr<Element> createTabSpanElement(Document& document, PassRefPtr<Node> pr
pTabTextNode) |
844 { | 840 { |
845 RefPtr<Node> tabTextNode = prpTabTextNode; | 841 RefPtr<Node> tabTextNode = prpTabTextNode; |
846 | 842 |
847 // Make the span to hold the tab. | 843 // Make the span to hold the tab. |
848 RefPtr<Element> spanElement = document.createElement(spanTag, false); | 844 RefPtr<Element> spanElement = document.createElement(spanTag, false); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
949 bool lineBreakExistsAtVisiblePosition(const VisiblePosition& visiblePosition) | 945 bool lineBreakExistsAtVisiblePosition(const VisiblePosition& visiblePosition) |
950 { | 946 { |
951 return lineBreakExistsAtPosition(visiblePosition.deepEquivalent().downstream
()); | 947 return lineBreakExistsAtPosition(visiblePosition.deepEquivalent().downstream
()); |
952 } | 948 } |
953 | 949 |
954 bool lineBreakExistsAtPosition(const Position& position) | 950 bool lineBreakExistsAtPosition(const Position& position) |
955 { | 951 { |
956 if (position.isNull()) | 952 if (position.isNull()) |
957 return false; | 953 return false; |
958 | 954 |
959 if (position.anchorNode()->hasTagName(brTag) && position.atFirstEditingPosit
ionForNode()) | 955 if (isHTMLBRElement(*position.anchorNode()) && position.atFirstEditingPositi
onForNode()) |
960 return true; | 956 return true; |
961 | 957 |
962 if (!position.anchorNode()->renderer()) | 958 if (!position.anchorNode()->renderer()) |
963 return false; | 959 return false; |
964 | 960 |
965 if (!position.anchorNode()->isTextNode() || !position.anchorNode()->renderer
()->style()->preserveNewline()) | 961 if (!position.anchorNode()->isTextNode() || !position.anchorNode()->renderer
()->style()->preserveNewline()) |
966 return false; | 962 return false; |
967 | 963 |
968 Text* textNode = toText(position.anchorNode()); | 964 Text* textNode = toText(position.anchorNode()); |
969 unsigned offset = position.offsetInContainerNode(); | 965 unsigned offset = position.offsetInContainerNode(); |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1116 // if the selection starts just before a paragraph break, skip over it | 1112 // if the selection starts just before a paragraph break, skip over it |
1117 if (isEndOfParagraph(visiblePosition)) | 1113 if (isEndOfParagraph(visiblePosition)) |
1118 return visiblePosition.next().deepEquivalent().downstream(); | 1114 return visiblePosition.next().deepEquivalent().downstream(); |
1119 | 1115 |
1120 // otherwise, make sure to be at the start of the first selected node, | 1116 // otherwise, make sure to be at the start of the first selected node, |
1121 // instead of possibly at the end of the last node before the selection | 1117 // instead of possibly at the end of the last node before the selection |
1122 return visiblePosition.deepEquivalent().downstream(); | 1118 return visiblePosition.deepEquivalent().downstream(); |
1123 } | 1119 } |
1124 | 1120 |
1125 } // namespace WebCore | 1121 } // namespace WebCore |
OLD | NEW |