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 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