1 /* Copyright (c) 2008 Sadrul Habib Chowdhury (sadrul@users.sf.net)
2 * 2009 Rui Guo (firemeteor.guo@gmail.com)
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3, or (at your option)
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program (see the file COPYING); if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
19 ****************************************************************
26 /*Binding structure & functions*/
28 struct binding
*bindings
= NULL
;
31 register_binding (struct binding
*new_binding
)
33 if (!new_binding
->registered
)
35 new_binding
->b_next
= bindings
;
36 bindings
= new_binding
;
37 new_binding
->registered
= 1;
42 extern struct binding lua_binding
;
46 extern struct binding py_binding
;
49 void LoadBindings(void)
52 register_binding(&lua_binding
);
56 register_binding(&py_binding
);
61 FinalizeBindings (void)
63 struct binding
*binding
=bindings
;
68 binding
= binding
->b_next
;
73 ScriptSource(int argc
, const char **argv
)
77 const char *bd_select
= 0, *script
;
78 struct binding
*binding
= bindings
;
80 /* Parse the commandline options
81 * sourcescript [-async|-a] [-binding|-b <binding>] script
83 while (*argv
&& **argv
== '-')
85 /* check for (-a | -async) */
86 const char *arg
= *argv
;
87 if ((arg
[1] == 'a' && !arg
[2])
88 || strcmp(arg
, "-async") == 0)
90 /* check for (-b | -binding) */
91 else if ((arg
[1] == 'b' && !arg
[2])
92 || strcmp(arg
, "-binding") == 0) {
101 if (!bd_select
|| strcmp(bd_select
, binding
->name
) == 0) {
102 /*dynamically initialize the binding*/
103 if (!binding
->inited
)
109 /*and source the script*/
110 if (ret
= binding
->bd_Source(script
, async
))
113 binding
= binding
->b_next
;
116 LMsg(1, "Could not source specified script %s", script
);
120 ScriptCall(const char *func
, const char **argv
)
123 return LuaCall(func
, argv
);
127 ScriptCmd(int argc
, const char **argv
)
129 const char * sub
= *argv
;
131 if (!strcmp(sub
, "call"))
132 ScriptCall(*argv
, argv
+1);
133 else if (!strcmp(sub
, "source"))
134 ScriptSource(argc
, argv
);
137 /* Event notification handling */
139 struct gevents globalevents
;
141 /* To add a new event, introduce a field for that event to the object in
142 * question, and don't forget to put an descriptor here. NOTE: keep the
143 * name field sorted in alphabet order, the searching relies on it.
145 * the params string specifies the expected parameters. The length of the
146 * string equals to the number of parameters. Each char specifies the type of
147 * the parameter, with its meaning similar to those in printf().
150 * S: string array (char **)
155 struct sev_description
{
161 {"global_cmdexecuted", "sS", offsetof(struct gevents
, cmdexecuted
)},
162 {"global_detached", "di", offsetof(struct gevents
, detached
)},
163 /* The command "detach" triggers both 'cmdexecuted' and 'detached' events.
164 However, we need the 'detached' event to trigger callbacks from remote detaches.
168 {"window_resize", "", offsetof(struct win
, w_sev
.resize
)},
169 {"window_can_resize", "", offsetof(struct win
, w_sev
.canresize
)}
172 /* Get the event queue with the given name in the obj. If the obj is NULL,
173 * global events are searched. If no event is found, a NULL is returned.
175 struct script_event
*
176 object_get_event(char *obj
, const char *name
)
180 obj
= (char *)&globalevents
;
183 n
= hi
= sizeof(event_table
) / sizeof(struct sev_description
);
187 half
= (lo
+ hi
) >> 1;
188 cmp
= strcmp(name
, event_table
[half
].name
);
195 if (lo
>= n
|| strcmp(name
, event_table
[lo
].name
))
200 struct script_event
*res
;
201 res
= (struct script_event
*) (obj
+ event_table
[lo
].offset
);
202 /*Setup the parameter record.*/
203 res
->params
= event_table
[lo
].params
;
208 /* Put a listener in a proper position in the chain
209 * according to the privlege.
210 * Not insert duplicate entry. return zero if successful.*/
212 register_listener(struct script_event
*ev
, struct listener
*l
)
214 unsigned int priv
= l
->priv
;
215 struct listener
*p
, *iter
= &ev
->listeners
;
218 while(iter
->chain
&& priv
>= iter
->chain
->priv
)
221 /* return if duplicate found*/
222 if (iter
->handler
== l
->handler
223 && iter
->dispatcher
== l
->dispatcher
)
238 unregister_listener(struct listener
*l
)
240 struct listener
*p
= l
->prev
;
244 l
->chain
= l
->prev
= 0;
249 /* Trigger event with given parameters.*/
251 trigger_sevent(struct script_event
*ev
, VA_DOTS
)
254 struct listener
*chain
;
257 /*invalid or un-registered event structure*/
258 if (!ev
|| !ev
->params
)
261 /*process the chain in order, stop if any of the handler returns true.*/
262 chain
= ev
->listeners
.chain
;
267 res
= chain
->dispatcher(chain
->handler
, params
, va
);
271 chain
= chain
->chain
;
277 #define ALL_SCRIPTS(fn, params, stop) do { \
278 struct binding *iter; \
279 for (iter = bindings; iter; iter = iter->b_next) \
281 if (iter->fns && iter->fns->fn && (ret = (iter->fns->fn params)) && stop) \
286 void ScriptForeWindowChanged(void)
289 ALL_SCRIPTS(sf_ForeWindowChanged
, (), 0);
292 int ScriptProcessCaption(const char *str
, struct win
*win
, int len
)
295 ALL_SCRIPTS(sf_ProcessCaption
, (str
, win
, len
), 1);