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