KTextEditor

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

KDE's Doxygen guidelines are available online.