File indexing completed on 2023-09-24 04:11:27
0001 /* 0002 SPDX-FileCopyrightText: 2010 Christoph Cullmann <cullmann@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #ifndef KATE_TEXTBLOCK_H 0008 #define KATE_TEXTBLOCK_H 0009 0010 #include "katetextline.h" 0011 0012 #include <unordered_map> 0013 #include <unordered_set> 0014 0015 #include <QSet> 0016 #include <QVarLengthArray> 0017 #include <QVector> 0018 0019 #include <ktexteditor/cursor.h> 0020 #include <ktexteditor_export.h> 0021 0022 namespace KTextEditor 0023 { 0024 class View; 0025 } 0026 0027 namespace Kate 0028 { 0029 class TextBuffer; 0030 class TextCursor; 0031 class TextRange; 0032 class TextLineData; 0033 typedef std::shared_ptr<TextLineData> TextLine; 0034 0035 /** 0036 * Class representing a text block. 0037 * This is used to build up a Kate::TextBuffer. 0038 * This class should only be used by TextBuffer/Cursor/Range. 0039 */ 0040 class KTEXTEDITOR_EXPORT TextBlock 0041 { 0042 public: 0043 /** 0044 * Construct an empty text block. 0045 * @param buffer parent text buffer 0046 * @param startLine start line of this block 0047 */ 0048 TextBlock(TextBuffer *buffer, int startLine); 0049 0050 /** 0051 * Destruct the text block 0052 */ 0053 ~TextBlock(); 0054 0055 /** 0056 * Start line of this block. 0057 * @return start line of this block 0058 */ 0059 int startLine() const 0060 { 0061 return m_startLine; 0062 } 0063 0064 /** 0065 * Set start line of this block. 0066 * @param startLine new start line of this block 0067 */ 0068 void setStartLine(int startLine); 0069 0070 /** 0071 * Retrieve a text line. 0072 * @param line wanted line number 0073 * @return text line 0074 */ 0075 TextLine line(int line) const; 0076 0077 /** 0078 * Retrieve length for @p line. 0079 * @param line wanted line number 0080 * @return length of line 0081 */ 0082 int lineLength(int line) const 0083 { 0084 Q_ASSERT(line >= startLine() && (line - startLine()) < lines()); 0085 return m_lines[line - startLine()]->length(); 0086 } 0087 0088 /** 0089 * Append a new line with given text. 0090 * @param textOfLine text of the line to append 0091 */ 0092 void appendLine(const QString &textOfLine); 0093 0094 /** 0095 * Clear the lines. 0096 */ 0097 void clearLines(); 0098 0099 /** 0100 * Number of lines in this block. 0101 * @return number of lines 0102 */ 0103 int lines() const 0104 { 0105 return static_cast<int>(m_lines.size()); 0106 } 0107 0108 /** 0109 * Retrieve text of block. 0110 * @param text for this block, lines separated by '\n' 0111 */ 0112 void text(QString &text) const; 0113 0114 /** 0115 * Wrap line at given cursor position. 0116 * @param position line/column as cursor where to wrap 0117 * @param fixStartLinesStartIndex start index to fix start lines, normally this is this block 0118 */ 0119 void wrapLine(const KTextEditor::Cursor position, int fixStartLinesStartIndex); 0120 0121 /** 0122 * Unwrap given line. 0123 * @param line line to unwrap 0124 * @param previousBlock previous block, if any, if we unwrap first line in block, we need to have this 0125 * @param fixStartLinesStartIndex start index to fix start lines, normally this is this block or the previous one 0126 */ 0127 void unwrapLine(int line, TextBlock *previousBlock, int fixStartLinesStartIndex); 0128 0129 /** 0130 * Insert text at given cursor position. 0131 * @param position position where to insert text 0132 * @param text text to insert 0133 */ 0134 void insertText(const KTextEditor::Cursor position, const QString &text); 0135 0136 /** 0137 * Remove text at given range. 0138 * @param range range of text to remove, must be on one line only. 0139 * @param removedText will be filled with removed text 0140 */ 0141 void removeText(KTextEditor::Range range, QString &removedText); 0142 0143 /** 0144 * Debug output, print whole block content with line numbers and line length 0145 * @param blockIndex index of this block in buffer 0146 */ 0147 void debugPrint(int blockIndex) const; 0148 0149 /** 0150 * Split given block. A new block will be created and all lines starting from the given index will 0151 * be moved to it, together with the cursors belonging to it. 0152 * @param fromLine line from which to split 0153 * @return new block containing the lines + cursors removed from this one 0154 */ 0155 TextBlock *splitBlock(int fromLine); 0156 0157 /** 0158 * Merge this block with given one, the given one must be a direct predecessor. 0159 * @param targetBlock block to merge with 0160 */ 0161 void mergeBlock(TextBlock *targetBlock); 0162 0163 /** 0164 * Delete the block content, delete all lines and delete all cursors not bound to ranges. 0165 * This is used in destructor of TextBuffer, for fast cleanup. Only stuff remaining afterwards are cursors which are 0166 * part of a range, TextBuffer will delete them itself... 0167 */ 0168 void deleteBlockContent(); 0169 0170 /** 0171 * Clear the block content, delete all lines, move all cursors not bound to range to given block at 0,0. 0172 * This is used by clear() of TextBuffer. 0173 * @param targetBlock empty target block for cursors 0174 */ 0175 void clearBlockContent(TextBlock *targetBlock); 0176 0177 /** 0178 * Return all ranges in this block which might intersect the given line. 0179 * @param line line to check intersection 0180 * @param view only return ranges associated with given view 0181 * @param rangesWithAttributeOnly ranges with attributes only? 0182 * @return list of possible candidate ranges 0183 */ 0184 QVector<TextRange *> rangesForLine(int line, KTextEditor::View *view, bool rangesWithAttributeOnly) const; 0185 0186 /** 0187 * Is the given range contained in this block? 0188 * @param range range to check for 0189 * @return contained in this blocks mapping? 0190 */ 0191 bool containsRange(TextRange *range) const 0192 { 0193 return m_cachedLineForRanges.find(range) != m_cachedLineForRanges.end() || m_uncachedRanges.contains(range); 0194 } 0195 0196 /** 0197 * Flag all modified text lines as saved on disk. 0198 */ 0199 void markModifiedLinesAsSaved(); 0200 0201 /** 0202 * Insert cursor into this block. 0203 * @param cursor cursor to insert 0204 */ 0205 void insertCursor(Kate::TextCursor *cursor) 0206 { 0207 m_cursors.insert(cursor); 0208 } 0209 0210 /** 0211 * Remove cursor from this block. 0212 * @param cursor cursor to remove 0213 */ 0214 void removeCursor(Kate::TextCursor *cursor) 0215 { 0216 m_cursors.erase(cursor); 0217 } 0218 0219 /** 0220 * Update a range from this block. 0221 * Will move the range to right set, either cached for one-line ranges or not. 0222 * @param range range to update 0223 */ 0224 void updateRange(TextRange *range); 0225 0226 /** 0227 * Remove a range from this block. 0228 * @param range range to remove 0229 */ 0230 void removeRange(TextRange *range); 0231 0232 /** 0233 * Return all ranges in this block which might intersect the given line and only span one line. 0234 * For them an internal fast lookup cache is hold. 0235 * @param line line to check intersection 0236 * @return set of ranges 0237 */ 0238 QSet<TextRange *> cachedRangesForLine(int line) const 0239 { 0240 line -= m_startLine; 0241 if (line >= 0 && (size_t)line < m_cachedRangesForLine.size()) { 0242 return m_cachedRangesForLine[line]; 0243 } else { 0244 return QSet<TextRange *>(); 0245 } 0246 } 0247 0248 private: 0249 /** 0250 * parent text buffer 0251 */ 0252 TextBuffer *m_buffer; 0253 0254 /** 0255 * Lines contained in this buffer. These are shared pointers. 0256 * We need no sharing, use STL. 0257 */ 0258 std::vector<Kate::TextLine> m_lines; 0259 0260 /** 0261 * Startline of this block 0262 */ 0263 int m_startLine; 0264 0265 /** 0266 * Set of cursors for this block. 0267 * We need no sharing, use STL. 0268 */ 0269 std::unordered_set<TextCursor *> m_cursors; 0270 0271 /** 0272 * Contains for each line-offset the ranges that were cached into it. 0273 * These ranges are fully contained by the line. 0274 */ 0275 std::vector<QSet<TextRange *>> m_cachedRangesForLine; 0276 0277 /** 0278 * Maps for each cached range the line into which the range was cached. 0279 */ 0280 std::unordered_map<TextRange *, int> m_cachedLineForRanges; 0281 0282 /** 0283 * This contains all the ranges that are not cached. 0284 */ 0285 QVarLengthArray<TextRange *, 1> m_uncachedRanges; 0286 }; 0287 0288 } 0289 0290 #endif