Reviewed by Dave Harrison.
[WebKit-https.git] / WebCore / khtml / editing / visible_position.h
1 /*
2  * Copyright (C) 2004 Apple Computer, 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 COMPUTER, 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 COMPUTER, 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 KHTML_EDITING_VISIBLE_POSITION_H
27 #define KHTML_EDITING_VISIBLE_POSITION_H
28
29 #include <qstring.h>
30
31 #include "xml/dom_position.h"
32 #include "text_affinity.h"
33
34 namespace DOM {
35     class NodeImpl;
36     class Range;
37     class RangeImpl;
38 }
39
40 namespace khtml {
41
42 #define VP_DEFAULT_AFFINITY DOWNSTREAM
43
44 class VisiblePosition
45 {
46 public:
47     typedef DOM::NodeImpl NodeImpl;
48     typedef DOM::Position Position;
49
50     enum EInitHint { 
51         INIT_UP, 
52         INIT_DOWN
53     };
54
55     VisiblePosition() { m_affinity = VP_DEFAULT_AFFINITY; };
56     VisiblePosition(NodeImpl *, long offset, EAffinity, EInitHint initHint=INIT_DOWN);
57     VisiblePosition(const Position &, EAffinity, EInitHint initHint=INIT_DOWN);
58     VisiblePosition(const VisiblePosition &);
59
60     void clear() { m_deepPosition.clear(); }
61
62     bool isNull() const { return m_deepPosition.isNull(); }
63     bool isNotNull() const { return m_deepPosition.isNotNull(); }
64
65     Position position() const { return rangeCompliantEquivalent(m_deepPosition); }
66     Position deepEquivalent() const { return m_deepPosition; }
67     EAffinity affinity() const { assert(m_affinity == UPSTREAM || m_affinity == DOWNSTREAM); return m_affinity; }
68     void setAffinity(EAffinity affinity) { m_affinity = affinity; }
69     
70     Position downstreamDeepEquivalent() const;
71
72     friend bool operator==(const VisiblePosition &a, const VisiblePosition &b);
73     friend bool operator!=(const VisiblePosition &a, const VisiblePosition &b);
74
75     friend bool isEqualIgnoringAffinity(const VisiblePosition &a, const VisiblePosition &b);
76     friend bool isNotEqualIgnoringAffinity(const VisiblePosition &a, const VisiblePosition &b);
77
78     // next() and previous() will increment/decrement by a character cluster.
79     VisiblePosition next() const;
80     VisiblePosition previous() const;
81
82     bool isLastInBlock() const;
83
84     QChar character() const;
85     
86     void debugPosition(const char *msg = "") const;
87
88 #ifndef NDEBUG
89     void formatForDebugger(char *buffer, unsigned length) const;
90 #endif
91     
92 private:
93     void init(const Position &, EInitHint, EAffinity);
94     void initUpstream(const Position &);
95     void initDownstream(const Position &);
96
97     static Position deepEquivalent(const Position &);
98     static Position rangeCompliantEquivalent(const Position &);
99
100     static long maxOffset(const NodeImpl *);
101     static bool isAtomicNode(const NodeImpl *);
102     
103     static Position previousVisiblePosition(const Position &);
104     static Position nextVisiblePosition(const Position &);
105
106     static bool isCandidate(const Position &);
107         
108     Position m_deepPosition;
109     EAffinity m_affinity;
110 };
111
112 inline bool operator==(const VisiblePosition &a, const VisiblePosition &b)
113 {
114     return a.m_deepPosition == b.m_deepPosition && a.m_affinity == b.m_affinity;
115 }
116  
117 inline bool operator!=(const VisiblePosition &a, const VisiblePosition &b)
118 {
119     return !(a == b);
120 }
121
122 DOM::Range makeRange(const VisiblePosition &start, const VisiblePosition &end);
123 bool setStart(DOM::Range &, const VisiblePosition &start);
124 bool setStart(DOM::RangeImpl *, const VisiblePosition &start);
125 bool setEnd(DOM::Range &, const VisiblePosition &start);
126 bool setEnd(DOM::RangeImpl *, const VisiblePosition &start);
127 VisiblePosition startVisiblePosition(const DOM::Range &, EAffinity);
128 VisiblePosition startVisiblePosition(const DOM::RangeImpl *, EAffinity);
129 VisiblePosition endVisiblePosition(const DOM::Range &, EAffinity);
130 VisiblePosition endVisiblePosition(const DOM::RangeImpl *, EAffinity);
131
132 void setAffinityUsingLinePosition(VisiblePosition &);
133
134 DOM::NodeImpl *enclosingBlockFlowElement(const VisiblePosition &);
135
136 bool visiblePositionsOnDifferentLines(const VisiblePosition &, const VisiblePosition &);
137 bool visiblePositionsInDifferentBlocks(const VisiblePosition &, const VisiblePosition &);
138 bool isFirstVisiblePositionOnLine(const VisiblePosition &);
139 bool isFirstVisiblePositionInParagraph(const VisiblePosition &);
140 bool isFirstVisiblePositionInBlock(const VisiblePosition &);
141 bool isFirstVisiblePositionInNode(const VisiblePosition &, const DOM::NodeImpl *);
142 bool isLastVisiblePositionOnLine(const VisiblePosition &);
143 bool isLastVisiblePositionInParagraph(const VisiblePosition &);
144 bool isLastVisiblePositionInBlock(const VisiblePosition &);
145 bool isLastVisiblePositionInNode(const VisiblePosition &, const DOM::NodeImpl *);
146
147 } // namespace khtml
148
149 #endif // KHTML_EDITING_VISIBLE_POSITION_H