﻿#include "LuaDll.h"
#include "lua_dll_resource.h"
#include "CommCtrl.h"
#define GSTR_APPNAME    ("lua_gdb_test")
#include "ComLog.h"
#include "CWSH.h"
#include "FileMgr.h"
#include "CWSHIfObj.h"
extern HWND hGwnd;
extern HINSTANCE hInstanceDll;
HWND hwndDllDlg;
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
#include <vector>
// extern bool(*chkIsDlgMsg)(MSG *msg);
std::vector<HWND>  hWnd_vec;
bool checkIsDialogMessage(MSG *msg){
	int sz = hWnd_vec.size();
	for (int i = 0; i<sz; i++){
		if (hWnd_vec[i] && IsDialogMessage(hWnd_vec[i], msg))
			return true;
	}
	return false;
}

///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
static bool tracebackEnabled = true;

// HWND hwndDlg = NULL;
static lua_State *luaState = NULL;

void luaDll_get_State(lua_State *L){
	luaState = L;
}

lua_State *get_luaState(void){
	return luaState;
}
#ifdef LOG_OUTPUT
void dumpStack(lua_State* L)
{
	int i;
	static  int  cnt=0;
	char  buf2[512];
	
	char *buf= new char[512];
	
	memset(buf,0x00, 512);
	//スタックに積まれている数を取得する
	sprintf(buf, "==dumpStack start[%d]=============================",++cnt);
	COMLOGF(RT_D_DEBUG,"%s",buf);
	//to_log(buf);
	int stackSize = lua_gettop(L);
	for (i = stackSize; i >= 1; i--){
		int type = lua_type(L, i);
		sprintf(buf2, "Stack[%2d-%10s] : ", i, lua_typename(L, type));
		
		switch(type){
			case LUA_TNUMBER:
				//number 型
				sprintf(buf,"%s%f",buf2, lua_tonumber(L, i));
				break;
			case LUA_TBOOLEAN:
				//boolean 型
				if (lua_toboolean(L, i)){
					//printf("true");
					sprintf(buf,"%s%s",buf2,"true");
				}else{
					// printf("false");
					sprintf(buf,"%s%s",buf2,"false");
				}
				break;
			case LUA_TSTRING:
			{
				//string 型
				// printf("%s", lua_tostring(L, i));
				const char *pc= lua_tostring(L, i);
				int len=strlen(pc);
				if (len>256){
					delete [] buf;
					buf= new char[len*2];
				}
				sprintf(buf,"%s%s",buf2, pc);
			}
				break;
			case LUA_TNIL:
				//nil
				sprintf(buf,"%s%s",buf2, "     " );
				break;
			default:
				//その他の型
				// printf("%s", lua_typename(L, type));
				sprintf(buf,"%s%s",buf2,  lua_typename(L, type) );
				break;
		}
		// printf("\n");
		// sprintf(buf2,"%s                    ",buf);
		COMLOGF(RT_D_DEBUG,"%s                    ",buf);
		// to_log(buf2);
	}
	sprintf(buf,"==dumpStack end  [%d]=============================", cnt);
	COMLOGF(RT_D_DEBUG,"%s",buf);
	delete [] buf;
	// to_log(buf);
}
#endif


inline void raise_error(lua_State *L, const char *errMsg = NULL){
	luaL_where(L, 1);
	if (errMsg){
		lua_pushstring(L, errMsg);
	} else {
		lua_insert(L, -2);
	}
	lua_concat(L, 2);
	lua_error(L);
}

static int cf_setCheckIsDialogMessage(lua_State *L){
	const int selfArg = 0;
	if (lua_isinteger(L, selfArg + 1)){
		lua_Integer  addrOfChkIsDlgMsg = luaL_checkinteger(L, selfArg + 1);
		*(bool(**)(MSG *))addrOfChkIsDlgMsg = checkIsDialogMessage;
		// *(void **)addrOfChkIsDlgMsg = (void *)checkIsDialogMessage;
	} else {
		raise_error(L, "String argument required for property access");
	}
	return 0;
}

static int cf_vec_metatable_erase(lua_State *L){
	const int selfArg = 0;
	if (lua_isinteger(L, selfArg + 1)){
		int i = luaL_checkinteger(L, selfArg + 1);
		if (lua_isinteger(L, selfArg + 2)){
			int j = luaL_checkinteger(L, selfArg + 2);
			hWnd_vec.erase(hWnd_vec.begin()+i, hWnd_vec.begin()+j);
		}
		else{
			hWnd_vec.erase(hWnd_vec.begin()+i);
		}
	} else {
		raise_error(L, "String argument required for property access");
	}
	return 0;
}
static int cf_vec_metatable_size(lua_State *L){
	//const int selfArg = lua_isuserdata(L, 1) ? 1 : 0;
	lua_pushinteger(L, (lua_Integer)hWnd_vec.size());
	return 1;
}

static int cf_vec_metatable_clear(lua_State *L){
	hWnd_vec.clear();
	return 0;
}

static int cf_vec_metatable_insert(lua_State *L){
	//const int selfArg = lua_isuserdata(L, 1) ? 1 : 0;
	const int selfArg = 0;
	if (lua_isinteger(L, selfArg + 1)){
		int i = luaL_checkinteger(L, selfArg + 1);
		hWnd_vec.insert(hWnd_vec.begin()+i, (HWND)luaL_checkinteger(L, selfArg + 2));
	} else {
		raise_error(L, "String argument required for property access");
	}
	return 0;
}

static int cf_vec_metatable_index(lua_State *L){
	// const int selfArg = lua_isuserdata(L, 1) ? 1 : 0;
	const int selfArg = 1;
	if (lua_isinteger(L, selfArg + 1)){
		int i = luaL_checkinteger(L, selfArg + 1);
		if (i < hWnd_vec.size()){
			lua_pushinteger(L, (lua_Integer)hWnd_vec[i]);
			return 1;
		}
		else{
			raise_error(L, "array index is out of range");
		}
	} else {
		raise_error(L, "String argument required for property access");
	}
	return 0;
}

static int cf_vec_metatable_newindex(lua_State *L){
	const int selfArg = lua_isuserdata(L, 1)? 1 : 0;
	int i = lua_isinteger(L, selfArg + 1)? luaL_checkinteger(L, selfArg + 1): 0;
	HWND v = (HWND)luaL_checkinteger(L, selfArg + 2);
	
	if (lua_isnil(L, selfArg + 2)){
		hWnd_vec[i] = NULL;
	}else{
		hWnd_vec[i] = v;
	}
	return 0;
}

static bool call_function(lua_State *L, int nargs, bool ignoreFunctionReturnValue = false){
	bool handled = false;
	if (L){
		int traceback = 0;
		if (tracebackEnabled){
			lua_getglobal(L, "debug");
			lua_getfield(L, -1, "traceback");
			lua_remove(L, -2);
			if (lua_isfunction(L, -1)){
				traceback = lua_gettop(L)- nargs - 1;
				lua_insert(L, traceback);
			} else {
				lua_pop(L, 1);
			}
		}
		
		const int result = lua_pcall(L, nargs, ignoreFunctionReturnValue ? 0 : 1, traceback);
		
		if (traceback){
			lua_remove(L, traceback);
		}
		
		if (0 == result){
			if (ignoreFunctionReturnValue){
				handled = true;
			} else {
				handled = (0 != lua_toboolean(L, -1));
				lua_pop(L, 1);
			}
		} else if (result == LUA_ERRRUN){
			lua_getglobal(L, "print");
			lua_insert(L, -2); // use pushed error message
			lua_pcall(L, 1, 0, 0);
		} else {
			lua_pop(L, 1);
			lua_getglobal(L, "print");
			if (result == LUA_ERRMEM){
				// host->Trace("> Lua: memory allocation error\n");
				lua_pushstring(L, "> Lua: memory allocation error\n");
			} else if (result == LUA_ERRERR){
				// host->Trace("> Lua: an error occurred, but cannot be reported due to failure in _TRACEBACK\n");
				lua_pushstring(L, "> Lua: an error occurred, but cannot be reported due to failure in _TRACEBACK\n");
			} else {
				// host->Trace("> Lua: unexpected error\n");
				lua_pushstring(L, "> Lua: unexpected error\n");
			}
			lua_pcall(L, 1, 0, 0);
			
		}
	}
	return handled;
}
static bool CallNamedFunction(const char *name, lua_Integer numberArg, const char *stringArg2){
	bool handled = false;
	if (luaState){
		lua_getglobal(luaState, name);
		if (lua_isfunction(luaState, -1)){
			lua_pushinteger(luaState, numberArg);
			lua_pushstring(luaState, stringArg2);
			handled = call_function(luaState, 2);
		} else {
			lua_pop(luaState, 1);
		}
	}
	return handled;
}


///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
static int lua_setFuncOfJscript(lua_State *L);
static int lua_runJscript(lua_State *L);
static int lua_clearJscript(lua_State *L);
std::map<std::wstring, std::vector<MacroFuncInfo>>  macroFuncInfoMap;

void SetFunctions( lua_State *L,std::vector<MacroFuncInfo> &info)
{
	static int key=F_FUNCTION_FIRST;
	int order=0;
	MacroFuncInfo func;

	lua_pushnil(L); // push nil, so lua_next removes it from stack and puts (k, v) on stack
	// dumpStack(L);
	while (lua_next(L, -2) != 0) {
		// dumpStack(L);
		order++;
		if ( (order==1) && ( lua_type(L, -1) == LUA_TFUNCTION)  ){
			// ==> stack: ..., 1,func
			lua_getglobal(L, "spawner");// ==> stack: ..., 1,func, spawner{},
			lua_getfield(L,-1,"wsh"); // ==> stack: ..., 1,func, spawner{}, wsh{}
			lua_pushinteger(L, ++key); // ==> stack: ..., 1,func, spawner{}, wsh{},key
			lua_pushvalue(L,-4);   // ==> stack: ..., 1,func, spawner{}, wsh{},key,func
			lua_settable(L,-3);    // ==> stack: ..., 1,func, spawner{}, wsh{}   ; wsh[key]=func
			lua_pop(L, 2);
			func.m_nFuncID=key;
		}
		else if ( (order==2)  && (lua_type(L, -1) == LUA_TSTRING)  ){
			const char *pc=lua_tostring(L, -1);
			int len=strlen(pc);
			wchar_t *buf = new wchar_t[len + 1];
			int L2 = ::MultiByteToWideChar(CP_ACP, 0, pc, len, buf, len);
			buf[L2]=0;
			func.m_pszFuncName=buf;	
		}
		else if ( (order==3)  && (lua_type(L, -1) == LUA_TTABLE)  ){
			// ==> stack: ..., 3,{}
			lua_pushnil(L);  // ==> stack: ..., 3,{},nil
			while (lua_next(L, -2) != 0) {
				order++;
				if ( ( lua_type(L, -1) == LUA_TNUMBER) ){
					func.m_varArguments[order-4]=(VARTYPE)luaL_checkinteger(L, -1);
				}
				lua_pop(L, 1);
			}
		}
		else if ( (order==8)  && (lua_type(L, -1) == LUA_TNUMBER)  ){
			func.m_varResult=(VARTYPE)luaL_checkinteger(L, -1);
		}		
		lua_pop(L, 1);
	}
	func.m_pData=NULL;
	info.push_back(func);
	return ;
}

void SetObj( lua_State *L)
{
	int i, n;
	std::wstring nm;
	std::vector<MacroFuncInfo> info;

	lua_pushnil(L); // push nil, so lua_next removes it from stack and puts (k, v) on stack
	// dumpStack(L);
	while (lua_next(L, -2) != 0) {
		// dumpStack(L);
		if ((lua_type(L, -2) == LUA_TSTRING) && (strcmp(lua_tostring(L, -2), "obj")==0)) {
			const char *pc=lua_tostring(L, -1);
			int len=strlen(pc);
			wchar_t *buf = new wchar_t[len + 1];
			int L2 = ::MultiByteToWideChar(CP_ACP, 0, pc, len, buf, len);
			buf[L2]=0;
			nm=buf;
			delete[] buf;
		}
		else if ( ( lua_type(L, -1) == LUA_TTABLE)  ){ //&& (lua_type(L, -2) == LUA_TSTRING) &&  (strcmp(lua_tostring(L, -2), "member")==0) 
			n = luaL_len(L, -1);
			for (i = 1; i <= n; i++){
				lua_geti(L, -1, i);
				int type = lua_type(L, -1);
				if (type == LUA_TTABLE){
					SetFunctions(L,info);
				}
				lua_pop(L, 1);
			}
		}
		lua_pop(L, 1);
	}

	if ( info.size() > 0 ){
		macroFuncInfoMap.insert ( std::pair<std::wstring, std::vector<MacroFuncInfo>>( nm ,info) );
	}
	return ;
}



#ifdef _M_AMD64
#define GWL_HINSTANCE	GWLP_HINSTANCE
#endif

#ifdef __cplusplus
extern "C" {
	
	static int luaB_t1b1(lua_State *L)
	{
		
		int i, j, n, m;
		
		DWORD dwIndex;
		char achTemp[256];
		n = lua_gettop(L);
		// dwIndex = SendMessage(hwndGroupsBox, CB_ADDSTRING, 0, (LPARAM)achTemp);  hInst
		
		CLuaDll cDlg;
		
		// ダイアログタイトルとファイル名を設定
		luaL_checktype(L, 1, LUA_TTABLE);
		/*
		lua_getfield(L, 1, "hWndDlg");
		lua_getfield(L, 1, "hCombo");
		lua_getfield(L, 1, "hwndButton");
		hwndDlg =luaL_checkinteger(L, -3) 
		hCombo =luaL_checkinteger(L, -2) 
		hwndButton =luaL_checkinteger(L, -1) 
		if ( luaL_checkinteger(L, -1) == 0){
		}
		*/
		HINSTANCE hInst = GetModuleHandle(NULL);
		// HWND hGwnd = GetForegroundWindow();
		// hGwnd = NULL;
		// HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtr(hGwnd, GWL_HINSTANCE);
		HINSTANCE hInstance = hInstanceDll;
		GetWindowTextA(hGwnd, achTemp, 256);
		// MessageBox(NULL, achTemp, "DoGetForegroundWindow1", MB_OK);
		
		HWND hwndDlg = cDlg.DoModeless(hInstance, hGwnd, IDD_LINE_JUMP); // エディタビジーでも表示できるよう、親を指定しない
		hwndDllDlg = hwndDlg;
		HWND hCombo = GetDlgItem(hwndDlg, IDC_COMBO1);
		HWND hwndButton = GetDlgItem(hwndDlg, ID_WORK);
		
		lua_getfield(L, 1, "dlg");
		lua_getfield(L, 1, "button");
		lua_getfield(L, 1, "show_idx");
		
		
		for (i = 2; i <= n; i++){
			int type = lua_type(L, i);
			if (type == LUA_TTABLE){
				m = luaL_len(L, i);
				for (j = 1; j <= m; j++){
					lua_geti(L, i, j); /* push t[j] */
					int type2 = lua_type(L, -1);
					if (type2 == LUA_TSTRING){
						
						SendMessageA(hCombo, CB_ADDSTRING, 0, (LPARAM)lua_tostring(L, -1));
					}
					else if (type2 == LUA_TNUMBER){
						sprintf(achTemp, "%d", luaL_checkinteger(L, -1));
						SendMessageA(hCombo, CB_ADDSTRING, 0, (LPARAM)achTemp);
					}
					lua_remove(L, -1);
				}
			}
			else if (type == LUA_TSTRING){
				SendMessageA(hCombo, CB_ADDSTRING, 0, (LPARAM)lua_tostring(L, i));
				
			}
			else if (type == LUA_TNUMBER){
				sprintf(achTemp, "%d", luaL_checkinteger(L, i));
				SendMessageA(hCombo, CB_ADDSTRING, 0, (LPARAM)lua_tostring(L, i));
			}
		}
		::SendMessageA(hwndDlg, WM_SETTEXT, 0, (LPARAM)lua_tostring(L, -3));
		::SendMessageA(hwndButton, WM_SETTEXT, 0, (LPARAM)lua_tostring(L, -2));
		::SendDlgItemMessageA(hwndDlg, IDC_COMBO1, CB_SETCURSEL, luaL_checkinteger(L, -1), 0);
		::SendMessageA(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_COMBO1), TRUE);
		
		lua_settop(L, 0);
		lua_createtable(L, 0, 4);
		lua_pushinteger(L, (lua_Integer)hGwnd);
		lua_setfield(L, -2, "hGwnd");
		lua_pushinteger(L, (lua_Integer)hInstance);
		lua_setfield(L, -2, "hInstance");
		lua_pushinteger(L, (lua_Integer)hwndDlg);
		lua_setfield(L, -2, "hWndDlg");
		lua_pushinteger(L, (lua_Integer)hCombo);
		lua_setfield(L, -2, "hCombo");
		lua_pushinteger(L, (lua_Integer)hwndButton);
		lua_setfield(L, -2, "hwndButton");
		// luaDll_get_State(L);
		return 1;
	}
	
	extern int cf_hWnds_vec_init(lua_State *L){
		lua_getglobal(L, "spawner");
		if (lua_isnil(L, -1)){
			lua_pop(L, 1);
			lua_newtable(L);
		}
		lua_pushcfunction(L, luaB_t1b1);
		lua_setfield(L, -2, "dlgTextButton");
		lua_pushcfunction(L, cf_setCheckIsDialogMessage);
		lua_setfield(L, -2, "setChkIsDlgMsg");
		lua_newuserdata(L, 1); // the value doesn't matter.             //   {}  ⇒ { u(1) } ;     
		// lua_createtable(L, 0, 0);
		if (luaL_newmetatable(L, "hWnd_meta1")){                        //   { u(1) }  ⇒ { meta , u(1) } ;                            
			
			lua_pushcfunction(L, cf_vec_metatable_size); //   { meta , u(1) }  ⇒ { in, meta , u(1) } ;            
			lua_setfield(L, -2, "size"); //  { size, meta , u(1) }  ⇒ {  meta , u(1) } ;meta{size}     
			
			lua_pushcfunction(L, cf_vec_metatable_clear); //   {  meta , u(1) } ;meta{size}   ⇒ { clear, meta , u(1) } ;meta{size};       
			lua_setfield(L, -2, "clear"); //  { clear, meta , u(1) } ;meta{size}   ⇒ {  meta , u(1) } ;meta{size,clear}   
			
			lua_pushcfunction(L, cf_vec_metatable_insert); //   {  meta , u(1) } ;meta{size,clear}  ⇒ { insert,  meta , u(1) } ;meta{size,clear};   
			lua_setfield(L, -2, "insert"); //  { insert,  meta , u(1) } ;meta{size,clear} ⇒ { meta , u(1) } ;meta{insert,size,clear}   
			
			lua_pushcfunction(L, cf_vec_metatable_erase); //   { meta , u(1) }  ⇒ { in, meta , u(1) } ;            
			lua_setfield(L, -2, "erase"); //  { size, meta , u(1) }  ⇒ {  meta , u(1) } ;meta{size}     
			
			lua_pushvalue(L, -1); //  { meta , u(1) } ;meta{insert,size,clear} ⇒  { meta, meta , u(1) } ;meta{insert,size,clear} 
			lua_setfield(L, -2, "__index"); //  { meta1, meta1 , u(1) } ;meta{insert,size,clear} ⇒ { meta1 , u(1) } ;meta1{__index=self,insert,size,clear}
			if (luaL_newmetatable(L, "hWnd_meta2")){                     //  { meta1 , u(1) } ;meta1{__index=self,insert,size,clear}  ⇒  { meta2, meta1 , u(1) } ;meta1{__index=self,insert,size,clear}
				lua_pushcfunction(L, cf_vec_metatable_index); //  { meta2, meta1 , u(1) } ;meta1{__index=self,insert,size,clear}   ⇒  { in. meta2, meta1 , u(1) } ;meta1{__index=self,insert,size,clear} 
				lua_setfield(L, -2, "__index"); //  { in. meta2, meta1 , u(1) } ;meta1{__index=self,insert,size,clear}  ⇒ { meta2, meta1 , u(1) } ;meta1{__index=self,insert,size,clear};meta2{__index=in}
			}
			lua_setmetatable(L, -2); //   { meta2, meta1 , u(1) } ;meta1{__index=self,insert,size,clear};meta2{__index=in} ⇒ { meta1 , u(1) } ;meta1{ meta=meta2{__index=in},__index=self,insert,size,clear};
			lua_pushcfunction(L, cf_vec_metatable_newindex); //  { meta1 , u(1) } ;meta1{ meta=meta2{__index=in},__index=self,insert,size,clear}; ⇒ { nin,meta1 , u(1) } ;meta1{ meta=meta2{__index=in},__index=self,insert,size,clear};
			lua_setfield(L, -2, "__newindex"); //  { nin,meta1 , u(1) } ;meta1{ meta=meta2{__index=in},__index=self,insert,size,clear}; ⇒ { meta1 , u(1) } ;meta1{ meta=meta2{__index=in},__index=self,__newindex=nin,insert,size,clear};   
			
		}
		lua_setmetatable(L, -2); //  { meta1 , u(1) } ;meta1{ meta=meta2{__index=in},__index=self,__newindex=nin,insert,size,clear} ⇒ {u(1)};u(1){meta=meta1{ meta=meta2{__index=in},__index=self,__newindex=nin,insert,size,clear}}
		lua_setfield(L, -2, "hWnds"); //  {u(1), tbl };u(1){meta=meta1{ meta=meta2{__index=in},__index=self,__newindex=nin,insert,size,clear}} ⇒ {};tbl["hWnds"]=u(1){meta=meta1{ meta=meta2{__index=in},__index=self,__newindex=nin,insert,size,clear}}  
		lua_setglobal(L, "spawner"); // { tbl };  ⇒  g["spawner"]=tbl
		return 0;
	}
	
	extern void lua_setEquipment(lua_State *L)
	{
	   lua_getglobal(L, "spawner");
		if (lua_isnil(L, -1)) {
		  lua_pop(L, 1);
		  lua_newtable(L);
		}
		lua_pushliteral( L, "wsh" ); // ==> stack: ..., spawner{}, "wsh"
		lua_newtable( L ); // ==> stack: ..., spawner{}, "wsh", {}
		lua_settable( L, -3 );// ==> stack: ..., spawner{wsh{}},

		lua_pushcfunction(L, lua_setFuncOfJscript); // ==> stack: ..., spawner{wsh{}},func
		lua_setfield(L, -2, "setFuncOfJscript"); // ==> stack: ..., spawner{wsh{},xx=func}

		lua_pushcfunction(L, lua_runJscript); // ==> stack: ..., spawner{wsh{}},func 
		lua_setfield(L, -2, "runJscript"); // ==> stack: ..., spawner{wsh{},xx=func}

		lua_pushcfunction(L, lua_clearJscript); // ==> stack: ..., spawner{wsh{}},func
		lua_setfield(L, -2, "clearJscript"); // ==> stack: ..., spawner{wsh{},xx=func}

		lua_setglobal(L, "spawner"); // { tbl };  ⇒  g["spawner"]=tbl

		return;
	}


}
#endif

static int lua_setFuncOfJscript(lua_State *L)
{
	int i, n;
	n = luaL_len(L, 1);
	// all_tricks.clear();
	for (i = 1; i <= n; i++){
		lua_geti(L, 1, i);
		int type = lua_type(L, -1);
		if (type == LUA_TTABLE){
			SetObj(L);
		}
		lua_pop(L, 1);
	}
	return 0;
}
static int lua_runJscript(lua_State *L)
{
	// int i, n;
	// get_luaState();

	int type = lua_type(L, 1);
	if ( LUA_TSTRING !=type ){
		raise_error(L, "path is not stirng");
	}

	const char *path=lua_tostring(L, -1);
	COMLOGF(RT_D_DEBUG, "path=[%s]", path);
	std::wstring  _path;
	{
		// int len=_tcslen(path);
		int wlen=::MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0);
		wchar_t *buf = new wchar_t[wlen];
		::MultiByteToWideChar(CP_ACP, 0, path, -1, buf, wlen);
		buf[wlen-1]=0;
		COMLOGFW(RT_D_DEBUG, L"buf=[%ls],wlen=(%d)", buf,wlen);
		_path = buf;
		delete[] buf;
	}
	std::wstring  mcroPath = _path;
#ifdef  UNICODE 
	const TCHAR *tpath = mcroPath.c_str();
#else   /* UNICODE */
	const TCHAR *tpath = path;
#endif
	//-------------------------------------------------------------------------------
	std::wstring g_EngineName;
	const TCHAR *ext = _tcsrchr(tpath, _T('.'));
	if (ext != NULL) {
		TCHAR FileType[1024], EngineName[1024];
		memset(FileType, 0x00, sizeof(FileType));
		if (ReadRegistry(HKEY_CLASSES_ROOT, ext, NULL, FileType, sizeof(FileType))) {
			_tcscat(FileType, _T("\\ScriptEngine"));
			memset(EngineName, 0x00, sizeof(EngineName));
			if (ReadRegistry(HKEY_CLASSES_ROOT, FileType, NULL, EngineName, 1024))
			{
#ifdef  UNICODE 
				g_EngineName = EngineName;
#else   /* UNICODE */
				// g_EngineName = strtools::MStrToWStr(std::string(EngineName));
				int len=_tcslen(EngineName);
				wchar_t *buf = new wchar_t[len + 1];
				int L2 = MultiByteToWideChar(CP_ACP, 0, EngineName, -1, buf, len);
				buf[len]=0;
				g_EngineName = buf;
				COMLOGFW(RT_D_DEBUG, L"buf=[%ls],len=(%d),L2=(%d)", buf,len,L2);
				delete[] buf;
#endif
				COMLOGF(RT_D_DEBUG, "FileType=[%s]EngineName=[%s]", FileType,EngineName);
				// GetDlgItem(IDC_CTRLPAUSESTART)->ShowWindow(SW_HIDE);
				// ShowWindow(GetDlgItem(hDlg, IDD_FILTERING), SW_HIDE);
				// GetDlgItem(IDC_FILENAME)->ShowWindow(SW_HIDE);
				// GetDlgItem(IDC_LINENO)->ShowWindow(SW_HIDE);
				// return TRUE;
			}
		}
	}

	COMLOGFW(RT_D_DEBUG, L"mcroPath=[%ls]", mcroPath.c_str());
	CFileMgr fMgr(mcroPath);
	int ret = fMgr.open();
	if (ret < 0) {
		if (-1 == ret) {
			raise_error(L, "file open error");
		}
	}
	SrunMacroParam oParam;
	oParam.m_Source = fMgr.pBuf;
	oParam.HMainWin = hGwnd;
	oParam.hInst = hInstanceDll;
#ifdef  UNICODE 
	std::wstring  _mcroPath = mcroPath;
#else   /* UNICODE */
	std::string  _mcroPath = path;
#endif
	_tcsncpy_s(oParam.sMcroPath, _countof(oParam.sMcroPath), _mcroPath.c_str(), _TRUNCATE);
	CWSHClient* Engine;
	COMLOGFW(RT_D_DEBUG, L"g_EngineName.c_str()=[%ls]", g_EngineName.c_str());
	Engine = new CWSHClient(g_EngineName.c_str(), MacroError, &oParam);
	if (Engine->m_Valid)
	{
		/*
		//僀儞僞僼僃乕僗僆僽僕僃僋僩偺搊榐
		CWSHIfObj* obj = new CWSHIfObj(L"Mcro1", true);
		obj->ReadyMethods(oParam.pObj);
		Engine->AddInterfaceObject(obj);

		CWSHIfObj* obj2 = new CWSHIfObj(L"Mcro2", true);
		obj2->ReadyMethods2(oParam.pObj);
		Engine->AddInterfaceObject(obj2);
		*/
		for (std::map<std::wstring, std::vector<MacroFuncInfo>> ::iterator it=macroFuncInfoMap.begin(); it!=macroFuncInfoMap.end(); ++it){
			CWSHIfObj* obj = new CWSHIfObj(it->first.c_str(), true);
			obj->ReadyLuaMethods(it->second,0);
			Engine->AddInterfaceObject(obj);

		}
		// luaDll_get_State(L);
		bool bRet = Engine->Execute(&oParam);
		COMLOGF(RT_D_DEBUG, "Engine->Execute() bRet=%d", bRet);
	}
	delete Engine;
	;;
	return 0;
}
static int lua_clearJscript(lua_State *L)
{
	for (std::map<std::wstring, std::vector<MacroFuncInfo>> ::iterator it=macroFuncInfoMap.begin(); it!=macroFuncInfoMap.end(); ++it){
		for (std::vector<MacroFuncInfo>::iterator it2=it->second.begin(); it2!=it->second.end(); ++it2){
			if(it2->m_pszFuncName){
				delete it2->m_pszFuncName;
				it2->m_pszFuncName=NULL;
			}
		}
		it->second.clear();
	}
	macroFuncInfoMap.clear();
	return 0;
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
HHOOK hHook;
LRESULT FAR PASCAL GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	LPMSG lpMsg = (LPMSG)lParam;
	
	if (nCode >= 0 && PM_REMOVE == wParam)
	{
		// Don't translate non-input events.
		if ((lpMsg->message >= WM_KEYFIRST && lpMsg->message <= WM_KEYLAST))
		{
			if (IsDialogMessage(hwndDllDlg, lpMsg))
			{
				// The value returned from this hookproc is ignored, 
				// and it cannot be used to tell Windows the message
				// has been handled. To avoid further processing,
				// convert the message to WM_NULL before returning.
				lpMsg->message = WM_NULL;
				lpMsg->lParam = 0;
				lpMsg->wParam = 0;
			}
		}
	}
	return CallNextHookEx(hHook, nCode, wParam, lParam);
}
INT_PTR CALLBACK LuaDllDialogProc(
	HWND hwndDlg, // handle to dialog box
	UINT uMsg, // message
	WPARAM wParam, // first message parameter
	LPARAM lParam 	// second message parameter
)
{
	char buf[256];
	CLuaDll* pCDialog;
	switch(uMsg){
		case WM_INITDIALOG:
			pCDialog = (CLuaDll*)lParam;
			if (NULL != pCDialog){ 
				::SetWindowLongPtr(hwndDlg, DWLP_USER, lParam);
				// g_oldDlgdProc = (WNDPROC)GetWindowLongPtr(hwndDlg, GWLP_WNDPROC); 
				// ::SetWindowLongPtr(hwndDlg, GWLP_WNDPROC, (INT_PTR)&DlgWindowsProc);
				hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc,
					NULL, GetCurrentThreadId());
				return pCDialog->DispatchEvent(hwndDlg, uMsg, wParam, lParam);
				return TRUE;
			}
		case WM_KEYDOWN:
			sprintf(buf, "WM_KEYDOWN:wMsg=0x%08X, wParam=0x%08X,lParam=0x%08X,", uMsg,wParam, lParam);
			CallNamedFunction("OnLuaMsgTest", (lua_Integer)uMsg, buf);
			return TRUE;
		case WM_CHAR:
			sprintf(buf, "WM_CHAR:wMsg=0x%08X, wParam=0x%08X,lParam=0x%08X,", uMsg,wParam, lParam);
			CallNamedFunction("OnLuaMsgTest", (lua_Integer)uMsg, buf);
			return TRUE;
		case WM_KEYUP:
			sprintf(buf, "WM_KEYUP:wMsg=0x%08X, wParam=0x%08X,lParam=0x%08X,", uMsg,wParam, lParam);
			CallNamedFunction("OnLuaMsgTest", (lua_Integer)uMsg, buf);
			return TRUE;
		case WM_DESTROY:
			UnhookWindowsHookEx(hHook);
			return FALSE;
		default:
			// Modified by KEITA for WIN64 2003.9.6
			pCDialog = (CLuaDll*)::GetWindowLongPtr(hwndDlg, DWLP_USER);
			if (NULL != pCDialog){
				INT_PTR result = pCDialog->DispatchEvent(hwndDlg, uMsg, wParam, lParam);
				/*
				if ( FALSE == result )
				return CallWindowProc(g_oldDlgdProc,hwndDlg, uMsg, wParam, lParam);
				else
				*/
				return result;
			}
			else {
				return FALSE;
			}
	}
	
	
}


CLuaDll::CLuaDll()
{
	;; //m_bCANCEL = FALSE;	/* IDCANCELボタンが押された */
}

/** 標準以外のメッセージを捕捉する
@date 2008.05.28 ryoji 新規作成
*/
INT_PTR CLuaDll::DispatchEvent(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
	INT_PTR result = FALSE;
	char buf[256];
	switch(wMsg){
		case WM_INITDIALOG:	
			return OnInitDialog(hWnd, wParam, lParam);
		case WM_CLOSE:
			CallNamedFunction("OnLuaJumpClose", (lua_Integer)hWnd, "");
			::DestroyWindow(hWnd);
			return TRUE;
			break;
		case WM_KEYDOWN:
			sprintf(buf, "WM_KEYDOWN:wMsg=0x%08X, wParam=0x%08X,lParam=0x%08X,", wMsg,wParam, lParam);
			CallNamedFunction("OnLuaMsgTest", (lua_Integer)wMsg, buf);
			break;
		case WM_CHAR:
			sprintf(buf, "WM_CHAR:wMsg=0x%08X, wParam=0x%08X,lParam=0x%08X,", wMsg,wParam, lParam);
			CallNamedFunction("OnLuaMsgTest", (lua_Integer)wMsg, buf);
			break;
		case WM_KEYUP:
			sprintf(buf, "WM_KEYUP:wMsg=0x%08X, wParam=0x%08X,lParam=0x%08X,", wMsg,wParam, lParam);
			CallNamedFunction("OnLuaMsgTest", (lua_Integer)wMsg, buf);
			break;
		case WM_COMMAND:
			return OnCommand(hWnd, wParam, lParam);
		default:
			
			break;
	}
	//return DefWindowProc(hWnd, wMsg, wParam, lParam);;
	return result;
}
BOOL CLuaDll::OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
	WORD	wID;
	BOOL	ret = FALSE;
	char achTemp[256];
	
	wID = LOWORD(wParam); /* 項目ID、 コントロールID、 またはアクセラレータID */
	// IDOK と IDCANCEL はボタンからでなくても同じ扱い
	// MSDN [Windows Management] "Dialog Box Programming Considerations"
	if (wID == ID_WORK){
		
		// HWND hwndGroupsBox = GetDlgItem(hwndDlg, IDC_COMBO1);
		// コンボボックスID_COMBO1のテキスト部分の内容を取得し, tszBufに格納.
		HWND hCombo = GetDlgItem(hWnd, IDC_COMBO1); // GetDlgItemでID_COMBO1のウィンドウハンドルhComboを取得.
		GetWindowTextA(hCombo, achTemp, sizeof(achTemp)); // GetWindowTextでhComboのエディットボックス部分のテキスト内容を取得してtszBufに格納.
		if (CallNamedFunction("OnLuaJump", (lua_Integer)hWnd, achTemp))
			ret = TRUE;
	}
	return ret;
}

/* モードレスダイアログの表示 */
HWND CLuaDll::DoModeless(HINSTANCE hInstance, HWND hwndParent, int nDlgTemplete)
{
	// m_bCANCEL = FALSE;	/* IDCANCELボタンが押された */
	// return CDialog::doDoModeless( hInstance, hwndParent, nDlgTemplete, (LPARAM)NULL, SW_SHOW );
	COMLOGF(RT_D_DEBUG, "hInstance(0x%X),hwndParent(0x%X),nDlgTemplete(%d) ",hInstance,hwndParent,nDlgTemplete);
	// HGLOBAL hglob = LoadResource(hInstance, FindResource(hInstance, MAKEINTRESOURCE(nDlgTemplete), RT_DIALOG));
	// LPCDLGTEMPLATE pdlgTemplate = (LPCDLGTEMPLATE)LockResource(hglob);
	// COMLOGF(RT_D_DEBUG, "hglob(0x%X)",hglob);

	HWND m_hWnd = ::CreateDialogParam(
		hInstance,
		MAKEINTRESOURCE(nDlgTemplete),
		hwndParent,
		LuaDllDialogProc,
		reinterpret_cast<LPARAM>(this)
		//(LPARAM)this
	);
	if (NULL != m_hWnd){
		::ShowWindow(m_hWnd, SW_SHOW);
	}
	else {
		
		char buf[100];
		DWORD err=GetLastError();
		COMLOGF(RT_D_DEBUG, "err(0x%X)",err);
		sprintf(buf, "Error x%x", err);
		// 0x716 means "The specified resource name cannot be found in the image file"
		// 0x716 means "The specified resource name cannot be found in the image file"
		MessageBoxA(0, buf, "CreateDialog", MB_ICONEXCLAMATION | MB_OK);
		
	}
	return m_hWnd;
	
}

BOOL CLuaDll::OnInitDialog(HWND hwndDlg, WPARAM wParam, LPARAM lParam)
{
	//	m_hWnd = hwndDlg;
	HICON	hIcon;
	hIcon = ::LoadIcon(NULL, IDI_ASTERISK);
	//	hIcon = ::LoadIcon( m_hInstance, MAKEINTRESOURCE( IDI_ICON_GREP ) );
	//	::SendMessage(m_hWnd, WM_SETICON, ICON_SMALL, (LPARAM)NULL );
	//	::SendMessage(m_hWnd, WM_SETICON, ICON_SMALL, (LPARAM)hIcon );
	//	::SendMessage(m_hWnd, WM_SETICON, ICON_BIG, (LPARAM)NULL );
	//	::SendMessage(m_hWnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon );
	
	//SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_COMBO1), TRUE);
	// ::SendDlgItemMessage(hwndDlg, IDC_COMBO1, CB_SETCURSEL, 0, 0);
	// ::SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_COMBO1), TRUE);
	
	return FALSE;
}

void CLuaDll::CloseDialog(void)
{
	
	//	::DestroyWindow(m_hWnd);
	
	return;
}
void InitGroupListTest(HINSTANCE hInst, HWND hDlg)
{
	TCHAR achTemp[256];
	DWORD dwIndex;
	
	// Get the handle of the food groups combo box.
	HWND hwndGroupsBox = GetDlgItem(hDlg, IDC_COMBO1);
	
	LoadString(hInst, IDS_TEST1, achTemp, sizeof(achTemp)/sizeof(TCHAR));
	dwIndex = SendMessageA(hwndGroupsBox, CB_ADDSTRING, 0, (LPARAM)achTemp);
	// SendMessage(hwndGroupsBox, CB_SETITEMDATA, dwIndex, (LPARAM) hbmBread);
	
	LoadString(hInst, IDS_TEST2, achTemp, sizeof(achTemp)/sizeof(TCHAR));
	dwIndex = SendMessageA(hwndGroupsBox, CB_ADDSTRING, 0, (LPARAM)achTemp);
	// SendMessage(hwndGroupsBox, CB_SETITEMDATA, dwIndex, (LPARAM) hbmDairy);
	
	LoadString(hInst, IDS_TEST3, achTemp, sizeof(achTemp)/sizeof(TCHAR));
	dwIndex = SendMessageA(hwndGroupsBox, CB_ADDSTRING, 0, (LPARAM)achTemp);
	// SendMessage(hwndGroupsBox, CB_SETITEMDATA, dwIndex, (LPARAM) hbmFruit); 
	
	LoadString(hInst, IDS_TEST4, achTemp, sizeof(achTemp)/sizeof(TCHAR));
	dwIndex = SendMessageA(hwndGroupsBox, CB_ADDSTRING, 0, (LPARAM)achTemp);
	// SendMessage(hwndGroupsBox, CB_SETITEMDATA, dwIndex, (LPARAM) hbmMeat);
	
	return;
}





