File indexing completed on 2024-05-12 15:45:40
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/document.h> 0015 #include <ktexteditor_export.h> 0016 0017 #include <QDebug> 0018 0019 namespace KTextEditor 0020 { 0021 class MovingRange; 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(const 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 private: 0139 /** 0140 * no copy constructor, don't allow this to be copied. 0141 */ 0142 MovingCursor(const MovingCursor &); 0143 0144 /** 0145 * no assignment operator, no copying around clever cursors. 0146 */ 0147 MovingCursor &operator=(const MovingCursor &); 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 inline bool isValidTextPosition() const 0178 { 0179 return document()->isValidTextPosition(toCursor()); 0180 } 0181 0182 /** 0183 * \overload 0184 * 0185 * Set the cursor position to \e line and \e column. 0186 * 0187 * \param line new cursor line 0188 * \param column new cursor column 0189 */ 0190 void setPosition(int line, int column); 0191 0192 /** 0193 * Set the cursor line to \e line. 0194 * \param line new cursor line 0195 */ 0196 void setLine(int line); 0197 0198 /** 0199 * Set the cursor column to \e column. 0200 * \param column new cursor column 0201 */ 0202 void setColumn(int column); 0203 0204 /** 0205 * Determine if this cursor is located at column 0 of a valid text line. 0206 * 0207 * \return \e true if cursor is a valid text position and column()=0, otherwise \e false. 0208 */ 0209 bool atStartOfLine() const; 0210 0211 /** 0212 * Determine if this cursor is located at the end of the current line. 0213 * 0214 * \return \e true if the cursor is situated at the end of the line, otherwise \e false. 0215 */ 0216 bool atEndOfLine() const; 0217 0218 /** 0219 * Determine if this cursor is located at line 0 and column 0. 0220 * 0221 * \return \e true if the cursor is at start of the document, otherwise \e false. 0222 */ 0223 bool atStartOfDocument() const; 0224 0225 /** 0226 * Determine if this cursor is located at the end of the last line in the 0227 * document. 0228 * 0229 * \return \e true if the cursor is at the end of the document, otherwise \e false. 0230 */ 0231 bool atEndOfDocument() const; 0232 0233 /** 0234 * Moves the cursor to the next line and sets the column to 0. If the cursor 0235 * position is already in the last line of the document, the cursor position 0236 * remains unchanged and the return value is \e false. 0237 * 0238 * \return \e true on success, otherwise \e false 0239 */ 0240 bool gotoNextLine(); 0241 0242 /** 0243 * Moves the cursor to the previous line and sets the column to 0. If the 0244 * cursor position is already in line 0, the cursor position remains 0245 * unchanged and the return value is \e false. 0246 * 0247 * \return \e true on success, otherwise \e false 0248 */ 0249 bool gotoPreviousLine(); 0250 0251 /** 0252 * Moves the cursor \p chars character forward or backwards. If \e wrapBehavior 0253 * equals WrapBehavior::Wrap, the cursor is automatically wrapped to the 0254 * next line at the end of a line. 0255 * 0256 * When moving backwards, the WrapBehavior does not have any effect. 0257 * \note If the cursor could not be moved the amount of chars requested, 0258 * the cursor is not moved at all! 0259 * 0260 * \return \e true on success, otherwise \e false 0261 */ 0262 bool move(int chars, WrapBehavior wrapBehavior = Wrap); 0263 0264 /** 0265 * Convert this clever cursor into a dumb one. 0266 * Even if this cursor belongs to a range, the created one not. 0267 * @return normal cursor 0268 */ 0269 const Cursor toCursor() const 0270 { 0271 return Cursor(line(), column()); 0272 } 0273 0274 /** 0275 * Convert this clever cursor into a dumb one. Equal to toCursor, allowing to use implicit conversion. 0276 * Even if this cursor belongs to a range, the created one not. 0277 * @return normal cursor 0278 */ 0279 operator Cursor() const 0280 { 0281 return Cursor(line(), column()); 0282 } 0283 0284 // 0285 // operators for: MovingCursor <-> MovingCursor 0286 // 0287 /** 0288 * Equality operator. 0289 * 0290 * \note comparison between two invalid cursors is undefined. 0291 * comparison between an invalid and a valid cursor will always be \e false. 0292 * 0293 * \param c1 first cursor to compare 0294 * \param c2 second cursor to compare 0295 * \return \e true, if c1's and c2's line and column are \e equal. 0296 */ 0297 inline friend bool operator==(const MovingCursor &c1, const MovingCursor &c2) 0298 { 0299 return c1.line() == c2.line() && c1.column() == c2.column(); 0300 } 0301 0302 /** 0303 * Inequality operator. 0304 * \param c1 first cursor to compare 0305 * \param c2 second cursor to compare 0306 * \return \e true, if c1's and c2's line and column are \e not equal. 0307 */ 0308 inline friend bool operator!=(const MovingCursor &c1, const MovingCursor &c2) 0309 { 0310 return !(c1 == c2); 0311 } 0312 0313 /** 0314 * Greater than operator. 0315 * \param c1 first cursor to compare 0316 * \param c2 second cursor to compare 0317 * \return \e true, if c1's position is greater than c2's position, 0318 * otherwise \e false. 0319 */ 0320 inline friend bool operator>(const MovingCursor &c1, const MovingCursor &c2) 0321 { 0322 return c1.line() > c2.line() || (c1.line() == c2.line() && c1.column() > c2.column()); 0323 } 0324 0325 /** 0326 * Greater than or equal to operator. 0327 * \param c1 first cursor to compare 0328 * \param c2 second cursor to compare 0329 * \return \e true, if c1's position is greater than or equal to c2's 0330 * position, otherwise \e false. 0331 */ 0332 inline friend bool operator>=(const MovingCursor &c1, const MovingCursor &c2) 0333 { 0334 return c1.line() > c2.line() || (c1.line() == c2.line() && c1.column() >= c2.column()); 0335 } 0336 0337 /** 0338 * Less than operator. 0339 * \param c1 first cursor to compare 0340 * \param c2 second cursor to compare 0341 * \return \e true, if c1's position is greater than or equal to c2's 0342 * position, otherwise \e false. 0343 */ 0344 inline friend bool operator<(const MovingCursor &c1, const MovingCursor &c2) 0345 { 0346 return !(c1 >= c2); 0347 } 0348 0349 /** 0350 * Less than or equal to operator. 0351 * \param c1 first cursor to compare 0352 * \param c2 second cursor to compare 0353 * \return \e true, if c1's position is lesser than or equal to c2's 0354 * position, otherwise \e false. 0355 */ 0356 inline friend bool operator<=(const MovingCursor &c1, const MovingCursor &c2) 0357 { 0358 return !(c1 > c2); 0359 } 0360 0361 /** 0362 * qDebug() stream operator. Writes this cursor to the debug output in a nicely formatted way. 0363 * @param s debug stream 0364 * @param cursor cursor to print 0365 * @return debug stream 0366 */ 0367 inline friend QDebug operator<<(QDebug s, const MovingCursor *cursor) 0368 { 0369 if (cursor) { 0370 s.nospace() << "(" << cursor->line() << ", " << cursor->column() << ")"; 0371 } else { 0372 s.nospace() << "(null cursor)"; 0373 } 0374 return s.space(); 0375 } 0376 0377 /** 0378 * qDebug() stream operator. Writes this cursor to the debug output in a nicely formatted way. 0379 * @param s debug stream 0380 * @param cursor cursor to print 0381 * @return debug stream 0382 */ 0383 inline friend QDebug operator<<(QDebug s, const MovingCursor &cursor) 0384 { 0385 return s << &cursor; 0386 } 0387 }; 0388 0389 } 0390 0391 #endif