#include "stdafx.h"
#include "resource.h"
#include "FWatchApp.hpp"
#include "SettingDlg.hpp"
#include "Utility.hpp"

#include <Commdlg.h>
#include <shlwapi.h>
#pragma comment(lib, "shlwapi.lib")

#include <assert.h>

#include <shlobj.h>

#include <string>
#include <vector>



tstring WindowUtility::getWindowText(HWND v_hWnd) const throw()
{
	//required:
	assert(v_hWnd != NULL && "v_hWndにNULLは指定できません。");

	//do:
	const int len = ::GetWindowTextLength(v_hWnd);
	if (len > 0) {
		std::vector<tstring::value_type> buffer(len + 1);
		::GetWindowText(v_hWnd, &buffer[0], len + 1);
		return tstring(&buffer[0]);
	}
	return _T("");
}

void WindowUtility::setWindowText(HWND v_hWnd, const tstring& v_text) const throw()
{
	//required:
	assert(v_hWnd != NULL && "v_hWndにNULLは指定できません。");

	//do:
	::SetWindowText(v_hWnd, v_text.c_str());
}

//////////////

CSettingDlg::CSettingDlg( const CSettingInfo& v_settingInfo )
	: hDlg_( NULL )
	, settingInfo_( v_settingInfo )
	, factory_( v_settingInfo )
	, errorOccured_( false )
{
}

CSettingDlg::~CSettingDlg()
{
}

bool CSettingDlg::show(HWND hWnd)
{
	return DialogBoxParam(
		app.getInstanceHandle(),
		(LPCTSTR) IDD_SELDIRDLG,
		hWnd,
		(DLGPROC) DlgProc,
		(LPARAM) this
		) == IDOK;
}

/*!
 * ファクトリからパラメータの設定に過ちがあるたびにエラーが通知されます。
 * 戻り値としてfalseを指定するとパラメータは設定されません。
 * trueを指定すると、回復できる場合は回復させてパラメータを設定させます。
 * ただし、パラメータの回復ができない場合はfalseと同じです。
 * \param v_errorInfo エラー情報
 * \return 回復させる場合はtrueを指定します。
 */
bool CSettingDlg::notifyErrorInfo(const tstring& v_errorInfo) throw()
{
	const tstring errorCaption = app.LoadString(IDS_ERROR_SETTING);
	errorOccured_ = true;
	::MessageBox(hDlg_, v_errorInfo.c_str(), errorCaption.c_str(), MB_ICONERROR | MB_OK);
	return false;
}

CSettingInfo CSettingDlg::createSettingInfo() const
{
	try{
		return factory_.create();
	}
	catch (const CSettingInfoFactory::CSettingInfoFactoryException&) {
		assert(false && "パラメータの構築に失敗しました。showメソッドが正常終了させずに呼び出した可能性があります。");
		throw;
	}
}

void CSettingDlg::OnInitDialog()
{
	hDir  = GetDlgItem(hDlg_, IDC_WATCHDIR);
	assert(hDir != NULL && "監視ディレクトリのウィンドウハンドルが取得できません。");
	SHAutoComplete(hDir, SHACF_FILESYS_DIRS);

	hName = GetDlgItem(hDlg_, IDC_FILETYPE);
	assert(hName != NULL && "監視ファイルのウィンドウハンドルが取得できません。");

	hVerb = GetDlgItem(hDlg_, IDC_ACTION);
	assert(hVerb != NULL && "アクションのウィンドウハンドルが取得できません。");

	hApp  = GetDlgItem(hDlg_, IDC_APPNAME);
	assert(hApp != NULL && "アプリケーションのウィンドウハンドルが取得できません。");
	SHAutoComplete(hApp, SHACF_FILESYSTEM);

	hParam= GetDlgItem(hDlg_, IDC_PARAM);
	assert(hParam != NULL && "起動パラメータのウィンドウハンドルが取得できません。");

	SendMessage(hParam, EM_SETWORDBREAKPROC, 0, (LPARAM) NoWordwrapProc);

	hShowWindow = GetDlgItem(hDlg_, IDC_WINDOWSIZE);
	assert(hShowWindow != NULL && "ウィンドウサイズのウィンドウハンドルが取得できません。");

	hWaitWrite = GetDlgItem(hDlg_, IDC_WAITWRITABLE);
	assert(hWaitWrite != NULL && "サイズが落ち着くまで待つのウィンドウハンドルが取得できません。");

	hTolerance = GetDlgItem(hDlg_, IDC_TOLERANCE);
	assert(hTolerance != NULL && "ファイルを同一とみなす時間のウィンドウハンドルが取得できません。");

	hDeletePending = GetDlgItem(hDlg_, IDC_DELETEPENDING);
	assert(hDeletePending != NULL && "削除まち時間のウィンドウハンドルが取得できません。");

	hLog = GetDlgItem(hDlg_, IDC_LOGFILE);
	assert(hLog != NULL && "ログのウィンドウハンドルが取得できません。");
	SHAutoComplete(hLog, SHACF_FILESYSTEM);

	hMaxProcess = GetDlgItem(hDlg_, IDC_MAXPROCESS);
	assert(hMaxProcess != NULL && "最大プロセス数のウィンドウハンドルが取得できません。");

	hMaxDepth = GetDlgItem(hDlg_, IDC_MAXDEPTH);
	assert(hMaxDepth != NULL && "フォルダの最大深さのウィンドウハンドルが取得できません。");

	hDirNotificationAPIRetrySpan = GetDlgItem(hDlg_, IDC_DIRNOTIFICATIONAPIRETRYSPAN);
	assert(hDirNotificationAPIRetrySpan != NULL && "監視APIのリトライ間隔のウィンドウハンドルが取得できません。");

	hDirNotificationAPIExpirySpan = GetDlgItem(hDlg_, IDC_DIRNOTIFICATIONAPIRETRYEXPIRYSPAN);
	assert(hDirNotificationAPIExpirySpan != NULL && "監視APIの有効期間のウィンドウハンドルが取得できません。");

	hForceInterval = GetDlgItem(hDlg_, IDC_FORCEINTERVAL);
	assert(hForceInterval != NULL && "定期フォルダ監視間隔のウィンドウハンドルが取得できません。");

	hAppCurrentDir = GetDlgItem(hDlg_, IDC_CURDIR);
	assert(hAppCurrentDir != NULL && "カレントディレクトリのウィンドウハンドルが取得できません。");
	SHAutoComplete(hAppCurrentDir, SHACF_FILESYS_DIRS);

	hLogLevel = GetDlgItem(hDlg_, IDC_LOGLEVEL);
	assert(hLogLevel != NULL && "ログレベルのウィンドウハンドルが取得できません。");

	hPersist = GetDlgItem(hDlg_, IDC_PERSIST);
	assert(hPersist && "永続化のウィンドウハンドルが取得できません。");
	SHAutoComplete(hPersist, SHACF_FILESYSTEM);


	hArchiveOnly = GetDlgItem(hDlg_, IDC_ARCHIVEONLY);
	assert(hArchiveOnly && "アーカイブ属性のみのウィンドウハンドルが取得できません。");

	hWatchDelay = GetDlgItem(hDlg_, IDC_WATCHDELAY);
	assert(hWatchDelay && "通知をまとめるのウィンドウハンドルが取得できません。");

	hNotifyOnStart = GetDlgItem(hDlg_, IDC_NOTIFYONSTART);
	assert(hNotifyOnStart && "開始時点で通知するのウィンドウハンドルが取得できません。");


	hIgnoreDuplicate = GetDlgItem(hDlg_, IDC_IGNORE_DUPLICATE);
	assert(hIgnoreDuplicate && "同一ファイルの多重起動禁止のウィンドウハンドルが取得できません。");

	
	hImpersonate = GetDlgItem(hDlg_, IDC_IMPERSONATE);
	assert(hImpersonate && "偽装のウィンドウハンドルが取得できません。");

	hImpersonateUser = GetDlgItem(hDlg_, IDC_IMPERSONATE_USER);
	assert(hImpersonateUser && "偽装ユーザのウィンドウハンドルが取得できません。");

	hImpersonateDomain = GetDlgItem(hDlg_, IDC_IMPERSONATE_DOMAIN);
	assert(hImpersonateDomain && "偽装ドメインのウィンドウハンドルが取得できません。");

	hImpersonatePassword = GetDlgItem(hDlg_, IDC_IMPERSONATE_PASSWORD);
	assert(hImpersonatePassword && "偽装パスワードのウィンドウハンドルが取得できません。");

	hWatchDisabled = GetDlgItem(hDlg_, IDC_WATCH_DISABLED);
	assert(hWatchDisabled && "監視無効のウィンドウハンドルが取得できません。");


	// ウィンドウサイズの選択肢
	SendMessage(hShowWindow, CB_INSERTSTRING, 0, (LPARAM) ShowWindowType::valueOf(0).getDescription().c_str());
	SendMessage(hShowWindow, CB_INSERTSTRING, 1, (LPARAM) ShowWindowType::valueOf(1).getDescription().c_str());
	SendMessage(hShowWindow, CB_INSERTSTRING, 2, (LPARAM) ShowWindowType::valueOf(2).getDescription().c_str());
	SendMessage(hShowWindow, CB_INSERTSTRING, 3, (LPARAM) ShowWindowType::valueOf(3).getDescription().c_str());
	SendMessage(hShowWindow, CB_INSERTSTRING, 4, (LPARAM) ShowWindowType::valueOf(4).getDescription().c_str());


	// アクションの選択肢
	const tstring verbList = app.LoadString(IDS_SETTINGMES_VERBLIST);
	tstring::size_type lastpos = 0;
	for (;;) {
		tstring::size_type pos = verbList.find('|', lastpos);
		tstring verb;
		if (pos != tstring::npos) {
			verb = verbList.substr(lastpos, pos - lastpos);
		}
		else {
			verb = verbList.substr( lastpos );
		}
		SendMessage(hVerb, (UINT) CB_INSERTSTRING, (WPARAM) -1, (LPARAM) verb.c_str());

		if (pos == tstring::npos) {
			break;
		}
		lastpos = pos + 1;
	}

	setInitialParam();

	// ファクトリからのエラー通知を、このダイアログが受けます。
	factory_.setErrorInfoListener( this );
}

void CSettingDlg::setInitialParam()
{
	SendMessage(hShowWindow, CB_SETCURSEL, settingInfo_.getShowWindow(), 0);

	setWindowText(hVerb, settingInfo_.getAction());
	setWindowText(hDir, settingInfo_.getWatchDir());
	setWindowText(hName, settingInfo_.getWatchFile());
	setWindowText(hApp, settingInfo_.getAppName());
	setWindowText(hParam, settingInfo_.getParam());
	setWindowText(hLog, settingInfo_.getLog());

	setWindowText(hTolerance, IntToString(settingInfo_.getTolerance()));
	setWindowText(hWaitWrite, IntToString(settingInfo_.getWaitWrite()));

	setWindowText(hDeletePending, IntToString(settingInfo_.getDeletePending()));
	setWindowText(hMaxProcess, IntToString(settingInfo_.getMaxProcess()));

	setWindowText(hMaxDepth, IntToString(settingInfo_.getMaxDepth()));

	CheckDlgButton(hDlg_, IDC_USEDIRNITIFICATIONAPI, settingInfo_.isUsingDirNotificationAPI() ? BST_CHECKED : BST_UNCHECKED);

	setWindowText(hDirNotificationAPIRetrySpan, IntToString(settingInfo_.getDirNotificationAPIRetryInterval()));
	setWindowText(hDirNotificationAPIExpirySpan, IntToString(settingInfo_.getDirNotificationAPIExpirySpan()));
	setWindowText(hForceInterval, IntToString(settingInfo_.getForceInterval()));

	setWindowText(hLogLevel, IntToString(settingInfo_.getLogLevel()));
	setWindowText(hAppCurrentDir, settingInfo_.getAppCurrentDir());
	setWindowText(hPersist, settingInfo_.getPersist());

	CheckDlgButton(hDlg_, IDC_ARCHIVEONLY, settingInfo_.isArchiveOnly() ? BST_CHECKED : BST_UNCHECKED);
	CheckDlgButton(hDlg_, IDC_NOTIFYONSTART, settingInfo_.isNotifyOnStart() ? BST_CHECKED : BST_UNCHECKED);
	setWindowText(hWatchDelay, IntToString(settingInfo_.getWatchDelay()));

	CheckDlgButton(hDlg_, IDC_IGNORE_DUPLICATE, settingInfo_.isIgnoreDuplicate() ? BST_CHECKED : BST_UNCHECKED);

	CheckDlgButton(hDlg_, IDC_IMPERSONATE, settingInfo_.isImpersonate() ? BST_CHECKED : BST_UNCHECKED);
	setWindowText(hImpersonateUser, settingInfo_.getImpersonateUser());
	setWindowText(hImpersonateDomain, settingInfo_.getImpersonateDomain());
	setWindowText(hImpersonatePassword, settingInfo_.getImpersonatePassword());

	CheckDlgButton(hDlg_, IDC_WATCH_DISABLED, settingInfo_.isWatchDisabled() ? BST_CHECKED : BST_UNCHECKED);
}

void CSettingDlg::onOK()
{
	clearError();

	factory_.setWatchDir(getWindowText(hDir));
	factory_.setWatchFile(getWindowText(hName));
	factory_.setAction(getWindowText(hVerb));
	factory_.setAppName(getWindowText(hApp));
	factory_.setParam(getWindowText(hParam));
	factory_.setLog(getWindowText(hLog));
	factory_.setWaitWrite(atoi(getWindowText(hWaitWrite)));
	factory_.setTolerance(atoi(getWindowText(hTolerance)));

	factory_.setDeletePending(atoi(getWindowText(hDeletePending)));
	factory_.setMaxProcess(atoi(getWindowText(hMaxProcess)));

	const int forceInterval = atoi(getWindowText(hForceInterval));
	if (forceInterval > 0) {
		factory_.setForceInterval(forceInterval );
		factory_.setUsingDirNotificationAPI((IsDlgButtonChecked(hDlg_, IDC_USEDIRNITIFICATIONAPI) == BST_CHECKED ) ? true : false);
	}
	else {
		factory_.setUsingDirNotificationAPI((IsDlgButtonChecked(hDlg_, IDC_USEDIRNITIFICATIONAPI) == BST_CHECKED) ? true : false);
		factory_.setForceInterval(forceInterval);
	}

	factory_.setDirNotificationAPIRetryInterval(atoi(getWindowText(hDirNotificationAPIRetrySpan)));
	factory_.setDirNotificationAPIExpirySpan(atoi(getWindowText(hDirNotificationAPIExpirySpan)));

	factory_.setLogLevel(atoi(getWindowText(hLogLevel)));
	factory_.setAppCurrentDir(getWindowText(hAppCurrentDir));
	factory_.setPersist(getWindowText(hPersist));

	factory_.setWatchDelay(atoi(getWindowText(hWatchDelay)));
	factory_.setArchiveOnly((IsDlgButtonChecked(hDlg_, IDC_ARCHIVEONLY) == BST_CHECKED) ? true : false);
	factory_.setNotifyOnStart((IsDlgButtonChecked(hDlg_, IDC_NOTIFYONSTART) == BST_CHECKED) ? true : false);

	factory_.setIgnoreDuplicate((IsDlgButtonChecked(hDlg_, IDC_IGNORE_DUPLICATE) == BST_CHECKED) ? true : false);

	factory_.setImpersonate((IsDlgButtonChecked(hDlg_, IDC_IMPERSONATE) == BST_CHECKED) ? true : false);
	factory_.setImpersonateUser(getWindowText(hImpersonateUser));
	factory_.setImpersonateDomain(getWindowText(hImpersonateDomain));
	factory_.setImpersonatePassword(getWindowText(hImpersonatePassword));

	factory_.setWatchDisabled((IsDlgButtonChecked(hDlg_, IDC_WATCH_DISABLED) == BST_CHECKED) ? true : false);

	factory_.setMaxDepth(atoi(getWindowText(hMaxDepth)));

	int nShowWindow;
	if ((nShowWindow = static_cast<int>(SendMessage(hShowWindow, CB_GETCURSEL, 0, 0))) == CB_ERR) {
		nShowWindow = 1;
	}
	factory_.setShowWindow(ShowWindowType::valueOf(nShowWindow));

	if ( !isErrorOccured() && factory_.validate(false)) {
		EndDialog(hDlg_,IDOK);
	}
}

void CSettingDlg::onCancel()
{
#ifdef _DEBUG
	// クラッシュテスト (SHIFT + ALT + CLICK)
	if (::GetAsyncKeyState(VK_SHIFT) & 0x8000 && ::GetAsyncKeyState(VK_MENU) & 0x8000) {
		int* p = 0;
		*p = 1234; // アクセス違反
	}
#endif

	EndDialog(hDlg_,IDCANCEL);
}

void CSettingDlg::onBrowseDir()
{
	IMalloc* pMalloc = NULL;
	if (FAILED(::SHGetMalloc(&pMalloc))) {
		app.showMessageBox(MB_ICONERROR | MB_OK, NULL, IDS_MAINPROC_SHELLALLOCERROR);
		return;
	}

	const tstring caption = app.LoadString(IDS_SETTINGMES_SELECTDIR);

	tstring watchDir = getWindowText(hDir);
	PropertyStringExpander expander;
	app.setAppConfVariablesTo(expander);
	watchDir = expander.expandString(watchDir);

	CBrowseFolder browseFolder(hDlg_, caption);
	browseFolder.SetCurrent(watchDir);
	if (browseFolder.BrowseFolder(pMalloc)) {
		watchDir = browseFolder.GetCurrent();

		// %LSTDIR%からの相対パスであれば、特殊変数に置き換える。
		tstring relativeWatchDir = GetRelativePath(app.getInfDir(), watchDir);
		tstring prefix = _T(".\\");
		if (relativeWatchDir.compare(0, prefix.length(), prefix) == 0) {
			watchDir = _T("%LSTDIR%");
			watchDir += relativeWatchDir.substr(2);
		}

		setWindowText(hDir, watchDir);
	}

	pMalloc->Release();
}

void CSettingDlg::onBrowseCurDir()
{
	IMalloc* pMalloc = NULL;
	if (FAILED(::SHGetMalloc(&pMalloc))) {
		app.showMessageBox(MB_ICONERROR | MB_OK, NULL, IDS_MAINPROC_SHELLALLOCERROR);
		return;
	}

	const tstring caption = app.LoadString(IDS_SETTINGMES_SELECT_CURDIR);

	CBrowseFolder browseFolder(hDlg_, caption);
	browseFolder.SetCurrent(getWindowText(hAppCurrentDir));
	if (browseFolder.BrowseFolder(pMalloc)) {
		setWindowText(hAppCurrentDir,  browseFolder.GetCurrent());
	}

	pMalloc->Release();
}

void CSettingDlg::onOpen()
{
	IMalloc* g_pMalloc = NULL;
	if (FAILED(::SHGetMalloc( &g_pMalloc))) {
		app.showMessageBox(MB_ICONERROR | MB_OK, NULL, IDS_MAINPROC_SHELLALLOCERROR);
		return;
	}
	TCHAR InitDir[MAX_PATH] = {0};
	LPITEMIDLIST itemidlist;
	if (::SHGetSpecialFolderLocation(hDlg_, CSIDL_STARTMENU, &itemidlist) == NOERROR) {
		::SHGetPathFromIDList(itemidlist, InitDir);
		g_pMalloc->Free(itemidlist);
	}
	g_pMalloc->Release();

	tstring filter = app.LoadString(IDS_SETTINGMES_OPENFILEFILTER);
	tstring::size_type pos;
	while ((pos = filter.find('|')) != tstring::npos) {
		filter.replace(pos, 1, 1, '\0');
	}
	filter.push_back('\0');

	TCHAR openname[MAX_PATH] = {0};
	tstring text = getWindowText(hApp);
	if (text.length() >= MAX_PATH) {
		text = text.substr(0, MAX_PATH - 1);
	}
	_tcscpy_s(openname, MAX_PATH, text.c_str());

	OPENFILENAME ofn = {0};
	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.hwndOwner = hDlg_;
	ofn.hInstance = app.getInstanceHandle();
	ofn.lpstrFilter = filter.data();
	ofn.lpstrCustomFilter = NULL;
	ofn.nMaxCustFilter = 0;
	ofn.nFilterIndex = 0;
	ofn.lpstrFile = openname;
	ofn.nMaxFile = MAX_PATH;
	ofn.lpstrInitialDir = InitDir;
	ofn.lpstrTitle = NULL;
	ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_ENABLESIZING | OFN_HIDEREADONLY;
	if (::GetOpenFileName(&ofn)) {
		setWindowText(hApp, openname);
	}
}

void CSettingDlg::onLogSelect()
{
	tstring filter = app.LoadString(IDS_SETTINGMES_LOGFILEFILTER);
	tstring::size_type pos;
	while ((pos = filter.find('|')) != tstring::npos) {
		filter.replace(pos, 1, 1, '\0');
	}
	filter.push_back('\0');

	TCHAR savename[MAX_PATH] = {0};
	tstring text = getWindowText(hLog);
	if (text.length() >= MAX_PATH) {
		text = text.substr(0, MAX_PATH - 1);
	}
	_tcscpy_s(savename, MAX_PATH, text.c_str());

	OPENFILENAME ofn = {0};
	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.hwndOwner = hDlg_;
	ofn.hInstance = app.getInstanceHandle();
	ofn.lpstrFilter = filter.data();
	ofn.lpstrCustomFilter = NULL;
	ofn.nMaxCustFilter = 0;
	ofn.nFilterIndex = 0;
	ofn.lpstrFile = savename;
	ofn.nMaxFile = MAX_PATH;
	ofn.lpstrInitialDir = NULL;
	ofn.lpstrTitle = NULL;
	ofn.Flags = OFN_ENABLESIZING | OFN_HIDEREADONLY;
	ofn.lpstrDefExt = _T("log");
	if (::GetSaveFileName(&ofn)) {
		setWindowText(hLog, savename);
	}
}

void CSettingDlg::onSelPersist()
{
	tstring filter = app.LoadString(IDS_SETTINGMES_PERSISTFILTER);
	tstring::size_type pos;
	while ((pos = filter.find('|')) != tstring::npos) {
		filter.replace(pos, 1, 1, '\0');
	}
	filter.push_back('\0');

	TCHAR savename[MAX_PATH] = {0};
	tstring text = getWindowText(hPersist);
	if (text.length() >= MAX_PATH) {
		text = text.substr(0, MAX_PATH - 1);
	}
	_tcscpy_s(savename, MAX_PATH, text.c_str());

	OPENFILENAME ofn = {0};
	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.hwndOwner = hDlg_;
	ofn.hInstance = app.getInstanceHandle();
	ofn.lpstrFilter = filter.data();
	ofn.lpstrCustomFilter = NULL;
	ofn.nMaxCustFilter = 0;
	ofn.nFilterIndex = 0;
	ofn.lpstrFile = savename;
	ofn.nMaxFile = MAX_PATH;
	ofn.lpstrInitialDir = NULL;
	ofn.lpstrTitle = NULL;
	ofn.Flags = OFN_ENABLESIZING | OFN_HIDEREADONLY;
	ofn.lpstrDefExt = _T("fw_session");
	if (::GetSaveFileName(&ofn)) {
		setWindowText(hPersist, savename);
	}
}

BOOL CSettingDlg::onCommand(UINT btn)
{
	switch(btn)
	{
	case IDOK:
		onOK();
		break;
		
	case IDCANCEL:
		onCancel();
		break;

	case IDC_BROWSE:
		onBrowseDir();
		break;

	case IDC_BROWSE_CURDIR:
		onBrowseCurDir();
		break;

	case IDC_OPEN:
		onOpen();
		break;

	case IDC_LOGFILESELECT:
		onLogSelect();
		break;

	case IDC_SEL_PERSIST:
		onSelPersist();
		break;
	
	default:
		return FALSE;
	}
	
	return TRUE;
}

LRESULT CALLBACK CSettingDlg::DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	CSettingDlg* me = (CSettingDlg*) ::GetWindowLongPtr(hDlg, DWLP_USER);
	assert((me == NULL || me->hDlg_ == hDlg) && "参照が不正です。");

	if (message == WM_INITDIALOG) {
		me = reinterpret_cast<CSettingDlg *>(lParam);
		assert(me != NULL && "インスタンスへのポインタが設定されていません。");
		::SetWindowLongPtr(hDlg, DWLP_USER, (LONG) me);
		me->hDlg_ = hDlg;
		me->OnInitDialog();
		return TRUE;
	}
	else if (message == WM_COMMAND) {
		return me->onCommand(LOWORD(wParam));
	}

	return FALSE;
}

int CALLBACK CSettingDlg::NoWordwrapProc(LPTSTR, int ichCurrent, int, int code)
{
	return (code == WB_ISDELIMITER) ? 0 : ichCurrent;
}


////////////////////////////////////////

CBrowseFolder::CBrowseFolder(HWND hParent, const tstring& caption)
	: hParent_(hParent)
	, caption_(caption)
{
}

void CBrowseFolder::SetCurrent(const tstring& current)
{
	current_ = current;
}

const tstring& CBrowseFolder::GetCurrent() const
{
	return current_;
}

/*!
 * フォルダ選択ダイアログを表示し、フォルダが選択された場合、
 * trueを返します。falseの場合はキャンセルされた場合です。
 * \param pMalloc フォルダパスを変換するためにシェルのアロケータを使用するため必要となります。
 * \return フォルダが選択された場合はtrue
 */
bool CBrowseFolder::BrowseFolder(IMalloc* pMalloc)
{
	assert(pMalloc && "IMallocインターフェィスは必須です。");

	TCHAR dirname[MAX_PATH] = {0};

	BROWSEINFO bi = {0};
	bi.hwndOwner = hParent_;
	bi.pidlRoot = NULL;
	bi.pszDisplayName = dirname;
	bi.lpszTitle = caption_.c_str();
	bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
	bi.lpfn = CallbackProc;
	bi.lParam = reinterpret_cast<LPARAM>(this);
	bi.iImage = 0;
	LPITEMIDLIST pidlist = ::SHBrowseForFolder(&bi);
	bool result = false;
	if (pidlist) {
		if (::SHGetPathFromIDList(pidlist, dirname)) {
			current_ = tstring(StrTrim(dirname));
			result = true;
		}
		pMalloc->Free(pidlist);
	}
	return result;
}

int __stdcall CBrowseFolder::CallbackProc(HWND hwnd, UINT uMsg, LPARAM, LPARAM lpData)
{
	CBrowseFolder *me = reinterpret_cast<CBrowseFolder *>(lpData);

	switch (uMsg)
	{
	case BFFM_INITIALIZED:
		{
			// 初期選択
			if (me->current_.length() > 0) {
				LPCTSTR strCurrent = me->current_.c_str();
				SendMessage(hwnd, BFFM_SETSELECTION, TRUE, reinterpret_cast<LPARAM>(strCurrent));
			}
			return 0;
		}

	case BFFM_VALIDATEFAILED:
		return 1; // nonzero to keep the dialog displayed.
	};
	return 0;
}
