File indexing completed on 2024-04-21 03:57:19
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_TEXTLINE_H 0008 #define KATE_TEXTLINE_H 0009 0010 #include <KSyntaxHighlighting/State> 0011 0012 #include <QList> 0013 #include <QString> 0014 0015 namespace Kate 0016 { 0017 /** 0018 * Class representing a single text line. 0019 * For efficiency reasons, not only pure text is stored here, but also additional data. 0020 */ 0021 class TextLine 0022 { 0023 public: 0024 /** 0025 * Attribute storage 0026 */ 0027 class Attribute 0028 { 0029 public: 0030 /** 0031 * Attribute constructor 0032 * @param _offset offset 0033 * @param _length length 0034 * @param _attributeValue attribute value 0035 */ 0036 explicit Attribute(int _offset = 0, int _length = 0, int _attributeValue = 0) 0037 : offset(_offset) 0038 , length(_length) 0039 , attributeValue(_attributeValue) 0040 { 0041 } 0042 0043 /** 0044 * offset 0045 */ 0046 int offset; 0047 0048 /** 0049 * length 0050 */ 0051 int length; 0052 0053 /** 0054 * attribute value (to encode type of this range) 0055 */ 0056 int attributeValue; 0057 }; 0058 0059 /** 0060 * Flags of TextLine 0061 */ 0062 enum Flags { flagAutoWrapped = 1, flagFoldingStartAttribute = 2, flagFoldingEndAttribute = 4, flagLineModified = 8, flagLineSavedOnDisk = 16 }; 0063 0064 /** 0065 * Construct an empty text line. 0066 */ 0067 TextLine() = default; 0068 0069 /** 0070 * Construct an text line with given text. 0071 * @param text text to use for this line 0072 */ 0073 explicit TextLine(const QString &text) 0074 : m_text(text) 0075 , m_flags(0) 0076 { 0077 } 0078 0079 /** 0080 * Accessor to the text contained in this line. 0081 * @return text of this line as constant reference 0082 */ 0083 const QString &text() const 0084 { 0085 return m_text; 0086 } 0087 0088 /** 0089 * Accessor to the text contained in this line. 0090 * @return text of this line as reference 0091 */ 0092 QString &text() 0093 { 0094 return m_text; 0095 } 0096 0097 /** 0098 * Returns the position of the first non-whitespace character 0099 * @return position of first non-whitespace char or -1 if there is none 0100 */ 0101 int firstChar() const; 0102 0103 /** 0104 * Returns the position of the last non-whitespace character 0105 * @return position of last non-whitespace char or -1 if there is none 0106 */ 0107 int lastChar() const; 0108 0109 /** 0110 * Find the position of the next char that is not a space. 0111 * @param pos Column of the character which is examined first. 0112 * @return True if the specified or a following character is not a space 0113 * Otherwise false. 0114 */ 0115 int nextNonSpaceChar(int pos) const; 0116 0117 /** 0118 * Find the position of the previous char that is not a space. 0119 * @param pos Column of the character which is examined first. 0120 * @return The position of the first non-whitespace character preceding pos, 0121 * or -1 if none is found. 0122 */ 0123 int previousNonSpaceChar(int pos) const; 0124 0125 /** 0126 * Returns the character at the given \e column. If \e column is out of 0127 * range, the return value is QChar(). 0128 * @param column column you want char for 0129 * @return char at given column or QChar() 0130 */ 0131 inline QChar at(int column) const 0132 { 0133 if (column >= 0 && column < m_text.length()) { 0134 return m_text.at(column); 0135 } 0136 0137 return QChar(); 0138 } 0139 0140 inline void markAsModified(bool modified) 0141 { 0142 if (modified) { 0143 m_flags |= flagLineModified; 0144 m_flags &= (~flagLineSavedOnDisk); 0145 } else { 0146 m_flags &= (~flagLineModified); 0147 } 0148 } 0149 0150 inline bool markedAsModified() const 0151 { 0152 return m_flags & flagLineModified; 0153 } 0154 0155 inline void markAsSavedOnDisk(bool savedOnDisk) 0156 { 0157 if (savedOnDisk) { 0158 m_flags |= flagLineSavedOnDisk; 0159 m_flags &= (~flagLineModified); 0160 } else { 0161 m_flags &= (~flagLineSavedOnDisk); 0162 } 0163 } 0164 0165 inline bool markedAsSavedOnDisk() const 0166 { 0167 return m_flags & flagLineSavedOnDisk; 0168 } 0169 0170 /** 0171 * Clear folding start and end status. 0172 */ 0173 void clearMarkedAsFoldingStartAndEnd() 0174 { 0175 m_flags &= ~flagFoldingStartAttribute; 0176 m_flags &= ~flagFoldingEndAttribute; 0177 } 0178 0179 /** 0180 * Is on this line a folding start per attribute? 0181 * @return folding start line per attribute? or not? 0182 */ 0183 bool markedAsFoldingStartAttribute() const 0184 { 0185 return m_flags & flagFoldingStartAttribute; 0186 } 0187 0188 /** 0189 * Mark as folding start line of an attribute based folding. 0190 */ 0191 void markAsFoldingStartAttribute() 0192 { 0193 m_flags |= flagFoldingStartAttribute; 0194 } 0195 0196 /** 0197 * Is on this line a folding end per attribute? 0198 * @return folding end line per attribute? or not? 0199 */ 0200 bool markedAsFoldingEndAttribute() const 0201 { 0202 return m_flags & flagFoldingEndAttribute; 0203 } 0204 0205 /** 0206 * Mark as folding end line of an attribute based folding. 0207 */ 0208 void markAsFoldingEndAttribute() 0209 { 0210 m_flags |= flagFoldingEndAttribute; 0211 } 0212 0213 /** 0214 * Returns the line's length. 0215 */ 0216 int length() const 0217 { 0218 return m_text.length(); 0219 } 0220 0221 /** 0222 * Returns \e true, if the line was automagically wrapped, otherwise returns 0223 * \e false. 0224 * @return was this line auto-wrapped? 0225 */ 0226 bool isAutoWrapped() const 0227 { 0228 return m_flags & flagAutoWrapped; 0229 } 0230 0231 /** 0232 * Returns the substring with \e length beginning at the given \e column. 0233 * @param column start column of text to return 0234 * @param length length of text to return 0235 * @return wanted part of text 0236 */ 0237 QString string(int column, int length) const 0238 { 0239 return m_text.mid(column, length); 0240 } 0241 0242 /** 0243 * Leading whitespace of this line 0244 * @return leading whitespace of this line 0245 */ 0246 QString leadingWhitespace() const; 0247 0248 /** 0249 * Returns the indentation depth with each tab expanded into \e tabWidth characters. 0250 */ 0251 int indentDepth(int tabWidth) const; 0252 0253 /** 0254 * Returns the \e column with each tab expanded into \e tabWidth characters. 0255 */ 0256 int toVirtualColumn(int column, int tabWidth) const; 0257 0258 /** 0259 * Returns the "real" column where each tab only counts one character. 0260 * The conversion calculates with \e tabWidth characters for each tab. 0261 */ 0262 int fromVirtualColumn(int column, int tabWidth) const; 0263 0264 /** 0265 * Returns the text length with each tab expanded into \e tabWidth characters. 0266 */ 0267 int virtualLength(int tabWidth) const; 0268 0269 /** 0270 * Returns \e true, if \e match equals to the text at position \e column, 0271 * otherwise returns \e false. 0272 */ 0273 bool matchesAt(int column, const QString &match) const; 0274 0275 /** 0276 * Returns \e true, if the line starts with \e match, otherwise returns \e false. 0277 */ 0278 bool startsWith(const QString &match) const 0279 { 0280 return m_text.startsWith(match); 0281 } 0282 0283 /** 0284 * Returns \e true, if the line ends with \e match, otherwise returns \e false. 0285 */ 0286 bool endsWith(const QString &match) const 0287 { 0288 return m_text.endsWith(match); 0289 } 0290 0291 /** 0292 * context stack 0293 * @return context stack 0294 */ 0295 const KSyntaxHighlighting::State &highlightingState() const 0296 { 0297 return m_highlightingState; 0298 } 0299 0300 /** 0301 * Sets the syntax highlight context number 0302 * @param val new context array 0303 */ 0304 void setHighlightingState(const KSyntaxHighlighting::State &val) 0305 { 0306 m_highlightingState = val; 0307 } 0308 0309 /** 0310 * Add attribute to this line. 0311 * @param attribute new attribute to append 0312 */ 0313 void addAttribute(const Attribute &attribute); 0314 0315 /** 0316 * Clear attributes and foldings of this line 0317 */ 0318 void clearAttributes() 0319 { 0320 m_attributesList.clear(); 0321 } 0322 0323 /** 0324 * Accessor to attributes 0325 * @return attributes of this line 0326 */ 0327 const QList<Attribute> &attributesList() const 0328 { 0329 return m_attributesList; 0330 } 0331 0332 /** 0333 * Gets the attribute at the given position 0334 * use KRenderer::attributes to get the KTextAttribute for this. 0335 * 0336 * @param pos position of attribute requested 0337 * @return value of attribute 0338 */ 0339 int attribute(int pos) const; 0340 0341 /** 0342 * set auto-wrapped property 0343 * @param wrapped line was wrapped? 0344 */ 0345 void setAutoWrapped(bool wrapped) 0346 { 0347 if (wrapped) { 0348 m_flags = m_flags | flagAutoWrapped; 0349 } else { 0350 m_flags = m_flags & ~flagAutoWrapped; 0351 } 0352 } 0353 0354 private: 0355 /** 0356 * text of this line 0357 */ 0358 QString m_text; 0359 0360 /** 0361 * attributes of this line 0362 */ 0363 QList<Attribute> m_attributesList; 0364 0365 /** 0366 * current highlighting state 0367 */ 0368 KSyntaxHighlighting::State m_highlightingState; 0369 0370 /** 0371 * flags of this line 0372 */ 0373 unsigned int m_flags = 0; 0374 }; 0375 } 0376 0377 #endif