kde-workspace/kate/part/buffer/katetextbuffer.h
Ivailo Monev f68295ea28 generic: move sub-projects from kde-baseapps [ci reset]
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
2022-05-14 21:56:54 +03:00

548 lines
16 KiB
C++

/* This file is part of the Kate project.
*
* Copyright (C) 2010 Christoph Cullmann <cullmann@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef KATE_TEXTBUFFER_H
#define KATE_TEXTBUFFER_H
#include <QtCore/QObject>
#include <QtCore/QString>
#include <QtCore/QVector>
#include <QtCore/QSet>
#include <QtCore/QTextCodec>
#include <ktexteditor/document.h>
#include "katedocument.h"
#include "katepartinterfaces_export.h"
#include "katetextblock.h"
#include "katetextcursor.h"
#include "katetextrange.h"
#include "katetexthistory.h"
namespace Kate {
/**
* Class representing a text buffer.
* The interface is line based, internally the text will be stored in blocks of text lines.
*/
class KATEPARTINTERFACES_EXPORT TextBuffer : public QObject {
friend class TextCursor;
friend class TextRange;
friend class TextBlock;
Q_OBJECT
public:
/**
* End of line mode
*/
enum EndOfLineMode {
eolUnknown = -1
, eolUnix = 0
, eolDos = 1
, eolMac = 2
};
/**
* Construct an empty text buffer.
* Empty means one empty line in one block.
* @param parent parent qobject
* @param blockSize block size in lines the buffer should try to hold, default 64 lines
*/
TextBuffer (KateDocument *parent, int blockSize = 64);
/**
* Destruct the text buffer
* Virtual, we allow inheritance
*/
virtual ~TextBuffer ();
/**
* Clears the buffer, reverts to initial empty state.
* Empty means one empty line in one block.
* Virtual, can be overwritten.
*/
virtual void clear ();
/**
* Set fallback codec for this buffer to use for load.
* @param codec fallback QTextCodec to use for encoding
*/
void setFallbackTextCodec (QTextCodec *codec) { m_fallbackTextCodec = codec; }
/**
* Get fallback codec for this buffer
* @return currently in use fallback codec of this buffer
*/
QTextCodec *fallbackTextCodec () const { return m_fallbackTextCodec; }
/**
* Set codec for this buffer to use for load/save.
* Loading might overwrite this, if it encounters problems and finds a better codec.
* Might change BOM setting.
* @param codec QTextCodec to use for encoding
*/
void setTextCodec (QTextCodec *codec);
/**
* Get codec for this buffer
* @return currently in use codec of this buffer
*/
QTextCodec *textCodec () const { return m_textCodec; }
/**
* Generate byte order mark on save.
* Loading might overwrite this setting, if there is a BOM found inside the file.
* @param generateByteOrderMark should BOM be generated?
*/
void setGenerateByteOrderMark (bool generateByteOrderMark) { m_generateByteOrderMark = generateByteOrderMark; }
/**
* Generate byte order mark on save?
* @return should BOM be generated?
*/
bool generateByteOrderMark () const { return m_generateByteOrderMark; }
/**
* Set end of line mode for this buffer, not allowed to be set to unknown.
* Loading might overwrite this setting, if there is a eol found inside the file.
* @param endOfLineMode new eol mode
*/
void setEndOfLineMode (EndOfLineMode endOfLineMode) { Q_ASSERT (endOfLineMode != eolUnknown); m_endOfLineMode = endOfLineMode; }
/**
* Get end of line mode
* @return end of line mode
*/
EndOfLineMode endOfLineMode () const { return m_endOfLineMode; }
/**
* Set whether to insert a newline character on save at the end of the file
* @param newlineAtEof should newline be added if non-existing
*/
void setNewLineAtEof(bool newlineAtEof) { m_newLineAtEof = newlineAtEof; }
/**
* Set line length limit
* @param lineLengthLimit new line length limit
*/
void setLineLengthLimit (int lineLengthLimit) { m_lineLengthLimit = lineLengthLimit; }
/**
* Load the given file. This will first clear the buffer and then load the file.
* Even on error during loading the buffer will still be cleared.
* Before calling this, setTextCodec must have been used to set codec!
* @param filename file to open
* @param encodingErrors were there problems occurred while decoding the file?
* @param tooLongLinesWrapped were too long lines found and wrapped?
* @param enforceTextCodec enforce to use only the set text codec
* @return success, the file got loaded, perhaps with encoding errors
* Virtual, can be overwritten.
*/
virtual bool load (const QString &filename, bool &encodingErrors, bool &tooLongLinesWrapped, bool enforceTextCodec);
/**
* Save the current buffer content to the given file.
* Before calling this, setTextCodec and setFallbackTextCodec must have been used to set codec!
* @param filename file to save
* @return success
* Virtual, can be overwritten.
*/
virtual bool save (const QString &filename);
/**
* Lines currently stored in this buffer.
* This is never 0, even clear will let one empty line remain.
*/
int lines () const { Q_ASSERT (m_lines > 0); return m_lines; }
/**
* Revision of this buffer. Is set to 0 on construction, clear() (load will trigger clear()).
* Is incremented on each change to the buffer.
* @return current revision
*/
qint64 revision () const { return m_revision; }
/**
* Retrieve a text line.
* @param line wanted line number
* @return text line
*/
TextLine line (int line) const;
/**
* Retrieve text of complete buffer.
* @return text for this buffer, lines separated by '\n'
*/
QString text () const;
/**
* Start an editing transaction, the wrapLine/unwrapLine/insertText and removeText functions
* are only to be allowed to be called inside a editing transaction.
* Editing transactions can stack. The number startEdit and endEdit calls must match.
* @return returns true, if no transaction was already running
* Virtual, can be overwritten.
*/
virtual bool startEditing ();
/**
* Finish an editing transaction. Only allowed to be called if editing transaction is started.
* @return returns true, if this finished last running transaction
* Virtual, can be overwritten.
*/
virtual bool finishEditing ();
/**
* Query the number of editing transactions running atm.
* @return number of running transactions
*/
int editingTransactions () const { return m_editingTransactions; }
/**
* Query the revsion of this buffer before the ongoing editing transactions.
* @return revision of buffer before current editing transaction altered it
*/
qint64 editingLastRevision () const { return m_editingLastRevision; }
/**
* Query the number of lines of this buffer before the ongoing editing transactions.
* @return number of lines of buffer before current editing transaction altered it
*/
int editingLastLines () const { return m_editingLastLines; }
/**
* Query information from the last editing transaction: was the content of the buffer changed?
* This is checked by comparing the editingLastRevision() with the current revision().
* @return content of buffer was changed in last transaction?
*/
bool editingChangedBuffer () const { return editingLastRevision() != revision(); }
/**
* Query information from the last editing transaction: was the number of lines of the buffer changed?
* This is checked by comparing the editingLastLines() with the current lines().
* @return content of buffer was changed in last transaction?
*/
bool editingChangedNumberOfLines () const { return editingLastLines() != lines(); }
/**
* Get minimal line number changed by last editing transaction
* @return maximal line number changed by last editing transaction, or -1, if none changed
*/
int editingMinimalLineChanged () const { return m_editingMinimalLineChanged; }
/**
* Get maximal line number changed by last editing transaction
* @return maximal line number changed by last editing transaction, or -1, if none changed
*/
int editingMaximalLineChanged () const { return m_editingMaximalLineChanged; }
/**
* Wrap line at given cursor position.
* @param position line/column as cursor where to wrap
* Virtual, can be overwritten.
*/
virtual void wrapLine (const KTextEditor::Cursor &position);
/**
* Unwrap given line.
* @param line line to unwrap
* Virtual, can be overwritten.
*/
virtual void unwrapLine (int line);
/**
* Insert text at given cursor position. Does nothing if text is empty, beside some consistency checks.
* @param position position where to insert text
* @param text text to insert
* Virtual, can be overwritten.
*/
virtual void insertText (const KTextEditor::Cursor &position, const QString &text);
/**
* Remove text at given range. Does nothing if range is empty, beside some consistency checks.
* @param range range of text to remove, must be on one line only.
* Virtual, can be overwritten.
*/
virtual void removeText (const KTextEditor::Range &range);
/**
* TextHistory of this buffer
* @return text history for this buffer
*/
TextHistory &history () { return m_history; }
Q_SIGNALS:
/**
* Buffer got cleared. This is emitted when constructor or load have called clear() internally,
* or when the user of the buffer has called clear() itself.
*/
void cleared ();
/**
* Buffer loaded successfully a file
* @param filename file which was loaded
* @param encodingErrors were there problems occurred while decoding the file?
*/
void loaded (const QString &filename, bool encodingErrors);
/**
* Buffer saved successfully a file
* @param filename file which was saved
*/
void saved (const QString &filename);
/**
* Editing transaction has started.
*/
void editingStarted ();
/**
* Editing transaction has finished.
*/
void editingFinished ();
/**
* A line got wrapped.
* @param position position where the wrap occurred
*/
void lineWrapped (const KTextEditor::Cursor &position);
/**
* A line got unwrapped.
* @param line line where the unwrap occurred
*/
void lineUnwrapped (int line);
/**
* Text got inserted.
* @param position position where the insertion occurred
* @param text inserted text
*/
void textInserted (const KTextEditor::Cursor &position, const QString &text);
/**
* Text got removed.
* @param range range where the removal occurred
* @param text removed text
*/
void textRemoved (const KTextEditor::Range &range, const QString &text);
private:
/**
* Find block containing given line.
* @param line we want to find block for this line
* @return index of found block
*/
int blockForLine (int line) const;
/**
* Fix start lines of all blocks after the given one
* @param startBlock index of block from which we start to fix
*/
void fixStartLines (int startBlock);
/**
* Balance the given block. Look if it is too small or too large.
* @param index block to balance
*/
void balanceBlock (int index);
/**
* Block for given index in block list.
* @param index block index
* @return block matching this index
*/
TextBlock *blockForIndex (int index) { return m_blocks[index]; }
/**
* A range changed, notify the views, in case of attributes or feedback.
* @param view which view is affected? 0 for all views
* @param startLine start line of change
* @param endLine end line of change
* @param rangeWithAttribute attribute changed or is active, this will perhaps lead to repaints
*/
void notifyAboutRangeChange (KTextEditor::View *view, int startLine, int endLine, bool rangeWithAttribute);
/**
* Mark all modified lines as lines saved on disk (modified line system).
*/
void markModifiedLinesAsSaved();
public:
/**
* Gets the document to which this buffer is bound.
* \return a pointer to the document
*/
KateDocument *document () const { return m_document; }
/**
* Debug output, print whole buffer content with line numbers and line length
* @param title title for this output
*/
void debugPrint (const QString &title) const;
/**
* Return the ranges which affect the given line.
* @param line line to look at
* @param view only return ranges associated with given view
* @param rangesWithAttributeOnly only return ranges which have a attribute set
* @return list of ranges affecting this line
*/
QList<TextRange *> rangesForLine (int line, KTextEditor::View *view, bool rangesWithAttributeOnly) const;
/**
* Check if the given range pointer is still valid.
* @return range pointer still belongs to range for this buffer
*/
bool rangePointerValid (TextRange *range) const { return m_ranges.contains (range); }
/**
* Invalidate all ranges in this buffer.
*/
void invalidateRanges();
//
// sha1 checksum handling
//
public:
/**
* sha1 digest of the document on disk, set either through file loading
* in openFile() or in KateDocument::saveFile()
* @return sha1 digest for this document
*/
const QByteArray &digest () const;
/**
* Set the sha1sum of this buffer. Make sure this checksum is up-to-date
* when reading digest().
* @param sha1sum sha1 digest for the document on disk
*/
void setDigest (const QByteArray & sha1sum);
private:
QByteArray m_digest;
private:
/**
* parent document
*/
KateDocument *m_document;
/**
* text history
*/
TextHistory m_history;
/**
* block size in lines the buffer will try to hold
*/
const int m_blockSize;
/**
* List of blocks which contain the lines of this buffer
*/
QVector<TextBlock *> m_blocks;
/**
* Number of lines in buffer
*/
int m_lines;
/**
* Last used block in the buffer. Is used for speeding up blockForLine.
* May contain invalid index, must be checked before using.
*/
mutable int m_lastUsedBlock;
/**
* Revision of the buffer.
*/
qint64 m_revision;
/**
* Current number of running edit transactions
*/
int m_editingTransactions;
/**
* Revision remembered at start of current editing transaction
*/
qint64 m_editingLastRevision;
/**
* Number of lines remembered at start of current editing transaction
*/
int m_editingLastLines;
/**
* minimal line number changed by last editing transaction
*/
int m_editingMinimalLineChanged;
/**
* maximal line number changed by last editing transaction
*/
int m_editingMaximalLineChanged;
/**
* Set of invalid cursors for this whole buffer.
* Valid cursors are inside the block the belong to.
*/
QSet<TextCursor *> m_invalidCursors;
/**
* Set of ranges of this whole buffer.
*/
QSet<TextRange *> m_ranges;
/**
* Fallback text codec to use
*/
QTextCodec *m_fallbackTextCodec;
/**
* Text codec to use
*/
QTextCodec *m_textCodec;
/**
* Should byte order mark be created?
*/
bool m_generateByteOrderMark;
/**
* End of line mode, default is Unix
*/
EndOfLineMode m_endOfLineMode;
/**
* Insert newline character at the end of the file?
*/
bool m_newLineAtEof;
/**
* Limit for line length, longer lines will be wrapped on load
*/
int m_lineLengthLimit;
};
}
#endif