source: ogBrowser-Git/qtermwidget/lib/History.h

jenkins
Last change on this file was 64efc22, checked in by Vadim Troshchinskiy <vtroshchinskiy@…>, 19 months ago

Update qtermwidget to modern version

  • Property mode set to 100644
File size: 13.0 KB
Line 
1/*
2    This file is part of Konsole, an X terminal.
3    Copyright 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
4
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.
9
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.
14
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
18    02110-1301  USA.
19*/
20
21#ifndef TEHISTORY_H
22#define TEHISTORY_H
23
24// Qt
25#include <QBitRef>
26#include <QHash>
27#include <QVector>
28#include <QTemporaryFile>
29
30// KDE
31//#include <ktemporaryfile.h>
32
33// Konsole
34#include "BlockArray.h"
35#include "Character.h"
36
37// map
38#include <sys/mman.h>
39
40namespace Konsole
41{
42
43#if 1
44/*
45   An extendable tmpfile(1) based buffer.
46*/
47
48class HistoryFile
49{
50public:
51  HistoryFile();
52  virtual ~HistoryFile();
53
54  virtual void add(const unsigned char* bytes, int len);
55  virtual void get(unsigned char* bytes, int len, int loc);
56  virtual int  len();
57
58  //mmaps the file in read-only mode
59  void map();
60  //un-mmaps the file
61  void unmap();
62  //returns true if the file is mmap'ed
63  bool isMapped() const;
64
65
66private:
67  int  ion;
68  int  length;
69  QTemporaryFile tmpFile;
70
71  //pointer to start of mmap'ed file data, or 0 if the file is not mmap'ed
72  char* fileMap;
73
74  //incremented whenever 'add' is called and decremented whenever
75  //'get' is called.
76  //this is used to detect when a large number of lines are being read and processed from the history
77  //and automatically mmap the file for better performance (saves the overhead of many lseek-read calls).
78  int readWriteBalance;
79
80  //when readWriteBalance goes below this threshold, the file will be mmap'ed automatically
81  static const int MAP_THRESHOLD = -1000;
82};
83#endif
84
85//////////////////////////////////////////////////////////////////////
86
87//////////////////////////////////////////////////////////////////////
88// Abstract base class for file and buffer versions
89//////////////////////////////////////////////////////////////////////
90class HistoryType;
91
92class HistoryScroll
93{
94public:
95  HistoryScroll(HistoryType*);
96 virtual ~HistoryScroll();
97
98  virtual bool hasScroll();
99
100  // access to history
101  virtual int  getLines() = 0;
102  virtual int  getLineLen(int lineno) = 0;
103  virtual void getCells(int lineno, int colno, int count, Character res[]) = 0;
104  virtual bool isWrappedLine(int lineno) = 0;
105
106  // backward compatibility (obsolete)
107  Character   getCell(int lineno, int colno) { Character res; getCells(lineno,colno,1,&res); return res; }
108
109  // adding lines.
110  virtual void addCells(const Character a[], int count) = 0;
111  // convenience method - this is virtual so that subclasses can take advantage
112  // of QVector's implicit copying
113  virtual void addCellsVector(const QVector<Character>& cells)
114  {
115    addCells(cells.data(),cells.size());
116  }
117
118  virtual void addLine(bool previousWrapped=false) = 0;
119
120  //
121  // FIXME:  Passing around constant references to HistoryType instances
122  // is very unsafe, because those references will no longer
123  // be valid if the history scroll is deleted.
124  //
125  const HistoryType& getType() { return *m_histType; }
126
127protected:
128  HistoryType* m_histType;
129
130};
131
132#if 1
133
134//////////////////////////////////////////////////////////////////////
135// File-based history (e.g. file log, no limitation in length)
136//////////////////////////////////////////////////////////////////////
137
138class HistoryScrollFile : public HistoryScroll
139{
140public:
141  HistoryScrollFile(const QString &logFileName);
142  ~HistoryScrollFile() override;
143
144  int  getLines() override;
145  int  getLineLen(int lineno) override;
146  void getCells(int lineno, int colno, int count, Character res[]) override;
147  bool isWrappedLine(int lineno) override;
148
149  void addCells(const Character a[], int count) override;
150  void addLine(bool previousWrapped=false) override;
151
152private:
153  int startOfLine(int lineno);
154
155  QString m_logFileName;
156  HistoryFile index; // lines Row(int)
157  HistoryFile cells; // text  Row(Character)
158  HistoryFile lineflags; // flags Row(unsigned char)
159};
160
161
162//////////////////////////////////////////////////////////////////////
163// Buffer-based history (limited to a fixed nb of lines)
164//////////////////////////////////////////////////////////////////////
165class HistoryScrollBuffer : public HistoryScroll
166{
167public:
168  typedef QVector<Character> HistoryLine;
169
170  HistoryScrollBuffer(unsigned int maxNbLines = 1000);
171  ~HistoryScrollBuffer() override;
172
173  int  getLines() override;
174  int  getLineLen(int lineno) override;
175  void getCells(int lineno, int colno, int count, Character res[]) override;
176  bool isWrappedLine(int lineno) override;
177
178  void addCells(const Character a[], int count) override;
179  void addCellsVector(const QVector<Character>& cells) override;
180  void addLine(bool previousWrapped=false) override;
181
182  void setMaxNbLines(unsigned int nbLines);
183  unsigned int maxNbLines() const { return _maxLineCount; }
184
185
186private:
187  int bufferIndex(int lineNumber) const;
188
189  HistoryLine* _historyBuffer;
190  QBitArray _wrappedLine;
191  int _maxLineCount;
192  int _usedLines;
193  int _head;
194
195  //QVector<histline*> m_histBuffer;
196  //QBitArray m_wrappedLine;
197  //unsigned int m_maxNbLines;
198  //unsigned int m_nbLines;
199  //unsigned int m_arrayIndex;
200  //bool         m_buffFilled;
201};
202
203/*class HistoryScrollBufferV2 : public HistoryScroll
204{
205public:
206  virtual int  getLines();
207  virtual int  getLineLen(int lineno);
208  virtual void getCells(int lineno, int colno, int count, Character res[]);
209  virtual bool isWrappedLine(int lineno);
210
211  virtual void addCells(const Character a[], int count);
212  virtual void addCells(const QVector<Character>& cells);
213  virtual void addLine(bool previousWrapped=false);
214
215};*/
216
217#endif
218
219//////////////////////////////////////////////////////////////////////
220// Nothing-based history (no history :-)
221//////////////////////////////////////////////////////////////////////
222class HistoryScrollNone : public HistoryScroll
223{
224public:
225  HistoryScrollNone();
226  ~HistoryScrollNone() override;
227
228  bool hasScroll() override;
229
230  int  getLines() override;
231  int  getLineLen(int lineno) override;
232  void getCells(int lineno, int colno, int count, Character res[]) override;
233  bool isWrappedLine(int lineno) override;
234
235  void addCells(const Character a[], int count) override;
236  void addLine(bool previousWrapped=false) override;
237};
238
239//////////////////////////////////////////////////////////////////////
240// BlockArray-based history
241//////////////////////////////////////////////////////////////////////
242class HistoryScrollBlockArray : public HistoryScroll
243{
244public:
245  HistoryScrollBlockArray(size_t size);
246  ~HistoryScrollBlockArray() override;
247
248  int  getLines() override;
249  int  getLineLen(int lineno) override;
250  void getCells(int lineno, int colno, int count, Character res[]) override;
251  bool isWrappedLine(int lineno) override;
252
253  void addCells(const Character a[], int count) override;
254  void addLine(bool previousWrapped=false) override;
255
256protected:
257  BlockArray m_blockArray;
258  QHash<int,size_t> m_lineLengths;
259};
260
261//////////////////////////////////////////////////////////////////////
262// History using compact storage
263// This implementation uses a list of fixed-sized blocks
264// where history lines are allocated in (avoids heap fragmentation)
265//////////////////////////////////////////////////////////////////////
266typedef QVector<Character> TextLine;
267
268class CharacterFormat
269{
270public:
271  bool equalsFormat(const CharacterFormat &other) const {
272    return other.rendition==rendition && other.fgColor==fgColor && other.bgColor==bgColor;
273  }
274
275  bool equalsFormat(const Character &c) const {
276    return c.rendition==rendition && c.foregroundColor==fgColor && c.backgroundColor==bgColor;
277  }
278
279  void setFormat(const Character& c) {
280    rendition=c.rendition;
281    fgColor=c.foregroundColor;
282    bgColor=c.backgroundColor;
283  }
284
285  CharacterColor fgColor, bgColor;
286  quint16 startPos;
287  quint8 rendition;
288};
289
290class CompactHistoryBlock
291{
292public:
293
294  CompactHistoryBlock(){
295    blockLength = 4096*64; // 256kb
296    head = (quint8*) mmap(nullptr, blockLength, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
297    //head = (quint8*) malloc(blockLength);
298    Q_ASSERT(head != MAP_FAILED);
299    tail = blockStart = head;
300    allocCount=0;
301  }
302
303  virtual ~CompactHistoryBlock(){
304    //free(blockStart);
305    munmap(blockStart, blockLength);
306  }
307
308  virtual unsigned int remaining(){ return blockStart+blockLength-tail;}
309  virtual unsigned  length() { return blockLength; }
310  virtual void* allocate(size_t length);
311  virtual bool contains(void *addr) {return addr>=blockStart && addr<(blockStart+blockLength);}
312  virtual void deallocate();
313  virtual bool isInUse(){ return allocCount!=0; } ;
314
315private:
316  size_t blockLength;
317  quint8* head;
318  quint8* tail;
319  quint8* blockStart;
320  int allocCount;
321};
322
323class CompactHistoryBlockList {
324public:
325  CompactHistoryBlockList() {};
326  ~CompactHistoryBlockList();
327
328  void *allocate( size_t size );
329  void deallocate(void *);
330  int length() {return list.size();}
331private:
332  QList<CompactHistoryBlock*> list;
333};
334
335class CompactHistoryLine
336{
337public:
338  CompactHistoryLine(const TextLine&, CompactHistoryBlockList& blockList);
339  virtual ~CompactHistoryLine();
340
341  // custom new operator to allocate memory from custom pool instead of heap
342  static void *operator new( size_t size, CompactHistoryBlockList& blockList);
343  static void operator delete( void *) { /* do nothing, deallocation from pool is done in destructor*/ } ;
344
345  virtual void getCharacters(Character* array, int length, int startColumn) ;
346  virtual void getCharacter(int index, Character &r) ;
347  virtual bool isWrapped() const {return wrapped;};
348  virtual void setWrapped(bool isWrapped) { wrapped=isWrapped;};
349  virtual unsigned int getLength() const {return length;};
350
351protected:
352  CompactHistoryBlockList& blockList;
353  CharacterFormat* formatArray;
354  quint16 length;
355  quint16* text;
356  quint16 formatLength;
357  bool wrapped;
358};
359
360class CompactHistoryScroll : public HistoryScroll
361{
362  typedef QList<CompactHistoryLine*> HistoryArray;
363
364public:
365  CompactHistoryScroll(unsigned int maxNbLines = 1000);
366  ~CompactHistoryScroll() override;
367
368  int  getLines() override;
369  int  getLineLen(int lineno) override;
370  void getCells(int lineno, int colno, int count, Character res[]) override;
371  bool isWrappedLine(int lineno) override;
372
373  void addCells(const Character a[], int count) override;
374  void addCellsVector(const TextLine& cells) override;
375  void addLine(bool previousWrapped=false) override;
376
377  void setMaxNbLines(unsigned int nbLines);
378  unsigned int maxNbLines() const { return _maxLineCount; }
379
380private:
381  bool hasDifferentColors(const TextLine& line) const;
382  HistoryArray lines;
383  CompactHistoryBlockList blockList;
384
385  unsigned int _maxLineCount;
386};
387
388//////////////////////////////////////////////////////////////////////
389// History type
390//////////////////////////////////////////////////////////////////////
391
392class HistoryType
393{
394public:
395  HistoryType();
396  virtual ~HistoryType();
397
398  /**
399   * Returns true if the history is enabled ( can store lines of output )
400   * or false otherwise.
401   */
402  virtual bool isEnabled()           const = 0;
403  /**
404   * Returns true if the history size is unlimited.
405   */
406  bool isUnlimited() const { return maximumLineCount() == 0; }
407  /**
408   * Returns the maximum number of lines which this history type
409   * can store or 0 if the history can store an unlimited number of lines.
410   */
411  virtual int maximumLineCount()    const = 0;
412
413  virtual HistoryScroll* scroll(HistoryScroll *) const = 0;
414};
415
416class HistoryTypeNone : public HistoryType
417{
418public:
419  HistoryTypeNone();
420
421  bool isEnabled() const override;
422  int maximumLineCount() const override;
423
424  HistoryScroll* scroll(HistoryScroll *) const override;
425};
426
427class HistoryTypeBlockArray : public HistoryType
428{
429public:
430  HistoryTypeBlockArray(size_t size);
431
432  bool isEnabled() const override;
433  int maximumLineCount() const override;
434
435  HistoryScroll* scroll(HistoryScroll *) const override;
436
437protected:
438  size_t m_size;
439};
440
441#if 1
442class HistoryTypeFile : public HistoryType
443{
444public:
445  HistoryTypeFile(const QString& fileName=QString());
446
447  bool isEnabled() const override;
448  virtual const QString& getFileName() const;
449  int maximumLineCount() const override;
450
451  HistoryScroll* scroll(HistoryScroll *) const override;
452
453protected:
454  QString m_fileName;
455};
456
457
458class HistoryTypeBuffer : public HistoryType
459{
460    friend class HistoryScrollBuffer;
461
462public:
463  HistoryTypeBuffer(unsigned int nbLines);
464
465  bool isEnabled() const override;
466  int maximumLineCount() const override;
467
468  HistoryScroll* scroll(HistoryScroll *) const override;
469
470protected:
471  unsigned int m_nbLines;
472};
473
474class CompactHistoryType : public HistoryType
475{
476public:
477  CompactHistoryType(unsigned int size);
478
479  bool isEnabled() const override;
480  int maximumLineCount() const override;
481
482  HistoryScroll* scroll(HistoryScroll *) const override;
483
484protected:
485  unsigned int m_nbLines;
486};
487
488
489#endif
490
491}
492
493#endif // TEHISTORY_H
Note: See TracBrowser for help on using the repository browser.