Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / dom / NodeTraversal.cpp
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 WebCore {
31 namespace NodeTraversal {
32
33 Node* previousIncludingPseudo(const Node& current, const Node* stayWithin)
34 {
35     if (current == stayWithin)
36         return 0;
37     if (Node* previous = current.pseudoAwarePreviousSibling()) {
38         while (previous->pseudoAwareLastChild())
39             previous = previous->pseudoAwareLastChild();
40         return previous;
41     }
42     return current.parentNode();
43 }
44
45 Node* nextIncludingPseudo(const Node& current, const Node* stayWithin)
46 {
47     if (Node* next = current.pseudoAwareFirstChild())
48         return next;
49     if (current == stayWithin)
50         return 0;
51     if (Node* next = current.pseudoAwareNextSibling())
52         return next;
53     for (Node* parent = current.parentNode(); parent; parent = parent->parentNode()) {
54         if (parent == stayWithin)
55             return 0;
56         if (Node* next = parent->pseudoAwareNextSibling())
57             return next;
58     }
59     return 0;
60 }
61
62 Node* nextIncludingPseudoSkippingChildren(const Node& current, const Node* stayWithin)
63 {
64     if (current == stayWithin)
65         return 0;
66     if (Node* next = current.pseudoAwareNextSibling())
67         return next;
68     for (Node* parent = current.parentNode(); parent; parent = parent->parentNode()) {
69         if (parent == stayWithin)
70             return 0;
71         if (Node* next = parent->pseudoAwareNextSibling())
72             return next;
73     }
74     return 0;
75 }
76
77 Node* nextAncestorSibling(const Node& current)
78 {
79     ASSERT(!current.nextSibling());
80     for (Node* parent = current.parentNode(); parent; parent = parent->parentNode()) {
81         if (parent->nextSibling())
82             return parent->nextSibling();
83     }
84     return 0;
85 }
86
87 Node* nextAncestorSibling(const Node& current, const Node* stayWithin)
88 {
89     ASSERT(!current.nextSibling());
90     ASSERT(current != stayWithin);
91     for (Node* parent = current.parentNode(); parent; parent = parent->parentNode()) {
92         if (parent == stayWithin)
93             return 0;
94         if (parent->nextSibling())
95             return parent->nextSibling();
96     }
97     return 0;
98 }
99
100 Node* previous(const Node& current, const Node* stayWithin)
101 {
102     if (current == stayWithin)
103         return 0;
104     if (current.previousSibling()) {
105         Node* previous = current.previousSibling();
106         while (previous->lastChild())
107             previous = previous->lastChild();
108         return previous;
109     }
110     return current.parentNode();
111 }
112
113 Node* previousSkippingChildren(const Node& current, const Node* stayWithin)
114 {
115     if (current == stayWithin)
116         return 0;
117     if (current.previousSibling())
118         return current.previousSibling();
119     for (Node* parent = current.parentNode(); parent; parent = parent->parentNode()) {
120         if (parent == stayWithin)
121             return 0;
122         if (parent->previousSibling())
123             return parent->previousSibling();
124     }
125     return 0;
126 }
127
128 Node* nextPostOrder(const Node& current, const Node* stayWithin)
129 {
130     if (current == stayWithin)
131         return 0;
132     if (!current.nextSibling())
133         return current.parentNode();
134     Node* next = current.nextSibling();
135     while (next->firstChild())
136         next = next->firstChild();
137     return next;
138 }
139
140 static Node* previousAncestorSiblingPostOrder(const Node& current, const Node* stayWithin)
141 {
142     ASSERT(!current.previousSibling());
143     for (Node* parent = current.parentNode(); parent; parent = parent->parentNode()) {
144         if (parent == stayWithin)
145             return 0;
146         if (parent->previousSibling())
147             return parent->previousSibling();
148     }
149     return 0;
150 }
151
152 Node* previousPostOrder(const Node& current, const Node* stayWithin)
153 {
154     if (current.lastChild())
155         return current.lastChild();
156     if (current == stayWithin)
157         return 0;
158     if (current.previousSibling())
159         return current.previousSibling();
160     return previousAncestorSiblingPostOrder(current, stayWithin);
161 }
162
163 }
164 }