2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
6 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
26 #include "core/dom/NodeTraversal.h"
28 #include "core/dom/ContainerNode.h"
29 #include "core/dom/Range.h"
33 Node
* NodeTraversal::previousIncludingPseudo(const Node
& current
, const Node
* stayWithin
)
35 if (current
== stayWithin
)
37 if (Node
* previous
= current
.pseudoAwarePreviousSibling()) {
38 while (previous
->pseudoAwareLastChild())
39 previous
= previous
->pseudoAwareLastChild();
42 return current
.parentNode();
45 Node
* NodeTraversal::nextIncludingPseudo(const Node
& current
, const Node
* stayWithin
)
47 if (Node
* next
= current
.pseudoAwareFirstChild())
49 if (current
== stayWithin
)
51 if (Node
* next
= current
.pseudoAwareNextSibling())
53 for (Node
* parent
= current
.parentNode(); parent
; parent
= parent
->parentNode()) {
54 if (parent
== stayWithin
)
56 if (Node
* next
= parent
->pseudoAwareNextSibling())
62 Node
* NodeTraversal::nextIncludingPseudoSkippingChildren(const Node
& current
, const Node
* stayWithin
)
64 if (current
== stayWithin
)
66 if (Node
* next
= current
.pseudoAwareNextSibling())
68 for (Node
* parent
= current
.parentNode(); parent
; parent
= parent
->parentNode()) {
69 if (parent
== stayWithin
)
71 if (Node
* next
= parent
->pseudoAwareNextSibling())
77 Node
* NodeTraversal::nextAncestorSibling(const Node
& current
)
79 ASSERT(!current
.nextSibling());
80 for (Node
* parent
= current
.parentNode(); parent
; parent
= parent
->parentNode()) {
81 if (parent
->nextSibling())
82 return parent
->nextSibling();
87 Node
* NodeTraversal::nextAncestorSibling(const Node
& current
, const Node
* stayWithin
)
89 ASSERT(!current
.nextSibling());
90 ASSERT(current
!= stayWithin
);
91 for (Node
* parent
= current
.parentNode(); parent
; parent
= parent
->parentNode()) {
92 if (parent
== stayWithin
)
94 if (parent
->nextSibling())
95 return parent
->nextSibling();
100 Node
* NodeTraversal::lastWithin(const ContainerNode
& current
)
102 Node
* descendant
= current
.lastChild();
103 for (Node
* child
= descendant
; child
; child
= child
->lastChild())
108 Node
& NodeTraversal::lastWithinOrSelf(Node
& current
)
110 Node
* lastDescendant
= current
.isContainerNode() ? NodeTraversal::lastWithin(toContainerNode(current
)) : 0;
111 return lastDescendant
? *lastDescendant
: current
;
114 Node
* NodeTraversal::previous(const Node
& current
, const Node
* stayWithin
)
116 if (current
== stayWithin
)
118 if (current
.previousSibling()) {
119 Node
* previous
= current
.previousSibling();
120 while (Node
* child
= previous
->lastChild())
124 return current
.parentNode();
127 Node
* NodeTraversal::previousSkippingChildren(const Node
& current
, const Node
* stayWithin
)
129 if (current
== stayWithin
)
131 if (current
.previousSibling())
132 return current
.previousSibling();
133 for (Node
* parent
= current
.parentNode(); parent
; parent
= parent
->parentNode()) {
134 if (parent
== stayWithin
)
136 if (parent
->previousSibling())
137 return parent
->previousSibling();
142 Node
* NodeTraversal::nextPostOrder(const Node
& current
, const Node
* stayWithin
)
144 if (current
== stayWithin
)
146 if (!current
.nextSibling())
147 return current
.parentNode();
148 Node
* next
= current
.nextSibling();
149 while (Node
* child
= next
->firstChild())
154 static Node
* previousAncestorSiblingPostOrder(const Node
& current
, const Node
* stayWithin
)
156 ASSERT(!current
.previousSibling());
157 for (Node
* parent
= current
.parentNode(); parent
; parent
= parent
->parentNode()) {
158 if (parent
== stayWithin
)
160 if (parent
->previousSibling())
161 return parent
->previousSibling();
166 Node
* NodeTraversal::previousPostOrder(const Node
& current
, const Node
* stayWithin
)
168 if (Node
* lastChild
= current
.lastChild())
170 if (current
== stayWithin
)
172 if (current
.previousSibling())
173 return current
.previousSibling();
174 return previousAncestorSiblingPostOrder(current
, stayWithin
);
177 Node
* NodeTraversal::commonAncestor(const Node
& nodeA
, const Node
& nodeB
)
179 return Range::commonAncestorContainer(&nodeA
, &nodeB
);