1 /* Lua scripting support
3 * Copyright (c) 2008 Sadrul Habib Chowdhury (sadrul@users.sf.net)
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3, or (at your option)
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program (see the file COPYING); if not, write to the
17 * Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
20 ****************************************************************
22 #include <sys/types.h>
39 static int StackDump(lua_State
*L
, const char *message
)
41 FILE *f
= fopen("/tmp/debug/stack", "ab");
42 int i
= lua_gettop(L
);
44 fprintf(f
, "%s", message
);
47 int t
= lua_type(L
, i
);
51 fprintf(f
, "String: %s\n", lua_tostring(L
, i
));
55 fprintf(f
, "Boolean: %s\n", lua_toboolean(L
, i
) ? "true" : "false");
59 fprintf(f
, "Number: %g\n", lua_tonumber(L
, i
));
63 fprintf(f
, "Type: %s\n", lua_typename(L
, t
));
73 extern struct win
*windows
, *fore
;
74 extern struct display
*displays
, *display
;
75 extern struct LayFuncs WinLf
;
76 extern struct layer
*flayer
;
78 static int LuaDispatch(void *handler
, const char *params
, va_list va
);
79 static int LuaRegEvent(lua_State
*L
);
80 static int LuaUnRegEvent(lua_State
*L
);
81 static void LuaShowErr(lua_State
*L
);
83 typedef int lua_handler
;
84 #define LuaAllocHandler(a) a
85 #define LuaFreeHandler(a)
89 #define CHECK_TYPE(name, type) \
91 check_##name(lua_State *L, int index) \
94 luaL_checktype(L, index, LUA_TUSERDATA); \
95 var = (type **) luaL_checkudata(L, index, #name); \
97 luaL_typerror(L, index, #name); \
101 #define PUSH_TYPE(name, type) \
103 push_##name(lua_State *L, type **t) \
110 r = (type **)lua_newuserdata(L, sizeof(type *)); \
112 luaL_getmetatable(L, #name); \
113 lua_setmetatable(L,-2); \
117 /* Much of the following template comes from:
118 * http://lua-users.org/wiki/BindingWithMembersAndMethods
121 static int get_int (lua_State
*L
, void *v
)
123 lua_pushinteger (L
, *(int*)v
);
127 static int set_int (lua_State
*L
, void *v
)
129 *(int*)v
= luaL_checkint(L
, 3);
133 static int get_number (lua_State
*L
, void *v
)
135 lua_pushnumber(L
, *(lua_Number
*)v
);
139 static int set_number (lua_State
*L
, void *v
)
141 *(lua_Number
*)v
= luaL_checknumber(L
, 3);
145 static int get_string (lua_State
*L
, void *v
)
147 lua_pushstring(L
, (char*)v
);
151 static int set_string (lua_State
*L
, void *v
)
153 *(const char**)v
= luaL_checkstring(L
, 3);
157 typedef int (*Xet_func
) (lua_State
*L
, void *v
);
159 /* member info for get and set handlers */
162 const char *name
; /* member name */
163 Xet_func func
; /* get or set function for type of member */
164 size_t offset
; /* offset of member within the struct */
165 int (*absolute
)(lua_State
*);
168 static void Xet_add (lua_State
*L
, const struct Xet_reg
*l
)
174 lua_pushstring(L
, l
->name
);
175 lua_pushlightuserdata(L
, (void*)l
);
180 static int Xet_call (lua_State
*L
)
182 /* for get: stack has userdata, index, lightuserdata */
183 /* for set: stack has userdata, index, value, lightuserdata */
184 const struct Xet_reg
*m
= (const struct Xet_reg
*)lua_touserdata(L
, -1); /* member info */
185 lua_pop(L
, 1); /* drop lightuserdata */
186 luaL_checktype(L
, 1, LUA_TUSERDATA
);
188 return m
->absolute(L
);
189 return m
->func(L
, *(char**)lua_touserdata(L
, 1) + m
->offset
);
192 static int index_handler (lua_State
*L
)
194 /* stack has userdata, index */
195 lua_pushvalue(L
, 2); /* dup index */
196 lua_rawget(L
, lua_upvalueindex(1)); /* lookup member by name */
197 if (!lua_islightuserdata(L
, -1))
199 lua_pop(L
, 1); /* drop value */
200 lua_pushvalue(L
, 2); /* dup index */
201 lua_gettable(L
, lua_upvalueindex(2)); /* else try methods */
202 if (lua_isnil(L
, -1)) /* invalid member */
203 luaL_error(L
, "cannot get member '%s'", lua_tostring(L
, 2));
206 return Xet_call(L
); /* call get function */
209 static int newindex_handler (lua_State
*L
)
211 /* stack has userdata, index, value */
212 lua_pushvalue(L
, 2); /* dup index */
213 lua_rawget(L
, lua_upvalueindex(1)); /* lookup member by name */
214 if (!lua_islightuserdata(L
, -1)) /* invalid member */
215 luaL_error(L
, "cannot set member '%s'", lua_tostring(L
, 2));
216 return Xet_call(L
); /* call set function */
220 struct_register(lua_State
*L
, const char *name
, const luaL_reg fn_methods
[], const luaL_reg meta_methods
[],
221 const struct Xet_reg setters
[], const struct Xet_reg getters
[])
223 int metatable
, methods
;
225 /* create methods table & add it to the table of globals */
226 luaL_register(L
, name
, fn_methods
);
227 methods
= lua_gettop(L
);
229 /* create metatable & add it to the registry */
230 luaL_newmetatable(L
, name
);
231 luaL_register(L
, 0, meta_methods
); /* fill metatable */
233 /* To identify the type of object */
234 lua_pushstring(L
, "_objname");
235 lua_pushstring(L
, name
);
238 metatable
= lua_gettop(L
);
240 lua_pushliteral(L
, "__metatable");
241 lua_pushvalue(L
, methods
); /* dup methods table*/
242 lua_rawset(L
, metatable
); /* hide metatable:
243 metatable.__metatable = methods */
245 lua_pushliteral(L
, "__index");
246 lua_pushvalue(L
, metatable
); /* upvalue index 1 */
247 Xet_add(L
, getters
); /* fill metatable with getters */
248 lua_pushvalue(L
, methods
); /* upvalue index 2 */
249 lua_pushcclosure(L
, index_handler
, 2);
250 lua_rawset(L
, metatable
); /* metatable.__index = index_handler */
252 lua_pushliteral(L
, "__newindex");
253 lua_newtable(L
); /* table for members you can set */
254 Xet_add(L
, setters
); /* fill with setters */
255 lua_pushcclosure(L
, newindex_handler
, 1);
256 lua_rawset(L
, metatable
); /* metatable.__newindex = newindex_handler */
258 /* FIXME: Why do we leave an element on the stack? */
259 lua_pop(L
, 1); /* drop metatable */
260 return 1; /* return methods on the stack */
267 PUSH_TYPE(window
, struct win
)
269 CHECK_TYPE(window
, struct win
)
271 static int get_window(lua_State
*L
, void *v
)
273 push_window(L
, (struct win
**)v
);
278 window_change_title(lua_State
*L
)
280 struct win
*w
= check_window(L
, 1);
282 const char *title
= luaL_checklstring(L
, 2, &len
);
283 ChangeAKA(w
, (char *)title
, len
);
288 window_get_monitor_status(lua_State
*L
)
290 struct win
*w
= check_window(L
, 1);
291 int activity
= luaL_checkint(L
, 2);
294 lua_pushinteger(L
, w
->w_monitor
!= MON_OFF
);
297 lua_pushinteger(L
, w
->w_silence
== SILENCE_ON
? w
->w_silencewait
: 0);
302 static const luaL_reg window_methods
[] = {
303 {"get_monitor_status", window_get_monitor_status
},
304 {"hook", LuaRegEvent
},
309 window_tostring(lua_State
*L
)
312 struct win
*w
= check_window(L
, 1);
313 snprintf(str
, sizeof(str
), "{window #%d: '%s'}", w
->w_number
, w
->w_title
);
314 lua_pushstring(L
, str
);
319 window_equality(lua_State
*L
)
321 struct win
*w1
= check_window(L
, 1), *w2
= check_window(L
, 2);
322 lua_pushboolean(L
, (w1
== w2
|| (w1
&& w2
&& w1
->w_number
== w2
->w_number
)));
326 static const luaL_reg window_metamethods
[] = {
327 {"__tostring", window_tostring
},
328 {"__eq", window_equality
},
332 static const struct Xet_reg window_setters
[] = {
333 {"title", 0, 0, window_change_title
/*absolute setter*/},
337 static const struct Xet_reg window_getters
[] = {
338 {"title", get_string
, offsetof(struct win
, w_title
) + 8},
339 {"number", get_int
, offsetof(struct win
, w_number
)},
340 {"dir", get_string
, offsetof(struct win
, w_dir
)},
341 {"tty", get_string
, offsetof(struct win
, w_tty
)},
342 {"pid", get_int
, offsetof(struct win
, w_pid
)},
343 {"group", get_window
, offsetof(struct win
, w_group
)},
344 {"bell", get_int
, offsetof(struct win
, w_bell
)},
353 PUSH_TYPE(user
, struct acluser
)
355 CHECK_TYPE(user
, struct acluser
)
358 get_user(lua_State
*L
, void *v
)
360 push_user(L
, (struct acluser
**)v
);
364 static const luaL_reg user_methods
[] = {
369 user_tostring(lua_State
*L
)
372 struct acluser
*u
= check_user(L
, 1);
373 snprintf(str
, sizeof(str
), "{user '%s'}", u
->u_name
);
374 lua_pushstring(L
, str
);
378 static const luaL_reg user_metamethods
[] = {
379 {"__tostring", user_tostring
},
383 static const struct Xet_reg user_setters
[] = {
387 static const struct Xet_reg user_getters
[] = {
388 {"name", get_string
, offsetof(struct acluser
, u_name
)},
389 {"password", get_string
, offsetof(struct acluser
, u_password
)},
397 PUSH_TYPE(canvas
, struct canvas
)
399 CHECK_TYPE(canvas
, struct canvas
)
402 get_canvas(lua_State
*L
, void *v
)
404 push_canvas(L
, (struct canvas
**)v
);
409 canvas_select(lua_State
*L
)
411 struct canvas
*c
= check_canvas(L
, 1);
412 if (!display
|| D_forecv
== c
)
414 SetCanvasWindow(c
, Layer2Window(c
->c_layer
));
417 /* XXX: the following all is duplicated from process.c:DoAction.
418 * Should these be in some better place?
420 ResizeCanvas(&D_canvas
);
421 RecreateCanvasChain();
422 RethinkDisplayViewports();
423 ResizeLayersToCanvases(); /* redisplays */
424 fore
= D_fore
= Layer2Window(D_forecv
->c_layer
);
425 flayer
= D_forecv
->c_layer
;
427 if (D_xtermosc
[2] || D_xtermosc
[3])
437 flayer
= D_forecv
->c_layer
;
438 CV_CALL(D_forecv
, LayRestore();LaySetCursor());
439 WindowChanged(0, 'F');
443 static const luaL_reg canvas_methods
[] = {
444 {"select", canvas_select
},
448 static const luaL_reg canvas_metamethods
[] = {
452 static const struct Xet_reg canvas_setters
[] = {
457 canvas_get_window(lua_State
*L
)
459 struct canvas
*c
= check_canvas(L
, 1);
460 struct win
*win
= Layer2Window(c
->c_layer
);
462 push_window(L
, &win
);
468 static const struct Xet_reg canvas_getters
[] = {
469 {"next", get_canvas
, offsetof(struct canvas
, c_next
)},
470 {"xoff", get_int
, offsetof(struct canvas
, c_xoff
)},
471 {"yoff", get_int
, offsetof(struct canvas
, c_yoff
)},
472 {"xs", get_int
, offsetof(struct canvas
, c_xs
)},
473 {"ys", get_int
, offsetof(struct canvas
, c_ys
)},
474 {"xe", get_int
, offsetof(struct canvas
, c_xe
)},
475 {"ye", get_int
, offsetof(struct canvas
, c_ye
)},
476 {"window", 0, 0, canvas_get_window
},
484 PUSH_TYPE(layout
, struct layout
)
485 CHECK_TYPE(layout
, struct layout
)
487 static const struct Xet_reg layout_getters
[] = {
492 get_layout(lua_State
*L
, void *v
)
494 push_layout(L
, (struct layout
**)v
);
502 PUSH_TYPE(display
, struct display
)
504 CHECK_TYPE(display
, struct display
)
507 display_get_canvases(lua_State
*L
)
513 d
= check_display(L
, 1);
515 for (iter
= d
->d_cvlist
, count
= 0; iter
; iter
= iter
->c_next
, count
++) {
516 lua_pushinteger(L
, count
);
517 push_canvas(L
, &iter
);
524 static const luaL_reg display_methods
[] = {
525 {"get_canvases", display_get_canvases
},
530 display_tostring(lua_State
*L
)
533 struct display
*d
= check_display(L
, 1);
534 snprintf(str
, sizeof(str
), "{display: tty = '%s', term = '%s'}", d
->d_usertty
, d
->d_termname
);
535 lua_pushstring(L
, str
);
539 static const luaL_reg display_metamethods
[] = {
540 {"__tostring", display_tostring
},
544 static const struct Xet_reg display_setters
[] = {
548 static const struct Xet_reg display_getters
[] = {
549 {"tty", get_string
, offsetof(struct display
, d_usertty
)},
550 {"term", get_string
, offsetof(struct display
, d_termname
)},
551 {"fore", get_window
, offsetof(struct display
, d_fore
)},
552 {"other", get_window
, offsetof(struct display
, d_other
)},
553 {"width", get_int
, offsetof(struct display
, d_width
)},
554 {"height", get_int
, offsetof(struct display
, d_height
)},
555 {"user", get_user
, offsetof(struct display
, d_user
)},
556 {"layout", get_layout
, offsetof(struct display
, d_layout
)},
565 screen_get_windows(lua_State
*L
)
571 for (iter
= windows
, count
= 0; iter
; iter
= iter
->w_next
, count
++) {
572 lua_pushinteger(L
, iter
->w_number
);
573 push_window(L
, &iter
);
581 screen_get_displays(lua_State
*L
)
583 struct display
*iter
;
587 for (iter
= displays
, count
= 0; iter
; iter
= iter
->d_next
, count
++) {
588 lua_pushinteger(L
, count
);
589 push_display(L
, &iter
);
597 screen_get_display(lua_State
*L
)
599 push_display(L
, &display
);
604 screen_exec_command(lua_State
*L
)
609 command
= luaL_checklstring(L
, 1, &len
);
611 RcLine((char *)command
, len
);
617 screen_append_msg(lua_State
*L
)
619 const char *msg
, *color
;
621 msg
= luaL_checklstring(L
, 1, &len
);
625 color
= luaL_checklstring(L
, 2, &len
);
626 AppendWinMsgRend(msg
, color
);
631 script_input_fn(char *buf
, int len
, char *priv
)
633 lua_State
*L
= (lua_State
*)priv
;
634 lua_pushstring(L
, buf
);
635 if (lua_pcall(L
, 1, 0, 0) == LUA_ERRRUN
)
637 if(lua_isstring(L
, -1))
645 screen_input(lua_State
*L
)
647 char * prompt
= NULL
;
649 prompt
= (char *)luaL_checkstring(L
, 1);
650 Input(prompt
, 100, INP_COOKED
, script_input_fn
, (char *)L
, 0);
655 static const luaL_reg screen_methods
[] = {
656 {"windows", screen_get_windows
},
657 {"displays", screen_get_displays
},
658 {"display", screen_get_display
},
659 {"command", screen_exec_command
},
660 {"append_msg", screen_append_msg
},
661 {"hook", LuaRegEvent
},
662 {"unhook", LuaUnRegEvent
},
663 {"input", screen_input
},
667 static const luaL_reg screen_metamethods
[] = {
671 static const struct Xet_reg screen_setters
[] = {
675 static const struct Xet_reg screen_getters
[] = {
681 /** Public functions {{{ */
689 #define REGISTER(X) struct_register(L, #X , X ## _methods, X##_metamethods, X##_setters, X##_getters)
697 /* To store handler funcs */
698 luaL_getmetatable(L
, "screen");
699 /* two kinds of info in this table:
700 * _funckey[func]->key
701 * _funckey[key]->refcnt */
702 lua_pushstring(L
, "_funckey");
705 /* two kinds of info in this table:
706 * _keyfunc[key]->func
707 * _keyfunc[func]->name */
708 lua_pushstring(L
, "_keyfunc");
716 /* An error message on top of the stack. */
718 LuaShowErr(lua_State
*L
)
720 struct display
*d
= display
;
722 const char *message
= luaL_checklstring(L
, -1, &len
);
723 LMsg(0, "%s", message
? message
: "Unknown error");
730 void (*push_fn
)(lua_State
*, void*);
735 LuaCallProcess(const char *name
, struct fn_def defs
[])
739 lua_getfield(L
, LUA_GLOBALSINDEX
, name
);
740 if (lua_isnil(L
, -1))
745 for (argc
= 0; defs
[argc
].push_fn
; argc
++)
746 defs
[argc
].push_fn(L
, defs
[argc
].value
);
747 if (lua_pcall(L
, argc
, 0, 0) == LUA_ERRRUN
&& lua_isstring(L
, -1))
755 int LuaSource(const char *file
, int async
)
760 if (stat(file
, &st
) == -1)
761 Msg(errno
, "Error loading lua script file '%s'", file
);
764 int len
= strlen(file
);
765 if (len
< 4 || strncmp(file
+ len
- 4, ".lua", 4) != 0)
767 if (luaL_dofile(L
, file
) && lua_isstring(L
, -1))
786 LuaProcessCaption(const char *caption
, struct win
*win
, int len
)
790 struct fn_def params
[] = {
791 {lua_pushstring
, caption
},
793 {lua_pushinteger
, len
},
796 return LuaCallProcess("process_caption", params
);
800 push_stringarray(lua_State
*L
, char **args
)
804 for (i
= 1; args
&& *args
; i
++) {
805 lua_pushinteger(L
, i
);
806 lua_pushstring(L
, *args
++);
812 LuaPushParams(lua_State
*L
, const char *params
, va_list va
)
820 lua_pushstring(L
, va_arg(va
, char *));
823 push_stringarray(L
, va_arg(va
, char **));
826 lua_pushinteger(L
, va_arg(va
, int));
834 int LuaCall(char *func
, char **argv
)
840 StackDump(L
, "Before LuaCall\n");
841 lua_getfield(L
, LUA_GLOBALSINDEX
, func
);
842 if (lua_isnil(L
, -1))
845 lua_pushstring(L
, "Could not find the script function\n");
849 for (argc
= 0; *argv
; argv
++, argc
++)
851 lua_pushstring(L
, *argv
);
853 if (lua_pcall(L
, argc
, 0, 0) == LUA_ERRRUN
)
855 if(lua_isstring(L
, -1))
857 StackDump(L
, "After LuaCall\n");
865 /*** Lua callback handler management {{{ */
868 LuaPushHTable(lua_State
*L
, int screen
, const char * t
)
870 lua_pushstring(L
, t
);
871 lua_rawget(L
, screen
);
872 /* FIXME: Do we need to balance the stack here? */
873 if (lua_isnil(L
, -1))
874 luaL_error(L
, "Fatal! Fail to get function registeration table!");
875 return lua_gettop(L
);
879 LuaPushHandler(lua_State
*L
, lua_handler lh
)
882 luaL_getmetatable(L
, "screen");
883 keyfunc
= LuaPushHTable(L
, -1, "_keyfunc");
884 lua_rawgeti(L
, keyfunc
, lh
);
890 LuaFuncKey(lua_State
*L
, int idx
)
892 int key
, funckey
, sc
;
893 luaL_getmetatable(L
, "screen");
895 funckey
= LuaPushHTable(L
, sc
, "_funckey");
897 lua_pushvalue(L
, idx
);
898 lua_gettable(L
, funckey
);/*funckey[func] ==?*/
899 if (lua_isnil(L
, -1))
901 /* Not found, alloc a new key */
904 lua_pushinteger(L
, 1);
905 key
= luaL_ref(L
, funckey
);
907 /*funckey[func]=key*/
908 lua_pushvalue(L
, idx
);
909 lua_pushinteger(L
, key
);
910 lua_settable(L
, funckey
);
912 int keyfunc
= LuaPushHTable(L
, sc
, "_keyfunc");
913 /*keyfunc[key] = func*/
914 lua_pushinteger(L
, key
);
915 lua_pushvalue(L
, idx
);
916 lua_settable(L
, keyfunc
);
921 key
= lua_tointeger(L
, -1);/*key = funckey[func]*/
928 LuaHRef(lua_State
*L
, int key
, int reg
)
930 int funckey
, keyfunc
, cnt
, sc
, idx
;
931 luaL_getmetatable(L
, "screen");
933 funckey
= LuaPushHTable(L
, sc
, "_funckey");
934 keyfunc
= LuaPushHTable(L
, sc
, "_keyfunc");
936 lua_rawgeti(L
, keyfunc
, key
);
939 lua_rawgeti(L
, funckey
, key
);
940 cnt
= lua_tointeger(L
, -1);/*cnt = htable[key]*/
941 if (!reg
&& cnt
<= 1)
943 /*release the last reference*/
944 luaL_unref(L
, funckey
, key
);
945 lua_pushvalue(L
, idx
);
947 lua_settable(L
, funckey
); /*htable[func]=key*/
951 lua_pushinteger(L
, key
);
952 lua_pushinteger(L
, reg
? cnt
+ 1 : cnt
- 1);
953 lua_settable(L
, funckey
); /*htable[key] = cnt + 1*/
959 LuaHSetName(lua_State
*L
, int key
, int name
)
962 luaL_getmetatable(L
, "screen");
964 keyfunc
= LuaPushHTable(L
, sc
, "_keyfunc");
966 lua_rawgeti(L
, keyfunc
, key
);
967 lua_pushvalue(L
, name
);
968 lua_rawset(L
, keyfunc
);
973 /* Do not hold the return value for long */
975 LuaHGetName(lua_State
*L
, lua_handler key
)
979 luaL_getmetatable(L
, "screen");
981 keyfunc
= LuaPushHTable(L
, sc
, "_keyfunc");
983 lua_rawgeti(L
, keyfunc
, key
);
984 lua_rawget(L
, keyfunc
);
985 name
= lua_tostring(L
, -1);
991 LuaCheckHandler(lua_State
*L
, int idx
, int reg
)
993 int name
= 0, key
, sc
;
994 if (lua_isstring(L
, idx
))
996 const char * handler
;
997 /* registered with func name.*/
998 handler
= luaL_checkstring(L
, idx
);
1000 lua_getfield(L
, LUA_GLOBALSINDEX
, handler
);
1001 if (!lua_isfunction(L
, -1))
1002 luaL_error(L
, "The specified handler %s in param #%d is not a function", handler
, idx
);
1004 else if (!lua_isfunction(L
, idx
))
1005 luaL_error(L
, "Handler should be a function or the name of function");
1008 key
= LuaFuncKey(L
, idx
);
1009 LuaHRef(L
, key
, reg
);
1012 LuaHSetName(L
, key
, name
);
1015 return LuaAllocHandler(key
);
1021 LuaDispatch(void *handler
, const char *params
, va_list va
)
1023 lua_handler lh
= (lua_handler
)handler
;
1026 StackDump(L
, "before dispatch");
1028 LuaPushHandler(L
, lh
);
1029 if (lua_isnil(L
, -1))
1034 argc
= LuaPushParams(L
, params
, va
);
1036 if (lua_pcall(L
, argc
, 1, 0) == LUA_ERRRUN
&& lua_isstring(L
, -1))
1038 StackDump(L
, "After LuaDispatch\n");
1042 retvalue
= lua_tonumber(L
, -1);
1047 int LuaForeWindowChanged(void)
1049 struct fn_def params
[] = {
1050 {push_display
, &display
},
1051 {push_window
, display
? &D_fore
: &fore
},
1056 return LuaCallProcess("fore_changed", params
);
1059 #define SEVNAME_MAX 30
1061 LuaRegEvent(lua_State
*L
)
1063 /* signature: hook(obj, event, handler, priv);
1064 * or: hook(event, handler, priv)
1065 * returns: A ticket for later unregister. */
1066 int idx
= 1, argc
= lua_gettop(L
);
1067 unsigned int priv
= 31; /* Default privilege */
1071 const char *objname
= "global";
1073 static char evbuf
[SEVNAME_MAX
];
1076 struct script_event
*sev
;
1078 StackDump(L
, "Before RegEvent\n");
1080 /* Identify the object, if specified */
1081 if (luaL_getmetafield(L
, 1, "_objname"))
1083 objname
= luaL_checkstring(L
, -1);
1085 if (!strcmp("screen", objname
))
1088 obj
= *(char **)lua_touserdata(L
, 1);
1092 event
= luaL_checkstring(L
, idx
++);
1093 snprintf(evbuf
, SEVNAME_MAX
, "%s_%s", objname
, event
);
1095 /* Check and get the handler */
1096 lh
= LuaCheckHandler(L
, idx
++, 1);
1098 luaL_error(L
, "Out of memory");
1100 StackDump(L
, "In RegEvent\n");
1103 priv
= luaL_checkinteger(L
, idx
);
1105 sev
= object_get_event(obj
, evbuf
);
1109 l
= (struct listener
*)malloc(sizeof(struct listener
));
1111 return luaL_error(L
, "Out of memory");
1113 l
->dispatcher
= LuaDispatch
;
1114 if (register_listener(sev
, l
))
1116 const char *fname
= LuaHGetName(L
, lh
);
1119 return luaL_error(L
, "Handler %s has already been registered", fname
);
1121 return luaL_error(L
, "Handler has already been registered");
1123 /* Return the handler for un-register */
1124 l
->handler
= (void *)lh
;
1125 lua_pushlightuserdata(L
, l
);
1128 return luaL_error(L
, "Invalid event specified: %s for object %s", event
, objname
);
1130 StackDump(L
, "After RegEvent\n");
1135 LuaUnRegEvent(lua_State
*L
)
1137 /* signature: unhook([obj], ticket)
1138 * returns: true of success, false otherwise */
1142 /* If the param is not as expected */
1143 if (!lua_islightuserdata(L
, idx
))
1145 /* Then it should be the userdata to be ignore, but if not ... */
1146 if (!lua_isuserdata(L
, idx
))
1147 luaL_checktype(L
, idx
, LUA_TLIGHTUSERDATA
);
1149 luaL_checktype(L
, idx
, LUA_TLIGHTUSERDATA
);
1152 l
= (struct listener
*)lua_touserdata(L
, idx
++);
1154 /* Validate the listener structure */
1155 if (!l
|| !l
->handler
)
1158 lua_pushboolean(L
,0);
1162 LuaHRef(L
, (lua_handler
)l
->handler
, 0);
1163 LuaFreeHandler(((lua_handler
)&(l
->handler
)));
1164 unregister_listener(l
);
1165 lua_pushboolean(L
, 1);
1173 struct ScriptFuncs LuaFuncs
=
1175 LuaForeWindowChanged
,
1179 struct binding lua_binding
=