// ShitarabianPlugInTest.cpp: CShitarabianDllImp クラスのインプリメンテーション
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
//#include "shitarabian.h"
#include "resource.h"
#include "ShitarabianDllImp.h"
#include "SettingDlg.h"
#include "DocumentIF.h"
#include "Common.h"

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

const int	iROIMode = 3;
const int	iNormalMode = 0;



//////////////////////////////////////////////////////////////////////
// 構築/消滅
//////////////////////////////////////////////////////////////////////

CShitarabianDllImp::CShitarabianDllImp()
	: m_bRecording( FALSE )
	, m_atKeyCommandz()
{

}

CShitarabianDllImp::~CShitarabianDllImp()
{
	RemoveAll();
}

const char* CShitarabianDllImp::GetPlugInName()
{
	return( "キーマクロ ver1.1" );
}



void CShitarabianDllImp::OnSetting(
	CDocumentIF*	pDocIF
)
{
	CSettingDlg		dlg;
	if ( dlg.DoModal() == IDOK )
	{
		if ( dlg.m_bEnable )
		{
			pDocIF->EntryToolBar( IDR_DLLTOOLBAR );
			pDocIF->ShowToolBar( TRUE );
		}
		else
		{
			pDocIF->ShowToolBar( FALSE );
		}
	}
}



void CShitarabianDllImp::OnToolButton(
	CDocumentIF*	pDocIF,
	int				idxButton
)
{
	switch( idxButton )
	{
	case 0:		// 記録
		RemoveAll();
		m_bRecording = TRUE;
		TRACE( "記録開始\n" );
		break;

	case 1:		// 停止
		m_bRecording = FALSE;
		TRACE( "記録停止\n" );
		break;

	case 2:		// セパレータ
		break;

	case 3:		// 再生
		TRACE( "再生開始\n" );
		{
			POSITION	pos = m_atKeyCommandz.GetHeadPosition();
			while( pos != NULL )
			{
				TKeyCommand& tCommand = m_atKeyCommandz.GetNext( pos );

				// なんらかの方法でキー入力を投げる
				switch( tCommand.eType )
				{
				case KeyCommandDown:
					pDocIF->KeyDown(
						tCommand.strChar,
						tCommand.bShift,
						tCommand.bCtrl,
						tCommand.bAlt
					);
					break;

				case KeyCommandInput:
					pDocIF->KeyInput(
						tCommand.strChar,
						tCommand.bShift,
						tCommand.bCtrl,
						tCommand.bAlt
					);
					break;

				default:
					break;
				}
			}
		}
		pDocIF->ScrollToCaret();
		pDocIF->ReDraw();
		break;

	case 4:		// セパレータ
		break;

	case 5:		// 読み込み
		Load();
		break;

	case 6:		// 書き込み
		Save();
		break;

	default:
		ASSERT( FALSE );
		break;
	}
}




void CShitarabianDllImp::OnToolButtonUI(
	CDocumentIF*	pDocIF,
	int				idxButton,
	CCmdUI*			pCmdUI
)
{
	BOOL	bEditMode = FALSE;
	{
		int		iMode = iNormalMode;
		pDocIF->GetSelectMode( &iMode );
		bEditMode = ( iMode == iNormalMode );
	}

	// 停止
	m_bRecording &= bEditMode;

	switch( idxButton )
	{
	case 0:		// 記録
	case 5:		// 読み込み
		pCmdUI->Enable( (!m_bRecording) && bEditMode );
		break;

	case 1:		// 停止
		pCmdUI->Enable( m_bRecording && bEditMode );
		break;

	case 3:		// 再生
	case 6:		// 書き出し
		pCmdUI->Enable( (!m_bRecording)&&(m_atKeyCommandz.GetCount()>0) );
		break;

	default:
		return;
		break;
	}
}

// キーが押されたときのハンドラ
void CShitarabianDllImp::OnKeyDown(
	CDocumentIF*	pDocIF,
	UCHAR*			punKey,
	BOOL*			pbShift,
	BOOL*			pbCtrl,
	BOOL*			pbAlt
)
{
	BOOL	bEditMode = FALSE;
	{
		int		iMode = iNormalMode;
		pDocIF->GetSelectMode( &iMode );
		bEditMode = ( iMode == iNormalMode );
	}

	if ( bEditMode )
	if ( m_bRecording )
	{
		TKeyCommand	tCommand;
		{
			tCommand.eType = KeyCommandDown;
			tCommand.strChar = CString( (*punKey) );
			tCommand.bShift = *pbShift;
			tCommand.bCtrl = *pbCtrl;
			tCommand.bAlt = *pbAlt;
		}
		m_atKeyCommandz.AddTail( tCommand );
	}
//	TRACE( "KEY = x%02X (%c)\n", *punKey, *punKey );
}

// キーが押されたときのハンドラ
void CShitarabianDllImp::OnChar(
	CDocumentIF*	pDocIF,
	CString*		pstrChar,
	BOOL*			pbShift,
	BOOL*			pbCtrl,
	BOOL*			pbAlt
)
{
	BOOL	bEditMode = FALSE;
	{
		int		iMode = iNormalMode;
		pDocIF->GetSelectMode( &iMode );
		bEditMode = ( iMode == iNormalMode );
	}

	if ( bEditMode )
	if ( m_bRecording )
	{
		TKeyCommand	tCommand;
		{
			tCommand.eType = KeyCommandInput;
			tCommand.strChar = CString( *pstrChar );
			tCommand.bShift = *pbShift;
			tCommand.bCtrl = *pbCtrl;
			tCommand.bAlt = *pbAlt;
		}
		m_atKeyCommandz.AddTail( tCommand );
	}
//	TRACE( "char = (%s)\n", *pstrChar );
}


void CShitarabianDllImp::RemoveAll()
{
	m_atKeyCommandz.RemoveAll();
}







void CShitarabianDllImp::Save()
{
	CFileDialog		dlgFile(
		FALSE,			// ← TRUEなら『開く』、FALSEなら、『名前を付けて保存』となる
		"txt",			// ← デフォルトのファイル拡張子(NULLならなし)
		NULL,			// ← 初期表示されるファイル名(NULLならなし)
		OFN_FILEMUSTEXIST|OFN_HIDEREADONLY,
		"TXT|*.txt|"	// ← ファイルの拡張子の種類
	);
	if ( dlgFile.DoModal() == IDOK )
	{
		CString		strFileName = dlgFile.GetPathName();
		CStdioFile	File( strFileName, CFile::modeCreate|CFile::modeWrite );

		POSITION	pos = m_atKeyCommandz.GetHeadPosition();
		while( pos != NULL )
		{
			TKeyCommand& tCommand = m_atKeyCommandz.GetNext( pos );
			CString		strCommand;

			if( !tCommand.strChar.IsEmpty() )
			switch( tCommand.eType )
			{
			case KeyCommandDown:
				strCommand.Format(
					"keydown= %s, %s, %s, %d\n",
					::BoolToString( tCommand.bShift ),
					::BoolToString( tCommand.bCtrl ),
					::BoolToString( tCommand.bAlt ),
					tCommand.strChar[0]
				);
				break;

			case KeyCommandInput:
				strCommand.Format(
					"keyinput= %s, %s, %s, %s\n",
					::BoolToString( tCommand.bShift ),
					::BoolToString( tCommand.bCtrl ),
					::BoolToString( tCommand.bAlt ),
					::QuoteString( tCommand.strChar )
				);
				break;

			default:
				break;
			}
			File.WriteString( strCommand );
		}
	}
}



#define KEYDOWN_KEY "keydown="
#define KEYINPUT_KEY "keyinput="

void CShitarabianDllImp::Load()
{
	CFileDialog		dlgFile(
		TRUE,			// ← TRUEなら『開く』、FALSEなら、『名前を付けて保存』となる
		"txt",			// ← デフォルトのファイル拡張子(NULLならなし)
		NULL,			// ← 初期表示されるファイル名(NULLならなし)
		OFN_FILEMUSTEXIST|OFN_HIDEREADONLY,
		"TXT|*.txt|"	// ← ファイルの拡張子の種類
	);
	if ( dlgFile.DoModal() == IDOK )
	{
		m_atKeyCommandz.RemoveAll();
		CString		strFileName( dlgFile.GetPathName() );

		try
		{
			CStdioFile	File( strFileName, CFile::modeRead | CFile::shareDenyNone );

			while( TRUE )
			{
				CString		strLine;
				BOOL	bExists = File.ReadString( strLine );
				if( !bExists )
				{
					break;
				}

				TKeyCommand		tCommand;
				// まず、コマンド種類を判別。
				tCommand.eType = KeyCommandUnknown;
				{
					int		iKeyLength;
					iKeyLength = strlen( KEYDOWN_KEY );
					if ( strLine.Left(iKeyLength) == KEYDOWN_KEY )
					{
						tCommand.eType = KeyCommandDown;
						strLine = strLine.Mid(iKeyLength);
					}
					iKeyLength = strlen( KEYINPUT_KEY );
					if ( strLine.Left(iKeyLength) == KEYINPUT_KEY )
					{
						tCommand.eType = KeyCommandInput;
						strLine = strLine.Mid(iKeyLength);
					}
				}

				// BOOL値を三つ取得
				int		iSeparator;
				iSeparator = strLine.Find( ',' );
				tCommand.bShift = ::StringToBool( strLine.Left( iSeparator ) );
				strLine = strLine.Mid( iSeparator+1 );

				iSeparator = strLine.Find( ',' );
				tCommand.bCtrl = ::StringToBool( strLine.Left( iSeparator ) );
				strLine = strLine.Mid( iSeparator+1 );

				iSeparator = strLine.Find( ',' );
				tCommand.bAlt = ::StringToBool( strLine.Left( iSeparator ) );
				strLine = strLine.Mid( iSeparator+1 );

				// 文字列の取得
				switch( tCommand.eType )
				{
				case KeyCommandDown:
					tCommand.strChar = (char)::StringToLong( strLine );
					break;
				case KeyCommandInput:
					tCommand.strChar = ::DeQuoteString( strLine );
					break;
				default:
					break;
				}

				m_atKeyCommandz.AddTail( tCommand );
			}
		}
		catch( CFileException* e )
		{
			e->Delete();
			ASSERT( FALSE );
		}
	}
}
