1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 00:07:36 +00:00

LibVT: Correct color handling

VT100's documentation says that more than one SGR (Set Graphics
Rendition) parameters may be included in a single escape sequence.
However, we treated those with more than 3 parameters as color
sequences, so this behavior was not replicated.
This commit is contained in:
Daniel Bertalan 2021-05-17 16:33:47 +02:00 committed by Andreas Kling
parent 507ace5174
commit c1e292e5bc

View file

@ -66,7 +66,7 @@ void Terminal::alter_mode(bool should_set, Parameters params, Intermediates inte
dbgln("Terminal: Show Cursor escapecode received. Not needed: ignored."); dbgln("Terminal: Show Cursor escapecode received. Not needed: ignored.");
break; break;
default: default:
dbgln("Terminal::alter_mode: Unimplemented private mode {}", mode); dbgln("Terminal::alter_mode: Unimplemented private mode {} (should_set={})", mode, should_set);
break; break;
} }
} }
@ -75,7 +75,7 @@ void Terminal::alter_mode(bool should_set, Parameters params, Intermediates inte
switch (mode) { switch (mode) {
// FIXME: implement *something* for this // FIXME: implement *something* for this
default: default:
dbgln("Terminal::alter_mode: Unimplemented mode {} (set={})", mode, should_set); dbgln("Terminal::alter_mode: Unimplemented mode {} (should_set={})", mode, should_set);
break; break;
} }
} }
@ -98,111 +98,115 @@ void Terminal::SGR(Parameters params)
m_current_attribute.reset(); m_current_attribute.reset();
return; return;
} }
if (params.size() >= 3) {
bool should_set = true;
auto kind = params[1];
u32 color = 0;
switch (kind) {
case 5: // 8-bit
color = xterm_colors[params[2]];
break;
case 2: // 24-bit
for (size_t i = 0; i < 3; ++i) {
u8 component = 0;
if (params.size() - 2 > i) {
component = params[i + 2];
}
color <<= 8;
color |= component;
}
break;
default:
should_set = false;
break;
}
if (should_set) { auto parse_color = [&]() -> Optional<u32> {
if (params[0] == 38) { if (params.size() < 2) {
m_current_attribute.foreground_color = color; dbgln("Color code has no type");
return; return {};
} else if (params[0] == 48) {
m_current_attribute.background_color = color;
return;
}
} }
} u32 color = 0;
for (auto param : params) { switch (params[1]) {
switch (param) { case 5: // 8-bit
case 0: if (params.size() < 3) {
// Reset dbgln("8-bit color code has too few parameters");
m_current_attribute.reset(); return {};
break; }
case 1: return xterm_colors[params[2]];
m_current_attribute.flags |= Attribute::Bold; case 2: // 24-bit
break; if (params.size() < 5) {
case 3: dbgln("24-bit color code has too few parameters");
m_current_attribute.flags |= Attribute::Italic; return {};
break; }
case 4: for (size_t i = 0; i < 3; ++i) {
m_current_attribute.flags |= Attribute::Underline; color <<= 8;
break; color |= params[i + 2];
case 5: }
m_current_attribute.flags |= Attribute::Blink; return color;
break;
case 7:
m_current_attribute.flags |= Attribute::Negative;
break;
case 22:
m_current_attribute.flags &= ~Attribute::Bold;
break;
case 23:
m_current_attribute.flags &= ~Attribute::Italic;
break;
case 24:
m_current_attribute.flags &= ~Attribute::Underline;
break;
case 25:
m_current_attribute.flags &= ~Attribute::Blink;
break;
case 27:
m_current_attribute.flags &= ~Attribute::Negative;
break;
case 30:
case 31:
case 32:
case 33:
case 34:
case 35:
case 36:
case 37:
// Foreground color
if (m_current_attribute.flags & Attribute::Bold)
param += 8;
m_current_attribute.foreground_color = xterm_colors[param - 30];
break;
case 39:
// reset foreground
m_current_attribute.foreground_color = Attribute::default_foreground_color;
break;
case 40:
case 41:
case 42:
case 43:
case 44:
case 45:
case 46:
case 47:
// Background color
if (m_current_attribute.flags & Attribute::Bold)
param += 8;
m_current_attribute.background_color = xterm_colors[param - 40];
break;
case 49:
// reset background
m_current_attribute.background_color = Attribute::default_background_color;
break;
default: default:
dbgln("FIXME: SGR: p: {}", param); dbgln("Unknown color type {}", params[1]);
return {};
}
};
if (params[0] == 38) {
m_current_attribute.foreground_color = parse_color().value_or(m_current_attribute.foreground_color);
} else if (params[0] == 48) {
m_current_attribute.background_color = parse_color().value_or(m_current_attribute.background_color);
} else {
// A single escape sequence may set multiple parameters.
for (auto param : params) {
switch (param) {
case 0:
// Reset
m_current_attribute.reset();
break;
case 1:
m_current_attribute.flags |= Attribute::Bold;
break;
case 3:
m_current_attribute.flags |= Attribute::Italic;
break;
case 4:
m_current_attribute.flags |= Attribute::Underline;
break;
case 5:
m_current_attribute.flags |= Attribute::Blink;
break;
case 7:
m_current_attribute.flags |= Attribute::Negative;
break;
case 22:
m_current_attribute.flags &= ~Attribute::Bold;
break;
case 23:
m_current_attribute.flags &= ~Attribute::Italic;
break;
case 24:
m_current_attribute.flags &= ~Attribute::Underline;
break;
case 25:
m_current_attribute.flags &= ~Attribute::Blink;
break;
case 27:
m_current_attribute.flags &= ~Attribute::Negative;
break;
case 30:
case 31:
case 32:
case 33:
case 34:
case 35:
case 36:
case 37:
// Foreground color
if (m_current_attribute.flags & Attribute::Bold)
param += 8;
m_current_attribute.foreground_color = xterm_colors[param - 30];
break;
case 39:
// reset foreground
m_current_attribute.foreground_color = Attribute::default_foreground_color;
break;
case 40:
case 41:
case 42:
case 43:
case 44:
case 45:
case 46:
case 47:
// Background color
if (m_current_attribute.flags & Attribute::Bold)
param += 8;
m_current_attribute.background_color = xterm_colors[param - 40];
break;
case 49:
// reset background
m_current_attribute.background_color = Attribute::default_background_color;
break;
default:
dbgln("FIXME: SGR: p: {}", param);
}
} }
} }
} }