complete cursor movement routines taking Encoding and tabs into account
This commit is contained in:
parent
b478d17e16
commit
33a190c495
@ -116,25 +116,11 @@ void PieceTable::Iterator::go_prev_piece()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
PieceTable::Cursor::Cursor(PieceTable * pt) : iterator(pt)
|
||||||
uint32_t PieceTable::Cursor::column() const
|
|
||||||
{
|
{
|
||||||
/* TODO: support tabs */
|
line = iterator.valid() ? 1u : 0u;
|
||||||
Cursor sol = *this;
|
init_column();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void PieceTable::Cursor::go_start_of_line()
|
void PieceTable::Cursor::go_start_of_line()
|
||||||
{
|
{
|
||||||
@ -142,6 +128,7 @@ void PieceTable::Cursor::go_start_of_line()
|
|||||||
{
|
{
|
||||||
iterator.go_prev_piece();
|
iterator.go_prev_piece();
|
||||||
}
|
}
|
||||||
|
init_column();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PieceTable::Cursor::go_end_of_line()
|
void PieceTable::Cursor::go_end_of_line()
|
||||||
@ -151,9 +138,10 @@ void PieceTable::Cursor::go_end_of_line()
|
|||||||
iterator.go_next_piece();
|
iterator.go_next_piece();
|
||||||
}
|
}
|
||||||
iterator.go_end_of_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();
|
Piece * p = prev_line();
|
||||||
if (p == nullptr)
|
if (p == nullptr)
|
||||||
@ -162,14 +150,13 @@ bool PieceTable::Cursor::go_up(int n)
|
|||||||
}
|
}
|
||||||
iterator.piece = p;
|
iterator.piece = p;
|
||||||
iterator.offset = 0u;
|
iterator.offset = 0u;
|
||||||
#if 0
|
line--;
|
||||||
uint32_t current_column = column();
|
init_column();
|
||||||
forward_to_column(current_column);
|
forward_to_column(desired_column);
|
||||||
#endif
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PieceTable::Cursor::go_down(int n)
|
bool PieceTable::Cursor::go_down(int n, uint32_t desired_column)
|
||||||
{
|
{
|
||||||
Piece * p = next_line();
|
Piece * p = next_line();
|
||||||
if (p == nullptr)
|
if (p == nullptr)
|
||||||
@ -178,10 +165,9 @@ bool PieceTable::Cursor::go_down(int n)
|
|||||||
}
|
}
|
||||||
iterator.piece = p;
|
iterator.piece = p;
|
||||||
iterator.offset = 0u;
|
iterator.offset = 0u;
|
||||||
#if 0
|
line++;
|
||||||
uint32_t current_column = column();
|
init_column();
|
||||||
forward_to_column(current_column);
|
forward_to_column(desired_column);
|
||||||
#endif
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +177,17 @@ bool PieceTable::Cursor::go_left(int n)
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
uint32_t chr = *iterator;
|
||||||
iterator.go_prev_position();
|
iterator.go_prev_position();
|
||||||
|
if (chr == '\t')
|
||||||
|
{
|
||||||
|
calculate_column();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* TODO: handle multi-column characters */
|
||||||
|
column--;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,6 +198,17 @@ bool PieceTable::Cursor::go_right(int n)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
iterator.go_next_position();
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,23 +264,36 @@ PieceTable::Piece * PieceTable::Cursor::next_line() const
|
|||||||
return p;
|
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)
|
void PieceTable::Cursor::forward_to_column(uint32_t c)
|
||||||
{
|
{
|
||||||
uint32_t current_column = column();
|
int32_t diff = abs((int32_t)(c - column));
|
||||||
/* TODO: support tabs */
|
while (go_right(1))
|
||||||
/* TODO: Use Encoding */
|
|
||||||
int32_t diff = abs((int32_t)(c - current_column));
|
|
||||||
while (go_right())
|
|
||||||
{
|
{
|
||||||
current_column++;
|
int32_t new_diff = abs((int32_t)(c - column));
|
||||||
int32_t new_diff = abs((int32_t)(c - current_column));
|
|
||||||
if (new_diff > diff)
|
if (new_diff > diff)
|
||||||
{
|
{
|
||||||
go_left();
|
go_left(1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
diff = new_diff;
|
diff = new_diff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
@ -98,26 +98,32 @@ public:
|
|||||||
{
|
{
|
||||||
Iterator iterator;
|
Iterator iterator;
|
||||||
|
|
||||||
|
uint32_t line;
|
||||||
|
|
||||||
|
uint32_t column;
|
||||||
|
|
||||||
/** Get the character pointed to by the cursor. */
|
/** Get the character pointed to by the cursor. */
|
||||||
uint32_t operator*() const
|
uint32_t operator*() const
|
||||||
{
|
{
|
||||||
return *iterator;
|
return *iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cursor(PieceTable * pt) : iterator(pt) {}
|
Cursor(PieceTable * pt);
|
||||||
|
|
||||||
void go_start_of_line();
|
void go_start_of_line();
|
||||||
void go_end_of_line();
|
void go_end_of_line();
|
||||||
bool go_up(int n = 1);
|
bool go_up(int n, uint32_t desired_column);
|
||||||
bool go_down(int n = 1);
|
bool go_down(int n, uint32_t desired_column);
|
||||||
bool go_left(int n = 1);
|
bool go_left(int n);
|
||||||
bool go_right(int n = 1);
|
bool go_right(int n);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool is_start_of_line();
|
bool is_start_of_line();
|
||||||
bool is_end_of_line();
|
bool is_end_of_line();
|
||||||
Piece * prev_line() const;
|
Piece * prev_line() const;
|
||||||
Piece * next_line() const;
|
Piece * next_line() const;
|
||||||
|
void init_column();
|
||||||
|
void calculate_column();
|
||||||
void forward_to_column(uint32_t c);
|
void forward_to_column(uint32_t c);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -28,16 +28,16 @@ TEST(BufferTest, allows_navigating_using_cursors)
|
|||||||
ASSERT_TRUE(b.load_from_file("test/files/line_endings/lf_format.txt"));
|
ASSERT_TRUE(b.load_from_file("test/files/line_endings/lf_format.txt"));
|
||||||
std::shared_ptr<PieceTable::Cursor> cursor = b.piece_table->add_cursor();
|
std::shared_ptr<PieceTable::Cursor> cursor = b.piece_table->add_cursor();
|
||||||
ASSERT_EQ((uint32_t)'H', **cursor);
|
ASSERT_EQ((uint32_t)'H', **cursor);
|
||||||
cursor->go_up();
|
cursor->go_up(1, cursor->column);
|
||||||
ASSERT_EQ((uint32_t)'H', **cursor);
|
ASSERT_EQ((uint32_t)'H', **cursor);
|
||||||
cursor->go_right();
|
cursor->go_right(1);
|
||||||
ASSERT_EQ((uint32_t)'e', **cursor);
|
ASSERT_EQ((uint32_t)'e', **cursor);
|
||||||
cursor->go_down();
|
cursor->go_down(1, cursor->column);
|
||||||
ASSERT_EQ((uint32_t)'h', **cursor);
|
ASSERT_EQ((uint32_t)'h', **cursor);
|
||||||
cursor->go_left();
|
cursor->go_left(1);
|
||||||
ASSERT_EQ((uint32_t)'T', **cursor);
|
ASSERT_EQ((uint32_t)'T', **cursor);
|
||||||
cursor->go_left();
|
cursor->go_left(1);
|
||||||
ASSERT_EQ((uint32_t)'T', **cursor);
|
ASSERT_EQ((uint32_t)'T', **cursor);
|
||||||
cursor->go_down();
|
cursor->go_down(1, cursor->column);
|
||||||
ASSERT_EQ((uint32_t)'T', **cursor);
|
ASSERT_EQ((uint32_t)'T', **cursor);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user