mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 08:47:34 +00:00
LibVT: Move out the Line class from Terminal to its own class
This commit is contained in:
parent
345fbd1fc1
commit
16965db86b
6 changed files with 232 additions and 149 deletions
|
@ -1,4 +1,5 @@
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
|
Line.cpp
|
||||||
Terminal.cpp
|
Terminal.cpp
|
||||||
TerminalWidget.cpp
|
TerminalWidget.cpp
|
||||||
)
|
)
|
||||||
|
|
95
Libraries/LibVT/Line.cpp
Normal file
95
Libraries/LibVT/Line.cpp
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <LibVT/Line.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
namespace VT {
|
||||||
|
|
||||||
|
Line::Line(u16 length)
|
||||||
|
{
|
||||||
|
set_length(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
Line::~Line()
|
||||||
|
{
|
||||||
|
delete[] m_characters;
|
||||||
|
delete[] m_attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Line::set_length(u16 new_length)
|
||||||
|
{
|
||||||
|
if (m_length == new_length)
|
||||||
|
return;
|
||||||
|
auto* new_characters = new u8[new_length];
|
||||||
|
auto* new_attributes = new Attribute[new_length];
|
||||||
|
memset(new_characters, ' ', new_length);
|
||||||
|
if (m_characters && m_attributes) {
|
||||||
|
memcpy(new_characters, m_characters, min(m_length, new_length));
|
||||||
|
for (size_t i = 0; i < min(m_length, new_length); ++i)
|
||||||
|
new_attributes[i] = m_attributes[i];
|
||||||
|
}
|
||||||
|
delete[] m_characters;
|
||||||
|
delete[] m_attributes;
|
||||||
|
m_characters = new_characters;
|
||||||
|
m_attributes = new_attributes;
|
||||||
|
m_length = new_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Line::clear(Attribute attribute)
|
||||||
|
{
|
||||||
|
if (m_dirty) {
|
||||||
|
memset(m_characters, ' ', m_length);
|
||||||
|
for (u16 i = 0; i < m_length; ++i)
|
||||||
|
m_attributes[i] = attribute;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (unsigned i = 0; i < m_length; ++i) {
|
||||||
|
if (m_characters[i] != ' ')
|
||||||
|
m_dirty = true;
|
||||||
|
m_characters[i] = ' ';
|
||||||
|
}
|
||||||
|
for (unsigned i = 0; i < m_length; ++i) {
|
||||||
|
if (m_attributes[i] != attribute)
|
||||||
|
m_dirty = true;
|
||||||
|
m_attributes[i] = attribute;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Line::has_only_one_background_color() const
|
||||||
|
{
|
||||||
|
if (!m_length)
|
||||||
|
return true;
|
||||||
|
// FIXME: Cache this result?
|
||||||
|
auto color = m_attributes[0].background_color;
|
||||||
|
for (size_t i = 1; i < m_length; ++i) {
|
||||||
|
if (m_attributes[i].background_color != color)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
111
Libraries/LibVT/Line.h
Normal file
111
Libraries/LibVT/Line.h
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/Noncopyable.h>
|
||||||
|
#include <AK/String.h>
|
||||||
|
#include <LibVT/XtermColors.h>
|
||||||
|
|
||||||
|
namespace VT {
|
||||||
|
|
||||||
|
struct Attribute {
|
||||||
|
Attribute() { reset(); }
|
||||||
|
|
||||||
|
static const u32 default_foreground_color = xterm_colors[7];
|
||||||
|
static const u32 default_background_color = xterm_colors[0];
|
||||||
|
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
foreground_color = default_foreground_color;
|
||||||
|
background_color = default_background_color;
|
||||||
|
flags = Flags::NoAttributes;
|
||||||
|
}
|
||||||
|
u32 foreground_color;
|
||||||
|
u32 background_color;
|
||||||
|
|
||||||
|
String href;
|
||||||
|
String href_id;
|
||||||
|
|
||||||
|
enum Flags : u8 {
|
||||||
|
NoAttributes = 0x00,
|
||||||
|
Bold = 0x01,
|
||||||
|
Italic = 0x02,
|
||||||
|
Underline = 0x04,
|
||||||
|
Negative = 0x08,
|
||||||
|
Blink = 0x10,
|
||||||
|
Touched = 0x20,
|
||||||
|
};
|
||||||
|
|
||||||
|
bool is_untouched() const { return !(flags & Touched); }
|
||||||
|
|
||||||
|
// TODO: it would be really nice if we had a helper for enums that
|
||||||
|
// exposed bit ops for class enums...
|
||||||
|
u8 flags = Flags::NoAttributes;
|
||||||
|
|
||||||
|
bool operator==(const Attribute& other) const
|
||||||
|
{
|
||||||
|
return foreground_color == other.foreground_color && background_color == other.background_color && flags == other.flags;
|
||||||
|
}
|
||||||
|
bool operator!=(const Attribute& other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Line {
|
||||||
|
AK_MAKE_NONCOPYABLE(Line);
|
||||||
|
AK_MAKE_NONMOVABLE(Line);
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Line(u16 columns);
|
||||||
|
~Line();
|
||||||
|
|
||||||
|
void clear(Attribute);
|
||||||
|
bool has_only_one_background_color() const;
|
||||||
|
void set_length(u16);
|
||||||
|
|
||||||
|
StringView text() const { return { m_characters, m_length }; }
|
||||||
|
|
||||||
|
u16 length() const { return m_length; }
|
||||||
|
|
||||||
|
const u8* characters() const { return m_characters; }
|
||||||
|
u8* characters() { return m_characters; }
|
||||||
|
|
||||||
|
bool is_dirty() const { return m_dirty; }
|
||||||
|
void set_dirty(bool b) { m_dirty = b; }
|
||||||
|
|
||||||
|
const Attribute* attributes() const { return m_attributes; }
|
||||||
|
Attribute* attributes() { return m_attributes; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
u8* m_characters { nullptr };
|
||||||
|
Attribute* m_attributes { nullptr };
|
||||||
|
bool m_dirty { false };
|
||||||
|
u16 m_length { 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -41,68 +41,6 @@ Terminal::~Terminal()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Terminal::Line::Line(u16 length)
|
|
||||||
{
|
|
||||||
set_length(length);
|
|
||||||
}
|
|
||||||
|
|
||||||
Terminal::Line::~Line()
|
|
||||||
{
|
|
||||||
delete[] characters;
|
|
||||||
delete[] attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Terminal::Line::set_length(u16 new_length)
|
|
||||||
{
|
|
||||||
if (m_length == new_length)
|
|
||||||
return;
|
|
||||||
auto* new_characters = new u8[new_length];
|
|
||||||
auto* new_attributes = new Attribute[new_length];
|
|
||||||
memset(new_characters, ' ', new_length);
|
|
||||||
if (characters && attributes) {
|
|
||||||
memcpy(new_characters, characters, min(m_length, new_length));
|
|
||||||
for (size_t i = 0; i < min(m_length, new_length); ++i)
|
|
||||||
new_attributes[i] = attributes[i];
|
|
||||||
}
|
|
||||||
delete[] characters;
|
|
||||||
delete[] attributes;
|
|
||||||
characters = new_characters;
|
|
||||||
attributes = new_attributes;
|
|
||||||
m_length = new_length;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Terminal::Line::clear(Attribute attribute)
|
|
||||||
{
|
|
||||||
if (dirty) {
|
|
||||||
memset(characters, ' ', m_length);
|
|
||||||
for (u16 i = 0; i < m_length; ++i)
|
|
||||||
attributes[i] = attribute;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (unsigned i = 0; i < m_length; ++i) {
|
|
||||||
if (characters[i] != ' ')
|
|
||||||
dirty = true;
|
|
||||||
characters[i] = ' ';
|
|
||||||
}
|
|
||||||
for (unsigned i = 0; i < m_length; ++i) {
|
|
||||||
if (attributes[i] != attribute)
|
|
||||||
dirty = true;
|
|
||||||
attributes[i] = attribute;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Terminal::Line::has_only_one_background_color() const
|
|
||||||
{
|
|
||||||
if (!m_length)
|
|
||||||
return true;
|
|
||||||
// FIXME: Cache this result?
|
|
||||||
auto color = attributes[0].background_color;
|
|
||||||
for (size_t i = 1; i < m_length; ++i) {
|
|
||||||
if (attributes[i].background_color != color)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Terminal::clear()
|
void Terminal::clear()
|
||||||
{
|
{
|
||||||
|
@ -590,14 +528,14 @@ void Terminal::escape$P(const ParamVector& params)
|
||||||
auto& line = m_lines[m_cursor_row];
|
auto& line = m_lines[m_cursor_row];
|
||||||
|
|
||||||
// Move n characters of line to the left
|
// Move n characters of line to the left
|
||||||
for (int i = m_cursor_column; i < line.m_length - num; i++)
|
for (int i = m_cursor_column; i < line.length() - num; i++)
|
||||||
line.characters[i] = line.characters[i + num];
|
line.characters()[i] = line.characters()[i + num];
|
||||||
|
|
||||||
// Fill remainder of line with blanks
|
// Fill remainder of line with blanks
|
||||||
for (int i = line.m_length - num; i < line.m_length; i++)
|
for (int i = line.length() - num; i < line.length(); i++)
|
||||||
line.characters[i] = ' ';
|
line.characters()[i] = ' ';
|
||||||
|
|
||||||
line.dirty = true;
|
line.set_dirty(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Terminal::execute_xterm_command()
|
void Terminal::execute_xterm_command()
|
||||||
|
@ -828,10 +766,10 @@ void Terminal::put_character_at(unsigned row, unsigned column, u8 ch)
|
||||||
ASSERT(row < rows());
|
ASSERT(row < rows());
|
||||||
ASSERT(column < columns());
|
ASSERT(column < columns());
|
||||||
auto& line = m_lines[row];
|
auto& line = m_lines[row];
|
||||||
line.characters[column] = ch;
|
line.characters()[column] = ch;
|
||||||
line.attributes[column] = m_current_attribute;
|
line.attributes()[column] = m_current_attribute;
|
||||||
line.attributes[column].flags |= Attribute::Touched;
|
line.attributes()[column].flags |= Attribute::Touched;
|
||||||
line.dirty = true;
|
line.set_dirty(true);
|
||||||
|
|
||||||
m_last_char = ch;
|
m_last_char = ch;
|
||||||
}
|
}
|
||||||
|
@ -1087,7 +1025,7 @@ void Terminal::set_size(u16 columns, u16 rows)
|
||||||
|
|
||||||
void Terminal::invalidate_cursor()
|
void Terminal::invalidate_cursor()
|
||||||
{
|
{
|
||||||
m_lines[m_cursor_row].dirty = true;
|
m_lines[m_cursor_row].set_dirty(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Terminal::execute_hashtag(u8 hashtag)
|
void Terminal::execute_hashtag(u8 hashtag)
|
||||||
|
@ -1113,9 +1051,9 @@ Attribute Terminal::attribute_at(const Position& position) const
|
||||||
if (position.row() >= static_cast<int>(line_count()))
|
if (position.row() >= static_cast<int>(line_count()))
|
||||||
return {};
|
return {};
|
||||||
auto& line = this->line(position.row());
|
auto& line = this->line(position.row());
|
||||||
if (position.column() >= line.m_length)
|
if (position.column() >= line.length())
|
||||||
return {};
|
return {};
|
||||||
return line.attributes[position.column()];
|
return line.attributes()[position.column()];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,14 +30,14 @@
|
||||||
#include <AK/NonnullOwnPtrVector.h>
|
#include <AK/NonnullOwnPtrVector.h>
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
|
#include <LibVT/Line.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;
|
||||||
|
@ -46,50 +46,6 @@ public:
|
||||||
virtual void emit(const u8*, size_t) = 0;
|
virtual void emit(const u8*, size_t) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Attribute {
|
|
||||||
Attribute() { reset(); }
|
|
||||||
|
|
||||||
static const u32 default_foreground_color = xterm_colors[7];
|
|
||||||
static const u32 default_background_color = xterm_colors[0];
|
|
||||||
|
|
||||||
void reset()
|
|
||||||
{
|
|
||||||
foreground_color = default_foreground_color;
|
|
||||||
background_color = default_background_color;
|
|
||||||
flags = Flags::NoAttributes;
|
|
||||||
}
|
|
||||||
u32 foreground_color;
|
|
||||||
u32 background_color;
|
|
||||||
|
|
||||||
String href;
|
|
||||||
String href_id;
|
|
||||||
|
|
||||||
enum Flags : u8 {
|
|
||||||
NoAttributes = 0x00,
|
|
||||||
Bold = 0x01,
|
|
||||||
Italic = 0x02,
|
|
||||||
Underline = 0x04,
|
|
||||||
Negative = 0x08,
|
|
||||||
Blink = 0x10,
|
|
||||||
Touched = 0x20,
|
|
||||||
};
|
|
||||||
|
|
||||||
bool is_untouched() const { return !(flags & Touched); }
|
|
||||||
|
|
||||||
// TODO: it would be really nice if we had a helper for enums that
|
|
||||||
// exposed bit ops for class enums...
|
|
||||||
u8 flags = Flags::NoAttributes;
|
|
||||||
|
|
||||||
bool operator==(const Attribute& other) const
|
|
||||||
{
|
|
||||||
return foreground_color == other.foreground_color && background_color == other.background_color && flags == other.flags;
|
|
||||||
}
|
|
||||||
bool operator!=(const Attribute& other) const
|
|
||||||
{
|
|
||||||
return !(*this == other);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class Terminal {
|
class Terminal {
|
||||||
public:
|
public:
|
||||||
explicit Terminal(TerminalClient&);
|
explicit Terminal(TerminalClient&);
|
||||||
|
@ -108,24 +64,6 @@ public:
|
||||||
u16 cursor_column() const { return m_cursor_column; }
|
u16 cursor_column() const { return m_cursor_column; }
|
||||||
u16 cursor_row() const { return m_cursor_row; }
|
u16 cursor_row() const { return m_cursor_row; }
|
||||||
|
|
||||||
struct Line {
|
|
||||||
AK_MAKE_NONCOPYABLE(Line);
|
|
||||||
AK_MAKE_NONMOVABLE(Line);
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit Line(u16 columns);
|
|
||||||
~Line();
|
|
||||||
void clear(Attribute);
|
|
||||||
bool has_only_one_background_color() const;
|
|
||||||
void set_length(u16);
|
|
||||||
StringView text() const { return { characters, m_length }; }
|
|
||||||
|
|
||||||
u8* characters { nullptr };
|
|
||||||
Attribute* attributes { nullptr };
|
|
||||||
bool dirty { false };
|
|
||||||
u16 m_length { 0 };
|
|
||||||
};
|
|
||||||
|
|
||||||
size_t line_count() const
|
size_t line_count() const
|
||||||
{
|
{
|
||||||
return m_history.size() + m_lines.size();
|
return m_history.size() + m_lines.size();
|
||||||
|
|
|
@ -336,7 +336,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, color_from_rgb(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
|
||||||
|
@ -369,7 +369,7 @@ void TerminalWidget::paint_event(GUI::PaintEvent& event)
|
||||||
&& visual_row == row_with_cursor
|
&& visual_row == row_with_cursor
|
||||||
&& column == m_terminal.cursor_column();
|
&& column == m_terminal.cursor_column();
|
||||||
should_reverse_fill_for_cursor_or_selection |= selection_contains({ first_row_from_history + visual_row, column });
|
should_reverse_fill_for_cursor_or_selection |= selection_contains({ first_row_from_history + visual_row, column });
|
||||||
attribute = line.attributes[column];
|
attribute = line.attributes()[column];
|
||||||
text_color = color_from_rgb(should_reverse_fill_for_cursor_or_selection ? attribute.background_color : attribute.foreground_color);
|
text_color = color_from_rgb(should_reverse_fill_for_cursor_or_selection ? attribute.background_color : attribute.foreground_color);
|
||||||
auto character_rect = glyph_rect(visual_row, column);
|
auto character_rect = glyph_rect(visual_row, column);
|
||||||
auto cell_rect = character_rect.inflated(0, m_line_spacing);
|
auto cell_rect = character_rect.inflated(0, m_line_spacing);
|
||||||
|
@ -430,7 +430,7 @@ void TerminalWidget::paint_event(GUI::PaintEvent& event)
|
||||||
auto& cursor_line = m_terminal.line(first_row_from_history + row_with_cursor);
|
auto& cursor_line = m_terminal.line(first_row_from_history + 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, color_from_rgb(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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -456,9 +456,9 @@ void TerminalWidget::flush_dirty_lines()
|
||||||
}
|
}
|
||||||
Gfx::Rect rect;
|
Gfx::Rect rect;
|
||||||
for (int i = 0; i < m_terminal.rows(); ++i) {
|
for (int i = 0; i < m_terminal.rows(); ++i) {
|
||||||
if (m_terminal.visible_line(i).dirty) {
|
if (m_terminal.visible_line(i).is_dirty()) {
|
||||||
rect = rect.united(row_rect(i));
|
rect = rect.united(row_rect(i));
|
||||||
m_terminal.visible_line(i).dirty = false;
|
m_terminal.visible_line(i).set_dirty(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
update(rect);
|
update(rect);
|
||||||
|
@ -583,16 +583,16 @@ void TerminalWidget::doubleclick_event(GUI::MouseEvent& event)
|
||||||
|
|
||||||
auto position = buffer_position_at(event.position());
|
auto position = buffer_position_at(event.position());
|
||||||
auto& line = m_terminal.line(position.row());
|
auto& line = m_terminal.line(position.row());
|
||||||
bool want_whitespace = line.characters[position.column()] == ' ';
|
bool want_whitespace = line.characters()[position.column()] == ' ';
|
||||||
|
|
||||||
int start_column = 0;
|
int start_column = 0;
|
||||||
int end_column = 0;
|
int end_column = 0;
|
||||||
|
|
||||||
for (int column = position.column(); column >= 0 && (line.characters[column] == ' ') == want_whitespace; --column) {
|
for (int column = position.column(); column >= 0 && (line.characters()[column] == ' ') == want_whitespace; --column) {
|
||||||
start_column = column;
|
start_column = column;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int column = position.column(); column < m_terminal.columns() && (line.characters[column] == ' ') == want_whitespace; ++column) {
|
for (int column = position.column(); column < m_terminal.columns() && (line.characters()[column] == ' ') == want_whitespace; ++column) {
|
||||||
end_column = column;
|
end_column = column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -758,12 +758,12 @@ String TerminalWidget::selected_text() const
|
||||||
int last_column = last_selection_column_on_row(row);
|
int last_column = last_selection_column_on_row(row);
|
||||||
for (int column = first_column; column <= last_column; ++column) {
|
for (int column = first_column; column <= last_column; ++column) {
|
||||||
auto& line = m_terminal.line(row);
|
auto& line = m_terminal.line(row);
|
||||||
if (line.attributes[column].is_untouched()) {
|
if (line.attributes()[column].is_untouched()) {
|
||||||
builder.append('\n');
|
builder.append('\n');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
builder.append(line.characters[column]);
|
builder.append(line.characters()[column]);
|
||||||
if (column == line.m_length - 1 || (m_rectangle_selection && column == last_column)) {
|
if (column == line.length() - 1 || (m_rectangle_selection && column == last_column)) {
|
||||||
builder.append('\n');
|
builder.append('\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue