diff --git a/src/window.cc b/src/window.cc index f34abcece..0544031e5 100644 --- a/src/window.cc +++ b/src/window.cc @@ -1,5 +1,7 @@ #include "window.hh" +#include "assert.hh" + #include namespace Kakoune @@ -9,7 +11,8 @@ Window::Window(Buffer& buffer) : m_buffer(buffer), m_position(0, 0), m_cursor(0, 0), - m_dimensions(0, 0) + m_dimensions(0, 0), + m_current_inserter(nullptr) { } @@ -215,4 +218,64 @@ void Window::scroll_to_keep_cursor_visible_ifn() } } +IncrementalInserter::IncrementalInserter(Window& window, bool append) + : m_window(window) +{ + assert(not m_window.m_current_inserter); + m_window.m_current_inserter = this; + + if (m_window.m_selections.empty()) + { + WindowCoord pos = m_window.m_cursor; + if (append) + pos += WindowCoord(0, 1); + m_cursors.push_back(pos); + } + else + { + for (auto& sel : m_window.m_selections) + { + const BufferIterator& pos = append ? sel.end() : sel.begin(); + m_cursors.push_back(m_window.line_and_column_at(pos)); + } + } + m_window.m_buffer.begin_undo_group(); +} + +IncrementalInserter::~IncrementalInserter() +{ + assert(m_window.m_current_inserter == this); + m_window.m_current_inserter = nullptr; + + m_window.m_buffer.end_undo_group(); +} + +void IncrementalInserter::insert(const Window::String& string) +{ + for (auto& cursor : m_cursors) + { + m_window.m_buffer.insert(m_window.iterator_at(cursor), string); + move_cursor(measure_string(string)); + } +} + +void IncrementalInserter::erase() +{ + for (auto& cursor : m_cursors) + { + BufferIterator pos = m_window.iterator_at(cursor); + m_window.m_buffer.erase(pos - 1, pos); + move_cursor(WindowCoord(0, -1)); + } +} + +void IncrementalInserter::move_cursor(const WindowCoord& offset) +{ + for (auto& cursor : m_cursors) + { + BufferCoord target = m_window.window_to_buffer(cursor + offset); + cursor = m_window.buffer_to_window(m_window.m_buffer.clamp(target)); + } +} + } diff --git a/src/window.hh b/src/window.hh index e4afbe2b1..85e871be2 100644 --- a/src/window.hh +++ b/src/window.hh @@ -44,6 +44,8 @@ private: typedef std::vector SelectionList; +class IncrementalInserter; + class Window { public: @@ -67,8 +69,6 @@ public: void move_cursor(const WindowCoord& offset); - const SelectionList& selections() const { return m_selections; } - void empty_selections(); void select(bool append, const Selector& selector); @@ -89,6 +89,9 @@ private: void scroll_to_keep_cursor_visible_ifn(); + friend class IncrementalInserter; + IncrementalInserter* m_current_inserter; + Buffer& m_buffer; BufferCoord m_position; WindowCoord m_cursor; @@ -97,6 +100,25 @@ private: DisplayBuffer m_display_buffer; }; +class IncrementalInserter +{ +public: + typedef std::vector CursorList; + + IncrementalInserter(Window& window, bool append = false); + ~IncrementalInserter(); + + void insert(const Window::String& string); + void erase(); + void move_cursor(const WindowCoord& offset); + + const CursorList& cursors() const { return m_cursors; } + +private: + Window& m_window; + std::vector m_cursors; +}; + } #endif // window_hh_INCLUDED