/* * Copyright (C) 2004 Apple Computer, 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 COMPUTER, 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 COMPUTER, 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. */ #ifndef KHTML_EDITING_VISIBLE_POSITION_H #define KHTML_EDITING_VISIBLE_POSITION_H #include #include "xml/dom_position.h" #include "text_affinity.h" namespace DOM { class NodeImpl; class Range; class RangeImpl; } namespace khtml { #define VP_DEFAULT_AFFINITY DOWNSTREAM class VisiblePosition { public: typedef DOM::NodeImpl NodeImpl; typedef DOM::Position Position; enum EInitHint { INIT_UP, INIT_DOWN }; VisiblePosition() { m_affinity = VP_DEFAULT_AFFINITY; }; VisiblePosition(NodeImpl *, long offset, EAffinity, EInitHint initHint=INIT_DOWN); VisiblePosition(const Position &, EAffinity, EInitHint initHint=INIT_DOWN); VisiblePosition(const VisiblePosition &); void clear() { m_deepPosition.clear(); } bool isNull() const { return m_deepPosition.isNull(); } bool isNotNull() const { return m_deepPosition.isNotNull(); } Position position() const { return rangeCompliantEquivalent(m_deepPosition); } Position deepEquivalent() const { return m_deepPosition; } EAffinity affinity() const { assert(m_affinity == UPSTREAM || m_affinity == DOWNSTREAM); return m_affinity; } void setAffinity(EAffinity affinity) { m_affinity = affinity; } Position downstreamDeepEquivalent() const; friend bool operator==(const VisiblePosition &a, const VisiblePosition &b); friend bool operator!=(const VisiblePosition &a, const VisiblePosition &b); friend bool isEqualIgnoringAffinity(const VisiblePosition &a, const VisiblePosition &b); friend bool isNotEqualIgnoringAffinity(const VisiblePosition &a, const VisiblePosition &b); // next() and previous() will increment/decrement by a character cluster. VisiblePosition next() const; VisiblePosition previous() const; bool isLastInBlock() const; QChar character() const; void debugPosition(const char *msg = "") const; #ifndef NDEBUG void formatForDebugger(char *buffer, unsigned length) const; #endif private: void init(const Position &, EInitHint, EAffinity); void initUpstream(const Position &); void initDownstream(const Position &); static Position deepEquivalent(const Position &); static Position rangeCompliantEquivalent(const Position &); static long maxOffset(const NodeImpl *); static bool isAtomicNode(const NodeImpl *); static Position previousVisiblePosition(const Position &); static Position nextVisiblePosition(const Position &); static Position previousPosition(const Position &); static Position nextPosition(const Position &); static bool atStart(const Position &); static bool atEnd(const Position &); static bool isCandidate(const Position &); Position m_deepPosition; EAffinity m_affinity; }; inline bool operator==(const VisiblePosition &a, const VisiblePosition &b) { return a.m_deepPosition == b.m_deepPosition && a.m_affinity == b.m_affinity; } inline bool operator!=(const VisiblePosition &a, const VisiblePosition &b) { return !(a == b); } DOM::Range makeRange(const VisiblePosition &start, const VisiblePosition &end); bool setStart(DOM::Range &, const VisiblePosition &start); bool setStart(DOM::RangeImpl *, const VisiblePosition &start); bool setEnd(DOM::Range &, const VisiblePosition &start); bool setEnd(DOM::RangeImpl *, const VisiblePosition &start); VisiblePosition startVisiblePosition(const DOM::Range &, EAffinity); VisiblePosition startVisiblePosition(const DOM::RangeImpl *, EAffinity); VisiblePosition endVisiblePosition(const DOM::Range &, EAffinity); VisiblePosition endVisiblePosition(const DOM::RangeImpl *, EAffinity); void setAffinityUsingLinePosition(VisiblePosition &); bool visiblePositionsOnDifferentLines(const VisiblePosition &, const VisiblePosition &); bool visiblePositionsInDifferentBlocks(const VisiblePosition &, const VisiblePosition &); bool isFirstVisiblePositionOnLine(const VisiblePosition &); bool isFirstVisiblePositionInParagraph(const VisiblePosition &); bool isFirstVisiblePositionInBlock(const VisiblePosition &); bool isFirstVisiblePositionInNode(const VisiblePosition &, const DOM::NodeImpl *); bool isLastVisiblePositionOnLine(const VisiblePosition &); bool isLastVisiblePositionInParagraph(const VisiblePosition &); bool isLastVisiblePositionInBlock(const VisiblePosition &); bool isLastVisiblePositionInNode(const VisiblePosition &, const DOM::NodeImpl *); } // namespace khtml #endif // KHTML_EDITING_VISIBLE_POSITION_H