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