//---------------------------------------------------------------------------
#include <vcl.h>
#include <Vcl.Imaging.pngimage.hpp>
#pragma hdrstop

#include "GlobalUnit.h"
#include "UseStylePanel.h"
#include "MidiTrack.h"
#include "Undo.h"
#include "SwitchProgFormUnit.h"
#include "SwitchTextureForm.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)

extern int 	w_xOffDrag, //图片左上角与鼠标距离
			w_yOffDrag;

__fastcall TUseStylePanel::TUseStylePanel(TComponent* AOwner)
	: TStylePanel(AOwner)
{
	m_pContentPanel = NULL;
	m_pPlayTimer = NULL;
	m_bAddWeakupBar = true;

	m_strTitle = "使用风格";
}
//---------------------------------------------------------------------------

void TUseStylePanel::ClearAllItems()
{
	TStylePanel::ClearAllItems();
}
//---------------------------------------------------------------------------

void TUseStylePanel::CountTotalLine()
{
	m_nTotalLine = 0;

	if( m_pTopItem ){
		//计算总行数
		TCommonItem* pItem = m_pTopItem;
		while( pItem ){ //所有显示的子孙项
			m_nTotalLine++;
			pItem = GetNextItem( pItem );
		}
	}
}
//---------------------------------------------------------------------------

bool __fastcall TUseStylePanel::Charge4Fonts()
{
	for( int i=g_aMidiTracks.size()-1; i>=0; i-- ){
		if( g_aMidiTracks[i]->bank!=0xFF ){
			return true;
		}
	}

	return false;
}
//---------------------------------------------------------------------------

void __fastcall TUseStylePanel::DoChangeFontProg(TObject* Sender)
{
	Stop( STOP_ALL );

	if( Sender )
		SetSelect( m_pFocItem, m_iFocLine );

	TTrackItem *pItem = (TTrackItem *)m_pSelItem ;
	TTrack* pTrack = pItem->pTrack;

	TSwitchProgForm *sPf = new TSwitchProgForm( NULL, pTrack->iBank, pTrack->iProg, pTrack->iChanNo );

	BYTE data[100000];
	int len = 100000;
	GetDemoData( pItem, len, data, sPf->m_iStartBar, sPf->m_lenBar );
	f_MM_LoadDemo( data, len );

	if( sPf->ShowModal() == mrOk ){
		bool bChanged = false;

		int iStage = FindItemStage( pItem );
		BYTE iBank = pTrack->iBank,
			iBankSet = sPf->m_iFont==g_idFont ? 0xFF : sPf->m_iFont;
		char iProg = sPf->m_iProg,
			iChno = sPf->m_iChno;

		if( iBank!=iBankSet || iProg!=pTrack->iProg || iChno!=pTrack->iChanNo ){
			int range = g_Opus.StageRange(iStage),
				iMT = g_Midi.GetMidiTrackIndex( pTrack->iFile, pTrack->iChanSpec );

			ChangeFont( LOWORD(range), HIWORD(range), iMT, iBankSet, iProg, iChno, pItem->iType );
		}
	}

	delete sPf;
	f_MM_LoadDemo( NULL, 0 );
}
//---------------------------------------------------------------------------

TTrackItem* TUseStylePanel::FindTrackItem( int iStage, TTrack* pTrk )
{
	TStyleItem* pStyleItem = (TStyleItem*)m_aItems->First();
	TSegmentItem* pSeg = (TSegmentItem*)pStyleItem->aItems->Items[iStage];

	for( int i=0; i<pSeg->aItems->Count; i++ ){
		TTrackItem* pTrkItem = (TTrackItem*)pSeg->aItems->Items[i];

		if( pTrkItem->pTrack==pTrk )
			return pTrkItem;
	}

	return NULL;
}
//---------------------------------------------------------------------------

void __fastcall TUseStylePanel::ChangeFont( int iSBar, int iEBar, int iMT, int iBank, int iProg, int iChno, int op )
{
	int iBStage = iSBar<0 ? 0 : GetInsertStage( iSBar ),
		iEStage = iEBar<0 ? g_Opus.StageCount() : GetInsertStage( iEBar+1 );

	int iDelMT = iMT, iAddMT = -1;
	TMidiTrack *pDelMT = g_aMidiTracks[iMT], *pAddMT = NULL;
	vector<DWORD>* aStagesBefore = new vector<DWORD>,
				* aStagesAfter = new vector<DWORD>;
	vector<TTrack*> aTracksBefore, aTracksAfter;

	bool bInit = false;
	vector<int> aAddStages;
	TStyleItem* pStyleItem = (TStyleItem*)m_aItems->First();
	vector<int>::iterator itDelStage = pDelMT->aStages.begin();
	while( itDelStage!=pDelMT->aStages.end() ){
		int iStage = *itDelStage;//pDelMT->aStages[i];

		if( iStage<iBStage )
			itDelStage++;
		else if( iStage>=iEStage )
			break;
		else{
			TOpusStage* pStage = g_lstOpusStages[iStage];
			TSegmentItem* pSeg = (TSegmentItem*)pStyleItem->aItems->Items[iStage];

			for( int j=0; j<pStage->aTracks.size(); j++ ){
				TTrack* pTrack = pStage->aTracks[j];
				if( pTrack->iFile==pDelMT->file && pTrack->iChanSpec==pDelMT->chno ){
					int iFBar = g_Opus.StageFirstBar(iStage),
						iLBar = g_Opus.StageLastBar(iStage);

					aTracksBefore.push_back( new TTrack(pTrack) );
				//	aStagesBefore->push_back( MAKELONG(iStage, j) );
					DWORD dwFLT = iFBar + (iLBar<<12) + (j<<24);
					aStagesBefore->push_back( dwFLT );

					pTrack->iBank = iBank;
					pTrack->iProg = iProg;
					pTrack->iChanSpec = iChno;

					aTracksAfter.push_back( pTrack );
//					aStagesAfter->push_back( MAKELONG(iStage, j) );
					aStagesAfter->push_back( dwFLT );
					aAddStages.push_back( iStage );

					break;
				}
			}

			itDelStage = pDelMT->aStages.erase( itDelStage );
		}
	}

	TTrack *pBefore = NULL, *pAfter = NULL;
	int count = aAddStages.size();

	if( count==0 ){
		delete aStagesBefore;
		delete aStagesAfter;

		return;
	}

	int stateDel = pDelMT->state,
		volumeDel = pDelMT->volume,
		panDel = pDelMT->pan,
		iErase = g_Midi.ClearEmptyTrack();

	int nMTOri = g_aMidiTracks.size();
	pAddMT = g_Midi.GetValidMidiTrack( aAddStages, 0xFF, iChno, iBank, iProg );
	if( nMTOri<g_aMidiTracks.size() ){
		bInit = true;

		if( iDelMT>=0 ){
			pAddMT->state = stateDel;
			pAddMT->volume = volumeDel;
			pAddMT->pan = panDel;
		}
	}

	if( iErase>=0 ){
		if( bInit && iErase==iMT ){
			g_aMidiTracks.pop_back();
			g_aMidiTracks.insert( g_aMidiTracks.begin()+iMT, pAddMT );

			iAddMT = iMT;
			bInit = false;
		}
		else
			bInit = true;
	}

	pBefore = new TTrack[count];
	pAfter = new TTrack[count];

	for( int i=0; i<count; i++ ){
		memcpy( &pBefore[i], aTracksBefore[i], sizeof(TTrack) );
		delete aTracksBefore[i];

		aTracksAfter[i]->iFile = pAddMT->file;
		aTracksAfter[i]->iChanSpec = pAddMT->chno;
		memcpy( &pAfter[i], aTracksAfter[i], sizeof(TTrack) );
	}

	if( iAddMT<0 )
		iAddMT = g_Midi.GetMidiTrackIndex( pAddMT->file, pAddMT->chno );

	int iCode = op,
		iExt1 = iDelMT>=0 ? iDelMT + (stateDel<<8) + (volumeDel<<16) + (panDel<<24) : -1,
		iExt2 = iAddMT>=0 ? iAddMT + (pAddMT->state<<8) + (pAddMT->volume<<16) + (pAddMT->pan<<24) : -1;

	g_Undo.AddUndo( UNDO_MIDI_FONT, op, iSBar, iEBar, (void*)pBefore, (void*)pAfter );
	g_Undo.SetUndoExtra( iExt1, iExt2, -1, aStagesBefore, aStagesAfter );

	int iShowTrack = -1;
	if( !m_pContentPanel->IsVertical() ){
		if( bInit ){
			m_pContentPanel->InitialVars();
		}
		else{
			if( iDelMT>=0 ){
				int iST = m_pContentPanel->GetShowTrackId( ST_MIDI, iDelMT );
				if( iST>0 )
					m_pContentPanel->InvalidateBars( iSBar, iEBar, BAR_TRACK | iST );
			}
		}
	}

	IntegrateStages( iBStage );
	Paint();

	if( !m_pContentPanel->IsVertical() ){
		if( iAddMT>=0 ){
			if( iAddMT==iDelMT )
				m_pContentPanel->SelectTrack( -1, -1, -1, false );

			if( iShowTrack<0 )
				iShowTrack = m_pContentPanel->GetShowTrackId( ST_MIDI, iAddMT ) - 1;

			if( iShowTrack>=0 ){
				m_pContentPanel->SelectTrack( iShowTrack, -1, -1, false );
				m_pContentPanel->SetSelectRange( iSBar, 0, iEBar, POINTS_PER_BAR-1 );
			}
		}

		GenerateCompose();
	}

	if( g_iPreStage==0 ){
		g_Theme.Set( g_pUseStyle->pStyle->idLoc, g_pUseStyle->pStyle->idStyle,
																	g_lstOpusStages );
	}
}
//---------------------------------------------------------------------------

void __fastcall TUseStylePanel::ChangeTexture( int iSBar, int iEBar, char sType,
														int iMT, TTrack* pSubTrack, int op )
{
	int iBStage = iSBar<0 ? 0 : GetInsertStage( iSBar ),
		iEStage = iEBar<0 ? g_Opus.StageCount() : GetInsertStage( iEBar+1 );

	vector<DWORD>* aStagesBefore = new vector<DWORD>,
				* aStagesAfter = new vector<DWORD>;
	vector<TTrack*> aTracksBefore, aTracksAfter;
	int iUndoType = iMT<0 ? UNDO_MIDI_ADD : ( pSubTrack ? UNDO_MIDI_SUB : UNDO_MIDI_DEL );
	if( iSBar<0 && iEBar<0 ) {
		if( iMT<0 )
			iUndoType = UNDO_TRKMID_ADD;
		else if( !pSubTrack )
			iUndoType = UNDO_TRKMID_DEL;
	}

	int iDelMT = iMT,
		iAddMT = -1;

	if( pSubTrack && pSubTrack->iFile!=0xFF )
		iAddMT = g_Midi.GetMidiTrackIndex( pSubTrack->iFile, pSubTrack->iChanSpec );

	TMidiTrack* pDelMT = iDelMT<0 ? NULL : g_aMidiTracks[iDelMT],
		* pAddMT = iAddMT<0 ? NULL : g_aMidiTracks[iAddMT];
	BYTE iDelFile = pDelMT ? pDelMT->file : 0xFF,
		iDelChan = pDelMT ? pDelMT->chno : 0xFF,
		iAddFile = pAddMT ? pAddMT->file : 0xFF,
		iAddChan = pAddMT ? pAddMT->chno : 0xFF;
	bool bDrum = false;

	if( pSubTrack ){
		if( pSubTrack->iChanNo==9 )
			bDrum = true;
	}

	vector<int> aAddStages;
	TStyleItem* pStyleItem = (TStyleItem*)m_aItems->First();
	for( int i=iBStage; i<iEStage; i++ ){
		TOpusStage* pStage = g_lstOpusStages[i];
		TSegmentItem* pSeg = (TSegmentItem*)pStyleItem->aItems->Items[i];
		int iFBar = g_Opus.StageFirstBar(i),
			iLBar = g_Opus.StageLastBar(i);

		TTrack *pDelTrack = NULL,
			*pAddTrack = NULL;
		int iDelTrack = -1,
			iAddTrack = -1;

		if( iDelChan!=0xFF && ( sType<0 || pStage->iSegType==sType ) ){
			for( int j=0; j<pStage->aTracks.size(); j++ ){
				TTrack* pTmpTrack = pStage->aTracks[j];
				if( iDelFile!=0xFF && pTmpTrack->iFile==iDelFile && pTmpTrack->iChanSpec==iDelChan ){
					pDelTrack = pTmpTrack;
					iDelTrack = j;
					break;
				}
			}
		}

		if( pDelTrack ){
			if( !pDelMT || pDelMT->file!=pDelTrack->iFile )
				pDelMT = g_Midi.FindMidiTrack( pDelTrack->iFile, pDelTrack->iChanSpec );

			pDelMT->DelStage( i );

// 			aStagesBefore->push_back( MAKELONG( i, iDelTrack ) );
			DWORD dwFLT = iFBar + (iLBar<<12) + (iDelTrack<<24);
			aStagesBefore->push_back( dwFLT );

			if( pSubTrack ){
				aTracksBefore.push_back( new TTrack(pDelTrack) );

				if( pDelTrack->iStyleLoc!=pSubTrack->iStyleLoc
								|| pDelTrack->iStyleId!=pSubTrack->iStyleId ){
					TTrackItem* pTrkItem = (TTrackItem*)pSeg->aItems->Items[iDelTrack];
					pTrkItem->pStyle = GetStyleInfo( pSubTrack->iStyleLoc, pSubTrack->iStyleId );
				}

				memcpy( pDelTrack, pSubTrack, sizeof(TTrack) );
				aTracksAfter.push_back( pDelTrack );
//				aStagesAfter->push_back( MAKELONG(i, iDelTrack) );
				aStagesAfter->push_back( dwFLT );

				if( pAddMT )
					pAddMT->AddStage( i );
				else
					aAddStages.push_back( i );

				if( iUndoType!=UNDO_MIDI_SUB )
					iUndoType==UNDO_MIDI_SUB;
			}
			else{
				TTrackItem* pDelItem = (TTrackItem*)pSeg->aItems->Items[iDelTrack];//FindTrackItem( i, pDelTrack );
				TStylePanel::DeleteItem( pDelItem, -1 );

				aTracksBefore.push_back( pDelTrack );
				pStage->aTracks.erase( pStage->aTracks.begin()+iDelTrack );
			}
		}
		else if( pSubTrack && pStage->iSegType==sType && ( !bDrum || iMT<0 || iDelChan==9 ) ){
			TTrack* pTrk = new TTrack( pSubTrack );

			if( pAddMT )
				pAddMT->AddStage( i );
			else
				aAddStages.push_back( i );

			int iTrk = 0;
			if( bDrum ){
				pStage->aTracks.insert( pStage->aTracks.begin(), pTrk );
			}
			else{
				iTrk = pStage->aTracks.size();
				pStage->aTracks.push_back( pTrk );
			}

			AddTrack( pSeg, pTrk );

			aTracksAfter.push_back( pTrk );
//			aStagesAfter->push_back( MAKELONG(i, iTrk) );
			DWORD dwFLT = iFBar + (iLBar<<12) + (iTrk<<24);
			aStagesAfter->push_back( dwFLT );
		}
	}

	TTrack *pBefore = NULL, *pAfter = NULL;

	int iExt1 = iDelMT>=0 ? iDelMT + (pDelMT->state<<8) + (pDelMT->volume<<16) + (pDelMT->pan<<24) : -1,
		iErase = g_Midi.ClearEmptyTrack();

	if( !aStagesBefore->empty() ){
		int count = aStagesBefore->size();
		pBefore = new TTrack[count];

		for( int i=0; i<count; i++ ){
			memcpy( &pBefore[i], aTracksBefore[i], sizeof(TTrack) );
			delete aTracksBefore[i];
		}
	}
	else if( iUndoType==UNDO_MIDI_SUB ){
		iUndoType = UNDO_MIDI_ADD;
	}

 	bool bInit = false;
	if( !aStagesAfter->empty() ){
		if( !pAddMT && !aAddStages.empty() ){
			int nMTOri = g_aMidiTracks.size();
			pAddMT = g_Midi.GetValidMidiTrack( aAddStages, pSubTrack->iFile, pSubTrack->iChanNo,
															pSubTrack->iBank, pSubTrack->iProg );

			if( nMTOri<g_aMidiTracks.size() )
				bInit = true;
		}

		int count = aStagesAfter->size();
		pAfter = new TTrack[count];

		for( int i=0; i<count; i++ ){
			if( pAddMT ) {
				aTracksAfter[i]->iFile = pAddMT->file;
				aTracksAfter[i]->iChanSpec = pAddMT->chno;
			}
			memcpy( &pAfter[i], aTracksAfter[i], sizeof(TTrack) );
		}
	}

	if( iErase>=0 ){
		if( bInit && iErase==iMT && pAddMT ){
			g_aMidiTracks.pop_back();
			g_aMidiTracks.insert( g_aMidiTracks.begin()+iMT, pAddMT );

			iAddMT = iMT;
			bInit = false;
		}
		else
			bInit = true;
	}

	if( pAddMT && iAddMT<0 )
		iAddMT = g_Midi.GetMidiTrackIndex( pAddMT->file, pAddMT->chno );

	int iCode = op,
		iExt2 = iAddMT>=0 ? iAddMT + (pAddMT->state<<8) + (pAddMT->volume<<16) + (pAddMT->pan<<24) : -1;

	g_Undo.AddUndo( iUndoType, iCode, iSBar, iEBar,	(void*)pBefore, (void*)pAfter );
	g_Undo.SetUndoExtra( iExt1, iExt2, -1, aStagesBefore, aStagesAfter );

	int iShowTrack = -1;
	if( !m_pContentPanel->IsVertical() ){
		if( bInit ){
			m_pContentPanel->InitialVars();
		}
		else{
			if( iDelMT>=0 ){
				int iST = m_pContentPanel->GetShowTrackId( ST_MIDI, iDelMT );
				if( iST>0 )
					m_pContentPanel->InvalidateBars( iSBar, iEBar, BAR_TRACK | iST );
			}
		}
	}

	IntegrateStages( iBStage );
	Paint();

	if( g_iSegColorMode==1 )
		m_pContentPanel->InvalidateBars( iSBar, iEBar, BAR_DATA );

	if( !m_pContentPanel->IsVertical() ){
		if( iAddMT>=0 ){
			if( VIEW_TRACK!=g_iViewMode ){
				Application->MainForm->Perform( UM_SETVIEWMODE, VIEW_TRACK, 0 );
			}
			else if( iAddMT==iDelMT )
				m_pContentPanel->SelectTrack( -1, -1, -1, false );

			if( iShowTrack<0 )
				iShowTrack = m_pContentPanel->GetShowTrackId( ST_MIDI, iAddMT ) - 1;

			if( iShowTrack>=0 ){
				m_pContentPanel->SelectTrack( iShowTrack, -1, -1, false );
				m_pContentPanel->SetSelectRange( iSBar, 0, iEBar, POINTS_PER_BAR-1 );
			}
		}

		GenerateCompose();
	}

	if( g_iPreStage==0 ){
		g_Theme.Set( g_pUseStyle->pStyle->idLoc, g_pUseStyle->pStyle->idStyle,
																	g_lstOpusStages );
	}
}
//---------------------------------------------------------------------------

void __fastcall TUseStylePanel::DoChangeTexture(TObject* Sender)
{
	Stop( STOP_ALL );

	if( Sender )
		SetSelect( m_pFocItem, m_iFocLine );

	TTrackItem *pItem = (TTrackItem *)m_pSelItem ;
	TTrack* pTrack = pItem->pTrack;
	int stype = pItem->GetSegType();
	char progOri = pTrack->iProgOrig;

	int iStage = FindItemStage( pItem );
	TOpusStage* pStage = g_lstOpusStages[iStage];
	int iSBar = g_Opus.StageFirstBar( iStage ),
		lenBar = pStage->aBars.size();
	TStageList m_lstStage;
	TStage *stage = new TStage;

	TStageList lstStages;
	stage->iSegType = stype;
	stage->iSegKey = pStage->iSegKey;
	stage->nBarNum = lenBar;
	stage->nTrkNum = 0;
	lstStages.push_back( stage );

	if( stype<=SEGTYPE_FILL ){
		stage->aChords = new TBarChords[lenBar];
		for( int j=0; j<lenBar; j++ ){
			memcpy( &stage->aChords[j],
						&pStage->aBars[j]->aChords,
						sizeof(TBarChords) );
		}
	}

	TSwitchTextureForm *pProgPar = new TSwitchTextureForm(NULL, (1<<stype), progOri,
											   pTrack->iBank, pTrack->iProg, pItem->pStyle,
											   pTrack->iChanNo, pTrack->iSegNo, &lstStages, 0);

	if(pProgPar->ShowModal() == mrOk){
		TTrack subTrk;
		subTrk.iStyleLoc = pProgPar->m_pSetStyle->idLoc;
		subTrk.iStyleId = pProgPar->m_pSetStyle->idStyle;
		subTrk.iSegNo 	  = pProgPar->m_cSetSegNo;
		subTrk.iChanNo	  = pProgPar->m_cSetchan;
		subTrk.iProgOrig = pProgPar->m_cSetProgOri;
		subTrk.nVol  	  = pProgPar->m_cSetVol;
		subTrk.nVolOrig  = pProgPar->m_cSetVolOri;

		if( pProgPar->m_bSetCur ){
			subTrk.iProg = pProgPar->m_cSetProg;
			subTrk.iChanSpec = subTrk.iChanNo;
			subTrk.iBank = 0xFF;
			subTrk.iFile = 0xFF;
		}
		else{
			subTrk.iProg = pTrack->iProg;
			subTrk.iChanSpec = pTrack->iChanSpec;
			subTrk.iBank = pTrack->iBank;
			subTrk.iFile = pTrack->iFile;
		}

		int iMT = g_Midi.GetMidiTrackIndex( pTrack->iFile, pTrack->iChanSpec );
		ChangeTexture( iSBar, iSBar+lenBar-1, stype, iMT, &subTrk, SEGTYPE_TRACK );
	}

	delete pProgPar;
	delete stage;
}
//---------------------------------------------------------------------------

void __fastcall TUseStylePanel::DeleteAllTexture( bool bAddUndo )
{
	if( g_Midi.IsEmpty() || g_Opus.BarCount()==0 )
		return;

	TStyleItem* pStyleItem = (TStyleItem*)m_aItems->First();
	TOpusStageList *lstStageBefore = NULL,
				*lstStageAfter = NULL;
	UINT idLocBefore(-1), idStyleBefore(-1),
		idLocAfter(-1),	idStyleAfter(-1);
	int nTrks = g_aMidiTracks.size();
	TMidiTrackList *lstTracksBefore = NULL;

	if( bAddUndo ){
		lstStageBefore = new TOpusStageList;
		g_Opus.CopyStages( 0, g_Opus.BarCount()-1, lstStageBefore );

		if( pStyleItem->pStyle ){
			idLocBefore = pStyleItem->pStyle->idLoc;
			idStyleBefore = pStyleItem->pStyle->idStyle;
		}

		lstTracksBefore = new TMidiTrackList;
		for( int i=0; i<nTrks; i++ )
			lstTracksBefore->push_back( new TMidiTrack(g_aMidiTracks[i]) );
	}

	for( int i=0; i<g_lstOpusStages.size(); i++ ){
		TOpusStage* pStage = g_lstOpusStages[i];
		TSegmentItem* pSeg = (TSegmentItem*)pStyleItem->aItems->Items[i];

		while( !pStage->aTracks.empty() ){
			TTrackItem* pDelItem = (TTrackItem*)pSeg->aItems->Last();
			TStylePanel::DeleteItem( pDelItem, -1 );

			TTrack* pTrack = pStage->aTracks.back();
			pStage->aTracks.pop_back();
		}
	}

	g_Midi.ClearMidiTracks();

	IntegrateStages( 0 );
	Paint();

	if( bAddUndo ){
		lstStageAfter = new TOpusStageList;
		g_Opus.CopyStages( 0, g_Opus.BarCount()-1, lstStageAfter );

		if( pStyleItem->pStyle ){
			idLocAfter = pStyleItem->pStyle->idLoc;
			idStyleAfter = pStyleItem->pStyle->idStyle;
		}

		g_Undo.AddUndo( UNDO_TRKMID_DELALL, ST_MIDI, idStyleBefore, idStyleAfter,
										(void*)lstStageBefore, (void*)lstStageAfter );
		g_Undo.SetUndoExtra( idLocBefore, idLocAfter, 0, (void*)lstTracksBefore, NULL );
	}

	if( !m_pContentPanel->IsVertical() ){
		m_pContentPanel->InitialVars();
		GenerateCompose();
	}
	else if( g_iSegColorMode==1 ){
		m_pContentPanel->InvalidateBars( 0, g_Opus.BarCount()-1, BAR_DATA );
	}

	if( g_iPreStage==0 ){
		g_Theme.Set( g_pUseStyle->pStyle->idLoc, g_pUseStyle->pStyle->idStyle,
																	g_lstOpusStages );
	}
}
//---------------------------------------------------------------------------

TSegmentItem* TUseStylePanel::AddStage( TOpusStage* pStage )
{
	TStyleItem* pStyItem = (TStyleItem*)m_aItems->First();

	int ind = 0;
	DWORD opts = OPT_DEL|OPT_VOL;
	if( pStage->iSegType<=SEGTYPE_FILL ){
		ind = pStyItem->nSegNum[0] + pStyItem->nSegNum[1];
		opts |= OPT_BRUSH;
	}
	else
		ind = pStyItem->nSegNum[pStage->iSegType];

	TSegmentItem* pSegItem = pStyItem->AddSegment( pStage->iSegType,
													pStage->iSegNo,
													opts,
													pStage->aBars.size(),
													ind,
													pStage->nVol,
													false );
	opts = OPT_DEL|OPT_FONTPROG|OPT_VOL;
	if( pStage->iSegType<SEGTYPE_INTRO )
		opts |= OPT_TEXTURE;

	for( int j=0; j<pStage->aTracks.size(); j++ ){
		TTrack* pTrack = pStage->aTracks[j];
		pSegItem->AddTrack( NULL, pTrack, opts, false );
	}

	return pSegItem;
}
//---------------------------------------------------------------------------

int TUseStylePanel::GetDemoData( TCommonItem* pItem, int &nLen, BYTE* pData, int& iStartBar, int& lenBar )
{
	int ret = 0;

	if( pItem->iType==SEGTYPE_TRACK ){ //播放单一轨道{
		int iStage = FindItemStage( pItem );
		TOpusStage* pStage = g_lstOpusStages[iStage];
		TSegmentItem* pSeg = (TSegmentItem*)pItem->up;

		int stype = pItem->GetSegType();
		TTrack* pTrk = ((TTrackItem*)pItem)->pTrack;
		TStage stage;
		stage.aTracks = new TComposeTrack[1];
		int nStageNum = 1;

		stage.iSegType = stype;
		stage.iSegKey = pStage->iSegKey;
		stage.nBarNum = lenBar;
		stage.nTrkNum = 1;

		stage.aTracks->iStyleId = pTrk->iStyleId;// >pStyle->idStyle;
		stage.aTracks->iStyleLoc = pTrk->iStyleLoc;// >pStyle->idLoc;

		if( stype>=SEGTYPE_INTRO ){
			char cType = (pTrk->iSegNo / 4 + 1) << 4;
			char sno = pTrk->iSegNo % 4;
			stage.aTracks->iSegNo = sno + cType;
		}
		else
			stage.aTracks->iSegNo = pTrk->iSegNo;

		stage.aTracks->iChanNo = pTrk->iChanNo;
		stage.aTracks->iChanSpec = pTrk->iChanSpec;
		stage.aTracks->iProg = pTrk->iProg;
		stage.aTracks->nVol = pTrk->nVol<0 ? 0 : pTrk->nVol * pSeg->volume / 100.0;

		if( stype<=SEGTYPE_FILL ){
			stage.aChords = new TBarChords[lenBar];
			for( int j=0; j<lenBar; j++ ){
				memcpy( &stage.aChords[j],
							&pStage->aBars[j]->aChords,
							sizeof(TBarChords) );
			}
		}

		ret = f_CM_Compose( &nLen, pData, g_iMelodyTimeSignature, g_nMelodyTempo,
											nStageNum, &stage, false, NULL, NULL );
	}

	return ret;
}
//---------------------------------------------------------------------------

void TUseStylePanel::PlayDemo( TCommonItem *pItem, int tempo )
{
	if( !pItem || g_lstOpusStages.size()==0 )
		return;

	Stop( STOP_ALL );

	if( pItem->iType!=SEGTYPE_TRACK ){
		GenerateCompose();
		SetTrackParams( false );
	}

	int iStartBar(0), lenBar(0);
	if( pItem->iType==SEGTYPE_STYLE ){ //播放完整全曲
		f_MM_Play( Handle, 0, TYPE_COMPOSE ); //仅播放编曲
		m_bPlaying = true;
	}
	else{
		int iStage = FindItemStage( pItem );
		TOpusStage* pStage = g_lstOpusStages[iStage];

		for( int i=0; i<iStage; i++ ){
			iStartBar += g_lstOpusStages[i]->aBars.size();
		}

		lenBar = pStage->aBars.size();

		if( pItem->iType==SEGTYPE_TRACK ){ //播放单一轨道
			BYTE data[100000];
			int len = 100000;
			int ret = GetDemoData( pItem, len, data, iStartBar, lenBar );

			if( ret==0 ){
				BYTE iBank = ((TTrackItem*)pItem)->pTrack->iBank;
				char* strFile = iBank==0xFF ? NULL : iBank<0x80 ? g_lstFonts[iBank]->strFileName
														: g_lstVSTi[iBank-0x80]->strFileName;

				f_MM_LoadDemo( data, len );
				f_MM_PlayDemo( Handle, 0, -1, -1, iBank, strFile );

				m_bPlaying = true;
			}
			else{
				DebugPrint( "Compose error: %d", ret );
			}
		}
		else{
			f_MM_Play( Handle, iStartBar, TYPE_COMPOSE ); //仅播放编曲
			m_bPlaying = true;
		}

		if( m_bPlaying ){
			if( !m_pPlayTimer ){
				m_pPlayTimer = new TTimer(this);
			}
			m_pPlayTimer->Interval = lenBar * g_dblTimePerBar - 100;
			m_pPlayTimer->OnTimer = PlayEndProc;
			m_pPlayTimer->Enabled = true;
		}
	}

	if( m_bPlaying )
		m_pPlayItem = pItem;
}
//---------------------------------------------------------------------------

void __fastcall TUseStylePanel::PlayEndProc(TObject* Sender)
{
	Stop(STOP_SELF);
}
//---------------------------------------------------------------------------

void __fastcall TUseStylePanel::OnPlayEnd(TMessage &msg)
{
	Stop(STOP_SELF);
}
//---------------------------------------------------------------------------

void TUseStylePanel::SetSelect( TCommonItem *pItem, int iLine )
{
	TCommonItem * pOldSeg = NULL;

	if( m_pSelItem && m_pSelItem->iType>=SEGTYPE_VAR
						&& m_pSelItem->iType<=SEGTYPE_ENDING ){
		pOldSeg = m_pSelItem;
	}

	if( !pItem || pItem->iType==SEGTYPE_STYLE ){
		m_pContentPanel->SelectStage( -1 );
	}

	TStylePanel::SetSelect( pItem, iLine );

	if( pOldSeg!=m_pSelItem && m_pSelItem && m_pSelItem->iType>=SEGTYPE_VAR
										&& m_pSelItem->iType<=SEGTYPE_ENDING ){
		TStyleItem* pStyle = (TStyleItem*)m_aItems->Items[0];

		for( int i=0; i<pStyle->aItems->Count; i++ ){
			if( m_pSelItem==pStyle->aItems->Items[i] ){
				m_pContentPanel->SelectStage( i );
				break;
			}
		}
	}
}
//---------------------------------------------------------------------------
void TUseStylePanel::Stop( DWORD dwSpec )
{
	if( m_pPlayTimer ){
		delete m_pPlayTimer;
		m_pPlayTimer = NULL;
	}

	if( m_bPlaying ){
		dwSpec = STOP_SELF;

		if( m_pPlayItem && m_pPlayItem->iType!=SEGTYPE_TRACK )
			SetTrackParams();
	}

	TStylePanel::Stop( dwSpec );
}
//---------------------------------------------------------------------------

bool TUseStylePanel::HandleHoverEvent(TPoint ptMouse)
{
	int X = ptMouse.X,
		Y = ptMouse.Y;

	TCommonItem* pHoverItem = NULL;
	int iHoverLine = -1;

	TCommonItem* pItem = HitTest( X, Y-m_nTitleHeight, NULL );
	if( pItem && m_pDropItem ){
		if( m_pDropItem->iType==SEGTYPE_TRACK ){
			iHoverLine = (Y - m_nTitleHeight)/m_nItemHeight;

			pHoverItem = GetTrackHoverItem( pItem, iHoverLine );
		}
		else if( m_pDropItem->iType==SEGTYPE_STYLE ){
			//查看风格是否缺少片段
			if( ((TStyleItem*)m_pDropItem)->nSegNum[0]>0 ){
				pHoverItem = (TCommonItem*)m_aItems->Items[0];
				iHoverLine = -m_iTopLine;
			}
		}
		else{
			int iDropType = m_pDropItem->GetSegType(),
				iHoverType = pItem->GetSegType();

			 if( iDropType==iHoverType  //类型相同可替换
						|| ( iHoverType==SEGTYPE_FILL
							|| iHoverType==SEGTYPE_VAR)
						   && (iDropType==SEGTYPE_FILL
							|| iDropType==SEGTYPE_VAR )){  //伴奏与加花可替换
				iHoverLine = (Y - m_nTitleHeight)/m_nItemHeight;
				pHoverItem = pItem;
			 }
		}
	}

	SetUnfoldTimer( pItem, pHoverItem );
	SetHover( pHoverItem, iHoverLine );

	return pHoverItem!=NULL;
}
//---------------------------------------------------------------------------

void TUseStylePanel::HandleDropEvent( int iState )
{
	if( m_pDropItem && m_pHoverItem ){
		Stop();

		if( m_pDropItem->iType==SEGTYPE_STYLE ){ //应用风格
			PostMessage( Parent->Handle, UM_APPLYSTYLE, 1, LPARAM(m_pDropItem) );
		}
		else{ //应用片段
			int iStage = FindItemStage( m_pHoverItem );

			if( m_pDropItem->iType==SEGTYPE_TRACK ){ //添加track
				TSegmentItem* pSeg = (TSegmentItem*)m_pHoverItem;
				if( m_pHoverItem->iType==SEGTYPE_TRACK )
					pSeg = (TSegmentItem*)m_pHoverItem->up;

				TTrack *pSrcTrack = new TTrack( ((TTrackItem*)m_pDropItem)->pTrack ),
					*pDstTrack = NULL;

				if( pSrcTrack->iChanNo==9 ){
					for( int i=0; i<pSeg->aItems->Count; i++ ){
						TTrackItem* pTmpItem = (TTrackItem*)pSeg->aItems->Items[i];
						if( pTmpItem->pTrack->iChanNo==9 ){
							pDstTrack = pTmpItem->pTrack;
							break;
						}
					}
				}

				int iMT = -1;
				if( pDstTrack ){
					iMT = g_Midi.GetMidiTrackIndex( pDstTrack->iFile, pDstTrack->iChanSpec );
				}
				else{
					pSrcTrack->iFile = 0xFF;
					pSrcTrack->iChanSpec = pSrcTrack->iChanNo;
				}

				TOpusStage* pStage = g_lstOpusStages[iStage];
				int iSBar = FirstBar( iStage ),
					iEBar = iSBar + pStage->aBars.size() - 1;

				ChangeTexture( iSBar, iEBar, pStage->iSegType, iMT, pSrcTrack, SEGTYPE_TRACK );
			}
			else{
				ReformStage( iStage, (TSegmentItem*)m_pDropItem );
			}
		}
	}
}
//---------------------------------------------------------------------------

String TUseStylePanel::ChargeTip( TStyleItem* pItem )
{
	String strTip = "   风格支付预估\n\n  风格   唱作音符\n";
	strTip += "------------------------\n";

	char buf[512];
	int nFee = 0;
	for( int i=0; i<m_aStyles.size(); i++ ){
		if( m_aStyles[i]->idLoc==0 && m_aStyles[i]->pOrigin->cost>0 ){
			TPROSTYLE* pStyle = m_aStyles[i];

			sprintf( buf, "[%4d]      %d\n", pStyle->idStyle, pStyle->pOrigin->cost );
			strTip += buf;

			nFee += pStyle->pOrigin->cost;
		}
	}

	strTip += "------------------------\n";
	strTip += "   合计      " + IntToStr( nFee );

	return strTip;
}
//---------------------------------------------------------------------------

void TUseStylePanel::ApplyStyle( TStyleItem* pSrcStyle )
{
	g_Midi.ClearMidiTracks();

	TStyleItem* pDestStyle = (TStyleItem*)m_aItems->Items[0];

	//Set Undo
	bool bMMUndo = false;
	int nBars = pDestStyle->nBars,
		idLoc = (pDestStyle && pDestStyle->pStyle) ? pDestStyle->pStyle->idLoc : 0,
		idStyle = (pDestStyle && pDestStyle->pStyle) ? pDestStyle->pStyle->idStyle : 0;

	TAudioTrackList* lstAudio = NULL;
	TOpusStageList* lstStageBefore = new TOpusStageList;
	g_Opus.CopyStages( 0, nBars-1, lstStageBefore );

	//替换风格
	pDestStyle->pStyle = pSrcStyle->pStyle;

	int nSegNum[4];
	vector<TSegmentItem*> aSegments[4];
	memset( nSegNum, 0, sizeof(int)*4 );

	for( int i=0; i<pSrcStyle->aItems->Count; i++ ){
		TSegmentItem* pSegment = (TSegmentItem*)pSrcStyle->aItems->Items[i];
		int stype = pSegment->GetSegType();
		aSegments[stype].push_back( pSegment );
		nSegNum[stype]++;
	}

	m_pFocItem = NULL;
	m_iFocLine = -1;
	m_pSelItem = NULL;
	m_iSelLine = -1;

	for( int i=pDestStyle->aItems->Count-1; i>=0; i-- ){
		TSegmentItem* pDestSeg = (TSegmentItem*)pDestStyle->aItems->Items[i];
		TSegmentItem* pSrcSeg = NULL;
		int stype = pDestSeg->iSegType;
		int sno = pDestSeg->iSegNo;

		if( stype>=SEGTYPE_INTRO ){
			if( nSegNum[stype]>0 ){
				TSegmentItem* pBackup = NULL;
				int t = sno / 2,
					c = sno % 2;

				for( int j=0; j<nSegNum[stype]; j++ ){
					if( aSegments[stype][j]->iSegNo % 2 == c ){
						if( aSegments[stype][j]->iSegNo / 2 == t ){
							pSrcSeg = aSegments[stype][j];
							break;
						}
						else{
							pBackup = aSegments[stype][j];
						}
					}
				}

				if( !pSrcSeg ){
					if( pBackup )
						pSrcSeg = pBackup;
					else
						pSrcSeg = aSegments[stype][0]; //大小调不分
				}
			}

			if( !bMMUndo && ( !pSrcSeg || pSrcSeg->nBars!=pDestSeg->nBars ) ){
				f_MM_AddUndoBefore( -1, NULL );

				lstAudio = new TAudioTrackList;
				g_Audio.CopyTrackList( 0, nBars, lstAudio );

				bMMUndo = true;
			}
		}
		else{
			if( stype==SEGTYPE_FILL && nSegNum[SEGTYPE_FILL]==0 ){
				stype = SEGTYPE_VAR;
			}
			else if( stype==SEGTYPE_VAR && nSegNum[SEGTYPE_VAR]==0 ){
				stype = SEGTYPE_FILL;
			}

			sno = min( sno, nSegNum[stype]-1 );
			pSrcSeg = aSegments[stype][sno];
		}

		if( pSrcSeg ){
			ReplaceSegment( pDestSeg, pSrcSeg );
		}
		else{ //删除段落
			RemoveSegment( pDestSeg );
		}
	}

	IntegrateStages( 0 );

	if( bMMUndo ){
		f_MM_AddUndoAfter( -1, NULL );
	}

	TOpusStageList* lstStageAfter = new TOpusStageList;
	g_Opus.CopyStages( 0, pDestStyle->nBars-1, lstStageAfter );

	g_Undo.AddUndo( UNDO_OPUS_STYLE, 0, idLoc, idStyle,	(void*)lstStageBefore,
														(void*)lstStageAfter );

	if( bMMUndo )
		g_Undo.SetUndoExtra( 0, 0, 0, (void*)lstAudio, NULL );

	if( !pDestStyle->IsUnfold() )
		SetFold( pDestStyle, 0 );
	else if( m_pTopItem!=pDestStyle )
		ScrollView( 0, true );
	else
		InvalidateRgn( Handle, NULL, false );

	m_pContentPanel->OnStageChanged( 0, MODE_INIT );
}
//---------------------------------------------------------------------------

void TUseStylePanel::ReplaceSegment( TSegmentItem* pDestSeg, TSegmentItem* pSrcSeg )
{
	int iStage = FindItemStage( pDestSeg );
	TOpusStage* pStage = g_lstOpusStages[iStage];
	TStyleItem *pStyItem = (TStyleItem*)m_aItems->Items[0];

	int nBar = pStage->aBars.size();
	if( pSrcSeg->iSegType>=SEGTYPE_INTRO )
		nBar = pSrcSeg->nBars;

	bool bPreChange = g_iPreStage==0;
	if( pStage->aBars.size()!=nBar ){ //段落长度调整
		int offset = nBar - pStage->aBars.size();
		int iOrigEnd = FirstBar(iStage) + pStage->aBars.size();

		if( bPreChange ){
			DuplicateRawBars();
			SendMessage( Parent->Handle, UM_STAGECHANGED, 3, 0 );
		}

		if( offset!=0 && pStage->iSegType==SEGTYPE_INTRO ){
			if( g_Theme.IsWeadup() && !memcmp( g_aAudioTracks[1]->lstBars[iOrigEnd-1]->aVols,
											g_aAudioTracks[0]->lstBars[0]->aVols,
											POINTS_PER_BAR * sizeof(DWORD) )){
				iOrigEnd--;
			}
		}

		if( offset>0 ){ //添加小节
			for( int i=0; i<offset; i++ ){
				TBar* pBar = new TBar;
				pStage->aBars.push_back(pBar);

				for( int j=1; j<g_aAudioTracks.size(); j++ ){
					TWaveBar* pWvBar = new TWaveBar;
					g_aAudioTracks[j]->lstBars.insert( g_aAudioTracks[j]->lstBars.begin() + iOrigEnd, pWvBar );
				}
			}

			for( int j=1; j<g_aAudioTracks.size(); j++ ){
				f_MM_AudioMove( j, iOrigEnd, -1, 0, offset, MODE_INSERT );
			}
		}
		else{ //删除小节
			iOrigEnd--;

			for( int i=0; i>offset; i-- ){
				delete pStage->aBars.back();
				pStage->aBars.pop_back();

				for( int j=1; j<g_aAudioTracks.size(); j++ ){
					delete g_aAudioTracks[j]->lstBars[iOrigEnd+i];
					g_aAudioTracks[j]->lstBars.erase( g_aAudioTracks[j]->lstBars.begin() + iOrigEnd+i );
				}
			}

			for( int j=1; j<g_aAudioTracks.size(); j++ ){
				f_MM_AudioMove( -1, 0, j, iOrigEnd+offset+1, iOrigEnd+1, MODE_DELETE );
			}
		}

		pDestSeg->nBars += offset;
		pStyItem->nBars += offset;

		g_Opus.CountBars();
	}

	if( pDestSeg->iType != pSrcSeg->iType ){
		pStyItem->nSegNum[pDestSeg->iType]--;
		pStyItem->nSegNum[pSrcSeg->iType]++;
	}

	pDestSeg->iType = pSrcSeg->iType;
	pStage->nVol = pDestSeg->volume = pSrcSeg->volume;
	pStage->iSegType = pDestSeg->iSegType = pSrcSeg->iSegType;
	pStage->iSegNo = pDestSeg->iSegNo = pSrcSeg->iSegNo;

	g_Midi.RemoveStage( iStage, false );
	//清空tracks
	while( pStage->aTracks.size()>0 ){
		delete pStage->aTracks.back();
		pStage->aTracks.pop_back();
	}

	int iSegLine = 0, nTrkBefore = 0, nTrkAfter = 0;

	if( pStyItem->IsUnfold() ){
		TCommonItem *pItem = pStyItem;
		while( pItem && pItem!=pDestSeg ){
			iSegLine++;
			pItem = GetNextItem( pItem );
		}

		if( pDestSeg->IsUnfold() ){
			if( m_pSelItem && m_pSelItem->up==pDestSeg ){
				m_pSelItem = NULL;
				m_iSelLine = -1;
			}

			nTrkBefore = pDestSeg->aItems->Count;
			nTrkAfter = pSrcSeg->aItems->Count;

			if( m_pTopItem && m_pTopItem->up==pDestSeg ){
				TCommonItem * pItem = m_pTopItem;
				int iTopLine = m_iTopLine;
				while( pItem!=pDestSeg ){
					iTopLine--;
					pItem = GetPrevItem( pItem );
				}

				ScrollView( iTopLine, true );
			}
		}
	}

	pDestSeg->ClearSubItems();
	DWORD opts = OPT_DEL|OPT_VOL;
	if( pDestSeg->iSegType<SEGTYPE_INTRO )
		opts |= OPT_TEXTURE;

	int nMTCount = g_aMidiTracks.size();
	for( int i=0; i<pSrcSeg->aItems->Count; i++ ){
		TTrackItem* pTrkItem = (TTrackItem*)pSrcSeg->aItems->Items[i];
		TTrack * pTrack = new TTrack( pTrkItem->pTrack );

		pDestSeg->AddTrack( pTrkItem->pStyle, pTrack, opts, false );
		pStage->aTracks.push_back( pTrack );

		TMidiTrack* pMT = g_Midi.GetValidMidiTrack( iStage, pTrack->iFile, pTrack->iChanNo,
													pTrack->iBank, pTrack->iProg );
		pTrack->iFile = pMT->file;
		pTrack->iChanSpec = pMT->chno;
	}

	bool bDeletedMT = g_Midi.ClearEmptyTrack()>=0;
	if( bPreChange || !m_pContentPanel->IsVertical() && ( bDeletedMT
										|| nMTCount!=g_aMidiTracks.size() ))
		m_pContentPanel->InitialVars();

	m_nTotalLine += nTrkAfter - nTrkBefore;

	if( m_iTopLine>iSegLine ){
		m_iTopLine += nTrkAfter - nTrkBefore;
	}

	ResetScrollBar();
	Paint();
}
//---------------------------------------------------------------------------

void TUseStylePanel::DeleteItem( TCommonItem *pItem, int iLine )
{
	Stop();
	TStyleItem *pStyItem = (TStyleItem*)m_aItems->Items[0];

	int iStage = FindItemStage( pItem );

	if( pItem->iType==SEGTYPE_TRACK ){
		DeleteTrack( iStage, (TTrackItem*)pItem, iLine );
	}
	else{
		RemoveStage( iStage );

		if( pStyItem->aItems->Count==0 ){
//			g_Midi.ClearMidiTracks();
			ClearAllItems();

			g_pUseStyle = NULL;
			Paint();
		}
	}
}
//---------------------------------------------------------------------------

void TUseStylePanel::DeleteTrack( int iStage, TTrackItem* pTrkItem, int iLine )
{
	TOpusStage* pStage = g_lstOpusStages[iStage];
	for( int i=0; i<pStage->aTracks.size(); i++ ){
		TTrack* pTrack = pStage->aTracks[i];
		if( pTrkItem->pTrack==pTrack ){
			int iFirstBar = FirstBar( iStage ),
				iEndBar = iFirstBar + pStage->aBars.size() - 1;
			int iMT= g_Midi.GetMidiTrackIndex( pTrack->iFile, pTrack->iChanSpec );

			ChangeTexture( iFirstBar, iEndBar, pStage->iSegType, iMT, NULL, SEGTYPE_TRACK );

			break;
		}
	}
}
//---------------------------------------------------------------------------

TSegmentItem* TUseStylePanel::InsertSegment( int iStage, TSegmentItem* pSrcSeg, int nBars  )
{
	if( m_aItems->Count==0 ){
		g_pUseStyle = AddStyle( ((TTrackItem*)pSrcSeg->aItems->Items[0])->pStyle );
	}

	TStyleItem* pStyleItem = (TStyleItem*)m_aItems->First();

	int ind = 0;
	DWORD opts = OPT_DEL|OPT_VOL;
	int stype = pSrcSeg->iSegType;
	if( pSrcSeg->iSegType<=SEGTYPE_FILL ){
		stype = SEGTYPE_VAR;
		opts |= OPT_BRUSH;
	}

	if( iStage<0 || iStage>=pStyleItem->aItems->Count ){
		iStage = pStyleItem->aItems->Count;

		if( pSrcSeg->iSegType<=SEGTYPE_FILL ){
			ind = pStyleItem->nSegNum[SEGTYPE_VAR]
						+ pStyleItem->nSegNum[SEGTYPE_FILL];
		}
		else
			ind = pStyleItem->nSegNum[pSrcSeg->iSegType];
	}
	else{
		for( int i=0; i<pStyleItem->aItems->Count; i++ ){
			TSegmentItem* pTmpSeg = (TSegmentItem*)pStyleItem->aItems->Items[i];

			if( pTmpSeg->iSegType<=SEGTYPE_FILL && stype==SEGTYPE_VAR ){
				if( i<iStage )
					ind++;
				else
					pTmpSeg->iInd++;
			}
			else if( pTmpSeg->iSegType==stype ){
				if( i<iStage )
					ind++;
				else
					pTmpSeg->iInd++;
			}
		}
	}

	TSegmentItem* pDestSeg = new TSegmentItem( pStyleItem, pSrcSeg->iSegType, pSrcSeg->iSegNo,
													opts, nBars, ind, pSrcSeg->volume, false );
	opts = OPT_DEL|OPT_VOL;
	if( pSrcSeg->iSegType<SEGTYPE_INTRO )
		opts |= OPT_TEXTURE;

	TOpusStage* pStage = g_lstOpusStages[iStage];
	for( int i=0; i<pStage->aTracks.size(); i++ ){
		TTrack* pTrack = pStage->aTracks[i];
		pDestSeg->AddTrack( NULL, pTrack, opts, false );
	}

	if( pStyleItem->IsUnfold() ){
		m_nTotalLine++;

		int iTopStage = FindItemStage( m_pTopItem );

		if( iTopStage>=iStage ){
			m_iTopLine++;
		}
	}

	pStyleItem->InsertSegment( iStage, pDestSeg, nBars );

	return pDestSeg;
}
//---------------------------------------------------------------------------

void TUseStylePanel::RemoveSegment( TSegmentItem* pItem, bool bSetMM )
{
	int iStage = FindItemStage( pItem );
	TOpusStage* pStage = g_lstOpusStages[iStage];

	int iFirstBar = FirstBar(iStage);
	int iEndBar =  iFirstBar + pStage->aBars.size();

	if( bSetMM && iEndBar>iFirstBar ){
		if( g_iPreStage==0 )
			DuplicateRawBars();

		for( int i=1; i<g_aAudioTracks.size(); i++ ){
			MoveAudio( i, iFirstBar, iEndBar, -1, 0, MODE_DELETE | OPT_BARS );
		}
	}

	g_Opus.RemoveStage( iStage );
	g_Midi.RemoveStage( iStage, true );

	TStyleItem* pStyItem = (TStyleItem*)m_aItems->First();

	if( m_pTopItem ){
		int iTopStage = FindItemStage( m_pTopItem );

		if( pStyItem->IsUnfold() ){
			if( iTopStage>iStage ){
				m_iTopLine--;

				if( pItem->IsUnfold() ){
					m_iTopLine -= pItem->aItems->Count;
				}
			}
			else if( iTopStage==iStage && m_pTopItem!=pItem ){ //展开且TopItem是Track
				TCommonItem* pTmpItem = m_pTopItem;
				m_pTopItem = GetPrevItem( pItem );

				while( pTmpItem!=m_pTopItem ){
					m_iTopLine--;
					pTmpItem = GetPrevItem( pTmpItem );
				}
			}
		}
	}

	TStylePanel::DeleteItem( pItem, -1 );

	pStyItem->nBars -= iEndBar - iFirstBar;
}
//---------------------------------------------------------------------------

int TUseStylePanel::FindItemStage( TCommonItem* pItem )
{
	int iStage = -1;
	TStyleItem* pStyle = (TStyleItem*)m_aItems->First();
	TSegmentItem* pSeg = NULL;

	if( pItem->iType!=SEGTYPE_STYLE ){
		if( pItem->iType==SEGTYPE_TRACK )
			pSeg = (TSegmentItem*)pItem->up;
		else
			pSeg = (TSegmentItem*)pItem;

		for( int i=0; i<pStyle->aItems->Count; i++ ){
			if( pSeg==pStyle->aItems->Items[i] ){
				iStage = i;
				break;
			}
		}
	}

	return iStage;
}
// ---------------------------------------------------------------------------
/*
TCommonItem* TUseStylePanel::DrawDragStageItem( int iStage )
{
	TStyleItem* pStyle= (TStyleItem*)m_aItems->First();
	TSegmentItem* pSeg = (TSegmentItem*)pStyle->aItems->Items[iStage];

	DrawDragImg( pSeg );

	return pSeg;
}
// ---------------------------------------------------------------------------
*/
void TUseStylePanel::SetSelectStage( int iStage )
{
	if( m_aItems->Count==0 )
		return;

	TStyleItem* pStyle = (TStyleItem*)m_aItems->Items[0];
	if( iStage>=0 && iStage<pStyle->aItems->Count ){
		TSegmentItem* pSeg = (TSegmentItem*)pStyle->aItems->Items[iStage];

		if( !pStyle->IsUnfold() ){
			SetFold( pStyle, 0 );
		}

		TCommonItem* pItem = GetNextItem( pStyle );
		int iLine = 1;
		while( pItem!=pSeg ){
			pItem = GetNextItem( pItem );
			iLine++;
		}

		SetSelect( pSeg, iLine - m_iTopLine );

		ShowSelItem();
	}
	else{
		SetSelect( NULL, -1 );
	}
}
// ---------------------------------------------------------------------------

void TUseStylePanel::VolumeChanged( TCommonItem *pItem, char volNew )
{
	char volOld = pItem->iType==SEGTYPE_TRACK ? ((TTrackItem*)pItem)->pTrack->nVol
							: ((TSegmentItem*)pItem)->volume;

	if( volNew==(char)0x80 ){
		if( pItem->IsMute() )
			volNew = volOld & ~0x80;
		else
			volNew = volOld | 0x80;
	}
	else if( volOld<0 ){
			volNew |= 0x80;
	}

	int iStage = FindItemStage( pItem );

	if( iStage<0 )
		return;

	ChangeVolume( iStage, pItem, volNew );
}
// ---------------------------------------------------------------------------

void TUseStylePanel::ChangeVolume( int iStage, TCommonItem* pItem, char newVol, bool bAddUndo )
{
	bool bSetUndo = false;
	int volBefore, volAfter = newVol,
		iUndoType = -1,
		iUndoCode = -1;
	TTrack* pUndoExt = NULL;

	int iStartBar = FirstBar( iStage ),
		iEndBar = iStartBar + g_lstOpusStages[iStage]->aBars.size();

	TOpusStage* pStage = g_lstOpusStages[iStage];
	TSegmentItem* pSeg = NULL;
	TTrackItem* pTrkItem = NULL;

	if( pItem->iType==SEGTYPE_TRACK ){
		pSeg = (TSegmentItem*)pItem->up;
		pTrkItem = (TTrackItem*)pItem;
	}
	else{
		pSeg = (TSegmentItem*)pItem;

		if( bAddUndo ){
			bSetUndo = true;
			iUndoType = UNDO_STAGE_VOL;
			iUndoCode = MAKELONG( iStage, -1 );
			volBefore = pStage->nVol;
		}

		pStage->nVol = pSeg->volume = newVol;
	}

	float fSegVol = pSeg->volume / 100.0;

	for( int i=0; i<pStage->aTracks.size(); i++ ){
		TTrack* pTrk = pStage->aTracks[i];

		if( pTrkItem ){
			if( pTrk==pTrkItem->pTrack ){
				if( bAddUndo ){
					bSetUndo = true;
					iUndoType = UNDO_PROG_VOL;
					iUndoCode = MAKELONG( iStage, (pTrk->iFile<<8) + pTrk->iChanSpec );
					volBefore = (char)pTrk->nVol;
					pUndoExt = new TTrack( pTrk );
				}

				pTrk->nVol = newVol;

				int vol = pTrk->nVol<0 ? 0 : pTrk->nVol * fSegVol;
				f_MM_SetTrackEvent( MIDI_EVENT_VOLUME, iStartBar, iEndBar,
													pTrk->iChanSpec, vol, pTrk->iFile );

				if( m_bPlaying && ( pTrkItem==m_pSelItem )){
					f_MM_SetTrackEvent( MIDI_EVENT_VOLUME, 0, iEndBar-iStartBar,
															pTrk->iChanSpec, vol, -1 );
				}

				int iMT = g_Midi.GetMidiTrackIndex( pTrk->iFile, pTrk->iChanSpec );
				g_Midi.ChangeNotesVolume( iMT, iStartBar, iEndBar, vol );

				if( !m_pContentPanel->IsVertical() ){
					int iShowTrack = m_pContentPanel->GetShowTrackId( ST_MIDI, iMT );
					m_pContentPanel->InvalidateBars( iStartBar, iEndBar-1, BAR_TRACK | iShowTrack );
				}

				break;
			}
		}
		else if( pTrk->nVol>0 ){
			int vol = pTrk->nVol * fSegVol;

			f_MM_SetTrackEvent( MIDI_EVENT_VOLUME, iStartBar, iEndBar,
														pTrk->iChanSpec, vol, pTrk->iFile );

			if( m_bPlaying && pSeg==m_pSelItem->up ){
				f_MM_SetTrackEvent( MIDI_EVENT_VOLUME, 0, iEndBar-iStartBar,
														pTrk->iChanSpec, vol, -1 );
			}

			int iMT = g_Midi.GetMidiTrackIndex( pTrk->iFile, pTrk->iChanSpec );
			g_Midi.ChangeNotesVolume( iMT, iStartBar, iEndBar, vol );

			if( !m_pContentPanel->IsVertical() ){
				int iShowTrack = m_pContentPanel->GetShowTrackId( ST_MIDI, iMT );
				m_pContentPanel->InvalidateBars( iStartBar, iEndBar-1, BAR_TRACK | iShowTrack );
			}
		}
	}

	if( bSetUndo ){
		TUndoLite* pLite = g_Undo.GetLastLite();
		if( pLite && pLite->iType==iUndoType && pLite->iCode==iUndoCode ){
			bool bMuteCurr = volBefore>=0 && volAfter<0 || volBefore<0 && volAfter>=0,
				bMuteLast = ( (int)pLite->pBefore >= 0 && (int)pLite->pAfter < 0
								|| (int)pLite->pBefore < 0 && (int)pLite->pAfter >= 0 );

			if( bMuteCurr==bMuteLast ){
				bSetUndo = false;

				if( (char)pLite->pBefore==volAfter )
					g_Undo.CancelUndo();
				else
					pLite->pAfter = (void*)volAfter;

				if( pUndoExt )
					delete pUndoExt;
			}
		}

		if( bSetUndo ){
			g_Undo.AddUndo( iUndoType, iUndoCode, iStartBar, iEndBar,
										(void*)volBefore, (void*)volAfter );

			if( pUndoExt )
				g_Undo.SetUndoExtra( 0, 0, 0, pUndoExt, NULL );
		}
	}

	if( g_iPreStage==0 ){
		g_Theme.Set( g_pUseStyle->pStyle->idLoc, g_pUseStyle->pStyle->idStyle,
																	g_lstOpusStages );
	}
}
// ---------------------------------------------------------------------------

bool TUseStylePanel::IntegrateStages( int iStageBegin, bool bSetMM )
{
	iStageBegin--;

	if( iStageBegin<0 )
		iStageBegin = 0;

	if( g_lstOpusStages.size()==0 ){
		ClearAllItems();
		g_pUseStyle = NULL;
	}

	if( g_lstOpusStages.size()<=iStageBegin ){
		return false;
	}

	bool bIntegrated = false;
	TStyleItem* pStyleItem = (TStyleItem*)m_aItems->First();
	TSegmentItem* pSegItem1 = (TSegmentItem*)pStyleItem->aItems->Items[iStageBegin];

	TOpusStageList::iterator iterFirst, iterSecond;
	iterFirst = iterSecond = g_lstOpusStages.begin() + iStageBegin;

	while( (++iterSecond)!=g_lstOpusStages.end() ){
		TOpusStage *pStage1 = *iterFirst,
				   *pStage2 = *iterSecond;
		TSegmentItem* pSegItem2 = (TSegmentItem*)pSegItem1->next;

		if( pStage1->iSegType<=SEGTYPE_FILL && pStage2->iSegType==pStage1->iSegType
											 && !DiffStages( pStage1, pStage2 ) ){
			if( !pStage1->aTracks.empty() ){
				int num = pStage1->aTracks.size();
				bool* aMatch = new bool[num];
				memset( aMatch, false, sizeof(bool)*num );

				for( int i=0; i<num; i++ ){
					TTrack* pTrk1 = pStage1->aTracks[i];

					for( int j=0; j<num; j++ ){
						TTrack* pTrk2 = pStage2->aTracks[j];
						if( !aMatch[j] && pTrk1->iStyleId==pTrk2->iStyleId
										&& pTrk1->iStyleLoc==pTrk2->iStyleLoc
										&& pTrk1->iSegNo==pTrk2->iSegNo
										&& pTrk1->iChanNo==pTrk2->iChanNo
										&& pTrk1->iBank==pTrk2->iBank
										&& pTrk1->iProg==pTrk2->iProg
										&& pTrk1->nVol==pTrk2->nVol	){
							if( pTrk1->iFile==0xFF && pTrk2->iFile!=0xFF ){
								pTrk1->iFile = pTrk2->iFile;
								pTrk1->iChanSpec = pTrk2->iChanSpec;
							}

							aMatch[j] = true;

							break;
						}
					}
				}

				delete[] aMatch;
			}

			pSegItem1->nBars += pSegItem2->nBars;
			for( int i=0; i<pStage2->aBars.size(); i++ ){
				pStage1->aBars.push_back( pStage2->aBars[i] );
			}
			pStage2->aBars.clear();

			g_Opus.ChangeStageBar( iterFirst - g_lstOpusStages.begin(), pSegItem2->nBars, false );

			RemoveSegment( pSegItem2, bSetMM );

			bIntegrated = true;
			iterSecond = iterFirst;
		}
		else{
			iterFirst++;
			pSegItem1 = (TSegmentItem*)pSegItem1->next;
		}
	}

	CountStyles();

	HandleWeakup( iStageBegin, bSetMM );

	return bIntegrated;
}
//---------------------------------------------------------------------------

void TUseStylePanel::HandleWeakup( int iStageBegin, bool bSetMM )
{
	if( !g_Theme.IsWeadup() || g_aAudioTracks.size()<2
							|| g_aAudioTracks[0]->lstBars.empty()
							|| g_aAudioTracks[1]->lstBars.empty() )
		return;

	TStyleItem* pStyleItem = (TStyleItem*)m_aItems->First();
	TSegmentItem* pSegItem1 = (TSegmentItem*)pStyleItem->aItems->Items[iStageBegin];

	TOpusStageList::iterator iterFirst, iterSecond;
	iterFirst = iterSecond = g_lstOpusStages.begin() + iStageBegin;

	int iFirstBar = FirstBar( iStageBegin );

	if( iFirstBar==0 ){
		if( pSegItem1->iSegType<=SEGTYPE_FILL ){
			if( m_bAddWeakupBar ){
				TOpusStage *pStage0 = *iterFirst;
				if( !memcmp( g_aAudioTracks[1]->lstBars[0]->aVols,
											g_aAudioTracks[0]->lstBars[1]->aVols,
											POINTS_PER_BAR * sizeof(DWORD) )){
					TBar * pBar0 = new TBar( g_Theme.GetFirstBar() );
					pStage0->aBars.insert( pStage0->aBars.begin(), pBar0 );
					pSegItem1->nBars++;
					pStyleItem->nBars++;

					for( int i=1; i<g_aAudioTracks.size(); i++ ){
						TWaveBar* pWvBar = NULL;

						if( i==1 ){//音轨1添加弱起小节
							pWvBar = new TWaveBar( g_aAudioTracks[0]->lstBars[0] );
							if( bSetMM )
								f_MM_AudioMove( 1, 0, 0, 0, 1, MODE_INSERT );
						}
						else{//其它音轨添加空白小节
							pWvBar = new TWaveBar;
							if( bSetMM )
								f_MM_AudioMove( i, 0, -1, 0, 1, MODE_INSERT );
						}

						g_aAudioTracks[i]->lstBars.insert( g_aAudioTracks[i]->lstBars.begin(), pWvBar );
					}
				}

				iFirstBar += pSegItem1->nBars;
				iterFirst++;
				iterSecond++;
			}
		}
		else{
			m_bAddWeakupBar = true;
		}
	}

	while( pSegItem1->next && (++iterSecond)!=g_lstOpusStages.end() ){
		TOpusStage *pStage1 = *iterFirst,
				   *pStage2 = *iterSecond;
		TSegmentItem* pSegItem2 = (TSegmentItem*)pSegItem1->next;

		if( pStage1->iSegType==SEGTYPE_INTRO ){
			int iFirstBar2 = iFirstBar + pSegItem2->nBars;
			if( pStage2->iSegType<=SEGTYPE_FILL
							&& !memcmp( g_aAudioTracks[1]->lstBars[iFirstBar2]->aVols,
														g_aAudioTracks[0]->lstBars[1]->aVols,
														POINTS_PER_BAR * sizeof(DWORD) )){
				bool bCopy = true;
				for( int i=0; i<POINTS_PER_BAR; i++ ){
					if( g_aAudioTracks[1]->lstBars[iFirstBar2-1]->aVols[i]!=0 ){
						bCopy = false;
						break;
					}
				}

				if( bCopy ){
					memcpy( g_aAudioTracks[1]->lstBars[iFirstBar2-1]->aVols,
														g_aAudioTracks[0]->lstBars[0]->aVols,
														POINTS_PER_BAR * sizeof(DWORD) );
					if( bSetMM )
						f_MM_AudioMove( 1, iFirstBar2-1, 0, 0, 1, MODE_COPY );
				}
			}
			else{
				if( !memcmp( g_aAudioTracks[1]->lstBars[iFirstBar2-1]->aVols,
														g_aAudioTracks[0]->lstBars[0]->aVols,
														POINTS_PER_BAR * sizeof(DWORD) )){
					memset( g_aAudioTracks[1]->lstBars[iFirstBar2-1]->aVols, 0,
														POINTS_PER_BAR * sizeof(DWORD) );

					if( bSetMM )
						f_MM_AudioMove( -1, 0, 1, iFirstBar2-1, iFirstBar2, MODE_ERASE );
				}
			}
		}

		iFirstBar += pSegItem1->nBars;
		iterFirst++;
		pSegItem1 = (TSegmentItem*)pSegItem1->next;
	}
}

int TUseStylePanel::GetInsertStage( int iInsertBar )
{
	int iFirstBar,
		iDestStage = FindStage( iInsertBar, &iFirstBar );

	if( iDestStage>=0 ){
		TStyleItem* pStyleItem = (TStyleItem*)m_aItems->First();
		TSegmentItem* pSrcSeg = (TSegmentItem*)pStyleItem->aItems->Items[iDestStage];

		if( iInsertBar!=iFirstBar ){//分段插入
			int nBarNum = pSrcSeg->nBars - ( iInsertBar - iFirstBar );

			g_Opus.CutStage( iDestStage, iInsertBar );
			g_Midi.CutStage( iDestStage );

			InsertSegment( iDestStage+1, pSrcSeg, nBarNum );
			pSrcSeg->nBars -= nBarNum;
			pStyleItem->nBars -= nBarNum;

			iDestStage++;
		}
	}
	else if( iInsertBar>0 ){
		iDestStage = g_lstOpusStages.size();
	}

	return iDestStage;
}
//-----------------------------------------------------------------------------

TTrackItem* TUseStylePanel::AddTrack( TSegmentItem* pSeg, TTrack* pSrcTrk, int iInd )
{
	TTrackItem* pDestTrk = NULL;

	if( pSeg && pSrcTrk ){
		int nTrksBefore = pSeg->aItems->Count;
		TPROSTYLE* info = GetStyleInfo( pSrcTrk->iStyleLoc, pSrcTrk->iStyleId );

		if( info ){
			DWORD opts = OPT_DEL|OPT_VOL;
			if( pSeg->iSegType<SEGTYPE_INTRO )
				opts |= OPT_TEXTURE;

			pDestTrk = pSeg->AddTrack( info, pSrcTrk, opts, false, iInd );

			int nTrksAfter = pSeg->aItems->Count;
			if( pSeg->IsUnfold() && nTrksAfter!=nTrksBefore ){
				m_nTotalLine += nTrksAfter-nTrksBefore;
			}
		}
	}

	return pDestTrk;
}

void __fastcall TUseStylePanel::InsertStage( int iInsertBar, TSegmentItem* pSrcSeg )
{
	Stop();

	int iDestStage = GetInsertStage( iInsertBar );

	TOpusStage* pNewStage = new TOpusStage;
	pNewStage->iSegKey = g_iMelodyKey;
	pNewStage->iSegNo = pSrcSeg->iSegNo;
	pNewStage->iSegType = pSrcSeg->iSegType;
	pNewStage->nVol = pSrcSeg->volume;

	int nBarNum = 0;
	if( pSrcSeg->iSegType>=SEGTYPE_INTRO )
		nBarNum = pSrcSeg->nBars;

	bool bPreChange = g_iPreStage==0;
	if( bPreChange ){
		DuplicateRawBars();
	}

	for( int j=0; j<nBarNum; j++ ){
		TBar* pBar = new TBar;
		pNewStage->aBars.push_back(pBar);
	}

	bool bCountDown = false;
	for( int i=1; i<g_aAudioTracks.size(); i++ ){
		bCountDown |= MoveAudio( -1, 0, nBarNum, i, iInsertBar, MODE_INSERT | OPT_BARS );
	}

	ProduceTracks( pNewStage, pSrcSeg );

	g_Opus.InsertStage( iDestStage, pNewStage );
	g_Midi.InsertStage( iDestStage );

	int nMTCountOld = g_aMidiTracks.size();
	for( int i=0; i<pNewStage->aTracks.size(); i++ ){
		TTrack* pTrack = pNewStage->aTracks[i];

		TMidiTrack* pMT = g_Midi.GetValidMidiTrack( iDestStage, pTrack->iFile, pTrack->iChanNo,
													pTrack->iBank, pTrack->iProg );
		pTrack->iFile = pMT->file;
		pTrack->iChanSpec = pMT->chno;
	}

	if( bPreChange || nMTCountOld!=g_aMidiTracks.size() )
		m_pContentPanel->InitialVars();

	InsertSegment( iDestStage, pSrcSeg, nBarNum );

	IntegrateStages( iDestStage );

	ResetScrollBar();
	Paint();

	m_pContentPanel->OnStageChanged( iDestStage, MODE_INSERT );
}
//-----------------------------------------------------------------------------

void __fastcall TUseStylePanel::RemoveStage( int iStage )
{
	TStyleItem* pStyle = (TStyleItem*)m_aItems->First();
	TSegmentItem* pSegItem = (TSegmentItem*)pStyle->aItems->Items[iStage];

	bool bPreChange = g_iPreStage==0;
	if( bPreChange )
		DuplicateRawBars();

	f_MM_AddUndoBefore( -1, NULL );

	SetBarsUndo( UNDO_BAR_DELETE, FirstBar(iStage), pSegItem->nBars );

	RemoveSegment( pSegItem );

	f_MM_AddUndoAfter( -1, NULL );

	IntegrateStages( iStage );

	ResetScrollBar();
	Paint();
//	InvalidateRgn( Handle, NULL, false );

	if( bPreChange )
		m_pContentPanel->InitialVars();

	m_pContentPanel->OnStageChanged( iStage, MODE_DELETE );
}
//-----------------------------------------------------------------------------

void __fastcall TUseStylePanel::MoveBars( int iStartBar, int iEndBar, int iInsertBar, int iMode )
{
	if( iMode==MODE_MOVE && ( iInsertBar>=iStartBar && iInsertBar<=iEndBar+1 ) )//无须移动
		return;

	Stop();

	bool bPreChange = g_iPreStage==0;
	if( bPreChange )
		DuplicateRawBars();

	int nBars = iEndBar - iStartBar + 1,
		nOrigBars = g_Opus.BarCount();

	if( iMode==MODE_DELETE ){
		SetBarsUndo( UNDO_BAR_DELETE, iStartBar, nBars );
	}
	else if( iMode==MODE_MOVE ){
		SetBarsUndo( UNDO_BAR_MOVE, iStartBar, nBars, iInsertBar );
	}

	f_MM_AddUndoBefore( -1, NULL );

	int iDestStage = GetInsertStage( iInsertBar ),
		iSrcStage = FindStage( iStartBar, NULL ),
		iFirstChangeStage = (iMode==MODE_MOVE) ? min(iSrcStage, iDestStage) :
							(iMode==MODE_DELETE) ? iSrcStage : iDestStage;

	TStyleItem* pStyleItem = (TStyleItem*)m_aItems->First();

	if( g_Theme.IsWeadup() && iStartBar==0 && iEndBar==0
								&& ( iMode==MODE_MOVE || iMode==MODE_DELETE )){
		TOpusStage* pFirstStage = g_lstOpusStages[iSrcStage];
		if( pFirstStage->iSegType<=SEGTYPE_FILL ){
			if( !memcmp( g_aAudioTracks[1]->lstBars[0]->aVols,
												g_aAudioTracks[0]->lstBars[0]->aVols,
												POINTS_PER_BAR * sizeof(DWORD) )){
				m_bAddWeakupBar = false;
			}
		}
	}

	// 音频操作
	bool bCountDown = false;
	for( int i=1; i<g_aAudioTracks.size(); i++ ){
		bCountDown |= MoveAudio( i, iStartBar, iEndBar+1, i, iInsertBar, iMode | OPT_BARS );
	}

	// 曲式操作
	int iBar = iStartBar;
	int nBarCount = 0, nMTCount = g_aMidiTracks.size();
	while( iBar<=iEndBar ){
		int iFirstBar, nOffsetBar;

		iSrcStage = FindStage( iBar, &iFirstBar ),
		nOffsetBar = iBar-iFirstBar;

		TSegmentItem* pSrcSeg = (TSegmentItem*)pStyleItem->aItems->Items[iSrcStage];

		TOpusStage* pOriStage = g_lstOpusStages[iSrcStage];
		TOpusStage* pNewStage = (iMode==MODE_DELETE) ? NULL : new TOpusStage;
		int nCopyBar = pOriStage->aBars.size() - nOffsetBar;
		if( nCopyBar>iEndBar-iBar+1 )
			nCopyBar = iEndBar-iBar+1;

		if( pNewStage ){
			pNewStage->iSegKey = pOriStage->iSegKey;
			pNewStage->iSegNo = pOriStage->iSegNo;
			pNewStage->iSegType = pOriStage->iSegType;
			pNewStage->nVol = pOriStage->nVol;

			for( int i=0; i<pOriStage->aTracks.size(); i++ ){
				TTrack * pTrack = new TTrack( pOriStage->aTracks[i] );

				pNewStage->aTracks.push_back( pTrack );
			}
		}

		int iCopyBar = nOffsetBar;
		for( int i=0; i<nCopyBar; i++ ){
			if( pNewStage ){
				TBar* pBar = NULL;
				if( iMode==MODE_COPY )
					pBar = new TBar( pOriStage->aBars[iCopyBar] );
				else
					pBar = pOriStage->aBars[iCopyBar];

				pNewStage->aBars.push_back( pBar );
			}

			if( iMode==MODE_MOVE || iMode==MODE_DELETE )
				pOriStage->aBars.erase( pOriStage->aBars.begin() + iCopyBar );
			else
				iCopyBar++;
		}

		if( iMode!=MODE_DELETE ){
			g_lstOpusStages.insert( g_lstOpusStages.begin()+iDestStage, pNewStage );
			g_Midi.CutStage( iDestStage );
			InsertSegment( iDestStage, pSrcSeg, nCopyBar );
		}

		if( iMode==MODE_MOVE || iMode==MODE_DELETE ){
			if( iMode==MODE_MOVE && iDestStage<=iSrcStage )
				iSrcStage++;
			else{
				iBar -= nCopyBar;
				iEndBar -= nCopyBar;
			}

			if( pOriStage->aBars.size()==0 ){ //删除原段落
				RemoveSegment( pSrcSeg );

				if( iMode!=MODE_DELETE && iDestStage>=iSrcStage )
					iDestStage--;
			}
			else{
				pSrcSeg->nBars -= nCopyBar;
			}

			pStyleItem->nBars -= nCopyBar;
		}
		else if( iDestStage<=iSrcStage ){
			iBar += nCopyBar;
			iEndBar += nCopyBar;
		}

		g_Opus.CountBars();

		iBar += nCopyBar;

		if( iMode!=MODE_DELETE ){
			nBarCount += nCopyBar;
			iDestStage++;
		}
	}

	if( iMode!=MODE_MOVE )
		g_Opus.CountBars();

	IntegrateStages( iFirstChangeStage );

	f_MM_AddUndoAfter( -1, NULL );

	if( iMode==MODE_COPY ){
		SetBarsUndo( UNDO_BAR_INSERT, iInsertBar, nBars );
	}
	else{
		//计算是否AddWeakupBar
		bool bAddWeakupBar = false;
		int nCurrBars = g_Opus.BarCount();

		if( iMode==MODE_MOVE && nCurrBars>nOrigBars
					|| iMode==MODE_DELETE && nCurrBars>nOrigBars-nBars )
			bAddWeakupBar = true;

		if( bAddWeakupBar )
			g_Undo.SetUndoCode( bAddWeakupBar );
	}

	if( iMode==MODE_DELETE ){
		m_pContentPanel->SelectBars( -1, - 1 );

/*		if( pStyleItem->aItems->Count==0 ){
//			g_Midi.ClearMidiTracks();
			ClearAllItems();
			g_pUseStyle = NULL;
		}
*/
	}
	else if( iMode==MODE_COPY || iInsertBar<iStartBar ){
		m_pContentPanel->SelectBars( iInsertBar, iInsertBar + nBars - 1 );
	}
	else if( iInsertBar>iEndBar ){
		m_pContentPanel->SelectBars( iInsertBar - nBars, iInsertBar - 1 );
	}

	ResetScrollBar();
	Paint();

	bool bDeletedMT = g_Midi.ClearEmptyTrack()>=0;
	if( bPreChange || (bDeletedMT || nMTCount!=g_aMidiTracks.size() )
							&& !m_pContentPanel->IsVertical() )
		m_pContentPanel->InitialVars();

	m_pContentPanel->OnStageChanged( bCountDown ? 0 : iFirstChangeStage, iMode );
}
//-----------------------------------------------------------------------------

void __fastcall TUseStylePanel::ReformBars( int iStartBarP, int iEndBarP,
												TSegmentItem* pSrcSeg, bool bAddUndo )
{
	Stop();

	int iStartBar = iStartBarP;
	int iChangeStage = -1;

	TOpusStageList* lstStageBefore = NULL;
	if( bAddUndo ){
		lstStageBefore = new TOpusStageList;
		g_Opus.CopyStages( iStartBarP, iEndBarP, lstStageBefore );
	}

	while( iStartBar<=iEndBarP ){
		int iFirstBar,
			iStage = FindStage( iStartBar, &iFirstBar );
		TOpusStage* pOriStage = g_lstOpusStages[iStage];

		if( pOriStage->iSegType>=SEGTYPE_INTRO ){
			iStartBar = iFirstBar + pOriStage->aBars.size();
		}
		else{
			bool bChange = false;
			TStyleItem* pStyleItem = (TStyleItem*)m_aItems->First();
			TSegmentItem* pOriSegItem = (TSegmentItem*)pStyleItem->aItems->Items[iStage];
			TSegmentItem* pDestSegItem = NULL;

			if( pOriStage->iSegType==pSrcSeg->iSegType
						&& pOriStage->iSegNo==pSrcSeg->iSegNo
						&& pOriStage->nVol==pSrcSeg->volume
						&& pOriStage->aTracks.size()==pSrcSeg->aItems->Count ){
				if( pOriStage->aTracks.size()>0 ){
					int num = pOriStage->aTracks.size();
					bool* aMatch = new bool[num];
					memset( aMatch, false, sizeof(bool)*num );

					for( int i=0; i<num; i++ ){
						TTrack* pTrk1 = pOriStage->aTracks[i];

						bool bFound = false;
						for( int j=0; j<num; j++ ){
							TTrack* pTrk2 = ((TTrackItem*)pSrcSeg->aItems->Items[j])->pTrack;
							if( !aMatch[j] && pTrk1->iStyleId==pTrk2->iStyleId
										&& pTrk1->iStyleLoc==pTrk2->iStyleLoc
										&& pTrk1->iSegNo==pTrk2->iSegNo
										&& pTrk1->iChanNo==pTrk2->iChanNo
										&& pTrk1->iBank==pTrk2->iBank
										&& pTrk1->iProg==pTrk2->iProg
										&& pTrk1->nVol==pTrk2->nVol ){
								bFound = true;
								aMatch[j] = true;

								break;
							}
						}

						if( !bFound ){
							bChange = true;
							break;
						}
					}

					delete[] aMatch;
				}
			}
			else
				bChange = true;

			if( !bChange )
				iStartBar = iFirstBar + pOriStage->aBars.size();
			else{
				TOpusStage* pBrushStage = NULL;
				int iEndBar = iFirstBar + pOriStage->aBars.size()-1;
				if( iEndBar>iEndBarP ){
					g_Opus.CutStage( iStage, iEndBarP+1 );
					g_Midi.CutStage( iStage );

					InsertSegment( iStage+1,  pOriSegItem, iEndBar - iEndBarP );
					pOriSegItem->nBars -= iEndBar - iEndBarP;
					pStyleItem->nBars -= iEndBar - iEndBarP;

					iEndBar = iEndBarP;
				}

				if( iStartBar>iFirstBar ){
					g_Opus.CutStage( iStage, iStartBar );
					g_Midi.CutStage( iStage );

					pDestSegItem = InsertSegment( iStage+1,  pOriSegItem, iEndBar-iStartBar+1 );
					pOriSegItem->nBars -= iEndBar-iStartBar+1;
					pStyleItem->nBars -= iEndBar-iStartBar+1;

					iStage++;
				}
				else{
					pBrushStage = pOriStage;
					pDestSegItem = pOriSegItem;
				}

				ReplaceSegment( pDestSegItem, pSrcSeg );

				//g_Opus.CountBars();

				iStartBar = iEndBar + 1;

				if( iChangeStage<0 )
					iChangeStage = iStage;
			}
		}
	}

	if( iChangeStage>=0 ){
		IntegrateStages( iChangeStage );

		if( bAddUndo ){
			TOpusStageList* lstStageAfter = new TOpusStageList;
			g_Opus.CopyStages( iStartBarP, iEndBarP, lstStageAfter );

			g_Undo.AddUndo( UNDO_BAR_CHANGE, 0, iStartBarP, iEndBarP,
									(void*)lstStageBefore, (void*)lstStageAfter );
		}

		ResetScrollBar();
		Paint();

		m_pContentPanel->OnStageChanged( iChangeStage, MODE_CHANGE );
	}
	else if( lstStageBefore ){
		for( int i=0; i<lstStageBefore->size(); i++ ){
			delete (*lstStageBefore)[i];
		}

		delete lstStageBefore;
    }
}

void __fastcall TUseStylePanel::ReformStage( int iDestStage, TSegmentItem* pSrcSeg )
{
	Stop();

	TStyleItem* pStyleItem = (TStyleItem*)m_aItems->First();
	TSegmentItem* pDestSeg = (TSegmentItem*)pStyleItem->aItems->Items[iDestStage];

	int iStartBar = FirstBar( iDestStage ),
		iEndBar = iStartBar + pDestSeg->nBars -1,
		nOffset = 0;
	bool bMMUndo = false;

	TAudioTrackList* lstAudio = NULL;
	TOpusStageList* lstStageBefore = new TOpusStageList;
	g_Opus.CopyStages( iStartBar, iEndBar, lstStageBefore );

	if( pSrcSeg->iSegType>=SEGTYPE_INTRO && pSrcSeg->nBars!=pDestSeg->nBars ){
		nOffset = pSrcSeg->nBars - pDestSeg->nBars;

		if( nOffset<0 ){ //小节减少，复制将删除部分波形
			int nWaveBars = -nOffset;
			lstAudio = new TAudioTrackList;

			g_Audio.CopyTrackList( iEndBar+nOffset+1, nWaveBars, lstAudio );
		}

		bMMUndo = true;
	}

	if( bMMUndo ){
		f_MM_AddUndoBefore( -1, NULL );
	}

	ReplaceSegment( pDestSeg, pSrcSeg );

	IntegrateStages( iDestStage );

//	if( bMMUndo ){
//		f_MM_AddUndoAfter( -1, NULL );
//	}

	TOpusStageList* lstStageAfter = new TOpusStageList;
	g_Opus.CopyStages( iStartBar, iEndBar+nOffset, lstStageAfter );

	g_Undo.AddUndo( UNDO_BAR_CHANGE, 0, iStartBar, iEndBar,
					(void*)lstStageBefore, (void*)lstStageAfter );

	if( bMMUndo ){
		f_MM_AddUndoAfter( -1, NULL );
		g_Undo.SetUndoExtra( nOffset, 0, 0, (void*)lstAudio, NULL );
	}

	ResetScrollBar();
	Paint();

	m_pContentPanel->OnStageChanged( iDestStage, MODE_CHANGE );
}
//-----------------------------------------------------------------------------

void __fastcall TUseStylePanel::InitOpus( TStyleItem* pPreStyle, int iMode )
{
	//清空内容
	ClearGlobalVars( LIST_OPUSSTAGES | LIST_OPUSAUDIOS );
	ClearAllItems();

	g_pUseStyle = NULL;
	m_bAddWeakupBar = true;

	if( iMode<0 || !pPreStyle ){
		ClearGlobalVars( LIST_RAWAUDIO );
		m_pContentPanel->InitialVars();
		Paint();

		return;
	}

	if( iMode==0 ){
		UINT idLoc, idStyle;
		g_Theme.Get( idLoc, idStyle, g_lstOpusStages );

		g_pUseStyle = AddStyle( GetStyleInfo( idLoc, idStyle ) );

		for( int i=0; i<g_lstOpusStages.size(); i++ ){
			TOpusStage* pStage = g_lstOpusStages[i];
			AddStage( pStage );
		}

		g_aAudioTracks[0]->Hide(false);

		((TStyleItem*)m_aItems->First())->SetCharge( g_pUseStyle->pStyle->idLoc==0
														&& g_pUseStyle->pStyle->pOrigin->cost>0 );
	}
	else{
		g_pUseStyle = AddStyle( pPreStyle->pStyle );

		int iFirstStage = g_Theme.IsWeadup() ? 1 : 0;
		int nRepeat = iMode>=2 ? 2 : 1;

		int nSegNum[4];
		vector<TSegmentItem*> aSegments[4];
		memset( nSegNum, 0, sizeof(int)*4 );

		for( int i=0; i<pPreStyle->aItems->Count; i++ ){
			TSegmentItem* pSegment = (TSegmentItem*)pPreStyle->aItems->Items[i];
			int stype = pSegment->GetSegType();
			aSegments[stype].push_back( pSegment );
			nSegNum[stype]++;
		}

		if( g_aAudioTracks[0]->lstBars.size()>0 ){
			DuplicateRawBars();

			if( iMode==2 )
				MoveAudio( 1, 0, g_aAudioTracks[0]->lstBars.size(), 1, 0, MODE_COPY | OPT_BARS );
		}

		int iSegNo;
		int nBarCount = 0;
		int nThemeStages = g_Theme.StageCount();

		while( nRepeat>0 ){
			if( iMode>0 && iMode<=3 && nSegNum[SEGTYPE_INTRO]>0 ){ //添加前奏
				int iM = iMode>=2 ? 2 : 1;
				iSegNo = (iM - nRepeat) % nSegNum[SEGTYPE_INTRO];
				int iChord = g_Theme.GetFirstChord();
				int ctype = LOWORD( iChord ),
					key = HIWORD( iChord );

				if( ctype==3 ) ctype = 1;
				else if( ctype>1 ) ctype = 0;

				if( ctype==1 )
					key = ( key + 3 ) % 12;

				TSegmentItem *pSegment = NULL;
				TSegmentItem* pBackup = NULL;

				for( int j=0; j<nSegNum[SEGTYPE_INTRO]; j++ ){
					if( aSegments[SEGTYPE_INTRO][j]->iSegNo / 4 == ctype ){
						if( aSegments[SEGTYPE_INTRO][j]->iSegNo % 4 == iSegNo ){
							pSegment = aSegments[SEGTYPE_INTRO][j];
							break;
						}
						else{
							pBackup = aSegments[SEGTYPE_INTRO][j];
						}
					}
				}

				if( !pSegment ){
					if( pBackup )
						pSegment = pBackup;
					else
						pSegment = aSegments[SEGTYPE_INTRO][0]; //大小调不分
				}

				TOpusStage* pNewStage = new TOpusStage;
				pNewStage->iSegNo = pSegment->iSegNo;
				pNewStage->iSegType = SEGTYPE_INTRO;
				pNewStage->iSegKey = key;
				pNewStage->nVol = pSegment->volume;

				int nBarNum = pSegment->nBars;
				for( int i=0; i<nBarNum; i++ ){
					TBar* pBar = new TBar;
					pNewStage->aBars.push_back(pBar);
				}

				ProduceTracks( pNewStage, pSegment );

				g_lstOpusStages.push_back( pNewStage );

				int nWaveBars = nBarNum;
				if( iFirstStage>0 )
					nWaveBars--;

				if( g_aAudioTracks.size()>1 )
					MoveAudio( -1, 0, nWaveBars, 1, nBarCount, MODE_INSERT | OPT_BARS );

				InsertSegment( -1, pSegment, nBarNum );

				nBarCount += nBarNum;
			}

			//添加主旋律部分
			iSegNo = 0;
			int iStartStage = iFirstStage;

			if( iMode>2 && nRepeat==1 && nThemeStages>iFirstStage + 2 ){
				iStartStage++;
				if( nSegNum[SEGTYPE_VAR]>1 )
					iSegNo = 1;
			}

			for( int i=iStartStage; i<nThemeStages; i++ ){
				TOpusStage* pStage = g_Theme.CopyStageAt( i );

				g_lstOpusStages.push_back( pStage );
				TSegmentItem* pSegItem = AddStage( pStage );

				nBarCount += pStage->aBars.size();

				if( i==nThemeStages-1 && nSegNum[SEGTYPE_FILL]>0 && pStage->aBars.size()>1
						&& iMode>0 && iMode<=3 && ( nRepeat>0 && nSegNum[SEGTYPE_INTRO]>0
													|| nRepeat==0 && nSegNum[SEGTYPE_ENDING]>0 )){
					int iFill = 1 % nSegNum[SEGTYPE_FILL];
					TSegmentItem *pSegFill = aSegments[SEGTYPE_FILL][iFill];
					TOpusStage * pFillStage = new TOpusStage;

					pFillStage->iSegType = SEGTYPE_FILL;
					pFillStage->iSegNo = pSegFill->iSegNo;
					pFillStage->iSegKey = pStage->iSegKey;
					pFillStage->nVol = pStage->nVol;
					pFillStage->aBars.push_back( pStage->aBars.back() );

					pStage->aBars.pop_back();
					pSegItem->nBars--;
					g_pUseStyle->nBars--;

					ProduceTracks( pFillStage, pSegFill );

					g_lstOpusStages.push_back( pFillStage );

					AddStage( pFillStage );
				}
			}

			nRepeat--;
		}

		if( iMode<=3 && nSegNum[SEGTYPE_ENDING]>0 ){ //添加尾奏
			int iChord = g_Theme.GetLastChord();
			int ctype = LOWORD( iChord ),
				key = HIWORD( iChord );

			if( ctype==3 ) ctype = 1;
			else if( ctype>1 ) ctype = 0;

			if( ctype==1 )
				key = ( key + 3 ) % 12;

			TSegmentItem *pSegment = NULL;

			for( int j=0; j<nSegNum[SEGTYPE_ENDING]; j++ ){
				if( aSegments[SEGTYPE_ENDING][j]->iSegNo / 4 == ctype ){
					pSegment = aSegments[SEGTYPE_ENDING][j];
					break;
				}
			}

			if( !pSegment ){
				pSegment = aSegments[SEGTYPE_ENDING][0]; //大小调不分
			}

			TOpusStage* pNewStage = new TOpusStage;
			pNewStage->iSegType = SEGTYPE_ENDING;
			pNewStage->iSegNo = pSegment->iSegNo;
			pNewStage->iSegKey = key;
			pNewStage->nVol = pSegment->volume;

			int nBarNum = pSegment->nBars;
			for( int i=0; i<nBarNum; i++ ){
				TBar* pBar = new TBar;
				pNewStage->aBars.push_back(pBar);
			}

			ProduceTracks( pNewStage, pSegment );

			g_lstOpusStages.push_back( pNewStage );

			if( g_aAudioTracks.size()>1 )
				MoveAudio( -1, 0, nBarNum, 1, nBarCount, MODE_INSERT | OPT_BARS );

			InsertSegment( -1, pSegment, nBarNum );

			nBarCount += nBarNum;
		}
	}

	g_Opus.CountBars();
	IntegrateStages( 0 );
	g_Midi.SortMidiTracks();

	SetFold( (TCommonItem*)m_aItems->First(), 0 );

	ResetScrollBar();
	Paint();
//	InvalidateRgn( Handle, NULL, false );

	m_pContentPanel->OnStageChanged( 0, MODE_INIT );
}
// ---------------------------------------------------------------------------

void __fastcall TUseStylePanel::SetStyleItem( TStyleItem* pStyItem )
{
	TStylePanel::SetStyleItem( pStyItem );

	if( pStyItem ){
		IntegrateStages( 0, false );
		if( g_Midi.IsEmpty() )
			g_Midi.SortMidiTracks();
	}
}
// ---------------------------------------------------------------------------

void TUseStylePanel::RestoreItems()
{
	for( int i=0; i<g_lstOpusStages.size(); i++ ){
		AddStage( g_lstOpusStages[i] );
	}
}
// ---------------------------------------------------------------------------

void __fastcall TUseStylePanel::InsertBlankBar( int iInsertBar )
{
	Stop();

	TOpusStage* pNewStage = new TOpusStage;
	TBar * pNewBar = new TBar;
	pNewStage->aBars.push_back( pNewBar ); //添加一个小节

	int iBarT1 = iInsertBar;
	// 处理弱起
	if( g_bWeakup ){
		if( iInsertBar>0 ){
			int iFirstBar,
				iLastStage = FindStage( iInsertBar-1, &iFirstBar );
			TOpusStage *pLastStage = g_lstOpusStages[iLastStage];
			if( pLastStage->iSegType>SEGTYPE_FILL
									&& !memcmp( g_aAudioTracks[1]->lstBars[iInsertBar-1]->aVols,
												g_aAudioTracks[0]->lstBars[0]->aVols,
												POINTS_PER_BAR * sizeof(DWORD) )){
				iBarT1--;
			}
		}
	}

	bool bCountDown = false;
	for( int i=1; i<g_aAudioTracks.size(); i++ ){
		// 音效处理
		bCountDown |= MoveAudio( -1, 0, 1, i, iInsertBar, MODE_INSERT | OPT_BARS );
	}

	int iDestStage = GetInsertStage( iInsertBar );

	TStyleItem* pStyleItem = (TStyleItem*)m_aItems->First();

	//根据前后小节位置确定和弦与伴奏型
	TSegmentItem *pSrcSeg = NULL;
	int iFirstBar1, iFirstBar2,
		iLastStage = FindStage( iInsertBar-1, &iFirstBar1 ),
		iNextStage = FindStage( iInsertBar, &iFirstBar2 );
	TOpusStage *pLastStage = iLastStage>=0 ? g_lstOpusStages[iLastStage] : NULL,
			   *pNextStage = g_lstOpusStages[iNextStage];

	//是否前一小节可用
	if( pLastStage && pLastStage->iSegType<=SEGTYPE_FILL ){
		pNewStage->iSegKey = pLastStage->iSegKey;

		TBar *pLastBar = pLastStage->aBars[iInsertBar-iFirstBar1-1];
		pNewBar->iBarKey = pLastBar->iBarKey;

		for( int i=0; i<g_nChordNumPerBar; i++ ){
			pNewBar->aChords.iKey[i] = pLastBar->aChords.iKey[g_nChordNumPerBar-1];
			pNewBar->aChords.iType[i] = pLastBar->aChords.iType[g_nChordNumPerBar-1];
		}
		pSrcSeg = (TSegmentItem*)pStyleItem->aItems->Items[iLastStage];
	}
	else if( pNextStage->iSegType<=SEGTYPE_FILL ){ //是否后一小节可用
		pNewStage->iSegKey = pNextStage->iSegKey;

		TBar *pNextBar = pNextStage->aBars[iInsertBar-iFirstBar2];
		pNewBar->iBarKey = pNextBar->iBarKey;

		for( int i=0; i<g_nChordNumPerBar; i++ ){
			pNewBar->aChords.iKey[i] = pNextBar->aChords.iKey[0];
			pNewBar->aChords.iType[i] = pNextBar->aChords.iType[0];
		}
		pSrcSeg = (TSegmentItem*)pStyleItem->aItems->Items[iNextStage];
	}
	else{ //前后小节皆不可用
		int iSegKey,
			iKey,
			iType = 0;

		if( pLastStage ){
			iKey = pNewBar->iBarKey = pNewStage->iSegKey = pLastStage->iSegKey;

			if( pLastStage->iSegNo % 2 > 0 ){
				iKey = ( iKey + 9 ) % 12;
				iType = 1;
			}
		}
		else{
			iKey = pNewBar->iBarKey = pNewStage->iSegKey = pNextStage->iSegKey;

			if( pNextStage->iSegNo % 2 > 0 ){ //小调
				iKey = ( iKey + 9 ) % 12;
				iType = 1;
			}
		}

		for( int i=0; i<g_nChordNumPerBar; i++ ){
			pNewBar->aChords.iKey[i] = iKey;
			pNewBar->aChords.iType[i] = iType;
		}

		for( int i=0; i<g_pPreStyle->aItems->Count; i++ ){
			TSegmentItem* pSegment = (TSegmentItem*)g_pPreStyle->aItems->Items[i];
			int stype = pSegment->GetSegType();
			if( stype==SEGTYPE_VAR || stype==SEGTYPE_FILL ){
				pSrcSeg = pSegment;
				break;
			}
		}
	}

	pNewStage->iSegType = pSrcSeg->iSegType;
	pNewStage->iSegNo = pSrcSeg->iSegNo;

//	ProduceTracks( pNewStage, pSrcSeg );

	g_Opus.InsertStage( iDestStage, pNewStage );
	g_Midi.InsertStage( iDestStage );

	InsertSegment( iDestStage, pSrcSeg, 1 );

	IntegrateStages( iDestStage );

	ResetScrollBar();
	Paint();

	m_pContentPanel->OnStageChanged( iDestStage, MODE_INSERT );
}
// ---------------------------------------------------------------------------

void TUseStylePanel::CountStyles()
{
	m_aStyles.clear();
	if( m_aItems->Count==0 )
		return;

	TStyleItem* pStyItem = (TStyleItem*)m_aItems->First();
	TPROSTYLE* pStyle = pStyItem->pStyle,
			*pMainStyle = NULL;

	vector<int> lstCount;
	for( int i=0; i<pStyItem->aItems->Count; i++ ){
		TSegmentItem* pSeg = (TSegmentItem*)pStyItem->aItems->Items[i];
		for( int j=0; j<pSeg->aItems->Count; j++ ){
			TTrackItem* pTrk = (TTrackItem*)pSeg->aItems->Items[j];

			bool bMatch = false;
			for( int k=0; k<m_aStyles.size(); k++ ){
//				if( pTrk->pStyle->idLoc==m_aStyles[k]->idLoc
//							&& pTrk->pStyle->idStyle==m_aStyles[k]->idStyle ){
				if( pTrk->pStyle==m_aStyles[k] ){
					bMatch = true;
					lstCount[k]++;
					break;
				}
			}

			if( !bMatch ){
				m_aStyles.push_back( pTrk->pStyle );
				lstCount.push_back( 1 );
			}
		}
	}

	bool bKeep = false;
	bool bCharge = false;
	int maxCount = 0;
	for( int i=0; i<lstCount.size(); i++ ){
		if( lstCount[i]>maxCount ){
			maxCount = lstCount[i];
			pMainStyle = m_aStyles[i];
		}

		if( pStyle && pStyle->idLoc==m_aStyles[i]->idLoc
					&& pStyle->idStyle==m_aStyles[i]->idStyle ){
			bKeep = true;
		}

		if( !bCharge && m_aStyles[i]->idLoc==0
						&& m_aStyles[i]->pOrigin->cost>0 ){
			bCharge = true;
		}
	}

	if( !pStyle || !bKeep ){
		pStyItem->pStyle = pMainStyle;

		if( m_pTopItem==pStyItem )
			DrawItem( pStyItem, 0, -1 );
	}

	pStyItem->SetCharge( bCharge );
}
// ---------------------------------------------------------------------------

void TUseStylePanel::CopyUndoBars( int iStartBar, int iEndBar, TOpusStageList* lstStages,
																TAudioTrackList* lstAudio, bool bFx )
{
	if( lstStages )
		g_Opus.CopyStages( iStartBar, iEndBar, lstStages );

	if( lstAudio )
		g_Audio.CopyTrackList( iStartBar, iEndBar-iStartBar+1, lstAudio, bFx );
}

void TUseStylePanel::CopyBars( int iStartBar, int iEndBar, TOpusStageList* lstStages,
									TSegmentList* lstSegments, TAudioTrackList* lstAudio )
{
	int iBar = iStartBar;

	while( iBar<=iEndBar ){
		int iFirstBar, iSrcStage = FindStage( iBar, &iFirstBar ),
			nOffsetBar = iBar-iFirstBar;
		TOpusStage* pOriStage = g_lstOpusStages[iSrcStage];
		int nCopyBar = pOriStage->aBars.size() - nOffsetBar;

		if( nCopyBar>iEndBar-iBar+1 )
			nCopyBar = iEndBar-iBar+1;

		if( lstStages ){
			TOpusStage* pNewStage = new TOpusStage( pOriStage );

			for( int i=nOffsetBar; i<nCopyBar; i++ ){
				pNewStage->aBars.push_back( new TBar( pOriStage->aBars[i] ) );
			}

			for( int j=0; j<pOriStage->aTracks.size(); j++ ){
				pNewStage->aTracks.push_back( new TTrack( pOriStage->aTracks[j] ));
			}

			lstStages->push_back( pNewStage );
		}

		iBar += nCopyBar;
	}

	if( lstAudio ){
		for( int i=1; i<g_aAudioTracks.size(); i++ ){
			TAudioTrack* pAudio = CopyAudioTrack( i, iStartBar, iEndBar-iStartBar+1 );
			lstAudio->push_back( pAudio );
		}
	}
}
// ---------------------------------------------------------------------------
/*
void TUseStylePanel::InsertStages( int iInsertBar, TOpusStageList lstStages )
{
	int iDestStage = GetInsertStage( iInsertBar );

	for( int i=lstStages.size()-1; i>=0; i-- ){
		TOpusStage* pStage = lstStages[i];
		g_lstOpusStages.insert( g_lstOpusStages.begin()+iDestStage, pStage );
	}
}
// ---------------------------------------------------------------------------
*/
void TUseStylePanel::DeleteBars( int iStartBarP, int iEndBarP, bool bDelWave )
{
	TStyleItem* pStyItem = (TStyleItem*)m_aItems->First();
	int iBar = iStartBarP,
		iEndBar = iEndBarP;

	while( iBar<=iEndBar ){
		int iFirstBar, iSrcStage = FindStage( iBar, &iFirstBar ),
			nOffsetBar = iBar-iFirstBar;

		TSegmentItem* pSrcSeg = (TSegmentItem*)pStyItem->aItems->Items[iSrcStage];
		TOpusStage* pOriStage = g_lstOpusStages[iSrcStage];

		int nDelBar = pOriStage->aBars.size() - nOffsetBar;
		if( nDelBar>iEndBar-iBar+1 )
			nDelBar = iEndBar-iBar+1;

		pOriStage->aBars.erase( pOriStage->aBars.begin() + nOffsetBar,
									   pOriStage->aBars.begin() + nOffsetBar + nDelBar );
		iEndBar -= nDelBar;

		g_Opus.ChangeStageBar( iSrcStage, -nDelBar, true );

		if( pOriStage->aBars.empty() ){ //删除原段落
			RemoveSegment( pSrcSeg, false );
		}
		else{
			pSrcSeg->nBars -= nDelBar;
		}

		pStyItem->nBars -= nDelBar;
	}

//	g_Opus.CountBars();

	if( bDelWave ){
		for( int i=1; i<g_aAudioTracks.size(); i++ ){
			RemoveWaveBars( i, iStartBarP, iEndBarP - iStartBarP + 1 );
//			RemoveAudioEffects( g_aAudioTracks[i]->lstEffects, iStartBarP, iEndBarP+1 );
		}
	}

	m_pContentPanel->SelectBars( -1, -1 );
}
// ---------------------------------------------------------------------------

void TUseStylePanel::Undo( bool bUndo )
{
	if( m_VolTrackBar ){
		delete m_VolTrackBar;
		m_VolTrackBar = NULL;
	}

	int iMode=-1, iChangeStage = 0;
	TUndoLite* pLite = bUndo ? g_Undo.Undo() : g_Undo.Redo();
	int iType = pLite->iType;

	if( ( iType<UNDO_MIDI_ADD || iType>UNDO_MIDI_FONT )
								&& ( iType<UNDO_TRKMID_ADD || iType>UNDO_TRKMID_DELALL )
								&& VIEW_STYLE!=g_iViewMode )
		Application->MainForm->Perform( UM_SETVIEWMODE, VIEW_STYLE, 0 );

	if( iType!=UNDO_STAGE_VOL )
		Stop();

	if( iType>=UNDO_BAR_INSERT && iType<=UNDO_BAR_CHANGE ){
		if( bUndo && pLite->iCode>0 ){ //处理AddWeakupBar
			m_bAddWeakupBar = true;

			//删除第一小节
			for( int i=1; i<g_aAudioTracks.size(); i++ ){
				TAudioTrack* pAT = g_aAudioTracks[i];

				delete pAT->lstBars[0];
				pAT->lstBars.erase( pAT->lstBars.begin() );
			}

			TOpusStage* pStage = g_lstOpusStages[0];
			delete pStage->aBars[0];
			pStage->aBars.erase( pStage->aBars.begin() );
			g_Opus.CountBars();

			TStyleItem* pStyItem = (TStyleItem*)m_aItems->First();
			TSegmentItem* pSegment = (TSegmentItem*)pStyItem->aItems->Items[0];
			pSegment->nBars--;
			pStyItem->nBars--;
		}

		int iDelStart = pLite->iBegin,
			iDelEnd = pLite->iEnd,
			iInsStart = pLite->iBegin,
			iInsEnd = pLite->iEnd,
			nBars = pLite->iEnd - pLite->iBegin + 1;

		TOpusStageList* lstStages = ( iType>=UNDO_BAR_CHANGE && !bUndo || iType==UNDO_BAR_INSERT )
														? (TOpusStageList*)pLite->pAfter
														: (TOpusStageList*)pLite->pBefore;

		if( iType<UNDO_BAR_CHANGE || pLite->iExt1 )
			f_MM_Undo( bUndo );

		if( iType==UNDO_BAR_INSERT && bUndo
						|| iType==UNDO_BAR_DELETE && !bUndo ){
			iMode = MODE_DELETE;
		}
		else if( iType==UNDO_BAR_INSERT && !bUndo
						|| iType==UNDO_BAR_DELETE && bUndo ){
			iMode = MODE_INSERT;
		}
		else if( iType==UNDO_BAR_MOVE ){
			iMode = MODE_MOVE;

			if( bUndo ){
				iDelStart = pLite->iExt1;
				iDelEnd = iDelStart + nBars - 1;
			}
			else{
				iInsStart = pLite->iExt1;
				iInsEnd = iInsStart + nBars - 1;
			}
		}
		else{
			iMode = MODE_CHANGE;

			if( bUndo  )
				iDelEnd += pLite->iExt1;
			else
				iInsEnd += pLite->iExt1;
		}

		iChangeStage = FindStage( min( iDelStart, iInsStart ), NULL );

		int nMTCount = g_aMidiTracks.size();
		if( iMode==MODE_DELETE || iMode==MODE_MOVE || iMode==MODE_CHANGE ){
			DeleteBars( iDelStart, iDelEnd, iMode==MODE_CHANGE ? false : true );
		}

		if( iMode==MODE_INSERT || iMode==MODE_MOVE || iMode==MODE_CHANGE ){
			//还原波形
			if( iMode==MODE_INSERT || iMode==MODE_MOVE ){
				TAudioTrackList* lstAudio = (TAudioTrackList*)pLite->pExt1;

				for( int i=1; i<g_aAudioTracks.size(); i++ ){
					TAudioTrack* pAudio = lstAudio ? (*lstAudio)[i-1] : NULL;
					InsertAudioTrack( i, iInsStart, nBars, pAudio );
				}
			}

			if( iMode==MODE_CHANGE ){
				if( iInsEnd > iDelEnd ){
					TAudioTrackList* lstAudio = (TAudioTrackList*)pLite->pExt1;
					for( int i=1; i<g_aAudioTracks.size(); i++ ){
						TAudioTrack* pAudio = lstAudio ? (*lstAudio)[i-1] : NULL;
						InsertAudioTrack( i, iDelEnd+1, iInsEnd-iDelEnd, pAudio );
					}
				}
				else if( iInsEnd<iDelEnd ){
					for( int i=1; i<g_aAudioTracks.size(); i++ ){
						RemoveWaveBars( i, iInsEnd+1, iDelEnd-iInsEnd );
					}
				}
			}

			//还原Segment和OpusStage
			int iStage = GetInsertStage( iInsStart );
			if( iStage<0 )
				iStage = 0;

			for( int s=0; s<(*lstStages).size(); s++ ){
				TOpusStage* pStage = DuplicateStage( (*lstStages)[s] );
				g_Opus.InsertStage( iStage, pStage );
				g_Midi.InsertStage( iStage );

				TSegmentItem* pSegment = new TSegmentItem;
				pSegment->iSegType = pStage->iSegType;
				pSegment->iSegNo = pStage->iSegNo;
				pSegment->volume = pStage->nVol;
				pSegment->nBars = pStage->aBars.size();

				DWORD opts = OPT_DEL|OPT_VOL;
				if( pStage->iSegType<SEGTYPE_INTRO )
					opts |= OPT_TEXTURE;

				//检查风格有效性
				for( int i=0; i<pStage->aTracks.size(); i++ ){
					TTrack* pTrack = pStage->aTracks[i];

					TPROSTYLE* pStyle = GetStyleInfo( pTrack->iStyleLoc, pTrack->iStyleId );
					if( pStyle ){
						pSegment->AddTrack( pStyle, pTrack, opts, false );

						TMidiTrack* pMT = g_Midi.GetValidMidiTrack( iStage, pTrack->iFile, pTrack->iChanSpec,
																		pTrack->iBank, pTrack->iProg );
						pTrack->iFile = pMT->file;
						pTrack->iChanSpec = pMT->chno;
					}
					else{
						DebugPrint( "风格文件已失效！\n" );

						delete pTrack;
						pStage->aTracks.erase( pStage->aTracks.begin() + i );
						i--;
					}
				}

				InsertSegment( iStage, pSegment, pStage->aBars.size() );
				delete pSegment;

				iStage++;
			}

			m_pContentPanel->SelectBars( iInsStart, iInsEnd );
		}

		IntegrateStages( iChangeStage, false );

		ResetScrollBar();
		Paint();

		bool bDeletedMT = g_Midi.ClearEmptyTrack()>=0;
		if( m_pContentPanel->IsVertical() && nBars==g_Opus.BarCount() ||
			!m_pContentPanel->IsVertical() && ( bDeletedMT || nMTCount!=g_aMidiTracks.size()) ){
			m_pContentPanel->InitialVars();
		}

//		if( !m_pContentPanel->IsVertical() )
//			GenerateCompose();
	}
	else if( iType==UNDO_TRKMID_DELALL ){
		if( m_pContentPanel->IsVertical() ){
			if( pLite->iCode==ST_MIDI )
				m_pContentPanel->SetScrollMode( false );
		}
		TOpusStageList* lstStages = bUndo ? (TOpusStageList*)pLite->pBefore
										  :	(TOpusStageList*)pLite->pAfter;
		TMidiTrackList *lstTracks = bUndo ? (TMidiTrackList*)pLite->pExt1 : NULL;
		UINT idLoc = bUndo ? pLite->iExt1 : pLite->iExt2,
			idStyle = bUndo ? pLite->iBegin : pLite->iEnd;

		ClearAllItems();
		g_Midi.ClearMidiTracks();

		if( lstTracks ){
			for( int i=0; i<lstTracks->size(); i++ ){
				TMidiTrack* pMT = new TMidiTrack((*lstTracks)[i]);
				g_Midi.AddMidiTrack( pMT );
            }
		}

		g_Opus.Set( idLoc, idStyle, *lstStages );
 		g_Midi.SortMidiTracks();
		g_Opus.BuildStyleItem();
		TStylePanel::SetStyleItem( g_pUseStyle );

		ResetScrollBar();
		Paint();

		if( !m_pContentPanel->IsVertical() ){
			m_pContentPanel->InitialVars();
			GenerateCompose();
		}
		else if( g_iSegColorMode==1 ){
			m_pContentPanel->InvalidateBars( 0, g_Opus.BarCount()-1, BAR_DATA );
		}

		if( g_iPreStage==0 ){
			g_Theme.Set( g_pUseStyle->pStyle->idLoc, g_pUseStyle->pStyle->idStyle,
																		g_lstOpusStages );
		}
	}
	else if( iType>=UNDO_MIDI_ADD && iType<=UNDO_MIDI_FONT || iType==UNDO_TRKMID_ADD || iType==UNDO_TRKMID_DEL ){
		if( m_pContentPanel->IsVertical() ){
			if( pLite->iCode==ST_MIDI )
				m_pContentPanel->SetScrollMode( false );
			else if( VIEW_STYLE!=g_iViewMode )
				Application->MainForm->Perform( UM_SETVIEWMODE, VIEW_STYLE, 0 );
		}
		
		vector<DWORD> *aAddStage = (vector<DWORD>*)( bUndo ? pLite->pExt1 : pLite->pExt2 ),
			  *aDelStage = (vector<DWORD>*)( bUndo ? pLite->pExt2 : pLite->pExt1 );
		TTrack *aAddTrks = bUndo ? (TTrack*)pLite->pBefore : (TTrack*)pLite->pAfter;

		int iSBar = pLite->iBegin,
			iEBar = pLite->iEnd,
			iBStage = iSBar<0 ? 0 : GetInsertStage( iSBar ),
			infoAdd = bUndo ? pLite->iExt1 : pLite->iExt2,
			infoDel = bUndo ? pLite->iExt2 : pLite->iExt1,
			iAddMT = infoAdd==-1 ? -1 : (infoAdd & 0xFF),
			iDelMT = infoDel==-1 ? -1 : (infoDel & 0xFF);
		BYTE iAddMTState = infoAdd==-1 ? 0 : (infoAdd & 0xFF00)>>8,
			iAddMTVol = infoAdd==-1 ? 0 : (infoAdd & 0xFF0000)>>16;
		char iAddMTPan = infoAdd==-1 ? 0 : (infoAdd & 0xFF000000)>>24;

		if( iEBar>=0 )
			GetInsertStage( iEBar+1 );

		TMidiTrack *pDelMT = NULL, *pAddMT = NULL;
		if( iDelMT>=0 && iDelMT<g_aMidiTracks.size() )
			pDelMT = g_aMidiTracks[iDelMT];
		if( iAddMT>=0 && iAddMT<g_aMidiTracks.size() )
			pAddMT = g_aMidiTracks[iAddMT];

		vector<DWORD>::iterator itAdd = aAddStage->begin(),
			itDel = aDelStage->begin();
		int iAddStage(-1), iAddTrack(-1),
			iDelStage(-1), iDelTrack(-1);

		if( itAdd!=aAddStage->end() ){
			int iFBar = (*itAdd) & 0xFFF,
				iLBar = ((*itAdd) & 0xFFF000)>>12;

			iAddTrack = ((*itAdd) & 0xFF000000)>>24;
			iAddStage = GetInsertStage( iFBar );
			GetInsertStage( iLBar+1 );
		}

		if( itDel!=aDelStage->end() ){
			int iFBar = (*itDel) & 0xFFF,
				iLBar = ((*itDel) & 0xFFF000)>>12;

			iDelTrack = ((*itDel) & 0xFF000000)>>24;
			iDelStage = GetInsertStage( iFBar );
			GetInsertStage( iLBar+1 );
		}

		bool bAddedMT = false;
		TStyleItem* pStyItem = (TStyleItem*)m_aItems->First();
		while( itAdd!=aAddStage->end() || itDel!=aDelStage->end() ){
			if( iDelStage>=0 && (iAddStage<0 || iDelStage<iAddStage) ){
				TOpusStage* pStage = g_lstOpusStages[iDelStage];
				TTrack* pTrack = pStage->aTracks[iDelTrack];

				if( !pDelMT || pDelMT->file!=pTrack->iFile || pDelMT->chno!=pTrack->iChanSpec ){
					pDelMT = g_Midi.FindMidiTrack( pTrack->iFile, pTrack->iChanSpec );
				}

				delete pTrack;
				pStage->aTracks.erase( pStage->aTracks.begin()+iDelTrack );

				TSegmentItem* pSegment = (TSegmentItem*)pStyItem->aItems->Items[iDelStage];
				TTrackItem* pTrkItem = (TTrackItem*)pSegment->aItems->Items[iDelTrack];
				TStylePanel::DeleteItem( pTrkItem, -1 );

				pDelMT->DelStage( iDelStage );

				if( ++itDel!=aDelStage->end() ){
					int iFBar = (*itDel) & 0xFFF,
						iLBar = ((*itDel) & 0xFFF000)>>12;

					iDelTrack = ((*itDel) & 0xFF000000)>>24;
					iDelStage = GetInsertStage( iFBar );
					GetInsertStage( iLBar+1 );
				}
				else{
					iDelStage = -1;
					iDelTrack = -1;
				}
			}
			else if( iDelStage>=0 && iDelStage==iAddStage ){
				TOpusStage* pStage = g_lstOpusStages[iDelStage];
				TTrack *pTrack = pStage->aTracks[iDelTrack],
					 *pSubTrack = &aAddTrks[itAdd - aAddStage->begin()];

				if( !pDelMT || pDelMT->file!=pTrack->iFile || pDelMT->chno!=pTrack->iChanSpec ){
					pDelMT = g_Midi.FindMidiTrack( pTrack->iFile, pTrack->iChanSpec );
				}

				if( pSubTrack->iFile!=pDelMT->file || pSubTrack->iChanSpec!=pDelMT->chno ){
					if( !pAddMT || pAddMT->file!=pSubTrack->iFile || pAddMT->chno!=pSubTrack->iChanSpec
																|| pAddMT->prog!=pSubTrack->iProg
								|| !( pAddMT=g_Midi.FindMidiTrack( pSubTrack->iFile, pSubTrack->iChanSpec )) ){
						pAddMT = new TMidiTrack( pSubTrack->iBank, pSubTrack->iChanSpec, pSubTrack->iProg, pSubTrack->iFile );
						pAddMT->state = iAddMTState;
						pAddMT->volume = iAddMTVol;
						pAddMT->pan = iAddMTPan;
						g_Midi.AddMidiTrack( pAddMT, iAddMT );

						bAddedMT = true;
					}

					pDelMT->DelStage( iDelStage );
					pAddMT->AddStage( iAddStage );
				}
				else if( pAddMT==pDelMT && pSubTrack->iProg!=pAddMT->prog ){
					pAddMT->prog = pSubTrack->iProg;
				}

				if( pTrack->iStyleLoc!=pSubTrack->iStyleLoc
								|| pTrack->iStyleId!=pSubTrack->iStyleId ){
					TSegmentItem* pSeg = (TSegmentItem*)pStyItem->aItems->Items[iDelStage];
					TTrackItem* pTrkItem = (TTrackItem*)pSeg->aItems->Items[iDelTrack];
					pTrkItem->pStyle = GetStyleInfo( pSubTrack->iStyleLoc, pSubTrack->iStyleId );
				}

				memcpy( pTrack, pSubTrack, sizeof(TTrack) );

				if( ++itAdd!=aAddStage->end() ){
					int iFBar = (*itAdd) & 0xFFF,
						iLBar = ((*itAdd) & 0xFFF000)>>12;

					iAddTrack = ((*itAdd) & 0xFF000000)>>24;
					iAddStage = GetInsertStage( iFBar );
					GetInsertStage( iLBar+1 );
				}
				else{
					iAddStage = -1,
					iAddTrack = -1;
				}

				if( ++itDel!=aDelStage->end() ){
					int iFBar = (*itDel) & 0xFFF,
						iLBar = ((*itDel) & 0xFFF000)>>12;

					iDelTrack = ((*itDel) & 0xFF000000)>>24;
					iDelStage = GetInsertStage( iFBar );
					GetInsertStage( iLBar+1 );
				}
				else{
					iDelStage = -1;
					iDelTrack = -1;
				}
			}
			else if( iAddStage>=0 && ( iDelStage<0 || iDelStage>iAddStage ) ){
				TTrack* pTrack = new TTrack( &aAddTrks[itAdd - aAddStage->begin()] );

				if( !pAddMT || pAddMT->file!=pTrack->iFile || pAddMT->chno!=pTrack->iChanSpec
							|| !( pAddMT=g_Midi.FindMidiTrack( pTrack->iFile, pTrack->iChanSpec )) ){
					pAddMT = new TMidiTrack( pTrack->iBank, pTrack->iChanSpec, pTrack->iProg, pTrack->iFile );
					pAddMT->state = iAddMTState;
					pAddMT->volume = iAddMTVol;
					pAddMT->pan = iAddMTPan;
					g_Midi.AddMidiTrack( pAddMT, iAddMT );

					bAddedMT = true;
				}

				TOpusStage* pStage = g_lstOpusStages[iAddStage];
				TSegmentItem* pSeg = (TSegmentItem*)pStyItem->aItems->Items[iAddStage];

				pStage->aTracks.insert( pStage->aTracks.begin()+iAddTrack, pTrack );
				AddTrack( pSeg, pTrack, iAddTrack );
				pAddMT->AddStage( iAddStage );

				if( ++itAdd!=aAddStage->end() ){
					int iFBar = (*itAdd) & 0xFFF,
						iLBar = ((*itAdd) & 0xFFF000)>>12;

					iAddTrack = ((*itAdd) & 0xFF000000)>>24;
					iAddStage = GetInsertStage( iFBar );
					GetInsertStage( iLBar+1 );
				}
				else{
					iAddStage = -1,
					iAddTrack = -1;
				}
			}
		}

		IntegrateStages( iBStage, false );

		ResetScrollBar();
		Paint();

		bool bDeletedMT = g_Midi.ClearEmptyTrack()>=0;
		if( !m_pContentPanel->IsVertical() ){
			if( bDeletedMT || bAddedMT ){
				m_pContentPanel->InitialVars();
			}
			else{
				if( iDelMT>=0 ){
					int iST = m_pContentPanel->GetShowTrackId( ST_MIDI, iDelMT );
					if( iST>0 )
						m_pContentPanel->InvalidateBars( iSBar, iEBar, BAR_TRACK | iST );
				}
			}

			if( iAddMT>=0 && !aAddStage->empty() || iDelMT>=0 && !bDeletedMT ){
				if( VIEW_TRACK!=g_iViewMode )
					Application->MainForm->Perform( UM_SETVIEWMODE, VIEW_TRACK, 0 );

				if( iAddMT==iDelMT )
					m_pContentPanel->SelectTrack( -1, -1, -1, false );

				int iMT = iAddMT>=0 && !aAddStage->empty() ? iAddMT : iDelMT,
					iST = m_pContentPanel->GetShowTrackId( ST_MIDI, iMT );

				if( iST>0 ){
					m_pContentPanel->SelectTrack( iST-1, -1, -1, false );
					m_pContentPanel->SetSelectRange( iSBar, 0, iEBar, POINTS_PER_BAR-1, true );
				}
			}

			GenerateCompose();
		}

		if( g_iSegColorMode==1 && iType!=UNDO_MIDI_FONT )
			m_pContentPanel->InvalidateBars( iSBar, iEBar, BAR_DATA );

	}
	else if( iType==UNDO_OPUS_STYLE ){ //全曲风格替换
		iMode = MODE_INIT;

		TAudioTrackList* lstAudio = (TAudioTrackList*)pLite->pExt1;
		TOpusStageList* lstStages = (TOpusStageList*)( bUndo ? pLite->pBefore
															: pLite->pAfter );
		if( lstAudio ){
			f_MM_Undo( bUndo );
		}

		g_Audio.RestoreAudio( lstStages, lstAudio, bUndo );

		g_Opus.Set( pLite->iBegin, pLite->iEnd, *lstStages );
		g_Opus.BuildStyleItem();
		g_Midi.ClearMidiTracks();

		SetStyleItem( g_pUseStyle );

		if( g_iPreStage==0 ){
			g_Theme.Set( g_pUseStyle->pStyle->idLoc, g_pUseStyle->pStyle->idStyle,
																		g_lstOpusStages );
		}
	}
	else if( iType==UNDO_STAGE_VOL || iType==UNDO_PROG_VOL ){
		int iStage = GetInsertStage( pLite->iBegin ),
			nStageLen = pLite->iEnd - pLite->iBegin;

		TStyleItem* pStyItem = (TStyleItem*)m_aItems->First();
		TSegmentItem* pTempSeg = (TSegmentItem*)pStyItem->aItems->Items[iStage];

		if( pTempSeg->iSegType<SEGTYPE_FILL && pTempSeg->nBars>nStageLen )
			GetInsertStage( pLite->iEnd );

		TSegmentItem* pSegItem = (TSegmentItem*)pStyItem->aItems->Items[iStage];

		int iSet = (int)(bUndo ? pLite->pBefore : pLite->pAfter ),
			iOther = (int)(!bUndo ? pLite->pBefore : pLite->pAfter );

		TCommonItem* pSetItem = NULL;

		if( iType==UNDO_STAGE_VOL ){
			SetSelectStage( iStage );
			pSetItem = pSegItem;
		}
		else{
			TTrack* pExt = (TTrack*)pLite->pExt1;

			for( int i=0; i<pSegItem->aItems->Count; i++ ){
				TTrackItem* pTrkItem = (TTrackItem*)pSegItem->aItems->Items[i];
				TTrack* pTrack = pTrkItem->pTrack;

				if( pTrack->iStyleLoc==pExt->iStyleLoc && pTrack->iStyleId==pExt->iStyleId
										&& pTrack->iSegNo==pExt->iSegNo && pTrack->iBank==pExt->iBank
										&& pTrack->iProg==pExt->iProg && pTrack->nVol==iOther ){
					pSetItem = pTrkItem;
					SetSelectTrack( pTrkItem );
					break;
				}
			}
		}

		ChangeVolume( iStage, pSetItem, iSet, false );

		if( iSet>=0 && iOther<0 || iSet<0 && iOther>=0 ){ //静音操作
			DrawItem( m_pSelItem, m_iSelLine, COL_FOLD );
		}
		else{
			DrawItem( m_pSelItem, m_iSelLine, COL_TEXT );
			DoAdjustVolume( NULL );
		}
	}

	if( iMode>=0 )
		m_pContentPanel->OnStageChanged( iChangeStage, iMode );
}
// ---------------------------------------------------------------------------

void TUseStylePanel::SetSelectTrack(  TTrackItem* pTrack )
{
	TStyleItem* pStyle = (TStyleItem*)m_aItems->Items[0];
	TSegmentItem* pSeg = (TSegmentItem*)pTrack->up;

	if( !pStyle->IsUnfold() ){
		SetFold( pStyle, 0 );
	}

	TCommonItem* pItem = GetNextItem( pStyle );
	int iLine = 1;
	while( pItem!=pSeg ){
		pItem = GetNextItem( pItem );
		iLine++;
	}

	if( !pSeg->IsUnfold() ){
		SetFold( pSeg, iLine );
	}

	while( pItem!=pTrack ){
		pItem = GetNextItem( pItem );
		iLine++;
	}

	SetSelect( pTrack, iLine - m_iTopLine );

	ShowSelItem();
}
// ---------------------------------------------------------------------------

bool __fastcall TUseStylePanel::GetPrebeat( BYTE* pData, int& nSize )
{
	if( m_aItems->Count==0 )
		return false;

	TStyleItem* pStyItem = (TStyleItem*)m_aItems->Items[0];
	TTrack* pDrumTrk = NULL;

	for( int i=pStyItem->aItems->Count-1; !pDrumTrk && i>=0; i-- ){
		TSegmentItem* pSeg = (TSegmentItem*)pStyItem->aItems->Items[i];
		int stype = pSeg->GetSegType();

		if( stype!=SEGTYPE_ENDING ){
			for( int j=0; j<pSeg->aItems->Count; j++ ){
				TTrack* pTrk = ((TTrackItem*)pSeg->aItems->Items[j])->pTrack;

				if( pTrk->iChanNo==9 ){
					pDrumTrk = pTrk;
					break;
				}
			}
		}
	}

	if( pDrumTrk ){
		int nStageNum = 1;
		TStage* aStages = new TStage[nStageNum];
		aStages[0].iSegType = SEGTYPE_VAR;
		aStages[0].iSegKey = 0;
		aStages[0].nBarNum = 4;
		aStages[0].aChords = new TBarChords[aStages[0].nBarNum];
		for( int j=0; j<4; j++ ){
			aStages[0].aChords[j].iKey[0]
					= aStages[0].aChords[j].iKey[1]
					= aStages[0].aChords[j].iKey[2]
					= aStages[0].aChords[j].iKey[3] = 0;
			aStages[0].aChords[j].iType[0]
					= aStages[0].aChords[j].iType[1]
					= aStages[0].aChords[j].iType[2]
					= aStages[0].aChords[j].iType[3] = 0;
		}

		//tracks
		aStages[0].nTrkNum = 1;
		aStages[0].aTracks = new TComposeTrack[aStages[0].nTrkNum];
		aStages[0].aTracks[0].iStyleLoc = pDrumTrk->iStyleLoc;
		aStages[0].aTracks[0].iStyleId = pDrumTrk->iStyleId;
		aStages[0].aTracks[0].iSegNo = pDrumTrk->iSegNo;
		aStages[0].aTracks[0].iChanNo = pDrumTrk->iChanNo;
		aStages[0].aTracks[0].iChanSpec = pDrumTrk->iChanSpec;
		aStages[0].aTracks[0].iProg = pDrumTrk->iProg;
		aStages[0].aTracks[0].nVol = 110;

		int ret = f_CM_Compose( &nSize, pData, g_iMelodyTimeSignature, g_nMelodyTempo,
										nStageNum, aStages, false, NULL, NULL );

		if( ret==0 ){
			return true;
		}
	}

	return false;
}
// ---------------------------------------------------------------------------

 void TUseStylePanel::SetBarsUndo( int iMode, int iStartBar, int nBars, int iMoveTo )
{
	int iEndBar = iStartBar + nBars - 1;

	TOpusStageList* lstStages = new TOpusStageList;
	TAudioTrackList* lstAudio = new TAudioTrackList;

	CopyUndoBars( iStartBar, iEndBar, lstStages, lstAudio );

	void *pBefore = iMode==UNDO_BAR_INSERT ? NULL : (void*)lstStages,
		*pAfter = iMode==UNDO_BAR_INSERT ? (void*)lstStages : NULL;

	g_Undo.AddUndo( iMode, 0, iStartBar, iEndBar, pBefore, pAfter );

	if( iMode==UNDO_BAR_MOVE && iMoveTo > iStartBar )
		iMoveTo -= nBars;

	g_Undo.SetUndoExtra( iMoveTo, 0, 0, (void*)lstAudio, NULL );
}
//---------------------------------------------------------------------------


