1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 1999 Antti Koivisto (koivisto (at) kde.org) 4 * (C) 2001 Dirk Mueller (mueller (at) 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 Node* previousSkippingChildrenPostOrder(const Node& current, const Node* stayWithin) 164 { 165 if (current == stayWithin) 166 return 0; 167 if (current.previousSibling()) 168 return current.previousSibling(); 169 return previousAncestorSiblingPostOrder(current, stayWithin); 170 } 171 172 } 173 } 174