diff options
Diffstat (limited to 'src/buffer.cc')
| -rw-r--r-- | src/buffer.cc | 88 |
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); +} + } |
