2
This file is part of Konsole, an X terminal.
3
Copyright 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
5
This program is free software; you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation; either version 2 of the License, or
8
(at your option) any later version.
10
This program 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
13
GNU General Public License for more details.
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25
#include <QtCore/QBitRef>
26
#include <QtCore/QHash>
27
#include <QtCore/QVector>
28
#include <QTemporaryFile>
31
//#include <ktemporaryfile.h>
34
#include "BlockArray.h"
35
#include "Character.h"
43
An extendable tmpfile(1) based buffer.
50
virtual ~HistoryFile();
52
virtual void add(const unsigned char* bytes, int len);
53
virtual void get(unsigned char* bytes, int len, int loc);
56
//mmaps the file in read-only mode
60
//returns true if the file is mmap'ed
67
QTemporaryFile tmpFile;
69
//pointer to start of mmap'ed file data, or 0 if the file is not mmap'ed
72
//incremented whenver 'add' is called and decremented whenever
74
//this is used to detect when a large number of lines are being read and processed from the history
75
//and automatically mmap the file for better performance (saves the overhead of many lseek-read calls).
78
//when readWriteBalance goes below this threshold, the file will be mmap'ed automatically
79
static const int MAP_THRESHOLD = -1000;
83
//////////////////////////////////////////////////////////////////////
85
//////////////////////////////////////////////////////////////////////
86
// Abstract base class for file and buffer versions
87
//////////////////////////////////////////////////////////////////////
93
HistoryScroll(HistoryType*);
94
virtual ~HistoryScroll();
96
virtual bool hasScroll();
99
virtual int getLines() = 0;
100
virtual int getLineLen(int lineno) = 0;
101
virtual void getCells(int lineno, int colno, int count, Character res[]) = 0;
102
virtual bool isWrappedLine(int lineno) = 0;
104
// backward compatibility (obsolete)
105
Character getCell(int lineno, int colno) { Character res; getCells(lineno,colno,1,&res); return res; }
108
virtual void addCells(const Character a[], int count) = 0;
109
// convenience method - this is virtual so that subclasses can take advantage
110
// of QVector's implicit copying
111
virtual void addCellsVector(const QVector<Character>& cells)
113
addCells(cells.data(),cells.size());
116
virtual void addLine(bool previousWrapped=false) = 0;
119
// FIXME: Passing around constant references to HistoryType instances
120
// is very unsafe, because those references will no longer
121
// be valid if the history scroll is deleted.
123
const HistoryType& getType() { return *m_histType; }
126
HistoryType* m_histType;
132
//////////////////////////////////////////////////////////////////////
133
// File-based history (e.g. file log, no limitation in length)
134
//////////////////////////////////////////////////////////////////////
136
class HistoryScrollFile : public HistoryScroll
139
HistoryScrollFile(const QString &logFileName);
140
virtual ~HistoryScrollFile();
142
virtual int getLines();
143
virtual int getLineLen(int lineno);
144
virtual void getCells(int lineno, int colno, int count, Character res[]);
145
virtual bool isWrappedLine(int lineno);
147
virtual void addCells(const Character a[], int count);
148
virtual void addLine(bool previousWrapped=false);
151
int startOfLine(int lineno);
153
QString m_logFileName;
154
HistoryFile index; // lines Row(int)
155
HistoryFile cells; // text Row(Character)
156
HistoryFile lineflags; // flags Row(unsigned char)
160
//////////////////////////////////////////////////////////////////////
161
// Buffer-based history (limited to a fixed nb of lines)
162
//////////////////////////////////////////////////////////////////////
163
class HistoryScrollBuffer : public HistoryScroll
166
typedef QVector<Character> HistoryLine;
168
HistoryScrollBuffer(unsigned int maxNbLines = 1000);
169
virtual ~HistoryScrollBuffer();
171
virtual int getLines();
172
virtual int getLineLen(int lineno);
173
virtual void getCells(int lineno, int colno, int count, Character res[]);
174
virtual bool isWrappedLine(int lineno);
176
virtual void addCells(const Character a[], int count);
177
virtual void addCellsVector(const QVector<Character>& cells);
178
virtual void addLine(bool previousWrapped=false);
180
void setMaxNbLines(unsigned int nbLines);
181
unsigned int maxNbLines() { return _maxLineCount; }
185
int bufferIndex(int lineNumber);
187
HistoryLine* _historyBuffer;
188
QBitArray _wrappedLine;
193
//QVector<histline*> m_histBuffer;
194
//QBitArray m_wrappedLine;
195
//unsigned int m_maxNbLines;
196
//unsigned int m_nbLines;
197
//unsigned int m_arrayIndex;
201
/*class HistoryScrollBufferV2 : public HistoryScroll
204
virtual int getLines();
205
virtual int getLineLen(int lineno);
206
virtual void getCells(int lineno, int colno, int count, Character res[]);
207
virtual bool isWrappedLine(int lineno);
209
virtual void addCells(const Character a[], int count);
210
virtual void addCells(const QVector<Character>& cells);
211
virtual void addLine(bool previousWrapped=false);
217
//////////////////////////////////////////////////////////////////////
218
// Nothing-based history (no history :-)
219
//////////////////////////////////////////////////////////////////////
220
class HistoryScrollNone : public HistoryScroll
224
virtual ~HistoryScrollNone();
226
virtual bool hasScroll();
228
virtual int getLines();
229
virtual int getLineLen(int lineno);
230
virtual void getCells(int lineno, int colno, int count, Character res[]);
231
virtual bool isWrappedLine(int lineno);
233
virtual void addCells(const Character a[], int count);
234
virtual void addLine(bool previousWrapped=false);
237
//////////////////////////////////////////////////////////////////////
238
// BlockArray-based history
239
//////////////////////////////////////////////////////////////////////
240
class HistoryScrollBlockArray : public HistoryScroll
243
HistoryScrollBlockArray(size_t size);
244
virtual ~HistoryScrollBlockArray();
246
virtual int getLines();
247
virtual int getLineLen(int lineno);
248
virtual void getCells(int lineno, int colno, int count, Character res[]);
249
virtual bool isWrappedLine(int lineno);
251
virtual void addCells(const Character a[], int count);
252
virtual void addLine(bool previousWrapped=false);
255
BlockArray m_blockArray;
256
QHash<int,size_t> m_lineLengths;
259
//////////////////////////////////////////////////////////////////////
260
// History using compact storage
261
// This implementation uses a list of fixed-sized blocks
262
// where history lines are allocated in (avoids heap fragmentation)
263
//////////////////////////////////////////////////////////////////////
264
typedef QVector<Character> TextLine;
266
class CharacterFormat
269
bool equalsFormat(const CharacterFormat &other) const {
270
return other.rendition==rendition && other.fgColor==fgColor && other.bgColor==bgColor;
273
bool equalsFormat(const Character &c) const {
274
return c.rendition==rendition && c.foregroundColor==fgColor && c.backgroundColor==bgColor;
277
void setFormat(const Character& c) {
278
rendition=c.rendition;
279
fgColor=c.foregroundColor;
280
bgColor=c.backgroundColor;
283
CharacterColor fgColor, bgColor;
288
class CompactHistoryBlock
292
CompactHistoryBlock(){
293
blockLength = 4096*64; // 256kb
294
head = (quint8*) mmap(0, blockLength, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
295
//head = (quint8*) malloc(blockLength);
296
Q_ASSERT(head != MAP_FAILED);
297
tail = blockStart = head;
301
virtual ~CompactHistoryBlock(){
303
munmap(blockStart, blockLength);
306
virtual unsigned int remaining(){ return blockStart+blockLength-tail;}
307
virtual unsigned length() { return blockLength; }
308
virtual void* allocate(size_t length);
309
virtual bool contains(void *addr) {return addr>=blockStart && addr<(blockStart+blockLength);}
310
virtual void deallocate();
311
virtual bool isInUse(){ return allocCount!=0; } ;
321
class CompactHistoryBlockList {
323
CompactHistoryBlockList() {};
324
~CompactHistoryBlockList();
326
void *allocate( size_t size );
327
void deallocate(void *);
328
int length() {return list.size();}
330
QList<CompactHistoryBlock*> list;
333
class CompactHistoryLine
336
CompactHistoryLine(const TextLine&, CompactHistoryBlockList& blockList);
337
virtual ~CompactHistoryLine();
339
// custom new operator to allocate memory from custom pool instead of heap
340
static void *operator new( size_t size, CompactHistoryBlockList& blockList);
341
static void operator delete( void *) { /* do nothing, deallocation from pool is done in destructor*/ } ;
343
virtual void getCharacters(Character* array, int length, int startColumn) ;
344
virtual void getCharacter(int index, Character &r) ;
345
virtual bool isWrapped() const {return wrapped;};
346
virtual void setWrapped(bool isWrapped) { wrapped=isWrapped;};
347
virtual unsigned int getLength() const {return length;};
350
CompactHistoryBlockList& blockList;
351
CharacterFormat* formatArray;
354
quint16 formatLength;
358
class CompactHistoryScroll : public HistoryScroll
360
typedef QList<CompactHistoryLine*> HistoryArray;
363
CompactHistoryScroll(unsigned int maxNbLines = 1000);
364
virtual ~CompactHistoryScroll();
366
virtual int getLines();
367
virtual int getLineLen(int lineno);
368
virtual void getCells(int lineno, int colno, int count, Character res[]);
369
virtual bool isWrappedLine(int lineno);
371
virtual void addCells(const Character a[], int count);
372
virtual void addCellsVector(const TextLine& cells);
373
virtual void addLine(bool previousWrapped=false);
375
void setMaxNbLines(unsigned int nbLines);
376
unsigned int maxNbLines() const { return _maxLineCount; }
379
bool hasDifferentColors(const TextLine& line) const;
381
CompactHistoryBlockList blockList;
383
unsigned int _maxLineCount;
386
//////////////////////////////////////////////////////////////////////
388
//////////////////////////////////////////////////////////////////////
394
virtual ~HistoryType();
397
* Returns true if the history is enabled ( can store lines of output )
398
* or false otherwise.
400
virtual bool isEnabled() const = 0;
402
* Returns true if the history size is unlimited.
404
bool isUnlimited() const { return maximumLineCount() == 0; }
406
* Returns the maximum number of lines which this history type
407
* can store or 0 if the history can store an unlimited number of lines.
409
virtual int maximumLineCount() const = 0;
411
virtual HistoryScroll* scroll(HistoryScroll *) const = 0;
414
class HistoryTypeNone : public HistoryType
419
virtual bool isEnabled() const;
420
virtual int maximumLineCount() const;
422
virtual HistoryScroll* scroll(HistoryScroll *) const;
425
class HistoryTypeBlockArray : public HistoryType
428
HistoryTypeBlockArray(size_t size);
430
virtual bool isEnabled() const;
431
virtual int maximumLineCount() const;
433
virtual HistoryScroll* scroll(HistoryScroll *) const;
440
class HistoryTypeFile : public HistoryType
443
HistoryTypeFile(const QString& fileName=QString());
445
virtual bool isEnabled() const;
446
virtual const QString& getFileName() const;
447
virtual int maximumLineCount() const;
449
virtual HistoryScroll* scroll(HistoryScroll *) const;
456
class HistoryTypeBuffer : public HistoryType
458
friend class HistoryScrollBuffer;
461
HistoryTypeBuffer(unsigned int nbLines);
463
virtual bool isEnabled() const;
464
virtual int maximumLineCount() const;
466
virtual HistoryScroll* scroll(HistoryScroll *) const;
469
unsigned int m_nbLines;
472
class CompactHistoryType : public HistoryType
475
CompactHistoryType(unsigned int size);
477
virtual bool isEnabled() const;
478
virtual int maximumLineCount() const;
480
virtual HistoryScroll* scroll(HistoryScroll *) const;
483
unsigned int m_nbLines;
490
#endif // TEHISTORY_H