Fix duplicate check on event hooking.
authorRui Guo <firemeteor.guo@gmail.com>
Fri, 12 Jun 2009 08:31:09 +0000 (12 16:31 +0800)
committerRui Guo <firemeteor.guo@gmail.com>
Fri, 12 Jun 2009 08:31:09 +0000 (12 16:31 +0800)
src/lua.c
src/script.c
src/script.h

index 8a9c527..496e7bb 100644 (file)
--- a/src/lua.c
+++ b/src/lua.c
@@ -79,6 +79,7 @@ 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);
+struct binding lua_binding;
 
 typedef int lua_handler;
 #define LuaAllocHandler(a) a
@@ -880,7 +881,7 @@ LuaPushHandler(lua_State *L, lua_handler lh)
 {
   int keyfunc;
   luaL_getmetatable(L, "screen");
-  keyfunc = LuaPushHTable(L, -1, "_keyfunc");
+  keyfunc = LuaPushHTable(L, lua_gettop(L), "_keyfunc");
   lua_rawgeti(L, keyfunc, lh);
   lua_replace(L, -3);
   lua_pop(L, 1);
@@ -1015,6 +1016,12 @@ LuaCheckHandler(lua_State *L, int idx, int reg)
   return LuaAllocHandler(key);
 }
 
+int
+LuaHdlrComp(lua_handler h1, lua_handler h2)
+{
+  return h1 - h2;
+}
+
 /* }}} **/
 
 static int
@@ -1110,7 +1117,8 @@ LuaRegEvent(lua_State *L)
       if (!l)
         return luaL_error(L, "Out of memory");
       l->priv = priv;
-      l->dispatcher = LuaDispatch;
+      l->bd = &lua_binding;
+      l->handler = (void *)lh;
       if (register_listener(sev, l))
         {
           const char *fname = LuaHGetName(L, lh);
@@ -1121,7 +1129,6 @@ LuaRegEvent(lua_State *L)
            return luaL_error(L, "Handler has already been registered");
         }
       /* Return the handler for un-register */
-      l->handler = (void *)lh;
       lua_pushlightuserdata(L, l);
     }
   else
@@ -1185,6 +1192,8 @@ struct binding lua_binding =
     LuaFinit,
     LuaCall,
     LuaSource,
+    LuaDispatch,
+    LuaHdlrComp,
     0,     /*b_next*/
     &LuaFuncs
 };
index 91e913f..81befdc 100644 (file)
@@ -202,8 +202,8 @@ register_listener(struct script_event *ev, struct listener *l)
     {
       iter = iter->chain;
       /* return if duplicate found*/
-      if (iter->handler == l->handler
-          && iter->dispatcher == l->dispatcher)
+      if (iter->bd == l->bd
+          && !iter->bd->bd_hdlrcmp(iter->handler, l->handler))
         return 1;
     }
   p = iter;
@@ -212,9 +212,8 @@ register_listener(struct script_event *ev, struct listener *l)
     {
       iter = iter->chain;
       /* return if duplicate found*/
-      /*FIXME: this check will not work*/
-      if (iter->handler == l->handler
-          && iter->dispatcher == l->dispatcher)
+      if (iter->bd == l->bd
+          && !iter->bd->bd_hdlrcmp(iter->handler, l->handler))
         return 1;
     }
 
@@ -256,7 +255,7 @@ trigger_sevent(struct script_event *ev, VA_DOTS)
   while (chain)
     {
       VA_START(va, ev);
-      res = chain->dispatcher(chain->handler, params, va);
+      res = chain->bd->bd_dispatch(chain->handler, params, va);
       VA_END(va);
       if (res)
         break;
index 307cb69..36e347c 100644 (file)
@@ -40,6 +40,12 @@ struct binding
   int (*bd_call) __P((char *func, char **argv));
   /*Returns zero on failure, non zero on success*/
   int (*bd_Source) __P((const char *, int));
+  /* The return value is significant: 
+   * a non-zero value will stop further
+   * notification to the rest of the chain.*/
+  int (*bd_dispatch) __P((void *handler, const char *params, va_list va)); 
+  int (*bd_hdlrcmp) __P((void * h1, void *h2));
+  
   struct binding *b_next;
   struct ScriptFuncs *fns;
 };
@@ -56,13 +62,8 @@ struct listener
 {
   /*Binding dependent event handler data*/
   void *handler; 
+  struct binding *bd;
 
-  /* dispatcher provided by the binding.
-   * The return value is significant: 
-   * a non-zero value will stop further
-   * notification to the rest of the chain.*/
-  int (*dispatcher) __P((void *handler, const char *params, va_list va)); 
-  
   /* smaller means higher privilege.*/
   unsigned int priv;
   struct listener *chain;