1 /* 2 * Copyright (C) 2007, 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 #include "config.h" 27 #include "PositionIterator.h" 28 29 #include "Node.h" 30 #include "RenderBlock.h" 31 #include "htmlediting.h" 32 33 namespace WebCore { 34 35 using namespace HTMLNames; 36 37 PositionIterator::operator Position() const 38 { 39 if (m_nodeAfterPositionInAnchor) { 40 ASSERT(m_nodeAfterPositionInAnchor->parentNode() == m_anchorNode); 41 return positionInParentBeforeNode(m_nodeAfterPositionInAnchor); 42 } 43 if (m_anchorNode->hasChildNodes()) 44 return lastDeepEditingPositionForNode(m_anchorNode); 45 return Position(m_anchorNode, m_offsetInAnchor); 46 } 47 48 void PositionIterator::increment() 49 { 50 if (!m_anchorNode) 51 return; 52 53 if (m_nodeAfterPositionInAnchor) { 54 m_anchorNode = m_nodeAfterPositionInAnchor; 55 m_nodeAfterPositionInAnchor = m_anchorNode->firstChild(); 56 m_offsetInAnchor = 0; 57 return; 58 } 59 60 if (!m_anchorNode->hasChildNodes() && m_offsetInAnchor < lastOffsetForEditing(m_anchorNode)) 61 m_offsetInAnchor = Position::uncheckedNextOffset(m_anchorNode, m_offsetInAnchor); 62 else { 63 m_nodeAfterPositionInAnchor = m_anchorNode; 64 m_anchorNode = m_nodeAfterPositionInAnchor->parentNode(); 65 m_nodeAfterPositionInAnchor = m_nodeAfterPositionInAnchor->nextSibling(); 66 m_offsetInAnchor = 0; 67 } 68 } 69 70 void PositionIterator::decrement() 71 { 72 if (!m_anchorNode) 73 return; 74 75 if (m_nodeAfterPositionInAnchor) { 76 m_anchorNode = m_nodeAfterPositionInAnchor->previousSibling(); 77 if (m_anchorNode) { 78 m_nodeAfterPositionInAnchor = 0; 79 m_offsetInAnchor = m_anchorNode->hasChildNodes() ? 0 : lastOffsetForEditing(m_anchorNode); 80 } else { 81 m_nodeAfterPositionInAnchor = m_nodeAfterPositionInAnchor->parentNode(); 82 m_anchorNode = m_nodeAfterPositionInAnchor->parentNode(); 83 m_offsetInAnchor = 0; 84 } 85 return; 86 } 87 88 if (m_offsetInAnchor) { 89 m_offsetInAnchor = Position::uncheckedPreviousOffset(m_anchorNode, m_offsetInAnchor); 90 } else { 91 if (m_anchorNode->hasChildNodes()) { 92 m_anchorNode = m_anchorNode->lastChild(); 93 if (!m_anchorNode->hasChildNodes()) 94 m_offsetInAnchor = lastOffsetForEditing(m_anchorNode); 95 } else { 96 m_nodeAfterPositionInAnchor = m_anchorNode; 97 m_anchorNode = m_anchorNode->parentNode(); 98 } 99 } 100 } 101 102 bool PositionIterator::atStart() const 103 { 104 if (!m_anchorNode) 105 return true; 106 if (m_anchorNode->parentNode()) 107 return false; 108 return (!m_anchorNode->hasChildNodes() && !m_offsetInAnchor) || (m_nodeAfterPositionInAnchor && !m_nodeAfterPositionInAnchor->previousSibling()); 109 } 110 111 bool PositionIterator::atEnd() const 112 { 113 if (!m_anchorNode) 114 return true; 115 if (m_nodeAfterPositionInAnchor) 116 return false; 117 return !m_anchorNode->parentNode() && (m_anchorNode->hasChildNodes() || m_offsetInAnchor >= lastOffsetForEditing(m_anchorNode)); 118 } 119 120 bool PositionIterator::atStartOfNode() const 121 { 122 if (!m_anchorNode) 123 return true; 124 if (!m_nodeAfterPositionInAnchor) 125 return !m_anchorNode->hasChildNodes() && !m_offsetInAnchor; 126 return !m_nodeAfterPositionInAnchor->previousSibling(); 127 } 128 129 bool PositionIterator::atEndOfNode() const 130 { 131 if (!m_anchorNode) 132 return true; 133 if (m_nodeAfterPositionInAnchor) 134 return false; 135 return m_anchorNode->hasChildNodes() || m_offsetInAnchor >= lastOffsetForEditing(m_anchorNode); 136 } 137 138 bool PositionIterator::isCandidate() const 139 { 140 if (!m_anchorNode) 141 return false; 142 143 RenderObject* renderer = m_anchorNode->renderer(); 144 if (!renderer) 145 return false; 146 147 if (renderer->style()->visibility() != VISIBLE) 148 return false; 149 150 if (renderer->isBR()) 151 return !m_offsetInAnchor && !Position::nodeIsUserSelectNone(m_anchorNode->parent()); 152 153 if (renderer->isText()) 154 return Position(*this).inRenderedText() && !Position::nodeIsUserSelectNone(m_anchorNode); 155 156 if (isTableElement(m_anchorNode) || editingIgnoresContent(m_anchorNode)) 157 return (atStartOfNode() || atEndOfNode()) && !Position::nodeIsUserSelectNone(m_anchorNode->parent()); 158 159 if (!m_anchorNode->hasTagName(htmlTag) && renderer->isBlockFlow()) { 160 if (toRenderBlock(renderer)->height() || m_anchorNode->hasTagName(bodyTag)) { 161 if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(renderer)) 162 return atStartOfNode() && !Position::nodeIsUserSelectNone(m_anchorNode); 163 return m_anchorNode->isContentEditable() && !Position::nodeIsUserSelectNone(m_anchorNode) && Position(*this).atEditingBoundary(); 164 } 165 } 166 167 return false; 168 } 169 170 } // namespace WebCore 171