diff --git a/src/core/BufferView.cc b/src/core/BufferView.cc index 9a9addd..99e8ec1 100644 --- a/src/core/BufferView.cc +++ b/src/core/BufferView.cc @@ -34,12 +34,14 @@ BufferView::Iterator BufferView::vert_iter() return Iterator(*this); } -/************************************************************************** - * Internal functions - *************************************************************************/ - void BufferView::update() { + /* Update the cursor screen row in case the cursor position changed. */ + m_cursor_screen_row = determine_new_cursor_screen_row(); + + /* Limit the cursor screen row taking into account view dimensions, + * available buffer contents above and below the current line, and scroll + * offset. */ std::list>> backward_lines; auto start_of_line = std::make_shared(*m_iterator); start_of_line->go_start_of_line(); @@ -93,6 +95,34 @@ void BufferView::update() } } +/************************************************************************** + * Internal functions + *************************************************************************/ + +int BufferView::determine_new_cursor_screen_row() +{ + if (m_lines.size() > 0) + { + if (m_iterator->line() < m_lines.begin()->line->line()) + { + return 0; + } + if (m_iterator->line() > m_lines.rbegin()->line->line()) + { + return m_height; + } + for (const LineDescriptor & screen_line : m_lines) + { + if (screen_line.line->line() == m_iterator->line()) + { + calculate_rows_in_cursor_line(screen_line.line); + return screen_line.row_offset + m_cursor_row_offset; + } + } + } + return 0; +} + int BufferView::calculate_rows_in_line(std::shared_ptr start_of_line) { int saved_row_offset = 0; diff --git a/src/core/BufferView.h b/src/core/BufferView.h index b39d6d8..f093151 100644 --- a/src/core/BufferView.h +++ b/src/core/BufferView.h @@ -89,6 +89,7 @@ protected: { return std::min(m_scroll_offset, (m_height - 1) / 2); } + int determine_new_cursor_screen_row(); int calculate_rows_in_line(std::shared_ptr start_of_line); int calculate_rows_in_cursor_line(std::shared_ptr start_of_line); int screen_rows_below_line(std::shared_ptr line); diff --git a/test/src/test_BufferView.cc b/test/src/test_BufferView.cc index 363562d..a3418ea 100644 --- a/test/src/test_BufferView.cc +++ b/test/src/test_BufferView.cc @@ -137,3 +137,55 @@ TEST(BufferViewTest, fills_view_with_last_lines_of_buffer_when_cursor_warps_to_l EXPECT_EQ(0, bv.cursor_screen_column()); EXPECT_EQ(0, bv.cursor_virtual_column()); } + +TEST(BufferViewTest, adjusts_cursor_row_as_cursor_moves) +{ + auto b = buffer1(); + auto iterator = b->add_iterator(); + BufferView bv(b, iterator, Cwd); + bv.resize(5, 5); + bv.update(); + EXPECT_EQ(0, bv.cursor_screen_row()); + iterator->go_next_line(); // to 1 + bv.update(); + EXPECT_EQ(1, bv.cursor_screen_row()); + iterator->go_next_line(); // to 2 + bv.update(); + EXPECT_EQ(2, bv.cursor_screen_row()); + iterator->go_next_line(); // to 3 + bv.update(); + EXPECT_EQ(3, bv.cursor_screen_row()); + iterator->go_next_line(); // to 4 + bv.update(); + EXPECT_EQ(4, bv.cursor_screen_row()); + iterator->go_next_line(); // to 5 + bv.update(); + EXPECT_EQ(4, bv.cursor_screen_row()); + iterator->go_next_line(); // to 6 + bv.update(); + EXPECT_EQ(4, bv.cursor_screen_row()); + iterator->go_next_line(); // to 7 + bv.update(); + EXPECT_EQ(4, bv.cursor_screen_row()); + iterator->go_previous_line(); // to 6 + bv.update(); + EXPECT_EQ(2, bv.cursor_screen_row()); + iterator->go_previous_line(); // to 5 + bv.update(); + EXPECT_EQ(1, bv.cursor_screen_row()); + iterator->go_previous_line(); // to 4 + bv.update(); + EXPECT_EQ(0, bv.cursor_screen_row()); + iterator->go_previous_line(); // to 3 + bv.update(); + EXPECT_EQ(0, bv.cursor_screen_row()); + iterator->go_previous_line(); // to 2 + bv.update(); + EXPECT_EQ(0, bv.cursor_screen_row()); + iterator->go_previous_line(); // to 1 + bv.update(); + EXPECT_EQ(0, bv.cursor_screen_row()); + iterator->go_previous_line(); // to 0 + bv.update(); + EXPECT_EQ(0, bv.cursor_screen_row()); +}