Only redraw updated lines

This commit is contained in:
Maxime Coste 2019-12-01 11:09:01 +11:00
parent 07750656a8
commit 9e8f555a82
3 changed files with 80 additions and 43 deletions

View File

@ -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;
@ -147,6 +189,10 @@ void TerminalUI::Window::output()
DisplayCoord cursor_pos = pos; DisplayCoord cursor_pos = pos;
for (auto& line : lines) for (auto& line : lines)
{
auto line_hash = hash_value(line.atoms);
if (force or cursor_pos.line >= hashes.size() or
line_hash != hashes[(size_t)cursor_pos.line])
{ {
set_cursor_pos(cursor_pos); set_cursor_pos(cursor_pos);
for (auto& atom : line.atoms) for (auto& atom : line.atoms)
@ -158,40 +204,15 @@ void TerminalUI::Window::output()
printf("m"); printf("m");
fputs(atom.text.c_str(), stdout); 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};

View File

@ -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{};

View File

@ -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