summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2025-06-25 10:59:10 +1000
committerMaxime Coste <mawww@kakoune.org>2025-06-25 11:15:23 +1000
commit635452f2b47cdddb5118f07fe831224c93eb9803 (patch)
treec6f4fcc7c57fc7af800d9d7d3d9b3b8b81b4442f /src
parentfc013317fff00f4db66c3059ad87343656a4d9d9 (diff)
Rework highlighting management of cursor position
Move the whole responsibility of making the cursor visible to the window, removing cursor_pos from the display setup and resolving the cursor location by finding it in the display buffer afterwards. This simplifies hightlighters' do_compute_display_setup as they do not need to compute the cursor location. Highlighting may run on more lines than necessary after this change but this should be a minor performance hit.
Diffstat (limited to 'src')
-rw-r--r--src/highlighter.hh3
-rw-r--r--src/highlighters.cc102
-rw-r--r--src/window.cc58
3 files changed, 24 insertions, 139 deletions
diff --git a/src/highlighter.hh b/src/highlighter.hh
index 73520c53..8a60c0c1 100644
--- a/src/highlighter.hh
+++ b/src/highlighter.hh
@@ -43,11 +43,8 @@ struct DisplaySetup
LineCount line_count;
ColumnCount first_column;
ColumnCount widget_columns;
- // Position of the cursor in the window
- DisplayCoord cursor_pos;
// Offset of line and columns that must remain visible around cursor
DisplayCoord scroll_offset;
- bool ensure_cursor_visible;
};
using HighlighterIdList = ConstArrayView<StringView>;
diff --git a/src/highlighters.cc b/src/highlighters.cc
index 25f93245..2044ccd5 100644
--- a/src/highlighters.cc
+++ b/src/highlighters.cc
@@ -613,9 +613,7 @@ struct WrapHighlighter : Highlighter
return;
const Buffer& buffer = context.context.buffer();
- const auto& cursor = context.context.selections().main().cursor();
const int tabstop = context.context.options()["tabstop"].get<int>();
- const LineCount win_height = context.context.window().dimensions().line;
const ColumnCount marker_len = zero_if_greater(m_marker.column_length(), wrap_column);
const Face face_marker = context.context.faces()["WrapMarker"];
for (auto it = display_buffer.lines().begin();
@@ -658,19 +656,6 @@ struct WrapHighlighter : Highlighter
it->replace(String{' ', indent - marker_len});
}
- if (it+1 - display_buffer.lines().begin() == win_height)
- {
- if (cursor >= new_line.range().begin) // strip first lines if cursor is not visible
- {
- display_buffer.lines().erase(display_buffer.lines().begin(), display_buffer.lines().begin()+1);
- --it;
- }
- else
- {
- display_buffer.lines().erase(it+1, display_buffer.lines().end());
- return;
- }
- }
it = display_buffer.lines().insert(it+1, new_line);
pos = next_split_pos(buffer, wrap_column - prefix_len, prefix_len, tabstop, buf_line, pos);
@@ -688,80 +673,9 @@ struct WrapHighlighter : Highlighter
if (wrap_column <= 0)
return;
- const Buffer& buffer = context.context.buffer();
- const auto& cursor = context.context.selections().main().cursor();
- const int tabstop = context.context.options()["tabstop"].get<int>();
-
- auto line_wrap_count = [&](LineCount line, ColumnCount prefix_len) {
- LineCount count = 0;
- const ByteCount line_length = buffer[line].length();
- SplitPos pos{0, 0};
- while (true)
- {
- pos = next_split_pos(buffer, wrap_column - (pos.byte == 0 ? 0_col : prefix_len),
- prefix_len, tabstop, line, pos);
- if (pos.byte == line_length)
- break;
- ++count;
- }
- return count;
- };
-
- const auto win_height = context.context.window().dimensions().line;
-
// Disable horizontal scrolling when using a WrapHighlighter
setup.first_column = 0;
- setup.line_count = 0;
setup.scroll_offset.column = 0;
-
- const ColumnCount marker_len = zero_if_greater(m_marker.column_length(), wrap_column);
-
- for (auto buf_line = setup.first_line, win_line = 0_line;
- win_line < win_height or (setup.ensure_cursor_visible and buf_line <= cursor.line);
- ++buf_line, ++setup.line_count)
- {
- if (buf_line >= buffer.line_count())
- break;
-
- const ColumnCount indent = m_preserve_indent ?
- zero_if_greater(line_indent(buffer, tabstop, buf_line), wrap_column) : 0_col;
- const ColumnCount prefix_len = std::max(marker_len, indent);
-
- if (buf_line == cursor.line)
- {
- SplitPos pos{0, 0};
- for (LineCount count = 0; true; ++count)
- {
- auto next_pos = next_split_pos(buffer, wrap_column - (pos.byte != 0 ? prefix_len : 0_col),
- prefix_len, tabstop, buf_line, pos);
- if (next_pos.byte > cursor.column)
- {
- setup.cursor_pos = DisplayCoord{
- win_line + count,
- get_column(buffer, tabstop, cursor) -
- pos.column + (pos.byte != 0 ? indent : 0_col)
- };
- break;
- }
- pos = next_pos;
- }
- }
- const auto wrap_count = line_wrap_count(buf_line, prefix_len);
- win_line += wrap_count + 1;
-
- // scroll window to keep cursor visible, and update range as lines gets removed
- while (setup.ensure_cursor_visible and
- buf_line >= cursor.line and setup.first_line < cursor.line and
- setup.cursor_pos.line + setup.scroll_offset.line >= win_height)
- {
- auto remove_count = 1 + line_wrap_count(setup.first_line, indent);
- ++setup.first_line;
- --setup.line_count;
- setup.cursor_pos.line -= std::min(win_height, remove_count);
- win_line -= remove_count;
- kak_assert(setup.cursor_pos.line >= 0);
- }
- }
}
void fill_unique_ids(Vector<StringView>& unique_ids) const override
@@ -947,7 +861,6 @@ struct TabulationHighlighter : Highlighter
const ColumnCount offset = std::max(column + width - win_end, 0_col);
setup.first_column += offset;
- setup.cursor_pos.column -= offset;
}
};
@@ -1694,7 +1607,6 @@ private:
auto& buffer = context.context.buffer();
auto& sels = context.context.selections();
auto& range_and_faces = get_option(context);
- const int tabstop = context.context.options()["tabstop"].get<int>();
update_ranges(buffer, range_and_faces.prefix, range_and_faces.list);
range_and_faces.prefix = buffer.timestamp();
@@ -1707,19 +1619,7 @@ private:
if (range.first.line < setup.first_line and last.line >= setup.first_line)
setup.first_line = range.first.line;
- const auto& cursor = context.context.selections().main().cursor();
- if (cursor.line == last.line and cursor.column >= last.column)
- {
- auto first_column = get_column(buffer, tabstop, range.first);
- auto last_column = get_column(buffer, tabstop, last);
- auto replacement = parse_display_line(spec, context.context.faces());
- auto cursor_move = replacement.length() - ((range.first.line == last.line) ? last_column - first_column : last_column);
- setup.cursor_pos.line -= last.line - range.first.line;
- setup.cursor_pos.column += cursor_move;
- }
-
- if (setup.ensure_cursor_visible and
- last.line >= setup.first_line and
+ if (last.line >= setup.first_line and
range.first.line <= setup.first_line + setup.line_count and
range.first.line != last.line)
{
diff --git a/src/window.cc b/src/window.cc
index 520d77e1..2b8d4be9 100644
--- a/src/window.cc
+++ b/src/window.cc
@@ -132,7 +132,7 @@ const DisplayBuffer& Window::update_display_buffer(const Context& context)
return m_display_buffer;
kak_assert(&buffer() == &context.buffer());
- const DisplaySetup setup = compute_display_setup(context);
+ DisplaySetup setup = compute_display_setup(context);
for (LineCount line = 0; line < setup.line_count; ++line)
{
@@ -147,6 +147,24 @@ const DisplayBuffer& Window::update_display_buffer(const Context& context)
m_builtin_highlighters.highlight({context, setup, HighlightPass::Wrap, {}}, m_display_buffer, range);
m_builtin_highlighters.highlight({context, setup, HighlightPass::Move, {}}, m_display_buffer, range);
+ if (context.ensure_cursor_visible)
+ {
+ auto cursor_pos = display_coord(context.selections().main().cursor());
+ kak_assert(cursor_pos);
+
+ if (auto line_overflow = cursor_pos->line - m_dimensions.line + setup.scroll_offset.line + 1; line_overflow > 0)
+ {
+ lines.erase(lines.begin(), lines.begin() + (size_t)line_overflow);
+ setup.first_line = lines.begin()->range().begin.line;
+ }
+
+ auto max_first_column = cursor_pos->column - (setup.widget_columns + setup.scroll_offset.column);
+ setup.first_column = std::min(setup.first_column, max_first_column);
+
+ auto min_first_column = cursor_pos->column - (m_dimensions.column - setup.scroll_offset.column) + 1;
+ setup.first_column = std::max(setup.first_column, min_first_column);
+ }
+
for (auto& line : m_display_buffer.lines())
line.trim_from(setup.widget_columns, setup.first_column, m_dimensions.column);
if (m_display_buffer.lines().size() > m_dimensions.line)
@@ -203,11 +221,9 @@ DisplaySetup Window::compute_display_setup(const Context& context) const
offset.line = std::min(offset.line, (m_dimensions.line + 1) / 2);
offset.column = std::min(offset.column, (m_dimensions.column + 1) / 2);
- const int tabstop = context.options()["tabstop"].get<int>();
const auto& cursor = context.selections().main().cursor();
- bool ensure_cursor_visible = context.ensure_cursor_visible;
- if (ensure_cursor_visible)
+ if (context.ensure_cursor_visible)
{
if (cursor.line - offset.line < win_pos.line)
win_pos.line = std::max(0_line, cursor.line - offset.line);
@@ -216,39 +232,11 @@ DisplaySetup Window::compute_display_setup(const Context& context) const
}
win_pos.line = std::min(win_pos.line, buffer().line_count()-1);
- DisplaySetup setup{
- win_pos.line,
- m_dimensions.line,
- win_pos.column,
- 0_col,
- {cursor.line - win_pos.line,
- get_column(buffer(), tabstop, cursor) - win_pos.column},
- offset,
- ensure_cursor_visible
- };
- for (auto pass : { HighlightPass::Move, HighlightPass::Wrap })
- m_builtin_highlighters.compute_display_setup({context, setup, pass, {}}, setup);
+ DisplaySetup setup{win_pos.line, m_dimensions.line, win_pos.column, 0_col, offset};
+ m_builtin_highlighters.compute_display_setup({context, setup, HighlightPass::Move, {}}, setup);
+ m_builtin_highlighters.compute_display_setup({context, setup, HighlightPass::Wrap, {}}, setup);
check_display_setup(setup, *this);
- // now ensure the cursor column is visible
- if (ensure_cursor_visible)
- {
- auto underflow = std::max(-setup.first_column,
- setup.cursor_pos.column - setup.scroll_offset.column);
- if (underflow < 0)
- {
- setup.first_column += underflow;
- setup.cursor_pos.column -= underflow;
- }
- auto overflow = setup.cursor_pos.column + setup.scroll_offset.column - (m_dimensions.column - setup.widget_columns) + 1;
- if (overflow > 0)
- {
- setup.first_column += overflow;
- setup.cursor_pos.column -= overflow;
- }
- check_display_setup(setup, *this);
- }
-
return setup;
}