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