#ifndef BUFFERVIEW_H #define BUFFERVIEW_H #include "Buffer.h" #include "CharacterWidthDeterminer.h" #include #include "BufferLineWalker.h" #include /** * Tracks a "view" of a buffer, which is a two-dimensional grid of characters * that displays a section of a buffer's contents. */ class BufferView { public: enum class CursorMovement : uint8_t { LEFT, RIGHT, UP, DOWN, SOL, EOL, START_OF_FILE, END_OF_FILE, FIRST_LINE, LAST_LINE, SCREEN_ROW_UP, SCREEN_ROW_DOWN, FORWARD_UP_TO_CHAR, FORWARD_ON_TO_CHAR, BACK_UP_TO_CHAR, BACK_ON_TO_CHAR, TOP_OF_SCREEN, MIDDLE_OF_SCREEN, BOTTOM_OF_SCREEN, }; class Iterator { public: Iterator(BufferView & bv) : m_buffer_view(bv) { m_index = 0u; } void operator++() { (*this)++; } void operator++(int unused) { m_index++; } bool is_valid() { return m_index < m_buffer_view.m_lines.size(); } int row_offset() const { return m_buffer_view.m_lines[m_index].row_offset; } int n_rows() const { return m_buffer_view.m_lines[m_index].n_rows; } std::shared_ptr iterator() const { return m_buffer_view.m_lines[m_index].line; } protected: BufferView & m_buffer_view; size_t m_index; }; BufferView(std::shared_ptr buffer, std::shared_ptr iterator, CharacterWidthDeterminer & character_width_determiner); void resize(int width, int height); void set_scroll_offset(int scroll_offset); void update(); Iterator vert_iter(); BufferLineWalker horiz_iter(std::shared_ptr start_of_line) { return BufferLineWalker(m_buffer, start_of_line, m_width, m_character_width_determiner); } bool cursor_move(CursorMovement which, uint32_t c, bool allow_eol); bool cursor_move_to_line(size_t line); bool cursor_move_to_screen_position(int x, int y, bool allow_eol); int cursor_screen_row() const { return m_cursor_screen_row; } int cursor_screen_column() const { return m_cursor_screen_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; } void scroll_view_up(int n_lines, bool allow_eol); void scroll_view_down(int n_lines, bool allow_eol); protected: struct LineDescriptor { int row_offset; int n_rows; std::shared_ptr line; }; std::shared_ptr m_buffer; std::shared_ptr m_iterator; std::vector 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; /** Holds the screen row offset of the cursor in the current line */ int m_cursor_row_offset; int m_rows_in_cursor_line; int m_target_screen_column; int m_target_virtual_column; bool m_update_target_column; int effective_scroll_offset() { return std::min(m_scroll_offset, (m_height - 1) / 2); } void determine_new_cursor_screen_row(); int calculate_rows_in_line(std::shared_ptr start_of_line); int calculate_rows_in_cursor_line(std::shared_ptr start_of_line); int screen_rows_below_line(std::shared_ptr line); int screen_rows_above_line( std::shared_ptr line, std::list>> & backward_lines); void move_forward_to_column(int to_column, bool allow_eol); bool move_cursor_screen_row_up(bool allow_eol); bool move_cursor_screen_row_down(bool allow_eol); void move_forward_to_screen_position( std::shared_ptr line, int target_row_offset, bool allow_eol); int calculate_rows_above_screen(int stop_at); int calculate_rows_below_screen(int stop_at); int n_screen_rows_with_content() const; BufferLineWalker get_cursor_line_walker(); }; #endif