/** Emit a signal to an object. * \param L The Lua VM state. * \param oud The object index on the stack. * \param name The name of the signal. * \param nargs The number of arguments to pass to the called functions. */ void luaA_object_emit_signal(lua_State *L, int oud, const char *name, int nargs) { int oud_abs = luaA_absindex(L, oud); lua_object_t *obj = lua_touserdata(L, oud); if(!obj) luaL_error(L, "trying to emit signal on non-object"); signal_t *sigfound = signal_array_getbyid(&obj->signals, a_strhash((const unsigned char *) name)); if(sigfound) { int nbfunc = sigfound->sigfuncs.len; luaL_checkstack(L, lua_gettop(L) + nbfunc + nargs + 2, "too much signal"); /* Push all functions and then execute, because this list can change * while executing funcs. */ foreach(func, sigfound->sigfuncs) luaA_object_push_item(L, oud_abs, (void *) *func); for(int i = 0; i < nbfunc; i++) { /* push object */ lua_pushvalue(L, oud_abs); /* push all args */ for(int j = 0; j < nargs; j++) lua_pushvalue(L, - nargs - nbfunc - 1 + i); /* push first function */ lua_pushvalue(L, - nargs - nbfunc - 1 + i); /* remove this first function */ lua_remove(L, - nargs - nbfunc - 2 + i); luaA_dofunction(L, nargs + 1, 0); } } lua_pop(L, nargs); }
/** Convert a Lua table to a list of widget nodes. * \param L The Lua VM state. * \param idx Index of the table where to store the widgets references. * \param widgets The linked list of widget node. */ static void luaA_table2widgets(lua_State *L, int idx, widget_node_array_t *widgets) { if(lua_istable(L, -1)) { int table_idx = luaA_absindex(L, idx); lua_pushnil(L); while(luaA_next(L, -2)) luaA_table2widgets(L, table_idx, widgets); /* remove the table */ lua_pop(L, 1); } else { widget_t *widget = luaA_toudata(L, -1, &widget_class); if(widget) { widget_node_t w; p_clear(&w, 1); w.widget = luaA_object_ref_item(L, idx, -1); widget_node_array_append(widgets, w); } else lua_pop(L, 1); /* remove value */ } }
/** Emit a signal. * @tparam string name A signal name. * @param[opt] ... Various arguments. * @function emit_signal */ void luaA_object_emit_signal(lua_State *L, int oud, const char *name, int nargs) { int oud_abs = luaA_absindex(L, oud); lua_class_t *lua_class = luaA_class_get(L, oud); lua_object_t *obj = luaA_toudata(L, oud, lua_class); if(!obj) { luaA_warn(L, "Trying to emit signal '%s' on non-object", name); return; } else if(lua_class->checker && !lua_class->checker(obj)) { luaA_warn(L, "Trying to emit signal '%s' on invalid object", name); return; } signal_t *sigfound = signal_array_getbyid(&obj->signals, a_strhash((const unsigned char *) name)); if(sigfound) { int nbfunc = sigfound->sigfuncs.len; luaL_checkstack(L, lua_gettop(L) + nbfunc + nargs + 2, "too much signal"); /* Push all functions and then execute, because this list can change * while executing funcs. */ foreach(func, sigfound->sigfuncs) luaA_object_push_item(L, oud_abs, *func); for(int i = 0; i < nbfunc; i++) { /* push object */ lua_pushvalue(L, oud_abs); /* push all args */ for(int j = 0; j < nargs; j++) lua_pushvalue(L, - nargs - nbfunc - 1 + i); /* push first function */ lua_pushvalue(L, - nargs - nbfunc - 1 + i); /* remove this first function */ lua_remove(L, - nargs - nbfunc - 2 + i); luaA_dofunction(L, nargs + 1, 0); } } else { luaA_warn(L, "Trying to emit unknown signal '%s'", name); return; } /* Then emit signal on the class */ lua_pushvalue(L, oud); lua_insert(L, - nargs - 1); luaA_class_emit_signal(L, luaA_class_get(L, - nargs - 1), name, nargs + 1); }
static void move_global_to_table(lua_State *L, int index, const char *global_name, const char *local_name) { index = luaA_absindex(L, index); /* Get the global */ lua_getglobal(L, global_name); assert(!lua_isnil(L, -1)); /* Save it locally */ lua_setfield(L, index, local_name); /* Set the global to nil */ lua_pushnil(L); lua_setglobal(L, global_name); }