Retry only for https protocol
[elinks.git] / src / scripting / smjs / keybinding.c
blob0ddf421b336d6e8f74e1ec63813af5ea3c43919e
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-shared.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, jsid id, jsval *vp)
22 unsigned char *action_str;
23 const unsigned char *keystroke_str;
24 int *data;
25 jsval tmp;
27 /* This can be called if @obj if not itself an instance of the
28 * appropriate class but has one in its prototype chain. Fail
29 * such calls. */
30 if (!JS_InstanceOf(ctx, obj, (JSClass *) &keymap_class, NULL))
31 return JS_FALSE;
33 data = JS_GetInstancePrivate(ctx, obj,
34 (JSClass *) &keymap_class, NULL);
36 if (!JS_IdToValue(ctx, id, &tmp))
37 goto ret_null;
39 keystroke_str = JS_EncodeString(ctx, JS_ValueToString(ctx, tmp));
40 if (!keystroke_str) goto ret_null;
42 action_str = get_action_name_from_keystroke((enum keymap_id) *data,
43 keystroke_str);
44 if (!action_str || !strcmp(action_str, "none")) goto ret_null;
46 *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(ctx, action_str));
48 return JS_TRUE;
50 ret_null:
51 *vp = JSVAL_NULL;
53 return JS_TRUE;
56 static enum evhook_status
57 smjs_keybinding_action_callback(va_list ap, void *data)
59 jsval rval;
60 struct session *ses = va_arg(ap, struct session *);
61 JSObject *jsobj = data;
63 evhook_use_params(ses);
65 smjs_ses = ses;
67 JS_CallFunctionValue(smjs_ctx, NULL, OBJECT_TO_JSVAL(jsobj),
68 0, NULL, &rval);
70 smjs_ses = NULL;
72 return EVENT_HOOK_STATUS_LAST;
75 /* @keymap_class.setProperty */
76 static JSBool
77 keymap_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
79 int *data;
80 unsigned char *keymap_str;
81 jsval val;
82 const unsigned char *keystroke_str;
84 /* This can be called if @obj if not itself an instance of the
85 * appropriate class but has one in its prototype chain. Fail
86 * such calls. */
87 if (!JS_InstanceOf(ctx, obj, (JSClass *) &keymap_class, NULL))
88 return JS_FALSE;
90 data = JS_GetInstancePrivate(ctx, obj,
91 (JSClass *) &keymap_class, NULL);
93 /* Ugly fact: we need to get the string from the id to give to bind_do,
94 * which will of course then convert the string back to an id... */
95 keymap_str = get_keymap_name((enum keymap_id) *data);
96 if (!keymap_str) return JS_FALSE;
98 JS_IdToValue(ctx, id, &val);
99 keystroke_str = JS_EncodeString(ctx, JS_ValueToString(ctx, val));
100 if (!keystroke_str) return JS_FALSE;
102 if (JSVAL_IS_STRING(*vp)) {
103 unsigned char *action_str;
105 action_str = JS_EncodeString(ctx, JS_ValueToString(ctx, *vp));
106 if (!action_str) return JS_FALSE;
108 if (bind_do(keymap_str, keystroke_str, action_str, 0))
109 return JS_FALSE;
111 return JS_TRUE;
113 } else if (JSVAL_IS_NULL(*vp)) { /* before JSVAL_IS_OBJECT */
114 if (bind_do(keymap_str, keystroke_str, "none", 0))
115 return JS_FALSE;
117 return JS_TRUE;
119 } else if (JSVAL_IS_OBJECT(*vp)) {
120 unsigned char *err = NULL;
121 int event_id;
122 struct string event_name = NULL_STRING;
123 JSObject *jsobj = JSVAL_TO_OBJECT(*vp);
125 if (JS_FALSE == JS_ObjectIsFunction(ctx, jsobj))
126 return JS_FALSE;
128 if (!init_string(&event_name)) return JS_FALSE;
130 add_format_to_string(&event_name, "smjs-run-func %p", jsobj);
132 event_id = bind_key_to_event_name(keymap_str,
133 keystroke_str,
134 event_name.source, &err);
136 done_string(&event_name);
138 if (err) {
139 alert_smjs_error(err);
141 return JS_FALSE;
144 event_id = register_event_hook(event_id,
145 smjs_keybinding_action_callback,
146 0, (void *) jsobj);
148 if (event_id == EVENT_NONE) {
149 alert_smjs_error("error registering event hook"
150 " for keybinding");
152 return JS_FALSE;
155 return JS_TRUE;
158 return JS_FALSE;
161 /* @keymap_class.finalize */
162 static void
163 keymap_finalize(JSContext *ctx, JSObject *obj)
165 void *data;
167 assert(JS_InstanceOf(ctx, obj, (JSClass *) &keymap_class, NULL));
168 if_assert_failed return;
170 data = JS_GetInstancePrivate(ctx, obj,
171 (JSClass *) &keymap_class, NULL);
173 mem_free(data);
176 static const JSClass keymap_class = {
177 "keymap",
178 JSCLASS_HAS_PRIVATE, /* int * */
179 JS_PropertyStub, JS_PropertyStub,
180 keymap_get_property, keymap_set_property,
181 JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, keymap_finalize,
184 static JSObject *
185 smjs_get_keymap_object(enum keymap_id keymap_id)
187 int *data;
188 JSObject *keymap_object;
190 assert(smjs_ctx);
192 keymap_object = JS_NewObject(smjs_ctx, (JSClass *) &keymap_class,
193 NULL, NULL);
195 if (!keymap_object) return NULL;
197 data = intdup(keymap_id);
198 if (!data) return NULL;
200 if (JS_TRUE == JS_SetPrivate(smjs_ctx, keymap_object, data)) /* to @keymap_class */
201 return keymap_object;
203 mem_free(data);
205 return NULL;
208 static const JSClass keymaps_hash_class = {
209 "keymaps_hash",
210 JSCLASS_HAS_PRIVATE,
211 JS_PropertyStub, JS_PropertyStub,
212 JS_PropertyStub, JS_StrictPropertyStub,
213 JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
216 static JSObject *
217 smjs_get_keymap_hash_object(void)
219 jsval val;
220 enum keymap_id keymap_id;
221 JSObject *keymaps_hash;
223 keymaps_hash = JS_NewObject(smjs_ctx, (JSClass *) &keymaps_hash_class,
224 NULL, NULL);
225 if (!keymaps_hash) return NULL;
227 for (keymap_id = 0; keymap_id < KEYMAP_MAX; ++keymap_id) {
228 unsigned char *keymap_str = get_keymap_name(keymap_id);
229 JSObject *map = smjs_get_keymap_object(keymap_id);
231 assert(keymap_str);
233 if (!map) return NULL;
235 val = OBJECT_TO_JSVAL(map);
237 JS_SetProperty(smjs_ctx, keymaps_hash, keymap_str, &val);
240 return keymaps_hash;
243 void
244 smjs_init_keybinding_interface(void)
246 jsval val;
247 struct JSObject *keymaps_hash;
249 if (!smjs_ctx || !smjs_elinks_object)
250 return;
252 keymaps_hash = smjs_get_keymap_hash_object();
253 if (!keymaps_hash) return;
255 val = OBJECT_TO_JSVAL(keymaps_hash);
257 JS_SetProperty(smjs_ctx, smjs_elinks_object, "keymaps", &val);