// dllmain.cpp : DLL アプリケーションのエントリ ポイントを定義します。
#include "stdafx.h"
#include "dllmain.h"

//使用するWindowsAPIや、ライブラリのヘッダの例
//#include <algorithm>
//#include <Windows.h>
//#include <Winuser.h>

//パスの末尾に安全に\記号を付与するサンプルで、::PathAddBackslash()を使用するために使用しているヘッダとシステムライブラリです
//不要であれば以下の2行を削除してください
#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")

//As/R本体のウィンドウハンドルを返す、起動されていない場合はNULLが返ってくる
HWND GetAsrMainwindow();

//仮想フォルダか否かを判定する関数
BOOL IsVirtual(wstring fullpath);

//ステータステキストを配列に分解する関数のサンプル
#include <vector>
size_t TokenSplit(const wstring &buff, const wchar_t cDiv, vector<wstring> &retDiv);



//プラグインの動作フラグ
#define FLG_BACKGROUND 0x10000

////////////////////////////////////////////////////
//プラグインのロジック部

//プラグイン構造体番号を返す
DWORD WINAPI GetFunctionInfoEx(void)
{
	//DoProcessExで渡される引数が、PLUGIN_DATA_EX1のポインタであることを指示する、Ver.7.0の時点で1種類しか用意されていないので1固定
	//FLG_BACKGROUNDのフラグが組み合わされていれば、本体で管理されるバックグラウンドのスレッドで処理される
	//※要望があればPLUGIN_DATA_EX2、PLUGIN_DATA_EX3と増えていく想定です

	return 1;
	//return 1 | FLG_BACKGROUND;
}

//プラグインコマンド本体
void WINAPI DoProcessEx(void* pPlugInData)
{
	PLUGIN_DATA_EX1* data = (PLUGIN_DATA_EX1*)pPlugInData;

	{//パスの末尾に安全に\記号を付与するサンプル
		wchar_t test0[MAX_PATH] = L"C:";//→"C:\\"
		wchar_t test1[MAX_PATH] = L"C:\\";//→"C:\\"

		wchar_t test2[MAX_PATH] = L"C:\\test";//→"C:\\test\\"
		wchar_t test3[MAX_PATH] = L"C:\\test\\";//→"C:\test\"

		wchar_t test4[MAX_PATH] = L"\\\\server";//→"\\\\server\\"
		wchar_t test5[MAX_PATH] = L"\\\\server\\";//→"\\\\server\\"

		wchar_t test6[MAX_PATH] = L"\\\\server\\share";//→"\\\\server\\share\\"
		wchar_t test7[MAX_PATH] = L"\\\\server\\share\\";//→"\\\\server\\share\\"

		::PathAddBackslash(test0);
		::PathAddBackslash(test1);
		::PathAddBackslash(test2);
		::PathAddBackslash(test3);
		::PathAddBackslash(test4);
		::PathAddBackslash(test5);
		::PathAddBackslash(test6);
		::PathAddBackslash(test7);
	}

	{
		//As/R本体のウィンドウハンドルを取得するサンプル
		//PostMessage()などでコマンドを送信するような使い方をするためのサンプルです
		HWND hWnd = GetAsrMainwindow();
		if (hWnd)
		{
			//コマンドが呼ばれる時はアイコン化されてないので、あまり意味がないサンプルです
			if (::IsIconic(hWnd))//アイコン化されていれば
				ShowWindow(hWnd, SW_SHOWNORMAL);//元のサイズに戻す
			::PostMessage(hWnd, WM_COMMAND, 33301, NULL);//最新の状態に更新コマンドを発行
		}
	}

	//カレントリストの選択アイテムを列挙してメッセージボックスを表示するサンプル
	{
		//コマンド定義ファイルで、ファイルないしディレクトリを渡す設定（UI制御設定）をしておかないとパラメータが渡されません
		//PlugInCommand.txt
		//41504	NFD	O:\test\Win32test.dll	新型テスト
		//		↑これ

		//"NFD"は「アクティブペインが実体を持つフォルダー」(N)で、「ファイル選択あり」(F)で「フォルダー選択あり」(D)ならコマンドが実行されるという意味です。
		//例1)"N--"ならば「アクティブペインが実体を持つフォルダー」であれば、何も選択されていない状態でコマンド実行可能になりますが、lpszSelectedItems1やnItemCount1に値が格納されません。
		//例2)"NF-"ならば「アクティブペインが実体を持つフォルダー」であれば、「ファイル」/「フォルダー」を選択した状態であっても「ファイル」のパス名しか渡されません。
		//なお、画面分割のターゲットペインであるlpszSelectedItems2やnItemCount2はUI制御設定の影響を受けませんので、動作の違いにご注意ください。

		{
			wstring files;
			for (size_t i = 0; i < data->nItemCount1; i++)
			{
				files += L"Active:";
				files += data->lpszSelectedItems1[i];
				files += L"\n";
			}
			if (files.size() != 0)
				::MessageBox(data->hMainWnd, files.c_str(), data->szCurrentPath1, MB_OK);
		}
		{
			wstring files;
			for (size_t i = 0; i < data->nItemCount2; i++)
			{
				files += L"Target:";
				files += data->lpszSelectedItems2[i];
				files += L"\n";
			}
			if (files.size() != 0)
				::MessageBox(data->hMainWnd, files.c_str(), data->szCurrentPath2, MB_OK);
		}
	}

	//他のタブの情報の取り扱いのサンプル
	{
		wstring file = data->lpszActivePath[data->nCurrentTabNo];//カレントディレクトリ、こちらは仮想ディレクトリであろうと文字列で渡される
		::MessageBox(data->hMainWnd, file.c_str(), data->szCurrentPath1, MB_OK);
	}

	//ステータステキストを展開するサンプル
	{
		vector<wstring> retDiv;
		if (0 != TokenSplit(data->szStatusText1, ' ', retDiv))//半角スペースで区切られているので配列に分割
		{
			//末尾に記載している本体から渡されるステータス置換マクロの情報を参照して、使用するステータスの番号を求める
			//この情報はVer.7.0時点のものであり、以降のバージョンでは予備や予約エリアが使用されたり、総数が増えたりする事があるので注意すること

			//渡されるステータス値は数値で渡され、ほとんどの値は32ビットintで渡される
			//ファイルサイズ・アイテム数は例外で、64ビットの整数で渡されるので注意すること

			::MessageBox(data->hMainWnd, retDiv[1].c_str(), L"?State:StatusBar?", MB_OK);//ステータスバーの表示状態
			::MessageBox(data->hMainWnd, retDiv[64].c_str(), L"?State:ListItemCount?", MB_OK);//リスト上のアイテムの数
		}
	}
}

//As/R本体のウィンドウハンドルを取得する関数
HWND GetAsrMainwindow()
{
	return ::FindWindow(L"{0F04AF43-7B85-46A5-A0A7-6D323A84AD7C}", NULL);
}

//As/R本体のウィンドウハンドルを返す、起動されていない場合はNULLが返ってくる
BOOL IsVirtual(wstring fullpath)
{
	//先頭1文字が「:」「;」か、「ftp://」「http://」「https://」で始まるか否かで判定
	//※「;」は明らかにイレギュラーですが、残念ながら現存してるため追加しています
	size_t n = fullpath.size();
	if (n > 7 && _wcsnicmp(fullpath.c_str(), L"https://", 8) == 0)
		return TRUE;
	if (n > 6 && _wcsnicmp(fullpath.c_str(), L"http://", 7) == 0)
		return TRUE;
	if (n > 5 && _wcsnicmp(fullpath.c_str(), L"ftp://", 6) == 0)
		return TRUE;
	if (n > 0 && (fullpath[0] == ':' || fullpath[0] == ';'))
		return TRUE;
	return FALSE;
}

//参考用の関数
//UNICODE文字列とデリミタを受け取り、配列にセットして返す
size_t TokenSplit(const wstring &buff, const wchar_t cDiv, vector<wstring> &retDiv)
{
	size_t nLen = buff.size();
	wstring s;
	s.reserve(nLen);
	for (size_t i = 0; i < nLen; i++)
	{
		wchar_t c = buff.at(i);
		if (c == cDiv)
		{
			if (s[0] != 0)//デリミタが連続する場合はカウントしない
				retDiv.push_back(s);
			s.clear();
		}
		else
			s.append(1, c);
	}
	if (s[0] != 0)
		retDiv.push_back(s);
	return retDiv.size();
}

/*本体から渡されるステータス置換マクロの情報
const int nAttributeCount = 68;
TCHAR szAttribute[nAttributeCount][30]={
	//メインフレーム単位の情報
	L"ShowHideItem",	//0:隠しアイテムの表示有無
	L"StatusBar",		//1:ステータスバーの表示有無
	L"CaptionBar",		//2:キャプションバーの表示有無
	L"ToolBar",			//3:ツールバーの表示有無
	L"TabBar",			//4:タブバーの表示有無
	L"TreeBar",			//5:フォルダーバーの表示有無
	L"HistoryBar",		//6:最近閉じたウィンドウバーの表示有無
	L"PreviewBar",		//7:プレビューバーの表示有無
	L"WindowManageBar",	//8:ウィンドウ管理バーの表示有無
	L"WindowCount",		//9:タブの総数
	L"TabletAssistBar",	//10:タブレット支援バーの表示有無
	L"UserTreeBar",		//11:予備s1（名称変更の可能性があります）
	L"PropertiesBar",	//12:予備s2（名称変更の可能性があります）
	L"TagInfoBar",		//13:予備s3（名称変更の可能性があります）
	L"DriveBar",		//14:予備s4（名称変更の可能性があります）
	L"ToolBarFile",		//15:ツールバー(ファイル操作)
	L"ToolBarTool",		//16:ツールバー(ツール)
	L"ToolBarListMode",		//17:ツールバー(リストモード)
	L"ToolBarOperationMode",//18:ツールバー(操作モード)
	L"ToolBarSplitMode",	//19:ツールバー(分割モード)
	L"ToolBarWindow",	//20:ツールバー(ウィンドウ管理)
	L"t1",//予備		//21:
	L"t2",//予備		//22:
	L"t3",//予備		//23:
	L"t4",//予備		//24:
	L"OperationMode",	//25:デスクトップモードかタブレット支援モード
	L"TabletMode",		//26:タブレット支援モードのモード
	L"s1",				//27:予備
	L"s2",				//28:予備
	L"s3",				//29:予備
	L"UserBar0",		//30:ユーザー定義バーの表示有無（通常はランチャ）
	L"UserBar1",		//31:ユーザー定義バーの表示有無（通常はお気に入り）
	L"UserBar2",		//32
	L"UserBar3",		//33
	L"UserBar4",		//34
	L"UserBar5",		//35
	L"UserBar6",		//36
	L"UserBar7",		//37
	L"UserBar8",		//38
	L"UserBar9",		//39
	//フレーム単位の情報
	L"DivisionWindow",	//40:画面分割の有無40
	L"Navilock",		//41:ナビゲートロックの有無41
	L"SyncMove",		//42:フォルダの同期移動42
	L"SyncFocus",		//43:フォーカスの同期移動43
	L"SizeCmp",			//44:フォルダ比較モード
	L"f1",				//45:予備
	L"f2",				//46:予備
	L"f3",				//47:予備
	L"f4",				//48:予備
	L"f5",				//49:予備
	//ビュー単位の情報
	L"ViewMode",		//50:表示モード
	L"Sort",			//51:並び順
	L"IconMode",		//52:アイコンモード
	L"Order",			//53:昇順/降順
	L"FolderPriority",	//54:フォルダ優先ソート
	L"IsVirtual",		//55:仮想フォルダか否か
	L"IsNetwork",		//56:ネットワークか否か
	L"FilterArea",		//57:フィルタエリアが表示されているか否か
	L"SlectionArea",	//58:選択エリアが表示されているか否か
	L"v1",				//59:予備
	L"v2",				//60:予備
	L"v3",				//61:予備
	L"v4",				//62:予備
	L"v5",				//63:予備
	L"ListItemCount",	//64:アクティブリストのアイテム数(64ビット値)
	L"SelectedCount",	//65:アクティブリストで選択数数(64ビット値)
	L"ListItemSize",	//66:アクティブリストに表示されているアイテムのサイズ合計(64ビット値)
	L"SelectedSize"		//67:アクティブリストで選択されているアイテムのサイズ合計(64ビット値)
};

*/