File indexing completed on 2024-04-21 15:03:34

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