diff --git a/src/gui/lua/Makefile.am b/src/gui/lua/Makefile.am index f2684a0b0..d0f445f28 100644 --- a/src/gui/lua/Makefile.am +++ b/src/gui/lua/Makefile.am @@ -32,4 +32,5 @@ libneutrino_gui_lua_a_SOURCES = \ luainstance_helpers.cpp \ luainstance.cpp \ lua_configfile.cpp \ + lua_menue.cpp \ lua_video.cpp diff --git a/src/gui/lua/lua_menue.cpp b/src/gui/lua/lua_menue.cpp new file mode 100644 index 000000000..e8cf0337c --- /dev/null +++ b/src/gui/lua/lua_menue.cpp @@ -0,0 +1,562 @@ +/* + * lua menue + * + * (C) 2014 by martii + * (C) 2014-2015 M. Liebmann (micha-bbg) + * (C) 2014 Sven Hoefer (svenhoefer) + * (C) 2015 Jacek Jendrzej (SatBaby) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "luainstance.h" +#include "lua_menue.h" + +CLuaInstMenu* CLuaInstMenu::getInstance() +{ + static CLuaInstMenu* LuaInstMenu = NULL; + + if(!LuaInstMenu) + LuaInstMenu = new CLuaInstMenu(); + return LuaInstMenu; +} + +bool CLuaMenuChangeObserver::changeNotify(lua_State *L, const std::string &luaAction, const std::string &luaId, void *Data) +{ + const char *optionValue = (const char *) Data; + lua_pushglobaltable(L); + lua_getfield(L, -1, luaAction.c_str()); + lua_remove(L, -2); + lua_pushstring(L, luaId.c_str()); + lua_pushstring(L, optionValue); + int status = lua_pcall(L, 2 /* two args */, 1 /* one result */, 0); + if (status) { + fprintf(stderr, "[CLuaMenuChangeObserver::%s:%d] error in script: %s\n", __func__, __LINE__, lua_tostring(L, -1)); + luaL_error(L, " => %s", lua_tostring(L, -1)); + } + double res = lua_isnumber(L, -1) ? lua_tonumber(L, -1) : 0; + return (((int)res == menu_return::RETURN_REPAINT) || ((int)res == menu_return::RETURN_EXIT_REPAINT)); +} + +void CLuaInstMenu::MenuRegister(lua_State *L) +{ + luaL_Reg meth[] = { + { "new", CLuaInstMenu::MenuNew }, + { "addKey", CLuaInstMenu::MenuAddKey }, + { "addItem", CLuaInstMenu::MenuAddItem }, + { "exec", CLuaInstMenu::MenuExec }, + { "hide", CLuaInstMenu::MenuHide }, + { "setActive", CLuaInstMenu::MenuSetActive }, + { "setName", CLuaInstMenu::MenuSetName }, + { "__gc", CLuaInstMenu::MenuDelete }, + { NULL, NULL } + }; + + luaL_newmetatable(L, "menu"); + luaL_setfuncs(L, meth, 0); + lua_pushvalue(L, -1); + lua_setfield(L, -1, "__index"); + lua_setglobal(L, "menu"); + + // keep misspelled "menue" for backwards-compatibility + luaL_newmetatable(L, "menu"); + luaL_setfuncs(L, meth, 0); + lua_pushvalue(L, -1); + lua_setfield(L, -1, "__index"); + lua_setglobal(L, "menue"); +} + +CLuaMenu *CLuaInstMenu::MenuCheck(lua_State *L, int n) +{ + return *(CLuaMenu **) luaL_checkudata(L, n, "menu"); +} + +CLuaMenu::CLuaMenu() +{ + m = NULL; + observ = new CLuaMenuChangeObserver(); +} + +CLuaMenu::~CLuaMenu() +{ + itemmap.clear(); + delete m; + delete observ; +} + +CLuaMenuForwarder::CLuaMenuForwarder(lua_State *_L, std::string _luaAction, std::string _luaId) +{ + Init(_L, _luaAction, _luaId); +} + +void CLuaMenuForwarder::Init(lua_State *_L, std::string _luaAction, std::string _luaId) +{ + L = _L; + luaAction = _luaAction; + luaId = _luaId; +} + +CLuaMenuForwarder::~CLuaMenuForwarder() +{ +} + +int CLuaMenuForwarder::exec(CMenuTarget* /*parent*/, const std::string & /*actionKey*/) +{ + int res = menu_return::RETURN_REPAINT; + if (!luaAction.empty()) { + lua_pushglobaltable(L); + lua_getfield(L, -1, luaAction.c_str()); + lua_remove(L, -2); + lua_pushstring(L, luaId.c_str()); + int status = lua_pcall(L, 1 /* one arg */, 1 /* one result */, 0); + if (status) { + fprintf(stderr, "[CLuaMenuForwarder::%s:%d] error in script: %s\n", __func__, __LINE__, lua_tostring(L, -1)); + luaL_error(L, " => %s", lua_tostring(L, -1)); + } + if (lua_isnumber(L, -1)) + res = (int) lua_tonumber(L, -1); + lua_pop(L, 1); + } + return res; +} + +CLuaMenuFilebrowser::CLuaMenuFilebrowser(lua_State *_L, std::string _luaAction, std::string _luaId, std::string *_value, bool _dirMode) : CLuaMenuForwarder(_L, _luaAction, _luaId) +{ + Init(_value, _dirMode); +} + +void CLuaMenuFilebrowser::Init(std::string *_value, bool _dirMode) +{ + value = _value; + dirMode = _dirMode; +} + +int CLuaMenuFilebrowser::exec(CMenuTarget* /*parent*/, const std::string& /*actionKey*/) +{ + CFileBrowser fileBrowser; + fileBrowser.Dir_Mode = dirMode; + + CFileFilter fileFilter; + for (std::vector::iterator it = filter.begin(); it != filter.end(); ++it) + fileFilter.addFilter(*it); + if (!filter.empty()) + fileBrowser.Filter = &fileFilter; + + if (fileBrowser.exec(value->c_str()) == true) + *value = fileBrowser.getSelectedFile()->Name; + + if (!luaAction.empty()) { + lua_pushglobaltable(L); + lua_getfield(L, -1, luaAction.c_str()); + lua_remove(L, -2); + lua_pushstring(L, value->c_str()); + int status = lua_pcall(L, 1 /* one arg */, 1 /* one result */, 0); + if (status) { + fprintf(stderr, "[CLuaMenuFilebrowser::%s:%d] error in script: %s\n", __func__, __LINE__, lua_tostring(L, -1)); + luaL_error(L, " => %s", lua_tostring(L, -1)); + } + lua_pop(L, 1); + } + return menu_return::RETURN_REPAINT; +} + +CLuaMenuStringinput::CLuaMenuStringinput(lua_State *_L, std::string _luaAction, std::string _luaId, const char *_name, std::string *_value, int _size, std::string _valid_chars, CChangeObserver *_observ, const char *_icon, bool _sms) : CLuaMenuForwarder(_L, _luaAction, _luaId) +{ + Init(_name, _value, _size, _valid_chars, _observ, _icon, _sms); +} + +void CLuaMenuStringinput::Init(const char *_name, std::string *_value, int _size, std::string _valid_chars, CChangeObserver *_observ, const char *_icon, bool _sms) +{ + name = _name; + value = _value; + size = _size; + valid_chars = _valid_chars; + icon = _icon; + observ = _observ; + sms = _sms; +} + +int CLuaMenuStringinput::exec(CMenuTarget* /*parent*/, const std::string & /*actionKey*/) +{ + CStringInput *i; + if (sms) + i = new CStringInputSMS((char *)name, value, size, + NONEXISTANT_LOCALE, NONEXISTANT_LOCALE, valid_chars.c_str(), observ, icon); + else + i = new CStringInput((char *)name, value, size, + NONEXISTANT_LOCALE, NONEXISTANT_LOCALE, valid_chars.c_str(), observ, icon); + i->exec(NULL, ""); + delete i; + if (!luaAction.empty()) { + lua_pushglobaltable(L); + lua_getfield(L, -1, luaAction.c_str()); + lua_remove(L, -2); + lua_pushstring(L, luaId.c_str()); + lua_pushstring(L, value->c_str()); + int status = lua_pcall(L, 2 /* two arg */, 1 /* one result */, 0); + if (status) { + fprintf(stderr, "[CLuaMenuStringinput::%s:%d] error in script: %s\n", __func__, __LINE__, lua_tostring(L, -1)); + luaL_error(L, " => %s", lua_tostring(L, -1)); + } + lua_pop(L, 2); + } + return menu_return::RETURN_REPAINT; +} + +CLuaMenuKeyboardinput::CLuaMenuKeyboardinput(lua_State *_L, std::string _luaAction, std::string _luaId, const char *_name, std::string *_value, int _size, CChangeObserver *_observ, const char *_icon, std::string _help, std::string _help2) : CLuaMenuForwarder(_L, _luaAction, _luaId) +{ + Init(_name, _value, _size, _observ, _icon, _help, _help2); +} + +void CLuaMenuKeyboardinput::Init(const char *_name, std::string *_value, int _size, CChangeObserver *_observ, const char *_icon, std::string _help, std::string _help2) +{ + name = _name; + value = _value; + size = _size; + icon = _icon; + observ = _observ; + help = _help; + help2 = _help2; +} + +int CLuaMenuKeyboardinput::exec(CMenuTarget* /*parent*/, const std::string & /*actionKey*/) +{ + CKeyboardInput *i; + i = new CKeyboardInput((char *)name, value, size, observ, icon, help, help2); + i->exec(NULL, ""); + delete i; + if (!luaAction.empty()) { + lua_pushglobaltable(L); + lua_getfield(L, -1, luaAction.c_str()); + lua_remove(L, -2); + lua_pushstring(L, luaId.c_str()); + lua_pushstring(L, value->c_str()); + int status = lua_pcall(L, 2 /* two arg */, 1 /* one result */, 0); + if (status) { + fprintf(stderr, "[CLuaMenuKeyboardinput::%s:%d] error in script: %s\n", __func__, __LINE__, lua_tostring(L, -1)); + luaL_error(L, " => %s", lua_tostring(L, -1)); + } + lua_pop(L, 2); + } + return menu_return::RETURN_REPAINT; +} + +int CLuaInstMenu::MenuNew(lua_State *L) +{ + CMenuWidget *m; + + if (lua_istable(L, 1)) { + std::string name; tableLookup(L, "name", name) || tableLookup(L, "title", name); + std::string icon; tableLookup(L, "icon", icon); + lua_Integer mwidth; + if (tableLookup(L, "mwidth", mwidth)) + m = new CMenuWidget(name.c_str(), icon.c_str(), mwidth); + else + m = new CMenuWidget(name.c_str(), icon.c_str()); + } else + m = new CMenuWidget(); + + CLuaMenu **udata = (CLuaMenu **) lua_newuserdata(L, sizeof(CLuaMenu *)); + *udata = new CLuaMenu(); + (*udata)->m = m; + luaL_getmetatable(L, "menu"); + lua_setmetatable(L, -2); + return 1; +} + +int CLuaInstMenu::MenuAddKey(lua_State *L) +{ + CLuaMenu *m = MenuCheck(L, 1); + if (!m) + return 0; + lua_assert(lua_istable(L, 2)); + + std::string action; tableLookup(L, "action", action); + std::string id; tableLookup(L, "id", id); + lua_Unsigned directkey = CRCInput::RC_nokey; tableLookup(L, "directkey", directkey); + if ((!action.empty()) && (directkey != CRCInput::RC_nokey)) { + CLuaMenuForwarder *forwarder = new CLuaMenuForwarder(L, action, id); + m->m->addKey(directkey, forwarder, action); + m->targets.push_back(forwarder); + } + return 0; +} + +int CLuaInstMenu::MenuAddItem(lua_State *L) +{ + CLuaMenu *m = MenuCheck(L, 1); + if (!m) { + lua_pushnil(L); + return 1; + } + lua_assert(lua_istable(L, 2)); + + CMenuItem *mi = NULL; + CLuaMenuItem i; + m->items.push_back(i); + CLuaMenuItem *b = &m->items.back(); + + tableLookup(L, "name", b->name); + std::string type; tableLookup(L, "type", type); + if (type == "back") { + m->m->addItem(GenericMenuBack); + } else if (type == "next") { + m->m->addItem(GenericMenuNext); + } else if (type == "cancel") { + m->m->addItem(GenericMenuCancel); + } else if (type == "separator") { + m->m->addItem(GenericMenuSeparator); + } else if ((type == "separatorline") || (type == "subhead")) { + if (!b->name.empty()) { + int flag = (type == "separatorline") ? CMenuSeparator::LINE : CMenuSeparator::SUB_HEAD; + m->m->addItem(new CMenuSeparator(CMenuSeparator::STRING | flag, b->name.c_str(), NONEXISTANT_LOCALE)); + } else + m->m->addItem(GenericMenuSeparatorLine); + } else { + std::string right_icon_str; tableLookup(L, "right_icon", right_icon_str); + std::string action; tableLookup(L, "action", action); + std::string value; tableLookup(L, "value", value); + std::string hint; tableLookup(L, "hint", hint); + std::string hint_icon_str; tableLookup(L, "hint_icon", hint_icon_str); + std::string icon_str; tableLookup(L, "icon", icon_str); + std::string id; tableLookup(L, "id", id); + std::string tmp; + char *right_icon = NULL; + if (!right_icon_str.empty()) { + right_icon = strdup(right_icon_str.c_str()); + m->tofree.push_back(right_icon); + } + char *hint_icon = NULL; + if (!hint_icon_str.empty()) { + hint_icon = strdup(hint_icon_str.c_str()); + m->tofree.push_back(hint_icon); + } + char *icon = NULL; + if (!icon_str.empty()) { + icon = strdup(icon_str.c_str()); + m->tofree.push_back(icon); + } + + lua_Unsigned directkey = CRCInput::RC_nokey; tableLookup(L, "directkey", directkey); + lua_Integer pulldown = false; tableLookup(L, "pulldown", pulldown); + + bool enabled = true; + if (!(tableLookup(L, "enabled", enabled) || tableLookup(L, "active", enabled))) { + tmp = "true"; + if (tableLookup(L, "enabled", tmp) || tableLookup(L, "active", tmp)) + paramBoolDeprecated(L, tmp.c_str()); + enabled = (tmp == "true" || tmp == "1" || tmp == "yes"); + } + + tableLookup(L, "range", tmp); + int range_from = 0, range_to = 99; + sscanf(tmp.c_str(), "%d,%d", &range_from, &range_to); + + if (type == "forwarder") { + b->str_val = value; + CLuaMenuForwarder *forwarder = new CLuaMenuForwarder(L, action, id); + mi = new CMenuForwarder(b->name, enabled, b->str_val, forwarder, NULL/*ActionKey*/, directkey, icon, right_icon); + if (!hint.empty() || hint_icon) + mi->setHint(hint_icon, hint); + m->targets.push_back(forwarder); + } else if (type == "chooser") { + int options_count = 0; + lua_pushstring(L, "options"); + lua_gettable(L, -2); + if (lua_istable(L, -1)) + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 2)) { + lua_pushvalue(L, -2); + options_count++; + } + lua_pop(L, 1); + if (options_count == 0) { + m->m->addItem(new CMenuSeparator(CMenuSeparator::STRING | CMenuSeparator::LINE, "ERROR! (options_count)", NONEXISTANT_LOCALE)); + lua_pushnil(L); + return 1; + } + + CMenuOptionChooser::keyval_ext *kext = (CMenuOptionChooser::keyval_ext *)calloc(options_count, sizeof(CMenuOptionChooser::keyval_ext)); + m->tofree.push_back(kext); + lua_pushstring(L, "options"); + lua_gettable(L, -2); + b->int_val = 0; + if (lua_istable(L, -1)) { + int j = 0; + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 2)) { + lua_pushvalue(L, -2); + const char *key = lua_tostring(L, -1); + const char *val = lua_tostring(L, -2); + kext[j].key = atoi(key); + kext[j].value = NONEXISTANT_LOCALE; + kext[j].valname = strdup(val); + m->tofree.push_back((void *)kext[j].valname); + if (!strcmp(value.c_str(), kext[j].valname)) + b->int_val = kext[j].key; + j++; + } + } + lua_pop(L, 1); + mi = new CMenuOptionChooser(b->name.c_str(), &b->int_val, kext, options_count, enabled, m->observ, directkey, icon, pulldown); + } else if (type == "numeric") { + b->int_val = range_from; + sscanf(value.c_str(), "%d", &b->int_val); + mi = new CMenuOptionNumberChooser(b->name, &b->int_val, enabled, range_from, range_to, m->observ, 0, 0, NONEXISTANT_LOCALE, pulldown); + } else if (type == "string") { + b->str_val = value; + mi = new CMenuOptionStringChooser(b->name.c_str(), &b->str_val, enabled, m->observ, directkey, icon, pulldown); + } else if (type == "stringinput") { + b->str_val = value; + std::string valid_chars = "abcdefghijklmnopqrstuvwxyz0123456789!\"§$%&/()=?-. "; + tableLookup(L, "valid_chars", valid_chars); + lua_Integer sms = 0; tableLookup(L, "sms", sms); + lua_Integer size = 30; tableLookup(L, "size", size); + CLuaMenuStringinput *stringinput = new CLuaMenuStringinput(L, action, id, b->name.c_str(), &b->str_val, size, valid_chars, m->observ, icon, sms); + mi = new CMenuForwarder(b->name, enabled, b->str_val, stringinput, NULL/*ActionKey*/, directkey, icon, right_icon); + m->targets.push_back(stringinput); + } else if (type == "keyboardinput") { + b->str_val = value; + lua_Integer size = 0; tableLookup(L, "size", size); + std::string help = ""; tableLookup(L, "help", help); + std::string help2 = ""; tableLookup(L, "help2", help2); + CLuaMenuKeyboardinput *keyboardinput = new CLuaMenuKeyboardinput(L, action, id, b->name.c_str(), &b->str_val, size, m->observ, icon, help, help2); + mi = new CMenuForwarder(b->name, enabled, b->str_val, keyboardinput, NULL/*ActionKey*/, directkey, icon, right_icon); + m->targets.push_back(keyboardinput); + } else if (type == "filebrowser") { + b->str_val = value; + lua_Integer dirMode = 0; tableLookup(L, "dir_mode", dirMode); + CLuaMenuFilebrowser *filebrowser = new CLuaMenuFilebrowser(L, action, id, &b->str_val, dirMode); + lua_pushstring(L, "filter"); + lua_gettable(L, -2); + if (lua_istable(L, -1)) + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 2)) { + lua_pushvalue(L, -2); + const char *val = lua_tostring(L, -2); + filebrowser->addFilter(val); + } + lua_pop(L, 1); + + mi = new CMenuForwarder(b->name, enabled, b->str_val, filebrowser, NULL/*ActionKey*/, directkey, icon, right_icon); + m->targets.push_back(filebrowser); + } + if (mi) { + mi->setLua(L, action, id); + if (!hint.empty() || hint_icon) + mi->setHint(hint_icon, hint); + m->m->addItem(mi); + } + } + + if (mi) { + lua_Integer id = m->itemmap.size() + 1; + m->itemmap.insert(itemmap_pair_t(id, mi)); + lua_pushinteger(L, id); + } else + lua_pushnil(L); + + return 1; +} + +int CLuaInstMenu::MenuExec(lua_State *L) +{ + CLuaMenu *m = MenuCheck(L, 1); + if (!m) + return 0; + m->m->exec(NULL, ""); + m->m->hide(); + return 0; +} + +int CLuaInstMenu::MenuHide(lua_State *L) +{ + CLuaMenu *m = MenuCheck(L, 1); + if (!m) + return 0; + m->m->hide(); + return 0; +} + +int CLuaInstMenu::MenuSetActive(lua_State *L) +{ + CLuaMenu *m = MenuCheck(L, 1); + if (!m) + return 0; + lua_assert(lua_istable(L, 2)); + + lua_Integer id; tableLookup(L, "item", id); + bool activ; tableLookup(L, "activ", activ); + + CMenuItem* item = NULL; + for (itemmap_iterator_t it = m->itemmap.begin(); it != m->itemmap.end(); ++it) { + if (it->first == id) { + item = it->second; + break; + } + } + if (item) + item->setActive(activ); + return 0; +} + +int CLuaInstMenu::MenuSetName(lua_State *L) +{ + CLuaMenu *m = MenuCheck(L, 1); + if (!m) + return 0; + lua_assert(lua_istable(L, 2)); + + lua_Integer id; tableLookup(L, "item", id); + std::string name; tableLookup(L, "name", name); + + CMenuItem* item = NULL; + for (itemmap_iterator_t it = m->itemmap.begin(); it != m->itemmap.end(); ++it) { + if (it->first == id) { + item = it->second; + break; + } + } + if (item) + item->setName(name); + return 0; +} + +int CLuaInstMenu::MenuDelete(lua_State *L) +{ + CLuaMenu *m = MenuCheck(L, 1); + if (!m) + return 0; + + while (!m->targets.empty()) { + delete m->targets.back(); + m->targets.pop_back(); + } + while (!m->tofree.empty()) { + free(m->tofree.back()); + m->tofree.pop_back(); + } + + delete m; + return 0; +} diff --git a/src/gui/lua/lua_menue.h b/src/gui/lua/lua_menue.h new file mode 100644 index 000000000..7bee51603 --- /dev/null +++ b/src/gui/lua/lua_menue.h @@ -0,0 +1,132 @@ +/* + * lua menue + * + * (C) 2014 by martii + * (C) 2014-2015 M. Liebmann (micha-bbg) + * (C) 2014 Sven Hoefer (svenhoefer) + * (C) 2015 Jacek Jendrzej (SatBaby) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _LUAMENUE_H +#define _LUAMENUE_H + +struct CLuaMenuItem { + int int_val; + std::string str_val; + std::string name; +}; + +class CLuaMenuChangeObserver : public CChangeObserver +{ + public: + bool changeNotify(lua_State *, const std::string &, const std::string &, void *); +}; + +typedef std::pair itemmap_pair_t; +typedef std::map itemmap_t; +typedef itemmap_t::iterator itemmap_iterator_t; + +class CLuaMenu +{ + public: + CMenuWidget *m; + CLuaMenuChangeObserver *observ; + std::list items; + std::list targets; + std::list tofree; + itemmap_t itemmap; + CLuaMenu(); + ~CLuaMenu(); +}; + +class CLuaMenuForwarder : public CMenuTarget +{ + private: + void Init(lua_State *_L, std::string _luaAction, std::string _luaId); + public: + lua_State *L; + std::string luaAction; + std::string luaId; + CLuaMenuForwarder(lua_State *L, std::string _luaAction, std::string _luaId); + ~CLuaMenuForwarder(); + int exec(CMenuTarget* parent, const std::string & actionKey); +}; + +class CLuaMenuFilebrowser : public CLuaMenuForwarder +{ + private: + std::string *value; + bool dirMode; + std::vector filter; + void Init(std::string *_value, bool _dirMode); + public: + CLuaMenuFilebrowser(lua_State *_L, std::string _luaAction, std::string _luaId, std::string *_value, bool _dirMode); + int exec(CMenuTarget* parent, const std::string & actionKey); + void addFilter(std::string s) { filter.push_back(s); }; +}; + +class CLuaMenuStringinput : public CLuaMenuForwarder +{ + private: + std::string *value; + std::string valid_chars; + const char *name; + const char *icon; + bool sms; + int size; + CChangeObserver *observ; + void Init(const char *_name, std::string *_value, int _size, std::string _valid_chars, CChangeObserver *_observ, const char *_icon, bool _sms); + public: + CLuaMenuStringinput(lua_State *_L, std::string _luaAction, std::string _luaId, const char *_name, std::string *_value, int _size, std::string _valid_chars, CChangeObserver *_observ, const char *_icon, bool _sms); + int exec(CMenuTarget* parent, const std::string & actionKey); +}; + +class CLuaMenuKeyboardinput : public CLuaMenuForwarder +{ + private: + std::string *value; + const char *name; + const char *icon; + int size; + CChangeObserver *observ; + std::string help, help2; + void Init(const char *_name, std::string *_value, int _size, CChangeObserver *_observ, const char *_icon, std::string _help, std::string _help2); + public: + CLuaMenuKeyboardinput(lua_State *_L, std::string _luaAction, std::string _luaId, const char *_name, std::string *_value, int _size, CChangeObserver *_observ, const char *_icon, std::string _help, std::string _help2); + int exec(CMenuTarget* parent, const std::string & actionKey); +}; + +class CLuaInstMenu +{ + public: + CLuaInstMenu() {}; + ~CLuaInstMenu() {}; + static CLuaInstMenu* getInstance(); + static void MenuRegister(lua_State *L); + + private: + static CLuaMenu *MenuCheck(lua_State *L, int n); + static int MenuNew(lua_State *L); + static int MenuAddKey(lua_State *L); + static int MenuAddItem(lua_State *L); + static int MenuExec(lua_State *L); + static int MenuHide(lua_State *L); + static int MenuSetActive(lua_State *L); + static int MenuSetName(lua_State *L); + static int MenuDelete(lua_State *L); +}; + +#endif //_LUAMENUE_H diff --git a/src/gui/lua/luainstance.cpp b/src/gui/lua/luainstance.cpp index 22ac38fb9..bc44af0b2 100644 --- a/src/gui/lua/luainstance.cpp +++ b/src/gui/lua/luainstance.cpp @@ -29,8 +29,6 @@ #include #include #include -#include -#include #include #include #include @@ -40,6 +38,7 @@ #include "luainstance.h" #include "lua_configfile.h" +#include "lua_menue.h" #include "lua_video.h" static void set_lua_variables(lua_State *L) @@ -538,7 +537,7 @@ void CLuaInstance::registerFunctions() lua_pop(lua, 1); lua_register(lua, className, NewWindow); - MenuRegister(lua); + HintboxRegister(lua); MessageboxRegister(lua); CWindowRegister(lua); @@ -546,6 +545,7 @@ void CLuaInstance::registerFunctions() SignalBoxRegister(lua); CPictureRegister(lua); CLuaInstConfigFile::getInstance()->LuaConfigFileRegister(lua); + CLuaInstMenu::getInstance()->MenuRegister(lua); } CLuaData *CLuaInstance::CheckData(lua_State *L, int narg) @@ -1140,482 +1140,6 @@ int CLuaInstance::runScriptExt(lua_State *L) return 0; } -bool CLuaMenuChangeObserver::changeNotify(lua_State *L, const std::string &luaAction, const std::string &luaId, void *Data) -{ - const char *optionValue = (const char *) Data; - lua_pushglobaltable(L); - lua_getfield(L, -1, luaAction.c_str()); - lua_remove(L, -2); - lua_pushstring(L, luaId.c_str()); - lua_pushstring(L, optionValue); - int status = lua_pcall(L, 2 /* two args */, 1 /* one result */, 0); - if (status) { - fprintf(stderr, "[CLuaMenuChangeObserver::%s:%d] error in script: %s\n", __func__, __LINE__, lua_tostring(L, -1)); - luaL_error(L, " => %s", lua_tostring(L, -1)); - } - double res = lua_isnumber(L, -1) ? lua_tonumber(L, -1) : 0; - return (((int)res == menu_return::RETURN_REPAINT) || ((int)res == menu_return::RETURN_EXIT_REPAINT)); -} - -void CLuaInstance::MenuRegister(lua_State *L) -{ - luaL_Reg meth[] = { - { "new", CLuaInstance::MenuNew }, - { "addKey", CLuaInstance::MenuAddKey }, - { "addItem", CLuaInstance::MenuAddItem }, - { "exec", CLuaInstance::MenuExec }, - { "hide", CLuaInstance::MenuHide }, - { "setActive", CLuaInstance::MenuSetActive }, - { "__gc", CLuaInstance::MenuDelete }, - { NULL, NULL } - }; - - luaL_newmetatable(L, "menu"); - luaL_setfuncs(L, meth, 0); - lua_pushvalue(L, -1); - lua_setfield(L, -1, "__index"); - lua_setglobal(L, "menu"); - - // keep misspelled "menue" for backwards-compatibility - luaL_newmetatable(L, "menu"); - luaL_setfuncs(L, meth, 0); - lua_pushvalue(L, -1); - lua_setfield(L, -1, "__index"); - lua_setglobal(L, "menue"); -} - -CLuaMenu *CLuaInstance::MenuCheck(lua_State *L, int n) -{ - return *(CLuaMenu **) luaL_checkudata(L, n, "menu"); -} - -CLuaMenu::CLuaMenu() -{ - m = NULL; - observ = new CLuaMenuChangeObserver(); -} - -CLuaMenu::~CLuaMenu() -{ - itemmap.clear(); - delete m; - delete observ; -} - -CLuaMenuForwarder::CLuaMenuForwarder(lua_State *_L, std::string _luaAction, std::string _luaId) -{ - L = _L; - luaAction = _luaAction; - luaId = _luaId; -} - -CLuaMenuForwarder::~CLuaMenuForwarder() -{ -} - -int CLuaMenuForwarder::exec(CMenuTarget* /*parent*/, const std::string & /*actionKey*/) -{ - int res = menu_return::RETURN_REPAINT; - if (!luaAction.empty()){ - lua_pushglobaltable(L); - lua_getfield(L, -1, luaAction.c_str()); - lua_remove(L, -2); - lua_pushstring(L, luaId.c_str()); - int status = lua_pcall(L, 1 /* one arg */, 1 /* one result */, 0); - if (status) { - fprintf(stderr, "[CLuaMenuForwarder::%s:%d] error in script: %s\n", __func__, __LINE__, lua_tostring(L, -1)); - luaL_error(L, " => %s", lua_tostring(L, -1)); - } - if (lua_isnumber(L, -1)) - res = (int) lua_tonumber(L, -1); - lua_pop(L, 1); - } - return res; -} - -CLuaMenuFilebrowser::CLuaMenuFilebrowser(lua_State *_L, std::string _luaAction, std::string _luaId, std::string *_value, bool _dirMode) : CLuaMenuForwarder(_L, _luaAction, _luaId) -{ - value = _value; - dirMode = _dirMode; -} - -int CLuaMenuFilebrowser::exec(CMenuTarget* /*parent*/, const std::string& /*actionKey*/) -{ - CFileBrowser fileBrowser; - fileBrowser.Dir_Mode = dirMode; - - CFileFilter fileFilter; - for (std::vector::iterator it = filter.begin(); it != filter.end(); ++it) - fileFilter.addFilter(*it); - if (!filter.empty()) - fileBrowser.Filter = &fileFilter; - - if (fileBrowser.exec(value->c_str()) == true) - *value = fileBrowser.getSelectedFile()->Name; - - if (!luaAction.empty()){ - lua_pushglobaltable(L); - lua_getfield(L, -1, luaAction.c_str()); - lua_remove(L, -2); - lua_pushstring(L, value->c_str()); - int status = lua_pcall(L, 1 /* one arg */, 1 /* one result */, 0); - if (status) { - fprintf(stderr, "[CLuaMenuFilebrowser::%s:%d] error in script: %s\n", __func__, __LINE__, lua_tostring(L, -1)); - luaL_error(L, " => %s", lua_tostring(L, -1)); - } - lua_pop(L, 1); - } - return menu_return::RETURN_REPAINT; -} - -CLuaMenuStringinput::CLuaMenuStringinput(lua_State *_L, std::string _luaAction, std::string _luaId, const char *_name, std::string *_value, int _size, std::string _valid_chars, CChangeObserver *_observ, const char *_icon, bool _sms) : CLuaMenuForwarder(_L, _luaAction, _luaId) -{ - name = _name; - value = _value; - size = _size; - valid_chars = _valid_chars; - icon = _icon; - observ = _observ; - sms = _sms; -} - -int CLuaMenuStringinput::exec(CMenuTarget* /*parent*/, const std::string & /*actionKey*/) -{ - CStringInput *i; - if (sms) - i = new CStringInputSMS((char *)name, value, size, - NONEXISTANT_LOCALE, NONEXISTANT_LOCALE, valid_chars.c_str(), observ, icon); - else - i = new CStringInput((char *)name, value, size, - NONEXISTANT_LOCALE, NONEXISTANT_LOCALE, valid_chars.c_str(), observ, icon); - i->exec(NULL, ""); - delete i; - if (!luaAction.empty()){ - lua_pushglobaltable(L); - lua_getfield(L, -1, luaAction.c_str()); - lua_remove(L, -2); - lua_pushstring(L, luaId.c_str()); - lua_pushstring(L, value->c_str()); - int status = lua_pcall(L, 2 /* two arg */, 1 /* one result */, 0); - if (status) { - fprintf(stderr, "[CLuaMenuStringinput::%s:%d] error in script: %s\n", __func__, __LINE__, lua_tostring(L, -1)); - luaL_error(L, " => %s", lua_tostring(L, -1)); - } - lua_pop(L, 2); - } - return menu_return::RETURN_REPAINT; -} - -CLuaMenuKeyboardinput::CLuaMenuKeyboardinput(lua_State *_L, std::string _luaAction, std::string _luaId, const char *_name, std::string *_value, int _size, CChangeObserver *_observ, const char *_icon, std::string _help, std::string _help2) : CLuaMenuForwarder(_L, _luaAction, _luaId) -{ - name = _name; - value = _value; - size = _size; - icon = _icon; - observ = _observ; - help = _help; - help2 = _help2; -} - -int CLuaMenuKeyboardinput::exec(CMenuTarget* /*parent*/, const std::string & /*actionKey*/) -{ - CKeyboardInput *i; - i = new CKeyboardInput((char *)name, value, size, observ, icon, help, help2); - i->exec(NULL, ""); - delete i; - if (!luaAction.empty()){ - lua_pushglobaltable(L); - lua_getfield(L, -1, luaAction.c_str()); - lua_remove(L, -2); - lua_pushstring(L, luaId.c_str()); - lua_pushstring(L, value->c_str()); - int status = lua_pcall(L, 2 /* two arg */, 1 /* one result */, 0); - if (status) { - fprintf(stderr, "[CLuaMenuKeyboardinput::%s:%d] error in script: %s\n", __func__, __LINE__, lua_tostring(L, -1)); - luaL_error(L, " => %s", lua_tostring(L, -1)); - } - lua_pop(L, 2); - } - return menu_return::RETURN_REPAINT; -} - -int CLuaInstance::MenuNew(lua_State *L) -{ - CMenuWidget *m; - - if (lua_istable(L, 1)) { - std::string name, icon; - tableLookup(L, "name", name) || tableLookup(L, "title", name); - tableLookup(L, "icon", icon); - lua_Integer mwidth; - if(tableLookup(L, "mwidth", mwidth)) - m = new CMenuWidget(name.c_str(), icon.c_str(), mwidth); - else - m = new CMenuWidget(name.c_str(), icon.c_str()); - } else - m = new CMenuWidget(); - - CLuaMenu **udata = (CLuaMenu **) lua_newuserdata(L, sizeof(CLuaMenu *)); - *udata = new CLuaMenu(); - (*udata)->m = m; - luaL_getmetatable(L, "menu"); - lua_setmetatable(L, -2); - return 1; -} - -int CLuaInstance::MenuDelete(lua_State *L) -{ - CLuaMenu *m = MenuCheck(L, 1); - if (!m) - return 0; - - while(!m->targets.empty()) { - delete m->targets.back(); - m->targets.pop_back(); - } - while(!m->tofree.empty()) { - free(m->tofree.back()); - m->tofree.pop_back(); - } - - delete m; - return 0; -} - -int CLuaInstance::MenuAddKey(lua_State *L) -{ - CLuaMenu *m = MenuCheck(L, 1); - if (!m) - return 0; - lua_assert(lua_istable(L, 2)); - - std::string action; tableLookup(L, "action", action); - std::string id; tableLookup(L, "id", id); - lua_Unsigned directkey = CRCInput::RC_nokey; tableLookup(L, "directkey", directkey); - if ((!action.empty()) && (directkey != CRCInput::RC_nokey)) { - CLuaMenuForwarder *forwarder = new CLuaMenuForwarder(L, action, id); - m->m->addKey(directkey, forwarder, action); - m->targets.push_back(forwarder); - } - return 0; -} - -int CLuaInstance::MenuSetActive(lua_State *L) -{ - CLuaMenu *m = MenuCheck(L, 1); - if (!m) - return 0; - lua_assert(lua_istable(L, 2)); - - lua_Integer id; tableLookup(L, "item", id); - bool activ; tableLookup(L, "activ", activ); - - CMenuItem* item = NULL; - for (itemmap_iterator_t it = m->itemmap.begin(); it != m->itemmap.end(); ++it) { - if (it->first == id) { - item = it->second; - break; - } - } - if (item) - item->setActive(activ); - return 0; -} - -int CLuaInstance::MenuAddItem(lua_State *L) -{ - CLuaMenu *m = MenuCheck(L, 1); - if (!m) { - lua_pushnil(L); - return 1; - } - lua_assert(lua_istable(L, 2)); - - CMenuItem *mi = NULL; - CLuaMenuItem i; - m->items.push_back(i); - CLuaMenuItem *b = &m->items.back(); - - tableLookup(L, "name", b->name); - std::string type; tableLookup(L, "type", type); - if (type == "back") { - m->m->addItem(GenericMenuBack); - } else if (type == "next") { - m->m->addItem(GenericMenuNext); - } else if (type == "cancel") { - m->m->addItem(GenericMenuCancel); - } else if (type == "separator") { - m->m->addItem(GenericMenuSeparator); - } else if ((type == "separatorline") || (type == "subhead")) { - if (!b->name.empty()) { - int flag = (type == "separatorline") ? CMenuSeparator::LINE : CMenuSeparator::SUB_HEAD; - m->m->addItem(new CMenuSeparator(CMenuSeparator::STRING | flag, b->name.c_str(), NONEXISTANT_LOCALE)); - } else - m->m->addItem(GenericMenuSeparatorLine); - } else { - std::string right_icon_str; tableLookup(L, "right_icon", right_icon_str); - std::string action; tableLookup(L, "action", action); - std::string value; tableLookup(L, "value", value); - std::string hint; tableLookup(L, "hint", hint); - std::string hint_icon_str; tableLookup(L, "hint_icon", hint_icon_str); - std::string icon_str; tableLookup(L, "icon", icon_str); - std::string id; tableLookup(L, "id", id); - std::string tmp; - char *right_icon = NULL; - if (!right_icon_str.empty()) { - right_icon = strdup(right_icon_str.c_str()); - m->tofree.push_back(right_icon); - } - char *hint_icon = NULL; - if (!hint_icon_str.empty()) { - hint_icon = strdup(hint_icon_str.c_str()); - m->tofree.push_back(hint_icon); - } - char *icon = NULL; - if (!icon_str.empty()) { - icon = strdup(icon_str.c_str()); - m->tofree.push_back(icon); - } - - lua_Unsigned directkey = CRCInput::RC_nokey; tableLookup(L, "directkey", directkey); - lua_Integer pulldown = false; tableLookup(L, "pulldown", pulldown); - - bool enabled = true; - if (!(tableLookup(L, "enabled", enabled) || tableLookup(L, "active", enabled))) - { - tmp = "true"; - if (tableLookup(L, "enabled", tmp) || tableLookup(L, "active", tmp)) - paramBoolDeprecated(L, tmp.c_str()); - enabled = (tmp == "true" || tmp == "1" || tmp == "yes"); - } - - tableLookup(L, "range", tmp); - int range_from = 0, range_to = 99; - sscanf(tmp.c_str(), "%d,%d", &range_from, &range_to); - - if (type == "forwarder") { - b->str_val = value; - CLuaMenuForwarder *forwarder = new CLuaMenuForwarder(L, action, id); - mi = new CMenuForwarder(b->name, enabled, b->str_val, forwarder, NULL/*ActionKey*/, directkey, icon, right_icon); - if (!hint.empty() || hint_icon) - mi->setHint(hint_icon, hint); - m->targets.push_back(forwarder); - } else if (type == "chooser") { - int options_count = 0; - lua_pushstring(L, "options"); - lua_gettable(L, -2); - if (lua_istable(L, -1)) - for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 2)) { - lua_pushvalue(L, -2); - options_count++; - } - lua_pop(L, 1); - if (options_count == 0) { - m->m->addItem(new CMenuSeparator(CMenuSeparator::STRING | CMenuSeparator::LINE, "ERROR! (options_count)", NONEXISTANT_LOCALE)); - lua_pushnil(L); - return 1; - } - - CMenuOptionChooser::keyval_ext *kext = (CMenuOptionChooser::keyval_ext *)calloc(options_count, sizeof(CMenuOptionChooser::keyval_ext)); - m->tofree.push_back(kext); - lua_pushstring(L, "options"); - lua_gettable(L, -2); - b->int_val = 0; - int j = 0; - if (lua_istable(L, -1)) - for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 2)) { - lua_pushvalue(L, -2); - const char *key = lua_tostring(L, -1); - const char *val = lua_tostring(L, -2); - kext[j].key = atoi(key); - kext[j].value = NONEXISTANT_LOCALE; - kext[j].valname = strdup(val); - m->tofree.push_back((void *)kext[j].valname); - if (!strcmp(value.c_str(), kext[j].valname)) - b->int_val = kext[j].key; - j++; - } - lua_pop(L, 1); - mi = new CMenuOptionChooser(b->name.c_str(), &b->int_val, kext, options_count, enabled, m->observ, directkey, icon, pulldown); - } else if (type == "numeric") { - b->int_val = range_from; - sscanf(value.c_str(), "%d", &b->int_val); - mi = new CMenuOptionNumberChooser(b->name, &b->int_val, enabled, range_from, range_to, m->observ, 0, 0, NONEXISTANT_LOCALE, pulldown); - } else if (type == "string") { - b->str_val = value; - mi = new CMenuOptionStringChooser(b->name.c_str(), &b->str_val, enabled, m->observ, directkey, icon, pulldown); - } else if (type == "stringinput") { - b->str_val = value; - std::string valid_chars = "abcdefghijklmnopqrstuvwxyz0123456789!\"§$%&/()=?-. "; - tableLookup(L, "valid_chars", valid_chars); - lua_Integer sms = 0; tableLookup(L, "sms", sms); - lua_Integer size = 30; tableLookup(L, "size", size); - CLuaMenuStringinput *stringinput = new CLuaMenuStringinput(L, action, id, b->name.c_str(), &b->str_val, size, valid_chars, m->observ, icon, sms); - mi = new CMenuForwarder(b->name, enabled, b->str_val, stringinput, NULL/*ActionKey*/, directkey, icon, right_icon); - m->targets.push_back(stringinput); - } else if (type == "keyboardinput") { - b->str_val = value; - lua_Integer size = 0; tableLookup(L, "size", size); - std::string help = ""; tableLookup(L, "help", help); - std::string help2 = ""; tableLookup(L, "help2", help2); - CLuaMenuKeyboardinput *keyboardinput = new CLuaMenuKeyboardinput(L, action, id, b->name.c_str(), &b->str_val, size, m->observ, icon, help, help2); - mi = new CMenuForwarder(b->name, enabled, b->str_val, keyboardinput, NULL/*ActionKey*/, directkey, icon, right_icon); - m->targets.push_back(keyboardinput); - } else if (type == "filebrowser") { - b->str_val = value; - lua_Integer dirMode = 0; tableLookup(L, "dir_mode", dirMode); - CLuaMenuFilebrowser *filebrowser = new CLuaMenuFilebrowser(L, action, id, &b->str_val, dirMode); - lua_pushstring(L, "filter"); - lua_gettable(L, -2); - if (lua_istable(L, -1)) - for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 2)) { - lua_pushvalue(L, -2); - const char *val = lua_tostring(L, -2); - filebrowser->addFilter(val); - } - lua_pop(L, 1); - - mi = new CMenuForwarder(b->name, enabled, b->str_val, filebrowser, NULL/*ActionKey*/, directkey, icon, right_icon); - m->targets.push_back(filebrowser); - } - if (mi) { - mi->setLua(L, action, id); - if (!hint.empty() || hint_icon) - mi->setHint(hint_icon, hint); - m->m->addItem(mi); - } - } - - if (mi) { - lua_Integer id = m->itemmap.size() + 1; - m->itemmap.insert(itemmap_pair_t(id, mi)); - lua_pushinteger(L, id); - } - else - lua_pushnil(L); - - return 1; -} - -int CLuaInstance::MenuHide(lua_State *L) -{ - CLuaMenu *m = MenuCheck(L, 1); - if (!m) - return 0; - m->m->hide(); - return 0; -} - -int CLuaInstance::MenuExec(lua_State *L) -{ - CLuaMenu *m = MenuCheck(L, 1); - if (!m) - return 0; - m->m->exec(NULL, ""); - m->m->hide(); - return 0; -} - void CLuaInstance::HintboxRegister(lua_State *L) { luaL_Reg meth[] = { diff --git a/src/gui/lua/luainstance.h b/src/gui/lua/luainstance.h index a0c7cbc16..2c6ab30ea 100644 --- a/src/gui/lua/luainstance.h +++ b/src/gui/lua/luainstance.h @@ -26,7 +26,6 @@ extern "C" { #include } #include -#include #include #include #include @@ -37,87 +36,6 @@ extern "C" { #define LUA_API_VERSION_MAJOR 1 #define LUA_API_VERSION_MINOR 22 -struct CLuaMenuItem -{ - int int_val; - std::string str_val; - std::string name; -}; - -class CLuaMenuChangeObserver : public CChangeObserver -{ - public: - bool changeNotify(lua_State *, const std::string &, const std::string &, void *); -}; - -typedef std::pair itemmap_pair_t; -typedef std::map itemmap_t; -typedef itemmap_t::iterator itemmap_iterator_t; - -class CLuaMenu -{ - public: - CMenuWidget *m; - CLuaMenuChangeObserver *observ; - std::list items; - std::list targets; - std::list tofree; - itemmap_t itemmap; - CLuaMenu(); - ~CLuaMenu(); -}; - -class CLuaMenuForwarder : public CMenuTarget -{ - public: - lua_State *L; - std::string luaAction; - std::string luaId; - CLuaMenuForwarder(lua_State *L, std::string _luaAction, std::string _luaId); - ~CLuaMenuForwarder(); - int exec(CMenuTarget* parent, const std::string & actionKey); -}; - -class CLuaMenuFilebrowser : public CLuaMenuForwarder -{ - private: - std::string *value; - bool dirMode; - std::vector filter; - public: - CLuaMenuFilebrowser(lua_State *_L, std::string _luaAction, std::string _luaId, std::string *_value, bool _dirMode); - int exec(CMenuTarget* parent, const std::string & actionKey); - void addFilter(std::string s) { filter.push_back(s); }; -}; - -class CLuaMenuStringinput : public CLuaMenuForwarder -{ - private: - std::string *value; - std::string valid_chars; - const char *name; - const char *icon; - bool sms; - int size; - CChangeObserver *observ; - public: - CLuaMenuStringinput(lua_State *_L, std::string _luaAction, std::string _luaId, const char *_name, std::string *_value, int _size, std::string _valid_chars, CChangeObserver *_observ, const char *_icon, bool _sms); - int exec(CMenuTarget* parent, const std::string & actionKey); -}; - -class CLuaMenuKeyboardinput : public CLuaMenuForwarder -{ - private: - std::string *value; - const char *name; - const char *icon; - int size; - CChangeObserver *observ; - std::string help, help2; - public: - CLuaMenuKeyboardinput(lua_State *_L, std::string _luaAction, std::string _luaId, const char *_name, std::string *_value, int _size, CChangeObserver *_observ, const char *_icon, std::string _help, std::string _help2); - int exec(CMenuTarget* parent, const std::string & actionKey); -}; class CLuaHintbox { @@ -224,16 +142,6 @@ private: static int strFind(lua_State *L); static int strSub(lua_State *L); - void MenuRegister(lua_State *L); - static int MenuNew(lua_State *L); - static int MenuDelete(lua_State *L); - static int MenuAddKey(lua_State *L); - static int MenuAddItem(lua_State *L); - static int MenuHide(lua_State *L); - static int MenuExec(lua_State *L); - static CLuaMenu *MenuCheck(lua_State *L, int n); - static int MenuSetActive(lua_State *L); - void HintboxRegister(lua_State *L); static int HintboxNew(lua_State *L); static int HintboxDelete(lua_State *L);