Skip to content

Commit

Permalink
[vtbackend] Screen: Fixes screen destruction on sibling cells when ov…
Browse files Browse the repository at this point in the history
…erwriting wide characters

Signed-off-by: Christian Parpart <christian@parpart.family>
  • Loading branch information
christianparpart committed Dec 31, 2023
1 parent 790884b commit cff48c7
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 23 deletions.
1 change: 1 addition & 0 deletions metainfo.xml
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
<li>Fixes variable fonts loading</li>
<li>Fixes Command modifier for input mappings, such as Command+C or Command+V on on MacOS (#1379).</li>
<li>Fixes CSIu encoding of shift modifier produced characters (#1373).</li>
<li>Fixes screen destruction on sibling cells when overwriting wide characters, such as Emoji, Kanji, etc.</li>
<li>Changes VT sequence `DECSCUSR` (`CSI ? 0 SP q` and `CSI ? SP q`) to reset to user-configured cursor style (#1377).</li>
<li>Remove `contour-latest` terminfo file. Please use `contour` terminfo instead.</li>
<li>Adds `Command` as modifier to input mappings on MacOS to work along with `Meta` for convenience reasons (#1379).</li>
Expand Down
36 changes: 14 additions & 22 deletions src/vtbackend/Screen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -566,8 +566,7 @@ void Screen<Cell>::writeTextInternal(char32_t sourceCodepoint)
else
{
auto const extendedWidth = usePreviousCell().appendCharacter(codepoint);
if (extendedWidth > 0)
clearAndAdvance(extendedWidth);
clearAndAdvance(0, extendedWidth);
_terminal->markCellDirty(_lastCursorPosition);
}

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

auto const oldWidth = cell.width();

cell.write(_cursor.graphicsRendition,
codepoint,
static_cast<uint8_t>(unicode::width(codepoint)),
_cursor.hyperlink);

_lastCursorPosition = _cursor.position;

clearAndAdvance(cell.width());
clearAndAdvance(oldWidth, cell.width());

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

template <typename Cell>
CRISPY_REQUIRES(CellConcept<Cell>)
void Screen<Cell>::clearAndAdvance(int offset) noexcept
void Screen<Cell>::clearAndAdvance(int oldWidth, int newWidth) noexcept
{
if (offset == 0)
return;

bool const cursorInsideMargin =
_terminal->isModeEnabled(DECMode::LeftRightMargin) && isCursorInsideMargins();
auto const cellsAvailable = cursorInsideMargin ? *(margin().horizontal.to - _cursor.position.column) - 1
: *pageSize().columns - *_cursor.position.column - 1;
auto const n = min(offset, cellsAvailable);

if (n == offset)
{
_cursor.position.column++;
auto& line = currentLine();
for (int i = 1; i < n; ++i) // XXX It's not even clear if other TEs are doing that, too.
{
line.useCellAt(_cursor.position.column)
.reset(_cursor.graphicsRendition.with(CellFlag::WideCharContinuation), _cursor.hyperlink);
_cursor.position.column++;
}
}
auto const sgr = newWidth > 1 ? _cursor.graphicsRendition.with(CellFlag::WideCharContinuation)
: _cursor.graphicsRendition;
auto& line = currentLine();
for (int i = 1; i < min(max(oldWidth, newWidth), cellsAvailable); ++i)
line.useCellAt(_cursor.position.column + i).reset(sgr, _cursor.hyperlink);

if (newWidth == min(newWidth, cellsAvailable))
_cursor.position.column += ColumnOffset::cast_from(newWidth);
else if (_cursor.autoWrap)
{
_cursor.wrapPending = true;
}
}

template <typename Cell>
Expand Down
2 changes: 1 addition & 1 deletion src/vtbackend/Screen.h
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ class Screen final: public ScreenBase, public capabilities::StaticDatabase
void linefeed(ColumnOffset column);

void writeCharToCurrentAndAdvance(char32_t codepoint) noexcept;
void clearAndAdvance(int offset) noexcept;
void clearAndAdvance(int oldWidth, int newWidth) noexcept;

void scrollUp(LineCount n, GraphicsAttributes sgr, Margin margin);
void scrollUp(LineCount n, Margin margin);
Expand Down

0 comments on commit cff48c7

Please sign in to comment.