1/*
2 SPDX-FileCopyrightText: 2010 Christoph Cullmann <cullmann@kde.org>
3
4 Based on code of the SmartCursor/Range by:
5 SPDX-FileCopyrightText: 2003-2005 Hamish Rodda <rodda@kde.org>
6
7 SPDX-License-Identifier: LGPL-2.0-or-later
8*/
9
10#ifndef KATE_TEXTRANGE_H
11#define KATE_TEXTRANGE_H
12
13#include <ktexteditor/movingrange.h>
14
15#include "katetextcursor.h"
16
17namespace KTextEditor
18{
19class MovingRangeFeedback;
20class View;
21}
22
23namespace Kate
24{
25class TextBuffer;
26
27/**
28 * Class representing a 'clever' text range.
29 * It will automagically move if the text inside the buffer it belongs to is modified.
30 * By intention no subclass of KTextEditor::Range, must be converted manually.
31 *
32 * A TextRange is allowed to be empty. If you call setInvalidateIfEmpty(true),
33 * a TextRange will become automatically invalid as soon as start() == end()
34 * position holds.
35 */
36class TextRange final : public KTextEditor::MovingRange
37{
38 // this is a friend, block changes might invalidate ranges...
39 friend class TextBlock;
40 friend class TextBuffer;
41
42public:
43 /**
44 * Construct a text range.
45 *
46 * @param buffer parent text buffer
47 * @param range The initial text range assumed by the new range.
48 * @param insertBehavior Define whether the range should expand when text is inserted adjacent to the range.
49 * @param emptyBehavior Define whether the range should invalidate itself on becoming empty.
50 */
51 TextRange(TextBuffer *buffer, KTextEditor::Range range, InsertBehaviors insertBehavior, EmptyBehavior emptyBehavior = AllowEmpty);
52
53 /**
54 * No copy constructor, don't allow this to be copied.
55 */
56 TextRange(const TextRange &) = delete;
57
58 /**
59 * Destruct the text block
60 */
61 ~TextRange() override;
62
63 /**
64 * No assignment operator, no copying around.
65 */
66 TextRange &operator=(const TextRange &) = delete;
67
68 /**
69 * Set insert behaviors.
70 * @param insertBehaviors new insert behaviors
71 */
72 void setInsertBehaviors(InsertBehaviors insertBehaviors) override;
73
74 /**
75 * Get current insert behaviors.
76 * @return current insert behaviors
77 */
78 InsertBehaviors insertBehaviors() const override;
79
80 /**
81 * Set if this range will invalidate itself if it becomes empty.
82 * @param emptyBehavior behavior on becoming empty
83 */
84 void setEmptyBehavior(EmptyBehavior emptyBehavior) override;
85
86 /**
87 * Will this range invalidate itself if it becomes empty?
88 * @return behavior on becoming empty
89 */
90 EmptyBehavior emptyBehavior() const override
91 {
92 return m_invalidateIfEmpty ? InvalidateIfEmpty : AllowEmpty;
93 }
94
95 /**
96 * Gets the document to which this range is bound.
97 * \return a pointer to the document
98 */
99 KTextEditor::Document *document() const override;
100
101 /**
102 * Set the range of this range.
103 *
104 * @param range new range for this clever range
105 */
106 void setRange(KTextEditor::Range range) override;
107
108 /**
109 * \overload
110 * Set the range of this range
111 *
112 * @param start new start for this clever range
113 * @param end new end for this clever range
114 */
115 void setRange(KTextEditor::Cursor start, KTextEditor::Cursor end)
116 {
117 KTextEditor::MovingRange::setRange(start, end);
118 }
119
120 /**
121 * Set the range of this range and the connected attribute.
122 * Avoids internal overhead of separate setting that.
123 *
124 * @param range new range for this clever range
125 * @param attribute Attribute to assign to this range. If null, simply removes the previous Attribute.
126 *
127 * @since 6.0
128 */
129 void setRange(KTextEditor::Range range, KTextEditor::Attribute::Ptr attribute) override;
130
131 /**
132 * Set the range of this range and the connected attribute and Z-depth.
133 * Avoids internal overhead of separate setting that.
134 *
135 * @param range new range for this clever range
136 * @param attribute Attribute to assign to this range. If null, simply removes the previous Attribute.
137 * @param zDepth new Z-depth of this range
138 *
139 * @since 6.0
140 */
141 void setRange(KTextEditor::Range range, KTextEditor::Attribute::Ptr attribute, qreal zDepth) override;
142
143 /**
144 * Retrieve start cursor of this range, read-only.
145 * @return start cursor
146 */
147 const KTextEditor::MovingCursor &start() const override
148 {
149 return m_start;
150 }
151
152 /**
153 * Non-virtual version of start(), which is faster.
154 * @return start cursor
155 */
156 const TextCursor &startInternal() const
157 {
158 return m_start;
159 }
160
161 /**
162 * Retrieve end cursor of this range, read-only.
163 * @return end cursor
164 */
165 const KTextEditor::MovingCursor &end() const override
166 {
167 return m_end;
168 }
169
170 /**
171 * Nonvirtual version of end(), which is faster.
172 * @return end cursor
173 */
174 const TextCursor &endInternal() const
175 {
176 return m_end;
177 }
178
179 /**
180 * Hides parent's impl of toLineRange() and uses non-virtual functions internally.
181 */
182 KTextEditor::LineRange toLineRange() const
183 {
184 return {startInternal().lineInternal(), endInternal().lineInternal()};
185 }
186
187 /**
188 * Convert this clever range into a dumb one.
189 * @return normal range
190 */
191 const KTextEditor::Range toRange() const
192 {
193 auto startCursor = KTextEditor::Cursor(startInternal().lineInternal(), startInternal().columnInternal());
194 auto endCursor = KTextEditor::Cursor(endInternal().lineInternal(), endInternal().columnInternal());
195 return KTextEditor::Range(startCursor, endCursor);
196 }
197
198 /**
199 * Convert this clever range into a dumb one. Equal to toRange, allowing to use implicit conversion.
200 * @return normal range
201 */
202 operator KTextEditor::Range() const
203 {
204 return toRange();
205 }
206
207 /**
208 * Gets the active view for this range. Might be already invalid, internally only used for pointer comparisons.
209 *
210 * \return a pointer to the active view
211 */
212 KTextEditor::View *view() const override
213 {
214 return m_view;
215 }
216
217 /**
218 * Sets the currently active view for this range.
219 * This will trigger update of the relevant view parts, if the view changed.
220 * Set view before the attribute, that will avoid not needed redraws.
221 *
222 * \param view View to assign to this range. If null, simply
223 * removes the previous view.
224 */
225 void setView(KTextEditor::View *view) override;
226
227 /**
228 * Gets the active Attribute for this range.
229 *
230 * \return a pointer to the active attribute
231 */
232 const KTextEditor::Attribute::Ptr &attribute() const override
233 {
234 return m_attribute;
235 }
236
237 /**
238 * \return whether a nonzero attribute is set. This is faster than checking attribute(),
239 * because the reference-counting is omitted.
240 */
241 bool hasAttribute() const
242 {
243 return m_attribute.constData();
244 }
245
246 /**
247 * Sets the currently active attribute for this range.
248 * This will trigger update of the relevant view parts.
249 *
250 * \param attribute Attribute to assign to this range. If null, simply
251 * removes the previous Attribute.
252 */
253 void setAttribute(KTextEditor::Attribute::Ptr attribute) override;
254
255 /**
256 * Gets the active MovingRangeFeedback for this range.
257 *
258 * \return a pointer to the active MovingRangeFeedback
259 */
260 KTextEditor::MovingRangeFeedback *feedback() const override
261 {
262 return m_feedback;
263 }
264
265 /**
266 * Sets the currently active MovingRangeFeedback for this range.
267 * This will trigger evaluation if feedback must be send again (for example if mouse is already inside range).
268 *
269 * \param feedback MovingRangeFeedback to assign to this range. If null, simply
270 * removes the previous MovingRangeFeedback.
271 */
272 void setFeedback(KTextEditor::MovingRangeFeedback *feedback) override;
273
274 /**
275 * Is this range's attribute only visible in views, not for example prints?
276 * Default is false.
277 * @return range visible only for views
278 */
279 bool attributeOnlyForViews() const override
280 {
281 return m_attributeOnlyForViews;
282 }
283
284 /**
285 * Set if this range's attribute is only visible in views, not for example prints.
286 * @param onlyForViews attribute only valid for views
287 */
288 void setAttributeOnlyForViews(bool onlyForViews) override;
289
290 /**
291 * Gets the current Z-depth of this range.
292 * Ranges with smaller Z-depth than others will win during rendering.
293 * Default is 0.0.
294 *
295 * \return current Z-depth of this range
296 */
297 qreal zDepth() const override
298 {
299 return m_zDepth;
300 }
301
302 /**
303 * Set the current Z-depth of this range.
304 * Ranges with smaller Z-depth than others will win during rendering.
305 * This will trigger update of the relevant view parts, if the depth changed.
306 * Set depth before the attribute, that will avoid not needed redraws.
307 * Default is 0.0.
308 *
309 * \param zDepth new Z-depth of this range
310 */
311 void setZDepth(qreal zDepth) override;
312
313 bool spansMultipleBlocks() const
314 {
315 return m_start.m_block && m_end.m_block && m_start.m_block != m_end.m_block;
316 }
317
318private:
319 /**
320 * Check if range is valid, used by constructor and setRange.
321 * If at least one cursor is invalid, both will set to invalid.
322 * Same if range itself is invalid (start >= end).
323 *
324 * IMPORTANT: Notifications might need to deletion of this range!
325 *
326 * @param oldLineRange line range of this range before changing of cursors, needed to add/remove range from m_ranges in blocks, required!
327 * @param notifyAboutChange should feedback be emitted or not?
328 */
329 void checkValidity(bool notifyAboutChange = true);
330
331 /**
332 * Mark this range for later validity checking.
333 */
334 void setValidityCheckRequired()
335 {
336 m_isCheckValidityRequired = true;
337 }
338
339 /**
340 * Does this range need validity checking?
341 * @return is checking required?
342 */
343 bool isValidityCheckRequired() const
344 {
345 return m_isCheckValidityRequired;
346 }
347
348private:
349 /**
350 * parent text buffer
351 * is a reference, and no pointer, as this must always exist and can't change
352 */
353 TextBuffer *m_buffer;
354
355 /**
356 * Start cursor for this range, is a clever cursor
357 *
358 * Kate::TextBlock::mergeBlock needs m_start to come before m_end.
359 */
360 TextCursor m_start;
361
362 /**
363 * End cursor for this range, is a clever cursor
364 *
365 * Kate::TextBlock::mergeBlock needs m_end to come after m_start.
366 */
367 TextCursor m_end;
368
369 /**
370 * The view for which the attribute is valid, 0 means any view
371 */
372 KTextEditor::View *m_view;
373
374 /**
375 * This range's current attribute.
376 */
377 KTextEditor::Attribute::Ptr m_attribute;
378
379 /**
380 * pointer to the active MovingRangeFeedback
381 */
382 KTextEditor::MovingRangeFeedback *m_feedback;
383
384 /**
385 * Z-depth of this range for rendering
386 */
387 qreal m_zDepth;
388
389 /**
390 * Is this range's attribute only visible in views, not for example prints?
391 */
392 bool m_attributeOnlyForViews;
393
394 /**
395 * Will this range invalidate itself if it becomes empty?
396 */
397 bool m_invalidateIfEmpty;
398
399 /**
400 * Should this range be validated?
401 * Used by KateTextBlock to avoid multiple updates without costly hashing.
402 * Reset by checkValidity().
403 */
404 bool m_isCheckValidityRequired = false;
405};
406
407}
408
409#endif
410

source code of ktexteditor/src/buffer/katetextrange.h