diff --git a/src/gui/BufferPane.cc b/src/gui/BufferPane.cc index 37bcab9..f7172da 100644 --- a/src/gui/BufferPane.cc +++ b/src/gui/BufferPane.cc @@ -206,7 +206,7 @@ void BufferPane::draw() } else { - draw_cursor(col_x(0), row_y(0), m_buffer->insert_mode()); + draw_cursor(col_x(0), row_y(0)); } draw_status_bar(); } @@ -224,7 +224,7 @@ int BufferPane::draw_buffer_line(int screen_row, const Buffer::Iterator & start_ if (i == *m_iterator) { /* TODO: highlight multi-column characters */ - draw_cursor(x, y, m_buffer->insert_mode()); + draw_cursor(x, y); } if ((code_point == '\n') || (code_point == Buffer::Iterator::INVALID_CODE_POINT)) { @@ -274,11 +274,11 @@ void BufferPane::draw_buffer_character(int screen_column, int screen_row, uint32 } } -void BufferPane::draw_cursor(int x, int y, bool insert_mode) +void BufferPane::draw_cursor(int x, int y) { int width = m_window->font()->get_advance(); int height = m_window->font()->get_line_height(); - if (insert_mode) + if (insert_mode()) { m_window->gl()->draw_rect(win_x(x), win_y(y), 1, height, 1.0, 0.2, 1.0, 1.0); m_window->gl()->draw_rect(win_x(x + 1), win_y(y + height - 1), 2, 1, 1.0, 0.2, 1.0, 1.0); @@ -290,103 +290,63 @@ void BufferPane::draw_cursor(int x, int y, bool insert_mode) } } -void BufferPane::handle_key(uint32_t keyval) +void BufferPane::exit_insert_mode() { - if (m_buffer->insert_mode()) + if (insert_mode()) { - if (keyval == '\033') + m_buffer->exit_insert_mode(); + if (!m_iterator->is_start_of_line()) { - m_buffer->exit_insert_mode(); - if (!m_iterator->is_start_of_line()) - { - m_iterator->go_back(); - } + m_iterator->go_back(); } - else if (keyval == SDLK_BACKSPACE) + m_window->request_redraw(); + } +} + +void BufferPane::insert_code_point(uint32_t code_point) +{ + if (insert_mode()) + { + if (code_point == '\b') { Buffer::Iterator i = *m_iterator; i.go_back(); if (i.valid()) { m_buffer->erase_code_point(i); - m_window->request_redraw(); } } - else if (keyval <= 0xFFu) + else { - if (keyval == SDLK_RETURN) + if (code_point == '\r') { - keyval = '\n'; + code_point = '\n'; m_cursor_screen_row++; } - m_buffer->insert_code_point(keyval); + m_buffer->insert_code_point(code_point); } m_window->request_redraw(); } - else +} + +void BufferPane::kill_character_at_cursor() +{ + if (**m_iterator != '\n') { - switch (keyval) + m_buffer->erase_code_point(*m_iterator); + if (**m_iterator == '\n') { - case '0': - cursor_move(CursorMovement::SOL); - break; - case '$': - cursor_move(CursorMovement::EOL); - break; - case 'A': - enter_insert_mode(EnterInsertModeMode::END_OF_LINE); - break; - case 'G': - cursor_move(CursorMovement::LAST_LINE); - break; - case 'I': - enter_insert_mode(EnterInsertModeMode::START_OF_LINE); - break; - case 'O': - enter_insert_mode(EnterInsertModeMode::NEW_LINE_BEFORE); - break; - case 'a': - enter_insert_mode(EnterInsertModeMode::END_OF_CHAR); - break; - case 'g': - cursor_move(CursorMovement::FIRST_LINE); - break; - case 'h': - cursor_move(CursorMovement::LEFT); - break; - case 'i': - enter_insert_mode(EnterInsertModeMode::START_OF_CHAR); - break; - case 'j': - cursor_move(CursorMovement::DOWN); - break; - case 'k': - cursor_move(CursorMovement::UP); - break; - case 'l': - cursor_move(CursorMovement::RIGHT); - break; - case 'o': - enter_insert_mode(EnterInsertModeMode::NEW_LINE_AFTER); - break; - case 'x': - if (**m_iterator != '\n') - { - m_buffer->erase_code_point(*m_iterator); - if (**m_iterator == '\n') - { - m_iterator->go_left_in_line(); - } - m_window->request_redraw(); - } - break; - case Window::KEYMOD_CTRL + 'w': - if (m_buffer->filename() != "") - { - m_buffer->write_to_file(m_buffer->filename().c_str()); - } - break; + m_iterator->go_left_in_line(); } + m_window->request_redraw(); + } +} + +void BufferPane::write_file() +{ + if (m_buffer->filename() != "") + { + m_buffer->write_to_file(m_buffer->filename().c_str()); } } @@ -396,7 +356,7 @@ size_t BufferPane::display_column() const { return 0u; } - if ((**m_iterator == '\n') && (!m_buffer->insert_mode())) + if ((**m_iterator == '\n') && (!insert_mode())) { Buffer::Iterator i = *m_iterator; if (!i.go_left_in_line()) @@ -407,31 +367,31 @@ size_t BufferPane::display_column() const return m_cursor_virtual_column + 1u; } -void BufferPane::cursor_move(CursorMovement which) +void BufferPane::cursor_move(Window::CursorMovement which) { bool moved = false; switch (which) { - case CursorMovement::LEFT: + case Window::CursorMovement::LEFT: moved = m_iterator->go_left_in_line(); break; - case CursorMovement::RIGHT: - moved = m_iterator->go_right_in_line(m_buffer->insert_mode()); + case Window::CursorMovement::RIGHT: + moved = m_iterator->go_right_in_line(insert_mode()); break; - case CursorMovement::UP: + case Window::CursorMovement::UP: moved = m_iterator->go_previous_line(); break; - case CursorMovement::DOWN: + case Window::CursorMovement::DOWN: moved = m_iterator->go_next_line(); break; - case CursorMovement::SOL: + case Window::CursorMovement::SOL: moved = m_iterator->go_start_of_line(); break; - case CursorMovement::EOL: - moved = m_iterator->go_end_of_line(m_buffer->insert_mode()); + case Window::CursorMovement::EOL: + moved = m_iterator->go_end_of_line(insert_mode()); break; - case CursorMovement::FIRST_LINE: + case Window::CursorMovement::FIRST_LINE: { auto it = m_buffer->begin(); if (it != *m_iterator) @@ -441,7 +401,7 @@ void BufferPane::cursor_move(CursorMovement which) } } break; - case CursorMovement::LAST_LINE: + case Window::CursorMovement::LAST_LINE: { auto it = m_buffer->end(); it.go_back(); @@ -458,8 +418,8 @@ void BufferPane::cursor_move(CursorMovement which) { switch (which) { - case CursorMovement::LEFT: - case CursorMovement::RIGHT: + case Window::CursorMovement::LEFT: + case Window::CursorMovement::RIGHT: { int cursor_row_offset; Buffer::Iterator start_of_line = *m_iterator; @@ -468,22 +428,22 @@ void BufferPane::cursor_move(CursorMovement which) m_target_column = m_cursor_virtual_column; } break; - case CursorMovement::UP: - forward_to_column(m_target_column, m_buffer->insert_mode()); + case Window::CursorMovement::UP: + forward_to_column(m_target_column, insert_mode()); break; - case CursorMovement::DOWN: - forward_to_column(m_target_column, m_buffer->insert_mode()); + case Window::CursorMovement::DOWN: + forward_to_column(m_target_column, insert_mode()); break; - case CursorMovement::SOL: + case Window::CursorMovement::SOL: m_target_column = 0; break; - case CursorMovement::EOL: + case Window::CursorMovement::EOL: m_target_column = INT_MAX; break; - case CursorMovement::FIRST_LINE: + case Window::CursorMovement::FIRST_LINE: m_cursor_screen_row = 0; break; - case CursorMovement::LAST_LINE: + case Window::CursorMovement::LAST_LINE: m_cursor_screen_row = m_rows; break; } @@ -492,40 +452,40 @@ void BufferPane::cursor_move(CursorMovement which) } } -void BufferPane::enter_insert_mode(EnterInsertModeMode which) +void BufferPane::enter_insert_mode(Window::EnterInsertModeMode which) { - if (m_buffer->insert_mode()) + if (insert_mode()) return; switch (which) { - case EnterInsertModeMode::START_OF_CHAR: + case Window::EnterInsertModeMode::START_OF_CHAR: m_buffer->enter_insert_mode(*m_iterator); break; - case EnterInsertModeMode::END_OF_CHAR: + case Window::EnterInsertModeMode::END_OF_CHAR: if (**m_iterator != '\n') { m_iterator->go_forward(); } m_buffer->enter_insert_mode(*m_iterator); break; - case EnterInsertModeMode::START_OF_LINE: + case Window::EnterInsertModeMode::START_OF_LINE: m_iterator->go_start_of_line(); - enter_insert_mode(EnterInsertModeMode::START_OF_CHAR); + enter_insert_mode(Window::EnterInsertModeMode::START_OF_CHAR); break; - case EnterInsertModeMode::END_OF_LINE: + case Window::EnterInsertModeMode::END_OF_LINE: m_iterator->go_end_of_line(false); - enter_insert_mode(EnterInsertModeMode::END_OF_CHAR); + enter_insert_mode(Window::EnterInsertModeMode::END_OF_CHAR); break; - case EnterInsertModeMode::NEW_LINE_BEFORE: + case Window::EnterInsertModeMode::NEW_LINE_BEFORE: m_iterator->go_start_of_line(); m_buffer->enter_insert_mode(*m_iterator); m_buffer->insert_code_point('\n'); m_buffer->exit_insert_mode(); - cursor_move(CursorMovement::UP); - enter_insert_mode(EnterInsertModeMode::START_OF_CHAR); + cursor_move(Window::CursorMovement::UP); + enter_insert_mode(Window::EnterInsertModeMode::START_OF_CHAR); break; - case EnterInsertModeMode::NEW_LINE_AFTER: + case Window::EnterInsertModeMode::NEW_LINE_AFTER: m_iterator->go_end_of_line(true); m_buffer->enter_insert_mode(*m_iterator); m_buffer->insert_code_point('\n'); diff --git a/src/gui/BufferPane.h b/src/gui/BufferPane.h index 135a03f..fb6a1fe 100644 --- a/src/gui/BufferPane.h +++ b/src/gui/BufferPane.h @@ -14,31 +14,15 @@ public: BufferPane(Window * window, std::shared_ptr buffer); void resize(int width, int height) override; void draw(); - void handle_key(uint32_t keyval); + void cursor_move(Window::CursorMovement which); + void enter_insert_mode(Window::EnterInsertModeMode which); + void insert_code_point(uint32_t code_point); + void exit_insert_mode(); + void kill_character_at_cursor(); + void write_file(); + bool insert_mode() const { return m_buffer->insert_mode(); } protected: - enum class CursorMovement : uint8_t - { - LEFT, - RIGHT, - UP, - DOWN, - SOL, - EOL, - FIRST_LINE, - LAST_LINE, - }; - - enum class EnterInsertModeMode : uint8_t - { - START_OF_CHAR, - END_OF_CHAR, - START_OF_LINE, - END_OF_LINE, - NEW_LINE_BEFORE, - NEW_LINE_AFTER, - }; - int effective_scroll_offset() { return std::min(m_scroll_offset, (m_rows - 1) / 2); @@ -46,7 +30,7 @@ protected: int draw_buffer_line(int screen_row, const Buffer::Iterator & start_of_line); int character_width(uint32_t character); void draw_buffer_character(int screen_column, int screen_row, uint32_t character); - void draw_cursor(int x, int y, bool insert_mode); + void draw_cursor(int x, int y); int rows_in_line(const Buffer::Iterator & start_of_line); int rows_in_line_with_iterator_offset(const Buffer::Iterator & start_of_line, const Buffer::Iterator & reference, int * iterator_row_offset); int screen_rows_below_line(const Buffer::Iterator & line); @@ -62,8 +46,6 @@ protected: { return m_height - (row + 1) * m_window->font()->get_line_height(); } - void cursor_move(CursorMovement which); - void enter_insert_mode(EnterInsertModeMode which); void forward_to_column(int column, bool allow_eol); size_t display_line() const { return m_iterator->line() + 1u; } size_t display_column() const; diff --git a/src/gui/Window.cc b/src/gui/Window.cc index 962eaba..cc724ba 100644 --- a/src/gui/Window.cc +++ b/src/gui/Window.cc @@ -226,13 +226,73 @@ void Window::handle_keysym(uint32_t keysym) void Window::handle_keyval(uint32_t keyval) { - if (keyval == KEYMOD_CTRL + 'q') + if (m_buffer_pane->insert_mode()) { - m_exit_requested = true; + if (keyval == '\033') + { + m_buffer_pane->exit_insert_mode(); + } + else if (keyval < 0xFFu) + { + m_buffer_pane->insert_code_point(keyval); + } } else { - m_buffer_pane->handle_key(keyval); + switch (keyval) + { + case '0': + m_buffer_pane->cursor_move(CursorMovement::SOL); + break; + case '$': + m_buffer_pane->cursor_move(CursorMovement::EOL); + break; + case 'A': + m_buffer_pane->enter_insert_mode(EnterInsertModeMode::END_OF_LINE); + break; + case 'G': + m_buffer_pane->cursor_move(CursorMovement::LAST_LINE); + break; + case 'I': + m_buffer_pane->enter_insert_mode(EnterInsertModeMode::START_OF_LINE); + break; + case 'O': + m_buffer_pane->enter_insert_mode(EnterInsertModeMode::NEW_LINE_BEFORE); + break; + case 'a': + m_buffer_pane->enter_insert_mode(EnterInsertModeMode::END_OF_CHAR); + break; + case 'g': + m_buffer_pane->cursor_move(CursorMovement::FIRST_LINE); + break; + case 'h': + m_buffer_pane->cursor_move(CursorMovement::LEFT); + break; + case 'i': + m_buffer_pane->enter_insert_mode(EnterInsertModeMode::START_OF_CHAR); + break; + case 'j': + m_buffer_pane->cursor_move(CursorMovement::DOWN); + break; + case 'k': + m_buffer_pane->cursor_move(CursorMovement::UP); + break; + case 'l': + m_buffer_pane->cursor_move(CursorMovement::RIGHT); + break; + case 'o': + m_buffer_pane->enter_insert_mode(EnterInsertModeMode::NEW_LINE_AFTER); + break; + case 'x': + m_buffer_pane->kill_character_at_cursor(); + break; + case KEYMOD_CTRL + 'w': + m_buffer_pane->write_file(); + break; + case KEYMOD_CTRL + 'q': + m_exit_requested = true; + break; + } } } diff --git a/src/gui/Window.h b/src/gui/Window.h index acb2670..5835f53 100644 --- a/src/gui/Window.h +++ b/src/gui/Window.h @@ -21,6 +21,28 @@ public: KEYMOD_GUI = 0x80000, }; + enum class CursorMovement : uint8_t + { + LEFT, + RIGHT, + UP, + DOWN, + SOL, + EOL, + FIRST_LINE, + LAST_LINE, + }; + + enum class EnterInsertModeMode : uint8_t + { + START_OF_CHAR, + END_OF_CHAR, + START_OF_LINE, + END_OF_LINE, + NEW_LINE_BEFORE, + NEW_LINE_AFTER, + }; + bool create(std::shared_ptr buffer); void run_event_loop(); void request_redraw() { m_redraw_requested = true; }