mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 06:47:34 +00:00
LibVT: Support RGB colors (\x1b[38;2;<r>;<g>;<b>m)
This commit is contained in:
parent
ccdef5a675
commit
8487806ec0
4 changed files with 48 additions and 22 deletions
|
@ -174,13 +174,37 @@ void Terminal::SGR(const ParamVector& params)
|
||||||
m_current_attribute.reset();
|
m_current_attribute.reset();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (params.size() == 3 && params[1] == 5) {
|
if (params.size() >= 3) {
|
||||||
if (params[0] == 38) {
|
bool should_set = true;
|
||||||
m_current_attribute.foreground_color = params[2];
|
auto kind = params[1];
|
||||||
return;
|
u32 color = 0;
|
||||||
} else if (params[0] == 48) {
|
switch (kind) {
|
||||||
m_current_attribute.background_color = params[2];
|
case 5: // 8-bit
|
||||||
return;
|
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) {
|
||||||
|
if (params[0] == 38) {
|
||||||
|
m_current_attribute.foreground_color = color;
|
||||||
|
return;
|
||||||
|
} else if (params[0] == 48) {
|
||||||
|
m_current_attribute.background_color = color;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto param : params) {
|
for (auto param : params) {
|
||||||
|
@ -230,7 +254,7 @@ void Terminal::SGR(const ParamVector& params)
|
||||||
// Foreground color
|
// Foreground color
|
||||||
if (m_current_attribute.flags & Attribute::Bold)
|
if (m_current_attribute.flags & Attribute::Bold)
|
||||||
param += 8;
|
param += 8;
|
||||||
m_current_attribute.foreground_color = param - 30;
|
m_current_attribute.foreground_color = xterm_colors[param - 30];
|
||||||
break;
|
break;
|
||||||
case 39:
|
case 39:
|
||||||
// reset foreground
|
// reset foreground
|
||||||
|
@ -247,7 +271,7 @@ void Terminal::SGR(const ParamVector& params)
|
||||||
// Background color
|
// Background color
|
||||||
if (m_current_attribute.flags & Attribute::Bold)
|
if (m_current_attribute.flags & Attribute::Bold)
|
||||||
param += 8;
|
param += 8;
|
||||||
m_current_attribute.background_color = param - 40;
|
m_current_attribute.background_color = xterm_colors[param - 40];
|
||||||
break;
|
break;
|
||||||
case 49:
|
case 49:
|
||||||
// reset background
|
// reset background
|
||||||
|
|
|
@ -31,12 +31,13 @@
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
#include <LibVT/Position.h>
|
#include <LibVT/Position.h>
|
||||||
|
#include <LibVT/XtermColors.h>
|
||||||
|
|
||||||
namespace VT {
|
namespace VT {
|
||||||
|
|
||||||
class TerminalClient {
|
class TerminalClient {
|
||||||
public:
|
public:
|
||||||
virtual ~TerminalClient() {}
|
virtual ~TerminalClient() { }
|
||||||
|
|
||||||
virtual void beep() = 0;
|
virtual void beep() = 0;
|
||||||
virtual void set_window_title(const StringView&) = 0;
|
virtual void set_window_title(const StringView&) = 0;
|
||||||
|
@ -48,8 +49,8 @@ public:
|
||||||
struct Attribute {
|
struct Attribute {
|
||||||
Attribute() { reset(); }
|
Attribute() { reset(); }
|
||||||
|
|
||||||
static const u8 default_foreground_color = 7;
|
static const u32 default_foreground_color = xterm_colors[7];
|
||||||
static const u8 default_background_color = 0;
|
static const u32 default_background_color = xterm_colors[0];
|
||||||
|
|
||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
|
@ -57,8 +58,8 @@ struct Attribute {
|
||||||
background_color = default_background_color;
|
background_color = default_background_color;
|
||||||
flags = Flags::NoAttributes;
|
flags = Flags::NoAttributes;
|
||||||
}
|
}
|
||||||
u8 foreground_color;
|
u32 foreground_color;
|
||||||
u8 background_color;
|
u32 background_color;
|
||||||
|
|
||||||
String href;
|
String href;
|
||||||
String href_id;
|
String href_id;
|
||||||
|
@ -110,6 +111,7 @@ public:
|
||||||
struct Line {
|
struct Line {
|
||||||
AK_MAKE_NONCOPYABLE(Line);
|
AK_MAKE_NONCOPYABLE(Line);
|
||||||
AK_MAKE_NONMOVABLE(Line);
|
AK_MAKE_NONMOVABLE(Line);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Line(u16 columns);
|
explicit Line(u16 columns);
|
||||||
~Line();
|
~Line();
|
||||||
|
|
|
@ -146,9 +146,9 @@ TerminalWidget::~TerminalWidget()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Color lookup_color(unsigned color)
|
static inline Color color_from_rgb(unsigned color)
|
||||||
{
|
{
|
||||||
return Color::from_rgb(xterm_colors[color]);
|
return Color::from_rgb(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
Gfx::Rect TerminalWidget::glyph_rect(u16 row, u16 column)
|
Gfx::Rect TerminalWidget::glyph_rect(u16 row, u16 column)
|
||||||
|
@ -349,7 +349,7 @@ void TerminalWidget::paint_event(GUI::PaintEvent& event)
|
||||||
if (m_visual_beep_timer->is_active())
|
if (m_visual_beep_timer->is_active())
|
||||||
painter.clear_rect(row_rect, Color::Red);
|
painter.clear_rect(row_rect, Color::Red);
|
||||||
else if (has_only_one_background_color)
|
else if (has_only_one_background_color)
|
||||||
painter.clear_rect(row_rect, lookup_color(line.attributes[0].background_color).with_alpha(m_opacity));
|
painter.clear_rect(row_rect, color_from_rgb(line.attributes[0].background_color).with_alpha(m_opacity));
|
||||||
|
|
||||||
// The terminal insists on thinking characters and
|
// The terminal insists on thinking characters and
|
||||||
// bytes are the same thing. We want to still draw
|
// bytes are the same thing. We want to still draw
|
||||||
|
@ -385,14 +385,14 @@ void TerminalWidget::paint_event(GUI::PaintEvent& event)
|
||||||
auto character_rect = glyph_rect(row, column);
|
auto character_rect = glyph_rect(row, column);
|
||||||
auto cell_rect = character_rect.inflated(0, m_line_spacing);
|
auto cell_rect = character_rect.inflated(0, m_line_spacing);
|
||||||
if (!has_only_one_background_color || should_reverse_fill_for_cursor_or_selection) {
|
if (!has_only_one_background_color || should_reverse_fill_for_cursor_or_selection) {
|
||||||
painter.clear_rect(cell_rect, lookup_color(should_reverse_fill_for_cursor_or_selection ? attribute.foreground_color : attribute.background_color).with_alpha(m_opacity));
|
painter.clear_rect(cell_rect, color_from_rgb(should_reverse_fill_for_cursor_or_selection ? attribute.foreground_color : attribute.background_color).with_alpha(m_opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool should_paint_underline = attribute.flags & VT::Attribute::Underline
|
bool should_paint_underline = attribute.flags & VT::Attribute::Underline
|
||||||
|| (!m_hovered_href.is_empty() && m_hovered_href_id == attribute.href_id);
|
|| (!m_hovered_href.is_empty() && m_hovered_href_id == attribute.href_id);
|
||||||
|
|
||||||
if (should_paint_underline)
|
if (should_paint_underline)
|
||||||
painter.draw_line(cell_rect.bottom_left(), cell_rect.bottom_right(), lookup_color(should_reverse_fill_for_cursor_or_selection ? attribute.background_color : attribute.foreground_color));
|
painter.draw_line(cell_rect.bottom_left(), cell_rect.bottom_right(), color_from_rgb(should_reverse_fill_for_cursor_or_selection ? attribute.background_color : attribute.foreground_color));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (codepoint == ' ')
|
if (codepoint == ' ')
|
||||||
|
@ -405,7 +405,7 @@ void TerminalWidget::paint_event(GUI::PaintEvent& event)
|
||||||
character_rect.location(),
|
character_rect.location(),
|
||||||
codepoint,
|
codepoint,
|
||||||
attribute.flags & VT::Attribute::Bold ? bold_font() : font(),
|
attribute.flags & VT::Attribute::Bold ? bold_font() : font(),
|
||||||
lookup_color(should_reverse_fill_for_cursor_or_selection ? attribute.background_color : attribute.foreground_color));
|
color_from_rgb(should_reverse_fill_for_cursor_or_selection ? attribute.background_color : attribute.foreground_color));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,7 +413,7 @@ void TerminalWidget::paint_event(GUI::PaintEvent& event)
|
||||||
auto& cursor_line = line_for_visual_row(row_with_cursor);
|
auto& cursor_line = line_for_visual_row(row_with_cursor);
|
||||||
if (m_terminal.cursor_row() < (m_terminal.rows() - rows_from_history)) {
|
if (m_terminal.cursor_row() < (m_terminal.rows() - rows_from_history)) {
|
||||||
auto cell_rect = glyph_rect(row_with_cursor, m_terminal.cursor_column()).inflated(0, m_line_spacing);
|
auto cell_rect = glyph_rect(row_with_cursor, m_terminal.cursor_column()).inflated(0, m_line_spacing);
|
||||||
painter.draw_rect(cell_rect, lookup_color(cursor_line.attributes[m_terminal.cursor_column()].foreground_color));
|
painter.draw_rect(cell_rect, color_from_rgb(cursor_line.attributes[m_terminal.cursor_column()].foreground_color));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
static const unsigned xterm_colors[256] = {
|
static constexpr unsigned xterm_colors[256] = {
|
||||||
0x000000,
|
0x000000,
|
||||||
0xcc0000,
|
0xcc0000,
|
||||||
0x3e9a06,
|
0x3e9a06,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue