Do not crash on unhook.
authorSadrul Habib Chowdhury <sadrul@users.sourceforge.net>
Sun, 14 Jun 2009 23:50:45 +0000 (14 19:50 -0400)
committerSadrul Habib Chowdhury <sadrul@users.sourceforge.net>
Sun, 14 Jun 2009 23:50:45 +0000 (14 19:50 -0400)
Use the handler to unhook event callbacks. The cmdcallback.lua
script has been updated to show the use.

src/lua.c
src/scripts/cmdcallback.lua

index 7b3ec71..7aa3aa5 100644 (file)
--- 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);
index 54fa4eb..22c982f 100644 (file)
@@ -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