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