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
){
96 if(*ksb_ret
!=NoSymbol
){
97 warn_obj(str
, TR("Insane key combination."));
100 if(XKeysymToKeycode(ioncore_g
.dpy
, keysym
)==0){
101 ioncore_warn_nolog("%s: %s", str
,
102 TR("Could not convert keysym to keycode."));
107 i
=stringintmap_ndx(state_map
, p
);
110 i
=stringintmap_ndx(button_map
, p
);
113 warn(TR("Unknown button \"%s\"."), p
);
117 if(!button
|| *ksb_ret
!=NoSymbol
){
118 warn_obj(str
, TR("Insane button combination."));
121 *ksb_ret
=button_map
[i
].value
;
123 if(*mod_ret
==AnyModifier
){
125 warn_obj(str
, TR("Insane modifier combination."));
128 *mod_ret
=state_map
[i
].value
;
131 if(*mod_ret
!=0 && state_map
[i
].value
==AnyModifier
){
132 warn_obj(str
, TR("Insane modifier combination."));
135 *mod_ret
|=state_map
[i
].value
;
160 /*{{{ bindmap_defbindings */
163 static bool do_action(WBindmap
*bindmap
, const char *str
,
164 ExtlFn func
, uint act
, uint mod
, uint ksb
,
170 warn(TR("Can not wait on modifiers when no modifiers set in \"%s\"."),
179 binding
.kcb
=(act
==BINDING_KEYPRESS
? XKeysymToKeycode(ioncore_g
.dpy
, ksb
) : ksb
);
183 if(func
!=extl_fn_none()){
184 binding
.func
=extl_ref_fn(func
);
185 if(bindmap_add_binding(bindmap
, &binding
))
187 extl_unref_fn(binding
.func
);
188 warn(TR("Unable to add binding %s."), str
);
191 if(bindmap_remove_binding(bindmap
, &binding
))
193 /*warn(TR("Unable to remove binding %s."), str);*/
200 static bool do_submap(WBindmap
*bindmap
, const char *str
,
201 ExtlTab subtab
, uint action
, uint mod
, uint ksb
)
203 WBinding binding
, *bnd
;
206 if(action
!=BINDING_KEYPRESS
)
209 kcb
=XKeysymToKeycode(ioncore_g
.dpy
, ksb
);
211 bnd
=bindmap_lookup_binding(bindmap
, action
, mod
, kcb
);
213 if(bnd
!=NULL
&& bnd
->submap
!=NULL
&& bnd
->state
==mod
)
214 return bindmap_defbindings(bnd
->submap
, subtab
, TRUE
);
217 binding
.act
=BINDING_KEYPRESS
;
222 binding
.func
=extl_fn_none();
223 binding
.submap
=create_bindmap();
225 if(binding
.submap
==NULL
)
228 if(bindmap_add_binding(bindmap
, &binding
))
229 return bindmap_defbindings(binding
.submap
, subtab
, TRUE
);
231 binding_deinit(&binding
);
233 warn(TR("Unable to add submap for binding %s."), str
);
239 static StringIntMap action_map
[]={
240 {"kpress", BINDING_KEYPRESS
},
241 {"mpress", BINDING_BUTTONPRESS
},
242 {"mclick", BINDING_BUTTONCLICK
},
243 {"mdblclick", BINDING_BUTTONDBLCLICK
},
244 {"mdrag", BINDING_BUTTONMOTION
},
245 {"submap_enter", BINDING_SUBMAP_ENTER
},
246 {"submap_wait", BINDING_SUBMAP_RELEASEMOD
},
247 /*{"submap_leave", BINDING_SUBMAP_LEAVE},*/
252 static bool do_entry(WBindmap
*bindmap
, ExtlTab tab
,
253 const StringIntMap
*areamap
, bool init_any
)
256 char *action_str
=NULL
, *ksb_str
=NULL
, *area_str
=NULL
;
264 if(!extl_table_gets_s(tab
, "action", &action_str
)){
265 warn(TR("Binding type not set."));
269 if(strcmp(action_str
, "kpress_wait")==0){
270 action
=BINDING_KEYPRESS
;
273 action
=stringintmap_value(action_map
, action_str
, -1);
275 warn(TR("Unknown binding type \"%s\"."), action_str
);
280 if(!BINDING_IS_PSEUDO(action
)){
281 if(!extl_table_gets_s(tab
, "kcb", &ksb_str
))
284 if(!ioncore_parse_keybut(ksb_str
, &mod
, &ksb
,
285 (action
!=BINDING_KEYPRESS
&& action
!=-1),
291 if(extl_table_gets_t(tab
, "submap", &subtab
)){
292 ret
=do_submap(bindmap
, ksb_str
, subtab
, action
, mod
, ksb
);
293 extl_unref_table(subtab
);
296 if(extl_table_gets_s(tab
, "area", &area_str
)){
297 area
=stringintmap_value(areamap
, area_str
, -1);
299 warn(TR("Unknown area \"%s\" for binding %s."),
306 if(!extl_table_gets_f(tab
, "func", &func
)){
307 /*warn("Function for binding %s not set/nil/undefined.", ksb_str);
311 ret
=do_action(bindmap
, ksb_str
, func
, action
, mod
, ksb
, area
, wr
);
327 bool bindmap_defbindings(WBindmap
*bindmap
, ExtlTab tab
, bool submap
)
332 n
=extl_table_get_n(tab
);
335 if(extl_table_geti_t(tab
, i
, &ent
)){
336 nok
+=do_entry(bindmap
, ent
, bindmap
->areamap
, submap
);
337 extl_unref_table(ent
);
340 warn(TR("Unable to get bindmap entry %d."), i
);
349 /*{{{ bindmap_getbindings */
352 static char *get_mods(uint state
)
357 if(state
==AnyModifier
){
358 ret
=scopy("AnyModifier+");
361 for(i
=0; i
<=MOD5_NDX
; i
++){
364 if((int)(state
&state_map
[i
].value
)==state_map
[i
].value
){
366 ret
=scat3(ret
, state_map
[i
].string
, "+");
376 static char *get_key(char *mods
, uint ksb
)
378 const char *s
=XKeysymToString(ksb
);
381 warn(TR("Unable to convert keysym to string."));
385 return scat(mods
, s
);
389 static char *get_button(char *mods
, uint ksb
)
391 const char *s
=stringintmap_key(button_map
, ksb
, NULL
);
394 warn(TR("Unable to convert button to string."));
398 return scat(mods
, s
);
402 static bool get_kpress(WBindmap
*bindmap
, WBinding
*b
, ExtlTab t
)
408 extl_table_sets_s(t
, "action", "kpress_wait");
410 extl_table_sets_s(t
, "action", "kpress");
412 mods
=get_mods(b
->state
);
417 key
=get_key(mods
, b
->ksb
);
424 extl_table_sets_s(t
, "kcb", key
);
429 ExtlTab stab
=bindmap_getbindings(b
->submap
);
430 extl_table_sets_t(t
, "submap", stab
);
432 extl_table_sets_f(t
, "func", b
->func
);
439 static bool get_mact(WBindmap
*bindmap
, WBinding
*b
, ExtlTab t
)
444 extl_table_sets_s(t
, "action", stringintmap_key(action_map
, b
->act
, NULL
));
446 mods
=get_mods(b
->state
);
451 button
=get_button(mods
, b
->ksb
);
458 extl_table_sets_s(t
, "kcb", button
);
462 if(b
->area
!=0 && bindmap
->areamap
!=NULL
)
463 extl_table_sets_s(t
, "area",
464 stringintmap_key(bindmap
->areamap
, b
->area
, NULL
));
466 extl_table_sets_f(t
, "func", b
->func
);
472 static ExtlTab
getbinding(WBindmap
*bindmap
, WBinding
*b
)
474 ExtlTab t
=extl_create_table();
476 if(b
->act
==BINDING_KEYPRESS
){
477 if(get_kpress(bindmap
, b
, t
))
480 if(get_mact(bindmap
, b
, t
))
484 return extl_unref_table(t
);
488 ExtlTab
bindmap_getbindings(WBindmap
*bindmap
)
496 tab
=extl_create_table();
498 FOR_ALL_BINDINGS(b
, node
, bindmap
->bindings
){
499 btab
=getbinding(bindmap
, b
);
500 extl_table_seti_t(tab
, n
+1, btab
);
501 extl_unref_table(btab
);