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