summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2011-10-24 14:26:21 +0000
committerMaxime Coste <frrrwww@gmail.com>2011-10-24 14:26:21 +0000
commitd2c6ceb47b532d125c3cafffdca79fada54ee21f (patch)
treee13757428f023d134cf0ba51bfab880a60c8ae40 /src
parentbace526fa31f1ce9fbc89a1c468f2dc91bee8845 (diff)
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
Diffstat (limited to 'src')
-rw-r--r--src/buffer.cc4
-rw-r--r--src/buffer.hh7
-rw-r--r--src/buffer_iterator.inl.h5
-rw-r--r--src/dynamic_buffer_iterator.cc71
-rw-r--r--src/dynamic_buffer_iterator.hh35
-rw-r--r--src/window.cc6
-rw-r--r--src/window.hh5
7 files changed, 120 insertions, 13 deletions
diff --git a/src/buffer.cc b/src/buffer.cc
index f9aac0b8..d5ec4349 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 aee9fba2..ac3f0d60 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<UndoGroup>::iterator m_last_save_undo_group;
- std::vector<BufferModificationListener*> m_modification_listeners;
+ mutable std::vector<BufferModificationListener*> m_modification_listeners;
};
}
diff --git a/src/buffer_iterator.inl.h b/src/buffer_iterator.inl.h
index db59a8b4..feae368d 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 00000000..42c9d39c
--- /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 00000000..17e74485
--- /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<const BufferIterator&>(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 0c7991c7..5f10618c 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 9ae7862c..2b62794b 100644
--- a/src/window.hh
+++ b/src/window.hh
@@ -4,6 +4,7 @@
#include <functional>
#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<Selection> SelectionList;