• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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/)
7  *
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.
12  *
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.
17  *
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.
22  *
23  */
24 
25 #include "config.h"
26 #include "core/dom/NodeTraversal.h"
27 
28 #include "core/dom/ContainerNode.h"
29 
30 namespace blink {
31 
previousIncludingPseudo(const Node & current,const Node * stayWithin)32 Node* NodeTraversal::previousIncludingPseudo(const Node& current, const Node* stayWithin)
33 {
34     if (current == stayWithin)
35         return 0;
36     if (Node* previous = current.pseudoAwarePreviousSibling()) {
37         while (previous->pseudoAwareLastChild())
38             previous = previous->pseudoAwareLastChild();
39         return previous;
40     }
41     return current.parentNode();
42 }
43 
nextIncludingPseudo(const Node & current,const Node * stayWithin)44 Node* NodeTraversal::nextIncludingPseudo(const Node& current, const Node* stayWithin)
45 {
46     if (Node* next = current.pseudoAwareFirstChild())
47         return next;
48     if (current == stayWithin)
49         return 0;
50     if (Node* next = current.pseudoAwareNextSibling())
51         return next;
52     for (Node* parent = current.parentNode(); parent; parent = parent->parentNode()) {
53         if (parent == stayWithin)
54             return 0;
55         if (Node* next = parent->pseudoAwareNextSibling())
56             return next;
57     }
58     return 0;
59 }
60 
nextIncludingPseudoSkippingChildren(const Node & current,const Node * stayWithin)61 Node* NodeTraversal::nextIncludingPseudoSkippingChildren(const Node& current, const Node* stayWithin)
62 {
63     if (current == stayWithin)
64         return 0;
65     if (Node* next = current.pseudoAwareNextSibling())
66         return next;
67     for (Node* parent = current.parentNode(); parent; parent = parent->parentNode()) {
68         if (parent == stayWithin)
69             return 0;
70         if (Node* next = parent->pseudoAwareNextSibling())
71             return next;
72     }
73     return 0;
74 }
75 
nextAncestorSibling(const Node & current)76 Node* NodeTraversal::nextAncestorSibling(const Node& current)
77 {
78     ASSERT(!current.nextSibling());
79     for (Node* parent = current.parentNode(); parent; parent = parent->parentNode()) {
80         if (parent->nextSibling())
81             return parent->nextSibling();
82     }
83     return 0;
84 }
85 
nextAncestorSibling(const Node & current,const Node * stayWithin)86 Node* NodeTraversal::nextAncestorSibling(const Node& current, const Node* stayWithin)
87 {
88     ASSERT(!current.nextSibling());
89     ASSERT(current != stayWithin);
90     for (Node* parent = current.parentNode(); parent; parent = parent->parentNode()) {
91         if (parent == stayWithin)
92             return 0;
93         if (parent->nextSibling())
94             return parent->nextSibling();
95     }
96     return 0;
97 }
98 
lastWithin(const ContainerNode & current)99 Node* NodeTraversal::lastWithin(const ContainerNode& current)
100 {
101     Node* descendant = current.lastChild();
102     for (Node* child = descendant; child; child = child->lastChild())
103         descendant = child;
104     return descendant;
105 }
106 
lastWithinOrSelf(Node & current)107 Node& NodeTraversal::lastWithinOrSelf(Node& current)
108 {
109     Node* lastDescendant = current.isContainerNode() ? NodeTraversal::lastWithin(toContainerNode(current)) : 0;
110     return lastDescendant ? *lastDescendant : current;
111 }
112 
previous(const Node & current,const Node * stayWithin)113 Node* NodeTraversal::previous(const Node& current, const Node* stayWithin)
114 {
115     if (current == stayWithin)
116         return 0;
117     if (current.previousSibling()) {
118         Node* previous = current.previousSibling();
119         while (Node* child = previous->lastChild())
120             previous = child;
121         return previous;
122     }
123     return current.parentNode();
124 }
125 
previousSkippingChildren(const Node & current,const Node * stayWithin)126 Node* NodeTraversal::previousSkippingChildren(const Node& current, const Node* stayWithin)
127 {
128     if (current == stayWithin)
129         return 0;
130     if (current.previousSibling())
131         return current.previousSibling();
132     for (Node* parent = current.parentNode(); parent; parent = parent->parentNode()) {
133         if (parent == stayWithin)
134             return 0;
135         if (parent->previousSibling())
136             return parent->previousSibling();
137     }
138     return 0;
139 }
140 
nextPostOrder(const Node & current,const Node * stayWithin)141 Node* NodeTraversal::nextPostOrder(const Node& current, const Node* stayWithin)
142 {
143     if (current == stayWithin)
144         return 0;
145     if (!current.nextSibling())
146         return current.parentNode();
147     Node* next = current.nextSibling();
148     while (Node* child = next->firstChild())
149         next = child;
150     return next;
151 }
152 
previousAncestorSiblingPostOrder(const Node & current,const Node * stayWithin)153 static Node* previousAncestorSiblingPostOrder(const Node& current, const Node* stayWithin)
154 {
155     ASSERT(!current.previousSibling());
156     for (Node* parent = current.parentNode(); parent; parent = parent->parentNode()) {
157         if (parent == stayWithin)
158             return 0;
159         if (parent->previousSibling())
160             return parent->previousSibling();
161     }
162     return 0;
163 }
164 
previousPostOrder(const Node & current,const Node * stayWithin)165 Node* NodeTraversal::previousPostOrder(const Node& current, const Node* stayWithin)
166 {
167     if (Node* lastChild = current.lastChild())
168         return lastChild;
169     if (current == stayWithin)
170         return 0;
171     if (current.previousSibling())
172         return current.previousSibling();
173     return previousAncestorSiblingPostOrder(current, stayWithin);
174 }
175 
176 } // namespace blink
177