complete cursor movement routines taking Encoding and tabs into account

This commit is contained in:
Josh Holtrop 2016-08-27 16:53:55 -04:00
parent b478d17e16
commit 33a190c495
3 changed files with 74 additions and 48 deletions

View File

@ -116,25 +116,11 @@ void PieceTable::Iterator::go_prev_piece()
}
}
#if 0
uint32_t PieceTable::Cursor::column() const
PieceTable::Cursor::Cursor(PieceTable * pt) : iterator(pt)
{
/* TODO: support tabs */
Cursor sol = *this;
sol.go_start_of_line();
if (sol.piece->eol() && sol.piece->length == 0u)
{
return 0u;
}
uint32_t c = 1u;
while ((sol.piece != piece) || (sol.offset < offset))
{
sol.go_right();
c++;
}
return c;
line = iterator.valid() ? 1u : 0u;
init_column();
}
#endif
void PieceTable::Cursor::go_start_of_line()
{
@ -142,6 +128,7 @@ void PieceTable::Cursor::go_start_of_line()
{
iterator.go_prev_piece();
}
init_column();
}
void PieceTable::Cursor::go_end_of_line()
@ -151,9 +138,10 @@ void PieceTable::Cursor::go_end_of_line()
iterator.go_next_piece();
}
iterator.go_end_of_piece();
calculate_column();
}
bool PieceTable::Cursor::go_up(int n)
bool PieceTable::Cursor::go_up(int n, uint32_t desired_column)
{
Piece * p = prev_line();
if (p == nullptr)
@ -162,14 +150,13 @@ bool PieceTable::Cursor::go_up(int n)
}
iterator.piece = p;
iterator.offset = 0u;
#if 0
uint32_t current_column = column();
forward_to_column(current_column);
#endif
line--;
init_column();
forward_to_column(desired_column);
return true;
}
bool PieceTable::Cursor::go_down(int n)
bool PieceTable::Cursor::go_down(int n, uint32_t desired_column)
{
Piece * p = next_line();
if (p == nullptr)
@ -178,10 +165,9 @@ bool PieceTable::Cursor::go_down(int n)
}
iterator.piece = p;
iterator.offset = 0u;
#if 0
uint32_t current_column = column();
forward_to_column(current_column);
#endif
line++;
init_column();
forward_to_column(desired_column);
return true;
}
@ -191,7 +177,17 @@ bool PieceTable::Cursor::go_left(int n)
{
return false;
}
uint32_t chr = *iterator;
iterator.go_prev_position();
if (chr == '\t')
{
calculate_column();
}
else
{
/* TODO: handle multi-column characters */
column--;
}
return true;
}
@ -202,6 +198,17 @@ bool PieceTable::Cursor::go_right(int n)
return false;
}
iterator.go_next_position();
uint32_t chr = *iterator;
if (chr == '\t')
{
column += iterator.piece_table->tabstop;
column -= column % iterator.piece_table->tabstop;
}
else
{
/* TODO: handle multi-column characters */
column++;
}
return true;
}
@ -257,23 +264,36 @@ PieceTable::Piece * PieceTable::Cursor::next_line() const
return p;
}
#if 0
void PieceTable::Cursor::init_column()
{
uint32_t chr = *iterator;
/* TODO: handle multi-column characters */
column = (chr == 0xFFFFFFFFu) ? 0u : (chr == '\t') ? iterator.piece_table->tabstop : 1u;
}
void PieceTable::Cursor::calculate_column()
{
Cursor tmp_cursor = *this;
tmp_cursor.go_start_of_line();
while ((tmp_cursor.iterator.piece != iterator.piece) ||
(tmp_cursor.iterator.offset < iterator.offset))
{
tmp_cursor.go_right(1);
}
column = tmp_cursor.column;
}
void PieceTable::Cursor::forward_to_column(uint32_t c)
{
uint32_t current_column = column();
/* TODO: support tabs */
/* TODO: Use Encoding */
int32_t diff = abs((int32_t)(c - current_column));
while (go_right())
int32_t diff = abs((int32_t)(c - column));
while (go_right(1))
{
current_column++;
int32_t new_diff = abs((int32_t)(c - current_column));
int32_t new_diff = abs((int32_t)(c - column));
if (new_diff > diff)
{
go_left();
go_left(1);
return;
}
diff = new_diff;
}
}
#endif

View File

@ -98,26 +98,32 @@ public:
{
Iterator iterator;
uint32_t line;
uint32_t column;
/** Get the character pointed to by the cursor. */
uint32_t operator*() const
{
return *iterator;
}
Cursor(PieceTable * pt) : iterator(pt) {}
Cursor(PieceTable * pt);
void go_start_of_line();
void go_end_of_line();
bool go_up(int n = 1);
bool go_down(int n = 1);
bool go_left(int n = 1);
bool go_right(int n = 1);
bool go_up(int n, uint32_t desired_column);
bool go_down(int n, uint32_t desired_column);
bool go_left(int n);
bool go_right(int n);
protected:
bool is_start_of_line();
bool is_end_of_line();
Piece * prev_line() const;
Piece * next_line() const;
void init_column();
void calculate_column();
void forward_to_column(uint32_t c);
};

View File

@ -28,16 +28,16 @@ TEST(BufferTest, allows_navigating_using_cursors)
ASSERT_TRUE(b.load_from_file("test/files/line_endings/lf_format.txt"));
std::shared_ptr<PieceTable::Cursor> cursor = b.piece_table->add_cursor();
ASSERT_EQ((uint32_t)'H', **cursor);
cursor->go_up();
cursor->go_up(1, cursor->column);
ASSERT_EQ((uint32_t)'H', **cursor);
cursor->go_right();
cursor->go_right(1);
ASSERT_EQ((uint32_t)'e', **cursor);
cursor->go_down();
cursor->go_down(1, cursor->column);
ASSERT_EQ((uint32_t)'h', **cursor);
cursor->go_left();
cursor->go_left(1);
ASSERT_EQ((uint32_t)'T', **cursor);
cursor->go_left();
cursor->go_left(1);
ASSERT_EQ((uint32_t)'T', **cursor);
cursor->go_down();
cursor->go_down(1, cursor->column);
ASSERT_EQ((uint32_t)'T', **cursor);
}