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