File indexing completed on 2024-05-19 05:54:10
0001 /* 0002 SPDX-FileCopyrightText: 2021-2021 Carlos Alves <cbcalves@gmail.com> 0003 SPDX-FileCopyrightText: 1997, 1998 Lars Doelle <lars.doelle@on-line.de> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 // Own 0009 #include "CompactHistoryScroll.h" 0010 #include "CompactHistoryType.h" 0011 0012 using namespace Konsole; 0013 0014 CompactHistoryScroll::CompactHistoryScroll(const unsigned int maxLineCount) 0015 : HistoryScroll(new CompactHistoryType(maxLineCount)) 0016 , _maxLineCount(0) 0017 { 0018 setMaxNbLines(maxLineCount); 0019 } 0020 0021 void CompactHistoryScroll::removeLinesFromTop(size_t lines) 0022 { 0023 if (_lineDatas.size() > 1) { 0024 const unsigned int removing = _lineDatas.at(lines - 1).index; 0025 _lineDatas.erase(_lineDatas.begin(), _lineDatas.begin() + lines); 0026 0027 _cells.erase(_cells.begin(), _cells.begin() + (removing - _indexBias)); 0028 _indexBias = removing; 0029 } else { 0030 _lineDatas.clear(); 0031 _cells.clear(); 0032 } 0033 } 0034 0035 void CompactHistoryScroll::addCells(const Character a[], const int count) 0036 { 0037 _cells.insert(_cells.end(), a, a + count); 0038 0039 // store the (biased) start of next line + default flag 0040 // the flag is later updated when addLine is called 0041 _lineDatas.push_back({static_cast<unsigned int>(_cells.size() + _indexBias), LineProperty()}); 0042 0043 if (_lineDatas.size() > _maxLineCount + 5) { 0044 removeLinesFromTop(5); 0045 } 0046 } 0047 0048 void CompactHistoryScroll::addCellsMove(Character characters[], const int count) 0049 { 0050 std::move(characters, characters + count, std::back_inserter(_cells)); 0051 0052 // store the (biased) start of next line + default flag 0053 // the flag is later updated when addLine is called 0054 _lineDatas.push_back({static_cast<unsigned int>(_cells.size() + _indexBias), LineProperty()}); 0055 0056 if (_lineDatas.size() > _maxLineCount + 5) { 0057 removeLinesFromTop(5); 0058 } 0059 } 0060 0061 void CompactHistoryScroll::addLine(const LineProperty lineProperty) 0062 { 0063 auto &flag = _lineDatas.back().flag; 0064 flag = lineProperty; 0065 } 0066 0067 int CompactHistoryScroll::getLines() const 0068 { 0069 return _lineDatas.size(); 0070 } 0071 0072 int CompactHistoryScroll::getMaxLines() const 0073 { 0074 return _maxLineCount; 0075 } 0076 0077 int CompactHistoryScroll::getLineLen(int lineNumber) const 0078 { 0079 if (size_t(lineNumber) >= _lineDatas.size()) { 0080 return 0; 0081 } 0082 0083 return lineLen(lineNumber); 0084 } 0085 0086 void CompactHistoryScroll::getCells(const int lineNumber, const int startColumn, const int count, Character buffer[]) const 0087 { 0088 if (count == 0) { 0089 return; 0090 } 0091 Q_ASSERT((size_t)lineNumber < _lineDatas.size()); 0092 0093 Q_ASSERT(startColumn >= 0); 0094 Q_ASSERT(startColumn <= lineLen(lineNumber) - count); 0095 0096 auto startCopy = _cells.begin() + startOfLine(lineNumber) + startColumn; 0097 auto endCopy = startCopy + count; 0098 std::copy(startCopy, endCopy, buffer); 0099 } 0100 0101 void CompactHistoryScroll::setMaxNbLines(const int lineCount) 0102 { 0103 Q_ASSERT(lineCount >= 0); 0104 _maxLineCount = lineCount; 0105 0106 if (_lineDatas.size() > _maxLineCount) { 0107 int linesToRemove = _lineDatas.size() - _maxLineCount; 0108 removeLinesFromTop(linesToRemove); 0109 } 0110 } 0111 0112 void CompactHistoryScroll::removeCells() 0113 { 0114 if (_lineDatas.size() > 1) { 0115 /** Here we remove a line from the "end" of the buffers **/ 0116 0117 // Get last line start 0118 int lastLineStart = startOfLine(_lineDatas.size() - 1); 0119 0120 // remove info about this line 0121 _lineDatas.pop_back(); 0122 0123 // remove the actual line content 0124 _cells.erase(_cells.begin() + lastLineStart, _cells.end()); 0125 } else { 0126 _cells.clear(); 0127 _lineDatas.clear(); 0128 } 0129 } 0130 0131 bool CompactHistoryScroll::isWrappedLine(const int lineNumber) const 0132 { 0133 Q_ASSERT((size_t)lineNumber < _lineDatas.size()); 0134 return (_lineDatas.at(lineNumber).flag.flags.f.wrapped) > 0; 0135 } 0136 0137 LineProperty CompactHistoryScroll::getLineProperty(const int lineNumber) const 0138 { 0139 Q_ASSERT((size_t)lineNumber < _lineDatas.size()); 0140 return _lineDatas.at(lineNumber).flag; 0141 } 0142 0143 void CompactHistoryScroll::setLineProperty(const int lineNumber, LineProperty prop) 0144 { 0145 Q_ASSERT((size_t)lineNumber < _lineDatas.size()); 0146 _lineDatas.at(lineNumber).flag = prop; 0147 } 0148 0149 int CompactHistoryScroll::reflowLines(const int columns, std::map<int, int> *deltas) 0150 { 0151 std::vector<LineData> newLineData; 0152 0153 auto reflowLineLen = [](int start, int end) { 0154 return end - start; 0155 }; 0156 auto setNewLine = [](std::vector<LineData> &change, unsigned int index, LineProperty flag) { 0157 change.push_back({index, flag}); 0158 }; 0159 0160 int currentPos = 0; 0161 int newPos = 0; 0162 int delta = 0; 0163 while (currentPos < getLines()) { 0164 int startLine = startOfLine(currentPos); 0165 int endLine = startOfLine(currentPos + 1); 0166 LineProperty lineProperty = getLineProperty(currentPos); 0167 0168 // Join the lines if they are wrapped 0169 while (currentPos < getLines() - 1 && isWrappedLine(currentPos)) { 0170 currentPos++; 0171 endLine = startOfLine(currentPos + 1); 0172 } 0173 0174 // Now reflow the lines 0175 while (reflowLineLen(startLine, endLine) > columns && !(lineProperty.flags.f.doubleheight_bottom | lineProperty.flags.f.doubleheight_top)) { 0176 startLine += columns; 0177 lineProperty.flags.f.wrapped = 1; 0178 setNewLine(newLineData, startLine + _indexBias, lineProperty); 0179 lineProperty.resetStarts(); 0180 newPos++; 0181 } 0182 lineProperty.flags.f.wrapped = 0; 0183 setNewLine(newLineData, endLine + _indexBias, lineProperty); 0184 currentPos++; 0185 newPos++; 0186 if (deltas && delta != newPos - currentPos) { 0187 (*deltas)[currentPos - getLines()] = newPos - currentPos - delta; 0188 delta = newPos - currentPos; 0189 } 0190 } 0191 _lineDatas = std::move(newLineData); 0192 0193 int deletedLines = 0; 0194 size_t totalLines = getLines(); 0195 if (totalLines > _maxLineCount) { 0196 deletedLines = totalLines - _maxLineCount; 0197 removeLinesFromTop(deletedLines); 0198 } 0199 0200 return deletedLines; 0201 }