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