Skip to content

Prevent horizontally scrolling wide chars erasing themselves#14650

Merged
2 commits merged intomicrosoft:mainfrom
j4james:fix-dbcs-scrolling
Jan 13, 2023
Merged

Prevent horizontally scrolling wide chars erasing themselves#14650
2 commits merged intomicrosoft:mainfrom
j4james:fix-dbcs-scrolling

Conversation

@j4james
Copy link
Collaborator

@j4james j4james commented Jan 8, 2023

When the buffer contains wide characters that occupy more than one cell,
and those cells are scrolled horizontally by exactly one column, that
operation can result in the wide characters being completely erased.
This PR attempts to fix that bug, although it's not an ideal long term
solution.

Although not really to blame, it was PR #13626 that exposed this issue.

The root of the problem is that scrolling operations copy cells one by
one, but wide characters are written to the buffer two cells at a time.
So when you move a wide character one position to the left or right, it
can overwrite itself before it's finished copying, and the end result is
the whole character gets erased.

I've attempt to solve this by getting the affected operations to read
two cells in advance before they start writing, so there's no risk of
losing the source data before it's fully output. This may not work in
the long term, with characters wider than two cells, but it should at
least be good enough for now.

I've also changed the TextBuffer::Write call to a WriteLine call to
improve the handling of a wide character on the end of the line, where
moving it right by one column would place it half off screen. It should
just be dropped, but with the Write method, it would end up pushed
onto the following line.

Validation Steps Performed

I've manually confirmed this fixes all the test cases described in
#14626, and also added some unit tests that replicate those scenarios.

Closes #14626

@ghost ghost added Area-Output Related to output processing (inserting text into buffer, retrieving buffer text, etc.) Area-VT Virtual Terminal sequence support Issue-Bug It either shouldn't be doing this or needs an investigation. Product-Conhost For issues in the Console codebase Severity-Blocking We won't ship a release like this! No-siree. labels Jan 8, 2023
@j4james j4james marked this pull request as ready for review January 8, 2023 18:05
@zadjii-msft zadjii-msft added this to the Terminal v1.17 milestone Jan 10, 2023
Copy link
Member

@carlos-zamora carlos-zamora left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Straightforward and tested. Thanks for doing this!

Comment on lines 112 to +113
source.WalkInBounds(sourcePos, walkDirection);
next = OutputCell(*screenInfo.GetCellDataAt(sourcePos));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible for this to result in source running out of space (somehow?) before target does? I guess we're doing it in the previous code as well, but maybe one fewer time.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you look at the WalkInBounds implementation, it just doesn't update the position once it has reached the end of the range, so all we'll be doing is reading the final position twice.

bool Viewport::WalkInBounds(til::point& pos, const WalkDir dir, bool allowEndExclusive) const noexcept
{
auto copy = pos;
if (WalkInBoundsCircular(copy, dir, allowEndExclusive))
{
pos = copy;
return true;
}
else
{
return false;
}
}

@zadjii-msft
Copy link
Member

So when you move a wide character one position to the left or right, it can overwrite itself before it's finished copying, and the end result is the whole character gets erased.

for some reason this is hilarious to me. Like, of course it does, classic wide char code 🙃

@DHowett DHowett added the AutoMerge Marked for automatic merge by the bot when requirements are met label Jan 13, 2023
@ghost
Copy link

ghost commented Jan 13, 2023

Hello @DHowett!

Because this pull request has the AutoMerge label, I will be glad to assist with helping to merge this pull request once all check-in policies pass.

p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (@msftbot) and give me an instruction to get started! Learn more here.

@ghost ghost merged commit fb485a2 into microsoft:main Jan 13, 2023
@lhecker lhecker removed their assignment Jan 18, 2023
@j4james j4james deleted the fix-dbcs-scrolling branch January 19, 2023 20:52
@ghost
Copy link

ghost commented Jan 24, 2023

🎉Windows Terminal Preview v1.17.1023 has been released which incorporates this pull request.:tada:

Handy links:

zadjii-msft pushed a commit that referenced this pull request Mar 22, 2023
When a `DECCRA` operation is copying content that spans a double width
line, it's possible that some range of the bounding rectangle will be
off-screen, and that range is not supposed to be copied. However, the
code checking for off-screen positions was using incorrect coordinates,
so we would mistakenly copy content that shouldn't be copied, and drop
content that should have been copied. This PR fixes that.

## References and Relevant Issues

This was a regression introduced in PR #14650 when fixing an issue with
horizontal scrolling of DBCS characters.

## Validation Steps Performed

I manually verified this fixes the test case in #15019, and I've also
added a unit test that replicates that case.

Closes #15019
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area-Output Related to output processing (inserting text into buffer, retrieving buffer text, etc.) Area-VT Virtual Terminal sequence support AutoMerge Marked for automatic merge by the bot when requirements are met Issue-Bug It either shouldn't be doing this or needs an investigation. Product-Conhost For issues in the Console codebase Severity-Blocking We won't ship a release like this! No-siree.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ICH no longer works correctly on lines containing wide characters

5 participants