Make the merged unhooking code work again.
authorRui Guo <firemeteor.guo@gmail.com>
Mon, 15 Jun 2009 12:15:27 +0000 (15 20:15 +0800)
committerRui Guo <firemeteor.guo@gmail.com>
Mon, 15 Jun 2009 12:15:27 +0000 (15 20:15 +0800)
The ref counting is going to be removed as requested by Sadrul.

src/lua.c

index 742a7d0..8f5a5f4 100644 (file)
--- a/src/lua.c
+++ b/src/lua.c
@@ -77,6 +77,7 @@ extern struct win *windows, *fore;
 extern struct display *displays, *display;
 extern struct LayFuncs WinLf;
 extern struct layer *flayer;
+extern void AppendWinMsgRend(const char *str, const char *color);
 
 static int LuaDispatch(void *handler, const char *params, va_list va);
 static int LuaRegEvent(lua_State *L);
@@ -95,16 +96,51 @@ struct lua_handler
   int type;
   union
   {
-    char *name;
+    const char *name;
     int reference;
   } u;
   struct listener *listener;
 };
 
+typedef struct lua_handler *lua_handler;
 void LuaPushHandler(lua_State *L, lua_handler lh);
 void LuaHRef(lua_State *L, int key, int reg);
 lua_handler LuaCheckHandler(lua_State *L, int idx, int ref);
 
+lua_handler 
+LuaAllocHandler(const char *name, int ref)
+{
+  struct lua_handler *lh;
+  lh = (struct lua_handler*) malloc(sizeof(struct lua_handler));
+  if (!lh)
+    return NULL;
+
+  if (name)
+    {
+      lh->type = LUA_HANDLER_TYPE_N;
+      lh->u.name = name;
+    }
+  else
+    {
+      lh->type = LUA_HANDLER_TYPE_F;
+      lh->u.reference = ref;
+    }
+
+  return lh;
+}
+
+void
+LuaFreeHandler(lua_State *L, struct lua_handler **lh)
+{
+  if ((*lh)->type == LUA_HANDLER_TYPE_N)
+    Free((*lh)->u.name)
+  else
+    {
+      LuaHRef(L, (*lh)->u.reference, 0);
+      (*lh)->u.reference = 0;
+    }
+  Free(*lh);
+}
 /** Template {{{ */
 
 #define CHECK_TYPE(name, type) \
@@ -306,7 +342,7 @@ callback_unhook(lua_State *L)
        }
       else
        {
-         luaL_unref(L, LUA_REGISTRYINDEX, lh->u.reference);
+          LuaHRef(L, lh->u.reference, 0);
          lh->u.reference = 0;
        }
       unregister_listener(lh->listener);
@@ -706,6 +742,7 @@ struct sinput_data
   lua_State *L;
   lua_handler lh;
 };
+
 void
 script_input_fn(char *buf, int len, char *priv)
 {
@@ -723,7 +760,7 @@ script_input_fn(char *buf, int len, char *priv)
        }
     }
   free(sidata);
-  LuaHRef(L, lh, 0);
+  LuaFreeHandler(L, &lh);
 }
 
 static int
@@ -799,8 +836,7 @@ int LuaInit(void)
   lua_newtable(L);
   lua_rawset(L, -3);
   /* two kinds of info in this table:
-   * _keyfunc[key]->func
-   * _keyfunc[func]->name */
+   * _keyfunc[key]->func */
   lua_pushstring(L, "_keyfunc");
   lua_newtable(L);
   lua_rawset(L, -3);
@@ -982,11 +1018,18 @@ void
 LuaPushHandler(lua_State *L, lua_handler lh)
 {
   int keyfunc;
-  luaL_getmetatable(L, "screen");
-  keyfunc = LuaPushHTable(L, lua_gettop(L), "_keyfunc");
-  lua_rawgeti(L, keyfunc, lh);
-  lua_replace(L, -3);
-  lua_pop(L, 1);
+  if (lh->type == LUA_HANDLER_TYPE_F)
+    {
+      luaL_getmetatable(L, "screen");
+      keyfunc = LuaPushHTable(L, lua_gettop(L), "_keyfunc");
+      lua_rawgeti(L, keyfunc, lh->u.reference);
+      lua_replace(L, -3);
+      lua_pop(L, 1);
+    }
+  else
+    {
+      lua_getfield(L, LUA_GLOBALSINDEX, lh->u.name);
+    }
 }
 
 void
@@ -1065,62 +1108,26 @@ LuaFuncKey(lua_State *L, int idx, int ref)
   return key;
 }
 
-void
-LuaHSetName(lua_State *L, int key, int name)
-{
-  int keyfunc, sc;
-  luaL_getmetatable(L, "screen");
-  sc = lua_gettop(L);
-  keyfunc = LuaPushHTable(L, sc, "_keyfunc");
-
-  lua_rawgeti(L, keyfunc, key);
-  lua_pushvalue(L, name);
-  lua_rawset(L, keyfunc);
-
-  lua_pop(L, 2);
-}
-
-/* Do not hold the return value for long */
-const char *
-LuaHGetName(lua_State *L, lua_handler key)
-{
-  int keyfunc, sc;
-  const char * name;
-  luaL_getmetatable(L, "screen");
-  sc = lua_gettop(L);
-  keyfunc = LuaPushHTable(L, sc, "_keyfunc");
-
-  lua_rawgeti(L, keyfunc, key);
-  lua_rawget(L, keyfunc);
-  name = lua_tostring(L, -1);
-  lua_pop(L, 3);
-  return name;
-}
-
 lua_handler
 LuaCheckHandler(lua_State *L, int idx, int ref)
 {
-  int name = 0, key;
+  int key;
   if (lua_isstring(L, idx))
     {
       const char * handler;
       /* registered with func name.*/
       handler = luaL_checkstring(L, idx);
-      name = idx++;
       lua_getfield(L, LUA_GLOBALSINDEX, handler);
       if (!lua_isfunction(L, -1))
         luaL_error(L, "The specified handler %s in param #%d is not a function", handler, idx);
+      lua_pop(L, 1);
+      return LuaAllocHandler(handler, 0);
     }
   else if (!lua_isfunction(L, idx))
     luaL_error(L, "Handler should be a function or the name of function");
 
   key = LuaFuncKey(L, idx, ref);
-  if (name && key != LUA_NOREF)
-    {
-      LuaHSetName(L, key, name);
-      lua_pop(L, 1);
-    }
-  return LuaAllocHandler(key);
+  return LuaAllocHandler(NULL, key);
 }
 
 int
@@ -1228,18 +1235,17 @@ LuaRegEvent(lua_State *L)
       l->handler = (void *)lh;
       if (register_listener(sev, l))
         {
-          const char *fname = LuaHGetName(L, lh);
           free(l);
-         if (fname)
-           return luaL_error(L, "Handler %s has already been registered", fname);
-         else
-           return luaL_error(L, "Handler has already been registered");
+          if (lh->type == LUA_HANDLER_TYPE_N)
+            return luaL_error(L, "Handler %s has already been registered", lh->u.name);
+          else
+            return luaL_error(L, "Handler has already been registered");
         }
       /* Return the handler for un-register */
-      l->handler = lua_newuserdata(L, sizeof(struct lua_handler));
-      memcpy(l->handler, &lh, sizeof(struct lua_handler));
-      ((struct lua_handler *)l->handler)->listener = l;
-      push_callback(L, &l->handler);
+      /*l->handler = lua_newuserdata(L, sizeof(struct lua_handler));
+      memcpy(l->handler, &lh, sizeof(struct lua_handler));*/
+      lh->listener = l;
+      push_callback(L, (lua_handler *)&l->handler);
     }
   else
     return luaL_error(L, "Invalid event specified: %s for object %s", event, objname);
@@ -1255,7 +1261,6 @@ LuaUnRegEvent(lua_State *L)
    *   returns: true of success, false otherwise */
   int idx = 1;
   struct listener *l;
-  lua_handler lh;
 
   /* If the param is not as expected */
   if (!lua_islightuserdata(L, idx))
@@ -1268,20 +1273,16 @@ LuaUnRegEvent(lua_State *L)
     }
 
   l = (struct listener*)lua_touserdata(L, idx++);
-  /* the handler is used to validate the ticket.
-   * This is important, otherwise double unhook can crash screen. */
-  lh = LuaCheckHandler(L, idx, 0);
 
   /* Validate the listener structure */
-  if (lh == LUA_NOREF || !l || !l->handler)
+  if (!l || !l->handler)
     {
       /* invalid */
       lua_pushboolean(L,0);
     }
   else
     {
-      LuaHRef(L, (lua_handler)l->handler, 0);
-      LuaFreeHandler(((lua_handler)&(l->handler)));
+      LuaFreeHandler(L, ((lua_handler *)&(l->handler)));
       unregister_listener(l);
       lua_pushboolean(L, 1);
     }