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  /**
132  * Returns a Cursor created from the string \p str containing the format
133  * "(line, column)". In case the string cannot be parsed, Cursor::invalid()
134  * is returned.
135  * \see toString()
136  */
137  // TODO KF6: Remove this overload in favor of fromString(QStringView).
138  static Cursor fromString(const QString &str) Q_DECL_NOEXCEPT
139  {
140  return fromString(str.leftRef(-1));
141  }
142 
143  /**
144  * Returns a Cursor created from the string \p str containing the format
145  * "(line, column)". In case the string cannot be parsed, Cursor::invalid()
146  * is returned.
147  * \see toString()
148  */
149  // TODO KF6: Remove this overload in favor of fromString(QStringView).
150  static Cursor fromString(const QStringRef &str) Q_DECL_NOEXCEPT;
151 
152  /**
153  * Returns a Cursor created from the string \p str containing the format
154  * "(line, column)". In case the string cannot be parsed, Cursor::invalid()
155  * is returned.
156  * \see toString()
157  */
158  static Cursor fromString(QStringView str) Q_DECL_NOEXCEPT;
159 
160  /**
161  * \name Position
162  *
163  * The following functions provide access to, and manipulation of, the cursor's position.
164  * \{
165  */
166  /**
167  * Set the current cursor position to \e position.
168  *
169  * \param position new cursor position
170  */
171  inline void setPosition(const Cursor &position) Q_DECL_NOEXCEPT
172  {
173  m_line = position.m_line;
174  m_column = position.m_column;
175  }
176 
177  /**
178  * \overload
179  *
180  * Set the cursor position to \e line and \e column.
181  *
182  * \param line new cursor line
183  * \param column new cursor column
184  */
185  inline void setPosition(int line, int column) Q_DECL_NOEXCEPT
186  {
187  m_line = line;
188  m_column = column;
189  }
190 
191  /**
192  * Retrieve the line on which this cursor is situated.
193  * \return line number, where 0 is the first line.
194  */
195  Q_DECL_CONSTEXPR inline int line() const Q_DECL_NOEXCEPT
196  {
197  return m_line;
198  }
199 
200  /**
201  * Set the cursor line to \e line.
202  * \param line new cursor line
203  */
204  inline void setLine(int line) Q_DECL_NOEXCEPT
205  {
206  m_line = line;
207  }
208 
209  /**
210  * Retrieve the column on which this cursor is situated.
211  * \return column number, where 0 is the first column.
212  */
213  Q_DECL_CONSTEXPR inline int column() const Q_DECL_NOEXCEPT
214  {
215  return m_column;
216  }
217 
218  /**
219  * Set the cursor column to \e column.
220  * \param column new cursor column
221  */
222  inline void setColumn(int column) Q_DECL_NOEXCEPT
223  {
224  m_column = column;
225  }
226 
227  /**
228  * Determine if this cursor is located at the start of a line (= at column 0).
229  * \return \e true if the cursor is situated at the start of the line, \e false if it isn't.
230  */
231  Q_DECL_CONSTEXPR inline bool atStartOfLine() const Q_DECL_NOEXCEPT
232  {
233  return m_column == 0;
234  }
235 
236  /**
237  * Determine if this cursor is located at the start of a document (= at position (0, 0)).
238  * \return \e true if the cursor is situated at the start of the document, \e false if it isn't.
239  */
240  Q_DECL_CONSTEXPR inline bool atStartOfDocument() const Q_DECL_NOEXCEPT
241  {
242  return m_line == 0 && m_column == 0;
243  }
244 
245  /**
246  * Get both the line and column of the cursor position.
247  * \param line will be filled with current cursor line
248  * \param column will be filled with current cursor column
249  */
250  inline void position(int &line, int &column) const Q_DECL_NOEXCEPT
251  {
252  line = m_line;
253  column = m_column;
254  }
255  //!\}
256 
257  /**
258  * Addition operator. Takes two cursors and returns their summation.
259  * \param c1 the first position
260  * \param c2 the second position
261  * \return a the summation of the two input cursors
262  */
263  Q_DECL_CONSTEXPR inline friend Cursor operator+(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
264  {
265  return Cursor(c1.line() + c2.line(), c1.column() + c2.column());
266  }
267 
268  /**
269  * Addition assignment operator. Adds \p c2 to this cursor.
270  * \param c1 the cursor being added to
271  * \param c2 the position to add
272  * \return a reference to the cursor which has just been added to
273  */
274  inline friend Cursor &operator+=(Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
275  {
276  c1.setPosition(c1.line() + c2.line(), c1.column() + c2.column());
277  return c1;
278  }
279 
280  /**
281  * Subtraction operator. Takes two cursors and returns the subtraction
282  * of \p c2 from \p c1.
283  *
284  * \param c1 the first position
285  * \param c2 the second position
286  * \return a cursor representing the subtraction of \p c2 from \p c1
287  */
288  Q_DECL_CONSTEXPR inline friend Cursor operator-(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
289  {
290  return Cursor(c1.line() - c2.line(), c1.column() - c2.column());
291  }
292 
293  /**
294  * Subtraction assignment operator. Subtracts \p c2 from \p c1.
295  * \param c1 the cursor being subtracted from
296  * \param c2 the position to subtract
297  * \return a reference to the cursor which has just been subtracted from
298  */
299  inline friend Cursor &operator-=(Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
300  {
301  c1.setPosition(c1.line() - c2.line(), c1.column() - c2.column());
302  return c1;
303  }
304 
305  /**
306  * Equality operator.
307  *
308  * \note comparison between two invalid cursors is undefined.
309  * comparison between and invalid and a valid cursor will always be \e false.
310  *
311  * \param c1 first cursor to compare
312  * \param c2 second cursor to compare
313  * \return \e true, if c1's and c2's line and column are \e equal.
314  */
315  Q_DECL_CONSTEXPR inline friend bool operator==(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
316  {
317  return c1.line() == c2.line() && c1.column() == c2.column();
318  }
319 
320  /**
321  * Inequality operator.
322  * \param c1 first cursor to compare
323  * \param c2 second cursor to compare
324  * \return \e true, if c1's and c2's line and column are \e not equal.
325  */
326  Q_DECL_CONSTEXPR inline friend bool operator!=(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
327  {
328  return !(c1 == c2);
329  }
330 
331  /**
332  * Greater than operator.
333  * \param c1 first cursor to compare
334  * \param c2 second cursor to compare
335  * \return \e true, if c1's position is greater than c2's position,
336  * otherwise \e false.
337  */
338  Q_DECL_CONSTEXPR inline friend bool operator>(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
339  {
340  return c1.line() > c2.line() || (c1.line() == c2.line() && c1.m_column > c2.m_column);
341  }
342 
343  /**
344  * Greater than or equal to operator.
345  * \param c1 first cursor to compare
346  * \param c2 second cursor to compare
347  * \return \e true, if c1's position is greater than or equal to c2's
348  * position, otherwise \e false.
349  */
350  Q_DECL_CONSTEXPR inline friend bool operator>=(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
351  {
352  return c1.line() > c2.line() || (c1.line() == c2.line() && c1.m_column >= c2.m_column);
353  }
354 
355  /**
356  * Less than operator.
357  * \param c1 first cursor to compare
358  * \param c2 second cursor to compare
359  * \return \e true, if c1's position is greater than or equal to c2's
360  * position, otherwise \e false.
361  */
362  Q_DECL_CONSTEXPR inline friend bool operator<(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
363  {
364  return !(c1 >= c2);
365  }
366 
367  /**
368  * Less than or equal to operator.
369  * \param c1 first cursor to compare
370  * \param c2 second cursor to compare
371  * \return \e true, if c1's position is lesser than or equal to c2's
372  * position, otherwise \e false.
373  */
374  Q_DECL_CONSTEXPR inline friend bool operator<=(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
375  {
376  return !(c1 > c2);
377  }
378 
379  /**
380  * qDebug() stream operator. Writes this cursor to the debug output in a nicely formatted way.
381  */
382  inline friend QDebug operator<<(QDebug s, const Cursor &cursor)
383  {
384  s.nospace() << "(" << cursor.line() << ", " << cursor.column() << ")";
385  return s.space();
386  }
387 
388 private:
389  /**
390  * \internal
391  *
392  * Cursor line
393  */
394  int m_line = 0;
395 
396  /**
397  * \internal
398  *
399  * Cursor column
400  */
401  int m_column = 0;
402 };
403 
404 } // namespace KTextEditor
405 
406 Q_DECLARE_TYPEINFO(KTextEditor::Cursor, Q_MOVABLE_TYPE);
407 Q_DECLARE_METATYPE(KTextEditor::Cursor)
408 
409 /**
410  * QHash function for KTextEditor::Cursor.
411  * Returns the hash value for @p cursor.
412  */
413 inline uint qHash(const KTextEditor::Cursor &cursor, uint seed = 0) Q_DECL_NOTHROW
414 {
415  return qHash(qMakePair(cursor.line(), cursor.column()), seed);
416 }
417 
418 namespace QTest
419 {
420 // forward declaration of template in qtestcase.h
421 template<typename T>
422 char *toString(const T &);
423 
424 /**
425  * QTestLib integration to have nice output in e.g. QCOMPARE failures.
426  */
427 template<>
428 KTEXTEDITOR_EXPORT char *toString(const KTextEditor::Cursor &cursor);
429 }
430 
431 #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:213
QString number(int n, int base)
constexpr friend bool operator!=(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
Inequality operator.
Definition: cursor.h:326
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:185
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:250
QDebug & space()
constexpr friend bool operator<(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
Less than operator.
Definition: cursor.h:362
constexpr friend Cursor operator-(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
Subtraction operator.
Definition: cursor.h:288
The Cursor represents a position in a Document.
Definition: cursor.h:71
constexpr friend bool operator==(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
Equality operator.
Definition: cursor.h:315
void setLine(int line) Q_DECL_NOEXCEPT
Set the cursor line to line.
Definition: cursor.h:204
friend Cursor & operator-=(Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
Subtraction assignment operator.
Definition: cursor.h:299
KCALENDARCORE_EXPORT uint qHash(const KCalendarCore::Period &key)
void setColumn(int column) Q_DECL_NOEXCEPT
Set the cursor column to column.
Definition: cursor.h:222
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:374
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:171
friend Cursor & operator+=(Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
Addition assignment operator.
Definition: cursor.h:274
constexpr friend bool operator>=(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
Greater than or equal to operator.
Definition: cursor.h:350
constexpr friend bool operator>(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
Greater than operator.
Definition: cursor.h:338
constexpr int line() const Q_DECL_NOEXCEPT
Retrieve the line on which this cursor is situated.
Definition: cursor.h:195
constexpr friend Cursor operator+(const Cursor &c1, const Cursor &c2) Q_DECL_NOEXCEPT
Addition operator.
Definition: cursor.h:263
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:231
friend QDebug operator<<(QDebug s, const Cursor &cursor)
qDebug() stream operator.
Definition: cursor.h:382
char * toString(const EngineQuery &query)
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:240
static Cursor fromString(const QString &str) Q_DECL_NOEXCEPT
Returns a Cursor created from the string str containing the format "(line, column)".
Definition: cursor.h:138
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Tue Oct 3 2023 03:49:34 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.