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;
// Range of lines and columns from the buffer that will get displayed
DisplayCoord window_range;
// Offset of line and columns that must remain visible around cursor
DisplayCoord scroll_offset;
// Position of the cursor in the window
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 compute_display_setup(const Context& context, HighlightPass pass,
DisplayCoord scroll_offset, DisplaySetup& setup) {}
DisplaySetup& setup) {}
virtual bool has_children() const { return false; }
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,
DisplayCoord scroll_offset, DisplaySetup& setup)
DisplaySetup& setup)
{
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)

View File

@ -20,7 +20,7 @@ public:
void highlight(const Context& context, HighlightPass pass, DisplayBuffer& display_buffer, BufferRange range) override;
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; }
void add_child(HighlighterAndId&& hl) override;

View File

@ -719,12 +719,12 @@ struct WrapHighlighter : Highlighter
}
void compute_display_setup(const Context& context, HighlightPass pass,
DisplayCoord scroll_offset, DisplaySetup& setup) override
DisplaySetup& setup) override
{
if (pass != HighlightPass::Wrap)
return;
ColumnCount column = context.window().display_setup().window_range.column;
ColumnCount column = setup.window_range.column;
if (column < 0)
return;
@ -752,9 +752,11 @@ struct WrapHighlighter : Highlighter
setup.cursor_pos.line += (int)(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)
setup.window_pos.column = new_cursor_buffer_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 - setup.scroll_offset.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);
@ -775,8 +777,10 @@ struct WrapHighlighter : Highlighter
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;
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,
DisplayCoord scroll_offset, DisplaySetup& setup) override
DisplaySetup& setup) override
{
if (pass != HighlightPass::Move)
return;
ColumnCount width = compute_digit_count(context) + m_separator.column_length();
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)
@ -1171,7 +1170,7 @@ struct FlagLinesHighlighter : Highlighter
}
void compute_display_setup(const Context& context, HighlightPass pass,
DisplayCoord scroll_offset, DisplaySetup& setup) override
DisplaySetup& setup) override
{
if (pass != HighlightPass::Move)
return;
@ -1185,11 +1184,6 @@ struct FlagLinesHighlighter : Highlighter
width = std::max(parse_display_line(std::get<1>(line)).length(), 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)

View File

@ -122,8 +122,7 @@ const DisplayBuffer& Window::update_display_buffer(const Context& context)
return m_display_buffer;
kak_assert(&buffer() == &context.buffer());
m_display_setup = compute_display_setup(context);
m_position = m_display_setup.window_pos;
compute_display_setup(context);
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>
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)
void Window::compute_display_setup(const Context& context)
{
DisplayCoord offset = options()["scrolloff"].get<DisplayCoord>();
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();
m_position.line = adapt_view_pos(cursor.line, offset.line,
m_position.line, m_dimensions.line);
// Ensure cursor line is visible
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>();
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_dimensions,
offset,
DisplayCoord{cursor.line - m_position.line, cursor_col - m_position.column}
};
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 })
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

View File

@ -53,7 +53,7 @@ private:
Window(const Window&) = delete;
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,
String client_name = "");
@ -63,8 +63,8 @@ private:
DisplayCoord m_position;
DisplayCoord m_dimensions;
DisplayBuffer m_display_buffer;
DisplaySetup m_display_setup;
DisplayBuffer m_display_buffer;
HighlighterGroup m_highlighters;
HighlighterGroup m_builtin_highlighters;