663eddbb64511040aeb8a947e22d1156e8a2ee36
[screen-lua.git] / src / script.c
blob663eddbb64511040aeb8a947e22d1156e8a2ee36
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 <stddef.h>
26 /*Binding structure & functions*/
28 struct binding *bindings = NULL;
30 static void
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;
41 #ifdef LUA_BINDING
42 extern struct binding lua_binding;
43 #endif
45 void LoadBindings(void)
47 #ifdef LUA_BINDING
48 register_binding(&lua_binding);
49 #endif
52 void
53 FinalizeBindings (void)
55 struct binding *binding=bindings;
56 while(binding)
58 if (binding->inited)
59 binding->bd_Finit();
60 binding = binding->b_next;
64 void
65 ScriptSource(int argc, const char **argv)
67 int ret = 0;
68 int async = 0;
69 const char *bd_select = 0, *script;
70 struct binding *binding = bindings;
72 /* Parse the commandline options
73 * sourcescript [-async|-a] [-binding|-b <binding>] script
75 while (*argv && **argv == '-')
77 /* check for (-a | -async) */
78 const char *arg = *argv;
79 if ((arg[1] == 'a' && !arg[2])
80 || strcmp(arg, "-async") == 0)
81 async = 1;
82 /* check for (-b | -binding) */
83 else if ((arg[1] == 'b' && !arg[2])
84 || strcmp(arg, "-binding") == 0) {
85 argv++;
86 bd_select = *argv;
88 argv++;
90 script = *argv;
92 while (binding) {
93 if (!bd_select || strcmp(bd_select, binding->name) == 0) {
94 /*dynamically initialize the binding*/
95 if (!binding->inited)
97 binding->bd_Init();
98 binding->inited = 1;
101 /*and source the script*/
102 if (ret = binding->bd_Source(script, async))
103 break;
105 binding = binding->b_next;
107 if (!ret)
108 LMsg(1, "Could not source specified script %s", script);
112 ScriptCall(const char *func, const char **argv)
114 /*TODO*/
115 return LuaCall(func, argv);
118 void
119 ScriptCmd(int argc, const char **argv)
121 const char * sub = *argv;
122 argv++;argc--;
123 if (!strcmp(sub, "call"))
124 ScriptCall(*argv, argv+1);
125 else if (!strcmp(sub, "source"))
126 ScriptSource(argc, argv);
129 /* Event notification handling */
131 struct gevents globalevents;
133 /* To add a new event, introduce a field for that event to the object in
134 * question, and don't forget to put an descriptor here. NOTE: keep the
135 * name field sorted in alphabet order, the searching relies on it.
137 * the params string specifies the expected parameters. The length of the
138 * string equals to the number of parameters. Each char specifies the type of
139 * the parameter, with its meaning similar to those in printf().
141 * s: string (char *)
142 * S: string array (char **)
143 * i: signed int
144 * d: display
147 struct sev_description {
148 char *name;
149 char *params;
150 int offset;
151 } event_table[] = {
152 /* Global events */
153 {"global_cmdexecuted", "sS", offsetof(struct gevents, cmdexecuted)},
154 {"global_detached", "di", offsetof(struct gevents, detached)},
155 /* The command "detach" triggers both 'cmdexecuted' and 'detached' events.
156 However, we need the 'detached' event to trigger callbacks from remote detaches.
159 /* Window events */
160 {"window_resize", "", offsetof(struct win, w_sev.resize)},
161 {"window_can_resize", "", offsetof(struct win, w_sev.canresize)}
164 /* Get the event queue with the given name in the obj. If the obj is NULL,
165 * global events are searched. If no event is found, a NULL is returned.
167 struct script_event *
168 object_get_event(char *obj, const char *name)
170 int lo, hi, n, cmp;
171 if (!obj)
172 obj = (char *)&globalevents;
174 lo = 0;
175 n = hi = sizeof(event_table) / sizeof(struct sev_description);
176 while (lo < hi)
178 int half;
179 half = (lo + hi) >> 1;
180 cmp = strcmp(name, event_table[half].name);
181 if (cmp > 0)
182 lo = half + 1;
183 else
184 hi = half;
187 if (lo >= n || strcmp(name, event_table[lo].name))
188 return 0;
189 else
191 /*found an entry.*/
192 struct script_event *res;
193 res = (struct script_event *) (obj + event_table[lo].offset);
194 /*Setup the parameter record.*/
195 res->params = event_table[lo].params;
196 return res;
200 /* Put a listener in a proper position in the chain
201 * according to the privlege.
202 * Not insert duplicate entry. return zero if successful.*/
204 register_listener(struct script_event *ev, struct listener *l)
206 unsigned int priv = l->priv;
207 struct listener *p, *iter = &ev->listeners;
209 while(iter->chain && priv >= iter->chain->priv)
211 iter = iter->chain;
212 /* return if duplicate found*/
213 if (iter->bd == l->bd
214 && !iter->bd->bd_hdlrcmp(iter->handler, l->handler))
215 return 1;
217 p = iter;
219 while(iter->chain)
221 iter = iter->chain;
222 /* return if duplicate found*/
223 if (iter->bd == l->bd
224 && !iter->bd->bd_hdlrcmp(iter->handler, l->handler))
225 return 1;
228 l->chain = p->chain;
229 l->prev = p;
230 if (p->chain)
231 p->chain->prev = l;
232 p->chain = l;
233 return 0;
236 void
237 unregister_listener(struct listener *l)
239 struct listener *p = l->prev;
240 p->chain = l->chain;
241 if (l->chain)
242 l->chain->prev = p;
243 l->chain = l->prev = 0;
244 l->handler = 0;
245 free(l);
248 /* Trigger event with given parameters.*/
250 trigger_sevent(struct script_event *ev, VA_DOTS)
252 int res = 0;
253 struct listener *chain;
254 char *params;
255 VA_LIST(va);
256 /*invalid or un-registered event structure*/
257 if (!ev || !ev->params)
258 return 0;
260 /*process the chain in order, stop if any of the handler returns true.*/
261 chain = ev->listeners.chain;
262 params = ev->params;
263 while (chain)
265 VA_START(va, ev);
266 res = chain->bd->bd_dispatch(chain->handler, params, va);
267 VA_END(va);
268 if (res)
269 break;
270 chain = chain->chain;
273 return res;
276 #define ALL_SCRIPTS(fn, params, stop) do { \
277 struct binding *iter; \
278 for (iter = bindings; iter; iter = iter->b_next) \
280 if (iter->fns && iter->fns->fn && (ret = (iter->fns->fn params)) && stop) \
281 break; \
283 } while (0)
285 void ScriptForeWindowChanged(void)
287 int ret;
288 ALL_SCRIPTS(sf_ForeWindowChanged, (), 0);
291 int ScriptProcessCaption(const char *str, struct win *win, int len)
293 int ret = 0;
294 ALL_SCRIPTS(sf_ProcessCaption, (str, win, len), 1);
295 return ret;