diff options
Diffstat (limited to 'apps/plugins/lua')
-rw-r--r-- | apps/plugins/lua/rocklib.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/apps/plugins/lua/rocklib.c b/apps/plugins/lua/rocklib.c index 033975d7fe..77b49dc8ec 100644 --- a/apps/plugins/lua/rocklib.c +++ b/apps/plugins/lua/rocklib.c | |||
@@ -202,18 +202,60 @@ RB_WRAP(gui_syncyesno_run) | |||
202 | return 1; | 202 | return 1; |
203 | } | 203 | } |
204 | 204 | ||
205 | static lua_State* store_luastate(lua_State *L, bool bStore) | ||
206 | { | ||
207 | /* it is dangerous to store the lua state byond its guaranteed lifetime | ||
208 | be sure to clear state asap (as in before you exit the calling function) */ | ||
209 | static lua_State *LStored = NULL; | ||
210 | if(bStore) | ||
211 | LStored = L; | ||
212 | return LStored; | ||
213 | } | ||
214 | |||
215 | static int menu_callback(int action, const struct menu_item_ex *this_item) | ||
216 | { | ||
217 | (void) this_item; | ||
218 | static int lua_ref = LUA_NOREF; | ||
219 | lua_State *L = store_luastate(NULL, false); | ||
220 | if(!L) | ||
221 | { | ||
222 | lua_ref = action; | ||
223 | action = ACTION_STD_CANCEL; | ||
224 | } | ||
225 | else if (lua_ref != LUA_NOREF) | ||
226 | { | ||
227 | lua_rawgeti(L, LUA_REGISTRYINDEX, lua_ref); | ||
228 | lua_pushnumber(L, action); | ||
229 | lua_pcall (L, 1, 1, 0); | ||
230 | action = luaL_optnumber (L, -1, ACTION_STD_CANCEL); | ||
231 | lua_pop(L, 1); | ||
232 | } | ||
233 | |||
234 | return action; | ||
235 | } | ||
236 | |||
205 | RB_WRAP(do_menu) | 237 | RB_WRAP(do_menu) |
206 | { | 238 | { |
207 | struct menu_callback_with_desc menu_desc = {NULL, NULL, Icon_NOICON}; | 239 | struct menu_callback_with_desc menu_desc = {NULL, NULL, Icon_NOICON}; |
208 | struct menu_item_ex menu = {MT_RETURN_ID | MENU_HAS_DESC, {.strings = NULL}, | 240 | struct menu_item_ex menu = {MT_RETURN_ID | MENU_HAS_DESC, {.strings = NULL}, |
209 | {.callback_and_desc = &menu_desc}}; | 241 | {.callback_and_desc = &menu_desc}}; |
210 | int n, start_selected; | 242 | int n, start_selected; |
243 | int ref_lua = LUA_NOREF; | ||
211 | const char **items, *title; | 244 | const char **items, *title; |
212 | 245 | ||
213 | title = luaL_checkstring(L, 1); | 246 | title = luaL_checkstring(L, 1); |
214 | 247 | ||
215 | start_selected = lua_tointeger(L, 3); | 248 | start_selected = lua_tointeger(L, 3); |
216 | 249 | ||
250 | if (lua_isfunction (L, -1)) | ||
251 | { | ||
252 | /*lua callback function cb(action) return action end */ | ||
253 | ref_lua = luaL_ref(L, LUA_REGISTRYINDEX); | ||
254 | menu_callback(ref_lua, NULL); | ||
255 | store_luastate(L, true); | ||
256 | menu_desc.menu_callback = &menu_callback; | ||
257 | } | ||
258 | |||
217 | /* newuserdata will be pushed onto stack after args*/ | 259 | /* newuserdata will be pushed onto stack after args*/ |
218 | items = get_table_items(L, 2, &n); | 260 | items = get_table_items(L, 2, &n); |
219 | 261 | ||
@@ -223,6 +265,13 @@ RB_WRAP(do_menu) | |||
223 | 265 | ||
224 | int result = rb->do_menu(&menu, &start_selected, NULL, false); | 266 | int result = rb->do_menu(&menu, &start_selected, NULL, false); |
225 | 267 | ||
268 | if (ref_lua != LUA_NOREF) | ||
269 | { | ||
270 | store_luastate(NULL, true); | ||
271 | luaL_unref (L, LUA_REGISTRYINDEX, ref_lua); | ||
272 | menu_callback(LUA_NOREF, NULL); | ||
273 | } | ||
274 | |||
226 | lua_pushinteger(L, result); | 275 | lua_pushinteger(L, result); |
227 | return 1; | 276 | return 1; |
228 | } | 277 | } |