File indexing completed on 2025-03-23 09:57:51
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 KATE_TEXTRANGE_H 0011 #define KATE_TEXTRANGE_H 0012 0013 #include <ktexteditor/movingrange.h> 0014 0015 #include "katetextcursor.h" 0016 #include <ktexteditor_export.h> 0017 0018 namespace KTextEditor 0019 { 0020 class MovingRangeFeedback; 0021 class View; 0022 } 0023 0024 namespace Kate 0025 { 0026 class TextBuffer; 0027 0028 /** 0029 * Class representing a 'clever' text range. 0030 * It will automagically move if the text inside the buffer it belongs to is modified. 0031 * By intention no subclass of KTextEditor::Range, must be converted manually. 0032 * A TextRange is allowed to be empty. If you call setInvalidateIfEmpty(true), 0033 * a TextRange will become automatically invalid as soon as start() == end() 0034 * position holds. 0035 */ 0036 class KTEXTEDITOR_EXPORT TextRange final : public KTextEditor::MovingRange 0037 { 0038 // this is a friend, block changes might invalidate ranges... 0039 friend class TextBlock; 0040 0041 public: 0042 /** 0043 * Construct a text range. 0044 * A TextRange is not allowed to be empty, as soon as start == end position, it will become 0045 * automatically invalid! 0046 * @param buffer parent text buffer 0047 * @param range The initial text range assumed by the new range. 0048 * @param insertBehavior Define whether the range should expand when text is inserted adjacent to the range. 0049 * @param emptyBehavior Define whether the range should invalidate itself on becoming empty. 0050 */ 0051 TextRange(TextBuffer &buffer, KTextEditor::Range range, InsertBehaviors insertBehavior, EmptyBehavior emptyBehavior = AllowEmpty); 0052 0053 /** 0054 * Destruct the text block 0055 */ 0056 ~TextRange() override; 0057 0058 /** 0059 * Set insert behaviors. 0060 * @param insertBehaviors new insert behaviors 0061 */ 0062 void setInsertBehaviors(InsertBehaviors insertBehaviors) override; 0063 0064 /** 0065 * Get current insert behaviors. 0066 * @return current insert behaviors 0067 */ 0068 InsertBehaviors insertBehaviors() const override; 0069 0070 /** 0071 * Set if this range will invalidate itself if it becomes empty. 0072 * @param emptyBehavior behavior on becoming empty 0073 */ 0074 void setEmptyBehavior(EmptyBehavior emptyBehavior) override; 0075 0076 /** 0077 * Will this range invalidate itself if it becomes empty? 0078 * @return behavior on becoming empty 0079 */ 0080 EmptyBehavior emptyBehavior() const override 0081 { 0082 return m_invalidateIfEmpty ? InvalidateIfEmpty : AllowEmpty; 0083 } 0084 0085 /** 0086 * Gets the document to which this range is bound. 0087 * \return a pointer to the document 0088 */ 0089 KTextEditor::Document *document() const override; 0090 0091 /** 0092 * Set the range of this range. 0093 * A TextRange is not allowed to be empty, as soon as start == end position, it will become 0094 * automatically invalid! 0095 * @param range new range for this clever range 0096 */ 0097 void setRange(const KTextEditor::Range &range) override; 0098 0099 /** 0100 * \overload 0101 * Set the range of this range 0102 * A TextRange is not allowed to be empty, as soon as start == end position, it will become 0103 * automatically invalid! 0104 * @param start new start for this clever range 0105 * @param end new end for this clever range 0106 */ 0107 void setRange(const KTextEditor::Cursor &start, const KTextEditor::Cursor &end) 0108 { 0109 KTextEditor::MovingRange::setRange(start, end); 0110 } 0111 0112 /** 0113 * Retrieve start cursor of this range, read-only. 0114 * @return start cursor 0115 */ 0116 const KTextEditor::MovingCursor &start() const override 0117 { 0118 return m_start; 0119 } 0120 0121 /** 0122 * Non-virtual version of start(), which is faster. 0123 * @return start cursor 0124 */ 0125 const TextCursor &startInternal() const 0126 { 0127 return m_start; 0128 } 0129 0130 /** 0131 * Retrieve end cursor of this range, read-only. 0132 * @return end cursor 0133 */ 0134 const KTextEditor::MovingCursor &end() const override 0135 { 0136 return m_end; 0137 } 0138 0139 /** 0140 * Nonvirtual version of end(), which is faster. 0141 * @return end cursor 0142 */ 0143 const TextCursor &endInternal() const 0144 { 0145 return m_end; 0146 } 0147 0148 /** 0149 * Hides parent's impl of toLineRange() and uses non-virtual functions internally. 0150 */ 0151 KTextEditor::LineRange toLineRange() const 0152 { 0153 return {startInternal().lineInternal(), endInternal().lineInternal()}; 0154 } 0155 0156 /** 0157 * Convert this clever range into a dumb one. 0158 * @return normal range 0159 */ 0160 const KTextEditor::Range toRange() const 0161 { 0162 auto startCursor = KTextEditor::Cursor(startInternal().lineInternal(), startInternal().columnInternal()); 0163 auto endCursor = KTextEditor::Cursor(endInternal().lineInternal(), endInternal().columnInternal()); 0164 return KTextEditor::Range(startCursor, endCursor); 0165 } 0166 0167 /** 0168 * Convert this clever range into a dumb one. Equal to toRange, allowing to use implicit conversion. 0169 * @return normal range 0170 */ 0171 operator KTextEditor::Range() const 0172 { 0173 return toRange(); 0174 } 0175 0176 /** 0177 * Gets the active view for this range. Might be already invalid, internally only used for pointer comparisons. 0178 * 0179 * \return a pointer to the active view 0180 */ 0181 KTextEditor::View *view() const override 0182 { 0183 return m_view; 0184 } 0185 0186 /** 0187 * Sets the currently active view for this range. 0188 * This will trigger update of the relevant view parts, if the view changed. 0189 * Set view before the attribute, that will avoid not needed redraws. 0190 * 0191 * \param view View to assign to this range. If null, simply 0192 * removes the previous view. 0193 */ 0194 void setView(KTextEditor::View *view) override; 0195 0196 /** 0197 * Gets the active Attribute for this range. 0198 * 0199 * \return a pointer to the active attribute 0200 */ 0201 KTextEditor::Attribute::Ptr attribute() const override 0202 { 0203 return m_attribute; 0204 } 0205 0206 /** 0207 * \return whether a nonzero attribute is set. This is faster than checking attribute(), 0208 * because the reference-counting is omitted. 0209 */ 0210 bool hasAttribute() const 0211 { 0212 return m_attribute.constData(); 0213 } 0214 0215 /** 0216 * Sets the currently active attribute for this range. 0217 * This will trigger update of the relevant view parts. 0218 * 0219 * \param attribute Attribute to assign to this range. If null, simply 0220 * removes the previous Attribute. 0221 */ 0222 void setAttribute(KTextEditor::Attribute::Ptr attribute) override; 0223 0224 /** 0225 * Gets the active MovingRangeFeedback for this range. 0226 * 0227 * \return a pointer to the active MovingRangeFeedback 0228 */ 0229 KTextEditor::MovingRangeFeedback *feedback() const override 0230 { 0231 return m_feedback; 0232 } 0233 0234 /** 0235 * Sets the currently active MovingRangeFeedback for this range. 0236 * This will trigger evaluation if feedback must be send again (for example if mouse is already inside range). 0237 * 0238 * \param feedback MovingRangeFeedback to assign to this range. If null, simply 0239 * removes the previous MovingRangeFeedback. 0240 */ 0241 void setFeedback(KTextEditor::MovingRangeFeedback *feedback) override; 0242 0243 /** 0244 * Is this range's attribute only visible in views, not for example prints? 0245 * Default is false. 0246 * @return range visible only for views 0247 */ 0248 bool attributeOnlyForViews() const override 0249 { 0250 return m_attributeOnlyForViews; 0251 } 0252 0253 /** 0254 * Set if this range's attribute is only visible in views, not for example prints. 0255 * @param onlyForViews attribute only valid for views 0256 */ 0257 void setAttributeOnlyForViews(bool onlyForViews) override; 0258 0259 /** 0260 * Gets the current Z-depth of this range. 0261 * Ranges with smaller Z-depth than others will win during rendering. 0262 * Default is 0.0. 0263 * 0264 * \return current Z-depth of this range 0265 */ 0266 qreal zDepth() const override 0267 { 0268 return m_zDepth; 0269 } 0270 0271 /** 0272 * Set the current Z-depth of this range. 0273 * Ranges with smaller Z-depth than others will win during rendering. 0274 * This will trigger update of the relevant view parts, if the depth changed. 0275 * Set depth before the attribute, that will avoid not needed redraws. 0276 * Default is 0.0. 0277 * 0278 * \param zDepth new Z-depth of this range 0279 */ 0280 void setZDepth(qreal zDepth) override; 0281 0282 private: 0283 /** 0284 * no copy constructor, don't allow this to be copied. 0285 */ 0286 TextRange(const TextRange &) = delete; 0287 0288 /** 0289 * no assignment operator, no copying around. 0290 */ 0291 TextRange &operator=(const TextRange &) = delete; 0292 0293 /** 0294 * Check if range is valid, used by constructor and setRange. 0295 * If at least one cursor is invalid, both will set to invalid. 0296 * Same if range itself is invalid (start >= end). 0297 * 0298 * IMPORTANT: Notifications might need to deletion of this range! 0299 * 0300 * @param oldLineRange line range of this range before changing of cursors, needed to add/remove range from m_ranges in blocks, required! 0301 * @param notifyAboutChange should feedback be emitted or not? 0302 */ 0303 KTEXTEDITOR_NO_EXPORT 0304 void checkValidity(KTextEditor::LineRange oldLineRange, bool notifyAboutChange = true); 0305 0306 /** 0307 * Add/Remove range from the lookup m_ranges hash of each block 0308 * @param oldLineRange old line range before changing of cursors, needed to add/remove range from m_ranges in blocks 0309 * @param lineRange line range to start looking for the range to remove 0310 */ 0311 KTEXTEDITOR_NO_EXPORT 0312 void fixLookup(KTextEditor::LineRange oldLineRange, KTextEditor::LineRange lineRange); 0313 0314 /** 0315 * Mark this range for later validity checking. 0316 */ 0317 void setValidityCheckRequired() 0318 { 0319 m_isCheckValidityRequired = true; 0320 } 0321 0322 /** 0323 * Does this range need validity checking? 0324 * @return is checking required? 0325 */ 0326 bool isValidityCheckRequired() const 0327 { 0328 return m_isCheckValidityRequired; 0329 } 0330 0331 private: 0332 /** 0333 * parent text buffer 0334 * is a reference, and no pointer, as this must always exist and can't change 0335 */ 0336 TextBuffer &m_buffer; 0337 0338 /** 0339 * Start cursor for this range, is a clever cursor 0340 */ 0341 TextCursor m_start; 0342 0343 /** 0344 * End cursor for this range, is a clever cursor 0345 */ 0346 TextCursor m_end; 0347 0348 /** 0349 * The view for which the attribute is valid, 0 means any view 0350 */ 0351 KTextEditor::View *m_view; 0352 0353 /** 0354 * This range's current attribute. 0355 */ 0356 KTextEditor::Attribute::Ptr m_attribute; 0357 0358 /** 0359 * pointer to the active MovingRangeFeedback 0360 */ 0361 KTextEditor::MovingRangeFeedback *m_feedback; 0362 0363 /** 0364 * Z-depth of this range for rendering 0365 */ 0366 qreal m_zDepth; 0367 0368 /** 0369 * Is this range's attribute only visible in views, not for example prints? 0370 */ 0371 bool m_attributeOnlyForViews; 0372 0373 /** 0374 * Will this range invalidate itself if it becomes empty? 0375 */ 0376 bool m_invalidateIfEmpty; 0377 0378 /** 0379 * Should this range be validated? 0380 * Used by KateTextBlock to avoid multiple updates without costly hashing. 0381 * Reset by checkValidity(). 0382 */ 0383 bool m_isCheckValidityRequired = false; 0384 }; 0385 0386 } 0387 0388 #endif