blob: 34328d65479d94e827eb3b8d545dc77dd3e3525b [file] [log] [blame]
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001/*
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
Ben Murdoch02772c62013-07-26 10:21:05 +010023 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010024 */
25
26#include "config.h"
27#include "core/dom/PositionIterator.h"
28
29#include "HTMLNames.h"
30#include "core/dom/Node.h"
31#include "core/editing/htmlediting.h"
Ben Murdoche69819b2013-07-17 14:56:49 +010032#include "core/html/HTMLHtmlElement.h"
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010033#include "core/rendering/RenderBlock.h"
34
35namespace WebCore {
36
37using namespace HTMLNames;
38
39PositionIterator::operator Position() const
40{
41 if (m_nodeAfterPositionInAnchor) {
42 ASSERT(m_nodeAfterPositionInAnchor->parentNode() == m_anchorNode);
43 // FIXME: This check is inadaquete because any ancestor could be ignored by editing
44 if (editingIgnoresContent(m_nodeAfterPositionInAnchor->parentNode()))
45 return positionBeforeNode(m_anchorNode);
46 return positionInParentBeforeNode(m_nodeAfterPositionInAnchor);
47 }
48 if (m_anchorNode->hasChildNodes())
49 return lastPositionInOrAfterNode(m_anchorNode);
50 return createLegacyEditingPosition(m_anchorNode, m_offsetInAnchor);
51}
52
53void PositionIterator::increment()
54{
55 if (!m_anchorNode)
56 return;
57
58 if (m_nodeAfterPositionInAnchor) {
59 m_anchorNode = m_nodeAfterPositionInAnchor;
60 m_nodeAfterPositionInAnchor = m_anchorNode->firstChild();
61 m_offsetInAnchor = 0;
62 return;
63 }
64
65 if (!m_anchorNode->hasChildNodes() && m_offsetInAnchor < lastOffsetForEditing(m_anchorNode))
66 m_offsetInAnchor = Position::uncheckedNextOffset(m_anchorNode, m_offsetInAnchor);
67 else {
68 m_nodeAfterPositionInAnchor = m_anchorNode;
69 m_anchorNode = m_nodeAfterPositionInAnchor->parentNode();
70 m_nodeAfterPositionInAnchor = m_nodeAfterPositionInAnchor->nextSibling();
71 m_offsetInAnchor = 0;
72 }
73}
74
75void PositionIterator::decrement()
76{
77 if (!m_anchorNode)
78 return;
79
80 if (m_nodeAfterPositionInAnchor) {
81 m_anchorNode = m_nodeAfterPositionInAnchor->previousSibling();
82 if (m_anchorNode) {
83 m_nodeAfterPositionInAnchor = 0;
84 m_offsetInAnchor = m_anchorNode->hasChildNodes() ? 0 : lastOffsetForEditing(m_anchorNode);
85 } else {
86 m_nodeAfterPositionInAnchor = m_nodeAfterPositionInAnchor->parentNode();
87 m_anchorNode = m_nodeAfterPositionInAnchor->parentNode();
88 m_offsetInAnchor = 0;
89 }
90 return;
91 }
Ben Murdoch02772c62013-07-26 10:21:05 +010092
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010093 if (m_anchorNode->hasChildNodes()) {
94 m_anchorNode = m_anchorNode->lastChild();
95 m_offsetInAnchor = m_anchorNode->hasChildNodes()? 0: lastOffsetForEditing(m_anchorNode);
96 } else {
97 if (m_offsetInAnchor)
98 m_offsetInAnchor = Position::uncheckedPreviousOffset(m_anchorNode, m_offsetInAnchor);
99 else {
100 m_nodeAfterPositionInAnchor = m_anchorNode;
101 m_anchorNode = m_anchorNode->parentNode();
102 }
103 }
104}
105
106bool PositionIterator::atStart() const
107{
108 if (!m_anchorNode)
109 return true;
110 if (m_anchorNode->parentNode())
111 return false;
112 return (!m_anchorNode->hasChildNodes() && !m_offsetInAnchor) || (m_nodeAfterPositionInAnchor && !m_nodeAfterPositionInAnchor->previousSibling());
113}
114
115bool PositionIterator::atEnd() const
116{
117 if (!m_anchorNode)
118 return true;
119 if (m_nodeAfterPositionInAnchor)
120 return false;
121 return !m_anchorNode->parentNode() && (m_anchorNode->hasChildNodes() || m_offsetInAnchor >= lastOffsetForEditing(m_anchorNode));
122}
123
124bool PositionIterator::atStartOfNode() const
125{
126 if (!m_anchorNode)
127 return true;
128 if (!m_nodeAfterPositionInAnchor)
129 return !m_anchorNode->hasChildNodes() && !m_offsetInAnchor;
130 return !m_nodeAfterPositionInAnchor->previousSibling();
131}
132
133bool PositionIterator::atEndOfNode() const
134{
135 if (!m_anchorNode)
136 return true;
137 if (m_nodeAfterPositionInAnchor)
138 return false;
139 return m_anchorNode->hasChildNodes() || m_offsetInAnchor >= lastOffsetForEditing(m_anchorNode);
140}
141
142bool PositionIterator::isCandidate() const
143{
144 if (!m_anchorNode)
145 return false;
146
147 RenderObject* renderer = m_anchorNode->renderer();
148 if (!renderer)
149 return false;
Ben Murdoch02772c62013-07-26 10:21:05 +0100150
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100151 if (renderer->style()->visibility() != VISIBLE)
152 return false;
153
154 if (renderer->isBR())
155 return !m_offsetInAnchor && !Position::nodeIsUserSelectNone(m_anchorNode->parentNode());
156
157 if (renderer->isText())
158 return !Position::nodeIsUserSelectNone(m_anchorNode) && Position(*this).inRenderedText();
159
160 if (isTableElement(m_anchorNode) || editingIgnoresContent(m_anchorNode))
161 return (atStartOfNode() || atEndOfNode()) && !Position::nodeIsUserSelectNone(m_anchorNode->parentNode());
162
Ben Murdoche69819b2013-07-17 14:56:49 +0100163 if (!isHTMLHtmlElement(m_anchorNode) && renderer->isBlockFlow()) {
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100164 if (toRenderBlock(renderer)->logicalHeight() || m_anchorNode->hasTagName(bodyTag)) {
165 if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(renderer))
166 return atStartOfNode() && !Position::nodeIsUserSelectNone(m_anchorNode);
167 return m_anchorNode->rendererIsEditable() && !Position::nodeIsUserSelectNone(m_anchorNode) && Position(*this).atEditingBoundary();
168 }
169 }
170
171 return false;
172}
173
174} // namespace WebCore