Commit e71df623 authored by Tomaz  Canabrava's avatar Tomaz Canabrava
Browse files

Revert "Reflow lines when Terminal Shrinks"

Unfortunately the code is still fragile and I froze konsole
a few times in a few minutes. This is something that konsole
really needs, but we need more time to squish all the bugs
we find.
parent dec1ad5d
......@@ -11,7 +11,6 @@
// Qt
#include <QSet>
#include <QTextStream>
#include <QDebug>
// Konsole decoders
#include <PlainTextDecoder.h>
......@@ -48,13 +47,11 @@ Screen::Screen(int lines, int columns):
_currentTerminalDisplay(nullptr),
_lines(lines),
_columns(columns),
_screenLines(_lines + 1),
_screenLines(new ImageLine[_lines + 1]),
_screenLinesSize(_lines),
_scrolledLines(0),
_lastScrolledRegion(QRect()),
_droppedLines(0),
_oldTotalLines(0),
_isResize(false),
_lineProperties(QVarLengthArray<LineProperty, 64>()),
_history(new HistoryScrollNone()),
_cuX(0),
......@@ -89,6 +86,7 @@ Screen::Screen(int lines, int columns):
Screen::~Screen()
{
delete[] _screenLines;
delete _history;
delete _escapeSequenceUrlExtractor;
}
......@@ -369,160 +367,47 @@ void Screen::restoreCursor()
updateEffectiveRendition();
}
int Screen::getOldTotalLines()
{
return _oldTotalLines;
}
bool Screen::isResize()
{
if (_isResize) {
_isResize = false;
return true;
}
return _isResize;
}
void Screen::resizeImage(int new_lines, int new_columns)
{
if ((new_lines == _lines) && (new_columns == _columns)) {
return;
}
// set min values of columns and lines here
new_columns = (17 < new_columns)? new_columns : 17; // FIXME: bug when column <= 16
new_lines = (3 < new_lines)? new_lines : 3; // FIXME: bug when lines <= 2
_oldTotalLines = getLines() + getHistLines();
_isResize = true;
// First join everything.
int currentPos = 0;
if (new_columns != _columns) {
while (currentPos < _cuY && currentPos < _screenLines.count() - 1) {
// if the line have the 'LINE_WRAPPED' property, concat with the next line and remove it.
if ((_lineProperties[currentPos] & LINE_WRAPPED) != 0) {
_screenLines[currentPos].append(_screenLines[currentPos + 1]);
_screenLines.remove(currentPos + 1);
_lineProperties.remove(currentPos);
_cuY--;
continue;
}
currentPos++;
}
// Then move the data to lines below.
currentPos = 0;
while (currentPos != _screenLines.count() && currentPos != _cuY) {
const bool shouldCopy = _screenLines[currentPos].size() > new_columns;
// Copy from the current line, to the next one.
if (shouldCopy) {
_cuY++;
auto values = _screenLines[currentPos].mid(new_columns);
_screenLines[currentPos].remove(new_columns, values.size());
_lineProperties.insert(currentPos + 1, _lineProperties[currentPos]);
_screenLines.insert(currentPos + 1, values);
_lineProperties[currentPos] |= LINE_WRAPPED;
}
currentPos += 1;
}
}
// Check if it need to move from _screenLine to _history
while (_cuY > new_lines - 1) {
_history->addCellsVector(_screenLines[0]);
_history->addLine((_lineProperties[0] & LINE_WRAPPED) != 0);
_screenLines.pop_front();
_lineProperties.remove(0);
_cuY--;
}
_lineProperties.resize(new_lines + 1);
_screenLines.resize(new_lines + 1);
// Check if _history need to change
if (new_columns != _columns && _history->getLines()) {
// Join next line from _screenLine to _history
while (_history->isWrappedLine(_history->getLines() - 1)) {
_history->addCellsVector(_screenLines[0]);
_history->addLine((_lineProperties[0] & LINE_WRAPPED) != 0);
_screenLines.pop_front();
_lineProperties.remove(0);
_cuY--;
}
currentPos = 0;
while (currentPos < _history->getLines() - 1) {
// if it's true, join the line with next line
if (_history->isWrappedLine(currentPos)) {
int curr_linelen = _history->getLineLen(currentPos);
int next_linelen = _history->getLineLen(currentPos + 1);
auto *new_line = getCharacterBuffer(curr_linelen + next_linelen);
bool new_line_property = _history->isWrappedLine(currentPos + 1);
// Join the lines
_history->getCells(currentPos, 0, curr_linelen, new_line);
_history->getCells(currentPos + 1, 0, next_linelen, new_line + curr_linelen);
// save the new_line in history and remove the next line
_history->setCellsAt(currentPos, new_line, curr_linelen + next_linelen);
_history->setLineAt(currentPos, new_line_property);
_history->removeCells(currentPos + 1);
continue;
}
currentPos++;
}
// Move data to next line if needed
currentPos = 0;
while (currentPos < _history->getLines()) {
int curr_linelen = _history->getLineLen(currentPos);
// if the current line > new_columns it will need a new line
if (curr_linelen > new_columns) {
auto *curr_line = getCharacterBuffer(curr_linelen);
bool curr_line_property = _history->isWrappedLine(currentPos);
_history->getCells(currentPos, 0, curr_linelen, curr_line);
_history->setCellsAt(currentPos, curr_line, new_columns);
_history->setLineAt(currentPos, true);
if (currentPos < _history->getMaxLines() - 1) {
_history->insertCells(currentPos + 1, curr_line + new_columns, curr_linelen - new_columns);
_history->setLineAt(currentPos + 1, curr_line_property);
} else {
_history->addCells(curr_line + new_columns, curr_linelen - new_columns);
_history->addLine(curr_line_property);
}
}
currentPos++;
if (_cuY > new_lines - 1) {
// attempt to preserve focus and _lines
_bottomMargin = _lines - 1; //FIXME: margin lost
for (int i = 0; i < _cuY - (new_lines - 1); i++) {
addHistLine();
scrollUp(0, 1);
}
}
// Check cursor position and send from _history to _screenLines
ImageLine histLine;
histLine.reserve(1024);
while (_cuY < new_lines - 1 && _history->getLines()) {
int histPos = _history->getLines() - 1;
int histLineLen = _history->getLineLen(histPos);
int isWrapped = _history->isWrappedLine(histPos)? LINE_WRAPPED : LINE_DEFAULT;
histLine.resize(histLineLen);
_history->getCells(histPos, 0, histLineLen, histLine.data());
_screenLines.insert(0, histLine);
_lineProperties.insert(0, isWrapped);
_history->removeCells(histPos);
_cuY++;
// create new screen _lines and copy from old to new
auto newScreenLines = new ImageLine[new_lines + 1];
for (int i = 0; i < qMin(_lines, new_lines + 1) ; i++) {
newScreenLines[i] = _screenLines[i];
}
_lineProperties.resize(new_lines + 1);
for (int i = _screenLines.count(); (i > 0) && (i < new_lines + 1); i++) {
for (int i = _lines; (i > 0) && (i < new_lines + 1); i++) {
_lineProperties[i] = LINE_DEFAULT;
}
_screenLines.resize(new_lines + 1);
clearSelection();
delete[] _screenLines;
_screenLines = newScreenLines;
_screenLinesSize = new_lines;
_lines = new_lines;
_columns = new_columns;
_cuX = qMin(_cuX, _columns - 1);
_cuY = qMin(_cuY, _lines - 1);
// FIXME: try to keep values, evtl.
setDefaultMargins();
_topMargin = 0;
_bottomMargin = _lines - 1;
initTabStops();
clearSelection();
}
......@@ -1500,7 +1385,7 @@ int Screen::copyLineToStream(int line ,
screenLine = qMin(screenLine, _screenLinesSize);
auto* data = _screenLines[screenLine].data();
Character* data = _screenLines[screenLine].data();
int length = _screenLines[screenLine].count();
// Don't remove end spaces in lines that wrap
......@@ -1577,61 +1462,21 @@ void Screen::addHistLine()
// add line to history buffer
// we have to take care about scrolling, too...
const int oldHistLines = _history->getLines();
int newHistLines = _history->getLines();
if (hasScroll()) {
// Check if _history have 'new line' property and join lines before adding a new one to history
if (oldHistLines > 0 && _history->isWrappedLine(oldHistLines - 1)) {
int hist_linelen = _history->getLineLen(oldHistLines - 1);
auto *hist_line = getCharacterBuffer(hist_linelen + _screenLines[0].count());
_history->getCells(oldHistLines - 1, 0, hist_linelen, hist_line);
// Join the new line into the old line
for (int i = 0; i < _screenLines[0].count(); i++) {
hist_line[hist_linelen + i] = _screenLines[0][i];
}
hist_linelen += _screenLines[0].count();
// After join, check if it needs new line in history to show it on scroll
if (hist_linelen > _columns) {
_history->setCellsAt(oldHistLines - 1, hist_line, _columns);
_history->setLineAt(oldHistLines - 1, true);
_history->addCells(hist_line + _columns, hist_linelen - _columns);
_history->addLine((_lineProperties[0] & LINE_WRAPPED) != 0);
newHistLines = _history->getLines();
// If the history is full, increment the count
// of dropped _lines
if (newHistLines == oldHistLines) {
_droppedLines++;
// We removed a line, we need to verify if we need to remove a URL.
_escapeSequenceUrlExtractor->historyLinesRemoved(1);
}
} else {
// Doesn't need a new line
_history->setCellsAt(oldHistLines - 1, hist_line, hist_linelen);
_history->setLineAt(oldHistLines - 1, (_lineProperties[0] & LINE_WRAPPED) != 0);
}
} else {
_history->addCellsVector(_screenLines[0]);
_history->addLine((_lineProperties[0] & LINE_WRAPPED) != 0);
_history->addCellsVector(_screenLines[0]);
_history->addLine((_lineProperties[0] & LINE_WRAPPED) != 0);
newHistLines = _history->getLines();
const int newHistLines = _history->getLines();
// If the history is full, increment the count
// of dropped _lines
if (newHistLines == oldHistLines) {
_droppedLines++;
const bool beginIsTL = (_selBegin == _selTopLeft);
// We removed a line, we need to verify if we need to remove a URL.
_escapeSequenceUrlExtractor->historyLinesRemoved(1);
}
// If the history is full, increment the count
// of dropped _lines
if (newHistLines == oldHistLines) {
_droppedLines++;
}
bool beginIsTL = (_selBegin == _selTopLeft);
// Adjust selection for the new point of reference
if (newHistLines > oldHistLines) {
if (_selBegin != -1) {
......@@ -1667,6 +1512,12 @@ void Screen::addHistLine()
}
}
}
// We removed a line, we need to verify if we need to remove a URL.
const int newHistLines = _history->getLines();
if (oldHistLines == newHistLines) {
_escapeSequenceUrlExtractor->historyLinesRemoved(1);
}
}
int Screen::getHistLines() const
......
......@@ -588,9 +588,6 @@ public:
static const Character DefaultChar;
int getOldTotalLines();
bool isResize();
private:
//copies a line of text from the screen or history into a stream using a
//specified character decoder. Returns the number of lines actually copied,
......@@ -656,7 +653,7 @@ private:
int _columns;
typedef QVector<Character> ImageLine; // [0..columns]
QVector<ImageLine> _screenLines; // [lines]
ImageLine *_screenLines; // [lines]
int _screenLinesSize; // _screenLines.size()
int _scrolledLines;
......@@ -664,9 +661,6 @@ private:
int _droppedLines;
int _oldTotalLines;
bool _isResize;
QVarLengthArray<LineProperty, 64> _lineProperties;
// history buffer ---------------
......
......@@ -290,21 +290,10 @@ QRect ScreenWindow::scrollRegion() const
if (atEndOfOutput() && equalToScreenSize) {
return _screen->lastScrolledRegion();
}
}
return {0, 0, windowColumns(), windowLines()};
}
void ScreenWindow::updateCurrentLine()
{
if (!_screen->isResize()) {
return;
}
if (_currentLine > 0) {
_currentLine -= _screen->getOldTotalLines() - lineCount();
}
_currentLine = qBound(0, _currentLine, lineCount() - windowLines());
}
void ScreenWindow::notifyOutputChanged()
{
// move window to the bottom of the screen and update scroll count
......
......@@ -218,8 +218,6 @@ public:
*/
QString selectedText(const Screen::DecodingOptions options) const;
void updateCurrentLine();
public Q_SLOTS:
/**
* Notifies the window that the contents of the associated terminal screen have changed.
......
......@@ -32,7 +32,6 @@ public:
// access to history
virtual int getLines() = 0;
virtual int getMaxLines() = 0;
virtual int getLineLen(int lineno) = 0;
virtual void getCells(int lineno, int colno, int count, Character res[]) = 0;
virtual bool isWrappedLine(int lineNumber) = 0;
......@@ -48,14 +47,6 @@ public:
virtual void addLine(bool previousWrapped = false) = 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, bool previousWrapped) = 0;
//
// FIXME: Passing around constant references to HistoryType instances
// is very unsafe, because those references will no longer
......
......@@ -33,11 +33,6 @@ int HistoryScrollFile::getLines()
return _index.len() / sizeof(qint64);
}
int HistoryScrollFile::getMaxLines()
{
return _index.len() / sizeof(qint64);
}
int HistoryScrollFile::getLineLen(int lineno)
{
return (startOfLine(lineno + 1) - startOfLine(lineno)) / sizeof(Character);
......@@ -84,27 +79,3 @@ void HistoryScrollFile::addLine(bool previousWrapped)
unsigned char flags = previousWrapped ? 0x01 : 0x00;
_lineflags.add(reinterpret_cast<char *>(&flags), sizeof(char));
}
void HistoryScrollFile::insertCells(int , const Character [], int)
{
}
void HistoryScrollFile::removeCells(int )
{
}
void HistoryScrollFile::insertCellsVector(int , const QVector<Character> &)
{
}
void HistoryScrollFile::setCellsAt(int , const Character [], int)
{
}
void HistoryScrollFile::setCellsVectorAt(int , const QVector<Character> &)
{
}
void HistoryScrollFile::setLineAt(int , bool)
{
}
......@@ -27,7 +27,6 @@ public:
~HistoryScrollFile() override;
int getLines() override;
int getMaxLines() override;
int getLineLen(int lineno) override;
void getCells(int lineno, int colno, int count, Character res[]) override;
bool isWrappedLine(int lineno) override;
......@@ -35,13 +34,6 @@ public:
void addCells(const Character text[], int count) override;
void addLine(bool previousWrapped = false) override;
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, bool previousWrapped) override;
private:
qint64 startOfLine(int lineno);
......
......@@ -30,11 +30,6 @@ int HistoryScrollNone::getLines()
return 0;
}
int HistoryScrollNone::getMaxLines()
{
return 0;
}
int HistoryScrollNone::getLineLen(int)
{
return 0;
......@@ -56,27 +51,3 @@ void HistoryScrollNone::addCells(const Character [], int)
void HistoryScrollNone::addLine(bool)
{
}
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::setLineAt(int , bool)
{
}
\ No newline at end of file
......@@ -26,20 +26,12 @@ public:
bool hasScroll() override;
int getLines() override;
int getMaxLines() override;
int getLineLen(int lineno) override;
void getCells(int lineno, int colno, int count, Character res[]) override;
bool isWrappedLine(int lineno) override;
void addCells(const Character a[], int count) override;
void addLine(bool previousWrapped = false) override;
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, bool previousWrapped) override;
};
}
......
......@@ -57,11 +57,6 @@ int CompactHistoryScroll::getLines()
return _lines.size();
}
int CompactHistoryScroll::getMaxLines()
{
return static_cast<int>(_maxLineCount);
}
int CompactHistoryScroll::getLineLen(int lineNumber)
{
if ((lineNumber < 0) || (lineNumber >= _lines.size())) {
......@@ -96,51 +91,6 @@ void CompactHistoryScroll::setMaxNbLines(unsigned int lineCount)
////qDebug() << "set max lines to: " << _maxLineCount;
}
void CompactHistoryScroll::insertCellsVector(int position, const TextLine &cells)
{
CompactHistoryLine *line = new(_blockList) CompactHistoryLine(cells, _blockList);
_lines.insert(position, line);
if (_lines.size() > static_cast<int>(_maxLineCount)) {
delete _lines.takeAt(0);
}
}
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)
{
delete _lines.takeAt(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)
{
CompactHistoryLine *line = new(_blockList) CompactHistoryLine(cells, _blockList);
delete _lines.takeAt(position);
_lines.insert(position, line);
}
void CompactHistoryScroll::setLineAt(int position, bool previousWrapped)
{
CompactHistoryLine *line = _lines.at(position);
line->setWrapped(previousWrapped);
}
bool CompactHistoryScroll::isWrappedLine(int lineNumber)
{
Q_ASSERT(lineNumber < _lines.size());
......
......@@ -24,7 +24,6 @@ public:
~CompactHistoryScroll() override;
int getLines() override;
int getMaxLines() override;
int getLineLen(int lineNumber) override;
void getCells(int lineNumber, int startColumn, int count, Character buffer[]) override;
bool isWrappedLine(int lineNumber) override;
......@@ -33,14 +32,7 @@ public:
void addCellsVector(const TextLine &cells) override;
void addLine(bool previousWrapped = false) 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 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, bool previousWrapped) override;
private:
bool hasDifferentColors(const TextLine &line) const;
......
......@@ -497,9 +497,6 @@ void TerminalDisplay::updateImage()
return;
}
// Better control over screen resizing visual glitches
_screenWindow->updateCurrentLine();
// optimization - scroll the existing image where possible and
// avoid expensive text drawing for parts of the image that
// can simply be moved up or down
......