CompactHistoryScroll.cpp 6.55 KB
Newer Older
1
/*
2
    SPDX-FileCopyrightText: 1997, 1998 Lars Doelle <lars.doelle@on-line.de>
3

4
    SPDX-License-Identifier: GPL-2.0-or-later
5
6
7
8
9
*/

// Own
#include "CompactHistoryScroll.h"

10
#include "CompactHistoryType.h"
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

using namespace Konsole;

CompactHistoryScroll::CompactHistoryScroll(unsigned int maxLineCount) :
    HistoryScroll(new CompactHistoryType(maxLineCount)),
    _lines(),
    _blockList(),
    _maxLineCount(0)
{
    ////qDebug() << "scroll of length " << maxLineCount << " created";
    setMaxNbLines(maxLineCount);
}

CompactHistoryScroll::~CompactHistoryScroll()
{
    _lines.clear();
}

void CompactHistoryScroll::addCellsVector(const TextLine &cells)
{
31
    auto line = std::unique_ptr<CompactHistoryLine>(new (_blockList) CompactHistoryLine(cells, _blockList));
Carlos Alves's avatar
Carlos Alves committed
32

33
    _lines.push_back(std::move(line));
34

35
36
    if (_lines.size() > static_cast<size_t>(_maxLineCount)) {
        _lines.pop_front();
37
38
39
40
41
42
43
44
45
46
    }
}

void CompactHistoryScroll::addCells(const Character a[], int count)
{
    TextLine newLine(count);
    std::copy(a, a + count, newLine.begin());
    addCellsVector(newLine);
}

47
void CompactHistoryScroll::addLine(LineProperty lineProperty)
48
{
49
    auto line = _lines.back().get();
50
    ////qDebug() << "last line at address " << line;
51
    line->setLineProperty(lineProperty);
52
53
54
55
}

int CompactHistoryScroll::getLines()
{
Carlos Alves's avatar
Carlos Alves committed
56
    return static_cast<int>(_lines.size());
57
58
}

59
60
61
62
63
int CompactHistoryScroll::getMaxLines()
{
    return static_cast<int>(_maxLineCount);
}

64
65
int CompactHistoryScroll::getLineLen(int lineNumber)
{
Carlos Alves's avatar
Carlos Alves committed
66
    if ((lineNumber < 0) || (static_cast<size_t>(lineNumber) >= _lines.size())) {
67
68
69
70
        //qDebug() << "requested line invalid: 0 < " << lineNumber << " < " <<_lines.size();
        //Q_ASSERT(lineNumber >= 0 && lineNumber < _lines.size());
        return 0;
    }
71
    auto line = _lines[lineNumber].get();
72
73
74
75
76
77
78
79
80
    ////qDebug() << "request for line at address " << line;
    return line->getLength();
}

void CompactHistoryScroll::getCells(int lineNumber, int startColumn, int count, Character buffer[])
{
    if (count == 0) {
        return;
    }
Carlos Alves's avatar
Carlos Alves committed
81
    Q_ASSERT(static_cast<size_t>(lineNumber) < _lines.size());
82
    auto line = _lines[lineNumber].get();
83
84
85
86
87
88
89
90
91
    Q_ASSERT(startColumn >= 0);
    Q_ASSERT(static_cast<unsigned int>(startColumn) <= line->getLength() - count);
    line->getCharacters(buffer, count, startColumn);
}

void CompactHistoryScroll::setMaxNbLines(unsigned int lineCount)
{
    _maxLineCount = lineCount;

92
93
    while (_lines.size() > static_cast<size_t>(lineCount)) {
        _lines.pop_front();
94
95
96
97
    }
    ////qDebug() << "set max lines to: " << _maxLineCount;
}

98
99
void CompactHistoryScroll::insertCellsVector(int position, const TextLine &cells)
{
100
    auto line = std::unique_ptr<CompactHistoryLine>(new (_blockList) CompactHistoryLine(cells, _blockList));
101

102
    _lines.insert(_lines.begin() + position, std::move(line));
103

104
105
    if (_lines.size() > static_cast<size_t>(_maxLineCount)) {
        _lines.pop_front();
106
107
108
109
110
111
112
113
114
115
116
117
    }
}

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)
{
118
    _lines.erase(_lines.begin() + position);
119
120
121
122
123
124
125
126
127
128
129
}

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)
{
130
    _lines[position]->setCharacters(cells);
131
132
}

133
void CompactHistoryScroll::setLineAt(int position, LineProperty lineProperty)
134
{
135
    auto line = _lines.at(position).get();
136

137
    line->setLineProperty(lineProperty);
138
139
}

140
141
bool CompactHistoryScroll::isWrappedLine(int lineNumber)
{
Carlos Alves's avatar
Carlos Alves committed
142
    Q_ASSERT(static_cast<size_t>(lineNumber) < _lines.size());
143
144
    return _lines[lineNumber]->isWrapped();
}
Carlos Alves's avatar
Carlos Alves committed
145

146
147
148
149
150
151
LineProperty CompactHistoryScroll::getLineProperty(int lineNumber)
{
    Q_ASSERT(static_cast<size_t>(lineNumber) < _lines.size());
    return _lines[lineNumber]->getLineProperty();
}

Carlos Alves's avatar
Carlos Alves committed
152
153
154
155
156
157
158
159
160
161
162
int CompactHistoryScroll::reflowLines(int columns)
{
    auto getCharacterBuffer = [](int size) {
        static QVector<Character> characterBuffer(1024);
        if (characterBuffer.count() < size) {
            characterBuffer.resize(size);
        }

        return characterBuffer.data();
    };

Carlos Alves's avatar
Carlos Alves committed
163
    // Join the line and move the data to next line if needed
Carlos Alves's avatar
Carlos Alves committed
164
165
    int removedLines = 0;
    int currentPos = 0;
Carlos Alves's avatar
Carlos Alves committed
166
167
168
    if (getLines() > MAX_REFLOW_LINES) {
        currentPos = getLines() - MAX_REFLOW_LINES;
    }
Carlos Alves's avatar
Carlos Alves committed
169
170
171
172
173
174
    while (currentPos < getLines()) {
        int curr_linelen = getLineLen(currentPos);
        // Join wrapped line in current history position
        if (isWrappedLine(currentPos) && currentPos < getLines() - 1) {
            int next_linelen = getLineLen(currentPos + 1);
            auto *new_line = getCharacterBuffer(curr_linelen + next_linelen);
175
            LineProperty new_line_property = getLineProperty(currentPos + 1);
Carlos Alves's avatar
Carlos Alves committed
176
177
178
179
180
181
182
183
184
185
186
187
188

            // Join the lines
            getCells(currentPos, 0, curr_linelen, new_line);
            getCells(currentPos + 1, 0, next_linelen, new_line + curr_linelen);

            // save the new_line in history and remove the next line
            setCellsAt(currentPos, new_line, curr_linelen + next_linelen);
            setLineAt(currentPos, new_line_property);
            removeCells(currentPos + 1);
            continue;
        }

        // if the current line > columns it will need a new line
189
        if (curr_linelen > columns && !(getLineProperty(currentPos) & (LINE_DOUBLEHEIGHT_BOTTOM | LINE_DOUBLEHEIGHT_TOP))) {
Carlos Alves's avatar
Carlos Alves committed
190
191
            bool removeLine = getLines() == getMaxLines();
            auto *curr_line = getCharacterBuffer(curr_linelen);
192
            LineProperty curr_line_property = getLineProperty(currentPos);
Carlos Alves's avatar
Carlos Alves committed
193
194
195
            getCells(currentPos, 0, curr_linelen, curr_line);

            setCellsAt(currentPos, curr_line, columns);
196
            setLineAt(currentPos, curr_line_property | LINE_WRAPPED);
Carlos Alves's avatar
Carlos Alves committed
197
198
199
200
201
202
203
            if (currentPos < getMaxLines() - 1) {
                int correctPosition = (getLines() == getMaxLines()) ? 0 : 1;
                insertCells(currentPos + 1, curr_line + columns, curr_linelen - columns);
                setLineAt(currentPos + correctPosition, curr_line_property);
            } else {
                addCells(curr_line + columns, curr_linelen - columns);
                addLine(curr_line_property);
Carlos Alves's avatar
Carlos Alves committed
204
                currentPos--;
Carlos Alves's avatar
Carlos Alves committed
205
206
207
208
209
210
211
212
            }
            if (removeLine) {
                removedLines += 1;
            }
        }
        currentPos++;
    }
    return removedLines;
Kurt Hindenburg's avatar
Kurt Hindenburg committed
213
214
}