You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdelibs/kate/part/katebuffer.h

710 lines
15 KiB

/* This file is part of the KDE libraries
Copyright (c) 2000 Waldo Bastian <bastian@kde.org>
Copyright (C) 2002-2004 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 version 2 as published by the Free Software Foundation.
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_BUFFER_H__
#define __KATE_BUFFER_H__
#include "katetextline.h"
#include "katecodefoldinghelpers.h"
#include <kvmallocator.h>
#include <qptrlist.h>
#include <qobject.h>
#include <qtimer.h>
#include <qvaluevector.h>
class KateLineInfo;
class KateDocument;
class KateHighlighting;
class KateBufBlockList;
class KateBuffer;
class KateFileLoader;
class QTextCodec;
/**
* The KateBufBlock class contains an amount of data representing
* a certain number of lines.
*
* @author Waldo Bastian <bastian@kde.org>
* @author Christoph Cullmann <cullmann@kde.org>
*/
class KateBufBlock
{
friend class KateBufBlockList;
public:
/**
* Create an empty block. (empty == ONE line)
* @param parent buffer the block belongs to
* @param prev previous bufblock in the list
* @param next next bufblock in the list
* @param stream stream to load the content from, if any given
*/
KateBufBlock ( KateBuffer *parent, KateBufBlock *prev = 0, KateBufBlock *next = 0,
KateFileLoader *stream = 0 );
/**
* destroy this block and take care of freeing all mem
*/
~KateBufBlock ();
private:
/**
* fill the block with the lines from the given stream
* @param stream stream to load data from
*/
void fillBlock (KateFileLoader *stream);
public:
/**
* state flags
*/
enum State
{
stateSwapped = 0,
stateClean = 1,
stateDirty = 2
};
/**
* returns the current state of this block
* @return state
*/
State state () const { return m_state; }
public:
/**
* return line @p i
* The first line of this block is line 0.
* if you modifiy this line, please mark the block as dirty
* @param i line to return
* @return line pointer
*/
KateTextLine::Ptr line(uint i);
/**
* insert @p line in front of line @p i
* marks the block dirty
* @param i where to insert
* @param line line pointer
*/
void insertLine(uint i, KateTextLine::Ptr line);
/**
* remove line @p i
* marks the block dirty
* @param i line to remove
*/
void removeLine(uint i);
/**
* mark this block as dirty, will invalidate the swap data
* insert/removeLine will mark the block dirty itself
*/
void markDirty ();
public:
/**
* startLine
* @return first line in block
*/
inline uint startLine () const { return m_startLine; };
/**
* update the first line, needed to keep it up to date
* @param line new startLine
*/
inline void setStartLine (uint line) { m_startLine = line; }
/**
* first line behind this block
* @return line behind block
*/
inline uint endLine () const { return m_startLine + m_lines; }
/**
* lines in this block
* @return lines
*/
inline uint lines () const { return m_lines; }
/**
* prev block
* @return previous block
*/
inline KateBufBlock *prev () { return m_prev; }
/**
* next block
* @return next block
*/
inline KateBufBlock *next () { return m_next; }
/**
* methodes to swap in/out
*/
private:
/**
* swap in the kvmallocater data, create string list
*/
void swapIn ();
/**
* swap our string list out, delete it !
*/
void swapOut ();
private:
/**
* VERY IMPORTANT, state of this block
* this uchar indicates if the block is swapped, loaded, clean or dirty
*/
KateBufBlock::State m_state;
/**
* IMPORTANT, start line
*/
uint m_startLine;
/**
* IMPORTANT, line count
*/
uint m_lines;
/**
* here we swap our stuff
*/
KVMAllocator::Block *m_vmblock;
/**
* swapped size
*/
uint m_vmblockSize;
/**
* list of textlines
*/
QValueVector<KateTextLine::Ptr> m_stringList;
/**
* parent buffer.
*/
KateBuffer* m_parent;
/**
* prev block
*/
KateBufBlock *m_prev;
/**
* next block
*/
KateBufBlock *m_next;
private:
/**
* list pointer, to which list I belong
* list element pointers for the KateBufBlockList ONLY !!!
*/
KateBufBlockList *list;
/**
* prev list item
*/
KateBufBlock *listPrev;
/**
* next list item
*/
KateBufBlock *listNext;
};
/**
* list which allows O(1) inserts/removes
* will not delete the elements on remove
* will use the next/prevNode pointers in the KateBufBlocks !
* internal use: loaded/clean/dirty block lists
*
* @author Christoph Cullmann <cullmann@kde.org>
*/
class KateBufBlockList
{
public:
/**
* Default Constructor
*/
KateBufBlockList ();
public:
/**
* count of blocks in this list
* @return count of blocks
*/
inline uint count() const { return m_count; }
/**
* first block in this list or 0
* @return head of list
*/
inline KateBufBlock *first () { return m_first; };
/**
* last block in this list or 0
* @return end of list
*/
inline KateBufBlock *last () { return m_last; };
/**
* is buf the last block?
* @param buf block to test
* @return is this block the first one?
*/
inline bool isFirst (KateBufBlock *buf) { return m_first == buf; };
/**
* is buf the last block?
* @param buf block to test
* @return is this block the last one?
*/
inline bool isLast (KateBufBlock *buf) { return m_last == buf; };
/**
* append a block to this list !
* will remove it from the list it belonged before !
* @param buf block to append
*/
void append (KateBufBlock *buf);
/**
* remove the block from the list it belongs to !
* @param buf block to remove
*/
inline static void remove (KateBufBlock *buf)
{
if (buf->list)
buf->list->removeInternal (buf);
}
private:
/**
* internal helper for remove
* @param buf block to remove
*/
void removeInternal (KateBufBlock *buf);
private:
/**
* count of blocks in list
*/
uint m_count;
/**
* first block
*/
KateBufBlock *m_first;
/**
* last block
*/
KateBufBlock *m_last;
};
/**
* The KateBuffer class maintains a collections of lines.
* It allows to maintain state information in a lazy way.
* It handles swapping out of data using secondary storage.
*
* It is designed to handle large amounts of text-data efficiently
* with respect to CPU and memory usage.
*
* @author Waldo Bastian <bastian@kde.org>
* @author Christoph Cullmann <cullmann@kde.org>
*/
class KateBuffer : public QObject
{
Q_OBJECT
friend class KateBufBlock;
public:
/**
* maximal loaded block count
* @return max loaded blocks
*/
inline static uint maxLoadedBlocks () { return m_maxLoadedBlocks; }
/**
* modifier for max loaded blocks limit
* @param count new limit
*/
static void setMaxLoadedBlocks (uint count);
private:
/**
* global max loaded blocks limit
*/
static uint m_maxLoadedBlocks;
public:
/**
* Create an empty buffer.
* @param doc parent document
*/
KateBuffer (KateDocument *doc);
/**
* Goodbye buffer
*/
~KateBuffer ();
public:
/**
* start some editing action
*/
void editStart ();
/**
* finish some editing action
*/
void editEnd ();
/**
* were there changes in the current running
* editing session?
* @return changes done?
*/
inline bool editChanged () const { return editChangesDone; }
/**
* dirty lines start
* @return start line
*/
inline uint editTagStart () const { return editTagLineStart; }
/**
* dirty lines end
* @return end line
*/
inline uint editTagEnd () const { return editTagLineEnd; }
/**
* line inserted/removed?
* @return line inserted/removed?
*/
inline bool editTagFrom () const { return editTagLineFrom; }
private:
/**
* edit session recursion
*/
uint editSessionNumber;
/**
* is a edit session running
*/
bool editIsRunning;
/**
* dirty lines start at line
*/
uint editTagLineStart;
/**
* dirty lines end at line
*/
uint editTagLineEnd;
/**
* a line was inserted or removed
*/
bool editTagLineFrom;
/**
* changes done?
*/
bool editChangesDone;
public:
/**
* Clear the buffer.
*/
void clear();
/**
* Open a file, use the given filename
* @param m_file filename to open
* @return success
*/
bool openFile (const QString &m_file);
/**
* was the last loading broken because of not enough tmp disk space ?
* (will be reseted on successful save of the file, user gets warning if he really wants to do it)
* @return was loading borked?
*/
bool loadingBorked () const { return m_loadingBorked; }
/**
* is this file a binary?
* @return binary file?
*/
bool binary () const { return m_binary; }
/**
* Can the current codec handle all chars
* @return chars can be encoded
*/
bool canEncode ();
/**
* Save the buffer to a file, use the given filename + codec + end of line chars (internal use of qtextstream)
* @param m_file filename to save to
* @return success
*/
bool saveFile (const QString &m_file);
public:
/**
* Return line @p i
*/
inline KateTextLine::Ptr line(uint i)
{
KateBufBlock *buf = findBlock(i);
if (!buf)
return 0;
if (i < m_lineHighlighted)
return buf->line (i - buf->startLine());
return line_internal (buf, i);
}
private:
/**
* line needs hl
*/
KateTextLine::Ptr line_internal (KateBufBlock *buf, uint i);
inline void addIndentBasedFoldingInformation(QMemArray<uint> &foldingList,bool addindent,uint deindent);
inline void updatePreviousNotEmptyLine(KateBufBlock *blk,uint current_line,bool addindent,uint deindent);
public:
/**
* Return line @p i without triggering highlighting
*/
inline KateTextLine::Ptr plainLine(uint i)
{
KateBufBlock *buf = findBlock(i);
if (!buf)
return 0;
return buf->line(i - buf->startLine());
}
/**
* Return the total number of lines in the buffer.
*/
inline uint count() const { return m_lines; }
private:
/**
* Find the block containing line @p i
* index pointer gets filled with index of block in m_blocks
* index only valid if returned block != 0 !
*/
KateBufBlock *findBlock (uint i, uint *index = 0)
{
// out of range !
if (i >= m_lines)
return 0;
if ((m_blocks[m_lastFoundBlock]->startLine() <= i) && (m_blocks[m_lastFoundBlock]->endLine() > i))
{
if (index)
(*index) = m_lastFoundBlock;
return m_blocks[m_lastFoundBlock];
}
return findBlock_internal (i, index);
}
KateBufBlock *findBlock_internal (uint i, uint *index = 0);
public:
/**
* Mark line @p i as changed !
*/
void changeLine(uint i);
/**
* Insert @p line in front of line @p i
*/
void insertLine(uint i, KateTextLine::Ptr line);
/**
* Remove line @p i
*/
void removeLine(uint i);
public:
inline uint countVisible () { return m_lines - m_regionTree.getHiddenLinesCount(m_lines); }
inline uint lineNumber (uint visibleLine) { return m_regionTree.getRealLine (visibleLine); }
inline uint lineVisibleNumber (uint line) { return m_regionTree.getVirtualLine (line); }
inline void lineInfo (KateLineInfo *info, unsigned int line) { m_regionTree.getLineInfo(info,line); }
inline uint tabWidth () const { return m_tabWidth; }
public:
void setTabWidth (uint w);
/**
* Use @p highlight for highlighting
*
* @p highlight may be 0 in which case highlighting
* will be disabled.
*/
void setHighlight (uint hlMode);
KateHighlighting *highlight () { return m_highlight; };
/**
* Invalidate highlighting of whole buffer.
*/
void invalidateHighlighting();
KateCodeFoldingTree *foldingTree () { return &m_regionTree; };
public slots:
void codeFoldingColumnUpdate(unsigned int lineNr);
private:
/**
* Highlight information needs to be updated.
*
* @param buf The buffer being processed.
* @param startState highlighting state of last line before range
* @param from first line in range
* @param to last line in range
* @param invalidat should the rehighlighted lines be tagged ?
*
* @returns true when the highlighting in the next block needs to be updated,
* false otherwise.
*/
bool doHighlight (KateBufBlock *buf, uint from, uint to, bool invalidate);
signals:
/**
* Emittend if codefolding returned with a changed list
*/
void codeFoldingUpdated();
/**
* Emitted when the highlighting of a certain range has
* changed.
*/
void tagLines(int start, int end);
private:
/**
* document we belong too
*/
KateDocument *m_doc;
/**
* current line count
*/
uint m_lines;
/**
* ALL blocks
* in order of linenumbers
*/
QValueVector<KateBufBlock*> m_blocks;
/**
* last block where the start/end line is in sync with real life
*/
uint m_lastInSyncBlock;
/**
* last block found by findBlock, there to make searching faster
*/
uint m_lastFoundBlock;
/**
* status of the cache read/write errors
* write errors get handled, read errors not really atm
*/
bool m_cacheReadError;
bool m_cacheWriteError;
/**
* had we cache error while loading ?
*/
bool m_loadingBorked;
/**
* binary file loaded ?
*/
bool m_binary;
/**
* highlighting & folding relevant stuff
*/
private:
/**
* current highlighting mode or 0
*/
KateHighlighting *m_highlight;
/**
* folding tree
*/
KateCodeFoldingTree m_regionTree;
// for the scrapty indent sensitive langs
uint m_tabWidth;
uint m_lineHighlightedMax;
uint m_lineHighlighted;
/**
* number of dynamic contexts causing a full invalidation
*/
uint m_maxDynamicContexts;
/**
* only used from the KateBufBlocks !
*/
private:
/**
* all not swapped blocks !
*/
KateBufBlockList m_loadedBlocks;
};
#endif
// kate: space-indent on; indent-width 2; replace-tabs on;