1 /*
2     This file is part of Konsole, an X terminal.
3     Copyright (C) 1997-1998, 2013 by Lars Doelle <lars.doelle@on-line.de>
4 
5     Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
6 
7     This program is free software: you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11 
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16 
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20     02110-1301  USA.
21 */
22 
23 #ifndef HISTORY_H
24 #define HISTORY_H
25 
26 // Qt
27 #include <QtCore/QBitRef>
28 #include <QtCore/QHash>
29 #include <QtCore>
30 
31 // Konsole
32 #include "unix/BlockArray.h"
33 #include "unix/Character.h"
34 
35 
36 class HistoryFile
37 {
38 public:
39   HistoryFile();
40   virtual ~HistoryFile();
41 
42   virtual void add(const unsigned char* bytes, int len);
43   virtual void get(unsigned char* bytes, int len, int loc);
44   virtual int  len();
45 
46   //mmaps the file in read-only mode
47   void map();
48   //un-mmaps the file
49   void unmap();
50   //returns true if the file is mmap'ed
51   bool isMapped();
52 
53 
54 private:
55   int  ion;
56   int  length;
57   QTemporaryFile tmpFile;
58 
59   //pointer to start of mmap'ed file data, or 0 if the file is not mmap'ed
60   char* fileMap;
61 
62   //incremented whenver 'add' is called and decremented whenever
63   //'get' is called.
64   //this is used to detect when a large number of lines are being read and processed from the history
65   //and automatically mmap the file for better performance (saves the overhead of many lseek-read calls).
66   int readWriteBalance;
67 
68   //when readWriteBalance goes below this threshold, the file will be mmap'ed automatically
69   static const int MAP_THRESHOLD = -1000;
70 };
71 
72 //////////////////////////////////////////////////////////////////////
73 
74 //////////////////////////////////////////////////////////////////////
75 // Abstract base class for file and buffer versions
76 //////////////////////////////////////////////////////////////////////
77 class HistoryType;
78 
79 class HistoryScroll
80 {
81 public:
82   HistoryScroll(HistoryType*);
83  virtual ~HistoryScroll();
84 
85   virtual bool hasScroll();
86 
87   // access to history
88   virtual int  getLines() = 0;
89   virtual int  getLineLen(int lineno) = 0;
90   virtual void getCells(int lineno, int colno, int count, Character res[]) = 0;
91   virtual bool isWrappedLine(int lineno) = 0;
92 
93   // backward compatibility (obsolete)
getCell(int lineno,int colno)94   Character   getCell(int lineno, int colno) { Character res; getCells(lineno,colno,1,&res); return res; }
95 
96   // adding lines.
97   virtual void addCells(const Character a[], int count) = 0;
98   // convenience method - this is virtual so that subclasses can take advantage
99   // of QVector's implicit copying
addCellsVector(const QVector<Character> & cells)100   virtual void addCellsVector(const QVector<Character>& cells)
101   {
102     addCells(cells.data(),cells.size());
103   }
104 
105   virtual void addLine(bool previousWrapped=false) = 0;
106 
107   //
108   // FIXME:  Passing around constant references to HistoryType instances
109   // is very unsafe, because those references will no longer
110   // be valid if the history scroll is deleted.
111   //
getType()112   const HistoryType& getType() { return *m_histType; }
113 
114 protected:
115   HistoryType* m_histType;
116 
117 };
118 
119 
120 //////////////////////////////////////////////////////////////////////
121 // File-based history (e.g. file log, no limitation in length)
122 //////////////////////////////////////////////////////////////////////
123 
124 class HistoryScrollFile : public HistoryScroll
125 {
126 public:
127   HistoryScrollFile(const QString &logFileName);
128   virtual ~HistoryScrollFile();
129 
130   virtual int  getLines();
131   virtual int  getLineLen(int lineno);
132   virtual void getCells(int lineno, int colno, int count, Character res[]);
133   virtual bool isWrappedLine(int lineno);
134 
135   virtual void addCells(const Character a[], int count);
136   virtual void addLine(bool previousWrapped=false);
137 
138 private:
139   int startOfLine(int lineno);
140 
141   QString m_logFileName;
142   HistoryFile index; // lines Row(int)
143   HistoryFile cells; // text  Row(Character)
144   HistoryFile lineflags; // flags Row(unsigned char)
145 };
146 
147 
148 //////////////////////////////////////////////////////////////////////
149 // Buffer-based history (limited to a fixed nb of lines)
150 //////////////////////////////////////////////////////////////////////
151 class HistoryScrollBuffer : public HistoryScroll
152 {
153 public:
154   typedef QVector<Character> HistoryLine;
155 
156   HistoryScrollBuffer(unsigned int maxNbLines = 1000);
157   virtual ~HistoryScrollBuffer();
158 
159   virtual int  getLines();
160   virtual int  getLineLen(int lineno);
161   virtual void getCells(int lineno, int colno, int count, Character res[]);
162   virtual bool isWrappedLine(int lineno);
163 
164   virtual void addCells(const Character a[], int count);
165   virtual void addCellsVector(const QVector<Character>& cells);
166   virtual void addLine(bool previousWrapped=false);
167 
168   void setMaxNbLines(unsigned int nbLines);
maxNbLines()169   unsigned int maxNbLines() { return _maxLineCount; }
170 
171 
172 private:
173   int bufferIndex(int lineNumber);
174 
175   HistoryLine* _historyBuffer;
176   QBitArray _wrappedLine;
177   int _maxLineCount;
178   int _usedLines;
179   int _head;
180 
181   //QVector<histline*> m_histBuffer;
182   //QBitArray m_wrappedLine;
183   //unsigned int m_maxNbLines;
184   //unsigned int m_nbLines;
185   //unsigned int m_arrayIndex;
186   //bool         m_buffFilled;
187 };
188 
189 /*class HistoryScrollBufferV2 : public HistoryScroll
190 {
191 public:
192   virtual int  getLines();
193   virtual int  getLineLen(int lineno);
194   virtual void getCells(int lineno, int colno, int count, Character res[]);
195   virtual bool isWrappedLine(int lineno);
196 
197   virtual void addCells(const Character a[], int count);
198   virtual void addCells(const QVector<Character>& cells);
199   virtual void addLine(bool previousWrapped=false);
200 
201 };*/
202 
203 
204 //////////////////////////////////////////////////////////////////////
205 // Nothing-based history (no history :-)
206 //////////////////////////////////////////////////////////////////////
207 class HistoryScrollNone : public HistoryScroll
208 {
209 public:
210   HistoryScrollNone();
211   virtual ~HistoryScrollNone();
212 
213   virtual bool hasScroll();
214 
215   virtual int  getLines();
216   virtual int  getLineLen(int lineno);
217   virtual void getCells(int lineno, int colno, int count, Character res[]);
218   virtual bool isWrappedLine(int lineno);
219 
220   virtual void addCells(const Character a[], int count);
221   virtual void addLine(bool previousWrapped=false);
222 };
223 
224 //////////////////////////////////////////////////////////////////////
225 // BlockArray-based history
226 //////////////////////////////////////////////////////////////////////
227 class HistoryScrollBlockArray : public HistoryScroll
228 {
229 public:
230   HistoryScrollBlockArray(size_t size);
231   virtual ~HistoryScrollBlockArray();
232 
233   virtual int  getLines();
234   virtual int  getLineLen(int lineno);
235   virtual void getCells(int lineno, int colno, int count, Character res[]);
236   virtual bool isWrappedLine(int lineno);
237 
238   virtual void addCells(const Character a[], int count);
239   virtual void addLine(bool previousWrapped=false);
240 
241 protected:
242   BlockArray m_blockArray;
243   QHash<int,size_t> m_lineLengths;
244 };
245 
246 //////////////////////////////////////////////////////////////////////
247 // History type
248 //////////////////////////////////////////////////////////////////////
249 
250 class HistoryType
251 {
252 public:
253   HistoryType();
254   virtual ~HistoryType();
255 
256   /**
257    * Returns true if the history is enabled ( can store lines of output )
258    * or false otherwise.
259    */
260   virtual bool isEnabled()           const = 0;
261   /**
262    * Returns true if the history size is unlimited.
263    */
isUnlimited()264   bool isUnlimited() const { return maximumLineCount() == 0; }
265   /**
266    * Returns the maximum number of lines which this history type
267    * can store or 0 if the history can store an unlimited number of lines.
268    */
269   virtual int maximumLineCount()    const = 0;
270 
271   virtual HistoryScroll* scroll(HistoryScroll *) const = 0;
272 };
273 
274 class HistoryTypeNone : public HistoryType
275 {
276 public:
277   HistoryTypeNone();
278 
279   virtual bool isEnabled() const;
280   virtual int maximumLineCount() const;
281 
282   virtual HistoryScroll* scroll(HistoryScroll *) const;
283 };
284 
285 class HistoryTypeBlockArray : public HistoryType
286 {
287 public:
288   HistoryTypeBlockArray(size_t size);
289 
290   virtual bool isEnabled() const;
291   virtual int maximumLineCount() const;
292 
293   virtual HistoryScroll* scroll(HistoryScroll *) const;
294 
295 protected:
296   size_t m_size;
297 };
298 
299 
300 class HistoryTypeFile : public HistoryType
301 {
302 public:
303   HistoryTypeFile(const QString& fileName=QString());
304 
305   virtual bool isEnabled() const;
306   virtual const QString& getFileName() const;
307   virtual int maximumLineCount() const;
308 
309   virtual HistoryScroll* scroll(HistoryScroll *) const;
310 
311 protected:
312   QString m_fileName;
313 };
314 
315 
316 class HistoryTypeBuffer : public HistoryType
317 {
318 public:
319   HistoryTypeBuffer(unsigned int nbLines);
320 
321   virtual bool isEnabled() const;
322   virtual int maximumLineCount() const;
323 
324   virtual HistoryScroll* scroll(HistoryScroll *) const;
325 
326 protected:
327   unsigned int m_nbLines;
328 };
329 
330 #endif // HISTORY_H
331