36
36
#include " Screen.h"
37
37
#include " ScreenWindow.h"
38
38
#include " TerminalCharacterDecoder.h"
39
+ #include " TerminalDisplay.h"
39
40
40
41
Emulation::Emulation ()
41
42
: _currentScreen(nullptr )
@@ -87,6 +88,7 @@ ScreenWindow *Emulation::createWindow() {
87
88
ScreenWindow *window = new ScreenWindow ();
88
89
window->setScreen (_currentScreen);
89
90
_windows << window;
91
+ ExtendedCharTable::instance.windows << window;
90
92
91
93
connect (window, &ScreenWindow::selectionChanged, this , &Emulation::bufferedUpdate);
92
94
connect (this , &Emulation::outputChanged, window, &ScreenWindow::notifyOutputChanged);
@@ -105,7 +107,9 @@ Emulation::~Emulation() {
105
107
QListIterator<ScreenWindow *> windowIter (_windows);
106
108
107
109
while (windowIter.hasNext ()) {
108
- delete windowIter.next ();
110
+ auto win = windowIter.next ();
111
+ ExtendedCharTable::instance.windows .remove (win);
112
+ delete win;
109
113
}
110
114
111
115
delete _screen[0 ];
@@ -335,18 +339,16 @@ QSize Emulation::imageSize() const {
335
339
return {_currentScreen->getColumns (), _currentScreen->getLines ()};
336
340
}
337
341
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 ;
341
344
for (ushort i = 0 ; i < length; i++) {
342
345
hash = 31 * hash + unicodePoints[i];
343
346
}
344
347
return hash;
345
348
}
346
349
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];
350
352
351
353
// compare given length with stored sequence length ( given as the first
352
354
// ushort in the stored buffer )
@@ -361,27 +363,55 @@ bool ExtendedCharTable::extendedCharMatch(ushort hash, ushort *unicodePoints,
361
363
return true ;
362
364
}
363
365
364
- ushort ExtendedCharTable::createExtendedChar (ushort *unicodePoints,
365
- ushort length) {
366
+ uint ExtendedCharTable::createExtendedChar (uint* unicodePoints , ushort length) {
366
367
// 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 ;
368
371
369
372
// 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
371
374
if (extendedCharMatch (hash, unicodePoints, length)) {
372
375
// this sequence already has an entry in the table,
373
376
// return its hash
374
377
return hash;
375
378
} 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
378
381
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
+ }
379
409
}
380
410
}
381
411
382
412
// add the new sequence to the table and
383
413
// return that index
384
- ushort * buffer = new ushort [length + 1 ];
414
+ uint* buffer = new uint [length+ 1 ];
385
415
buffer[0 ] = length;
386
416
for (int i = 0 ; i < length; i++)
387
417
buffer[i + 1 ] = unicodePoints[i];
@@ -391,11 +421,10 @@ ushort ExtendedCharTable::createExtendedChar(ushort *unicodePoints,
391
421
return hash;
392
422
}
393
423
394
- ushort *ExtendedCharTable::lookupExtendedChar (ushort hash,
395
- ushort &length) const {
424
+ uint* ExtendedCharTable::lookupExtendedChar (uint hash , ushort& length) const {
396
425
// lookup index in table and if found, set the length
397
426
// argument and return a pointer to the character sequence
398
- ushort * buffer = extendedCharTable[hash];
427
+ uint* buffer = extendedCharTable[hash];
399
428
if (buffer) {
400
429
length = buffer[0 ];
401
430
return buffer + 1 ;
@@ -410,7 +439,7 @@ ExtendedCharTable::ExtendedCharTable() {
410
439
411
440
ExtendedCharTable::~ExtendedCharTable () {
412
441
// free all allocated character buffers
413
- QHashIterator<ushort, ushort *> iter (extendedCharTable);
442
+ QHashIterator<uint,uint *> iter (extendedCharTable);
414
443
while (iter.hasNext ()) {
415
444
iter.next ();
416
445
delete[] iter.value ();
0 commit comments