Home | History | Annotate | Download | only in dom
      1 /*
      2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #ifndef RangeBoundaryPoint_h
     27 #define RangeBoundaryPoint_h
     28 
     29 #include "Node.h"
     30 #include "Position.h"
     31 
     32 namespace WebCore {
     33 
     34 class RangeBoundaryPoint {
     35 public:
     36     explicit RangeBoundaryPoint(PassRefPtr<Node> container);
     37 
     38     const Position toPosition() const;
     39 
     40     Node* container() const;
     41     int offset() const;
     42     Node* childBefore() const;
     43 
     44     void clear();
     45 
     46     void set(PassRefPtr<Node> container, int offset, Node* childBefore);
     47     void setOffset(int offset);
     48 
     49     void setToBeforeChild(Node*);
     50     void setToStartOfNode(PassRefPtr<Node>);
     51     void setToEndOfNode(PassRefPtr<Node>);
     52 
     53     void childBeforeWillBeRemoved();
     54     void invalidateOffset() const;
     55     void ensureOffsetIsValid() const;
     56 
     57 private:
     58     static const int invalidOffset = -1;
     59 
     60     RefPtr<Node> m_containerNode;
     61     mutable int m_offsetInContainer;
     62     Node* m_childBeforeBoundary;
     63 };
     64 
     65 inline RangeBoundaryPoint::RangeBoundaryPoint(PassRefPtr<Node> container)
     66     : m_containerNode(container)
     67     , m_offsetInContainer(0)
     68     , m_childBeforeBoundary(0)
     69 {
     70     ASSERT(m_containerNode);
     71 }
     72 
     73 inline Node* RangeBoundaryPoint::container() const
     74 {
     75     return m_containerNode.get();
     76 }
     77 
     78 inline Node* RangeBoundaryPoint::childBefore() const
     79 {
     80     return m_childBeforeBoundary;
     81 }
     82 
     83 inline void RangeBoundaryPoint::ensureOffsetIsValid() const
     84 {
     85     if (m_offsetInContainer >= 0)
     86         return;
     87 
     88     ASSERT(m_childBeforeBoundary);
     89     m_offsetInContainer = m_childBeforeBoundary->nodeIndex() + 1;
     90 }
     91 
     92 inline const Position RangeBoundaryPoint::toPosition() const
     93 {
     94     ensureOffsetIsValid();
     95     return Position(m_containerNode.get(), m_offsetInContainer);
     96 }
     97 
     98 inline int RangeBoundaryPoint::offset() const
     99 {
    100     ensureOffsetIsValid();
    101     return m_offsetInContainer;
    102 }
    103 
    104 inline void RangeBoundaryPoint::clear()
    105 {
    106     m_containerNode.clear();
    107     m_offsetInContainer = 0;
    108     m_childBeforeBoundary = 0;
    109 }
    110 
    111 inline void RangeBoundaryPoint::set(PassRefPtr<Node> container, int offset, Node* childBefore)
    112 {
    113     ASSERT(container);
    114     ASSERT(offset >= 0);
    115     ASSERT(childBefore == (offset ? container->childNode(offset - 1) : 0));
    116     m_containerNode = container;
    117     m_offsetInContainer = offset;
    118     m_childBeforeBoundary = childBefore;
    119 }
    120 
    121 inline void RangeBoundaryPoint::setOffset(int offset)
    122 {
    123     ASSERT(m_containerNode);
    124     ASSERT(m_containerNode->offsetInCharacters());
    125     ASSERT(m_offsetInContainer >= 0);
    126     ASSERT(!m_childBeforeBoundary);
    127     m_offsetInContainer = offset;
    128 }
    129 
    130 inline void RangeBoundaryPoint::setToBeforeChild(Node* child)
    131 {
    132     ASSERT(child);
    133     ASSERT(child->parentNode());
    134     m_childBeforeBoundary = child->previousSibling();
    135     m_containerNode = child->parentNode();
    136     m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0;
    137 }
    138 
    139 inline void RangeBoundaryPoint::setToStartOfNode(PassRefPtr<Node> container)
    140 {
    141     ASSERT(container);
    142     m_containerNode = container;
    143     m_offsetInContainer = 0;
    144     m_childBeforeBoundary = 0;
    145 }
    146 
    147 inline void RangeBoundaryPoint::setToEndOfNode(PassRefPtr<Node> container)
    148 {
    149     ASSERT(container);
    150     m_containerNode = container;
    151     if (m_containerNode->offsetInCharacters()) {
    152         m_offsetInContainer = m_containerNode->maxCharacterOffset();
    153         m_childBeforeBoundary = 0;
    154     } else {
    155         m_childBeforeBoundary = m_containerNode->lastChild();
    156         m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0;
    157     }
    158 }
    159 
    160 inline void RangeBoundaryPoint::childBeforeWillBeRemoved()
    161 {
    162     ASSERT(m_offsetInContainer);
    163     m_childBeforeBoundary = m_childBeforeBoundary->previousSibling();
    164     if (!m_childBeforeBoundary)
    165         m_offsetInContainer = 0;
    166     else if (m_offsetInContainer > 0)
    167         --m_offsetInContainer;
    168 }
    169 
    170 inline void RangeBoundaryPoint::invalidateOffset() const
    171 {
    172     m_offsetInContainer = invalidOffset;
    173 }
    174 
    175 inline bool operator==(const RangeBoundaryPoint& a, const RangeBoundaryPoint& b)
    176 {
    177     if (a.container() != b.container())
    178         return false;
    179     if (a.childBefore() || b.childBefore()) {
    180         if (a.childBefore() != b.childBefore())
    181             return false;
    182     } else {
    183         if (a.offset() != b.offset())
    184             return false;
    185     }
    186     return true;
    187 }
    188 
    189 }
    190 
    191 #endif
    192