Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tundo.h"
Toshihiro Shimizu 890ddd
#include <deque></deque>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using std::for_each;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void deleteUndo(const TUndo *undo) { delete undo; }
Toshihiro Shimizu 890ddd
void callUndo(const TUndo *undo) { undo->undo(); }
Toshihiro Shimizu 890ddd
void callRedo(const TUndo *undo) { undo->redo(); }
Toshihiro Shimizu 890ddd
// void callRepeat(const TUndo* undo) {undo->repeat(); }
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class TUndoBlock final : public TUndo {
Shinya Kitaoka 120a6e
  std::vector<tundo *=""> m_undos;</tundo>
Shinya Kitaoka 120a6e
  typedef std::vector<tundo *="">::const_iterator Iterator;</tundo>
Shinya Kitaoka 120a6e
  typedef std::vector<tundo *="">::const_reverse_iterator ReverseIterator;</tundo>
Shinya Kitaoka 120a6e
  mutable bool m_deleted, m_undoing;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  TUndoBlock() : m_deleted(false), m_undoing(false) {}
Shinya Kitaoka 120a6e
  ~TUndoBlock() {
Shinya Kitaoka 120a6e
    assert(m_undoing == false);
Shinya Kitaoka 120a6e
    assert(m_deleted == false);
Shinya Kitaoka 120a6e
    m_deleted = true;
Shinya Kitaoka 120a6e
    for_each(m_undos.begin(), m_undos.end(), deleteUndo);
Shinya Kitaoka 120a6e
    m_undos.clear();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  int getSize() const override {
Shinya Kitaoka 120a6e
    int size = sizeof(*this);
Shinya Kitaoka 120a6e
    for (Iterator cit = m_undos.begin(); cit != m_undos.end(); ++cit)
Shinya Kitaoka 120a6e
      size += (*cit)->getSize();
Shinya Kitaoka 120a6e
    size += (m_undos.capacity() - m_undos.size()) * sizeof(TUndo *);
Shinya Kitaoka 120a6e
    return size;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  int getUndoCount() const { return (int)m_undos.size(); }
Shinya Kitaoka 120a6e
  void setLast() {
Shinya Kitaoka 120a6e
    for (UINT i                   = 1; i < m_undos.size(); i++)
Shinya Kitaoka 120a6e
      m_undos[i]->m_isLastInBlock = false;
Shinya Kitaoka 120a6e
    m_undos[0]->m_isLastInBlock   = true;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void undo() const override {
Shinya Kitaoka 120a6e
    assert(!m_deleted);
Shinya Kitaoka 120a6e
    assert(!m_undoing);
Shinya Kitaoka 120a6e
    m_undoing = true;
Shinya Kitaoka 120a6e
    // VERSIONE CORRETTA
Shinya Kitaoka 120a6e
    for_each(m_undos.rbegin(), m_undos.rend(), callUndo);
Shinya Kitaoka 120a6e
    // VERSIONE SBAGLIATA
Shinya Kitaoka 120a6e
    // for_each(m_undos.begin(), m_undos.end(), callUndo);
Shinya Kitaoka 120a6e
    m_undoing = false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 473e70
  void redo() const override {
Shinya Kitaoka 120a6e
    assert(!m_deleted);
Shinya Kitaoka 120a6e
    // VERSIONE CORRETTA
Shinya Kitaoka 120a6e
    for_each(m_undos.begin(), m_undos.end(), callRedo);
Shinya Kitaoka 120a6e
    // VERSIONE SBAGLIATA
Shinya Kitaoka 120a6e
    // for_each(m_undos.rbegin(), m_undos.rend(), callRedo);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // void repeat() const {
Shinya Kitaoka 120a6e
  //  for_each(m_undos.begin(), m_undos.end(), callRepeat);
Shinya Kitaoka 120a6e
  //}
Shinya Kitaoka 473e70
  void onAdd() override {}
Shinya Kitaoka 120a6e
  void add(TUndo *undo) {
Shinya Kitaoka 120a6e
    undo->m_isLastInBlock = true;
Shinya Kitaoka 120a6e
    m_undos.push_back(undo);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void popUndo(int n) {
Shinya Kitaoka 120a6e
    if (n == -1) n = m_undos.size();
Shinya Kitaoka 120a6e
    if (m_undos.empty() || n <= 0) return;
Shinya Kitaoka 120a6e
    while (n > 0 && !m_undos.empty()) {
Shinya Kitaoka 120a6e
      TUndo *undo = m_undos.back();
Shinya Kitaoka 120a6e
      m_undos.pop_back();
Shinya Kitaoka 120a6e
      delete undo;
Shinya Kitaoka 120a6e
      n--;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  QString getHistoryString() override {
Shinya Kitaoka 120a6e
    if (m_undos.empty())
Shinya Kitaoka 120a6e
      return TUndo::getHistoryString();
Shinya Kitaoka 120a6e
    else if ((int)m_undos.size() == 1)
Shinya Kitaoka 120a6e
      return m_undos.back()->getHistoryString();
Shinya Kitaoka 120a6e
    else {
Shinya Kitaoka 120a6e
      return QString("%1  etc..").arg(m_undos.back()->getHistoryString());
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  int getHistoryType() override {
Shinya Kitaoka 120a6e
    if (m_undos.empty())
Shinya Kitaoka 120a6e
      return TUndo::getHistoryType();
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      return m_undos.back()->getHistoryType();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef std::deque<tundo *=""> UndoList;</tundo>
Toshihiro Shimizu 890ddd
typedef UndoList::iterator UndoListIterator;
Toshihiro Shimizu 890ddd
typedef UndoList::const_iterator UndoListConstIterator;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct TUndoManager::TUndoManagerImp {
Shinya Kitaoka 120a6e
  UndoList m_undoList;
Shinya Kitaoka 120a6e
  UndoListIterator m_current;
Shinya Kitaoka 120a6e
  bool m_skipped;
Shinya Kitaoka 120a6e
  int m_undoMemorySize;  // in bytes
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::vector<tundoblock *=""> m_blockStack;</tundoblock>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  TUndoManagerImp() : m_skipped(false), m_undoMemorySize(0) {
Shinya Kitaoka 120a6e
    m_current = m_undoList.end();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  ~TUndoManagerImp() {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void add(TUndo *undo);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  static struct ManagerPtr {
Shinya Kitaoka 120a6e
    TUndoManager *m_ptr;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  public:
Shinya Kitaoka 120a6e
    ManagerPtr() : m_ptr(0) {}
Shinya Kitaoka 120a6e
    ~ManagerPtr() {
Shinya Kitaoka 120a6e
      if (m_ptr) delete m_ptr;
Shinya Kitaoka 120a6e
      m_ptr = 0;
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  } theManager;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  void doAdd(TUndo *undo);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TUndoManager::TUndoManagerImp::ManagerPtr
Shinya Kitaoka 120a6e
    TUndoManager::TUndoManagerImp::theManager;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TUndoManager *TUndoManager::manager() {
Shinya Kitaoka 120a6e
  if (!TUndoManagerImp::theManager.m_ptr)
Shinya Kitaoka 120a6e
    TUndoManagerImp::theManager.m_ptr = new TUndoManager;
Shinya Kitaoka 120a6e
  return TUndoManagerImp::theManager.m_ptr;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TUndoManager::TUndoManager() : m_imp(new TUndoManagerImp) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TUndoManager::~TUndoManager() {
Shinya Kitaoka 120a6e
  // cout << "Distrutto undo manager" << endl;
Shinya Kitaoka 120a6e
  assert(m_imp->m_blockStack.empty());
Shinya Kitaoka 120a6e
  reset();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TUndoManager::TUndoManagerImp::add(TUndo *undo) {
Shinya Kitaoka 120a6e
  assert(undo);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!m_blockStack.empty()) {
Shinya Kitaoka 120a6e
    assert(m_current == m_undoList.end());
Shinya Kitaoka 120a6e
    m_blockStack.back()->add(undo);
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    doAdd(undo);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TUndoManager::TUndoManagerImp::doAdd(TUndo *undo) {
Shinya Kitaoka 120a6e
  if (m_current != m_undoList.end()) {
Shinya Kitaoka 120a6e
    for_each(m_current, m_undoList.end(), deleteUndo);
Shinya Kitaoka 120a6e
    m_undoList.erase(m_current, m_undoList.end());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int i, memorySize = 0, count = m_undoList.size();
Shinya Kitaoka 120a6e
  for (i = 0; i < count; i++) memorySize += m_undoList[i]->getSize();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  while (
Shinya Kitaoka 120a6e
      count > 100 ||
Shinya Kitaoka 120a6e
      (count != 0 && memorySize + undo->getSize() > m_undoMemorySize))  // 20MB
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    --count;
Shinya Kitaoka 120a6e
    TUndo *undo = m_undoList.front();
Shinya Kitaoka 120a6e
    m_undoList.pop_front();
Shinya Kitaoka 120a6e
    memorySize -= undo->getSize();
Shinya Kitaoka 120a6e
    delete undo;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  undo->m_isLastInBlock = true;
Shinya Kitaoka 120a6e
  m_undoList.push_back(undo);
Shinya Kitaoka 120a6e
  m_current = m_undoList.end();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TUndoManager::beginBlock() {
Shinya Kitaoka 120a6e
  if (m_imp->m_current != m_imp->m_undoList.end()) {
Shinya Kitaoka 120a6e
    for_each(m_imp->m_current, m_imp->m_undoList.end(), deleteUndo);
Shinya Kitaoka 120a6e
    m_imp->m_undoList.erase(m_imp->m_current, m_imp->m_undoList.end());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TUndoBlock *undoBlock = new TUndoBlock;
Shinya Kitaoka 120a6e
  m_imp->m_blockStack.push_back(undoBlock);
Shinya Kitaoka 120a6e
  m_imp->m_current = m_imp->m_undoList.end();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TUndoManager::endBlock() {
Shinya Kitaoka 120a6e
  // vogliamo fare anche resize del vector ???
Shinya Kitaoka 120a6e
  assert(m_imp->m_blockStack.empty() == false);
Shinya Kitaoka 120a6e
  TUndoBlock *undoBlock = m_imp->m_blockStack.back();
Shinya Kitaoka 120a6e
  m_imp->m_blockStack.pop_back();
Shinya Kitaoka 120a6e
  if (undoBlock->getUndoCount() > 0) {
Shinya Kitaoka 120a6e
    undoBlock->setLast();
Shinya Kitaoka 120a6e
    m_imp->add(undoBlock);
Shinya Kitaoka 120a6e
    emit historyChanged();
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    delete undoBlock;
Shinya Kitaoka 120a6e
    m_imp->m_current = m_imp->m_undoList.end();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TUndoManager::undo() {
Shinya Kitaoka 120a6e
  assert(m_imp->m_blockStack.empty());
Shinya Kitaoka 120a6e
  UndoListIterator &it = m_imp->m_current;
Shinya Kitaoka 120a6e
  if (it != m_imp->m_undoList.begin()) {
Shinya Kitaoka 120a6e
    m_imp->m_skipped = false;
Shinya Kitaoka 120a6e
    --it;
Shinya Kitaoka 120a6e
    (*it)->undo();
Shinya Kitaoka 120a6e
    emit historyChanged();
Shinya Kitaoka 120a6e
    if (m_imp->m_skipped) {
Shinya Kitaoka 120a6e
      m_imp->m_skipped = false;
Shinya Kitaoka 120a6e
      return undo();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    return true;
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TUndoManager::redo() {
Shinya Kitaoka 120a6e
  assert(m_imp->m_blockStack.empty());
Shinya Kitaoka 120a6e
  UndoListIterator &it = m_imp->m_current;
Shinya Kitaoka 120a6e
  if (it != m_imp->m_undoList.end()) {
Shinya Kitaoka 120a6e
    m_imp->m_skipped = false;
Shinya Kitaoka 120a6e
    (*it)->redo();
Shinya Kitaoka 120a6e
    ++it;
Shinya Kitaoka 120a6e
    emit historyChanged();
Shinya Kitaoka 120a6e
    if (m_imp->m_skipped) {
Shinya Kitaoka 120a6e
      m_imp->m_skipped = false;
Shinya Kitaoka 120a6e
      return redo();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    return true;
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Shinya Kitaoka 120a6e
// repeat e' come redo ma non sposta il puntatore al corrente
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
void TUndoManager::repeat()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
  assert(m_imp->m_blockStack.empty());
Toshihiro Shimizu 890ddd
  UndoListIterator &it = m_imp->m_current;
Toshihiro Shimizu 890ddd
  if (it != m_imp->m_undoList.end())
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    (*it)->repeat();
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TUndoManager::skip() { m_imp->m_skipped = true; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TUndoManager::setUndoMemorySize(int memorySyze) {
Shinya Kitaoka 120a6e
  m_imp->m_undoMemorySize = 1048576 * memorySyze;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TUndoManager::add(TUndo *undo) {
Shinya Kitaoka 120a6e
  assert(undo);
Shinya Kitaoka 120a6e
  if (!undo) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_imp->add(undo);
Shinya Kitaoka 120a6e
  Q_EMIT historyChanged();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  undo->onAdd();
Shinya Kitaoka 120a6e
  Q_EMIT somethingChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TUndoManager::reset() {
Shinya Kitaoka 120a6e
  assert(m_imp->m_blockStack.empty());
Shinya Kitaoka 120a6e
  m_imp->m_blockStack.clear();
Shinya Kitaoka 120a6e
  UndoList &lst = m_imp->m_undoList;
Shinya Kitaoka 120a6e
  for_each(lst.begin(), lst.end(), deleteUndo);
Shinya Kitaoka 120a6e
  lst.clear();
Shinya Kitaoka 120a6e
  m_imp->m_current = m_imp->m_undoList.end();
Shinya Kitaoka 120a6e
  Q_EMIT historyChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TUndoManager::popUndo(int n, bool forward) {
Shinya Kitaoka 120a6e
  if (!forward) {
Shinya Kitaoka 120a6e
    if (m_imp->m_blockStack.empty()) {
Shinya Kitaoka 120a6e
      if (n == -1) {
Shinya Kitaoka 120a6e
        UndoListIterator start = m_imp->m_undoList.begin();
Shinya Kitaoka 120a6e
        n                      = 0;
Shinya Kitaoka 120a6e
        while (start != m_imp->m_current) ++n;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      if (m_imp->m_undoList.empty() || n <= 0) return;
Shinya Kitaoka 120a6e
      if (m_imp->m_current == m_imp->m_undoList.end()) {
Shinya Kitaoka 120a6e
        int i;
Shinya Kitaoka 120a6e
        for (i = 0; i < n && m_imp->m_current != m_imp->m_undoList.begin();
Shinya Kitaoka 120a6e
             i++) {
Shinya Kitaoka 120a6e
          m_imp->m_current--;
Shinya Kitaoka 120a6e
          delete (*m_imp->m_current);
Shinya Kitaoka 120a6e
          m_imp->m_undoList.erase(m_imp->m_current);
Shinya Kitaoka 120a6e
          m_imp->m_current = m_imp->m_undoList.end();
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        TUndo *undo = *m_imp->m_current;
Shinya Kitaoka 120a6e
        UndoListIterator start, end = m_imp->m_current;
Shinya Kitaoka 120a6e
        if (end == m_imp->m_undoList.begin()) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        int i;
Shinya Kitaoka 120a6e
        for (i = 0; i < n && m_imp->m_current != m_imp->m_undoList.begin(); i++)
Shinya Kitaoka 120a6e
          m_imp->m_current--;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        start                 = m_imp->m_current;
Shinya Kitaoka 120a6e
        UndoListIterator _end = end;
Shinya Kitaoka 120a6e
        while (_end != start) {
Shinya Kitaoka 120a6e
          _end--;
Shinya Kitaoka 120a6e
          delete (*_end);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        m_imp->m_undoList.erase(start, end);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        m_imp->m_current = m_imp->m_undoList.begin();
Shinya Kitaoka 120a6e
        while (*m_imp->m_current != undo) m_imp->m_current++;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      m_imp->m_blockStack.back()->popUndo(n);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_imp->m_current == m_imp->m_undoList.end()) return;
Shinya Kitaoka 120a6e
  if (m_imp->m_blockStack.empty()) {
Shinya Kitaoka 120a6e
    UndoListIterator end, start = m_imp->m_current++;
Shinya Kitaoka 120a6e
    if (n == -1)
Shinya Kitaoka 120a6e
      end = m_imp->m_undoList.end();
Shinya Kitaoka 120a6e
    else {
Shinya Kitaoka 120a6e
      UndoListIterator it = start;
Shinya Kitaoka 120a6e
      end                 = it;
Shinya Kitaoka 120a6e
      int i               = 0;
Shinya Kitaoka 120a6e
      while (i != n && end != m_imp->m_undoList.end()) {
Shinya Kitaoka 120a6e
        ++end;
Shinya Kitaoka 120a6e
        i++;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    for_each(start, end, deleteUndo);
Shinya Kitaoka 120a6e
    m_imp->m_undoList.erase(start, end);
Shinya Kitaoka 120a6e
    m_imp->m_current = m_imp->m_undoList.end();
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    m_imp->m_blockStack.back()->popUndo(n);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TUndoManager::getHistoryCount() { return (int)m_imp->m_undoList.size(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TUndoManager::getCurrentHistoryIndex() {
Shinya Kitaoka 120a6e
  int index           = 0;
Shinya Kitaoka 120a6e
  UndoListIterator it = m_imp->m_undoList.begin();
Shinya Kitaoka 120a6e
  while (1) {
Shinya Kitaoka 120a6e
    if (it == m_imp->m_current) return index;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (it == m_imp->m_undoList.end()) break;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    index++;
Shinya Kitaoka 120a6e
    it++;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TUndo *TUndoManager::getUndoItem(int index) {
Shinya Kitaoka 120a6e
  if (index > (int)m_imp->m_undoList.size() || index <= 0) return 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return m_imp->m_undoList.at(index - 1);
Toshihiro Shimizu 890ddd
}