Tizen 2.1 release
[platform/core/uifw/e17.git] / src / modules / conf_keybindings / e_int_config_keybindings.c
1 #include "e.h"
2
3 #define TEXT_NONE_ACTION_KEY    _("<None>")
4 #define TEXT_PRESS_KEY_SEQUENCE _("Please press key sequence,<br><br>" \
5                                   "or <hilight>Escape</hilight> to abort.")
6
7 #define TEXT_NO_PARAMS          _("<None>")
8 #define TEXT_NO_MODIFIER_HEADER _("Single key")
9
10 static void        *_create_data(E_Config_Dialog *cfd);
11 static void         _free_data(E_Config_Dialog *cfd,
12                                E_Config_Dialog_Data *cfdata);
13 static int          _basic_apply_data(E_Config_Dialog *cfd,
14                                       E_Config_Dialog_Data *cfdata);
15 static Evas_Object *_basic_create_widgets(E_Config_Dialog *cfd,
16                                           Evas *evas,
17                                           E_Config_Dialog_Data *cfdata);
18
19 /********* private functions ***************/
20 static void         _fill_actions_list(E_Config_Dialog_Data *cfdata);
21
22 /**************** Updates ***********/
23 static int          _update_key_binding_list(E_Config_Dialog_Data *cfdata,
24                                              E_Config_Binding_Key *bi);
25 static void         _update_action_list(E_Config_Dialog_Data *cfdata);
26 static void         _update_action_params(E_Config_Dialog_Data *cfdata);
27 static void         _update_buttons(E_Config_Dialog_Data *cfdata);
28
29 /**************** Callbacks *********/
30 static void         _binding_change_cb(void *data);
31 static void         _action_change_cb(void *data);
32 static void         _delete_all_key_binding_cb(void *data,
33                                                void *data2);
34 static void         _delete_key_binding_cb(void *data,
35                                            void *data2);
36 static void         _restore_key_binding_defaults_cb(void *data,
37                                                      void *data2);
38 static void         _add_key_binding_cb(void *data,
39                                         void *data2);
40 static void         _modify_key_binding_cb(void *data,
41                                            void *data2);
42
43 /********* Helper *************************/
44 static char        *_key_binding_header_get(int modifiers);
45 static char        *_key_binding_text_get(E_Config_Binding_Key *bi);
46 static void         _auto_apply_changes(E_Config_Dialog_Data *cfdata);
47 static void         _find_key_binding_action(const char *action,
48                                              const char *params,
49                                              int *g,
50                                              int *a,
51                                              int *n);
52
53 /********* Sorting ************************/
54 static int       _key_binding_sort_cb(const void *d1,
55                                       const void *d2);
56
57 /**************** grab window *******/
58 static void      _grab_wnd_show(E_Config_Dialog_Data *cfdata);
59 static Eina_Bool _grab_key_down_cb(void *data,
60                                    int type,
61                                    void *event);
62
63 struct _E_Config_Dialog_Data
64 {
65    Evas *evas;
66    struct
67    {
68       Eina_List *key;
69    } binding;
70    struct
71    {
72       const char    *binding, *action, *cur;
73       char          *params;
74       int            cur_act, add;
75
76       E_Grab_Dialog *eg;
77    } locals;
78    struct
79    {
80       Evas_Object *o_add, *o_mod, *o_del, *o_del_all;
81       Evas_Object *o_binding_list, *o_action_list;
82       Evas_Object *o_params;
83    } gui;
84
85    char            *params;
86    E_Config_Dialog *cfd;
87 };
88
89 E_Config_Dialog *
90 e_int_config_keybindings(E_Container *con,
91                          const char *params)
92 {
93    E_Config_Dialog *cfd;
94    E_Config_Dialog_View *v;
95
96    if (e_config_dialog_find("E", "keyboard_and_mouse/key_bindings")) return NULL;
97    v = E_NEW(E_Config_Dialog_View, 1);
98
99    v->create_cfdata = _create_data;
100    v->free_cfdata = _free_data;
101    v->basic.apply_cfdata = _basic_apply_data;
102    v->basic.create_widgets = _basic_create_widgets;
103    v->override_auto_apply = 1;
104
105    cfd = e_config_dialog_new(con, _("Key Bindings Settings"), "E",
106                              "keyboard_and_mouse/key_bindings",
107                              "preferences-desktop-keyboard-shortcuts", 0, v, NULL);
108    if ((params) && (params[0]))
109      {
110         cfd->cfdata->params = strdup(params);
111         _add_key_binding_cb(cfd->cfdata, NULL);
112      }
113
114    return cfd;
115 }
116
117 static void
118 _fill_data(E_Config_Dialog_Data *cfdata)
119 {
120    Eina_List *l = NULL;
121    E_Config_Binding_Key *bi, *bi2;
122
123    cfdata->locals.binding = eina_stringshare_add("");
124    cfdata->locals.action = eina_stringshare_add("");
125    cfdata->locals.params = strdup("");
126    cfdata->locals.cur = NULL;
127    cfdata->binding.key = NULL;
128    cfdata->locals.eg = NULL;
129
130    EINA_LIST_FOREACH(e_config->key_bindings, l, bi)
131      {
132         if (!bi) continue;
133
134         bi2 = E_NEW(E_Config_Binding_Key, 1);
135         bi2->context = bi->context;
136         bi2->key = eina_stringshare_add(bi->key);
137         bi2->modifiers = bi->modifiers;
138         bi2->any_mod = bi->any_mod;
139         bi2->action = eina_stringshare_ref(bi->action);
140         bi2->params = eina_stringshare_ref(bi->params);
141
142         cfdata->binding.key = eina_list_append(cfdata->binding.key, bi2);
143      }
144 }
145
146 static void *
147 _create_data(E_Config_Dialog *cfd)
148 {
149    E_Config_Dialog_Data *cfdata;
150
151    cfdata = E_NEW(E_Config_Dialog_Data, 1);
152    cfdata->cfd = cfd;
153    cfdata->locals.cur_act = -1;
154    _fill_data(cfdata);
155
156    return cfdata;
157 }
158
159 static void
160 _free_data(E_Config_Dialog *cfd  __UNUSED__,
161            E_Config_Dialog_Data *cfdata)
162 {
163    E_Config_Binding_Key *bi;
164
165    EINA_LIST_FREE(cfdata->binding.key, bi)
166      {
167         eina_stringshare_del(bi->key);
168         eina_stringshare_del(bi->action);
169         eina_stringshare_del(bi->params);
170         E_FREE(bi);
171      }
172
173    eina_stringshare_del(cfdata->locals.cur);
174    eina_stringshare_del(cfdata->locals.binding);
175    eina_stringshare_del(cfdata->locals.action);
176
177    if (cfdata->locals.params) free(cfdata->locals.params);
178    if (cfdata->params) free(cfdata->params);
179    E_FREE(cfdata);
180 }
181
182 static int
183 _basic_apply_data(E_Config_Dialog *cfd  __UNUSED__,
184                   E_Config_Dialog_Data *cfdata)
185 {
186    Eina_List *l = NULL;
187    E_Config_Binding_Key *bi, *bi2;
188
189    _auto_apply_changes(cfdata);
190
191    e_managers_keys_ungrab();
192    EINA_LIST_FREE(e_config->key_bindings, bi)
193      {
194         e_bindings_key_del(bi->context, bi->key, bi->modifiers, bi->any_mod,
195                            bi->action, bi->params);
196         if (bi->key) eina_stringshare_del(bi->key);
197         if (bi->action) eina_stringshare_del(bi->action);
198         if (bi->params) eina_stringshare_del(bi->params);
199         E_FREE(bi);
200      }
201
202    EINA_LIST_FOREACH(cfdata->binding.key, l, bi2)
203      {
204         bi2 = l->data;
205
206         if (!bi2->key || !bi2->key[0]) continue;
207
208         bi = E_NEW(E_Config_Binding_Key, 1);
209         bi->context = bi2->context;
210         bi->key = eina_stringshare_add(bi2->key);
211         bi->modifiers = bi2->modifiers;
212         bi->any_mod = bi2->any_mod;
213         bi->action =
214           ((!bi2->action) || (!bi2->action[0])) ? NULL : eina_stringshare_ref(bi2->action);
215         bi->params =
216           ((!bi2->params) || (!bi2->params[0])) ? NULL : eina_stringshare_ref(bi2->params);
217
218         e_config->key_bindings = eina_list_append(e_config->key_bindings, bi);
219         e_bindings_key_add(bi->context, bi->key, bi->modifiers, bi->any_mod,
220                            bi->action, bi->params);
221      }
222    e_managers_keys_grab();
223    e_config_save_queue();
224
225    return 1;
226 }
227
228 static Evas_Object *
229 _basic_create_widgets(E_Config_Dialog *cfd,
230                       Evas *evas,
231                       E_Config_Dialog_Data *cfdata)
232 {
233    Evas_Object *o, *ot, *of, *ob;
234
235    cfdata->evas = evas;
236    o = e_widget_list_add(evas, 0, 1);
237
238    of = e_widget_frametable_add(evas, _("Key Bindings"), 0);
239    ob = e_widget_ilist_add(evas, 32, 32, &(cfdata->locals.binding));
240    cfdata->gui.o_binding_list = ob;
241    e_widget_size_min_set(ob, 200, 200);
242    e_widget_frametable_object_append(of, ob, 0, 0, 2, 1, 1, 1, 1, 1);
243    ob = e_widget_button_add(evas, _("Add"), "list-add", _add_key_binding_cb, cfdata, NULL);
244    cfdata->gui.o_add = ob;
245    e_widget_frametable_object_append(of, ob, 0, 1, 1, 1, 1, 0, 1, 0);
246    ob = e_widget_button_add(evas, _("Delete"), "list-remove", _delete_key_binding_cb, cfdata, NULL);
247    cfdata->gui.o_del = ob;
248    e_widget_disabled_set(ob, 1);
249    e_widget_frametable_object_append(of, ob, 1, 1, 1, 1, 1, 0, 1, 0);
250    ob = e_widget_button_add(evas, _("Modify"), NULL, _modify_key_binding_cb, cfdata, NULL);
251    cfdata->gui.o_mod = ob;
252    e_widget_disabled_set(ob, 1);
253    e_widget_frametable_object_append(of, ob, 0, 2, 1, 1, 1, 0, 1, 0);
254    ob = e_widget_button_add(evas, _("Delete All"), "edit-clear", _delete_all_key_binding_cb, cfdata, NULL);
255    cfdata->gui.o_del_all = ob;
256    e_widget_disabled_set(ob, 1);
257    e_widget_frametable_object_append(of, ob, 1, 2, 1, 1, 1, 0, 1, 0);
258    ob = e_widget_button_add(evas, _("Restore Default Bindings"), "enlightenment", _restore_key_binding_defaults_cb, cfdata, NULL);
259    e_widget_frametable_object_append(of, ob, 0, 3, 2, 1, 1, 0, 1, 0);
260    e_widget_list_object_append(o, of, 1, 1, 0.5);
261
262    ot = e_widget_table_add(evas, 0);
263    of = e_widget_framelist_add(evas, _("Action"), 0);
264    ob = e_widget_ilist_add(evas, 24, 24, &(cfdata->locals.action));
265    cfdata->gui.o_action_list = ob;
266    e_widget_size_min_set(ob, 200, 280);
267    e_widget_framelist_object_append(of, ob);
268    e_widget_table_object_append(ot, of, 0, 0, 1, 1, 1, 1, 1, 1);
269
270    of = e_widget_framelist_add(evas, _("Action Params"), 0);
271    ob = e_widget_entry_add(evas, &(cfdata->locals.params), NULL, NULL, NULL);
272    cfdata->gui.o_params = ob;
273    e_widget_disabled_set(ob, 1);
274    e_widget_framelist_object_append(of, ob);
275    e_widget_table_object_append(ot, of, 0, 1, 1, 1, 1, 1, 1, 0);
276    e_widget_list_object_append(o, ot, 1, 1, 0.5);
277
278    _update_key_binding_list(cfdata, NULL);
279    _fill_actions_list(cfdata);
280
281    e_dialog_resizable_set(cfd->dia, 1);
282    return o;
283 }
284
285 static void
286 _fill_actions_list(E_Config_Dialog_Data *cfdata)
287 {
288    char buf[1024];
289    Eina_List *l, *l2;
290    E_Action_Group *actg;
291    E_Action_Description *actd;
292    int g, a;
293
294    evas_event_freeze(evas_object_evas_get(cfdata->gui.o_action_list));
295    edje_freeze();
296    e_widget_ilist_freeze(cfdata->gui.o_action_list);
297
298    e_widget_ilist_clear(cfdata->gui.o_action_list);
299    for (l = e_action_groups_get(), g = 0; l; l = l->next, g++)
300      {
301         actg = l->data;
302
303         if (!actg->acts) continue;
304
305         e_widget_ilist_header_append(cfdata->gui.o_action_list, NULL, _(actg->act_grp));
306
307         for (l2 = actg->acts, a = 0; l2; l2 = l2->next, a++)
308           {
309              actd = l2->data;
310
311              snprintf(buf, sizeof(buf), "%d %d", g, a);
312              e_widget_ilist_append(cfdata->gui.o_action_list, NULL, _(actd->act_name),
313                                    _action_change_cb, cfdata, buf);
314           }
315      }
316    e_widget_ilist_go(cfdata->gui.o_action_list);
317    e_widget_ilist_thaw(cfdata->gui.o_action_list);
318    edje_thaw();
319    evas_event_thaw(evas_object_evas_get(cfdata->gui.o_action_list));
320 }
321
322 /**************** Callbacks *********/
323
324 static void
325 _add_key_binding_cb(void *data,
326                     void *data2 __UNUSED__)
327 {
328    E_Config_Dialog_Data *cfdata;
329
330    cfdata = data;
331
332    _auto_apply_changes(cfdata);
333
334    cfdata->locals.add = 1;
335    _grab_wnd_show(cfdata);
336 }
337
338 static void
339 _modify_key_binding_cb(void *data,
340                        void *data2 __UNUSED__)
341 {
342    E_Config_Dialog_Data *cfdata;
343
344    cfdata = data;
345
346    _auto_apply_changes(cfdata);
347
348    cfdata->locals.add = 0;
349    _grab_wnd_show(cfdata);
350 }
351
352 static void
353 _binding_change_cb(void *data)
354 {
355    E_Config_Dialog_Data *cfdata;
356
357    cfdata = data;
358
359    _auto_apply_changes(cfdata);
360    eina_stringshare_del(cfdata->locals.cur);
361    cfdata->locals.cur = NULL;
362    cfdata->locals.cur_act = -1;
363
364    if ((!cfdata->locals.binding) || (!cfdata->locals.binding[0])) return;
365
366    cfdata->locals.cur = eina_stringshare_add(cfdata->locals.binding);
367
368    _update_buttons(cfdata);
369    _update_action_list(cfdata);
370 }
371
372 static void
373 _action_change_cb(void *data)
374 {
375    E_Config_Dialog_Data *cfdata;
376
377    cfdata = data;
378    _update_action_params(cfdata);
379    cfdata->locals.cur_act = e_widget_ilist_selected_get(cfdata->gui.o_action_list);
380 }
381
382 static void
383 _delete_all_key_binding_cb(void *data,
384                            void *data2 __UNUSED__)
385 {
386    E_Config_Binding_Key *bi;
387    E_Config_Dialog_Data *cfdata;
388
389    cfdata = data;
390
391    /* FIXME: need confirmation dialog */
392    EINA_LIST_FREE(cfdata->binding.key, bi)
393      {
394         eina_stringshare_del(bi->key);
395         eina_stringshare_del(bi->action);
396         eina_stringshare_del(bi->params);
397         E_FREE(bi);
398      }
399
400    eina_stringshare_del(cfdata->locals.cur);
401    cfdata->locals.cur = NULL;
402
403    e_widget_ilist_clear(cfdata->gui.o_binding_list);
404    e_widget_ilist_go(cfdata->gui.o_binding_list);
405    e_widget_ilist_unselect(cfdata->gui.o_action_list);
406    e_widget_entry_clear(cfdata->gui.o_params);
407    e_widget_disabled_set(cfdata->gui.o_params, 1);
408
409    _update_buttons(cfdata);
410 }
411
412 static void
413 _delete_key_binding_cb(void *data,
414                        void *data2 __UNUSED__)
415 {
416    Eina_List *l = NULL;
417    const char *n;
418    int sel;
419    E_Config_Dialog_Data *cfdata;
420    E_Config_Binding_Key *bi;
421
422    cfdata = data;
423
424    sel = e_widget_ilist_selected_get(cfdata->gui.o_binding_list);
425    if (cfdata->locals.binding[0] == 'k')
426      {
427         n = cfdata->locals.binding;
428         l = eina_list_nth_list(cfdata->binding.key, atoi(++n));
429
430         /* FIXME: need confirmation dialog */
431         if (l)
432           {
433              bi = eina_list_data_get(l);
434              eina_stringshare_del(bi->key);
435              eina_stringshare_del(bi->action);
436              eina_stringshare_del(bi->params);
437              E_FREE(bi);
438
439              cfdata->binding.key = eina_list_remove_list(cfdata->binding.key, l);
440           }
441      }
442
443    _update_key_binding_list(cfdata, NULL);
444
445    if (sel >= e_widget_ilist_count(cfdata->gui.o_binding_list))
446      sel = e_widget_ilist_count(cfdata->gui.o_binding_list) - 1;
447
448    eina_stringshare_del(cfdata->locals.cur);
449    cfdata->locals.cur = NULL;
450
451    if (sel < 0)
452      {
453         e_widget_ilist_unselect(cfdata->gui.o_action_list);
454         e_widget_entry_clear(cfdata->gui.o_params);
455         e_widget_disabled_set(cfdata->gui.o_params, 1);
456         _update_buttons(cfdata);
457      }
458    else
459      {
460         e_widget_ilist_selected_set(cfdata->gui.o_binding_list, sel);
461         e_widget_ilist_nth_show(cfdata->gui.o_binding_list, sel, 0);
462      }
463 }
464
465 static void
466 _restore_key_binding_defaults_cb(void *data,
467                                  void *data2 __UNUSED__)
468 {
469    E_Config_Dialog_Data *cfdata;
470    E_Config_Binding_Key *bi;
471
472    cfdata = data;
473
474    EINA_LIST_FREE(cfdata->binding.key, bi)
475      {
476         eina_stringshare_del(bi->key);
477         eina_stringshare_del(bi->action);
478         eina_stringshare_del(bi->params);
479         E_FREE(bi);
480      }
481
482 #define CFG_KEYBIND_DFLT(_context, _key, _modifiers, _anymod, _action, _params) \
483   bi = E_NEW(E_Config_Binding_Key, 1);                                          \
484   bi->context = _context;                                                       \
485   bi->key = eina_stringshare_add(_key);                                         \
486   bi->modifiers = _modifiers;                                                   \
487   bi->any_mod = _anymod;                                                        \
488   bi->action = eina_stringshare_add(_action);                                   \
489   bi->params = eina_stringshare_add(_params);                                   \
490   cfdata->binding.key = eina_list_append(cfdata->binding.key, bi)
491
492    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "Left",
493                     E_BINDING_MODIFIER_SHIFT | E_BINDING_MODIFIER_ALT, 0,
494                     "desk_flip_by", "-1 0");
495    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "Right",
496                     E_BINDING_MODIFIER_SHIFT | E_BINDING_MODIFIER_ALT, 0,
497                     "desk_flip_by", "1 0");
498    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "Up",
499                     E_BINDING_MODIFIER_SHIFT | E_BINDING_MODIFIER_ALT, 0,
500                     "desk_flip_by", "0 -1");
501    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "Down",
502                     E_BINDING_MODIFIER_SHIFT | E_BINDING_MODIFIER_ALT, 0,
503                     "desk_flip_by", "0 1");
504    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "Up",
505                     E_BINDING_MODIFIER_CTRL | E_BINDING_MODIFIER_ALT, 0,
506                     "window_raise", NULL);
507    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "Down",
508                     E_BINDING_MODIFIER_CTRL | E_BINDING_MODIFIER_ALT, 0,
509                     "window_lower", NULL);
510    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "x",
511                     E_BINDING_MODIFIER_CTRL | E_BINDING_MODIFIER_ALT, 0,
512                     "window_close", NULL);
513    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "k",
514                     E_BINDING_MODIFIER_CTRL | E_BINDING_MODIFIER_ALT, 0,
515                     "window_kill", NULL);
516    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "w",
517                     E_BINDING_MODIFIER_CTRL | E_BINDING_MODIFIER_ALT, 0,
518                     "window_menu", NULL);
519    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "s",
520                     E_BINDING_MODIFIER_CTRL | E_BINDING_MODIFIER_ALT, 0,
521                     "window_sticky_toggle", NULL);
522    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "i",
523                     E_BINDING_MODIFIER_CTRL | E_BINDING_MODIFIER_ALT, 0,
524                     "window_iconic_toggle", NULL);
525    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "f",
526                     E_BINDING_MODIFIER_CTRL | E_BINDING_MODIFIER_ALT, 0,
527                     "window_maximized_toggle", NULL);
528    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "F10",
529                     E_BINDING_MODIFIER_SHIFT, 0,
530                     "window_maximized_toggle", "default vertical");
531    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "F10",
532                     E_BINDING_MODIFIER_CTRL, 0,
533                     "window_maximized_toggle", "default horizontal");
534    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "Left",
535                     E_BINDING_MODIFIER_WIN, 0,
536                     "window_maximized_toggle", "default left");
537    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "Right",
538                     E_BINDING_MODIFIER_WIN, 0,
539                     "window_maximized_toggle", "default right");
540    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "r",
541                     E_BINDING_MODIFIER_CTRL | E_BINDING_MODIFIER_ALT, 0,
542                     "window_shaded_toggle", NULL);
543    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "Left",
544                     E_BINDING_MODIFIER_CTRL | E_BINDING_MODIFIER_ALT, 0,
545                     "desk_linear_flip_by", "-1");
546    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "Right",
547                     E_BINDING_MODIFIER_CTRL | E_BINDING_MODIFIER_ALT, 0,
548                     "desk_linear_flip_by", "1");
549    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "F1",
550                     E_BINDING_MODIFIER_ALT, 0,
551                     "desk_linear_flip_to", "0");
552    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "F2",
553                     E_BINDING_MODIFIER_ALT, 0,
554                     "desk_linear_flip_to", "1");
555    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "F3",
556                     E_BINDING_MODIFIER_ALT, 0,
557                     "desk_linear_flip_to", "2");
558    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "F4",
559                     E_BINDING_MODIFIER_ALT, 0,
560                     "desk_linear_flip_to", "3");
561    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "F5",
562                     E_BINDING_MODIFIER_ALT, 0,
563                     "desk_linear_flip_to", "4");
564    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "F6",
565                     E_BINDING_MODIFIER_ALT, 0,
566                     "desk_linear_flip_to", "5");
567    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "F7",
568                     E_BINDING_MODIFIER_ALT, 0,
569                     "desk_linear_flip_to", "6");
570    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "F8",
571                     E_BINDING_MODIFIER_ALT, 0,
572                     "desk_linear_flip_to", "7");
573    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "F9",
574                     E_BINDING_MODIFIER_ALT, 0,
575                     "desk_linear_flip_to", "8");
576    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "F10",
577                     E_BINDING_MODIFIER_ALT, 0,
578                     "desk_linear_flip_to", "9");
579    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "F11",
580                     E_BINDING_MODIFIER_ALT, 0,
581                     "desk_linear_flip_to", "10");
582    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "F12",
583                     E_BINDING_MODIFIER_ALT, 0,
584                     "desk_linear_flip_to", "11");
585    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "m",
586                     E_BINDING_MODIFIER_CTRL | E_BINDING_MODIFIER_ALT, 0,
587                     "menu_show", "main");
588    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "a",
589                     E_BINDING_MODIFIER_CTRL | E_BINDING_MODIFIER_ALT, 0,
590                     "menu_show", "favorites");
591    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "Menu",
592                     0, 0,
593                     "menu_show", "main");
594    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "Menu",
595                     E_BINDING_MODIFIER_CTRL, 0,
596                     "menu_show", "clients");
597    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "Menu",
598                     E_BINDING_MODIFIER_ALT, 0,
599                     "menu_show", "favorites");
600    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "Insert",
601                     E_BINDING_MODIFIER_CTRL | E_BINDING_MODIFIER_ALT, 0,
602                     "exec", "Eterm");
603    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "Tab",
604                     E_BINDING_MODIFIER_ALT, 0,
605                     "winlist", "next");
606    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "Tab",
607                     E_BINDING_MODIFIER_SHIFT | E_BINDING_MODIFIER_ALT, 0,
608                     "winlist", "prev");
609    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "End",
610                     E_BINDING_MODIFIER_CTRL | E_BINDING_MODIFIER_ALT, 0,
611                     "restart", NULL);
612    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "Delete",
613                     E_BINDING_MODIFIER_CTRL | E_BINDING_MODIFIER_ALT, 0,
614                     "logout", NULL);
615    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "Escape",
616                     E_BINDING_MODIFIER_ALT, 0,
617                     "everything", NULL);
618    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "l",
619                     E_BINDING_MODIFIER_CTRL | E_BINDING_MODIFIER_ALT, 0,
620                     "desk_lock", NULL);
621    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "d",
622                     E_BINDING_MODIFIER_CTRL | E_BINDING_MODIFIER_ALT, 0,
623                     "desk_deskshow_toggle", NULL);
624    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "Left",
625                     E_BINDING_MODIFIER_CTRL | E_BINDING_MODIFIER_SHIFT, 0,
626                     "screen_send_by", "-1");
627    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "Right",
628                     E_BINDING_MODIFIER_CTRL | E_BINDING_MODIFIER_SHIFT, 0,
629                     "screen_send_by", "1");
630    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "F1",
631                     E_BINDING_MODIFIER_CTRL | E_BINDING_MODIFIER_SHIFT, 0,
632                     "screen_send_to", "0");
633    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "F2",
634                     E_BINDING_MODIFIER_CTRL | E_BINDING_MODIFIER_SHIFT, 0,
635                     "screen_send_to", "1");
636    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "F3",
637                     E_BINDING_MODIFIER_CTRL | E_BINDING_MODIFIER_SHIFT, 0,
638                     "screen_send_to", "2");
639    CFG_KEYBIND_DFLT(E_BINDING_CONTEXT_ANY, "F4",
640                     E_BINDING_MODIFIER_CTRL | E_BINDING_MODIFIER_SHIFT, 0,
641                     "screen_send_to", "3");
642
643    eina_stringshare_del(cfdata->locals.cur);
644    cfdata->locals.cur = NULL;
645
646    _update_key_binding_list(cfdata, NULL);
647    _update_buttons(cfdata);
648
649    e_widget_ilist_unselect(cfdata->gui.o_action_list);
650    e_widget_entry_clear(cfdata->gui.o_params);
651    e_widget_disabled_set(cfdata->gui.o_params, 1);
652 }
653
654 /**************** Updates ***********/
655 static void
656 _update_action_list(E_Config_Dialog_Data *cfdata)
657 {
658    E_Config_Binding_Key *bi;
659    int j = -1, i, n, cnt;
660    const char *action, *params;
661
662    if (!cfdata->locals.cur) return;
663
664    if (cfdata->locals.cur[0] == 'k')
665      {
666         sscanf(cfdata->locals.cur, "k%d", &n);
667         bi = eina_list_nth(cfdata->binding.key, n);
668         if (!bi)
669           {
670              e_widget_ilist_unselect(cfdata->gui.o_action_list);
671              e_widget_entry_clear(cfdata->gui.o_params);
672              e_widget_disabled_set(cfdata->gui.o_params, 1);
673              return;
674           }
675         action = bi->action;
676         params = bi->params;
677      }
678    else
679      return;
680
681    _find_key_binding_action(action, params, NULL, NULL, &j);
682
683    if (j >= 0)
684      {
685         cnt = e_widget_ilist_count(cfdata->gui.o_action_list);
686         for (i = 0; i < cnt; i++)
687           {
688              if (i > j) break;
689              if (e_widget_ilist_nth_is_header(cfdata->gui.o_action_list, i)) j++;
690           }
691      }
692
693    if (j >= 0)
694      {
695         if (j == e_widget_ilist_selected_get(cfdata->gui.o_action_list))
696           _update_action_params(cfdata);
697         else
698           e_widget_ilist_selected_set(cfdata->gui.o_action_list, j);
699      }
700    else
701      {
702         e_widget_ilist_unselect(cfdata->gui.o_action_list);
703         eina_stringshare_del(cfdata->locals.action);
704         cfdata->locals.action = eina_stringshare_add("");
705         e_widget_entry_clear(cfdata->gui.o_params);
706      }
707
708    /*if (cfdata->locals.cur[0] == 'k')
709       {
710         sscanf(cfdata->locals.cur, "k%d", &n);
711         bi = eina_list_nth(cfdata->binding.key, n);
712         if (!bi)
713           {
714              e_widget_ilist_unselect(cfdata->gui.o_action_list);
715              e_widget_entry_clear(cfdata->gui.o_params);
716              e_widget_disabled_set(cfdata->gui.o_params, 1);
717              return;
718           }
719
720         _find_key_binding_action(bi, NULL, NULL, &j);
721         if (j >= 0)
722           {
723              for (i = 0; i < e_widget_ilist_count(cfdata->gui.o_action_list); i++)
724                {
725                   if (i > j) break;
726                   if (e_widget_ilist_nth_is_header(cfdata->gui.o_action_list, i)) j++;
727                }
728           }
729
730         if (j >= 0)
731           {
732              if (j == e_widget_ilist_selected_get(cfdata->gui.o_action_list))
733                _update_action_params(cfdata);
734              else
735                e_widget_ilist_selected_set(cfdata->gui.o_action_list, j);
736           }
737         else
738           {
739              e_widget_ilist_unselect(cfdata->gui.o_action_list);
740              if (cfdata->locals.action) free(cfdata->locals.action);
741              cfdata->locals.action = strdup("");
742              e_widget_entry_clear(cfdata->gui.o_params);
743           }
744       }*/
745 }
746
747 static void
748 _update_action_params(E_Config_Dialog_Data *cfdata)
749 {
750    int g, a, b;
751    E_Action_Group *actg;
752    E_Action_Description *actd;
753    E_Config_Binding_Key *bi;
754    const char *action, *params;
755
756 #define KB_EXAMPLE_PARAMS                                           \
757   if ((!actd->param_example) || (!actd->param_example[0]))          \
758     e_widget_entry_text_set(cfdata->gui.o_params, TEXT_NO_PARAMS);  \
759   else                                                              \
760     e_widget_entry_text_set(cfdata->gui.o_params, actd->param_example)
761
762    if ((!cfdata->locals.action) || (!cfdata->locals.action[0]))
763      {
764         e_widget_disabled_set(cfdata->gui.o_params, 1);
765         e_widget_entry_clear(cfdata->gui.o_params);
766         return;
767      }
768    sscanf(cfdata->locals.action, "%d %d", &g, &a);
769
770    actg = eina_list_nth(e_action_groups_get(), g);
771    if (!actg) return;
772    actd = eina_list_nth(actg->acts, a);
773    if (!actd) return;
774
775    if (actd->act_params)
776      {
777         e_widget_disabled_set(cfdata->gui.o_params, 1);
778         e_widget_entry_text_set(cfdata->gui.o_params, actd->act_params);
779         return;
780      }
781
782    if ((!cfdata->locals.cur) || (!cfdata->locals.cur[0]))
783      {
784         e_widget_disabled_set(cfdata->gui.o_params, 1);
785         KB_EXAMPLE_PARAMS;
786         return;
787      }
788
789    if (!actd->editable)
790      e_widget_disabled_set(cfdata->gui.o_params, 1);
791    else
792      e_widget_disabled_set(cfdata->gui.o_params, 0);
793
794    if (cfdata->locals.cur[0] == 'k')
795      {
796         sscanf(cfdata->locals.cur, "k%d", &b);
797         bi = eina_list_nth(cfdata->binding.key, b);
798         if (!bi)
799           {
800              e_widget_disabled_set(cfdata->gui.o_params, 1);
801              KB_EXAMPLE_PARAMS;
802              return;
803           }
804         action = bi->action;
805         params = bi->params;
806      }
807    else
808      {
809         e_widget_disabled_set(cfdata->gui.o_params, 1);
810         KB_EXAMPLE_PARAMS;
811         return;
812      }
813
814    if (action)
815      {
816         if (!e_util_strcmp(action, actd->act_cmd))
817           {
818              if ((cfdata->locals.cur_act >= 0) && (cfdata->locals.cur_act != e_widget_ilist_selected_get(cfdata->gui.o_action_list)))
819                KB_EXAMPLE_PARAMS;
820              else
821                e_widget_entry_text_set(cfdata->gui.o_params, params);
822           }
823         else
824           KB_EXAMPLE_PARAMS;
825      }
826    else
827      KB_EXAMPLE_PARAMS;
828 }
829
830 static int
831 _update_key_binding_list(E_Config_Dialog_Data *cfdata,
832                          E_Config_Binding_Key *bi_new)
833 {
834    int i;
835    char *b, b2[64];
836    Eina_List *l;
837    E_Config_Binding_Key *bi;
838    int modifiers = -1;
839    int bi_pos = 0;
840    int ret = -1;
841
842    evas_event_freeze(evas_object_evas_get(cfdata->gui.o_binding_list));
843    edje_freeze();
844    e_widget_ilist_freeze(cfdata->gui.o_binding_list);
845
846    e_widget_ilist_clear(cfdata->gui.o_binding_list);
847    e_widget_ilist_go(cfdata->gui.o_binding_list);
848
849    if (cfdata->binding.key)
850      {
851         cfdata->binding.key = eina_list_sort(cfdata->binding.key,
852                                              eina_list_count(cfdata->binding.key), _key_binding_sort_cb);
853      }
854
855    for (l = cfdata->binding.key, i = 0; l; l = l->next, i++)
856      {
857         bi = l->data;
858         if (bi == bi_new) ret = bi_pos;
859         if (ret < 0) bi_pos++;
860
861         if (modifiers != (int)bi->modifiers)
862           {
863              modifiers = bi->modifiers;
864              b = _key_binding_header_get(modifiers);
865              if (b)
866                {
867                   if (ret < 0) bi_pos++;
868                   e_widget_ilist_header_append(cfdata->gui.o_binding_list, NULL, b);
869                   free(b);
870                }
871           }
872
873         b = _key_binding_text_get(bi);
874         if (!b) continue;
875
876         snprintf(b2, sizeof(b2), "k%d", i);
877         e_widget_ilist_append(cfdata->gui.o_binding_list, NULL, b,
878                               _binding_change_cb, cfdata, b2);
879         free(b);
880      }
881    e_widget_ilist_go(cfdata->gui.o_binding_list);
882
883    e_widget_ilist_thaw(cfdata->gui.o_binding_list);
884    edje_thaw();
885    evas_event_thaw(evas_object_evas_get(cfdata->gui.o_binding_list));
886
887    if (eina_list_count(cfdata->binding.key))
888      e_widget_disabled_set(cfdata->gui.o_del_all, 0);
889    else
890      e_widget_disabled_set(cfdata->gui.o_del_all, 1);
891
892    return ret;
893 }
894
895 static void
896 _update_buttons(E_Config_Dialog_Data *cfdata)
897 {
898    if (e_widget_ilist_count(cfdata->gui.o_binding_list))
899      e_widget_disabled_set(cfdata->gui.o_del_all, 0);
900    else
901      e_widget_disabled_set(cfdata->gui.o_del_all, 1);
902
903    if (!cfdata->locals.cur)
904      {
905         e_widget_disabled_set(cfdata->gui.o_mod, 1);
906         e_widget_disabled_set(cfdata->gui.o_del, 1);
907         return;
908      }
909    e_widget_disabled_set(cfdata->gui.o_mod, 0);
910    e_widget_disabled_set(cfdata->gui.o_del, 0);
911 }
912
913 /*************** Sorting *****************************/
914 static int
915 _key_binding_sort_cb(const void *d1,
916                      const void *d2)
917 {
918    int i, j;
919    const E_Config_Binding_Key *bi, *bi2;
920
921    bi = d1;
922    bi2 = d2;
923
924    i = 0; j = 0;
925    if (bi->modifiers & E_BINDING_MODIFIER_CTRL) i++;
926    if (bi->modifiers & E_BINDING_MODIFIER_ALT) i++;
927    if (bi->modifiers & E_BINDING_MODIFIER_SHIFT) i++;
928    if (bi->modifiers & E_BINDING_MODIFIER_WIN) i++;
929
930    if (bi2->modifiers & E_BINDING_MODIFIER_CTRL) j++;
931    if (bi2->modifiers & E_BINDING_MODIFIER_ALT) j++;
932    if (bi2->modifiers & E_BINDING_MODIFIER_SHIFT) j++;
933    if (bi2->modifiers & E_BINDING_MODIFIER_WIN) j++;
934
935    if (i < j) return -1;
936    else if (i > j)
937      return 1;
938
939    if (bi->modifiers < bi2->modifiers) return -1;
940    else if (bi->modifiers > bi2->modifiers)
941      return 1;
942
943    i = strlen(bi->key ? bi->key : "");
944    j = strlen(bi2->key ? bi2->key : "");
945
946    if (i < j) return -1;
947    else if (i > j)
948      return 1;
949
950    i = e_util_strcmp(bi->key, bi2->key);
951    if (i < 0) return -1;
952    else if (i > 0)
953      return 1;
954
955    return 0;
956 }
957
958 /**************** grab window *******/
959
960 static void
961 _grab_wnd_hide(void *data)
962 {
963    E_Config_Dialog_Data *cfdata;
964
965    cfdata = e_object_data_get(data);
966    cfdata->locals.eg = NULL;
967 }
968
969 static void
970 _grab_wnd_show(E_Config_Dialog_Data *cfdata)
971 {
972    if (cfdata->locals.eg) return;
973    cfdata->locals.eg = e_grab_dialog_show(cfdata->cfd->dia->win, EINA_FALSE, _grab_key_down_cb, NULL, NULL, cfdata);
974    e_object_data_set(E_OBJECT(cfdata->locals.eg), cfdata);
975    e_object_del_attach_func_set(E_OBJECT(cfdata->locals.eg), _grab_wnd_hide);
976 }
977
978 static Eina_Bool
979 _grab_key_down_cb(void *data,
980                   __UNUSED__ int type,
981                   void *event)
982 {
983    E_Config_Dialog_Data *cfdata;
984    Ecore_Event_Key *ev;
985
986    ev = event;
987    cfdata = data;
988
989    if ((ev->keyname) && (ev->key) && (ev->compose))
990      printf("'%s' '%s' '%s'\n", ev->keyname, ev->key, ev->compose);
991    else if ((ev->keyname) && (ev->key))
992      printf("'%s' '%s'\n", ev->keyname, ev->key);
993    else
994      printf("unknown key!!!!\n");
995    if (!e_util_strcmp(ev->keyname, "Control_L") || !e_util_strcmp(ev->keyname, "Control_R") ||
996        !e_util_strcmp(ev->keyname, "Shift_L") || !e_util_strcmp(ev->keyname, "Shift_R") ||
997        !e_util_strcmp(ev->keyname, "Alt_L") || !e_util_strcmp(ev->keyname, "Alt_R") ||
998        !e_util_strcmp(ev->keyname, "Super_L") || !e_util_strcmp(ev->keyname, "Super_R"))
999      {
1000         /* Do nothing */
1001      }
1002    else
1003      {
1004         E_Config_Binding_Key *bi = NULL;
1005         const Eina_List *l = NULL;
1006         unsigned int mod = E_BINDING_MODIFIER_NONE;
1007         unsigned int n, found = 0;
1008
1009         if (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT)
1010           mod |= E_BINDING_MODIFIER_SHIFT;
1011         if (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL)
1012           mod |= E_BINDING_MODIFIER_CTRL;
1013         if (ev->modifiers & ECORE_EVENT_MODIFIER_ALT)
1014           mod |= E_BINDING_MODIFIER_ALT;
1015         if (ev->modifiers & ECORE_EVENT_MODIFIER_WIN)
1016           mod |= E_BINDING_MODIFIER_WIN;
1017
1018         if (cfdata->locals.add)
1019           found = !!e_util_binding_match(cfdata->binding.key, ev, &n, NULL);
1020         else if (cfdata->locals.cur && cfdata->locals.cur[0])
1021           {
1022              sscanf(cfdata->locals.cur, "k%d", &n);
1023              bi = eina_list_nth(cfdata->binding.key, n);
1024              found = !!e_util_binding_match(cfdata->binding.key, ev, &n, bi);
1025           }
1026
1027         if (!found)
1028           {
1029              if (cfdata->locals.add)
1030                {
1031                   bi = E_NEW(E_Config_Binding_Key, 1);
1032
1033                   bi->context = E_BINDING_CONTEXT_ANY;
1034                   bi->modifiers = mod;
1035                   bi->key = eina_stringshare_add(ev->keyname);
1036                   bi->action = NULL;
1037                   bi->params = NULL;
1038                   bi->any_mod = 0;
1039
1040                   cfdata->binding.key = eina_list_append(cfdata->binding.key, bi);
1041
1042                   n = _update_key_binding_list(cfdata, bi);
1043
1044                   e_widget_ilist_selected_set(cfdata->gui.o_binding_list, n);
1045                   e_widget_ilist_nth_show(cfdata->gui.o_binding_list, n, 0);
1046                   e_widget_ilist_unselect(cfdata->gui.o_action_list);
1047                   eina_stringshare_del(cfdata->locals.action);
1048                   cfdata->locals.action = eina_stringshare_add("");
1049                   if ((cfdata->params) && (cfdata->params[0]))
1050                     {
1051                        int j, g = -1;
1052                        _find_key_binding_action("exec", NULL, &g, NULL, &j);
1053                        if (j >= 0)
1054                          {
1055                             e_widget_ilist_unselect(cfdata->gui.o_action_list);
1056                             e_widget_ilist_selected_set(cfdata->gui.o_action_list, (j + g + 1));
1057                             e_widget_entry_clear(cfdata->gui.o_params);
1058                             e_widget_entry_text_set(cfdata->gui.o_params, cfdata->params);
1059                          }
1060                     }
1061                   else
1062                     {
1063                        e_widget_entry_clear(cfdata->gui.o_params);
1064                        e_widget_disabled_set(cfdata->gui.o_params, 1);
1065                     }
1066                }
1067              else if (cfdata->locals.cur && cfdata->locals.cur[0])
1068                {
1069                   char *label;
1070                   E_Ilist_Item *it;
1071                   unsigned int i = 0;
1072
1073                   sscanf(cfdata->locals.cur, "k%d", &n);
1074                   bi = eina_list_nth(cfdata->binding.key, n);
1075
1076                   bi->modifiers = mod;
1077                   if (bi->key) eina_stringshare_del(bi->key);
1078                   bi->key = eina_stringshare_add(ev->keyname);
1079                   printf("blub\n");
1080
1081                   label = _key_binding_text_get(bi);
1082
1083                   EINA_LIST_FOREACH(e_widget_ilist_items_get(cfdata->gui.o_binding_list), l, it)
1084                     {
1085                        if (it->header) n++;
1086                        if (i++ >= n) break;
1087                     }
1088
1089                   e_widget_ilist_nth_label_set(cfdata->gui.o_binding_list, n, label);
1090                   free(label);
1091                }
1092           }
1093         else
1094           {
1095              unsigned int i = 0;
1096              E_Ilist_Item *it;
1097 #if 0
1098              /* this advice is rather irritating as one sees that the
1099                 key is bound to an action. if you want to set a
1100                 keybinding you dont care about whether there is
1101                 sth else set to it. */
1102              int g, a, j;
1103              const char *label = NULL;
1104              E_Action_Group *actg = NULL;
1105              E_Action_Description *actd = NULL;
1106
1107              if (cfdata->locals.add)
1108                _find_key_binding_action(bi->action, bi->params, &g, &a, &j);
1109              else
1110                _find_key_binding_action(bi2->action, bi2->params, &g, &a, &j);
1111
1112              actg = eina_list_nth(e_action_groups_get(), g);
1113              if (actg) actd = eina_list_nth(actg->acts, a);
1114
1115              if (actd) label = _(actd->act_name);
1116
1117              e_util_dialog_show(_("Binding Key Error"),
1118                                 _("The binding key sequence, that you choose,"
1119                                   " is already used by <br>"
1120                                   "<hilight>%s</hilight> action.<br>"
1121                                   "Please choose another binding key sequence."),
1122                                 label ? label : _("Unknown"));
1123 #endif
1124              EINA_LIST_FOREACH(e_widget_ilist_items_get(cfdata->gui.o_binding_list), l, it)
1125                {
1126                   if (it->header) n++;
1127                   if (i++ >= n) break;
1128                }
1129
1130              e_widget_ilist_nth_show(cfdata->gui.o_binding_list, n - 1, 1);
1131              e_widget_ilist_selected_set(cfdata->gui.o_binding_list, n - 1);
1132           }
1133         e_object_del(E_OBJECT(cfdata->locals.eg));
1134      }
1135    return ECORE_CALLBACK_PASS_ON;
1136 }
1137
1138
1139 /********** Helper *********************************/
1140 static void
1141 _auto_apply_changes(E_Config_Dialog_Data *cfdata)
1142 {
1143    int n, g, a, ok;
1144    E_Config_Binding_Key *bi;
1145    E_Action_Group *actg;
1146    E_Action_Description *actd;
1147
1148    if ((!cfdata->locals.cur) || (!cfdata->locals.cur[0]) ||
1149        (!cfdata->locals.action) || (!cfdata->locals.action[0])) return;
1150
1151    sscanf(cfdata->locals.cur, "k%d", &n);
1152    sscanf(cfdata->locals.action, "%d %d", &g, &a);
1153
1154    bi = eina_list_nth(cfdata->binding.key, n);
1155    if (!bi) return;
1156
1157    actg = eina_list_nth(e_action_groups_get(), g);
1158    if (!actg) return;
1159    actd = eina_list_nth(actg->acts, a);
1160    if (!actd) return;
1161
1162    eina_stringshare_del(bi->action);
1163    bi->action = NULL;
1164
1165    if (actd->act_cmd) bi->action = eina_stringshare_add(actd->act_cmd);
1166
1167    eina_stringshare_del(bi->params);
1168    bi->params = NULL;
1169
1170    if (actd->act_params)
1171      bi->params = eina_stringshare_add(actd->act_params);
1172    else
1173      {
1174         ok = 1;
1175         if (cfdata->locals.params)
1176           {
1177              if (!e_util_strcmp(cfdata->locals.params, TEXT_NO_PARAMS))
1178                ok = 0;
1179
1180              if ((actd->param_example) && (!e_util_strcmp(cfdata->locals.params, actd->param_example)))
1181                ok = 0;
1182           }
1183         else
1184           ok = 0;
1185
1186         if (ok)
1187           bi->params = eina_stringshare_add(cfdata->locals.params);
1188      }
1189 }
1190
1191 static void
1192 _find_key_binding_action(const char *action,
1193                          const char *params,
1194                          int *g,
1195                          int *a,
1196                          int *n)
1197 {
1198    Eina_List *l, *l2;
1199    int gg = -1, aa = -1, nn = -1, found;
1200    E_Action_Group *actg;
1201    E_Action_Description *actd;
1202
1203    if (g) *g = -1;
1204    if (a) *a = -1;
1205    if (n) *n = -1;
1206
1207    found = 0;
1208    for (l = e_action_groups_get(), gg = 0, nn = 0; l; l = l->next, gg++)
1209      {
1210         actg = l->data;
1211
1212         for (l2 = actg->acts, aa = 0; l2; l2 = l2->next, aa++)
1213           {
1214              actd = l2->data;
1215              if (!e_util_strcmp((!action ? "" : action), (!actd->act_cmd ? "" : actd->act_cmd)))
1216                {
1217                   if (!params || !params[0])
1218                     {
1219                        if ((!actd->act_params) || (!actd->act_params[0]))
1220                          {
1221                             if (g) *g = gg;
1222                             if (a) *a = aa;
1223                             if (n) *n = nn;
1224                             return;
1225                          }
1226                        else
1227                          continue;
1228                     }
1229                   else
1230                     {
1231                        if ((!actd->act_params) || (!actd->act_params[0]))
1232                          {
1233                             if (g) *g = gg;
1234                             if (a) *a = aa;
1235                             if (n) *n = nn;
1236                             found = 1;
1237                          }
1238                        else
1239                          {
1240                             if (!e_util_strcmp(params, actd->act_params))
1241                               {
1242                                  if (g) *g = gg;
1243                                  if (a) *a = aa;
1244                                  if (n) *n = nn;
1245                                  return;
1246                               }
1247                          }
1248                     }
1249                }
1250              nn++;
1251           }
1252         if (found) break;
1253      }
1254
1255    if (!found)
1256      {
1257         if (g) *g = -1;
1258         if (a) *a = -1;
1259         if (n) *n = -1;
1260      }
1261 }
1262
1263 static char *
1264 _key_binding_header_get(int modifiers)
1265 {
1266    char b[256] = "";
1267
1268    if (modifiers & E_BINDING_MODIFIER_CTRL)
1269      strcat(b, _("CTRL"));
1270
1271    if (modifiers & E_BINDING_MODIFIER_ALT)
1272      {
1273         if (b[0]) strcat(b, " + ");
1274         strcat(b, _("ALT"));
1275      }
1276
1277    if (modifiers & E_BINDING_MODIFIER_SHIFT)
1278      {
1279         if (b[0]) strcat(b, " + ");
1280         strcat(b, _("SHIFT"));
1281      }
1282
1283    if (modifiers & E_BINDING_MODIFIER_WIN)
1284      {
1285         if (b[0]) strcat(b, " + ");
1286         strcat(b, _("WIN"));
1287      }
1288
1289    if (!b[0]) return strdup(TEXT_NO_MODIFIER_HEADER);
1290    return strdup(b);
1291 }
1292
1293 static char *
1294 _key_binding_text_get(E_Config_Binding_Key *bi)
1295 {
1296    char b[256] = "";
1297
1298    if (!bi) return NULL;
1299
1300    if (bi->modifiers & E_BINDING_MODIFIER_CTRL)
1301      strcat(b, _("CTRL"));
1302
1303    if (bi->modifiers & E_BINDING_MODIFIER_ALT)
1304      {
1305         if (b[0]) strcat(b, " + ");
1306         strcat(b, _("ALT"));
1307      }
1308
1309    if (bi->modifiers & E_BINDING_MODIFIER_SHIFT)
1310      {
1311         if (b[0]) strcat(b, " + ");
1312         strcat(b, _("SHIFT"));
1313      }
1314
1315    if (bi->modifiers & E_BINDING_MODIFIER_WIN)
1316      {
1317         if (b[0]) strcat(b, " + ");
1318         strcat(b, _("WIN"));
1319      }
1320
1321    if (bi->key && bi->key[0])
1322      {
1323         char *l;
1324         if (b[0]) strcat(b, " + ");
1325
1326         l = strdup(bi->key);
1327         l[0] = (char)toupper(bi->key[0]);
1328         strcat(b, l);
1329         free(l);
1330      }
1331
1332    /* see comment in e_bindings on numlock
1333       if (bi->modifiers & ECORE_X_LOCK_NUM)
1334       {
1335         if (b[0]) strcat(b, " ");
1336         strcat(b, _("OFF"));
1337       }
1338     */
1339
1340    if (!b[0]) return strdup(TEXT_NONE_ACTION_KEY);
1341    return strdup(b);
1342 }
1343