Split some PieceTable::Cursor functionality into PieceTable::Iterator
This commit is contained in:
parent
f659c14242
commit
d6b3810a3c
@ -31,16 +31,89 @@ std::shared_ptr<PieceTable::Cursor> PieceTable::add_cursor()
|
||||
{
|
||||
auto cursor = std::make_shared<Cursor>();
|
||||
|
||||
cursor->piece_table = this;
|
||||
cursor->piece = start_piece->next;
|
||||
cursor->line_number = 0u;
|
||||
cursor->offset = 0u;
|
||||
cursor->iterator.piece_table = this;
|
||||
cursor->iterator.piece = start_piece->next;
|
||||
cursor->iterator.offset = 0u;
|
||||
|
||||
m_cursors.push_back(cursor);
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
uint8_t PieceTable::Iterator::num_bytes_in_code_point() const
|
||||
{
|
||||
if (offset >= piece->length)
|
||||
{
|
||||
return 0u;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Encoding::num_bytes_in_code_point(piece_table->encoding, &piece->start[offset]);
|
||||
}
|
||||
}
|
||||
|
||||
void PieceTable::Iterator::go_next_position()
|
||||
{
|
||||
uint8_t code_point_size = num_bytes_in_code_point();
|
||||
if ((offset + code_point_size) >= piece->length)
|
||||
{
|
||||
go_next_piece();
|
||||
return;
|
||||
}
|
||||
offset += code_point_size;
|
||||
}
|
||||
|
||||
void PieceTable::Iterator::go_prev_position()
|
||||
{
|
||||
if (offset > 0)
|
||||
{
|
||||
offset = Encoding::beginning_of_code_point(piece_table->encoding, &piece->start[offset - 1u]) - piece->start;
|
||||
}
|
||||
else if (piece != piece_table->start_piece)
|
||||
{
|
||||
piece = piece->prev;
|
||||
if (piece->length > 0u)
|
||||
{
|
||||
offset = Encoding::beginning_of_code_point(piece_table->encoding, &piece->start[piece->length - 1u]) - piece->start;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = 0u;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PieceTable::Iterator::go_end_of_piece()
|
||||
{
|
||||
if (piece->length > 0u)
|
||||
{
|
||||
offset = Encoding::beginning_of_code_point(piece_table->encoding, &piece->start[piece->length - 1u]) - piece->start;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = 0u;
|
||||
}
|
||||
}
|
||||
|
||||
void PieceTable::Iterator::go_next_piece()
|
||||
{
|
||||
if (piece != piece_table->end_piece)
|
||||
{
|
||||
piece = piece->next;
|
||||
offset = 0u;
|
||||
}
|
||||
}
|
||||
|
||||
void PieceTable::Iterator::go_prev_piece()
|
||||
{
|
||||
if (piece != piece_table->start_piece)
|
||||
{
|
||||
piece = piece->prev;
|
||||
offset = 0u;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
uint32_t PieceTable::Cursor::column() const
|
||||
{
|
||||
/* TODO: support tabs */
|
||||
@ -58,119 +131,104 @@ uint32_t PieceTable::Cursor::column() const
|
||||
}
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
void PieceTable::Cursor::go_start_of_line()
|
||||
{
|
||||
while ((!piece->prev->eol()) && (piece->prev != piece_table->start_piece))
|
||||
while (iterator.valid() && (!iterator.piece->prev->eol()))
|
||||
{
|
||||
piece = piece->prev;
|
||||
iterator.go_prev_piece();
|
||||
}
|
||||
offset = 0u;
|
||||
}
|
||||
|
||||
void PieceTable::Cursor::go_end_of_line()
|
||||
{
|
||||
/* TODO: Use Encoding */
|
||||
while ((!piece->eol()) && (piece->next != piece_table->end_piece))
|
||||
while (iterator.valid() && (!iterator.piece->eol()))
|
||||
{
|
||||
piece = piece->next;
|
||||
iterator.go_next_piece();
|
||||
}
|
||||
offset = (piece->length > 0u) ? piece->length - 1u : 0u;
|
||||
iterator.go_end_of_piece();
|
||||
}
|
||||
|
||||
bool PieceTable::Cursor::go_up(int n)
|
||||
{
|
||||
/* TODO: Use Encoding */
|
||||
/* TODO: support tabs */
|
||||
/* TODO: support n */
|
||||
Piece * p = prev_line();
|
||||
if (p == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
iterator.piece = p;
|
||||
iterator.offset = 0u;
|
||||
#if 0
|
||||
uint32_t current_column = column();
|
||||
piece = p;
|
||||
offset = 0u;
|
||||
line_number--;
|
||||
forward_to_column(current_column);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PieceTable::Cursor::go_down(int n)
|
||||
{
|
||||
/* TODO: Use Encoding */
|
||||
/* TODO: support tabs */
|
||||
/* TODO: support n */
|
||||
Piece * p = next_line();
|
||||
if (p == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
iterator.piece = p;
|
||||
iterator.offset = 0u;
|
||||
#if 0
|
||||
uint32_t current_column = column();
|
||||
piece = p;
|
||||
offset = 0u;
|
||||
line_number++;
|
||||
forward_to_column(current_column);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PieceTable::Cursor::go_left(int n)
|
||||
{
|
||||
/* TODO: Use Encoding */
|
||||
/* TODO: support tabs */
|
||||
/* TODO: support n */
|
||||
if (offset > 0)
|
||||
{
|
||||
offset--;
|
||||
}
|
||||
else if ((piece->prev != piece_table->start_piece) &&
|
||||
(!piece->prev->eol()))
|
||||
{
|
||||
piece = piece->prev;
|
||||
offset = piece->length - 1u;
|
||||
}
|
||||
else
|
||||
if (is_start_of_line())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
iterator.go_prev_position();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PieceTable::Cursor::go_right(int n)
|
||||
{
|
||||
/* TODO: Use Encoding */
|
||||
/* TODO: support tabs */
|
||||
/* TODO: support n */
|
||||
if (offset < piece->length - 1u)
|
||||
{
|
||||
offset++;
|
||||
}
|
||||
else if ((piece->next != piece_table->end_piece) &&
|
||||
(!piece->eol()))
|
||||
{
|
||||
piece = piece->next;
|
||||
offset = 0u;
|
||||
}
|
||||
else
|
||||
if (is_end_of_line())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
iterator.go_next_position();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PieceTable::Cursor::is_start_of_line()
|
||||
{
|
||||
return iterator.valid() &&
|
||||
(iterator.offset == 0u) &&
|
||||
(iterator.piece->prev->eol());
|
||||
}
|
||||
|
||||
bool PieceTable::Cursor::is_end_of_line()
|
||||
{
|
||||
return iterator.valid() &&
|
||||
((iterator.offset + iterator.num_bytes_in_code_point()) >= iterator.piece->length) &&
|
||||
iterator.piece->eol();
|
||||
}
|
||||
|
||||
PieceTable::Piece * PieceTable::Cursor::prev_line() const
|
||||
{
|
||||
Piece * p = piece;
|
||||
while ((!p->prev->eol()) && (p->prev != piece_table->start_piece))
|
||||
Piece * p = iterator.piece;
|
||||
while ((!p->prev->eol()) && (p->prev != iterator.piece_table->start_piece))
|
||||
{
|
||||
p = p->prev;
|
||||
}
|
||||
if (p->prev == piece_table->start_piece)
|
||||
if (p->prev == iterator.piece_table->start_piece)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
p = p->prev;
|
||||
while ((!p->prev->eol()) && (p->prev != piece_table->start_piece))
|
||||
while ((!p->prev->eol()) && (p->prev != iterator.piece_table->start_piece))
|
||||
{
|
||||
p = p->prev;
|
||||
}
|
||||
@ -179,23 +237,24 @@ PieceTable::Piece * PieceTable::Cursor::prev_line() const
|
||||
|
||||
PieceTable::Piece * PieceTable::Cursor::next_line() const
|
||||
{
|
||||
Piece * p = piece;
|
||||
while ((!p->eol()) && (p->next != piece_table->end_piece))
|
||||
Piece * p = iterator.piece;
|
||||
while ((!p->eol()) && (p->next != iterator.piece_table->end_piece))
|
||||
{
|
||||
p = p->next;
|
||||
}
|
||||
if (p->next == piece_table->end_piece)
|
||||
if (p->next == iterator.piece_table->end_piece)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
p = p->next;
|
||||
while ((!p->eol()) && (p->next != piece_table->end_piece))
|
||||
while ((!p->eol()) && (p->next != iterator.piece_table->end_piece))
|
||||
{
|
||||
p = p->next;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void PieceTable::Cursor::forward_to_column(uint32_t c)
|
||||
{
|
||||
uint32_t current_column = column();
|
||||
@ -214,3 +273,4 @@ void PieceTable::Cursor::forward_to_column(uint32_t c)
|
||||
diff = new_diff;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -48,7 +48,7 @@ public:
|
||||
void toggle_eol() { flags ^= EOL_FLAG; }
|
||||
};
|
||||
|
||||
struct Cursor
|
||||
struct Iterator
|
||||
{
|
||||
/** The piece table the cursor belongs to. */
|
||||
PieceTable * piece_table;
|
||||
@ -59,23 +59,49 @@ public:
|
||||
/** Byte offset within the piece. */
|
||||
uint32_t offset;
|
||||
|
||||
/** Line number the cursor is on (0 based). */
|
||||
uint32_t line_number;
|
||||
/** Get the character pointed to by the cursor. */
|
||||
uint32_t operator*() const
|
||||
{
|
||||
if (has_char())
|
||||
{
|
||||
return Encoding::decode(piece_table->encoding, &piece->start[offset]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0xFFFFFFFFu;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t num_bytes_in_code_point() const;
|
||||
|
||||
void go_next_position();
|
||||
void go_prev_position();
|
||||
void go_end_of_piece();
|
||||
void go_next_piece();
|
||||
void go_prev_piece();
|
||||
|
||||
bool valid() const
|
||||
{
|
||||
return (piece != piece_table->start_piece) &&
|
||||
(piece != piece_table->end_piece);
|
||||
}
|
||||
|
||||
bool has_char() const
|
||||
{
|
||||
return valid() && (offset < piece->length);
|
||||
}
|
||||
};
|
||||
|
||||
struct Cursor
|
||||
{
|
||||
Iterator iterator;
|
||||
|
||||
/** Get the character pointed to by the cursor. */
|
||||
uint32_t operator*() const
|
||||
{
|
||||
return Encoding::decode(piece_table->encoding, &piece->start[offset]);
|
||||
return *iterator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the screen column of the cursor (taking into account tabs).
|
||||
*
|
||||
* This function will return 0 only if the cursor is on an empty line.
|
||||
* The first column of a line with at least one character is column 1.
|
||||
*/
|
||||
uint32_t column() const;
|
||||
|
||||
void go_start_of_line();
|
||||
void go_end_of_line();
|
||||
bool go_up(int n = 1);
|
||||
@ -84,6 +110,8 @@ public:
|
||||
bool go_right(int n = 1);
|
||||
|
||||
protected:
|
||||
bool is_start_of_line();
|
||||
bool is_end_of_line();
|
||||
Piece * prev_line() const;
|
||||
Piece * next_line() const;
|
||||
void forward_to_column(uint32_t c);
|
||||
|
Loading…
x
Reference in New Issue
Block a user