perf(qmltermwidget): skip the tokenizer for plain text and move screen lines on scroll

main
reionwong 3 weeks ago
parent 88edbaadc5
commit 9890608d19

@ -253,13 +253,26 @@ void Emulation::receiveData(const char* text, int length)
* U+10FFFF
* https://unicodebook.readthedocs.io/unicode_encodings.html#surrogates
*/
QByteArray ba(text, length);
QString str = _toUtf16(ba);
std::wstring unicodeText = str.toStdWString();
const QString str = _toUtf16(QByteArrayView(text, length));
//send characters to terminal emulator
for (size_t i=0;i<unicodeText.length();i++)
receiveChar(unicodeText[i]);
//send characters to terminal emulator; an unpaired surrogate becomes U+FFFD
const QChar* unit = str.constData();
const QChar* end = unit + str.size();
while (unit < end)
{
const QChar current = *unit++;
if (Q_UNLIKELY(current.isSurrogate()))
{
if (current.isHighSurrogate() && unit < end && unit->isLowSurrogate())
receiveChar(wchar_t(QChar::surrogateToUcs4(current, *unit++)));
else
receiveChar(wchar_t(QChar::ReplacementCharacter));
}
else
{
receiveChar(wchar_t(current.unicode()));
}
}
//look for z-modem indicator
//-- someone who understands more about z-modems that I do may be able to move

@ -309,7 +309,12 @@ void HistoryScrollBuffer::addCellsVector(const QVector<Character>& cells)
_head = 0;
}
_historyBuffer[bufferIndex(_usedLines-1)] = cells;
// Screen lines keep a whole row of capacity to write into; a history line
// keeps only the cells it holds.
if (cells.capacity() > cells.size())
_historyBuffer[bufferIndex(_usedLines-1)] = QVector<Character>(cells.cbegin(), cells.cend());
else
_historyBuffer[bufferIndex(_usedLines-1)] = cells;
_wrappedLine[bufferIndex(_usedLines-1)] = false;
}
void HistoryScrollBuffer::addCells(const Character a[], int count)

@ -315,11 +315,6 @@ void Screen::restoreMode(int m)
currentModes[m] = savedModes[m];
}
bool Screen::getMode(int m) const
{
return currentModes[m];
}
void Screen::saveCursor()
{
savedState.cursorColumn = cuX;
@ -658,10 +653,8 @@ void Screen::newLine()
index();
}
void Screen::checkSelection(int from, int to)
void Screen::clearOverlappingSelection(int from, int to)
{
if (selBegin == -1)
return;
int scr_TL = loc(0, history->getLines());
//Clear entire selection if it overlaps region [from, to]
if ( (selBottomRight >= (from+scr_TL)) && (selTopLeft <= (to+scr_TL)) )
@ -816,6 +809,10 @@ notcombine:
int size = screenLines[cuY].size();
if (size < cuX+w)
{
// A line fills up one character at a time; allocate it once. The
// history keeps its own copy of what the line holds.
if (screenLines[cuY].capacity() < columns)
screenLines[cuY].reserve(columns);
screenLines[cuY].resize(cuX+w);
}
@ -1031,20 +1028,32 @@ void Screen::moveImage(int dest, int sourceBegin, int sourceEnd)
//so it matters that we do the copy in the right order -
//forwards if dest < sourceBegin or backwards otherwise.
//(search the web for 'memmove implementation' for details)
const int destLine = dest / columns;
const int sourceLine = sourceBegin / columns;
const int shift = qAbs(destLine - sourceLine);
LineProperty* properties = lineProperties.data();
//a source line a later step overwrites is moved, which spares sharing a buffer
//per line per scroll; a line nothing overwrites keeps its contents
if (dest < sourceBegin)
{
for (int i=0;i<=lines;i++)
{
screenLines[ (dest/columns)+i ] = screenLines[ (sourceBegin/columns)+i ];
lineProperties[(dest/columns)+i]=lineProperties[(sourceBegin/columns)+i];
if (i <= lines - shift)
screenLines[destLine + i] = std::move(screenLines[sourceLine + i]);
else
screenLines[destLine + i] = screenLines[sourceLine + i];
properties[destLine + i] = properties[sourceLine + i];
}
}
else
{
for (int i=lines;i>=0;i--)
{
screenLines[ (dest/columns)+i ] = screenLines[ (sourceBegin/columns)+i ];
lineProperties[(dest/columns)+i]=lineProperties[(sourceBegin/columns)+i];
if (shift > 0 && i >= shift)
screenLines[destLine + i] = std::move(screenLines[sourceLine + i]);
else
screenLines[destLine + i] = screenLines[sourceLine + i];
properties[destLine + i] = properties[sourceLine + i];
}
}

@ -242,7 +242,10 @@ public:
/** Restores the state of a screen @p mode saved by calling saveMode() */
void restoreMode(int mode);
/** Returns whether the specified screen @p mode is enabled or not .*/
bool getMode(int mode) const;
bool getMode(int mode) const
{
return currentModes[mode];
}
/**
* Saves the current position and appearance (text color and style) of the cursor.
@ -500,7 +503,12 @@ public:
* @param from The start of the area to check.
* @param to The end of the area to check
*/
void checkSelection(int from, int to);
void checkSelection(int from, int to)
{
// Every printed character checks; there is rarely a selection.
if (selBegin != -1)
clearOverlappingSelection(from, to);
}
/**
* Sets or clears an attribute of the current line.
@ -633,6 +641,7 @@ private:
void reverseRendition(Character& p) const;
bool isSelectionValid() const;
void clearOverlappingSelection(int from, int to);
// copies text from 'startIndex' to 'endIndex' to a stream
// startIndex and endIndex are positions generated using the loc(x,y) macro
void writeToStream(TerminalCharacterDecoder* decoder, int startIndex,

@ -287,6 +287,14 @@ void Vt102Emulation::receiveChar(wchar_t cc)
if (cc == DEL)
return; //VT100: ignore.
// Most output is printable text between sequences: what lun() below does, with
// the tokenizer already reset whenever its buffer is empty.
if (tokenBufferPos == 0 && cc >= 32 && cc != ESC+128 && getMode(MODE_Ansi))
{
_currentScreen->displayCharacter(applyCharset(cc));
return;
}
if (ces(CTL))
{
// ignore control characters in the text part of Xpe (aka OSC) "ESC]"
@ -1705,11 +1713,6 @@ void Vt102Emulation::restoreMode(int m)
resetMode(m);
}
bool Vt102Emulation::getMode(int m)
{
return _currentModes.mode[m];
}
char Vt102Emulation::eraseChar() const
{
KeyboardTranslator::Entry entry = _keyTranslator->findEntry(

@ -127,7 +127,7 @@ private:
void setDefaultMargins();
// returns true if 'mode' is set or false otherwise
bool getMode (int mode);
bool getMode (int mode) { return _currentModes.mode[mode]; }
// saves the current boolean value of 'mode'
void saveMode (int mode);
// restores the boolean value of 'mode'

@ -19,6 +19,10 @@
int konsole_wcwidth(wchar_t ucs)
{
// Printable ASCII is one column in every locale, and most output is ASCII.
if (ucs >= 0x20 && ucs < 0x7f)
return 1;
#ifdef HAVE_UTF8PROC
utf8proc_category_t cat = utf8proc_category( ucs );
if (cat == UTF8PROC_CATEGORY_CO) {

Loading…
Cancel
Save