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
This commit is contained in:
Maxime Coste 2011-10-24 14:26:21 +00:00
parent bace526fa3
commit d2c6ceb47b
7 changed files with 120 additions and 13 deletions

View File

@ -254,14 +254,14 @@ void Buffer::notify_saved()
m_last_save_undo_group = m_history_cursor; 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(listener);
assert(not contains(m_modification_listeners, listener)); assert(not contains(m_modification_listeners, listener));
m_modification_listeners.push_back(listener); m_modification_listeners.push_back(listener);
} }
void Buffer::unregister_modification_listener(BufferModificationListener* listener) void Buffer::unregister_modification_listener(BufferModificationListener* listener) const
{ {
assert(listener); assert(listener);
auto it = std::find(m_modification_listeners.begin(), auto it = std::find(m_modification_listeners.begin(),

View File

@ -63,6 +63,7 @@ public:
bool is_begin() const; bool is_begin() const;
bool is_end() const; bool is_end() const;
bool is_valid() const;
const Buffer& buffer() const; const Buffer& buffer() const;
@ -145,8 +146,8 @@ public:
Type type() const { return m_type; } Type type() const { return m_type; }
void notify_saved(); void notify_saved();
void register_modification_listener(BufferModificationListener* listener); void register_modification_listener(BufferModificationListener* listener) const;
void unregister_modification_listener(BufferModificationListener* listener); void unregister_modification_listener(BufferModificationListener* listener) const;
private: private:
BufferChar at(BufferPos position) const; BufferChar at(BufferPos position) const;
@ -185,7 +186,7 @@ private:
std::vector<UndoGroup>::iterator m_last_save_undo_group; std::vector<UndoGroup>::iterator m_last_save_undo_group;
std::vector<BufferModificationListener*> m_modification_listeners; mutable std::vector<BufferModificationListener*> m_modification_listeners;
}; };
} }

View File

@ -18,6 +18,11 @@ inline const Buffer& BufferIterator::buffer() const
return *m_buffer; return *m_buffer;
} }
inline bool BufferIterator::is_valid() const
{
return m_buffer;
}
inline BufferIterator& BufferIterator::operator=(const BufferIterator& iterator) inline BufferIterator& BufferIterator::operator=(const BufferIterator& iterator)
{ {
m_buffer = iterator.m_buffer; m_buffer = iterator.m_buffer;

View File

@ -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);
}
}

View File

@ -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<const BufferIterator&>(other)); }
~DynamicBufferIterator();
void on_modification(const BufferModification& modification);
private:
void register_ifp();
void unregister_ifn();
};
}
#endif // dynamic_buffer_iterator_hh_INCLUDED

View File

@ -144,10 +144,7 @@ void Window::erase_noundo()
{ {
check_invariant(); check_invariant();
for (auto& sel : m_selections) for (auto& sel : m_selections)
{
m_buffer.erase(sel.begin(), sel.end()); m_buffer.erase(sel.begin(), sel.end());
sel = Selection(sel.begin(), sel.begin());
}
scroll_to_keep_cursor_visible_ifn(); scroll_to_keep_cursor_visible_ifn();
} }
@ -183,10 +180,7 @@ void Window::insert(const String& string)
void Window::insert_noundo(const String& string) void Window::insert_noundo(const String& string)
{ {
for (auto& sel : m_selections) for (auto& sel : m_selections)
{
m_buffer.insert(sel.begin(), string); m_buffer.insert(sel.begin(), string);
sel.offset(string.length());
}
scroll_to_keep_cursor_visible_ifn(); scroll_to_keep_cursor_visible_ifn();
} }

View File

@ -4,6 +4,7 @@
#include <functional> #include <functional>
#include "buffer.hh" #include "buffer.hh"
#include "dynamic_buffer_iterator.hh"
#include "display_buffer.hh" #include "display_buffer.hh"
namespace Kakoune namespace Kakoune
@ -23,8 +24,8 @@ struct Selection
void offset(int offset); void offset(int offset);
private: private:
BufferIterator m_first; DynamicBufferIterator m_first;
BufferIterator m_last; DynamicBufferIterator m_last;
}; };
typedef std::vector<Selection> SelectionList; typedef std::vector<Selection> SelectionList;