Only redraw updated lines
This commit is contained in:
parent
07750656a8
commit
9e8f555a82
|
@ -49,8 +49,20 @@ struct TerminalUI::Window::Line
|
||||||
{
|
{
|
||||||
String text;
|
String text;
|
||||||
Face face;
|
Face face;
|
||||||
|
|
||||||
|
friend bool operator==(const Atom& lhs, const Atom& rhs) { return lhs.text == rhs.text and lhs.face == rhs.face; }
|
||||||
|
friend bool operator!=(const Atom& lhs, const Atom& rhs) { return not (lhs == rhs); }
|
||||||
|
friend size_t hash_value(const Atom& atom) { return hash_values(atom.text, atom.face); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void append(String text, Face face)
|
||||||
|
{
|
||||||
|
if (not atoms.empty() and atoms.back().face == face)
|
||||||
|
atoms.back().text += text;
|
||||||
|
else
|
||||||
|
atoms.push_back({std::move(text), face});
|
||||||
|
}
|
||||||
|
|
||||||
void resize(ColumnCount width)
|
void resize(ColumnCount width)
|
||||||
{
|
{
|
||||||
auto it = atoms.begin();
|
auto it = atoms.begin();
|
||||||
|
@ -59,7 +71,7 @@ struct TerminalUI::Window::Line
|
||||||
column += it->text.column_length();
|
column += it->text.column_length();
|
||||||
|
|
||||||
if (column < width)
|
if (column < width)
|
||||||
atoms.push_back(Atom{String{' ', width - column}, atoms.empty() ? Face{} : atoms.back().face});
|
append(String{' ', width - column}, atoms.empty() ? Face{} : atoms.back().face);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
atoms.erase(it, atoms.end());
|
atoms.erase(it, atoms.end());
|
||||||
|
@ -122,7 +134,37 @@ void TerminalUI::Window::blit(Window& target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminalUI::Window::output()
|
void TerminalUI::Window::move_cursor(DisplayCoord coord)
|
||||||
|
{
|
||||||
|
cursor = {std::min(size.line-1, coord.line), std::min(size.column-1, coord.column)};
|
||||||
|
}
|
||||||
|
|
||||||
|
void TerminalUI::Window::draw(ConstArrayView<DisplayAtom> atoms,
|
||||||
|
const Face& default_face)
|
||||||
|
{
|
||||||
|
lines[(size_t)cursor.line].resize(cursor.column);
|
||||||
|
for (const DisplayAtom& atom : atoms)
|
||||||
|
{
|
||||||
|
StringView content = atom.content();
|
||||||
|
if (content.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto face = merge_faces(default_face, atom.face);
|
||||||
|
if (content.back() == '\n')
|
||||||
|
{
|
||||||
|
lines[(int)cursor.line].append(content.substr(0, content.length()-1).str(), face);
|
||||||
|
lines[(int)cursor.line].append(" ", face);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
lines[(int)cursor.line].append(content.str(), face);
|
||||||
|
cursor.column += content.column_length();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursor.column < size.column)
|
||||||
|
lines[(int)cursor.line].append(String(' ', size.column - cursor.column), default_face);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TerminalUI::Screen::output(bool force)
|
||||||
{
|
{
|
||||||
if (lines.empty())
|
if (lines.empty())
|
||||||
return;
|
return;
|
||||||
|
@ -148,50 +190,29 @@ void TerminalUI::Window::output()
|
||||||
DisplayCoord cursor_pos = pos;
|
DisplayCoord cursor_pos = pos;
|
||||||
for (auto& line : lines)
|
for (auto& line : lines)
|
||||||
{
|
{
|
||||||
set_cursor_pos(cursor_pos);
|
auto line_hash = hash_value(line.atoms);
|
||||||
for (auto& atom : line.atoms)
|
if (force or cursor_pos.line >= hashes.size() or
|
||||||
|
line_hash != hashes[(size_t)cursor_pos.line])
|
||||||
{
|
{
|
||||||
printf("\033[");
|
set_cursor_pos(cursor_pos);
|
||||||
set_attributes(atom.face.attributes);
|
for (auto& atom : line.atoms)
|
||||||
set_color(true, atom.face.fg);
|
{
|
||||||
set_color(false, atom.face.bg);
|
printf("\033[");
|
||||||
printf("m");
|
set_attributes(atom.face.attributes);
|
||||||
fputs(atom.text.c_str(), stdout);
|
set_color(true, atom.face.fg);
|
||||||
|
set_color(false, atom.face.bg);
|
||||||
|
printf("m");
|
||||||
|
fputs(atom.text.c_str(), stdout);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (hashes.size() <= cursor_pos.line)
|
||||||
|
hashes.push_back(line_hash);
|
||||||
|
else
|
||||||
|
hashes[(size_t)cursor_pos.line] = line_hash;
|
||||||
++cursor_pos.line;
|
++cursor_pos.line;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminalUI::Window::move_cursor(DisplayCoord coord)
|
|
||||||
{
|
|
||||||
cursor = {std::min(size.line-1, coord.line), std::min(size.column-1, coord.column)};
|
|
||||||
}
|
|
||||||
|
|
||||||
void TerminalUI::Window::draw(ConstArrayView<DisplayAtom> atoms,
|
|
||||||
const Face& default_face)
|
|
||||||
{
|
|
||||||
lines[(size_t)cursor.line].resize(cursor.column);
|
|
||||||
for (const DisplayAtom& atom : atoms)
|
|
||||||
{
|
|
||||||
StringView content = atom.content();
|
|
||||||
if (content.empty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
auto face = merge_faces(default_face, atom.face);
|
|
||||||
if (content.back() == '\n')
|
|
||||||
{
|
|
||||||
lines[(int)cursor.line].atoms.push_back({content.substr(0, content.length()-1).str(), face});
|
|
||||||
lines[(int)cursor.line].atoms.push_back({" ", face});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
lines[(int)cursor.line].atoms.push_back({content.str(), face});
|
|
||||||
cursor.column += content.column_length();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cursor.column < size.column)
|
|
||||||
lines[(int)cursor.line].atoms.push_back({String(' ', size.column - cursor.column), default_face});
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr int TerminalUI::default_shift_function_key;
|
constexpr int TerminalUI::default_shift_function_key;
|
||||||
|
|
||||||
static constexpr StringView assistant_cat[] =
|
static constexpr StringView assistant_cat[] =
|
||||||
|
@ -334,7 +355,7 @@ void TerminalUI::redraw(bool force)
|
||||||
|
|
||||||
m_info.blit(m_screen);
|
m_info.blit(m_screen);
|
||||||
|
|
||||||
m_screen.output();
|
m_screen.output(force);
|
||||||
if (m_cursor.mode == CursorMode::Prompt)
|
if (m_cursor.mode == CursorMode::Prompt)
|
||||||
set_cursor_pos({m_status_on_top ? 0 : m_dimensions.line, m_cursor.coord.column});
|
set_cursor_pos({m_status_on_top ? 0 : m_dimensions.line, m_cursor.coord.column});
|
||||||
else
|
else
|
||||||
|
@ -462,6 +483,7 @@ void TerminalUI::check_resize(bool force)
|
||||||
|
|
||||||
m_window.create({0, 0}, {ws.ws_row, ws.ws_col});
|
m_window.create({0, 0}, {ws.ws_row, ws.ws_col});
|
||||||
m_screen.create({0, 0}, {ws.ws_row, ws.ws_col});
|
m_screen.create({0, 0}, {ws.ws_row, ws.ws_col});
|
||||||
|
m_screen.hashes.clear();
|
||||||
kak_assert(m_window);
|
kak_assert(m_window);
|
||||||
|
|
||||||
m_dimensions = DisplayCoord{ws.ws_row-1, ws.ws_col};
|
m_dimensions = DisplayCoord{ws.ws_row-1, ws.ws_col};
|
||||||
|
|
|
@ -78,7 +78,6 @@ private:
|
||||||
void create(const DisplayCoord& pos, const DisplayCoord& size);
|
void create(const DisplayCoord& pos, const DisplayCoord& size);
|
||||||
void destroy();
|
void destroy();
|
||||||
void blit(Window& target);
|
void blit(Window& target);
|
||||||
void output();
|
|
||||||
void move_cursor(DisplayCoord coord);
|
void move_cursor(DisplayCoord coord);
|
||||||
void draw(ConstArrayView<DisplayAtom> atoms, const Face& default_face);
|
void draw(ConstArrayView<DisplayAtom> atoms, const Face& default_face);
|
||||||
|
|
||||||
|
@ -89,8 +88,14 @@ private:
|
||||||
DisplayCoord cursor;
|
DisplayCoord cursor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Screen : Window
|
||||||
|
{
|
||||||
|
void output(bool force);
|
||||||
|
Vector<size_t> hashes;
|
||||||
|
};
|
||||||
|
|
||||||
Window m_window;
|
Window m_window;
|
||||||
Window m_screen;
|
Screen m_screen;
|
||||||
|
|
||||||
DisplayCoord m_dimensions;
|
DisplayCoord m_dimensions;
|
||||||
termios m_original_termios{};
|
termios m_original_termios{};
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define vector_hh_INCLUDED
|
#define vector_hh_INCLUDED
|
||||||
|
|
||||||
#include "memory.hh"
|
#include "memory.hh"
|
||||||
|
#include "hash.hh"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -11,6 +12,15 @@ namespace Kakoune
|
||||||
template<typename T, MemoryDomain domain = memory_domain(Meta::Type<T>{})>
|
template<typename T, MemoryDomain domain = memory_domain(Meta::Type<T>{})>
|
||||||
using Vector = std::vector<T, Allocator<T, domain>>;
|
using Vector = std::vector<T, Allocator<T, domain>>;
|
||||||
|
|
||||||
|
template<typename T, MemoryDomain domain>
|
||||||
|
size_t hash_value(const Vector<T, domain>& vector)
|
||||||
|
{
|
||||||
|
size_t hash = 0x1235678;
|
||||||
|
for (auto&& elem : vector)
|
||||||
|
hash = combine_hash(hash, hash_value(elem));
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // vector_hh_INCLUDED
|
#endif // vector_hh_INCLUDED
|
||||||
|
|
Loading…
Reference in New Issue
Block a user