diff options
Diffstat (limited to 'kate/part/katebuffer.h')
-rw-r--r-- | kate/part/katebuffer.h | 709 |
1 files changed, 709 insertions, 0 deletions
diff --git a/kate/part/katebuffer.h b/kate/part/katebuffer.h new file mode 100644 index 000000000..6b2d48ead --- /dev/null +++ b/kate/part/katebuffer.h @@ -0,0 +1,709 @@ +/* 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; |