summaryrefslogtreecommitdiff
path: root/src/buffer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/buffer.cc')
-rw-r--r--src/buffer.cc88
1 files changed, 87 insertions, 1 deletions
diff --git a/src/buffer.cc b/src/buffer.cc
index ef8e0e1e..5e42a295 100644
--- a/src/buffer.cc
+++ b/src/buffer.cc
@@ -127,11 +127,23 @@ Buffer::Buffer(const std::string& name, const BufferString& initial_content)
void Buffer::erase(const BufferIterator& begin, const BufferIterator& end)
{
+ append_modification(Modification(Modification::Erase, begin, string(begin, end)));
+ do_erase(begin, end);
+}
+
+void Buffer::insert(const BufferIterator& position, const BufferString& string)
+{
+ append_modification(Modification(Modification::Insert, position, string));
+ do_insert(position, string);
+}
+
+void Buffer::do_erase(const BufferIterator& begin, const BufferIterator& end)
+{
m_content.erase(begin.m_position, end - begin);
compute_lines();
}
-void Buffer::insert(const BufferIterator& position, const BufferString& string)
+void Buffer::do_insert(const BufferIterator& position, const BufferString& string)
{
m_content.insert(position.m_position, string);
compute_lines();
@@ -223,4 +235,78 @@ BufferChar Buffer::at(BufferPos position) const
return m_content[position];
}
+void Buffer::begin_undo_group()
+{
+ assert(m_current_undo_group.empty());
+ m_history.erase(m_history_cursor, m_history.end());
+ m_history_cursor = m_history.end();
+}
+
+void Buffer::end_undo_group()
+{
+ m_history.push_back(m_current_undo_group);
+ m_history_cursor = m_history.end();
+
+ m_current_undo_group.clear();
+}
+
+Buffer::Modification Buffer::Modification::inverse() const
+{
+ Modification::Type inverse_type;
+ switch (type)
+ {
+ case Modification::Insert: inverse_type = Erase; break;
+ case Modification::Erase: inverse_type = Insert; break;
+ default: assert(false);
+ }
+ return Modification(inverse_type, position, content);
+}
+
+bool Buffer::undo()
+{
+ if (m_history_cursor == m_history.begin())
+ return false;
+
+ --m_history_cursor;
+
+ for (const Modification& modification : reversed(*m_history_cursor))
+ replay_modification(modification.inverse());
+}
+
+bool Buffer::redo()
+{
+ if (m_history_cursor == m_history.end())
+ return false;
+
+ for (const Modification& modification : *m_history_cursor)
+ replay_modification(modification);
+
+ ++m_history_cursor;
+}
+
+void Buffer::replay_modification(const Modification& modification)
+{
+ switch (modification.type)
+ {
+ case Modification::Insert:
+ do_insert(modification.position, modification.content);
+ break;
+ case Modification::Erase:
+ {
+ BufferIterator begin = modification.position;
+ BufferIterator end = begin + modification.content.size();
+ assert(string(begin, end) == modification.content);
+ do_erase(begin, end);
+ break;
+ }
+ default:
+ assert(false);
+ }
+}
+
+void Buffer::append_modification(Modification&& modification)
+{
+ m_current_undo_group.push_back(modification);
+}
+
}