diff --git a/src/dynamic_buffer_iterator.cc b/src/dynamic_buffer_iterator.cc deleted file mode 100644 index 363207e4b..000000000 --- a/src/dynamic_buffer_iterator.cc +++ /dev/null @@ -1,73 +0,0 @@ -#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 Modification& modification) -{ - if (*this < modification.position) - return; - - size_t length = modification.content.length(); - if (modification.type == Modification::Erase) - { - // do not move length on the other side of the inequality, - // as modification.position + length may be after buffer end - if (*this - length <= modification.position) - BufferIterator::operator=(modification.position); - else - *this -= length; - } - else - { - assert(modification.type == Modification::Insert); - *this += length; - } -} - -void DynamicBufferIterator::register_ifp() -{ - if (is_valid()) - const_cast(buffer()).register_modification_listener(this); -} - -void DynamicBufferIterator::unregister_ifn() -{ - if (is_valid()) - const_cast(buffer()).unregister_modification_listener(this); -} - -} diff --git a/src/dynamic_buffer_iterator.hh b/src/dynamic_buffer_iterator.hh deleted file mode 100644 index 873792bd3..000000000 --- a/src/dynamic_buffer_iterator.hh +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef dynamic_buffer_iterator_hh_INCLUDED -#define dynamic_buffer_iterator_hh_INCLUDED - -#include "buffer.hh" - -namespace Kakoune -{ - -class DynamicBufferIterator : public BufferIterator, - public ModificationListener -{ -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 Modification& 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 4e1e481fa..52edf3315 100644 --- a/src/window.cc +++ b/src/window.cc @@ -11,6 +11,55 @@ namespace Kakoune { +Selection::Selection(const BufferIterator& first, const BufferIterator& last, + const CaptureList& captures) + : m_first(first), m_last(last), m_captures(captures) +{ + register_with_buffer(); +} + +Selection::Selection(const BufferIterator& first, const BufferIterator& last, + CaptureList&& captures) + : m_first(first), m_last(last), m_captures(captures) +{ + register_with_buffer(); +} + +Selection::Selection(const Selection& other) + : m_first(other.m_first), m_last(other.m_last), + m_captures(other.m_captures) +{ + register_with_buffer(); +} + +Selection::Selection(Selection&& other) + : m_first(other.m_first), m_last(other.m_last), + m_captures(other.m_captures) +{ + register_with_buffer(); +} + +Selection::~Selection() +{ + unregister_with_buffer(); +} + +Selection& Selection::operator=(const Selection& other) +{ + const bool new_buffer = &m_first.buffer() != &other.m_first.buffer(); + if (new_buffer) + unregister_with_buffer(); + + m_first = other.m_first; + m_last = other.m_last; + m_captures = other.m_captures; + + if (new_buffer) + register_with_buffer(); + + return *this; +} + BufferIterator Selection::begin() const { return std::min(m_first, m_last); @@ -37,6 +86,45 @@ BufferString Selection::capture(size_t index) const return ""; } +static void update_iterator(const Modification& modification, + BufferIterator& iterator) +{ + if (iterator < modification.position) + return; + + size_t length = modification.content.length(); + if (modification.type == Modification::Erase) + { + // do not move length on the other side of the inequality, + // as modification.position + length may be after buffer end + if (iterator - length <= modification.position) + iterator = modification.position; + else + iterator -= length; + } + else + { + assert(modification.type == Modification::Insert); + iterator += length; + } +} + +void Selection::on_modification(const Modification& modification) +{ + update_iterator(modification, m_first); + update_iterator(modification, m_last); +} + +void Selection::register_with_buffer() +{ + const_cast(m_first.buffer()).register_modification_listener(this); +} + +void Selection::unregister_with_buffer() +{ + const_cast(m_first.buffer()).unregister_modification_listener(this); +} + struct scoped_undo_group { scoped_undo_group(Buffer& buffer) diff --git a/src/window.hh b/src/window.hh index 628730541..e1591d40d 100644 --- a/src/window.hh +++ b/src/window.hh @@ -4,7 +4,6 @@ #include #include "buffer.hh" -#include "dynamic_buffer_iterator.hh" #include "display_buffer.hh" #include "completion.hh" #include "highlighter.hh" @@ -16,17 +15,22 @@ namespace Kakoune { -struct Selection +struct Selection : public ModificationListener { typedef std::vector CaptureList; Selection(const BufferIterator& first, const BufferIterator& last, - const CaptureList& captures = CaptureList()) - : m_first(first), m_last(last), m_captures(captures) {} + const CaptureList& captures = CaptureList()); Selection(const BufferIterator& first, const BufferIterator& last, - CaptureList&& captures) - : m_first(first), m_last(last), m_captures(captures) {} + CaptureList&& captures); + + Selection(const Selection& other); + Selection(Selection&& other); + + ~Selection(); + + Selection& operator=(const Selection& other); BufferIterator begin() const; BufferIterator end() const; @@ -40,10 +44,17 @@ struct Selection const CaptureList& captures() const { return m_captures; } private: - DynamicBufferIterator m_first; - DynamicBufferIterator m_last; + BufferIterator m_first; + BufferIterator m_last; CaptureList m_captures; + + void on_modification(const Modification& modification); + + void register_with_buffer(); + void unregister_with_buffer(); + + void check_invariant(); }; typedef std::vector SelectionList;