Add cursor movement logic to BufferView
This commit is contained in:
parent
7ad28ceb67
commit
fcd198b691
@ -1,6 +1,7 @@
|
|||||||
#include "BufferView.h"
|
#include "BufferView.h"
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
BufferView::BufferView(std::shared_ptr<Buffer> buffer,
|
BufferView::BufferView(std::shared_ptr<Buffer> buffer,
|
||||||
std::shared_ptr<Buffer::Iterator> iterator,
|
std::shared_ptr<Buffer::Iterator> iterator,
|
||||||
@ -16,6 +17,8 @@ BufferView::BufferView(std::shared_ptr<Buffer> buffer,
|
|||||||
m_cursor_screen_column = 0;
|
m_cursor_screen_column = 0;
|
||||||
m_cursor_virtual_column = 0;
|
m_cursor_virtual_column = 0;
|
||||||
m_cursor_row_offset = 0;
|
m_cursor_row_offset = 0;
|
||||||
|
m_target_column = 0;
|
||||||
|
m_update_target_column = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferView::resize(int width, int height)
|
void BufferView::resize(int width, int height)
|
||||||
@ -42,9 +45,6 @@ void BufferView::update()
|
|||||||
start_of_line->go_start_of_line();
|
start_of_line->go_start_of_line();
|
||||||
int rows_in_cursor_line = calculate_rows_in_cursor_line(start_of_line);
|
int rows_in_cursor_line = calculate_rows_in_cursor_line(start_of_line);
|
||||||
|
|
||||||
/* 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,
|
/* Limit the cursor screen row taking into account view dimensions,
|
||||||
* available buffer contents above and below the current line, and scroll
|
* available buffer contents above and below the current line, and scroll
|
||||||
* offset. */
|
* offset. */
|
||||||
@ -98,31 +98,127 @@ void BufferView::update()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BufferView::cursor_move(CursorMovement which, bool allow_eol)
|
||||||
|
{
|
||||||
|
bool moved = false;
|
||||||
|
|
||||||
|
switch (which)
|
||||||
|
{
|
||||||
|
case CursorMovement::LEFT:
|
||||||
|
moved = m_iterator->go_left_in_line();
|
||||||
|
m_update_target_column = true;
|
||||||
|
break;
|
||||||
|
case CursorMovement::RIGHT:
|
||||||
|
moved = m_iterator->go_right_in_line(allow_eol);
|
||||||
|
m_update_target_column = true;
|
||||||
|
break;
|
||||||
|
case CursorMovement::UP:
|
||||||
|
moved = m_iterator->go_previous_line();
|
||||||
|
break;
|
||||||
|
case CursorMovement::DOWN:
|
||||||
|
moved = m_iterator->go_next_line();
|
||||||
|
break;
|
||||||
|
case CursorMovement::SOL:
|
||||||
|
moved = m_iterator->go_start_of_line();
|
||||||
|
m_target_column = 0;
|
||||||
|
break;
|
||||||
|
case CursorMovement::EOL:
|
||||||
|
moved = m_iterator->go_end_of_line(allow_eol);
|
||||||
|
m_target_column = INT_MAX;
|
||||||
|
break;
|
||||||
|
case CursorMovement::FIRST_LINE:
|
||||||
|
{
|
||||||
|
auto it = m_buffer->begin();
|
||||||
|
if (it != *m_iterator)
|
||||||
|
{
|
||||||
|
*m_iterator = it;
|
||||||
|
moved = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_target_column = 0;
|
||||||
|
break;
|
||||||
|
case CursorMovement::LAST_LINE:
|
||||||
|
{
|
||||||
|
auto it = m_buffer->end();
|
||||||
|
it.go_back();
|
||||||
|
it.go_start_of_line();
|
||||||
|
if (it != *m_iterator)
|
||||||
|
{
|
||||||
|
*m_iterator = it;
|
||||||
|
moved = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_target_column = 0;
|
||||||
|
break;
|
||||||
|
case CursorMovement::SCREEN_ROW_UP:
|
||||||
|
/* TODO */
|
||||||
|
#if 0
|
||||||
|
moved = move_cursor_screen_row_up();
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case CursorMovement::SCREEN_ROW_DOWN:
|
||||||
|
/* TODO */
|
||||||
|
#if 0
|
||||||
|
moved = move_cursor_screen_row_down();
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (moved)
|
||||||
|
{
|
||||||
|
switch (which)
|
||||||
|
{
|
||||||
|
case CursorMovement::LEFT:
|
||||||
|
case CursorMovement::RIGHT:
|
||||||
|
determine_new_cursor_screen_row();
|
||||||
|
break;
|
||||||
|
case CursorMovement::UP:
|
||||||
|
case CursorMovement::DOWN:
|
||||||
|
move_forward_to_column(m_target_column, allow_eol);
|
||||||
|
determine_new_cursor_screen_row();
|
||||||
|
break;
|
||||||
|
case CursorMovement::SOL:
|
||||||
|
case CursorMovement::EOL:
|
||||||
|
determine_new_cursor_screen_row();
|
||||||
|
break;
|
||||||
|
case CursorMovement::FIRST_LINE:
|
||||||
|
m_cursor_screen_row = 0;
|
||||||
|
break;
|
||||||
|
case CursorMovement::LAST_LINE:
|
||||||
|
m_cursor_screen_row = m_height - 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return moved;
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Internal functions
|
* Internal functions
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
|
|
||||||
int BufferView::determine_new_cursor_screen_row()
|
void BufferView::determine_new_cursor_screen_row()
|
||||||
{
|
{
|
||||||
if (m_lines.size() > 0)
|
if (m_lines.size() > 0)
|
||||||
{
|
{
|
||||||
if (m_iterator->line() < m_lines.begin()->line->line())
|
if (m_iterator->line() < m_lines.begin()->line->line())
|
||||||
{
|
{
|
||||||
return 0;
|
m_cursor_screen_row = 0;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (m_iterator->line() > m_lines.rbegin()->line->line())
|
if (m_iterator->line() > m_lines.rbegin()->line->line())
|
||||||
{
|
{
|
||||||
return m_height;
|
m_cursor_screen_row = m_height - 1;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
for (const LineDescriptor & screen_line : m_lines)
|
for (const LineDescriptor & screen_line : m_lines)
|
||||||
{
|
{
|
||||||
if (screen_line.line->line() == m_iterator->line())
|
if (screen_line.line->line() == m_iterator->line())
|
||||||
{
|
{
|
||||||
return screen_line.row_offset + m_cursor_row_offset;
|
m_cursor_screen_row = screen_line.row_offset + m_cursor_row_offset;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int BufferView::calculate_rows_in_line(std::shared_ptr<Buffer::Iterator> start_of_line)
|
int BufferView::calculate_rows_in_line(std::shared_ptr<Buffer::Iterator> start_of_line)
|
||||||
@ -151,6 +247,10 @@ int BufferView::calculate_rows_in_cursor_line(std::shared_ptr<Buffer::Iterator>
|
|||||||
{
|
{
|
||||||
m_cursor_virtual_column = it.virtual_column();
|
m_cursor_virtual_column = it.virtual_column();
|
||||||
m_cursor_screen_column = it.screen_column();
|
m_cursor_screen_column = it.screen_column();
|
||||||
|
if (m_update_target_column)
|
||||||
|
{
|
||||||
|
m_target_column = m_cursor_virtual_column;
|
||||||
|
}
|
||||||
m_cursor_row_offset = it.row_offset();
|
m_cursor_row_offset = it.row_offset();
|
||||||
}
|
}
|
||||||
if (!it.is_eol())
|
if (!it.is_eol())
|
||||||
@ -162,6 +262,7 @@ int BufferView::calculate_rows_in_cursor_line(std::shared_ptr<Buffer::Iterator>
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_update_target_column = false;
|
||||||
return saved_row_offset + 1;
|
return saved_row_offset + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,3 +291,23 @@ int BufferView::screen_rows_above_line(
|
|||||||
}
|
}
|
||||||
return rows;
|
return rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BufferView::move_forward_to_column(int to_column, bool allow_eol)
|
||||||
|
{
|
||||||
|
auto start_of_line = std::make_shared<Buffer::Iterator>(*m_iterator);
|
||||||
|
start_of_line->go_start_of_line();
|
||||||
|
for (auto it = horiz_iter(start_of_line); it.is_valid(); it++)
|
||||||
|
{
|
||||||
|
if (allow_eol || (!it.is_eol()))
|
||||||
|
{
|
||||||
|
if (it.virtual_column() <= to_column)
|
||||||
|
{
|
||||||
|
*m_iterator = *it.iterator();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -14,6 +14,20 @@
|
|||||||
class BufferView
|
class BufferView
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum class CursorMovement : uint8_t
|
||||||
|
{
|
||||||
|
LEFT,
|
||||||
|
RIGHT,
|
||||||
|
UP,
|
||||||
|
DOWN,
|
||||||
|
SOL,
|
||||||
|
EOL,
|
||||||
|
FIRST_LINE,
|
||||||
|
LAST_LINE,
|
||||||
|
SCREEN_ROW_UP,
|
||||||
|
SCREEN_ROW_DOWN,
|
||||||
|
};
|
||||||
|
|
||||||
class Iterator
|
class Iterator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -62,22 +76,16 @@ public:
|
|||||||
{
|
{
|
||||||
return BufferLineWalker(m_buffer, start_of_line, m_width, m_character_width_determiner);
|
return BufferLineWalker(m_buffer, start_of_line, m_width, m_character_width_determiner);
|
||||||
}
|
}
|
||||||
|
bool cursor_move(CursorMovement which, bool allow_eol);
|
||||||
int cursor_screen_row() const { return m_cursor_screen_row; }
|
int cursor_screen_row() const { return m_cursor_screen_row; }
|
||||||
int cursor_screen_column() const { return m_cursor_screen_column; }
|
int cursor_screen_column() const { return m_cursor_screen_column; }
|
||||||
int cursor_virtual_column() const { return m_cursor_virtual_column; }
|
int cursor_virtual_column() const { return m_cursor_virtual_column; }
|
||||||
|
void set_cursor_screen_row(int cursor_screen_row)
|
||||||
|
{
|
||||||
|
m_cursor_screen_row = cursor_screen_row;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::shared_ptr<Buffer> m_buffer;
|
|
||||||
std::shared_ptr<Buffer::Iterator> m_iterator;
|
|
||||||
int m_width;
|
|
||||||
int m_height;
|
|
||||||
int m_scroll_offset;
|
|
||||||
int m_cursor_screen_row;
|
|
||||||
int m_cursor_screen_column;
|
|
||||||
int m_cursor_virtual_column;
|
|
||||||
int m_cursor_row_offset;
|
|
||||||
CharacterWidthDeterminer & m_character_width_determiner;
|
|
||||||
|
|
||||||
struct LineDescriptor
|
struct LineDescriptor
|
||||||
{
|
{
|
||||||
int row_offset;
|
int row_offset;
|
||||||
@ -85,18 +93,32 @@ protected:
|
|||||||
std::shared_ptr<Buffer::Iterator> line;
|
std::shared_ptr<Buffer::Iterator> line;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::shared_ptr<Buffer> m_buffer;
|
||||||
|
std::shared_ptr<Buffer::Iterator> m_iterator;
|
||||||
|
std::vector<LineDescriptor> m_lines;
|
||||||
|
CharacterWidthDeterminer & m_character_width_determiner;
|
||||||
|
int m_width;
|
||||||
|
int m_height;
|
||||||
|
int m_scroll_offset;
|
||||||
|
int m_cursor_screen_row;
|
||||||
|
int m_cursor_screen_column;
|
||||||
|
int m_cursor_virtual_column;
|
||||||
|
int m_cursor_row_offset;
|
||||||
|
int m_target_column;
|
||||||
|
bool m_update_target_column;
|
||||||
|
|
||||||
int effective_scroll_offset()
|
int effective_scroll_offset()
|
||||||
{
|
{
|
||||||
return std::min(m_scroll_offset, (m_height - 1) / 2);
|
return std::min(m_scroll_offset, (m_height - 1) / 2);
|
||||||
}
|
}
|
||||||
int determine_new_cursor_screen_row();
|
void determine_new_cursor_screen_row();
|
||||||
int calculate_rows_in_line(std::shared_ptr<Buffer::Iterator> start_of_line);
|
int calculate_rows_in_line(std::shared_ptr<Buffer::Iterator> start_of_line);
|
||||||
int calculate_rows_in_cursor_line(std::shared_ptr<Buffer::Iterator> start_of_line);
|
int calculate_rows_in_cursor_line(std::shared_ptr<Buffer::Iterator> start_of_line);
|
||||||
int screen_rows_below_line(std::shared_ptr<Buffer::Iterator> line);
|
int screen_rows_below_line(std::shared_ptr<Buffer::Iterator> line);
|
||||||
int screen_rows_above_line(
|
int screen_rows_above_line(
|
||||||
std::shared_ptr<Buffer::Iterator> line,
|
std::shared_ptr<Buffer::Iterator> line,
|
||||||
std::list<std::pair<int, std::shared_ptr<Buffer::Iterator>>> & backward_lines);
|
std::list<std::pair<int, std::shared_ptr<Buffer::Iterator>>> & backward_lines);
|
||||||
std::vector<LineDescriptor> m_lines;
|
void move_forward_to_column(int to_column, bool allow_eol);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "BufferView.h"
|
#include "BufferView.h"
|
||||||
|
|
||||||
|
#define C(x) ((uint32_t)(x))
|
||||||
|
|
||||||
static std::shared_ptr<Buffer> buffer1()
|
static std::shared_ptr<Buffer> buffer1()
|
||||||
{
|
{
|
||||||
static const char data[] =
|
static const char data[] =
|
||||||
@ -44,6 +46,7 @@ static int LineNumber(std::shared_ptr<Buffer::Iterator> iterator)
|
|||||||
{
|
{
|
||||||
int line_number = 0;
|
int line_number = 0;
|
||||||
auto i = std::make_shared<Buffer::Iterator>(*iterator);
|
auto i = std::make_shared<Buffer::Iterator>(*iterator);
|
||||||
|
i->go_start_of_line();
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
uint32_t c = **i;
|
uint32_t c = **i;
|
||||||
@ -146,46 +149,46 @@ TEST(BufferViewTest, adjusts_cursor_row_as_cursor_moves)
|
|||||||
bv.resize(5, 5);
|
bv.resize(5, 5);
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(0, bv.cursor_screen_row());
|
EXPECT_EQ(0, bv.cursor_screen_row());
|
||||||
iterator->go_next_line(); // to 1
|
bv.cursor_move(BufferView::CursorMovement::DOWN, false); // to 1
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(1, bv.cursor_screen_row());
|
EXPECT_EQ(1, bv.cursor_screen_row());
|
||||||
iterator->go_next_line(); // to 2
|
bv.cursor_move(BufferView::CursorMovement::DOWN, false); // to 2
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(2, bv.cursor_screen_row());
|
EXPECT_EQ(2, bv.cursor_screen_row());
|
||||||
iterator->go_next_line(); // to 3
|
bv.cursor_move(BufferView::CursorMovement::DOWN, false); // to 3
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(3, bv.cursor_screen_row());
|
EXPECT_EQ(3, bv.cursor_screen_row());
|
||||||
iterator->go_next_line(); // to 4
|
bv.cursor_move(BufferView::CursorMovement::DOWN, false); // to 4
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(4, bv.cursor_screen_row());
|
EXPECT_EQ(4, bv.cursor_screen_row());
|
||||||
iterator->go_next_line(); // to 5
|
bv.cursor_move(BufferView::CursorMovement::DOWN, false); // to 5
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(4, bv.cursor_screen_row());
|
EXPECT_EQ(4, bv.cursor_screen_row());
|
||||||
iterator->go_next_line(); // to 6
|
bv.cursor_move(BufferView::CursorMovement::DOWN, false); // to 6
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(4, bv.cursor_screen_row());
|
EXPECT_EQ(4, bv.cursor_screen_row());
|
||||||
iterator->go_next_line(); // to 7
|
bv.cursor_move(BufferView::CursorMovement::DOWN, false); // to 7
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(4, bv.cursor_screen_row());
|
EXPECT_EQ(4, bv.cursor_screen_row());
|
||||||
iterator->go_previous_line(); // to 6
|
bv.cursor_move(BufferView::CursorMovement::UP, false); // to 6
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(2, bv.cursor_screen_row());
|
EXPECT_EQ(2, bv.cursor_screen_row());
|
||||||
iterator->go_previous_line(); // to 5
|
bv.cursor_move(BufferView::CursorMovement::UP, false); // to 5
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(1, bv.cursor_screen_row());
|
EXPECT_EQ(1, bv.cursor_screen_row());
|
||||||
iterator->go_previous_line(); // to 4
|
bv.cursor_move(BufferView::CursorMovement::UP, false); // to 4
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(0, bv.cursor_screen_row());
|
EXPECT_EQ(0, bv.cursor_screen_row());
|
||||||
iterator->go_previous_line(); // to 3
|
bv.cursor_move(BufferView::CursorMovement::UP, false); // to 3
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(0, bv.cursor_screen_row());
|
EXPECT_EQ(0, bv.cursor_screen_row());
|
||||||
iterator->go_previous_line(); // to 2
|
bv.cursor_move(BufferView::CursorMovement::UP, false); // to 2
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(0, bv.cursor_screen_row());
|
EXPECT_EQ(0, bv.cursor_screen_row());
|
||||||
iterator->go_previous_line(); // to 1
|
bv.cursor_move(BufferView::CursorMovement::UP, false); // to 1
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(0, bv.cursor_screen_row());
|
EXPECT_EQ(0, bv.cursor_screen_row());
|
||||||
iterator->go_previous_line(); // to 0
|
bv.cursor_move(BufferView::CursorMovement::UP, false); // to 0
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(0, bv.cursor_screen_row());
|
EXPECT_EQ(0, bv.cursor_screen_row());
|
||||||
}
|
}
|
||||||
@ -199,51 +202,51 @@ TEST(BufferViewTest, adjusts_cursor_row_as_cursor_moves_with_scroll_offset_1)
|
|||||||
bv.set_scroll_offset(1);
|
bv.set_scroll_offset(1);
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(0, bv.cursor_screen_row());
|
EXPECT_EQ(0, bv.cursor_screen_row());
|
||||||
iterator->go_next_line(); // to 1
|
bv.cursor_move(BufferView::CursorMovement::DOWN, false); // to 1
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(1, bv.cursor_screen_row());
|
EXPECT_EQ(1, bv.cursor_screen_row());
|
||||||
iterator->go_next_line(); // to 2
|
bv.cursor_move(BufferView::CursorMovement::DOWN, false); // to 2
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(2, bv.cursor_screen_row());
|
EXPECT_EQ(2, bv.cursor_screen_row());
|
||||||
iterator->go_next_line(); // to 3
|
bv.cursor_move(BufferView::CursorMovement::DOWN, false); // to 3
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(3, bv.cursor_screen_row());
|
EXPECT_EQ(3, bv.cursor_screen_row());
|
||||||
iterator->go_next_line(); // to 4
|
bv.cursor_move(BufferView::CursorMovement::DOWN, false); // to 4
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(3, bv.cursor_screen_row());
|
EXPECT_EQ(3, bv.cursor_screen_row());
|
||||||
iterator->go_next_line(); // to 5
|
bv.cursor_move(BufferView::CursorMovement::DOWN, false); // to 5
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(3, bv.cursor_screen_row());
|
EXPECT_EQ(3, bv.cursor_screen_row());
|
||||||
iterator->go_next_line(); // to 6
|
bv.cursor_move(BufferView::CursorMovement::DOWN, false); // to 6
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(3, bv.cursor_screen_row());
|
EXPECT_EQ(3, bv.cursor_screen_row());
|
||||||
iterator->go_next_line(); // to 7
|
bv.cursor_move(BufferView::CursorMovement::DOWN, false); // to 7
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(3, bv.cursor_screen_row());
|
EXPECT_EQ(3, bv.cursor_screen_row());
|
||||||
iterator->go_previous_line(); // to 6
|
bv.cursor_move(BufferView::CursorMovement::UP, false); // to 6
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(1, bv.cursor_screen_row());
|
EXPECT_EQ(1, bv.cursor_screen_row());
|
||||||
iterator->go_previous_line(); // to 5
|
bv.cursor_move(BufferView::CursorMovement::UP, false); // to 5
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(1, bv.cursor_screen_row());
|
EXPECT_EQ(1, bv.cursor_screen_row());
|
||||||
iterator->go_previous_line(); // to 4
|
bv.cursor_move(BufferView::CursorMovement::UP, false); // to 4
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(1, bv.cursor_screen_row());
|
EXPECT_EQ(1, bv.cursor_screen_row());
|
||||||
iterator->go_previous_line(); // to 3
|
bv.cursor_move(BufferView::CursorMovement::UP, false); // to 3
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(1, bv.cursor_screen_row());
|
EXPECT_EQ(1, bv.cursor_screen_row());
|
||||||
iterator->go_previous_line(); // to 2
|
bv.cursor_move(BufferView::CursorMovement::UP, false); // to 2
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(1, bv.cursor_screen_row());
|
EXPECT_EQ(1, bv.cursor_screen_row());
|
||||||
iterator->go_previous_line(); // to 1
|
bv.cursor_move(BufferView::CursorMovement::UP, false); // to 1
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(1, bv.cursor_screen_row());
|
EXPECT_EQ(1, bv.cursor_screen_row());
|
||||||
iterator->go_previous_line(); // to 0
|
bv.cursor_move(BufferView::CursorMovement::UP, false); // to 0
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(0, bv.cursor_screen_row());
|
EXPECT_EQ(0, bv.cursor_screen_row());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(BufferViewTest, moves_view_down_while_traversing_a_wrapped_line)
|
TEST(BufferViewTest, moves_view_down_while_traversing_a_wrapped_line_right)
|
||||||
{
|
{
|
||||||
auto b = buffer1();
|
auto b = buffer1();
|
||||||
auto iterator = b->add_iterator();
|
auto iterator = b->add_iterator();
|
||||||
@ -251,15 +254,16 @@ TEST(BufferViewTest, moves_view_down_while_traversing_a_wrapped_line)
|
|||||||
bv.resize(4, 10);
|
bv.resize(4, 10);
|
||||||
for (int i = 0; i < 9; i++)
|
for (int i = 0; i < 9; i++)
|
||||||
{
|
{
|
||||||
iterator->go_next_line();
|
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::DOWN, false));
|
||||||
bv.update();
|
bv.update();
|
||||||
}
|
}
|
||||||
EXPECT_EQ(9, bv.cursor_screen_row());
|
EXPECT_EQ(9, bv.cursor_screen_row());
|
||||||
EXPECT_EQ(0, bv.cursor_screen_column());
|
EXPECT_EQ(0, bv.cursor_screen_column());
|
||||||
EXPECT_EQ(0, bv.cursor_virtual_column());
|
EXPECT_EQ(0, bv.cursor_virtual_column());
|
||||||
|
EXPECT_EQ(C('9'), **iterator);
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
iterator->go_forward();
|
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::RIGHT, false));
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(9, bv.cursor_screen_row());
|
EXPECT_EQ(9, bv.cursor_screen_row());
|
||||||
EXPECT_EQ(1 + i, bv.cursor_screen_column());
|
EXPECT_EQ(1 + i, bv.cursor_screen_column());
|
||||||
@ -267,7 +271,7 @@ TEST(BufferViewTest, moves_view_down_while_traversing_a_wrapped_line)
|
|||||||
}
|
}
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
iterator->go_forward();
|
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::RIGHT, false));
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(9, bv.cursor_screen_row());
|
EXPECT_EQ(9, bv.cursor_screen_row());
|
||||||
EXPECT_EQ(i, bv.cursor_screen_column());
|
EXPECT_EQ(i, bv.cursor_screen_column());
|
||||||
@ -275,10 +279,191 @@ TEST(BufferViewTest, moves_view_down_while_traversing_a_wrapped_line)
|
|||||||
}
|
}
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
iterator->go_forward();
|
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::RIGHT, false));
|
||||||
bv.update();
|
bv.update();
|
||||||
EXPECT_EQ(9, bv.cursor_screen_row());
|
EXPECT_EQ(9, bv.cursor_screen_row());
|
||||||
EXPECT_EQ(i, bv.cursor_screen_column());
|
EXPECT_EQ(i, bv.cursor_screen_column());
|
||||||
EXPECT_EQ(8 + i, bv.cursor_virtual_column());
|
EXPECT_EQ(8 + i, bv.cursor_virtual_column());
|
||||||
}
|
}
|
||||||
|
EXPECT_EQ(C('k'), **iterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(BufferViewTest, moves_view_down_while_jumping_to_the_end_of_a_wrapped_line)
|
||||||
|
{
|
||||||
|
auto b = buffer1();
|
||||||
|
auto iterator = b->add_iterator();
|
||||||
|
BufferView bv(b, iterator, Cwd);
|
||||||
|
bv.resize(4, 10);
|
||||||
|
for (int i = 0; i < 9; i++)
|
||||||
|
{
|
||||||
|
bv.cursor_move(BufferView::CursorMovement::DOWN, false);
|
||||||
|
bv.update();
|
||||||
|
}
|
||||||
|
EXPECT_EQ(9, bv.cursor_screen_row());
|
||||||
|
EXPECT_EQ(0, bv.cursor_screen_column());
|
||||||
|
EXPECT_EQ(0, bv.cursor_virtual_column());
|
||||||
|
EXPECT_EQ(C('9'), **iterator);
|
||||||
|
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::EOL, false));
|
||||||
|
bv.update();
|
||||||
|
EXPECT_EQ(9, bv.cursor_screen_row());
|
||||||
|
EXPECT_EQ(3, bv.cursor_screen_column());
|
||||||
|
EXPECT_EQ(15, bv.cursor_virtual_column());
|
||||||
|
EXPECT_EQ(C('o'), **iterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(BufferViewTest, moves_view_up_while_traversing_a_wrapped_line_left)
|
||||||
|
{
|
||||||
|
auto b = buffer1();
|
||||||
|
auto iterator = b->add_iterator();
|
||||||
|
BufferView bv(b, iterator, Cwd);
|
||||||
|
bv.resize(2, 3);
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::DOWN, false));
|
||||||
|
bv.update();
|
||||||
|
}
|
||||||
|
EXPECT_EQ(2, bv.cursor_screen_row());
|
||||||
|
EXPECT_EQ(0, bv.cursor_screen_column());
|
||||||
|
EXPECT_EQ(0, bv.cursor_virtual_column());
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
iterator->go_back();
|
||||||
|
}
|
||||||
|
/* Cursor at end of line 2 */
|
||||||
|
bv.set_cursor_screen_row(0);
|
||||||
|
bv.update();
|
||||||
|
EXPECT_EQ(0, bv.cursor_screen_row());
|
||||||
|
EXPECT_EQ(1, bv.cursor_screen_column());
|
||||||
|
EXPECT_EQ(3, bv.cursor_virtual_column());
|
||||||
|
EXPECT_EQ(C('c'), **iterator);
|
||||||
|
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::LEFT, false));
|
||||||
|
bv.update();
|
||||||
|
EXPECT_EQ(0, bv.cursor_screen_row());
|
||||||
|
EXPECT_EQ(0, bv.cursor_screen_column());
|
||||||
|
EXPECT_EQ(2, bv.cursor_virtual_column());
|
||||||
|
EXPECT_EQ(C('b'), **iterator);
|
||||||
|
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::LEFT, false));
|
||||||
|
bv.update();
|
||||||
|
EXPECT_EQ(0, bv.cursor_screen_row());
|
||||||
|
EXPECT_EQ(1, bv.cursor_screen_column());
|
||||||
|
EXPECT_EQ(1, bv.cursor_virtual_column());
|
||||||
|
EXPECT_EQ(C('a'), **iterator);
|
||||||
|
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::LEFT, false));
|
||||||
|
bv.update();
|
||||||
|
EXPECT_EQ(0, bv.cursor_screen_row());
|
||||||
|
EXPECT_EQ(0, bv.cursor_screen_column());
|
||||||
|
EXPECT_EQ(0, bv.cursor_virtual_column());
|
||||||
|
EXPECT_EQ(C('2'), **iterator);
|
||||||
|
EXPECT_FALSE(bv.cursor_move(BufferView::CursorMovement::LEFT, false));
|
||||||
|
bv.update();
|
||||||
|
EXPECT_EQ(0, bv.cursor_screen_row());
|
||||||
|
EXPECT_EQ(0, bv.cursor_screen_column());
|
||||||
|
EXPECT_EQ(0, bv.cursor_virtual_column());
|
||||||
|
EXPECT_EQ(C('2'), **iterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(BufferViewTest, moves_view_up_while_jumping_to_start_of_a_wrapped_line)
|
||||||
|
{
|
||||||
|
auto b = buffer1();
|
||||||
|
auto iterator = b->add_iterator();
|
||||||
|
BufferView bv(b, iterator, Cwd);
|
||||||
|
bv.resize(2, 3);
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
bv.cursor_move(BufferView::CursorMovement::DOWN, false);
|
||||||
|
bv.update();
|
||||||
|
}
|
||||||
|
EXPECT_EQ(2, bv.cursor_screen_row());
|
||||||
|
EXPECT_EQ(0, bv.cursor_screen_column());
|
||||||
|
EXPECT_EQ(0, bv.cursor_virtual_column());
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
iterator->go_back();
|
||||||
|
}
|
||||||
|
/* Cursor at end of line 2 */
|
||||||
|
bv.set_cursor_screen_row(0);
|
||||||
|
bv.update();
|
||||||
|
EXPECT_EQ(0, bv.cursor_screen_row());
|
||||||
|
EXPECT_EQ(1, bv.cursor_screen_column());
|
||||||
|
EXPECT_EQ(3, bv.cursor_virtual_column());
|
||||||
|
EXPECT_EQ(C('c'), **iterator);
|
||||||
|
bv.cursor_move(BufferView::CursorMovement::SOL, false);
|
||||||
|
bv.update();
|
||||||
|
EXPECT_EQ(0, bv.cursor_screen_row());
|
||||||
|
EXPECT_EQ(0, bv.cursor_screen_column());
|
||||||
|
EXPECT_EQ(0, bv.cursor_virtual_column());
|
||||||
|
EXPECT_EQ(C('2'), **iterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(BufferViewTest, warps_view_when_jumping_to_beginning_and_end_of_buffer)
|
||||||
|
{
|
||||||
|
auto b = buffer1();
|
||||||
|
auto iterator = b->add_iterator();
|
||||||
|
BufferView bv(b, iterator, Cwd);
|
||||||
|
bv.resize(4, 4);
|
||||||
|
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::LAST_LINE, false));
|
||||||
|
bv.update();
|
||||||
|
EXPECT_EQ(12, LineNumber(iterator));
|
||||||
|
EXPECT_EQ(3, bv.cursor_screen_row());
|
||||||
|
EXPECT_EQ(0, bv.cursor_screen_column());
|
||||||
|
EXPECT_EQ(0, bv.cursor_virtual_column());
|
||||||
|
EXPECT_FALSE(bv.cursor_move(BufferView::CursorMovement::LAST_LINE, false));
|
||||||
|
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::FIRST_LINE, false));
|
||||||
|
bv.update();
|
||||||
|
EXPECT_EQ(0, LineNumber(iterator));
|
||||||
|
EXPECT_EQ(0, bv.cursor_screen_row());
|
||||||
|
EXPECT_EQ(0, bv.cursor_screen_column());
|
||||||
|
EXPECT_EQ(0, bv.cursor_virtual_column());
|
||||||
|
EXPECT_FALSE(bv.cursor_move(BufferView::CursorMovement::FIRST_LINE, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(BufferViewTest, sets_target_column_to_eol_when_jumping_to_SOL_and_EOL)
|
||||||
|
{
|
||||||
|
auto b = buffer1();
|
||||||
|
auto iterator = b->add_iterator();
|
||||||
|
BufferView bv(b, iterator, Cwd);
|
||||||
|
bv.resize(4, 4);
|
||||||
|
bv.cursor_move(BufferView::CursorMovement::EOL, false);
|
||||||
|
bv.update();
|
||||||
|
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::DOWN, false));
|
||||||
|
bv.update();
|
||||||
|
EXPECT_EQ(1, bv.cursor_screen_row());
|
||||||
|
EXPECT_EQ(C('b'), **iterator);
|
||||||
|
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::UP, false));
|
||||||
|
bv.update();
|
||||||
|
EXPECT_EQ(0, bv.cursor_screen_row());
|
||||||
|
bv.cursor_move(BufferView::CursorMovement::SOL, false);
|
||||||
|
bv.update();
|
||||||
|
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::DOWN, false));
|
||||||
|
EXPECT_EQ(C('1'), **iterator);
|
||||||
|
EXPECT_EQ(1, bv.cursor_screen_row());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(BufferViewTest, sets_target_column_when_traversing_left_and_right)
|
||||||
|
{
|
||||||
|
auto b = buffer1();
|
||||||
|
auto iterator = b->add_iterator();
|
||||||
|
BufferView bv(b, iterator, Cwd);
|
||||||
|
bv.resize(4, 4);
|
||||||
|
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::DOWN, false));
|
||||||
|
bv.update();
|
||||||
|
EXPECT_EQ(1, LineNumber(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(1, LineNumber(iterator));
|
||||||
|
EXPECT_EQ(C('b'), **iterator);
|
||||||
|
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::DOWN, false));
|
||||||
|
bv.update();
|
||||||
|
EXPECT_EQ(2, LineNumber(iterator));
|
||||||
|
EXPECT_EQ(C('b'), **iterator);
|
||||||
|
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::LEFT, false));
|
||||||
|
bv.update();
|
||||||
|
EXPECT_EQ(2, LineNumber(iterator));
|
||||||
|
EXPECT_EQ(C('a'), **iterator);
|
||||||
|
EXPECT_TRUE(bv.cursor_move(BufferView::CursorMovement::UP, false));
|
||||||
|
bv.update();
|
||||||
|
EXPECT_EQ(1, LineNumber(iterator));
|
||||||
|
EXPECT_EQ(C('a'), **iterator);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user