KTextEditor

katetextbuffer.h
1/*
2 SPDX-FileCopyrightText: 2010 Christoph Cullmann <cullmann@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6#ifndef KATE_TEXTBUFFER_H
7#define KATE_TEXTBUFFER_H
8
9#include <QList>
10#include <QObject>
11#include <QSet>
12#include <QString>
13
14#include "katetextblock.h"
15#include "katetexthistory.h"
16#include <ktexteditor_export.h>
17
18// encoding prober
19#include <KEncodingProber>
20
21namespace KTextEditor
22{
23class DocumentPrivate;
24}
25
27
28namespace Kate
29{
30class TextRange;
31class TextCursor;
32class TextBlock;
33
34constexpr int BufferBlockSize = 64;
35
36/**
37 * Class representing a text buffer.
38 * The interface is line based, internally the text will be stored in blocks of text lines.
39 */
40class KTEXTEDITOR_EXPORT TextBuffer : public QObject
41{
42 friend class TextCursor;
43 friend class TextRange;
44 friend class TextBlock;
45
46 Q_OBJECT
47
48public:
49 /**
50 * End of line mode
51 */
53 eolUnknown = -1,
54 eolUnix = 0,
55 eolDos = 1,
56 eolMac = 2
57 };
58
59 /**
60 * Construct an empty text buffer.
61 * Empty means one empty line in one block.
62 * @param parent parent qobject
63 */
64 explicit TextBuffer(KTextEditor::DocumentPrivate *parent, bool alwaysUseKAuth = false);
65
66 /**
67 * Destruct the text buffer
68 * Virtual, we allow inheritance
69 */
70 ~TextBuffer() override;
71
72 /**
73 * Clears the buffer, reverts to initial empty state.
74 * Empty means one empty line in one block.
75 * Virtual, can be overwritten.
76 */
77 virtual void clear();
78
79 /**
80 * Set encoding prober type for this buffer to use for load.
81 * @param proberType prober type to use for encoding
82 */
83 void setEncodingProberType(KEncodingProber::ProberType proberType)
84 {
85 m_encodingProberType = proberType;
86 }
87
88 /**
89 * Get encoding prober type for this buffer
90 * @return currently in use prober type of this buffer
91 */
92 KEncodingProber::ProberType encodingProberType() const
93 {
94 return m_encodingProberType;
95 }
96
97 /**
98 * Set fallback codec for this buffer to use for load.
99 * @param codec fallback to use for encoding
100 */
101 void setFallbackTextCodec(const QString &codec)
102 {
103 m_fallbackTextCodec = codec;
104 }
105
106 /**
107 * Get fallback codec for this buffer
108 * @return currently in use fallback codec of this buffer
109 */
111 {
112 return m_fallbackTextCodec;
113 }
114
115 /**
116 * Set codec for this buffer to use for load/save.
117 * Loading might overwrite this, if it encounters problems and finds a better codec.
118 * Might change BOM setting.
119 * @param codec to use for encoding
120 */
121 void setTextCodec(const QString &codec);
122
123 /**
124 * Get codec for this buffer
125 * @return currently in use codec of this buffer
126 */
128 {
129 return m_textCodec;
130 }
131
132 /**
133 * Generate byte order mark on save.
134 * Loading might overwrite this setting, if there is a BOM found inside the file.
135 * @param generateByteOrderMark should BOM be generated?
136 */
137 void setGenerateByteOrderMark(bool generateByteOrderMark)
138 {
139 m_generateByteOrderMark = generateByteOrderMark;
140 }
141
142 /**
143 * Generate byte order mark on save?
144 * @return should BOM be generated?
145 */
147 {
148 return m_generateByteOrderMark;
149 }
150
151 /**
152 * Set end of line mode for this buffer, not allowed to be set to unknown.
153 * Loading might overwrite this setting, if there is a eol found inside the file.
154 * @param endOfLineMode new eol mode
155 */
156 void setEndOfLineMode(EndOfLineMode endOfLineMode)
157 {
158 Q_ASSERT(endOfLineMode != eolUnknown);
159 m_endOfLineMode = endOfLineMode;
160 }
161
162 /**
163 * Get end of line mode
164 * @return end of line mode
165 */
167 {
168 return m_endOfLineMode;
169 }
170
171 /**
172 * Set line length limit
173 * @param lineLengthLimit new line length limit
174 */
175 void setLineLengthLimit(int lineLengthLimit)
176 {
177 m_lineLengthLimit = lineLengthLimit;
178 }
179
180 /**
181 * Load the given file. This will first clear the buffer and then load the file.
182 * Even on error during loading the buffer will still be cleared.
183 * Before calling this, setTextCodec must have been used to set codec!
184 * @param filename file to open
185 * @param encodingErrors were there problems occurred while decoding the file?
186 * @param tooLongLinesWrapped were too long lines found and wrapped?
187 * @param longestLineLoaded the longest line in the file (before wrapping)
188 * @param enforceTextCodec enforce to use only the set text codec
189 * @return success, the file got loaded, perhaps with encoding errors
190 * Virtual, can be overwritten.
191 */
192 virtual bool load(const QString &filename, bool &encodingErrors, bool &tooLongLinesWrapped, int &longestLineLoaded, bool enforceTextCodec);
193
194 /**
195 * Save the current buffer content to the given file.
196 * Before calling this, setTextCodec and setFallbackTextCodec must have been used to set codec!
197 * @param filename file to save
198 * @return success
199 * Virtual, can be overwritten.
200 */
201 virtual bool save(const QString &filename);
202
203 /**
204 * Lines currently stored in this buffer.
205 * This is never 0, even clear will let one empty line remain.
206 */
207 int lines() const
208 {
209 Q_ASSERT(m_lines > 0);
210 return m_lines;
211 }
212
213 /**
214 * Revision of this buffer. Is set to 0 on construction, clear() (load will trigger clear()).
215 * Is incremented on each change to the buffer.
216 * @return current revision
217 */
218 qint64 revision() const
219 {
220 return m_revision;
221 }
222
223 /**
224 * Retrieve a text line.
225 * @param line wanted line number
226 * @return text line
227 */
228 TextLine line(int line) const;
229
230 /**
231 * Transfer all non text attributes for the given line from the given text line to the one in the buffer.
232 * @param line line number to set attributes
233 * @param textLine line reference to get attributes from
234 */
235 void setLineMetaData(int line, const TextLine &textLine);
236
237 /**
238 * Retrieve length for @p line
239 * @param line wanted line number
240 * @return length of the line
241 */
242 int lineLength(int line) const
243 {
244 // get block, this will assert on invalid line
245 int blockIndex = blockForLine(line);
246
247 // get line length
248 return m_blocks.at(blockIndex)->lineLength(line);
249 }
250
251 /**
252 * Retrieve offset in text for the given cursor position
253 */
254 int cursorToOffset(KTextEditor::Cursor c) const;
255
256 /**
257 * Retrieve cursor in text for the given offset
258 */
259 KTextEditor::Cursor offsetToCursor(int offset) const;
260
261 /**
262 * Retrieve text of complete buffer.
263 * @return text for this buffer, lines separated by '\n'
264 */
265 QString text() const;
266
267 /**
268 * Start an editing transaction, the wrapLine/unwrapLine/insertText and removeText functions
269 * are only allowed to be called inside a editing transaction.
270 * Editing transactions can stack. The number of startEdit and endEdit calls must match.
271 * @return returns true, if no transaction was already running
272 * Virtual, can be overwritten.
273 */
274 virtual bool startEditing();
275
276 /**
277 * Finish an editing transaction. Only allowed to be called if editing transaction is started.
278 * @return returns true, if this finished last running transaction
279 * Virtual, can be overwritten.
280 */
281 virtual bool finishEditing();
282
283 /**
284 * Query the number of editing transactions running atm.
285 * @return number of running transactions
286 */
288 {
289 return m_editingTransactions;
290 }
291
292 /**
293 * Query the revision of this buffer before the ongoing editing transactions.
294 * @return revision of buffer before current editing transaction altered it
295 */
296 qint64 editingLastRevision() const
297 {
298 return m_editingLastRevision;
299 }
300
301 /**
302 * Query the number of lines of this buffer before the ongoing editing transactions.
303 * @return number of lines of buffer before current editing transaction altered it
304 */
306 {
307 return m_editingLastLines;
308 }
309
310 /**
311 * Query information from the last editing transaction: was the content of the buffer changed?
312 * This is checked by comparing the editingLastRevision() with the current revision().
313 * @return content of buffer was changed in last transaction?
314 */
316 {
317 return editingLastRevision() != revision();
318 }
319
320 /**
321 * Query information from the last editing transaction: was the number of lines of the buffer changed?
322 * This is checked by comparing the editingLastLines() with the current lines().
323 * @return content of buffer was changed in last transaction?
324 */
326 {
327 return editingLastLines() != lines();
328 }
329
330 /**
331 * Get minimal line number changed by last editing transaction
332 * @return maximal line number changed by last editing transaction, or -1, if none changed
333 */
335 {
336 return m_editingMinimalLineChanged;
337 }
338
339 /**
340 * Get maximal line number changed by last editing transaction
341 * @return maximal line number changed by last editing transaction, or -1, if none changed
342 */
344 {
345 return m_editingMaximalLineChanged;
346 }
347
348 /**
349 * Wrap line at given cursor position.
350 * @param position line/column as cursor where to wrap
351 * Virtual, can be overwritten.
352 */
353 virtual void wrapLine(const KTextEditor::Cursor position);
354
355 /**
356 * Unwrap given line.
357 * @param line line to unwrap
358 * Virtual, can be overwritten.
359 */
360 virtual void unwrapLine(int line);
361
362 /**
363 * Insert text at given cursor position. Does nothing if text is empty, beside some consistency checks.
364 * @param position position where to insert text
365 * @param text text to insert
366 * Virtual, can be overwritten.
367 */
368 virtual void insertText(const KTextEditor::Cursor position, const QString &text);
369
370 /**
371 * Remove text at given range. Does nothing if range is empty, beside some consistency checks.
372 * @param range range of text to remove, must be on one line only.
373 * Virtual, can be overwritten.
374 */
375 virtual void removeText(KTextEditor::Range range);
376
377 /**
378 * TextHistory of this buffer
379 * @return text history for this buffer
380 */
382 {
383 return m_history;
384 }
385
386Q_SIGNALS:
387 /**
388 * Buffer got cleared. This is emitted when constructor or load have called clear() internally,
389 * or when the user of the buffer has called clear() itself.
390 */
391 void cleared();
392
393 /**
394 * Buffer loaded successfully a file
395 * @param filename file which was loaded
396 * @param encodingErrors were there problems occurred while decoding the file?
397 */
398 void loaded(const QString &filename, bool encodingErrors);
399
400 /**
401 * Buffer saved successfully a file
402 * @param filename file which was saved
403 */
404 void saved(const QString &filename);
405
406private:
407 /**
408 * Save result which indicates an abstract reason why the operation has
409 * failed
410 */
411 enum class SaveResult {
412 Failed = 0,
413 MissingPermissions,
414 Success
415 };
416
417 /**
418 * Find block containing given line.
419 * @param line we want to find block for this line
420 * @return index of found block
421 */
422 int blockForLine(int line) const;
423 // exported for movingrange_test
424
425 /**
426 * Fix start lines of all blocks after the given one
427 * @param startBlock index of block from which we start to fix
428 */
429 KTEXTEDITOR_NO_EXPORT
430 void fixStartLines(int startBlock, int value);
431
432 /**
433 * Balance the given block. Look if it is too small or too large.
434 * @param index block to balance
435 */
436 KTEXTEDITOR_NO_EXPORT
437 void balanceBlock(int index);
438
439 /**
440 * A range changed, notify the views, in case of attributes or feedback.
441 * @param view which view is affected? nullptr for all views
442 * @param lineRange line range that the change spans
443 * @param needsRepaint do we need to trigger repaints? e.g. if ranges with attributes change
444 * @param deletedRange if set, points to the range that is deleted
445 */
446 KTEXTEDITOR_NO_EXPORT
447 void notifyAboutRangeChange(KTextEditor::View *view, KTextEditor::LineRange lineRange, bool needsRepaint, TextRange *deletedRange = nullptr);
448
449 /**
450 * Mark all modified lines as lines saved on disk (modified line system).
451 */
452 KTEXTEDITOR_NO_EXPORT
453 void markModifiedLinesAsSaved();
454
455 /**
456 * Save the current buffer content to the given already opened device
457 *
458 * @param filename path name for display/debugging purposes
459 * @param saveFile open device to write the buffer to
460 */
461 KTEXTEDITOR_NO_EXPORT
462 bool saveBuffer(const QString &filename, KCompressionDevice &saveFile);
463
464 /**
465 * Attempt to save the buffer content in the given filename location using
466 * current privileges.
467 */
468 KTEXTEDITOR_NO_EXPORT
469 SaveResult saveBufferUnprivileged(const QString &filename);
470
471 /**
472 * Attempt to save the buffer content in the given filename location using
473 * escalated privileges.
474 */
475 KTEXTEDITOR_NO_EXPORT
476 bool saveBufferEscalated(const QString &filename);
477
478public:
479 /**
480 * Gets the document to which this buffer is bound.
481 * \return a pointer to the document
482 */
484 {
485 return m_document;
486 }
487
488 /**
489 * Debug output, print whole buffer content with line numbers and line length
490 * @param title title for this output
491 */
492 void debugPrint(const QString &title) const;
493
494 /**
495 * Return the ranges which affect the given line.
496 * @param line line to look at
497 * @param view only return ranges associated with given view
498 * @param rangesWithAttributeOnly only return ranges which have a attribute set
499 * @return list of ranges affecting this line
500 */
501 QList<TextRange *> rangesForLine(int line, KTextEditor::View *view, bool rangesWithAttributeOnly) const
502 {
503 // get block, this will assert on invalid line
504 QList<TextRange *> outRanges;
505 rangesForLine(line, view, rangesWithAttributeOnly, outRanges);
506 return outRanges;
507 }
508
509 void rangesForLine(int line, KTextEditor::View *view, bool rangesWithAttributeOnly, QList<TextRange *> &outRanges) const;
510
511 /**
512 * Invalidate all ranges in this buffer.
513 */
514 void invalidateRanges();
515
516 /**
517 * Add/Remove a multiline range that spans multiple blocks
518 */
519 KTEXTEDITOR_NO_EXPORT void addMultilineRange(TextRange *range);
520 KTEXTEDITOR_NO_EXPORT void removeMultilineRange(TextRange *range);
521 bool hasMultlineRange(KTextEditor::MovingRange *range) const;
522
523 //
524 // checksum handling
525 //
526public:
527 /**
528 * Checksum of the document on disk, set either through file loading
529 * in openFile() or in KTextEditor::DocumentPrivate::saveFile()
530 * @return git compatible sha1 checksum for this document
531 */
532 const QByteArray &digest() const;
533
534 /**
535 * Set the checksum of this buffer. Make sure this checksum is up-to-date
536 * when reading digest().
537 * @param checksum git compatible sha1 digest for the document on disk
538 */
539 void setDigest(const QByteArray &checksum);
540
541private:
542 QByteArray m_digest;
543
544private:
545 /**
546 * parent document
547 */
549
550 /**
551 * text history
552 */
553 TextHistory m_history;
554
555 /**
556 * List of starting lines of the blocks in m_blocks
557 */
558 std::vector<int> m_startLines;
559
560 /**
561 * List of blocks which contain the lines of this buffer
562 */
563 std::vector<TextBlock *> m_blocks;
564
565 /**
566 * List of blocksizes of each block in m_blocks
567 */
568 std::vector<int> m_blockSizes;
569
570 /**
571 * Number of lines in buffer
572 */
573 int m_lines;
574
575 /**
576 * Revision of the buffer.
577 */
578 qint64 m_revision;
579
580 /**
581 * Current number of running edit transactions
582 */
583 int m_editingTransactions;
584
585 /**
586 * Revision remembered at start of current editing transaction
587 */
588 qint64 m_editingLastRevision;
589
590 /**
591 * Number of lines remembered at start of current editing transaction
592 */
593 int m_editingLastLines;
594
595 /**
596 * minimal line number changed by last editing transaction
597 */
598 int m_editingMinimalLineChanged;
599
600 /**
601 * maximal line number changed by last editing transaction
602 */
603 int m_editingMaximalLineChanged;
604
605 /**
606 * Multiline ranges that span multiple blocks
607 */
608 std::vector<TextRange *> m_multilineRanges;
609
610 /**
611 * Encoding prober type to use
612 */
613 KEncodingProber::ProberType m_encodingProberType;
614
615 /**
616 * Fallback text codec to use
617 */
618 QString m_fallbackTextCodec;
619
620 /**
621 * Text codec to use
622 */
623 QString m_textCodec;
624
625 /**
626 * Mime-Type used for transparent compression/decompression support
627 * Set by load(), reset by clear()
628 */
629 QString m_mimeTypeForFilterDev;
630
631 /**
632 * Should byte order mark be created?
633 */
634 bool m_generateByteOrderMark;
635
636 /**
637 * End of line mode, default is Unix
638 */
639 EndOfLineMode m_endOfLineMode;
640
641 /**
642 * Limit for line length, longer lines will be wrapped on load
643 */
644 int m_lineLengthLimit;
645
646 /**
647 * For unit-testing purposes only.
648 */
649 bool m_alwaysUseKAuthForSave;
650
651 /**
652 * For copying QBuffer -> QTemporaryFile while saving document in privileged mode
653 */
654 static const qint64 bufferLength = 4096;
655};
656
657}
658
659#endif
The Cursor represents a position in a Document.
Definition cursor.h:75
Backend of KTextEditor::Document related public KTextEditor interfaces.
An object representing lines from a start line to an end line.
Definition linerange.h:41
A range that is bound to a specific Document, and maintains its position.
An object representing a section of text, from one Cursor to another.
A text widget with KXMLGUIClient that represents a Document.
Definition view.h:244
Class representing a text block.
Class representing a text buffer.
void setEncodingProberType(KEncodingProber::ProberType proberType)
Set encoding prober type for this buffer to use for load.
qint64 editingLastRevision() const
Query the revision of this buffer before the ongoing editing transactions.
KEncodingProber::ProberType encodingProberType() const
Get encoding prober type for this buffer.
QList< TextRange * > rangesForLine(int line, KTextEditor::View *view, bool rangesWithAttributeOnly) const
Return the ranges which affect the given line.
void setLineLengthLimit(int lineLengthLimit)
Set line length limit.
QString fallbackTextCodec() const
Get fallback codec for this buffer.
void cleared()
Buffer got cleared.
int editingMaximalLineChanged() const
Get maximal line number changed by last editing transaction.
void setFallbackTextCodec(const QString &codec)
Set fallback codec for this buffer to use for load.
bool editingChangedNumberOfLines() const
Query information from the last editing transaction: was the number of lines of the buffer changed?...
int lineLength(int line) const
Retrieve length for line.
bool editingChangedBuffer() const
Query information from the last editing transaction: was the content of the buffer changed?...
qint64 revision() const
Revision of this buffer.
int lines() const
Lines currently stored in this buffer.
EndOfLineMode endOfLineMode() const
Get end of line mode.
bool generateByteOrderMark() const
Generate byte order mark on save?
QString textCodec() const
Get codec for this buffer.
void setEndOfLineMode(EndOfLineMode endOfLineMode)
Set end of line mode for this buffer, not allowed to be set to unknown.
void loaded(const QString &filename, bool encodingErrors)
Buffer loaded successfully a file.
void saved(const QString &filename)
Buffer saved successfully a file.
int editingTransactions() const
Query the number of editing transactions running atm.
EndOfLineMode
End of line mode.
KTextEditor::DocumentPrivate * document() const
Gets the document to which this buffer is bound.
int editingMinimalLineChanged() const
Get minimal line number changed by last editing transaction.
TextHistory & history()
TextHistory of this buffer.
void setGenerateByteOrderMark(bool generateByteOrderMark)
Generate byte order mark on save.
int editingLastLines() const
Query the number of lines of this buffer before the ongoing editing transactions.
Class representing a 'clever' text cursor.
Class representing the editing history of a TextBuffer.
Class representing a single text line.
Class representing a 'clever' text range.
The KTextEditor namespace contains all the public API that is required to use the KTextEditor compone...
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Dec 21 2024 17:01:55 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.