Get rid of DECLARE_LUACLASS
[lsnes.git] / src / lua / ibind.cpp
blobb2bfea131e2692233fac42df9e78da24108050f2
1 #include "lua/internal.hpp"
2 #include "core/keymapper.hpp"
3 #include "core/command.hpp"
4 #include <vector>
6 class lua_inverse_bind
8 public:
9 lua_inverse_bind(lua_state& L, const std::string& name, const std::string& cmd);
10 std::string print()
12 return ikey.getname();
14 private:
15 keyboard::invbind ikey;
18 class lua_command_binding : public command::base
20 public:
21 lua_command_binding(lua_state& _L, const std::string& cmd, int idx)
22 : command::base(lsnes_cmd, cmd), L(_L)
24 L.pushlightuserdata(this);
25 L.pushvalue(idx);
26 L.rawset(LUA_REGISTRYINDEX);
28 void invoke(const std::string& arguments) throw(std::bad_alloc, std::runtime_error)
30 L.pushlightuserdata(this);
31 L.rawget(LUA_REGISTRYINDEX);
32 L.pushstring(arguments.c_str());
33 int r = L.pcall(1, 0, 0);
34 std::string err;
35 if(r == LUA_ERRRUN)
36 err = L.get_string(-1, "Lua command callback");
37 else if(r == LUA_ERRMEM)
38 err = "Out of memory";
39 else if(r == LUA_ERRERR)
40 err = "Double fault";
41 else
42 err = "Unknown error";
43 if(r) {
44 messages << "Error running lua command hook: " << err << std::endl;
47 private:
48 lua_state& L;
51 class lua_command_bind
53 public:
54 lua_command_bind(lua_state& L, const std::string& cmd, int idx1, int idx2);
55 ~lua_command_bind();
56 std::string print()
58 if(b)
59 return a->get_name() + "," + b->get_name();
60 else
61 return a->get_name();
63 private:
64 lua_command_binding* a;
65 lua_command_binding* b;
68 lua_inverse_bind::lua_inverse_bind(lua_state& L, const std::string& name, const std::string& cmd)
69 : ikey(lsnes_mapper, cmd, "Lua‣" + name)
73 lua_command_bind::lua_command_bind(lua_state& L, const std::string& cmd, int idx1, int idx2)
75 if(L.type(idx2) == LUA_TFUNCTION) {
76 a = new lua_command_binding(L, "+" + cmd, idx1);
77 b = new lua_command_binding(L, "-" + cmd, idx2);
78 } else {
79 a = new lua_command_binding(L, cmd, idx1);
80 b = NULL;
84 lua_command_bind::~lua_command_bind()
86 delete a;
87 delete b;
90 namespace
92 function_ptr_luafun input_bindings(lua_func_misc, "list_bindings", [](lua_state& L, const std::string& fname)
93 -> int {
94 std::string target;
95 if(!L.isnoneornil(1))
96 target = L.get_string(1, fname.c_str());
97 L.newtable();
98 for(auto key : lsnes_mapper.get_bindings()) {
99 std::string _key = key;
100 std::string cmd = lsnes_mapper.get(key);
101 if(target != "" && cmd != target)
102 continue;
103 L.pushlstring(_key.c_str(), _key.length());
104 L.pushlstring(cmd.c_str(), cmd.length());
105 L.rawset(-3);
107 for(auto key : lsnes_mapper.get_controller_keys()) {
108 for(unsigned i = 0;; i++) {
109 std::string _key = key->get_string(i);
110 if(_key == "")
111 break;
112 std::string cmd = key->get_command();
113 _key = "|/" + _key;
114 if(target != "" && cmd != target)
115 continue;
116 L.pushlstring(_key.c_str(), _key.length());
117 L.pushlstring(cmd.c_str(), cmd.length());
118 L.rawset(-3);
121 return 1;
124 function_ptr_luafun get_alias(lua_func_misc, "get_alias", [](lua_state& L, const std::string& fname) -> int {
125 std::string name = L.get_string(1, fname.c_str());
126 std::string a = lsnes_cmd.get_alias_for(name);
127 if(a != "")
128 L.pushlstring(a.c_str(), a.length());
129 else
130 L.pushnil();
131 return 1;
134 function_ptr_luafun set_alias(lua_func_misc, "set_alias", [](lua_state& L, const std::string& fname) -> int {
135 std::string name = L.get_string(1, fname.c_str());
136 std::string value;
137 if(L.type(2) != LUA_TNIL)
138 value = L.get_string(2, fname.c_str());
139 lsnes_cmd.set_alias_for(name, value);
140 refresh_alias_binds();
141 return 0;
144 function_ptr_luafun create_ibind(lua_func_misc, "create_ibind", [](lua_state& L, const std::string& fname)
145 -> int {
146 std::string name = L.get_string(1, fname.c_str());
147 std::string command = L.get_string(2, fname.c_str());
148 lua_inverse_bind* b = lua_class<lua_inverse_bind>::create(L, name, command);
149 return 1;
152 function_ptr_luafun create_cmd(lua_func_misc, "create_command", [](lua_state& L, const std::string& fname)
153 -> int {
154 if(L.type(2) != LUA_TFUNCTION)
155 throw std::runtime_error("Argument 2 of create_command must be function");
156 if(L.type(3) != LUA_TFUNCTION && L.type(3) != LUA_TNIL && L.type(3) != LUA_TNONE)
157 throw std::runtime_error("Argument 2 of create_command must be function or nil");
158 std::string name = L.get_string(1, fname.c_str());
159 lua_command_bind* b = lua_class<lua_command_bind>::create(L, name, 2, 3);
160 return 1;
163 lua_class<lua_inverse_bind> class_inverse_bind("INVERSEBIND");
164 lua_class<lua_command_bind> class_command_bind("COMMANDBIND");