2 * ion/ioncore/conf-bindings.c
4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
12 #include <X11/keysymdef.h>
14 #ifdef CF_SUN_F1X_REMAP
15 #include <X11/Sunkeysym.h>
18 #include <libtu/map.h>
22 #include <libextl/readconfig.h>
24 #include <libextl/extl.h>
25 #include "conf-bindings.h"
35 static StringIntMap state_map
[]={
38 {"Control", ControlMask
},
44 {"AnyModifier", AnyModifier
},
49 static StringIntMap button_map
[]={
57 {"AnyButton", AnyButton
},
62 bool ioncore_parse_keybut(const char *str
, uint
*mod_ret
, uint
*ksb_ret
,
63 bool button
, bool init_any
)
66 int keysym
=NoSymbol
, i
;
70 *mod_ret
=(init_any
&& !button
? AnyModifier
: 0);
86 keysym
=XStringToKeysym(p
);
87 #ifdef CF_SUN_F1X_REMAP
90 else if(keysym
==XK_F12
)
95 if(!button
&& keysym
!=NoSymbol
){
97 if(*ksb_ret
!=NoSymbol
){
98 warn_obj(str
, TR("Insane key combination."));
101 if(XKeysymToKeycode(ioncore_g
.dpy
, keysym
)==0){
102 ioncore_warn_nolog("%s: %s", str
,
103 TR("Could not convert keysym to keycode."));
108 i
=stringintmap_ndx(state_map
, p
);
111 i
=stringintmap_ndx(button_map
, p
);
114 warn(TR("Unknown button \"%s\"."), p
);
118 if(!button
|| *ksb_ret
!=NoSymbol
){
119 warn_obj(str
, TR("Insane button combination."));
122 *ksb_ret
=button_map
[i
].value
;
124 if(*mod_ret
==AnyModifier
){
126 warn_obj(str
, TR("Insane modifier combination."));
129 *mod_ret
=state_map
[i
].value
;
132 if(*mod_ret
!=0 && state_map
[i
].value
==AnyModifier
){
133 warn_obj(str
, TR("Insane modifier combination."));
136 *mod_ret
|=state_map
[i
].value
;
161 /*{{{ bindmap_defbindings */
164 static bool do_action(WBindmap
*bindmap
, const char *str
,
165 ExtlFn func
, uint act
, uint mod
, uint ksb
,
171 warn(TR("Can not wait on modifiers when no modifiers set in \"%s\"."),
180 binding
.kcb
=(act
==BINDING_KEYPRESS
? XKeysymToKeycode(ioncore_g
.dpy
, ksb
) : ksb
);
184 if(func
!=extl_fn_none()){
185 binding
.func
=extl_ref_fn(func
);
186 if(bindmap_add_binding(bindmap
, &binding
))
188 extl_unref_fn(binding
.func
);
189 warn(TR("Unable to add binding %s."), str
);
192 if(bindmap_remove_binding(bindmap
, &binding
))
194 /*warn(TR("Unable to remove binding %s."), str);*/
201 static bool do_submap(WBindmap
*bindmap
, const char *str
,
202 ExtlTab subtab
, uint action
, uint mod
, uint ksb
)
204 WBinding binding
, *bnd
;
207 if(action
!=BINDING_KEYPRESS
)
210 kcb
=XKeysymToKeycode(ioncore_g
.dpy
, ksb
);
212 bnd
=bindmap_lookup_binding(bindmap
, action
, mod
, kcb
);
214 if(bnd
!=NULL
&& bnd
->submap
!=NULL
&& bnd
->state
==mod
)
215 return bindmap_defbindings(bnd
->submap
, subtab
, TRUE
);
218 binding
.act
=BINDING_KEYPRESS
;
223 binding
.func
=extl_fn_none();
224 binding
.submap
=create_bindmap();
226 if(binding
.submap
==NULL
)
229 if(bindmap_add_binding(bindmap
, &binding
))
230 return bindmap_defbindings(binding
.submap
, subtab
, TRUE
);
232 binding_deinit(&binding
);
234 warn(TR("Unable to add submap for binding %s."), str
);
240 static StringIntMap action_map
[]={
241 {"kpress", BINDING_KEYPRESS
},
242 {"mpress", BINDING_BUTTONPRESS
},
243 {"mclick", BINDING_BUTTONCLICK
},
244 {"mdblclick", BINDING_BUTTONDBLCLICK
},
245 {"mdrag", BINDING_BUTTONMOTION
},
246 {"submap_enter", BINDING_SUBMAP_ENTER
},
247 {"submap_wait", BINDING_SUBMAP_RELEASEMOD
},
248 /*{"submap_leave", BINDING_SUBMAP_LEAVE},*/
253 static bool do_entry(WBindmap
*bindmap
, ExtlTab tab
,
254 const StringIntMap
*areamap
, bool init_any
)
257 char *action_str
=NULL
, *ksb_str
=NULL
, *area_str
=NULL
;
266 if(!extl_table_gets_s(tab
, "action", &action_str
)){
267 warn(TR("Binding type not set."));
271 if(strcmp(action_str
, "kpress_wait")==0){
272 action
=BINDING_KEYPRESS
;
275 action
=stringintmap_value(action_map
, action_str
, -1);
277 warn(TR("Unknown binding type \"%s\"."), action_str
);
282 if(!BINDING_IS_PSEUDO(action
)){
283 if(!extl_table_gets_s(tab
, "kcb", &ksb_str
))
286 if(!ioncore_parse_keybut(ksb_str
, &mod
, &ksb
,
287 (action
!=BINDING_KEYPRESS
&& action
!=-1),
293 if(extl_table_gets_t(tab
, "submap", &subtab
)){
294 ret
=do_submap(bindmap
, ksb_str
, subtab
, action
, mod
, ksb
);
295 extl_unref_table(subtab
);
298 if(extl_table_gets_s(tab
, "area", &area_str
)){
299 area
=stringintmap_value(areamap
, area_str
, -1);
301 warn(TR("Unknown area \"%s\" for binding %s."),
308 if(!extl_table_gets_f(tab
, "func", &func
)){
309 /*warn("Function for binding %s not set/nil/undefined.", ksb_str);
313 ret
=do_action(bindmap
, ksb_str
, func
, action
, mod
, ksb
, area
, wr
);
329 bool bindmap_defbindings(WBindmap
*bindmap
, ExtlTab tab
, bool submap
)
334 n
=extl_table_get_n(tab
);
337 if(extl_table_geti_t(tab
, i
, &ent
)){
338 nok
+=do_entry(bindmap
, ent
, bindmap
->areamap
, submap
);
339 extl_unref_table(ent
);
342 warn(TR("Unable to get bindmap entry %d."), i
);
351 /*{{{ bindmap_getbindings */
354 static char *get_mods(uint state
)
359 if(state
==AnyModifier
){
360 ret
=scopy("AnyModifier+");
363 for(i
=0; i
<=MOD5_NDX
; i
++){
366 if((int)(state
&state_map
[i
].value
)==state_map
[i
].value
){
368 ret
=scat3(ret
, state_map
[i
].string
, "+");
378 static char *get_key(char *mods
, uint ksb
)
380 const char *s
=XKeysymToString(ksb
);
384 warn(TR("Unable to convert keysym to string."));
388 return scat(mods
, s
);
392 static char *get_button(char *mods
, uint ksb
)
394 const char *s
=stringintmap_key(button_map
, ksb
, NULL
);
398 warn(TR("Unable to convert button to string."));
402 return scat(mods
, s
);
406 static bool get_kpress(WBindmap
*bindmap
, WBinding
*b
, ExtlTab t
)
412 extl_table_sets_s(t
, "action", "kpress_wait");
414 extl_table_sets_s(t
, "action", "kpress");
416 mods
=get_mods(b
->state
);
421 key
=get_key(mods
, b
->ksb
);
428 extl_table_sets_s(t
, "kcb", key
);
433 ExtlTab stab
=bindmap_getbindings(b
->submap
);
434 extl_table_sets_t(t
, "submap", stab
);
436 extl_table_sets_f(t
, "func", b
->func
);
443 static bool get_mact(WBindmap
*bindmap
, WBinding
*b
, ExtlTab t
)
448 extl_table_sets_s(t
, "action", stringintmap_key(action_map
, b
->act
, NULL
));
450 mods
=get_mods(b
->state
);
455 button
=get_button(mods
, b
->ksb
);
462 extl_table_sets_s(t
, "kcb", button
);
466 if(b
->area
!=0 && bindmap
->areamap
!=NULL
)
467 extl_table_sets_s(t
, "area",
468 stringintmap_key(bindmap
->areamap
, b
->area
, NULL
));
470 extl_table_sets_f(t
, "func", b
->func
);
476 static ExtlTab
getbinding(WBindmap
*bindmap
, WBinding
*b
)
478 ExtlTab t
=extl_create_table();
480 if(b
->act
==BINDING_KEYPRESS
){
481 if(get_kpress(bindmap
, b
, t
))
484 if(get_mact(bindmap
, b
, t
))
488 return extl_unref_table(t
);
492 ExtlTab
bindmap_getbindings(WBindmap
*bindmap
)
500 tab
=extl_create_table();
502 FOR_ALL_BINDINGS(b
, node
, bindmap
->bindings
){
503 btab
=getbinding(bindmap
, b
);
504 extl_table_seti_t(tab
, n
+1, btab
);
505 extl_unref_table(btab
);