//---------------------------------------------------------------------------

#ifndef UndoH
#define UndoH
//---------------------------------------------------------------------------
#define UNDO_VOLUME		 	0x00
#define UNDO_PRESET			0x01
#define UNDO_FONT_SET		0x02

#define UNDO_KEY_MELODY		0x10
#define UNDO_KEY_BARS		0x11

#define UNDO_CHORD      	0x20

#define UNDO_AUDIO_ERASE	0x30
#define UNDO_AUDIO_COPY     0x31
#define UNDO_AUDIO_MOVE		0x32
#define UNDO_AUDIO_LOAD		0x33
#define UNDO_AUDIO_RECORD	0x34
#define UNDO_AUDIO_FX		0x35

#define UNDO_BAR_INSERT		0x40
#define UNDO_BAR_DELETE		0x41
#define UNDO_BAR_MOVE       0x42
#define UNDO_BAR_CHANGE     0x43

#define UNDO_MIDI_ADD		0x50
#define UNDO_MIDI_DEL		0x51
#define UNDO_MIDI_SUB		0x52
#define UNDO_MIDI_FONT		0x53

#define UNDO_OPUS_STYLE		0x60
#define UNDO_STAGE_VOL		0x61
#define UNDO_PROG_VOL		0x62

#define UNDO_FX_ADD			0x70
#define UNDO_FX_DEL			0x71
#define UNDO_FX_MOVE		0x72
#define UNDO_FX_PARAM 		0x73

#define UNDO_TRACK_STATE	0x80
#define UNDO_TRACK_VOL		0x81
#define UNDO_TRACK_PAN		0x82
#define UNDO_TRACK_GAIN		0x83
#define UNDO_TRACK_CHNO		0x84

#define UNDO_TRKAUD_ADD		0x90
#define UNDO_TRKAUD_DEL		0x91
#define UNDO_TRKAUD_DELALL	0x92
#define UNDO_TRKAUD_SHOW	0x93
#define UNDO_TRKAUD_SHOWALL	0x94
#define UNDO_TRKAUD_HIDE	0x95
#define UNDO_TRKAUD_HIDEALL	0x96

#define UNDO_TRKMID_ADD		0xA0
#define UNDO_TRKMID_DEL		0xA1
#define UNDO_TRKMID_DELALL	0xA2
#define UNDO_TRKMID_SHOW	0xA3
#define UNDO_TRKMID_SHOWALL	0xA4
#define UNDO_TRKMID_HIDE	0xA5
#define UNDO_TRKMID_HIDEALL	0xA6

#include <vector>
using namespace std;

extern char* g_strUndoType[][16];

typedef struct tagUndoLite
{
	int iType;
	int iCode;
	int iBegin, iEnd; //修改范围
	int iExt1, iExt2, iExt3; //整形附加参数
	void *pBefore, //修改前参数
		 *pAfter,  //修改后参数
		 *pExt1, //指针型附加参数1
		 *pExt2; //指针型附加参数2

	tagUndoLite( int iTypeP, int iCodeP, int iBeginP, int iEndP ){
		iType = iTypeP;
		iCode = iCodeP;
		iBegin = iBeginP;
		iEnd = iEndP;
		iExt1 = iExt2 = iExt3 = 0;
		pBefore = pAfter = pExt1 = pExt2 = NULL;
	}
} TUndoLite;

class TUndo
{
private:
	vector<TUndoLite*> m_lstLites; //操作列表
	int m_iPos; //当前位置

	void RemoveLites( int iFrom );
	void DelLiteParams( TUndoLite* pLite );

public:
	void AddUndo( int iType, int iCode, int iBegin, int iEnd, void* pBefore, void* pAfter );
	void SetUndoExtra( int iExt1, int iExt2, int iExt3, void* pExt1, void* pExt2 );
	void SetUndoCode( int iCode );
	void CancelUndo();

	TUndoLite* GetLastLite() { return m_iPos==0 ? NULL : m_lstLites[m_iPos-1]; };

	int GetUndoType()
		{ return m_iPos>0 ? m_lstLites[m_iPos-1]->iType : -1; };
	int GetRedoType()
		{ return m_iPos<m_lstLites.size() ? m_lstLites[m_iPos]->iType : -1; };
	int GetUndoCode()
		{ return m_iPos>0 ? m_lstLites[m_iPos-1]->iCode : -1; };
	int GetRedoCode()
		{ return m_iPos<m_lstLites.size() ? m_lstLites[m_iPos]->iCode : -1; };

	TUndoLite* Undo()
		{ return m_lstLites[--m_iPos]; };
	TUndoLite* Redo()
		{ return m_lstLites[m_iPos++]; };
	void ClearUndoList()
		{ RemoveLites( m_iPos = 0 ); };

	TUndo()
		{ m_iPos = 0; };
	~TUndo()
		{ ClearUndoList(); };
};

extern TUndo g_Undo;

#endif
