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