File indexing completed on 2024-05-19 04:00:03

0001 /*
0002     SPDX-FileCopyrightText: 2010 Christoph Cullmann <cullmann@kde.org>
0003 
0004     Based on code of the SmartCursor/Range by:
0005     SPDX-FileCopyrightText: 2003-2005 Hamish Rodda <rodda@kde.org>
0006 
0007     SPDX-License-Identifier: LGPL-2.0-or-later
0008 */
0009 
0010 #ifndef KTEXTEDITOR_MOVINGCURSOR_H
0011 #define KTEXTEDITOR_MOVINGCURSOR_H
0012 
0013 #include <ktexteditor/cursor.h>
0014 #include <ktexteditor_export.h>
0015 
0016 class QDebug;
0017 
0018 namespace KTextEditor
0019 {
0020 class MovingRange;
0021 class Document;
0022 
0023 /**
0024  * \class MovingCursor movingcursor.h <KTextEditor/MovingCursor>
0025  *
0026  * \short A Cursor which is bound to a specific Document, and maintains its position.
0027  *
0028  * \ingroup kte_group_moving_classes
0029  *
0030  * A MovingCursor is an extension of the basic Cursor class. It maintains its
0031  * position in the document. As a result of this, MovingCursor%s may not be copied, as they need
0032  * to maintain a connection to the associated Document.
0033  *
0034  * Create a new MovingCursor like this:
0035  * \code
0036  * // Retrieve the MovingInterface
0037  * KTextEditor::MovingInterface* moving =
0038  *     qobject_cast<KTextEditor::MovingInterface*>( yourDocument );
0039  *
0040  * if ( moving ) {
0041  *     KTextEditor::MovingCursor* cursor = moving->newMovingCursor();
0042  * }
0043  * \endcode
0044  *
0045  * When finished with a MovingCursor, simply delete it.
0046  * If the document the cursor belong to is deleted, it will get deleted automatically.
0047  *
0048  * \sa Cursor, Range, MovingRange and MovingInterface.
0049  *
0050  * \author Christoph Cullmann \<cullmann@kde.org\>
0051  *
0052  * \since 4.5
0053  */
0054 class KTEXTEDITOR_EXPORT MovingCursor
0055 {
0056     //
0057     // sub types
0058     //
0059 public:
0060     /**
0061      * Insert behavior of this cursor, should it stay if text is insert at its position
0062      * or should it move.
0063      */
0064     enum InsertBehavior {
0065         StayOnInsert = 0x0, ///< stay on insert
0066         MoveOnInsert = 0x1 ///< move on insert
0067     };
0068 
0069     /**
0070      * Wrap behavior for end of line treatement used in move().
0071      */
0072     enum WrapBehavior {
0073         Wrap = 0x0, ///< wrap at end of line
0074         NoWrap = 0x1 ///< do not wrap at end of line
0075     };
0076 
0077     //
0078     // stuff that needs to be implemented by editor part cursors
0079     //
0080 public:
0081     /**
0082      * Set insert behavior.
0083      * @param insertBehavior new insert behavior
0084      */
0085     virtual void setInsertBehavior(InsertBehavior insertBehavior) = 0;
0086 
0087     /**
0088      * Get current insert behavior.
0089      * @return current insert behavior
0090      */
0091     virtual InsertBehavior insertBehavior() const = 0;
0092 
0093     /**
0094      * Gets the document to which this cursor is bound.
0095      * \return a pointer to the document
0096      */
0097     virtual Document *document() const = 0;
0098 
0099     /**
0100      * Get range this cursor belongs to, if any
0101      * @return range this pointer is part of, else 0
0102      */
0103     virtual MovingRange *range() const = 0;
0104 
0105     /**
0106      * Set the current cursor position to \e position.
0107      *
0108      * \param position new cursor position
0109      */
0110     virtual void setPosition(KTextEditor::Cursor position) = 0;
0111 
0112     /**
0113      * Retrieve the line on which this cursor is situated.
0114      * \return line number, where 0 is the first line.
0115      */
0116     virtual int line() const = 0;
0117 
0118     /**
0119      * Retrieve the column on which this cursor is situated.
0120      * \return column number, where 0 is the first column.
0121      */
0122     virtual int column() const = 0;
0123 
0124     /**
0125      * Destruct the moving cursor.
0126      */
0127     virtual ~MovingCursor();
0128 
0129     //
0130     // forbidden stuff
0131     //
0132 protected:
0133     /**
0134      * For inherited class only.
0135      */
0136     MovingCursor();
0137 
0138 public:
0139     /**
0140      * no copy constructor, don't allow this to be copied.
0141      */
0142     MovingCursor(const MovingCursor &) = delete;
0143 
0144     /**
0145      * no assignment operator, no copying around clever cursors.
0146      */
0147     MovingCursor &operator=(const MovingCursor &) = delete;
0148 
0149     //
0150     // convenience API
0151     //
0152 public:
0153     /**
0154      * Returns whether the current position of this cursor is a valid position,
0155      * i.e. whether line() >= 0 and column() >= 0.
0156      *
0157      * \return \e true , if the cursor position is valid, otherwise \e false
0158      */
0159     inline bool isValid() const
0160     {
0161         return line() >= 0 && column() >= 0;
0162     }
0163 
0164     /**
0165      * Check whether this MovingCursor is located at a valid text position.
0166      * A cursor position at (line, column) is valid, if
0167      * - line >= 0 and line < document()->lines() holds, and
0168      * - column >= 0 and column <= lineLength(column).
0169      *
0170      * Further, the text position is also invalid if it is inside a Unicode
0171      * surrogate (utf-32 character).
0172      *
0173      * \return \e true, if the cursor is a valid text position, otherwise \e false
0174      *
0175      * \see Document::isValidTextPosition()
0176      */
0177     bool isValidTextPosition() const;
0178 
0179     /**
0180      * \overload
0181      *
0182      * Set the cursor position to \e line and \e column.
0183      *
0184      * \param line new cursor line
0185      * \param column new cursor column
0186      */
0187     void setPosition(int line, int column);
0188 
0189     /**
0190      * Set the cursor line to \e line.
0191      * \param line new cursor line
0192      */
0193     void setLine(int line);
0194 
0195     /**
0196      * Set the cursor column to \e column.
0197      * \param column new cursor column
0198      */
0199     void setColumn(int column);
0200 
0201     /**
0202      * Determine if this cursor is located at column 0 of a valid text line.
0203      *
0204      * \return \e true if cursor is a valid text position and column()=0, otherwise \e false.
0205      */
0206     bool atStartOfLine() const;
0207 
0208     /**
0209      * Determine if this cursor is located at the end of the current line.
0210      *
0211      * \return \e true if the cursor is situated at the end of the line, otherwise \e false.
0212      */
0213     bool atEndOfLine() const;
0214 
0215     /**
0216      * Determine if this cursor is located at line 0 and column 0.
0217      *
0218      * \return \e true if the cursor is at start of the document, otherwise \e false.
0219      */
0220     bool atStartOfDocument() const;
0221 
0222     /**
0223      * Determine if this cursor is located at the end of the last line in the
0224      * document.
0225      *
0226      * \return \e true if the cursor is at the end of the document, otherwise \e false.
0227      */
0228     bool atEndOfDocument() const;
0229 
0230     /**
0231      * Moves the cursor to the next line and sets the column to 0. If the cursor
0232      * position is already in the last line of the document, the cursor position
0233      * remains unchanged and the return value is \e false.
0234      *
0235      * \return \e true on success, otherwise \e false
0236      */
0237     bool gotoNextLine();
0238 
0239     /**
0240      * Moves the cursor to the previous line and sets the column to 0. If the
0241      * cursor position is already in line 0, the cursor position remains
0242      * unchanged and the return value is \e false.
0243      *
0244      * \return \e true on success, otherwise \e false
0245      */
0246     bool gotoPreviousLine();
0247 
0248     /**
0249      * Moves the cursor \p chars character forward or backwards. If \e wrapBehavior
0250      * equals WrapBehavior::Wrap, the cursor is automatically wrapped to the
0251      * next line at the end of a line.
0252      *
0253      * When moving backwards, the WrapBehavior does not have any effect.
0254      * \note If the cursor could not be moved the amount of chars requested,
0255      *       the cursor is not moved at all!
0256      *
0257      * \return \e true on success, otherwise \e false
0258      */
0259     bool move(int chars, WrapBehavior wrapBehavior = Wrap);
0260 
0261     /**
0262      * Convert this clever cursor into a dumb one.
0263      * Even if this cursor belongs to a range, the created one not.
0264      * @return normal cursor
0265      */
0266     const Cursor toCursor() const
0267     {
0268         return Cursor(line(), column());
0269     }
0270 
0271     /**
0272      * Convert this clever cursor into a dumb one. Equal to toCursor, allowing to use implicit conversion.
0273      * Even if this cursor belongs to a range, the created one not.
0274      * @return normal cursor
0275      */
0276     operator Cursor() const
0277     {
0278         return Cursor(line(), column());
0279     }
0280 
0281     //
0282     // operators for: MovingCursor <-> MovingCursor
0283     //
0284     /**
0285      * Equality operator.
0286      *
0287      * \note comparison between two invalid cursors is undefined.
0288      *       comparison between an invalid and a valid cursor will always be \e false.
0289      *
0290      * \param c1 first cursor to compare
0291      * \param c2 second cursor to compare
0292      * \return \e true, if c1's and c2's line and column are \e equal.
0293      */
0294     inline friend bool operator==(const MovingCursor &c1, const MovingCursor &c2)
0295     {
0296         return c1.line() == c2.line() && c1.column() == c2.column();
0297     }
0298 
0299     /**
0300      * Inequality operator.
0301      * \param c1 first cursor to compare
0302      * \param c2 second cursor to compare
0303      * \return \e true, if c1's and c2's line and column are \e not equal.
0304      */
0305     inline friend bool operator!=(const MovingCursor &c1, const MovingCursor &c2)
0306     {
0307         return !(c1 == c2);
0308     }
0309 
0310     /**
0311      * Greater than operator.
0312      * \param c1 first cursor to compare
0313      * \param c2 second cursor to compare
0314      * \return \e true, if c1's position is greater than c2's position,
0315      *         otherwise \e false.
0316      */
0317     inline friend bool operator>(const MovingCursor &c1, const MovingCursor &c2)
0318     {
0319         return c1.line() > c2.line() || (c1.line() == c2.line() && c1.column() > c2.column());
0320     }
0321 
0322     /**
0323      * Greater than or equal to operator.
0324      * \param c1 first cursor to compare
0325      * \param c2 second cursor to compare
0326      * \return \e true, if c1's position is greater than or equal to c2's
0327      *         position, otherwise \e false.
0328      */
0329     inline friend bool operator>=(const MovingCursor &c1, const MovingCursor &c2)
0330     {
0331         return c1.line() > c2.line() || (c1.line() == c2.line() && c1.column() >= c2.column());
0332     }
0333 
0334     /**
0335      * Less than operator.
0336      * \param c1 first cursor to compare
0337      * \param c2 second cursor to compare
0338      * \return \e true, if c1's position is greater than or equal to c2's
0339      *         position, otherwise \e false.
0340      */
0341     inline friend bool operator<(const MovingCursor &c1, const MovingCursor &c2)
0342     {
0343         return !(c1 >= c2);
0344     }
0345 
0346     /**
0347      * Less than or equal to operator.
0348      * \param c1 first cursor to compare
0349      * \param c2 second cursor to compare
0350      * \return \e true, if c1's position is lesser than or equal to c2's
0351      *         position, otherwise \e false.
0352      */
0353     inline friend bool operator<=(const MovingCursor &c1, const MovingCursor &c2)
0354     {
0355         return !(c1 > c2);
0356     }
0357 };
0358 
0359 /**
0360  * qDebug() stream operator. Writes this cursor to the debug output in a nicely formatted way.
0361  * @param s debug stream
0362  * @param cursor cursor to print
0363  * @return debug stream
0364  */
0365 KTEXTEDITOR_EXPORT QDebug operator<<(QDebug s, const MovingCursor *cursor);
0366 
0367 /**
0368  * qDebug() stream operator. Writes this cursor to the debug output in a nicely formatted way.
0369  * @param s debug stream
0370  * @param cursor cursor to print
0371  * @return debug stream
0372  */
0373 KTEXTEDITOR_EXPORT QDebug operator<<(QDebug s, const MovingCursor &cursor);
0374 }
0375 
0376 #endif