1/*
2 SPDX-FileCopyrightText: 2010 Christoph Cullmann <cullmann@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#ifndef KATE_TEXTLINE_H
8#define KATE_TEXTLINE_H
9
10#include <KSyntaxHighlighting/State>
11
12#include <QList>
13#include <QString>
14
15namespace Kate
16{
17/**
18 * Class representing a single text line.
19 * For efficiency reasons, not only pure text is stored here, but also additional data.
20 */
21class TextLine
22{
23public:
24 /**
25 * Attribute storage
26 */
27 class Attribute
28 {
29 public:
30 /**
31 * Attribute constructor
32 * @param _offset offset
33 * @param _length length
34 * @param _attributeValue attribute value
35 */
36 explicit Attribute(int _offset = 0, int _length = 0, int _attributeValue = 0)
37 : offset(_offset)
38 , length(_length)
39 , attributeValue(_attributeValue)
40 {
41 }
42
43 /**
44 * offset
45 */
46 int offset;
47
48 /**
49 * length
50 */
51 int length;
52
53 /**
54 * attribute value (to encode type of this range)
55 */
56 int attributeValue;
57 };
58
59 /**
60 * Flags of TextLine
61 */
62 enum Flags {
63 flagAutoWrapped = 1,
64 flagFoldingStartAttribute = 2,
65 flagFoldingEndAttribute = 4,
66 flagLineModified = 8,
67 flagLineSavedOnDisk = 16
68 };
69
70 /**
71 * Construct an empty text line.
72 */
73 TextLine() = default;
74
75 /**
76 * Construct an text line with given text.
77 * @param text text to use for this line
78 */
79 explicit TextLine(const QString &text)
80 : m_text(text)
81 , m_flags(0)
82 {
83 }
84
85 /**
86 * Accessor to the text contained in this line.
87 * @return text of this line as constant reference
88 */
89 const QString &text() const
90 {
91 return m_text;
92 }
93
94 /**
95 * Accessor to the text contained in this line.
96 * @return text of this line as reference
97 */
98 QString &text()
99 {
100 return m_text;
101 }
102
103 /**
104 * Returns the position of the first non-whitespace character
105 * @return position of first non-whitespace char or -1 if there is none
106 */
107 int firstChar() const;
108
109 /**
110 * Returns the position of the last non-whitespace character
111 * @return position of last non-whitespace char or -1 if there is none
112 */
113 int lastChar() const;
114
115 /**
116 * Find the position of the next char that is not a space.
117 * @param pos Column of the character which is examined first.
118 * @return True if the specified or a following character is not a space
119 * Otherwise false.
120 */
121 int nextNonSpaceChar(int pos) const;
122
123 /**
124 * Find the position of the previous char that is not a space.
125 * @param pos Column of the character which is examined first.
126 * @return The position of the first non-whitespace character preceding pos,
127 * or -1 if none is found.
128 */
129 int previousNonSpaceChar(int pos) const;
130
131 /**
132 * Returns the character at the given \e column. If \e column is out of
133 * range, the return value is QChar().
134 * @param column column you want char for
135 * @return char at given column or QChar()
136 */
137 inline QChar at(int column) const
138 {
139 if (column >= 0 && column < m_text.length()) {
140 return m_text.at(i: column);
141 }
142
143 return QChar();
144 }
145
146 inline void markAsModified(bool modified)
147 {
148 if (modified) {
149 m_flags |= flagLineModified;
150 m_flags &= (~flagLineSavedOnDisk);
151 } else {
152 m_flags &= (~flagLineModified);
153 }
154 }
155
156 inline bool markedAsModified() const
157 {
158 return m_flags & flagLineModified;
159 }
160
161 inline void markAsSavedOnDisk(bool savedOnDisk)
162 {
163 if (savedOnDisk) {
164 m_flags |= flagLineSavedOnDisk;
165 m_flags &= (~flagLineModified);
166 } else {
167 m_flags &= (~flagLineSavedOnDisk);
168 }
169 }
170
171 inline bool markedAsSavedOnDisk() const
172 {
173 return m_flags & flagLineSavedOnDisk;
174 }
175
176 /**
177 * Clear folding start and end status.
178 */
179 void clearMarkedAsFoldingStartAndEnd()
180 {
181 m_flags &= ~flagFoldingStartAttribute;
182 m_flags &= ~flagFoldingEndAttribute;
183 }
184
185 /**
186 * Is on this line a folding start per attribute?
187 * @return folding start line per attribute? or not?
188 */
189 bool markedAsFoldingStartAttribute() const
190 {
191 return m_flags & flagFoldingStartAttribute;
192 }
193
194 /**
195 * Mark as folding start line of an attribute based folding.
196 */
197 void markAsFoldingStartAttribute()
198 {
199 m_flags |= flagFoldingStartAttribute;
200 }
201
202 /**
203 * Is on this line a folding end per attribute?
204 * @return folding end line per attribute? or not?
205 */
206 bool markedAsFoldingEndAttribute() const
207 {
208 return m_flags & flagFoldingEndAttribute;
209 }
210
211 /**
212 * Mark as folding end line of an attribute based folding.
213 */
214 void markAsFoldingEndAttribute()
215 {
216 m_flags |= flagFoldingEndAttribute;
217 }
218
219 /**
220 * Returns the line's length.
221 */
222 int length() const
223 {
224 return m_text.length();
225 }
226
227 /**
228 * Returns \e true, if the line was automagically wrapped, otherwise returns
229 * \e false.
230 * @return was this line auto-wrapped?
231 */
232 bool isAutoWrapped() const
233 {
234 return m_flags & flagAutoWrapped;
235 }
236
237 /**
238 * Returns the substring with \e length beginning at the given \e column.
239 * @param column start column of text to return
240 * @param length length of text to return
241 * @return wanted part of text
242 */
243 QString string(int column, int length) const
244 {
245 return m_text.mid(position: column, n: length);
246 }
247
248 /**
249 * Leading whitespace of this line
250 * @return leading whitespace of this line
251 */
252 QString leadingWhitespace() const;
253
254 /**
255 * Returns the indentation depth with each tab expanded into \e tabWidth characters.
256 */
257 int indentDepth(int tabWidth) const;
258
259 /**
260 * Returns the \e column with each tab expanded into \e tabWidth characters.
261 */
262 int toVirtualColumn(int column, int tabWidth) const;
263
264 /**
265 * Returns the "real" column where each tab only counts one character.
266 * The conversion calculates with \e tabWidth characters for each tab.
267 */
268 int fromVirtualColumn(int column, int tabWidth) const;
269
270 /**
271 * Returns the text length with each tab expanded into \e tabWidth characters.
272 */
273 int virtualLength(int tabWidth) const;
274
275 /**
276 * Returns \e true, if \e match equals to the text at position \e column,
277 * otherwise returns \e false.
278 */
279 bool matchesAt(int column, const QString &match) const;
280
281 /**
282 * Returns \e true, if the line starts with \e match, otherwise returns \e false.
283 */
284 bool startsWith(const QString &match) const
285 {
286 return m_text.startsWith(s: match);
287 }
288
289 /**
290 * Returns \e true, if the line ends with \e match, otherwise returns \e false.
291 */
292 bool endsWith(const QString &match) const
293 {
294 return m_text.endsWith(s: match);
295 }
296
297 /**
298 * context stack
299 * @return context stack
300 */
301 const KSyntaxHighlighting::State &highlightingState() const
302 {
303 return m_highlightingState;
304 }
305
306 /**
307 * Sets the syntax highlight context number
308 * @param val new context array
309 */
310 void setHighlightingState(const KSyntaxHighlighting::State &val)
311 {
312 m_highlightingState = val;
313 }
314
315 /**
316 * Add attribute to this line.
317 * @param attribute new attribute to append
318 */
319 void addAttribute(const Attribute &attribute);
320
321 /**
322 * Clear attributes and foldings of this line
323 */
324 void clearAttributes()
325 {
326 m_attributesList.clear();
327 }
328
329 /**
330 * Accessor to attributes
331 * @return attributes of this line
332 */
333 const QList<Attribute> &attributesList() const
334 {
335 return m_attributesList;
336 }
337
338 /**
339 * Gets the attribute at the given position
340 * use KRenderer::attributes to get the KTextAttribute for this.
341 *
342 * @param pos position of attribute requested
343 * @return value of attribute
344 */
345 int attribute(int pos) const;
346
347 /**
348 * set auto-wrapped property
349 * @param wrapped line was wrapped?
350 */
351 void setAutoWrapped(bool wrapped)
352 {
353 if (wrapped) {
354 m_flags = m_flags | flagAutoWrapped;
355 } else {
356 m_flags = m_flags & ~flagAutoWrapped;
357 }
358 }
359
360private:
361 /**
362 * text of this line
363 */
364 QString m_text;
365
366 /**
367 * attributes of this line
368 */
369 QList<Attribute> m_attributesList;
370
371 /**
372 * current highlighting state
373 */
374 KSyntaxHighlighting::State m_highlightingState;
375
376 /**
377 * flags of this line
378 */
379 unsigned int m_flags = 0;
380};
381}
382
383#endif
384

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