diff --git a/src/buffer.cc b/src/buffer.cc index a342ac07..b0263134 100644 --- a/src/buffer.cc +++ b/src/buffer.cc @@ -45,7 +45,7 @@ Buffer::~Buffer() { m_windows.clear(); BufferManager::instance().unregister_buffer(this); - assert(m_iterators_to_update.empty()); + assert(m_change_listeners.empty()); m_hook_manager.run_hook("BufClose", m_name, Context(*this)); } @@ -213,7 +213,8 @@ void Buffer::insert(const BufferIterator& pos, const String& content) for (size_t i = pos.line()+1; i < line_count(); ++i) m_lines[i].start += content.length(); - BufferCoord end_pos; + BufferIterator begin_it; + BufferIterator end_it; // if we inserted at the end of the buffer, we may have created a new // line without inserting a '\n' if (pos == end() and (pos == begin() or *(pos-1) == '\n')) @@ -230,7 +231,8 @@ void Buffer::insert(const BufferIterator& pos, const String& content) if (start != content.length()) m_lines.push_back({ offset + start, content.substr(start) }); - end_pos = end().m_coord; + begin_it = iterator_at({ pos.m_coord.line + 1, 0 }); + end_it = end(); } else { @@ -265,13 +267,14 @@ void Buffer::insert(const BufferIterator& pos, const String& content) else line_it = m_lines.insert(line_it, { offset + start, content.substr(start) + suffix }); - end_pos = { int(line_it - m_lines.begin()), int(line_it->length() - suffix.length()) }; + begin_it = pos; + end_it = iterator_at({ int(line_it - m_lines.begin()), int(line_it->length() - suffix.length()) }); } check_invariant(); - for (auto iterator : m_iterators_to_update) - iterator->on_insert(pos.m_coord, end_pos); + for (auto listener : m_change_listeners) + listener->on_insert(begin_it, end_it); } void Buffer::erase(const BufferIterator& pos, BufferSize length) @@ -291,8 +294,8 @@ void Buffer::erase(const BufferIterator& pos, BufferSize length) check_invariant(); - for (auto iterator : m_iterators_to_update) - iterator->on_erase(pos.m_coord, end.m_coord); + for (auto listener : m_change_listeners) + listener->on_erase(pos, end); } void Buffer::apply_modification(const Modification& modification) @@ -360,19 +363,19 @@ void Buffer::notify_saved() m_last_save_undo_index = history_cursor_index; } -void Buffer::add_iterator_to_update(BufferIterator& iterator) +void Buffer::add_change_listener(BufferChangeListener& listener) { - assert(not contains(m_iterators_to_update, &iterator)); - m_iterators_to_update.push_back(&iterator); + assert(not contains(m_change_listeners, &listener)); + m_change_listeners.push_back(&listener); } -void Buffer::remove_iterator_from_update(BufferIterator& iterator) +void Buffer::remove_change_listener(BufferChangeListener& listener) { - auto it = std::find(m_iterators_to_update.begin(), - m_iterators_to_update.end(), - &iterator); - assert(it != m_iterators_to_update.end()); - m_iterators_to_update.erase(it); + auto it = std::find(m_change_listeners.begin(), + m_change_listeners.end(), + &listener); + assert(it != m_change_listeners.end()); + m_change_listeners.erase(it); } } diff --git a/src/buffer.hh b/src/buffer.hh index 5fcf5811..4a1b3dcd 100644 --- a/src/buffer.hh +++ b/src/buffer.hh @@ -71,6 +71,7 @@ public: void on_erase(const BufferCoord& begin, const BufferCoord& end); const Buffer& buffer() const; + const BufferCoord& coord() const { return m_coord; } BufferSize line() const { return m_coord.line; } BufferSize column() const { return m_coord.column; } @@ -100,6 +101,13 @@ struct Modification static Modification make_insert(BufferIterator position, String content); }; +class BufferChangeListener +{ +public: + virtual void on_insert(const BufferIterator& begin, const BufferIterator& end) = 0; + virtual void on_erase(const BufferIterator& begin, const BufferIterator& end) = 0; +}; + // A Buffer is a in-memory representation of a file // // The Buffer class permits to read and mutate this file @@ -157,8 +165,8 @@ public: // notify the buffer that it was saved in the current state void notify_saved(); - void add_iterator_to_update(BufferIterator& iterator); - void remove_iterator_from_update(BufferIterator& iterator); + void add_change_listener(BufferChangeListener& listener); + void remove_change_listener(BufferChangeListener& listener); // returns an iterator pointing to the first character of the line // iterator is on @@ -210,7 +218,7 @@ private: size_t m_last_save_undo_index; - std::vector m_iterators_to_update; + std::vector m_change_listeners; OptionManager m_option_manager; HookManager m_hook_manager; diff --git a/src/selection.cc b/src/selection.cc index 46a38e0f..a892e9fc 100644 --- a/src/selection.cc +++ b/src/selection.cc @@ -54,18 +54,28 @@ void Selection::merge_with(const Selection& selection) m_last = selection.m_last; } +void Selection::on_insert(const BufferIterator& begin, const BufferIterator& end) +{ + m_first.on_insert(begin.coord(), end.coord()); + m_last.on_insert(begin.coord(), end.coord()); +} + +void Selection::on_erase(const BufferIterator& begin, const BufferIterator& end) +{ + m_first.on_erase(begin.coord(), end.coord()); + m_last.on_erase(begin.coord(), end.coord()); +} + void Selection::register_with_buffer() { Buffer& buffer = const_cast(m_first.buffer()); - buffer.add_iterator_to_update(m_first); - buffer.add_iterator_to_update(m_last); + buffer.add_change_listener(*this); } void Selection::unregister_with_buffer() { Buffer& buffer = const_cast(m_first.buffer()); - buffer.remove_iterator_from_update(m_first); - buffer.remove_iterator_from_update(m_last); + buffer.remove_change_listener(*this); } } diff --git a/src/selection.hh b/src/selection.hh index b29af9a2..29a008a2 100644 --- a/src/selection.hh +++ b/src/selection.hh @@ -12,7 +12,7 @@ namespace Kakoune // Selections are oriented, first may be > last, and inclusive. // Selection updates it's iterators according to modifications made // in the buffer. -struct Selection +struct Selection : public BufferChangeListener { Selection(const BufferIterator& first, const BufferIterator& last); Selection(const Selection& other); @@ -30,6 +30,9 @@ struct Selection void merge_with(const Selection& selection); + void on_insert(const BufferIterator& begin, const BufferIterator& end); + void on_erase(const BufferIterator& begin, const BufferIterator& end); + private: BufferIterator m_first; BufferIterator m_last;