From 2aa61bb9943c4e00d1764fa45f2c210cc92a41de Mon Sep 17 00:00:00 2001 From: Carlos Alves Date: Thu, 29 Apr 2021 09:24:07 -0300 Subject: [PATCH] Change CompactHistory data storage It is removing the vector of lines storage. Now it is using a similar idea used in history file. All chars are stored in a linear way, only the line indexes are changed when reflowing. No speed problem found when removing lines. --- src/CMakeLists.txt | 3 - src/Screen.cpp | 2 +- src/history/HistoryScroll.h | 7 +- src/history/HistoryScrollFile.cpp | 38 +-- src/history/HistoryScrollFile.h | 7 +- src/history/HistoryScrollNone.cpp | 22 +- src/history/HistoryScrollNone.h | 7 +- src/history/compact/CompactHistoryBlock.cpp | 73 ------ src/history/compact/CompactHistoryBlock.h | 46 ---- .../compact/CompactHistoryBlockList.cpp | 55 ----- src/history/compact/CompactHistoryBlockList.h | 34 --- src/history/compact/CompactHistoryLine.cpp | 176 -------------- src/history/compact/CompactHistoryLine.h | 49 ---- src/history/compact/CompactHistoryScroll.cpp | 220 ++++++++---------- src/history/compact/CompactHistoryScroll.h | 27 +-- 15 files changed, 113 insertions(+), 653 deletions(-) delete mode 100644 src/history/compact/CompactHistoryBlock.cpp delete mode 100644 src/history/compact/CompactHistoryBlock.h delete mode 100644 src/history/compact/CompactHistoryBlockList.cpp delete mode 100644 src/history/compact/CompactHistoryBlockList.h delete mode 100644 src/history/compact/CompactHistoryLine.cpp delete mode 100644 src/history/compact/CompactHistoryLine.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 41a58224..1b8b038b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -159,9 +159,6 @@ set(konsoleprivate_SRCS ${windowadaptors_SRCS} history/HistoryType.cpp history/HistoryTypeFile.cpp history/HistoryTypeNone.cpp - history/compact/CompactHistoryBlock.cpp - history/compact/CompactHistoryBlockList.cpp - history/compact/CompactHistoryLine.cpp history/compact/CompactHistoryScroll.cpp history/compact/CompactHistoryType.cpp widgets/DetachableTabBar.cpp diff --git a/src/Screen.cpp b/src/Screen.cpp index bab3f941..afd2459a 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -516,7 +516,7 @@ void Screen::resizeImage(int new_lines, int new_columns) _history->getCells(histPos, 0, histLineLen, histLine.data()); _screenLines.insert(0, histLine); _lineProperties.insert(0, lineProperty); - _history->removeCells(histPos); + _history->removeCells(); cursorLine++; } } diff --git a/src/history/HistoryScroll.h b/src/history/HistoryScroll.h index df4c4f84..8948adbf 100644 --- a/src/history/HistoryScroll.h +++ b/src/history/HistoryScroll.h @@ -53,12 +53,7 @@ public: virtual void addLine(LineProperty lineProperty = 0) = 0; // modify history - virtual void insertCellsVector(int position, const QVector &cells) = 0; - virtual void insertCells(int position, const Character a[], int count) = 0; - virtual void removeCells(int position) = 0; - virtual void setCellsAt(int position, const Character a[], int count) = 0; - virtual void setCellsVectorAt(int position, const QVector &cells) = 0; - virtual void setLineAt(int position, LineProperty lineProperty) = 0; + virtual void removeCells() = 0; virtual int reflowLines(int columns) = 0; // diff --git a/src/history/HistoryScrollFile.cpp b/src/history/HistoryScrollFile.cpp index 060fda94..fcafcb70 100644 --- a/src/history/HistoryScrollFile.cpp +++ b/src/history/HistoryScrollFile.cpp @@ -95,11 +95,7 @@ void HistoryScrollFile::addLine(LineProperty lineProperty) _lineflags.add(reinterpret_cast(&lineProperty), sizeof(char)); } -void HistoryScrollFile::insertCells(int, const Character[], int) -{ -} - -void HistoryScrollFile::removeCells(int) +void HistoryScrollFile::removeCells() { qint64 res = (getLines() - 2) * sizeof(qint64); if (getLines() < 2) { @@ -113,26 +109,6 @@ void HistoryScrollFile::removeCells(int) _lineflags.removeLast(res * sizeof(unsigned char)); } -void HistoryScrollFile::insertCellsVector(int, const QVector &) -{ -} - -void HistoryScrollFile::setCellsAt(int, const Character text[], int count) -{ - qint64 res = (getLines() - 2) * sizeof(qint64); - if (getLines() < 2) { - _cells.removeLast(0); - } else { - _index.get(reinterpret_cast(&res), sizeof(qint64), res); - _cells.removeLast(res); - } - _cells.add(reinterpret_cast(text), count * sizeof(Character)); -} - -void HistoryScrollFile::setCellsVectorAt(int, const QVector &) -{ -} - int HistoryScrollFile::reflowLines(int columns) { auto reflowFile = std::make_unique(); @@ -196,15 +172,3 @@ int HistoryScrollFile::reflowLines(int columns) return 0; } - -void HistoryScrollFile::setLineAt(int, LineProperty lineProperty) -{ - qint64 locn = qMax(0, getLines() - 1); - _index.removeLast(locn * sizeof(qint64)); - _lineflags.removeLast(locn * sizeof(unsigned char)); - - locn = _cells.len(); - _index.add(reinterpret_cast(&locn), sizeof(qint64)); - - _lineflags.add(reinterpret_cast(&lineProperty), sizeof(char)); -} diff --git a/src/history/HistoryScrollFile.h b/src/history/HistoryScrollFile.h index b70c4118..13f63aee 100644 --- a/src/history/HistoryScrollFile.h +++ b/src/history/HistoryScrollFile.h @@ -37,12 +37,7 @@ public: void addLine(LineProperty lineProperty = 0) override; // Modify history - void insertCellsVector(int position, const QVector &cells) override; - void insertCells(int position, const Character a[], int count) override; - void removeCells(int position) override; - void setCellsAt(int position, const Character a[], int count) override; - void setCellsVectorAt(int position, const QVector &cells) override; - void setLineAt(int position, LineProperty lineProperty) override; + void removeCells() override; int reflowLines(int columns) override; private: diff --git a/src/history/HistoryScrollNone.cpp b/src/history/HistoryScrollNone.cpp index ffbd3754..9e392280 100644 --- a/src/history/HistoryScrollNone.cpp +++ b/src/history/HistoryScrollNone.cpp @@ -62,23 +62,7 @@ void HistoryScrollNone::addLine(LineProperty) { } -void HistoryScrollNone::insertCells(int , const Character [], int) -{ -} - -void HistoryScrollNone::removeCells(int ) -{ -} - -void HistoryScrollNone::insertCellsVector(int , const QVector &) -{ -} - -void HistoryScrollNone::setCellsAt(int , const Character [], int) -{ -} - -void HistoryScrollNone::setCellsVectorAt(int , const QVector &) +void HistoryScrollNone::removeCells() { } @@ -86,7 +70,3 @@ int HistoryScrollNone::reflowLines(int) { return 0; } - -void HistoryScrollNone::setLineAt(int , LineProperty) -{ -} diff --git a/src/history/HistoryScrollNone.h b/src/history/HistoryScrollNone.h index fa28bae0..90dbeb9f 100644 --- a/src/history/HistoryScrollNone.h +++ b/src/history/HistoryScrollNone.h @@ -36,12 +36,7 @@ public: void addLine(LineProperty lineProperty = 0) override; // Modify history (do nothing here) - void insertCellsVector(int position, const QVector &cells) override; - void insertCells(int position, const Character a[], int count) override; - void removeCells(int position) override; - void setCellsAt(int position, const Character a[], int count) override; - void setCellsVectorAt(int position, const QVector &cells) override; - void setLineAt(int position, LineProperty lineProperty) override; + void removeCells() override; int reflowLines(int) override; }; diff --git a/src/history/compact/CompactHistoryBlock.cpp b/src/history/compact/CompactHistoryBlock.cpp deleted file mode 100644 index e1acb572..00000000 --- a/src/history/compact/CompactHistoryBlock.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - SPDX-FileCopyrightText: 1997, 1998 Lars Doelle - - SPDX-License-Identifier: GPL-2.0-or-later -*/ - -// Own -#include "CompactHistoryBlock.h" - -using namespace Konsole; - -constexpr size_t BLOCK_LENGTH = 4096 * 64 ; // 256kb - -CompactHistoryBlock::CompactHistoryBlock(size_t blockLength) : - _blockLength(BLOCK_LENGTH), - _tail(nullptr), - _blockStart(nullptr), - _allocCount(0) -{ - if (blockLength > _blockLength) { - _blockLength = blockLength; - } - - _head = static_cast(mmap(nullptr, _blockLength, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0)); - Q_ASSERT(_head != MAP_FAILED); - _tail = _blockStart = _head; -} - -CompactHistoryBlock::~CompactHistoryBlock() -{ - //free(_blockStart); - munmap(_blockStart, _blockLength); -} - -unsigned int CompactHistoryBlock::remaining() -{ - return _blockStart + _blockLength - _tail; -} - -unsigned CompactHistoryBlock::length() -{ - return _blockLength; -} - -bool CompactHistoryBlock::contains(void *addr) -{ - return addr >= _blockStart && addr < (_blockStart + _blockLength); -} - -bool CompactHistoryBlock::isInUse() -{ - return _allocCount != 0; -} - -void *CompactHistoryBlock::allocate(size_t size) -{ - Q_ASSERT(size > 0); - if (_tail - _blockStart + size > _blockLength) { - return nullptr; - } - - void *block = _tail; - _tail += size; - ////qDebug() << "allocated " << length << " bytes at address " << block; - _allocCount++; - return block; -} - -void CompactHistoryBlock::deallocate() -{ - _allocCount--; - Q_ASSERT(_allocCount >= 0); -} diff --git a/src/history/compact/CompactHistoryBlock.h b/src/history/compact/CompactHistoryBlock.h deleted file mode 100644 index 3ca949ba..00000000 --- a/src/history/compact/CompactHistoryBlock.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - SPDX-FileCopyrightText: 1997, 1998 Lars Doelle - - SPDX-License-Identifier: GPL-2.0-or-later -*/ - -#ifndef COMPACTHISTORYBLOCK_H -#define COMPACTHISTORYBLOCK_H - -// Konsole -#include "../characters/Character.h" - -// System -#include - -namespace Konsole -{ - -class CompactHistoryBlock -{ -public: - CompactHistoryBlock(size_t blockLength = 0); - - virtual ~CompactHistoryBlock(); - - virtual unsigned int remaining(); - - virtual unsigned length(); - - virtual void *allocate(size_t size); - virtual bool contains(void *addr); - - virtual void deallocate(); - virtual bool isInUse(); - -private: - size_t _blockLength; - quint8 *_head; - quint8 *_tail; - quint8 *_blockStart; - int _allocCount; -}; - -} - -#endif diff --git a/src/history/compact/CompactHistoryBlockList.cpp b/src/history/compact/CompactHistoryBlockList.cpp deleted file mode 100644 index 8001a9c5..00000000 --- a/src/history/compact/CompactHistoryBlockList.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - SPDX-FileCopyrightText: 1997, 1998 Lars Doelle - - SPDX-License-Identifier: GPL-2.0-or-later -*/ - -// Own -#include "CompactHistoryBlockList.h" - -// Qt - -using namespace Konsole; - -CompactHistoryBlockList::CompactHistoryBlockList() - : _blocks() -{ -} - -void *CompactHistoryBlockList::allocate(size_t size) -{ - if (_blocks.empty() || _blocks.back()->remaining() < size) { - _blocks.push_back(std::make_unique(size)); - ////qDebug() << "new block created, remaining " << block->remaining() << "number of blocks=" << _blocks.size(); - } - return _blocks.back()->allocate(size); -} - -void CompactHistoryBlockList::deallocate(void *ptr) -{ - Q_ASSERT(!_blocks.empty()); - - auto block = _blocks.begin(); - while (block != _blocks.end() && !(*block)->contains(ptr)) { - block++; - } - - Q_ASSERT(block != _blocks.end()); - - (*block)->deallocate(); - - if (!(*block)->isInUse()) { - _blocks.erase(block); - ////qDebug() << "block deleted, new size = " << list.size(); - } -} - -int CompactHistoryBlockList::length() -{ - return _blocks.size(); -} - -CompactHistoryBlockList::~CompactHistoryBlockList() -{ - _blocks.clear(); -} diff --git a/src/history/compact/CompactHistoryBlockList.h b/src/history/compact/CompactHistoryBlockList.h deleted file mode 100644 index 0a3fbb7f..00000000 --- a/src/history/compact/CompactHistoryBlockList.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - SPDX-FileCopyrightText: 1997, 1998 Lars Doelle - - SPDX-License-Identifier: GPL-2.0-or-later -*/ - -#ifndef COMPACTHISTORYBLOCKLIST_H -#define COMPACTHISTORYBLOCKLIST_H - -#include -#include - -#include "CompactHistoryBlock.h" - -namespace Konsole -{ - -class CompactHistoryBlockList -{ -public: - CompactHistoryBlockList(); - ~CompactHistoryBlockList(); - - void *allocate(size_t size); - void deallocate(void *); - int length(); - -private: - std::vector> _blocks; -}; - -} - -#endif diff --git a/src/history/compact/CompactHistoryLine.cpp b/src/history/compact/CompactHistoryLine.cpp deleted file mode 100644 index 4f6afdbd..00000000 --- a/src/history/compact/CompactHistoryLine.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - SPDX-FileCopyrightText: 1997, 1998 Lars Doelle - - SPDX-License-Identifier: GPL-2.0-or-later -*/ - -#include "CompactHistoryLine.h" - -using namespace Konsole; - -void *CompactHistoryLine::operator new(size_t size, CompactHistoryBlockList &blockList) -{ - return blockList.allocate(size); -} - -void CompactHistoryLine::operator delete(void *) -{ - /* do nothing, deallocation from pool is done in destructor*/ -} - -CompactHistoryLine::CompactHistoryLine(const TextLine &line, CompactHistoryBlockList &bList) : - _blockListRef(bList), - _formatArray(nullptr), - _text(nullptr), - _formatLength(0), - _lineProperty(0) -{ - if (!line.isEmpty()) { - _length = line.size(); - - // count number of different formats in this text line - Character c = line[0]; - _formatLength = 1; - for (auto &k : line) { - if (!(k.equalsFormat(c))) { - _formatLength++; // format change detected - c = k; - } - } - - _formatArray = static_cast(_blockListRef.allocate(sizeof(CharacterFormat) * _formatLength)); - Q_ASSERT(_formatArray != nullptr); - _text = static_cast(_blockListRef.allocate(sizeof(uint) * line.size())); - Q_ASSERT(_text != nullptr); - - c = line[0]; - _formatArray[0].setFormat(c); - _formatArray[0].startPos = 0; - for (int i = 0, k = 1; i < _length; i++) { - if (!line[i].equalsFormat(c)) { - c = line[i]; - _formatArray[k].setFormat(c); - _formatArray[k].startPos = i; - k++; - } - _text[i] = line[i].character; - } - - _lineProperty = 0; - } -} - -CompactHistoryLine::~CompactHistoryLine() -{ - if (_length > 0) { - _blockListRef.deallocate(_text); - _blockListRef.deallocate(_formatArray); - } - _blockListRef.deallocate(this); -} - -void CompactHistoryLine::getCharacters(Character *array, int size, int startColumn) -{ - Q_ASSERT(startColumn >= 0 && size >= 0); - Q_ASSERT(startColumn + size <= static_cast(getLength())); - - int formatPos = 0; - while ((formatPos + 1) < _formatLength && startColumn >= _formatArray[formatPos + 1].startPos) { - formatPos++; - } - - for (int i = startColumn; i < size + startColumn; i++) { - if ((formatPos + 1) < _formatLength && i == _formatArray[formatPos + 1].startPos) { - formatPos++; - } - array[i - startColumn] = Character(_text[i], - _formatArray[formatPos].fgColor, - _formatArray[formatPos].bgColor, - _formatArray[formatPos].rendition, - _formatArray[formatPos].isRealCharacter); - } -} - -void CompactHistoryLine::setCharacters(const TextLine &line) -{ - if (line.isEmpty()) { - if (_formatArray) { - _blockListRef.deallocate(_formatArray); - } - if (_text) { - _blockListRef.deallocate(_text); - } - _formatArray = nullptr; - _text = nullptr; - _formatLength = 0; - _length = 0; - return; - } - int new_length = line.size(); - - // count number of different formats in this text line - Character c = line[0]; - int new_formatLength = 1; - for (auto &k : line) { - if (!(k.equalsFormat(c))) { - new_formatLength++; // format change detected - c = k; - } - } - - if (_formatLength < new_formatLength) { - _blockListRef.deallocate(_formatArray); - _formatArray = static_cast(_blockListRef.allocate(sizeof(CharacterFormat) * new_formatLength)); - Q_ASSERT(_formatArray != nullptr); - } - - if (_length < new_length) { - _blockListRef.deallocate(_text); - _text = static_cast(_blockListRef.allocate(sizeof(uint) * new_length)); - Q_ASSERT(_text != nullptr); - } - _length = new_length; - _formatLength = new_formatLength; - - c = line[0]; - _formatArray[0].setFormat(c); - _formatArray[0].startPos = 0; - for (int i = 0, k = 1; i < _length; i++) { - if (!line[i].equalsFormat(c)) { - c = line[i]; - _formatArray[k].setFormat(c); - _formatArray[k].startPos = i; - k++; - } - _text[i] = line[i].character; - } -} - -bool CompactHistoryLine::isWrapped() const -{ - return _lineProperty & LINE_WRAPPED; -} - -void CompactHistoryLine::setWrapped(bool value) -{ - if (value) { - _lineProperty |= LINE_WRAPPED; - } else { - _lineProperty &= ~LINE_WRAPPED; - } -} - -LineProperty CompactHistoryLine::getLineProperty() const -{ - return _lineProperty; -} - -void CompactHistoryLine::setLineProperty(LineProperty value) -{ - _lineProperty = value; -} - -unsigned int CompactHistoryLine::getLength() const -{ - return _length; -} diff --git a/src/history/compact/CompactHistoryLine.h b/src/history/compact/CompactHistoryLine.h deleted file mode 100644 index 4d30d5e6..00000000 --- a/src/history/compact/CompactHistoryLine.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - SPDX-FileCopyrightText: 1997, 1998 Lars Doelle - - SPDX-License-Identifier: GPL-2.0-or-later -*/ - -#ifndef COMPACTHISTORYLINE_H -#define COMPACTHISTORYLINE_H - -#include - -#include "../characters/CharacterFormat.h" -#include "CompactHistoryBlockList.h" - -namespace Konsole -{ - -typedef QVector TextLine; - -class CompactHistoryLine -{ -public: - CompactHistoryLine(const TextLine &, CompactHistoryBlockList &blockList); - virtual ~CompactHistoryLine(); - - // custom new operator to allocate memory from custom pool instead of heap - static void *operator new(size_t size, CompactHistoryBlockList &blockList); - static void operator delete(void *); - - virtual void setCharacters(const TextLine &); - virtual void getCharacters(Character *array, int size, int startColumn); - virtual bool isWrapped() const; - virtual void setWrapped(bool value); - virtual LineProperty getLineProperty() const; - virtual void setLineProperty(LineProperty value); - virtual unsigned int getLength() const; - -protected: - CompactHistoryBlockList &_blockListRef; - CharacterFormat *_formatArray; - int _length; - uint *_text; - int _formatLength; - LineProperty _lineProperty; -}; - -} - -#endif diff --git a/src/history/compact/CompactHistoryScroll.cpp b/src/history/compact/CompactHistoryScroll.cpp index abbc201d..cf5d5ec5 100644 --- a/src/history/compact/CompactHistoryScroll.cpp +++ b/src/history/compact/CompactHistoryScroll.cpp @@ -11,66 +11,79 @@ using namespace Konsole; +struct reflowData { // data to reflow lines + QList index; + QList flags; +}; + CompactHistoryScroll::CompactHistoryScroll(unsigned int maxLineCount) : HistoryScroll(new CompactHistoryType(maxLineCount)), - _lines(), - _blockList(), + _cells(), + _index(), + _flags(), _maxLineCount(0) { - ////qDebug() << "scroll of length " << maxLineCount << " created"; setMaxNbLines(maxLineCount); } -CompactHistoryScroll::~CompactHistoryScroll() +void CompactHistoryScroll::removeFirstLine() { - _lines.clear(); + _flags.pop_front(); + + auto removing = _index.first(); + _index.pop_front(); + std::transform(_index.begin(), _index.end(), _index.begin(), [removing](int i) { return i - removing; }); + + while (_cells.size() > _index.last()) { + _cells.pop_front(); + } } -void CompactHistoryScroll::addCellsVector(const TextLine &cells) +inline int CompactHistoryScroll::lineLen(int line) { - auto line = std::unique_ptr(new (_blockList) CompactHistoryLine(cells, _blockList)); - - _lines.push_back(std::move(line)); + return line == 0 ? _index[0] : _index[line] - _index[line - 1]; +} - if (_lines.size() > static_cast(_maxLineCount)) { - _lines.pop_front(); - } +inline int CompactHistoryScroll::startOfLine(int line) +{ + return line == 0 ? 0 : _index[line - 1]; } void CompactHistoryScroll::addCells(const Character a[], int count) { - TextLine newLine(count); - std::copy(a, a + count, newLine.begin()); - addCellsVector(newLine); + std::copy(a, a + count, std::back_inserter(_cells)); + + _index.append(_cells.size()); + _flags.append(LINE_DEFAULT); + + if (_index.size() > _maxLineCount) { + removeFirstLine(); + } } void CompactHistoryScroll::addLine(LineProperty lineProperty) { - auto line = _lines.back().get(); - ////qDebug() << "last line at address " << line; - line->setLineProperty(lineProperty); + auto &flag = _flags.last(); + flag = lineProperty; } int CompactHistoryScroll::getLines() { - return static_cast(_lines.size()); + return _index.size(); } int CompactHistoryScroll::getMaxLines() { - return static_cast(_maxLineCount); + return _maxLineCount; } int CompactHistoryScroll::getLineLen(int lineNumber) { - if ((lineNumber < 0) || (static_cast(lineNumber) >= _lines.size())) { - //qDebug() << "requested line invalid: 0 < " << lineNumber << " < " <<_lines.size(); - //Q_ASSERT(lineNumber >= 0 && lineNumber < _lines.size()); + if (lineNumber < 0 || lineNumber >= _index.size()) { return 0; } - auto line = _lines[lineNumber].get(); - ////qDebug() << "request for line at address " << line; - return line->getLength(); + + return lineLen(lineNumber); } void CompactHistoryScroll::getCells(int lineNumber, int startColumn, int count, Character buffer[]) @@ -78,137 +91,94 @@ void CompactHistoryScroll::getCells(int lineNumber, int startColumn, int count, if (count == 0) { return; } - Q_ASSERT(static_cast(lineNumber) < _lines.size()); - auto line = _lines[lineNumber].get(); + Q_ASSERT(lineNumber < _index.size()); + Q_ASSERT(startColumn >= 0); - Q_ASSERT(static_cast(startColumn) <= line->getLength() - count); - line->getCharacters(buffer, count, startColumn); + Q_ASSERT(startColumn <= lineLen(lineNumber) - count); + + auto startCopy = _cells.begin() + startOfLine(lineNumber); + auto endCopy = startCopy + count; + std::copy(startCopy, endCopy, buffer); } -void CompactHistoryScroll::setMaxNbLines(unsigned int lineCount) +void CompactHistoryScroll::setMaxNbLines(int lineCount) { + Q_ASSERT(lineCount >= 0); _maxLineCount = lineCount; - while (_lines.size() > static_cast(lineCount)) { - _lines.pop_front(); + while (_index.size() > lineCount) { + removeFirstLine(); } - ////qDebug() << "set max lines to: " << _maxLineCount; } -void CompactHistoryScroll::insertCellsVector(int position, const TextLine &cells) +void CompactHistoryScroll::removeCells() { - auto line = std::unique_ptr(new (_blockList) CompactHistoryLine(cells, _blockList)); - - _lines.insert(_lines.begin() + position, std::move(line)); + if (_index.size() > 1) { + _index.pop_back(); + _flags.pop_back(); - if (_lines.size() > static_cast(_maxLineCount)) { - _lines.pop_front(); + while (_cells.size() > _index.last()) { + _cells.pop_back(); + } + } else { + _cells.clear(); + _index.clear(); + _flags.clear(); } } -void CompactHistoryScroll::insertCells(int position, const Character a[], int count) -{ - TextLine newLine(count); - std::copy(a, a + count, newLine.begin()); - insertCellsVector(position, newLine); -} - -void CompactHistoryScroll::removeCells(int position) -{ - _lines.erase(_lines.begin() + position); -} - -void CompactHistoryScroll::setCellsAt(int position, const Character a[], int count) -{ - TextLine newLine(count); - std::copy(a, a + count, newLine.begin()); - setCellsVectorAt(position, newLine); -} - -void CompactHistoryScroll::setCellsVectorAt(int position, const TextLine &cells) -{ - _lines[position]->setCharacters(cells); -} - -void CompactHistoryScroll::setLineAt(int position, LineProperty lineProperty) -{ - auto line = _lines.at(position).get(); - - line->setLineProperty(lineProperty); -} - bool CompactHistoryScroll::isWrappedLine(int lineNumber) { - Q_ASSERT(static_cast(lineNumber) < _lines.size()); - return _lines[lineNumber]->isWrapped(); + Q_ASSERT(lineNumber < _index.size()); + return _flags[lineNumber] & LINE_WRAPPED; } LineProperty CompactHistoryScroll::getLineProperty(int lineNumber) { - Q_ASSERT(static_cast(lineNumber) < _lines.size()); - return _lines[lineNumber]->getLineProperty(); + Q_ASSERT(lineNumber < _index.size()); + return _flags[lineNumber]; } int CompactHistoryScroll::reflowLines(int columns) { - auto getCharacterBuffer = [](int size) { - static QVector characterBuffer(1024); - if (characterBuffer.count() < size) { - characterBuffer.resize(size); - } + reflowData newLine; - return characterBuffer.data(); + auto reflowLineLen = [](int start, int end) { + return end - start; + }; + auto setNewLine = [](reflowData &change, int index, LineProperty flag) { + change.index.append(index); + change.flags.append(flag); }; - // Join the line and move the data to next line if needed - int removedLines = 0; int currentPos = 0; - if (getLines() > MAX_REFLOW_LINES) { - currentPos = getLines() - MAX_REFLOW_LINES; - } while (currentPos < getLines()) { - int curr_linelen = getLineLen(currentPos); - // Join wrapped line in current history position - if (isWrappedLine(currentPos) && currentPos < getLines() - 1) { - int next_linelen = getLineLen(currentPos + 1); - auto *new_line = getCharacterBuffer(curr_linelen + next_linelen); - LineProperty new_line_property = getLineProperty(currentPos + 1); - - // Join the lines - getCells(currentPos, 0, curr_linelen, new_line); - getCells(currentPos + 1, 0, next_linelen, new_line + curr_linelen); - - // save the new_line in history and remove the next line - setCellsAt(currentPos, new_line, curr_linelen + next_linelen); - setLineAt(currentPos, new_line_property); - removeCells(currentPos + 1); - continue; + int startLine = startOfLine(currentPos); + int endLine = startOfLine(currentPos + 1); + LineProperty lineProperty = getLineProperty(currentPos); + + // Join the lines if they are wrapped + while (isWrappedLine(currentPos)) { + currentPos++; + endLine = startOfLine(currentPos + 1); } - // if the current line > columns it will need a new line - if (curr_linelen > columns && !(getLineProperty(currentPos) & (LINE_DOUBLEHEIGHT_BOTTOM | LINE_DOUBLEHEIGHT_TOP))) { - bool removeLine = getLines() == getMaxLines(); - auto *curr_line = getCharacterBuffer(curr_linelen); - LineProperty curr_line_property = getLineProperty(currentPos); - getCells(currentPos, 0, curr_linelen, curr_line); - - setCellsAt(currentPos, curr_line, columns); - setLineAt(currentPos, curr_line_property | LINE_WRAPPED); - if (currentPos < getMaxLines() - 1) { - int correctPosition = (getLines() == getMaxLines()) ? 0 : 1; - insertCells(currentPos + 1, curr_line + columns, curr_linelen - columns); - setLineAt(currentPos + correctPosition, curr_line_property); - } else { - addCells(curr_line + columns, curr_linelen - columns); - addLine(curr_line_property); - currentPos--; - } - if (removeLine) { - removedLines += 1; - } + // Now reflow the lines + while (reflowLineLen(startLine, endLine) > columns && !(lineProperty & (LINE_DOUBLEHEIGHT_BOTTOM | LINE_DOUBLEHEIGHT_TOP))) { + startLine += columns; + setNewLine(newLine, startLine, lineProperty | LINE_WRAPPED); } + setNewLine(newLine, endLine, lineProperty & ~LINE_WRAPPED); currentPos++; } - return removedLines; -} + _index = newLine.index; + _flags = newLine.flags; + + int deletedLines = 0; + while (getLines() > _maxLineCount) { + removeFirstLine(); + ++deletedLines; + } + return deletedLines; +} diff --git a/src/history/compact/CompactHistoryScroll.h b/src/history/compact/CompactHistoryScroll.h index d080826d..09edffde 100644 --- a/src/history/compact/CompactHistoryScroll.h +++ b/src/history/compact/CompactHistoryScroll.h @@ -13,18 +13,17 @@ #include "konsoleprivate_export.h" #include "history/HistoryScroll.h" -#include "history/compact/CompactHistoryLine.h" namespace Konsole { class KONSOLEPRIVATE_EXPORT CompactHistoryScroll : public HistoryScroll { - typedef std::deque> HistoryArray; + typedef QVector TextLine; public: explicit CompactHistoryScroll(unsigned int maxLineCount = 1000); - ~CompactHistoryScroll() override; + ~CompactHistoryScroll() = default; int getLines() override; int getMaxLines() override; @@ -34,26 +33,24 @@ public: LineProperty getLineProperty(int lineNumber) override; void addCells(const Character a[], int count) override; - void addCellsVector(const TextLine &cells) override; void addLine(LineProperty lineProperty = 0) override; - void insertCellsVector(int position, const TextLine &cells) override; - void insertCells(int position, const Character a[], int count) override; - void removeCells(int position) override; + void removeCells() override; - void setMaxNbLines(unsigned int lineCount); - void setCellsAt(int position, const Character a[], int count) override; - void setCellsVectorAt(int position, const TextLine &cells) override; - void setLineAt(int position, LineProperty lineProperty) override; + void setMaxNbLines(int lineCount); int reflowLines(int columns) override; private: - bool hasDifferentColors(const TextLine &line) const; - HistoryArray _lines; - CompactHistoryBlockList _blockList; + QList _cells; + QList _index; + QList _flags; - unsigned int _maxLineCount; + int _maxLineCount; + + void removeFirstLine(); + inline int lineLen(const int line); + inline int startOfLine(int line); }; }