From a955d18f62f335f84e0926f351eb85d78224cba6 Mon Sep 17 00:00:00 2001 From: aunsane Date: Sun, 20 May 2018 21:10:10 +0300 Subject: MirLua: project reordering --- plugins/MirLua/src/Modules/m_chat.cpp | 25 + plugins/MirLua/src/Modules/m_clist.cpp | 140 ++++++ plugins/MirLua/src/Modules/m_core.cpp | 433 +++++++++++++++++ plugins/MirLua/src/Modules/m_database.cpp | 691 ++++++++++++++++++++++++++++ plugins/MirLua/src/Modules/m_genmenu.cpp | 95 ++++ plugins/MirLua/src/Modules/m_hotkeys.cpp | 103 +++++ plugins/MirLua/src/Modules/m_http.cpp | 443 ++++++++++++++++++ plugins/MirLua/src/Modules/m_icolib.cpp | 150 ++++++ plugins/MirLua/src/Modules/m_json.cpp | 243 ++++++++++ plugins/MirLua/src/Modules/m_message.cpp | 73 +++ plugins/MirLua/src/Modules/m_options.cpp | 117 +++++ plugins/MirLua/src/Modules/m_protocols.cpp | 281 +++++++++++ plugins/MirLua/src/Modules/m_sounds.cpp | 54 +++ plugins/MirLua/src/Modules/m_srmm.cpp | 138 ++++++ plugins/MirLua/src/environment.cpp | 101 ++++ plugins/MirLua/src/environment.h | 33 ++ plugins/MirLua/src/function_loader.cpp | 194 ++++++++ plugins/MirLua/src/function_loader.h | 14 + plugins/MirLua/src/icons.cpp | 33 ++ plugins/MirLua/src/m_chat.cpp | 25 - plugins/MirLua/src/m_clist.cpp | 100 ---- plugins/MirLua/src/m_core.cpp | 433 ----------------- plugins/MirLua/src/m_database.cpp | 691 ---------------------------- plugins/MirLua/src/m_database.h | 9 - plugins/MirLua/src/m_genmenu.cpp | 133 ------ plugins/MirLua/src/m_genmenu.h | 11 - plugins/MirLua/src/m_hotkeys.cpp | 103 ----- plugins/MirLua/src/m_http.cpp | 443 ------------------ plugins/MirLua/src/m_icolib.cpp | 155 ------- plugins/MirLua/src/m_json.cpp | 241 ---------- plugins/MirLua/src/m_json.h | 9 - plugins/MirLua/src/m_message.cpp | 73 --- plugins/MirLua/src/m_options.cpp | 117 ----- plugins/MirLua/src/m_protocols.cpp | 276 ----------- plugins/MirLua/src/m_protocols.h | 13 - plugins/MirLua/src/m_sounds.cpp | 56 --- plugins/MirLua/src/m_srmm.cpp | 138 ------ plugins/MirLua/src/metatable.h | 344 ++++++++++++++ plugins/MirLua/src/mlua_environment.cpp | 101 ---- plugins/MirLua/src/mlua_environment.h | 33 -- plugins/MirLua/src/mlua_function_loader.cpp | 194 -------- plugins/MirLua/src/mlua_function_loader.h | 14 - plugins/MirLua/src/mlua_icons.cpp | 33 -- plugins/MirLua/src/mlua_metatable.h | 347 -------------- plugins/MirLua/src/mlua_module_loader.cpp | 46 -- plugins/MirLua/src/mlua_module_loader.h | 17 - plugins/MirLua/src/mlua_options.cpp | 130 ------ plugins/MirLua/src/mlua_options.h | 31 -- plugins/MirLua/src/mlua_script.cpp | 137 ------ plugins/MirLua/src/mlua_script.h | 42 -- plugins/MirLua/src/mlua_script_loader.cpp | 70 --- plugins/MirLua/src/mlua_script_loader.h | 17 - plugins/MirLua/src/mlua_utils.cpp | 99 ---- plugins/MirLua/src/module_loader.cpp | 46 ++ plugins/MirLua/src/module_loader.h | 17 + plugins/MirLua/src/modules.h | 44 ++ plugins/MirLua/src/options.cpp | 131 ++++++ plugins/MirLua/src/options.h | 27 ++ plugins/MirLua/src/script.cpp | 137 ++++++ plugins/MirLua/src/script.h | 38 ++ plugins/MirLua/src/script_loader.cpp | 70 +++ plugins/MirLua/src/script_loader.h | 17 + plugins/MirLua/src/stdafx.h | 63 +-- plugins/MirLua/src/utils.cpp | 99 ++++ 64 files changed, 4342 insertions(+), 4389 deletions(-) create mode 100644 plugins/MirLua/src/Modules/m_chat.cpp create mode 100644 plugins/MirLua/src/Modules/m_clist.cpp create mode 100644 plugins/MirLua/src/Modules/m_core.cpp create mode 100644 plugins/MirLua/src/Modules/m_database.cpp create mode 100644 plugins/MirLua/src/Modules/m_genmenu.cpp create mode 100644 plugins/MirLua/src/Modules/m_hotkeys.cpp create mode 100644 plugins/MirLua/src/Modules/m_http.cpp create mode 100644 plugins/MirLua/src/Modules/m_icolib.cpp create mode 100644 plugins/MirLua/src/Modules/m_json.cpp create mode 100644 plugins/MirLua/src/Modules/m_message.cpp create mode 100644 plugins/MirLua/src/Modules/m_options.cpp create mode 100644 plugins/MirLua/src/Modules/m_protocols.cpp create mode 100644 plugins/MirLua/src/Modules/m_sounds.cpp create mode 100644 plugins/MirLua/src/Modules/m_srmm.cpp create mode 100644 plugins/MirLua/src/environment.cpp create mode 100644 plugins/MirLua/src/environment.h create mode 100644 plugins/MirLua/src/function_loader.cpp create mode 100644 plugins/MirLua/src/function_loader.h create mode 100644 plugins/MirLua/src/icons.cpp delete mode 100644 plugins/MirLua/src/m_chat.cpp delete mode 100644 plugins/MirLua/src/m_clist.cpp delete mode 100644 plugins/MirLua/src/m_core.cpp delete mode 100644 plugins/MirLua/src/m_database.cpp delete mode 100644 plugins/MirLua/src/m_database.h delete mode 100644 plugins/MirLua/src/m_genmenu.cpp delete mode 100644 plugins/MirLua/src/m_genmenu.h delete mode 100644 plugins/MirLua/src/m_hotkeys.cpp delete mode 100644 plugins/MirLua/src/m_http.cpp delete mode 100644 plugins/MirLua/src/m_icolib.cpp delete mode 100644 plugins/MirLua/src/m_json.cpp delete mode 100644 plugins/MirLua/src/m_json.h delete mode 100644 plugins/MirLua/src/m_message.cpp delete mode 100644 plugins/MirLua/src/m_options.cpp delete mode 100644 plugins/MirLua/src/m_protocols.cpp delete mode 100644 plugins/MirLua/src/m_protocols.h delete mode 100644 plugins/MirLua/src/m_sounds.cpp delete mode 100644 plugins/MirLua/src/m_srmm.cpp create mode 100644 plugins/MirLua/src/metatable.h delete mode 100644 plugins/MirLua/src/mlua_environment.cpp delete mode 100644 plugins/MirLua/src/mlua_environment.h delete mode 100644 plugins/MirLua/src/mlua_function_loader.cpp delete mode 100644 plugins/MirLua/src/mlua_function_loader.h delete mode 100644 plugins/MirLua/src/mlua_icons.cpp delete mode 100644 plugins/MirLua/src/mlua_metatable.h delete mode 100644 plugins/MirLua/src/mlua_module_loader.cpp delete mode 100644 plugins/MirLua/src/mlua_module_loader.h delete mode 100644 plugins/MirLua/src/mlua_options.cpp delete mode 100644 plugins/MirLua/src/mlua_options.h delete mode 100644 plugins/MirLua/src/mlua_script.cpp delete mode 100644 plugins/MirLua/src/mlua_script.h delete mode 100644 plugins/MirLua/src/mlua_script_loader.cpp delete mode 100644 plugins/MirLua/src/mlua_script_loader.h delete mode 100644 plugins/MirLua/src/mlua_utils.cpp create mode 100644 plugins/MirLua/src/module_loader.cpp create mode 100644 plugins/MirLua/src/module_loader.h create mode 100644 plugins/MirLua/src/modules.h create mode 100644 plugins/MirLua/src/options.cpp create mode 100644 plugins/MirLua/src/options.h create mode 100644 plugins/MirLua/src/script.cpp create mode 100644 plugins/MirLua/src/script.h create mode 100644 plugins/MirLua/src/script_loader.cpp create mode 100644 plugins/MirLua/src/script_loader.h create mode 100644 plugins/MirLua/src/utils.cpp (limited to 'plugins/MirLua/src') diff --git a/plugins/MirLua/src/Modules/m_chat.cpp b/plugins/MirLua/src/Modules/m_chat.cpp new file mode 100644 index 0000000000..c1a2a65d9b --- /dev/null +++ b/plugins/MirLua/src/Modules/m_chat.cpp @@ -0,0 +1,25 @@ +#include "../stdafx.h" + +static luaL_Reg chatApi[] = +{ + { nullptr, nullptr } +}; + +LUAMOD_API int luaopen_m_chat(lua_State *L) +{ + luaL_newlib(L, chatApi); + + MT(L, "GCEVENT") + .Field(&GCEVENT::pszModule, "Module", LUA_TSTRINGA) + .Field(&GCEVENT::ptszID, "Id", LUA_TSTRINGW) + .Field(&GCEVENT::iType, "Type", LUA_TINTEGER) + .Field(&GCEVENT::time, "Timestamp", LUA_TINTEGER) + .Field(&GCEVENT::time, "IsMe", LUA_TINTEGER) + .Field(&GCEVENT::time, "Flags", LUA_TINTEGER) + .Field(&GCEVENT::ptszNick, "Nick", LUA_TSTRINGW) + .Field(&GCEVENT::ptszUID, "Uid", LUA_TSTRINGW) + .Field(&GCEVENT::ptszStatus, "Status", LUA_TSTRINGW) + .Field(&GCEVENT::ptszText, "Text", LUA_TSTRINGW); + + return 1; +} diff --git a/plugins/MirLua/src/Modules/m_clist.cpp b/plugins/MirLua/src/Modules/m_clist.cpp new file mode 100644 index 0000000000..5e5b7475b8 --- /dev/null +++ b/plugins/MirLua/src/Modules/m_clist.cpp @@ -0,0 +1,140 @@ +#include "../stdafx.h" + + + +void MakeMenuItem(lua_State *L, CMenuItem &mi) +{ + mi.langId = CMLuaEnvironment::GetEnvironmentId(L); + + lua_getfield(L, -1, "Flags"); + mi.flags = lua_tointeger(L, -1); + lua_pop(L, 1); + + if (!(mi.flags & CMIF_UNICODE)) + mi.flags |= CMIF_UNICODE; + + lua_getfield(L, -1, "Uid"); + const char* uuid = lua_tostring(L, -1); + if (UuidFromStringA((RPC_CSTR)uuid, (UUID*)&mi.uid)) + UNSET_UID(mi); + lua_pop(L, 1); + + lua_getfield(L, -1, "Name"); + mi.name.w = mir_utf8decodeW(luaL_checkstring(L, -1)); + lua_pop(L, 1); + + lua_getfield(L, -1, "Position"); + mi.position = lua_tointeger(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "Icon"); + mi.hIcolibItem = (HANDLE)lua_touserdata(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "Service"); + mi.pszService = lua_tostring(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "Parent"); + mi.root = (HGENMENU)lua_touserdata(L, -1); + lua_pop(L, 1); +} + +static int clist_AddMainMenuRoot(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + int position = lua_tointeger(L, 2); + HANDLE hIcon = (HANDLE)lua_touserdata(L, 3); + + HGENMENU res = Menu_CreateRoot(MO_MAIN, ptrW(Utf8DecodeW(name)), position, hIcon); + if (res != nullptr) + lua_pushlightuserdata(L, res); + else + lua_pushnil(L); + + return 1; +} + +static int clist_AddMainMenuItem(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + CMenuItem mi; + MakeMenuItem(L, mi); + + HGENMENU res = Menu_AddMainMenuItem(&mi); + if (res != nullptr) + lua_pushlightuserdata(L, res); + else + lua_pushnil(L); + + return 1; +} + +static int clist_AddContactMenuRoot(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + int position = lua_tointeger(L, 2); + HANDLE hIcon = (HANDLE)lua_touserdata(L, 3); + + HGENMENU res = Menu_CreateRoot(MO_MAIN, ptrW(Utf8DecodeW(name)), position, hIcon); + if (res != nullptr) + lua_pushlightuserdata(L, res); + else + lua_pushnil(L); + + return 1; +} + +static int clist_AddContactMenuItem(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + CMenuItem mi; + MakeMenuItem(L, mi); + + ptrA szProto(mir_utf8decodeA(lua_tostring(L, 2))); + HGENMENU res = Menu_AddContactMenuItem(&mi, szProto); + if (res != nullptr) + lua_pushlightuserdata(L, res); + else + lua_pushnil(L); + + return 1; +} + +static int clist_AddTrayMenuItem(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + CMenuItem mi; + MakeMenuItem(L, mi); + + HGENMENU res = Menu_AddTrayMenuItem(&mi); + if (res != nullptr) + lua_pushlightuserdata(L, res); + else + lua_pushnil(L); + + return 1; +} + +static luaL_Reg clistApi[] = +{ + { "AddMainMenuRoot", clist_AddMainMenuRoot }, + { "AddMainMenuItem", clist_AddMainMenuItem }, + + { "AddContactMenuRoot", clist_AddContactMenuRoot }, + { "AddContactMenuItem", clist_AddContactMenuItem }, + + { "AddTrayMenuItem", clist_AddTrayMenuItem }, + + { nullptr, nullptr } +}; + +LUAMOD_API int luaopen_m_clist(lua_State *L) +{ + luaL_newlib(L, clistApi); + + return 1; +} 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 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 diff --git a/plugins/MirLua/src/Modules/m_database.cpp b/plugins/MirLua/src/Modules/m_database.cpp new file mode 100644 index 0000000000..3d0d53ba48 --- /dev/null +++ b/plugins/MirLua/src/Modules/m_database.cpp @@ -0,0 +1,691 @@ +#include "../stdafx.h" + +void luaM_pushdbvt(lua_State *L, const DBVARIANT &value) +{ + switch (value.type) { + case DBVT_BYTE: + lua_pushinteger(L, value.bVal); + break; + case DBVT_WORD: + lua_pushinteger(L,value.wVal); + break; + case DBVT_DWORD: + lua_pushnumber(L, value.dVal); + break; + case DBVT_ASCIIZ: + lua_pushstring(L, ptrA(mir_utf8encode(value.pszVal))); + break; + case DBVT_UTF8: + lua_pushstring(L, value.pszVal); + break; + case DBVT_WCHAR: + lua_pushstring(L, ptrA(mir_utf8encodeW(value.pwszVal))); + break; + case DBVT_BLOB: + { + lua_createtable(L, value.cpbVal, 0); + for (int i = 0; i < value.cpbVal; i++) { + lua_pushinteger(L, value.pbVal[i]); + lua_rawseti(L, -2, i + 1); + } + } + break; + default: + lua_pushnil(L); + } +} + +/***********************************************/ + +static int db_ContactIterator(lua_State *L) +{ + MCONTACT hContact = lua_tointeger(L, lua_upvalueindex(1)); + const char *szModule = lua_tostring(L, lua_upvalueindex(2)); + + hContact = hContact == NULL + ? db_find_first(szModule) + : db_find_next(hContact, szModule); + + if (hContact) { + lua_pushinteger(L, hContact); + lua_pushvalue(L, -1); + lua_replace(L, lua_upvalueindex(1)); + } + else + lua_pushnil(L); + + return 1; +} + +static int db_Contacts(lua_State *L) +{ + const char *szModule = nullptr; + + switch (lua_type(L, 1)) { + case LUA_TNONE: + break; + case LUA_TSTRING: + szModule = lua_tostring(L, 1); + break; + case LUA_TUSERDATA: + { + PROTOACCOUNT **pa = (PROTOACCOUNT**)luaL_checkudata(L, 1, MT_PROTOACCOUNT); + szModule = (*pa)->szModuleName; + break; + } + default: + luaL_argerror(L, 1, luaL_typename(L, 1)); + } + + lua_pushinteger(L, 0); + lua_pushstring(L, szModule); + lua_pushcclosure(L, db_ContactIterator, 2); + + return 1; +} + +static const char *mods[] = +{ + "FirstName", + "LastName", + "Nick", + "CustomNick", + "Email", + "City", + "State", + "Country", + "Phone", + "Homepage", + "About", + "Gender", + "Age", + "FullName", + "Uid", + "DisplayName", + nullptr +}; + +static int db_GetContactInfo(lua_State *L) +{ + MCONTACT hContact = luaL_checkinteger(L, 1); + + int type = 0; + switch (lua_type(L, 2)) { + case LUA_TNUMBER: + type = luaL_checkinteger(L, 2); + break; + case LUA_TSTRING: + type = luaL_checkoption(L, 2, nullptr, mods) + 1; + break; + default: + luaL_argerror(L, 2, luaL_typename(L, 2)); + } + + ptrW value(Contact_GetInfo(type, hContact)); + if (value) + lua_pushstring(L, ptrA(mir_utf8encodeW(value))); + else + lua_pushnil(L); + + return 1; +} + +/***********************************************/ + +static int db_GetEventCount(lua_State *L) +{ + MCONTACT hContact = luaL_checkinteger(L, 1); + + int res = db_event_count(hContact); + lua_pushinteger(L, res); + + return 1; +} + +static int db_GetFirstEvent(lua_State *L) +{ + MCONTACT hContact = luaL_checkinteger(L, 1); + + MEVENT res = db_event_first(hContact); + lua_pushinteger(L, res); + + return 1; +} + +static int db_GetPrevEvent(lua_State *L) +{ + MCONTACT hContact = luaL_checkinteger(L, 1); + MEVENT hDbEvent = luaL_checkinteger(L, 2); + + MEVENT res = db_event_prev(hContact, hDbEvent); + lua_pushinteger(L, res); + + return 1; +} + +static int db_GetNextEvent(lua_State *L) +{ + MCONTACT hContact = luaL_checkinteger(L, 1); + MEVENT hDbEvent = luaL_checkinteger(L, 2); + + MEVENT res = db_event_next(hContact, hDbEvent); + lua_pushinteger(L, res); + + return 1; +} + +static int db_GetLastEvent(lua_State *L) +{ + MCONTACT hContact = luaL_checkinteger(L, 1); + + MEVENT res = db_event_last(hContact); + lua_pushinteger(L, res); + + return 1; +} + +static int db_GetFirstUnreadEvent(lua_State *L) +{ + MCONTACT hContact = luaL_checkinteger(L, 1); + + MEVENT res = db_event_firstUnread(hContact); + lua_pushinteger(L, res); + + return 1; +} + +static int db_EventIterator(lua_State *L) +{ + MCONTACT hContact = luaL_checkinteger(L, lua_upvalueindex(1)); + MEVENT hDbEvent = luaL_checkinteger(L, lua_upvalueindex(2)); + + hDbEvent = hDbEvent == NULL + ? db_event_first(hContact) + : db_event_next(hContact, hDbEvent); + + if (hDbEvent) { + lua_pushinteger(L, hDbEvent); + lua_pushvalue(L, -1); + lua_replace(L, lua_upvalueindex(2)); + } + else + lua_pushnil(L); + + return 1; +} + +static int db_Events(lua_State *L) +{ + MCONTACT hContact = luaL_checkinteger(L, 1); + + lua_pushinteger(L, hContact); + lua_pushinteger(L, NULL); + lua_pushcclosure(L, db_EventIterator, 2); + + return 1; +} + +static int db_EventReverseIterator(lua_State *L) +{ + MCONTACT hContact = luaL_checkinteger(L, lua_upvalueindex(1)); + MEVENT hDbEvent = luaL_checkinteger(L, lua_upvalueindex(2)); + + hDbEvent = hDbEvent == NULL + ? db_event_last(hContact) + : db_event_prev(hContact, hDbEvent); + + if (hDbEvent) { + lua_pushinteger(L, hDbEvent); + lua_pushvalue(L, -1); + lua_replace(L, lua_upvalueindex(2)); + } + else + lua_pushnil(L); + + return 1; +} + +static int db_EventsFromEnd(lua_State *L) +{ + MCONTACT hContact = luaL_checkinteger(L, 1); + + lua_pushinteger(L, hContact); + lua_pushinteger(L, NULL); + lua_pushcclosure(L, db_EventReverseIterator, 2); + + return 1; +} + +static int db_UnreadEventIterator(lua_State *L) +{ + MCONTACT hContact = luaL_checkinteger(L, lua_upvalueindex(1)); + MEVENT hDbEvent = luaL_checkinteger(L, lua_upvalueindex(2)); + + hDbEvent = db_event_firstUnread(hContact); + + if (hDbEvent) { + lua_pushinteger(L, hDbEvent); + lua_pushvalue(L, -1); + lua_replace(L, lua_upvalueindex(2)); + } + else + lua_pushnil(L); + + return 1; +} + +static int db_UnreadEvents(lua_State *L) +{ + MCONTACT hContact = luaL_checkinteger(L, 1); + + lua_pushinteger(L, hContact); + lua_pushinteger(L, NULL); + lua_pushcclosure(L, db_UnreadEventIterator, 2); + + return 1; +} + +void MakeDbEvent(lua_State *L, DBEVENTINFO &dbei) +{ + lua_getfield(L, -1, "Module"); + dbei.szModule = mir_strdup(lua_tostring(L, -1)); + lua_pop(L, 1); + + lua_getfield(L, -1, "Type"); + dbei.eventType = lua_tointeger(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "Timestamp"); + dbei.timestamp = lua_tonumber(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "Flags"); + dbei.flags = lua_tointeger(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "Blob"); + switch (lua_type(L, -1)) { + case LUA_TTABLE: + dbei.cbBlob = (DWORD)lua_rawlen(L, 4); + dbei.pBlob = (BYTE*)mir_calloc(dbei.cbBlob); + for (DWORD i = 0; i < dbei.cbBlob; i++) { + lua_geti(L, 4, i + 1); + dbei.pBlob[i] = lua_tointeger(L, -1); + lua_pop(L, 1); + } + break; + case LUA_TSTRING: + size_t nLen; + const char *str = lua_tolstring(L, -1, &nLen); + dbei.cbBlob = (DWORD)nLen; + dbei.pBlob = (BYTE*)mir_alloc(nLen); + memcpy(dbei.pBlob, str, nLen); + break; + } + lua_pop(L, 1); +} + +static int db_AddEvent(lua_State *L) +{ + MCONTACT hContact = luaL_checkinteger(L, 1); + + DBEVENTINFO dbei; + MakeDbEvent(L, dbei); + MEVENT hDbEvent = db_event_add(hContact, &dbei); + + if (hDbEvent) + lua_pushnumber(L, hDbEvent); + else + lua_pushnil(L); + + return 1; +} + +static int db_MarkReadEvent(lua_State *L) +{ + MCONTACT hContact = luaL_checkinteger(L, 1); + MEVENT hDbEvent = luaL_checkinteger(L, 2); + + int res = db_event_markRead(hContact, hDbEvent); + lua_pushnumber(L, res); + + return 1; +} + +/***********************************************/ + +static int ModulesEnumProc(const char *szModuleName, void *lParam) +{ + if (szModuleName) { + LIST* p = (LIST*)lParam; + p->insert(mir_strdup(szModuleName)); + } + + return 0; +} + +static int db_ModulesIterator(lua_State *L) +{ + int i = lua_tointeger(L, lua_upvalueindex(1)); + LIST ¶m = *(LIST*)lua_touserdata(L, lua_upvalueindex(2)); + + if (i < param.getCount()) { + lua_pushinteger(L, (i + 1)); + lua_replace(L, lua_upvalueindex(1)); + lua_pushstring(L, ptrA(mir_utf8encode(param[i]))); + mir_free(param[i]); + } + else { + lua_pushnil(L); + delete ¶m; + } + + return 1; +} + +static int db_Modules(lua_State *L) +{ + LIST *param = new LIST(5, PtrKeySortT); + + db_enum_modules(ModulesEnumProc, param); + + lua_pushinteger(L, 0); + lua_pushlightuserdata(L, param); + lua_pushcclosure(L, db_ModulesIterator, 2); + + return 1; +} + +static int db_DeleteModule(lua_State *L) +{ + MCONTACT hContact = lua_tointeger(L, 1); + const char *szModule = luaL_checkstring(L, 2); + + INT_PTR res = db_delete_module(hContact, szModule); + lua_pushboolean(L, !res); + + return 1; +} + +static int SettingsEnumProc(const char* szSetting, void *lParam) +{ + if (szSetting ) { + LIST* p = (LIST*)lParam; + p->insert(mir_strdup(szSetting)); + } + return 0; +} + +static int db_SettingIterator(lua_State *L) +{ + int i = lua_tointeger(L, lua_upvalueindex(1)); + LIST ¶m = *(LIST*)lua_touserdata(L, lua_upvalueindex(2)); + + if (i < param.getCount()) { + lua_pushinteger(L, (i + 1)); + lua_replace(L, lua_upvalueindex(1)); + lua_pushstring(L, ptrA(mir_utf8encode(param[i]))); + mir_free(param[i]); + } + else { + lua_pushnil(L); + delete ¶m; + } + + return 1; +} + +static int db_Settings(lua_State *L) +{ + MCONTACT hContact = lua_tointeger(L, 1); + const char* szModule = luaL_checkstring(L, 2); + + LIST *param = new LIST(5, PtrKeySortT); + db_enum_settings(hContact, SettingsEnumProc, szModule, param); + + lua_pushinteger(L, 0); + lua_pushlightuserdata(L, param); + lua_pushcclosure(L, db_SettingIterator, 2); + + return 1; +} + +static int db_GetSetting(lua_State *L) +{ + MCONTACT hContact = lua_tointeger(L, 1); + const char *szModule = luaL_checkstring(L, 2); + const char *szSetting = luaL_checkstring(L, 3); + + DBVARIANT dbv; + if (db_get(hContact, szModule, szSetting, &dbv)) { + lua_pushvalue(L, 4); + return 1; + } + + luaM_pushdbvt(L, dbv); + db_free(&dbv); + + if (lua_isnil(L, -1) && !lua_isnoneornil(L, 4)) { + lua_pop(L, 1); + lua_pushvalue(L, 4); + } + + return 1; +} + +static int db_WriteSetting(lua_State *L) +{ + MCONTACT hContact = lua_tointeger(L, 1); + const char *szModule = luaL_checkstring(L, 2); + const char *szSetting = luaL_checkstring(L, 3); + luaL_checkany(L, 4); + + DBVARIANT dbv; + if (lua_isnoneornil(L, 5)) { + int type = lua_type(L, 4); + switch (type) { + case LUA_TBOOLEAN: + dbv.type = DBVT_BYTE; + break; + case LUA_TNUMBER: + dbv.type = DBVT_DWORD; + break; + case LUA_TSTRING: + dbv.type = DBVT_UTF8; + break; + case LUA_TTABLE: + dbv.type = DBVT_BLOB; + break; + default: + lua_pushboolean(L, false); + return 1; + } + } + else + dbv.type = luaL_checkinteger(L, 5); + + switch (dbv.type) { + case DBVT_BYTE: + dbv.bVal = lua_isboolean(L, 4) + ? lua_toboolean(L, 4) + : luaL_checknumber(L, 4); + break; + case DBVT_WORD: + dbv.wVal = luaL_checknumber(L, 4); + break; + case DBVT_DWORD: + dbv.dVal = luaL_checknumber(L, 4); + break; + case DBVT_UTF8: + dbv.pszVal = mir_strdup(luaL_checkstring(L, 4)); + break; + case DBVT_ASCIIZ: + dbv.pszVal = mir_utf8decodeA(luaL_checkstring(L, 4)); + break; + case DBVT_WCHAR: + dbv.pwszVal = mir_utf8decodeW(luaL_checkstring(L, 4)); + break; + case DBVT_BLOB: + { + dbv.cpbVal = (WORD)lua_rawlen(L, 4); + dbv.pbVal = (BYTE*)mir_calloc(dbv.cpbVal); + for (int i = 0; i < dbv.cpbVal; i++) { + lua_geti(L, 4, i + 1); + dbv.pbVal[i] = lua_tointeger(L, -1); + lua_pop(L, 1); + } + } + break; + default: + lua_pushboolean(L, false); + return 1; + } + + INT_PTR res = db_set(hContact, szModule, szSetting, &dbv); + lua_pushboolean(L, !res); + + return 1; +} + +static int db_DeleteSetting(lua_State *L) +{ + MCONTACT hContact = lua_tointeger(L, 1); + LPCSTR szModule = luaL_checkstring(L, 2); + LPCSTR szSetting = luaL_checkstring(L, 3); + + INT_PTR res = db_unset(hContact, szModule, szSetting); + lua_pushboolean(L, !res); + + return 1; +} + +/***********************************************/ + +static luaL_Reg databaseApi[] = +{ + { "Contacts", db_Contacts }, + { "GetContactInfo", db_GetContactInfo }, + + { "GetEventCount", db_GetEventCount }, + + { "GetFirstEvent", db_GetFirstEvent }, + { "GetPrevEvent", db_GetPrevEvent }, + { "GetNextEvent", db_GetNextEvent }, + { "GetLastEvent", db_GetLastEvent }, + { "GetFirstUnreadEvent", db_GetFirstUnreadEvent }, + { "Events", db_Events }, + { "EventsFromEnd", db_EventsFromEnd }, + { "UnreadEvents", db_UnreadEvents }, + { "AddEvent", db_AddEvent }, + { "MarkReadEvent", db_MarkReadEvent }, + + { "Settings", db_Settings }, + { "Modules", db_Modules }, + + { "DeleteModule", db_DeleteModule }, + + { "GetSetting", db_GetSetting }, + { "WriteSetting", db_WriteSetting }, + { "SetSetting", db_WriteSetting }, + { "DeleteSetting", db_DeleteSetting }, + + { "DBVT_BYTE", nullptr }, + { "DBVT_WORD", nullptr }, + { "DBVT_DWORD", nullptr }, + { "DBVT_ASCIIZ", nullptr }, + { "DBVT_UTF8", nullptr }, + { "DBVT_WCHAR", nullptr }, + + { nullptr, nullptr } +}; + +/***********************************************/ + +#define MT_DBCONTACTWRITESETTING "DBCONTACTWRITESETTING" + +template <> +int MT::Get(lua_State *L, DBCONTACTWRITESETTING *dbcw) +{ + const char *key = luaL_checkstring(L, 2); + + if (mir_strcmpi(key, "Value") == 0) + luaM_pushdbvt(L, dbcw->value); + else + lua_pushnil(L); + + return 1; +} + +/***********************************************/ + +#define MT_DBEVENTINFO "DBEVENTINFO" + +template <> +DBEVENTINFO* MT::Init(lua_State *L) +{ + MEVENT hDbEvent = luaL_checkinteger(L, 1); + + DBEVENTINFO* dbei = (DBEVENTINFO*)mir_calloc(sizeof(DBEVENTINFO)); + dbei->cbBlob = db_event_getBlobSize((MEVENT)hDbEvent); + dbei->pBlob = (PBYTE)mir_calloc(dbei->cbBlob); + db_event_get((MEVENT)hDbEvent, dbei); + + return dbei; +} + +template <> +int MT::Get(lua_State *L, DBEVENTINFO *dbei) +{ + const char *key = luaL_checkstring(L, 2); + + if (mir_strcmpi(key, "Blob") == 0) { + lua_createtable(L, dbei->cbBlob, 0); + for (DWORD i = 0; i < dbei->cbBlob; i++) { + lua_pushinteger(L, dbei->pBlob[i]); + lua_rawseti(L, -2, i + 1); + } + } + else + lua_pushnil(L); + + return 1; +} + +template <> +void MT::Free(lua_State*, DBEVENTINFO **dbei) +{ + mir_free((*dbei)->pBlob); + mir_free(*dbei); +} + +/***********************************************/ + +LUAMOD_API int luaopen_m_database(lua_State *L) +{ + luaL_newlib(L, databaseApi); + + lua_pushnumber(L, DBVT_BYTE); + lua_setfield(L, -2, "DBVT_BYTE"); + lua_pushnumber(L, DBVT_WORD); + lua_setfield(L, -2, "DBVT_WORD"); + lua_pushnumber(L, DBVT_DWORD); + lua_setfield(L, -2, "DBVT_DWORD"); + lua_pushnumber(L, DBVT_ASCIIZ); + lua_setfield(L, -2, "DBVT_ASCIIZ"); + lua_pushnumber(L, DBVT_UTF8); + lua_setfield(L, -2, "DBVT_UTF8"); + lua_pushnumber(L, DBVT_WCHAR); + lua_setfield(L, -2, "DBVT_WCHAR"); + + MT(L, MT_DBCONTACTWRITESETTING) + .Field(&DBCONTACTWRITESETTING::szModule, "Module", LUA_TSTRINGA) + .Field(&DBCONTACTWRITESETTING::szSetting, "Setting", LUA_TSTRINGA); + + MT(L, MT_DBEVENTINFO) + .Field(&DBEVENTINFO::szModule, "Module", LUA_TSTRINGA) + .Field(&DBEVENTINFO::timestamp, "Timestamp", LUA_TINTEGER) + .Field(&DBEVENTINFO::eventType, "Type", LUA_TINTEGER) + .Field(&DBEVENTINFO::flags, "Flags", LUA_TINTEGER); + + return 1; +} diff --git a/plugins/MirLua/src/Modules/m_genmenu.cpp b/plugins/MirLua/src/Modules/m_genmenu.cpp new file mode 100644 index 0000000000..0c2d0ab492 --- /dev/null +++ b/plugins/MirLua/src/Modules/m_genmenu.cpp @@ -0,0 +1,95 @@ +#include "../stdafx.h" + +static int genmenu_ModifyMenuItem(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); + HGENMENU hMenuItem = (HGENMENU)lua_touserdata(L, 1); + ptrW name(mir_utf8decodeW(lua_tostring(L, 2))); + HANDLE hIcolibItem = luaL_opt(L, lua_touserdata, 3, INVALID_HANDLE_VALUE); + int flags = luaL_optinteger(L, 4, -1); + + if (!(flags & CMIF_UNICODE)) + flags |= CMIF_UNICODE; + + INT_PTR res = Menu_ModifyItem(hMenuItem, name, hIcolibItem, flags); + lua_pushboolean(L, res == 0); + + return 1; +} + +static int genmenu_ConfigureMenuItem(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); + HGENMENU hMenuItem = (HGENMENU)lua_touserdata(L, 1); + int option = luaL_checkinteger(L, 2); + luaL_checktype(L, 3, LUA_TLIGHTUSERDATA); + INT_PTR value = (INT_PTR)lua_touserdata(L, 3); + + int res = Menu_ConfigureItem(hMenuItem, option, value); + lua_pushboolean(L, res >= 0); + + return 1; +} + +static int genmenu_ShowMenuItem(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); + HGENMENU hMenuItem = (HGENMENU)lua_touserdata(L, 1); + bool isShow = luaM_toboolean(L, 2); + + Menu_ShowItem(hMenuItem, isShow); + + return 0; +} + +static int genmenu_EnableMenuItem(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); + HGENMENU hMenuItem = (HGENMENU)lua_touserdata(L, 1); + bool isEnable = luaM_toboolean(L, 2); + + Menu_EnableItem(hMenuItem, isEnable); + + return 0; +} + +static int genmenu_CheckMenuItem(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); + HGENMENU hMenuItem = (HGENMENU)lua_touserdata(L, 1); + bool isChecked = luaM_toboolean(L, 2); + + Menu_SetChecked(hMenuItem, isChecked); + + return 0; +} + +static int genmenu_RemoveMenuItem(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); + HGENMENU hMenuItem = (HGENMENU)lua_touserdata(L, 1); + + INT_PTR res = Menu_RemoveItem(hMenuItem); + lua_pushboolean(L, res == 0); + + return 1; +} + +static luaL_Reg genmenuApi[] = +{ + { "ModifyMenuItem", genmenu_ModifyMenuItem }, + { "ConfigureMenuItem", genmenu_ConfigureMenuItem }, + { "ShowMenuItem", genmenu_ShowMenuItem }, + { "EnableMenuItem", genmenu_EnableMenuItem }, + { "CheckMenuItem", genmenu_CheckMenuItem }, + { "RemoveMenuItem", genmenu_RemoveMenuItem }, + + { nullptr, nullptr } +}; + +LUAMOD_API int luaopen_m_genmenu(lua_State *L) +{ + luaL_newlib(L, genmenuApi); + + return 1; +} diff --git a/plugins/MirLua/src/Modules/m_hotkeys.cpp b/plugins/MirLua/src/Modules/m_hotkeys.cpp new file mode 100644 index 0000000000..1245d2348f --- /dev/null +++ b/plugins/MirLua/src/Modules/m_hotkeys.cpp @@ -0,0 +1,103 @@ +#include "../stdafx.h" + +void MakeHotkey(lua_State *L, HOTKEYDESC &hk) +{ + lua_getfield(L, -1, "Flags"); + hk.dwFlags = lua_tointeger(L, -1); + lua_pop(L, 1); + + if (!(hk.dwFlags & HKD_UNICODE)) + hk.dwFlags |= HKD_UNICODE; + + lua_getfield(L, -1, "Name"); + hk.pszName = mir_utf8decodeA(luaL_checkstring(L, -1)); + lua_pop(L, 1); + + lua_getfield(L, -1, "Description"); + hk.szDescription.w = mir_utf8decodeW(lua_tostring(L, -1)); + lua_pop(L, 1); + + lua_getfield(L, -1, "Section"); + hk.szSection.w = mir_utf8decodeW(luaL_optstring(L, -1, MODULENAME)); + lua_pop(L, 1); + + lua_getfield(L, -1, "Hotkey"); + hk.DefHotKey = lua_tointeger(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "Service"); + hk.pszService = mir_utf8decodeA(luaL_checkstring(L, -1)); + lua_pop(L, 1); + + lua_getfield(L, -1, "lParam"); + hk.lParam = (LPARAM)lua_touserdata(L, -1); + lua_pop(L, 1); +} + +static int hotkeys_Register(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + HOTKEYDESC hk; + MakeHotkey(L, hk); + + int hScriptLangpack = CMLuaEnvironment::GetEnvironmentId(L); + + INT_PTR res = Hotkey_Register(&hk, hScriptLangpack); + lua_pushboolean(L, res); + + return 1; +} + +static int hotkeys_Unregister(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + + Hotkey_Unregister(name); + + return 0; +} + +static const char *mods[] = { "shift", "ctrl", "alt", "ext", nullptr }; + +static int hotkeys_MakeHotkey(lua_State *L) +{ + int mod = 0; + switch (lua_type(L, 1)) + { + case LUA_TNUMBER: + mod = luaL_checkinteger(L, 1); + break; + case LUA_TSTRING: + mod = (1 << (luaL_checkoption(L, 1, nullptr, mods) - 1)); + break; + case LUA_TTABLE: + for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 1)) + mod |= (1 << (luaL_checkoption(L, -1, nullptr, mods) - 1)); + break; + default: + luaL_argerror(L, 1, luaL_typename(L, 1)); + } + int vk = luaL_checknumber(L, 2); + + WORD res = HOTKEYCODE(mod, vk); + lua_pushinteger(L, res); + + return 1; +} + +static luaL_Reg hotkeysApi[] = +{ + { "MakeHotkey", hotkeys_MakeHotkey }, + { "Register", hotkeys_Register }, + { "Unregister", hotkeys_Unregister }, + + { nullptr, nullptr } +}; + +LUAMOD_API int luaopen_m_hotkeys(lua_State *L) +{ + luaL_newlib(L, hotkeysApi); + + return 1; +} diff --git a/plugins/MirLua/src/Modules/m_http.cpp b/plugins/MirLua/src/Modules/m_http.cpp new file mode 100644 index 0000000000..31def57a9a --- /dev/null +++ b/plugins/MirLua/src/Modules/m_http.cpp @@ -0,0 +1,443 @@ +#include "../stdafx.h" + +/***********************************************/ + +#define MT_NETLIBHTTPHEADERS "NETLIBHTTPHEADERS" + +struct NETLIBHTTPHEADERS +{ + const NETLIBHTTPHEADER *headers; + int count; +}; + +static void AddHeader(NETLIBHTTPREQUEST *request, const char *name, const char *value) +{ + request->headers = (NETLIBHTTPHEADER*)mir_realloc(request->headers, + sizeof(NETLIBHTTPHEADER)*(request->headersCount + 1)); + NETLIBHTTPHEADER &header = request->headers[request->headersCount]; + header.szName = mir_strdup(name); + header.szValue = mir_strdup(value); + request->headersCount++; +} + +static void SetHeader(NETLIBHTTPREQUEST *request, const char *name, const char *value) +{ + for (int i = 0; i < request->headersCount; i++) { + if (mir_strcmp(request->headers[i].szName, name) == 0) { + mir_free(request->headers[i].szValue); + request->headers[i].szValue = mir_strdup(value); + return; + } + } + AddHeader(request, name, value); +} + +static int headers_Iterator(lua_State *L) +{ + NETLIBHTTPHEADER *headers = (NETLIBHTTPHEADER*)lua_touserdata(L, lua_upvalueindex(1)); + int count = lua_tointeger(L, lua_upvalueindex(2)); + int idx = lua_tointeger(L, lua_upvalueindex(3)); + + if (idx < count) { + lua_pushstring(L, headers[idx].szName); + lua_pushstring(L, headers[idx].szValue); + lua_pushinteger(L, idx + 1); + lua_replace(L, lua_upvalueindex(3)); + return 2; + } + + lua_pushnil(L); + + return 1; +} + +static int headers__call(lua_State *L) +{ + NETLIBHTTPHEADERS *headers = (NETLIBHTTPHEADERS*)luaL_checkudata(L, 1, MT_NETLIBHTTPHEADERS); + + lua_pushlightuserdata(L, (void*)headers->headers); + lua_pushinteger(L, headers->count); + lua_pushinteger(L, 0); + lua_pushcclosure(L, headers_Iterator, 3); + + return 1; +} + +static int headers__index(lua_State *L) +{ + NETLIBHTTPHEADERS *headers = (NETLIBHTTPHEADERS*)luaL_checkudata(L, 1, MT_NETLIBHTTPHEADERS); + + if (lua_isinteger(L, 2)) { + int idx = lua_tointeger(L, 2); + if (idx > 0 && idx <= headers->count) { + lua_pushstring(L, headers->headers[idx - 1].szValue); + return 1; + } + } + + const char *key = lua_tostring(L, 2); + for (int i = 0; i < headers->count; i++) { + if (mir_strcmp(headers->headers[i].szName, key) == 0) { + lua_pushstring(L, headers->headers[i].szValue); + return 1; + } + } + + lua_pushnil(L); + + return 1; +} + +static int headers__len(lua_State *L) +{ + NETLIBHTTPHEADERS *headers = (NETLIBHTTPHEADERS*)luaL_checkudata(L, 1, MT_NETLIBHTTPHEADERS); + + lua_pushinteger(L, headers->count); + + return 1; +} + +static const luaL_Reg headersApi[] = +{ + { "__call", headers__call }, + { "__index", headers__index }, + { "__len", headers__len }, + + { nullptr, nullptr } +}; + +/***********************************************/ + +#define MT_NETLIBHTTPCONTENT "NETLIBHTTPCONTENT" + +struct NETLIBHTTPCONTENT +{ + const char *data; + int length; +}; + +static int content__index(lua_State *L) +{ + NETLIBHTTPCONTENT *content = (NETLIBHTTPCONTENT*)luaL_checkudata(L, 1, MT_NETLIBHTTPCONTENT); + + int idx = luaL_checkinteger(L, 2); + if (idx > 0 && idx <= content->length) { + lua_pushinteger(L, content->data[idx - 1]); + return 1; + } + + lua_pushnil(L); + + return 1; +} + +static int content__len(lua_State *L) +{ + NETLIBHTTPCONTENT *content = (NETLIBHTTPCONTENT*)luaL_checkudata(L, 1, MT_NETLIBHTTPCONTENT); + + lua_pushinteger(L, content->length); + + return 1; +} + +static int content__tostring(lua_State *L) +{ + NETLIBHTTPCONTENT *content = (NETLIBHTTPCONTENT*)luaL_checkudata(L, 1, MT_NETLIBHTTPCONTENT); + + lua_pushlstring(L, content->data, content->length); + + return 1; +} + +static const luaL_Reg contentApi[] = +{ + { "__index", content__index }, + { "__len", content__len }, + { "__tostring", content__tostring }, + + { nullptr, nullptr } +}; + +/***********************************************/ + +#define MT_NETLIBHTTPRESPONSE "NETLIBHTTPRESPONSE" + +static NETLIBHTTPREQUEST* response_Create(lua_State *L, NETLIBHTTPREQUEST *request) +{ + NETLIBHTTPREQUEST **response = (NETLIBHTTPREQUEST**)lua_newuserdata(L, sizeof(NETLIBHTTPREQUEST*)); + *response = Netlib_HttpTransaction(hNetlib, request); + luaL_setmetatable(L, MT_NETLIBHTTPRESPONSE); + + return *response; +} + +static int response__index(lua_State *L) +{ + NETLIBHTTPREQUEST *response = *(NETLIBHTTPREQUEST**)luaL_checkudata(L, 1, MT_NETLIBHTTPRESPONSE); + const char *key = lua_tostring(L, 2); + + if (mir_strcmpi(key, "Headers") == 0) { + NETLIBHTTPHEADERS *headers = (NETLIBHTTPHEADERS*)lua_newuserdata(L, sizeof(NETLIBHTTPHEADERS)); + headers->headers = response->headers; + headers->count = response->headersCount; + luaL_setmetatable(L, MT_NETLIBHTTPHEADERS); + } + else if (mir_strcmpi(key, "Content") == 0) { + NETLIBHTTPCONTENT *content = (NETLIBHTTPCONTENT*)lua_newuserdata(L, sizeof(NETLIBHTTPCONTENT)); + content->data = response->pData; + content->length = response->dataLength; + luaL_setmetatable(L, MT_NETLIBHTTPCONTENT); + } + else if (mir_strcmpi(key, "StatusCode") == 0) + lua_pushinteger(L, response->resultCode); + else if (mir_strcmpi(key, "IsSuccess") == 0) { + lua_pushboolean(L, HTTP_CODE_SUCCESS(response->resultCode)); + } + else + lua_pushnil(L); + + return 1; +} + +static int response__gc(lua_State *L) +{ + NETLIBHTTPREQUEST **response = (NETLIBHTTPREQUEST**)luaL_checkudata(L, 1, MT_NETLIBHTTPRESPONSE); + + Netlib_FreeHttpRequest(*response); + + return 0; +} + +static const luaL_Reg responseApi[] = +{ + { "__index", response__index }, + { "__gc", response__gc }, + + { nullptr, nullptr } +}; + +/***********************************************/ + +#define MT_NETLIBHTTPREQUEST "NETLIBHTTPREQUEST" + +static NETLIBHTTPREQUEST* CreateRequest(lua_State *L) +{ + NETLIBHTTPREQUEST **request = (NETLIBHTTPREQUEST**)lua_newuserdata(L, sizeof(NETLIBHTTPREQUEST*)); + *request = (NETLIBHTTPREQUEST*)mir_calloc(sizeof(NETLIBHTTPREQUEST)); + (*request)->cbSize = sizeof(NETLIBHTTPREQUEST); + (*request)->flags = NLHRF_HTTP11 | NLHRF_NODUMP; + + luaL_setmetatable(L, MT_NETLIBHTTPREQUEST); + + return *request; +} + +static void request_SetUrl(lua_State *L, int idx, NETLIBHTTPREQUEST *request) +{ + const char *url = luaL_checkstring(L, idx); + request->szUrl = mir_strdup(url); + if (mir_strncmpi(request->szUrl, "https", 5) == 0) + request->flags |= NLHRF_SSL; + else + request->flags &= ~(NLHRF_SSL); +} + +static void request_SetHeaders(lua_State *L, int idx, NETLIBHTTPREQUEST *request) +{ + if (lua_isnoneornil(L, idx)) + return; + + luaL_checktype(L, idx, LUA_TTABLE); + + idx = lua_absindex(L, idx); + for (lua_pushnil(L); lua_next(L, idx); lua_pop(L, 2)) { + lua_pushvalue(L, -2); + const char *name = lua_tostring(L, -1); + const char *value = lua_tostring(L, -2); + AddHeader(request, name, value); + } +} + +static void request_SetContent(lua_State *L, int idx, NETLIBHTTPREQUEST *request) +{ + CMStringA data; + + switch (lua_type(L, idx)) + { + case LUA_TNONE: + case LUA_TNIL: + return; + case LUA_TSTRING: + data = lua_tostring(L, idx); + SetHeader(request, "Content-Type", "text/plain"); + break; + case LUA_TTABLE: + { + idx = lua_absindex(L, idx); + for (lua_pushnil(L); lua_next(L, idx); lua_pop(L, 2)) { + lua_pushvalue(L, -2); + const char *name = lua_tostring(L, -1); + const char *value = lua_tostring(L, -2); + data.AppendFormat("&%s=%s", name, value); + } + data.Delete(0); + SetHeader(request, "Content-Type", "application/x-www-form-urlencoded"); + break; + } + default: + luaL_argerror(L, idx, luaL_typename(L, idx)); + } + + request->pData = mir_strdup(data); + request->dataLength = data.GetLength(); +} + +static void request_SetContentType(lua_State *L, int idx, NETLIBHTTPREQUEST *request) +{ + if (!lua_isstring(L, idx)) + return; + + const char *type = lua_tostring(L, idx); + SetHeader(request, "Content-Type", type); +} + +static const char *httpMethods[] = { "GET", "POST", "PUT", "DELETE", nullptr }; + +static int request_Send(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + NETLIBHTTPREQUEST *request = CreateRequest(L); + + lua_getfield(L, 1, "Method"); + request->requestType = (1 << (luaL_checkoption(L, -1, nullptr, httpMethods))); + lua_pop(L, 1); + + lua_getfield(L, 1, "Url"); + request_SetUrl(L, -1, request); + lua_pop(L, 1); + + lua_getfield(L, 1, "Headers"); + request_SetHeaders(L, -1, request); + lua_pop(L, 1); + + lua_getfield(L, 1, "Content"); + request_SetContent(L, -1, request); + lua_pop(L, 1); + + lua_getfield(L, 1, "Timeout"); + request->timeout = luaL_optinteger(L, -1, 0); + lua_pop(L, 1); + + response_Create(L, request); + + return 1; +} + +static int request_Get(lua_State *L) +{ + NETLIBHTTPREQUEST *request = CreateRequest(L); + request->requestType = REQUEST_GET; + request_SetUrl(L, 1, request); + + response_Create(L, request); + + return 1; +} + +static int request_Post(lua_State *L) +{ + NETLIBHTTPREQUEST *request = CreateRequest(L); + request->requestType = REQUEST_POST; + request_SetUrl(L, 1, request); + request_SetContent(L, 2, request); + request_SetContentType(L, 3, request); + + response_Create(L, request); + + return 1; +} + +static int request_Put(lua_State *L) +{ + NETLIBHTTPREQUEST *request = CreateRequest(L); + request->requestType = REQUEST_PUT; + request_SetUrl(L, 1, request); + request_SetContent(L, 2, request); + request_SetContentType(L, 3, request); + + response_Create(L, request); + + return 1; +} + +static int request_Delete(lua_State *L) +{ + NETLIBHTTPREQUEST *request = CreateRequest(L); + request->requestType = REQUEST_DELETE; + request_SetUrl(L, 1, request); + request_SetContent(L, 2, request); + request_SetContentType(L, 2, request); + + response_Create(L, request); + + return 1; +} + +static int request__gc(lua_State *L) +{ + NETLIBHTTPREQUEST **request = (NETLIBHTTPREQUEST**)luaL_checkudata(L, 1, MT_NETLIBHTTPREQUEST); + + mir_free((*request)->szUrl); + for (int i = 0; i < (*request)->headersCount; i++) { + mir_free((*request)->headers[i].szName); + mir_free((*request)->headers[i].szValue); + } + mir_free((*request)->headers); + mir_free((*request)->pData); + + return 0; +} + +static const luaL_Reg requestApi[] = +{ + { "__gc", request__gc }, + + { nullptr, nullptr } +}; + +/***********************************************/ + +static const luaL_Reg httpApi[] = +{ + { "Send", request_Send }, + { "Get", request_Get }, + { "Post", request_Post }, + { "Put", request_Put }, + { "Delete", request_Delete }, + + { nullptr, nullptr } +}; + +LUAMOD_API int luaopen_m_http(lua_State *L) +{ + luaL_newlib(L, httpApi); + + luaL_newmetatable(L, MT_NETLIBHTTPREQUEST); + luaL_setfuncs(L, requestApi, 0); + lua_pop(L, 1); + + luaL_newmetatable(L, MT_NETLIBHTTPRESPONSE); + luaL_setfuncs(L, responseApi, 0); + lua_pop(L, 1); + + luaL_newmetatable(L, MT_NETLIBHTTPHEADERS); + luaL_setfuncs(L, headersApi, 0); + lua_pop(L, 1); + + luaL_newmetatable(L, MT_NETLIBHTTPCONTENT); + luaL_setfuncs(L, contentApi, 0); + lua_pop(L, 1); + + return 1; +} diff --git a/plugins/MirLua/src/Modules/m_icolib.cpp b/plugins/MirLua/src/Modules/m_icolib.cpp new file mode 100644 index 0000000000..86b5163290 --- /dev/null +++ b/plugins/MirLua/src/Modules/m_icolib.cpp @@ -0,0 +1,150 @@ +#include "../stdafx.h" + +static void MakeSKINICONDESC(lua_State *L, SKINICONDESC &sid) +{ + lua_getfield(L, -1, "Flags"); + sid.flags = lua_tointeger(L, -1); + lua_pop(L, 1); + + if (!(sid.flags & SIDF_ALL_UNICODE)) + sid.flags |= SIDF_ALL_UNICODE; + + lua_getfield(L, -1, "Name"); + sid.pszName = mir_utf8decodeA(luaL_checkstring(L, -1)); + lua_pop(L, 1); + + lua_getfield(L, -1, "Description"); + sid.description.w = mir_utf8decodeW(luaL_checkstring(L, -1)); + lua_pop(L, 1); + + lua_getfield(L, -1, "Section"); + sid.section.w = mir_utf8decodeW(luaL_optstring(L, 3, MODULENAME)); + lua_pop(L, 1); + + lua_getfield(L, -1, "DefaultFile"); + sid.defaultFile.w = mir_utf8decodeW(lua_tostring(L, -1)); + lua_pop(L, 1); + + if (sid.defaultFile.w == nullptr) { + sid.defaultFile.w = (wchar_t*)mir_calloc(MAX_PATH + 1); + GetModuleFileName(g_plugin.getInst(), sid.defaultFile.w, MAX_PATH); + } + + lua_getfield(L, -1, "DefaultIndex"); + sid.iDefaultIndex = lua_tointeger(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "DefaultIcon"); + sid.hDefaultIcon = (HICON)lua_touserdata(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "SizeX"); + sid.iDefaultIndex = lua_tointeger(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "SizeY"); + sid.iDefaultIndex = lua_tointeger(L, -1); + lua_pop(L, 1); +} + +static int lua_AddIcon(lua_State *L) +{ + SKINICONDESC sid = { }; + + if (lua_type(L, 1) == LUA_TSTRING) { + sid.flags = SIDF_ALL_UNICODE; + sid.pszName = mir_utf8decodeA(luaL_checkstring(L, 1)); + sid.description.w = mir_utf8decodeW(luaL_checkstring(L, 2)); + sid.section.w = mir_utf8decodeW(luaL_optstring(L, 3, MODULENAME)); + sid.defaultFile.w = mir_utf8decodeW(lua_tostring(L, 4)); + sid.hDefaultIcon = GetIcon(IDI_SCRIPT); + + if (sid.defaultFile.w == nullptr) { + sid.defaultFile.w = (wchar_t*)mir_calloc(MAX_PATH + 1); + GetModuleFileName(g_plugin.getInst(), sid.defaultFile.w, MAX_PATH); + } + } + else if (lua_type(L, 1) == LUA_TTABLE) + MakeSKINICONDESC(L, sid); + else + luaL_argerror(L, 1, luaL_typename(L, 1)); + + int hScriptLangpack = CMLuaEnvironment::GetEnvironmentId(L); + HANDLE res = IcoLib_AddIcon(&sid, hScriptLangpack); + lua_pushlightuserdata(L, res); + + mir_free((void*)sid.pszName); + mir_free((void*)sid.description.w); + mir_free((void*)sid.section.w); + mir_free((void*)sid.defaultFile.w); + + return 1; +} + +static int lua_GetIcon(lua_State *L) +{ + bool big = luaM_toboolean(L, 2); + + HICON hIcon = nullptr; + switch (lua_type(L, 1)) { + case LUA_TLIGHTUSERDATA: + hIcon = IcoLib_GetIconByHandle(lua_touserdata(L, 1), big); + break; + case LUA_TSTRING: + hIcon = IcoLib_GetIcon(lua_tostring(L, 1), big); + break; + default: + luaL_argerror(L, 1, luaL_typename(L, 1)); + } + + if (hIcon) + lua_pushlightuserdata(L, hIcon); + else + lua_pushnil(L); + + return 1; +} + +static int lua_GetIconHandle(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + + HANDLE res = IcoLib_GetIconHandle(name); + lua_pushlightuserdata(L, res); + + return 1; +} + +static int lua_RemoveIcon(lua_State *L) +{ + switch (lua_type(L, 1)) { + case LUA_TLIGHTUSERDATA: + IcoLib_RemoveIconByHandle(lua_touserdata(L, 1)); + break; + case LUA_TSTRING: + IcoLib_RemoveIcon(luaL_checkstring(L, 1)); + break; + default: + luaL_argerror(L, 1, luaL_typename(L, 1)); + } + + return 0; +} + +static luaL_Reg icolibApi[] = +{ + { "AddIcon", lua_AddIcon }, + { "GetIcon", lua_GetIcon }, + { "GetHandle", lua_GetIconHandle }, + { "GetIconHandle", lua_GetIconHandle }, + { "RemoveIcon", lua_RemoveIcon }, + + { nullptr, nullptr } +}; + +LUAMOD_API int luaopen_m_icolib(lua_State *L) +{ + luaL_newlib(L, icolibApi); + + return 1; +} diff --git a/plugins/MirLua/src/Modules/m_json.cpp b/plugins/MirLua/src/Modules/m_json.cpp new file mode 100644 index 0000000000..24e32cab09 --- /dev/null +++ b/plugins/MirLua/src/Modules/m_json.cpp @@ -0,0 +1,243 @@ +#include "../stdafx.h" + +#define MT_JSON "JSON" + +static void lua2json(lua_State *L, JSONNode &node) +{ + switch (lua_type(L, -1)) { + case LUA_TNIL: + node.nullify(); + break; + case LUA_TSTRING: + node = lua_tostring(L, -1); + break; + case LUA_TBOOLEAN: + node = lua_toboolean(L, -1) != 0; + break; + case LUA_TNUMBER: + { + lua_Integer val = lua_tointeger(L, -1); + if (lua_isinteger(L, -1) && val >= LONG_MIN && val <= LONG_MIN) + node = (long)val; + else + node = lua_tonumber(L, -1); + break; + } + case LUA_TTABLE: + { + ptrA name(mir_strdup(node.name())); + node.cast(JSON_ARRAY); + node.set_name((char*)name); + + lua_pushnil(L); + while (lua_next(L, -2) != 0) { + JSONNode child; + if (!lua_isnumber(L, -2)) { + if (node.type() == JSON_ARRAY) { + node.cast(JSON_NODE); + node.set_name((char*)name); + } + const char *key = lua_tostring(L, -2); + child.set_name(key); + } + lua2json(L, child); + node << child; + + lua_pop(L, 1); + } + + break; + } + } +} + +/***********************************************/ + +static int json__index(lua_State *L) +{ + JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); + + JSONNode *child; + if (node->type() == JSON_ARRAY) { + int idx = lua_tointeger(L, 2); + child = &node->at(idx - 1); + } + else { + const char *key = lua_tostring(L, 2); + child = &node->at(key); + } + + switch (child->type()) + { + case JSON_NULL: + lua_pushnil(L); + break; + case JSON_STRING: + lua_pushstring(L, child->as_string().c_str()); + break; + case JSON_NUMBER: + lua_pushnumber(L, child->as_int()); + break; + case JSON_BOOL: + lua_pushboolean(L, child->as_bool()); + break; + case JSON_ARRAY: + case JSON_NODE: + JSONNode **udata = (JSONNode**)lua_newuserdata(L, sizeof(JSONNode*)); + *udata = child; + luaL_setmetatable(L, MT_JSON); + } + + return 1; +} + +static int json__newindex(lua_State *L) +{ + JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); + const char *key = lua_tostring(L, 2); + + if (json_type(node) == JSON_ARRAY) { + int idx = lua_tointeger(L, 2); + JSONNode *child = json_at(node, idx - 1); + lua2json(L, *child); + return 0; + } + + JSONNode *child = json_get(node, key); + if (json_type(child) == JSON_NULL) { + json_set_name(child, key); + lua2json(L, *child); + json_push_back(node, child); + return 0; + } + + lua2json(L, *child); + + return 0; +} + +static int json__len(lua_State *L) +{ + JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); + lua_pushnumber(L, json_size(node)); + + return 1; +} + +static int json__tostring(lua_State *L) +{ + JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); + + lua_pushstring(L, node->write().c_str()); + + return 1; +} + +static int json__gc(lua_State *L) +{ + JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); + + json_delete(node); + + return 0; +} + +const struct luaL_Reg jsonApi[] = +{ + { "__index", json__index }, + { "__newindex", json__newindex }, + { "__len", json__len }, + { "__tostring", json__tostring }, + { "__gc", json__gc }, + + { nullptr, nullptr } +}; + + +/***********************************************/ + +static int lua_Decode(lua_State *L) +{ + const char *string = luaL_checkstring(L, 1); + + JSONNode **udata = (JSONNode**)lua_newuserdata(L, sizeof(JSONNode*)); + *udata = json_parse(string); + luaL_setmetatable(L, MT_JSON); + + return 1; +} + +static int lua_Encode(lua_State *L) +{ + switch (lua_type(L, 1)) { + case LUA_TNIL: + lua_pushliteral(L, "null"); + break; + case LUA_TBOOLEAN: + lua_pushstring(L, lua_toboolean(L, 1) ? "true" : "false"); + break; + case LUA_TNUMBER: + { + if (lua_isinteger(L, 1)) { + lua_pushfstring(L, "%I", lua_tointeger(L, 1)); + break; + } + char decpoint = lua_getlocaledecpoint(); + if (decpoint != '.') { + char p[2] = { decpoint }; + luaL_gsub(L, lua_tostring(L, 1), p, "."); + } + else + lua_pushfstring(L, "%f", lua_tonumber(L, 1)); + break; + } + case LUA_TSTRING: + lua_pushfstring(L, "\"%s\"", lua_tostring(L, 1)); + break; + case LUA_TTABLE: + { + JSONNode node; + lua_pushnil(L); + lua_pushvalue(L, 1); + lua2json(L, node); + lua_pop(L, 2); + lua_pushstring(L, node.write().c_str()); + break; + } + case LUA_TUSERDATA: + { + JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); + lua_pushstring(L, node->write().c_str()); + break; + } + case LUA_TLIGHTUSERDATA: + if (lua_touserdata(L, 1) == nullptr) + { + lua_pushliteral(L, "null"); + break; + } + default: + luaL_argerror(L, 1, luaL_typename(L, 1)); + } + + return 1; +} + +static const luaL_Reg methods[] = +{ + { "Decode", lua_Decode }, + { "Encode", lua_Encode }, + + { nullptr, nullptr } +}; + +LUAMOD_API int luaopen_m_json(lua_State *L) +{ + luaL_newlib(L, methods); + + luaL_newmetatable(L, MT_JSON); + luaL_setfuncs(L, jsonApi, 0); + lua_pop(L, 1); + + return 1; +} \ No newline at end of file diff --git a/plugins/MirLua/src/Modules/m_message.cpp b/plugins/MirLua/src/Modules/m_message.cpp new file mode 100644 index 0000000000..c369237796 --- /dev/null +++ b/plugins/MirLua/src/Modules/m_message.cpp @@ -0,0 +1,73 @@ +#include "../stdafx.h" + +static int message_Paste(lua_State *L) +{ + MCONTACT hContact = luaL_checkinteger(L, 1); + ptrW text(mir_utf8decodeW(luaL_checkstring(L, 2))); + + MessageWindowData mwd; + INT_PTR res = Srmm_GetWindowData(hContact, mwd); + lua_pushinteger(L, res); + if (res) + return 1; + + HWND hEdit = GetDlgItem(mwd.hwndWindow, 1002 /*IDC_MESSAGE*/); + if (!hEdit) hEdit = GetDlgItem(mwd.hwndWindow, 1009 /*IDC_CHATMESSAGE*/); + + SendMessage(hEdit, EM_REPLACESEL, TRUE, (LPARAM)text); + + return 1; +} + +static int message_Send(lua_State *L) +{ + MCONTACT hContact = luaL_checkinteger(L, 1); + const char *message = luaL_checkstring(L, 2); + + INT_PTR res = 1; + + const char *szProto = GetContactProto(hContact); + if (db_get_b(hContact, szProto, "ChatRoom", 0) == TRUE) { + ptrW wszChatRoom(db_get_wsa(hContact, szProto, "ChatRoomID")); + ptrW wszMessage(mir_utf8decodeW(message)); + res = Chat_SendUserMessage(szProto, wszChatRoom, wszMessage); + lua_pushinteger(L, res); + } + else if ((res = ProtoChainSend(hContact, PSS_MESSAGE, 0, (LPARAM)message)) != ACKRESULT_FAILED) { + DBEVENTINFO dbei = {}; + dbei.szModule = MODULENAME; + dbei.timestamp = time(0); + dbei.eventType = EVENTTYPE_MESSAGE; + dbei.cbBlob = (DWORD)mir_strlen(message); + dbei.pBlob = (PBYTE)mir_strdup(message); + dbei.flags = DBEF_UTF | DBEF_SENT; + db_event_add(hContact, &dbei); + + lua_pushinteger(L, res); + return 1; + } + + lua_pushinteger(L, res); + + return 1; +} + +static luaL_Reg messageApi[] = +{ + { "Paste", message_Paste }, + { "Send", message_Send }, + + { nullptr, nullptr } +}; + +LUAMOD_API int luaopen_m_message(lua_State *L) +{ + luaL_newlib(L, messageApi); + + MT(L, "MessageWindowEventData") + .Field(&MessageWindowEventData::uType, "Type", LUA_TINTEGER) + .Field(&MessageWindowEventData::hContact, "hContact", LUA_TINTEGER) + .Field(&MessageWindowEventData::uFlags, "Flags", LUA_TINTEGER); + + return 1; +} diff --git a/plugins/MirLua/src/Modules/m_options.cpp b/plugins/MirLua/src/Modules/m_options.cpp new file mode 100644 index 0000000000..babcfe3909 --- /dev/null +++ b/plugins/MirLua/src/Modules/m_options.cpp @@ -0,0 +1,117 @@ +#include "../stdafx.h" + +class CMLuaScriptOptionPage : public CDlgBase +{ +private: + int m_onInitDialogRef; + int m_onApplyRef; + lua_State *L; + +public: + CMLuaScriptOptionPage(lua_State *_L, int onInitDialogRef, int onApplyRef) + : CDlgBase(g_plugin, IDD_SCRIPTOPTIONSPAGE), L(_L), + m_onInitDialogRef(onInitDialogRef), m_onApplyRef(onApplyRef) + { + } + + void OnInitDialog() override + { + if (m_onInitDialogRef) + { + lua_rawgeti(L, LUA_REGISTRYINDEX, m_onInitDialogRef); + lua_pushlightuserdata(L, m_hwnd); + luaM_pcall(L, 1, 0); + } + } + + void OnApply() override + { + if (m_onApplyRef) + { + lua_rawgeti(L, LUA_REGISTRYINDEX, m_onApplyRef); + lua_pushlightuserdata(L, m_hwnd); + luaM_pcall(L, 1, 0); + } + } + + void OnDestroy() override + { + lua_pushnil(L); + lua_rawsetp(L, LUA_REGISTRYINDEX, this); + } +}; + +void MakeOptionDialogPage(lua_State *L, OPTIONSDIALOGPAGE &odp) +{ + odp.hInstance = g_plugin.getInst(); + odp.langId = CMLuaEnvironment::GetEnvironmentId(L); + + lua_getfield(L, -1, "Flags"); + odp.flags = luaL_optinteger(L, -1, ODPF_BOLDGROUPS | ODPF_UNICODE | ODPF_DONTTRANSLATE); + lua_pop(L, 1); + + if (!(odp.flags & ODPF_UNICODE)) + odp.flags |= ODPF_UNICODE; + + lua_getfield(L, -1, "Group"); + odp.szGroup.w = mir_utf8decodeW(lua_tostring(L, -1)); + lua_pop(L, 1); + + lua_getfield(L, -1, "Title"); + odp.szTitle.w = mir_utf8decodeW(luaL_checkstring(L, -1)); + lua_pop(L, 1); + + lua_getfield(L, -1, "Tab"); + odp.szTab.w = mir_utf8decodeW(lua_tostring(L, -1)); + lua_pop(L, 1); + + int onInitDialogRef = LUA_NOREF; + lua_getfield(L, -1, "OnInitDialog"); + if (lua_isfunction(L, -1)) + onInitDialogRef = luaL_ref(L, LUA_REGISTRYINDEX); + else + lua_pop(L, 1); + + int onApplyRef = LUA_NOREF; + lua_getfield(L, -1, "OnApply"); + if (lua_isfunction(L, -1)) + onApplyRef = luaL_ref(L, LUA_REGISTRYINDEX); + else + lua_pop(L, 1); + + lua_State *T = lua_newthread(L); + lua_rawsetp(L, LUA_REGISTRYINDEX, T); + odp.pDialog = new CMLuaScriptOptionPage(T, onInitDialogRef, onApplyRef); +} + +int opt_AddPage(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); + WPARAM wParam = (WPARAM)lua_touserdata(L, 1); + + OPTIONSDIALOGPAGE odp = { 0 }; + MakeOptionDialogPage(L, odp); + + INT_PTR res = Options_AddPage(wParam, &odp); + lua_pushboolean(L, !res); + + mir_free(odp.szGroup.w); + mir_free(odp.szTitle.w); + mir_free(odp.szTab.w); + + return 1; +} + +static luaL_Reg optionsApi[] = +{ + { "AddPage", opt_AddPage }, + + { nullptr, nullptr } +}; + +LUAMOD_API int luaopen_m_options(lua_State *L) +{ + luaL_newlib(L, optionsApi); + + return 1; +} \ No newline at end of file diff --git a/plugins/MirLua/src/Modules/m_protocols.cpp b/plugins/MirLua/src/Modules/m_protocols.cpp new file mode 100644 index 0000000000..1dac3e3ea6 --- /dev/null +++ b/plugins/MirLua/src/Modules/m_protocols.cpp @@ -0,0 +1,281 @@ +#include "../stdafx.h" + +#define MT_PROTOCOLDESCRIPTOR "PROTOCOLDESCRIPTOR" + +HANDLE hRecvMessage = nullptr; + +static int lua_GetProtocol(lua_State *L) +{ + const char *szProto = nullptr; + + switch (lua_type(L, 1)) { + case LUA_TNUMBER: + { + const char *szModule = GetContactProto(lua_tonumber(L, 1)); + PROTOACCOUNT *pa = Proto_GetAccount(szModule); + if (pa) + szProto = pa->szProtoName; + break; + } + case LUA_TSTRING: + szProto = lua_tostring(L, 1); + break; + default: + luaL_argerror(L, 1, luaL_typename(L, 1)); + } + + PROTOCOLDESCRIPTOR *pd = Proto_IsProtocolLoaded(szProto); + if (pd) + MT::Apply(L, pd); + else + lua_pushnil(L); + + return 1; +} + +static int lua_ProtocolIterator(lua_State *L) +{ + int i = lua_tointeger(L, lua_upvalueindex(1)); + int count = lua_tointeger(L, lua_upvalueindex(2)); + PROTOCOLDESCRIPTOR **protos = (PROTOCOLDESCRIPTOR**)lua_touserdata(L, lua_upvalueindex(3)); + + if (i < count) { + lua_pushinteger(L, (i + 1)); + lua_replace(L, lua_upvalueindex(1)); + MT::Apply(L, protos[i]); + } + else + lua_pushnil(L); + + return 1; +} + +static int lua_Protocols(lua_State *L) +{ + int count; + PROTOCOLDESCRIPTOR **protos; + Proto_EnumProtocols(&count, &protos); + + lua_pushinteger(L, 0); + lua_pushinteger(L, count); + lua_pushlightuserdata(L, protos); + lua_pushcclosure(L, lua_ProtocolIterator, 3); + + return 1; +} + +static int lua_ChainSend(lua_State *L) +{ + MCONTACT hContact = luaL_checknumber(L, 1); + const char *service = luaL_checkstring(L, 2); + WPARAM wParam = (WPARAM)luaM_tomparam(L, 3); + LPARAM lParam = (LPARAM)luaM_tomparam(L, 4); + + INT_PTR res = ProtoChainSend(hContact, service, wParam, lParam); + lua_pushinteger(L, res); + + return 1; +} + +static int lua_ChainRecv(lua_State *L) +{ + MCONTACT hContact = luaL_checknumber(L, 1); + const char *service = luaL_checkstring(L, 2); + WPARAM wParam = (WPARAM)luaM_tomparam(L, 3); + LPARAM lParam = (LPARAM)luaM_tomparam(L, 4); + + INT_PTR res = ProtoChainRecv(hContact, service, wParam, lParam); + lua_pushinteger(L, res); + + return 1; +} + +/***********************************************/ + +static int lua_GetAccount(lua_State *L) +{ + const char *name = nullptr; + + switch (lua_type(L, 1)) + { + case LUA_TNUMBER: + name = GetContactProto(lua_tonumber(L, 1)); + break; + case LUA_TSTRING: + name = lua_tostring(L, 1); + break; + default: + luaL_argerror(L, 1, luaL_typename(L, 1)); + } + + PROTOACCOUNT *pa = Proto_GetAccount(name); + if (pa) + MT::Apply(L, pa); + else + lua_pushnil(L); + + return 1; +} + +static int lua_AccountIterator(lua_State *L) +{ + int i = lua_tointeger(L, lua_upvalueindex(1)); + int count = lua_tointeger(L, lua_upvalueindex(2)); + PROTOACCOUNT **accounts = (PROTOACCOUNT**)lua_touserdata(L, lua_upvalueindex(3)); + const char *szProto = lua_tostring(L, lua_upvalueindex(4)); + + if (szProto) + while (i < count && mir_strcmp(szProto, accounts[i]->szProtoName)) + i++; + + if (i < count) + { + lua_pushinteger(L, (i + 1)); + lua_replace(L, lua_upvalueindex(1)); + MT::Apply(L, accounts[i]); + } + else + lua_pushnil(L); + + return 1; +} + +static int lua_Accounts(lua_State *L) +{ + const char *szProto = nullptr; + + switch (lua_type(L, 1)) + { + case LUA_TNONE: + break; + case LUA_TSTRING: + szProto = lua_tostring(L, 1); + break; + case LUA_TUSERDATA: + { + PROTOCOLDESCRIPTOR *pd = *(PROTOCOLDESCRIPTOR**)luaL_checkudata(L, 1, MT_PROTOCOLDESCRIPTOR); + szProto = pd->szName; + break; + } + default: + luaL_argerror(L, 1, luaL_typename(L, 1)); + } + + int count; + PROTOACCOUNT **accounts; + Proto_EnumAccounts(&count, &accounts); + + lua_pushinteger(L, 0); + lua_pushinteger(L, count); + lua_pushlightuserdata(L, accounts); + lua_pushstring(L, szProto); + lua_pushcclosure(L, lua_AccountIterator, 4); + + return 1; +} + +static int lua_CallService(lua_State *L) +{ + const char *szModule = nullptr; + + switch (lua_type(L, 1)) + { + case LUA_TNUMBER: + szModule = GetContactProto(lua_tonumber(L, 1)); + break; + case LUA_TSTRING: + szModule = lua_tostring(L, 1); + break; + case LUA_TUSERDATA: + { + PROTOACCOUNT *pa = *(PROTOACCOUNT**)luaL_checkudata(L, 1, MT_PROTOACCOUNT); + szModule = pa->szModuleName; + break; + } + default: + luaL_argerror(L, 1, luaL_typename(L, 1)); + } + + const char *service = luaL_checkstring(L, 2); + WPARAM wParam = (WPARAM)luaM_tomparam(L, 3); + LPARAM lParam = (LPARAM)luaM_tomparam(L, 4); + + INT_PTR res = CallProtoService(szModule, service, wParam, lParam); + lua_pushinteger(L, res); + + return 1; +} + +/***********************************************/ + +INT_PTR FilterRecvMessage(WPARAM wParam, LPARAM lParam) +{ + int res = NotifyEventHooks(hRecvMessage, wParam, lParam); + if (res) return res; + Proto_ChainRecv(wParam, (CCSDATA*)lParam); + return 0; +} + +/***********************************************/ + +static luaL_Reg protocolsApi[] = +{ + { "GetProtocol", lua_GetProtocol }, + { "Protocols", lua_Protocols }, + + { "CallSendChain", lua_ChainSend }, + { "CallReceiveChain", lua_ChainRecv }, + + { "GetAccount", lua_GetAccount }, + { "Accounts", lua_Accounts }, + + { "CallService", lua_CallService }, + + { nullptr, nullptr } +}; + +/***********************************************/ + +LUAMOD_API int luaopen_m_protocols(lua_State *L) +{ + hRecvMessage = CreateHookableEvent(MODULENAME PSR_MESSAGE); + CreateProtoServiceFunction(MODULENAME, PSR_MESSAGE, FilterRecvMessage); + + luaL_newlib(L, protocolsApi); + + MT(L, MT_PROTOCOLDESCRIPTOR) + .Field(&PROTOCOLDESCRIPTOR::szName, "Name", LUA_TSTRINGA) + .Field(&PROTOCOLDESCRIPTOR::type, "Type", LUA_TINTEGER) + .Field(lua_Accounts, "Accounts"); + + MT(L, MT_PROTOACCOUNT) + .Field(&PROTOACCOUNT::szModuleName, "ModuleName", LUA_TSTRINGA) + .Field(&PROTOACCOUNT::tszAccountName, "AccountName", LUA_TSTRINGW) + .Field(&PROTOACCOUNT::szProtoName, "ProtoName", LUA_TSTRINGA) + .Field(&PROTOACCOUNT::bIsEnabled, "IsEnabled", LUA_TBOOLEAN) + .Field(&PROTOACCOUNT::bIsVisible, "IsVisible", LUA_TBOOLEAN) + .Field(&PROTOACCOUNT::bIsVirtual, "IsVirtual", LUA_TBOOLEAN) + .Field(&PROTOACCOUNT::bOldProto, "IsOldProto", LUA_TBOOLEAN) + .Field(lua_CallService, "CallService"); + + MT(L, "ACKDATA") + .Field(&ACKDATA::szModule, "Module", LUA_TSTRINGA) + .Field(&ACKDATA::hContact, "hContact", LUA_TINTEGER) + .Field(&ACKDATA::type, "Type", LUA_TINTEGER) + .Field(&ACKDATA::result, "Result", LUA_TINTEGER) + .Field(&ACKDATA::hProcess, "hProcess", LUA_TLIGHTUSERDATA) + .Field(&ACKDATA::lParam, "lParam", LUA_TLIGHTUSERDATA); + + MT(L, "CCSDATA") + .Field(&CCSDATA::hContact, "hContact", LUA_TINTEGER) + .Field(&CCSDATA::szProtoService, "Service", LUA_TSTRINGA) + .Field(&CCSDATA::wParam, "wParam", LUA_TLIGHTUSERDATA) + .Field(&CCSDATA::lParam, "lParam", LUA_TLIGHTUSERDATA); + + MT(L, "PROTORECVEVENT") + .Field(&PROTORECVEVENT::timestamp, "Timestamp", LUA_TINTEGER) + .Field(&PROTORECVEVENT::flags, "Flags", LUA_TINTEGER) + .Field(&PROTORECVEVENT::szMessage, "Message", LUA_TSTRING); + + return 1; +} diff --git a/plugins/MirLua/src/Modules/m_sounds.cpp b/plugins/MirLua/src/Modules/m_sounds.cpp new file mode 100644 index 0000000000..74b17f12cd --- /dev/null +++ b/plugins/MirLua/src/Modules/m_sounds.cpp @@ -0,0 +1,54 @@ +#include "../stdafx.h" + +static int lua_AddSound(lua_State *L) +{ + ptrA name(mir_utf8decodeA(luaL_checkstring(L, 1))); + ptrW description(mir_utf8decodeW(luaL_checkstring(L, 2))); + ptrW section(mir_utf8decodeW(luaL_optstring(L, 3, MODULENAME))); + ptrW filePath(mir_utf8decodeW(lua_tostring(L, 4))); + + int res = 1; + CMPluginBase *pPlugin = CMLuaEnvironment::GetEnvironment(L); + if (pPlugin != nullptr) + res = pPlugin->addSound(name, section, description, filePath); + lua_pushboolean(L, res == 0); + + return 1; +} + +static int lua_PlaySound(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + + INT_PTR res = Skin_PlaySound(name); + lua_pushboolean(L, res == 0); + + return 1; +} + +static int lua_PlayFile(lua_State *L) +{ + ptrW filePath(mir_utf8decodeW(luaL_checkstring(L, 1))); + + INT_PTR res = Skin_PlaySoundFile(filePath); + lua_pushboolean(L, res == 0); + + return 1; +} + +static luaL_Reg soundApi[] = +{ + { "AddSound", lua_AddSound }, + + { "PlaySound", lua_PlaySound }, + { "PlayFile", lua_PlayFile }, + + { nullptr, nullptr } +}; + +LUAMOD_API int luaopen_m_sounds(lua_State *L) +{ + luaL_newlib(L, soundApi); + + return 1; +} diff --git a/plugins/MirLua/src/Modules/m_srmm.cpp b/plugins/MirLua/src/Modules/m_srmm.cpp new file mode 100644 index 0000000000..f7296d1d70 --- /dev/null +++ b/plugins/MirLua/src/Modules/m_srmm.cpp @@ -0,0 +1,138 @@ +#include "../stdafx.h" + +#define MT_BBBUTTON "BBButton" + +static void MakeBBButton(lua_State *L, BBButton &bbb) +{ + bbb.dwDefPos = 100; + + lua_getfield(L, -1, "Module"); + bbb.pszModuleName = mir_utf8decodeA(luaL_checkstring(L, -1)); + lua_pop(L, 1); + + lua_getfield(L, -1, "ButtonId"); + bbb.dwButtonID = luaL_checkinteger(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "Flags"); + bbb.bbbFlags = luaL_optinteger(L, -1, BBBF_ISIMBUTTON); + lua_pop(L, 1); + + lua_getfield(L, -1, "Text"); + bbb.pwszText = mir_utf8decodeW(lua_tostring(L, -1)); + lua_pop(L, 1); + + lua_getfield(L, -1, "Tooltip"); + bbb.pwszTooltip = mir_utf8decodeW(lua_tostring(L, -1)); + lua_pop(L, 1); + + lua_getfield(L, -1, "Icon"); + bbb.hIcon = (HANDLE)lua_touserdata(L, -1); + lua_pop(L, 1); +} + +static void CleanBBButton(BBButton &bbb) +{ + mir_free((void*)bbb.pszModuleName); + mir_free((void*)bbb.pwszText); + mir_free((void*)bbb.pwszTooltip); +} + +/***********************************************/ + +static int lua_AddButton(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + BBButton bbb = {}; + MakeBBButton(L, bbb); + + int hScriptLangpack = CMLuaEnvironment::GetEnvironmentId(L); + HANDLE res = Srmm_AddButton(&bbb, hScriptLangpack); + CleanBBButton(bbb); + + if (!res) + { + lua_pushnil(L); + return 1; + } + + lua_pushvalue(L, 1); + luaL_setmetatable(L, MT_BBBUTTON); + + return 1; +} + +static int lua_ModifyButton(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + lua_pushvalue(L, 1); + + BBButton bbb = {}; + MakeBBButton(L, bbb); + INT_PTR res = Srmm_ModifyButton(&bbb); + CleanBBButton(bbb); + lua_pushboolean(L, !res); + + return 2; +} + +static int lua_RemoveButton(lua_State *L) +{ + BBButton bbb = {}; + + switch (lua_type(L, 1)) + { + case LUA_TSTRING: + bbb.pszModuleName = mir_utf8decodeA(lua_tostring(L, 1)); + bbb.dwButtonID = luaL_checkinteger(L, 2); + break; + case LUA_TTABLE: + MakeBBButton(L, bbb); + break; + default: + luaL_argerror(L, 1, luaL_typename(L, 1)); + } + + INT_PTR res = Srmm_RemoveButton(&bbb); + CleanBBButton(bbb); + lua_pushboolean(L, !res); + + return 1; +} + +static luaL_Reg srmmApi[] = +{ + { "AddButton", lua_AddButton }, + { "ModifyButton", lua_ModifyButton }, + { "RemoveButton", lua_RemoveButton }, + + { nullptr, nullptr } +}; + +/***********************************************/ + +LUAMOD_API int luaopen_m_srmm(lua_State *L) +{ + luaL_newlib(L, srmmApi); + + luaL_newmetatable(L, MT_BBBUTTON); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + lua_pushliteral(L, MT_BBBUTTON); + lua_setfield(L, -2, "__metatable"); + lua_pushcfunction(L, lua_ModifyButton); + lua_setfield(L, -2, "Modify"); + lua_pushcfunction(L, lua_RemoveButton); + lua_setfield(L, -2, "Remove"); + lua_pop(L, 1); + + MT(L, "CustomButtonClickData") + .Field(&CustomButtonClickData::pszModule, "Module", LUA_TSTRINGA) + .Field(&CustomButtonClickData::dwButtonId, "ButtonId", LUA_TINTEGER) + .Field(&CustomButtonClickData::hContact, "hContact", LUA_TINTEGER) + .Field(&CustomButtonClickData::flags, "Flags", LUA_TINTEGER); + + return 1; +} diff --git a/plugins/MirLua/src/environment.cpp b/plugins/MirLua/src/environment.cpp new file mode 100644 index 0000000000..4a82e63231 --- /dev/null +++ b/plugins/MirLua/src/environment.cpp @@ -0,0 +1,101 @@ +#include "stdafx.h" + +#define MT_ENVIRONMENT "ENVIRONMENT" + +CMLuaEnvironment::CMLuaEnvironment(lua_State *L) + : L(L) +{ + MUUID muidLast = MIID_LAST; + m_id = GetPluginLangId(muidLast, 0); +} + +CMLuaEnvironment::~CMLuaEnvironment() +{ + KillModuleIcons(m_id); + KillModuleSounds(m_id); + KillModuleMenus(m_id); + KillModuleHotkeys(m_id); + + KillObjectEventHooks(this); + KillObjectServices(this); + + for (auto &it : m_hookRefs) + luaL_unref(L, LUA_REGISTRYINDEX, it.second); + + for (auto &it : m_serviceRefs) + luaL_unref(L, LUA_REGISTRYINDEX, it.second); +} + +CMLuaEnvironment* CMLuaEnvironment::GetEnvironment(lua_State *L) +{ + if (!luaM_getenv(L)) + return nullptr; + + lua_rawgeti(L, -1, NULL); + CMLuaEnvironment *env = (CMLuaEnvironment*)lua_touserdata(L, -1); + lua_pop(L, 3); + + return env; +} + +int CMLuaEnvironment::GetEnvironmentId(lua_State *L) +{ + CMLuaEnvironment *script = GetEnvironment(L); + return script != nullptr + ? script->GetId() + : hMLuaLangpack; +} + +int CMLuaEnvironment::GetId() const +{ + return m_id; +} + +void CMLuaEnvironment::AddHookRef(HANDLE h, int ref) +{ + m_hookRefs[h] = ref; +} + +void CMLuaEnvironment::ReleaseHookRef(HANDLE h) +{ + auto it = m_hookRefs.find(h); + if (it != m_hookRefs.end()) + luaL_unref(L, LUA_REGISTRYINDEX, it->second); +} + +void CMLuaEnvironment::AddServiceRef(HANDLE h, int ref) +{ + m_serviceRefs[h] = ref; +} + +void CMLuaEnvironment::ReleaseServiceRef(HANDLE h) +{ + auto it = m_serviceRefs.find(h); + if (it != m_serviceRefs.end()) + luaL_unref(L, LUA_REGISTRYINDEX, it->second); +} + +void CMLuaEnvironment::CreateEnvironmentTable() +{ + lua_createtable(L, 1, 1); + lua_pushlightuserdata(L, this); + lua_rawseti(L, -2, NULL); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "_G"); + lua_createtable(L, 0, 2); + lua_pushliteral(L, MT_ENVIRONMENT); + lua_setfield(L, -2, "__metatable"); + lua_getglobal(L, "_G"); + lua_setfield(L, -2, "__index"); + lua_setmetatable(L, -2); +} + +bool CMLuaEnvironment::Load() +{ + luaL_checktype(L, -1, LUA_TFUNCTION); + + CreateEnvironmentTable(); + lua_setupvalue(L, -2, 1); + + return lua_pcall(L, 0, 1, 0) == LUA_OK; +} diff --git a/plugins/MirLua/src/environment.h b/plugins/MirLua/src/environment.h new file mode 100644 index 0000000000..aa6ebb103a --- /dev/null +++ b/plugins/MirLua/src/environment.h @@ -0,0 +1,33 @@ +#ifndef _LUA_ENVIRONMENT_H_ +#define _LUA_ENVIRONMENT_H_ + +class CMLuaEnvironment +{ +private: + int m_id; + std::map m_hookRefs; + std::map m_serviceRefs; + + void CreateEnvironmentTable(); + +public: + lua_State *L; + + CMLuaEnvironment(lua_State *L); + virtual ~CMLuaEnvironment(); + + static CMLuaEnvironment* GetEnvironment(lua_State *L); + static int GetEnvironmentId(lua_State *L); + + int GetId() const; + + void AddHookRef(HANDLE h, int ref); + void ReleaseHookRef(HANDLE h); + + void AddServiceRef(HANDLE h, int ref); + void ReleaseServiceRef(HANDLE h); + + bool Load(); +}; + +#endif //_LUA_ENVIRONMENT_H_ diff --git a/plugins/MirLua/src/function_loader.cpp b/plugins/MirLua/src/function_loader.cpp new file mode 100644 index 0000000000..6e82086d29 --- /dev/null +++ b/plugins/MirLua/src/function_loader.cpp @@ -0,0 +1,194 @@ +#include "stdafx.h" + +CMLuaFunctionLoader::CMLuaFunctionLoader(lua_State *L) : L(L) +{ +} + +/***********************************************/ + +static int mlua_print(lua_State *L) +{ + CMStringA data; + int nargs = lua_gettop(L); + for (int i = 1; i <= nargs; i++) { + switch (lua_type(L, i)) { + case LUA_TNIL: + data.Append("nil"); + break; + case LUA_TBOOLEAN: + data.AppendFormat("%s", lua_toboolean(L, i) ? "true" : "false"); + break; + case LUA_TNUMBER: + data.AppendFormat("%s", lua_tostring(L, i)); + break; + case LUA_TSTRING: + data.AppendFormat("'%s'", lua_tostring(L, i)); + break; + default: + if (luaL_callmeta(L, i, "__tostring")) { + data.AppendFormat("'%s'", lua_tostring(L, -1)); + break; + } + data.AppendFormat("%s(0x%p)", luaL_typename(L, i), lua_topointer(L, i)); + break; + } + data.Append(", "); + } + if (data.GetLength() >= 1) + data.Delete(data.GetLength() - 2, 2); + + Log(data.GetBuffer()); + + return 0; +} + +static int mlua_toansi(lua_State *L) +{ + const char *value = luaL_checkstring(L, 1); + int codepage = luaL_optinteger(L, 2, Langpack_GetDefaultCodePage()); + + ptrA string(mir_strdup(value)); + lua_pushstring(L, mir_utf8decodecp(string, codepage, nullptr)); + + return 1; +} + +static int mlua_toucs2(lua_State *L) +{ + const char *value = luaL_checkstring(L, 1); + + ptrW unicode(mir_utf8decodeW(value)); + size_t length = mir_wstrlen(unicode) * sizeof(wchar_t); + + ptrA string((char*)mir_calloc(length + 1)); + memcpy(string, unicode, length); + + lua_pushlstring(L, string, length + 1); + + return 1; +} + +static int mlua_topointer(lua_State *L) +{ + switch (lua_type(L, 1)) { + case LUA_TBOOLEAN: + lua_pushlightuserdata(L, (void*)lua_toboolean(L, 1)); + break; + case LUA_TNUMBER: + if (lua_isinteger(L, 1)) { + lua_Integer value = lua_tointeger(L, 1); + if (value > INTPTR_MAX) { + const char *msg = lua_pushfstring(L, "%f is larger than %d", value, INTPTR_MAX); + return luaL_argerror(L, 1, msg); + } + lua_pushlightuserdata(L, (void*)value); + } + break; + case LUA_TSTRING: + lua_pushlightuserdata(L, (void*)lua_tostring(L, 1)); + break; + case LUA_TLIGHTUSERDATA: + lua_pushvalue(L, 1); + default: + return luaL_argerror(L, 1, luaL_typename(L, 1)); + } + + return 1; +} + +static int mlua_tonumber(lua_State *L) +{ + if (lua_islightuserdata(L, 1)) { + lua_Integer value = (lua_Integer)lua_touserdata(L, 1); + lua_pushinteger(L, value); + return 1; + } + + int n = lua_gettop(L); + lua_pushvalue(L, lua_upvalueindex(1)); + lua_pushvalue(L, 1); + if (n == 2) + lua_pushvalue(L, 2); + luaM_pcall(L, n, 1); + + return 1; +} + +static int mlua_interpolate(lua_State *L) +{ + const char *string = luaL_checkstring(L, 1); + + char pattern[128]; + + if (lua_istable(L, 2)) { + for (lua_pushnil(L); lua_next(L, 2); lua_pop(L, 3)) { + lua_pushvalue(L, -2); + const char *key = lua_tostring(L, -1); + const char *val = lua_tostring(L, -2); + + mir_snprintf(pattern, "{%s}", key); + string = luaL_gsub(L, string, pattern, val ? val : ""); + } + } + else { + int nargs = lua_gettop(L); + for (int i = 2; i <= nargs; i++) { + const char *val = lua_tostring(L, i); + + mir_snprintf(pattern, "{%d}", i - 1); + string = luaL_gsub(L, string, pattern, val ? val : ""); + lua_pop(L, 1); + } + } + + lua_Debug ar; + int level = 1; + while (lua_getstack(L, level++, &ar)) { + int i = 1; + while (const char *name = lua_getlocal(L, &ar, i++)) { + const char *val = lua_tostring(L, -1); + mir_snprintf(pattern, "{%s}", name); + string = luaL_gsub(L, string, pattern, val ? val : ""); + lua_pop(L, 1); + } + } + + lua_pushstring(L, string); + + return 1; +} + +/***********************************************/ + +void CMLuaFunctionLoader::LoadFunctions() +{ + Log("Loading additional functions"); + + lua_register(L, "print", mlua_print); + lua_register(L, "a", mlua_toansi); + lua_register(L, "toansi", mlua_toansi); + lua_register(L, "u", mlua_toucs2); + lua_register(L, "toucs2", mlua_toucs2); + lua_register(L, "topointer", mlua_topointer); + + lua_getglobal(L, "tonumber"); + lua_pushcclosure(L, mlua_tonumber, 1); + lua_setglobal(L, "tonumber"); + + lua_pushstring(L, ""); + lua_getmetatable(L, -1); + lua_pushstring(L, "__mod"); + lua_pushcfunction(L, mlua_interpolate); + lua_rawset(L, -3); + lua_pushstring(L, "__index"); + lua_rawget(L, -2); + lua_pushcfunction(L, mlua_interpolate); + lua_setfield(L, -2, "interpolate"); + lua_pop(L, 3); +} + +void CMLuaFunctionLoader::Load(lua_State *L) +{ + CMLuaFunctionLoader loader(L); + loader.LoadFunctions(); +} \ No newline at end of file diff --git a/plugins/MirLua/src/function_loader.h b/plugins/MirLua/src/function_loader.h new file mode 100644 index 0000000000..9724ccdc3d --- /dev/null +++ b/plugins/MirLua/src/function_loader.h @@ -0,0 +1,14 @@ +#pragma once + +class CMLuaFunctionLoader +{ +private: + lua_State *L; + + CMLuaFunctionLoader(lua_State *L); + + void LoadFunctions(); + +public: + static void Load(lua_State *L); +}; diff --git a/plugins/MirLua/src/icons.cpp b/plugins/MirLua/src/icons.cpp new file mode 100644 index 0000000000..4a6cc91219 --- /dev/null +++ b/plugins/MirLua/src/icons.cpp @@ -0,0 +1,33 @@ +#include "stdafx.h" + +IconItem Icons[] = +{ + { LPGEN("Script"), "script", IDI_SCRIPT }, + { LPGEN("Loaded"), "loaded", IDI_LOADED }, + { LPGEN("Failed"), "failed", IDI_FAILED }, + { LPGEN("Open"), "open", IDI_OPEN }, + { LPGEN("Reload"), "reload", IDI_RELOAD }, +}; + +void InitIcons() +{ + g_plugin.registerIcon(MODULENAME, Icons, MODULENAME); +} + +HICON GetIcon(int iconId) +{ + for (auto &it : Icons) + if (it.defIconID == iconId) + return IcoLib_GetIconByHandle(it.hIcolib); + + return nullptr; +} + +HANDLE GetIconHandle(int iconId) +{ + for (auto &it : Icons) + if (it.defIconID == iconId) + return it.hIcolib; + + return nullptr; +} \ No newline at end of file diff --git a/plugins/MirLua/src/m_chat.cpp b/plugins/MirLua/src/m_chat.cpp deleted file mode 100644 index ed57b7b9de..0000000000 --- a/plugins/MirLua/src/m_chat.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "stdafx.h" - -static luaL_Reg chatApi[] = -{ - { nullptr, nullptr } -}; - -LUAMOD_API int luaopen_m_chat(lua_State *L) -{ - luaL_newlib(L, chatApi); - - MT(L, "GCEVENT") - .Field(&GCEVENT::pszModule, "Module", LUA_TSTRINGA) - .Field(&GCEVENT::ptszID, "Id", LUA_TSTRINGW) - .Field(&GCEVENT::iType, "Type", LUA_TINTEGER) - .Field(&GCEVENT::time, "Timestamp", LUA_TINTEGER) - .Field(&GCEVENT::time, "IsMe", LUA_TINTEGER) - .Field(&GCEVENT::time, "Flags", LUA_TINTEGER) - .Field(&GCEVENT::ptszNick, "Nick", LUA_TSTRINGW) - .Field(&GCEVENT::ptszUID, "Uid", LUA_TSTRINGW) - .Field(&GCEVENT::ptszStatus, "Status", LUA_TSTRINGW) - .Field(&GCEVENT::ptszText, "Text", LUA_TSTRINGW); - - return 1; -} diff --git a/plugins/MirLua/src/m_clist.cpp b/plugins/MirLua/src/m_clist.cpp deleted file mode 100644 index cc32c188db..0000000000 --- a/plugins/MirLua/src/m_clist.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include "stdafx.h" - -static int clist_AddMainMenuRoot(lua_State *L) -{ - const char *name = luaL_checkstring(L, 1); - int position = lua_tointeger(L, 2); - HANDLE hIcon = (HANDLE)lua_touserdata(L, 3); - - HGENMENU res = Menu_CreateRoot(MO_MAIN, ptrW(Utf8DecodeW(name)), position, hIcon); - if (res != nullptr) - lua_pushlightuserdata(L, res); - else - lua_pushnil(L); - - return 1; -} - -static int clist_AddMainMenuItem(lua_State *L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - - CMenuItem mi; - MakeMenuItem(L, mi); - - HGENMENU res = Menu_AddMainMenuItem(&mi); - if (res != nullptr) - lua_pushlightuserdata(L, res); - else - lua_pushnil(L); - - return 1; -} - -static int clist_AddContactMenuRoot(lua_State *L) -{ - const char *name = luaL_checkstring(L, 1); - int position = lua_tointeger(L, 2); - HANDLE hIcon = (HANDLE)lua_touserdata(L, 3); - - HGENMENU res = Menu_CreateRoot(MO_MAIN, ptrW(Utf8DecodeW(name)), position, hIcon); - if (res != nullptr) - lua_pushlightuserdata(L, res); - else - lua_pushnil(L); - - return 1; -} - -static int clist_AddContactMenuItem(lua_State *L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - - CMenuItem mi; - MakeMenuItem(L, mi); - - ptrA szProto(mir_utf8decodeA(lua_tostring(L, 2))); - HGENMENU res = Menu_AddContactMenuItem(&mi, szProto); - if (res != nullptr) - lua_pushlightuserdata(L, res); - else - lua_pushnil(L); - - return 1; -} - -static int clist_AddTrayMenuItem(lua_State *L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - - CMenuItem mi; - MakeMenuItem(L, mi); - - HGENMENU res = Menu_AddTrayMenuItem(&mi); - if (res != nullptr) - lua_pushlightuserdata(L, res); - else - lua_pushnil(L); - - return 1; -} - -static luaL_Reg clistApi[] = -{ - { "AddMainMenuRoot", clist_AddMainMenuRoot }, - { "AddMainMenuItem", clist_AddMainMenuItem }, - - { "AddContactMenuRoot", clist_AddContactMenuRoot }, - { "AddContactMenuItem", clist_AddContactMenuItem }, - - { "AddTrayMenuItem", clist_AddTrayMenuItem }, - - { nullptr, nullptr } -}; - -LUAMOD_API int luaopen_m_clist(lua_State *L) -{ - luaL_newlib(L, clistApi); - - return 1; -} diff --git a/plugins/MirLua/src/m_core.cpp b/plugins/MirLua/src/m_core.cpp deleted file mode 100644 index 9bcbdd5205..0000000000 --- a/plugins/MirLua/src/m_core.cpp +++ /dev/null @@ -1,433 +0,0 @@ -#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 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 diff --git a/plugins/MirLua/src/m_database.cpp b/plugins/MirLua/src/m_database.cpp deleted file mode 100644 index 7425b45ddd..0000000000 --- a/plugins/MirLua/src/m_database.cpp +++ /dev/null @@ -1,691 +0,0 @@ -#include "stdafx.h" - -void luaM_pushdbvt(lua_State *L, const DBVARIANT &value) -{ - switch (value.type) { - case DBVT_BYTE: - lua_pushinteger(L, value.bVal); - break; - case DBVT_WORD: - lua_pushinteger(L,value.wVal); - break; - case DBVT_DWORD: - lua_pushnumber(L, value.dVal); - break; - case DBVT_ASCIIZ: - lua_pushstring(L, ptrA(mir_utf8encode(value.pszVal))); - break; - case DBVT_UTF8: - lua_pushstring(L, value.pszVal); - break; - case DBVT_WCHAR: - lua_pushstring(L, ptrA(mir_utf8encodeW(value.pwszVal))); - break; - case DBVT_BLOB: - { - lua_createtable(L, value.cpbVal, 0); - for (int i = 0; i < value.cpbVal; i++) { - lua_pushinteger(L, value.pbVal[i]); - lua_rawseti(L, -2, i + 1); - } - } - break; - default: - lua_pushnil(L); - } -} - -/***********************************************/ - -static int db_ContactIterator(lua_State *L) -{ - MCONTACT hContact = lua_tointeger(L, lua_upvalueindex(1)); - const char *szModule = lua_tostring(L, lua_upvalueindex(2)); - - hContact = hContact == NULL - ? db_find_first(szModule) - : db_find_next(hContact, szModule); - - if (hContact) { - lua_pushinteger(L, hContact); - lua_pushvalue(L, -1); - lua_replace(L, lua_upvalueindex(1)); - } - else - lua_pushnil(L); - - return 1; -} - -static int db_Contacts(lua_State *L) -{ - const char *szModule = nullptr; - - switch (lua_type(L, 1)) { - case LUA_TNONE: - break; - case LUA_TSTRING: - szModule = lua_tostring(L, 1); - break; - case LUA_TUSERDATA: - { - PROTOACCOUNT **pa = (PROTOACCOUNT**)luaL_checkudata(L, 1, MT_PROTOACCOUNT); - szModule = (*pa)->szModuleName; - break; - } - default: - luaL_argerror(L, 1, luaL_typename(L, 1)); - } - - lua_pushinteger(L, 0); - lua_pushstring(L, szModule); - lua_pushcclosure(L, db_ContactIterator, 2); - - return 1; -} - -static const char *mods[] = -{ - "FirstName", - "LastName", - "Nick", - "CustomNick", - "Email", - "City", - "State", - "Country", - "Phone", - "Homepage", - "About", - "Gender", - "Age", - "FullName", - "Uid", - "DisplayName", - nullptr -}; - -static int db_GetContactInfo(lua_State *L) -{ - MCONTACT hContact = luaL_checkinteger(L, 1); - - int type = 0; - switch (lua_type(L, 2)) { - case LUA_TNUMBER: - type = luaL_checkinteger(L, 2); - break; - case LUA_TSTRING: - type = luaL_checkoption(L, 2, nullptr, mods) + 1; - break; - default: - luaL_argerror(L, 2, luaL_typename(L, 2)); - } - - ptrW value(Contact_GetInfo(type, hContact)); - if (value) - lua_pushstring(L, ptrA(mir_utf8encodeW(value))); - else - lua_pushnil(L); - - return 1; -} - -/***********************************************/ - -static int db_GetEventCount(lua_State *L) -{ - MCONTACT hContact = luaL_checkinteger(L, 1); - - int res = db_event_count(hContact); - lua_pushinteger(L, res); - - return 1; -} - -static int db_GetFirstEvent(lua_State *L) -{ - MCONTACT hContact = luaL_checkinteger(L, 1); - - MEVENT res = db_event_first(hContact); - lua_pushinteger(L, res); - - return 1; -} - -static int db_GetPrevEvent(lua_State *L) -{ - MCONTACT hContact = luaL_checkinteger(L, 1); - MEVENT hDbEvent = luaL_checkinteger(L, 2); - - MEVENT res = db_event_prev(hContact, hDbEvent); - lua_pushinteger(L, res); - - return 1; -} - -static int db_GetNextEvent(lua_State *L) -{ - MCONTACT hContact = luaL_checkinteger(L, 1); - MEVENT hDbEvent = luaL_checkinteger(L, 2); - - MEVENT res = db_event_next(hContact, hDbEvent); - lua_pushinteger(L, res); - - return 1; -} - -static int db_GetLastEvent(lua_State *L) -{ - MCONTACT hContact = luaL_checkinteger(L, 1); - - MEVENT res = db_event_last(hContact); - lua_pushinteger(L, res); - - return 1; -} - -static int db_GetFirstUnreadEvent(lua_State *L) -{ - MCONTACT hContact = luaL_checkinteger(L, 1); - - MEVENT res = db_event_firstUnread(hContact); - lua_pushinteger(L, res); - - return 1; -} - -static int db_EventIterator(lua_State *L) -{ - MCONTACT hContact = luaL_checkinteger(L, lua_upvalueindex(1)); - MEVENT hDbEvent = luaL_checkinteger(L, lua_upvalueindex(2)); - - hDbEvent = hDbEvent == NULL - ? db_event_first(hContact) - : db_event_next(hContact, hDbEvent); - - if (hDbEvent) { - lua_pushinteger(L, hDbEvent); - lua_pushvalue(L, -1); - lua_replace(L, lua_upvalueindex(2)); - } - else - lua_pushnil(L); - - return 1; -} - -static int db_Events(lua_State *L) -{ - MCONTACT hContact = luaL_checkinteger(L, 1); - - lua_pushinteger(L, hContact); - lua_pushinteger(L, NULL); - lua_pushcclosure(L, db_EventIterator, 2); - - return 1; -} - -static int db_EventReverseIterator(lua_State *L) -{ - MCONTACT hContact = luaL_checkinteger(L, lua_upvalueindex(1)); - MEVENT hDbEvent = luaL_checkinteger(L, lua_upvalueindex(2)); - - hDbEvent = hDbEvent == NULL - ? db_event_last(hContact) - : db_event_prev(hContact, hDbEvent); - - if (hDbEvent) { - lua_pushinteger(L, hDbEvent); - lua_pushvalue(L, -1); - lua_replace(L, lua_upvalueindex(2)); - } - else - lua_pushnil(L); - - return 1; -} - -static int db_EventsFromEnd(lua_State *L) -{ - MCONTACT hContact = luaL_checkinteger(L, 1); - - lua_pushinteger(L, hContact); - lua_pushinteger(L, NULL); - lua_pushcclosure(L, db_EventReverseIterator, 2); - - return 1; -} - -static int db_UnreadEventIterator(lua_State *L) -{ - MCONTACT hContact = luaL_checkinteger(L, lua_upvalueindex(1)); - MEVENT hDbEvent = luaL_checkinteger(L, lua_upvalueindex(2)); - - hDbEvent = db_event_firstUnread(hContact); - - if (hDbEvent) { - lua_pushinteger(L, hDbEvent); - lua_pushvalue(L, -1); - lua_replace(L, lua_upvalueindex(2)); - } - else - lua_pushnil(L); - - return 1; -} - -static int db_UnreadEvents(lua_State *L) -{ - MCONTACT hContact = luaL_checkinteger(L, 1); - - lua_pushinteger(L, hContact); - lua_pushinteger(L, NULL); - lua_pushcclosure(L, db_UnreadEventIterator, 2); - - return 1; -} - -void MakeDbEvent(lua_State *L, DBEVENTINFO &dbei) -{ - lua_getfield(L, -1, "Module"); - dbei.szModule = mir_strdup(lua_tostring(L, -1)); - lua_pop(L, 1); - - lua_getfield(L, -1, "Type"); - dbei.eventType = lua_tointeger(L, -1); - lua_pop(L, 1); - - lua_getfield(L, -1, "Timestamp"); - dbei.timestamp = lua_tonumber(L, -1); - lua_pop(L, 1); - - lua_getfield(L, -1, "Flags"); - dbei.flags = lua_tointeger(L, -1); - lua_pop(L, 1); - - lua_getfield(L, -1, "Blob"); - switch (lua_type(L, -1)) { - case LUA_TTABLE: - dbei.cbBlob = (DWORD)lua_rawlen(L, 4); - dbei.pBlob = (BYTE*)mir_calloc(dbei.cbBlob); - for (DWORD i = 0; i < dbei.cbBlob; i++) { - lua_geti(L, 4, i + 1); - dbei.pBlob[i] = lua_tointeger(L, -1); - lua_pop(L, 1); - } - break; - case LUA_TSTRING: - size_t nLen; - const char *str = lua_tolstring(L, -1, &nLen); - dbei.cbBlob = (DWORD)nLen; - dbei.pBlob = (BYTE*)mir_alloc(nLen); - memcpy(dbei.pBlob, str, nLen); - break; - } - lua_pop(L, 1); -} - -static int db_AddEvent(lua_State *L) -{ - MCONTACT hContact = luaL_checkinteger(L, 1); - - DBEVENTINFO dbei; - MakeDbEvent(L, dbei); - MEVENT hDbEvent = db_event_add(hContact, &dbei); - - if (hDbEvent) - lua_pushnumber(L, hDbEvent); - else - lua_pushnil(L); - - return 1; -} - -static int db_MarkReadEvent(lua_State *L) -{ - MCONTACT hContact = luaL_checkinteger(L, 1); - MEVENT hDbEvent = luaL_checkinteger(L, 2); - - int res = db_event_markRead(hContact, hDbEvent); - lua_pushnumber(L, res); - - return 1; -} - -/***********************************************/ - -static int ModulesEnumProc(const char *szModuleName, void *lParam) -{ - if (szModuleName) { - LIST* p = (LIST*)lParam; - p->insert(mir_strdup(szModuleName)); - } - - return 0; -} - -static int db_ModulesIterator(lua_State *L) -{ - int i = lua_tointeger(L, lua_upvalueindex(1)); - LIST ¶m = *(LIST*)lua_touserdata(L, lua_upvalueindex(2)); - - if (i < param.getCount()) { - lua_pushinteger(L, (i + 1)); - lua_replace(L, lua_upvalueindex(1)); - lua_pushstring(L, ptrA(mir_utf8encode(param[i]))); - mir_free(param[i]); - } - else { - lua_pushnil(L); - delete ¶m; - } - - return 1; -} - -static int db_Modules(lua_State *L) -{ - LIST *param = new LIST(5, PtrKeySortT); - - db_enum_modules(ModulesEnumProc, param); - - lua_pushinteger(L, 0); - lua_pushlightuserdata(L, param); - lua_pushcclosure(L, db_ModulesIterator, 2); - - return 1; -} - -static int db_DeleteModule(lua_State *L) -{ - MCONTACT hContact = lua_tointeger(L, 1); - const char *szModule = luaL_checkstring(L, 2); - - INT_PTR res = db_delete_module(hContact, szModule); - lua_pushboolean(L, !res); - - return 1; -} - -static int SettingsEnumProc(const char* szSetting, void *lParam) -{ - if (szSetting ) { - LIST* p = (LIST*)lParam; - p->insert(mir_strdup(szSetting)); - } - return 0; -} - -static int db_SettingIterator(lua_State *L) -{ - int i = lua_tointeger(L, lua_upvalueindex(1)); - LIST ¶m = *(LIST*)lua_touserdata(L, lua_upvalueindex(2)); - - if (i < param.getCount()) { - lua_pushinteger(L, (i + 1)); - lua_replace(L, lua_upvalueindex(1)); - lua_pushstring(L, ptrA(mir_utf8encode(param[i]))); - mir_free(param[i]); - } - else { - lua_pushnil(L); - delete ¶m; - } - - return 1; -} - -static int db_Settings(lua_State *L) -{ - MCONTACT hContact = lua_tointeger(L, 1); - const char* szModule = luaL_checkstring(L, 2); - - LIST *param = new LIST(5, PtrKeySortT); - db_enum_settings(hContact, SettingsEnumProc, szModule, param); - - lua_pushinteger(L, 0); - lua_pushlightuserdata(L, param); - lua_pushcclosure(L, db_SettingIterator, 2); - - return 1; -} - -static int db_GetSetting(lua_State *L) -{ - MCONTACT hContact = lua_tointeger(L, 1); - const char *szModule = luaL_checkstring(L, 2); - const char *szSetting = luaL_checkstring(L, 3); - - DBVARIANT dbv; - if (db_get(hContact, szModule, szSetting, &dbv)) { - lua_pushvalue(L, 4); - return 1; - } - - luaM_pushdbvt(L, dbv); - db_free(&dbv); - - if (lua_isnil(L, -1) && !lua_isnoneornil(L, 4)) { - lua_pop(L, 1); - lua_pushvalue(L, 4); - } - - return 1; -} - -static int db_WriteSetting(lua_State *L) -{ - MCONTACT hContact = lua_tointeger(L, 1); - const char *szModule = luaL_checkstring(L, 2); - const char *szSetting = luaL_checkstring(L, 3); - luaL_checkany(L, 4); - - DBVARIANT dbv; - if (lua_isnoneornil(L, 5)) { - int type = lua_type(L, 4); - switch (type) { - case LUA_TBOOLEAN: - dbv.type = DBVT_BYTE; - break; - case LUA_TNUMBER: - dbv.type = DBVT_DWORD; - break; - case LUA_TSTRING: - dbv.type = DBVT_UTF8; - break; - case LUA_TTABLE: - dbv.type = DBVT_BLOB; - break; - default: - lua_pushboolean(L, false); - return 1; - } - } - else - dbv.type = luaL_checkinteger(L, 5); - - switch (dbv.type) { - case DBVT_BYTE: - dbv.bVal = lua_isboolean(L, 4) - ? lua_toboolean(L, 4) - : luaL_checknumber(L, 4); - break; - case DBVT_WORD: - dbv.wVal = luaL_checknumber(L, 4); - break; - case DBVT_DWORD: - dbv.dVal = luaL_checknumber(L, 4); - break; - case DBVT_UTF8: - dbv.pszVal = mir_strdup(luaL_checkstring(L, 4)); - break; - case DBVT_ASCIIZ: - dbv.pszVal = mir_utf8decodeA(luaL_checkstring(L, 4)); - break; - case DBVT_WCHAR: - dbv.pwszVal = mir_utf8decodeW(luaL_checkstring(L, 4)); - break; - case DBVT_BLOB: - { - dbv.cpbVal = (WORD)lua_rawlen(L, 4); - dbv.pbVal = (BYTE*)mir_calloc(dbv.cpbVal); - for (int i = 0; i < dbv.cpbVal; i++) { - lua_geti(L, 4, i + 1); - dbv.pbVal[i] = lua_tointeger(L, -1); - lua_pop(L, 1); - } - } - break; - default: - lua_pushboolean(L, false); - return 1; - } - - INT_PTR res = db_set(hContact, szModule, szSetting, &dbv); - lua_pushboolean(L, !res); - - return 1; -} - -static int db_DeleteSetting(lua_State *L) -{ - MCONTACT hContact = lua_tointeger(L, 1); - LPCSTR szModule = luaL_checkstring(L, 2); - LPCSTR szSetting = luaL_checkstring(L, 3); - - INT_PTR res = db_unset(hContact, szModule, szSetting); - lua_pushboolean(L, !res); - - return 1; -} - -/***********************************************/ - -static luaL_Reg databaseApi[] = -{ - { "Contacts", db_Contacts }, - { "GetContactInfo", db_GetContactInfo }, - - { "GetEventCount", db_GetEventCount }, - - { "GetFirstEvent", db_GetFirstEvent }, - { "GetPrevEvent", db_GetPrevEvent }, - { "GetNextEvent", db_GetNextEvent }, - { "GetLastEvent", db_GetLastEvent }, - { "GetFirstUnreadEvent", db_GetFirstUnreadEvent }, - { "Events", db_Events }, - { "EventsFromEnd", db_EventsFromEnd }, - { "UnreadEvents", db_UnreadEvents }, - { "AddEvent", db_AddEvent }, - { "MarkReadEvent", db_MarkReadEvent }, - - { "Settings", db_Settings }, - { "Modules", db_Modules }, - - { "DeleteModule", db_DeleteModule }, - - { "GetSetting", db_GetSetting }, - { "WriteSetting", db_WriteSetting }, - { "SetSetting", db_WriteSetting }, - { "DeleteSetting", db_DeleteSetting }, - - { "DBVT_BYTE", nullptr }, - { "DBVT_WORD", nullptr }, - { "DBVT_DWORD", nullptr }, - { "DBVT_ASCIIZ", nullptr }, - { "DBVT_UTF8", nullptr }, - { "DBVT_WCHAR", nullptr }, - - { nullptr, nullptr } -}; - -/***********************************************/ - -#define MT_DBCONTACTWRITESETTING "DBCONTACTWRITESETTING" - -template <> -int MT::Get(lua_State *L, DBCONTACTWRITESETTING *dbcw) -{ - const char *key = luaL_checkstring(L, 2); - - if (mir_strcmpi(key, "Value") == 0) - luaM_pushdbvt(L, dbcw->value); - else - lua_pushnil(L); - - return 1; -} - -/***********************************************/ - -#define MT_DBEVENTINFO "DBEVENTINFO" - -template <> -DBEVENTINFO* MT::Init(lua_State *L) -{ - MEVENT hDbEvent = luaL_checkinteger(L, 1); - - DBEVENTINFO* dbei = (DBEVENTINFO*)mir_calloc(sizeof(DBEVENTINFO)); - dbei->cbBlob = db_event_getBlobSize((MEVENT)hDbEvent); - dbei->pBlob = (PBYTE)mir_calloc(dbei->cbBlob); - db_event_get((MEVENT)hDbEvent, dbei); - - return dbei; -} - -template <> -int MT::Get(lua_State *L, DBEVENTINFO *dbei) -{ - const char *key = luaL_checkstring(L, 2); - - if (mir_strcmpi(key, "Blob") == 0) { - lua_createtable(L, dbei->cbBlob, 0); - for (DWORD i = 0; i < dbei->cbBlob; i++) { - lua_pushinteger(L, dbei->pBlob[i]); - lua_rawseti(L, -2, i + 1); - } - } - else - lua_pushnil(L); - - return 1; -} - -template <> -void MT::Free(lua_State*, DBEVENTINFO **dbei) -{ - mir_free((*dbei)->pBlob); - mir_free(*dbei); -} - -/***********************************************/ - -LUAMOD_API int luaopen_m_database(lua_State *L) -{ - luaL_newlib(L, databaseApi); - - lua_pushnumber(L, DBVT_BYTE); - lua_setfield(L, -2, "DBVT_BYTE"); - lua_pushnumber(L, DBVT_WORD); - lua_setfield(L, -2, "DBVT_WORD"); - lua_pushnumber(L, DBVT_DWORD); - lua_setfield(L, -2, "DBVT_DWORD"); - lua_pushnumber(L, DBVT_ASCIIZ); - lua_setfield(L, -2, "DBVT_ASCIIZ"); - lua_pushnumber(L, DBVT_UTF8); - lua_setfield(L, -2, "DBVT_UTF8"); - lua_pushnumber(L, DBVT_WCHAR); - lua_setfield(L, -2, "DBVT_WCHAR"); - - MT(L, MT_DBCONTACTWRITESETTING) - .Field(&DBCONTACTWRITESETTING::szModule, "Module", LUA_TSTRINGA) - .Field(&DBCONTACTWRITESETTING::szSetting, "Setting", LUA_TSTRINGA); - - MT(L, MT_DBEVENTINFO) - .Field(&DBEVENTINFO::szModule, "Module", LUA_TSTRINGA) - .Field(&DBEVENTINFO::timestamp, "Timestamp", LUA_TINTEGER) - .Field(&DBEVENTINFO::eventType, "Type", LUA_TINTEGER) - .Field(&DBEVENTINFO::flags, "Flags", LUA_TINTEGER); - - return 1; -} diff --git a/plugins/MirLua/src/m_database.h b/plugins/MirLua/src/m_database.h deleted file mode 100644 index 73ba76f28c..0000000000 --- a/plugins/MirLua/src/m_database.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _LUA_M_DATABASE_H_ -#define _LUA_M_DATABASE_H_ - -#include - -#define MLUA_DATABASE "m_database" -LUAMOD_API int (luaopen_m_database)(lua_State *L); - -#endif //_LUA_M_DATABASE_H_ \ No newline at end of file diff --git a/plugins/MirLua/src/m_genmenu.cpp b/plugins/MirLua/src/m_genmenu.cpp deleted file mode 100644 index 50043827ed..0000000000 --- a/plugins/MirLua/src/m_genmenu.cpp +++ /dev/null @@ -1,133 +0,0 @@ -#include "stdafx.h" - -void MakeMenuItem(lua_State *L, CMenuItem &mi) -{ - mi.langId = CMLuaEnvironment::GetEnvironmentId(L); - - lua_getfield(L, -1, "Flags"); - mi.flags = lua_tointeger(L, -1); - lua_pop(L, 1); - - if (!(mi.flags & CMIF_UNICODE)) - mi.flags |= CMIF_UNICODE; - - lua_getfield(L, -1, "Uid"); - const char* uuid = lua_tostring(L, -1); - if (UuidFromStringA((RPC_CSTR)uuid, (UUID*)&mi.uid)) - UNSET_UID(mi); - lua_pop(L, 1); - - lua_getfield(L, -1, "Name"); - mi.name.w = mir_utf8decodeW(luaL_checkstring(L, -1)); - lua_pop(L, 1); - - lua_getfield(L, -1, "Position"); - mi.position = lua_tointeger(L, -1); - lua_pop(L, 1); - - lua_getfield(L, -1, "Icon"); - mi.hIcolibItem = (HANDLE)lua_touserdata(L, -1); - lua_pop(L, 1); - - lua_getfield(L, -1, "Service"); - mi.pszService = lua_tostring(L, -1); - lua_pop(L, 1); - - lua_getfield(L, -1, "Parent"); - mi.root = (HGENMENU)lua_touserdata(L, -1); - lua_pop(L, 1); -} - -static int genmenu_ModifyMenuItem(lua_State *L) -{ - luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); - HGENMENU hMenuItem = (HGENMENU)lua_touserdata(L, 1); - ptrW name(mir_utf8decodeW(lua_tostring(L, 2))); - HANDLE hIcolibItem = luaL_opt(L, lua_touserdata, 3, INVALID_HANDLE_VALUE); - int flags = luaL_optinteger(L, 4, -1); - - if (!(flags & CMIF_UNICODE)) - flags |= CMIF_UNICODE; - - INT_PTR res = Menu_ModifyItem(hMenuItem, name, hIcolibItem, flags); - lua_pushboolean(L, res == 0); - - return 1; -} - -static int genmenu_ConfigureMenuItem(lua_State *L) -{ - luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); - HGENMENU hMenuItem = (HGENMENU)lua_touserdata(L, 1); - int option = luaL_checkinteger(L, 2); - luaL_checktype(L, 3, LUA_TLIGHTUSERDATA); - INT_PTR value = (INT_PTR)lua_touserdata(L, 3); - - int res = Menu_ConfigureItem(hMenuItem, option, value); - lua_pushboolean(L, res >= 0); - - return 1; -} - -static int genmenu_ShowMenuItem(lua_State *L) -{ - luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); - HGENMENU hMenuItem = (HGENMENU)lua_touserdata(L, 1); - bool isShow = luaM_toboolean(L, 2); - - Menu_ShowItem(hMenuItem, isShow); - - return 0; -} - -static int genmenu_EnableMenuItem(lua_State *L) -{ - luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); - HGENMENU hMenuItem = (HGENMENU)lua_touserdata(L, 1); - bool isEnable = luaM_toboolean(L, 2); - - Menu_EnableItem(hMenuItem, isEnable); - - return 0; -} - -static int genmenu_CheckMenuItem(lua_State *L) -{ - luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); - HGENMENU hMenuItem = (HGENMENU)lua_touserdata(L, 1); - bool isChecked = luaM_toboolean(L, 2); - - Menu_SetChecked(hMenuItem, isChecked); - - return 0; -} - -static int genmenu_RemoveMenuItem(lua_State *L) -{ - luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); - HGENMENU hMenuItem = (HGENMENU)lua_touserdata(L, 1); - - INT_PTR res = Menu_RemoveItem(hMenuItem); - lua_pushboolean(L, res == 0); - - return 1; -} - -static luaL_Reg genmenuApi[] = -{ - { "ModifyMenuItem", genmenu_ModifyMenuItem }, - { "ConfigureMenuItem", genmenu_ConfigureMenuItem }, - { "ShowMenuItem", genmenu_ShowMenuItem }, - { "EnableMenuItem", genmenu_EnableMenuItem }, - { "CheckMenuItem", genmenu_CheckMenuItem }, - { "RemoveMenuItem", genmenu_RemoveMenuItem }, - - { nullptr, nullptr } -}; - -LUAMOD_API int luaopen_m_genmenu(lua_State *L) -{ - luaL_newlib(L, genmenuApi); - - return 1; -} diff --git a/plugins/MirLua/src/m_genmenu.h b/plugins/MirLua/src/m_genmenu.h deleted file mode 100644 index b368627dc8..0000000000 --- a/plugins/MirLua/src/m_genmenu.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _LUA_M_GENMENU_H_ -#define _LUA_M_GENMENU_H_ - -#include - -#define MLUA_GENMENU "m_genmenu" -LUAMOD_API int (luaopen_m_genmenu)(lua_State *L); - -void MakeMenuItem(lua_State *L, CMenuItem &mi); - -#endif //_LUA_M_GENMENU_H_ \ No newline at end of file diff --git a/plugins/MirLua/src/m_hotkeys.cpp b/plugins/MirLua/src/m_hotkeys.cpp deleted file mode 100644 index 8e38f16bf8..0000000000 --- a/plugins/MirLua/src/m_hotkeys.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#include "stdafx.h" - -void MakeHotkey(lua_State *L, HOTKEYDESC &hk) -{ - lua_getfield(L, -1, "Flags"); - hk.dwFlags = lua_tointeger(L, -1); - lua_pop(L, 1); - - if (!(hk.dwFlags & HKD_UNICODE)) - hk.dwFlags |= HKD_UNICODE; - - lua_getfield(L, -1, "Name"); - hk.pszName = mir_utf8decodeA(luaL_checkstring(L, -1)); - lua_pop(L, 1); - - lua_getfield(L, -1, "Description"); - hk.szDescription.w = mir_utf8decodeW(lua_tostring(L, -1)); - lua_pop(L, 1); - - lua_getfield(L, -1, "Section"); - hk.szSection.w = mir_utf8decodeW(luaL_optstring(L, -1, MODULENAME)); - lua_pop(L, 1); - - lua_getfield(L, -1, "Hotkey"); - hk.DefHotKey = lua_tointeger(L, -1); - lua_pop(L, 1); - - lua_getfield(L, -1, "Service"); - hk.pszService = mir_utf8decodeA(luaL_checkstring(L, -1)); - lua_pop(L, 1); - - lua_getfield(L, -1, "lParam"); - hk.lParam = (LPARAM)lua_touserdata(L, -1); - lua_pop(L, 1); -} - -static int hotkeys_Register(lua_State *L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - - HOTKEYDESC hk; - MakeHotkey(L, hk); - - int hScriptLangpack = CMLuaEnvironment::GetEnvironmentId(L); - - INT_PTR res = Hotkey_Register(&hk, hScriptLangpack); - lua_pushboolean(L, res); - - return 1; -} - -static int hotkeys_Unregister(lua_State *L) -{ - const char *name = luaL_checkstring(L, 1); - - Hotkey_Unregister(name); - - return 0; -} - -static const char *mods[] = { "shift", "ctrl", "alt", "ext", nullptr }; - -static int hotkeys_MakeHotkey(lua_State *L) -{ - int mod = 0; - switch (lua_type(L, 1)) - { - case LUA_TNUMBER: - mod = luaL_checkinteger(L, 1); - break; - case LUA_TSTRING: - mod = (1 << (luaL_checkoption(L, 1, nullptr, mods) - 1)); - break; - case LUA_TTABLE: - for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 1)) - mod |= (1 << (luaL_checkoption(L, -1, nullptr, mods) - 1)); - break; - default: - luaL_argerror(L, 1, luaL_typename(L, 1)); - } - int vk = luaL_checknumber(L, 2); - - WORD res = HOTKEYCODE(mod, vk); - lua_pushinteger(L, res); - - return 1; -} - -static luaL_Reg hotkeysApi[] = -{ - { "MakeHotkey", hotkeys_MakeHotkey }, - { "Register", hotkeys_Register }, - { "Unregister", hotkeys_Unregister }, - - { nullptr, nullptr } -}; - -LUAMOD_API int luaopen_m_hotkeys(lua_State *L) -{ - luaL_newlib(L, hotkeysApi); - - return 1; -} diff --git a/plugins/MirLua/src/m_http.cpp b/plugins/MirLua/src/m_http.cpp deleted file mode 100644 index 5d1e7d4519..0000000000 --- a/plugins/MirLua/src/m_http.cpp +++ /dev/null @@ -1,443 +0,0 @@ -#include "stdafx.h" - -/***********************************************/ - -#define MT_NETLIBHTTPHEADERS "NETLIBHTTPHEADERS" - -struct NETLIBHTTPHEADERS -{ - const NETLIBHTTPHEADER *headers; - int count; -}; - -static void AddHeader(NETLIBHTTPREQUEST *request, const char *name, const char *value) -{ - request->headers = (NETLIBHTTPHEADER*)mir_realloc(request->headers, - sizeof(NETLIBHTTPHEADER)*(request->headersCount + 1)); - NETLIBHTTPHEADER &header = request->headers[request->headersCount]; - header.szName = mir_strdup(name); - header.szValue = mir_strdup(value); - request->headersCount++; -} - -static void SetHeader(NETLIBHTTPREQUEST *request, const char *name, const char *value) -{ - for (int i = 0; i < request->headersCount; i++) { - if (mir_strcmp(request->headers[i].szName, name) == 0) { - mir_free(request->headers[i].szValue); - request->headers[i].szValue = mir_strdup(value); - return; - } - } - AddHeader(request, name, value); -} - -static int headers_Iterator(lua_State *L) -{ - NETLIBHTTPHEADER *headers = (NETLIBHTTPHEADER*)lua_touserdata(L, lua_upvalueindex(1)); - int count = lua_tointeger(L, lua_upvalueindex(2)); - int idx = lua_tointeger(L, lua_upvalueindex(3)); - - if (idx < count) { - lua_pushstring(L, headers[idx].szName); - lua_pushstring(L, headers[idx].szValue); - lua_pushinteger(L, idx + 1); - lua_replace(L, lua_upvalueindex(3)); - return 2; - } - - lua_pushnil(L); - - return 1; -} - -static int headers__call(lua_State *L) -{ - NETLIBHTTPHEADERS *headers = (NETLIBHTTPHEADERS*)luaL_checkudata(L, 1, MT_NETLIBHTTPHEADERS); - - lua_pushlightuserdata(L, (void*)headers->headers); - lua_pushinteger(L, headers->count); - lua_pushinteger(L, 0); - lua_pushcclosure(L, headers_Iterator, 3); - - return 1; -} - -static int headers__index(lua_State *L) -{ - NETLIBHTTPHEADERS *headers = (NETLIBHTTPHEADERS*)luaL_checkudata(L, 1, MT_NETLIBHTTPHEADERS); - - if (lua_isinteger(L, 2)) { - int idx = lua_tointeger(L, 2); - if (idx > 0 && idx <= headers->count) { - lua_pushstring(L, headers->headers[idx - 1].szValue); - return 1; - } - } - - const char *key = lua_tostring(L, 2); - for (int i = 0; i < headers->count; i++) { - if (mir_strcmp(headers->headers[i].szName, key) == 0) { - lua_pushstring(L, headers->headers[i].szValue); - return 1; - } - } - - lua_pushnil(L); - - return 1; -} - -static int headers__len(lua_State *L) -{ - NETLIBHTTPHEADERS *headers = (NETLIBHTTPHEADERS*)luaL_checkudata(L, 1, MT_NETLIBHTTPHEADERS); - - lua_pushinteger(L, headers->count); - - return 1; -} - -static const luaL_Reg headersApi[] = -{ - { "__call", headers__call }, - { "__index", headers__index }, - { "__len", headers__len }, - - { nullptr, nullptr } -}; - -/***********************************************/ - -#define MT_NETLIBHTTPCONTENT "NETLIBHTTPCONTENT" - -struct NETLIBHTTPCONTENT -{ - const char *data; - int length; -}; - -static int content__index(lua_State *L) -{ - NETLIBHTTPCONTENT *content = (NETLIBHTTPCONTENT*)luaL_checkudata(L, 1, MT_NETLIBHTTPCONTENT); - - int idx = luaL_checkinteger(L, 2); - if (idx > 0 && idx <= content->length) { - lua_pushinteger(L, content->data[idx - 1]); - return 1; - } - - lua_pushnil(L); - - return 1; -} - -static int content__len(lua_State *L) -{ - NETLIBHTTPCONTENT *content = (NETLIBHTTPCONTENT*)luaL_checkudata(L, 1, MT_NETLIBHTTPCONTENT); - - lua_pushinteger(L, content->length); - - return 1; -} - -static int content__tostring(lua_State *L) -{ - NETLIBHTTPCONTENT *content = (NETLIBHTTPCONTENT*)luaL_checkudata(L, 1, MT_NETLIBHTTPCONTENT); - - lua_pushlstring(L, content->data, content->length); - - return 1; -} - -static const luaL_Reg contentApi[] = -{ - { "__index", content__index }, - { "__len", content__len }, - { "__tostring", content__tostring }, - - { nullptr, nullptr } -}; - -/***********************************************/ - -#define MT_NETLIBHTTPRESPONSE "NETLIBHTTPRESPONSE" - -static NETLIBHTTPREQUEST* response_Create(lua_State *L, NETLIBHTTPREQUEST *request) -{ - NETLIBHTTPREQUEST **response = (NETLIBHTTPREQUEST**)lua_newuserdata(L, sizeof(NETLIBHTTPREQUEST*)); - *response = Netlib_HttpTransaction(hNetlib, request); - luaL_setmetatable(L, MT_NETLIBHTTPRESPONSE); - - return *response; -} - -static int response__index(lua_State *L) -{ - NETLIBHTTPREQUEST *response = *(NETLIBHTTPREQUEST**)luaL_checkudata(L, 1, MT_NETLIBHTTPRESPONSE); - const char *key = lua_tostring(L, 2); - - if (mir_strcmpi(key, "Headers") == 0) { - NETLIBHTTPHEADERS *headers = (NETLIBHTTPHEADERS*)lua_newuserdata(L, sizeof(NETLIBHTTPHEADERS)); - headers->headers = response->headers; - headers->count = response->headersCount; - luaL_setmetatable(L, MT_NETLIBHTTPHEADERS); - } - else if (mir_strcmpi(key, "Content") == 0) { - NETLIBHTTPCONTENT *content = (NETLIBHTTPCONTENT*)lua_newuserdata(L, sizeof(NETLIBHTTPCONTENT)); - content->data = response->pData; - content->length = response->dataLength; - luaL_setmetatable(L, MT_NETLIBHTTPCONTENT); - } - else if (mir_strcmpi(key, "StatusCode") == 0) - lua_pushinteger(L, response->resultCode); - else if (mir_strcmpi(key, "IsSuccess") == 0) { - lua_pushboolean(L, HTTP_CODE_SUCCESS(response->resultCode)); - } - else - lua_pushnil(L); - - return 1; -} - -static int response__gc(lua_State *L) -{ - NETLIBHTTPREQUEST **response = (NETLIBHTTPREQUEST**)luaL_checkudata(L, 1, MT_NETLIBHTTPRESPONSE); - - Netlib_FreeHttpRequest(*response); - - return 0; -} - -static const luaL_Reg responseApi[] = -{ - { "__index", response__index }, - { "__gc", response__gc }, - - { nullptr, nullptr } -}; - -/***********************************************/ - -#define MT_NETLIBHTTPREQUEST "NETLIBHTTPREQUEST" - -static NETLIBHTTPREQUEST* CreateRequest(lua_State *L) -{ - NETLIBHTTPREQUEST **request = (NETLIBHTTPREQUEST**)lua_newuserdata(L, sizeof(NETLIBHTTPREQUEST*)); - *request = (NETLIBHTTPREQUEST*)mir_calloc(sizeof(NETLIBHTTPREQUEST)); - (*request)->cbSize = sizeof(NETLIBHTTPREQUEST); - (*request)->flags = NLHRF_HTTP11 | NLHRF_NODUMP; - - luaL_setmetatable(L, MT_NETLIBHTTPREQUEST); - - return *request; -} - -static void request_SetUrl(lua_State *L, int idx, NETLIBHTTPREQUEST *request) -{ - const char *url = luaL_checkstring(L, idx); - request->szUrl = mir_strdup(url); - if (mir_strncmpi(request->szUrl, "https", 5) == 0) - request->flags |= NLHRF_SSL; - else - request->flags &= ~(NLHRF_SSL); -} - -static void request_SetHeaders(lua_State *L, int idx, NETLIBHTTPREQUEST *request) -{ - if (lua_isnoneornil(L, idx)) - return; - - luaL_checktype(L, idx, LUA_TTABLE); - - idx = lua_absindex(L, idx); - for (lua_pushnil(L); lua_next(L, idx); lua_pop(L, 2)) { - lua_pushvalue(L, -2); - const char *name = lua_tostring(L, -1); - const char *value = lua_tostring(L, -2); - AddHeader(request, name, value); - } -} - -static void request_SetContent(lua_State *L, int idx, NETLIBHTTPREQUEST *request) -{ - CMStringA data; - - switch (lua_type(L, idx)) - { - case LUA_TNONE: - case LUA_TNIL: - return; - case LUA_TSTRING: - data = lua_tostring(L, idx); - SetHeader(request, "Content-Type", "text/plain"); - break; - case LUA_TTABLE: - { - idx = lua_absindex(L, idx); - for (lua_pushnil(L); lua_next(L, idx); lua_pop(L, 2)) { - lua_pushvalue(L, -2); - const char *name = lua_tostring(L, -1); - const char *value = lua_tostring(L, -2); - data.AppendFormat("&%s=%s", name, value); - } - data.Delete(0); - SetHeader(request, "Content-Type", "application/x-www-form-urlencoded"); - break; - } - default: - luaL_argerror(L, idx, luaL_typename(L, idx)); - } - - request->pData = mir_strdup(data); - request->dataLength = data.GetLength(); -} - -static void request_SetContentType(lua_State *L, int idx, NETLIBHTTPREQUEST *request) -{ - if (!lua_isstring(L, idx)) - return; - - const char *type = lua_tostring(L, idx); - SetHeader(request, "Content-Type", type); -} - -static const char *httpMethods[] = { "GET", "POST", "PUT", "DELETE", nullptr }; - -static int request_Send(lua_State *L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - - NETLIBHTTPREQUEST *request = CreateRequest(L); - - lua_getfield(L, 1, "Method"); - request->requestType = (1 << (luaL_checkoption(L, -1, nullptr, httpMethods))); - lua_pop(L, 1); - - lua_getfield(L, 1, "Url"); - request_SetUrl(L, -1, request); - lua_pop(L, 1); - - lua_getfield(L, 1, "Headers"); - request_SetHeaders(L, -1, request); - lua_pop(L, 1); - - lua_getfield(L, 1, "Content"); - request_SetContent(L, -1, request); - lua_pop(L, 1); - - lua_getfield(L, 1, "Timeout"); - request->timeout = luaL_optinteger(L, -1, 0); - lua_pop(L, 1); - - response_Create(L, request); - - return 1; -} - -static int request_Get(lua_State *L) -{ - NETLIBHTTPREQUEST *request = CreateRequest(L); - request->requestType = REQUEST_GET; - request_SetUrl(L, 1, request); - - response_Create(L, request); - - return 1; -} - -static int request_Post(lua_State *L) -{ - NETLIBHTTPREQUEST *request = CreateRequest(L); - request->requestType = REQUEST_POST; - request_SetUrl(L, 1, request); - request_SetContent(L, 2, request); - request_SetContentType(L, 3, request); - - response_Create(L, request); - - return 1; -} - -static int request_Put(lua_State *L) -{ - NETLIBHTTPREQUEST *request = CreateRequest(L); - request->requestType = REQUEST_PUT; - request_SetUrl(L, 1, request); - request_SetContent(L, 2, request); - request_SetContentType(L, 3, request); - - response_Create(L, request); - - return 1; -} - -static int request_Delete(lua_State *L) -{ - NETLIBHTTPREQUEST *request = CreateRequest(L); - request->requestType = REQUEST_DELETE; - request_SetUrl(L, 1, request); - request_SetContent(L, 2, request); - request_SetContentType(L, 2, request); - - response_Create(L, request); - - return 1; -} - -static int request__gc(lua_State *L) -{ - NETLIBHTTPREQUEST **request = (NETLIBHTTPREQUEST**)luaL_checkudata(L, 1, MT_NETLIBHTTPREQUEST); - - mir_free((*request)->szUrl); - for (int i = 0; i < (*request)->headersCount; i++) { - mir_free((*request)->headers[i].szName); - mir_free((*request)->headers[i].szValue); - } - mir_free((*request)->headers); - mir_free((*request)->pData); - - return 0; -} - -static const luaL_Reg requestApi[] = -{ - { "__gc", request__gc }, - - { nullptr, nullptr } -}; - -/***********************************************/ - -static const luaL_Reg httpApi[] = -{ - { "Send", request_Send }, - { "Get", request_Get }, - { "Post", request_Post }, - { "Put", request_Put }, - { "Delete", request_Delete }, - - { nullptr, nullptr } -}; - -LUAMOD_API int luaopen_m_http(lua_State *L) -{ - luaL_newlib(L, httpApi); - - luaL_newmetatable(L, MT_NETLIBHTTPREQUEST); - luaL_setfuncs(L, requestApi, 0); - lua_pop(L, 1); - - luaL_newmetatable(L, MT_NETLIBHTTPRESPONSE); - luaL_setfuncs(L, responseApi, 0); - lua_pop(L, 1); - - luaL_newmetatable(L, MT_NETLIBHTTPHEADERS); - luaL_setfuncs(L, headersApi, 0); - lua_pop(L, 1); - - luaL_newmetatable(L, MT_NETLIBHTTPCONTENT); - luaL_setfuncs(L, contentApi, 0); - lua_pop(L, 1); - - return 1; -} diff --git a/plugins/MirLua/src/m_icolib.cpp b/plugins/MirLua/src/m_icolib.cpp deleted file mode 100644 index a83c9877d7..0000000000 --- a/plugins/MirLua/src/m_icolib.cpp +++ /dev/null @@ -1,155 +0,0 @@ -#include "stdafx.h" - -static void MakeSKINICONDESC(lua_State *L, SKINICONDESC &sid) -{ - lua_getfield(L, -1, "Flags"); - sid.flags = lua_tointeger(L, -1); - lua_pop(L, 1); - - if (!(sid.flags & SIDF_ALL_UNICODE)) - sid.flags |= SIDF_ALL_UNICODE; - - lua_getfield(L, -1, "Name"); - sid.pszName = mir_utf8decodeA(luaL_checkstring(L, -1)); - lua_pop(L, 1); - - lua_getfield(L, -1, "Description"); - sid.description.w = mir_utf8decodeW(luaL_checkstring(L, -1)); - lua_pop(L, 1); - - lua_getfield(L, -1, "Section"); - sid.section.w = mir_utf8decodeW(luaL_optstring(L, 3, MODULENAME)); - lua_pop(L, 1); - - lua_getfield(L, -1, "DefaultFile"); - sid.defaultFile.w = mir_utf8decodeW(lua_tostring(L, -1)); - lua_pop(L, 1); - - if (sid.defaultFile.w == nullptr) - { - sid.defaultFile.w = (wchar_t*)mir_calloc(MAX_PATH + 1); - GetModuleFileName(g_plugin.getInst(), sid.defaultFile.w, MAX_PATH); - } - - lua_getfield(L, -1, "DefaultIndex"); - sid.iDefaultIndex = lua_tointeger(L, -1); - lua_pop(L, 1); - - lua_getfield(L, -1, "DefaultIcon"); - sid.hDefaultIcon = (HICON)lua_touserdata(L, -1); - lua_pop(L, 1); - - lua_getfield(L, -1, "SizeX"); - sid.iDefaultIndex = lua_tointeger(L, -1); - lua_pop(L, 1); - - lua_getfield(L, -1, "SizeY"); - sid.iDefaultIndex = lua_tointeger(L, -1); - lua_pop(L, 1); -} - -static int lua_AddIcon(lua_State *L) -{ - SKINICONDESC sid = { }; - - if (lua_type(L, 1) == LUA_TSTRING) - { - sid.flags = SIDF_ALL_UNICODE; - sid.pszName = mir_utf8decodeA(luaL_checkstring(L, 1)); - sid.description.w = mir_utf8decodeW(luaL_checkstring(L, 2)); - sid.section.w = mir_utf8decodeW(luaL_optstring(L, 3, MODULENAME)); - sid.defaultFile.w = mir_utf8decodeW(lua_tostring(L, 4)); - sid.hDefaultIcon = GetIcon(IDI_SCRIPT); - - if (sid.defaultFile.w == nullptr) - { - sid.defaultFile.w = (wchar_t*)mir_calloc(MAX_PATH + 1); - GetModuleFileName(g_plugin.getInst(), sid.defaultFile.w, MAX_PATH); - } - } - else if (lua_type(L, 1) == LUA_TTABLE) - MakeSKINICONDESC(L, sid); - else - luaL_argerror(L, 1, luaL_typename(L, 1)); - - int hScriptLangpack = CMLuaEnvironment::GetEnvironmentId(L); - HANDLE res = IcoLib_AddIcon(&sid, hScriptLangpack); - lua_pushlightuserdata(L, res); - - mir_free((void*)sid.pszName); - mir_free((void*)sid.description.w); - mir_free((void*)sid.section.w); - mir_free((void*)sid.defaultFile.w); - - return 1; -} - -static int lua_GetIcon(lua_State *L) -{ - bool big = luaM_toboolean(L, 2); - - HICON hIcon = nullptr; - switch (lua_type(L, 1)) - { - case LUA_TLIGHTUSERDATA: - hIcon = IcoLib_GetIconByHandle(lua_touserdata(L, 1), big); - break; - case LUA_TSTRING: - hIcon = IcoLib_GetIcon(lua_tostring(L, 1), big); - break; - default: - luaL_argerror(L, 1, luaL_typename(L, 1)); - } - - if (hIcon) - lua_pushlightuserdata(L, hIcon); - else - lua_pushnil(L); - - return 1; -} - -static int lua_GetIconHandle(lua_State *L) -{ - const char *name = luaL_checkstring(L, 1); - - HANDLE res = IcoLib_GetIconHandle(name); - lua_pushlightuserdata(L, res); - - return 1; -} - -static int lua_RemoveIcon(lua_State *L) -{ - switch (lua_type(L, 1)) - { - case LUA_TLIGHTUSERDATA: - IcoLib_RemoveIconByHandle(lua_touserdata(L, 1)); - break; - case LUA_TSTRING: - IcoLib_RemoveIcon(luaL_checkstring(L, 1)); - break; - default: - luaL_argerror(L, 1, luaL_typename(L, 1)); - } - - return 0; -} - -static luaL_Reg icolibApi[] = -{ - { "AddIcon", lua_AddIcon }, - { "GetIcon", lua_GetIcon }, - { "GetHandle", lua_GetIconHandle }, - { "GetIconHandle", lua_GetIconHandle }, - { "RemoveIcon", lua_RemoveIcon }, - - { nullptr, nullptr } -}; - -LUAMOD_API int luaopen_m_icolib(lua_State *L) -{ - luaL_newlib(L, icolibApi); - - return 1; -} diff --git a/plugins/MirLua/src/m_json.cpp b/plugins/MirLua/src/m_json.cpp deleted file mode 100644 index eccef5cff2..0000000000 --- a/plugins/MirLua/src/m_json.cpp +++ /dev/null @@ -1,241 +0,0 @@ -#include "stdafx.h" - -static void lua2json(lua_State *L, JSONNode &node) -{ - switch (lua_type(L, -1)) { - case LUA_TNIL: - node.nullify(); - break; - case LUA_TSTRING: - node = lua_tostring(L, -1); - break; - case LUA_TBOOLEAN: - node = lua_toboolean(L, -1) != 0; - break; - case LUA_TNUMBER: - { - lua_Integer val = lua_tointeger(L, -1); - if (lua_isinteger(L, -1) && val >= LONG_MIN && val <= LONG_MIN) - node = (long)val; - else - node = lua_tonumber(L, -1); - break; - } - case LUA_TTABLE: - { - ptrA name(mir_strdup(node.name())); - node.cast(JSON_ARRAY); - node.set_name((char*)name); - - lua_pushnil(L); - while (lua_next(L, -2) != 0) { - JSONNode child; - if (!lua_isnumber(L, -2)) { - if (node.type() == JSON_ARRAY) { - node.cast(JSON_NODE); - node.set_name((char*)name); - } - const char *key = lua_tostring(L, -2); - child.set_name(key); - } - lua2json(L, child); - node << child; - - lua_pop(L, 1); - } - - break; - } - } -} - -/***********************************************/ - -static int json__index(lua_State *L) -{ - JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); - - JSONNode *child; - if (node->type() == JSON_ARRAY) { - int idx = lua_tointeger(L, 2); - child = &node->at(idx - 1); - } - else { - const char *key = lua_tostring(L, 2); - child = &node->at(key); - } - - switch (child->type()) - { - case JSON_NULL: - lua_pushnil(L); - break; - case JSON_STRING: - lua_pushstring(L, child->as_string().c_str()); - break; - case JSON_NUMBER: - lua_pushnumber(L, child->as_int()); - break; - case JSON_BOOL: - lua_pushboolean(L, child->as_bool()); - break; - case JSON_ARRAY: - case JSON_NODE: - JSONNode **udata = (JSONNode**)lua_newuserdata(L, sizeof(JSONNode*)); - *udata = child; - luaL_setmetatable(L, MT_JSON); - } - - return 1; -} - -static int json__newindex(lua_State *L) -{ - JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); - const char *key = lua_tostring(L, 2); - - if (json_type(node) == JSON_ARRAY) { - int idx = lua_tointeger(L, 2); - JSONNode *child = json_at(node, idx - 1); - lua2json(L, *child); - return 0; - } - - JSONNode *child = json_get(node, key); - if (json_type(child) == JSON_NULL) { - json_set_name(child, key); - lua2json(L, *child); - json_push_back(node, child); - return 0; - } - - lua2json(L, *child); - - return 0; -} - -static int json__len(lua_State *L) -{ - JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); - lua_pushnumber(L, json_size(node)); - - return 1; -} - -static int json__tostring(lua_State *L) -{ - JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); - - lua_pushstring(L, node->write().c_str()); - - return 1; -} - -static int json__gc(lua_State *L) -{ - JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); - - json_delete(node); - - return 0; -} - -const struct luaL_Reg jsonApi[] = -{ - { "__index", json__index }, - { "__newindex", json__newindex }, - { "__len", json__len }, - { "__tostring", json__tostring }, - { "__gc", json__gc }, - - { nullptr, nullptr } -}; - - -/***********************************************/ - -static int lua_Decode(lua_State *L) -{ - const char *string = luaL_checkstring(L, 1); - - JSONNode **udata = (JSONNode**)lua_newuserdata(L, sizeof(JSONNode*)); - *udata = json_parse(string); - luaL_setmetatable(L, MT_JSON); - - return 1; -} - -static int lua_Encode(lua_State *L) -{ - switch (lua_type(L, 1)) { - case LUA_TNIL: - lua_pushliteral(L, "null"); - break; - case LUA_TBOOLEAN: - lua_pushstring(L, lua_toboolean(L, 1) ? "true" : "false"); - break; - case LUA_TNUMBER: - { - if (lua_isinteger(L, 1)) { - lua_pushfstring(L, "%I", lua_tointeger(L, 1)); - break; - } - char decpoint = lua_getlocaledecpoint(); - if (decpoint != '.') { - char p[2] = { decpoint }; - luaL_gsub(L, lua_tostring(L, 1), p, "."); - } - else - lua_pushfstring(L, "%f", lua_tonumber(L, 1)); - break; - } - case LUA_TSTRING: - lua_pushfstring(L, "\"%s\"", lua_tostring(L, 1)); - break; - case LUA_TTABLE: - { - JSONNode node; - lua_pushnil(L); - lua_pushvalue(L, 1); - lua2json(L, node); - lua_pop(L, 2); - lua_pushstring(L, node.write().c_str()); - break; - } - case LUA_TUSERDATA: - { - JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); - lua_pushstring(L, node->write().c_str()); - break; - } - case LUA_TLIGHTUSERDATA: - if (lua_touserdata(L, 1) == nullptr) - { - lua_pushliteral(L, "null"); - break; - } - default: - luaL_argerror(L, 1, luaL_typename(L, 1)); - } - - return 1; -} - -static const luaL_Reg methods[] = -{ - { "Decode", lua_Decode }, - { "Encode", lua_Encode }, - - { nullptr, nullptr } -}; - -LUAMOD_API int luaopen_m_json(lua_State *L) -{ - luaL_newlib(L, methods); - - luaL_newmetatable(L, MT_JSON); - luaL_setfuncs(L, jsonApi, 0); - lua_pop(L, 1); - - return 1; -} \ No newline at end of file diff --git a/plugins/MirLua/src/m_json.h b/plugins/MirLua/src/m_json.h deleted file mode 100644 index 1357505bec..0000000000 --- a/plugins/MirLua/src/m_json.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _LUA_M_JSON_H_ -#define _LUA_M_JSON_H_ - -#define MT_JSON "JSON" - -#define MLUA_JSON "m_json" -LUAMOD_API int (luaopen_m_json)(lua_State *L); - -#endif //_LUA_M_PROTOCOLS_H_ \ No newline at end of file diff --git a/plugins/MirLua/src/m_message.cpp b/plugins/MirLua/src/m_message.cpp deleted file mode 100644 index 4ac1f991e9..0000000000 --- a/plugins/MirLua/src/m_message.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "stdafx.h" - -static int message_Paste(lua_State *L) -{ - MCONTACT hContact = luaL_checkinteger(L, 1); - ptrW text(mir_utf8decodeW(luaL_checkstring(L, 2))); - - MessageWindowData mwd; - INT_PTR res = Srmm_GetWindowData(hContact, mwd); - lua_pushinteger(L, res); - if (res) - return 1; - - HWND hEdit = GetDlgItem(mwd.hwndWindow, 1002 /*IDC_MESSAGE*/); - if (!hEdit) hEdit = GetDlgItem(mwd.hwndWindow, 1009 /*IDC_CHATMESSAGE*/); - - SendMessage(hEdit, EM_REPLACESEL, TRUE, (LPARAM)text); - - return 1; -} - -static int message_Send(lua_State *L) -{ - MCONTACT hContact = luaL_checkinteger(L, 1); - const char *message = luaL_checkstring(L, 2); - - INT_PTR res = 1; - - const char *szProto = GetContactProto(hContact); - if (db_get_b(hContact, szProto, "ChatRoom", 0) == TRUE) { - ptrW wszChatRoom(db_get_wsa(hContact, szProto, "ChatRoomID")); - ptrW wszMessage(mir_utf8decodeW(message)); - res = Chat_SendUserMessage(szProto, wszChatRoom, wszMessage); - lua_pushinteger(L, res); - } - else if ((res = ProtoChainSend(hContact, PSS_MESSAGE, 0, (LPARAM)message)) != ACKRESULT_FAILED) { - DBEVENTINFO dbei = {}; - dbei.szModule = MODULENAME; - dbei.timestamp = time(0); - dbei.eventType = EVENTTYPE_MESSAGE; - dbei.cbBlob = (DWORD)mir_strlen(message); - dbei.pBlob = (PBYTE)mir_strdup(message); - dbei.flags = DBEF_UTF | DBEF_SENT; - db_event_add(hContact, &dbei); - - lua_pushinteger(L, res); - return 1; - } - - lua_pushinteger(L, res); - - return 1; -} - -static luaL_Reg messageApi[] = -{ - { "Paste", message_Paste }, - { "Send", message_Send }, - - { nullptr, nullptr } -}; - -LUAMOD_API int luaopen_m_message(lua_State *L) -{ - luaL_newlib(L, messageApi); - - MT(L, "MessageWindowEventData") - .Field(&MessageWindowEventData::uType, "Type", LUA_TINTEGER) - .Field(&MessageWindowEventData::hContact, "hContact", LUA_TINTEGER) - .Field(&MessageWindowEventData::uFlags, "Flags", LUA_TINTEGER); - - return 1; -} diff --git a/plugins/MirLua/src/m_options.cpp b/plugins/MirLua/src/m_options.cpp deleted file mode 100644 index 32df2ca366..0000000000 --- a/plugins/MirLua/src/m_options.cpp +++ /dev/null @@ -1,117 +0,0 @@ -#include "stdafx.h" - -class CMLuaScriptOptionPage : public CDlgBase -{ -private: - int m_onInitDialogRef; - int m_onApplyRef; - lua_State *L; - -public: - CMLuaScriptOptionPage(lua_State *_L, int onInitDialogRef, int onApplyRef) - : CDlgBase(g_plugin, IDD_SCRIPTOPTIONSPAGE), L(_L), - m_onInitDialogRef(onInitDialogRef), m_onApplyRef(onApplyRef) - { - } - - void OnInitDialog() override - { - if (m_onInitDialogRef) - { - lua_rawgeti(L, LUA_REGISTRYINDEX, m_onInitDialogRef); - lua_pushlightuserdata(L, m_hwnd); - luaM_pcall(L, 1, 0); - } - } - - void OnApply() override - { - if (m_onApplyRef) - { - lua_rawgeti(L, LUA_REGISTRYINDEX, m_onApplyRef); - lua_pushlightuserdata(L, m_hwnd); - luaM_pcall(L, 1, 0); - } - } - - void OnDestroy() override - { - lua_pushnil(L); - lua_rawsetp(L, LUA_REGISTRYINDEX, this); - } -}; - -void MakeOptionDialogPage(lua_State *L, OPTIONSDIALOGPAGE &odp) -{ - odp.hInstance = g_plugin.getInst(); - odp.langId = CMLuaEnvironment::GetEnvironmentId(L); - - lua_getfield(L, -1, "Flags"); - odp.flags = luaL_optinteger(L, -1, ODPF_BOLDGROUPS | ODPF_UNICODE | ODPF_DONTTRANSLATE); - lua_pop(L, 1); - - if (!(odp.flags & ODPF_UNICODE)) - odp.flags |= ODPF_UNICODE; - - lua_getfield(L, -1, "Group"); - odp.szGroup.w = mir_utf8decodeW(lua_tostring(L, -1)); - lua_pop(L, 1); - - lua_getfield(L, -1, "Title"); - odp.szTitle.w = mir_utf8decodeW(luaL_checkstring(L, -1)); - lua_pop(L, 1); - - lua_getfield(L, -1, "Tab"); - odp.szTab.w = mir_utf8decodeW(lua_tostring(L, -1)); - lua_pop(L, 1); - - int onInitDialogRef = LUA_NOREF; - lua_getfield(L, -1, "OnInitDialog"); - if (lua_isfunction(L, -1)) - onInitDialogRef = luaL_ref(L, LUA_REGISTRYINDEX); - else - lua_pop(L, 1); - - int onApplyRef = LUA_NOREF; - lua_getfield(L, -1, "OnApply"); - if (lua_isfunction(L, -1)) - onApplyRef = luaL_ref(L, LUA_REGISTRYINDEX); - else - lua_pop(L, 1); - - lua_State *T = lua_newthread(L); - lua_rawsetp(L, LUA_REGISTRYINDEX, T); - odp.pDialog = new CMLuaScriptOptionPage(T, onInitDialogRef, onApplyRef); -} - -int opt_AddPage(lua_State *L) -{ - luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); - WPARAM wParam = (WPARAM)lua_touserdata(L, 1); - - OPTIONSDIALOGPAGE odp = { 0 }; - MakeOptionDialogPage(L, odp); - - INT_PTR res = Options_AddPage(wParam, &odp); - lua_pushboolean(L, !res); - - mir_free(odp.szGroup.w); - mir_free(odp.szTitle.w); - mir_free(odp.szTab.w); - - return 1; -} - -static luaL_Reg optionsApi[] = -{ - { "AddPage", opt_AddPage }, - - { nullptr, nullptr } -}; - -LUAMOD_API int luaopen_m_options(lua_State *L) -{ - luaL_newlib(L, optionsApi); - - return 1; -} \ No newline at end of file diff --git a/plugins/MirLua/src/m_protocols.cpp b/plugins/MirLua/src/m_protocols.cpp deleted file mode 100644 index a2e3d7fbc1..0000000000 --- a/plugins/MirLua/src/m_protocols.cpp +++ /dev/null @@ -1,276 +0,0 @@ -#include "stdafx.h" - -HANDLE hRecvMessage = nullptr; - -static int lua_GetProtocol(lua_State *L) -{ - const char *szProto = nullptr; - - switch (lua_type(L, 1)) { - case LUA_TNUMBER: - { - const char *szModule = GetContactProto(lua_tonumber(L, 1)); - PROTOACCOUNT *pa = Proto_GetAccount(szModule); - if (pa) - szProto = pa->szProtoName; - break; - } - case LUA_TSTRING: - szProto = lua_tostring(L, 1); - break; - default: - luaL_argerror(L, 1, luaL_typename(L, 1)); - } - - PROTOCOLDESCRIPTOR *pd = Proto_IsProtocolLoaded(szProto); - if (pd) - MT::Apply(L, pd); - else - lua_pushnil(L); - - return 1; -} - -static int lua_ProtocolIterator(lua_State *L) -{ - int i = lua_tointeger(L, lua_upvalueindex(1)); - int count = lua_tointeger(L, lua_upvalueindex(2)); - PROTOCOLDESCRIPTOR **protos = (PROTOCOLDESCRIPTOR**)lua_touserdata(L, lua_upvalueindex(3)); - - if (i < count) { - lua_pushinteger(L, (i + 1)); - lua_replace(L, lua_upvalueindex(1)); - MT::Apply(L, protos[i]); - } - else - lua_pushnil(L); - - return 1; -} - -static int lua_Protocols(lua_State *L) -{ - int count; - PROTOCOLDESCRIPTOR **protos; - Proto_EnumProtocols(&count, &protos); - - lua_pushinteger(L, 0); - lua_pushinteger(L, count); - lua_pushlightuserdata(L, protos); - lua_pushcclosure(L, lua_ProtocolIterator, 3); - - return 1; -} - -static int lua_ChainSend(lua_State *L) -{ - MCONTACT hContact = luaL_checknumber(L, 1); - const char *service = luaL_checkstring(L, 2); - WPARAM wParam = (WPARAM)luaM_tomparam(L, 3); - LPARAM lParam = (LPARAM)luaM_tomparam(L, 4); - - INT_PTR res = ProtoChainSend(hContact, service, wParam, lParam); - lua_pushinteger(L, res); - - return 1; -} - -static int lua_ChainRecv(lua_State *L) -{ - MCONTACT hContact = luaL_checknumber(L, 1); - const char *service = luaL_checkstring(L, 2); - WPARAM wParam = (WPARAM)luaM_tomparam(L, 3); - LPARAM lParam = (LPARAM)luaM_tomparam(L, 4); - - INT_PTR res = ProtoChainRecv(hContact, service, wParam, lParam); - lua_pushinteger(L, res); - - return 1; -} - -/***********************************************/ - -static int lua_GetAccount(lua_State *L) -{ - const char *name = nullptr; - - switch (lua_type(L, 1)) - { - case LUA_TNUMBER: - name = GetContactProto(lua_tonumber(L, 1)); - break; - case LUA_TSTRING: - name = lua_tostring(L, 1); - break; - default: - luaL_argerror(L, 1, luaL_typename(L, 1)); - } - - PROTOACCOUNT *pa = Proto_GetAccount(name); - if (pa) - MT::Apply(L, pa); - else - lua_pushnil(L); - - return 1; -} - -static int lua_AccountIterator(lua_State *L) -{ - int i = lua_tointeger(L, lua_upvalueindex(1)); - int count = lua_tointeger(L, lua_upvalueindex(2)); - PROTOACCOUNT **accounts = (PROTOACCOUNT**)lua_touserdata(L, lua_upvalueindex(3)); - const char *szProto = lua_tostring(L, lua_upvalueindex(4)); - - if (szProto) - while (i < count && mir_strcmp(szProto, accounts[i]->szProtoName)) - i++; - - if (i < count) - { - lua_pushinteger(L, (i + 1)); - lua_replace(L, lua_upvalueindex(1)); - MT::Apply(L, accounts[i]); - } - else - lua_pushnil(L); - - return 1; -} - -static int lua_Accounts(lua_State *L) -{ - const char *szProto = nullptr; - - switch (lua_type(L, 1)) - { - case LUA_TNONE: - break; - case LUA_TSTRING: - szProto = lua_tostring(L, 1); - break; - case LUA_TUSERDATA: - { - PROTOCOLDESCRIPTOR *pd = *(PROTOCOLDESCRIPTOR**)luaL_checkudata(L, 1, MT_PROTOCOLDESCRIPTOR); - szProto = pd->szName; - break; - } - default: - luaL_argerror(L, 1, luaL_typename(L, 1)); - } - - int count; - PROTOACCOUNT **accounts; - Proto_EnumAccounts(&count, &accounts); - - lua_pushinteger(L, 0); - lua_pushinteger(L, count); - lua_pushlightuserdata(L, accounts); - lua_pushstring(L, szProto); - lua_pushcclosure(L, lua_AccountIterator, 4); - - return 1; -} - -static int lua_CallService(lua_State *L) -{ - const char *szModule = nullptr; - - switch (lua_type(L, 1)) - { - case LUA_TNUMBER: - szModule = GetContactProto(lua_tonumber(L, 1)); - break; - case LUA_TSTRING: - szModule = lua_tostring(L, 1); - break; - case LUA_TUSERDATA: - { - PROTOACCOUNT *pa = *(PROTOACCOUNT**)luaL_checkudata(L, 1, MT_PROTOACCOUNT); - szModule = pa->szModuleName; - break; - } - default: - luaL_argerror(L, 1, luaL_typename(L, 1)); - } - - const char *service = luaL_checkstring(L, 2); - WPARAM wParam = (WPARAM)luaM_tomparam(L, 3); - LPARAM lParam = (LPARAM)luaM_tomparam(L, 4); - - INT_PTR res = CallProtoService(szModule, service, wParam, lParam); - lua_pushinteger(L, res); - - return 1; -} - -/***********************************************/ - -INT_PTR FilterRecvMessage(WPARAM wParam, LPARAM lParam) -{ - int res = NotifyEventHooks(hRecvMessage, wParam, lParam); - if (res) return res; - Proto_ChainRecv(wParam, (CCSDATA*)lParam); - return 0; -} - -/***********************************************/ - -static luaL_Reg protocolsApi[] = -{ - { "GetProtocol", lua_GetProtocol }, - { "Protocols", lua_Protocols }, - - { "CallSendChain", lua_ChainSend }, - { "CallReceiveChain", lua_ChainRecv }, - - { "GetAccount", lua_GetAccount }, - { "Accounts", lua_Accounts }, - - { "CallService", lua_CallService }, - - { nullptr, nullptr } -}; - -/***********************************************/ - -LUAMOD_API int luaopen_m_protocols(lua_State *L) -{ - luaL_newlib(L, protocolsApi); - - MT(L, MT_PROTOCOLDESCRIPTOR) - .Field(&PROTOCOLDESCRIPTOR::szName, "Name", LUA_TSTRINGA) - .Field(&PROTOCOLDESCRIPTOR::type, "Type", LUA_TINTEGER) - .Field(lua_Accounts, "Accounts"); - - MT(L, MT_PROTOACCOUNT) - .Field(&PROTOACCOUNT::szModuleName, "ModuleName", LUA_TSTRINGA) - .Field(&PROTOACCOUNT::tszAccountName, "AccountName", LUA_TSTRINGW) - .Field(&PROTOACCOUNT::szProtoName, "ProtoName", LUA_TSTRINGA) - .Field(&PROTOACCOUNT::bIsEnabled, "IsEnabled", LUA_TBOOLEAN) - .Field(&PROTOACCOUNT::bIsVisible, "IsVisible", LUA_TBOOLEAN) - .Field(&PROTOACCOUNT::bIsVirtual, "IsVirtual", LUA_TBOOLEAN) - .Field(&PROTOACCOUNT::bOldProto, "IsOldProto", LUA_TBOOLEAN) - .Field(lua_CallService, "CallService"); - - MT(L, "ACKDATA") - .Field(&ACKDATA::szModule, "Module", LUA_TSTRINGA) - .Field(&ACKDATA::hContact, "hContact", LUA_TINTEGER) - .Field(&ACKDATA::type, "Type", LUA_TINTEGER) - .Field(&ACKDATA::result, "Result", LUA_TINTEGER) - .Field(&ACKDATA::hProcess, "hProcess", LUA_TLIGHTUSERDATA) - .Field(&ACKDATA::lParam, "lParam", LUA_TLIGHTUSERDATA); - - MT(L, "CCSDATA") - .Field(&CCSDATA::hContact, "hContact", LUA_TINTEGER) - .Field(&CCSDATA::szProtoService, "Service", LUA_TSTRINGA) - .Field(&CCSDATA::wParam, "wParam", LUA_TLIGHTUSERDATA) - .Field(&CCSDATA::lParam, "lParam", LUA_TLIGHTUSERDATA); - - MT(L, "PROTORECVEVENT") - .Field(&PROTORECVEVENT::timestamp, "Timestamp", LUA_TINTEGER) - .Field(&PROTORECVEVENT::flags, "Flags", LUA_TINTEGER) - .Field(&PROTORECVEVENT::szMessage, "Message", LUA_TSTRING); - - return 1; -} diff --git a/plugins/MirLua/src/m_protocols.h b/plugins/MirLua/src/m_protocols.h deleted file mode 100644 index b80d38023b..0000000000 --- a/plugins/MirLua/src/m_protocols.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef _LUA_M_PROTOCOLS_H_ -#define _LUA_M_PROTOCOLS_H_ - -#define MLUA_PROTOCOLS "m_protocols" -LUAMOD_API int (luaopen_m_protocols)(lua_State *L); - -#define MT_PROTOCOLDESCRIPTOR "PROTOCOLDESCRIPTOR" -#define MT_PROTOACCOUNT "PROTOACCOUNT" - -extern HANDLE hRecvMessage; -INT_PTR FilterRecvMessage(WPARAM wParam, LPARAM lParam); - -#endif //_LUA_M_PROTOCOLS_H_ \ No newline at end of file diff --git a/plugins/MirLua/src/m_sounds.cpp b/plugins/MirLua/src/m_sounds.cpp deleted file mode 100644 index 177148320a..0000000000 --- a/plugins/MirLua/src/m_sounds.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "stdafx.h" - -static int lua_AddSound(lua_State *L) -{ - ptrA name(mir_utf8decodeA(luaL_checkstring(L, 1))); - ptrW description(mir_utf8decodeW(luaL_checkstring(L, 2))); - ptrW section(mir_utf8decodeW(luaL_optstring(L, 3, MODULENAME))); - ptrW filePath(mir_utf8decodeW(lua_tostring(L, 4))); - - int res; - CMPluginBase *pPlugin = GetPluginByLangId(CMLuaEnvironment::GetEnvironmentId(L)); - if (pPlugin != nullptr) - res = pPlugin->addSound(name, section, description, filePath); - else - res = 1; - lua_pushboolean(L, res == 0); - - return 1; -} - -static int lua_PlaySound(lua_State *L) -{ - const char *name = luaL_checkstring(L, 1); - - INT_PTR res = Skin_PlaySound(name); - lua_pushboolean(L, res == 0); - - return 1; -} - -static int lua_PlayFile(lua_State *L) -{ - ptrW filePath(mir_utf8decodeW(luaL_checkstring(L, 1))); - - INT_PTR res = Skin_PlaySoundFile(filePath); - lua_pushboolean(L, res == 0); - - return 1; -} - -static luaL_Reg soundApi[] = -{ - { "AddSound", lua_AddSound }, - - { "PlaySound", lua_PlaySound }, - { "PlayFile", lua_PlayFile }, - - { nullptr, nullptr } -}; - -LUAMOD_API int luaopen_m_sounds(lua_State *L) -{ - luaL_newlib(L, soundApi); - - return 1; -} diff --git a/plugins/MirLua/src/m_srmm.cpp b/plugins/MirLua/src/m_srmm.cpp deleted file mode 100644 index 8ec739bd27..0000000000 --- a/plugins/MirLua/src/m_srmm.cpp +++ /dev/null @@ -1,138 +0,0 @@ -#include "stdafx.h" - -#define MT_BBBUTTON "BBButton" - -static void MakeBBButton(lua_State *L, BBButton &bbb) -{ - bbb.dwDefPos = 100; - - lua_getfield(L, -1, "Module"); - bbb.pszModuleName = mir_utf8decodeA(luaL_checkstring(L, -1)); - lua_pop(L, 1); - - lua_getfield(L, -1, "ButtonId"); - bbb.dwButtonID = luaL_checkinteger(L, -1); - lua_pop(L, 1); - - lua_getfield(L, -1, "Flags"); - bbb.bbbFlags = luaL_optinteger(L, -1, BBBF_ISIMBUTTON); - lua_pop(L, 1); - - lua_getfield(L, -1, "Text"); - bbb.pwszText = mir_utf8decodeW(lua_tostring(L, -1)); - lua_pop(L, 1); - - lua_getfield(L, -1, "Tooltip"); - bbb.pwszTooltip = mir_utf8decodeW(lua_tostring(L, -1)); - lua_pop(L, 1); - - lua_getfield(L, -1, "Icon"); - bbb.hIcon = (HANDLE)lua_touserdata(L, -1); - lua_pop(L, 1); -} - -static void CleanBBButton(BBButton &bbb) -{ - mir_free((void*)bbb.pszModuleName); - mir_free((void*)bbb.pwszText); - mir_free((void*)bbb.pwszTooltip); -} - -/***********************************************/ - -static int lua_AddButton(lua_State *L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - - BBButton bbb = {}; - MakeBBButton(L, bbb); - - int hScriptLangpack = CMLuaEnvironment::GetEnvironmentId(L); - HANDLE res = Srmm_AddButton(&bbb, hScriptLangpack); - CleanBBButton(bbb); - - if (!res) - { - lua_pushnil(L); - return 1; - } - - lua_pushvalue(L, 1); - luaL_setmetatable(L, MT_BBBUTTON); - - return 1; -} - -static int lua_ModifyButton(lua_State *L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - - lua_pushvalue(L, 1); - - BBButton bbb = {}; - MakeBBButton(L, bbb); - INT_PTR res = Srmm_ModifyButton(&bbb); - CleanBBButton(bbb); - lua_pushboolean(L, !res); - - return 2; -} - -static int lua_RemoveButton(lua_State *L) -{ - BBButton bbb = {}; - - switch (lua_type(L, 1)) - { - case LUA_TSTRING: - bbb.pszModuleName = mir_utf8decodeA(lua_tostring(L, 1)); - bbb.dwButtonID = luaL_checkinteger(L, 2); - break; - case LUA_TTABLE: - MakeBBButton(L, bbb); - break; - default: - luaL_argerror(L, 1, luaL_typename(L, 1)); - } - - INT_PTR res = Srmm_RemoveButton(&bbb); - CleanBBButton(bbb); - lua_pushboolean(L, !res); - - return 1; -} - -static luaL_Reg srmmApi[] = -{ - { "AddButton", lua_AddButton }, - { "ModifyButton", lua_ModifyButton }, - { "RemoveButton", lua_RemoveButton }, - - { nullptr, nullptr } -}; - -/***********************************************/ - -LUAMOD_API int luaopen_m_srmm(lua_State *L) -{ - luaL_newlib(L, srmmApi); - - luaL_newmetatable(L, MT_BBBUTTON); - lua_pushvalue(L, -1); - lua_setfield(L, -2, "__index"); - lua_pushliteral(L, MT_BBBUTTON); - lua_setfield(L, -2, "__metatable"); - lua_pushcfunction(L, lua_ModifyButton); - lua_setfield(L, -2, "Modify"); - lua_pushcfunction(L, lua_RemoveButton); - lua_setfield(L, -2, "Remove"); - lua_pop(L, 1); - - MT(L, "CustomButtonClickData") - .Field(&CustomButtonClickData::pszModule, "Module", LUA_TSTRINGA) - .Field(&CustomButtonClickData::dwButtonId, "ButtonId", LUA_TINTEGER) - .Field(&CustomButtonClickData::hContact, "hContact", LUA_TINTEGER) - .Field(&CustomButtonClickData::flags, "Flags", LUA_TINTEGER); - - return 1; -} diff --git a/plugins/MirLua/src/metatable.h b/plugins/MirLua/src/metatable.h new file mode 100644 index 0000000000..aa736428ca --- /dev/null +++ b/plugins/MirLua/src/metatable.h @@ -0,0 +1,344 @@ +#pragma once + +#include +#include +#include + +#define LUA_TINTEGER LUA_NUMTAGS + 1 +#define LUA_TSTRINGA LUA_NUMTAGS + 2 +#define LUA_TSTRINGW LUA_NUMTAGS + 3 + +union MTValue +{ + void *userdata; + int boolean; + lua_Integer integer; + lua_Number number; + const char *string; + const char *stringA; + const wchar_t *stringW; + lua_CFunction function; +}; + +class CMTField +{ + ptrA name; + int type; + +public: + CMTField(const char *name, int type) : + name(mir_strdup(name)), type(type) {} + + const char* GetName() const { return name; } + int GetType() const { return type; } + + static int Compare(const CMTField *p1, const CMTField *p2) { + return mir_strcmp(p1->name, p2->name); + } + + virtual MTValue GetValue(void *obj) = 0; +}; + +template +class CMTFieldOffset : public CMTField +{ + ptrdiff_t offset; + size_t size; + +public: + CMTFieldOffset(const char *name, int type, ptrdiff_t offset, size_t size) + : CMTField(name, type), offset(offset), size(size) {} + + virtual MTValue GetValue(void *obj) + { + MTValue value = {}; + memcpy(&value, ((char*)obj + offset), sizeof(R)); + return value; + } +}; + +class CMTFieldFunction : public CMTField +{ + lua_CFunction function; +public: + + CMTFieldFunction(const char *name, lua_CFunction function) : + CMTField(name, LUA_TFUNCTION), function(function) {} + + virtual MTValue GetValue(void*) + { + MTValue value = {}; + value.function = function; + return value; + } +}; + +template +class CMTFieldLambda : public CMTField +{ + int type; + std::function lambda; +public: + + CMTFieldLambda(const char *name, int type, decltype(lambda) lambda) + : CMTField(name, type), lambda(lambda), type(type) {} + + virtual MTValue GetValue(void *obj) { + return lambda((Obj*)obj); + } +}; + +template +class MT +{ +private: + lua_State *L; + + static const char *Name; + static const luaL_Reg Events[]; + static OBJLIST Fields; + + static T* Init(lua_State *L) + { + luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); + return (T*)lua_touserdata(L, 1); + } + + static int Get(lua_State *L, T* /*obj*/) + { + lua_pushnil(L); + return 1; + } + + static bool Set(lua_State* /*L*/, T* /*obj*/) + { + return false; + } + + static void Free(lua_State* /*L*/, T **obj) + { + *obj = nullptr; + } + + static int lua__new(lua_State *L) + { + T **udata = (T**)lua_newuserdata(L, sizeof(T*)); + + *udata = Init(L); + if (*udata == nullptr) { + lua_pushnil(L); + return 1; + } + + luaL_setmetatable(L, Name); + + return 1; + } + + static int lua__gc(lua_State *L) + { + T **obj = (T**)luaL_checkudata(L, 1, Name); + Free(L, obj); + + return 0; + } + + static int lua__bnot(lua_State *L) + { + T *obj = *(T**)luaL_checkudata(L, 1, Name); + lua_pushlightuserdata(L, obj); + + return 1; + } + + static int lua__index(lua_State *L) + { + T *obj = *(T**)luaL_checkudata(L, 1, Name); + const char *key = lua_tostring(L, 2); + + const void *tmp[2] = { nullptr, key }; + CMTField *field = Fields.find((CMTField*)&tmp); + if (field == nullptr) + return Get(L, obj); + + MTValue value = field->GetValue(obj); + int type = field->GetType(); + switch (type) { + case LUA_TBOOLEAN: + lua_pushboolean(L, value.boolean); + break; + case LUA_TINTEGER: + lua_pushinteger(L, value.integer); + break; + case LUA_TNUMBER: + lua_pushnumber(L, value.number); + break; + case LUA_TSTRING: + lua_pushstring(L, value.string); + break; + case LUA_TSTRINGA: + lua_pushstring(L, ptrA(mir_utf8encode(value.stringA))); + break; + case LUA_TSTRINGW: + lua_pushstring(L, T2Utf(value.stringW)); + break; + case LUA_TLIGHTUSERDATA: + lua_pushlightuserdata(L, value.userdata); + break; + case LUA_TFUNCTION: + lua_pushcfunction(L, value.function); + break; + default: + lua_pushnil(L); + } + + return 1; + } + + static int lua__newindex(lua_State *L) + { + T *obj = *(T**)luaL_checkudata(L, 1, Name); + + if (!Set(L, obj)) { + const char *key = lua_tostring(L, 2); + luaL_error(L, "attempt to index a %s value (%s is readonly)", Name, key); + } + + return 0; + } + + static int lua__tostring(lua_State *L) + { + T *obj = *(T**)luaL_checkudata(L, 1, Name); + CMStringA data(Name); + data += "("; + + for (auto &it : Fields) { + data += it->GetName(); + data += "="; + + MTValue value = it->GetValue(obj); + int type = it->GetType(); + switch (type) { + case LUA_TNIL: + data.Append("nil"); + break; + case LUA_TBOOLEAN: + data.Append(value.boolean == 0 ? "false" : "true"); + break; + case LUA_TINTEGER: + data.AppendFormat("%d", value.integer); + break; + case LUA_TNUMBER: + data.AppendFormat("%f", value.number); + break; + case LUA_TSTRING: + data.Append(value.string); + break; + case LUA_TSTRINGA: + data.Append(ptrA(mir_utf8encode(value.stringA))); + break; + case LUA_TSTRINGW: + data.Append(T2Utf(value.stringW)); + break; + default: + data.AppendFormat("%s(0x%p)", lua_typename(L, type), value.userdata); + break; + } + data += ", "; + } + data += ")"; + lua_pushstring(L, data.c_str()); + return 1; + } + + static int lua__call(lua_State *L) + { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + + int nres = lua_gettop(L) - 1; + + lua_getfield(L, 1, "new"); + for (int i = 1; i <= nres; i++) + lua_pushvalue(L, i + 1); + luaM_pcall(L, nres, 1); + + return 1; + } + +public: + MT(lua_State *L, const char *name) + : L(L) + { + Name = name; + + luaL_newmetatable(L, Name); + luaL_setfuncs(L, Events, 0); + lua_pop(L, 1); + + lua_createtable(L, 0, 1); + lua_pushcfunction(L, lua__new); + lua_setfield(L, -2, "new"); + + lua_createtable(L, 0, 2); + lua_pushcfunction(L, lua__call); + lua_setfield(L, -2, "__call"); + lua_setmetatable(L, -2); + lua_setglobal(L, Name); + } + + template + MT& Field(R T:: *M, const char *name, int type, size_t size = 0) + { + if (size == 0) + size = sizeof(M); + size_t offset = (size_t)(&(((T*)0)->*M)); + if (type != LUA_TNONE) + Fields.insert(new CMTFieldOffset(name, type, offset, size)); + return *this; + } + + template + MT& Field(const L &lambda, const char *name, int type) + { + if (type != LUA_TNONE) + Fields.insert(new CMTFieldLambda(name, type, lambda)); + return *this; + } + + MT& Field(const lua_CFunction function, const char *name) + { + Fields.insert(new CMTFieldFunction(name, function)); + return *this; + } + + static void Apply(lua_State *L, T *obj) + { + if (obj == nullptr) { + lua_pushnil(L); + return; + } + + T **udata = (T**)lua_newuserdata(L, sizeof(T)); + *udata = obj; + luaL_setmetatable(L, Name); + } +}; + +template +const char *MT::Name; + +template +const luaL_Reg MT::Events[] = { + { "__index", lua__index }, + { "__newindex", lua__newindex }, + { "__bnot", lua__bnot }, + { "__tostring", lua__tostring }, + { "__gc", lua__gc }, + + { NULL, NULL }, +}; + +template +OBJLIST MT::Fields(5, &CMTField::Compare); diff --git a/plugins/MirLua/src/mlua_environment.cpp b/plugins/MirLua/src/mlua_environment.cpp deleted file mode 100644 index 4a82e63231..0000000000 --- a/plugins/MirLua/src/mlua_environment.cpp +++ /dev/null @@ -1,101 +0,0 @@ -#include "stdafx.h" - -#define MT_ENVIRONMENT "ENVIRONMENT" - -CMLuaEnvironment::CMLuaEnvironment(lua_State *L) - : L(L) -{ - MUUID muidLast = MIID_LAST; - m_id = GetPluginLangId(muidLast, 0); -} - -CMLuaEnvironment::~CMLuaEnvironment() -{ - KillModuleIcons(m_id); - KillModuleSounds(m_id); - KillModuleMenus(m_id); - KillModuleHotkeys(m_id); - - KillObjectEventHooks(this); - KillObjectServices(this); - - for (auto &it : m_hookRefs) - luaL_unref(L, LUA_REGISTRYINDEX, it.second); - - for (auto &it : m_serviceRefs) - luaL_unref(L, LUA_REGISTRYINDEX, it.second); -} - -CMLuaEnvironment* CMLuaEnvironment::GetEnvironment(lua_State *L) -{ - if (!luaM_getenv(L)) - return nullptr; - - lua_rawgeti(L, -1, NULL); - CMLuaEnvironment *env = (CMLuaEnvironment*)lua_touserdata(L, -1); - lua_pop(L, 3); - - return env; -} - -int CMLuaEnvironment::GetEnvironmentId(lua_State *L) -{ - CMLuaEnvironment *script = GetEnvironment(L); - return script != nullptr - ? script->GetId() - : hMLuaLangpack; -} - -int CMLuaEnvironment::GetId() const -{ - return m_id; -} - -void CMLuaEnvironment::AddHookRef(HANDLE h, int ref) -{ - m_hookRefs[h] = ref; -} - -void CMLuaEnvironment::ReleaseHookRef(HANDLE h) -{ - auto it = m_hookRefs.find(h); - if (it != m_hookRefs.end()) - luaL_unref(L, LUA_REGISTRYINDEX, it->second); -} - -void CMLuaEnvironment::AddServiceRef(HANDLE h, int ref) -{ - m_serviceRefs[h] = ref; -} - -void CMLuaEnvironment::ReleaseServiceRef(HANDLE h) -{ - auto it = m_serviceRefs.find(h); - if (it != m_serviceRefs.end()) - luaL_unref(L, LUA_REGISTRYINDEX, it->second); -} - -void CMLuaEnvironment::CreateEnvironmentTable() -{ - lua_createtable(L, 1, 1); - lua_pushlightuserdata(L, this); - lua_rawseti(L, -2, NULL); - lua_pushvalue(L, -1); - lua_setfield(L, -2, "_G"); - lua_createtable(L, 0, 2); - lua_pushliteral(L, MT_ENVIRONMENT); - lua_setfield(L, -2, "__metatable"); - lua_getglobal(L, "_G"); - lua_setfield(L, -2, "__index"); - lua_setmetatable(L, -2); -} - -bool CMLuaEnvironment::Load() -{ - luaL_checktype(L, -1, LUA_TFUNCTION); - - CreateEnvironmentTable(); - lua_setupvalue(L, -2, 1); - - return lua_pcall(L, 0, 1, 0) == LUA_OK; -} diff --git a/plugins/MirLua/src/mlua_environment.h b/plugins/MirLua/src/mlua_environment.h deleted file mode 100644 index aa6ebb103a..0000000000 --- a/plugins/MirLua/src/mlua_environment.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef _LUA_ENVIRONMENT_H_ -#define _LUA_ENVIRONMENT_H_ - -class CMLuaEnvironment -{ -private: - int m_id; - std::map m_hookRefs; - std::map m_serviceRefs; - - void CreateEnvironmentTable(); - -public: - lua_State *L; - - CMLuaEnvironment(lua_State *L); - virtual ~CMLuaEnvironment(); - - static CMLuaEnvironment* GetEnvironment(lua_State *L); - static int GetEnvironmentId(lua_State *L); - - int GetId() const; - - void AddHookRef(HANDLE h, int ref); - void ReleaseHookRef(HANDLE h); - - void AddServiceRef(HANDLE h, int ref); - void ReleaseServiceRef(HANDLE h); - - bool Load(); -}; - -#endif //_LUA_ENVIRONMENT_H_ diff --git a/plugins/MirLua/src/mlua_function_loader.cpp b/plugins/MirLua/src/mlua_function_loader.cpp deleted file mode 100644 index 6e82086d29..0000000000 --- a/plugins/MirLua/src/mlua_function_loader.cpp +++ /dev/null @@ -1,194 +0,0 @@ -#include "stdafx.h" - -CMLuaFunctionLoader::CMLuaFunctionLoader(lua_State *L) : L(L) -{ -} - -/***********************************************/ - -static int mlua_print(lua_State *L) -{ - CMStringA data; - int nargs = lua_gettop(L); - for (int i = 1; i <= nargs; i++) { - switch (lua_type(L, i)) { - case LUA_TNIL: - data.Append("nil"); - break; - case LUA_TBOOLEAN: - data.AppendFormat("%s", lua_toboolean(L, i) ? "true" : "false"); - break; - case LUA_TNUMBER: - data.AppendFormat("%s", lua_tostring(L, i)); - break; - case LUA_TSTRING: - data.AppendFormat("'%s'", lua_tostring(L, i)); - break; - default: - if (luaL_callmeta(L, i, "__tostring")) { - data.AppendFormat("'%s'", lua_tostring(L, -1)); - break; - } - data.AppendFormat("%s(0x%p)", luaL_typename(L, i), lua_topointer(L, i)); - break; - } - data.Append(", "); - } - if (data.GetLength() >= 1) - data.Delete(data.GetLength() - 2, 2); - - Log(data.GetBuffer()); - - return 0; -} - -static int mlua_toansi(lua_State *L) -{ - const char *value = luaL_checkstring(L, 1); - int codepage = luaL_optinteger(L, 2, Langpack_GetDefaultCodePage()); - - ptrA string(mir_strdup(value)); - lua_pushstring(L, mir_utf8decodecp(string, codepage, nullptr)); - - return 1; -} - -static int mlua_toucs2(lua_State *L) -{ - const char *value = luaL_checkstring(L, 1); - - ptrW unicode(mir_utf8decodeW(value)); - size_t length = mir_wstrlen(unicode) * sizeof(wchar_t); - - ptrA string((char*)mir_calloc(length + 1)); - memcpy(string, unicode, length); - - lua_pushlstring(L, string, length + 1); - - return 1; -} - -static int mlua_topointer(lua_State *L) -{ - switch (lua_type(L, 1)) { - case LUA_TBOOLEAN: - lua_pushlightuserdata(L, (void*)lua_toboolean(L, 1)); - break; - case LUA_TNUMBER: - if (lua_isinteger(L, 1)) { - lua_Integer value = lua_tointeger(L, 1); - if (value > INTPTR_MAX) { - const char *msg = lua_pushfstring(L, "%f is larger than %d", value, INTPTR_MAX); - return luaL_argerror(L, 1, msg); - } - lua_pushlightuserdata(L, (void*)value); - } - break; - case LUA_TSTRING: - lua_pushlightuserdata(L, (void*)lua_tostring(L, 1)); - break; - case LUA_TLIGHTUSERDATA: - lua_pushvalue(L, 1); - default: - return luaL_argerror(L, 1, luaL_typename(L, 1)); - } - - return 1; -} - -static int mlua_tonumber(lua_State *L) -{ - if (lua_islightuserdata(L, 1)) { - lua_Integer value = (lua_Integer)lua_touserdata(L, 1); - lua_pushinteger(L, value); - return 1; - } - - int n = lua_gettop(L); - lua_pushvalue(L, lua_upvalueindex(1)); - lua_pushvalue(L, 1); - if (n == 2) - lua_pushvalue(L, 2); - luaM_pcall(L, n, 1); - - return 1; -} - -static int mlua_interpolate(lua_State *L) -{ - const char *string = luaL_checkstring(L, 1); - - char pattern[128]; - - if (lua_istable(L, 2)) { - for (lua_pushnil(L); lua_next(L, 2); lua_pop(L, 3)) { - lua_pushvalue(L, -2); - const char *key = lua_tostring(L, -1); - const char *val = lua_tostring(L, -2); - - mir_snprintf(pattern, "{%s}", key); - string = luaL_gsub(L, string, pattern, val ? val : ""); - } - } - else { - int nargs = lua_gettop(L); - for (int i = 2; i <= nargs; i++) { - const char *val = lua_tostring(L, i); - - mir_snprintf(pattern, "{%d}", i - 1); - string = luaL_gsub(L, string, pattern, val ? val : ""); - lua_pop(L, 1); - } - } - - lua_Debug ar; - int level = 1; - while (lua_getstack(L, level++, &ar)) { - int i = 1; - while (const char *name = lua_getlocal(L, &ar, i++)) { - const char *val = lua_tostring(L, -1); - mir_snprintf(pattern, "{%s}", name); - string = luaL_gsub(L, string, pattern, val ? val : ""); - lua_pop(L, 1); - } - } - - lua_pushstring(L, string); - - return 1; -} - -/***********************************************/ - -void CMLuaFunctionLoader::LoadFunctions() -{ - Log("Loading additional functions"); - - lua_register(L, "print", mlua_print); - lua_register(L, "a", mlua_toansi); - lua_register(L, "toansi", mlua_toansi); - lua_register(L, "u", mlua_toucs2); - lua_register(L, "toucs2", mlua_toucs2); - lua_register(L, "topointer", mlua_topointer); - - lua_getglobal(L, "tonumber"); - lua_pushcclosure(L, mlua_tonumber, 1); - lua_setglobal(L, "tonumber"); - - lua_pushstring(L, ""); - lua_getmetatable(L, -1); - lua_pushstring(L, "__mod"); - lua_pushcfunction(L, mlua_interpolate); - lua_rawset(L, -3); - lua_pushstring(L, "__index"); - lua_rawget(L, -2); - lua_pushcfunction(L, mlua_interpolate); - lua_setfield(L, -2, "interpolate"); - lua_pop(L, 3); -} - -void CMLuaFunctionLoader::Load(lua_State *L) -{ - CMLuaFunctionLoader loader(L); - loader.LoadFunctions(); -} \ No newline at end of file diff --git a/plugins/MirLua/src/mlua_function_loader.h b/plugins/MirLua/src/mlua_function_loader.h deleted file mode 100644 index 9724ccdc3d..0000000000 --- a/plugins/MirLua/src/mlua_function_loader.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -class CMLuaFunctionLoader -{ -private: - lua_State *L; - - CMLuaFunctionLoader(lua_State *L); - - void LoadFunctions(); - -public: - static void Load(lua_State *L); -}; diff --git a/plugins/MirLua/src/mlua_icons.cpp b/plugins/MirLua/src/mlua_icons.cpp deleted file mode 100644 index 3b2466bc27..0000000000 --- a/plugins/MirLua/src/mlua_icons.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "stdafx.h" - -IconItem Icons[] = -{ - { LPGEN("Script"), "script", IDI_SCRIPT }, - { LPGEN("Loaded"), "loaded", IDI_LOADED }, - { LPGEN("Failed"), "failed", IDI_FAILED }, - { LPGEN("Open"), "open", IDI_OPEN }, - { LPGEN("Reload"), "reload", IDI_RELOAD }, -}; - -void InitIcons() -{ - g_plugin.registerIcon(MODULENAME, Icons, MODULENAME); -} - -HICON GetIcon(int iconId) -{ - for (auto &it : Icons) - if (it.defIconID == iconId) - return IcoLib_GetIconByHandle(it.hIcolib); - - return nullptr; -} - -HANDLE GetIconHandle(int iconId) -{ - for (auto &it : Icons) - if (it.defIconID == iconId) - return it.hIcolib; - - return nullptr; -} \ No newline at end of file diff --git a/plugins/MirLua/src/mlua_metatable.h b/plugins/MirLua/src/mlua_metatable.h deleted file mode 100644 index 33d3b40e7e..0000000000 --- a/plugins/MirLua/src/mlua_metatable.h +++ /dev/null @@ -1,347 +0,0 @@ -#ifndef _LUA_METATABLE_H_ -#define _LUA_METATABLE_H_ - -#include -#include -#include - -#define LUA_TINTEGER LUA_NUMTAGS + 1 -#define LUA_TSTRINGA LUA_NUMTAGS + 2 -#define LUA_TSTRINGW LUA_NUMTAGS + 3 - -union MTValue -{ - void *userdata; - int boolean; - lua_Integer integer; - lua_Number number; - const char *string; - const char *stringA; - const wchar_t *stringW; - lua_CFunction function; -}; - -class CMTField -{ - ptrA name; - int type; - -public: - CMTField(const char *name, int type) : - name(mir_strdup(name)), type(type) {} - - const char* GetName() const { return name; } - int GetType() const { return type; } - - static int Compare(const CMTField *p1, const CMTField *p2) { - return mir_strcmp(p1->name, p2->name); - } - - virtual MTValue GetValue(void *obj) = 0; -}; - -template -class CMTFieldOffset : public CMTField -{ - ptrdiff_t offset; - size_t size; - -public: - CMTFieldOffset(const char *name, int type, ptrdiff_t offset, size_t size) - : CMTField(name, type), offset(offset), size(size) {} - - virtual MTValue GetValue(void *obj) - { - MTValue value = {}; - memcpy(&value, ((char*)obj + offset), sizeof(R)); - return value; - } -}; - -class CMTFieldFunction : public CMTField -{ - lua_CFunction function; -public: - - CMTFieldFunction(const char *name, lua_CFunction function) : - CMTField(name, LUA_TFUNCTION), function(function) {} - - virtual MTValue GetValue(void*) - { - MTValue value = {}; - value.function = function; - return value; - } -}; - -template -class CMTFieldLambda : public CMTField -{ - int type; - std::function lambda; -public: - - CMTFieldLambda(const char *name, int type, decltype(lambda) lambda) - : CMTField(name, type), lambda(lambda), type(type) {} - - virtual MTValue GetValue(void *obj) { - return lambda((Obj*)obj); - } -}; - -template -class MT -{ -private: - lua_State *L; - - static const char *Name; - static const luaL_Reg Events[]; - static OBJLIST Fields; - - static T* Init(lua_State *L) - { - luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); - return (T*)lua_touserdata(L, 1); - } - - static int Get(lua_State *L, T* /*obj*/) - { - lua_pushnil(L); - return 1; - } - - static bool Set(lua_State* /*L*/, T* /*obj*/) - { - return false; - } - - static void Free(lua_State* /*L*/, T **obj) - { - *obj = nullptr; - } - - static int lua__new(lua_State *L) - { - T **udata = (T**)lua_newuserdata(L, sizeof(T*)); - - *udata = Init(L); - if (*udata == nullptr) { - lua_pushnil(L); - return 1; - } - - luaL_setmetatable(L, Name); - - return 1; - } - - static int lua__gc(lua_State *L) - { - T **obj = (T**)luaL_checkudata(L, 1, Name); - Free(L, obj); - - return 0; - } - - static int lua__bnot(lua_State *L) - { - T *obj = *(T**)luaL_checkudata(L, 1, Name); - lua_pushlightuserdata(L, obj); - - return 1; - } - - static int lua__index(lua_State *L) - { - T *obj = *(T**)luaL_checkudata(L, 1, Name); - const char *key = lua_tostring(L, 2); - - const void *tmp[2] = { nullptr, key }; - CMTField *field = Fields.find((CMTField*)&tmp); - if (field == nullptr) - return Get(L, obj); - - MTValue value = field->GetValue(obj); - int type = field->GetType(); - switch (type) { - case LUA_TBOOLEAN: - lua_pushboolean(L, value.boolean); - break; - case LUA_TINTEGER: - lua_pushinteger(L, value.integer); - break; - case LUA_TNUMBER: - lua_pushnumber(L, value.number); - break; - case LUA_TSTRING: - lua_pushstring(L, value.string); - break; - case LUA_TSTRINGA: - lua_pushstring(L, ptrA(mir_utf8encode(value.stringA))); - break; - case LUA_TSTRINGW: - lua_pushstring(L, T2Utf(value.stringW)); - break; - case LUA_TLIGHTUSERDATA: - lua_pushlightuserdata(L, value.userdata); - break; - case LUA_TFUNCTION: - lua_pushcfunction(L, value.function); - break; - default: - lua_pushnil(L); - } - - return 1; - } - - static int lua__newindex(lua_State *L) - { - T *obj = *(T**)luaL_checkudata(L, 1, Name); - - if (!Set(L, obj)) { - const char *key = lua_tostring(L, 2); - luaL_error(L, "attempt to index a %s value (%s is readonly)", Name, key); - } - - return 0; - } - - static int lua__tostring(lua_State *L) - { - T *obj = *(T**)luaL_checkudata(L, 1, Name); - CMStringA data(Name); - data += "("; - - for (auto &it : Fields) { - data += it->GetName(); - data += "="; - - MTValue value = it->GetValue(obj); - int type = it->GetType(); - switch (type) { - case LUA_TNIL: - data.Append("nil"); - break; - case LUA_TBOOLEAN: - data.Append(value.boolean == 0 ? "false" : "true"); - break; - case LUA_TINTEGER: - data.AppendFormat("%d", value.integer); - break; - case LUA_TNUMBER: - data.AppendFormat("%f", value.number); - break; - case LUA_TSTRING: - data.Append(value.string); - break; - case LUA_TSTRINGA: - data.Append(ptrA(mir_utf8encode(value.stringA))); - break; - case LUA_TSTRINGW: - data.Append(T2Utf(value.stringW)); - break; - default: - data.AppendFormat("%s(0x%p)", lua_typename(L, type), value.userdata); - break; - } - data += ", "; - } - data += ")"; - lua_pushstring(L, data.c_str()); - return 1; - } - - static int lua__call(lua_State *L) - { - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checkany(L, 2); - - int nres = lua_gettop(L) - 1; - - lua_getfield(L, 1, "new"); - for (int i = 1; i <= nres; i++) - lua_pushvalue(L, i + 1); - luaM_pcall(L, nres, 1); - - return 1; - } - -public: - MT(lua_State *L, const char *name) - : L(L) - { - Name = name; - - luaL_newmetatable(L, Name); - luaL_setfuncs(L, Events, 0); - lua_pop(L, 1); - - lua_createtable(L, 0, 1); - lua_pushcfunction(L, lua__new); - lua_setfield(L, -2, "new"); - - lua_createtable(L, 0, 2); - lua_pushcfunction(L, lua__call); - lua_setfield(L, -2, "__call"); - lua_setmetatable(L, -2); - lua_setglobal(L, Name); - } - - template - MT& Field(R T:: *M, const char *name, int type, size_t size = 0) - { - if (size == 0) - size = sizeof(M); - size_t offset = (size_t)(&(((T*)0)->*M)); - if (type != LUA_TNONE) - Fields.insert(new CMTFieldOffset(name, type, offset, size)); - return *this; - } - - template - MT& Field(const L &lambda, const char *name, int type) - { - if (type != LUA_TNONE) - Fields.insert(new CMTFieldLambda(name, type, lambda)); - return *this; - } - - MT& Field(const lua_CFunction function, const char *name) - { - Fields.insert(new CMTFieldFunction(name, function)); - return *this; - } - - static void Apply(lua_State *L, T *obj) - { - if (obj == nullptr) { - lua_pushnil(L); - return; - } - - T **udata = (T**)lua_newuserdata(L, sizeof(T)); - *udata = obj; - luaL_setmetatable(L, Name); - } -}; - -template -const char *MT::Name; - -template -const luaL_Reg MT::Events[] = { - { "__index", lua__index }, - { "__newindex", lua__newindex }, - { "__bnot", lua__bnot }, - { "__tostring", lua__tostring }, - { "__gc", lua__gc }, - - { NULL, NULL }, -}; - -template -OBJLIST MT::Fields(5, &CMTField::Compare); - -#endif //_LUA_METATABLE_H_ diff --git a/plugins/MirLua/src/mlua_module_loader.cpp b/plugins/MirLua/src/mlua_module_loader.cpp deleted file mode 100644 index ff9594f363..0000000000 --- a/plugins/MirLua/src/mlua_module_loader.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "stdafx.h" - -CMLuaModuleLoader::CMLuaModuleLoader(lua_State *L) : L(L) -{ -} - -void CMLuaModuleLoader::Load(const char *name, lua_CFunction loader) -{ - luaL_requiref(L, name, loader, 0); -} - -void CMLuaModuleLoader::Preload(const char *name, lua_CFunction loader) -{ - luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); - lua_pushcfunction(L, loader); - lua_setfield(L, -2, name); - lua_pop(L, 1); -} - -void CMLuaModuleLoader::LoadModules() -{ - Log("Loading miranda modules"); - - // load m_core module - Load(MLUA_CORE, luaopen_m_core); - // load all internal modules - Preload(MLUA_CHAT, luaopen_m_chat); - Preload(MLUA_CLIST, luaopen_m_clist); - Preload(MLUA_DATABASE, luaopen_m_database); - Preload(MLUA_GENMENU, luaopen_m_genmenu); - Preload(MLUA_HOTKEYS, luaopen_m_hotkeys); - Preload(MLUA_HTTP, luaopen_m_http); - Preload(MLUA_ICOLIB, luaopen_m_icolib); - Preload(MLUA_JSON, luaopen_m_json); - Preload(MLUA_MESSAGE, luaopen_m_message); - Preload(MLUA_OPTIONS, luaopen_m_options); - Preload(MLUA_PROTOCOLS, luaopen_m_protocols); - Preload(MLUA_SOUNDS, luaopen_m_sounds); - Preload(MLUA_SRMM, luaopen_m_srmm); -} - -void CMLuaModuleLoader::Load(lua_State *L) -{ - CMLuaModuleLoader loader(L); - loader.LoadModules(); -} \ No newline at end of file diff --git a/plugins/MirLua/src/mlua_module_loader.h b/plugins/MirLua/src/mlua_module_loader.h deleted file mode 100644 index bab8e79e84..0000000000 --- a/plugins/MirLua/src/mlua_module_loader.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -class CMLuaModuleLoader -{ -private: - lua_State *L; - - CMLuaModuleLoader(lua_State *L); - - void Load(const char *name, lua_CFunction loader); - void Preload(const char *name, lua_CFunction loader); - - void LoadModules(); - -public: - static void Load(lua_State *L); -}; diff --git a/plugins/MirLua/src/mlua_options.cpp b/plugins/MirLua/src/mlua_options.cpp deleted file mode 100644 index 226a925fd9..0000000000 --- a/plugins/MirLua/src/mlua_options.cpp +++ /dev/null @@ -1,130 +0,0 @@ -#include "stdafx.h" - -CMLuaOptions::CMLuaOptions(CMLua *mLua) - : CPluginDlgBase(g_plugin, IDD_OPTIONS, MODULENAME), - m_mLua(mLua), isScriptListInit(false), - m_popupOnError(this, IDC_POPUPONERROR), - m_popupOnObsolete(this, IDC_POPUPONOBSOLETE), - m_scripts(this, IDC_SCRIPTS), m_reload(this, IDC_RELOAD) -{ - CreateLink(m_popupOnError, "PopupOnError", DBVT_BYTE, 1); - CreateLink(m_popupOnObsolete, "PopupOnObsolete", DBVT_BYTE, 1); - - m_scripts.OnClick = Callback(this, &CMLuaOptions::OnScriptListClick); - m_reload.OnClick = Callback(this, &CMLuaOptions::OnReload); -} - -void CMLuaOptions::LoadScripts() -{ - for (auto &script : m_mLua->Scripts) { - wchar_t *fileName = NEWWSTR_ALLOCA(script->GetFileName()); - int iIcon = script->GetStatus() - 1; - int iItem = m_scripts.AddItem(fileName, iIcon, (LPARAM)script); - m_scripts.SetCheckState(iItem, script->IsEnabled()); - m_scripts.SetItem(iItem, 1, TranslateT("Open"), 2); - m_scripts.SetItem(iItem, 2, TranslateT("Reload"), 3); - } -} - -void CMLuaOptions::OnInitDialog() -{ - CDlgBase::OnInitDialog(); - - m_scripts.SetExtendedListViewStyle(LVS_EX_SUBITEMIMAGES | LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES | LVS_EX_INFOTIP); - - HIMAGELIST hImageList = m_scripts.CreateImageList(LVSIL_SMALL); - ImageList_AddIcon(hImageList, GetIcon(IDI_LOADED)); - ImageList_AddIcon(hImageList, GetIcon(IDI_FAILED)); - ImageList_AddIcon(hImageList, GetIcon(IDI_OPEN)); - ImageList_AddIcon(hImageList, GetIcon(IDI_RELOAD)); - - wchar_t scriptDir[MAX_PATH]; - FoldersGetCustomPathT(g_hScriptsFolder, scriptDir, _countof(scriptDir), VARSW(MIRLUA_PATHT)); - - wchar_t relativeScriptDir[MAX_PATH]; - PathToRelativeW(scriptDir, relativeScriptDir, nullptr); - - wchar_t header[MAX_PATH + 100]; - mir_snwprintf(header, L"%s (%s)", TranslateT("Common scripts"), relativeScriptDir); - - m_scripts.AddColumn(0, L"Script", 380); - m_scripts.AddColumn(1, nullptr, 32 - GetSystemMetrics(SM_CXVSCROLL)); - m_scripts.AddColumn(2, nullptr, 32 - GetSystemMetrics(SM_CXVSCROLL)); - - LoadScripts(); - - isScriptListInit = true; -} - -void CMLuaOptions::OnApply() -{ - int count = m_scripts.GetItemCount(); - for (int iItem = 0; iItem < count; iItem++) { - CMLuaScript *script = (CMLuaScript*)m_scripts.GetItemData(iItem); - if (!m_scripts.GetCheckState(iItem)) - script->Disable(); - else - script->Enable(); - } -} - -INT_PTR CMLuaOptions::DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) { - case WM_NOTIFY: - { - LPNMHDR lpnmHdr = (LPNMHDR)lParam; - if (lpnmHdr->idFrom == (UINT_PTR)m_scripts.GetCtrlId() && lpnmHdr->code == LVN_ITEMCHANGED) { - LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam; - if (pnmv->uChanged & LVIF_STATE && pnmv->uNewState & LVIS_STATEIMAGEMASK) { - if (isScriptListInit) - NotifyChange(); - } - } - } - break; - } - return CDlgBase::DlgProc(msg, wParam, lParam); -} - -void CMLuaOptions::OnScriptListClick(CCtrlListView::TEventInfo *evt) -{ - LVITEM lvi = {}; - lvi.iItem = evt->nmlvia->iItem; - if (lvi.iItem == -1) - return; - - lvi.pszText = (LPTSTR)mir_calloc(MAX_PATH * sizeof(wchar_t)); - lvi.cchTextMax = MAX_PATH; - lvi.mask = LVIF_GROUPID | LVIF_TEXT | LVIF_PARAM; - m_scripts.GetItem(&lvi); - lvi.iSubItem = evt->nmlvia->iSubItem; - - CMLuaScript *script = (CMLuaScript*)lvi.lParam; - - switch (lvi.iSubItem) { - case 1: - ShellExecute(m_hwnd, L"open", script->GetFilePath(), nullptr, nullptr, SW_SHOWNORMAL); - break; - - case 2: - script->Reload(); - lvi.mask = LVIF_IMAGE; - lvi.iSubItem = 0; - lvi.iImage = script->GetStatus() - 1; - m_scripts.SetItem(&lvi); - m_scripts.Update(lvi.iItem); - break; - } - - mir_free(lvi.pszText); -} - -void CMLuaOptions::OnReload(CCtrlBase*) -{ - isScriptListInit = false; - m_scripts.DeleteAllItems(); - m_mLua->Reload(); - LoadScripts(); - isScriptListInit = true; -} diff --git a/plugins/MirLua/src/mlua_options.h b/plugins/MirLua/src/mlua_options.h deleted file mode 100644 index 2e3b4ff7f7..0000000000 --- a/plugins/MirLua/src/mlua_options.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef _LUA_OPTIONS_H_ -#define _LUA_OPTIONS_H_ - -class CMLuaOptions : public CPluginDlgBase -{ -private: - CMLua *m_mLua; - bool isScriptListInit; - - CCtrlCheck m_popupOnError; - CCtrlCheck m_popupOnObsolete; - - CCtrlListView m_scripts; - CCtrlButton m_reload; - - void LoadScripts(); - -protected: - void OnInitDialog(); - void OnApply(); - - void OnScriptListClick(CCtrlListView::TEventInfo *evt); - void OnReload(CCtrlBase*); - - INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam); - -public: - CMLuaOptions(CMLua *mLua); -}; - -#endif //_LUA_OPTIONS_H_ \ No newline at end of file diff --git a/plugins/MirLua/src/mlua_script.cpp b/plugins/MirLua/src/mlua_script.cpp deleted file mode 100644 index 9e4cc4ffbe..0000000000 --- a/plugins/MirLua/src/mlua_script.cpp +++ /dev/null @@ -1,137 +0,0 @@ -#include "stdafx.h" - -#define MT_SCRIPT "SCRIPT" - -CMLuaScript::CMLuaScript(lua_State *L, const wchar_t *path) - : CMLuaEnvironment(L), status(None), unloadRef(LUA_NOREF) -{ - mir_wstrcpy(filePath, path); - - fileName = wcsrchr(filePath, '\\') + 1; - wchar_t *dot = wcsrchr(fileName, '.'); - - size_t length = mir_wstrlen(fileName) - mir_wstrlen(dot) + 1; - - ptrW name((wchar_t*)mir_calloc(sizeof(wchar_t) * (length + 1))); - mir_wstrncpy(name, fileName, length); - - moduleName = mir_utf8encodeW(name); -} - -CMLuaScript::CMLuaScript(const CMLuaScript &script) - : CMLuaEnvironment(script.L), status(None), unloadRef(LUA_NOREF) -{ - mir_wstrcpy(filePath, script.filePath); - fileName = mir_wstrdup(script.fileName); - moduleName = mir_strdup(script.moduleName); -} - -CMLuaScript::~CMLuaScript() -{ - Unload(); - mir_free(moduleName); -} - -const wchar_t* CMLuaScript::GetFilePath() const -{ - return filePath; -} - -const wchar_t* CMLuaScript::GetFileName() const -{ - return fileName; -} - -bool CMLuaScript::IsEnabled() -{ - return db_get_b(NULL, MODULENAME, _T2A(fileName), 1); -} - -void CMLuaScript::Enable() -{ - db_unset(NULL, MODULENAME, _T2A(fileName)); -} - -void CMLuaScript::Disable() -{ - db_set_b(NULL, MODULENAME, _T2A(fileName), 0); -} - -CMLuaScript::Status CMLuaScript::GetStatus() const -{ - return status; -} - -bool CMLuaScript::Load() -{ - status = Failed; - - if (luaL_loadfile(L, _T2A(filePath))) { - ReportError(L); - return false; - } - - if (!CMLuaEnvironment::Load()) { - ReportError(L); - return false; - } - - status = Loaded; - - if (lua_isnoneornil(L, -1)) - return true; - - luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); - lua_getfield(L, -1, moduleName); - if (!lua_toboolean(L, -1)) { - lua_pop(L, 1); - lua_pushvalue(L, -2); - lua_setfield(L, -2, moduleName); - lua_pop(L, 1); - } - else - lua_remove(L, -2); - - if (!lua_istable(L, -1)) - return true; - - lua_getfield(L, -1, "Load"); - if (lua_isfunction(L, -1)) - luaM_pcall(L); - else - lua_pop(L, 1); - - lua_getfield(L, -1, "Unload"); - if (lua_isfunction(L, -1)) { - lua_pushvalue(L, -1); - unloadRef = luaL_ref(L, LUA_REGISTRYINDEX); - } - lua_pop(L, 1); - - lua_pop(L, 1); - - return true; -} - -void CMLuaScript::Unload() -{ - if (status == Loaded) { - lua_rawgeti(L, LUA_REGISTRYINDEX, unloadRef); - if (lua_isfunction(L, -1)) - luaM_pcall(L); - lua_pushnil(L); - lua_rawsetp(L, LUA_REGISTRYINDEX, this); - status = None; - } - - luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); - lua_pushnil(L); - lua_setfield(L, -2, moduleName); - lua_pop(L, 1); -} - -bool CMLuaScript::Reload() -{ - Unload(); - return Load(); -} diff --git a/plugins/MirLua/src/mlua_script.h b/plugins/MirLua/src/mlua_script.h deleted file mode 100644 index 70c044741e..0000000000 --- a/plugins/MirLua/src/mlua_script.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef _LUA_SCRIPT_H_ -#define _LUA_SCRIPT_H_ - -class CMLuaScript : public CMLuaEnvironment -{ -public: - enum Status - { - None, - Loaded, - Failed - }; - -private: - Status status; - int unloadRef; - - char *moduleName; - wchar_t *fileName; - wchar_t filePath[MAX_PATH]; - - void Unload(); - -public: - CMLuaScript(lua_State *L, const wchar_t *path); - CMLuaScript(const CMLuaScript &script); - ~CMLuaScript(); - - const wchar_t* GetFilePath() const; - const wchar_t* GetFileName() const; - - bool IsEnabled(); - void Enable(); - void Disable(); - - Status GetStatus() const; - - bool Load(); - bool Reload(); -}; - -#endif //_LUA_SCRIPT_H_ diff --git a/plugins/MirLua/src/mlua_script_loader.cpp b/plugins/MirLua/src/mlua_script_loader.cpp deleted file mode 100644 index 95701b4559..0000000000 --- a/plugins/MirLua/src/mlua_script_loader.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include "stdafx.h" - -CMLuaScriptLoader::CMLuaScriptLoader(lua_State *L) - : L(L) -{ -} - -void CMLuaScriptLoader::SetPaths() -{ - wchar_t path[MAX_PATH]; - - lua_getglobal(L, LUA_LOADLIBNAME); - - FoldersGetCustomPathT(g_hCLibsFolder, path, _countof(path), VARSW(MIRLUA_PATHT)); - lua_pushfstring(L, "%s\\?.dll", T2Utf(path)); - lua_setfield(L, -2, "cpath"); - - FoldersGetCustomPathT(g_hScriptsFolder, path, _countof(path), VARSW(MIRLUA_PATHT)); - lua_pushfstring(L, "%s\\?.lua", T2Utf(path)); - lua_setfield(L, -2, "path"); - - lua_pop(L, 1); -} - -void CMLuaScriptLoader::LoadScript(const wchar_t *scriptDir, const wchar_t *file) -{ - wchar_t fullPath[MAX_PATH], path[MAX_PATH]; - mir_snwprintf(fullPath, L"%s\\%s", scriptDir, file); - PathToRelativeW(fullPath, path); - - CMLuaScript *script = new CMLuaScript(L, path); - g_mLua->Scripts.insert(script); - - if (!script->IsEnabled()) { - Log(L"%s:PASS", path); - return; - } - - if (script->Load()) - Log(L"%s:OK", path); -} - -void CMLuaScriptLoader::LoadScripts() -{ - SetPaths(); - - wchar_t scriptDir[MAX_PATH]; - FoldersGetCustomPathT(g_hScriptsFolder, scriptDir, _countof(scriptDir), VARSW(MIRLUA_PATHT)); - - Log(L"Loading scripts from %s", scriptDir); - - wchar_t searchMask[MAX_PATH]; - mir_snwprintf(searchMask, L"%s\\%s", scriptDir, L"*.lua"); - - WIN32_FIND_DATA fd; - HANDLE hFind = FindFirstFile(searchMask, &fd); - if (hFind != INVALID_HANDLE_VALUE) { - do { - if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - continue; - LoadScript(scriptDir, fd.cFileName); - } while (FindNextFile(hFind, &fd)); - FindClose(hFind); - } -} - -void CMLuaScriptLoader::Load(lua_State *L) -{ - CMLuaScriptLoader(L).LoadScripts(); -} \ No newline at end of file diff --git a/plugins/MirLua/src/mlua_script_loader.h b/plugins/MirLua/src/mlua_script_loader.h deleted file mode 100644 index 74489a0500..0000000000 --- a/plugins/MirLua/src/mlua_script_loader.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -class CMLuaScriptLoader -{ -private: - lua_State *L; - - CMLuaScriptLoader(lua_State *L); - - void SetPaths(); - - void LoadScript(const wchar_t *scriptDir, const wchar_t *file); - void LoadScripts(); - -public: - static void Load(lua_State *L); -}; diff --git a/plugins/MirLua/src/mlua_utils.cpp b/plugins/MirLua/src/mlua_utils.cpp deleted file mode 100644 index 5ecdbc677d..0000000000 --- a/plugins/MirLua/src/mlua_utils.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "stdafx.h" - -void Log(const char *format, ...) -{ - va_list args; - va_start(args, format); - Netlib_Log(hNetlib, CMStringA().FormatV(format, args)); - va_end(args); -} - -void Log(const wchar_t *format, ...) -{ - va_list args; - va_start(args, format); - Netlib_LogW(hNetlib, CMStringW().FormatV(format, args)); - va_end(args); -} - -void ShowNotification(const char *caption, const char *message, int flags, MCONTACT hContact) -{ - if (Miranda_IsTerminated()) - return; - - if (ServiceExists(MS_POPUP_ADDPOPUPT) && db_get_b(NULL, "Popup", "ModuleIsEnabled", 1)) - { - POPUPDATA ppd = { 0 }; - ppd.lchContact = hContact; - mir_strncpy(ppd.lpzContactName, caption, MAX_CONTACTNAME); - mir_strncpy(ppd.lpzText, message, MAX_SECONDLINE); - - if (!PUAddPopup(&ppd)) - return; - } - - MessageBoxA(nullptr, message, caption, MB_OK | flags); -} - -void ObsoleteMethod(lua_State *L, const char *message) -{ - lua_Debug ar; - if (lua_getstack(L, 0, &ar) == 0 || lua_getinfo(L, "n", &ar) == 0) - return; - - char text[512]; - mir_snprintf(text, "%s is obsolete. %s", ar.name, message); - Log(text); - if (db_get_b(NULL, MODULENAME, "PopupOnObsolete", 0)) - ShowNotification(MODULENAME, text, MB_OK | MB_ICONWARNING, NULL); -} - -void ReportError(lua_State *L) -{ - const char *message = lua_tostring(L, -1); - Log(message); - if (db_get_b(NULL, MODULENAME, "PopupOnError", 0)) - ShowNotification(MODULENAME, message, MB_OK | MB_ICONERROR); -} - -int luaM_atpanic(lua_State *L) -{ - ReportError(L); - return 0; -} - -int luaM_pcall(lua_State *L, int n, int r) -{ - int res = lua_pcall(L, n, r, 0); - if (res != LUA_OK) - ReportError(L); - return res; -} - -int luaM_getenv(lua_State *L) -{ - lua_Debug ar; - if (lua_getstack(L, 1, &ar) == 0 || - lua_getinfo(L, "f", &ar) == 0 || - lua_iscfunction(L, -1)) - { - lua_pop(L, 1); - return 0; - } - - const char *env = lua_getupvalue(L, -1, 1); - if (!env || strcmp(env, "_ENV") != 0) - { - lua_pop(L, 1); - return 0; - } - - return 1; -} - -bool luaM_toboolean(lua_State *L, int idx) -{ - if (lua_isnumber(L, idx)) - return lua_tonumber(L, idx) > 0; - return lua_toboolean(L, idx) > 0; -} \ No newline at end of file diff --git a/plugins/MirLua/src/module_loader.cpp b/plugins/MirLua/src/module_loader.cpp new file mode 100644 index 0000000000..9b82f8fdcf --- /dev/null +++ b/plugins/MirLua/src/module_loader.cpp @@ -0,0 +1,46 @@ +#include "stdafx.h" + +CMLuaModuleLoader::CMLuaModuleLoader(lua_State *L) : L(L) +{ +} + +void CMLuaModuleLoader::Load(const char *name, lua_CFunction loader) +{ + luaL_requiref(L, name, loader, 0); +} + +void CMLuaModuleLoader::Preload(const char *name, lua_CFunction loader) +{ + luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); + lua_pushcfunction(L, loader); + lua_setfield(L, -2, name); + lua_pop(L, 1); +} + +void CMLuaModuleLoader::LoadModules() +{ + Log("Loading miranda modules"); + + // load m_core module + Load(MLUA_CORE, luaopen_m_core); + // load all internal modules + Preload(MLUA_CHAT, luaopen_m_chat); + Preload(MLUA_CLIST, luaopen_m_clist); + Preload(MLUA_DATABASE, luaopen_m_database); + Preload(MLUA_GENMENU, luaopen_m_genmenu); + Preload(MLUA_HOTKEYS, luaopen_m_hotkeys); + Preload(MLUA_HTTP, luaopen_m_http); + Preload(MLUA_ICOLIB, luaopen_m_icolib); + Preload(MLUA_JSON, luaopen_m_json); + Preload(MLUA_MESSAGE, luaopen_m_message); + Preload(MLUA_OPTIONS, luaopen_m_options); + Preload(MLUA_PROTOCOLS, luaopen_m_protocols); + Preload(MLUA_SOUNDS, luaopen_m_sounds); + Preload(MLUA_SRMM, luaopen_m_srmm); +} + +void CMLuaModuleLoader::Load(lua_State *L) +{ + CMLuaModuleLoader loader(L); + loader.LoadModules(); +} \ No newline at end of file diff --git a/plugins/MirLua/src/module_loader.h b/plugins/MirLua/src/module_loader.h new file mode 100644 index 0000000000..5b43e7ca49 --- /dev/null +++ b/plugins/MirLua/src/module_loader.h @@ -0,0 +1,17 @@ +#pragma once + +class CMLuaModuleLoader +{ +private: + lua_State *L; + + CMLuaModuleLoader(lua_State *L); + + void Load(const char *name, lua_CFunction loader); + void Preload(const char *name, lua_CFunction loader); + + void LoadModules(); + +public: + static void Load(lua_State *L); +}; diff --git a/plugins/MirLua/src/modules.h b/plugins/MirLua/src/modules.h new file mode 100644 index 0000000000..7aa4402efb --- /dev/null +++ b/plugins/MirLua/src/modules.h @@ -0,0 +1,44 @@ +#pragma once + +#define MLUA_CORE "m_core" +LUAMOD_API int (luaopen_m_core)(lua_State *L); + +#define MLUA_CHAT "m_chat" +LUAMOD_API int (luaopen_m_chat)(lua_State *L); + +#define MLUA_CLIST "m_clist" +LUAMOD_API int (luaopen_m_clist)(lua_State *L); + +#define MLUA_DATABASE "m_database" +LUAMOD_API int (luaopen_m_database)(lua_State *L); + +#define MLUA_ICOLIB "m_icolib" +LUAMOD_API int (luaopen_m_icolib)(lua_State *L); + +#define MLUA_GENMENU "m_genmenu" +LUAMOD_API int (luaopen_m_genmenu)(lua_State *L); + +#define MLUA_HTTP "m_http" +LUAMOD_API int (luaopen_m_http)(lua_State *L); + +#define MLUA_HOTKEYS "m_hotkeys" +LUAMOD_API int (luaopen_m_hotkeys)(lua_State *L); + +#define MLUA_JSON "m_json" +LUAMOD_API int (luaopen_m_json)(lua_State *L); + +#define MLUA_MESSAGE "m_message" +LUAMOD_API int (luaopen_m_message)(lua_State *L); + +#define MLUA_OPTIONS "m_options" +LUAMOD_API int (luaopen_m_options)(lua_State *L); + +#define MLUA_PROTOCOLS "m_protocols" +#define MT_PROTOACCOUNT "PROTOACCOUNT" +LUAMOD_API int (luaopen_m_protocols)(lua_State *L); + +#define MLUA_SOUNDS "m_sounds" +LUAMOD_API int (luaopen_m_sounds)(lua_State *L); + +#define MLUA_SRMM "m_srmm" +LUAMOD_API int (luaopen_m_srmm)(lua_State *L); \ No newline at end of file diff --git a/plugins/MirLua/src/options.cpp b/plugins/MirLua/src/options.cpp new file mode 100644 index 0000000000..3c2dade81b --- /dev/null +++ b/plugins/MirLua/src/options.cpp @@ -0,0 +1,131 @@ +#include "stdafx.h" + +CMLuaOptions::CMLuaOptions() + : CPluginDlgBase(g_plugin, IDD_OPTIONS, MODULENAME), + isScriptListInit(false), + m_popupOnError(this, IDC_POPUPONERROR), + m_popupOnObsolete(this, IDC_POPUPONOBSOLETE), + m_scripts(this, IDC_SCRIPTS), + m_reload(this, IDC_RELOAD) +{ + CreateLink(m_popupOnError, "PopupOnError", DBVT_BYTE, 1); + CreateLink(m_popupOnObsolete, "PopupOnObsolete", DBVT_BYTE, 1); + + m_scripts.OnClick = Callback(this, &CMLuaOptions::OnScriptListClick); + m_reload.OnClick = Callback(this, &CMLuaOptions::OnReload); +} + +void CMLuaOptions::LoadScripts() +{ + for (auto &script : g_plugin.Scripts) { + wchar_t *fileName = NEWWSTR_ALLOCA(script->GetFileName()); + int iIcon = script->GetStatus() - 1; + int iItem = m_scripts.AddItem(fileName, iIcon, (LPARAM)script); + m_scripts.SetCheckState(iItem, script->IsEnabled()); + m_scripts.SetItem(iItem, 1, TranslateT("Open"), 2); + m_scripts.SetItem(iItem, 2, TranslateT("Reload"), 3); + } +} + +void CMLuaOptions::OnInitDialog() +{ + CDlgBase::OnInitDialog(); + + m_scripts.SetExtendedListViewStyle(LVS_EX_SUBITEMIMAGES | LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES | LVS_EX_INFOTIP); + + HIMAGELIST hImageList = m_scripts.CreateImageList(LVSIL_SMALL); + ImageList_AddIcon(hImageList, GetIcon(IDI_LOADED)); + ImageList_AddIcon(hImageList, GetIcon(IDI_FAILED)); + ImageList_AddIcon(hImageList, GetIcon(IDI_OPEN)); + ImageList_AddIcon(hImageList, GetIcon(IDI_RELOAD)); + + wchar_t scriptDir[MAX_PATH]; + FoldersGetCustomPathT(g_hScriptsFolder, scriptDir, _countof(scriptDir), VARSW(MIRLUA_PATHT)); + + wchar_t relativeScriptDir[MAX_PATH]; + PathToRelativeW(scriptDir, relativeScriptDir, nullptr); + + wchar_t header[MAX_PATH + 100]; + mir_snwprintf(header, L"%s (%s)", TranslateT("Common scripts"), relativeScriptDir); + + m_scripts.AddColumn(0, L"Script", 380); + m_scripts.AddColumn(1, nullptr, 32 - GetSystemMetrics(SM_CXVSCROLL)); + m_scripts.AddColumn(2, nullptr, 32 - GetSystemMetrics(SM_CXVSCROLL)); + + LoadScripts(); + + isScriptListInit = true; +} + +void CMLuaOptions::OnApply() +{ + int count = m_scripts.GetItemCount(); + for (int iItem = 0; iItem < count; iItem++) { + CMLuaScript *script = (CMLuaScript*)m_scripts.GetItemData(iItem); + if (!m_scripts.GetCheckState(iItem)) + script->Disable(); + else + script->Enable(); + } +} + +INT_PTR CMLuaOptions::DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_NOTIFY: + { + LPNMHDR lpnmHdr = (LPNMHDR)lParam; + if (lpnmHdr->idFrom == (UINT_PTR)m_scripts.GetCtrlId() && lpnmHdr->code == LVN_ITEMCHANGED) { + LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam; + if (pnmv->uChanged & LVIF_STATE && pnmv->uNewState & LVIS_STATEIMAGEMASK) { + if (isScriptListInit) + NotifyChange(); + } + } + } + break; + } + return CDlgBase::DlgProc(msg, wParam, lParam); +} + +void CMLuaOptions::OnScriptListClick(CCtrlListView::TEventInfo *evt) +{ + LVITEM lvi = {}; + lvi.iItem = evt->nmlvia->iItem; + if (lvi.iItem == -1) + return; + + lvi.pszText = (LPTSTR)mir_calloc(MAX_PATH * sizeof(wchar_t)); + lvi.cchTextMax = MAX_PATH; + lvi.mask = LVIF_GROUPID | LVIF_TEXT | LVIF_PARAM; + m_scripts.GetItem(&lvi); + lvi.iSubItem = evt->nmlvia->iSubItem; + + CMLuaScript *script = (CMLuaScript*)lvi.lParam; + + switch (lvi.iSubItem) { + case 1: + ShellExecute(m_hwnd, L"open", script->GetFilePath(), nullptr, nullptr, SW_SHOWNORMAL); + break; + + case 2: + script->Reload(); + lvi.mask = LVIF_IMAGE; + lvi.iSubItem = 0; + lvi.iImage = script->GetStatus() - 1; + m_scripts.SetItem(&lvi); + m_scripts.Update(lvi.iItem); + break; + } + + mir_free(lvi.pszText); +} + +void CMLuaOptions::OnReload(CCtrlBase*) +{ + isScriptListInit = false; + m_scripts.DeleteAllItems(); + g_plugin.Reload(); + LoadScripts(); + isScriptListInit = true; +} diff --git a/plugins/MirLua/src/options.h b/plugins/MirLua/src/options.h new file mode 100644 index 0000000000..9658ffe336 --- /dev/null +++ b/plugins/MirLua/src/options.h @@ -0,0 +1,27 @@ +#pragma once + +class CMLuaOptions : public CPluginDlgBase +{ +private: + bool isScriptListInit; + + CCtrlCheck m_popupOnError; + CCtrlCheck m_popupOnObsolete; + + CCtrlListView m_scripts; + CCtrlButton m_reload; + + void LoadScripts(); + +protected: + void OnInitDialog(); + void OnApply(); + + void OnScriptListClick(CCtrlListView::TEventInfo *evt); + void OnReload(CCtrlBase*); + + INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam); + +public: + CMLuaOptions(); +}; diff --git a/plugins/MirLua/src/script.cpp b/plugins/MirLua/src/script.cpp new file mode 100644 index 0000000000..976ed79688 --- /dev/null +++ b/plugins/MirLua/src/script.cpp @@ -0,0 +1,137 @@ +#include "stdafx.h" + +#define MT_SCRIPT "SCRIPT" + +CMLuaScript::CMLuaScript(lua_State *L, const wchar_t *path) + : CMLuaEnvironment(L), status(None), unloadRef(LUA_NOREF) +{ + mir_wstrcpy(filePath, path); + + fileName = wcsrchr(filePath, L'\\') + 1; + const wchar_t *dot = wcsrchr(fileName, '.'); + + size_t length = mir_wstrlen(fileName) - mir_wstrlen(dot) + 1; + + ptrW name((wchar_t*)mir_calloc(sizeof(wchar_t) * (length + 1))); + mir_wstrncpy(name, fileName, length); + + m_szModuleName = mir_utf8encodeW(name); +} + +CMLuaScript::CMLuaScript(const CMLuaScript &script) + : CMLuaEnvironment(script.L), status(None), unloadRef(LUA_NOREF) +{ + mir_wstrcpy(filePath, script.filePath); + fileName = mir_wstrdup(script.fileName); + m_szModuleName = mir_strdup(script.m_szModuleName); +} + +CMLuaScript::~CMLuaScript() +{ + Unload(); + mir_free((char*)m_szModuleName); +} + +const wchar_t* CMLuaScript::GetFilePath() const +{ + return filePath; +} + +const wchar_t* CMLuaScript::GetFileName() const +{ + return fileName; +} + +bool CMLuaScript::IsEnabled() +{ + return db_get_b(NULL, MODULENAME, _T2A(fileName), 1); +} + +void CMLuaScript::Enable() +{ + db_unset(NULL, MODULENAME, _T2A(fileName)); +} + +void CMLuaScript::Disable() +{ + db_set_b(NULL, MODULENAME, _T2A(fileName), 0); +} + +CMLuaScript::Status CMLuaScript::GetStatus() const +{ + return status; +} + +bool CMLuaScript::Load() +{ + status = Failed; + + if (luaL_loadfile(L, _T2A(filePath))) { + ReportError(L); + return false; + } + + if (!CMLuaEnvironment::Load()) { + ReportError(L); + return false; + } + + status = Loaded; + + if (lua_isnoneornil(L, -1)) + return true; + + luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); + lua_getfield(L, -1, m_szModuleName); + if (!lua_toboolean(L, -1)) { + lua_pop(L, 1); + lua_pushvalue(L, -2); + lua_setfield(L, -2, m_szModuleName); + lua_pop(L, 1); + } + else + lua_remove(L, -2); + + if (!lua_istable(L, -1)) + return true; + + lua_getfield(L, -1, "Load"); + if (lua_isfunction(L, -1)) + luaM_pcall(L); + else + lua_pop(L, 1); + + lua_getfield(L, -1, "Unload"); + if (lua_isfunction(L, -1)) { + lua_pushvalue(L, -1); + unloadRef = luaL_ref(L, LUA_REGISTRYINDEX); + } + lua_pop(L, 1); + + lua_pop(L, 1); + + return true; +} + +void CMLuaScript::Unload() +{ + if (status == Loaded) { + lua_rawgeti(L, LUA_REGISTRYINDEX, unloadRef); + if (lua_isfunction(L, -1)) + luaM_pcall(L); + lua_pushnil(L); + lua_rawsetp(L, LUA_REGISTRYINDEX, this); + status = None; + } + + luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); + lua_pushnil(L); + lua_setfield(L, -2, m_szModuleName); + lua_pop(L, 1); +} + +bool CMLuaScript::Reload() +{ + Unload(); + return Load(); +} diff --git a/plugins/MirLua/src/script.h b/plugins/MirLua/src/script.h new file mode 100644 index 0000000000..8ff5b40600 --- /dev/null +++ b/plugins/MirLua/src/script.h @@ -0,0 +1,38 @@ +#pragma once + +class CMLuaScript : public CMLuaEnvironment +{ +public: + enum Status + { + None, + Loaded, + Failed + }; + +private: + Status status; + int unloadRef; + + const wchar_t *fileName; + wchar_t filePath[MAX_PATH]; + + void Unload(); + +public: + CMLuaScript(lua_State *L, const wchar_t *path); + CMLuaScript(const CMLuaScript &script); + ~CMLuaScript(); + + const wchar_t* GetFilePath() const; + const wchar_t* GetFileName() const; + + bool IsEnabled(); + void Enable(); + void Disable(); + + Status GetStatus() const; + + bool Load(); + bool Reload(); +}; diff --git a/plugins/MirLua/src/script_loader.cpp b/plugins/MirLua/src/script_loader.cpp new file mode 100644 index 0000000000..0092cca372 --- /dev/null +++ b/plugins/MirLua/src/script_loader.cpp @@ -0,0 +1,70 @@ +#include "stdafx.h" + +CMLuaScriptLoader::CMLuaScriptLoader(lua_State *L) + : L(L) +{ +} + +void CMLuaScriptLoader::SetPaths() +{ + wchar_t path[MAX_PATH]; + + lua_getglobal(L, LUA_LOADLIBNAME); + + FoldersGetCustomPathT(g_hCLibsFolder, path, _countof(path), VARSW(MIRLUA_PATHT)); + lua_pushfstring(L, "%s\\?.dll", T2Utf(path)); + lua_setfield(L, -2, "cpath"); + + FoldersGetCustomPathT(g_hScriptsFolder, path, _countof(path), VARSW(MIRLUA_PATHT)); + lua_pushfstring(L, "%s\\?.lua", T2Utf(path)); + lua_setfield(L, -2, "path"); + + lua_pop(L, 1); +} + +void CMLuaScriptLoader::LoadScript(const wchar_t *scriptDir, const wchar_t *file) +{ + wchar_t fullPath[MAX_PATH], path[MAX_PATH]; + mir_snwprintf(fullPath, L"%s\\%s", scriptDir, file); + PathToRelativeW(fullPath, path); + + CMLuaScript *script = new CMLuaScript(L, path); + g_plugin.Scripts.insert(script); + + if (!script->IsEnabled()) { + Log(L"%s:PASS", path); + return; + } + + if (script->Load()) + Log(L"%s:OK", path); +} + +void CMLuaScriptLoader::LoadScripts() +{ + SetPaths(); + + wchar_t scriptDir[MAX_PATH]; + FoldersGetCustomPathT(g_hScriptsFolder, scriptDir, _countof(scriptDir), VARSW(MIRLUA_PATHT)); + + Log(L"Loading scripts from %s", scriptDir); + + wchar_t searchMask[MAX_PATH]; + mir_snwprintf(searchMask, L"%s\\%s", scriptDir, L"*.lua"); + + WIN32_FIND_DATA fd; + HANDLE hFind = FindFirstFile(searchMask, &fd); + if (hFind != INVALID_HANDLE_VALUE) { + do { + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + continue; + LoadScript(scriptDir, fd.cFileName); + } while (FindNextFile(hFind, &fd)); + FindClose(hFind); + } +} + +void CMLuaScriptLoader::Load(lua_State *L) +{ + CMLuaScriptLoader(L).LoadScripts(); +} \ No newline at end of file diff --git a/plugins/MirLua/src/script_loader.h b/plugins/MirLua/src/script_loader.h new file mode 100644 index 0000000000..21236df491 --- /dev/null +++ b/plugins/MirLua/src/script_loader.h @@ -0,0 +1,17 @@ +#pragma once + +class CMLuaScriptLoader +{ +private: + lua_State *L; + + CMLuaScriptLoader(lua_State *L); + + void SetPaths(); + + void LoadScript(const wchar_t *scriptDir, const wchar_t *file); + void LoadScripts(); + +public: + static void Load(lua_State *L); +}; diff --git a/plugins/MirLua/src/stdafx.h b/plugins/MirLua/src/stdafx.h index f97ecd09de..e8a358ac24 100644 --- a/plugins/MirLua/src/stdafx.h +++ b/plugins/MirLua/src/stdafx.h @@ -10,8 +10,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -35,24 +37,18 @@ class CMLuaScript; -#include "mlua.h" -#include "mlua_environment.h" -#include "mlua_script.h" -#include "mlua_function_loader.h" -#include "mlua_module_loader.h" -#include "mlua_script_loader.h" -#include "mlua_options.h" -#include "mlua_metatable.h" +#include "mplugin.h" +#include "modules.h" +#include "environment.h" +#include "script.h" +#include "function_loader.h" +#include "module_loader.h" +#include "script_loader.h" +#include "options.h" +#include "metatable.h" #define MODULENAME "MirLua" -struct CMPlugin : public PLUGIN -{ - CMPlugin(); -}; - -extern CMLua *g_mLua; - extern int hMLuaLangpack; extern HANDLE g_hCLibsFolder; @@ -65,43 +61,6 @@ extern HANDLE g_hScriptsFolder; /* modules */ -#define MLUA_CORE "m_core" -LUAMOD_API int (luaopen_m_core)(lua_State *L); - -#define MLUA_CHAT "m_chat" -LUAMOD_API int (luaopen_m_chat)(lua_State *L); - -#define MLUA_CLIST "m_clist" -LUAMOD_API int (luaopen_m_clist)(lua_State *L); - -#include "m_database.h" - -#define MLUA_ICOLIB "m_icolib" -LUAMOD_API int (luaopen_m_icolib)(lua_State *L); - -#include "m_json.h" - -#include "m_genmenu.h" - -#define MLUA_HTTP "m_http" -LUAMOD_API int (luaopen_m_http)(lua_State *L); - -#define MLUA_HOTKEYS "m_hotkeys" -LUAMOD_API int (luaopen_m_hotkeys)(lua_State *L); - -#define MLUA_MESSAGE "m_message" -LUAMOD_API int (luaopen_m_message)(lua_State *L); - -#define MLUA_OPTIONS "m_options" -LUAMOD_API int (luaopen_m_options)(lua_State *L); - -#include "m_protocols.h" - -#define MLUA_SOUNDS "m_sounds" -LUAMOD_API int (luaopen_m_sounds)(lua_State *L); - -#define MLUA_SRMM "m_srmm" -LUAMOD_API int (luaopen_m_srmm)(lua_State *L); /* utils */ diff --git a/plugins/MirLua/src/utils.cpp b/plugins/MirLua/src/utils.cpp new file mode 100644 index 0000000000..f8f15f185f --- /dev/null +++ b/plugins/MirLua/src/utils.cpp @@ -0,0 +1,99 @@ +#include "stdafx.h" + +void Log(const char *format, ...) +{ + va_list args; + va_start(args, format); + Netlib_Log(hNetlib, CMStringA().FormatV(format, args)); + va_end(args); +} + +void Log(const wchar_t *format, ...) +{ + va_list args; + va_start(args, format); + Netlib_LogW(hNetlib, CMStringW().FormatV(format, args)); + va_end(args); +} + +void ShowNotification(const char *caption, const char *message, int flags, MCONTACT hContact) +{ + if (Miranda_IsTerminated()) + return; + + if (ServiceExists(MS_POPUP_ADDPOPUPT) && db_get_b(NULL, "Popup", "ModuleIsEnabled", 1)) + { + POPUPDATA ppd = { 0 }; + ppd.lchContact = hContact; + mir_strncpy(ppd.lpzContactName, caption, MAX_CONTACTNAME); + mir_strncpy(ppd.lpzText, message, MAX_SECONDLINE); + + if (!PUAddPopup(&ppd)) + return; + } + + MessageBoxA(nullptr, message, caption, MB_OK | flags); +} + +void ObsoleteMethod(lua_State *L, const char *message) +{ + lua_Debug ar; + if (lua_getstack(L, 0, &ar) == 0 || lua_getinfo(L, "n", &ar) == 0) + return; + + char text[512]; + mir_snprintf(text, "%s is obsolete. %s", ar.name, message); + Log(text); + if (db_get_b(NULL, MODULENAME, "PopupOnObsolete", 0)) + ShowNotification(MODULENAME, text, MB_OK | MB_ICONWARNING, NULL); +} + +void ReportError(lua_State *L) +{ + const char *message = lua_tostring(L, -1); + Log(message); + if (db_get_b(NULL, MODULENAME, "PopupOnError", 0)) + ShowNotification(MODULENAME, message, MB_OK | MB_ICONERROR); +} + +int luaM_atpanic(lua_State *L) +{ + ReportError(L); + return 0; +} + +int luaM_pcall(lua_State *L, int n, int r) +{ + int res = lua_pcall(L, n, r, 0); + if (res != LUA_OK) + ReportError(L); + return res; +} + +int luaM_getenv(lua_State *L) +{ + lua_Debug ar; + if (lua_getstack(L, 1, &ar) == 0 || + lua_getinfo(L, "f", &ar) == 0 || + lua_iscfunction(L, -1)) + { + lua_pop(L, 1); + return 0; + } + + const char *env = lua_getupvalue(L, -1, 1); + if (!env || strcmp(env, "_ENV") != 0) + { + lua_pop(L, 1); + return 0; + } + + return 1; +} + +bool luaM_toboolean(lua_State *L, int idx) +{ + if (lua_isnumber(L, idx)) + return lua_tonumber(L, idx) > 0; + return lua_toboolean(L, idx) > 0; +} \ No newline at end of file -- cgit v1.2.3