#ifndef __BUFFER_HPP #define __BUFFER_HPP struct BlockHeader { unsigned bytesUsed; unsigned lines; }; #define BLOCKSIZE 4096 #define BLOCKSPARE (BLOCKSIZE-sizeof(BlockHeader)) struct Block : public BlockHeader { char c[BLOCKSPARE]; Block(); void splitLine(unsigned line, unsigned col); void joinLine(unsigned line); void removeLine(unsigned line); char *queryLinePtr(unsigned line); const char *queryLinePtr(unsigned line) const; unsigned queryLineLength(unsigned line) const; unsigned available() const { return BLOCKSPARE-bytesUsed; } void splitTo(Block *bp); void insert(unsigned line, unsigned col, char c); void insert(unsigned line, unsigned col, const char *s, unsigned stringlength); void remove(unsigned line, unsigned col); void remove(unsigned line, unsigned col, unsigned chars); void appendLine(); //private: void recalcLines(); unsigned findLineStart(unsigned line); }; class BufferMark; class Buffer { Block **block; unsigned blocks; unsigned blocksAlloc; BufferMark *firstMark; int changed; friend int main(int,char**); public: Buffer(); virtual ~Buffer(); enum { last_line=0xFFFFFFFFUL, last_character=0xFFFFFFFFUL }; void splitLine(unsigned line, unsigned col); void joinLine(unsigned line); void removeLine(unsigned line); void appendLine(); void insert(unsigned line, unsigned col, char c); void insert(unsigned line, unsigned col, const char *s, int sl=-1); void remove(unsigned line, unsigned col, unsigned chars); void clear(); unsigned queryLineCount() const; char *queryLinePtr(unsigned line); const char *queryLinePtr(unsigned line) const; unsigned queryLineLength(unsigned line) const; void addMark(BufferMark *bm); void removeMark(BufferMark *bm); void compact(); void fastCompact(); int queryChanged() const { return changed; } void setChanged(int newflag) { changed=newflag; } private: unsigned findBlockWithLine(unsigned *line) const; void splitBlock(unsigned &b, unsigned absoluteLine, unsigned &relativeLine); void insertBlock(Block *bp, unsigned before); void removeBlock(unsigned at); static void fixcol(Block *bp, unsigned line, unsigned &col); static void fixcolpo(Block *bp, unsigned line, unsigned &col); }; class BufferMark { unsigned line,col; unsigned char changed; BufferMark *next; friend class Buffer; public: enum stickto { left,right}; private: stickto stick; public: BufferMark() : line(0),col(0),changed(0),next(0), stick(right) {} BufferMark(unsigned l, unsigned c, stickto s) : line(l), col(c), changed(0),next(0), stick(s) {} BufferMark(const BufferMark &bm) : line(bm.line), col(bm.col), changed(0), next(0), stick(bm.stick) {} virtual ~BufferMark() {}; BufferMark &operator=(const BufferMark &bm) { line=bm.line; col=bm.col; changed=1; return *this; } unsigned queryLine() const { return line; } unsigned queryCol() const { return col; } void setLine(unsigned nl) { line=nl; changed=1; } void setCol(unsigned nc) { col=nc; changed=1; } void set(unsigned l, unsigned c) { line=l; col=c; changed=1; } int queryChanged() const { return changed; } void resetChanged() { changed=0; } int operator<(const BufferMark &bm) const { return line=(const BufferMark &bm) const { return line>bm.line || (line==bm.line && col>=bm.col); } int operator>(const BufferMark &bm) const { return line>bm.line || (line==bm.line && col>bm.col); } int operator!=(const BufferMark &bm) const { return line!=bm.line || line!=bm.line; } }; #endif