1/* This file is part of the Kate project.
2 *
3 * Copyright (C) 2010 Christoph Cullmann <cullmann@kde.org>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21#ifndef KATE_TEXTBUFFER_H
22#define KATE_TEXTBUFFER_H
23
24#include <QtCore/QObject>
25#include <QtCore/QString>
26#include <QtCore/QVector>
27#include <QtCore/QSet>
28#include <QtCore/QTextCodec>
29
30#include <ktexteditor/document.h>
31
32#include "katedocument.h"
33#include "katepartprivate_export.h"
34#include "katetextblock.h"
35#include "katetextcursor.h"
36#include "katetextrange.h"
37#include "katetexthistory.h"
38
39// encoding prober
40#include <kencodingprober.h>
41
42namespace Kate {
43
44/**
45 * Class representing a text buffer.
46 * The interface is line based, internally the text will be stored in blocks of text lines.
47 */
48class KATEPART_TESTS_EXPORT TextBuffer : public QObject {
49 friend class TextCursor;
50 friend class TextRange;
51 friend class TextBlock;
52
53 Q_OBJECT
54
55 public:
56 /**
57 * End of line mode
58 */
59 enum EndOfLineMode {
60 eolUnknown = -1
61 , eolUnix = 0
62 , eolDos = 1
63 , eolMac = 2
64 };
65
66 /**
67 * Construct an empty text buffer.
68 * Empty means one empty line in one block.
69 * @param parent parent qobject
70 * @param blockSize block size in lines the buffer should try to hold, default 64 lines
71 */
72 TextBuffer (KateDocument *parent, int blockSize = 64);
73
74 /**
75 * Destruct the text buffer
76 * Virtual, we allow inheritance
77 */
78 virtual ~TextBuffer ();
79
80 /**
81 * Clears the buffer, reverts to initial empty state.
82 * Empty means one empty line in one block.
83 * Virtual, can be overwritten.
84 */
85 virtual void clear ();
86
87 /**
88 * Set encoding prober type for this buffer to use for load.
89 * @param proberType prober type to use for encoding
90 */
91 void setEncodingProberType (KEncodingProber::ProberType proberType) { m_encodingProberType = proberType; }
92
93 /**
94 * Get encoding prober type for this buffer
95 * @return currently in use prober type of this buffer
96 */
97 KEncodingProber::ProberType encodingProberType () const { return m_encodingProberType; }
98
99 /**
100 * Set fallback codec for this buffer to use for load.
101 * @param codec fallback QTextCodec to use for encoding
102 */
103 void setFallbackTextCodec (QTextCodec *codec) { m_fallbackTextCodec = codec; }
104
105 /**
106 * Get fallback codec for this buffer
107 * @return currently in use fallback codec of this buffer
108 */
109 QTextCodec *fallbackTextCodec () const { return m_fallbackTextCodec; }
110
111 /**
112 * Set codec for this buffer to use for load/save.
113 * Loading might overwrite this, if it encounters problems and finds a better codec.
114 * Might change BOM setting.
115 * @param codec QTextCodec to use for encoding
116 */
117 void setTextCodec (QTextCodec *codec);
118
119 /**
120 * Get codec for this buffer
121 * @return currently in use codec of this buffer
122 */
123 QTextCodec *textCodec () const { return m_textCodec; }
124
125 /**
126 * Generate byte order mark on save.
127 * Loading might overwrite this setting, if there is a BOM found inside the file.
128 * @param generateByteOrderMark should BOM be generated?
129 */
130 void setGenerateByteOrderMark (bool generateByteOrderMark) { m_generateByteOrderMark = generateByteOrderMark; }
131
132 /**
133 * Generate byte order mark on save?
134 * @return should BOM be generated?
135 */
136 bool generateByteOrderMark () const { return m_generateByteOrderMark; }
137
138 /**
139 * Set end of line mode for this buffer, not allowed to be set to unknown.
140 * Loading might overwrite this setting, if there is a eol found inside the file.
141 * @param endOfLineMode new eol mode
142 */
143 void setEndOfLineMode (EndOfLineMode endOfLineMode) { Q_ASSERT (endOfLineMode != eolUnknown); m_endOfLineMode = endOfLineMode; }
144
145 /**
146 * Get end of line mode
147 * @return end of line mode
148 */
149 EndOfLineMode endOfLineMode () const { return m_endOfLineMode; }
150
151 /**
152 * Set whether to insert a newline character on save at the end of the file
153 * @param newlineAtEof should newline be added if non-existing
154 */
155 void setNewLineAtEof(bool newlineAtEof) { m_newLineAtEof = newlineAtEof; }
156
157 /**
158 * Set line length limit
159 * @param lineLengthLimit new line length limit
160 */
161 void setLineLengthLimit (int lineLengthLimit) { m_lineLengthLimit = lineLengthLimit; }
162
163 /**
164 * Load the given file. This will first clear the buffer and then load the file.
165 * Even on error during loading the buffer will still be cleared.
166 * Before calling this, setTextCodec must have been used to set codec!
167 * @param filename file to open
168 * @param encodingErrors were there problems occurred while decoding the file?
169 * @param tooLongLinesWrapped were too long lines found and wrapped?
170 * @param enforceTextCodec enforce to use only the set text codec
171 * @return success, the file got loaded, perhaps with encoding errors
172 * Virtual, can be overwritten.
173 */
174 virtual bool load (const QString &filename, bool &encodingErrors, bool &tooLongLinesWrapped, bool enforceTextCodec);
175
176 /**
177 * Save the current buffer content to the given file.
178 * Before calling this, setTextCodec and setFallbackTextCodec must have been used to set codec!
179 * @param filename file to save
180 * @return success
181 * Virtual, can be overwritten.
182 */
183 virtual bool save (const QString &filename);
184
185 /**
186 * Lines currently stored in this buffer.
187 * This is never 0, even clear will let one empty line remain.
188 */
189 int lines () const { Q_ASSERT (m_lines > 0); return m_lines; }
190
191 /**
192 * Revision of this buffer. Is set to 0 on construction, clear() (load will trigger clear()).
193 * Is incremented on each change to the buffer.
194 * @return current revision
195 */
196 qint64 revision () const { return m_revision; }
197
198 /**
199 * Retrieve a text line.
200 * @param line wanted line number
201 * @return text line
202 */
203 TextLine line (int line) const;
204
205 /**
206 * Retrieve text of complete buffer.
207 * @return text for this buffer, lines separated by '\n'
208 */
209 QString text () const;
210
211 /**
212 * Start an editing transaction, the wrapLine/unwrapLine/insertText and removeText functions
213 * are only to be allowed to be called inside a editing transaction.
214 * Editing transactions can stack. The number startEdit and endEdit calls must match.
215 * @return returns true, if no transaction was already running
216 * Virtual, can be overwritten.
217 */
218 virtual bool startEditing ();
219
220 /**
221 * Finish an editing transaction. Only allowed to be called if editing transaction is started.
222 * @return returns true, if this finished last running transaction
223 * Virtual, can be overwritten.
224 */
225 virtual bool finishEditing ();
226
227 /**
228 * Query the number of editing transactions running atm.
229 * @return number of running transactions
230 */
231 int editingTransactions () const { return m_editingTransactions; }
232
233 /**
234 * Query the revsion of this buffer before the ongoing editing transactions.
235 * @return revision of buffer before current editing transaction altered it
236 */
237 qint64 editingLastRevision () const { return m_editingLastRevision; }
238
239 /**
240 * Query the number of lines of this buffer before the ongoing editing transactions.
241 * @return number of lines of buffer before current editing transaction altered it
242 */
243 int editingLastLines () const { return m_editingLastLines; }
244
245 /**
246 * Query information from the last editing transaction: was the content of the buffer changed?
247 * This is checked by comparing the editingLastRevision() with the current revision().
248 * @return content of buffer was changed in last transaction?
249 */
250 bool editingChangedBuffer () const { return editingLastRevision() != revision(); }
251
252 /**
253 * Query information from the last editing transaction: was the number of lines of the buffer changed?
254 * This is checked by comparing the editingLastLines() with the current lines().
255 * @return content of buffer was changed in last transaction?
256 */
257 bool editingChangedNumberOfLines () const { return editingLastLines() != lines(); }
258
259 /**
260 * Get minimal line number changed by last editing transaction
261 * @return maximal line number changed by last editing transaction, or -1, if none changed
262 */
263 int editingMinimalLineChanged () const { return m_editingMinimalLineChanged; }
264
265 /**
266 * Get maximal line number changed by last editing transaction
267 * @return maximal line number changed by last editing transaction, or -1, if none changed
268 */
269 int editingMaximalLineChanged () const { return m_editingMaximalLineChanged; }
270
271 /**
272 * Wrap line at given cursor position.
273 * @param position line/column as cursor where to wrap
274 * Virtual, can be overwritten.
275 */
276 virtual void wrapLine (const KTextEditor::Cursor &position);
277
278 /**
279 * Unwrap given line.
280 * @param line line to unwrap
281 * Virtual, can be overwritten.
282 */
283 virtual void unwrapLine (int line);
284
285 /**
286 * Insert text at given cursor position. Does nothing if text is empty, beside some consistency checks.
287 * @param position position where to insert text
288 * @param text text to insert
289 * Virtual, can be overwritten.
290 */
291 virtual void insertText (const KTextEditor::Cursor &position, const QString &text);
292
293 /**
294 * Remove text at given range. Does nothing if range is empty, beside some consistency checks.
295 * @param range range of text to remove, must be on one line only.
296 * Virtual, can be overwritten.
297 */
298 virtual void removeText (const KTextEditor::Range &range);
299
300 /**
301 * TextHistory of this buffer
302 * @return text history for this buffer
303 */
304 TextHistory &history () { return m_history; }
305
306 Q_SIGNALS:
307 /**
308 * Buffer got cleared. This is emitted when constructor or load have called clear() internally,
309 * or when the user of the buffer has called clear() itself.
310 */
311 void cleared ();
312
313 /**
314 * Buffer loaded successfully a file
315 * @param filename file which was loaded
316 * @param encodingErrors were there problems occurred while decoding the file?
317 */
318 void loaded (const QString &filename, bool encodingErrors);
319
320 /**
321 * Buffer saved successfully a file
322 * @param filename file which was saved
323 */
324 void saved (const QString &filename);
325
326 /**
327 * Editing transaction has started.
328 */
329 void editingStarted ();
330
331 /**
332 * Editing transaction has finished.
333 */
334 void editingFinished ();
335
336 /**
337 * A line got wrapped.
338 * @param position position where the wrap occurred
339 */
340 void lineWrapped (const KTextEditor::Cursor &position);
341
342 /**
343 * A line got unwrapped.
344 * @param line line where the unwrap occurred
345 */
346 void lineUnwrapped (int line);
347
348 /**
349 * Text got inserted.
350 * @param position position where the insertion occurred
351 * @param text inserted text
352 */
353 void textInserted (const KTextEditor::Cursor &position, const QString &text);
354
355 /**
356 * Text got removed.
357 * @param range range where the removal occurred
358 * @param text removed text
359 */
360 void textRemoved (const KTextEditor::Range &range, const QString &text);
361
362 private:
363 /**
364 * Find block containing given line.
365 * @param line we want to find block for this line
366 * @return index of found block
367 */
368 int blockForLine (int line) const;
369
370 /**
371 * Fix start lines of all blocks after the given one
372 * @param startBlock index of block from which we start to fix
373 */
374 void fixStartLines (int startBlock);
375
376 /**
377 * Balance the given block. Look if it is too small or too large.
378 * @param index block to balance
379 */
380 void balanceBlock (int index);
381
382 /**
383 * Block for given index in block list.
384 * @param index block index
385 * @return block matching this index
386 */
387 TextBlock *blockForIndex (int index) { return m_blocks[index]; }
388
389 /**
390 * A range changed, notify the views, in case of attributes or feedback.
391 * @param view which view is affected? 0 for all views
392 * @param startLine start line of change
393 * @param endLine end line of change
394 * @param rangeWithAttribute attribute changed or is active, this will perhaps lead to repaints
395 */
396 void notifyAboutRangeChange (KTextEditor::View *view, int startLine, int endLine, bool rangeWithAttribute);
397
398 /**
399 * Mark all modified lines as lines saved on disk (modified line system).
400 */
401 void markModifiedLinesAsSaved();
402
403 public:
404 /**
405 * Gets the document to which this buffer is bound.
406 * \return a pointer to the document
407 */
408 KateDocument *document () const { return m_document; }
409
410 /**
411 * Debug output, print whole buffer content with line numbers and line length
412 * @param title title for this output
413 */
414 void debugPrint (const QString &title) const;
415
416 /**
417 * Return the ranges which affect the given line.
418 * @param line line to look at
419 * @param view only return ranges associated with given view
420 * @param rangesWithAttributeOnly only return ranges which have a attribute set
421 * @return list of ranges affecting this line
422 */
423 QList<TextRange *> rangesForLine (int line, KTextEditor::View *view, bool rangesWithAttributeOnly) const;
424
425 /**
426 * Check if the given range pointer is still valid.
427 * @return range pointer still belongs to range for this buffer
428 */
429 bool rangePointerValid (TextRange *range) const { return m_ranges.contains (range); }
430
431 /**
432 * Invalidate all ranges in this buffer.
433 */
434 void invalidateRanges();
435
436 //
437 // md5 checksum handling
438 //
439 public:
440 /**
441 * md5 digest of the document on disk, set either through file loading
442 * in openFile() or in KateDocument::saveFile()
443 * @return md5 digest for this document
444 */
445 const QByteArray &digest () const;
446
447 /**
448 * Set the md5sum of this buffer. Make sure this checksum is up-to-date
449 * when reading digest().
450 * @param md5sum md5 digest for the document on disk
451 */
452 void setDigest (const QByteArray & md5sum);
453
454 private:
455 QByteArray m_digest;
456
457 private:
458 /**
459 * parent document
460 */
461 KateDocument *m_document;
462
463 /**
464 * text history
465 */
466 TextHistory m_history;
467
468 /**
469 * block size in lines the buffer will try to hold
470 */
471 const int m_blockSize;
472
473 /**
474 * List of blocks which contain the lines of this buffer
475 */
476 QVector<TextBlock *> m_blocks;
477
478 /**
479 * Number of lines in buffer
480 */
481 int m_lines;
482
483 /**
484 * Last used block in the buffer. Is used for speeding up blockForLine.
485 * May contain invalid index, must be checked before using.
486 */
487 mutable int m_lastUsedBlock;
488
489 /**
490 * Revision of the buffer.
491 */
492 qint64 m_revision;
493
494 /**
495 * Current number of running edit transactions
496 */
497 int m_editingTransactions;
498
499 /**
500 * Revision remembered at start of current editing transaction
501 */
502 qint64 m_editingLastRevision;
503
504 /**
505 * Number of lines remembered at start of current editing transaction
506 */
507 int m_editingLastLines;
508
509 /**
510 * minimal line number changed by last editing transaction
511 */
512 int m_editingMinimalLineChanged;
513
514 /**
515 * maximal line number changed by last editing transaction
516 */
517 int m_editingMaximalLineChanged;
518
519 /**
520 * Set of invalid cursors for this whole buffer.
521 * Valid cursors are inside the block the belong to.
522 */
523 QSet<TextCursor *> m_invalidCursors;
524
525 /**
526 * Set of ranges of this whole buffer.
527 */
528 QSet<TextRange *> m_ranges;
529
530 /**
531 * Encoding prober type to use
532 */
533 KEncodingProber::ProberType m_encodingProberType;
534
535 /**
536 * Fallback text codec to use
537 */
538 QTextCodec *m_fallbackTextCodec;
539
540 /**
541 * Text codec to use
542 */
543 QTextCodec *m_textCodec;
544
545 /**
546 * Mime-Type used for transparent compression/decompression support
547 * Set by load(), reset by clear()
548 */
549 QString m_mimeTypeForFilterDev;
550
551 /**
552 * Should byte order mark be created?
553 */
554 bool m_generateByteOrderMark;
555
556 /**
557 * End of line mode, default is Unix
558 */
559 EndOfLineMode m_endOfLineMode;
560
561 /**
562 * Insert newline character at the end of the file?
563 */
564 bool m_newLineAtEof;
565
566 /**
567 * Limit for line length, longer lines will be wrapped on load
568 */
569 int m_lineLengthLimit;
570};
571
572}
573
574#endif
575