summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Libraries/LibVT/Terminal.cpp93
-rw-r--r--Userland/Libraries/LibVT/Terminal.h17
-rw-r--r--Userland/Libraries/LibVT/TerminalWidget.cpp57
-rw-r--r--Userland/Libraries/LibVT/TerminalWidget.h3
4 files changed, 156 insertions, 14 deletions
diff --git a/Userland/Libraries/LibVT/Terminal.cpp b/Userland/Libraries/LibVT/Terminal.cpp
index 2fc319be28..6e4575df4d 100644
--- a/Userland/Libraries/LibVT/Terminal.cpp
+++ b/Userland/Libraries/LibVT/Terminal.cpp
@@ -46,24 +46,64 @@ void Terminal::clear_including_history()
void Terminal::alter_mode(bool should_set, Parameters params, Intermediates intermediates)
{
+ auto steady_cursor_to_blinking = [](CursorStyle style) {
+ switch (style) {
+ case SteadyBar:
+ return BlinkingBar;
+ case SteadyBlock:
+ return BlinkingBlock;
+ case SteadyUnderline:
+ return BlinkingUnderline;
+ default:
+ return style;
+ }
+ };
+
+ auto blinking_cursor_to_steady = [](CursorStyle style) {
+ switch (style) {
+ case BlinkingBar:
+ return SteadyBar;
+ case BlinkingBlock:
+ return SteadyBlock;
+ case BlinkingUnderline:
+ return SteadyUnderline;
+ default:
+ return style;
+ }
+ };
+
if (intermediates.size() > 0 && intermediates[0] == '?') {
for (auto mode : params) {
switch (mode) {
case 3: {
// 80/132-column mode (DECCOLM)
- unsigned new_columns = should_set ? 80 : 132;
+ unsigned new_columns = should_set ? 132 : 80;
dbgln_if(TERMINAL_DEBUG, "Setting {}-column mode", new_columns);
set_size(new_columns, rows());
clear();
break;
}
+ case 12:
+ if (should_set) {
+ // Start blinking cursor
+ m_cursor_style = steady_cursor_to_blinking(m_cursor_style);
+ } else {
+ // Stop blinking cursor
+ m_cursor_style = blinking_cursor_to_steady(m_cursor_style);
+ }
+ m_client.set_cursor_style(m_cursor_style);
+ break;
case 25:
- // Hide cursor command, but doesn't need to be run (for now, because
- // we don't do inverse control codes anyways)
- if (should_set)
- dbgln("Terminal: Hide Cursor escapecode received. Not needed: ignored.");
- else
- dbgln("Terminal: Show Cursor escapecode received. Not needed: ignored.");
+ if (should_set) {
+ // Show cursor
+ m_cursor_style = m_saved_cursor_style;
+ m_client.set_cursor_style(m_cursor_style);
+ } else {
+ // Hide cursor
+ m_saved_cursor_style = m_cursor_style;
+ m_cursor_style = None;
+ m_client.set_cursor_style(None);
+ }
break;
default:
dbgln("Terminal::alter_mode: Unimplemented private mode {} (should_set={})", mode, should_set);
@@ -84,12 +124,12 @@ void Terminal::alter_mode(bool should_set, Parameters params, Intermediates inte
void Terminal::RM(Parameters params, Intermediates intermediates)
{
- alter_mode(true, params, intermediates);
+ alter_mode(false, params, intermediates);
}
void Terminal::SM(Parameters params, Intermediates intermediates)
{
- alter_mode(false, params, intermediates);
+ alter_mode(true, params, intermediates);
}
void Terminal::SGR(Parameters params)
@@ -454,6 +494,35 @@ void Terminal::SD(Parameters params)
scroll_down();
}
+void Terminal::DECSCUSR(Parameters params)
+{
+ unsigned style = 1;
+ if (params.size() >= 1 && params[0] != 0)
+ style = params[0];
+ switch (style) {
+ case 1:
+ m_client.set_cursor_style(BlinkingBlock);
+ break;
+ case 2:
+ m_client.set_cursor_style(SteadyBlock);
+ break;
+ case 3:
+ m_client.set_cursor_style(BlinkingUnderline);
+ break;
+ case 4:
+ m_client.set_cursor_style(SteadyUnderline);
+ break;
+ case 5:
+ m_client.set_cursor_style(BlinkingBar);
+ break;
+ case 6:
+ m_client.set_cursor_style(SteadyBar);
+ break;
+ default:
+ dbgln("Unknown cursor style {}", style);
+ }
+}
+
#ifndef KERNEL
void Terminal::IL(Parameters params)
{
@@ -833,6 +902,12 @@ void Terminal::execute_csi_sequence(Parameters parameters, Intermediates interme
case 'n':
DSR(parameters);
break;
+ case 'q':
+ if (intermediates.size() >= 1 && intermediates[0] == ' ')
+ DECSCUSR(parameters);
+ else
+ unimplemented_csi_sequence(parameters, intermediates, last_byte);
+ break;
default:
unimplemented_csi_sequence(parameters, intermediates, last_byte);
}
diff --git a/Userland/Libraries/LibVT/Terminal.h b/Userland/Libraries/LibVT/Terminal.h
index f5d8560013..3ede089c27 100644
--- a/Userland/Libraries/LibVT/Terminal.h
+++ b/Userland/Libraries/LibVT/Terminal.h
@@ -26,6 +26,16 @@ class VirtualConsole;
namespace VT {
+enum CursorStyle {
+ None,
+ BlinkingBlock,
+ SteadyBlock,
+ BlinkingUnderline,
+ SteadyUnderline,
+ BlinkingBar,
+ SteadyBar
+};
+
class TerminalClient {
public:
virtual ~TerminalClient() { }
@@ -36,6 +46,7 @@ public:
virtual void terminal_did_resize(u16 columns, u16 rows) = 0;
virtual void terminal_history_changed() = 0;
virtual void emit(const u8*, size_t) = 0;
+ virtual void set_cursor_style(CursorStyle) = 0;
};
class Terminal : public EscapeSequenceExecutor {
@@ -238,6 +249,9 @@ protected:
// DSR - Device Status Reports
void DSR(Parameters);
+ // DECSCUSR - Set Cursor Style
+ void DECSCUSR(Parameters);
+
#ifndef KERNEL
// ICH - Insert Character
void ICH(Parameters);
@@ -319,6 +333,9 @@ protected:
bool m_swallow_current { false };
bool m_stomp { false };
+ CursorStyle m_cursor_style { BlinkingBlock };
+ CursorStyle m_saved_cursor_style { BlinkingBlock };
+
Attribute m_current_attribute;
Attribute m_saved_attribute;
diff --git a/Userland/Libraries/LibVT/TerminalWidget.cpp b/Userland/Libraries/LibVT/TerminalWidget.cpp
index dc3cc504a4..432ff28df2 100644
--- a/Userland/Libraries/LibVT/TerminalWidget.cpp
+++ b/Userland/Libraries/LibVT/TerminalWidget.cpp
@@ -326,6 +326,7 @@ void TerminalWidget::paint_event(GUI::PaintEvent& event)
for (size_t column = 0; column < line.length(); ++column) {
bool should_reverse_fill_for_cursor_or_selection = m_cursor_blink_state
+ && (m_cursor_style == VT::CursorStyle::SteadyBlock || m_cursor_style == VT::CursorStyle::BlinkingBlock)
&& m_has_logical_focus
&& visual_row == row_with_cursor
&& column == m_terminal.cursor_column();
@@ -392,6 +393,7 @@ void TerminalWidget::paint_event(GUI::PaintEvent& event)
for (size_t column = 0; column < line.length(); ++column) {
auto attribute = line.attribute_at(column);
bool should_reverse_fill_for_cursor_or_selection = m_cursor_blink_state
+ && (m_cursor_style == VT::CursorStyle::SteadyBlock || m_cursor_style == VT::CursorStyle::BlinkingBlock)
&& m_has_logical_focus
&& visual_row == row_with_cursor
&& column == m_terminal.cursor_column();
@@ -417,11 +419,31 @@ void TerminalWidget::paint_event(GUI::PaintEvent& event)
}
// Draw cursor.
- if (!m_has_logical_focus && row_with_cursor < m_terminal.rows()) {
+ if (m_cursor_blink_state && row_with_cursor < m_terminal.rows()) {
auto& cursor_line = m_terminal.line(first_row_from_history + row_with_cursor);
- 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);
- painter.draw_rect(cell_rect, color_from_rgb(cursor_line.attribute_at(m_terminal.cursor_column()).effective_foreground_color()));
+ if (m_terminal.cursor_row() >= (m_terminal.rows() - rows_from_history))
+ return;
+
+ if (m_has_logical_focus && (m_cursor_style == VT::CursorStyle::BlinkingBlock || m_cursor_style == VT::CursorStyle::SteadyBlock))
+ return; // This has already been handled by inverting the cell colors
+
+ auto cursor_color = color_from_rgb(cursor_line.attribute_at(m_terminal.cursor_column()).effective_foreground_color());
+ auto cell_rect = glyph_rect(row_with_cursor, m_terminal.cursor_column()).inflated(0, m_line_spacing);
+ if (m_cursor_style == VT::CursorStyle::BlinkingUnderline || m_cursor_style == VT::CursorStyle::SteadyUnderline) {
+ auto x1 = cell_rect.bottom_left().x();
+ auto x2 = cell_rect.bottom_right().x();
+ auto y = cell_rect.bottom_left().y();
+ for (auto x = x1; x <= x2; ++x)
+ painter.set_pixel({ x, y }, cursor_color);
+ } else if (m_cursor_style == VT::CursorStyle::BlinkingBar || m_cursor_style == VT::CursorStyle::SteadyBar) {
+ auto x = cell_rect.bottom_left().x();
+ auto y1 = cell_rect.top_left().y();
+ auto y2 = cell_rect.bottom_left().y();
+ for (auto y = y1; y <= y2; ++y)
+ painter.set_pixel({ x, y }, cursor_color);
+ } else {
+ // We fall back to a block if we don't support the selected cursor type.
+ painter.draw_rect(cell_rect, cursor_color);
}
}
}
@@ -986,6 +1008,32 @@ void TerminalWidget::emit(const u8* data, size_t size)
}
}
+void TerminalWidget::set_cursor_style(CursorStyle style)
+{
+ switch (style) {
+ case None:
+ m_cursor_blink_timer->stop();
+ m_cursor_blink_state = false;
+ break;
+ case SteadyBlock:
+ case SteadyUnderline:
+ case SteadyBar:
+ m_cursor_blink_timer->stop();
+ m_cursor_blink_state = true;
+ break;
+ case BlinkingBlock:
+ case BlinkingUnderline:
+ case BlinkingBar:
+ m_cursor_blink_state = true;
+ m_cursor_blink_timer->restart();
+ break;
+ default:
+ dbgln("Cursor style not implemented");
+ }
+ m_cursor_style = style;
+ invalidate_cursor();
+}
+
void TerminalWidget::context_menu_event(GUI::ContextMenuEvent& event)
{
if (m_hovered_href_id.is_null()) {
@@ -1107,5 +1155,4 @@ void TerminalWidget::set_font_and_resize_to_fit(const Gfx::Font& font)
set_font(font);
resize(widget_size_for_font(font));
}
-
}
diff --git a/Userland/Libraries/LibVT/TerminalWidget.h b/Userland/Libraries/LibVT/TerminalWidget.h
index 81455da489..8e1e2fc790 100644
--- a/Userland/Libraries/LibVT/TerminalWidget.h
+++ b/Userland/Libraries/LibVT/TerminalWidget.h
@@ -114,6 +114,7 @@ private:
virtual void terminal_did_resize(u16 columns, u16 rows) override;
virtual void terminal_history_changed() override;
virtual void emit(const u8*, size_t) override;
+ virtual void set_cursor_style(CursorStyle) override;
void set_logical_focus(bool);
@@ -173,6 +174,8 @@ private:
bool m_cursor_blink_state { true };
bool m_automatic_size_policy { false };
+ VT::CursorStyle m_cursor_style { BlinkingBlock };
+
enum class AutoScrollDirection {
None,
Up,