diff --git a/src/highlighter.hh b/src/highlighter.hh index e35704cb..06c9796d 100644 --- a/src/highlighter.hh +++ b/src/highlighter.hh @@ -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"); } diff --git a/src/highlighter_group.cc b/src/highlighter_group.cc index a5df36b1..1d3defac 100644 --- a/src/highlighter_group.cc +++ b/src/highlighter_group.cc @@ -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) diff --git a/src/highlighter_group.hh b/src/highlighter_group.hh index fbb9d1c9..763fbbb7 100644 --- a/src/highlighter_group.hh +++ b/src/highlighter_group.hh @@ -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; diff --git a/src/highlighters.cc b/src/highlighters.cc index ac469d56..9a57d461 100644 --- a/src/highlighters.cc +++ b/src/highlighters.cc @@ -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) diff --git a/src/window.cc b/src/window.cc index 430085d4..ffe15687 100644 --- a/src/window.cc +++ b/src/window.cc @@ -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 -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(); 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(); 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 diff --git a/src/window.hh b/src/window.hh index 36bc0bd3..b287c80b 100644 --- a/src/window.hh +++ b/src/window.hh @@ -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;