KTextEditor

cursor.h
1 /*
2  SPDX-FileCopyrightText: 2003-2005 Hamish Rodda <[email protected]>
3  SPDX-FileCopyrightText: 2001-2005 Christoph Cullmann <[email protected]>
4  SPDX-FileCopyrightText: 2014 Dominik Haumann <[email protected]>
5  SPDX-FileCopyrightText: 2002 Christian Couder <[email protected]>
6  SPDX-FileCopyrightText: 2001 Joseph Wenninger <[email protected]>
7  SPDX-FileCopyrightText: 1999 Jochen Wilhelmy <[email protected]>
8 
9  SPDX-License-Identifier: LGPL-2.0-or-later
10 */
11 
12 #ifndef KTEXTEDITOR_CURSOR_H
13 #define KTEXTEDITOR_CURSOR_H
14 
15 #include <ktexteditor_export.h>
16 
17 #include <QDebug>
18 #include <QtGlobal>
19 
20 namespace KTextEditor
21 {
22 class Document;
23 class Range;
24 
25 /**
26  * \class Cursor cursor.h <KTextEditor/Cursor>
27  *
28  * \short The Cursor represents a position in a Document.
29  *
30  * \section kte_cursor_intro Introduction
31  * A Cursor represents a position in a Document through a tuple
32  * of two int%s, namely the line() and column(). A Cursor maintains
33  * no affiliation with a particular Document, meaning that it remains
34  * constant if not changed through the Cursor API.
35  *
36  * \section kte_cursor_notes Important Notes
37  *
38  * Working with a cursor, one should be aware of the following notes:
39  * - Lines and columns start a 0.
40  * - The Cursor class is designed to be passed by value (only 8 Bytes).
41  * - Think of cursors as having their position at the start of a character,
42  * not in the middle of one.
43  * - invalid() Cursor%s are located at (-1, -1). In addition, a Cursor
44  * is invalid(), if either its line() and/or its column() is arbitrarily
45  * negative, i.e. < 0.
46  * - All Cursor%s with line() >= 0 and column() >= 0 are valid. In this case
47  * isValid() returns \e true.
48  * - A Cursor has a non-virtual destructor. Hence, you cannot derive from Cursor.
49  *
50  * \section kte_cursor_properties Cursor Efficiency
51  *
52  * The Cursor consists of just two int%s, the line() and the column().
53  * Therefore, a Cursor instance takes 8 Bytes of memory. Further, a Cursor
54  * is a non-virtual class, turning it into a primitive old data type (POD).
55  * Thus, it can be moved and copied very efficiently.
56  *
57  * \section kte_cursor_more Additional Concepts
58  *
59  * In addition to the Cursor, the KTextEditor API provides advanced concepts:
60  * - The DocumentCursor is a Cursor bound to a specific Document. In addition
61  * to the Cursor API, it provides convenience functions like
62  * DocumentCursor::isValidTextPosition() or DocumentCursor::move().
63  * The DocumentCursor does not maintain its position, though.
64  * - The MovingCursor is also bound to a specific Document. In addition to the
65  * DocumentCursor, the MovingCursor maintains its position, meaning that
66  * whenever the Document changes, the MovingCursor moves, too.
67  * - The Cursor forms the basis for the Range.
68  *
69  * \sa DocumentCursor, MovingCursor, Range
70  */
71 class KTEXTEDITOR_EXPORT Cursor
72 {
73 public:
74  /**
75  * The default constructor creates a cursor at position (0, 0).
76  */
77  Q_DECL_CONSTEXPR Cursor() Q_DECL_NOEXCEPT
78  {
79  }
80 
81  /**
82  * This constructor creates a cursor initialized with \p line
83  * and \p column.
84  * \param line line for cursor
85  * \param column column for cursor
86  */
87  Q_DECL_CONSTEXPR Cursor(int line, int column) Q_DECL_NOEXCEPT : m_line(line), m_column(column)
88  {
89  }
90 
91  /**
92  * Returns whether the current position of this cursor is a valid position
93  * (line + column must both be >= 0).
94  *
95  * @note If you want to check, whether a cursor position is a valid
96  * \e text-position, use DocumentCursor::isValidTextPosition(),
97  * or Document::isValidTextPosition().
98  */
99  Q_DECL_CONSTEXPR inline bool isValid() const Q_DECL_NOEXCEPT
100  {
101  return m_line >= 0 && m_column >= 0;
102  }
103 
104  /**
105  * Returns an invalid cursor.
106  * The returned cursor position is set to (-1, -1).
107  * \see isValid()
108  */
109  Q_DECL_CONSTEXPR static Cursor invalid() Q_DECL_NOEXCEPT
110  {
111  return Cursor(-1, -1);
112  }
113 
114  /**
115  * Returns a cursor representing the start of any document - i.e., line 0, column 0.
116  */
117  Q_DECL_CONSTEXPR static Cursor start() Q_DECL_NOEXCEPT
118  {
119  return Cursor();
120  }
121 
122  /**
123  * Returns the cursor position as string in the format "(line, column)".
124  * \see fromString()
125  */
127  {
128  return QLatin1Char('(') + QString::number(m_line) + QLatin1String(", ") + QString::number(m_column) + QLatin1Char(')');
129  }
130 
131 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
132  /**
133  * Returns a Cursor created from the string \p str containing the format
134  * "(line, column)". In case the string cannot be parsed, Cursor::invalid()
135  * is returned.
136  * \see toString()
137  */
138  // TODO KF6: Remove this overload in favor of fromString(QStringView).
139  static Cursor fromString(const QString &str) Q_DECL_NOEXCEPT
140  {
141  return fromString(str.leftRef(-1));
142  }
143 
144  /**
145  * Returns a Cursor created from the string \p str containing the format
146  * "(line, column)". In case the string cannot be parsed, Cursor::invalid()
147  * is returned.
148  * \see toString()
149  */
150  // TODO KF6: Remove this overload in favor of fromString(QStringView).
151  static Cursor fromString(const QStringRef &str) Q_DECL_NOEXCEPT;
152 #endif
153 
154  /**
155  * Returns a Cursor created from the string \p str containing the format
156  * "(line, column)". In case the string cannot be parsed, Cursor::invalid()
157  * is returned.
158  * \see toString()
159  */
160  static Cursor fromString(QStringView str) Q_DECL_NOEXCEPT;
161 
162  /**
163  * \name Position
164  *
165  * The following functions provide access to, and manipulation of, the cursor's position.
166  * \{
167  */
168  /**
169  * Set the current cursor position to \e position.
170  *
171  * \param position new cursor position
172  */
173  inline void setPosition(const Cursor &position) Q_DECL_NOEXCEPT
174  {
175  m_line = position.m_line;
176  m_column = position.m_column;
177  }
178 
179  /**
180  * \overload
181  *
182  * Set the cursor position to \e line and \e column.
183  *
184  * \param line new cursor line
185  * \param column new cursor column
186  */
187  inline void setPosition(int line, int column) Q_DECL_NOEXCEPT
188  {
189  m_line = line;
190  m_column = column;
191  }
192 
193  /**
194  * Retrieve the line on which this cursor is situated.
195  * \return line number, where 0 is the first line.
196  */
197  Q_DECL_CONSTEXPR inline int line() const Q_DECL_NOEXCEPT
198  {
199  return m_line;
200  }
201 
202  /**
203  * Set the cursor line to \e line.
204  * \param line new cursor line
205  */
206  inline void setLine(int line) Q_DECL_NOEXCEPT
207  {
208  m_line = line;
209  }
210 
211  /**
212  * Retrieve the column on which this cursor is situated.
213  * \return column number, where 0 is the first column.
214  */
215  Q_DECL_CONSTEXPR inline int column() const Q_DECL_NOEXCEPT
216  {
217  return m_column;
218  }
219 
220  /**
221  * Set the cursor column to \e column.
222  * \param column new cursor column
223  */
224  inline void setColumn(int column) Q_DECL_NOEXCEPT
225  {
226  m_column = column;
227  }
228 
229  /**
230  * Determine if this cursor is located at the start of a line (= at column 0).
231  * \return \e true if the cursor is situated at the start of the line, \e false if it isn't.
232  */
233  Q_DECL_CONSTEXPR inline bool atStartOfLine() const Q_DECL_NOEXCEPT
234  {
235  return m_column == 0;
236  }
237 
238  /**
239  * Determine if this cursor is located at the start of a document (= at position (0, 0)).
240  * \return \e true if the cursor is situated at the start of the document, \e false if it isn't.
241  */
242  Q_DECL_CONSTEXPR inline bool atStartOfDocument() const Q_DECL_NOEXCEPT
243  {
244  return m_line == 0 && m_column == 0;
245  }
246 
247  /**
248  * Get both the line and column of the cursor position.
249  * \param line will be filled with current cursor line
250  * \param column will be filled with current cursor column
251  */
252  inline void position(int &line, int &column) const Q_DECL_NOEXCEPT
253  {
254  line = m_line;
255  column = m_column;
256  }
257  //!\}
258 
259  /**
260  * Addition operator. Takes two cursors and returns their summation.
261  * \param c1 the first position
262  * \param c2 the second position
263  * \return a the summation of the two input cursors
264  */
265  Q_DECL_CONSTEXPR inline friend Cursor operator+(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
266  {
267  return Cursor(c1.line() + c2.line(), c1.column() + c2.column());
268  }
269 
270  /**
271  * Addition assignment operator. Adds \p c2 to this cursor.
272  * \param c1 the cursor being added to
273  * \param c2 the position to add
274  * \return a reference to the cursor which has just been added to
275  */
276  inline friend Cursor &operator+=(Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
277  {
278  c1.setPosition(c1.line() + c2.line(), c1.column() + c2.column());
279  return c1;
280  }
281 
282  /**
283  * Subtraction operator. Takes two cursors and returns the subtraction
284  * of \p c2 from \p c1.
285  *
286  * \param c1 the first position
287  * \param c2 the second position
288  * \return a cursor representing the subtraction of \p c2 from \p c1
289  */
290  Q_DECL_CONSTEXPR inline friend Cursor operator-(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
291  {
292  return Cursor(c1.line() - c2.line(), c1.column() - c2.column());
293  }
294 
295  /**
296  * Subtraction assignment operator. Subtracts \p c2 from \p c1.
297  * \param c1 the cursor being subtracted from
298  * \param c2 the position to subtract
299  * \return a reference to the cursor which has just been subtracted from
300  */
301  inline friend Cursor &operator-=(Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
302  {
303  c1.setPosition(c1.line() - c2.line(), c1.column() - c2.column());
304  return c1;
305  }
306 
307  /**
308  * Equality operator.
309  *
310  * \note comparison between two invalid cursors is undefined.
311  * comparison between and invalid and a valid cursor will always be \e false.
312  *
313  * \param c1 first cursor to compare
314  * \param c2 second cursor to compare
315  * \return \e true, if c1's and c2's line and column are \e equal.
316  */
317  Q_DECL_CONSTEXPR inline friend bool operator==(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
318  {
319  return c1.line() == c2.line() && c1.column() == c2.column();
320  }
321 
322  /**
323  * Inequality operator.
324  * \param c1 first cursor to compare
325  * \param c2 second cursor to compare
326  * \return \e true, if c1's and c2's line and column are \e not equal.
327  */
328  Q_DECL_CONSTEXPR inline friend bool operator!=(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
329  {
330  return !(c1 == c2);
331  }
332 
333  /**
334  * Greater than operator.
335  * \param c1 first cursor to compare
336  * \param c2 second cursor to compare
337  * \return \e true, if c1's position is greater than c2's position,
338  * otherwise \e false.
339  */
340  Q_DECL_CONSTEXPR inline friend bool operator>(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
341  {
342  return c1.line() > c2.line() || (c1.line() == c2.line() && c1.m_column > c2.m_column);
343  }
344 
345  /**
346  * Greater than or equal to operator.
347  * \param c1 first cursor to compare
348  * \param c2 second cursor to compare
349  * \return \e true, if c1's position is greater than or equal to c2's
350  * position, otherwise \e false.
351  */
352  Q_DECL_CONSTEXPR inline friend bool operator>=(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
353  {
354  return c1.line() > c2.line() || (c1.line() == c2.line() && c1.m_column >= c2.m_column);
355  }
356 
357  /**
358  * Less than operator.
359  * \param c1 first cursor to compare
360  * \param c2 second cursor to compare
361  * \return \e true, if c1's position is greater than or equal to c2's
362  * position, otherwise \e false.
363  */
364  Q_DECL_CONSTEXPR inline friend bool operator<(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
365  {
366  return !(c1 >= c2);
367  }
368 
369  /**
370  * Less than or equal to operator.
371  * \param c1 first cursor to compare
372  * \param c2 second cursor to compare
373  * \return \e true, if c1's position is lesser than or equal to c2's
374  * position, otherwise \e false.
375  */
376  Q_DECL_CONSTEXPR inline friend bool operator<=(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
377  {
378  return !(c1 > c2);
379  }
380 
381  /**
382  * qDebug() stream operator. Writes this cursor to the debug output in a nicely formatted way.
383  */
384  inline friend QDebug operator<<(QDebug s, const Cursor &cursor)
385  {
386  s.nospace() << "(" << cursor.line() << ", " << cursor.column() << ")";
387  return s.space();
388  }
389 
390 private:
391  /**
392  * \internal
393  *
394  * Cursor line
395  */
396  int m_line = 0;
397 
398  /**
399  * \internal
400  *
401  * Cursor column
402  */
403  int m_column = 0;
404 };
405 
406 } // namespace KTextEditor
407 
408 Q_DECLARE_TYPEINFO(KTextEditor::Cursor, Q_MOVABLE_TYPE);
409 Q_DECLARE_METATYPE(KTextEditor::Cursor)
410 
411 /**
412  * QHash function for KTextEditor::Cursor.
413  * Returns the hash value for @p cursor.
414  */
415 inline uint qHash(const KTextEditor::Cursor &cursor, uint seed = 0) Q_DECL_NOTHROW
416 {
417  return qHash(qMakePair(cursor.line(), cursor.column()), seed);
418 }
419 
420 namespace QTest
421 {
422 // forward declaration of template in qtestcase.h
423 template<typename T>
424 char *toString(const T &);
425 
426 /**
427  * QTestLib integration to have nice output in e.g. QCOMPARE failures.
428  */
429 template<>
430 KTEXTEDITOR_EXPORT char *toString(const KTextEditor::Cursor &cursor);
431 }
432 
433 #endif
constexpr Cursor(int line, int column) Q_DECL_NOEXCEPT
This constructor creates a cursor initialized with line and column.
Definition: cursor.h:87
constexpr int column() const Q_DECL_NOEXCEPT
Retrieve the column on which this cursor is situated.
Definition: cursor.h:215
QString number(int n, int base)
constexpr friend bool operator!=(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
Inequality operator.
Definition: cursor.h:328
QDebug & nospace()
void setPosition(int line, int column) Q_DECL_NOEXCEPT
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: cursor.h:187
constexpr Cursor() Q_DECL_NOEXCEPT
The default constructor creates a cursor at position (0, 0).
Definition: cursor.h:77
constexpr static Cursor invalid() Q_DECL_NOEXCEPT
Returns an invalid cursor.
Definition: cursor.h:109
void position(int &line, int &column) const Q_DECL_NOEXCEPT
Get both the line and column of the cursor position.
Definition: cursor.h:252
QDebug & space()
constexpr friend bool operator<(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
Less than operator.
Definition: cursor.h:364
constexpr friend Cursor operator-(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
Subtraction operator.
Definition: cursor.h:290
The Cursor represents a position in a Document.
Definition: cursor.h:71
char * toString(const T &value)
constexpr friend bool operator==(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
Equality operator.
Definition: cursor.h:317
void setLine(int line) Q_DECL_NOEXCEPT
Set the cursor line to line.
Definition: cursor.h:206
friend Cursor & operator-=(Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
Subtraction assignment operator.
Definition: cursor.h:301
KCALENDARCORE_EXPORT uint qHash(const KCalendarCore::Period &key)
void setColumn(int column) Q_DECL_NOEXCEPT
Set the cursor column to column.
Definition: cursor.h:224
constexpr static Cursor start() Q_DECL_NOEXCEPT
Returns a cursor representing the start of any document - i.e., line 0, column 0.
Definition: cursor.h:117
constexpr friend bool operator<=(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
Less than or equal to operator.
Definition: cursor.h:376
The KTextEditor namespace contains all the public API that is required to use the KTextEditor compone...
Definition: katetextblock.h:22
void setPosition(const Cursor &position) Q_DECL_NOEXCEPT
Set the current cursor position to position.
Definition: cursor.h:173
friend Cursor & operator+=(Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
Addition assignment operator.
Definition: cursor.h:276
constexpr friend bool operator>=(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
Greater than or equal to operator.
Definition: cursor.h:352
constexpr friend bool operator>(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
Greater than operator.
Definition: cursor.h:340
constexpr int line() const Q_DECL_NOEXCEPT
Retrieve the line on which this cursor is situated.
Definition: cursor.h:197
constexpr friend Cursor operator+(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
Addition operator.
Definition: cursor.h:265
constexpr bool isValid() const Q_DECL_NOEXCEPT
Returns whether the current position of this cursor is a valid position (line + column must both be >...
Definition: cursor.h:99
QString toString() const
Returns the cursor position as string in the format "(line, column)".
Definition: cursor.h:126
constexpr bool atStartOfLine() const Q_DECL_NOEXCEPT
Determine if this cursor is located at the start of a line (= at column 0).
Definition: cursor.h:233
friend QDebug operator<<(QDebug s, const Cursor &cursor)
qDebug() stream operator.
Definition: cursor.h:384
constexpr bool atStartOfDocument() const Q_DECL_NOEXCEPT
Determine if this cursor is located at the start of a document (= at position (0, 0)).
Definition: cursor.h:242
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Mar 27 2023 04:03:53 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.