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 "core/dom/Node.h"
     30 #include "core/dom/Position.h"
     31 
     32 namespace WebCore {
     33 
     34 class RangeBoundaryPoint {
     35 public:
     36     explicit RangeBoundaryPoint(PassRefPtr<Node> container);
     37 
     38     explicit RangeBoundaryPoint(const RangeBoundaryPoint&);
     39 
     40     const Position toPosition() const;
     41 
     42     Node* container() const;
     43     int offset() const;
     44     Node* childBefore() const;
     45 
     46     void clear();
     47 
     48     void set(PassRefPtr<Node> container, int offset, Node* childBefore);
     49     void setOffset(int offset);
     50 
     51     void setToBeforeChild(Node*);
     52     void setToStartOfNode(PassRefPtr<Node>);
     53     void setToEndOfNode(PassRefPtr<Node>);
     54 
     55     void childBeforeWillBeRemoved();
     56     void invalidateOffset() const;
     57     void ensureOffsetIsValid() const;
     58 
     59 private:
     60     static const int invalidOffset = -1;
     61 
     62     RefPtr<Node> m_containerNode;
     63     mutable int m_offsetInContainer;
     64     RefPtr<Node> m_childBeforeBoundary;
     65 };
     66 
     67 inline RangeBoundaryPoint::RangeBoundaryPoint(PassRefPtr<Node> container)
     68     : m_containerNode(container)
     69     , m_offsetInContainer(0)
     70     , m_childBeforeBoundary(0)
     71 {
     72     ASSERT(m_containerNode);
     73 }
     74 
     75 inline RangeBoundaryPoint::RangeBoundaryPoint(const RangeBoundaryPoint& other)
     76     : m_containerNode(other.container())
     77     , m_offsetInContainer(other.offset())
     78     , m_childBeforeBoundary(other.childBefore())
     79 {
     80 }
     81 
     82 inline Node* RangeBoundaryPoint::container() const
     83 {
     84     return m_containerNode.get();
     85 }
     86 
     87 inline Node* RangeBoundaryPoint::childBefore() const
     88 {
     89     return m_childBeforeBoundary.get();
     90 }
     91 
     92 inline void RangeBoundaryPoint::ensureOffsetIsValid() const
     93 {
     94     if (m_offsetInContainer >= 0)
     95         return;
     96 
     97     ASSERT(m_childBeforeBoundary);
     98     m_offsetInContainer = m_childBeforeBoundary->nodeIndex() + 1;
     99 }
    100 
    101 inline const Position RangeBoundaryPoint::toPosition() const
    102 {
    103     ensureOffsetIsValid();
    104     return createLegacyEditingPosition(m_containerNode.get(), m_offsetInContainer);
    105 }
    106 
    107 inline int RangeBoundaryPoint::offset() const
    108 {
    109     ensureOffsetIsValid();
    110     return m_offsetInContainer;
    111 }
    112 
    113 inline void RangeBoundaryPoint::clear()
    114 {
    115     m_containerNode.clear();
    116     m_offsetInContainer = 0;
    117     m_childBeforeBoundary = 0;
    118 }
    119 
    120 inline void RangeBoundaryPoint::set(PassRefPtr<Node> container, int offset, Node* childBefore)
    121 {
    122     ASSERT(container);
    123     ASSERT(offset >= 0);
    124     ASSERT(childBefore == (offset ? container->childNode(offset - 1) : 0));
    125     m_containerNode = container;
    126     m_offsetInContainer = offset;
    127     m_childBeforeBoundary = childBefore;
    128 }
    129 
    130 inline void RangeBoundaryPoint::setOffset(int offset)
    131 {
    132     ASSERT(m_containerNode);
    133     ASSERT(m_containerNode->offsetInCharacters());
    134     ASSERT(m_offsetInContainer >= 0);
    135     ASSERT(!m_childBeforeBoundary);
    136     m_offsetInContainer = offset;
    137 }
    138 
    139 inline void RangeBoundaryPoint::setToBeforeChild(Node* child)
    140 {
    141     ASSERT(child);
    142     ASSERT(child->parentNode());
    143     m_childBeforeBoundary = child->previousSibling();
    144     m_containerNode = child->parentNode();
    145     m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0;
    146 }
    147 
    148 inline void RangeBoundaryPoint::setToStartOfNode(PassRefPtr<Node> container)
    149 {
    150     ASSERT(container);
    151     m_containerNode = container;
    152     m_offsetInContainer = 0;
    153     m_childBeforeBoundary = 0;
    154 }
    155 
    156 inline void RangeBoundaryPoint::setToEndOfNode(PassRefPtr<Node> container)
    157 {
    158     ASSERT(container);
    159     m_containerNode = container;
    160     if (m_containerNode->offsetInCharacters()) {
    161         m_offsetInContainer = m_containerNode->maxCharacterOffset();
    162         m_childBeforeBoundary = 0;
    163     } else {
    164         m_childBeforeBoundary = m_containerNode->lastChild();
    165         m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0;
    166     }
    167 }
    168 
    169 inline void RangeBoundaryPoint::childBeforeWillBeRemoved()
    170 {
    171     ASSERT(m_offsetInContainer);
    172     m_childBeforeBoundary = m_childBeforeBoundary->previousSibling();
    173     if (!m_childBeforeBoundary)
    174         m_offsetInContainer = 0;
    175     else if (m_offsetInContainer > 0)
    176         --m_offsetInContainer;
    177 }
    178 
    179 inline void RangeBoundaryPoint::invalidateOffset() const
    180 {
    181     m_offsetInContainer = invalidOffset;
    182 }
    183 
    184 inline bool operator==(const RangeBoundaryPoint& a, const RangeBoundaryPoint& b)
    185 {
    186     if (a.container() != b.container())
    187         return false;
    188     if (a.childBefore() || b.childBefore()) {
    189         if (a.childBefore() != b.childBefore())
    190             return false;
    191     } else {
    192         if (a.offset() != b.offset())
    193             return false;
    194     }
    195     return true;
    196 }
    197 
    198 }
    199 
    200 #endif
    201