
#include "stdafx.h"
#include "UndoManagerC.h"
#include "PajaTypes.h"
#include "UndoC.h"
#include "DataBlockI.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


using namespace PajaTypes;
using namespace Edit;


UndoManagerC::UndoManagerC() :
	m_i32Head( 0 ),
	m_i32Depth( 25 )
{
	// Initialize undo buffer
	m_rUndoStack.resize( m_i32Depth );
	for( uint32 i = 0; i < m_rUndoStack.size(); i++ )
		m_rUndoStack[i] = 0;
}

UndoManagerC::~UndoManagerC()
{
	// Delete old commands
	for( uint32 i = 0; i < m_rUndoStack.size(); i++ )
		delete m_rUndoStack[i];
}

void
UndoManagerC::push( UndoC* pCmd )
{
	// Delete the command we overwrite
	delete m_rUndoStack[m_i32Head];
	m_rUndoStack[m_i32Head] = 0;

	// Store new
	m_rUndoStack[m_i32Head] = pCmd;

	// Increment head pointer
	m_i32Head++;
	if( m_i32Head >= m_i32Depth )
		m_i32Head = 0;

	// Delete the command under head
	delete m_rUndoStack[m_i32Head];
	m_rUndoStack[m_i32Head] = 0;
}

void
UndoManagerC::undo()
{
	if( !can_undo() )
		return;

	// Decrement head pointer
	m_i32Head--;
	if( m_i32Head < 0 )
		m_i32Head = m_i32Depth - 1;

	m_rUndoStack[m_i32Head]->undo();
}

void
UndoManagerC::redo()
{
	if( !can_redo() )
		return;

	m_rUndoStack[m_i32Head]->redo();

	// Increment head pointer
	m_i32Head++;
	if( m_i32Head > m_i32Depth )
		m_i32Head = 0;
}

void
UndoManagerC::purge_redo()
{
	delete m_rUndoStack[m_i32Head];
	m_rUndoStack[m_i32Head] = 0;

	m_i32Head--;
	if( m_i32Head < 0 )
		m_i32Head = m_i32Depth - 1;
}

bool
UndoManagerC::can_undo()
{
	int32	i32Prev = m_i32Head - 1;
	if( i32Prev < 0 )
		i32Prev = m_i32Depth - 1;
	return m_rUndoStack[i32Prev] != 0;
}

bool
UndoManagerC::can_redo()
{
	if( m_rUndoStack[m_i32Head] && m_rUndoStack[m_i32Head]->can_redo() )
		return true;
	return false;
}

void
UndoManagerC::set_undo_depth( PajaTypes::int32 i32Depth )
{
	uint32 i;
	// Delete old commands
	for( i = 0; i < m_rUndoStack.size(); i++ )
		delete m_rUndoStack[i];

	m_i32Depth = i32Depth;
	m_i32Head = 0;

	// Initialize new undo buffer
	m_rUndoStack.resize( m_i32Depth );
	for( i = 0; i < m_rUndoStack.size(); i++ )
		m_rUndoStack[i] = 0;
}

const char*
UndoManagerC::get_undo_name() const
{
	int32	i32Prev = m_i32Head - 1;
	if( i32Prev < 0 )
		i32Prev = m_i32Depth - 1;
	if( m_rUndoStack[i32Prev] )
		return m_rUndoStack[i32Prev]->get_name();
	return 0;
}

const char*
UndoManagerC::get_redo_name() const
{
	if( m_rUndoStack[m_i32Head] )
		return m_rUndoStack[m_i32Head]->get_name();
	return 0;
}

void
UndoManagerC::purge()
{
	// delete whole undo stack
	for( uint32 i = 0; i < m_rUndoStack.size(); i++ ) {
		delete m_rUndoStack[i];
		m_rUndoStack[i] = 0;
	}

	m_i32Head = 0;
}
