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 */
20 keymap_get_property(JSContext
*ctx
, JSObject
*obj
, jsid id
, jsval
*vp
)
22 unsigned char *action_str
;
23 const unsigned char *keystroke_str
;
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
30 if (!JS_InstanceOf(ctx
, obj
, (JSClass
*) &keymap_class
, NULL
))
33 data
= JS_GetInstancePrivate(ctx
, obj
,
34 (JSClass
*) &keymap_class
, NULL
);
36 if (!JS_IdToValue(ctx
, id
, &tmp
))
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
,
44 if (!action_str
|| !strcmp(action_str
, "none")) goto ret_null
;
46 *vp
= STRING_TO_JSVAL(JS_NewStringCopyZ(ctx
, action_str
));
56 static enum evhook_status
57 smjs_keybinding_action_callback(va_list ap
, void *data
)
60 struct session
*ses
= va_arg(ap
, struct session
*);
61 JSObject
*jsobj
= data
;
63 evhook_use_params(ses
);
67 JS_CallFunctionValue(smjs_ctx
, NULL
, OBJECT_TO_JSVAL(jsobj
),
72 return EVENT_HOOK_STATUS_LAST
;
75 /* @keymap_class.setProperty */
77 keymap_set_property(JSContext
*ctx
, JSObject
*obj
, jsid id
, JSBool strict
, jsval
*vp
)
80 unsigned char *keymap_str
;
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
87 if (!JS_InstanceOf(ctx
, obj
, (JSClass
*) &keymap_class
, NULL
))
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))
113 } else if (JSVAL_IS_NULL(*vp
)) { /* before JSVAL_IS_OBJECT */
114 if (bind_do(keymap_str
, keystroke_str
, "none", 0))
119 } else if (JSVAL_IS_OBJECT(*vp
)) {
120 unsigned char *err
= NULL
;
122 struct string event_name
= NULL_STRING
;
123 JSObject
*jsobj
= JSVAL_TO_OBJECT(*vp
);
125 if (JS_FALSE
== JS_ObjectIsFunction(ctx
, jsobj
))
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
,
134 event_name
.source
, &err
);
136 done_string(&event_name
);
139 alert_smjs_error(err
);
144 event_id
= register_event_hook(event_id
,
145 smjs_keybinding_action_callback
,
148 if (event_id
== EVENT_NONE
) {
149 alert_smjs_error("error registering event hook"
161 /* @keymap_class.finalize */
163 keymap_finalize(JSContext
*ctx
, JSObject
*obj
)
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
);
176 static const JSClass keymap_class
= {
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
,
185 smjs_get_keymap_object(enum keymap_id keymap_id
)
188 JSObject
*keymap_object
;
192 keymap_object
= JS_NewObject(smjs_ctx
, (JSClass
*) &keymap_class
,
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
;
208 static const JSClass keymaps_hash_class
= {
211 JS_PropertyStub
, JS_PropertyStub
,
212 JS_PropertyStub
, JS_StrictPropertyStub
,
213 JS_EnumerateStub
, JS_ResolveStub
, JS_ConvertStub
, JS_FinalizeStub
,
217 smjs_get_keymap_hash_object(void)
220 enum keymap_id keymap_id
;
221 JSObject
*keymaps_hash
;
223 keymaps_hash
= JS_NewObject(smjs_ctx
, (JSClass
*) &keymaps_hash_class
,
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
);
233 if (!map
) return NULL
;
235 val
= OBJECT_TO_JSVAL(map
);
237 JS_SetProperty(smjs_ctx
, keymaps_hash
, keymap_str
, &val
);
244 smjs_init_keybinding_interface(void)
247 struct JSObject
*keymaps_hash
;
249 if (!smjs_ctx
|| !smjs_elinks_object
)
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
);