Make scrolling around work more correctly with wrapping

This commit is contained in:
Maxime Coste 2017-05-01 20:55:18 +01:00
parent bd3ba77e96
commit 39826afde5
6 changed files with 46 additions and 46 deletions

View File

@ -39,7 +39,8 @@ struct DisplaySetup
DisplayCoord window_pos; DisplayCoord window_pos;
// Range of lines and columns from the buffer that will get displayed // Range of lines and columns from the buffer that will get displayed
DisplayCoord window_range; DisplayCoord window_range;
// Offset of line and columns that must remain visible around cursor
DisplayCoord scroll_offset;
// Position of the cursor in the window // Position of the cursor in the window
DisplayCoord cursor_pos; DisplayCoord cursor_pos;
}; };
@ -50,7 +51,7 @@ struct Highlighter
virtual void highlight(const Context& context, HighlightPass pass, DisplayBuffer& display_buffer, BufferRange range) = 0; virtual void highlight(const Context& context, HighlightPass pass, DisplayBuffer& display_buffer, BufferRange range) = 0;
virtual void compute_display_setup(const Context& context, HighlightPass pass, virtual void compute_display_setup(const Context& context, HighlightPass pass,
DisplayCoord scroll_offset, DisplaySetup& setup) {} DisplaySetup& setup) {}
virtual bool has_children() const { return false; } virtual bool has_children() const { return false; }
virtual Highlighter& get_child(StringView path) { throw runtime_error("this highlighter do not hold children"); } virtual Highlighter& get_child(StringView path) { throw runtime_error("this highlighter do not hold children"); }

View File

@ -13,10 +13,10 @@ void HighlighterGroup::highlight(const Context& context, HighlightPass pass,
} }
void HighlighterGroup::compute_display_setup(const Context& context, HighlightPass pass, void HighlighterGroup::compute_display_setup(const Context& context, HighlightPass pass,
DisplayCoord scroll_offset, DisplaySetup& setup) DisplaySetup& setup)
{ {
for (auto& hl : m_highlighters) for (auto& hl : m_highlighters)
hl.value->compute_display_setup(context, pass, scroll_offset, setup); hl.value->compute_display_setup(context, pass, setup);
} }
void HighlighterGroup::add_child(HighlighterAndId&& hl) void HighlighterGroup::add_child(HighlighterAndId&& hl)

View File

@ -20,7 +20,7 @@ public:
void highlight(const Context& context, HighlightPass pass, DisplayBuffer& display_buffer, BufferRange range) override; void highlight(const Context& context, HighlightPass pass, DisplayBuffer& display_buffer, BufferRange range) override;
void compute_display_setup(const Context& context, HighlightPass pass, void compute_display_setup(const Context& context, HighlightPass pass,
DisplayCoord scroll_offset, DisplaySetup& setup) override; DisplaySetup& setup) override;
bool has_children() const override { return true; } bool has_children() const override { return true; }
void add_child(HighlighterAndId&& hl) override; void add_child(HighlighterAndId&& hl) override;

View File

@ -719,12 +719,12 @@ struct WrapHighlighter : Highlighter
} }
void compute_display_setup(const Context& context, HighlightPass pass, void compute_display_setup(const Context& context, HighlightPass pass,
DisplayCoord scroll_offset, DisplaySetup& setup) override DisplaySetup& setup) override
{ {
if (pass != HighlightPass::Wrap) if (pass != HighlightPass::Wrap)
return; return;
ColumnCount column = context.window().display_setup().window_range.column; ColumnCount column = setup.window_range.column;
if (column < 0) if (column < 0)
return; return;
@ -752,9 +752,11 @@ struct WrapHighlighter : Highlighter
setup.cursor_pos.line += (int)(cursor_buffer_column / column); setup.cursor_pos.line += (int)(cursor_buffer_column / column);
auto new_cursor_buffer_column = (cursor_buffer_column % column); auto new_cursor_buffer_column = (cursor_buffer_column % column);
if (new_cursor_buffer_column < setup.window_pos.column + scroll_offset.column) if (new_cursor_buffer_column < setup.window_pos.column + setup.scroll_offset.column)
setup.window_pos.column = new_cursor_buffer_column - scroll_offset.column; setup.window_pos.column = new_cursor_buffer_column - setup.scroll_offset.column;
setup.cursor_pos.column = new_cursor_buffer_column - setup.window_pos.column; setup.cursor_pos.column = new_cursor_buffer_column - setup.window_pos.column;
kak_assert(setup.cursor_pos.column >= 0 and setup.cursor_pos.column < setup.window_range.column);
} }
const auto wrap_count = line_wrap_count(buf_line); const auto wrap_count = line_wrap_count(buf_line);
@ -775,8 +777,10 @@ struct WrapHighlighter : Highlighter
setup.window_range.line += removed_lines - 1; setup.window_range.line += removed_lines - 1;
} }
if (setup.window_range.line < buf_line - setup.window_pos.line + 1) if (setup.window_range.line <= buf_line - setup.window_pos.line)
setup.window_range.line = buf_line - setup.window_pos.line + 1; setup.window_range.line = buf_line - setup.window_pos.line + 1;
kak_assert(setup.cursor_pos.line >= 0 and setup.cursor_pos.line < win_height);
} }
} }
@ -941,18 +945,13 @@ struct LineNumbersHighlighter : Highlighter
} }
void compute_display_setup(const Context& context, HighlightPass pass, void compute_display_setup(const Context& context, HighlightPass pass,
DisplayCoord scroll_offset, DisplaySetup& setup) override DisplaySetup& setup) override
{ {
if (pass != HighlightPass::Move) if (pass != HighlightPass::Move)
return; return;
ColumnCount width = compute_digit_count(context) + m_separator.column_length(); ColumnCount width = compute_digit_count(context) + m_separator.column_length();
setup.window_range.column -= width; setup.window_range.column -= width;
auto cursor_overflow = setup.cursor_pos.column + scroll_offset.column -
setup.window_range.column + 1;
if (cursor_overflow > 0)
setup.window_pos.column += cursor_overflow;
} }
static HighlighterAndId create(HighlighterParameters params) static HighlighterAndId create(HighlighterParameters params)
@ -1171,7 +1170,7 @@ struct FlagLinesHighlighter : Highlighter
} }
void compute_display_setup(const Context& context, HighlightPass pass, void compute_display_setup(const Context& context, HighlightPass pass,
DisplayCoord scroll_offset, DisplaySetup& setup) override DisplaySetup& setup) override
{ {
if (pass != HighlightPass::Move) if (pass != HighlightPass::Move)
return; return;
@ -1185,11 +1184,6 @@ struct FlagLinesHighlighter : Highlighter
width = std::max(parse_display_line(std::get<1>(line)).length(), width); width = std::max(parse_display_line(std::get<1>(line)).length(), width);
setup.window_range.column -= width; setup.window_range.column -= width;
auto cursor_overflow = setup.cursor_pos.column + scroll_offset.column -
setup.window_range.column + 1;
if (cursor_overflow > 0)
setup.window_pos.column += cursor_overflow;
} }
static HighlighterAndId create(HighlighterParameters params) static HighlighterAndId create(HighlighterParameters params)

View File

@ -122,8 +122,7 @@ const DisplayBuffer& Window::update_display_buffer(const Context& context)
return m_display_buffer; return m_display_buffer;
kak_assert(&buffer() == &context.buffer()); kak_assert(&buffer() == &context.buffer());
m_display_setup = compute_display_setup(context); compute_display_setup(context);
m_position = m_display_setup.window_pos;
for (LineCount line = 0; line < m_display_setup.window_range.line; ++line) for (LineCount line = 0; line < m_display_setup.window_range.line; ++line)
{ {
@ -174,18 +173,7 @@ void Window::set_dimensions(DisplayCoord dimensions)
} }
} }
template<typename Unit> void Window::compute_display_setup(const Context& context)
static Unit adapt_view_pos(Unit pos, Unit offset,
Unit view_pos, Unit view_size)
{
if (pos - offset < view_pos)
return std::max(Unit{0}, pos - offset);
else if (pos + offset >= view_pos + view_size)
return std::max(Unit{0}, pos + offset - view_size + 1);
return view_pos;
}
DisplaySetup Window::compute_display_setup(const Context& context)
{ {
DisplayCoord offset = options()["scrolloff"].get<DisplayCoord>(); DisplayCoord offset = options()["scrolloff"].get<DisplayCoord>();
offset.line = std::min(offset.line, (m_dimensions.line + 1) / 2); offset.line = std::min(offset.line, (m_dimensions.line + 1) / 2);
@ -193,25 +181,42 @@ DisplaySetup Window::compute_display_setup(const Context& context)
const auto& cursor = context.selections().main().cursor(); const auto& cursor = context.selections().main().cursor();
m_position.line = adapt_view_pos(cursor.line, offset.line, // Ensure cursor line is visible
m_position.line, m_dimensions.line); if (cursor.line - offset.line < m_position.line)
m_position.line = cursor.line - offset.line;
if (cursor.line + offset.line >= m_position.line + m_dimensions.line)
m_position.line = cursor.line + offset.line - m_dimensions.line + 1;
const int tabstop = context.options()["tabstop"].get<int>(); const int tabstop = context.options()["tabstop"].get<int>();
auto cursor_col = get_column(buffer(), tabstop, cursor); auto cursor_col = get_column(buffer(), tabstop, cursor);
m_position.column = adapt_view_pos(cursor_col, offset.column,
m_position.column, m_dimensions.column);
DisplaySetup setup{ m_display_setup = DisplaySetup{
m_position, m_position,
m_dimensions, m_dimensions,
offset,
DisplayCoord{cursor.line - m_position.line, cursor_col - m_position.column} DisplayCoord{cursor.line - m_position.line, cursor_col - m_position.column}
}; };
for (auto pass : { HighlightPass::Move, HighlightPass::Wrap }) for (auto pass : { HighlightPass::Move, HighlightPass::Wrap })
m_highlighters.compute_display_setup(context, pass, offset, setup); m_highlighters.compute_display_setup(context, pass, m_display_setup);
for (auto pass : { HighlightPass::Move, HighlightPass::Wrap }) for (auto pass : { HighlightPass::Move, HighlightPass::Wrap })
m_builtin_highlighters.compute_display_setup(context, pass, offset, setup); m_builtin_highlighters.compute_display_setup(context, pass, m_display_setup);
return setup; // now ensure the cursor column is visible
{
auto underflow = m_display_setup.cursor_pos.column - m_display_setup.scroll_offset.column;
if (underflow < 0)
{
m_display_setup.window_pos.column += underflow;
m_display_setup.cursor_pos.column -= underflow;
}
auto overflow = m_display_setup.cursor_pos.column + m_display_setup.scroll_offset.column - m_display_setup.window_range.column + 1;
if (overflow > 0)
{
m_display_setup.window_pos.column += overflow;
m_display_setup.cursor_pos.column -= overflow;
}
}
m_position = m_display_setup.window_pos;
} }
namespace namespace

View File

@ -53,7 +53,7 @@ private:
Window(const Window&) = delete; Window(const Window&) = delete;
void on_option_changed(const Option& option) override; void on_option_changed(const Option& option) override;
DisplaySetup compute_display_setup(const Context& context); void compute_display_setup(const Context& context);
void run_hook_in_own_context(StringView hook_name, StringView param, void run_hook_in_own_context(StringView hook_name, StringView param,
String client_name = ""); String client_name = "");
@ -63,8 +63,8 @@ private:
DisplayCoord m_position; DisplayCoord m_position;
DisplayCoord m_dimensions; DisplayCoord m_dimensions;
DisplayBuffer m_display_buffer;
DisplaySetup m_display_setup; DisplaySetup m_display_setup;
DisplayBuffer m_display_buffer;
HighlighterGroup m_highlighters; HighlighterGroup m_highlighters;
HighlighterGroup m_builtin_highlighters; HighlighterGroup m_builtin_highlighters;