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