/* SPDX-License-Identifier: ZLIB Copyright (c) 2014 - 2023 Guillaume Vareille http://ysengrin.com _________ / \ LUA_plugin.tinyfiledialogs.cpp v3.8.3 [Nov 1, 2020] |tiny file| LUA bindings created [2016] Copyright (c) 2016 Steven Johnson | dialogs | \____ ___/ http://tinyfiledialogs.sourceforge.net \| git clone http://git.code.sf.net/p/tinyfiledialogs/code tinyfd ____________________________________________ | | | email: tinyfiledialogs at ysengrin.com | |____________________________________________| If you like tinyfiledialogs, please upvote my stackoverflow answer https://stackoverflow.com/a/47651444 - License - This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. ----------- this file was contributed by Steven Johnson from the Corona SDK project and is offered here under the same zlib license as tinyfiledialogs -#include "CoronaLua.h" will typically be something like extern "C" { #include "lua.h" #include "lualib.h" #include "lauxlib.h" } in a normal(i.e.non - Corona) program. - For that matter, CORONA_EXPORT just hides the library exporting code. - The "_plugin_" stuff is part of a signature used by Corona to dynamically load the entry point function, but might be out of place in a non - Corona program. */ #include "CoronaLua.h" #include "tinyfiledialogs.h" #include #define STATIC_FILTER_COUNT 8 static int GetBool (lua_State * L, const char * key) { lua_getfield(L, 1, key);// ..., bool int bval = lua_toboolean(L, -1); lua_pop(L, 1); // ... return bval; } static const char * GetStrOrBlank (lua_State * L, const char * key, const char * blank = "") { lua_getfield(L, 1, key);// ..., str? const char * str = blank; // might be NULL, thus not using luaL_optstring if (!lua_isnil(L, -1)) str = luaL_checkstring(L, -1); lua_pop(L, 1); return str; } static int GetFilters (lua_State * L, const char *** filters) { int nfilters = 0; lua_getfield(L, 1, "filter_patterns"); // ..., patts if (lua_istable(L, -1)) { int n = lua_objlen(L, -1); if (n > STATIC_FILTER_COUNT) *filters = (const char **)lua_newuserdata(L, sizeof(const char *) * n);// ..., patts, filters for (int i = 1; i <= n; ++i, lua_pop(L, 1)) { lua_rawgeti(L, -1, i); // ..., patts[, filters], patt (*filters)[nfilters++] = luaL_checkstring(L, -1); } } else if (!lua_isnil(L, -1)) (*filters)[nfilters++] = luaL_checkstring(L, -1); return nfilters; } static int StringResponse (lua_State * L, const char * res) { if (!res) lua_pushboolean(L, 0);// ..., false else lua_pushstring(L, res);// ..., res return 1; } static luaL_Reg tfd_funcs[] = { { "notifyPopup", [](lua_State * L) { luaL_checktype(L, 1, LUA_TTABLE); const char * title = GetStrOrBlank(L, "title"); const char * message = GetStrOrBlank(L, "message"); const char * icon_types[] = { "info", "warning", "error" }; lua_getfield(L, 1, "icon_type"); // opts, icon_type const char * itype = icon_types[luaL_checkoption(L, -1, "info", icon_types)]; lua_pushboolean(L, tinyfd_notifyPopup(title, message, itype)); // opts, icon_type return 1; } }, { "messageBox", [](lua_State * L) { luaL_checktype(L, 1, LUA_TTABLE); const char * title = GetStrOrBlank(L, "title"); const char * message = GetStrOrBlank(L, "message"); const char * dialog_types[] = { "ok", "okcancel", "yesno", "yesnocancel" }; const char * icon_types[] = { "info", "warning", "error", "question" }; lua_getfield(L, 1, "dialog_type"); // opts, dialog_type lua_getfield(L, 1, "icon_type");// opts, dialog_type, icon_type const char * dtype = dialog_types[luaL_checkoption(L, -2, "ok", dialog_types)]; const char * itype = icon_types[luaL_checkoption(L, -1, "info", icon_types)]; lua_pushboolean(L, tinyfd_messageBox(title, message, dtype, itype, GetBool(L, "default_okyes"))); // opts, dialog_type, icon_type, ok / yes return 1; } }, { "inputBox", [](lua_State * L) { luaL_checktype(L, 1, LUA_TTABLE); const char * title = GetStrOrBlank(L, "title"); const char * message = GetStrOrBlank(L, "message"); // lua_getfield(L, 1, "default_input");// opts, def_input const char * def_input; if (lua_type(L, -1) == LUA_TBOOLEAN && !lua_toboolean(L, -1)) def_input = NULL; else def_input = luaL_optstring(L, -1, ""); return StringResponse(L, tinyfd_inputBox(title, message, def_input)); // opts, def_input, input } }, { "saveFileDialog", [](lua_State * L) { luaL_checktype(L, 1, LUA_TTABLE); const char * title = GetStrOrBlank(L, "title"); const char * def_path_and_file = GetStrOrBlank(L, "default_path_and_file"); const char * filter_description = GetStrOrBlank(L, "filter_description", NULL); const char * filter_array[STATIC_FILTER_COUNT] = { 0 }, ** filters = filter_array; int nfilters = GetFilters(L, &filters); // opts, patts[, filters] return StringResponse(L, tinyfd_saveFileDialog(title, def_path_and_file, nfilters, filters, filter_description)); // opts, patts[, filters], file } }, { "openFileDialog", [](lua_State * L) { luaL_checktype(L, 1, LUA_TTABLE); // const char * title = GetStrOrBlank(L, "title"); const char * def_path_and_file = GetStrOrBlank(L, "default_path_and_file"); const char * filter_description = GetStrOrBlank(L, "filter_description", NULL); const char * filter_array[STATIC_FILTER_COUNT] = { 0 }, ** filters = filter_array; int allow_multiple_selects = GetBool(L, "allow_multiple_selects"); int nfilters = GetFilters(L, &filters); // opts, patts[, filters] // const char * files = tinyfd_openFileDialog(title, def_path_and_file, nfilters, nfilters ? filters : NULL, filter_description, allow_multiple_selects); if (!allow_multiple_selects || !files) return StringResponse(L, files); // opts, patts[, filters], files? else { lua_newtable(L);// opts, patts[, filters], files char * from = (char *)files, * sep = from; // assign sep in order to pass first iteration for (int fi = 1; sep; ++fi) { sep = strchr(from, '|'); if (sep) { lua_pushlstring(L, from, sep - from); // opts, patts[, filters], files, file from = sep + 1; } else lua_pushstring(L, from);// opts, patts[, filters], files, file lua_rawseti(L, -2, fi); // opts, patts[, filters], files = { ..., file } } } return 1; } }, { "selectFolderDialog", [](lua_State * L) { luaL_checktype(L, 1, LUA_TTABLE); const char * title = GetStrOrBlank(L, "title"); const char * def_path = GetStrOrBlank(L, "default_path"); return StringResponse(L, tinyfd_selectFolderDialog(title, def_path)); // opts, folder } }, { "colorChooser", [](lua_State * L) { luaL_checktype(L, 1, LUA_TTABLE); lua_settop(L, 1); // opts lua_getfield(L, 1, "out_rgb"); // opts, out const char * title = GetStrOrBlank(L, "title"); // unsigned char rgb[3]; lua_getfield(L, 1, "rgb"); // opts, out, rgb const char * def_hex_rgb = NULL; if (lua_istable(L, 3)) { lua_getfield(L, 3, "r");// opts, out, rgb, r lua_getfield(L, 3, "g");// opts, out, rgb, r, g lua_getfield(L, 3, "b");// opts, out, rgb, r, g, b for (int i = 1; i <= 3; ++i) rgb[i - 1] = (unsigned char)(luaL_checknumber(L, 3 + i) * 255.0); } else def_hex_rgb = luaL_optstring(L, 3, "#000000"); const char * color = tinyfd_colorChooser(title, def_hex_rgb, rgb, rgb); if (color && lua_istable(L, 2)) { for (int i = 0; i < 3; ++i) lua_pushnumber(L, (double)rgb[i] / 255.0); // opts, out, rgb[, r, g, b], rout, gout, bout lua_setfield(L, 2, "b");// opts, out, rgb[, r, g, b], rout, gout lua_setfield(L, 2, "g");// opts, out, rgb[, r, g, b], rout lua_setfield(L, 2, "r");// opts, out, rgb[, r, g, b] } return StringResponse(L, color);// opts, out, rgb[, r, g, b], color } }, { NULL, NULL } }; CORONA_EXPORT int luaopen_plugin_tinyfiledialogs(lua_State* L) { lua_newtable(L);// t luaL_register(L, NULL, tfd_funcs); return 1; }