Skip to content

Commit 4fd3054

Browse files
committed
update qtermwidget by upstream
Signed-off-by: xiaoming <2014500726@smail.xtu.edu.cn>
1 parent 65d358b commit 4fd3054

File tree

7 files changed

+343
-144
lines changed

7 files changed

+343
-144
lines changed

lib/qtermwidget/Emulation.cpp

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "Screen.h"
3737
#include "ScreenWindow.h"
3838
#include "TerminalCharacterDecoder.h"
39+
#include "TerminalDisplay.h"
3940

4041
Emulation::Emulation()
4142
: _currentScreen(nullptr)
@@ -87,6 +88,7 @@ ScreenWindow *Emulation::createWindow() {
8788
ScreenWindow *window = new ScreenWindow();
8889
window->setScreen(_currentScreen);
8990
_windows << window;
91+
ExtendedCharTable::instance.windows << window;
9092

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

107109
while (windowIter.hasNext()) {
108-
delete windowIter.next();
110+
auto win = windowIter.next();
111+
ExtendedCharTable::instance.windows.remove(win);
112+
delete win;
109113
}
110114

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

338-
ushort ExtendedCharTable::extendedCharHash(ushort *unicodePoints,
339-
ushort length) const {
340-
ushort hash = 0;
342+
uint ExtendedCharTable::extendedCharHash(uint* unicodePoints , ushort length) const {
343+
uint hash = 0;
341344
for (ushort i = 0; i < length; i++) {
342345
hash = 31 * hash + unicodePoints[i];
343346
}
344347
return hash;
345348
}
346349

347-
bool ExtendedCharTable::extendedCharMatch(ushort hash, ushort *unicodePoints,
348-
ushort length) const {
349-
ushort *entry = extendedCharTable[hash];
350+
bool ExtendedCharTable::extendedCharMatch(uint hash , uint* unicodePoints , ushort length) const {
351+
uint* entry = extendedCharTable[hash];
350352

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

364-
ushort ExtendedCharTable::createExtendedChar(ushort *unicodePoints,
365-
ushort length) {
366+
uint ExtendedCharTable::createExtendedChar(uint* unicodePoints , ushort length) {
366367
// look for this sequence of points in the table
367-
ushort hash = extendedCharHash(unicodePoints, length);
368+
uint hash = extendedCharHash(unicodePoints,length);
369+
const uint initialHash = hash;
370+
bool triedCleaningSolution = false;
368371

369372
// check existing entry for match
370-
while (extendedCharTable.contains(hash)) {
373+
while (extendedCharTable.contains(hash) && hash != 0) { // 0 has a special meaning for chars so we don't use it
371374
if (extendedCharMatch(hash, unicodePoints, length)) {
372375
// this sequence already has an entry in the table,
373376
// return its hash
374377
return hash;
375378
} else {
376-
// if hash is already used by another, different sequence of unicode
377-
// character points then try next hash
379+
// if hash is already used by another, different sequence of
380+
// unicode character points, then try next hash
378381
hash++;
382+
383+
if (hash == initialHash) {
384+
if (!triedCleaningSolution) {
385+
triedCleaningSolution = true;
386+
// All the hashes are full, go to all Screens and try to free any
387+
// This is slow but should happen very rarely
388+
QSet<uint> usedExtendedChars;
389+
for (const auto &w : std::as_const(windows)) {
390+
if (w->screen()) {
391+
usedExtendedChars += w->screen()->usedExtendedChars();
392+
}
393+
}
394+
395+
QHash<uint,uint*>::iterator it = extendedCharTable.begin();
396+
QHash<uint,uint*>::iterator itEnd = extendedCharTable.end();
397+
while (it != itEnd) {
398+
if (usedExtendedChars.contains(it.key())) {
399+
++it;
400+
} else {
401+
it = extendedCharTable.erase(it);
402+
}
403+
}
404+
} else {
405+
qWarning() << "Using all the extended char hashes, going to miss this extended character";
406+
return 0;
407+
}
408+
}
379409
}
380410
}
381411

382412
// add the new sequence to the table and
383413
// return that index
384-
ushort *buffer = new ushort[length + 1];
414+
uint* buffer = new uint[length+1];
385415
buffer[0] = length;
386416
for (int i = 0; i < length; i++)
387417
buffer[i + 1] = unicodePoints[i];
@@ -391,11 +421,10 @@ ushort ExtendedCharTable::createExtendedChar(ushort *unicodePoints,
391421
return hash;
392422
}
393423

394-
ushort *ExtendedCharTable::lookupExtendedChar(ushort hash,
395-
ushort &length) const {
424+
uint* ExtendedCharTable::lookupExtendedChar(uint hash , ushort& length) const {
396425
// lookup index in table and if found, set the length
397426
// argument and return a pointer to the character sequence
398-
ushort *buffer = extendedCharTable[hash];
427+
uint* buffer = extendedCharTable[hash];
399428
if (buffer) {
400429
length = buffer[0];
401430
return buffer + 1;
@@ -410,7 +439,7 @@ ExtendedCharTable::ExtendedCharTable() {
410439

411440
ExtendedCharTable::~ExtendedCharTable() {
412441
// free all allocated character buffers
413-
QHashIterator<ushort, ushort *> iter(extendedCharTable);
442+
QHashIterator<uint,uint*> iter(extendedCharTable);
414443
while (iter.hasNext()) {
415444
iter.next();
416445
delete[] iter.value();

lib/qtermwidget/Screen.cpp

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -622,15 +622,70 @@ void Screen::displayCharacter(wchar_t c) {
622622
// putting the cursor one right to the last column of the screen.
623623

624624
int w = CharWidth::unicode_width(c);
625-
if (w <= 0)
625+
if (w < 0)
626626
return;
627627

628+
if (w == 0) {
629+
if (QChar(c).category() != QChar::Mark_NonSpacing)
630+
return;
631+
// Find previous "real character" to try to combine with
632+
int charToCombineWithX = qMin(cuX, screenLines[cuY].length());
633+
int charToCombineWithY = cuY;
634+
bool previousChar = true;
635+
do {
636+
if (charToCombineWithX > 0) {
637+
--charToCombineWithX;
638+
} else if (charToCombineWithY > 0 && lineProperties.at(charToCombineWithY - 1) & LINE_WRAPPED) {
639+
// Try previous line
640+
--charToCombineWithY;
641+
charToCombineWithX = screenLines[charToCombineWithY].length() - 1;
642+
} else {
643+
// Give up
644+
previousChar = false;
645+
break;
646+
}
647+
648+
// Failsafe
649+
if (charToCombineWithX < 0) {
650+
previousChar = false;
651+
break;
652+
}
653+
} while (screenLines[charToCombineWithY][charToCombineWithX] == 0);
654+
655+
if (!previousChar) {
656+
w = 2;
657+
goto notcombine;
658+
}
659+
660+
Character& currentChar = screenLines[charToCombineWithY][charToCombineWithX];
661+
if ((currentChar.rendition & RE_EXTENDED_CHAR) == 0) {
662+
uint chars[2] = { static_cast<uint>(currentChar.character), static_cast<uint>(c) };
663+
currentChar.rendition |= RE_EXTENDED_CHAR;
664+
currentChar.character = ExtendedCharTable::instance.createExtendedChar(chars, 2);
665+
} else {
666+
ushort extendedCharLength;
667+
const uint* oldChars = ExtendedCharTable::instance.lookupExtendedChar(currentChar.character, extendedCharLength);
668+
Q_ASSERT(oldChars);
669+
if (oldChars && extendedCharLength < 8) {
670+
Q_ASSERT(extendedCharLength > 1);
671+
Q_ASSERT(extendedCharLength < 65535); // redundant due to above check
672+
auto chars = std::make_unique<uint[]>(extendedCharLength + 1);
673+
std::copy_n(oldChars, extendedCharLength, chars.get());
674+
chars[extendedCharLength] = c;
675+
currentChar.character = ExtendedCharTable::instance.createExtendedChar(chars.get(), extendedCharLength + 1);
676+
}
677+
}
678+
return;
679+
}
680+
681+
notcombine:
628682
if (cuX + w > columns) {
629683
if (getMode(MODE_Wrap)) {
630684
lineProperties[cuY] = (LineProperty)(lineProperties[cuY] | LINE_WRAPPED);
631685
nextLine();
632-
} else
686+
} else {
633687
cuX = columns - w;
688+
}
634689
}
635690

636691
// ensure current line vector has enough elements

lib/qtermwidget/Screen.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#define SCREEN_H
2424

2525
#include <QRect>
26+
#include <QSet>
2627
#include <QTextStream>
2728
#include <QVarLengthArray>
2829

@@ -554,6 +555,19 @@ class Screen
554555
* Character style.
555556
*/
556557
static void fillWithDefaultChar(Character* dest, int count);
558+
559+
QSet<uint> usedExtendedChars() const {
560+
QSet<uint> result;
561+
for (int i = 0; i < lines; ++i) {
562+
const ImageLine &il = screenLines[i];
563+
for (int j = 0; j < columns; ++j) {
564+
if (il[j].rendition & RE_EXTENDED_CHAR) {
565+
result << il[j].character;
566+
}
567+
}
568+
}
569+
return result;
570+
}
557571

558572
private:
559573
Screen(const Screen &) = delete;

0 commit comments

Comments
 (0)