diff options
author | aunsane <aunsane@gmail.com> | 2018-05-20 21:10:10 +0300 |
---|---|---|
committer | aunsane <aunsane@gmail.com> | 2018-05-20 21:34:31 +0300 |
commit | a955d18f62f335f84e0926f351eb85d78224cba6 (patch) | |
tree | 7bd4d30040ec32bba5949dd2245cb68617fb4192 /plugins/MirLua/src/Modules/m_core.cpp | |
parent | 46363eef857b69761f1d6d28da5a53a954f76900 (diff) |
MirLua: project reordering
Diffstat (limited to 'plugins/MirLua/src/Modules/m_core.cpp')
-rw-r--r-- | plugins/MirLua/src/Modules/m_core.cpp | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/plugins/MirLua/src/Modules/m_core.cpp b/plugins/MirLua/src/Modules/m_core.cpp new file mode 100644 index 0000000000..027ff163ed --- /dev/null +++ b/plugins/MirLua/src/Modules/m_core.cpp @@ -0,0 +1,433 @@ +#include "../stdafx.h" + +static int core_CreateHookableEvent(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + + HANDLE res = CreateHookableEvent(name); + if (res != nullptr) + lua_pushlightuserdata(L, res); + else + lua_pushnil(L); + + return 1; +} + +int HookEventLuaParam(void *obj, WPARAM wParam, LPARAM lParam, LPARAM param) +{ + lua_State *L = (lua_State*)obj; + + int ref = param; + lua_rawgeti(L, LUA_REGISTRYINDEX, ref); + + if (wParam) + lua_pushlightuserdata(L, (void*)wParam); + else + lua_pushnil(L); + + if (lParam) + lua_pushlightuserdata(L, (void*)lParam); + else + lua_pushnil(L); + + luaM_pcall(L, 2, 1); + + return lua_tointeger(L, -1); +} + +int HookEventEnvParam(void *obj, WPARAM wParam, LPARAM lParam, LPARAM param) +{ + CMLuaEnvironment *env = (CMLuaEnvironment*)obj; + + int ref = param; + lua_rawgeti(env->L, LUA_REGISTRYINDEX, ref); + + if (wParam) + lua_pushlightuserdata(env->L, (void*)wParam); + else + lua_pushnil(env->L); + + if (lParam) + lua_pushlightuserdata(env->L, (void*)lParam); + else + lua_pushnil(env->L); + + luaM_pcall(env->L, 2, 1); + + return lua_tointeger(env->L, -1); +} + +static int core_HookEvent(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + luaL_checktype(L, 2, LUA_TFUNCTION); + + lua_pushvalue(L, 2); + int ref = luaL_ref(L, LUA_REGISTRYINDEX); + + HANDLE res = nullptr; + CMLuaEnvironment *env = CMLuaEnvironment::GetEnvironment(L); + if (env) { + res = HookEventObjParam(name, HookEventEnvParam, env, ref); + if (res) + env->AddHookRef(res, ref); + } + else + res = HookEventObjParam(name, HookEventLuaParam, L, ref); + + if (res == nullptr) { + luaL_unref(L, LUA_REGISTRYINDEX, ref); + lua_pushnil(L); + + return 1; + } + + lua_pushlightuserdata(L, res); + + return 1; +} + +static int core_HookTemporaryEvent(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + luaL_checktype(L, 2, LUA_TFUNCTION); + + lua_pushvalue(L, 2); + int ref = luaL_ref(L, LUA_REGISTRYINDEX); + + HANDLE res = nullptr; + CMLuaEnvironment *env = CMLuaEnvironment::GetEnvironment(L); + if (env) { + res = HookEventObjParam(name, HookEventEnvParam, env, ref); + if (res) + env->AddHookRef(res, ref); + } + else + res = HookEventObjParam(name, HookEventLuaParam, L, ref); + + // event does not exists, call hook immideatelly + if (res == nullptr) { + luaL_unref(L, LUA_REGISTRYINDEX, ref); + lua_pushnil(L); + lua_pushnil(L); + luaM_pcall(L, 2, 1); + return lua_tointeger(env->L, -1); + } + + lua_pushlightuserdata(L, res); + + return 1; +} + +static int core_UnhookEvent(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); + HANDLE hEvent = lua_touserdata(L, 1); + + int res = UnhookEvent(hEvent); + if (!res) { + CMLuaEnvironment *env = CMLuaEnvironment::GetEnvironment(L); + if (env) + env->ReleaseHookRef(hEvent); + } + lua_pushboolean(L, !res); + + return 1; +} + +static int core_NotifyEventHooks(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); + HANDLE hEvent = lua_touserdata(L, 1); + WPARAM wParam = (WPARAM)luaM_tomparam(L, 2); + LPARAM lParam = (LPARAM)luaM_tomparam(L, 3); + + int res = NotifyEventHooks(hEvent, wParam, lParam); + lua_pushboolean(L, res != -1); + + return 1; +} + +/***********************************************/ + +INT_PTR CreateServiceFunctionLuaStateParam(void *obj, WPARAM wParam, LPARAM lParam, LPARAM param) +{ + lua_State *L = (lua_State*)obj; + + int ref = param; + lua_rawgeti(L, LUA_REGISTRYINDEX, ref); + + lua_pushlightuserdata(L, (void*)wParam); + lua_pushlightuserdata(L, (void*)lParam); + luaM_pcall(L, 2, 1); + + INT_PTR res = lua_tointeger(L, 1); + lua_pushinteger(L, res); + + return res; +} + +INT_PTR CreateServiceFunctionEnvParam(void *obj, WPARAM wParam, LPARAM lParam, LPARAM param) +{ + CMLuaEnvironment *env = (CMLuaEnvironment*)obj; + + int ref = param; + lua_rawgeti(env->L, LUA_REGISTRYINDEX, ref); + + lua_pushlightuserdata(env->L, (void*)wParam); + lua_pushlightuserdata(env->L, (void*)lParam); + luaM_pcall(env->L, 2, 1); + + INT_PTR res = lua_tointeger(env->L, 1); + lua_pushinteger(env->L, res); + + return res; +} + +static int core_CreateServiceFunction(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + luaL_checktype(L, 2, LUA_TFUNCTION); + + lua_pushvalue(L, 2); + int ref = luaL_ref(L, LUA_REGISTRYINDEX); + + HANDLE res = nullptr; + CMLuaEnvironment *env = CMLuaEnvironment::GetEnvironment(L); + if (env) { + res = CreateServiceFunctionObjParam(name, CreateServiceFunctionEnvParam, env, ref); + if (res) + env->AddServiceRef(res, ref); + } + else + res = CreateServiceFunctionObjParam(name, CreateServiceFunctionLuaStateParam, L, ref); + + if (!res) { + luaL_unref(L, LUA_REGISTRYINDEX, ref); + lua_pushnil(L); + return 1; + } + + lua_pushlightuserdata(L, res); + + return 1; +} + +static int core_CallService(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + WPARAM wParam = (WPARAM)luaM_tomparam(L, 2); + LPARAM lParam = (LPARAM)luaM_tomparam(L, 3); + + INT_PTR res = CallService(name, wParam, lParam); + lua_pushinteger(L, res); + + return 1; +} + +static int core_ServiceExists(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + + int res = ServiceExists(name); + lua_pushboolean(L, res); + + return 1; +} + +static int core_DestroyServiceFunction(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); + HANDLE hService = lua_touserdata(L, 1); + + CMLuaEnvironment *env = CMLuaEnvironment::GetEnvironment(L); + if (env) + env->ReleaseHookRef(hService); + + DestroyServiceFunction(hService); + + return 0; +} + +/***********************************************/ + +static int core_IsPluginLoaded(lua_State *L) +{ + const char *value = lua_tostring(L, 1); + + MUUID uuid = { 0 }; + bool res = UuidFromStringA((RPC_CSTR)value, (UUID*)&uuid) == RPC_S_OK; + if (res) + res = IsPluginLoaded(uuid) > 0; + lua_pushboolean(L, res); + + return 1; +} + +static int core_Free(lua_State *L) +{ + if (lua_islightuserdata(L, 1)) + { + void *ptr = lua_touserdata(L, 1); + mir_free(ptr); + } + + return 0; +} + +static int core_Translate(lua_State *L) +{ + char *what = (char*)luaL_checkstring(L, 1); + + ptrW value(mir_utf8decodeW(what)); + lua_pushstring(L, T2Utf(TranslateW_LP(value, hLangpack))); + + return 1; +} + +static int core_Parse(lua_State *L) +{ + char *what = (char*)luaL_checkstring(L, 1); + + ptrW value(mir_utf8decodeW(what)); + lua_pushstring(L, T2Utf(VARSW(value))); + + return 1; +} + +static int core_GetFullPath(lua_State *L) +{ + wchar_t path[MAX_PATH]; + GetModuleFileName(nullptr, path, MAX_PATH); + + lua_pushstring(L, ptrA(mir_utf8encodeW(path))); + + return 1; +} + +/***********************************************/ + +struct core_ForkThreadParam +{ + lua_State *L; + int threadRef; + int functionRef; + HANDLE hThread; +}; + +std::map<HANDLE, core_ForkThreadParam*> lstThreads; + +void DestroyThread(core_ForkThreadParam *ftp) +{ + luaL_unref(ftp->L, LUA_REGISTRYINDEX, ftp->functionRef); + luaL_unref(ftp->L, LUA_REGISTRYINDEX, ftp->threadRef); + lstThreads.erase(ftp->hThread); + + delete ftp; +} + +void __cdecl ThreadFunc(void *p) +{ + core_ForkThreadParam *ftp = (core_ForkThreadParam*)p; + + lua_rawgeti(ftp->L, LUA_REGISTRYINDEX, ftp->functionRef); + luaM_pcall(ftp->L, 0, 1); + DestroyThread(ftp); +} + +static int core_ForkThread(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TFUNCTION); + + core_ForkThreadParam *p = new core_ForkThreadParam(); + + p->L = lua_newthread(L); + p->threadRef = luaL_ref(L, LUA_REGISTRYINDEX); + lua_pushvalue(L, 1); + p->functionRef = luaL_ref(L, LUA_REGISTRYINDEX); + + p->hThread = mir_forkthread(ThreadFunc, p); + lstThreads[p->hThread] = p; + lua_pushlightuserdata(L, p->hThread); + + return 1; +} + +static int core_TerminateThread(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); + HANDLE hThread = (HANDLE)lua_touserdata(L, 1); + + auto it = lstThreads.find(hThread); + if (it != lstThreads.end()) { + DestroyThread(it->second); + lua_pushboolean(L, TerminateThread(hThread, 0)); + } + else lua_pushboolean(L, 0); + + return 1; +} + +/***********************************************/ + +luaL_Reg coreApi[] = +{ + { "CreateHookableEvent", core_CreateHookableEvent }, + + { "NotifyEventHooks", core_NotifyEventHooks }, + + { "HookEvent", core_HookEvent }, + { "HookTemporaryEvent", core_HookTemporaryEvent }, + { "UnhookEvent", core_UnhookEvent }, + + { "CreateServiceFunction", core_CreateServiceFunction }, + { "DestroyServiceFunction", core_DestroyServiceFunction }, + + { "ServiceExists", core_ServiceExists }, + { "CallService", core_CallService }, + + { "IsPluginLoaded", core_IsPluginLoaded }, + + { "Free", core_Free }, + + { "Translate", core_Translate }, + + { "Parse", core_Parse }, + + { "GetFullPath", core_GetFullPath }, + + { "ForkThread", core_ForkThread }, + { "TerminateThread", core_TerminateThread }, + + { "Version", nullptr }, + + { "NULL", nullptr }, + { "INVALID_HANDLE_VALUE", nullptr }, + { "CALLSERVICE_NOTFOUND", nullptr }, + + { nullptr, nullptr } +}; + +/***********************************************/ + +LUAMOD_API int luaopen_m_core(lua_State *L) +{ + luaL_newlib(L, coreApi); + lua_pushlightuserdata(L, nullptr); + lua_setfield(L, -2, "NULL"); + lua_pushlightuserdata(L, INVALID_HANDLE_VALUE); + lua_setfield(L, -2, "INVALID_HANDLE_VALUE"); + lua_pushinteger(L, CALLSERVICE_NOTFOUND); + lua_setfield(L, -2, "CALLSERVICE_NOTFOUND"); + + char version[128]; + Miranda_GetVersionText(version, _countof(version)); + lua_pushstring(L, ptrA(mir_utf8encode(version))); + lua_setfield(L, -2, "Version"); + + // set copy to global variable m + lua_pushvalue(L, -1); + lua_setglobal(L, "m"); + + return 1; +}
\ No newline at end of file |