/* * Copyright (C) 2007 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "PositionIterator.h" #include "Node.h" #include "RenderObject.h" #include "htmlediting.h" namespace WebCore { using namespace HTMLNames; void PositionIterator::increment() { if (!m_parent) return; if (m_child) { m_parent = m_child; m_child = m_parent->firstChild(); m_offset = 0; return; } if (!m_parent->hasChildNodes() && m_offset < maxDeepOffset(m_parent)) m_offset = m_parent->nextOffset(m_offset); else { m_child = m_parent; m_parent = m_child->parentNode(); m_child = m_child->nextSibling(); m_offset = 0; } } void PositionIterator::decrement() { if (!m_parent) return; if (m_child) { m_parent = m_child->previousSibling(); if (m_parent) { m_child = 0; m_offset = m_parent->hasChildNodes() ? 0 : maxDeepOffset(m_parent); } else { m_child = m_child->parentNode(); m_parent = m_child->parentNode(); m_offset = 0; } return; } if (m_offset) { m_offset = m_parent->previousOffset(m_offset); } else { if (m_parent->hasChildNodes()) { m_parent = m_parent->lastChild(); if (!m_parent->hasChildNodes()) m_offset = maxDeepOffset(m_parent); } else { m_child = m_parent; m_parent = m_parent->parentNode(); } } } bool PositionIterator::atStart() const { if (!m_parent) return true; if (m_parent->parentNode()) return false; return !m_parent->hasChildNodes() && !m_offset || m_child && !m_child->previousSibling(); } bool PositionIterator::atEnd() const { if (!m_parent) return true; if (m_child) return false; return !m_parent->parentNode() && (m_parent->hasChildNodes() || m_offset >= maxDeepOffset(m_parent)); } bool PositionIterator::atStartOfNode() const { if (!m_parent) return true; if (!m_child) return !m_parent->hasChildNodes() && !m_offset; return !m_child->previousSibling(); } bool PositionIterator::atEndOfNode() const { if (!m_parent) return true; if (m_child) return false; return m_parent->hasChildNodes() || m_offset >= maxDeepOffset(m_parent); } bool PositionIterator::isCandidate() const { if (!m_parent) return false; RenderObject* renderer = m_parent->renderer(); if (!renderer) return false; if (renderer->style()->visibility() != VISIBLE) return false; if (renderer->isBR()) return !m_offset && !Position::nodeIsUserSelectNone(m_parent->parent()); if (renderer->isText()) return Position(*this).inRenderedText() && !Position::nodeIsUserSelectNone(m_parent); if (isTableElement(m_parent) || editingIgnoresContent(m_parent)) return (atStartOfNode() || atEndOfNode()) && !Position::nodeIsUserSelectNone(m_parent->parent()); if (!m_parent->hasTagName(htmlTag) && renderer->isBlockFlow() && !Position::hasRenderedNonAnonymousDescendantsWithHeight(renderer) && (renderer->height() || m_parent->hasTagName(bodyTag))) return atStartOfNode() && !Position::nodeIsUserSelectNone(m_parent); return false; } } // namespace WebCore