BufferView: add functions to move cursor up/down by screen row
This commit is contained in:
parent
fcd198b691
commit
84759d0a36
@ -17,7 +17,9 @@ BufferView::BufferView(std::shared_ptr<Buffer> buffer,
|
||||
m_cursor_screen_column = 0;
|
||||
m_cursor_virtual_column = 0;
|
||||
m_cursor_row_offset = 0;
|
||||
m_target_column = 0;
|
||||
m_rows_in_cursor_line = 0;
|
||||
m_target_screen_column = 0;
|
||||
m_target_virtual_column = 0;
|
||||
m_update_target_column = false;
|
||||
}
|
||||
|
||||
@ -43,7 +45,7 @@ void BufferView::update()
|
||||
* and cursor column values. */
|
||||
auto start_of_line = std::make_shared<Buffer::Iterator>(*m_iterator);
|
||||
start_of_line->go_start_of_line();
|
||||
int rows_in_cursor_line = calculate_rows_in_cursor_line(start_of_line);
|
||||
m_rows_in_cursor_line = calculate_rows_in_cursor_line(start_of_line);
|
||||
|
||||
/* Limit the cursor screen row taking into account view dimensions,
|
||||
* available buffer contents above and below the current line, and scroll
|
||||
@ -51,7 +53,7 @@ void BufferView::update()
|
||||
std::list<std::pair<int, std::shared_ptr<Buffer::Iterator>>> backward_lines;
|
||||
int so = effective_scroll_offset();
|
||||
int rows_above = screen_rows_above_line(start_of_line, backward_lines) + m_cursor_row_offset;
|
||||
int rows_below = screen_rows_below_line(start_of_line) + std::max(0, rows_in_cursor_line - m_cursor_row_offset - 1);
|
||||
int rows_below = screen_rows_below_line(start_of_line) + std::max(0, m_rows_in_cursor_line - m_cursor_row_offset - 1);
|
||||
int min_rows_to_leave_above = std::min(rows_above, so);
|
||||
int min_rows_to_leave_below = std::min(rows_below, so);
|
||||
m_cursor_screen_row = std::min(m_height - min_rows_to_leave_below - 1, m_cursor_screen_row);
|
||||
@ -120,11 +122,13 @@ bool BufferView::cursor_move(CursorMovement which, bool allow_eol)
|
||||
break;
|
||||
case CursorMovement::SOL:
|
||||
moved = m_iterator->go_start_of_line();
|
||||
m_target_column = 0;
|
||||
m_target_screen_column = 0;
|
||||
m_target_virtual_column = 0;
|
||||
break;
|
||||
case CursorMovement::EOL:
|
||||
moved = m_iterator->go_end_of_line(allow_eol);
|
||||
m_target_column = INT_MAX;
|
||||
m_target_screen_column = INT_MAX;
|
||||
m_target_virtual_column = INT_MAX;
|
||||
break;
|
||||
case CursorMovement::FIRST_LINE:
|
||||
{
|
||||
@ -135,7 +139,8 @@ bool BufferView::cursor_move(CursorMovement which, bool allow_eol)
|
||||
moved = true;
|
||||
}
|
||||
}
|
||||
m_target_column = 0;
|
||||
m_target_screen_column = 0;
|
||||
m_target_virtual_column = 0;
|
||||
break;
|
||||
case CursorMovement::LAST_LINE:
|
||||
{
|
||||
@ -148,19 +153,14 @@ bool BufferView::cursor_move(CursorMovement which, bool allow_eol)
|
||||
moved = true;
|
||||
}
|
||||
}
|
||||
m_target_column = 0;
|
||||
m_target_screen_column = 0;
|
||||
m_target_virtual_column = 0;
|
||||
break;
|
||||
case CursorMovement::SCREEN_ROW_UP:
|
||||
/* TODO */
|
||||
#if 0
|
||||
moved = move_cursor_screen_row_up();
|
||||
#endif
|
||||
moved = move_cursor_screen_row_up(allow_eol);
|
||||
break;
|
||||
case CursorMovement::SCREEN_ROW_DOWN:
|
||||
/* TODO */
|
||||
#if 0
|
||||
moved = move_cursor_screen_row_down();
|
||||
#endif
|
||||
moved = move_cursor_screen_row_down(allow_eol);
|
||||
break;
|
||||
}
|
||||
if (moved)
|
||||
@ -173,7 +173,7 @@ bool BufferView::cursor_move(CursorMovement which, bool allow_eol)
|
||||
break;
|
||||
case CursorMovement::UP:
|
||||
case CursorMovement::DOWN:
|
||||
move_forward_to_column(m_target_column, allow_eol);
|
||||
move_forward_to_column(m_target_virtual_column, allow_eol);
|
||||
determine_new_cursor_screen_row();
|
||||
break;
|
||||
case CursorMovement::SOL:
|
||||
@ -249,7 +249,8 @@ int BufferView::calculate_rows_in_cursor_line(std::shared_ptr<Buffer::Iterator>
|
||||
m_cursor_screen_column = it.screen_column();
|
||||
if (m_update_target_column)
|
||||
{
|
||||
m_target_column = m_cursor_virtual_column;
|
||||
m_target_screen_column = m_cursor_screen_column;
|
||||
m_target_virtual_column = m_cursor_virtual_column;
|
||||
}
|
||||
m_cursor_row_offset = it.row_offset();
|
||||
}
|
||||
@ -311,3 +312,65 @@ void BufferView::move_forward_to_column(int to_column, bool allow_eol)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool BufferView::move_cursor_screen_row_up(bool allow_eol)
|
||||
{
|
||||
if (m_cursor_row_offset > 0)
|
||||
{
|
||||
/* There are screen rows above the current in the current line. */
|
||||
auto start_of_line = std::make_shared<Buffer::Iterator>(*m_iterator);
|
||||
start_of_line->go_start_of_line();
|
||||
move_forward_to_screen_position(start_of_line, m_cursor_row_offset - 1, allow_eol);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto previous_line = std::make_shared<Buffer::Iterator>(*m_iterator);
|
||||
if (!previous_line->go_previous_line())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int target_row_offset = calculate_rows_in_line(previous_line) - 1;
|
||||
move_forward_to_screen_position(previous_line, target_row_offset, allow_eol);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BufferView::move_cursor_screen_row_down(bool allow_eol)
|
||||
{
|
||||
if (m_rows_in_cursor_line > (m_cursor_row_offset + 1))
|
||||
{
|
||||
/* There are screen rows below the current in the current line. */
|
||||
auto start_of_line = std::make_shared<Buffer::Iterator>(*m_iterator);
|
||||
start_of_line->go_start_of_line();
|
||||
move_forward_to_screen_position(start_of_line, m_cursor_row_offset + 1, allow_eol);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto next_line = std::make_shared<Buffer::Iterator>(*m_iterator);
|
||||
if (!next_line->go_next_line())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
move_forward_to_screen_position(next_line, 0, allow_eol);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void BufferView::move_forward_to_screen_position(
|
||||
std::shared_ptr<Buffer::Iterator> line, int target_row_offset,
|
||||
bool allow_eol)
|
||||
{
|
||||
for (auto it = horiz_iter(line); it.is_valid(); it++)
|
||||
{
|
||||
if ((allow_eol || (!it.is_eol())) &&
|
||||
((it.row_offset() < target_row_offset) ||
|
||||
(it.screen_column() <= m_target_screen_column)))
|
||||
{
|
||||
*m_iterator = *it.iterator();
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +104,9 @@ protected:
|
||||
int m_cursor_screen_column;
|
||||
int m_cursor_virtual_column;
|
||||
int m_cursor_row_offset;
|
||||
int m_target_column;
|
||||
int m_rows_in_cursor_line;
|
||||
int m_target_screen_column;
|
||||
int m_target_virtual_column;
|
||||
bool m_update_target_column;
|
||||
|
||||
int effective_scroll_offset()
|
||||
@ -119,6 +121,11 @@ protected:
|
||||
std::shared_ptr<Buffer::Iterator> line,
|
||||
std::list<std::pair<int, std::shared_ptr<Buffer::Iterator>>> & backward_lines);
|
||||
void move_forward_to_column(int to_column, bool allow_eol);
|
||||
bool move_cursor_screen_row_up(bool allow_eol);
|
||||
bool move_cursor_screen_row_down(bool allow_eol);
|
||||
void move_forward_to_screen_position(
|
||||
std::shared_ptr<Buffer::Iterator> line, int target_row_offset,
|
||||
bool allow_eol);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -467,3 +467,56 @@ TEST(BufferViewTest, sets_target_column_when_traversing_left_and_right)
|
||||
EXPECT_EQ(1, LineNumber(iterator));
|
||||
EXPECT_EQ(C('a'), **iterator);
|
||||
}
|
||||
|
||||
TEST(BufferViewTest, moves_cursor_by_screen_row)
|
||||
{
|
||||
auto b = buffer1();
|
||||
auto iterator = b->add_iterator();
|
||||
BufferView bv(b, iterator, Cwd);
|
||||
bv.resize(4, 4);
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::SCREEN_ROW_DOWN, false));
|
||||
bv.update();
|
||||
EXPECT_EQ(1 + i, LineNumber(iterator));
|
||||
}
|
||||
EXPECT_EQ(C('6'), **iterator);
|
||||
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::SCREEN_ROW_DOWN, false));
|
||||
bv.update();
|
||||
EXPECT_EQ(6, LineNumber(iterator));
|
||||
EXPECT_EQ(C('d'), **iterator);
|
||||
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::RIGHT, false));
|
||||
bv.update();
|
||||
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::RIGHT, false));
|
||||
bv.update();
|
||||
EXPECT_EQ(C('f'), **iterator);
|
||||
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::SCREEN_ROW_DOWN, false));
|
||||
bv.update();
|
||||
EXPECT_EQ(C('7'), **iterator);
|
||||
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::SCREEN_ROW_UP, false));
|
||||
bv.update();
|
||||
EXPECT_EQ(C('f'), **iterator);
|
||||
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::SCREEN_ROW_UP, false));
|
||||
bv.update();
|
||||
EXPECT_EQ(C('b'), **iterator);
|
||||
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::SCREEN_ROW_UP, false));
|
||||
bv.update();
|
||||
EXPECT_EQ(C('5'), **iterator);
|
||||
}
|
||||
|
||||
TEST(BufferViewTest, cursor_move_screen_row_up_and_down_returns_false_at_top_and_bottom)
|
||||
{
|
||||
auto b = buffer1();
|
||||
auto iterator = b->add_iterator();
|
||||
BufferView bv(b, iterator, Cwd);
|
||||
bv.resize(4, 4);
|
||||
EXPECT_FALSE(bv.cursor_move(BufferView::CursorMovement::SCREEN_ROW_UP, false));
|
||||
bv.update();
|
||||
EXPECT_EQ(0, LineNumber(iterator));
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::SCREEN_ROW_DOWN, false));
|
||||
bv.update();
|
||||
}
|
||||
EXPECT_FALSE(bv.cursor_move(BufferView::CursorMovement::SCREEN_ROW_DOWN, false));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user