Skip to content

Commit 835d52f

Browse files
Merge pull request #1395 from contour-terminal/fix/wide-emoji-overwrites
Fixes screen destruction on sibling cells when overwriting wide characters
2 parents a29dd9c + cff48c7 commit 835d52f

File tree

4 files changed

+18
-25
lines changed

4 files changed

+18
-25
lines changed

metainfo.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@
111111
<li>Fixes variable fonts loading</li>
112112
<li>Fixes Command modifier for input mappings, such as Command+C or Command+V on on MacOS (#1379).</li>
113113
<li>Fixes CSIu encoding of shift modifier produced characters (#1373).</li>
114+
<li>Fixes screen destruction on sibling cells when overwriting wide characters, such as Emoji, Kanji, etc.</li>
114115
<li>Changes VT sequence `DECSCUSR` (`CSI ? 0 SP q` and `CSI ? SP q`) to reset to user-configured cursor style (#1377).</li>
115116
<li>Remove `contour-latest` terminfo file. Please use `contour` terminfo instead.</li>
116117
<li>Adds `Command` as modifier to input mappings on MacOS to work along with `Meta` for convenience reasons (#1379).</li>

src/contour/helper.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ void sendWheelEvent(QWheelEvent* event, TerminalSession& session)
423423
session.addScrollX(xDelta);
424424
inputLog()("Accumulate x scroll with current value {} ", session.getScrollX());
425425
}
426-
if (std::abs(session.getScrollX()) > unbox(session.terminal().cellPixelSize().width))
426+
if (std::abs(session.getScrollX()) > unbox<int>(session.terminal().cellPixelSize().width))
427427
{
428428
auto const modifier = makeModifiers(event->modifiers());
429429
auto const button = session.getScrollX() > 0 ? VTMouseButton::WheelRight : VTMouseButton::WheelLeft;
@@ -441,7 +441,7 @@ void sendWheelEvent(QWheelEvent* event, TerminalSession& session)
441441
session.addScrollY(yDelta);
442442
inputLog()("Accumulate y scroll with current value {} ", session.getScrollY());
443443
}
444-
if (std::abs(session.getScrollY()) > unbox(session.terminal().cellPixelSize().height))
444+
if (std::abs(session.getScrollY()) > unbox<int>(session.terminal().cellPixelSize().height))
445445
{
446446
auto const modifier = makeModifiers(event->modifiers());
447447
auto const button = session.getScrollY() > 0 ? VTMouseButton::WheelUp : VTMouseButton::WheelDown;

src/vtbackend/Screen.cpp

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -566,8 +566,7 @@ void Screen<Cell>::writeTextInternal(char32_t sourceCodepoint)
566566
else
567567
{
568568
auto const extendedWidth = usePreviousCell().appendCharacter(codepoint);
569-
if (extendedWidth > 0)
570-
clearAndAdvance(extendedWidth);
569+
clearAndAdvance(0, extendedWidth);
571570
_terminal->markCellDirty(_lastCursorPosition);
572571
}
573572

@@ -592,17 +591,19 @@ void Screen<Cell>::writeCharToCurrentAndAdvance(char32_t codepoint) noexcept
592591
{
593592
// Erase the left half of the wide char.
594593
Cell& prevCell = line.useCellAt(_cursor.position.column - 1);
595-
prevCell.reset();
594+
prevCell.reset(_cursor.graphicsRendition);
596595
}
597596

597+
auto const oldWidth = cell.width();
598+
598599
cell.write(_cursor.graphicsRendition,
599600
codepoint,
600601
static_cast<uint8_t>(unicode::width(codepoint)),
601602
_cursor.hyperlink);
602603

603604
_lastCursorPosition = _cursor.position;
604605

605-
clearAndAdvance(cell.width());
606+
clearAndAdvance(oldWidth, cell.width());
606607

607608
// TODO: maybe move selector API up? So we can make this call conditional,
608609
// and only call it when something is selected?
@@ -614,32 +615,23 @@ void Screen<Cell>::writeCharToCurrentAndAdvance(char32_t codepoint) noexcept
614615

615616
template <typename Cell>
616617
CRISPY_REQUIRES(CellConcept<Cell>)
617-
void Screen<Cell>::clearAndAdvance(int offset) noexcept
618+
void Screen<Cell>::clearAndAdvance(int oldWidth, int newWidth) noexcept
618619
{
619-
if (offset == 0)
620-
return;
621-
622620
bool const cursorInsideMargin =
623621
_terminal->isModeEnabled(DECMode::LeftRightMargin) && isCursorInsideMargins();
624622
auto const cellsAvailable = cursorInsideMargin ? *(margin().horizontal.to - _cursor.position.column) - 1
625623
: *pageSize().columns - *_cursor.position.column - 1;
626-
auto const n = min(offset, cellsAvailable);
627624

628-
if (n == offset)
629-
{
630-
_cursor.position.column++;
631-
auto& line = currentLine();
632-
for (int i = 1; i < n; ++i) // XXX It's not even clear if other TEs are doing that, too.
633-
{
634-
line.useCellAt(_cursor.position.column)
635-
.reset(_cursor.graphicsRendition.with(CellFlag::WideCharContinuation), _cursor.hyperlink);
636-
_cursor.position.column++;
637-
}
638-
}
625+
auto const sgr = newWidth > 1 ? _cursor.graphicsRendition.with(CellFlag::WideCharContinuation)
626+
: _cursor.graphicsRendition;
627+
auto& line = currentLine();
628+
for (int i = 1; i < min(max(oldWidth, newWidth), cellsAvailable); ++i)
629+
line.useCellAt(_cursor.position.column + i).reset(sgr, _cursor.hyperlink);
630+
631+
if (newWidth == min(newWidth, cellsAvailable))
632+
_cursor.position.column += ColumnOffset::cast_from(newWidth);
639633
else if (_cursor.autoWrap)
640-
{
641634
_cursor.wrapPending = true;
642-
}
643635
}
644636

645637
template <typename Cell>

src/vtbackend/Screen.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@ class Screen final: public ScreenBase, public capabilities::StaticDatabase
616616
void linefeed(ColumnOffset column);
617617

618618
void writeCharToCurrentAndAdvance(char32_t codepoint) noexcept;
619-
void clearAndAdvance(int offset) noexcept;
619+
void clearAndAdvance(int oldWidth, int newWidth) noexcept;
620620

621621
void scrollUp(LineCount n, GraphicsAttributes sgr, Margin margin);
622622
void scrollUp(LineCount n, Margin margin);

0 commit comments

Comments
 (0)