diff options
Diffstat (limited to 'src/3rdparty/webkit/WebCore/dom/Position.h')
-rw-r--r-- | src/3rdparty/webkit/WebCore/dom/Position.h | 121 |
1 files changed, 97 insertions, 24 deletions
diff --git a/src/3rdparty/webkit/WebCore/dom/Position.h b/src/3rdparty/webkit/WebCore/dom/Position.h index 2624238..57f73ec 100644 --- a/src/3rdparty/webkit/WebCore/dom/Position.h +++ b/src/3rdparty/webkit/WebCore/dom/Position.h @@ -28,6 +28,7 @@ #include "TextAffinity.h" #include "TextDirection.h" +#include <wtf/Assertions.h> #include <wtf/PassRefPtr.h> #include <wtf/RefPtr.h> @@ -40,28 +41,76 @@ class Node; class Range; class RenderObject; -enum EUsingComposedCharacters { NotUsingComposedCharacters = false, UsingComposedCharacters = true }; - -// FIXME: Reduce the number of operations we have on a Position. -// This should be more like a humble struct, without so many different -// member functions. We should find better homes for these functions. +enum PositionMoveType { + CodePoint, // Move by a single code point. + Character, // Move to the next Unicode character break. + BackwardDeletion // Subject to platform conventions. +}; class Position { public: - RefPtr<Node> container; - int posOffset; // to be renamed to offset when we get rid of offset() - - Position() : posOffset(0) { } - Position(PassRefPtr<Node> c, int o) : container(c), posOffset(o) { } - - void clear() { container.clear(); posOffset = 0; } - - Node* node() const { return container.get(); } - int offset() const { return posOffset; } - Element* documentElement() const; - - bool isNull() const { return !container; } - bool isNotNull() const { return container; } + enum AnchorType { + PositionIsOffsetInAnchor, + PositionIsAfterAnchor, + PositionIsBeforeAnchor + }; + + Position() + : m_offset(0) + , m_anchorType(PositionIsOffsetInAnchor) + , m_isLegacyEditingPosition(false) + { + } + + // For creating legacy editing positions: (Anchor type will be determined from editingIgnoresContent(node)) + Position(PassRefPtr<Node> anchorNode, int offset); + + // For creating before/after positions: + Position(PassRefPtr<Node> anchorNode, AnchorType); + // For creating offset positions: + Position(PassRefPtr<Node> anchorNode, int offset, AnchorType); + + AnchorType anchorType() const { return m_anchorType; } + + void clear() { m_anchorNode.clear(); m_offset = 0; m_anchorType = PositionIsOffsetInAnchor; m_isLegacyEditingPosition = false; } + + // These are always DOM compliant values. Editing positions like [img, 0] (aka [img, before]) + // will return img->parentNode() and img->nodeIndex() from these functions. + Node* containerNode() const; // NULL for a before/after position anchored to a node with no parent + int computeOffsetInContainerNode() const; // O(n) for before/after-anchored positions, O(1) for parent-anchored positions + + // Inline O(1) access for Positions which callers know to be parent-anchored + int offsetInContainerNode() const + { + ASSERT(anchorType() == PositionIsOffsetInAnchor); + return m_offset; + } + + // New code should not use this function. + int deprecatedEditingOffset() const + { + // This should probably ASSERT(m_isLegacyEditingPosition); + return m_offset; + } + + // These are convenience methods which are smart about whether the position is neighbor anchored or parent anchored + Node* computeNodeBeforePosition() const; + Node* computeNodeAfterPosition() const; + + Node* anchorNode() const { return m_anchorNode.get(); } + + // FIXME: Callers should be moved off of node(), node() is not always the container for this position. + // For nodes which editingIgnoresContent(node()) returns true, positions like [ignoredNode, 0] + // will be treated as before ignoredNode (thus node() is really after the position, not containing it). + Node* node() const { return m_anchorNode.get(); } + + // These should only be used for PositionIsOffsetInAnchor positions, unless + // the position is a legacy editing position. + void moveToPosition(PassRefPtr<Node> anchorNode, int offset); + void moveToOffset(int offset); + + bool isNull() const { return !m_anchorNode; } + bool isNotNull() const { return m_anchorNode; } Element* element() const; PassRefPtr<CSSComputedStyleDeclaration> computedStyle() const; @@ -69,13 +118,19 @@ public: // Move up or down the DOM by one position. // Offsets are computed using render text for nodes that have renderers - but note that even when // using composed characters, the result may be inside a single user-visible character if a ligature is formed. - Position previous(EUsingComposedCharacters usingComposedCharacters=NotUsingComposedCharacters) const; - Position next(EUsingComposedCharacters usingComposedCharacters=NotUsingComposedCharacters) const; + Position previous(PositionMoveType = CodePoint) const; + Position next(PositionMoveType = CodePoint) const; static int uncheckedPreviousOffset(const Node*, int current); + static int uncheckedPreviousOffsetForBackwardDeletion(const Node*, int current); static int uncheckedNextOffset(const Node*, int current); - bool atStart() const; - bool atEnd() const; + // These can be either inside or just before/after the node, depending on + // if the node is ignored by editing or not. + bool atFirstEditingPositionForNode() const; + bool atLastEditingPositionForNode() const; + + bool atStartOfTree() const; + bool atEndOfTree() const; // FIXME: Make these non-member functions and put them somewhere in the editing directory. // These aren't really basic "position" operations. More high level editing helper functions. @@ -109,11 +164,23 @@ private: Position previousCharacterPosition(EAffinity) const; Position nextCharacterPosition(EAffinity) const; + + static AnchorType anchorTypeForLegacyEditingPosition(Node* anchorNode, int offset); + + RefPtr<Node> m_anchorNode; + // m_offset can be the offset inside m_anchorNode, or if editingIgnoresContent(m_anchorNode) + // returns true, then other places in editing will treat m_offset == 0 as "before the anchor" + // and m_offset > 0 as "after the anchor node". See rangeCompliantEquivalent for more info. + int m_offset; + AnchorType m_anchorType : 2; + bool m_isLegacyEditingPosition : 1; }; inline bool operator==(const Position& a, const Position& b) { - return a.container == b.container && a.posOffset == b.posOffset; + // FIXME: In <div><img></div> [div, 0] != [img, 0] even though most of the + // editing code will treat them as identical. + return a.anchorNode() == b.anchorNode() && a.deprecatedEditingOffset() == b.deprecatedEditingOffset(); } inline bool operator!=(const Position& a, const Position& b) @@ -124,6 +191,12 @@ inline bool operator!=(const Position& a, const Position& b) Position startPosition(const Range*); Position endPosition(const Range*); +// NOTE: first/lastDeepEditingPositionForNode can return "editing positions" (like [img, 0]) +// for elements which editing "ignores". the rest of the editing code will treat [img, 0] +// as "the last position before the img" +Position firstDeepEditingPositionForNode(Node*); +Position lastDeepEditingPositionForNode(Node*); + } // namespace WebCore #ifndef NDEBUG |