From: Sadrul Habib Chowdhury Date: Sun, 14 Jun 2009 23:50:45 +0000 (-0400) Subject: Do not crash on unhook. X-Git-Url: https://repo.or.cz/w/screen-lua.git/commitdiff_plain/d03daed69b4632fd1168faf1fe4fd6ce789ca539 Do not crash on unhook. Use the handler to unhook event callbacks. The cmdcallback.lua script has been updated to show the use. --- diff --git a/src/lua.c b/src/lua.c index 7b3ec71..7aa3aa5 100644 --- a/src/lua.c +++ b/src/lua.c @@ -81,6 +81,7 @@ extern struct layer *flayer; static int LuaDispatch(void *handler, const char *params, va_list va); static int LuaRegEvent(lua_State *L); static int LuaUnRegEvent(lua_State *L); +static void LuaShowErr(lua_State *L); enum { @@ -96,6 +97,7 @@ struct lua_handler char *name; int reference; } u; + struct listener *listener; }; /** Template {{{ */ @@ -275,6 +277,59 @@ struct_register(lua_State *L, const char *name, const luaL_reg fn_methods[], con /** }}} */ +/** Callback {{{ */ +PUSH_TYPE(callback, struct lua_handler) + +CHECK_TYPE(callback, struct lua_handler) + +static int +callback_unhook(lua_State *L) +{ + struct lua_handler *lh = check_callback(L, 1); + if (!lh->listener) + { + lua_pushboolean(L, 0); + lua_pushstring(L, "Callback already unhooked."); + LuaShowErr(L); + } + else + { + if (lh->type == LUA_HANDLER_TYPE_N) + { + Free(lh->u.name); + } + else + { + luaL_unref(L, LUA_REGISTRYINDEX, lh->u.reference); + lh->u.reference = 0; + } + unregister_listener(lh->listener); + lh->listener = NULL; + lua_pushboolean(L, 1); + } + return 1; +} + +static const luaL_reg callback_methods[] = { + {"unhook", callback_unhook}, + {0, 0} +}; + +static const luaL_reg callback_metamethods[] = { + {0, 0} +}; + +static const struct Xet_reg callback_setters[] = { + {0, 0} +}; + +static const struct Xet_reg callback_getters[] = { + {0, 0} +}; + + +/** }}} */ + /** Window {{{ */ PUSH_TYPE(window, struct win) @@ -647,7 +702,6 @@ static const luaL_reg screen_methods[] = { {"command", screen_exec_command}, {"append_msg", screen_append_msg}, {"hook", LuaRegEvent}, - {"unhook", LuaUnRegEvent}, {0, 0} }; @@ -680,6 +734,7 @@ int LuaInit(void) REGISTER(display); REGISTER(user); REGISTER(canvas); + REGISTER(callback); return 0; } @@ -961,9 +1016,10 @@ LuaRegEvent(lua_State *L) return luaL_error(L, "Handler has already been registered"); } /* Return the handler for un-register */ - l->handler = malloc(sizeof(struct lua_handler)); + l->handler = lua_newuserdata(L, sizeof(struct lua_handler)); memcpy(l->handler, &lh, sizeof(struct lua_handler)); - lua_pushlightuserdata(L, l); + ((struct lua_handler *)l->handler)->listener = l; + push_callback(L, &l->handler); } else return luaL_error(L, "Invalid event specified: %s for object %s", event, objname); diff --git a/src/scripts/cmdcallback.lua b/src/scripts/cmdcallback.lua index 54fa4eb..22c982f 100644 --- a/src/scripts/cmdcallback.lua +++ b/src/scripts/cmdcallback.lua @@ -31,14 +31,7 @@ end ticket2 = screen.hook("cmdexecuted", "cmd") function unhook() - if ticket1 ~= nil then - screen.unhook(ticket1) - ticket1 = nil - end - - if ticket2 ~= nil then - screen.unhook(ticket2) - ticket2 = nil - end + ticket1:unhook() + ticket2:unhook() end