• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "config.h"
27 #include "PositionIterator.h"
28 
29 #include "Node.h"
30 #include "RenderBlock.h"
31 #include "htmlediting.h"
32 
33 namespace WebCore {
34 
35 using namespace HTMLNames;
36 
operator Position() const37 PositionIterator::operator Position() const
38 {
39     if (m_nodeAfterPositionInAnchor) {
40         ASSERT(m_nodeAfterPositionInAnchor->parentNode() == m_anchorNode);
41         return positionInParentBeforeNode(m_nodeAfterPositionInAnchor);
42     }
43     if (m_anchorNode->hasChildNodes())
44         return lastDeepEditingPositionForNode(m_anchorNode);
45     return Position(m_anchorNode, m_offsetInAnchor);
46 }
47 
increment()48 void PositionIterator::increment()
49 {
50     if (!m_anchorNode)
51         return;
52 
53     if (m_nodeAfterPositionInAnchor) {
54         m_anchorNode = m_nodeAfterPositionInAnchor;
55         m_nodeAfterPositionInAnchor = m_anchorNode->firstChild();
56         m_offsetInAnchor = 0;
57         return;
58     }
59 
60     if (!m_anchorNode->hasChildNodes() && m_offsetInAnchor < lastOffsetForEditing(m_anchorNode))
61         m_offsetInAnchor = Position::uncheckedNextOffset(m_anchorNode, m_offsetInAnchor);
62     else {
63         m_nodeAfterPositionInAnchor = m_anchorNode;
64         m_anchorNode = m_nodeAfterPositionInAnchor->parentNode();
65         m_nodeAfterPositionInAnchor = m_nodeAfterPositionInAnchor->nextSibling();
66         m_offsetInAnchor = 0;
67     }
68 }
69 
decrement()70 void PositionIterator::decrement()
71 {
72     if (!m_anchorNode)
73         return;
74 
75     if (m_nodeAfterPositionInAnchor) {
76         m_anchorNode = m_nodeAfterPositionInAnchor->previousSibling();
77         if (m_anchorNode) {
78             m_nodeAfterPositionInAnchor = 0;
79             m_offsetInAnchor = m_anchorNode->hasChildNodes() ? 0 : lastOffsetForEditing(m_anchorNode);
80         } else {
81             m_nodeAfterPositionInAnchor = m_nodeAfterPositionInAnchor->parentNode();
82             m_anchorNode = m_nodeAfterPositionInAnchor->parentNode();
83             m_offsetInAnchor = 0;
84         }
85         return;
86     }
87 
88     if (m_offsetInAnchor) {
89         m_offsetInAnchor = Position::uncheckedPreviousOffset(m_anchorNode, m_offsetInAnchor);
90     } else {
91         if (m_anchorNode->hasChildNodes()) {
92             m_anchorNode = m_anchorNode->lastChild();
93             if (!m_anchorNode->hasChildNodes())
94                 m_offsetInAnchor = lastOffsetForEditing(m_anchorNode);
95         } else {
96             m_nodeAfterPositionInAnchor = m_anchorNode;
97             m_anchorNode = m_anchorNode->parentNode();
98         }
99     }
100 }
101 
atStart() const102 bool PositionIterator::atStart() const
103 {
104     if (!m_anchorNode)
105         return true;
106     if (m_anchorNode->parentNode())
107         return false;
108     return (!m_anchorNode->hasChildNodes() && !m_offsetInAnchor) || (m_nodeAfterPositionInAnchor && !m_nodeAfterPositionInAnchor->previousSibling());
109 }
110 
atEnd() const111 bool PositionIterator::atEnd() const
112 {
113     if (!m_anchorNode)
114         return true;
115     if (m_nodeAfterPositionInAnchor)
116         return false;
117     return !m_anchorNode->parentNode() && (m_anchorNode->hasChildNodes() || m_offsetInAnchor >= lastOffsetForEditing(m_anchorNode));
118 }
119 
atStartOfNode() const120 bool PositionIterator::atStartOfNode() const
121 {
122     if (!m_anchorNode)
123         return true;
124     if (!m_nodeAfterPositionInAnchor)
125         return !m_anchorNode->hasChildNodes() && !m_offsetInAnchor;
126     return !m_nodeAfterPositionInAnchor->previousSibling();
127 }
128 
atEndOfNode() const129 bool PositionIterator::atEndOfNode() const
130 {
131     if (!m_anchorNode)
132         return true;
133     if (m_nodeAfterPositionInAnchor)
134         return false;
135     return m_anchorNode->hasChildNodes() || m_offsetInAnchor >= lastOffsetForEditing(m_anchorNode);
136 }
137 
isCandidate() const138 bool PositionIterator::isCandidate() const
139 {
140     if (!m_anchorNode)
141         return false;
142 
143     RenderObject* renderer = m_anchorNode->renderer();
144     if (!renderer)
145         return false;
146 
147     if (renderer->style()->visibility() != VISIBLE)
148         return false;
149 
150     if (renderer->isBR())
151         return !m_offsetInAnchor && !Position::nodeIsUserSelectNone(m_anchorNode->parent());
152 
153     if (renderer->isText())
154         return Position(*this).inRenderedText() && !Position::nodeIsUserSelectNone(m_anchorNode);
155 
156     if (isTableElement(m_anchorNode) || editingIgnoresContent(m_anchorNode))
157         return (atStartOfNode() || atEndOfNode()) && !Position::nodeIsUserSelectNone(m_anchorNode->parent());
158 
159     if (!m_anchorNode->hasTagName(htmlTag) && renderer->isBlockFlow()) {
160         if (toRenderBlock(renderer)->height() || m_anchorNode->hasTagName(bodyTag)) {
161             if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(renderer))
162                 return atStartOfNode() && !Position::nodeIsUserSelectNone(m_anchorNode);
163             return m_anchorNode->isContentEditable() && !Position::nodeIsUserSelectNone(m_anchorNode) && Position(*this).atEditingBoundary();
164         }
165     }
166 
167     return false;
168 }
169 
170 } // namespace WebCore
171