Skip to content

Commit

Permalink
update qtermwidget by upstream
Browse files Browse the repository at this point in the history
Signed-off-by: xiaoming <[email protected]>
  • Loading branch information
QQxiaoming committed Dec 16, 2024
1 parent 65d358b commit 4fd3054
Show file tree
Hide file tree
Showing 7 changed files with 343 additions and 144 deletions.
65 changes: 47 additions & 18 deletions lib/qtermwidget/Emulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "Screen.h"
#include "ScreenWindow.h"
#include "TerminalCharacterDecoder.h"
#include "TerminalDisplay.h"

Emulation::Emulation()
: _currentScreen(nullptr)
Expand Down Expand Up @@ -87,6 +88,7 @@ ScreenWindow *Emulation::createWindow() {
ScreenWindow *window = new ScreenWindow();
window->setScreen(_currentScreen);
_windows << window;
ExtendedCharTable::instance.windows << window;

connect(window, &ScreenWindow::selectionChanged, this, &Emulation::bufferedUpdate);
connect(this, &Emulation::outputChanged, window, &ScreenWindow::notifyOutputChanged);
Expand All @@ -105,7 +107,9 @@ Emulation::~Emulation() {
QListIterator<ScreenWindow *> windowIter(_windows);

while (windowIter.hasNext()) {
delete windowIter.next();
auto win = windowIter.next();
ExtendedCharTable::instance.windows.remove(win);
delete win;
}

delete _screen[0];
Expand Down Expand Up @@ -335,18 +339,16 @@ QSize Emulation::imageSize() const {
return {_currentScreen->getColumns(), _currentScreen->getLines()};
}

ushort ExtendedCharTable::extendedCharHash(ushort *unicodePoints,
ushort length) const {
ushort hash = 0;
uint ExtendedCharTable::extendedCharHash(uint* unicodePoints , ushort length) const {
uint hash = 0;
for (ushort i = 0; i < length; i++) {
hash = 31 * hash + unicodePoints[i];
}
return hash;
}

bool ExtendedCharTable::extendedCharMatch(ushort hash, ushort *unicodePoints,
ushort length) const {
ushort *entry = extendedCharTable[hash];
bool ExtendedCharTable::extendedCharMatch(uint hash , uint* unicodePoints , ushort length) const {
uint* entry = extendedCharTable[hash];

// compare given length with stored sequence length ( given as the first
// ushort in the stored buffer )
Expand All @@ -361,27 +363,55 @@ bool ExtendedCharTable::extendedCharMatch(ushort hash, ushort *unicodePoints,
return true;
}

ushort ExtendedCharTable::createExtendedChar(ushort *unicodePoints,
ushort length) {
uint ExtendedCharTable::createExtendedChar(uint* unicodePoints , ushort length) {
// look for this sequence of points in the table
ushort hash = extendedCharHash(unicodePoints, length);
uint hash = extendedCharHash(unicodePoints,length);
const uint initialHash = hash;
bool triedCleaningSolution = false;

// check existing entry for match
while (extendedCharTable.contains(hash)) {
while (extendedCharTable.contains(hash) && hash != 0) { // 0 has a special meaning for chars so we don't use it
if (extendedCharMatch(hash, unicodePoints, length)) {
// this sequence already has an entry in the table,
// return its hash
return hash;
} else {
// if hash is already used by another, different sequence of unicode
// character points then try next hash
// if hash is already used by another, different sequence of
// unicode character points, then try next hash
hash++;

if (hash == initialHash) {
if (!triedCleaningSolution) {
triedCleaningSolution = true;
// All the hashes are full, go to all Screens and try to free any
// This is slow but should happen very rarely
QSet<uint> usedExtendedChars;
for (const auto &w : std::as_const(windows)) {
if (w->screen()) {
usedExtendedChars += w->screen()->usedExtendedChars();
}
}

QHash<uint,uint*>::iterator it = extendedCharTable.begin();
QHash<uint,uint*>::iterator itEnd = extendedCharTable.end();
while (it != itEnd) {
if (usedExtendedChars.contains(it.key())) {
++it;
} else {
it = extendedCharTable.erase(it);
}
}
} else {
qWarning() << "Using all the extended char hashes, going to miss this extended character";
return 0;
}
}
}
}

// add the new sequence to the table and
// return that index
ushort *buffer = new ushort[length + 1];
uint* buffer = new uint[length+1];
buffer[0] = length;
for (int i = 0; i < length; i++)
buffer[i + 1] = unicodePoints[i];
Expand All @@ -391,11 +421,10 @@ ushort ExtendedCharTable::createExtendedChar(ushort *unicodePoints,
return hash;
}

ushort *ExtendedCharTable::lookupExtendedChar(ushort hash,
ushort &length) const {
uint* ExtendedCharTable::lookupExtendedChar(uint hash , ushort& length) const {
// lookup index in table and if found, set the length
// argument and return a pointer to the character sequence
ushort *buffer = extendedCharTable[hash];
uint* buffer = extendedCharTable[hash];
if (buffer) {
length = buffer[0];
return buffer + 1;
Expand All @@ -410,7 +439,7 @@ ExtendedCharTable::ExtendedCharTable() {

ExtendedCharTable::~ExtendedCharTable() {
// free all allocated character buffers
QHashIterator<ushort, ushort *> iter(extendedCharTable);
QHashIterator<uint,uint*> iter(extendedCharTable);
while (iter.hasNext()) {
iter.next();
delete[] iter.value();
Expand Down
59 changes: 57 additions & 2 deletions lib/qtermwidget/Screen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -622,15 +622,70 @@ void Screen::displayCharacter(wchar_t c) {
// putting the cursor one right to the last column of the screen.

int w = CharWidth::unicode_width(c);
if (w <= 0)
if (w < 0)
return;

if (w == 0) {
if (QChar(c).category() != QChar::Mark_NonSpacing)
return;
// Find previous "real character" to try to combine with
int charToCombineWithX = qMin(cuX, screenLines[cuY].length());
int charToCombineWithY = cuY;
bool previousChar = true;
do {
if (charToCombineWithX > 0) {
--charToCombineWithX;
} else if (charToCombineWithY > 0 && lineProperties.at(charToCombineWithY - 1) & LINE_WRAPPED) {
// Try previous line
--charToCombineWithY;
charToCombineWithX = screenLines[charToCombineWithY].length() - 1;
} else {
// Give up
previousChar = false;
break;
}

// Failsafe
if (charToCombineWithX < 0) {
previousChar = false;
break;
}
} while (screenLines[charToCombineWithY][charToCombineWithX] == 0);

if (!previousChar) {
w = 2;
goto notcombine;
}

Character& currentChar = screenLines[charToCombineWithY][charToCombineWithX];
if ((currentChar.rendition & RE_EXTENDED_CHAR) == 0) {
uint chars[2] = { static_cast<uint>(currentChar.character), static_cast<uint>(c) };
currentChar.rendition |= RE_EXTENDED_CHAR;
currentChar.character = ExtendedCharTable::instance.createExtendedChar(chars, 2);
} else {
ushort extendedCharLength;
const uint* oldChars = ExtendedCharTable::instance.lookupExtendedChar(currentChar.character, extendedCharLength);
Q_ASSERT(oldChars);
if (oldChars && extendedCharLength < 8) {
Q_ASSERT(extendedCharLength > 1);
Q_ASSERT(extendedCharLength < 65535); // redundant due to above check
auto chars = std::make_unique<uint[]>(extendedCharLength + 1);
std::copy_n(oldChars, extendedCharLength, chars.get());
chars[extendedCharLength] = c;
currentChar.character = ExtendedCharTable::instance.createExtendedChar(chars.get(), extendedCharLength + 1);
}
}
return;
}

notcombine:
if (cuX + w > columns) {
if (getMode(MODE_Wrap)) {
lineProperties[cuY] = (LineProperty)(lineProperties[cuY] | LINE_WRAPPED);
nextLine();
} else
} else {
cuX = columns - w;
}
}

// ensure current line vector has enough elements
Expand Down
14 changes: 14 additions & 0 deletions lib/qtermwidget/Screen.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#define SCREEN_H

#include <QRect>
#include <QSet>
#include <QTextStream>
#include <QVarLengthArray>

Expand Down Expand Up @@ -554,6 +555,19 @@ class Screen
* Character style.
*/
static void fillWithDefaultChar(Character* dest, int count);

QSet<uint> usedExtendedChars() const {
QSet<uint> result;
for (int i = 0; i < lines; ++i) {
const ImageLine &il = screenLines[i];
for (int j = 0; j < columns; ++j) {
if (il[j].rendition & RE_EXTENDED_CHAR) {
result << il[j].character;
}
}
}
return result;
}

private:
Screen(const Screen &) = delete;
Expand Down
Loading

0 comments on commit 4fd3054

Please sign in to comment.