From 2a498d86625f65f6ab308fa20c421099c785bf94 Mon Sep 17 00:00:00 2001 From: aunsane Date: Thu, 22 Mar 2018 01:53:49 +0300 Subject: MirLua: various fixes - CMLua now inherit PLUGIN - additional lua fuctions initialization moved to separated loader - ability to realod script without object recreation - scropt object should control own enable state - fix m_json whit is not workes almost at all - version bump --- plugins/MirLua/src/m_json.cpp | 74 +++++---- plugins/MirLua/src/m_json.h | 23 --- plugins/MirLua/src/m_message.cpp | 6 +- plugins/MirLua/src/m_srmm.cpp | 2 +- plugins/MirLua/src/main.cpp | 46 +++--- plugins/MirLua/src/mlua.cpp | 234 +++------------------------- plugins/MirLua/src/mlua.h | 16 +- plugins/MirLua/src/mlua_function_loader.cpp | 194 +++++++++++++++++++++++ plugins/MirLua/src/mlua_function_loader.h | 14 ++ plugins/MirLua/src/mlua_module_loader.cpp | 2 + plugins/MirLua/src/mlua_module_loader.h | 5 +- plugins/MirLua/src/mlua_options.cpp | 78 ++++------ plugins/MirLua/src/mlua_options.h | 11 +- plugins/MirLua/src/mlua_script.cpp | 63 +++++--- plugins/MirLua/src/mlua_script.h | 9 +- plugins/MirLua/src/mlua_script_loader.cpp | 24 ++- plugins/MirLua/src/mlua_script_loader.h | 7 +- plugins/MirLua/src/stdafx.h | 13 +- plugins/MirLua/src/version.h | 2 +- 19 files changed, 423 insertions(+), 400 deletions(-) create mode 100644 plugins/MirLua/src/mlua_function_loader.cpp create mode 100644 plugins/MirLua/src/mlua_function_loader.h (limited to 'plugins') diff --git a/plugins/MirLua/src/m_json.cpp b/plugins/MirLua/src/m_json.cpp index 60f75411e9..eccef5cff2 100644 --- a/plugins/MirLua/src/m_json.cpp +++ b/plugins/MirLua/src/m_json.cpp @@ -2,8 +2,7 @@ static void lua2json(lua_State *L, JSONNode &node) { - switch (lua_type(L, -1)) - { + switch (lua_type(L, -1)) { case LUA_TNIL: node.nullify(); break; @@ -54,25 +53,36 @@ static void lua2json(lua_State *L, JSONNode &node) static int json__index(lua_State *L) { - JSONNode &node = *((JSON*)luaL_checkudata(L, 1, MT_JSON))->node; + 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 (node.type()) + switch (child->type()) { case JSON_NULL: lua_pushnil(L); break; case JSON_STRING: - lua_pushstring(L, node.as_string().c_str()); + lua_pushstring(L, child->as_string().c_str()); break; case JSON_NUMBER: - lua_pushnumber(L, node.as_int()); + lua_pushnumber(L, child->as_int()); break; case JSON_BOOL: - lua_pushboolean(L, node.as_bool()); + lua_pushboolean(L, child->as_bool()); break; - case JSON_NODE: case JSON_ARRAY: - new (L) JSONNode(node); + case JSON_NODE: + JSONNode **udata = (JSONNode**)lua_newuserdata(L, sizeof(JSONNode*)); + *udata = child; luaL_setmetatable(L, MT_JSON); } @@ -81,46 +91,51 @@ static int json__index(lua_State *L) static int json__newindex(lua_State *L) { - JSONNode &node = *((JSON*)luaL_checkudata(L, 1, MT_JSON))->node; + JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); const char *key = lua_tostring(L, 2); - JSONNode child = node[key]; - if (child.isnull()) { - child.set_name(key); - lua2json(L, child); - node << child; + if (json_type(node) == JSON_ARRAY) { + int idx = lua_tointeger(L, 2); + JSONNode *child = json_at(node, idx - 1); + lua2json(L, *child); return 0; } - lua2json(L, child); - node[key] = child; + 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 = *((JSON*)luaL_checkudata(L, 1, MT_JSON))->node; - - lua_pushnumber(L, node.size()); + 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 = *((JSON*)luaL_checkudata(L, 1, MT_JSON))->node; + JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); - lua_pushstring(L, node.write().c_str()); + lua_pushstring(L, node->write().c_str()); return 1; } static int json__gc(lua_State *L) { - JSON *json = (JSON*)luaL_checkudata(L, 1, MT_JSON); + JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); - delete json; + json_delete(node); return 0; } @@ -143,8 +158,8 @@ static int lua_Decode(lua_State *L) { const char *string = luaL_checkstring(L, 1); - JSONNode *node = json_parse(string); - new (L) JSON(node); + JSONNode **udata = (JSONNode**)lua_newuserdata(L, sizeof(JSONNode*)); + *udata = json_parse(string); luaL_setmetatable(L, MT_JSON); return 1; @@ -152,8 +167,7 @@ static int lua_Decode(lua_State *L) static int lua_Encode(lua_State *L) { - switch (lua_type(L, 1)) - { + switch (lua_type(L, 1)) { case LUA_TNIL: lua_pushliteral(L, "null"); break; @@ -190,8 +204,8 @@ static int lua_Encode(lua_State *L) } case LUA_TUSERDATA: { - JSONNode &node = *((JSON*)luaL_checkudata(L, 1, MT_JSON))->node; - lua_pushstring(L, node.write().c_str()); + JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); + lua_pushstring(L, node->write().c_str()); break; } case LUA_TLIGHTUSERDATA: diff --git a/plugins/MirLua/src/m_json.h b/plugins/MirLua/src/m_json.h index bb3a2e1568..1357505bec 100644 --- a/plugins/MirLua/src/m_json.h +++ b/plugins/MirLua/src/m_json.h @@ -1,29 +1,6 @@ #ifndef _LUA_M_JSON_H_ #define _LUA_M_JSON_H_ -#include - -struct JSON -{ - JSONNode *node; - bool bDelete; - - JSON(JSONNode &refNode, bool bCopy = false) - : node(bCopy ? json_copy(&refNode) : &refNode), bDelete(bCopy) { } - JSON(JSONNode *n, bool bD = true) - : node(n), bDelete(bD) { } - ~JSON() - { - if (bDelete) - json_delete(node); - } - - __inline void* operator new(size_t size, lua_State *L) - { - return lua_newuserdata(L, size); - } -}; - #define MT_JSON "JSON" #define MLUA_JSON "m_json" diff --git a/plugins/MirLua/src/m_message.cpp b/plugins/MirLua/src/m_message.cpp index c02adb0478..e382616954 100644 --- a/plugins/MirLua/src/m_message.cpp +++ b/plugins/MirLua/src/m_message.cpp @@ -27,15 +27,13 @@ static int message_Send(lua_State *L) INT_PTR res = 1; const char *szProto = GetContactProto(hContact); - if (db_get_b(hContact, szProto, "ChatRoom", 0) == TRUE) - { + 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) - { + else if ((res = ProtoChainSend(hContact, PSS_MESSAGE, 0, (LPARAM)message)) != ACKRESULT_FAILED) { DBEVENTINFO dbei = {}; dbei.szModule = MODULE; dbei.timestamp = time(nullptr); diff --git a/plugins/MirLua/src/m_srmm.cpp b/plugins/MirLua/src/m_srmm.cpp index cd1562fe61..9a98755380 100644 --- a/plugins/MirLua/src/m_srmm.cpp +++ b/plugins/MirLua/src/m_srmm.cpp @@ -44,7 +44,7 @@ static int lua_AddButton(lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); - BBButton bbb = { }; + BBButton bbb = {}; MakeBBButton(L, bbb); int hScriptLangpack = CMLuaEnvironment::GetEnvironmentId(L); diff --git a/plugins/MirLua/src/main.cpp b/plugins/MirLua/src/main.cpp index 22fabbbdef..d316b47cd0 100644 --- a/plugins/MirLua/src/main.cpp +++ b/plugins/MirLua/src/main.cpp @@ -38,41 +38,35 @@ extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD) return &pluginInfo; } -int OnModulesLoaded(WPARAM, LPARAM) +int OnOptionsInit(WPARAM wParam, LPARAM) { - g_hCLibsFolder = FoldersRegisterCustomPathT(MODULE, "CLibsFolder", MIRLUA_PATHT, TranslateT("C libs folder")); - g_hScriptsFolder = FoldersRegisterCustomPathT(MODULE, "ScriptsFolder", MIRLUA_PATHT, TranslateT("Scripts folder")); - - HookEvent(ME_OPT_INITIALISE, CMLuaOptions::OnOptionsInit); - - InitIcons(); - - g_mLua = new CMLua(); - g_mLua->Load(); + OPTIONSDIALOGPAGE odp = {}; + odp.hInstance = g_hInstance; + odp.flags = ODPF_BOLDGROUPS | ODPF_UNICODE | ODPF_DONTTRANSLATE; + odp.szGroup.w = LPGENW("Services"); + odp.szTitle.w = L"Lua"; + odp.szTab.w = LPGENW("Scripts"); + odp.pDialog = new CMLuaOptions(g_mLua); + Options_AddPage(wParam, &odp); return 0; } -INT_PTR Call(WPARAM wParam, LPARAM lParam) +int OnModulesLoaded(WPARAM, LPARAM) { - return g_mLua->Call(wParam, lParam); -} + g_hCLibsFolder = FoldersRegisterCustomPathT(MODULE, "CLibsFolder", MIRLUA_PATHT, TranslateT("C libs folder")); + g_hScriptsFolder = FoldersRegisterCustomPathT(MODULE, "ScriptsFolder", MIRLUA_PATHT, TranslateT("Scripts folder")); -INT_PTR Exec(WPARAM wParam, LPARAM lParam) -{ - return g_mLua->Exec(wParam, lParam); -} + HookEvent(ME_OPT_INITIALISE, OnOptionsInit); -INT_PTR Eval(WPARAM wParam, LPARAM lParam) -{ - return g_mLua->Eval(wParam, lParam); + return 0; } extern "C" int __declspec(dllexport) Load(void) { mir_getLP(&pluginInfo); - HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded); + InitIcons(); NETLIBUSER nlu = {}; nlu.flags = NUF_OUTGOING | NUF_INCOMING | NUF_HTTPCONNS; @@ -89,9 +83,10 @@ extern "C" int __declspec(dllexport) Load(void) hRecvMessage = CreateHookableEvent(MODULE PSR_MESSAGE); CreateProtoServiceFunction(MODULE, PSR_MESSAGE, FilterRecvMessage); - CreateServiceFunction(MS_LUA_CALL, Call); - CreateServiceFunction(MS_LUA_EXEC, Exec); - CreateServiceFunction(MS_LUA_EVAL, Eval); + g_mLua = new CMLua(); + g_mLua->Load(); + + HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded); return 0; } @@ -100,8 +95,7 @@ extern "C" int __declspec(dllexport) Unload(void) { delete g_mLua; - if (hNetlib) - { + if (hNetlib) { Netlib_CloseHandle(hNetlib); hNetlib = nullptr; } diff --git a/plugins/MirLua/src/mlua.cpp b/plugins/MirLua/src/mlua.cpp index 3f1da7760c..b0a12289c6 100644 --- a/plugins/MirLua/src/mlua.cpp +++ b/plugins/MirLua/src/mlua.cpp @@ -2,10 +2,17 @@ int hMLuaLangpack; -CMLua::CMLua() : L(nullptr), Scripts(1) +CMLua::CMLua() + : PLUGIN(MODULE), + L(nullptr), + Scripts(1) { MUUID muidLast = MIID_LAST; hMLuaLangpack = GetPluginLangId(muidLast, 0); + + CreatePluginService(MS_LUA_CALL, &CMLua::Call); + CreatePluginService(MS_LUA_EXEC, &CMLua::Exec); + CreatePluginService(MS_LUA_EVAL, &CMLua::Eval); } CMLua::~CMLua() @@ -13,216 +20,17 @@ CMLua::~CMLua() Unload(); } -/***********************************************/ - -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 CMLua::SetPaths() -{ - wchar_t path[MAX_PATH]; - - lua_getglobal(L, "package"); - - FoldersGetCustomPathT(g_hCLibsFolder, path, _countof(path), VARSW(MIRLUA_PATHT)); - lua_pushfstring(L, "%s\\?.dll", ptrA(mir_utf8encodeW(path))); - lua_setfield(L, -2, "cpath"); - - FoldersGetCustomPathT(g_hScriptsFolder, path, _countof(path), VARSW(MIRLUA_PATHT)); - lua_pushfstring(L, "%s\\?.lua", ptrA(mir_utf8encodeW(path))); - lua_setfield(L, -2, "path"); - - lua_pop(L, 1); -} - void CMLua::Load() { Log("Loading lua engine"); L = luaL_newstate(); - Log("Loading std modules"); + Log("Loading standard modules"); luaL_openlibs(L); - SetPaths(); - - 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); - lua_atpanic(L, luaM_atpanic); - Log("Loading miranda modules"); + CMLuaFunctionLoader::Load(L); CMLuaModuleLoader::Load(L); - Log("Loading scripts"); CMLuaScriptLoader::Load(L); } @@ -243,6 +51,12 @@ void CMLua::Unload() lua_close(L); } +void CMLua::Reload() +{ + Unload(); + Load(); +} + /***********************************************/ static int mlua_call(lua_State *L) @@ -276,7 +90,7 @@ INT_PTR CMLua::Call(WPARAM wParam, LPARAM lParam) lua_newtable(L); lua_pushcclosure(L, mlua_call, 1); - + CMLuaEnvironment env(L); env.Load(); @@ -286,11 +100,11 @@ INT_PTR CMLua::Call(WPARAM wParam, LPARAM lParam) return (INT_PTR)result; } -INT_PTR CMLua::Exec(WPARAM, LPARAM lParam) +INT_PTR CMLua::Eval(WPARAM, LPARAM lParam) { - const wchar_t *path = (const wchar_t*)lParam; + const wchar_t *script = (const wchar_t*)lParam; - if (luaL_loadfile(L, ptrA(mir_utf8encodeW(path)))) { + if (luaL_loadstring(L, ptrA(mir_utf8encodeW(script)))) { ReportError(L); return NULL; } @@ -304,11 +118,11 @@ INT_PTR CMLua::Exec(WPARAM, LPARAM lParam) return (INT_PTR)result; } -INT_PTR CMLua::Eval(WPARAM, LPARAM lParam) +INT_PTR CMLua::Exec(WPARAM, LPARAM lParam) { - const wchar_t *script = (const wchar_t*)lParam; + const wchar_t *path = (const wchar_t*)lParam; - if (luaL_loadstring(L, ptrA(mir_utf8encodeW(script)))) { + if (luaL_loadfile(L, ptrA(mir_utf8encodeW(path)))) { ReportError(L); return NULL; } @@ -320,4 +134,4 @@ INT_PTR CMLua::Eval(WPARAM, LPARAM lParam) lua_pop(L, 1); return (INT_PTR)result; -} \ No newline at end of file +} diff --git a/plugins/MirLua/src/mlua.h b/plugins/MirLua/src/mlua.h index 44ebd4a40d..6f5bdca432 100644 --- a/plugins/MirLua/src/mlua.h +++ b/plugins/MirLua/src/mlua.h @@ -1,12 +1,18 @@ #ifndef _LUA_CORE_H_ #define _LUA_CORE_H_ -class CMLua +class CMLua : private PLUGIN { + friend class CMLuaOptions; + private: lua_State *L; - void SetPaths(); + void Unload(); + + INT_PTR __cdecl Eval(WPARAM, LPARAM); + INT_PTR __cdecl Call(WPARAM, LPARAM); + INT_PTR __cdecl Exec(WPARAM, LPARAM); public: OBJLIST Scripts; @@ -15,11 +21,7 @@ public: ~CMLua(); void Load(); - void Unload(); - - INT_PTR Call(WPARAM, LPARAM); - INT_PTR Exec(WPARAM, LPARAM); - INT_PTR Eval(WPARAM, LPARAM); + void Reload(); }; #endif //_LUA_CORE_H_ diff --git a/plugins/MirLua/src/mlua_function_loader.cpp b/plugins/MirLua/src/mlua_function_loader.cpp new file mode 100644 index 0000000000..6e82086d29 --- /dev/null +++ b/plugins/MirLua/src/mlua_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/mlua_function_loader.h b/plugins/MirLua/src/mlua_function_loader.h new file mode 100644 index 0000000000..9724ccdc3d --- /dev/null +++ b/plugins/MirLua/src/mlua_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/mlua_module_loader.cpp b/plugins/MirLua/src/mlua_module_loader.cpp index d914bad120..ff9594f363 100644 --- a/plugins/MirLua/src/mlua_module_loader.cpp +++ b/plugins/MirLua/src/mlua_module_loader.cpp @@ -19,6 +19,8 @@ void CMLuaModuleLoader::Preload(const char *name, lua_CFunction loader) void CMLuaModuleLoader::LoadModules() { + Log("Loading miranda modules"); + // load m_core module Load(MLUA_CORE, luaopen_m_core); // load all internal modules diff --git a/plugins/MirLua/src/mlua_module_loader.h b/plugins/MirLua/src/mlua_module_loader.h index 123c05bf41..bab8e79e84 100644 --- a/plugins/MirLua/src/mlua_module_loader.h +++ b/plugins/MirLua/src/mlua_module_loader.h @@ -1,5 +1,4 @@ -#ifndef _LUA_MODULE_LOADER_H_ -#define _LUA_MODULE_LOADER_H_ +#pragma once class CMLuaModuleLoader { @@ -16,5 +15,3 @@ private: public: static void Load(lua_State *L); }; - -#endif //_LUA_MODULE_LOADER_H_ \ No newline at end of file diff --git a/plugins/MirLua/src/mlua_options.cpp b/plugins/MirLua/src/mlua_options.cpp index a4afbf33dc..9aff70ba3f 100644 --- a/plugins/MirLua/src/mlua_options.cpp +++ b/plugins/MirLua/src/mlua_options.cpp @@ -1,11 +1,11 @@ #include "stdafx.h" -CMLuaOptions::CMLuaOptions(int idDialog) - : CPluginDlgBase(g_hInstance, idDialog, MODULE), +CMLuaOptions::CMLuaOptions(CMLua *mLua) + : CPluginDlgBase(g_hInstance, IDD_OPTIONS, MODULE), + m_mLua(mLua), isScriptListInit(false), m_popupOnError(this, IDC_POPUPONERROR), m_popupOnObsolete(this, IDC_POPUPONOBSOLETE), - isScriptListInit(false), m_scripts(this, IDC_SCRIPTS), - m_reload(this, IDC_RELOAD) + m_scripts(this, IDC_SCRIPTS), m_reload(this, IDC_RELOAD) { CreateLink(m_popupOnError, "PopupOnError", DBVT_BYTE, 1); CreateLink(m_popupOnObsolete, "PopupOnObsolete", DBVT_BYTE, 1); @@ -16,12 +16,11 @@ CMLuaOptions::CMLuaOptions(int idDialog) void CMLuaOptions::LoadScripts() { - for (auto &it : g_mLua->Scripts) { - wchar_t *fileName = NEWWSTR_ALLOCA(it->GetFileName()); - int iIcon = it->GetStatus() - 1; - int iItem = m_scripts.AddItem(fileName, iIcon, (LPARAM)it); - if (db_get_b(NULL, MODULE, _T2A(fileName), 1)) - m_scripts.SetCheckState(iItem, TRUE); + 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); } @@ -39,9 +38,13 @@ void CMLuaOptions::OnInitDialog() ImageList_AddIcon(hImageList, GetIcon(IDI_OPEN)); ImageList_AddIcon(hImageList, GetIcon(IDI_RELOAD)); - wchar_t scriptDir[MAX_PATH], relativeScriptDir[MAX_PATH], header[MAX_PATH + 100]; + 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); @@ -57,12 +60,11 @@ void CMLuaOptions::OnApply() { int count = m_scripts.GetItemCount(); for (int iItem = 0; iItem < count; iItem++) { - wchar_t fileName[MAX_PATH]; - m_scripts.GetItemText(iItem, 0, fileName, _countof(fileName)); + CMLuaScript *script = (CMLuaScript*)m_scripts.GetItemData(iItem); if (!m_scripts.GetCheckState(iItem)) - db_set_b(NULL, MODULE, _T2A(fileName), 0); + script->Disable(); else - db_unset(NULL, MODULE, _T2A(fileName)); + script->Enable(); } } @@ -82,41 +84,36 @@ INT_PTR CMLuaOptions::DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) } break; } - return CDlgBase::DlgProc(msg, wParam, lParam); } void CMLuaOptions::OnScriptListClick(CCtrlListView::TEventInfo *evt) { - LVITEM lvi = { 0 }; + LVITEM lvi = {}; lvi.iItem = evt->nmlvia->iItem; - if (lvi.iItem == -1) return; + 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; - evt->treeviewctrl->GetItem(&lvi); + m_scripts.GetItem(&lvi); lvi.iSubItem = evt->nmlvia->iSubItem; CMLuaScript *script = (CMLuaScript*)lvi.lParam; - switch (lvi.iSubItem) - { + switch (lvi.iSubItem) { case 1: - ShellExecute(m_hwnd, L"Open", script->GetFilePath(), nullptr, nullptr, SW_SHOWNORMAL); + ShellExecute(m_hwnd, L"open", script->GetFilePath(), nullptr, nullptr, SW_SHOWNORMAL); break; case 2: - CMLuaScript *oldScript = script; - script = new CMLuaScript(*script); - delete oldScript; - script->Load(); - - lvi.mask = LVIF_PARAM | LVIF_IMAGE; + script->Reload(); + lvi.mask = LVIF_IMAGE; lvi.iSubItem = 0; - lvi.lParam = (LPARAM)script; lvi.iImage = script->GetStatus() - 1; - ListView_SetItem(m_scripts.GetHwnd(), &lvi); - m_scripts.Update(evt->nmlvia->iItem); + m_scripts.SetItem(&lvi); + m_scripts.Update(lvi.iItem); break; } @@ -127,24 +124,7 @@ void CMLuaOptions::OnReload(CCtrlBase*) { isScriptListInit = false; m_scripts.DeleteAllItems(); - g_mLua->Unload(); - g_mLua->Load(); + m_mLua->Reload(); LoadScripts(); isScriptListInit = true; } - -/****************************************/ - -int CMLuaOptions::OnOptionsInit(WPARAM wParam, LPARAM) -{ - OPTIONSDIALOGPAGE odp = { 0 }; - odp.hInstance = g_hInstance; - odp.flags = ODPF_BOLDGROUPS | ODPF_UNICODE | ODPF_DONTTRANSLATE; - odp.szGroup.w = LPGENW("Services"); - odp.szTitle.w = L"Lua"; - odp.szTab.w = LPGENW("Scripts"); - odp.pDialog = CMLuaOptions::CreateOptionsPage(); - Options_AddPage(wParam, &odp); - - return 0; -} \ No newline at end of file diff --git a/plugins/MirLua/src/mlua_options.h b/plugins/MirLua/src/mlua_options.h index a8168d70da..2e3b4ff7f7 100644 --- a/plugins/MirLua/src/mlua_options.h +++ b/plugins/MirLua/src/mlua_options.h @@ -1,15 +1,15 @@ #ifndef _LUA_OPTIONS_H_ #define _LUA_OPTIONS_H_ -#include - class CMLuaOptions : public CPluginDlgBase { private: + CMLua *m_mLua; + bool isScriptListInit; + CCtrlCheck m_popupOnError; CCtrlCheck m_popupOnObsolete; - bool isScriptListInit; CCtrlListView m_scripts; CCtrlButton m_reload; @@ -25,10 +25,7 @@ protected: INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam); public: - CMLuaOptions(int idDialog); - - static int OnOptionsInit(WPARAM wParam, LPARAM); - static CDlgBase *CreateOptionsPage() { return new CMLuaOptions(IDD_OPTIONS); } + 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 index 310fecddf9..83b5008e15 100644 --- a/plugins/MirLua/src/mlua_script.cpp +++ b/plugins/MirLua/src/mlua_script.cpp @@ -28,29 +28,10 @@ CMLuaScript::CMLuaScript(const CMLuaScript &script) CMLuaScript::~CMLuaScript() { - 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, "_LOADED"); - lua_pushnil(L); - lua_setfield(L, -2, moduleName); - lua_pop(L, 1); - + Unload(); mir_free(moduleName); } -const char* CMLuaScript::GetModuleName() const -{ - return moduleName; -} - const wchar_t* CMLuaScript::GetFilePath() const { return filePath; @@ -61,6 +42,21 @@ const wchar_t* CMLuaScript::GetFileName() const return fileName; } +bool CMLuaScript::IsEnabled() +{ + return db_get_b(NULL, MODULE, _T2A(fileName), 1); +} + +void CMLuaScript::Enable() +{ + db_unset(NULL, MODULE, _T2A(fileName)); +} + +void CMLuaScript::Disable() +{ + db_set_b(NULL, MODULE, _T2A(fileName), 0); +} + CMLuaScript::Status CMLuaScript::GetStatus() const { return status; @@ -85,7 +81,7 @@ bool CMLuaScript::Load() if (lua_isnoneornil(L, -1)) return true; - luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); + luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); lua_getfield(L, -1, moduleName); if (!lua_toboolean(L, -1)) { lua_pop(L, 1); @@ -115,4 +111,27 @@ bool CMLuaScript::Load() lua_pop(L, 1); return true; -} \ No newline at end of file +} + +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 index 9a1ec98390..70c044741e 100644 --- a/plugins/MirLua/src/mlua_script.h +++ b/plugins/MirLua/src/mlua_script.h @@ -19,19 +19,24 @@ private: 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 char* GetModuleName() const; - 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 index 60ceb5cbb5..95701b4559 100644 --- a/plugins/MirLua/src/mlua_script_loader.cpp +++ b/plugins/MirLua/src/mlua_script_loader.cpp @@ -1,9 +1,27 @@ #include "stdafx.h" -CMLuaScriptLoader::CMLuaScriptLoader(lua_State *L) : L(L) +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]; @@ -13,7 +31,7 @@ void CMLuaScriptLoader::LoadScript(const wchar_t *scriptDir, const wchar_t *file CMLuaScript *script = new CMLuaScript(L, path); g_mLua->Scripts.insert(script); - if (db_get_b(NULL, MODULE, _T2A(file), 1) == FALSE) { + if (!script->IsEnabled()) { Log(L"%s:PASS", path); return; } @@ -24,6 +42,8 @@ void CMLuaScriptLoader::LoadScript(const wchar_t *scriptDir, const wchar_t *file void CMLuaScriptLoader::LoadScripts() { + SetPaths(); + wchar_t scriptDir[MAX_PATH]; FoldersGetCustomPathT(g_hScriptsFolder, scriptDir, _countof(scriptDir), VARSW(MIRLUA_PATHT)); diff --git a/plugins/MirLua/src/mlua_script_loader.h b/plugins/MirLua/src/mlua_script_loader.h index e455793adf..74489a0500 100644 --- a/plugins/MirLua/src/mlua_script_loader.h +++ b/plugins/MirLua/src/mlua_script_loader.h @@ -1,5 +1,4 @@ -#ifndef _LUA_SCRIPT_LOADER_H_ -#define _LUA_SCRIPT_LOADER_H_ +#pragma once class CMLuaScriptLoader { @@ -7,6 +6,8 @@ private: lua_State *L; CMLuaScriptLoader(lua_State *L); + + void SetPaths(); void LoadScript(const wchar_t *scriptDir, const wchar_t *file); void LoadScripts(); @@ -14,5 +15,3 @@ private: public: static void Load(lua_State *L); }; - -#endif //_LUA_SCRIPT_LOADER_H_ \ No newline at end of file diff --git a/plugins/MirLua/src/stdafx.h b/plugins/MirLua/src/stdafx.h index 2939b66922..3b5d8ffb6d 100644 --- a/plugins/MirLua/src/stdafx.h +++ b/plugins/MirLua/src/stdafx.h @@ -1,5 +1,4 @@ -#ifndef _COMMON_H_ -#define _COMMON_H_ +#pragma once #include #include @@ -25,6 +24,9 @@ #include #include #include +#include +#include +#include #include #include @@ -37,6 +39,7 @@ 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" @@ -98,10 +101,6 @@ LUAMOD_API int (luaopen_m_sounds)(lua_State *L); #define MLUA_SRMM "m_srmm" LUAMOD_API int (luaopen_m_srmm)(lua_State *L); -/* services */ - -INT_PTR Call(WPARAM wParam, LPARAM lParam); - /* utils */ extern HNETLIBUSER hNetlib; @@ -124,5 +123,3 @@ bool luaM_toboolean(lua_State *L, int idx); void InitIcons(); HICON GetIcon(int iconId); HANDLE GetIconHandle(int iconId); - -#endif //_COMMON_H_ diff --git a/plugins/MirLua/src/version.h b/plugins/MirLua/src/version.h index 65a0d49d81..c178f55fb7 100644 --- a/plugins/MirLua/src/version.h +++ b/plugins/MirLua/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 0 #define __MINOR_VERSION 11 #define __RELEASE_NUM 8 -#define __BUILD_NUM 6 +#define __BUILD_NUM 7 #include -- cgit v1.2.3