diff --git a/src/gui/Window.cc b/src/gui/Window.cc index f23ff5e..91ed225 100644 --- a/src/gui/Window.cc +++ b/src/gui/Window.cc @@ -134,6 +134,7 @@ bool Window::create(std::shared_ptr buffer) m_cursor = m_buffer->piece_table->add_cursor(); m_start_piece = m_buffer->piece_table->start_piece->next; m_cursor_row = 0; + m_scroll_offset = 5; resize(); @@ -234,42 +235,73 @@ void Window::handle_key(uint32_t scancode, uint32_t mod) m_exit_requested = true; break; case SDL_SCANCODE_H: - cursor_left(); + cursor_move(CURSOR_LEFT); break; case SDL_SCANCODE_J: - cursor_down(); + cursor_move(CURSOR_DOWN); break; case SDL_SCANCODE_K: - cursor_up(); + cursor_move(CURSOR_UP); break; case SDL_SCANCODE_L: - cursor_right(); + cursor_move(CURSOR_RIGHT); break; } } -void Window::cursor_left() +void Window::cursor_move(int which) { - if (m_cursor->go_left(1)) + bool success = false; + int current_row_offset = m_cursor->column / m_columns; + int row_offset = 0; + + switch (which) + { + case CURSOR_LEFT: + success = m_cursor->go_left(1); + break; + case CURSOR_RIGHT: + success = m_cursor->go_right(1); + break; + case CURSOR_UP: + success = m_cursor->go_up(1, m_cursor->column); + break; + case CURSOR_DOWN: + success = m_cursor->go_down(1, m_cursor->column); + break; + } + if (success) + { + switch (which) + { + case CURSOR_LEFT: + case CURSOR_RIGHT: + row_offset = m_cursor->column / m_columns - current_row_offset; + break; + case CURSOR_UP: + { + PieceTable::Cursor c = *m_cursor; + c.go_end_of_line(); + row_offset = m_cursor->column / m_columns - c.column / m_columns - 1 - current_row_offset; + } + break; + case CURSOR_DOWN: + { + PieceTable::Cursor c = *m_cursor; + c.go_up(1, 0u); + c.go_end_of_line(); + row_offset = c.column / m_columns - current_row_offset + 1 + m_cursor->column / m_columns; + } + break; + } + update_cursor_row(m_cursor_row + row_offset); redraw(); + } } -void Window::cursor_right() +void Window::update_cursor_row(int cursor_row) { - if (m_cursor->go_right(1)) - redraw(); -} - -void Window::cursor_up() -{ - if (m_cursor->go_up(1, m_cursor->column)) - redraw(); -} - -void Window::cursor_down() -{ - if (m_cursor->go_down(1, m_cursor->column)) - redraw(); + m_cursor_row = std::max(m_scroll_offset, std::min(m_rows - m_scroll_offset - 1, cursor_row)); } std::pair Window::calculate_start_position() diff --git a/src/gui/Window.h b/src/gui/Window.h index c8fb945..b7c6c31 100644 --- a/src/gui/Window.h +++ b/src/gui/Window.h @@ -16,18 +16,24 @@ public: void run_event_loop(); protected: + enum + { + CURSOR_LEFT, + CURSOR_RIGHT, + CURSOR_UP, + CURSOR_DOWN, + }; + void resize(); void redraw(); void draw_cursor(int screen_column, int screen_row); void handle_event(SDL_Event & event); void handle_key(uint32_t scancode, uint32_t mod); - void cursor_left(); - void cursor_right(); - void cursor_up(); - void cursor_down(); + void cursor_move(int which); std::pair calculate_start_position(); void draw_text(); void draw_character(int screen_column, int screen_row, uint32_t character); + void update_cursor_row(int cursor_row); SDL_Window * m_window; bool m_exit_requested; @@ -43,6 +49,7 @@ protected: int m_columns; int m_rows; int m_cursor_row; + int m_scroll_offset; std::shared_ptr m_buffer;