Start implementation of setters.
[screen-lua.git] / src / script.c
blob6f20bc404c3c85d51089b11952e3e50dd14f7d46
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)
7 * any later version.
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 ****************************************************************
22 #include "config.h"
23 #include "screen.h"
24 #include "extern.h"
25 #include <stddef.h>
27 /*Binding structure & functions*/
29 struct binding *bindings = NULL;
31 static void
32 register_binding (struct binding *new_binding)
34 if (!new_binding->registered)
36 new_binding->b_next = bindings;
37 bindings = new_binding;
38 new_binding->registered = 1;
42 #ifdef LUA_BINDING
43 extern struct binding lua_binding;
44 #endif
46 #ifdef PY_BINDING
47 extern struct binding py_binding;
48 #endif
50 void LoadBindings(void)
52 #ifdef LUA_BINDING
53 register_binding(&lua_binding);
54 #endif
56 #ifdef PY_BINDING
57 register_binding(&py_binding);
58 #endif
61 void
62 FinalizeBindings (void)
64 struct binding *binding=bindings;
65 while(binding)
67 if (binding->inited)
68 binding->bd_Finit();
69 binding = binding->b_next;
73 void
74 ScriptSource(int argc, const char **argv)
76 int ret = 0;
77 int async = 0;
78 const char *bd_select = 0, *script;
79 struct binding *binding = bindings;
81 /* Parse the commandline options
82 * script source [-async|-a] [-binding|-b <binding>] script
84 while (*argv && **argv == '-')
86 /* check for (-a | -async) */
87 const char *arg = *argv;
88 if ((arg[1] == 'a' && !arg[2])
89 || strcmp(arg, "-async") == 0)
90 async = 1;
91 /* check for (-b | -binding) */
92 else if ((arg[1] == 'b' && !arg[2])
93 || strcmp(arg, "-binding") == 0)
95 argv++;
96 bd_select = *argv;
98 argv++;
100 script = *argv;
102 while (binding)
104 if (!bd_select || strcmp(bd_select, binding->name) == 0)
106 /*dynamically initialize the binding*/
107 if (!binding->inited)
109 binding->bd_Init();
110 binding->inited = 1;
113 /*and source the script*/
114 ret = binding->bd_Source(script, async);
115 if (ret)
116 break;
118 binding = binding->b_next;
120 if (!ret)
121 LMsg(0, "Could not source specified script %s", script);
125 ScriptCall(int argc, const char **argv)
127 int ret = 0;
128 struct binding *binding = bindings;
129 const char *bd_select = 0, *func;
130 /* Parse the commandline options
131 * script call [-binding|-b <binding>] function
133 while (*argv && **argv == '-')
135 const char *arg = *argv;
136 /* check for (-b | -binding) */
137 if ((arg[1] == 'b' && !arg[2])
138 || strcmp(arg, "-binding") == 0)
140 argv++;
141 bd_select = *argv;
143 argv++;
145 func = *argv;
146 argv++;
148 while (binding)
150 if (!bd_select || strcmp(bd_select, binding->name) == 0)
152 ret = binding->bd_call(func, argv);
153 if (ret)
154 break;
156 binding = binding->b_next;
159 if (!ret)
160 LMsg(0, "Failed to run specified script coummand '%s'", func);
161 return ret;
164 void
165 ScriptCmd(int argc, const char **argv)
167 const char * sub = *argv;
168 argv++;argc--;
169 if (!strcmp(sub, "call"))
170 ScriptCall(argc, argv);
171 else if (!strcmp(sub, "source"))
172 ScriptSource(argc, argv);
175 /* Event notification handling */
177 struct gevents globalevents;
179 /* To add a new event, introduce a field for that event to the object in
180 * question, and don't forget to put an descriptor here. NOTE: keep the
181 * name field sorted in alphabet order, the searching relies on it.
183 * the params string specifies the expected parameters. The length of the
184 * string equals to the number of parameters. Each char specifies the type of
185 * the parameter, with its meaning similar to those in printf().
187 * s: string (char *)
188 * S: string array (char **)
189 * i: signed int
190 * d: display
193 struct sev_description {
194 char *name;
195 char *params;
196 int offset;
197 } event_table[] = {
198 /* Global events */
199 {"global_cmdexecuted", "sS", offsetof(struct gevents, cmdexecuted)},
200 {"global_detached", "di", offsetof(struct gevents, detached)},
201 /* The command "detach" triggers both 'cmdexecuted' and 'detached' events.
202 However, we need the 'detached' event to trigger callbacks from remote detaches.
205 /* Window events */
206 {"window_resize", "", offsetof(struct win, w_sev.resize)},
207 {"window_can_resize", "", offsetof(struct win, w_sev.canresize)}
210 /* Get the event queue with the given name in the obj. If the obj is NULL,
211 * global events are searched. If no event is found, a NULL is returned.
213 struct script_event *
214 object_get_event(char *obj, const char *name)
216 int lo, hi, n, cmp;
217 if (!obj)
218 obj = (char *)&globalevents;
220 lo = 0;
221 n = hi = sizeof(event_table) / sizeof(struct sev_description);
222 while (lo < hi)
224 int half;
225 half = (lo + hi) >> 1;
226 cmp = strcmp(name, event_table[half].name);
227 if (cmp > 0)
228 lo = half + 1;
229 else
230 hi = half;
233 if (lo >= n || strcmp(name, event_table[lo].name))
234 return 0;
235 else
237 /*found an entry.*/
238 struct script_event *res;
239 res = (struct script_event *) (obj + event_table[lo].offset);
240 /*Setup the parameter record.*/
241 res->params = event_table[lo].params;
242 return res;
246 /* Put a listener in a proper position in the chain
247 * according to the privlege.
248 * Not insert duplicate entry. return zero if successful.*/
250 register_listener(struct script_event *ev, struct listener *l)
252 unsigned int priv = l->priv;
253 struct listener *p, *iter = &ev->listeners;
255 #if 0
256 while(iter->chain && priv >= iter->chain->priv)
258 iter = iter->chain;
259 /* return if duplicate found*/
260 if (iter->handler == l->handler
261 && iter->dispatcher == l->dispatcher)
262 return 1;
264 #endif
265 p = iter;
267 l->chain = p->chain;
268 l->prev = p;
269 if (p->chain)
270 p->chain->prev = l;
271 p->chain = l;
272 return 0;
275 void
276 unregister_listener(struct listener *l)
278 struct listener *p = l->prev;
279 p->chain = l->chain;
280 if (l->chain)
281 l->chain->prev = p;
282 l->chain = l->prev = 0;
283 l->handler = 0;
284 free(l);
287 /* Trigger event with given parameters.*/
289 trigger_sevent(struct script_event *ev, VA_DOTS)
291 int res = 0;
292 struct listener *chain;
293 char *params;
294 VA_LIST(va);
295 /*invalid or un-registered event structure*/
296 if (!ev || !ev->params)
297 return 0;
299 /*process the chain in order, stop if any of the handler returns true.*/
300 chain = ev->listeners.chain;
301 params = ev->params;
302 while (chain)
304 VA_START(va, ev);
305 res = chain->dispatcher(chain->handler, params, va);
306 VA_END(va);
307 if (res)
308 break;
309 chain = chain->chain;
312 return res;
315 #define ALL_SCRIPTS(fn, params, stop) do { \
316 struct binding *iter; \
317 for (iter = bindings; iter; iter = iter->b_next) \
319 if (iter->fns && iter->fns->fn && (ret = (iter->fns->fn params)) && stop) \
320 break; \
322 } while (0)
324 void ScriptForeWindowChanged(void)
326 int ret;
327 ALL_SCRIPTS(sf_ForeWindowChanged, (), 0);
330 int ScriptProcessCaption(const char *str, struct win *win, int len)
332 int ret = 0;
333 ALL_SCRIPTS(sf_ProcessCaption, (str, win, len), 1);
334 return ret;