39#define KDE_lseek lseek
41using namespace Konsole;
87HistoryFile::HistoryFile()
94 tmpFile.setAutoRemove(true);
95 ion = tmpFile.handle();
99HistoryFile::~HistoryFile()
108void HistoryFile::map()
110 Q_ASSERT(fileMap ==
nullptr);
112 fileMap = (
char *)mmap(
nullptr, length, PROT_READ, MAP_PRIVATE, ion, 0);
115 if (fileMap == MAP_FAILED) {
116 readWriteBalance = 0;
122void HistoryFile::unmap()
124 int result = munmap(fileMap, length);
125 Q_ASSERT(result == 0);
131bool HistoryFile::isMapped()
const
133 return (fileMap !=
nullptr);
136void HistoryFile::add(
const unsigned char *bytes,
int len)
145 rc = KDE_lseek(ion, length, SEEK_SET);
147 perror(
"HistoryFile::add.seek");
150 rc = write(ion, bytes, len);
152 perror(
"HistoryFile::add.write");
158void HistoryFile::get(
unsigned char *bytes,
int len,
int loc)
165 if (!fileMap && readWriteBalance < MAP_THRESHOLD)
169 for (
int i = 0; i < len; i++)
170 bytes[i] = fileMap[loc + i];
174 if (loc < 0 || len < 0 || loc + len > length)
175 fprintf(stderr,
"getHist(...,%d,%d): invalid args.\n", len, loc);
176 rc = KDE_lseek(ion, loc, SEEK_SET);
178 perror(
"HistoryFile::get.seek");
181 rc =
read(ion, bytes, len);
183 perror(
"HistoryFile::get.read");
189int HistoryFile::len()
196HistoryScroll::HistoryScroll(HistoryType *t)
201HistoryScroll::~HistoryScroll()
206bool HistoryScroll::hasScroll()
224HistoryScrollFile::HistoryScrollFile(
const QString &logFileName)
225 : HistoryScroll(new HistoryTypeFile(logFileName))
226 , m_logFileName(logFileName)
230HistoryScrollFile::~HistoryScrollFile()
234int HistoryScrollFile::getLines()
236 return index.len() /
sizeof(int);
239int HistoryScrollFile::getLineLen(
int lineno)
241 return (startOfLine(lineno + 1) - startOfLine(lineno)) /
sizeof(
Character);
244bool HistoryScrollFile::isWrappedLine(
int lineno)
246 if (lineno >= 0 && lineno <= getLines()) {
248 lineflags.get((
unsigned char *)&flag,
sizeof(
unsigned char), (lineno) *
sizeof(
unsigned char));
254int HistoryScrollFile::startOfLine(
int lineno)
258 if (lineno <= getLines()) {
259 if (!index.isMapped())
263 index.get((
unsigned char *)&res,
sizeof(
int), (lineno - 1) *
sizeof(
int));
269void HistoryScrollFile::getCells(
int lineno,
int colno,
int count, std::span<Character> res)
271 cells.get((
unsigned char *)res.data(), count *
sizeof(
Character), startOfLine(lineno) + colno *
sizeof(
Character));
274void HistoryScrollFile::addCells(std::span<const Character> text,
int count)
276 cells.add((
unsigned char *)text.data(), count *
sizeof(
Character));
279void HistoryScrollFile::addLine(
bool previousWrapped)
281 if (index.isMapped())
284 int locn = cells.len();
285 index.add((
unsigned char *)&locn,
sizeof(
int));
286 unsigned char flags = previousWrapped ? 0x01 : 0x00;
287 lineflags.add((
unsigned char *)&flags,
sizeof(
unsigned char));
291HistoryScrollBuffer::HistoryScrollBuffer(
unsigned int maxLineCount)
292 : HistoryScroll(new HistoryTypeBuffer(maxLineCount))
298 setMaxNbLines(maxLineCount);
301HistoryScrollBuffer::~HistoryScrollBuffer()
303 delete[] _historyBuffer;
309 if (_usedLines < _maxLineCount)
312 if (_head >= _maxLineCount) {
316 _historyBuffer[bufferIndex(_usedLines - 1)] = cells;
317 _wrappedLine[bufferIndex(_usedLines - 1)] =
false;
319void HistoryScrollBuffer::addCells(std::span<const Character> a,
int count)
321 HistoryLine newLine(count);
322 std::copy(a.data(), a.subspan(count).data(), newLine.begin());
324 addCellsVector(newLine);
327void HistoryScrollBuffer::addLine(
bool previousWrapped)
329 _wrappedLine[bufferIndex(_usedLines - 1)] = previousWrapped;
332int HistoryScrollBuffer::getLines()
337int HistoryScrollBuffer::getLineLen(
int lineNumber)
339 Q_ASSERT(lineNumber >= 0 && lineNumber < _maxLineCount);
341 if (lineNumber < _usedLines) {
342 return _historyBuffer[bufferIndex(lineNumber)].
size();
348bool HistoryScrollBuffer::isWrappedLine(
int lineNumber)
350 Q_ASSERT(lineNumber >= 0 && lineNumber < _maxLineCount);
352 if (lineNumber < _usedLines) {
354 return _wrappedLine[bufferIndex(lineNumber)];
359void HistoryScrollBuffer::getCells(
int lineNumber,
int startColumn,
int count, std::span<Character> buffer)
364 Q_ASSERT(lineNumber < _maxLineCount);
366 if (lineNumber >= _usedLines) {
367 memset(
static_cast<void *
>(buffer.data()), 0, count *
sizeof(
Character));
371 const HistoryLine &line = _historyBuffer[bufferIndex(lineNumber)];
377 Q_ASSERT(startColumn <= line.size() - count);
379 memcpy(buffer.data(), line.constData() + startColumn, count *
sizeof(
Character));
382void HistoryScrollBuffer::setMaxNbLines(
unsigned int lineCount)
384 HistoryLine *oldBuffer = _historyBuffer;
385 HistoryLine *newBuffer =
new HistoryLine[lineCount];
387 for (
int i = 0; i < qMin(_usedLines, (
int)lineCount); i++) {
388 newBuffer[i] = oldBuffer[bufferIndex(i)];
391 _usedLines = qMin(_usedLines, (
int)lineCount);
392 _maxLineCount = lineCount;
393 _head = (_usedLines == _maxLineCount) ? 0 : _usedLines - 1;
395 _historyBuffer = newBuffer;
398 _wrappedLine.
resize(lineCount);
399 dynamic_cast<HistoryTypeBuffer *
>(m_histType)->m_nbLines = lineCount;
402int HistoryScrollBuffer::bufferIndex(
int lineNumber)
const
404 Q_ASSERT(lineNumber >= 0);
405 Q_ASSERT(lineNumber < _maxLineCount);
406 Q_ASSERT((_usedLines == _maxLineCount) || lineNumber <= _head);
408 if (_usedLines == _maxLineCount) {
409 return (_head + lineNumber + 1) % _maxLineCount;
417HistoryScrollNone::HistoryScrollNone()
418 : HistoryScroll(new HistoryTypeNone())
422HistoryScrollNone::~HistoryScrollNone()
426bool HistoryScrollNone::hasScroll()
431int HistoryScrollNone::getLines()
436int HistoryScrollNone::getLineLen(
int)
441bool HistoryScrollNone::isWrappedLine(
int )
446void HistoryScrollNone::getCells(
int,
int,
int, std::span<Character>)
450void HistoryScrollNone::addCells(std::span<const Character>,
int)
454void HistoryScrollNone::addLine(
bool)
460HistoryScrollBlockArray::HistoryScrollBlockArray(
size_t size)
461 : HistoryScroll(new HistoryTypeBlockArray(size))
463 m_blockArray.setHistorySize(size);
466HistoryScrollBlockArray::~HistoryScrollBlockArray()
470int HistoryScrollBlockArray::getLines()
472 return m_lineLengths.
size();
475int HistoryScrollBlockArray::getLineLen(
int lineno)
478 return m_lineLengths[lineno];
483bool HistoryScrollBlockArray::isWrappedLine(
int )
488void HistoryScrollBlockArray::getCells(
int lineno,
int colno,
int count, std::span<Character> res)
493 const Block *b = m_blockArray.at(lineno);
496 memset(
static_cast<void *
>(res.data()), 0, count *
sizeof(
Character));
500 Q_ASSERT(((colno + count) *
sizeof(
Character)) < ENTRIES);
504void HistoryScrollBlockArray::addCells(std::span<const Character> a,
int count)
506 Block *b = m_blockArray.lastBlock();
512 Q_ASSERT((count *
sizeof(
Character)) < ENTRIES);
514 memset(b->data, 0,
sizeof(b->data));
516 memcpy(b->data, a.data(), count *
sizeof(
Character));
519 size_t res = m_blockArray.newBlock();
523 m_lineLengths.
insert(m_blockArray.getCurrent(), count);
526void HistoryScrollBlockArray::addLine(
bool)
533void *CompactHistoryBlock::allocate(
size_t length)
535 Q_ASSERT(length > 0);
536 if (tail - blockStart + length > blockLength)
546void CompactHistoryBlock::deallocate()
549 Q_ASSERT(allocCount >= 0);
552void *CompactHistoryBlockList::allocate(
size_t size)
554 CompactHistoryBlock *block;
555 if (list.
isEmpty() || list.
last()->remaining() < size) {
556 block =
new CompactHistoryBlock();
563 return block->allocate(size);
566void CompactHistoryBlockList::deallocate(
void *ptr)
571 CompactHistoryBlock *block = list.
at(i);
572 while (i < list.
size() && !block->contains(ptr)) {
577 Q_ASSERT(i < list.
size());
581 if (!block->isInUse()) {
588CompactHistoryBlockList::~CompactHistoryBlockList()
590 qDeleteAll(list.
begin(), list.
end());
594void *CompactHistoryLine::operator
new(
size_t size, CompactHistoryBlockList &blockList)
596 return blockList.allocate(size);
599CompactHistoryLine::CompactHistoryLine(
const TextLine &line, CompactHistoryBlockList &bList)
603 length = line.
size();
610 Character c = line[0];
612 if (!(line[k].equalsFormat(c))) {
620 formatArray = (CharacterFormat *)blockList.allocate(
sizeof(CharacterFormat) * formatLength);
621 Q_ASSERT(formatArray !=
nullptr);
622 text = (quint16 *)blockList.allocate(
sizeof(quint16) * line.
size());
623 Q_ASSERT(text !=
nullptr);
625 length = line.
size();
630 formatArray[0].setFormat(c);
631 formatArray[0].startPos = 0;
635 while (k < length && j < formatLength) {
636 if (!(line[k].equalsFormat(c))) {
638 formatArray[j].setFormat(c);
639 formatArray[j].startPos = k;
647 for (
int i = 0; i < line.
size(); i++) {
648 text[i] = line[i].character.unicode();
655CompactHistoryLine::~CompactHistoryLine()
659 blockList.deallocate(text);
660 blockList.deallocate(formatArray);
662 blockList.deallocate(
this);
665void CompactHistoryLine::getCharacter(
int index,
Character &r)
667 Q_ASSERT(index < length);
669 while ((formatPos + 1) < formatLength && index >= formatArray[formatPos + 1].startPos)
673 r.
rendition = formatArray[formatPos].rendition;
678void CompactHistoryLine::getCharacters(
Character *array,
int length,
int startColumn)
680 Q_ASSERT(startColumn >= 0 && length >= 0);
681 Q_ASSERT(startColumn + length <= (
int)getLength());
683 for (
int i = startColumn; i < length + startColumn; i++) {
684 getCharacter(i, array[i - startColumn]);
688CompactHistoryScroll::CompactHistoryScroll(
unsigned int maxLineCount)
689 : HistoryScroll(new CompactHistoryType(maxLineCount))
694 setMaxNbLines(maxLineCount);
697CompactHistoryScroll::~CompactHistoryScroll()
699 qDeleteAll(lines.
begin(), lines.
end());
703void CompactHistoryScroll::addCellsVector(
const TextLine &cells)
705 CompactHistoryLine *line;
706 line =
new (blockList) CompactHistoryLine(cells, blockList);
708 if (lines.
size() > (
int)_maxLineCount) {
714void CompactHistoryScroll::addCells(std::span<const Character> a,
int count)
717 std::copy(a.data(), a.subspan(count).data(), newLine.begin());
718 addCellsVector(newLine);
721void CompactHistoryScroll::addLine(
bool previousWrapped)
723 CompactHistoryLine *line = lines.
last();
725 line->setWrapped(previousWrapped);
728int CompactHistoryScroll::getLines()
733int CompactHistoryScroll::getLineLen(
int lineNumber)
735 Q_ASSERT(lineNumber >= 0 && lineNumber < lines.
size());
736 CompactHistoryLine *line = lines[lineNumber];
738 return line->getLength();
741void CompactHistoryScroll::getCells(
int lineNumber,
int startColumn,
int count, std::span<Character> buffer)
745 Q_ASSERT(lineNumber < lines.
size());
746 CompactHistoryLine *line = lines[lineNumber];
747 Q_ASSERT(startColumn >= 0);
748 Q_ASSERT((
unsigned int)startColumn <= line->getLength() - count);
749 line->getCharacters(buffer.data(), count, startColumn);
752void CompactHistoryScroll::setMaxNbLines(
unsigned int lineCount)
754 _maxLineCount = lineCount;
756 while (lines.
size() > (
int)lineCount) {
762bool CompactHistoryScroll::isWrappedLine(
int lineNumber)
764 Q_ASSERT(lineNumber < lines.
size());
765 return lines[lineNumber]->isWrapped();
772HistoryType::HistoryType()
776HistoryType::~HistoryType()
782HistoryTypeNone::HistoryTypeNone()
786bool HistoryTypeNone::isEnabled()
const
791std::unique_ptr<HistoryScroll> HistoryTypeNone::scroll(std::unique_ptr<HistoryScroll> &&)
const
793 return std::make_unique<HistoryScrollNone>();
796int HistoryTypeNone::maximumLineCount()
const
803HistoryTypeBlockArray::HistoryTypeBlockArray(
size_t size)
808bool HistoryTypeBlockArray::isEnabled()
const
813int HistoryTypeBlockArray::maximumLineCount()
const
818std::unique_ptr<HistoryScroll> HistoryTypeBlockArray::scroll(std::unique_ptr<HistoryScroll> &&)
const
820 return std::make_unique<HistoryScrollBlockArray>(m_size);
825HistoryTypeBuffer::HistoryTypeBuffer(
unsigned int nbLines)
830bool HistoryTypeBuffer::isEnabled()
const
835int HistoryTypeBuffer::maximumLineCount()
const
840std::unique_ptr<HistoryScroll> HistoryTypeBuffer::scroll(std::unique_ptr<HistoryScroll> &&old)
const
843 HistoryScrollBuffer *oldBuffer =
dynamic_cast<HistoryScrollBuffer *
>(old.get());
845 oldBuffer->setMaxNbLines(m_nbLines);
849 auto newScroll = std::make_unique<HistoryScrollBuffer>(m_nbLines);
850 int lines = old->getLines();
852 if (lines > (
int)m_nbLines)
853 startLine = lines - m_nbLines;
856 for (
int i = startLine; i < lines; i++) {
857 int size = old->getLineLen(i);
858 if (size > LINE_SIZE) {
859 auto tmp_line = std::vector<Character>(size);
860 old->getCells(i, 0, size, tmp_line);
861 newScroll->addCells(tmp_line, size);
862 newScroll->addLine(old->isWrappedLine(i));
864 old->getCells(i, 0, size, line);
865 newScroll->addCells(line, size);
866 newScroll->addLine(old->isWrappedLine(i));
871 return std::make_unique<HistoryScrollBuffer>(m_nbLines);
876HistoryTypeFile::HistoryTypeFile(
const QString &fileName)
877 : m_fileName(fileName)
881bool HistoryTypeFile::isEnabled()
const
886const QString &HistoryTypeFile::getFileName()
const
891std::unique_ptr<HistoryScroll> HistoryTypeFile::scroll(std::unique_ptr<HistoryScroll> &&old)
const
893 if (
dynamic_cast<HistoryFile *
>(old.get()))
896 auto newScroll = std::make_unique<HistoryScrollFile>(m_fileName);
899 int lines = (old !=
nullptr) ? old->getLines() : 0;
900 for (
int i = 0; i < lines; i++) {
901 int size = old->getLineLen(i);
902 if (size > LINE_SIZE) {
903 auto tmp_line = std::vector<Character>(size);
904 old->getCells(i, 0, size, tmp_line);
905 newScroll->addCells(tmp_line, size);
906 newScroll->addLine(old->isWrappedLine(i));
908 old->getCells(i, 0, size, line);
909 newScroll->addCells(line, size);
910 newScroll->addLine(old->isWrappedLine(i));
917int HistoryTypeFile::maximumLineCount()
const
924CompactHistoryType::CompactHistoryType(
unsigned int nbLines)
929bool CompactHistoryType::isEnabled()
const
934int CompactHistoryType::maximumLineCount()
const
939std::unique_ptr<HistoryScroll> CompactHistoryType::scroll(std::unique_ptr<HistoryScroll> &&old)
const
942 CompactHistoryScroll *oldBuffer =
dynamic_cast<CompactHistoryScroll *
>(old.get());
944 oldBuffer->setMaxNbLines(m_nbLines);
948 return std::make_unique<CompactHistoryScroll>(m_nbLines);
A single character in the terminal which consists of a unicode character value, foreground and backgr...
QChar character
The unicode character value for this character.
CharacterColor foregroundColor
The foreground color used to draw this character.
CharacterColor backgroundColor
The color used to draw this character's background.
quint8 rendition
A combination of RENDITION flags which specify options for drawing the character.
QVariant read(const QByteArray &data, int versionOverride=0)
void resize(qsizetype size)
bool contains(const Key &key) const const
iterator insert(const Key &key, const T &value)
qsizetype size() const const
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
bool isEmpty() const const
void removeAt(qsizetype i)
qsizetype size() const const