File indexing completed on 2024-05-05 16:11:41

0001 /*
0002  * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
0003  *
0004  * Redistribution and use in source and binary forms, with or without
0005  * modification, are permitted provided that the following conditions
0006  * are met:
0007  * 1. Redistributions of source code must retain the above copyright
0008  *    notice, this list of conditions and the following disclaimer.
0009  * 2. Redistributions in binary form must reproduce the above copyright
0010  *    notice, this list of conditions and the following disclaimer in the
0011  *    documentation and/or other materials provided with the distribution.
0012  *
0013  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
0014  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0015  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
0016  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
0017  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0018  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0019  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
0020  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
0021  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0022  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0023  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0024  */
0025 
0026 #ifndef __dom_selection_h__
0027 #define __dom_selection_h__
0028 
0029 #include "xml/dom_position.h"
0030 
0031 class KHTMLPart;
0032 class KHTMLView;
0033 class QPainter;
0034 class QRect;
0035 
0036 namespace khtml
0037 {
0038 class RenderObject;
0039 }
0040 
0041 namespace DOM
0042 {
0043 
0044 class NodeImpl;
0045 class Position;
0046 class Range;
0047 
0048 class Selection
0049 {
0050 public:
0051     enum EState { NONE, CARET, RANGE };
0052     enum EAlter { MOVE, EXTEND };
0053     enum EDirection { FORWARD, BACKWARD, RIGHT, LEFT };
0054     enum ETextGranularity { CHARACTER, WORD, LINE, PARAGRAPH };
0055 
0056     // These match the AppKit values for these concepts.
0057     // From NSTextView.h:
0058     // NSSelectionAffinityUpstream = 0
0059     // NSSelectionAffinityDownstream = 1
0060     enum EAffinity { UPSTREAM = 0, DOWNSTREAM = 1 };
0061 
0062     Selection();
0063     Selection(const Range &);
0064     Selection(const Position &);
0065     Selection(const Position &, const Position &);
0066     Selection(const Selection &);
0067 
0068     EState state() const
0069     {
0070         return m_state;
0071     }
0072     EAffinity affinity() const
0073     {
0074         return m_affinity;
0075     }
0076     void setAffinity(EAffinity);
0077 
0078     void moveTo(const Range &);
0079     void moveTo(const Selection &);
0080     void moveTo(const Position &);
0081     void moveTo(const Position &, const Position &);
0082     bool modify(EAlter, EDirection, ETextGranularity);
0083     bool expandUsingGranularity(ETextGranularity);
0084     void clear();
0085     void collapse();
0086 
0087     bool moveToRenderedContent();
0088 
0089     void setBase(const Position &pos);
0090     void setExtent(const Position &pos);
0091     void setBaseAndExtent(const Position &base, const Position &extent);
0092     void setStart(const Position &pos);
0093     void setEnd(const Position &pos);
0094     void setStartAndEnd(const Position &start, const Position &end);
0095 
0096     Position base() const
0097     {
0098         return m_base;
0099     }
0100     Position extent() const
0101     {
0102         return m_extent;
0103     }
0104     Position start() const
0105     {
0106         return m_start;
0107     }
0108     Position end() const
0109     {
0110         return m_end;
0111     }
0112     Position caretPos() const
0113     {
0114         return m_baseIsStart ? m_end : m_start;
0115     }
0116     Position nonCaretPos() const
0117     {
0118         return m_baseIsStart ? m_start : m_end;
0119     }
0120 
0121     QRect getRepaintRect() const;
0122     void setNeedsLayout(bool flag = true);
0123     void clearModifyBias()
0124     {
0125         m_modifyBiasSet = false;
0126     }
0127 
0128     bool isEmpty() const
0129     {
0130         return state() == NONE;
0131     }
0132     bool notEmpty() const
0133     {
0134         return !isEmpty();
0135     }
0136     Range toRange() const;
0137     bool isCollapsed() const
0138     {
0139         return m_state == CARET;
0140     }
0141 
0142     void getRange(NodeImpl *&start, long &so, NodeImpl *&end, long &eo) const;
0143 
0144     void debugPosition() const;
0145     void debugRenderer(khtml::RenderObject *r, bool selected) const;
0146 
0147     Selection &operator=(const Selection &o);
0148     Selection &operator=(const Range &r)
0149     {
0150         moveTo(r);
0151         return *this;
0152     }
0153     Selection &operator=(const Position &r)
0154     {
0155         moveTo(r);
0156         return *this;
0157     }
0158 
0159     friend bool operator==(const Selection &a, const Selection &b);
0160     friend bool operator!=(const Selection &a, const Selection &b);
0161 
0162     friend class ::KHTMLPart;
0163     friend class ::KHTMLView;
0164 
0165 private:
0166     enum EPositionType { START, END, BASE, EXTENT, CARETPOS };
0167 
0168     void init();
0169     void validate(ETextGranularity granularity = CHARACTER);
0170     void assignBase(const Position &pos)
0171     {
0172         m_base = pos;
0173     }
0174     void assignExtent(const Position &pos)
0175     {
0176         m_extent = pos;
0177     }
0178     void assignBaseAndExtent(const Position &base, const Position &extent)
0179     {
0180         m_base = base;
0181         m_extent = extent;
0182     }
0183     void assignStart(const Position &pos)
0184     {
0185         m_start = pos;
0186     }
0187     void assignEnd(const Position &pos)
0188     {
0189         m_end = pos;
0190     }
0191     void assignStartAndEnd(const Position &start, const Position &end)
0192     {
0193         m_start = start;
0194         m_end = end;
0195     }
0196 
0197     void layoutCaret();
0198     void needsCaretRepaint();
0199     void paintCaret(QPainter *p, const QRect &rect);
0200 
0201     bool nodeIsBeforeNode(NodeImpl *n1, NodeImpl *n2) const;
0202     int xPosForVerticalArrowNavigation(EPositionType, bool recalc = false) const;
0203 
0204     Position m_base;              // base position for the selection
0205     Position m_extent;            // extent position for the selection
0206     Position m_start;             // start position for the selection
0207     Position m_end;               // end position for the selection
0208 
0209     EState m_state;               // the state of the selection
0210     EAffinity m_affinity;         // the upstream/downstream affinity of the selection
0211 
0212     int m_caretX;                 // caret coordinates and size
0213     int m_caretY;
0214     int m_caretSize;
0215 
0216     bool m_baseIsStart : 1;       // true if base node is before the extent node
0217     bool m_needsCaretLayout : 1;  // true if the caret position needs to be calculated
0218     bool m_modifyBiasSet : 1;     // true if the selection has been horizontally
0219     // modified with EAlter::EXTEND
0220     bool m_visible : 1;           // true if caret should be painted
0221 };
0222 
0223 inline bool operator==(const Selection &a, const Selection &b)
0224 {
0225     return a.start() == b.start() && a.end() == b.end();
0226 }
0227 
0228 inline bool operator!=(const Selection &a, const Selection &b)
0229 {
0230     return !(a == b);
0231 }
0232 
0233 QDebug operator<<(QDebug stream, const Selection &selection);
0234 
0235 } // namespace DOM
0236 
0237 #endif  // __dom_selection_h__