854fa688ea4d9b108da23f340f4764abe3a6071d
[blender.git] / source / blender / windowmanager / intern / wm_keymap.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2007 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /** \file blender/windowmanager/intern/wm_keymap.c
30  *  \ingroup wm
31  */
32
33
34 #include <string.h>
35
36 #include "DNA_object_types.h"
37 #include "DNA_screen_types.h"
38 #include "DNA_space_types.h"
39 #include "DNA_userdef_types.h"
40 #include "DNA_windowmanager_types.h"
41
42 #include "MEM_guardedalloc.h"
43
44 #include "BLI_blenlib.h"
45 #include "BLI_utildefines.h"
46
47 #include "BKE_blender.h"
48 #include "BKE_context.h"
49 #include "BKE_idprop.h"
50 #include "BKE_global.h"
51 #include "BKE_library.h"
52 #include "BKE_main.h"
53 #include "BKE_screen.h"
54
55
56 #include "RNA_access.h"
57 #include "RNA_enum_types.h"
58
59 #include "WM_api.h"
60 #include "WM_types.h"
61 #include "wm_window.h"
62 #include "wm_event_system.h"
63 #include "wm_event_types.h"
64
65 /******************************* Keymap Item **********************************
66  * Item in a keymap, that maps from an event to an operator or modal map item */
67
68 static wmKeyMapItem *wm_keymap_item_copy(wmKeyMapItem *kmi)
69 {
70         wmKeyMapItem *kmin = MEM_dupallocN(kmi);
71
72         kmin->prev= kmin->next= NULL;
73         kmin->flag &= ~KMI_UPDATE;
74
75         if(kmin->properties) {
76                 kmin->ptr= MEM_callocN(sizeof(PointerRNA), "UserKeyMapItemPtr");
77                 WM_operator_properties_create(kmin->ptr, kmin->idname);
78
79                 kmin->properties= IDP_CopyProperty(kmin->properties);
80                 kmin->ptr->data= kmin->properties;
81         }
82
83         return kmin;
84 }
85
86 static void wm_keymap_item_free(wmKeyMapItem *kmi)
87 {
88         /* not kmi itself */
89         if(kmi->ptr) {
90                 WM_operator_properties_free(kmi->ptr);
91                 MEM_freeN(kmi->ptr);
92         }
93 }
94
95 static void wm_keymap_item_properties_set(wmKeyMapItem *kmi)
96 {
97         WM_operator_properties_alloc(&(kmi->ptr), &(kmi->properties), kmi->idname);
98         WM_operator_properties_sanitize(kmi->ptr, 1);
99 }
100
101 static int wm_keymap_item_equals_result(wmKeyMapItem *a, wmKeyMapItem *b)
102 {
103         if(strcmp(a->idname, b->idname) != 0)
104                 return 0;
105         
106         if(!((a->ptr==NULL && b->ptr==NULL) ||
107              (a->ptr && b->ptr && IDP_EqualsProperties(a->ptr->data, b->ptr->data))))
108                 return 0;
109         
110         if((a->flag & KMI_INACTIVE) != (b->flag & KMI_INACTIVE))
111                 return 0;
112         
113         return (a->propvalue == b->propvalue);
114 }
115
116 static int wm_keymap_item_equals(wmKeyMapItem *a, wmKeyMapItem *b)
117 {
118         return (wm_keymap_item_equals_result(a, b) &&
119                 a->type == b->type &&
120                 a->val == b->val &&
121                 a->shift == b->shift &&
122                 a->ctrl == b->ctrl &&
123                 a->alt == b->alt &&
124                 a->oskey == b->oskey &&
125                 a->keymodifier == b->keymodifier &&
126                 a->maptype == b->maptype);
127 }
128
129 /* properties can be NULL, otherwise the arg passed is used and ownership is given to the kmi */
130 void WM_keymap_properties_reset(wmKeyMapItem *kmi, struct IDProperty *properties)
131 {
132         WM_operator_properties_free(kmi->ptr);
133         MEM_freeN(kmi->ptr);
134
135         kmi->ptr = NULL;
136         kmi->properties = properties;
137
138         wm_keymap_item_properties_set(kmi);
139 }
140
141 /**************************** Keymap Diff Item *********************************
142  * Item in a diff keymap, used for saving diff of keymaps in user preferences */
143
144 static wmKeyMapDiffItem *wm_keymap_diff_item_copy(wmKeyMapDiffItem *kmdi)
145 {
146         wmKeyMapDiffItem *kmdin = MEM_dupallocN(kmdi);
147
148         kmdin->next = kmdin->prev = NULL;
149         if(kmdi->add_item)
150                 kmdin->add_item = wm_keymap_item_copy(kmdi->add_item);
151         if(kmdi->remove_item)
152                 kmdin->remove_item = wm_keymap_item_copy(kmdi->remove_item);
153         
154         return kmdin;
155 }
156
157 static void wm_keymap_diff_item_free(wmKeyMapDiffItem *kmdi)
158 {
159         if(kmdi->remove_item) {
160                 wm_keymap_item_free(kmdi->remove_item);
161                 MEM_freeN(kmdi->remove_item);
162         }
163         if(kmdi->add_item) {
164                 wm_keymap_item_free(kmdi->add_item);
165                 MEM_freeN(kmdi->add_item);
166         }
167 }
168
169 /***************************** Key Configuration ******************************
170  * List of keymaps for all editors, modes, ... . There is a builtin default key
171  * configuration, a user key configuration, and other preset configurations. */
172
173 wmKeyConfig *WM_keyconfig_new(wmWindowManager *wm, const char *idname)
174 {
175         wmKeyConfig *keyconf;
176         
177         keyconf= MEM_callocN(sizeof(wmKeyConfig), "wmKeyConfig");
178         BLI_strncpy(keyconf->idname, idname, sizeof(keyconf->idname));
179         BLI_addtail(&wm->keyconfigs, keyconf);
180
181         return keyconf;
182 }
183
184 wmKeyConfig *WM_keyconfig_new_user(wmWindowManager *wm, const char *idname)
185 {
186         wmKeyConfig *keyconf = WM_keyconfig_new(wm, idname);
187
188         keyconf->flag |= KEYCONF_USER;
189
190         return keyconf;
191 }
192
193 void WM_keyconfig_remove(wmWindowManager *wm, wmKeyConfig *keyconf)
194 {
195         if (keyconf) {
196                 if (strncmp(U.keyconfigstr, keyconf->idname, sizeof(U.keyconfigstr)) == 0) {
197                         BLI_strncpy(U.keyconfigstr, wm->defaultconf->idname, sizeof(U.keyconfigstr));
198                         WM_keyconfig_update_tag(NULL, NULL);
199                 }
200
201                 BLI_remlink(&wm->keyconfigs, keyconf);
202                 WM_keyconfig_free(keyconf);
203         }
204 }
205
206 void WM_keyconfig_free(wmKeyConfig *keyconf)
207 {
208         wmKeyMap *km;
209
210         while((km= keyconf->keymaps.first)) {
211                 WM_keymap_free(km);
212                 BLI_freelinkN(&keyconf->keymaps, km);
213         }
214
215         MEM_freeN(keyconf);
216 }
217
218 static wmKeyConfig *wm_keyconfig_list_find(ListBase *lb, char *idname)
219 {
220         wmKeyConfig *kc;
221
222         for(kc= lb->first; kc; kc= kc->next)
223                 if(0==strncmp(idname, kc->idname, KMAP_MAX_NAME))
224                         return kc;
225         
226         return NULL;
227 }
228
229 static wmKeyConfig *WM_keyconfig_active(wmWindowManager *wm)
230 {
231         wmKeyConfig *keyconf;
232
233         /* first try from preset */
234         keyconf= wm_keyconfig_list_find(&wm->keyconfigs, U.keyconfigstr);
235         if(keyconf)
236                 return keyconf;
237         
238         /* otherwise use default */
239         return wm->defaultconf;
240 }
241
242 void WM_keyconfig_set_active(wmWindowManager *wm, const char *idname)
243 {
244         /* setting a different key configuration as active: we ensure all is
245            updated properly before and after making the change */
246
247         WM_keyconfig_update(wm);
248
249         BLI_strncpy(U.keyconfigstr, idname, sizeof(U.keyconfigstr));
250
251         WM_keyconfig_update_tag(NULL, NULL);
252         WM_keyconfig_update(wm);
253 }
254
255 /********************************** Keymap *************************************
256  * List of keymap items for one editor, mode, modal operator, ... */
257
258 static wmKeyMap *wm_keymap_new(const char *idname, int spaceid, int regionid)
259 {
260         wmKeyMap *km= MEM_callocN(sizeof(struct wmKeyMap), "keymap list");
261
262         BLI_strncpy(km->idname, idname, KMAP_MAX_NAME);
263         km->spaceid= spaceid;
264         km->regionid= regionid;
265
266         return km;
267 }
268
269 static wmKeyMap *wm_keymap_copy(wmKeyMap *keymap)
270 {
271         wmKeyMap *keymapn = MEM_dupallocN(keymap);
272         wmKeyMapItem *kmi, *kmin;
273         wmKeyMapDiffItem *kmdi, *kmdin;
274
275         keymapn->modal_items= keymap->modal_items;
276         keymapn->poll= keymap->poll;
277         keymapn->items.first= keymapn->items.last= NULL;
278         keymapn->flag &= ~(KEYMAP_UPDATE|KEYMAP_EXPANDED);
279
280         for(kmdi=keymap->diff_items.first; kmdi; kmdi=kmdi->next) {
281                 kmdin= wm_keymap_diff_item_copy(kmdi);
282                 BLI_addtail(&keymapn->items, kmdin);
283         }
284
285         for(kmi=keymap->items.first; kmi; kmi=kmi->next) {
286                 kmin= wm_keymap_item_copy(kmi);
287                 BLI_addtail(&keymapn->items, kmin);
288         }
289
290         return keymapn;
291 }
292
293 void WM_keymap_free(wmKeyMap *keymap)
294 {
295         wmKeyMapItem *kmi;
296         wmKeyMapDiffItem *kmdi;
297
298         for(kmdi=keymap->diff_items.first; kmdi; kmdi=kmdi->next)
299                 wm_keymap_diff_item_free(kmdi);
300
301         for(kmi=keymap->items.first; kmi; kmi=kmi->next)
302                 wm_keymap_item_free(kmi);
303
304         BLI_freelistN(&keymap->diff_items);
305         BLI_freelistN(&keymap->items);
306 }
307
308 static void keymap_event_set(wmKeyMapItem *kmi, short type, short val, int modifier, short keymodifier)
309 {
310         kmi->type= type;
311         kmi->val= val;
312         kmi->keymodifier= keymodifier;
313         
314         if(modifier == KM_ANY) {
315                 kmi->shift= kmi->ctrl= kmi->alt= kmi->oskey= KM_ANY;
316         }
317         else {
318                 
319                 kmi->shift= kmi->ctrl= kmi->alt= kmi->oskey= 0;
320                 
321                 /* defines? */
322                 if(modifier & KM_SHIFT)
323                         kmi->shift= 1;
324                 else if(modifier & KM_SHIFT2)
325                         kmi->shift= 2;
326                 if(modifier & KM_CTRL)
327                         kmi->ctrl= 1;
328                 else if(modifier & KM_CTRL2)
329                         kmi->ctrl= 2;
330                 if(modifier & KM_ALT)
331                         kmi->alt= 1;
332                 else if(modifier & KM_ALT2)
333                         kmi->alt= 2;
334                 if(modifier & KM_OSKEY)
335                         kmi->oskey= 1;
336                 else if(modifier & KM_OSKEY2)
337                         kmi->oskey= 2;  
338         }
339 }
340
341 static void keymap_item_set_id(wmKeyMap *keymap, wmKeyMapItem *kmi)
342 {
343         keymap->kmi_id++;
344         if ((keymap->flag & KEYMAP_USER) == 0) {
345                 kmi->id = keymap->kmi_id;
346         } else {
347                 kmi->id = -keymap->kmi_id; // User defined keymap entries have negative ids
348         }
349 }
350
351 /* if item was added, then bail out */
352 wmKeyMapItem *WM_keymap_verify_item(wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier)
353 {
354         wmKeyMapItem *kmi;
355         
356         for(kmi= keymap->items.first; kmi; kmi= kmi->next)
357                 if(strncmp(kmi->idname, idname, OP_MAX_TYPENAME)==0)
358                         break;
359         if(kmi==NULL) {
360                 kmi= MEM_callocN(sizeof(wmKeyMapItem), "keymap entry");
361                 
362                 BLI_addtail(&keymap->items, kmi);
363                 BLI_strncpy(kmi->idname, idname, OP_MAX_TYPENAME);
364                 
365                 keymap_item_set_id(keymap, kmi);
366
367                 keymap_event_set(kmi, type, val, modifier, keymodifier);
368                 wm_keymap_item_properties_set(kmi);
369         }
370         return kmi;
371 }
372
373 /* always add item */
374 wmKeyMapItem *WM_keymap_add_item(wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier)
375 {
376         wmKeyMapItem *kmi= MEM_callocN(sizeof(wmKeyMapItem), "keymap entry");
377         
378         BLI_addtail(&keymap->items, kmi);
379         BLI_strncpy(kmi->idname, idname, OP_MAX_TYPENAME);
380
381         keymap_event_set(kmi, type, val, modifier, keymodifier);
382         wm_keymap_item_properties_set(kmi);
383
384         keymap_item_set_id(keymap, kmi);
385
386         WM_keyconfig_update_tag(keymap, kmi);
387
388         return kmi;
389 }
390
391 /* menu wrapper for WM_keymap_add_item */
392 wmKeyMapItem *WM_keymap_add_menu(wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier)
393 {
394         wmKeyMapItem *kmi= WM_keymap_add_item(keymap, "WM_OT_call_menu", type, val, modifier, keymodifier);
395         RNA_string_set(kmi->ptr, "name", idname);
396         return kmi;
397 }
398
399 void WM_keymap_remove_item(wmKeyMap *keymap, wmKeyMapItem *kmi)
400 {
401         if(BLI_findindex(&keymap->items, kmi) != -1) {
402                 if(kmi->ptr) {
403                         WM_operator_properties_free(kmi->ptr);
404                         MEM_freeN(kmi->ptr);
405                 }
406                 BLI_freelinkN(&keymap->items, kmi);
407
408                 WM_keyconfig_update_tag(keymap, kmi);
409         }
410 }
411
412 /************************** Keymap Diff and Patch ****************************
413  * Rather than saving the entire keymap for user preferences, we only save a
414  * diff so that changes in the defaults get synced. This system is not perfect
415  * but works better than overriding the keymap entirely when only few items
416  * are changed. */
417
418 static void wm_keymap_addon_add(wmKeyMap *keymap, wmKeyMap *addonmap)
419 {
420         wmKeyMapItem *kmi, *kmin;
421
422         for(kmi=addonmap->items.first; kmi; kmi=kmi->next) {
423                 kmin = wm_keymap_item_copy(kmi);
424                 keymap_item_set_id(keymap, kmin);
425                 BLI_addhead(&keymap->items, kmin);
426         }
427 }
428
429 static wmKeyMapItem *wm_keymap_find_item_equals(wmKeyMap *km, wmKeyMapItem *needle)
430 {
431         wmKeyMapItem *kmi;
432
433         for(kmi=km->items.first; kmi; kmi=kmi->next)
434                 if(wm_keymap_item_equals(kmi, needle))
435                         return kmi;
436         
437         return NULL;
438 }
439
440 static wmKeyMapItem *wm_keymap_find_item_equals_result(wmKeyMap *km, wmKeyMapItem *needle)
441 {
442         wmKeyMapItem *kmi;
443
444         for(kmi=km->items.first; kmi; kmi=kmi->next)
445                 if(wm_keymap_item_equals_result(kmi, needle))
446                         return kmi;
447         
448         return NULL;
449 }
450
451 static void wm_keymap_diff(wmKeyMap *diff_km, wmKeyMap *from_km, wmKeyMap *to_km, wmKeyMap *orig_km, wmKeyMap *addon_km)
452 {
453         wmKeyMapItem *kmi, *to_kmi, *orig_kmi;
454         wmKeyMapDiffItem *kmdi;
455
456         for(kmi=from_km->items.first; kmi; kmi=kmi->next) {
457                 to_kmi = WM_keymap_item_find_id(to_km, kmi->id);
458
459                 if(!to_kmi) {
460                         /* remove item */
461                         kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem");
462                         kmdi->remove_item = wm_keymap_item_copy(kmi);
463                         BLI_addtail(&diff_km->diff_items, kmdi);
464                 }
465                 else if(to_kmi && !wm_keymap_item_equals(kmi, to_kmi)) {
466                         /* replace item */
467                         kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem");
468                         kmdi->remove_item = wm_keymap_item_copy(kmi);
469                         kmdi->add_item = wm_keymap_item_copy(to_kmi);
470                         BLI_addtail(&diff_km->diff_items, kmdi);
471                 }
472
473                 /* sync expanded flag back to original so we don't loose it on repatch */
474                 if(to_kmi) {
475                         orig_kmi = WM_keymap_item_find_id(orig_km, kmi->id);
476
477                         if(!orig_kmi)
478                                 orig_kmi = wm_keymap_find_item_equals(addon_km, kmi);
479
480                         if(orig_kmi) {
481                                 orig_kmi->flag &= ~KMI_EXPANDED;
482                                 orig_kmi->flag |= (to_kmi->flag & KMI_EXPANDED);
483                         }
484                 }
485         }
486
487         for(kmi=to_km->items.first; kmi; kmi=kmi->next) {
488                 if(kmi->id < 0) {
489                         /* add item */
490                         kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem");
491                         kmdi->add_item = wm_keymap_item_copy(kmi);
492                         BLI_addtail(&diff_km->diff_items, kmdi);
493                 }
494         }
495 }
496
497 static void wm_keymap_patch(wmKeyMap *km, wmKeyMap *diff_km)
498 {
499         wmKeyMapDiffItem *kmdi;
500         wmKeyMapItem *kmi_remove, *kmi_add;
501
502         for(kmdi=diff_km->diff_items.first; kmdi; kmdi=kmdi->next) {
503                 /* find item to remove */
504                 kmi_remove = NULL;
505                 if(kmdi->remove_item) {
506                         kmi_remove = wm_keymap_find_item_equals(km, kmdi->remove_item);
507                         if(!kmi_remove)
508                                 kmi_remove = wm_keymap_find_item_equals_result(km, kmdi->remove_item);
509                 }
510
511                 /* add item */
512                 if(kmdi->add_item) {
513                         /* only if nothing to remove or item to remove found */
514                         if(!kmdi->remove_item || kmi_remove) {
515                                 kmi_add = wm_keymap_item_copy(kmdi->add_item);
516                                 kmi_add->flag |= KMI_USER_MODIFIED;
517
518                                 if(kmi_remove) {
519                                         kmi_add->flag &= ~KMI_EXPANDED;
520                                         kmi_add->flag |= (kmi_remove->flag & KMI_EXPANDED);
521                                         kmi_add->id = kmi_remove->id;
522                                         BLI_insertlinkbefore(&km->items, kmi_remove, kmi_add);
523                                 }
524                                 else {
525                                         keymap_item_set_id(km, kmi_add);
526                                         BLI_addtail(&km->items, kmi_add);
527                                 }
528                         }
529                 }
530
531                 /* remove item */
532                 if(kmi_remove) {
533                         wm_keymap_item_free(kmi_remove);
534                         BLI_freelinkN(&km->items, kmi_remove);
535                 }
536         }
537 }
538
539 static wmKeyMap *wm_keymap_patch_update(ListBase *lb, wmKeyMap *defaultmap, wmKeyMap *addonmap, wmKeyMap *usermap)
540 {
541         wmKeyMap *km;
542         int expanded = 0;
543
544         /* remove previous keymap in list, we will replace it */
545         km = WM_keymap_list_find(lb, defaultmap->idname, defaultmap->spaceid, defaultmap->regionid);
546         if(km) {
547                 expanded = (km->flag & (KEYMAP_EXPANDED|KEYMAP_CHILDREN_EXPANDED));
548                 WM_keymap_free(km);
549                 BLI_freelinkN(lb, km);
550         }
551
552         /* copy new keymap from an existing one */
553         if(usermap && !(usermap->flag & KEYMAP_DIFF)) {
554                 /* for compatibiltiy with old user preferences with non-diff
555                    keymaps we override the original entirely */
556                 wmKeyMapItem *kmi, *orig_kmi;
557
558                 km = wm_keymap_copy(usermap);
559
560                 /* try to find corresponding id's for items */
561                 for(kmi=km->items.first; kmi; kmi=kmi->next) {
562                         orig_kmi = wm_keymap_find_item_equals(defaultmap, kmi);
563                         if(!orig_kmi)
564                                 orig_kmi = wm_keymap_find_item_equals_result(defaultmap, kmi);
565
566                         if(orig_kmi)
567                                 kmi->id = orig_kmi->id;
568                         else
569                                 kmi->id = -(km->kmi_id++);
570                 }
571
572                 km->flag |= KEYMAP_UPDATE; /* update again to create diff */
573         }
574         else
575                 km = wm_keymap_copy(defaultmap);
576
577         /* add addon keymap items */
578         if(addonmap)
579                 wm_keymap_addon_add(km, addonmap);
580
581         /* tag as being user edited */
582         if(usermap)
583                 km->flag |= KEYMAP_USER_MODIFIED;
584         km->flag |= KEYMAP_USER|expanded;
585
586         /* apply user changes of diff keymap */
587         if(usermap && (usermap->flag & KEYMAP_DIFF))
588                 wm_keymap_patch(km, usermap);
589
590         /* add to list */
591         BLI_addtail(lb, km);
592         
593         return km;
594 }
595
596 static void wm_keymap_diff_update(ListBase *lb, wmKeyMap *defaultmap, wmKeyMap *addonmap, wmKeyMap *km)
597 {
598         wmKeyMap *diffmap, *prevmap, *origmap;
599
600         /* create temporary default + addon keymap for diff */
601         origmap = defaultmap;
602
603         if(addonmap) {
604                 defaultmap = wm_keymap_copy(defaultmap);
605                 wm_keymap_addon_add(defaultmap, addonmap);
606         }
607
608         /* remove previous diff keymap in list, we will replace it */
609         prevmap = WM_keymap_list_find(lb, km->idname, km->spaceid, km->regionid);
610         if(prevmap) {
611                 WM_keymap_free(prevmap);
612                 BLI_freelinkN(lb, prevmap);
613         }
614
615         /* create diff keymap */
616         diffmap= wm_keymap_new(km->idname, km->spaceid, km->regionid);
617         diffmap->flag |= KEYMAP_DIFF;
618         wm_keymap_diff(diffmap, defaultmap, km, origmap, addonmap);
619
620         /* add to list if not empty */
621         if(diffmap->diff_items.first) {
622                 BLI_addtail(lb, diffmap);
623         }
624         else {
625                 WM_keymap_free(diffmap);
626                 MEM_freeN(diffmap);
627         }
628
629         /* free temporary default map */
630         if(addonmap) {
631                 WM_keymap_free(defaultmap);
632                 MEM_freeN(defaultmap);
633         }
634 }
635
636 /* ****************** storage in WM ************ */
637
638 /* name id's are for storing general or multiple keymaps, 
639    space/region ids are same as DNA_space_types.h */
640 /* gets free'd in wm.c */
641
642 wmKeyMap *WM_keymap_list_find(ListBase *lb, const char *idname, int spaceid, int regionid)
643 {
644         wmKeyMap *km;
645
646         for(km= lb->first; km; km= km->next)
647                 if(km->spaceid==spaceid && km->regionid==regionid)
648                         if(0==strncmp(idname, km->idname, KMAP_MAX_NAME))
649                                 return km;
650         
651         return NULL;
652 }
653
654 wmKeyMap *WM_keymap_find(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid)
655 {
656         wmKeyMap *km= WM_keymap_list_find(&keyconf->keymaps, idname, spaceid, regionid);
657         
658         if(km==NULL) {
659                 km= wm_keymap_new(idname, spaceid, regionid);
660                 BLI_addtail(&keyconf->keymaps, km);
661
662                 WM_keyconfig_update_tag(km, NULL);
663         }
664         
665         return km;
666 }
667
668 wmKeyMap *WM_keymap_find_all(const bContext *C, const char *idname, int spaceid, int regionid)
669 {
670         wmWindowManager *wm= CTX_wm_manager(C);
671
672         return WM_keymap_list_find(&wm->userconf->keymaps, idname, spaceid, regionid);
673 }
674
675 /* ****************** modal keymaps ************ */
676
677 /* modal maps get linked to a running operator, and filter the keys before sending to modal() callback */
678
679 wmKeyMap *WM_modalkeymap_add(wmKeyConfig *keyconf, const char *idname, EnumPropertyItem *items)
680 {
681         wmKeyMap *km= WM_keymap_find(keyconf, idname, 0, 0);
682         km->flag |= KEYMAP_MODAL;
683         km->modal_items= items;
684
685         if(!items) {
686                 /* init modal items from default config */
687                 wmWindowManager *wm = G.main->wm.first;
688                 wmKeyMap *defaultkm= WM_keymap_list_find(&wm->defaultconf->keymaps, km->idname, 0, 0);
689
690                 if(defaultkm) {
691                         km->modal_items = defaultkm->modal_items;
692                         km->poll = defaultkm->poll;
693                 }
694         }
695         
696         return km;
697 }
698
699 wmKeyMap *WM_modalkeymap_get(wmKeyConfig *keyconf, const char *idname)
700 {
701         wmKeyMap *km;
702         
703         for(km= keyconf->keymaps.first; km; km= km->next)
704                 if(km->flag & KEYMAP_MODAL)
705                         if(0==strncmp(idname, km->idname, KMAP_MAX_NAME))
706                                 break;
707         
708         return km;
709 }
710
711
712 wmKeyMapItem *WM_modalkeymap_add_item(wmKeyMap *km, int type, int val, int modifier, int keymodifier, int value)
713 {
714         wmKeyMapItem *kmi= MEM_callocN(sizeof(wmKeyMapItem), "keymap entry");
715         
716         BLI_addtail(&km->items, kmi);
717         kmi->propvalue= value;
718         
719         keymap_event_set(kmi, type, val, modifier, keymodifier);
720
721         keymap_item_set_id(km, kmi);
722
723         WM_keyconfig_update_tag(km, kmi);
724
725         return kmi;
726 }
727
728 void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
729 {
730         wmOperatorType *ot= WM_operatortype_find(opname, 0);
731         
732         if(ot)
733                 ot->modalkeymap= km;
734         else
735                 printf("error: modalkeymap_assign, unknown operator %s\n", opname);
736 }
737
738 /* ***************** get string from key events **************** */
739
740 const char *WM_key_event_string(short type)
741 {
742         const char *name= NULL;
743         if(RNA_enum_name(event_type_items, (int)type, &name))
744                 return name;
745         
746         return "";
747 }
748
749 char *WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, int len)
750 {
751         char buf[128];
752
753         buf[0]= 0;
754
755         if (kmi->shift == KM_ANY &&
756                 kmi->ctrl == KM_ANY &&
757                 kmi->alt == KM_ANY &&
758                 kmi->oskey == KM_ANY) {
759
760                 strcat(buf, "Any ");
761         } else {
762                 if(kmi->shift)
763                         strcat(buf, "Shift ");
764
765                 if(kmi->ctrl)
766                         strcat(buf, "Ctrl ");
767
768                 if(kmi->alt)
769                         strcat(buf, "Alt ");
770
771                 if(kmi->oskey)
772                         strcat(buf, "Cmd ");
773         }
774                 
775         if(kmi->keymodifier) {
776                 strcat(buf, WM_key_event_string(kmi->keymodifier));
777                 strcat(buf, " ");
778         }
779
780         strcat(buf, WM_key_event_string(kmi->type));
781         BLI_strncpy(str, buf, len);
782
783         return str;
784 }
785
786 static wmKeyMapItem *wm_keymap_item_find_handlers(const bContext *C, ListBase *handlers, const char *opname, int UNUSED(opcontext), IDProperty *properties, int compare_props, int hotkey, wmKeyMap **keymap_r)
787 {
788         wmWindowManager *wm= CTX_wm_manager(C);
789         wmEventHandler *handler;
790         wmKeyMap *keymap;
791         wmKeyMapItem *kmi;
792
793         /* find keymap item in handlers */
794         for(handler=handlers->first; handler; handler=handler->next) {
795                 keymap= WM_keymap_active(wm, handler->keymap);
796
797                 if(keymap && (!keymap->poll || keymap->poll((bContext*)C))) {
798                         for(kmi=keymap->items.first; kmi; kmi=kmi->next) {
799                                 
800                                 if(strcmp(kmi->idname, opname) == 0 && WM_key_event_string(kmi->type)[0]) {
801                                         if (hotkey)
802                                                 if (!ISHOTKEY(kmi->type))
803                                                         continue;
804                                         
805                                         if(compare_props) {
806                                                 if(kmi->ptr && IDP_EqualsProperties(properties, kmi->ptr->data)) {
807                                                         if(keymap_r) *keymap_r= keymap;
808                                                         return kmi;
809                                                 }
810                                         }
811                                         else {
812                                                 if(keymap_r) *keymap_r= keymap;
813                                                 return kmi;
814                                         }
815                                 }
816                         }
817                 }
818         }
819         
820         /* ensure un-initialized keymap is never used */
821         if(keymap_r) *keymap_r= NULL;
822         return NULL;
823 }
824
825 static wmKeyMapItem *wm_keymap_item_find_props(const bContext *C, const char *opname, int opcontext, IDProperty *properties, int compare_props, int hotkey, wmKeyMap **keymap_r)
826 {
827         wmWindow *win= CTX_wm_window(C);
828         ScrArea *sa= CTX_wm_area(C);
829         ARegion *ar= CTX_wm_region(C);
830         wmKeyMapItem *found= NULL;
831
832         /* look into multiple handler lists to find the item */
833         if(win)
834                 found= wm_keymap_item_find_handlers(C, &win->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
835         
836
837         if(sa && found==NULL)
838                 found= wm_keymap_item_find_handlers(C, &sa->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
839
840         if(found==NULL) {
841                 if(ELEM(opcontext, WM_OP_EXEC_REGION_WIN, WM_OP_INVOKE_REGION_WIN)) {
842                         if(sa) {
843                                 if (!(ar && ar->regiontype == RGN_TYPE_WINDOW))
844                                         ar= BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
845                                 
846                                 if(ar)
847                                         found= wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
848                         }
849                 }
850                 else if(ELEM(opcontext, WM_OP_EXEC_REGION_CHANNELS, WM_OP_INVOKE_REGION_CHANNELS)) {
851                         if (!(ar && ar->regiontype == RGN_TYPE_CHANNELS))
852                                 ar= BKE_area_find_region_type(sa, RGN_TYPE_CHANNELS);
853
854                         if(ar)
855                                 found= wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
856                 }
857                 else if(ELEM(opcontext, WM_OP_EXEC_REGION_PREVIEW, WM_OP_INVOKE_REGION_PREVIEW)) {
858                         if (!(ar && ar->regiontype == RGN_TYPE_PREVIEW))
859                                 ar= BKE_area_find_region_type(sa, RGN_TYPE_PREVIEW);
860
861                         if(ar)
862                                 found= wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
863                 }
864                 else {
865                         if(ar)
866                                 found= wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
867                 }
868         }
869         
870         return found;
871 }
872
873 static wmKeyMapItem *wm_keymap_item_find(const bContext *C, const char *opname, int opcontext, IDProperty *properties, int hotkey, wmKeyMap **keymap_r)
874 {
875         wmKeyMapItem *found= wm_keymap_item_find_props(C, opname, opcontext, properties, 1, hotkey, keymap_r);
876
877         if(!found)
878                 found= wm_keymap_item_find_props(C, opname, opcontext, NULL, 0, hotkey, keymap_r);
879
880         return found;
881 }
882
883 char *WM_key_event_operator_string(const bContext *C, const char *opname, int opcontext, IDProperty *properties, char *str, int len)
884 {
885         wmKeyMapItem *kmi= wm_keymap_item_find(C, opname, opcontext, properties, 0, NULL);
886         
887         if(kmi) {
888                 WM_keymap_item_to_string(kmi, str, len);
889                 return str;
890         }
891
892         return NULL;
893 }
894
895 int WM_key_event_operator_id(const bContext *C, const char *opname, int opcontext, IDProperty *properties, int hotkey, wmKeyMap **keymap_r)
896 {
897         wmKeyMapItem *kmi= wm_keymap_item_find(C, opname, opcontext, properties, hotkey, keymap_r);
898         
899         if(kmi)
900                 return kmi->id;
901         else
902                 return 0;
903 }
904
905 int     WM_keymap_item_compare(wmKeyMapItem *k1, wmKeyMapItem *k2)
906 {
907         int k1type, k2type;
908
909         if (k1->flag & KMI_INACTIVE || k2->flag & KMI_INACTIVE)
910                 return 0;
911
912         /* take event mapping into account */
913         k1type = WM_userdef_event_map(k1->type);
914         k2type = WM_userdef_event_map(k2->type);
915
916         if(k1type != KM_ANY && k2type != KM_ANY && k1type != k2type)
917                 return 0;
918
919         if(k1->val != KM_ANY && k2->val != KM_ANY) {
920                 /* take click, press, release conflict into account */
921                 if (k1->val == KM_CLICK && ELEM3(k2->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0)
922                         return 0;
923                 if (k2->val == KM_CLICK && ELEM3(k1->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0)
924                         return 0;
925                 if (k1->val != k2->val)
926                         return 0;
927         }
928
929         if(k1->shift != KM_ANY && k2->shift != KM_ANY && k1->shift != k2->shift)
930                 return 0;
931
932         if(k1->ctrl != KM_ANY && k2->ctrl != KM_ANY && k1->ctrl != k2->ctrl)
933                 return 0;
934
935         if(k1->alt != KM_ANY && k2->alt != KM_ANY && k1->alt != k2->alt)
936                 return 0;
937
938         if(k1->oskey != KM_ANY && k2->oskey != KM_ANY && k1->oskey != k2->oskey)
939                 return 0;
940
941         if(k1->keymodifier != k2->keymodifier)
942                 return 0;
943
944         return 1;
945 }
946
947 /************************* Update Final Configuration *************************
948  * On load or other changes, the final user key configuration is rebuilt from
949  * the preset, addon and user preferences keymaps. We also test if the final
950  * configuration changed and write the changes to the user preferences. */
951
952 static int WM_KEYMAP_UPDATE = 0;
953
954 void WM_keyconfig_update_tag(wmKeyMap *km, wmKeyMapItem *kmi)
955 {
956         /* quick tag to do delayed keymap updates */
957         WM_KEYMAP_UPDATE= 1;
958
959         if(km)
960                 km->flag |= KEYMAP_UPDATE;
961         if(kmi)
962                 kmi->flag |= KMI_UPDATE;
963 }
964
965 static int wm_keymap_test_and_clear_update(wmKeyMap *km)
966 {
967         wmKeyMapItem *kmi;
968         int update;
969         
970         update= (km->flag & KEYMAP_UPDATE);
971         km->flag &= ~KEYMAP_UPDATE;
972
973         for(kmi=km->items.first; kmi; kmi=kmi->next) {
974                 update= update || (kmi->flag & KMI_UPDATE);
975                 kmi->flag &= ~KMI_UPDATE;
976         }
977         
978         return update;
979 }
980
981 static wmKeyMap *wm_keymap_preset(wmWindowManager *wm, wmKeyMap *km)
982 {
983         wmKeyConfig *keyconf= WM_keyconfig_active(wm);
984         wmKeyMap *keymap;
985
986         keymap= WM_keymap_list_find(&keyconf->keymaps, km->idname, km->spaceid, km->regionid);
987         if(!keymap)
988                 keymap= WM_keymap_list_find(&wm->defaultconf->keymaps, km->idname, km->spaceid, km->regionid);
989
990         return keymap;
991 }
992
993 void WM_keyconfig_update(wmWindowManager *wm)
994 {
995         wmKeyMap *km, *defaultmap, *addonmap, *usermap, *kmn;
996         wmKeyMapItem *kmi;
997         wmKeyMapDiffItem *kmdi;
998         int compat_update = 0;
999
1000         if(!WM_KEYMAP_UPDATE)
1001                 return;
1002         
1003         /* update operator properties for non-modal user keymaps */
1004         for(km=U.user_keymaps.first; km; km=km->next) {
1005                 if((km->flag & KEYMAP_MODAL) == 0) {
1006                         for(kmdi=km->diff_items.first; kmdi; kmdi=kmdi->next) {
1007                                 if(kmdi->add_item)
1008                                         wm_keymap_item_properties_set(kmdi->add_item);
1009                                 if(kmdi->remove_item)
1010                                         wm_keymap_item_properties_set(kmdi->remove_item);
1011                         }
1012
1013                         for(kmi=km->items.first; kmi; kmi=kmi->next)
1014                                 wm_keymap_item_properties_set(kmi);
1015                 }
1016         }
1017
1018         /* update U.user_keymaps with user key configuration changes */
1019         for(km=wm->userconf->keymaps.first; km; km=km->next) {
1020                 /* only diff if the user keymap was modified */
1021                 if(wm_keymap_test_and_clear_update(km)) {
1022                         /* find keymaps */
1023                         defaultmap= wm_keymap_preset(wm, km);
1024                         addonmap= WM_keymap_list_find(&wm->addonconf->keymaps, km->idname, km->spaceid, km->regionid);
1025
1026                         /* diff */
1027                         if(defaultmap)
1028                                 wm_keymap_diff_update(&U.user_keymaps, defaultmap, addonmap, km);
1029                 }
1030         }
1031
1032         /* create user key configuration from preset + addon + user preferences */
1033         for(km=wm->defaultconf->keymaps.first; km; km=km->next) {
1034                 /* find keymaps */
1035                 defaultmap= wm_keymap_preset(wm, km);
1036                 addonmap= WM_keymap_list_find(&wm->addonconf->keymaps, km->idname, km->spaceid, km->regionid);
1037                 usermap= WM_keymap_list_find(&U.user_keymaps, km->idname, km->spaceid, km->regionid);
1038
1039                 /* add */
1040                 kmn= wm_keymap_patch_update(&wm->userconf->keymaps, defaultmap, addonmap, usermap);
1041
1042                 if(kmn) {
1043                         kmn->modal_items= km->modal_items;
1044                         kmn->poll= km->poll;
1045                 }
1046
1047                 /* in case of old non-diff keymaps, force extra update to create diffs */
1048                 compat_update = compat_update || (usermap && !(usermap->flag & KEYMAP_DIFF));
1049         }
1050
1051         WM_KEYMAP_UPDATE= 0;
1052
1053         if(compat_update) {
1054                 WM_keyconfig_update_tag(NULL, NULL);
1055                 WM_keyconfig_update(wm);
1056         }
1057 }
1058
1059 /********************************* Event Handling *****************************
1060  * Handlers have pointers to the keymap in the default configuration. During
1061  * event handling this function is called to get the keymap from the final
1062  * configuration. */
1063
1064 wmKeyMap *WM_keymap_active(wmWindowManager *wm, wmKeyMap *keymap)
1065 {
1066         wmKeyMap *km;
1067
1068         if(!keymap)
1069                 return NULL;
1070         
1071         /* first user defined keymaps */
1072         km= WM_keymap_list_find(&wm->userconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
1073
1074         if(km)
1075                 return km;
1076
1077         return keymap;
1078 }
1079
1080 /******************************* Keymap Editor ********************************
1081  * In the keymap editor the user key configuration is edited. */
1082
1083 void WM_keymap_restore_item_to_default(bContext *C, wmKeyMap *keymap, wmKeyMapItem *kmi)
1084 {
1085         wmWindowManager *wm = CTX_wm_manager(C);
1086         wmKeyMap *defaultmap, *addonmap;
1087         wmKeyMapItem *orig;
1088
1089         if(!keymap)
1090                 return;
1091
1092         /* construct default keymap from preset + addons */
1093         defaultmap= wm_keymap_preset(wm, keymap);
1094         addonmap= WM_keymap_list_find(&wm->addonconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
1095
1096         if(addonmap) {
1097                 defaultmap = wm_keymap_copy(defaultmap);
1098                 wm_keymap_addon_add(defaultmap, addonmap);
1099         }
1100
1101         /* find original item */
1102         orig = WM_keymap_item_find_id(defaultmap, kmi->id);
1103
1104         if(orig) {
1105                 /* restore to original */
1106                 if(strcmp(orig->idname, kmi->idname) != 0) {
1107                         BLI_strncpy(kmi->idname, orig->idname, sizeof(kmi->idname));
1108                         WM_keymap_properties_reset(kmi, NULL);
1109                 }
1110
1111                 if (orig->properties) {
1112                         if(kmi->properties) {
1113                                 IDP_FreeProperty(kmi->properties);
1114                                 MEM_freeN(kmi->properties);
1115                                 kmi->properties= NULL;
1116                         }
1117
1118                         kmi->properties= IDP_CopyProperty(orig->properties);
1119                         kmi->ptr->data= kmi->properties;
1120                 }
1121
1122                 kmi->propvalue = orig->propvalue;
1123                 kmi->type = orig->type;
1124                 kmi->val = orig->val;
1125                 kmi->shift = orig->shift;
1126                 kmi->ctrl = orig->ctrl;
1127                 kmi->alt = orig->alt;
1128                 kmi->oskey = orig->oskey;
1129                 kmi->keymodifier = orig->keymodifier;
1130                 kmi->maptype = orig->maptype;
1131
1132                 WM_keyconfig_update_tag(keymap, kmi);
1133         }
1134
1135         /* free temporary keymap */
1136         if(addonmap) {
1137                 WM_keymap_free(defaultmap);
1138                 MEM_freeN(defaultmap);
1139         }
1140 }
1141
1142 void WM_keymap_restore_to_default(wmKeyMap *keymap, bContext *C)
1143 {
1144         wmWindowManager *wm = CTX_wm_manager(C);
1145         wmKeyMap *usermap;
1146
1147         /* remove keymap from U.user_keymaps and update */
1148         usermap= WM_keymap_list_find(&U.user_keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
1149
1150         if(usermap) {
1151                 WM_keymap_free(usermap);
1152                 BLI_freelinkN(&U.user_keymaps, usermap);
1153
1154                 WM_keyconfig_update_tag(NULL, NULL);
1155                 WM_keyconfig_update(wm);
1156         }
1157 }
1158
1159 wmKeyMapItem *WM_keymap_item_find_id(wmKeyMap *keymap, int id)
1160 {
1161         wmKeyMapItem *kmi;
1162         
1163         for (kmi=keymap->items.first; kmi; kmi=kmi->next) {
1164                 if (kmi->id == id) {
1165                         return kmi;
1166                 }
1167         }
1168         
1169         return NULL;
1170 }
1171
1172 /* Guess an appropriate keymap from the operator name */
1173 /* Needs to be kept up to date with Keymap and Operator naming */
1174 wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
1175 {
1176         wmKeyMap *km=NULL;
1177         SpaceLink *sl = CTX_wm_space_data(C);
1178         
1179         /* Window */
1180         if (strstr(opname, "WM_OT")) {
1181                 km = WM_keymap_find_all(C, "Window", 0, 0);
1182         }
1183         /* Screen */
1184         else if (strstr(opname, "SCREEN_OT")) {
1185                 km = WM_keymap_find_all(C, "Screen", 0, 0);
1186         }
1187         /* Grease Pencil */
1188         else if (strstr(opname, "GPENCIL_OT")) {
1189                 km = WM_keymap_find_all(C, "Grease Pencil", 0, 0);
1190         }
1191         /* Markers */
1192         else if (strstr(opname, "MARKER_OT")) {
1193                 km = WM_keymap_find_all(C, "Markers", 0, 0);
1194         }
1195         
1196         
1197         /* 3D View */
1198         else if (strstr(opname, "VIEW3D_OT")) {
1199                 km = WM_keymap_find_all(C, "3D View", sl->spacetype, 0);
1200         }
1201         else if (strstr(opname, "OBJECT_OT")) {
1202                 km = WM_keymap_find_all(C, "Object Mode", 0, 0);
1203         }
1204
1205         
1206         /* Editing Modes */
1207         else if (strstr(opname, "MESH_OT")) {
1208                 km = WM_keymap_find_all(C, "Mesh", 0, 0);
1209                 
1210                 /* some mesh operators are active in object mode too, like add-prim */
1211                 if(km && km->poll && km->poll((bContext *)C)==0) {
1212                         km = WM_keymap_find_all(C, "Object Mode", 0, 0);
1213                 }
1214         }
1215         else if (strstr(opname, "CURVE_OT")) {
1216                 km = WM_keymap_find_all(C, "Curve", 0, 0);
1217                 
1218                 /* some curve operators are active in object mode too, like add-prim */
1219                 if(km && km->poll && km->poll((bContext *)C)==0) {
1220                         km = WM_keymap_find_all(C, "Object Mode", 0, 0);
1221                 }
1222         }
1223         else if (strstr(opname, "ARMATURE_OT")) {
1224                 km = WM_keymap_find_all(C, "Armature", 0, 0);
1225         }
1226         else if (strstr(opname, "POSE_OT")) {
1227                 km = WM_keymap_find_all(C, "Pose", 0, 0);
1228         }
1229         else if (strstr(opname, "SCULPT_OT")) {
1230                 km = WM_keymap_find_all(C, "Sculpt", 0, 0);
1231         }
1232         else if (strstr(opname, "MBALL_OT")) {
1233                 km = WM_keymap_find_all(C, "Metaball", 0, 0);
1234                 
1235                 /* some mball operators are active in object mode too, like add-prim */
1236                 if(km && km->poll && km->poll((bContext *)C)==0) {
1237                         km = WM_keymap_find_all(C, "Object Mode", 0, 0);
1238                 }
1239         }
1240         else if (strstr(opname, "LATTICE_OT")) {
1241                 km = WM_keymap_find_all(C, "Lattice", 0, 0);
1242         }
1243         else if (strstr(opname, "PARTICLE_OT")) {
1244                 km = WM_keymap_find_all(C, "Particle", 0, 0);
1245         }
1246         else if (strstr(opname, "FONT_OT")) {
1247                 km = WM_keymap_find_all(C, "Font", 0, 0);
1248         }
1249         else if (strstr(opname, "PAINT_OT")) {
1250                 
1251                 /* check for relevant mode */
1252                 switch(CTX_data_mode_enum(C)) {
1253                         case OB_MODE_WEIGHT_PAINT:
1254                                 km = WM_keymap_find_all(C, "Weight Paint", 0, 0);
1255                                 break;
1256                         case OB_MODE_VERTEX_PAINT:
1257                                 km = WM_keymap_find_all(C, "Vertex Paint", 0, 0);
1258                                 break;
1259                         case OB_MODE_TEXTURE_PAINT:
1260                                 km = WM_keymap_find_all(C, "Image Paint", 0, 0);
1261                                 break;
1262                 }
1263         }
1264         /* Paint Face Mask */
1265         else if (strstr(opname, "PAINT_OT_face_select")) {
1266                 km = WM_keymap_find_all(C, "Face Mask", sl->spacetype, 0);
1267         }
1268         /* Timeline */
1269         else if (strstr(opname, "TIME_OT")) {
1270                 km = WM_keymap_find_all(C, "Timeline", sl->spacetype, 0);
1271         }
1272         /* Image Editor */
1273         else if (strstr(opname, "IMAGE_OT")) {
1274                 km = WM_keymap_find_all(C, "Image", sl->spacetype, 0);
1275         }
1276         /* UV Editor */
1277         else if (strstr(opname, "UV_OT")) {
1278                 km = WM_keymap_find_all(C, "UV Editor", sl->spacetype, 0);
1279         }
1280         /* Node Editor */
1281         else if (strstr(opname, "NODE_OT")) {
1282                 km = WM_keymap_find_all(C, "Node Editor", sl->spacetype, 0);
1283         }
1284         /* Animation Editor Channels */
1285         else if (strstr(opname, "ANIM_OT_channels")) {
1286                 km = WM_keymap_find_all(C, "Animation Channels", sl->spacetype, 0);
1287         }
1288         /* Animation Generic - after channels */
1289         else if (strstr(opname, "ANIM_OT")) {
1290                 km = WM_keymap_find_all(C, "Animation", 0, 0);
1291         }
1292         /* Graph Editor */
1293         else if (strstr(opname, "GRAPH_OT")) {
1294                 km = WM_keymap_find_all(C, "Graph Editor", sl->spacetype, 0);
1295         }
1296         /* Dopesheet Editor */
1297         else if (strstr(opname, "ACTION_OT")) {
1298                 km = WM_keymap_find_all(C, "Dopesheet", sl->spacetype, 0);
1299         }
1300         /* NLA Editor */
1301         else if (strstr(opname, "NLA_OT")) {
1302                 km = WM_keymap_find_all(C, "NLA Editor", sl->spacetype, 0);
1303         }
1304         /* Script */
1305         else if (strstr(opname, "SCRIPT_OT")) {
1306                 km = WM_keymap_find_all(C, "Script", sl->spacetype, 0);
1307         }
1308         /* Text */
1309         else if (strstr(opname, "TEXT_OT")) {
1310                 km = WM_keymap_find_all(C, "Text", sl->spacetype, 0);
1311         }
1312         /* Sequencer */
1313         else if (strstr(opname, "SEQUENCER_OT")) {
1314                 km = WM_keymap_find_all(C, "Sequencer", sl->spacetype, 0);
1315         }
1316         /* Console */
1317         else if (strstr(opname, "CONSOLE_OT")) {
1318                 km = WM_keymap_find_all(C, "Console", sl->spacetype, 0);
1319         }
1320         /* Console */
1321         else if (strstr(opname, "INFO_OT")) {
1322                 km = WM_keymap_find_all(C, "Info", sl->spacetype, 0);
1323         }
1324         
1325         /* Transform */
1326         else if (strstr(opname, "TRANSFORM_OT")) {
1327                 
1328                 /* check for relevant editor */
1329                 switch(sl->spacetype) {
1330                         case SPACE_VIEW3D:
1331                                 km = WM_keymap_find_all(C, "3D View", sl->spacetype, 0);
1332                                 break;
1333                         case SPACE_IPO:
1334                                 km = WM_keymap_find_all(C, "Graph Editor", sl->spacetype, 0);
1335                                 break;
1336                         case SPACE_ACTION:
1337                                 km = WM_keymap_find_all(C, "Dopesheet", sl->spacetype, 0);
1338                                 break;
1339                         case SPACE_NLA:
1340                                 km = WM_keymap_find_all(C, "NLA Editor", sl->spacetype, 0);
1341                                 break;
1342                         case SPACE_IMAGE:
1343                                 km = WM_keymap_find_all(C, "UV Editor", sl->spacetype, 0);
1344                                 break;
1345                         case SPACE_NODE:
1346                                 km = WM_keymap_find_all(C, "Node Editor", sl->spacetype, 0);
1347                                 break;
1348                         case SPACE_SEQ:
1349                                 km = WM_keymap_find_all(C, "Sequencer", sl->spacetype, 0);
1350                                 break;
1351                 }
1352         }
1353         
1354         return km;
1355 }
1356