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