Fix blitting of windows halfway through double-width codepoint
Display a whitespace in place of the uncovered half of the codepoint. (I know this is incorrect and we should be considering grapheme clusters instead of codepoints, but this is a far bigger refactoring and another can of worms to handle with terminal emulators). Fixes #4262
This commit is contained in:
parent
ac6420ee8d
commit
c643cd4467
|
@ -51,14 +51,19 @@ struct TerminalUI::Window::Line
|
||||||
ColumnCount length() const { return text.column_length() + skip; }
|
ColumnCount length() const { return text.column_length() + skip; }
|
||||||
void resize(ColumnCount size)
|
void resize(ColumnCount size)
|
||||||
{
|
{
|
||||||
auto text_len = text.column_length();
|
auto it = text.begin(), end = text.end();
|
||||||
if (size < text_len)
|
while (it != end and size > 0)
|
||||||
|
size -= codepoint_width(utf8::read_codepoint(it, end));
|
||||||
|
|
||||||
|
if (size < 0) // possible if resizing to the middle of a double-width codepoint
|
||||||
{
|
{
|
||||||
text.resize(text.byte_count_to(size), 0);
|
kak_assert(size == -1);
|
||||||
skip = 0;
|
utf8::to_previous(it, text.begin());
|
||||||
|
skip = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
skip = size - text_len;
|
skip = size;
|
||||||
|
text.resize(it - text.begin(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator==(const Atom& lhs, const Atom& rhs) { return lhs.text == rhs.text and lhs.skip == rhs.skip and lhs.face == rhs.face; }
|
friend bool operator==(const Atom& lhs, const Atom& rhs) { return lhs.text == rhs.text and lhs.skip == rhs.skip and lhs.face == rhs.face; }
|
||||||
|
@ -111,10 +116,16 @@ struct TerminalUI::Window::Line
|
||||||
Pos end = find_col(pos+len);
|
Pos end = find_col(pos+len);
|
||||||
|
|
||||||
auto make_tail = [](const Atom& atom, ColumnCount from) {
|
auto make_tail = [](const Atom& atom, ColumnCount from) {
|
||||||
if (atom.text.column_length() > from)
|
auto it = atom.text.begin(), end = atom.text.end();
|
||||||
return Atom{atom.text.substr(atom.text.byte_count_to(from)).str(), atom.skip, atom.face};
|
while (it != end and from > 0)
|
||||||
else
|
from -= codepoint_width(utf8::read_codepoint(it, end));
|
||||||
return Atom{{}, atom.length() - from, atom.face};
|
|
||||||
|
if (from < 0) // can happen if tail starts in the middle of a double-width codepoint
|
||||||
|
{
|
||||||
|
kak_assert(from == -1);
|
||||||
|
return Atom{" " + StringView{it, end}, atom.skip, atom.face};
|
||||||
|
}
|
||||||
|
return Atom{{it, end}, atom.skip - from, atom.face};
|
||||||
};
|
};
|
||||||
|
|
||||||
if (begin.it == end.it)
|
if (begin.it == end.it)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user