Draw non-ASCII text whole in the GUIs (B7); one span sanitizer
Highlighters emit one span per byte of a non-ASCII character, and the ImGui and Qt renderers decoded each span on its own, so every such character was drawn as replacement glyphs (reproduced under Xvfb: "héllo" showed as "h??llo"). kte::SanitizeSpans (Highlight.h) widens spans to whole UTF-8 characters and removes overlaps (the earlier span wins), and replaces the three renderers' copies of the clamp/sort code. The terminal renderer's token lookup rescanned the spans from the first for every byte drawn; it now walks them with a cursor. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015rcVQiiWyTzoNrsvLSaAfB
This commit is contained in:
+5
-27
@@ -310,30 +310,8 @@ protected:
|
||||
HasHighlighter()) {
|
||||
const kte::LineHighlight &lh = buf->Highlighter()->GetLine(
|
||||
*buf, static_cast<int>(i), buf->Version());
|
||||
struct SSpan {
|
||||
std::size_t s;
|
||||
std::size_t e;
|
||||
kte::TokenKind k;
|
||||
};
|
||||
std::vector<SSpan> spans;
|
||||
spans.reserve(lh.spans.size());
|
||||
const std::size_t line_len = line.size();
|
||||
for (const auto &sp: lh.spans) {
|
||||
int s_raw = sp.col_start;
|
||||
int e_raw = sp.col_end;
|
||||
if (e_raw < s_raw)
|
||||
std::swap(e_raw, s_raw);
|
||||
std::size_t s = static_cast<std::size_t>(std::max(
|
||||
0, std::min(s_raw, (int) line_len)));
|
||||
std::size_t e = static_cast<std::size_t>(std::max(
|
||||
(int) s, std::min(e_raw, (int) line_len)));
|
||||
if (s < e)
|
||||
spans.push_back({s, e, sp.kind});
|
||||
}
|
||||
std::sort(spans.begin(), spans.end(),
|
||||
[](const SSpan &a, const SSpan &b) {
|
||||
return a.s < b.s;
|
||||
});
|
||||
std::vector<kte::HighlightSpan> spans; // clamped, ordered, whole characters
|
||||
kte::SanitizeSpans(line, lh.spans, spans);
|
||||
|
||||
auto colorFor = [](kte::TokenKind k) -> QColor {
|
||||
// GUITheme provides colors via ImGui vector; avoid direct dependency types
|
||||
@@ -344,10 +322,10 @@ protected:
|
||||
|
||||
std::size_t pos = 0;
|
||||
for (const auto &sp: spans) {
|
||||
const std::size_t s = std::max(sp.s, pos);
|
||||
const std::size_t s = std::max(static_cast<std::size_t>(sp.col_start), pos);
|
||||
draw_seg(pos, s, fg);
|
||||
draw_seg(s, sp.e, colorFor(sp.k));
|
||||
pos = std::max(pos, sp.e);
|
||||
draw_seg(s, static_cast<std::size_t>(sp.col_end), colorFor(sp.kind));
|
||||
pos = std::max(pos, static_cast<std::size_t>(sp.col_end));
|
||||
}
|
||||
draw_seg(pos, line.size(), fg);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user