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.
wilder
Carlos Alves 5 years ago committed by Kurt Hindenburg
parent 92798b03bc
commit 2aa61bb994
  1. 3
      src/CMakeLists.txt
  2. 2
      src/Screen.cpp
  3. 7
      src/history/HistoryScroll.h
  4. 38
      src/history/HistoryScrollFile.cpp
  5. 7
      src/history/HistoryScrollFile.h
  6. 22
      src/history/HistoryScrollNone.cpp
  7. 7
      src/history/HistoryScrollNone.h
  8. 73
      src/history/compact/CompactHistoryBlock.cpp
  9. 46
      src/history/compact/CompactHistoryBlock.h
  10. 55
      src/history/compact/CompactHistoryBlockList.cpp
  11. 34
      src/history/compact/CompactHistoryBlockList.h
  12. 176
      src/history/compact/CompactHistoryLine.cpp
  13. 49
      src/history/compact/CompactHistoryLine.h
  14. 220
      src/history/compact/CompactHistoryScroll.cpp
  15. 27
      src/history/compact/CompactHistoryScroll.h

@ -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

@ -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++;
}
}

@ -53,12 +53,7 @@ public:
virtual void addLine(LineProperty lineProperty = 0) = 0;
// modify history
virtual void insertCellsVector(int position, const QVector<Character> &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<Character> &cells) = 0;
virtual void setLineAt(int position, LineProperty lineProperty) = 0;
virtual void removeCells() = 0;
virtual int reflowLines(int columns) = 0;
//

@ -95,11 +95,7 @@ void HistoryScrollFile::addLine(LineProperty lineProperty)
_lineflags.add(reinterpret_cast<char *>(&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<Character> &)
{
}
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<char *>(&res), sizeof(qint64), res);
_cells.removeLast(res);
}
_cells.add(reinterpret_cast<const char *>(text), count * sizeof(Character));
}
void HistoryScrollFile::setCellsVectorAt(int, const QVector<Character> &)
{
}
int HistoryScrollFile::reflowLines(int columns)
{
auto reflowFile = std::make_unique<HistoryFile>();
@ -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<char *>(&locn), sizeof(qint64));
_lineflags.add(reinterpret_cast<char *>(&lineProperty), sizeof(char));
}

@ -37,12 +37,7 @@ public:
void addLine(LineProperty lineProperty = 0) override;
// Modify history
void insertCellsVector(int position, const QVector<Character> &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<Character> &cells) override;
void setLineAt(int position, LineProperty lineProperty) override;
void removeCells() override;
int reflowLines(int columns) override;
private:

@ -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<Character> &)
{
}
void HistoryScrollNone::setCellsAt(int , const Character [], int)
{
}
void HistoryScrollNone::setCellsVectorAt(int , const QVector<Character> &)
void HistoryScrollNone::removeCells()
{
}
@ -86,7 +70,3 @@ int HistoryScrollNone::reflowLines(int)
{
return 0;
}
void HistoryScrollNone::setLineAt(int , LineProperty)
{
}

@ -36,12 +36,7 @@ public:
void addLine(LineProperty lineProperty = 0) override;
// Modify history (do nothing here)
void insertCellsVector(int position, const QVector<Character> &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<Character> &cells) override;
void setLineAt(int position, LineProperty lineProperty) override;
void removeCells() override;
int reflowLines(int) override;
};

@ -1,73 +0,0 @@
/*
SPDX-FileCopyrightText: 1997, 1998 Lars Doelle <lars.doelle@on-line.de>
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<quint8 *>(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);
}

@ -1,46 +0,0 @@
/*
SPDX-FileCopyrightText: 1997, 1998 Lars Doelle <lars.doelle@on-line.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef COMPACTHISTORYBLOCK_H
#define COMPACTHISTORYBLOCK_H
// Konsole
#include "../characters/Character.h"
// System
#include <sys/mman.h>
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

@ -1,55 +0,0 @@
/*
SPDX-FileCopyrightText: 1997, 1998 Lars Doelle <lars.doelle@on-line.de>
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<CompactHistoryBlock>(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();
}

@ -1,34 +0,0 @@
/*
SPDX-FileCopyrightText: 1997, 1998 Lars Doelle <lars.doelle@on-line.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef COMPACTHISTORYBLOCKLIST_H
#define COMPACTHISTORYBLOCKLIST_H
#include <memory>
#include <vector>
#include "CompactHistoryBlock.h"
namespace Konsole
{
class CompactHistoryBlockList
{
public:
CompactHistoryBlockList();
~CompactHistoryBlockList();
void *allocate(size_t size);
void deallocate(void *);
int length();
private:
std::vector<std::unique_ptr<CompactHistoryBlock>> _blocks;
};
}
#endif

@ -1,176 +0,0 @@
/*
SPDX-FileCopyrightText: 1997, 1998 Lars Doelle <lars.doelle@on-line.de>
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<CharacterFormat *>(_blockListRef.allocate(sizeof(CharacterFormat) * _formatLength));
Q_ASSERT(_formatArray != nullptr);
_text = static_cast<uint *>(_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<int>(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<CharacterFormat *>(_blockListRef.allocate(sizeof(CharacterFormat) * new_formatLength));
Q_ASSERT(_formatArray != nullptr);
}
if (_length < new_length) {
_blockListRef.deallocate(_text);
_text = static_cast<uint *>(_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;
}

@ -1,49 +0,0 @@
/*
SPDX-FileCopyrightText: 1997, 1998 Lars Doelle <lars.doelle@on-line.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef COMPACTHISTORYLINE_H
#define COMPACTHISTORYLINE_H
#include <QVector>
#include "../characters/CharacterFormat.h"
#include "CompactHistoryBlockList.h"
namespace Konsole
{
typedef QVector<Character> 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

@ -11,66 +11,79 @@
using namespace Konsole;
struct reflowData { // data to reflow lines
QList<int> index;
QList<LineProperty> 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<CompactHistoryLine>(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<size_t>(_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<int>(_lines.size());
return _index.size();
}
int CompactHistoryScroll::getMaxLines()
{
return static_cast<int>(_maxLineCount);
return _maxLineCount;
}
int CompactHistoryScroll::getLineLen(int lineNumber)
{
if ((lineNumber < 0) || (static_cast<size_t>(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<size_t>(lineNumber) < _lines.size());
auto line = _lines[lineNumber].get();
Q_ASSERT(lineNumber < _index.size());
Q_ASSERT(startColumn >= 0);
Q_ASSERT(static_cast<unsigned int>(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<size_t>(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<CompactHistoryLine>(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<size_t>(_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<size_t>(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<size_t>(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<Character> 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;
}

@ -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<std::unique_ptr<CompactHistoryLine>> HistoryArray;
typedef QVector<Character> 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<Character> _cells;
QList<int> _index;
QList<LineProperty> _flags;
unsigned int _maxLineCount;
int _maxLineCount;
void removeFirstLine();
inline int lineLen(const int line);
inline int startOfLine(int line);
};
}

Loading…
Cancel
Save