From 5cd00fd885de01cb5c313e5508e8d296693d7066 Mon Sep 17 00:00:00 2001 From: Tomaz Canabrava Date: Wed, 29 Jul 2020 12:06:31 +0200 Subject: [PATCH 01/23] Reflow lines when Terminal Shrinks There are plenty of bugs here, this is a *serious* wip. This is also the biggest feature that is missing from konsole for years and years. todo: - Handle history - Handle increase of columns in terminal size - handle new lines --- src/Screen.cpp | 58 +++++++++++++++++++++++++++++++++++++------- src/ScreenWindow.cpp | 2 +- 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/src/Screen.cpp b/src/Screen.cpp index 2d147821a..5e9ceab53 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -367,6 +367,8 @@ void Screen::restoreCursor() updateEffectiveRendition(); } +#include + void Screen::resizeImage(int new_lines, int new_columns) { if ((new_lines == _lines) && (new_columns == _columns)) { @@ -382,23 +384,61 @@ void Screen::resizeImage(int new_lines, int new_columns) } } - // create new screen _lines and copy from old to new + if (new_columns < _columns) { + QVector images; + // First copy everything. + for (int i = 0; i < qMin(_lines, new_lines + 1) ; i++) { + images.push_back(_screenLines[i]); + } + + // Then move the data to lines below. + int currentPos = 0; + while (currentPos != images.count()) { + + // If we are in the last line, append a new one. + const bool shouldCopy = images[currentPos].size() > new_columns; + if (shouldCopy && images.count() - 1 == currentPos) { + images.append(ImageLine{}); + } + + // Now copy from the current line, to the next one. + if (shouldCopy) { + auto values = images[currentPos].mid(new_columns); + images[currentPos].remove(new_columns, values.size()); + values.append(images[currentPos+1]); + images[currentPos+1] = values; + } + currentPos += 1; + } + + // Now set the correct image based on the moved lines. + auto newScreenLines = new ImageLine[new_lines + 1]; + for (int i = 0; i < qMin(_lines, new_lines + 1) ; i++) { + newScreenLines[i] = images[i]; + } + delete[] _screenLines; + _screenLines = newScreenLines; + } else if (new_columns > _columns) { + - auto newScreenLines = new ImageLine[new_lines + 1]; - for (int i = 0; i < qMin(_lines, new_lines + 1) ; i++) { - newScreenLines[i] = _screenLines[i]; + } else { + auto newScreenLines = new ImageLine[new_lines + 1]; + for (int i = 0; i < qMin(_lines, new_lines + 1) ; i++) { + newScreenLines[i] = _screenLines[i]; + } + + delete[] _screenLines; + _screenLines = newScreenLines; } + clearSelection(); + _screenLinesSize = new_lines; + _lineProperties.resize(new_lines + 1); for (int i = _lines; (i > 0) && (i < new_lines + 1); i++) { _lineProperties[i] = LINE_DEFAULT; } - clearSelection(); - - delete[] _screenLines; - _screenLines = newScreenLines; - _screenLinesSize = new_lines; _lines = new_lines; _columns = new_columns; diff --git a/src/ScreenWindow.cpp b/src/ScreenWindow.cpp index 5ff0d245e..e27ceaa7b 100644 --- a/src/ScreenWindow.cpp +++ b/src/ScreenWindow.cpp @@ -290,7 +290,7 @@ QRect ScreenWindow::scrollRegion() const if (atEndOfOutput() && equalToScreenSize) { return _screen->lastScrolledRegion(); - } + } return {0, 0, windowColumns(), windowLines()}; } -- GitLab From 86a486934ed66ab28c3f794ef37c0a69b4e29a83 Mon Sep 17 00:00:00 2001 From: Carlos Alves Date: Wed, 11 Nov 2020 17:43:00 -0300 Subject: [PATCH 02/23] Reflow lines when Terminal resizes: both ways An attempt to resize on both ways: shrink and expand. Still thinking on how to handle _history --- src/Screen.cpp | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/src/Screen.cpp b/src/Screen.cpp index 5e9ceab53..2cf50a9e1 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -384,43 +384,55 @@ void Screen::resizeImage(int new_lines, int new_columns) } } - if (new_columns < _columns) { + if (new_columns != _columns) { + // Random not printable char to mark nextline + const auto NextLine = Character(130, + CharacterColor(COLOR_SPACE_DEFAULT, DEFAULT_FORE_COLOR), + CharacterColor(COLOR_SPACE_DEFAULT, DEFAULT_BACK_COLOR), + DEFAULT_RENDITION, + false); QVector images; // First copy everything. for (int i = 0; i < qMin(_lines, new_lines + 1) ; i++) { + // if the line have the 'NextLine' char, concat with the next line before push_back. + if (_screenLines[i].count() && _screenLines[i].at(_screenLines[i].count() - 1) == NextLine) { + _screenLines[i].pop_back(); + _screenLines[i].append(_screenLines[i + 1]); + _screenLines[i + 1] = _screenLines[i]; + _cuY--; + continue; + } images.push_back(_screenLines[i]); } // Then move the data to lines below. int currentPos = 0; while (currentPos != images.count()) { - - // If we are in the last line, append a new one. const bool shouldCopy = images[currentPos].size() > new_columns; - if (shouldCopy && images.count() - 1 == currentPos) { - images.append(ImageLine{}); - } - // Now copy from the current line, to the next one. + // Copy from the current line, to the next one. if (shouldCopy) { + // If we are in the last line, append a new one. + if (currentPos == images.count() - 1) { + images.append(ImageLine{}); + } + auto values = images[currentPos].mid(new_columns); images[currentPos].remove(new_columns, values.size()); - values.append(images[currentPos+1]); - images[currentPos+1] = values; + images[currentPos].append(NextLine); + images.insert(currentPos + 1, values); + _cuY++; } currentPos += 1; } // Now set the correct image based on the moved lines. auto newScreenLines = new ImageLine[new_lines + 1]; - for (int i = 0; i < qMin(_lines, new_lines + 1) ; i++) { + for (int i = 0; i < qMin(images.count(), new_lines + 1) ; i++) { newScreenLines[i] = images[i]; } delete[] _screenLines; _screenLines = newScreenLines; - } else if (new_columns > _columns) { - - } else { auto newScreenLines = new ImageLine[new_lines + 1]; for (int i = 0; i < qMin(_lines, new_lines + 1) ; i++) { -- GitLab From ff0681d4c37755e1c75a0b9fa3d93359b2a04e6e Mon Sep 17 00:00:00 2001 From: Carlos Alves Date: Thu, 12 Nov 2020 15:34:26 -0300 Subject: [PATCH 03/23] Change _screenLines to QVector It was a fixed size array, as a QVector it will change size faster without the need of memory allocation. --- src/Screen.cpp | 60 +++++++++++++++++++------------------------------- src/Screen.h | 2 +- 2 files changed, 24 insertions(+), 38 deletions(-) diff --git a/src/Screen.cpp b/src/Screen.cpp index 2cf50a9e1..f56bbb0ec 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -47,7 +47,7 @@ Screen::Screen(int lines, int columns): _currentTerminalDisplay(nullptr), _lines(lines), _columns(columns), - _screenLines(new ImageLine[_lines + 1]), + _screenLines(_lines + 1), _screenLinesSize(_lines), _scrolledLines(0), _lastScrolledRegion(QRect()), @@ -86,7 +86,6 @@ Screen::Screen(int lines, int columns): Screen::~Screen() { - delete[] _screenLines; delete _history; delete _escapeSequenceUrlExtractor; } @@ -391,56 +390,43 @@ void Screen::resizeImage(int new_lines, int new_columns) CharacterColor(COLOR_SPACE_DEFAULT, DEFAULT_BACK_COLOR), DEFAULT_RENDITION, false); - QVector images; - // First copy everything. - for (int i = 0; i < qMin(_lines, new_lines + 1) ; i++) { - // if the line have the 'NextLine' char, concat with the next line before push_back. - if (_screenLines[i].count() && _screenLines[i].at(_screenLines[i].count() - 1) == NextLine) { - _screenLines[i].pop_back(); - _screenLines[i].append(_screenLines[i + 1]); - _screenLines[i + 1] = _screenLines[i]; + // First join everything. + int currentPos = 0; + while (currentPos != _screenLines.count()) { + // if the line have the 'NextLine' char, concat with the next line and remove it. + if (_screenLines[currentPos].count() && _screenLines[currentPos].at(_screenLines[currentPos].count() - 1) == NextLine) { + _screenLines[currentPos].pop_back(); // remove 'NextLine' + _screenLines[currentPos].append(_screenLines[currentPos + 1]); + _screenLines.remove(currentPos + 1); _cuY--; continue; } - images.push_back(_screenLines[i]); + currentPos++; } // Then move the data to lines below. - int currentPos = 0; - while (currentPos != images.count()) { - const bool shouldCopy = images[currentPos].size() > new_columns; + currentPos = 0; + while (currentPos != _screenLines.count()) { + const bool shouldCopy = _screenLines[currentPos].size() > new_columns; // Copy from the current line, to the next one. if (shouldCopy) { // If we are in the last line, append a new one. - if (currentPos == images.count() - 1) { - images.append(ImageLine{}); + if (currentPos == _screenLines.count() - 1) { + _screenLines.append(ImageLine{}); } - - auto values = images[currentPos].mid(new_columns); - images[currentPos].remove(new_columns, values.size()); - images[currentPos].append(NextLine); - images.insert(currentPos + 1, values); _cuY++; + + auto values = _screenLines[currentPos].mid(new_columns); + _screenLines[currentPos].remove(new_columns, values.size()); + _screenLines[currentPos].append(NextLine); + _screenLines.insert(currentPos + 1, values); } currentPos += 1; } - - // Now set the correct image based on the moved lines. - auto newScreenLines = new ImageLine[new_lines + 1]; - for (int i = 0; i < qMin(images.count(), new_lines + 1) ; i++) { - newScreenLines[i] = images[i]; - } - delete[] _screenLines; - _screenLines = newScreenLines; + _screenLines.resize(new_lines + 1); } else { - auto newScreenLines = new ImageLine[new_lines + 1]; - for (int i = 0; i < qMin(_lines, new_lines + 1) ; i++) { - newScreenLines[i] = _screenLines[i]; - } - - delete[] _screenLines; - _screenLines = newScreenLines; + _screenLines.resize(new_lines + 1); } clearSelection(); @@ -1437,7 +1423,7 @@ int Screen::copyLineToStream(int line , screenLine = qMin(screenLine, _screenLinesSize); - Character* data = _screenLines[screenLine].data(); + auto* data = _screenLines[screenLine].data(); int length = _screenLines[screenLine].count(); // Don't remove end spaces in lines that wrap diff --git a/src/Screen.h b/src/Screen.h index d90ea94f3..0a68d51b2 100644 --- a/src/Screen.h +++ b/src/Screen.h @@ -653,7 +653,7 @@ private: int _columns; typedef QVector ImageLine; // [0..columns] - ImageLine *_screenLines; // [lines] + QVector _screenLines; // [lines] int _screenLinesSize; // _screenLines.size() int _scrolledLines; -- GitLab From 284ed7aec20efcb42bddb9ba4438cffe6ec96d38 Mon Sep 17 00:00:00 2001 From: Carlos Alves Date: Thu, 12 Nov 2020 16:12:04 -0300 Subject: [PATCH 04/23] _history management of _screenLines when resizing Count the aditional lines that will be needed by the new size, if more than 'new_lines', send to history. --- src/Screen.cpp | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/Screen.cpp b/src/Screen.cpp index f56bbb0ec..46b930dac 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -11,6 +11,7 @@ // Qt #include #include +#include // Konsole decoders #include @@ -366,23 +367,12 @@ void Screen::restoreCursor() updateEffectiveRendition(); } -#include - void Screen::resizeImage(int new_lines, int new_columns) { if ((new_lines == _lines) && (new_columns == _columns)) { return; } - 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); - } - } - if (new_columns != _columns) { // Random not printable char to mark nextline const auto NextLine = Character(130, @@ -392,6 +382,7 @@ void Screen::resizeImage(int new_lines, int new_columns) false); // First join everything. int currentPos = 0; + int count_needed_lines = 0; while (currentPos != _screenLines.count()) { // if the line have the 'NextLine' char, concat with the next line and remove it. if (_screenLines[currentPos].count() && _screenLines[currentPos].at(_screenLines[currentPos].count() - 1) == NextLine) { @@ -401,9 +392,22 @@ void Screen::resizeImage(int new_lines, int new_columns) _cuY--; continue; } + count_needed_lines += _screenLines[currentPos].count() / (new_columns + 1); currentPos++; } + // If it will need more lines than new_lines have, send lines to _history + count_needed_lines += _cuY; + if (count_needed_lines > new_lines - 1) { + _screenLines.resize(_lines + 1); + // attempt to preserve focus and _lines + _bottomMargin = _lines - 1; //FIXME: margin lost + for (int i = 0; i < count_needed_lines - (new_lines - 1); i++) { + addHistLine(); + scrollUp(0, 1); + } + } + // Then move the data to lines below. currentPos = 0; while (currentPos != _screenLines.count()) { @@ -426,6 +430,14 @@ void Screen::resizeImage(int new_lines, int new_columns) } _screenLines.resize(new_lines + 1); } else { + 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); + } + } _screenLines.resize(new_lines + 1); } -- GitLab From 2be00da524b2be487347509312c4f2920dc88af5 Mon Sep 17 00:00:00 2001 From: Carlos Alves Date: Fri, 13 Nov 2020 16:27:10 -0300 Subject: [PATCH 05/23] Changed from 'NewLine' char to _lineProperties _lineProperties is something that existed before. And in some Terminal emulators it was used to wrap lines, I'm using it now to wrap lines while resizing. And improved the _history flux control when resizing. --- src/Screen.cpp | 114 ++++++++++++++++++++++--------------------------- 1 file changed, 50 insertions(+), 64 deletions(-) diff --git a/src/Screen.cpp b/src/Screen.cpp index 46b930dac..42a125f64 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -373,82 +373,68 @@ void Screen::resizeImage(int new_lines, int new_columns) return; } - if (new_columns != _columns) { - // Random not printable char to mark nextline - const auto NextLine = Character(130, - CharacterColor(COLOR_SPACE_DEFAULT, DEFAULT_FORE_COLOR), - CharacterColor(COLOR_SPACE_DEFAULT, DEFAULT_BACK_COLOR), - DEFAULT_RENDITION, - false); - // First join everything. - int currentPos = 0; - int count_needed_lines = 0; - while (currentPos != _screenLines.count()) { - // if the line have the 'NextLine' char, concat with the next line and remove it. - if (_screenLines[currentPos].count() && _screenLines[currentPos].at(_screenLines[currentPos].count() - 1) == NextLine) { - _screenLines[currentPos].pop_back(); // remove 'NextLine' - _screenLines[currentPos].append(_screenLines[currentPos + 1]); - _screenLines.remove(currentPos + 1); - _cuY--; - continue; - } - count_needed_lines += _screenLines[currentPos].count() / (new_columns + 1); - currentPos++; + // First join everything. + int currentPos = 0; + int count_needed_lines = 0; + while (currentPos != _screenLines.count()) { + // if the line have the 'NextLine' char, 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; } + count_needed_lines += _screenLines[currentPos].count() / (new_columns + 1); + currentPos++; + } - // If it will need more lines than new_lines have, send lines to _history - count_needed_lines += _cuY; - if (count_needed_lines > new_lines - 1) { - _screenLines.resize(_lines + 1); - // attempt to preserve focus and _lines - _bottomMargin = _lines - 1; //FIXME: margin lost - for (int i = 0; i < count_needed_lines - (new_lines - 1); i++) { - addHistLine(); - scrollUp(0, 1); - } + // If it will need more lines than new_lines have, send lines to _history + count_needed_lines += _cuY; + if (count_needed_lines > new_lines - 1) { + _lineProperties.resize(_lines + 1); + for (int i = _screenLines.count(); (i > 0) && (i < new_lines + 1); i++) { + _lineProperties[i] = LINE_DEFAULT; } + _screenLines.resize(_lines + 1); + // attempt to preserve focus and _lines + _bottomMargin = _lines - 1; //FIXME: margin lost + for (int i = 0; i < count_needed_lines - (new_lines - 1); i++) { + addHistLine(); + scrollUp(0, 1); + _cuY--; + } + } - // Then move the data to lines below. - currentPos = 0; - while (currentPos != _screenLines.count()) { - const bool shouldCopy = _screenLines[currentPos].size() > new_columns; - - // Copy from the current line, to the next one. - if (shouldCopy) { - // If we are in the last line, append a new one. - if (currentPos == _screenLines.count() - 1) { - _screenLines.append(ImageLine{}); - } - _cuY++; + // Then move the data to lines below. + currentPos = 0; + while (currentPos != _screenLines.count()) { + const bool shouldCopy = _screenLines[currentPos].size() > new_columns; - auto values = _screenLines[currentPos].mid(new_columns); - _screenLines[currentPos].remove(new_columns, values.size()); - _screenLines[currentPos].append(NextLine); - _screenLines.insert(currentPos + 1, values); - } - currentPos += 1; - } - _screenLines.resize(new_lines + 1); - } else { - 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); + // Copy from the current line, to the next one. + if (shouldCopy) { + // If we are in the last line, append a new one. + if (currentPos == _screenLines.count() - 1) { + _screenLines.append(ImageLine{}); } + _cuY++; + + auto values = _screenLines[currentPos].mid(new_columns); + _screenLines[currentPos].remove(new_columns, values.size()); + _lineProperties[currentPos] = _lineProperties[currentPos] | LINE_WRAPPED; + _screenLines.insert(currentPos + 1, values); + _lineProperties.insert(currentPos + 1, LINE_DEFAULT); } - _screenLines.resize(new_lines + 1); + currentPos += 1; } - - clearSelection(); - _screenLinesSize = new_lines; - _lineProperties.resize(new_lines + 1); - for (int i = _lines; (i > 0) && (i < new_lines + 1); i++) { + for (int i = _screenLines.count(); (i > 0) && (i < new_lines + 1); i++) { _lineProperties[i] = LINE_DEFAULT; } + _screenLines.resize(new_lines + 1); + clearSelection(); + _screenLinesSize = new_lines; _lines = new_lines; _columns = new_columns; -- GitLab From 4d4d70d616be3ab6a536711cff0911c6c1b25350 Mon Sep 17 00:00:00 2001 From: Carlos Alves Date: Fri, 13 Nov 2020 17:25:42 -0300 Subject: [PATCH 06/23] Ignore current cursor line Don't need to reflow the current cursor line. (it will bug and crash) --- src/Screen.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Screen.cpp b/src/Screen.cpp index 42a125f64..2716b37ed 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -408,15 +408,11 @@ void Screen::resizeImage(int new_lines, int new_columns) // Then move the data to lines below. currentPos = 0; - while (currentPos != _screenLines.count()) { + 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) { - // If we are in the last line, append a new one. - if (currentPos == _screenLines.count() - 1) { - _screenLines.append(ImageLine{}); - } _cuY++; auto values = _screenLines[currentPos].mid(new_columns); -- GitLab From bccd0a3fcdd1360aae856816a8b2adf9adc547c3 Mon Sep 17 00:00:00 2001 From: Tomaz Canabrava Date: Mon, 16 Nov 2020 18:05:24 +0000 Subject: [PATCH 07/23] Fix crash acessing wrong index --- src/Screen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Screen.cpp b/src/Screen.cpp index 2716b37ed..b6ba00d0a 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -376,7 +376,7 @@ void Screen::resizeImage(int new_lines, int new_columns) // First join everything. int currentPos = 0; int count_needed_lines = 0; - while (currentPos != _screenLines.count()) { + while (currentPos != _screenLines.count() - 1) { // if the line have the 'NextLine' char, concat with the next line and remove it. if ((_lineProperties[currentPos] & LINE_WRAPPED) != 0) { _screenLines[currentPos].append(_screenLines[currentPos + 1]); -- GitLab From 155cedeca2be6edb51b5b90926943061ac65c5bb Mon Sep 17 00:00:00 2001 From: Carlos Alves Date: Tue, 17 Nov 2020 07:59:34 -0300 Subject: [PATCH 08/23] Keep the lines property Instead of assign LINE_DEFAULT to next line, it will keep the current line property. --- src/Screen.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Screen.cpp b/src/Screen.cpp index b6ba00d0a..43f062e55 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -377,7 +377,7 @@ void Screen::resizeImage(int new_lines, int new_columns) int currentPos = 0; int count_needed_lines = 0; while (currentPos != _screenLines.count() - 1) { - // if the line have the 'NextLine' char, concat with the next line and remove it. + // 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); @@ -417,9 +417,9 @@ void Screen::resizeImage(int new_lines, int new_columns) auto values = _screenLines[currentPos].mid(new_columns); _screenLines[currentPos].remove(new_columns, values.size()); - _lineProperties[currentPos] = _lineProperties[currentPos] | LINE_WRAPPED; + _lineProperties.insert(currentPos + 1, _lineProperties[currentPos]); _screenLines.insert(currentPos + 1, values); - _lineProperties.insert(currentPos + 1, LINE_DEFAULT); + _lineProperties[currentPos] |= LINE_WRAPPED; } currentPos += 1; } -- GitLab From 3b182fa18c921c1ea21aff8585ee639f936e5054 Mon Sep 17 00:00:00 2001 From: Carlos Alves Date: Tue, 17 Nov 2020 09:46:20 -0300 Subject: [PATCH 09/23] Change a specific position at history Needed to correct the history when columns size change --- src/history/HistoryScroll.h | 4 ++++ src/history/HistoryScrollFile.cpp | 8 ++++++++ src/history/HistoryScrollFile.h | 3 +++ src/history/HistoryScrollNone.cpp | 8 ++++++++ src/history/HistoryScrollNone.h | 3 +++ src/history/compact/CompactHistoryScroll.cpp | 15 +++++++++++++++ src/history/compact/CompactHistoryScroll.h | 2 ++ 7 files changed, 43 insertions(+) diff --git a/src/history/HistoryScroll.h b/src/history/HistoryScroll.h index 69285618f..4bb2ed57d 100644 --- a/src/history/HistoryScroll.h +++ b/src/history/HistoryScroll.h @@ -47,6 +47,10 @@ public: virtual void addLine(bool previousWrapped = false) = 0; + // modify history + virtual void setCellsVectorAt(int position, const QVector &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 diff --git a/src/history/HistoryScrollFile.cpp b/src/history/HistoryScrollFile.cpp index ba524162b..4f9f267fc 100644 --- a/src/history/HistoryScrollFile.cpp +++ b/src/history/HistoryScrollFile.cpp @@ -79,3 +79,11 @@ void HistoryScrollFile::addLine(bool previousWrapped) unsigned char flags = previousWrapped ? 0x01 : 0x00; _lineflags.add(reinterpret_cast(&flags), sizeof(char)); } + +void HistoryScrollFile::setCellsVectorAt(int , const QVector &) +{ +} + +void HistoryScrollFile::setLineAt(int , bool) +{ +} diff --git a/src/history/HistoryScrollFile.h b/src/history/HistoryScrollFile.h index fc22ff926..f88d908d0 100644 --- a/src/history/HistoryScrollFile.h +++ b/src/history/HistoryScrollFile.h @@ -34,6 +34,9 @@ public: void addCells(const Character text[], int count) override; void addLine(bool previousWrapped = false) override; + void setCellsVectorAt(int position, const QVector &cells) override; + void setLineAt(int position, bool previousWrapped) override; + private: qint64 startOfLine(int lineno); diff --git a/src/history/HistoryScrollNone.cpp b/src/history/HistoryScrollNone.cpp index 0c0721b88..d92ce364d 100644 --- a/src/history/HistoryScrollNone.cpp +++ b/src/history/HistoryScrollNone.cpp @@ -51,3 +51,11 @@ void HistoryScrollNone::addCells(const Character [], int) void HistoryScrollNone::addLine(bool) { } + +void HistoryScrollNone::setCellsVectorAt(int , const QVector &) +{ +} + +void HistoryScrollNone::setLineAt(int , bool) +{ +} \ No newline at end of file diff --git a/src/history/HistoryScrollNone.h b/src/history/HistoryScrollNone.h index 647d808e1..edb3247b6 100644 --- a/src/history/HistoryScrollNone.h +++ b/src/history/HistoryScrollNone.h @@ -32,6 +32,9 @@ public: void addCells(const Character a[], int count) override; void addLine(bool previousWrapped = false) override; + + void setCellsVectorAt(int position, const QVector &cells) override; + void setLineAt(int position, bool previousWrapped) override; }; } diff --git a/src/history/compact/CompactHistoryScroll.cpp b/src/history/compact/CompactHistoryScroll.cpp index b0a103352..a320e449d 100644 --- a/src/history/compact/CompactHistoryScroll.cpp +++ b/src/history/compact/CompactHistoryScroll.cpp @@ -91,6 +91,21 @@ void CompactHistoryScroll::setMaxNbLines(unsigned int lineCount) ////qDebug() << "set max lines to: " << _maxLineCount; } +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()); diff --git a/src/history/compact/CompactHistoryScroll.h b/src/history/compact/CompactHistoryScroll.h index 74abbbfc3..23177c103 100644 --- a/src/history/compact/CompactHistoryScroll.h +++ b/src/history/compact/CompactHistoryScroll.h @@ -33,6 +33,8 @@ public: void addLine(bool previousWrapped = false) override; void setMaxNbLines(unsigned int lineCount); + void setCellsVectorAt(int position, const TextLine &cells) override; + void setLineAt(int position, bool previousWrapped) override; private: bool hasDifferentColors(const TextLine &line) const; -- GitLab From 6bcc3064608f2c381ff337af48782b2820a73b03 Mon Sep 17 00:00:00 2001 From: Carlos Alves Date: Tue, 17 Nov 2020 09:56:55 -0300 Subject: [PATCH 10/23] Join line when sending to history Before adding new lines to history it will check if it is a warpped line and join it. --- src/Screen.cpp | 58 +++++++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/src/Screen.cpp b/src/Screen.cpp index 43f062e55..4b6cb71e9 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -1494,26 +1494,46 @@ void Screen::addHistLine() // add line to history buffer // we have to take care about scrolling, too... const int oldHistLines = _history->getLines(); - if (hasScroll()) { - - _history->addCellsVector(_screenLines[0]); - _history->addLine((_lineProperties[0] & LINE_WRAPPED) != 0); + int newHistLines = _history->getLines(); + bool beginIsTL = (_selBegin == _selTopLeft); - const int newHistLines = _history->getLines(); + if (hasScroll()) { - const bool beginIsTL = (_selBegin == _selTopLeft); + // Check if _history have 'new line' property and join lines before adding new ones + if (oldHistLines > 0 && _history->isWrappedLine(oldHistLines - 1)) { + int hist_linelen = _history->getLineLen(oldHistLines - 1); + auto *hist_line = getCharacterBuffer(hist_linelen); + _history->getCells(oldHistLines - 1, 0, hist_linelen, hist_line); - // If the history is full, increment the count - // of dropped _lines - if (newHistLines == oldHistLines) { - _droppedLines++; - } + ImageLine joinline; + for (int i = 0; i < hist_linelen; i++) { + joinline << hist_line[i]; + } + joinline << _screenLines[0]; + _history->setCellsVectorAt(oldHistLines - 1, joinline); + _history->setLineAt(oldHistLines - 1, (_lineProperties[0] & LINE_WRAPPED) != 0); + } else { + _history->addCellsVector(_screenLines[0]); + _history->addLine((_lineProperties[0] & LINE_WRAPPED) != 0); + + newHistLines = _history->getLines(); + beginIsTL = (_selBegin == _selTopLeft); + + // 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); + } - // Adjust selection for the new point of reference - if (newHistLines > oldHistLines) { - if (_selBegin != -1) { - _selTopLeft += _columns; - _selBottomRight += _columns; + // Adjust selection for the new point of reference + if (newHistLines > oldHistLines) { + if (_selBegin != -1) { + _selTopLeft += _columns; + _selBottomRight += _columns; + } } } @@ -1544,12 +1564,6 @@ 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 -- GitLab From 4fc03400d98037046f9a0d41d6ced8af6c9b82a9 Mon Sep 17 00:00:00 2001 From: Carlos Alves Date: Tue, 17 Nov 2020 10:30:30 -0300 Subject: [PATCH 11/23] Add insert to history Modify old history to insert a line into an specific position. --- src/history/HistoryScroll.h | 4 +++ src/history/HistoryScrollFile.cpp | 16 +++++++++++ src/history/HistoryScrollFile.h | 4 +++ src/history/HistoryScrollNone.cpp | 16 +++++++++++ src/history/HistoryScrollNone.h | 4 +++ src/history/compact/CompactHistoryScroll.cpp | 30 ++++++++++++++++++++ src/history/compact/CompactHistoryScroll.h | 5 ++++ 7 files changed, 79 insertions(+) diff --git a/src/history/HistoryScroll.h b/src/history/HistoryScroll.h index 4bb2ed57d..eeba4ecd3 100644 --- a/src/history/HistoryScroll.h +++ b/src/history/HistoryScroll.h @@ -48,6 +48,10 @@ public: virtual void addLine(bool previousWrapped = false) = 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, bool previousWrapped) = 0; diff --git a/src/history/HistoryScrollFile.cpp b/src/history/HistoryScrollFile.cpp index 4f9f267fc..98d541d66 100644 --- a/src/history/HistoryScrollFile.cpp +++ b/src/history/HistoryScrollFile.cpp @@ -80,6 +80,22 @@ void HistoryScrollFile::addLine(bool previousWrapped) _lineflags.add(reinterpret_cast(&flags), sizeof(char)); } +void HistoryScrollFile::insertCells(int , const Character [], int) +{ +} + +void HistoryScrollFile::removeCells(int ) +{ +} + +void HistoryScrollFile::insertCellsVector(int , const QVector &) +{ +} + +void HistoryScrollFile::setCellsAt(int , const Character [], int) +{ +} + void HistoryScrollFile::setCellsVectorAt(int , const QVector &) { } diff --git a/src/history/HistoryScrollFile.h b/src/history/HistoryScrollFile.h index f88d908d0..1bbf650c9 100644 --- a/src/history/HistoryScrollFile.h +++ b/src/history/HistoryScrollFile.h @@ -34,6 +34,10 @@ public: void addCells(const Character text[], int count) override; void addLine(bool previousWrapped = false) override; + 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, bool previousWrapped) override; diff --git a/src/history/HistoryScrollNone.cpp b/src/history/HistoryScrollNone.cpp index d92ce364d..455e7991d 100644 --- a/src/history/HistoryScrollNone.cpp +++ b/src/history/HistoryScrollNone.cpp @@ -52,6 +52,22 @@ void HistoryScrollNone::addLine(bool) { } +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 &) { } diff --git a/src/history/HistoryScrollNone.h b/src/history/HistoryScrollNone.h index edb3247b6..08be6493d 100644 --- a/src/history/HistoryScrollNone.h +++ b/src/history/HistoryScrollNone.h @@ -33,6 +33,10 @@ public: void addCells(const Character a[], int count) override; void addLine(bool previousWrapped = false) override; + 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, bool previousWrapped) override; }; diff --git a/src/history/compact/CompactHistoryScroll.cpp b/src/history/compact/CompactHistoryScroll.cpp index a320e449d..174b41140 100644 --- a/src/history/compact/CompactHistoryScroll.cpp +++ b/src/history/compact/CompactHistoryScroll.cpp @@ -91,6 +91,36 @@ 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(_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); diff --git a/src/history/compact/CompactHistoryScroll.h b/src/history/compact/CompactHistoryScroll.h index 23177c103..7a2745299 100644 --- a/src/history/compact/CompactHistoryScroll.h +++ b/src/history/compact/CompactHistoryScroll.h @@ -32,7 +32,12 @@ 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; -- GitLab From 6bf62a2ae14ce5726c6e96adbd66b0825d48e1a8 Mon Sep 17 00:00:00 2001 From: Carlos Alves Date: Tue, 17 Nov 2020 22:01:12 -0300 Subject: [PATCH 12/23] Reflow the _history Reflow the _history when the terminal resizes. Reflow when a new text goes from _screenLine to _history. --- src/Screen.cpp | 93 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 76 insertions(+), 17 deletions(-) diff --git a/src/Screen.cpp b/src/Screen.cpp index 4b6cb71e9..d902ddabc 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -376,7 +376,7 @@ void Screen::resizeImage(int new_lines, int new_columns) // First join everything. int currentPos = 0; int count_needed_lines = 0; - while (currentPos != _screenLines.count() - 1) { + while (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]); @@ -429,6 +429,45 @@ void Screen::resizeImage(int new_lines, int new_columns) } _screenLines.resize(new_lines + 1); + // Check if _history need to change + if (new_columns != _columns && _history->getLines()) { + // Join next line history + 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); + + // 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, _history->isWrappedLine(currentPos + 1)); + _history->removeCells(currentPos + 1); + } + currentPos++; + } + // Move data to next line if needed + currentPos = 0; + while (currentPos < _history->getLines() - 1) { + 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); + _history->getCells(currentPos, 0, curr_linelen, curr_line); + + _history->setCellsAt(currentPos, curr_line, new_columns); + _history->setLineAt(currentPos, true); + _history->insertCells(currentPos + 1, curr_line + new_columns, curr_linelen - new_columns); + } + currentPos++; + } + } clearSelection(); _screenLinesSize = new_lines; @@ -1495,29 +1534,46 @@ void Screen::addHistLine() // we have to take care about scrolling, too... const int oldHistLines = _history->getLines(); int newHistLines = _history->getLines(); - bool beginIsTL = (_selBegin == _selTopLeft); if (hasScroll()) { - // Check if _history have 'new line' property and join lines before adding new ones + // 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); + auto *hist_line = getCharacterBuffer(hist_linelen + _screenLines[0].count()); _history->getCells(oldHistLines - 1, 0, hist_linelen, hist_line); - ImageLine joinline; - for (int i = 0; i < hist_linelen; i++) { - joinline << hist_line[i]; + // Join the new line into the old line + memcpy(hist_line + hist_linelen, _screenLines[0].data(), _screenLines[0].count()); + 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); } - joinline << _screenLines[0]; - _history->setCellsVectorAt(oldHistLines - 1, joinline); - _history->setLineAt(oldHistLines - 1, (_lineProperties[0] & LINE_WRAPPED) != 0); } else { _history->addCellsVector(_screenLines[0]); _history->addLine((_lineProperties[0] & LINE_WRAPPED) != 0); newHistLines = _history->getLines(); - beginIsTL = (_selBegin == _selTopLeft); // If the history is full, increment the count // of dropped _lines @@ -1528,12 +1584,15 @@ void Screen::addHistLine() _escapeSequenceUrlExtractor->historyLinesRemoved(1); } - // Adjust selection for the new point of reference - if (newHistLines > oldHistLines) { - if (_selBegin != -1) { - _selTopLeft += _columns; - _selBottomRight += _columns; - } + } + + bool beginIsTL = (_selBegin == _selTopLeft); + + // Adjust selection for the new point of reference + if (newHistLines > oldHistLines) { + if (_selBegin != -1) { + _selTopLeft += _columns; + _selBottomRight += _columns; } } -- GitLab From 110b36a03abb461c7edb180789cea9d59b645c0c Mon Sep 17 00:00:00 2001 From: Carlos Alves Date: Tue, 17 Nov 2020 22:16:19 -0300 Subject: [PATCH 13/23] Missing to set property for the new line It didn't crash or bug, but to be sure it won't. --- src/Screen.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Screen.cpp b/src/Screen.cpp index d902ddabc..9f497b8bb 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -464,6 +464,7 @@ void Screen::resizeImage(int new_lines, int new_columns) _history->setCellsAt(currentPos, curr_line, new_columns); _history->setLineAt(currentPos, true); _history->insertCells(currentPos + 1, curr_line + new_columns, curr_linelen - new_columns); + _history->setLineAt(currentPos + 1, false); } currentPos++; } -- GitLab From 14601a86a55dacb201268727e1df85504ddba5f1 Mon Sep 17 00:00:00 2001 From: Carlos Alves Date: Wed, 18 Nov 2020 10:00:41 -0300 Subject: [PATCH 14/23] Reflow bug fixes - Missing properties causing reflow bug. - _screenLines[0].data() not working as I thoughit would. TODO: - Check the bug when columns around less than 25. - Keep current line and take from _history to _screenLine. - Check how and if it affects file history. --- src/Screen.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Screen.cpp b/src/Screen.cpp index 9f497b8bb..86e83c6c4 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -439,6 +439,7 @@ void Screen::resizeImage(int new_lines, int new_columns) 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); @@ -446,25 +447,26 @@ void Screen::resizeImage(int new_lines, int new_columns) // save the new_line in history and remove the next line _history->setCellsAt(currentPos, new_line, curr_linelen + next_linelen); - _history->setLineAt(currentPos, _history->isWrappedLine(currentPos + 1)); + _history->setLineAt(currentPos, new_line_property); _history->removeCells(currentPos + 1); } currentPos++; } // Move data to next line if needed currentPos = 0; - while (currentPos < _history->getLines() - 1) { + 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); _history->insertCells(currentPos + 1, curr_line + new_columns, curr_linelen - new_columns); - _history->setLineAt(currentPos + 1, false); + _history->setLineAt(currentPos + 1, curr_line_property); } currentPos++; } @@ -1545,11 +1547,13 @@ void Screen::addHistLine() _history->getCells(oldHistLines - 1, 0, hist_linelen, hist_line); // Join the new line into the old line - memcpy(hist_line + hist_linelen, _screenLines[0].data(), _screenLines[0].count()); + 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) { + if (hist_linelen > _columns) { _history->setCellsAt(oldHistLines - 1, hist_line, _columns); _history->setLineAt(oldHistLines - 1, true); _history->addCells(hist_line + _columns, hist_linelen - _columns); @@ -1584,7 +1588,6 @@ void Screen::addHistLine() // We removed a line, we need to verify if we need to remove a URL. _escapeSequenceUrlExtractor->historyLinesRemoved(1); } - } bool beginIsTL = (_selBegin == _selTopLeft); -- GitLab From a0719bbe687ad724fd00e2a56e0e9bc385be3239 Mon Sep 17 00:00:00 2001 From: Carlos Alves Date: Mon, 23 Nov 2020 16:37:15 -0300 Subject: [PATCH 15/23] Adjust minimal line and column Reflow does not work when columns < 17 and/or lines < 3. Seems to me there is a conflict of the window pixels size limit, the columns that it can paint within those limits and the mouse position when adjusting to the minimal window size. --- src/Screen.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Screen.cpp b/src/Screen.cpp index 86e83c6c4..c120a4dce 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -372,11 +372,14 @@ 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 // First join everything. int currentPos = 0; int count_needed_lines = 0; - while (currentPos < _screenLines.count() - 1) { + 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]); @@ -462,7 +465,7 @@ void Screen::resizeImage(int new_lines, int 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); _history->insertCells(currentPos + 1, curr_line + new_columns, curr_linelen - new_columns); @@ -1565,7 +1568,7 @@ void Screen::addHistLine() // 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); } @@ -1584,7 +1587,7 @@ void Screen::addHistLine() // 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); } -- GitLab From 73ed15f2155733db6c05bc4f59e607289ec2ad10 Mon Sep 17 00:00:00 2001 From: Carlos Alves Date: Sun, 29 Nov 2020 16:41:08 -0300 Subject: [PATCH 16/23] Reflow from _history to _screenLine Keep the current cursor position and have a better visual continuity with _history lines. --- src/Screen.cpp | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/src/Screen.cpp b/src/Screen.cpp index c120a4dce..6d328c7f7 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -376,6 +376,8 @@ void Screen::resizeImage(int new_lines, int new_columns) 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 + const int old_cuY = qMin(_cuY, new_lines - 1); + // First join everything. int currentPos = 0; int count_needed_lines = 0; @@ -427,14 +429,16 @@ void Screen::resizeImage(int new_lines, int new_columns) currentPos += 1; } _lineProperties.resize(new_lines + 1); - for (int i = _screenLines.count(); (i > 0) && (i < new_lines + 1); i++) { - _lineProperties[i] = LINE_DEFAULT; - } _screenLines.resize(new_lines + 1); // Check if _history need to change if (new_columns != _columns && _history->getLines()) { - // Join next line history + // Join next line _history from _screenLine + while (_history->isWrappedLine(_history->getLines() - 1)) { + addHistLine(); + scrollUp(0, 1); + _cuY--; + } currentPos = 0; while (currentPos < _history->getLines() - 1) { // if it's true, join the line with next line @@ -473,7 +477,28 @@ void Screen::resizeImage(int new_lines, int new_columns) } currentPos++; } + // Check cursor position and send from _history to _screenLines + ImageLine histLine; + histLine.reserve(1024); + while (_cuY < old_cuY && _history->getLines()) { + int histPos = _history->getLines() - 1; + int histLineLen = _history->getLineLen(histPos); + histLine.resize(histLineLen); + _history->getCells(histPos, 0, histLineLen, histLine.data()); + + _screenLines.prepend(histLine); + _lineProperties.insert(0, _history->isWrappedLine(histPos)? LINE_WRAPPED : LINE_DEFAULT); + _history->removeCells(histPos); + _cuY++; + } + } + + _lineProperties.resize(new_lines + 1); + for (int i = _screenLines.count(); (i > 0) && (i < new_lines + 1); i++) { + _lineProperties[i] = LINE_DEFAULT; } + _screenLines.resize(new_lines + 1); + clearSelection(); _screenLinesSize = new_lines; -- GitLab From 02ba277d0f74b11b033d217b8d5911a26191f5ac Mon Sep 17 00:00:00 2001 From: Carlos Alves Date: Sun, 29 Nov 2020 17:20:18 -0300 Subject: [PATCH 17/23] Reflow current cursor bug Calculate the current cursor position lines needed. --- src/Screen.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Screen.cpp b/src/Screen.cpp index 6d328c7f7..4c475abda 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -393,6 +393,7 @@ void Screen::resizeImage(int new_lines, int new_columns) count_needed_lines += _screenLines[currentPos].count() / (new_columns + 1); currentPos++; } + count_needed_lines += _screenLines[currentPos].count() / (new_columns + 1); // If it will need more lines than new_lines have, send lines to _history count_needed_lines += _cuY; -- GitLab From 51280aa438870f7be9dbc865e6cf6f67ba7970f0 Mon Sep 17 00:00:00 2001 From: Carlos Alves Date: Mon, 30 Nov 2020 10:05:10 -0300 Subject: [PATCH 18/23] Add getMaxLines to history Add the getMaxLines function to return the maximum number of lines it is alowed to compactHistoryScroll. --- src/history/HistoryScroll.h | 1 + src/history/HistoryScrollFile.cpp | 5 +++++ src/history/HistoryScrollFile.h | 1 + src/history/HistoryScrollNone.cpp | 5 +++++ src/history/HistoryScrollNone.h | 1 + src/history/compact/CompactHistoryScroll.cpp | 5 +++++ src/history/compact/CompactHistoryScroll.h | 1 + 7 files changed, 19 insertions(+) diff --git a/src/history/HistoryScroll.h b/src/history/HistoryScroll.h index eeba4ecd3..68b274ecd 100644 --- a/src/history/HistoryScroll.h +++ b/src/history/HistoryScroll.h @@ -32,6 +32,7 @@ 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; diff --git a/src/history/HistoryScrollFile.cpp b/src/history/HistoryScrollFile.cpp index 98d541d66..da35cb7c4 100644 --- a/src/history/HistoryScrollFile.cpp +++ b/src/history/HistoryScrollFile.cpp @@ -33,6 +33,11 @@ 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); diff --git a/src/history/HistoryScrollFile.h b/src/history/HistoryScrollFile.h index 1bbf650c9..003f05651 100644 --- a/src/history/HistoryScrollFile.h +++ b/src/history/HistoryScrollFile.h @@ -27,6 +27,7 @@ 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; diff --git a/src/history/HistoryScrollNone.cpp b/src/history/HistoryScrollNone.cpp index 455e7991d..4119d691b 100644 --- a/src/history/HistoryScrollNone.cpp +++ b/src/history/HistoryScrollNone.cpp @@ -30,6 +30,11 @@ int HistoryScrollNone::getLines() return 0; } +int HistoryScrollNone::getMaxLines() +{ + return 0; +} + int HistoryScrollNone::getLineLen(int) { return 0; diff --git a/src/history/HistoryScrollNone.h b/src/history/HistoryScrollNone.h index 08be6493d..05cbf765c 100644 --- a/src/history/HistoryScrollNone.h +++ b/src/history/HistoryScrollNone.h @@ -26,6 +26,7 @@ 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; diff --git a/src/history/compact/CompactHistoryScroll.cpp b/src/history/compact/CompactHistoryScroll.cpp index 174b41140..9f741f635 100644 --- a/src/history/compact/CompactHistoryScroll.cpp +++ b/src/history/compact/CompactHistoryScroll.cpp @@ -57,6 +57,11 @@ int CompactHistoryScroll::getLines() return _lines.size(); } +int CompactHistoryScroll::getMaxLines() +{ + return static_cast(_maxLineCount); +} + int CompactHistoryScroll::getLineLen(int lineNumber) { if ((lineNumber < 0) || (lineNumber >= _lines.size())) { diff --git a/src/history/compact/CompactHistoryScroll.h b/src/history/compact/CompactHistoryScroll.h index 7a2745299..5bff5dc3f 100644 --- a/src/history/compact/CompactHistoryScroll.h +++ b/src/history/compact/CompactHistoryScroll.h @@ -24,6 +24,7 @@ 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; -- GitLab From c6eed957dfce0a69292ddd89ca7b6f833e6b7384 Mon Sep 17 00:00:00 2001 From: Carlos Alves Date: Mon, 30 Nov 2020 10:14:43 -0300 Subject: [PATCH 19/23] Fix _history limits and increase performance There was a bug on _history limits, now it is fixed. Increase the "_screenLines to _history when needed" performance --- src/Screen.cpp | 44 +++++++++++++++++++------------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/src/Screen.cpp b/src/Screen.cpp index 4c475abda..a17c6ae9e 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -380,7 +380,6 @@ void Screen::resizeImage(int new_lines, int new_columns) // First join everything. int currentPos = 0; - int count_needed_lines = 0; 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) { @@ -390,27 +389,8 @@ void Screen::resizeImage(int new_lines, int new_columns) _cuY--; continue; } - count_needed_lines += _screenLines[currentPos].count() / (new_columns + 1); currentPos++; } - count_needed_lines += _screenLines[currentPos].count() / (new_columns + 1); - - // If it will need more lines than new_lines have, send lines to _history - count_needed_lines += _cuY; - if (count_needed_lines > new_lines - 1) { - _lineProperties.resize(_lines + 1); - for (int i = _screenLines.count(); (i > 0) && (i < new_lines + 1); i++) { - _lineProperties[i] = LINE_DEFAULT; - } - _screenLines.resize(_lines + 1); - // attempt to preserve focus and _lines - _bottomMargin = _lines - 1; //FIXME: margin lost - for (int i = 0; i < count_needed_lines - (new_lines - 1); i++) { - addHistLine(); - scrollUp(0, 1); - _cuY--; - } - } // Then move the data to lines below. currentPos = 0; @@ -429,15 +409,23 @@ void Screen::resizeImage(int new_lines, int new_columns) } currentPos += 1; } + // Check if it need to move from _screenLine to _history + while (_cuY > new_lines - 1) { + addHistLine(); + _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 _history from _screenLine + // Join next line from _screenLine to _history while (_history->isWrappedLine(_history->getLines() - 1)) { addHistLine(); - scrollUp(0, 1); + _screenLines.pop_front(); + _lineProperties.remove(0); _cuY--; } currentPos = 0; @@ -457,6 +445,7 @@ void Screen::resizeImage(int new_lines, int new_columns) _history->setCellsAt(currentPos, new_line, curr_linelen + next_linelen); _history->setLineAt(currentPos, new_line_property); _history->removeCells(currentPos + 1); + continue; } currentPos++; } @@ -473,8 +462,13 @@ void Screen::resizeImage(int new_lines, int new_columns) _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++; } @@ -484,11 +478,12 @@ void Screen::resizeImage(int new_lines, int new_columns) while (_cuY < old_cuY && _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.prepend(histLine); - _lineProperties.insert(0, _history->isWrappedLine(histPos)? LINE_WRAPPED : LINE_DEFAULT); + _screenLines.insert(0, histLine); + _lineProperties.insert(0, isWrapped); _history->removeCells(histPos); _cuY++; } @@ -1568,7 +1563,6 @@ void Screen::addHistLine() 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); -- GitLab From a9d5945500783c9d295a6c143f737ef60826ac77 Mon Sep 17 00:00:00 2001 From: Carlos Alves Date: Tue, 1 Dec 2020 14:15:58 -0300 Subject: [PATCH 20/23] Ident and wait --- src/Screen.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Screen.cpp b/src/Screen.cpp index a17c6ae9e..54b0fc99d 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -463,8 +463,8 @@ void Screen::resizeImage(int new_lines, int new_columns) _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); + _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); -- GitLab From 4e10daa261b4a7787b57b1ad51a6a8dbb75aae3f Mon Sep 17 00:00:00 2001 From: Carlos Alves Date: Wed, 2 Dec 2020 09:33:45 -0300 Subject: [PATCH 21/23] Fix visual glitches and performance Some visual glitches with scroll position while changing screen size. --- src/Screen.cpp | 113 ++++++++++++++---------- src/Screen.h | 6 ++ src/ScreenWindow.cpp | 11 +++ src/ScreenWindow.h | 2 + src/terminalDisplay/TerminalDisplay.cpp | 3 + 5 files changed, 87 insertions(+), 48 deletions(-) diff --git a/src/Screen.cpp b/src/Screen.cpp index 54b0fc99d..f2fc7fe3b 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -53,6 +53,8 @@ Screen::Screen(int lines, int columns): _scrolledLines(0), _lastScrolledRegion(QRect()), _droppedLines(0), + _oldTotalLines(0), + _isResize(false), _lineProperties(QVarLengthArray()), _history(new HistoryScrollNone()), _cuX(0), @@ -367,6 +369,20 @@ 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)) { @@ -376,42 +392,45 @@ void Screen::resizeImage(int new_lines, int new_columns) 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 - const int old_cuY = qMin(_cuY, new_lines - 1); + _oldTotalLines = getLines() + getHistLines(); + _isResize = true; // First join everything. int currentPos = 0; - 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; + 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++; } - 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; + // 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; } - currentPos += 1; } // Check if it need to move from _screenLine to _history while (_cuY > new_lines - 1) { - addHistLine(); + _history->addCellsVector(_screenLines[0]); + _history->addLine((_lineProperties[0] & LINE_WRAPPED) != 0); _screenLines.pop_front(); _lineProperties.remove(0); _cuY--; @@ -423,7 +442,8 @@ void Screen::resizeImage(int new_lines, int new_columns) if (new_columns != _columns && _history->getLines()) { // Join next line from _screenLine to _history while (_history->isWrappedLine(_history->getLines() - 1)) { - addHistLine(); + _history->addCellsVector(_screenLines[0]); + _history->addLine((_lineProperties[0] & LINE_WRAPPED) != 0); _screenLines.pop_front(); _lineProperties.remove(0); _cuY--; @@ -472,21 +492,21 @@ void Screen::resizeImage(int new_lines, int new_columns) } currentPos++; } - // Check cursor position and send from _history to _screenLines - ImageLine histLine; - histLine.reserve(1024); - while (_cuY < old_cuY && _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++; - } + } + + // 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++; } _lineProperties.resize(new_lines + 1); @@ -495,17 +515,14 @@ void Screen::resizeImage(int new_lines, int new_columns) } _screenLines.resize(new_lines + 1); - clearSelection(); _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. - _topMargin = 0; - _bottomMargin = _lines - 1; + setDefaultMargins(); initTabStops(); clearSelection(); } diff --git a/src/Screen.h b/src/Screen.h index 0a68d51b2..cf5237111 100644 --- a/src/Screen.h +++ b/src/Screen.h @@ -588,6 +588,9 @@ 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, @@ -661,6 +664,9 @@ private: int _droppedLines; + int _oldTotalLines; + bool _isResize; + QVarLengthArray _lineProperties; // history buffer --------------- diff --git a/src/ScreenWindow.cpp b/src/ScreenWindow.cpp index e27ceaa7b..5aa8f1c82 100644 --- a/src/ScreenWindow.cpp +++ b/src/ScreenWindow.cpp @@ -294,6 +294,17 @@ QRect ScreenWindow::scrollRegion() const 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 diff --git a/src/ScreenWindow.h b/src/ScreenWindow.h index 29ffc3669..445cd50c6 100644 --- a/src/ScreenWindow.h +++ b/src/ScreenWindow.h @@ -218,6 +218,8 @@ 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. diff --git a/src/terminalDisplay/TerminalDisplay.cpp b/src/terminalDisplay/TerminalDisplay.cpp index 7381125df..39d1eaa7d 100644 --- a/src/terminalDisplay/TerminalDisplay.cpp +++ b/src/terminalDisplay/TerminalDisplay.cpp @@ -497,6 +497,9 @@ 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 -- GitLab From 6d9c1d27a1b33c6837ff2abe9fa1e5c7c9a90df7 Mon Sep 17 00:00:00 2001 From: Carlos Alves Date: Thu, 3 Dec 2020 10:45:05 -0300 Subject: [PATCH 22/23] Fixed limits and Urls bugs - Columns and lines limits fixed. - Verify if it's needed to remove an URL after remove of _history lines. --- src/Screen.cpp | 42 ++++++++++++++++++++++++++++-------------- src/Screen.h | 4 ++++ 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/Screen.cpp b/src/Screen.cpp index f2fc7fe3b..3719089ca 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -388,10 +388,8 @@ 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 + // Adjust scroll position, and fix glitches _oldTotalLines = getLines() + getHistLines(); _isResize = true; @@ -429,11 +427,7 @@ void Screen::resizeImage(int new_lines, int new_columns) } // 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--; + fastAddHistLine(); } _lineProperties.resize(new_lines + 1); _screenLines.resize(new_lines + 1); @@ -442,13 +436,10 @@ void Screen::resizeImage(int new_lines, int new_columns) 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--; + fastAddHistLine(); } currentPos = 0; + // Join everything in _history while (currentPos < _history->getLines() - 1) { // if it's true, join the line with next line if (_history->isWrappedLine(currentPos)) { @@ -469,13 +460,14 @@ void Screen::resizeImage(int new_lines, int new_columns) } currentPos++; } - // Move data to next line if needed + // Now 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) { + bool removeLine = _history->getLines() == _history->getMaxLines(); auto *curr_line = getCharacterBuffer(curr_linelen); bool curr_line_property = _history->isWrappedLine(currentPos); _history->getCells(currentPos, 0, curr_linelen, curr_line); @@ -489,6 +481,11 @@ void Screen::resizeImage(int new_lines, int new_columns) _history->addCells(curr_line + new_columns, curr_linelen - new_columns); _history->addLine(curr_line_property); } + // If _history size > max history size it will drop a line from _history. + // We need to verify if we need to remove a URL. + if (removeLine) { + _escapeSequenceUrlExtractor->historyLinesRemoved(1); + } } currentPos++; } @@ -1572,6 +1569,23 @@ void Screen::writeLinesToStream(TerminalCharacterDecoder* decoder, int fromLine, writeToStream(decoder, loc(0, fromLine), loc(_columns - 1, toLine), PreserveLineBreaks); } +void Screen::fastAddHistLine() +{ + bool removeLine = _history->getLines() == _history->getMaxLines(); + _history->addCellsVector(_screenLines[0]); + _history->addLine((_lineProperties[0] & LINE_WRAPPED) != 0); + + // If _history size > max history size it will drop a line from _history. + // We need to verify if we need to remove a URL. + if (removeLine) { + _escapeSequenceUrlExtractor->historyLinesRemoved(1); + } + + _screenLines.pop_front(); + _lineProperties.remove(0); + _cuY--; +} + void Screen::addHistLine() { // add line to history buffer diff --git a/src/Screen.h b/src/Screen.h index cf5237111..a794f0bdd 100644 --- a/src/Screen.h +++ b/src/Screen.h @@ -588,7 +588,9 @@ public: static const Character DefaultChar; + // Return the total number of lines before resize (fix scroll glitch) int getOldTotalLines(); + // Return if it was a resize signal (fix scroll glitch) bool isResize(); private: @@ -626,6 +628,8 @@ private: TerminalDisplay *_currentTerminalDisplay; void addHistLine(); + // add lines from _screen to _history and remove from _screen the added lines (used to resize lines and columns) + void fastAddHistLine(); void initTabStops(); -- GitLab From 876a1752a168ea2fc607c75091fcc6257f79eab5 Mon Sep 17 00:00:00 2001 From: Carlos Alves Date: Mon, 7 Dec 2020 09:46:18 -0300 Subject: [PATCH 23/23] Reflow when executing an app The reflow need to guess where the cursor line is when the user change the konsole window size while executing an app. --- src/Screen.cpp | 103 ++++++++++++++++++++++++++++------------- src/Screen.h | 8 +++- src/Vt102Emulation.cpp | 4 +- src/Vt102Emulation.h | 31 ++++++------- 4 files changed, 94 insertions(+), 52 deletions(-) diff --git a/src/Screen.cpp b/src/Screen.cpp index 3719089ca..62d2ee1df 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -383,6 +383,36 @@ bool Screen::isResize() return _isResize; } +// Not to production auxiliar functions to show what is written in screen or history +void toDebug(const Character s[], int count, bool wrapped = false) { + QString out; + for (int i = 0; i < count; i++) { + out += s[i].character; + } + qDebug() << out << (wrapped? " wrapped" : ""); +} +void toDebug(const QVector &s, bool wrapped = false) { + toDebug(s.data(), s.size(), wrapped); +} +///// + +int Screen::getCursorLine() +{ + if (_currentModes[MODE_AppScreen] == 1) { + return _savedState.cursorLine; + } + return _cuY; +} + +void Screen::setCursorLine(int newLine) +{ + if (_currentModes[MODE_AppScreen] == 1) { + _savedState.cursorLine = newLine; + } else { + _cuY = newLine; + } +} + void Screen::resizeImage(int new_lines, int new_columns) { if ((new_lines == _lines) && (new_columns == _columns)) { @@ -393,41 +423,47 @@ void Screen::resizeImage(int new_lines, int new_columns) _oldTotalLines = getLines() + getHistLines(); _isResize = true; + int cursorLine = getCursorLine(); + const int oldCursorLine = (cursorLine == _lines -1)? new_lines - 1 : cursorLine; + // 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++; + while (currentPos < cursorLine && 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); + cursorLine--; + continue; } - // 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; + currentPos++; + } + // Then move the data to lines below. + currentPos = 0; + while (currentPos < cursorLine && currentPos < _screenLines.count()) { + // Ignore whitespaces at the end of the line + int lineSize = _screenLines[currentPos].size(); + while (lineSize > 0 && QChar(_screenLines[currentPos][lineSize - 1].character).isSpace()) { + lineSize--; + } + const bool shouldCopy = lineSize > new_columns; + + // Copy from the current line, to the next one. + if (shouldCopy) { + 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; + cursorLine++; } + currentPos += 1; } // Check if it need to move from _screenLine to _history - while (_cuY > new_lines - 1) { + while (cursorLine > new_lines - 1) { fastAddHistLine(); + cursorLine--; } _lineProperties.resize(new_lines + 1); _screenLines.resize(new_lines + 1); @@ -437,6 +473,7 @@ void Screen::resizeImage(int new_lines, int new_columns) // Join next line from _screenLine to _history while (_history->isWrappedLine(_history->getLines() - 1)) { fastAddHistLine(); + cursorLine--; } currentPos = 0; // Join everything in _history @@ -494,7 +531,7 @@ void Screen::resizeImage(int new_lines, int new_columns) // Check cursor position and send from _history to _screenLines ImageLine histLine; histLine.reserve(1024); - while (_cuY < new_lines - 1 && _history->getLines()) { + while (cursorLine < oldCursorLine && _history->getLines()) { int histPos = _history->getLines() - 1; int histLineLen = _history->getLineLen(histPos); int isWrapped = _history->isWrappedLine(histPos)? LINE_WRAPPED : LINE_DEFAULT; @@ -503,7 +540,7 @@ void Screen::resizeImage(int new_lines, int new_columns) _screenLines.insert(0, histLine); _lineProperties.insert(0, isWrapped); _history->removeCells(histPos); - _cuY++; + cursorLine++; } _lineProperties.resize(new_lines + 1); @@ -516,7 +553,8 @@ void Screen::resizeImage(int new_lines, int new_columns) _lines = new_lines; _columns = new_columns; _cuX = qMin(_cuX, _columns - 1); - _cuY = qMin(_cuY, _lines - 1); + cursorLine = qBound(0, cursorLine, _lines - 1); + setCursorLine(cursorLine); // FIXME: try to keep values, evtl. setDefaultMargins(); @@ -1571,7 +1609,7 @@ void Screen::writeLinesToStream(TerminalCharacterDecoder* decoder, int fromLine, void Screen::fastAddHistLine() { - bool removeLine = _history->getLines() == _history->getMaxLines(); + const bool removeLine = _history->getLines() == _history->getMaxLines(); _history->addCellsVector(_screenLines[0]); _history->addLine((_lineProperties[0] & LINE_WRAPPED) != 0); @@ -1583,7 +1621,6 @@ void Screen::fastAddHistLine() _screenLines.pop_front(); _lineProperties.remove(0); - _cuY--; } void Screen::addHistLine() diff --git a/src/Screen.h b/src/Screen.h index a794f0bdd..28af05005 100644 --- a/src/Screen.h +++ b/src/Screen.h @@ -25,7 +25,8 @@ #define MODE_Screen 3 #define MODE_Cursor 4 #define MODE_NewLine 5 -#define MODES_SCREEN 6 +#define MODE_AppScreen 6 +#define MODES_SCREEN 7 namespace Konsole { class TerminalCharacterDecoder; @@ -653,6 +654,11 @@ private: // should be as minimal as possible static Character *getCharacterBuffer(const int size); + // Get the cursor line after checking if its app mode or not + int getCursorLine(); + // Set the cursor line after checking if its app mode or not + void setCursorLine (int newLine); + int getLineLength(const int line) const; // screen image ---------------- diff --git a/src/Vt102Emulation.cpp b/src/Vt102Emulation.cpp index e048f8ed2..2cdbc6d32 100644 --- a/src/Vt102Emulation.cpp +++ b/src/Vt102Emulation.cpp @@ -1464,8 +1464,8 @@ void Vt102Emulation::resetMode(int m) setScreen(0); break; } - // FIXME: Currently this has a redundant condition as MODES_SCREEN is 6 - // and MODE_NewLine is 5 + // FIXME: Currently this has a redundant condition as MODES_SCREEN is 7 + // MODE_AppScreen is 6 and MODE_NewLine is 5 if (m < MODES_SCREEN || m == MODE_NewLine) { _screen[0]->resetMode(m); _screen[1]->resetMode(m); diff --git a/src/Vt102Emulation.h b/src/Vt102Emulation.h index ee837752b..23ac93ec8 100644 --- a/src/Vt102Emulation.h +++ b/src/Vt102Emulation.h @@ -20,22 +20,21 @@ class QTimer; class QKeyEvent; -#define MODE_AppScreen (MODES_SCREEN+0) // Mode #1 -#define MODE_AppCuKeys (MODES_SCREEN+1) // Application cursor keys (DECCKM) -#define MODE_AppKeyPad (MODES_SCREEN+2) // -#define MODE_Mouse1000 (MODES_SCREEN+3) // Send mouse X,Y position on press and release -#define MODE_Mouse1001 (MODES_SCREEN+4) // Use Hilight mouse tracking -#define MODE_Mouse1002 (MODES_SCREEN+5) // Use cell motion mouse tracking -#define MODE_Mouse1003 (MODES_SCREEN+6) // Use all motion mouse tracking -#define MODE_Mouse1005 (MODES_SCREEN+7) // Xterm-style extended coordinates -#define MODE_Mouse1006 (MODES_SCREEN+8) // 2nd Xterm-style extended coordinates -#define MODE_Mouse1007 (MODES_SCREEN+9) // XTerm Alternate Scroll mode; also check AlternateScrolling profile property -#define MODE_Mouse1015 (MODES_SCREEN+10) // Urxvt-style extended coordinates -#define MODE_Ansi (MODES_SCREEN+11) // Use US Ascii for character sets G0-G3 (DECANM) -#define MODE_132Columns (MODES_SCREEN+12) // 80 <-> 132 column mode switch (DECCOLM) -#define MODE_Allow132Columns (MODES_SCREEN+13) // Allow DECCOLM mode -#define MODE_BracketedPaste (MODES_SCREEN+14) // Xterm-style bracketed paste mode -#define MODE_total (MODES_SCREEN+15) +#define MODE_AppCuKeys (MODES_SCREEN+0) // Application cursor keys (DECCKM) +#define MODE_AppKeyPad (MODES_SCREEN+1) // +#define MODE_Mouse1000 (MODES_SCREEN+2) // Send mouse X,Y position on press and release +#define MODE_Mouse1001 (MODES_SCREEN+3) // Use Hilight mouse tracking +#define MODE_Mouse1002 (MODES_SCREEN+4) // Use cell motion mouse tracking +#define MODE_Mouse1003 (MODES_SCREEN+5) // Use all motion mouse tracking +#define MODE_Mouse1005 (MODES_SCREEN+6) // Xterm-style extended coordinates +#define MODE_Mouse1006 (MODES_SCREEN+7) // 2nd Xterm-style extended coordinates +#define MODE_Mouse1007 (MODES_SCREEN+8) // XTerm Alternate Scroll mode; also check AlternateScrolling profile property +#define MODE_Mouse1015 (MODES_SCREEN+9) // Urxvt-style extended coordinates +#define MODE_Ansi (MODES_SCREEN+10) // Use US Ascii for character sets G0-G3 (DECANM) +#define MODE_132Columns (MODES_SCREEN+11) // 80 <-> 132 column mode switch (DECCOLM) +#define MODE_Allow132Columns (MODES_SCREEN+12) // Allow DECCOLM mode +#define MODE_BracketedPaste (MODES_SCREEN+13) // Xterm-style bracketed paste mode +#define MODE_total (MODES_SCREEN+14) namespace Konsole { extern unsigned short vt100_graphics[32]; -- GitLab