Added test for uploading big files.
[elinks.git] / src / scripting / smjs / keybinding.c
blobeff4c545019a9a2514ccd5882beebb4d5d9c633c
1 /* "elinks.keymaps" */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include "elinks.h"
9 #include "config/kbdbind.h"
10 #include "ecmascript/spidermonkey/util.h"
11 #include "main/event.h"
12 #include "scripting/smjs/core.h"
13 #include "scripting/smjs/elinks_object.h"
14 #include "util/memory.h"
16 static const JSClass keymap_class; /* defined below */
18 /* @keymap_class.getProperty */
19 static JSBool
20 keymap_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
22 unsigned char *action_str;
23 const unsigned char *keystroke_str;
24 int *data;
26 /* This can be called if @obj if not itself an instance of the
27 * appropriate class but has one in its prototype chain. Fail
28 * such calls. */
29 if (!JS_InstanceOf(ctx, obj, (JSClass *) &keymap_class, NULL))
30 return JS_FALSE;
32 data = JS_GetInstancePrivate(ctx, obj,
33 (JSClass *) &keymap_class, NULL);
35 keystroke_str = JS_GetStringBytes(JS_ValueToString(ctx, id));
36 if (!keystroke_str) goto ret_null;
38 action_str = get_action_name_from_keystroke((enum keymap_id) *data,
39 keystroke_str);
40 if (!action_str) goto ret_null;
42 *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(ctx, action_str));
44 return JS_TRUE;
46 ret_null:
47 *vp = JSVAL_NULL;
49 return JS_TRUE;
52 static enum evhook_status
53 smjs_keybinding_action_callback(va_list ap, void *data)
55 jsval rval;
56 struct session *ses = va_arg(ap, struct session *);
57 JSObject *jsobj = data;
58 JSFunction *func = JS_ValueToFunction(smjs_ctx, OBJECT_TO_JSVAL(jsobj));
60 evhook_use_params(ses);
62 assert(func);
64 smjs_ses = ses;
66 JS_CallFunction(smjs_ctx, NULL, func, 0, NULL, &rval);
68 smjs_ses = NULL;
70 return EVENT_HOOK_STATUS_LAST;
73 /* @keymap_class.setProperty */
74 static JSBool
75 keymap_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
77 int *data;
78 unsigned char *keymap_str;
79 const unsigned char *keystroke_str;
81 /* This can be called if @obj if not itself an instance of the
82 * appropriate class but has one in its prototype chain. Fail
83 * such calls. */
84 if (!JS_InstanceOf(ctx, obj, (JSClass *) &keymap_class, NULL))
85 return JS_FALSE;
87 data = JS_GetInstancePrivate(ctx, obj,
88 (JSClass *) &keymap_class, NULL);
90 /* Ugly fact: we need to get the string from the id to give to bind_do,
91 * which will of course then convert the string back to an id... */
92 keymap_str = get_keymap_name((enum keymap_id) *data);
93 if (!keymap_str) return JS_FALSE;
95 keystroke_str = JS_GetStringBytes(JS_ValueToString(ctx, id));
96 if (!keystroke_str) return JS_FALSE;
98 if (JSVAL_IS_STRING(*vp)) {
99 unsigned char *action_str;
101 action_str = JS_GetStringBytes(JS_ValueToString(ctx, *vp));
102 if (!action_str) return JS_FALSE;
104 if (bind_do(keymap_str, keystroke_str, action_str, 0))
105 return JS_FALSE;
107 return JS_TRUE;
109 } else if (JSVAL_IS_OBJECT(*vp)) {
110 unsigned char *err = NULL;
111 int event_id;
112 struct string event_name = NULL_STRING;
113 JSObject *jsobj = JSVAL_TO_OBJECT(*vp);
115 if (JS_FALSE == JS_ObjectIsFunction(ctx, jsobj))
116 return JS_FALSE;
118 if (!init_string(&event_name)) return JS_FALSE;
120 add_format_to_string(&event_name, "smjs-run-func %p", jsobj);
122 event_id = bind_key_to_event_name(keymap_str,
123 keystroke_str,
124 event_name.source, &err);
126 done_string(&event_name);
128 if (err) {
129 alert_smjs_error(err);
131 return JS_FALSE;
134 event_id = register_event_hook(event_id,
135 smjs_keybinding_action_callback,
136 0, (void *) jsobj);
138 if (event_id == EVENT_NONE) {
139 alert_smjs_error("error registering event hook"
140 " for keybinding");
142 return JS_FALSE;
145 return JS_TRUE;
148 return JS_FALSE;
151 /* @keymap_class.finalize */
152 static void
153 keymap_finalize(JSContext *ctx, JSObject *obj)
155 void *data;
157 assert(JS_InstanceOf(ctx, obj, (JSClass *) &keymap_class, NULL));
158 if_assert_failed return;
160 data = JS_GetInstancePrivate(ctx, obj,
161 (JSClass *) &keymap_class, NULL);
163 mem_free(data);
166 static const JSClass keymap_class = {
167 "keymap",
168 JSCLASS_HAS_PRIVATE, /* int * */
169 JS_PropertyStub, JS_PropertyStub,
170 keymap_get_property, keymap_set_property,
171 JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, keymap_finalize,
174 static JSObject *
175 smjs_get_keymap_object(enum keymap_id keymap_id)
177 int *data;
178 JSObject *keymap_object;
180 assert(smjs_ctx);
182 keymap_object = JS_NewObject(smjs_ctx, (JSClass *) &keymap_class,
183 NULL, NULL);
185 if (!keymap_object) return NULL;
187 data = intdup(keymap_id);
188 if (!data) return NULL;
190 if (JS_TRUE == JS_SetPrivate(smjs_ctx, keymap_object, data)) /* to @keymap_class */
191 return keymap_object;
193 mem_free(data);
195 return NULL;
198 static const JSClass keymaps_hash_class = {
199 "keymaps_hash",
200 JSCLASS_HAS_PRIVATE,
201 JS_PropertyStub, JS_PropertyStub,
202 JS_PropertyStub, JS_PropertyStub,
203 JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
206 static JSObject *
207 smjs_get_keymap_hash_object(void)
209 jsval val;
210 enum keymap_id keymap_id;
211 JSObject *keymaps_hash;
213 keymaps_hash = JS_NewObject(smjs_ctx, (JSClass *) &keymaps_hash_class,
214 NULL, NULL);
215 if (!keymaps_hash) return NULL;
217 for (keymap_id = 0; keymap_id < KEYMAP_MAX; ++keymap_id) {
218 unsigned char *keymap_str = get_keymap_name(keymap_id);
219 JSObject *map = smjs_get_keymap_object(keymap_id);
221 assert(keymap_str);
223 if (!map) return NULL;
225 val = OBJECT_TO_JSVAL(map);
227 JS_SetProperty(smjs_ctx, keymaps_hash, keymap_str, &val);
230 return keymaps_hash;
233 void
234 smjs_init_keybinding_interface(void)
236 jsval val;
237 struct JSObject *keymaps_hash;
239 if (!smjs_ctx || !smjs_elinks_object)
240 return;
242 keymaps_hash = smjs_get_keymap_hash_object();
243 if (!keymaps_hash) return;
245 val = OBJECT_TO_JSVAL(keymaps_hash);
247 JS_SetProperty(smjs_ctx, smjs_elinks_object, "keymaps", &val);