From d2c6ceb47b532d125c3cafffdca79fada54ee21f Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Mon, 24 Oct 2011 14:26:21 +0000 Subject: [PATCH] DynamicBufferIterator: add and use in Selections DynamicBufferIterator are a new type of BufferIterators that automatically update themselves when their buffer is modified. Selections now uses this type of iterators instead of plain ones --- src/buffer.cc | 4 +- src/buffer.hh | 7 ++-- src/buffer_iterator.inl.h | 5 +++ src/dynamic_buffer_iterator.cc | 71 ++++++++++++++++++++++++++++++++++ src/dynamic_buffer_iterator.hh | 35 +++++++++++++++++ src/window.cc | 6 --- src/window.hh | 5 ++- 7 files changed, 120 insertions(+), 13 deletions(-) create mode 100644 src/dynamic_buffer_iterator.cc create mode 100644 src/dynamic_buffer_iterator.hh diff --git a/src/buffer.cc b/src/buffer.cc index f9aac0b84..d5ec4349a 100644 --- a/src/buffer.cc +++ b/src/buffer.cc @@ -254,14 +254,14 @@ void Buffer::notify_saved() m_last_save_undo_group = m_history_cursor; } -void Buffer::register_modification_listener(BufferModificationListener* listener) +void Buffer::register_modification_listener(BufferModificationListener* listener) const { assert(listener); assert(not contains(m_modification_listeners, listener)); m_modification_listeners.push_back(listener); } -void Buffer::unregister_modification_listener(BufferModificationListener* listener) +void Buffer::unregister_modification_listener(BufferModificationListener* listener) const { assert(listener); auto it = std::find(m_modification_listeners.begin(), diff --git a/src/buffer.hh b/src/buffer.hh index aee9fba2d..ac3f0d609 100644 --- a/src/buffer.hh +++ b/src/buffer.hh @@ -63,6 +63,7 @@ public: bool is_begin() const; bool is_end() const; + bool is_valid() const; const Buffer& buffer() const; @@ -145,8 +146,8 @@ public: Type type() const { return m_type; } void notify_saved(); - void register_modification_listener(BufferModificationListener* listener); - void unregister_modification_listener(BufferModificationListener* listener); + void register_modification_listener(BufferModificationListener* listener) const; + void unregister_modification_listener(BufferModificationListener* listener) const; private: BufferChar at(BufferPos position) const; @@ -185,7 +186,7 @@ private: std::vector::iterator m_last_save_undo_group; - std::vector m_modification_listeners; + mutable std::vector m_modification_listeners; }; } diff --git a/src/buffer_iterator.inl.h b/src/buffer_iterator.inl.h index db59a8b40..feae368de 100644 --- a/src/buffer_iterator.inl.h +++ b/src/buffer_iterator.inl.h @@ -18,6 +18,11 @@ inline const Buffer& BufferIterator::buffer() const return *m_buffer; } +inline bool BufferIterator::is_valid() const +{ + return m_buffer; +} + inline BufferIterator& BufferIterator::operator=(const BufferIterator& iterator) { m_buffer = iterator.m_buffer; diff --git a/src/dynamic_buffer_iterator.cc b/src/dynamic_buffer_iterator.cc new file mode 100644 index 000000000..42c9d39cb --- /dev/null +++ b/src/dynamic_buffer_iterator.cc @@ -0,0 +1,71 @@ +#include "dynamic_buffer_iterator.hh" + +namespace Kakoune +{ + +DynamicBufferIterator::DynamicBufferIterator(const Buffer& buffer, + BufferPos position) + : BufferIterator(buffer, position) +{ + register_ifp(); +} + +DynamicBufferIterator::DynamicBufferIterator(DynamicBufferIterator&& other) + : BufferIterator(other) +{ + register_ifp(); +} + +DynamicBufferIterator::DynamicBufferIterator(const BufferIterator& other) + : BufferIterator(other) +{ + register_ifp(); +} + +DynamicBufferIterator& DynamicBufferIterator::operator=(const BufferIterator& other) +{ + unregister_ifn(); + BufferIterator::operator=(other); + register_ifp(); + + return *this; +} + +DynamicBufferIterator::~DynamicBufferIterator() +{ + unregister_ifn(); +} + +void DynamicBufferIterator::on_modification(const BufferModification& modification) +{ + if (*this < modification.position) + return; + + size_t length = modification.content.length(); + if (modification.type == BufferModification::Erase) + { + if (*this <= modification.position + length) + BufferIterator::operator=(modification.position); + else + *this -= length; + } + else + { + assert(modification.type == BufferModification::Insert); + *this += length; + } +} + +void DynamicBufferIterator::register_ifp() +{ + if (is_valid()) + buffer().register_modification_listener(this); +} + +void DynamicBufferIterator::unregister_ifn() +{ + if (is_valid()) + buffer().unregister_modification_listener(this); +} + +} diff --git a/src/dynamic_buffer_iterator.hh b/src/dynamic_buffer_iterator.hh new file mode 100644 index 000000000..17e744855 --- /dev/null +++ b/src/dynamic_buffer_iterator.hh @@ -0,0 +1,35 @@ +#ifndef dynamic_buffer_iterator_hh_INCLUDED +#define dynamic_buffer_iterator_hh_INCLUDED + +#include "buffer.hh" + +namespace Kakoune +{ + +class DynamicBufferIterator : public BufferIterator, + public BufferModificationListener +{ +public: + DynamicBufferIterator() : BufferIterator() {} + DynamicBufferIterator(const Buffer& buffer, BufferPos position); + DynamicBufferIterator(const BufferIterator& other); + DynamicBufferIterator(const DynamicBufferIterator& other) + : BufferIterator(other) { register_ifp(); } + + DynamicBufferIterator(DynamicBufferIterator&& other); + DynamicBufferIterator& operator=(const BufferIterator& other); + DynamicBufferIterator& operator=(const DynamicBufferIterator& other) + { return this->operator= (static_cast(other)); } + ~DynamicBufferIterator(); + + void on_modification(const BufferModification& modification); + +private: + void register_ifp(); + void unregister_ifn(); +}; + + +} + +#endif // dynamic_buffer_iterator_hh_INCLUDED diff --git a/src/window.cc b/src/window.cc index 0c7991c7b..5f10618c0 100644 --- a/src/window.cc +++ b/src/window.cc @@ -144,10 +144,7 @@ void Window::erase_noundo() { check_invariant(); for (auto& sel : m_selections) - { m_buffer.erase(sel.begin(), sel.end()); - sel = Selection(sel.begin(), sel.begin()); - } scroll_to_keep_cursor_visible_ifn(); } @@ -183,10 +180,7 @@ void Window::insert(const String& string) void Window::insert_noundo(const String& string) { for (auto& sel : m_selections) - { m_buffer.insert(sel.begin(), string); - sel.offset(string.length()); - } scroll_to_keep_cursor_visible_ifn(); } diff --git a/src/window.hh b/src/window.hh index 9ae7862cf..2b62794b1 100644 --- a/src/window.hh +++ b/src/window.hh @@ -4,6 +4,7 @@ #include #include "buffer.hh" +#include "dynamic_buffer_iterator.hh" #include "display_buffer.hh" namespace Kakoune @@ -23,8 +24,8 @@ struct Selection void offset(int offset); private: - BufferIterator m_first; - BufferIterator m_last; + DynamicBufferIterator m_first; + DynamicBufferIterator m_last; }; typedef std::vector SelectionList;