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

#include "GlobalUnit.h"
#include "StyleItem.h"
#include "FavorTextureUnit.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)

TPngImage *u_imgFold = NULL,
		*u_imgUnfold = NULL,
		*u_imgTrackOn = NULL,
		*u_imgTrackOff = NULL,
		*u_imgDelete = NULL,
		*u_imgDownload = NULL,
		*u_imgDownloading = NULL,
		*u_imgProg = NULL,
		*u_imgTexture = NULL,
		*u_imgVolume = NULL,
		*u_imgBrush = NULL,
		*u_imgCollect = NULL,
		*u_imgUnCollect = NULL,
		*u_imgScore = NULL,
		*u_imgSave = NULL,
		*u_imgImport = NULL,
		*u_imgUpload = NULL,
		*u_imgCharge = NULL;

COLORREF clrTextStyle = RGB(201, 214, 229), //Style文字
			clrTextHot = RGB( 225, 236, 255 ),	//高亮文字
			clrTextDirty = RGB( 226, 232, 187 ),
			clrTextDisable = RGB( 126, 131, 137 ),	//未下载文字
			clrTextLoading	= RGB( 105, 197, 235 ),	//正在下载
			clrBackground = RGB(47, 50, 57), //面板背景
			clrFocback = RGB( 67, 73, 80 ), //焦点背景
			clrSelback = RGB( 29, 31, 35 ); //选中背景

TStyleItem *g_pPreStyle = NULL,
		   *g_pUseStyle = NULL;

/////////////////////////////////////////////////////////////////////////////
// TCommonItem
__fastcall TCommonItem::TCommonItem()
{
	iType = 0;
	dwState = 0;
	iFocusCol = 0;

	aOptions = new System::Classes::TList();
	aItems = new System::Classes::TList();
	prev = next = up = NULL;
}

__fastcall TCommonItem::TCommonItem( char type, DWORD opts )
{
	iType = type;
	dwState = 0;
	iFocusCol = 0;

	aOptions = new System::Classes::TList();
	aItems = new System::Classes::TList();
	prev = next = up = NULL;

	if( opts!=0 ){
		for( int i=0; i<OPT_NUM; i++ ){
			if( opts & (1<<i) )
				aOptions->Add( (void*)(1<<i) );
		}
	}
}

__fastcall TCommonItem::~TCommonItem()
{
	ClearSubItems();

	delete aOptions;
	delete aItems;
}

void TCommonItem::ClearSubItems()
{
	for( int i=0; i<aItems->Count; i++ ){
		delete aItems->Items[i];
	}

	aItems->Clear();
}

void TCommonItem::RemoveSubItem( TCommonItem* pSub )
{
	if( pSub->prev )
		pSub->prev->next = pSub->next;
	if( pSub->next )
		pSub->next->prev = pSub->prev;

	aItems->Remove( pSub );
	delete pSub;
}

short __fastcall TCommonItem::GetColume( int X )
{
	return 0;
}

bool TCommonItem::IsUnfold()
{
	return dwState & STATE_UNFOLD;
}

bool TCommonItem::IsSelected()
{
	return dwState & STATE_SELECTED;
}
/*
void __fastcall TCommonItem::SetCollect( bool bSet )
{
	if( bSet )
		dwState |= STATE_COLLECTED;
	else
		dwState &= ~STATE_COLLECTED;
}
*/
void __fastcall TCommonItem::SetFocus( WORD iCol )
{
	iFocusCol = iCol;
}

void __fastcall TCommonItem::SetUnfold( bool bSet )
{
	if( bSet )
		dwState |= STATE_UNFOLD;
	else
		dwState &= ~STATE_UNFOLD;
}

void __fastcall TCommonItem::Select( bool bSet )
{
	if( bSet )
		dwState |= STATE_SELECTED;
	else
		dwState &= ~STATE_SELECTED;
}

void __fastcall TCommonItem::SetHover( bool bSet )
{
	if( bSet )
		dwState |= STATE_HOVER;
	else
		dwState &= ~STATE_HOVER;
}

DWORD TCommonItem::GetOption( int iCol )
{
	for( int i=0; i<OPT_COL_NUM; i++ ){
		if( iCol==(COL_OPT<<i) && aOptions->Count>i ){
			return (DWORD)aOptions->Items[i];
		}
	}

	return 0;
}

int TCommonItem::GetOnlineState()
{
	TStyleItem* pStyItem = GetStyleItem();

	if( pStyItem && pStyItem->pStyle ){
		if( pStyItem->pStyle->idLoc==0 )
			return pStyItem->pStyle->pOrigin->state;
		else if( pStyItem->pStyle->idLoc==1 ){
			if( iType==SEGTYPE_STYLE ){
				int iStyDlState = e_Downloaded;
				for( int i=0; i<aItems->Count; i++ ){
					TSegmentItem* pSeg = (TSegmentItem*)aItems->Items[i];
					int iState = pSeg->GetOnlineState();
					if( iState==e_UnDownload )
						return e_UnDownload;
					else if( iState==e_Downloading )
						iStyDlState = iState;
				}

				return iStyDlState;
			}
			else if( iType==SEGTYPE_TRACK ){
				TTrackItem* pTrk = (TTrackItem*)this;
				if( pTrk->pStyle->idLoc==0 )
					return pTrk->pStyle->pOrigin->state;
				else
					return e_Downloaded;
			}
			else{
				int iSegDlState = e_Downloaded;
				for( int i=0; i<aItems->Count; i++ ){
					TTrackItem* pTrk = (TTrackItem*)aItems->Items[i];
					int iState = pTrk->GetOnlineState();
					if( iState==e_UnDownload )
						return e_UnDownload;
					else if( iState==e_Downloading )
						iSegDlState = iState;
				}

				return iSegDlState;
			}
		}
	}

	return e_Downloaded;
}

TStyleItem* TCommonItem::GetStyleItem()
{
	if( iType==SEGTYPE_STYLE ){
		return (TStyleItem*)this;
	}
	else if( iType==SEGTYPE_TRACK ){
		return (TStyleItem*)up->up;
	}
	else{
		return (TStyleItem*)up;
	}
}

void TCommonItem::SetOnlineState( int iState )
{
	TStyleItem* pStyItem = GetStyleItem();

	if( pStyItem && pStyItem->pStyle ){
		if( pStyItem->pStyle->idLoc==0 )
			pStyItem->pStyle->pOrigin->state = iState;
		else if( pStyItem->pStyle->idLoc==1 && iType==SEGTYPE_TRACK ){
			TTrackItem* pTrk = (TTrackItem*)this;
			if( pTrk->pStyle->idLoc==0 )
				pTrk->pStyle->pOrigin->state = iState;
		}
	}
}

COLORREF TCommonItem::TextColor()
{
	return clrTextStyle;
}

void __fastcall TCommonItem::DrawItem( TCanvas* Canvas, TRect Rect, WORD iCol )
{
	int X, Y;

	if( iType!=SEGTYPE_STYLE ){
		Rect.Left += OPTION_WIDTH;

		if( iType==SEGTYPE_TRACK ){
			Rect.Left += OPTION_WIDTH;
		}
	}

	Canvas->Brush->Color = clrBackground;

	if( iCol==WORD(-1) ){
		//刷新左边
		TRect rtFresh( 0, Rect.Top, Rect.Left+OPTION_WIDTH, Rect.Bottom );
		Canvas->FillRect( rtFresh );
	}

	if( dwState & STATE_SELECTED ) //绘制选中背景
		Canvas->Brush->Color = clrSelback;
	else if( dwState & STATE_HOVER || iFocusCol>COL_FOLD )
		Canvas->Brush->Color = clrFocback;

	if( iCol & COL_FOLD ){
		TPngImage *pImg = NULL;
		if( aItems->Count>0 ){ //输出fold
			pImg = (dwState & STATE_UNFOLD) ? u_imgUnfold : u_imgFold;
		}
		else if( iType==SEGTYPE_TRACK ){ //输出mute
			pImg = IsMute() ? u_imgTrackOff : u_imgTrackOn;
		}

		if( pImg ){
			RECT rt;
			GetClipBox( Canvas->Handle, &rt );

			int w = pImg->Width/2,
				h = pImg->Height,
				l = ( iFocusCol==COL_FOLD ) ? w : 0;

			X = Rect.Left + (OPTION_WIDTH - w)/2;
			Y = Rect.Top + ( OPTION_HEIGHT - h) / 2;

			int x = X-rt.left,
				y = Y-rt.top,
				b = y+h;
			if( b > Rect.Bottom - rt.top )
				b = Rect.Bottom - rt.top;

			HRGN rgnClip = CreateRectRgn( x, y, x+w, b );

			SelectClipRgn( Canvas->Handle, rgnClip );
			Canvas->Draw( X-l, Y, pImg );
			SelectClipRgn( Canvas->Handle, NULL );
			DeleteObject(rgnClip);
		}
	}

	int iOnline = GetOnlineState();

	if( iCol >= COL_TEXT ){
		//输出文字
		if( iFocusCol>=COL_TEXT ){
			Canvas->Font->Color = clrTextHot;
		}
		else if( iOnline==e_UnDownload ){
			Canvas->Font->Color = clrTextDisable;
		}
		else if( iOnline==e_Downloading ){
			if( iType==SEGTYPE_STYLE )
				Canvas->Font->Color = clrTextLoading;
			else
				Canvas->Font->Color = clrTextDisable;
		}
		else{
			Canvas->Font->Color = TextColor();
		}

		String strText = GetCaption();

		Rect.Left += OPTION_WIDTH;
		Y = Rect.Top + ( OPTION_HEIGHT - Canvas->TextHeight(strText) )/2;

		//----处理字符过长------
		int nWidth = Rect.Width() - 4 - 8;
		if( iFocusCol > COL_FOLD || dwState & STATE_SELECTED )
			nWidth -= aOptions->Count*OPTION_WIDTH + 2;

		if( Canvas->TextWidth( strText )>nWidth ){
			UnicodeString strShorty = strText;
			while( Canvas->TextWidth( strShorty )>nWidth ){
					strShorty = strShorty.SubString( 1, strShorty.Length()-2 );
			}

			strText = strShorty;
			strText+="...";
		}
		//-----------
		Canvas->Brush->Style = bsSolid;
		Canvas->TextRect( Rect, Rect.Left+4, Y, strText );
	}

	for( int i=0; i<aOptions->Count; i++ ){
		DWORD iOpt = (DWORD)aOptions->Items[i];
		TPngImage* pImg = NULL;

		if( iOpt==OPT_DEL ){
			pImg = u_imgDelete;
		}
		else if( iOpt==OPT_DOWNLOAD ){
			if( iOnline==e_Downloading )
				pImg = u_imgDownloading;
			else
				pImg = u_imgDownload;
		}
		else if( iOpt==OPT_BRUSH )
			pImg = u_imgBrush;
		else if( iOpt==OPT_TEXTURE )
			pImg = u_imgTexture;
		else if( iOpt==OPT_FONTPROG )
			pImg = u_imgProg;
		else if( iOpt==OPT_VOL )
			pImg = u_imgVolume;
		else if( iOpt==OPT_COLLECT ){
			if( IsCollected() )
				pImg = u_imgCollect;
			else
				pImg = u_imgUnCollect;
		}
		else if( iOpt==OPT_SCORE )
			pImg = u_imgScore;
		else if( iOpt==OPT_SAVE )
			pImg = u_imgSave;
		else if( iOpt==OPT_IMPORT )
			pImg = u_imgImport;
		else if( iOpt==OPT_UPLOAD )
			pImg = u_imgUpload;
		else if( iOpt==OPT_CHARGE )
			pImg = u_imgCharge;

		if( iFocusCol>COL_FOLD  || (dwState & STATE_SELECTED) ){
			Rect.Right -= OPTION_WIDTH;

			if( pImg ){
				RECT rt;
				GetClipBox( Canvas->Handle, &rt );

				int w = pImg->Width/3,
					h = pImg->Height,
					l = ( iFocusCol==(1<<(i+2)) ) ? w : 0;

				X = Rect.Right + (OPTION_WIDTH - w)/2;
				Y = Rect.Top + ( OPTION_HEIGHT - h) / 2;

				int x = X-rt.left,
					y = Y-rt.top,
					b = y+h;
				if( b > Rect.Bottom - rt.top )
					b = Rect.Bottom - rt.top;

				HRGN rgnClip = CreateRectRgn( x, y, x+w, b );

				SelectClipRgn( Canvas->Handle, rgnClip );
				Canvas->Draw( X-l, Y, pImg );
				SelectClipRgn( Canvas->Handle, NULL );
				DeleteObject(rgnClip);
			}
		}
	}
}

/////////////////////////////////////////////////////////////////////////////
// TTrackItem
__fastcall TTrackItem::TTrackItem()
	: TCommonItem(SEGTYPE_TRACK, 0 )
{
	bOwnTrack = false;
	pTrack = NULL;
}

__fastcall TTrackItem::TTrackItem( TCommonItem* pUpItem, TPROSTYLE* info,
												char stype, char sno, char ch,
												char prog, char vol, DWORD opts )
	: TCommonItem( SEGTYPE_TRACK, opts )
{
	pStyle = info;
	up = pUpItem;
}

__fastcall TTrackItem::TTrackItem( TCommonItem* pUpItem, TPROSTYLE* info, TTrack* pTrk,
																DWORD opts, bool bOwn )
	: TCommonItem( SEGTYPE_TRACK, opts )
{
	up = pUpItem;
	pStyle = info;
	bOwnTrack = bOwn;
	pTrack = pTrk;
}

__fastcall TTrackItem::~TTrackItem()
{
	if( bOwnTrack && pTrack )
		delete pTrack;
}

void TTrackItem::SetMute( bool bSet )
{
	if( pTrack ){
		if( bSet )
			pTrack->nVol |= 0x80;
		else
			pTrack->nVol &= ~0x80;
	}
}

bool TTrackItem::IsCollected()
{
	return IsFavorTexture( pStyle->idLoc, pStyle->idStyle, GetSegType(),
									pTrack->iSegNo, pTrack->iChanNo );
}

void TTrackItem::StyleId2Str( String& strText )
{
	char strNo[20];
	if( pStyle->idLoc==0 ){
		sprintf( strNo, "[%d] ",  pStyle->idStyle );
	}
	else if( pStyle->idLoc==1 ){
		sprintf( strNo, "[S%d] ",  pStyle->idStyle );
	}
	else if( pStyle->idLoc==(UINT)-1 ){
		sprintf( strNo, "[T%d] ",  LOWORD(pStyle->idStyle) );
	}
	else{
		sprintf( strNo, "[L%d] ",  LOWORD(pStyle->idStyle) );
	}

	strText += strNo;
}

char TTrackItem::GetSegType()
{
	return ((TSegmentItem*)up)->iSegType;
}

char TTrackItem::GetSegNo()
{
	if( pTrack )
		return pTrack->iSegNo;
}

bool TTrackItem::IsMute()
{
	return pTrack ? pTrack->nVol < 0 : false;
}

void TTrackItem::AddStyleId( String& strText )
{
	TStyleItem* pStyItem = GetStyleItem();

	if( pStyItem->pStyle!=pStyle ){
		strText += " ";

		StyleId2Str( strText );
	}
}

String TTrackItem::GetCaption()
{
	String strText;

	if( pTrack->iBank!=0xFF || pTrack->iProg!=pTrack->iProgOrig
						|| (pTrack->nVolOrig & 0x7F) != (pTrack->nVol & 0x7F) ){
		strText += "* ";
	}

	if( (pTrack->iBank==0xFF || pTrack->iBank<0x80) && pTrack->iChanNo==9 )
		strText += "GM鼓";
	else
		strText += GetProgName( pTrack->iBank, pTrack->iChanNo, pTrack->iProg );

	AddStyleId( strText );

	return strText;
}

COLORREF TTrackItem::TextColor()
{
	if( pTrack->iBank!=0xFF ){
		return clrTextDirty;
	}

	return GetSegmentColor( GetSegType(), 0, false );
}

String TTrackItem::HintText()
{
	String strText = "织体：";

	StyleId2Str( strText );

	char strType_No[8];
	sprintf( strType_No, "%s - %d", NAME_SEG[GetSegType()], pTrack->iSegNo+1 );
	strText += strType_No;

	strText += "\n\n音源：";

	int iFont = pTrack->iBank==0xFF && !g_bExtFont ? g_idFont: pTrack->iBank;
	if( iFont==0xFF ){
		strText += "扩展音色库";
	}
	else if( iFont<0x80 ){
		FONTINFO* pFI = g_lstFonts[iFont];

		strText += pFI->strFontName;
	}
	else{
		VSTINFO* pFI = g_lstVSTi[iFont-0x80];
		strText += pFI->strVSTName;
	}

	strText += "\n";

	if( pTrack->iProg!=pTrack->iProgOrig )
		strText += "当前";
	strText += "乐器：";

	strText += GetProgName( pTrack->iBank, pTrack->iChanNo, pTrack->iProg );

	if( pTrack->iProg!=pTrack->iProgOrig ){
		strText += "\n原始乐器：";
		strText += GetProgName( 0xFF, pTrack->iChanNo, pTrack->iProgOrig );
	}
	strText += "\n\n";

	if( pTrack->nVol!=pTrack->nVolOrig )
		strText += "当前";
	strText += "音量：";

	if( pTrack->nVol<0 )
		strText += "静音";
	else
		strText += IntToStr( pTrack->nVol );

	if( pTrack->nVol!=pTrack->nVolOrig ){
		strText += "\n原始音量：";
		strText += IntToStr( pTrack->nVolOrig );
	}

	return strText;
}

/////////////////////////////////////////////////////////////////////////////
// TSegmentItem
__fastcall TSegmentItem::TSegmentItem()
	: TCommonItem(SEGTYPE_SEGMENT, 0)
{
	iSegType = 0;
	iSegNo = 0;
	iInd = 0;
	volume = 0;
	nBars = 0;
	bAutoSpec = false;
	memset( aChanUsed, 0, sizeof(aChanUsed) );
}

__fastcall TSegmentItem::TSegmentItem( TCommonItem* pUpItem, char stype, char sno, DWORD opts,
												int bars, char ind, char vol, bool bSpec )
	: TCommonItem( SEGTYPE_SEGMENT, opts )
{
	up = pUpItem;
	iSegType = stype;
	iSegNo = sno;
	iInd = ind;
	volume = vol;
	nBars = bars;
	bAutoSpec = bSpec;
	memset( aChanUsed, 0, sizeof(aChanUsed) );
}

void TSegmentItem::ClearSubItems()
{
	TCommonItem::ClearSubItems();
	memset( aChanUsed, 0, sizeof(aChanUsed) );
}

TTrackItem* __fastcall TSegmentItem::AddTrack( TPROSTYLE* info, TTrack* pTrack, DWORD opts, bool bOwn, int iInd )
{
	if( !info && !(info = GetStyleInfo( pTrack->iStyleLoc, pTrack->iStyleId )))
		return NULL;

	TTrackItem *pItem = NULL;

	if( iInd>=0 ){
		pItem = new TTrackItem( this, info, pTrack, opts, bOwn );
		if( iSegType==SEGTYPE_VAR || iSegType==SEGTYPE_FILL )
			pItem->aOptions->Add((void*)OPT_BRUSH);

		if( aItems->Count==0 ){
        	aItems->Add( pItem );
		}
		else if( iInd<aItems->Count ){
			TCommonItem *pNext = (TCommonItem*)aItems->Items[iInd];
			if( pNext->prev )
				pNext->prev->next = pItem;
			pItem->prev = pNext->prev;
			pNext->prev = pItem;
			pItem->next = pNext;

			aItems->Insert( iInd, pItem );
		}
		else{
			TCommonItem *pLast = (TCommonItem*)aItems->Last();
			pLast->next = pItem;
			pItem->prev = pLast;

			aItems->Add( pItem );
		}
	}
	else{
		for( int i=0; i<aItems->Count; i++ ){
			TTrackItem* pTmp = (TTrackItem*)aItems->Items[i];

			if( pTrack->iChanNo==9 && pTmp->pTrack->iChanNo==9 ){
				pItem = pTmp;
				break;
			}
		}

		if( pItem ){
			pItem->pStyle = info;
			pTrack->iBank = pItem->pTrack->iBank;
			pTrack->iChanSpec = pItem->pTrack->iChanSpec;
			pTrack->iFile = pItem->pTrack->iFile;

			if( bOwn )
				delete pItem->pTrack;
			pItem->pTrack = pTrack;
		}
		else{
			pItem = new TTrackItem( this, info, pTrack, opts, bOwn );
			if( iSegType==SEGTYPE_VAR || iSegType==SEGTYPE_FILL )
				pItem->aOptions->Add((void*)OPT_BRUSH);

			char ch = pTrack->iChanNo,
				chSpec = pTrack->iChanSpec;
			if( ch==9 ){
				aChanUsed[9] = true;
			}
			else if( bAutoSpec ){
				if( !aChanUsed[chSpec] ){
					aChanUsed[chSpec] = true;
				}
				else if( ch!=9 ){
					for( int i=0; i<16; i++ ){
						if( !aChanUsed[i] ){
							pTrack->iChanSpec = i;
							aChanUsed[i] = true;
							break;
						}
					}
				}
			}

			bool bInserted = false;
			if( aItems->Count>0 ){
				if( ch==9 ){ //只能一个打击乐轨，且总在第一个
					TTrackItem *pFirst = (TTrackItem*)aItems->First();
					pItem->next = pFirst;
					pFirst->prev = pItem;

					aItems->Insert( 0, pItem );
					bInserted = true;
				}
				else{
					TCommonItem *pLast = (TCommonItem*)aItems->Last();

					pLast->next = pItem;
					pItem->prev = pLast;
				}
			}

			if( !bInserted )
				aItems->Add( pItem );
		}
	}

	return  pItem;
}

TTrackItem* __fastcall TSegmentItem::AddTrack( TPROSTYLE* info, char sno, char ch,
													char prog, char vol, DWORD opts )
{
	TTrack* pTrack = new TTrack;
	pTrack->iStyleLoc = info->idLoc;
	pTrack->iStyleId = info->idStyle;
	pTrack->iSegNo = sno;
	pTrack->iChanNo = pTrack->iChanSpec = ch;
	pTrack->iProg = pTrack->iProgOrig = prog;
	pTrack->nVol = pTrack->nVolOrig = vol;

	return AddTrack( info, pTrack, opts, true );
}

TTrackItem* __fastcall TSegmentItem::AddTrack( TPROSTYLE* info, char sn, char tn,
															DWORD opts, bool bAddLocal )
{
	TTrackItem *pItem = NULL;
	char st = iSegType;

	if( info->idLoc==0 ){
		TSTYLEORIGIN* pOrigin = info->pOrigin;
		if( pOrigin->detail.tracks[st][sn][tn].no>=0 ){

			pItem = AddTrack( info, sn,
							pOrigin->detail.tracks[st][sn][tn].no,
							pOrigin->detail.tracks[st][sn][tn].prog,
							pOrigin->detail.tracks[st][sn][tn].vol,
							opts );
		}
	}
	else if( info->idLoc==1 ){
		TSTYLESHARE* pShare = info->pShare;
		TSHARETRACKREF& trkRef = pShare->trkRef[st][sn][tn];
		UINT idStyle = trkRef.idStyle;

		TPROSTYLE* pTrkInfo = NULL;

		if( idStyle>0 )
			pTrkInfo = GetStyleInfo( 0, idStyle );

		if( pTrkInfo ){
			int osn = trkRef.segNo;
			char chan = trkRef.chan,
				prog = trkRef.prog,
				vol = trkRef.vol;// & 0x7F;

			if( pTrkInfo!=info ){
				for( int t=0; t<16; t++ ){
					if( pTrkInfo->pOrigin->detail.tracks[st][osn][t].no==chan ){
						prog = pTrkInfo->pOrigin->detail.tracks[st][osn][t].prog;
						vol = pTrkInfo->pOrigin->detail.tracks[st][osn][t].vol;
						break;
					}
				}
			}

			pItem = AddTrack( pTrkInfo, osn, chan, prog, vol, opts );
			pItem->pTrack->iProg = trkRef.prog;
			pItem->pTrack->nVol = trkRef.vol;
		}
	}
	else{
		TSTYLELOCAL* pLocal = info->pLocal;
		TTRACKREF& trkRef = pLocal->trkRef[st][sn][tn];
		UINT idLoc = trkRef.idLoc,
			idStyle = trkRef.idStyle;

		TPROSTYLE* pTrkInfo = NULL;
		if( idStyle>0 && ( bAddLocal || idLoc==0 ) ){
			pTrkInfo = GetStyleInfo( idLoc, idStyle );
		}

		if( pTrkInfo ){
			int osn = trkRef.segNo;
			char chan = trkRef.chan,
				prog = trkRef.prog,
				vol = trkRef.vol;// & 0x7F;

			if( pTrkInfo!=info ){
				for( int t=0; t<16; t++ ){
					if( pTrkInfo->idLoc==0 ){
						if( pTrkInfo->pOrigin->detail.tracks[st][osn][t].no==chan ){
							prog = pTrkInfo->pOrigin->detail.tracks[st][osn][t].prog;
							vol = pTrkInfo->pOrigin->detail.tracks[st][osn][t].vol;
							break;
						}
					}
					else{
						int nSegNum = info->pLocal->nSegNum[st];
						int iStart = ( st<SEGTYPE_INTRO || sn<4 ) ? 0 : 4,
							iEnd = iStart + ( iStart==0 ? ( nSegNum & 0x0F ) : ( nSegNum>>4 ));

						bool bFind = false;
						for( int i=iStart; !bFind && i<iEnd; i++ ){
							for( int j=0; j<16; j++ ){
								if( pTrkInfo->pLocal->trkRef[st][i][j].idLoc==idLoc
											&& pTrkInfo->pLocal->trkRef[st][i][j].idStyle==idStyle
											&& pTrkInfo->pLocal->trkRef[st][i][j].segNo==osn
											&& pTrkInfo->pLocal->trkRef[st][i][j].chan==chan ){
									prog = pTrkInfo->pLocal->trkRef[st][i][j].prog;
									vol = pTrkInfo->pLocal->trkRef[st][i][j].vol;

									bFind = true;
									break;
								}
								else if( pTrkInfo->pLocal->trkRef[st][i][j].idLoc==0
											&& pTrkInfo->pLocal->trkRef[st][i][j].idStyle==0 ){
									break;
								}
							}
						}
					}
				}
			}

			pItem = AddTrack( pTrkInfo, osn, chan, prog, vol, opts );
			pItem->pTrack->iProg = trkRef.prog;
			pItem->pTrack->nVol = trkRef.vol;
		}
	}

	return pItem;
}
/*
TTrackItem* __fastcall TSegmentItem::AddTrack( TPROSTYLE* info, char st, char sn, char tn,
														DWORD opts, bool bAddLocal )
{
	TTrackItem *pItem = NULL;

	if( info->idLoc==0 ){
		TSTYLEORIGIN* pOrigin = info->pOrigin;
		if( pOrigin->detail.tracks[st][sn][tn].no>=0 ){
			pItem = AddTrack( info, st, sn,
							pOrigin->detail.tracks[st][sn][tn].no,
							pOrigin->detail.tracks[st][sn][tn].no,
							pOrigin->detail.tracks[st][sn][tn].prog,
							pOrigin->detail.tracks[st][sn][tn].vol,
							opts );
		}
	}
	else if( info->idLoc==1 ){
		TSTYLESHARE* pShare = info->pShare;
		TSHARETRACKREF& trkRef = pShare->trkRef[st][sn][tn];
		UINT idStyle = trkRef.idStyle;

		TPROSTYLE* pTrkInfo = NULL;

		if( idStyle>0 )
			pTrkInfo = GetStyleInfo( 0, idStyle );

		if( pTrkInfo ){
			int osn = trkRef.segNo;
			char chan = trkRef.chan,
				prog = trkRef.prog,
				vol = trkRef.vol;// & 0x7F;

			if( pTrkInfo!=info ){
				for( int t=0; t<16; t++ ){
					if( pTrkInfo->pOrigin->detail.tracks[st][osn][t].no==chan ){
						prog = pTrkInfo->pOrigin->detail.tracks[st][osn][t].prog;
						vol = pTrkInfo->pOrigin->detail.tracks[st][osn][t].vol;
						break;
					}
				}
			}

			pItem = AddTrack( pTrkInfo, st, osn, chan, chan, prog, vol, opts );
			pItem->progCurr = trkRef.prog;
			pItem->volCurr = trkRef.vol;
		}
	}
	else{
		TSTYLELOCAL* pLocal = info->pLocal;
		TTRACKREF& trkRef = pLocal->trkRef[st][sn][tn];
		UINT idLoc = trkRef.idLoc,
			idStyle = trkRef.idStyle;

		TPROSTYLE* pTrkInfo = NULL;
		if( idStyle>0 && ( bAddLocal || idLoc==0 ) ){
			pTrkInfo = GetStyleInfo( idLoc, idStyle );
		}

		if( pTrkInfo ){
			int osn = trkRef.segNo;
			char chan = trkRef.chan,
				prog = trkRef.prog,
				vol = trkRef.vol;// & 0x7F;

			if( pTrkInfo!=info ){
				for( int t=0; t<16; t++ ){
					if( pTrkInfo->idLoc==0 ){
						if( pTrkInfo->pOrigin->detail.tracks[st][osn][t].no==chan ){
							prog = pTrkInfo->pOrigin->detail.tracks[st][osn][t].prog;
							vol = pTrkInfo->pOrigin->detail.tracks[st][osn][t].vol;
							break;
						}
					}
					else{
						int nSegNum = info->pLocal->nSegNum[st];
						int iStart = ( st<SEGTYPE_INTRO || sn<4 ) ? 0 : 4,
							iEnd = iStart + ( iStart==0 ? ( nSegNum & 0x0F ) : ( nSegNum>>4 ));

						bool bFind = false;
						for( int i=iStart; !bFind && i<iEnd; i++ ){
							for( int j=0; j<16; j++ ){
								if( pTrkInfo->pLocal->trkRef[st][i][j].idLoc==idLoc
											&& pTrkInfo->pLocal->trkRef[st][i][j].idStyle==idStyle
											&& pTrkInfo->pLocal->trkRef[st][i][j].segNo==osn
											&& pTrkInfo->pLocal->trkRef[st][i][j].chan==chan ){
									prog = pTrkInfo->pLocal->trkRef[st][i][j].prog;
									vol = pTrkInfo->pLocal->trkRef[st][i][j].vol;

									bFind = true;
									break;
								}
								else if( pTrkInfo->pLocal->trkRef[st][i][j].idLoc==0
											&& pTrkInfo->pLocal->trkRef[st][i][j].idStyle==0 ){
									break;
								}
							}
						}
					}
				}
			}

			pItem = AddTrack( pTrkInfo, st, osn, chan, chan, prog, vol, opts );
			pItem->progCurr = trkRef.prog;
			pItem->volCurr = trkRef.vol;
		}
	}

	return pItem;
}
*/
void TSegmentItem::DeleteTrack( TCommonItem* pItem )
{
	if( ((TTrackItem*)pItem)->pTrack->iChanNo==9 )
		aChanUsed[9] = false;
	else if( bAutoSpec )
		aChanUsed[((TTrackItem*)pItem)->pTrack->iChanSpec] = false;

	aItems->Remove( pItem );
	delete pItem;
}

char TSegmentItem::GetIndType()
{
	char type = iSegType;

	if( ((TStyleItem*)up)->nBars>0 && type==SEGTYPE_FILL )
		type = SEGTYPE_VAR;

	return type;
}

String TSegmentItem::GetCaption()
{
	String strText;

	if( ((TStyleItem*)up)->nBars>0 ){
		if( iSegType<=SEGTYPE_FILL ){
			strText += "旋律";
			strText += String("-") + (int)(iInd+1);
			strText += " ";
			strText += g_strSegment[iSegType];
		}
		else{
			if( iSegType==SEGTYPE_INTRO ){
				int index = iInd;
				if( ((TCommonItem*)up->aItems->First())->GetSegType()!=SEGTYPE_INTRO )
					index++;

				if( index==0 ){
					strText += "前奏";
				}
				else{
					strText += "间奏";
					strText += String("-") + index;
				}
			}
			else{
				strText += "尾奏";
			}
		}
	}
	else{
		strText += g_strSegment[iSegType];
		strText += String("-") + (int)(iInd+1);
	}

	if( iSegType>=SEGTYPE_INTRO ){
		if( iSegNo<4 )
			strText += " 大调" ;
		else
			strText += " 小调" ;
	}

	if( nBars>0 ){
		char strNum[20];
		sprintf( strNum, " (%d小节)", nBars );
		strText += strNum;
	}

	return strText;
}

COLORREF TSegmentItem::TextColor()
{
	int ty = GetSegType(),
		iNo = g_iSegColorMode==0 ? GetSegNo() : aItems->Count;
	bool bInc = g_iSegColorMode==0 ? true
						: iNo>0 && ((TTrackItem*)aItems->Items[0])->pTrack->iChanNo==9;

	return GetSegmentColor( ty, iNo, bInc );
}

/////////////////////////////////////////////////////////////////////////////
// TStyleItem
__fastcall TStyleItem::TStyleItem()
	: TCommonItem(SEGTYPE_STYLE, 0)
{
	pStyle = NULL;
	nBars = 0;
//	nVarNum = nFillNum = nIntroMajNum = nIntroMinNum = nEndingMajNum = nEndingMinNum = 0;
	memset( nSegNum, 0, sizeof(int)*4 );
}

__fastcall TStyleItem::TStyleItem( TPROSTYLE* info, DWORD opts )
	: TCommonItem( SEGTYPE_STYLE, opts )
{
	pStyle = info;
	nBars = 0;
	memset( nSegNum, 0, sizeof(int)*4 );
//	idLoc = info->idLoc;
//	idStyle = info->idStyle;
}

bool TStyleItem::IsCollected()
{
	return IsCollectedStyle( pStyle->idLoc, pStyle->idStyle );
}

TSegmentItem* __fastcall TStyleItem::AddSegment( char stype, char sno, DWORD opts,
													int bars, char ind, char vol, bool bAutoSpec )
{
	int index = ind;
	if( ind<0 )
		index = sno;//nSegNum[stype];

	TSegmentItem *pItem = new TSegmentItem( this, stype, sno, opts, bars, index, vol, bAutoSpec );

	bool bInserted = false;
	if( aItems->Count>0 ){
		if( ind<0 ){
			ind = 0;
			for( int i=0; i<=stype; i++ ){
				ind += nSegNum[i];
			}
		}

		if( bars==0 && ind>=0 && aItems->Count>ind ){
			TCommonItem *pNext = (TCommonItem*)aItems->Items[ind];

			if( pNext->prev ){
				pItem->prev = pNext->prev;
				pNext->prev->next = pItem;
			}

			pItem->next = pNext;
			pNext->prev = pItem;

			aItems->Insert( ind, pItem );
			bInserted = true;
		}
		else{
			TCommonItem* pLast = (TCommonItem*)aItems->Last();
			pLast->next = pItem;
			pItem->prev = pLast;
		}
	}

	if( !bInserted ){
		aItems->Add( pItem );
	}

	nSegNum[stype]++;
	nBars += bars;

	return pItem;
}

void TStyleItem::InsertSegment( int ind, TSegmentItem* pItem, int bars )
{
	if( ind<0 || ind > aItems->Count )
		ind = aItems->Count;

	if( aItems->Count > ind ){
		TCommonItem *pNext = (TCommonItem*)aItems->Items[ind];

		if( pNext->prev ){
			pItem->prev = pNext->prev;
			pNext->prev->next = pItem;
		}

		pItem->next = pNext;
		pNext->prev = pItem;

		aItems->Insert( ind, pItem );
	}
	else{
		if( aItems->Count>0 ){
			TCommonItem* pLast = (TCommonItem*)aItems->Last();
			pLast->next = pItem;
			pItem->prev = pLast;
		}
		aItems->Add( pItem );
	}

//	pItem->iInd = ind;

	nSegNum[pItem->iSegType]++;
	nBars += bars;
}

void TStyleItem::DeleteSegment( TCommonItem* pSeg )
{
	nSegNum[pSeg->GetSegType()]--;

	if( pSeg->next ){
		int stype = ((TSegmentItem*)pSeg)->GetIndType();
		TSegmentItem* pNext = (TSegmentItem*)pSeg->next;
		while( pNext ){
			if( pNext->GetIndType()==stype )
				pNext->iInd--;

			pNext = (TSegmentItem*)pNext->next;
		}
	}

	aItems->Remove( pSeg );
	delete pSeg;
}

void TStyleItem::SetDownload()
{
	if( pStyle ){
		if( pStyle->idLoc==0 ){
//			pStyle->pOrigin->state = e_Downloaded;
			for( int i=0; i<aOptions->Count; i++ ){
				DWORD iOpt = (DWORD)aOptions->Items[i];
				if( iOpt==OPT_DOWNLOAD ){
					aOptions->Items[i] = (void*)OPT_COLLECT;
					break;
				}
			}
		}
		else if( pStyle->idLoc==1 ){
			bool bFull = true;
			for( int i=0; i<aItems->Count; i++ ){
				TSegmentItem* pSeg = (TSegmentItem*)aItems->Items[i];
				for( int j=0; j<pSeg->aItems->Count; j++ ){
					TTrackItem* pTrk = (TTrackItem*)pSeg->aItems->Items[j];
					if( pTrk->pStyle->idLoc==0 && pTrk->pStyle->pOrigin->state!=e_Downloaded ){
						bFull = false;
						break;
					}
				}

				if( !bFull )
					break;
			}

			if( bFull ){
				for( int i=0; i<aOptions->Count; i++ ){
					DWORD iOpt = (DWORD)aOptions->Items[i];
					if( iOpt==OPT_DOWNLOAD ){
						aOptions->Items[i] = (void*)OPT_COLLECT;
						break;
					}
				}
			}
		}
	}
}

void TStyleItem::SetImport()
{
	bool bSet = false;
	for( int i=0; i<4; i++ ){
		if( nSegNum[i]<8 ){
			bSet = true;
			break;
		}
	}

	int iImport = -1;
	for( int i=0; i<aOptions->Count; i++ ){
		DWORD iOpt = (DWORD)aOptions->Items[i];
		if( iOpt==OPT_IMPORT ){
			iImport = i;
			break;
		}
	}

	if( iImport<0 && bSet ){
		aOptions->Add((void*)OPT_IMPORT);
	}
	else if( iImport>=0 && !bSet ){
		aOptions->Delete( iImport );
	}
}

void TStyleItem::SetCharge( bool bSet )
{
	int iCharge = -1;
	for( int i=0; i<aOptions->Count; i++ ){
		DWORD iOpt = (DWORD)aOptions->Items[i];
		if( iOpt==OPT_CHARGE ){
			iCharge = i;
			break;
		}
	}

	if( iCharge<0 && bSet ){
		aOptions->Add((void*)OPT_CHARGE);
	}
	else if( iCharge>=0 && !bSet ){
		aOptions->Delete( iCharge );
	}
}

void TStyleItem::AddStyleId( String& strText )
{
	char strNo[20] = "";

	if( pStyle ){
		if( pStyle->idLoc==0 ){
			if( pStyle->idStyle>0 ){
				sprintf( strNo, "[%d] ", pStyle->idStyle );
			}
			else{
				strNo[0] = '\0';
			}
		}
		else if( pStyle->idLoc==1 ){
			sprintf( strNo, "[S%d] ", pStyle->idStyle );
		}
		else if( pStyle->idLoc!=(UINT)-1 ){
			sprintf( strNo, "[L%d] ", LOWORD(pStyle->idStyle) );
		}
	}

	strText += strNo;
}

String TStyleItem::GetCaption()
{
	String strText;

	AddStyleId( strText );

	if( pStyle ){
		if( pStyle->idLoc==0 )
			strText += UTF8ToMBCS(pStyle->pOrigin->detail.strStyleName).c_str();
		else if( pStyle->idLoc==1 )
			strText += UTF8ToMBCS(pStyle->pShare->strStyleName).c_str();
		else if( pStyle->idLoc!=(UINT)-1 )
			strText += UTF8ToMBCS(pStyle->pLocal->strStyleName).c_str();
		else
			strText += "未知风格";
	}
	else{
		if( this==g_pPreStyle )
			strText += "新建自定义风格";
		else if( this==g_pUseStyle )
			strText += "无";
	}

	if( nBars>0 ){
		char strNum[20];
		sprintf( strNum, " (%d段 %d小节)", aItems->Count, nBars );
		strText += strNum;
	}

	return strText;
}

String TStyleItem::HintText()
{
	String HintStr;

	if( !pStyle ){
		HintStr = "新建自定义风格\n";
	}
	else if( pStyle->idLoc==0 ){
		TSTYLEORIGIN* pOrig = pStyle->pOrigin;
		HintStr = "发布风格\n\n";
		HintStr += "名称：";
		HintStr += UTF8ToMBCS(pOrig->detail.strStyleName).c_str();

		HintStr += "\n作者：";
		HintStr += UTF8ToMBCS(pOrig->detail.strAuthor).c_str();

		HintStr += "\n简介：";
		HintStr += UTF8ToMBCS(pOrig->detail.strDescription).c_str();

		HintStr += "\n类型：";
		String strType;
		for( int i=0; i<4; i++ ){
			int type = pOrig->detail.type[i];

			if( type<0 )
				break;
			else{
				if( type<24 ){
					strType += (String)LSZ_STYLTYPES[type] + " ";
				}
			}
		}
		if (strType == L"") {
			strType = L"未知类型";
		}
		HintStr += strType;

		char buf[20];
		HintStr += "\n原速：";
		sprintf( buf, "%d", pOrig->detail.iTempo );
		HintStr += buf;

		HintStr += "\n价格：";
		if( pOrig->cost==0 )
			strcpy( buf, "免费" );
		else
			sprintf(buf, "%d个唱作音符", pOrig->cost);
		HintStr += buf;

		int score10 =  (int)(pOrig->score/10.0 + 0.5);
		sprintf( buf, "%.1f", score10 / 10.0 );

		HintStr += "\n评分：";
		HintStr += buf;

		HintStr += "\n状态：";
		if( pOrig->state==e_UnDownload )
			HintStr += "未下载";
		else if( pOrig->state==e_Downloading )
			HintStr += "正在下载";
		else
			HintStr += "已下载";
	}
	else if( pStyle->idLoc==1 ){
		TSTYLESHARE* pShare = pStyle->pShare;
		HintStr = "分享风格\n\n";
		HintStr += "名称：";
		HintStr += UTF8ToMBCS(pShare->strStyleName).c_str();

		HintStr += "\n作者：";
		HintStr += UTF8ToMBCS(pShare->strAuthor).c_str();

		HintStr += "\n简介：";
		HintStr += UTF8ToMBCS(pShare->strDescription).c_str();

		HintStr += "\n类型：";
		String strType;
		for( int i=0; i<2; i++ ){
			int type = pShare->type[i];

			if( type<0 )
				break;
			else{
				if( type<24 ){
					strType += (String)LSZ_STYLTYPES[type] + " ";
				}
			}
		}
		if (strType == L"") {
			strType = L"未知类型";
		}
		HintStr += strType;

		char buf[20];
		HintStr += "\n原速：";
		sprintf( buf, "%d", pShare->iTempo );
		HintStr += buf;

		int score10 =  (int)(pShare->score/10.0 + 0.5);
		sprintf( buf, "%.1f", score10 / 10.0 );

		HintStr += "\n评分：";
		HintStr += buf;
	}
	else if( pStyle->pLocal ){
		TSTYLELOCAL* pLocal = pStyle->pLocal;
		HintStr = "本地风格\n\n";
		HintStr += "名称：";
		HintStr += UTF8ToMBCS(pLocal->strStyleName).c_str();

		char buf[20];
		HintStr += "\n原速：";
		sprintf( buf, "%d", pLocal->iTempo );
		HintStr += buf;
	}

	return HintStr;
}
/////////////////////////////////////////////////////////////////////////

String GetProgName( BYTE iBank, BYTE iChan, BYTE iProg )
{
	String strText;

	if( iBank!=0xFF && iBank>=0x80 ){
		VSTINFO* pVst = g_lstVSTi[iBank-0x80];

		bool bSet = false;
		for( int i=0; i<pVst->aPlugins.size(); i++ ){
			if( iChan==pVst->aPlugins[i]->id ){
				return pVst->aPlugins[i]->name;
			}
		}

		if( !bSet ){
			strText += "ch " + IntToStr( iChan+1 ) + ": ";
			strText += pVst->strVSTName;
		}
	}
	else{
		FONTINFO* pFI = NULL;
		if( iBank==0xFF ){
			if( g_bExtFont ){
				if(iChan==9)
					pFI = g_lstCZFonts[16];
				else
					pFI = g_lstCZFonts[iProg/16];
			}
			else
				pFI = g_lstFonts[g_idFont];
		}
		else
			pFI = g_lstFonts[iBank];

		int num = iChan==9 ? pFI->nDrumCount : pFI->nInstCount;
		FONTPRESET* pSet = ( iChan==9 ? pFI->aDrums : pFI->aInsts );
		char** strInst = NULL;

		if( iChan==9 ){
			for( int i=0; i<num; i++) {
				if( pSet[i].id==iProg ){
					return pSet[i].text;
				}
			}
		}
		else{
			if( iBank==0xFF || g_bExtFontUsable && iBank<16
							|| !strcmp( pFI->strFontName, g_strDefaultSoundSet )
							|| !strcmp( pFI->strFontName, "Pop default" ) )
				strInst = GM_INSTRUMENT;

			if( strInst )
				return strInst[iProg];
			else{
				for( int i=0; i<num; i++ ){
					if( pSet[i].id==iProg ){
						return pSet[i].text;
					}
				}
			}
		}
	}

	return strText;
}
