#ifndef CURSOR_H #define CURSOR_H #include #include #include "Encoding.h" #include "GapBuffer.h" class Iterator { public: Iterator(GapBuffer * gap_buffer, Encoding::Type encoding) { m_gap_buffer = gap_buffer; m_offset = 0u; m_encoding = encoding; } bool valid() const { return m_offset < m_gap_buffer->size(); } void go_forward(); bool check_go_forward(); void go_back(); bool check_go_back(); uint8_t * address() const { return m_gap_buffer->address(m_offset); } uint32_t operator*() const { if (valid()) { return Encoding::decode(m_encoding, address()); } else { return 0xFFFFFFFFu; } } GapBuffer * gap_buffer() const { return m_gap_buffer; } bool operator<(const Iterator & other) const { return m_offset < other.m_offset; } size_t offset() { return m_offset; } void set_offset(size_t new_offset) { m_offset = new_offset; } protected: GapBuffer * m_gap_buffer; size_t m_offset; Encoding::Type m_encoding; }; class Cursor { public: Cursor(GapBuffer * gap_buffer, Encoding::Type encoding) : m_iterator(gap_buffer, encoding) { m_line = 0u; init_column(); } bool is_start_of_line(); bool is_end_of_line(bool allow_eol); bool go_start_of_line(); bool go_end_of_line(bool allow_eol); bool go_left(); bool go_right(bool allow_eol); bool go_up(size_t target_column); bool go_down(size_t target_column); bool operator<(const Cursor & other) const { return m_iterator < other.m_iterator; } uint32_t operator*() const { return *m_iterator; } uint8_t * address() const { return m_iterator.address(); } bool valid() const { return m_iterator.valid(); } size_t line() const { return m_line; } size_t column() const { return m_column; } Iterator & iterator() { return m_iterator; } void set_line(size_t line) { m_line = line; } void calculate_column(); protected: Iterator m_iterator; size_t m_line; size_t m_column; void init_column(); void forward_to_column(size_t target_column); }; #endif