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     DISALLOW_ALLOCATION();
     36 public:
     37     explicit RangeBoundaryPoint(PassRefPtrWillBeRawPtr<Node> container);
     38 
     39     explicit RangeBoundaryPoint(const RangeBoundaryPoint&);
     40 
     41     const Position toPosition() const;
     42 
     43     Node* container() const;
     44     int offset() const;
     45     Node* childBefore() const;
     46 
     47     void clear();
     48 
     49     void set(PassRefPtrWillBeRawPtr<Node> container, int offset, Node* childBefore);
     50     void setOffset(int offset);
     51 
     52     void setToBeforeChild(Node&);
     53     void setToStartOfNode(Node&);
     54     void setToEndOfNode(Node&);
     55 
     56     void childBeforeWillBeRemoved();
     57     void invalidateOffset() const;
     58     void ensureOffsetIsValid() const;
     59 
     60     void trace(Visitor*);
     61 
     62 private:
     63     static const int invalidOffset = -1;
     64 
     65     RefPtrWillBeMember<Node> m_containerNode;
     66     mutable int m_offsetInContainer;
     67     RefPtrWillBeMember<Node> m_childBeforeBoundary;
     68 };
     69 
     70 inline RangeBoundaryPoint::RangeBoundaryPoint(PassRefPtrWillBeRawPtr<Node> container)
     71     : m_containerNode(container)
     72     , m_offsetInContainer(0)
     73     , m_childBeforeBoundary(nullptr)
     74 {
     75     ASSERT(m_containerNode);
     76 }
     77 
     78 inline RangeBoundaryPoint::RangeBoundaryPoint(const RangeBoundaryPoint& other)
     79     : m_containerNode(other.container())
     80     , m_offsetInContainer(other.offset())
     81     , m_childBeforeBoundary(other.childBefore())
     82 {
     83 }
     84 
     85 inline Node* RangeBoundaryPoint::container() const
     86 {
     87     return m_containerNode.get();
     88 }
     89 
     90 inline Node* RangeBoundaryPoint::childBefore() const
     91 {
     92     return m_childBeforeBoundary.get();
     93 }
     94 
     95 inline void RangeBoundaryPoint::ensureOffsetIsValid() const
     96 {
     97     if (m_offsetInContainer >= 0)
     98         return;
     99 
    100     ASSERT(m_childBeforeBoundary);
    101     m_offsetInContainer = m_childBeforeBoundary->nodeIndex() + 1;
    102 }
    103 
    104 inline const Position RangeBoundaryPoint::toPosition() const
    105 {
    106     ensureOffsetIsValid();
    107     return createLegacyEditingPosition(m_containerNode.get(), m_offsetInContainer);
    108 }
    109 
    110 inline int RangeBoundaryPoint::offset() const
    111 {
    112     ensureOffsetIsValid();
    113     return m_offsetInContainer;
    114 }
    115 
    116 inline void RangeBoundaryPoint::clear()
    117 {
    118     m_containerNode.clear();
    119     m_offsetInContainer = 0;
    120     m_childBeforeBoundary = nullptr;
    121 }
    122 
    123 inline void RangeBoundaryPoint::set(PassRefPtrWillBeRawPtr<Node> container, int offset, Node* childBefore)
    124 {
    125     ASSERT(container);
    126     ASSERT(offset >= 0);
    127     ASSERT(childBefore == (offset ? container->traverseToChildAt(offset - 1) : 0));
    128     m_containerNode = container;
    129     m_offsetInContainer = offset;
    130     m_childBeforeBoundary = childBefore;
    131 }
    132 
    133 inline void RangeBoundaryPoint::setOffset(int offset)
    134 {
    135     ASSERT(m_containerNode);
    136     ASSERT(m_containerNode->offsetInCharacters());
    137     ASSERT(m_offsetInContainer >= 0);
    138     ASSERT(!m_childBeforeBoundary);
    139     m_offsetInContainer = offset;
    140 }
    141 
    142 inline void RangeBoundaryPoint::setToBeforeChild(Node& child)
    143 {
    144     ASSERT(child.parentNode());
    145     m_childBeforeBoundary = child.previousSibling();
    146     m_containerNode = child.parentNode();
    147     m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0;
    148 }
    149 
    150 inline void RangeBoundaryPoint::setToStartOfNode(Node& container)
    151 {
    152     m_containerNode = &container;
    153     m_offsetInContainer = 0;
    154     m_childBeforeBoundary = nullptr;
    155 }
    156 
    157 inline void RangeBoundaryPoint::setToEndOfNode(Node& container)
    158 {
    159     m_containerNode = &container;
    160     if (m_containerNode->offsetInCharacters()) {
    161         m_offsetInContainer = m_containerNode->maxCharacterOffset();
    162         m_childBeforeBoundary = nullptr;
    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 void RangeBoundaryPoint::trace(Visitor* visitor)
    185 {
    186     visitor->trace(m_containerNode);
    187     visitor->trace(m_childBeforeBoundary);
    188 }
    189 
    190 inline bool operator==(const RangeBoundaryPoint& a, const RangeBoundaryPoint& b)
    191 {
    192     if (a.container() != b.container())
    193         return false;
    194     if (a.childBefore() || b.childBefore()) {
    195         if (a.childBefore() != b.childBefore())
    196             return false;
    197     } else {
    198         if (a.offset() != b.offset())
    199             return false;
    200     }
    201     return true;
    202 }
    203 
    204 }
    205 
    206 #endif
    207