57b84fc18f4deebce3adeb7e1f0da2cee40dc80c
[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_library.h"
51 #include "BKE_main.h"
52 #include "BKE_screen.h"
53
54
55 #include "RNA_access.h"
56 #include "RNA_enum_types.h"
57
58 #include "WM_api.h"
59 #include "WM_types.h"
60 #include "wm_window.h"
61 #include "wm_event_system.h"
62 #include "wm_event_types.h"
63
64 /* ********************* key config ***********************/
65
66 static void keymap_properties_set(wmKeyMapItem *kmi)
67 {
68         WM_operator_properties_alloc(&(kmi->ptr), &(kmi->properties), kmi->idname);
69         WM_operator_properties_sanitize(kmi->ptr, 1);
70 }
71
72 /* properties can be NULL, otherwise the arg passed is used and ownership is given to the kmi */
73 void WM_keymap_properties_reset(wmKeyMapItem *kmi, struct IDProperty *properties)
74 {
75         WM_operator_properties_free(kmi->ptr);
76         MEM_freeN(kmi->ptr);
77
78         kmi->ptr = NULL;
79         kmi->properties = properties;
80
81         keymap_properties_set(kmi);
82 }
83
84 wmKeyConfig *WM_keyconfig_new(wmWindowManager *wm, const char *idname)
85 {
86         wmKeyConfig *keyconf;
87         
88         keyconf= MEM_callocN(sizeof(wmKeyConfig), "wmKeyConfig");
89         BLI_strncpy(keyconf->idname, idname, sizeof(keyconf->idname));
90         BLI_addtail(&wm->keyconfigs, keyconf);
91
92         return keyconf;
93 }
94
95 wmKeyConfig *WM_keyconfig_new_user(wmWindowManager *wm, const char *idname)
96 {
97         wmKeyConfig *keyconf = WM_keyconfig_new(wm, idname);
98
99         keyconf->flag |= KEYCONF_USER;
100
101         return keyconf;
102 }
103
104 void WM_keyconfig_remove(wmWindowManager *wm, wmKeyConfig *keyconf)
105 {
106         if (keyconf) {
107                 if (BLI_streq(U.keyconfigstr, keyconf->idname)) {
108                         BLI_strncpy(U.keyconfigstr, wm->defaultconf->idname, sizeof(U.keyconfigstr));
109                 }
110
111                 BLI_remlink(&wm->keyconfigs, keyconf);
112                 WM_keyconfig_free(keyconf);
113         }
114 }
115
116 void WM_keyconfig_free(wmKeyConfig *keyconf)
117 {
118         wmKeyMap *km;
119
120         while((km= keyconf->keymaps.first)) {
121                 WM_keymap_free(km);
122                 BLI_freelinkN(&keyconf->keymaps, km);
123         }
124
125         MEM_freeN(keyconf);
126 }
127
128 void WM_keyconfig_userdef(void)
129 {
130         wmKeyMap *km;
131         wmKeyMapItem *kmi;
132
133         for(km=U.keymaps.first; km; km=km->next) {
134                 /* modal keymaps don't have operator properties */
135                 if ((km->flag & KEYMAP_MODAL) == 0) {
136                         for(kmi=km->items.first; kmi; kmi=kmi->next) {
137                                 keymap_properties_set(kmi);
138                         }
139                 }
140         }
141 }
142
143 static wmKeyConfig *wm_keyconfig_list_find(ListBase *lb, char *idname)
144 {
145         wmKeyConfig *kc;
146
147         for(kc= lb->first; kc; kc= kc->next)
148                 if(0==strncmp(idname, kc->idname, KMAP_MAX_NAME))
149                         return kc;
150         
151         return NULL;
152 }
153
154 /* ************************ free ************************* */
155
156 void WM_keymap_free(wmKeyMap *keymap)
157 {
158         wmKeyMapItem *kmi;
159
160         for(kmi=keymap->items.first; kmi; kmi=kmi->next) {
161                 if(kmi->ptr) {
162                         WM_operator_properties_free(kmi->ptr);
163                         MEM_freeN(kmi->ptr);
164                 }
165         }
166
167         BLI_freelistN(&keymap->items);
168 }
169
170 /* ***************** generic call, exported **************** */
171
172 static void keymap_event_set(wmKeyMapItem *kmi, short type, short val, int modifier, short keymodifier)
173 {
174         kmi->type= type;
175         kmi->val= val;
176         kmi->keymodifier= keymodifier;
177         
178         if(modifier == KM_ANY) {
179                 kmi->shift= kmi->ctrl= kmi->alt= kmi->oskey= KM_ANY;
180         }
181         else {
182                 
183                 kmi->shift= kmi->ctrl= kmi->alt= kmi->oskey= 0;
184                 
185                 /* defines? */
186                 if(modifier & KM_SHIFT)
187                         kmi->shift= 1;
188                 else if(modifier & KM_SHIFT2)
189                         kmi->shift= 2;
190                 if(modifier & KM_CTRL)
191                         kmi->ctrl= 1;
192                 else if(modifier & KM_CTRL2)
193                         kmi->ctrl= 2;
194                 if(modifier & KM_ALT)
195                         kmi->alt= 1;
196                 else if(modifier & KM_ALT2)
197                         kmi->alt= 2;
198                 if(modifier & KM_OSKEY)
199                         kmi->oskey= 1;
200                 else if(modifier & KM_OSKEY2)
201                         kmi->oskey= 2;  
202         }
203 }
204
205 static void keymap_item_set_id(wmKeyMap *keymap, wmKeyMapItem *kmi)
206 {
207         keymap->kmi_id++;
208         if ((keymap->flag & KEYMAP_USER) == 0) {
209                 kmi->id = keymap->kmi_id;
210         } else {
211                 kmi->id = -keymap->kmi_id; // User defined keymap entries have negative ids
212         }
213 }
214
215 /* if item was added, then bail out */
216 wmKeyMapItem *WM_keymap_verify_item(wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier)
217 {
218         wmKeyMapItem *kmi;
219         
220         for(kmi= keymap->items.first; kmi; kmi= kmi->next)
221                 if(strncmp(kmi->idname, idname, OP_MAX_TYPENAME)==0)
222                         break;
223         if(kmi==NULL) {
224                 kmi= MEM_callocN(sizeof(wmKeyMapItem), "keymap entry");
225                 
226                 BLI_addtail(&keymap->items, kmi);
227                 BLI_strncpy(kmi->idname, idname, OP_MAX_TYPENAME);
228                 
229                 keymap_item_set_id(keymap, kmi);
230
231                 keymap_event_set(kmi, type, val, modifier, keymodifier);
232                 keymap_properties_set(kmi);
233         }
234         return kmi;
235 }
236
237 /* always add item */
238 wmKeyMapItem *WM_keymap_add_item(wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier)
239 {
240         wmKeyMapItem *kmi= MEM_callocN(sizeof(wmKeyMapItem), "keymap entry");
241         
242         BLI_addtail(&keymap->items, kmi);
243         BLI_strncpy(kmi->idname, idname, OP_MAX_TYPENAME);
244
245         keymap_event_set(kmi, type, val, modifier, keymodifier);
246         keymap_properties_set(kmi);
247
248         keymap_item_set_id(keymap, kmi);
249
250         return kmi;
251 }
252
253 /* menu wrapper for WM_keymap_add_item */
254 wmKeyMapItem *WM_keymap_add_menu(wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier)
255 {
256         wmKeyMapItem *kmi= WM_keymap_add_item(keymap, "WM_OT_call_menu", type, val, modifier, keymodifier);
257         RNA_string_set(kmi->ptr, "name", idname);
258         return kmi;
259 }
260
261 void WM_keymap_remove_item(wmKeyMap *keymap, wmKeyMapItem *kmi)
262 {
263         if(BLI_findindex(&keymap->items, kmi) != -1) {
264                 if(kmi->ptr) {
265                         WM_operator_properties_free(kmi->ptr);
266                         MEM_freeN(kmi->ptr);
267                 }
268                 BLI_freelinkN(&keymap->items, kmi);
269         }
270 }
271
272 /* ****************** storage in WM ************ */
273
274 /* name id's are for storing general or multiple keymaps, 
275    space/region ids are same as DNA_space_types.h */
276 /* gets free'd in wm.c */
277
278 wmKeyMap *WM_keymap_list_find(ListBase *lb, const char *idname, int spaceid, int regionid)
279 {
280         wmKeyMap *km;
281
282         for(km= lb->first; km; km= km->next)
283                 if(km->spaceid==spaceid && km->regionid==regionid)
284                         if(0==strncmp(idname, km->idname, KMAP_MAX_NAME))
285                                 return km;
286         
287         return NULL;
288 }
289
290 wmKeyMap *WM_keymap_find(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid)
291 {
292         wmKeyMap *km= WM_keymap_list_find(&keyconf->keymaps, idname, spaceid, regionid);
293         
294         if(km==NULL) {
295                 km= MEM_callocN(sizeof(struct wmKeyMap), "keymap list");
296                 BLI_strncpy(km->idname, idname, KMAP_MAX_NAME);
297                 km->spaceid= spaceid;
298                 km->regionid= regionid;
299                 BLI_addtail(&keyconf->keymaps, km);
300         }
301         
302         return km;
303 }
304
305 wmKeyMap *WM_keymap_find_all(const bContext *C, const char *idname, int spaceid, int regionid)
306 {
307         wmWindowManager *wm = CTX_wm_manager(C);
308         wmKeyConfig *keyconf;
309         wmKeyMap *km;
310         
311         /* first user defined keymaps */
312         km= WM_keymap_list_find(&U.keymaps, idname, spaceid, regionid);
313         if (km)
314                 return km;
315         
316         /* then user key config */
317         keyconf= wm_keyconfig_list_find(&wm->keyconfigs, U.keyconfigstr);
318         if(keyconf) {
319                 km= WM_keymap_list_find(&keyconf->keymaps, idname, spaceid, regionid);
320                 if (km)
321                         return km;
322         }
323         
324         /* then use default */
325         km= WM_keymap_list_find(&wm->defaultconf->keymaps, idname, spaceid, regionid);
326         if (km)
327                 return km;
328         else
329                 return NULL;
330 }
331
332 /* ****************** modal keymaps ************ */
333
334 /* modal maps get linked to a running operator, and filter the keys before sending to modal() callback */
335
336 wmKeyMap *WM_modalkeymap_add(wmKeyConfig *keyconf, const char *idname, EnumPropertyItem *items)
337 {
338         wmKeyMap *km= WM_keymap_find(keyconf, idname, 0, 0);
339         km->flag |= KEYMAP_MODAL;
340         km->modal_items= items;
341         
342         return km;
343 }
344
345 wmKeyMap *WM_modalkeymap_get(wmKeyConfig *keyconf, const char *idname)
346 {
347         wmKeyMap *km;
348         
349         for(km= keyconf->keymaps.first; km; km= km->next)
350                 if(km->flag & KEYMAP_MODAL)
351                         if(0==strncmp(idname, km->idname, KMAP_MAX_NAME))
352                                 break;
353         
354         return km;
355 }
356
357
358 wmKeyMapItem *WM_modalkeymap_add_item(wmKeyMap *km, int type, int val, int modifier, int keymodifier, int value)
359 {
360         wmKeyMapItem *kmi= MEM_callocN(sizeof(wmKeyMapItem), "keymap entry");
361         
362         BLI_addtail(&km->items, kmi);
363         kmi->propvalue= value;
364         
365         keymap_event_set(kmi, type, val, modifier, keymodifier);
366
367         keymap_item_set_id(km, kmi);
368
369         return kmi;
370 }
371
372 void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
373 {
374         wmOperatorType *ot= WM_operatortype_find(opname, 0);
375         
376         if(ot)
377                 ot->modalkeymap= km;
378         else
379                 printf("error: modalkeymap_assign, unknown operator %s\n", opname);
380 }
381
382 /* ***************** get string from key events **************** */
383
384 const char *WM_key_event_string(short type)
385 {
386         const char *name= NULL;
387         if(RNA_enum_name(event_type_items, (int)type, &name))
388                 return name;
389         
390         return "";
391 }
392
393 char *WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, int len)
394 {
395         char buf[128];
396
397         buf[0]= 0;
398
399         if (kmi->shift == KM_ANY &&
400                 kmi->ctrl == KM_ANY &&
401                 kmi->alt == KM_ANY &&
402                 kmi->oskey == KM_ANY) {
403
404                 strcat(buf, "Any ");
405         } else {
406                 if(kmi->shift)
407                         strcat(buf, "Shift ");
408
409                 if(kmi->ctrl)
410                         strcat(buf, "Ctrl ");
411
412                 if(kmi->alt)
413                         strcat(buf, "Alt ");
414
415                 if(kmi->oskey)
416                         strcat(buf, "Cmd ");
417         }
418                 
419         if(kmi->keymodifier) {
420                 strcat(buf, WM_key_event_string(kmi->keymodifier));
421                 strcat(buf, " ");
422         }
423
424         strcat(buf, WM_key_event_string(kmi->type));
425         BLI_strncpy(str, buf, len);
426
427         return str;
428 }
429
430 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)
431 {
432         wmWindowManager *wm= CTX_wm_manager(C);
433         wmEventHandler *handler;
434         wmKeyMap *keymap;
435         wmKeyMapItem *kmi;
436
437         /* find keymap item in handlers */
438         for(handler=handlers->first; handler; handler=handler->next) {
439                 keymap= WM_keymap_active(wm, handler->keymap);
440
441                 if(keymap && (!keymap->poll || keymap->poll((bContext*)C))) {
442                         for(kmi=keymap->items.first; kmi; kmi=kmi->next) {
443                                 
444                                 if(strcmp(kmi->idname, opname) == 0 && WM_key_event_string(kmi->type)[0]) {
445                                         if (hotkey)
446                                                 if (!ISHOTKEY(kmi->type))
447                                                         continue;
448                                         
449                                         if(compare_props) {
450                                                 if(kmi->ptr && IDP_EqualsProperties(properties, kmi->ptr->data)) {
451                                                         if(keymap_r) *keymap_r= keymap;
452                                                         return kmi;
453                                                 }
454                                         }
455                                         else {
456                                                 if(keymap_r) *keymap_r= keymap;
457                                                 return kmi;
458                                         }
459                                 }
460                         }
461                 }
462         }
463         
464         /* ensure un-initialized keymap is never used */
465         if(keymap_r) *keymap_r= NULL;
466         return NULL;
467 }
468
469 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)
470 {
471         wmWindow *win= CTX_wm_window(C);
472         ScrArea *sa= CTX_wm_area(C);
473         ARegion *ar= CTX_wm_region(C);
474         wmKeyMapItem *found= NULL;
475
476         /* look into multiple handler lists to find the item */
477         if(win)
478                 found= wm_keymap_item_find_handlers(C, &win->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
479         
480
481         if(sa && found==NULL)
482                 found= wm_keymap_item_find_handlers(C, &sa->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
483
484         if(found==NULL) {
485                 if(ELEM(opcontext, WM_OP_EXEC_REGION_WIN, WM_OP_INVOKE_REGION_WIN)) {
486                         if(sa) {
487                                 if (!(ar && ar->regiontype == RGN_TYPE_WINDOW))
488                                         ar= BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
489                                 
490                                 if(ar)
491                                         found= wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
492                         }
493                 }
494                 else if(ELEM(opcontext, WM_OP_EXEC_REGION_CHANNELS, WM_OP_INVOKE_REGION_CHANNELS)) {
495                         if (!(ar && ar->regiontype == RGN_TYPE_CHANNELS))
496                                         ar= BKE_area_find_region_type(sa, RGN_TYPE_CHANNELS);
497                                 
498                                 if(ar)
499                                         found= wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
500                 }
501                 else if(ELEM(opcontext, WM_OP_EXEC_REGION_PREVIEW, WM_OP_INVOKE_REGION_PREVIEW)) {
502                         if (!(ar && ar->regiontype == RGN_TYPE_PREVIEW))
503                                         ar= BKE_area_find_region_type(sa, RGN_TYPE_PREVIEW);
504                                 
505                                 if(ar)
506                                         found= wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
507                 }
508                 else {
509                         if(ar)
510                                 found= wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
511                 }
512         }
513         
514         return found;
515 }
516
517 static wmKeyMapItem *wm_keymap_item_find(const bContext *C, const char *opname, int opcontext, IDProperty *properties, int hotkey, wmKeyMap **keymap_r)
518 {
519         wmKeyMapItem *found= wm_keymap_item_find_props(C, opname, opcontext, properties, 1, hotkey, keymap_r);
520
521         if(!found)
522                 found= wm_keymap_item_find_props(C, opname, opcontext, NULL, 0, hotkey, keymap_r);
523
524         return found;
525 }
526
527 char *WM_key_event_operator_string(const bContext *C, const char *opname, int opcontext, IDProperty *properties, char *str, int len)
528 {
529         wmKeyMapItem *kmi= wm_keymap_item_find(C, opname, opcontext, properties, 0, NULL);
530         
531         if(kmi) {
532                 WM_keymap_item_to_string(kmi, str, len);
533                 return str;
534         }
535
536         return NULL;
537 }
538
539 int WM_key_event_operator_id(const bContext *C, const char *opname, int opcontext, IDProperty *properties, int hotkey, wmKeyMap **keymap_r)
540 {
541         wmKeyMapItem *kmi= wm_keymap_item_find(C, opname, opcontext, properties, hotkey, keymap_r);
542         
543         if(kmi)
544                 return kmi->id;
545         else
546                 return 0;
547 }
548
549 int     WM_keymap_item_compare(wmKeyMapItem *k1, wmKeyMapItem *k2)
550 {
551         int k1type, k2type;
552
553         if (k1->flag & KMI_INACTIVE || k2->flag & KMI_INACTIVE)
554                 return 0;
555
556         /* take event mapping into account */
557         k1type = WM_userdef_event_map(k1->type);
558         k2type = WM_userdef_event_map(k2->type);
559
560         if(k1type != KM_ANY && k2type != KM_ANY && k1type != k2type)
561                 return 0;
562
563         if(k1->val != KM_ANY && k2->val != KM_ANY) {
564                 /* take click, press, release conflict into account */
565                 if (k1->val == KM_CLICK && ELEM3(k2->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0)
566                         return 0;
567                 if (k2->val == KM_CLICK && ELEM3(k1->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0)
568                         return 0;
569                 if (k1->val != k2->val)
570                         return 0;
571         }
572
573         if(k1->shift != KM_ANY && k2->shift != KM_ANY && k1->shift != k2->shift)
574                 return 0;
575
576         if(k1->ctrl != KM_ANY && k2->ctrl != KM_ANY && k1->ctrl != k2->ctrl)
577                 return 0;
578
579         if(k1->alt != KM_ANY && k2->alt != KM_ANY && k1->alt != k2->alt)
580                 return 0;
581
582         if(k1->oskey != KM_ANY && k2->oskey != KM_ANY && k1->oskey != k2->oskey)
583                 return 0;
584
585         if(k1->keymodifier != k2->keymodifier)
586                 return 0;
587
588         return 1;
589 }
590
591 /* ***************** user preferences ******************* */
592
593 int WM_keymap_user_init(wmWindowManager *wm, wmKeyMap *keymap)
594 {
595         wmKeyConfig *keyconf;
596         wmKeyMap *km;
597
598         if(!keymap)
599                 return 0;
600
601         /* init from user key config */
602         keyconf= wm_keyconfig_list_find(&wm->keyconfigs, U.keyconfigstr);
603         if(keyconf) {
604                 km= WM_keymap_list_find(&keyconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
605                 if(km) {
606                         keymap->poll= km->poll; /* lazy init */
607                         keymap->modal_items= km->modal_items;
608                         return 1;
609                 }
610         }
611
612         /* or from default */
613         km= WM_keymap_list_find(&wm->defaultconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
614         if(km) {
615                 keymap->poll= km->poll; /* lazy init */
616                 keymap->modal_items= km->modal_items;
617                 return 1;
618         }
619
620         return 0;
621 }
622
623 wmKeyMap *WM_keymap_active(wmWindowManager *wm, wmKeyMap *keymap)
624 {
625         wmKeyConfig *keyconf;
626         wmKeyMap *km;
627
628         if(!keymap)
629                 return NULL;
630         
631         /* first user defined keymaps */
632         km= WM_keymap_list_find(&U.keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
633         if(km) {
634                 km->poll= keymap->poll; /* lazy init */
635                 km->modal_items= keymap->modal_items;
636                 return km;
637         }
638         
639         /* then user key config */
640         keyconf= wm_keyconfig_list_find(&wm->keyconfigs, U.keyconfigstr);
641         if(keyconf) {
642                 km= WM_keymap_list_find(&keyconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
643                 if(km) {
644                         km->poll= keymap->poll; /* lazy init */
645                         km->modal_items= keymap->modal_items;
646                         return km;
647                 }
648         }
649
650         /* then use default */
651         km= WM_keymap_list_find(&wm->defaultconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
652         return km;
653 }
654
655 wmKeyMap *WM_keymap_copy_to_user(wmKeyMap *keymap)
656 {
657         wmKeyMap *usermap;
658         wmKeyMapItem *kmi;
659
660         usermap= WM_keymap_list_find(&U.keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
661
662         /* XXX this function is only used by RMB setting hotkeys, and it clears maps on 2nd try this way */
663         if(keymap==usermap)
664                 return keymap;
665         
666         if(!usermap) {
667                 /* not saved yet, duplicate existing */
668                 usermap= MEM_dupallocN(keymap);
669                 usermap->modal_items= NULL;
670                 usermap->poll= NULL;
671                 usermap->flag |= KEYMAP_USER;
672
673                 BLI_addtail(&U.keymaps, usermap);
674         }
675         else {
676                 /* already saved, free items for re-copy */
677                 WM_keymap_free(usermap);
678         }
679
680         BLI_duplicatelist(&usermap->items, &keymap->items);
681
682         for(kmi=usermap->items.first; kmi; kmi=kmi->next) {
683                 if(kmi->properties) {
684                         kmi->ptr= MEM_callocN(sizeof(PointerRNA), "UserKeyMapItemPtr");
685                         WM_operator_properties_create(kmi->ptr, kmi->idname);
686
687                         kmi->properties= IDP_CopyProperty(kmi->properties);
688                         kmi->ptr->data= kmi->properties;
689                 }
690         }
691
692         for(kmi=keymap->items.first; kmi; kmi=kmi->next)
693                 kmi->flag &= ~KMI_EXPANDED;
694
695         return usermap;
696 }
697
698 void WM_keymap_restore_item_to_default(bContext *C, wmKeyMap *keymap, wmKeyMapItem *kmi)
699 {
700         wmWindowManager *wm = CTX_wm_manager(C);
701         wmKeyConfig *keyconf;
702         wmKeyMap *km = NULL;
703
704         /* look in user key config */
705         keyconf= wm_keyconfig_list_find(&wm->keyconfigs, U.keyconfigstr);
706         if(keyconf) {
707                 km= WM_keymap_list_find(&keyconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
708         }
709
710         if (!km) {
711                 /* or from default */
712                 km= WM_keymap_list_find(&wm->defaultconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
713         }
714
715         if (km) {
716                 wmKeyMapItem *orig = WM_keymap_item_find_id(km, kmi->id);
717
718                 if (orig) {
719                         if(strcmp(orig->idname, kmi->idname) != 0) {
720                                 BLI_strncpy(kmi->idname, orig->idname, sizeof(kmi->idname));
721
722                                 WM_keymap_properties_reset(kmi, NULL);
723                         }
724                         
725                         if (orig->properties) {
726                                 kmi->properties= IDP_CopyProperty(orig->properties);
727                                 kmi->ptr->data= kmi->properties;
728                         }
729
730                         kmi->propvalue = orig->propvalue;
731                         kmi->type = orig->type;
732                         kmi->val = orig->val;
733                         kmi->shift = orig->shift;
734                         kmi->ctrl = orig->ctrl;
735                         kmi->alt = orig->alt;
736                         kmi->oskey = orig->oskey;
737                         kmi->keymodifier = orig->keymodifier;
738                         kmi->maptype = orig->maptype;
739
740                 }
741
742         }
743 }
744
745 void WM_keymap_restore_to_default(wmKeyMap *keymap)
746 {
747         wmKeyMap *usermap;
748
749         usermap= WM_keymap_list_find(&U.keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
750
751         if(usermap) {
752                 WM_keymap_free(usermap);
753                 BLI_freelinkN(&U.keymaps, usermap);
754         }
755 }
756
757 wmKeyMapItem *WM_keymap_item_find_id(wmKeyMap *keymap, int id)
758 {
759         wmKeyMapItem *kmi;
760         
761         for (kmi=keymap->items.first; kmi; kmi=kmi->next) {
762                 if (kmi->id == id) {
763                         return kmi;
764                 }
765         }
766         
767         return NULL;
768 }
769
770 /* Guess an appropriate keymap from the operator name */
771 /* Needs to be kept up to date with Keymap and Operator naming */
772 wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
773 {
774         wmKeyMap *km=NULL;
775         SpaceLink *sl = CTX_wm_space_data(C);
776         
777         /* Window */
778         if (strstr(opname, "WM_OT")) {
779                 km = WM_keymap_find_all(C, "Window", 0, 0);
780         }
781         /* Screen */
782         else if (strstr(opname, "SCREEN_OT")) {
783                 km = WM_keymap_find_all(C, "Screen", 0, 0);
784         }
785         /* Grease Pencil */
786         else if (strstr(opname, "GPENCIL_OT")) {
787                 km = WM_keymap_find_all(C, "Grease Pencil", 0, 0);
788         }
789         /* Markers */
790         else if (strstr(opname, "MARKER_OT")) {
791                 km = WM_keymap_find_all(C, "Markers", 0, 0);
792         }
793         
794         
795         /* 3D View */
796         else if (strstr(opname, "VIEW3D_OT")) {
797                 km = WM_keymap_find_all(C, "3D View", sl->spacetype, 0);
798         }
799         else if (strstr(opname, "OBJECT_OT")) {
800                 km = WM_keymap_find_all(C, "Object Mode", 0, 0);
801         }
802
803         
804         /* Editing Modes */
805         else if (strstr(opname, "MESH_OT")) {
806                 km = WM_keymap_find_all(C, "Mesh", 0, 0);
807                 
808                 /* some mesh operators are active in object mode too, like add-prim */
809                 if(km && km->poll && km->poll((bContext *)C)==0) {
810                         km = WM_keymap_find_all(C, "Object Mode", 0, 0);
811                 }
812         }
813         else if (strstr(opname, "CURVE_OT")) {
814                 km = WM_keymap_find_all(C, "Curve", 0, 0);
815                 
816                 /* some curve operators are active in object mode too, like add-prim */
817                 if(km && km->poll && km->poll((bContext *)C)==0) {
818                         km = WM_keymap_find_all(C, "Object Mode", 0, 0);
819                 }
820         }
821         else if (strstr(opname, "ARMATURE_OT")) {
822                 km = WM_keymap_find_all(C, "Armature", 0, 0);
823         }
824         else if (strstr(opname, "POSE_OT")) {
825                 km = WM_keymap_find_all(C, "Pose", 0, 0);
826         }
827         else if (strstr(opname, "SCULPT_OT")) {
828                 km = WM_keymap_find_all(C, "Sculpt", 0, 0);
829         }
830         else if (strstr(opname, "MBALL_OT")) {
831                 km = WM_keymap_find_all(C, "Metaball", 0, 0);
832                 
833                 /* some mball operators are active in object mode too, like add-prim */
834                 if(km && km->poll && km->poll((bContext *)C)==0) {
835                         km = WM_keymap_find_all(C, "Object Mode", 0, 0);
836                 }
837         }
838         else if (strstr(opname, "LATTICE_OT")) {
839                 km = WM_keymap_find_all(C, "Lattice", 0, 0);
840         }
841         else if (strstr(opname, "PARTICLE_OT")) {
842                 km = WM_keymap_find_all(C, "Particle", 0, 0);
843         }
844         else if (strstr(opname, "FONT_OT")) {
845                 km = WM_keymap_find_all(C, "Font", 0, 0);
846         }
847         else if (strstr(opname, "PAINT_OT")) {
848                 
849                 /* check for relevant mode */
850                 switch(CTX_data_mode_enum(C)) {
851                         case OB_MODE_WEIGHT_PAINT:
852                                 km = WM_keymap_find_all(C, "Weight Paint", 0, 0);
853                                 break;
854                         case OB_MODE_VERTEX_PAINT:
855                                 km = WM_keymap_find_all(C, "Vertex Paint", 0, 0);
856                                 break;
857                         case OB_MODE_TEXTURE_PAINT:
858                                 km = WM_keymap_find_all(C, "Image Paint", 0, 0);
859                                 break;
860                 }
861         }
862         /* Paint Face Mask */
863         else if (strstr(opname, "PAINT_OT_face_select")) {
864                 km = WM_keymap_find_all(C, "Face Mask", sl->spacetype, 0);
865         }
866         /* Timeline */
867         else if (strstr(opname, "TIME_OT")) {
868                 km = WM_keymap_find_all(C, "Timeline", sl->spacetype, 0);
869         }
870         /* Image Editor */
871         else if (strstr(opname, "IMAGE_OT")) {
872                 km = WM_keymap_find_all(C, "Image", sl->spacetype, 0);
873         }
874         /* UV Editor */
875         else if (strstr(opname, "UV_OT")) {
876                 km = WM_keymap_find_all(C, "UV Editor", sl->spacetype, 0);
877         }
878         /* Node Editor */
879         else if (strstr(opname, "NODE_OT")) {
880                 km = WM_keymap_find_all(C, "Node Editor", sl->spacetype, 0);
881         }
882         /* Animation Editor Channels */
883         else if (strstr(opname, "ANIM_OT_channels")) {
884                 km = WM_keymap_find_all(C, "Animation Channels", sl->spacetype, 0);
885         }
886         /* Animation Generic - after channels */
887         else if (strstr(opname, "ANIM_OT")) {
888                 km = WM_keymap_find_all(C, "Animation", 0, 0);
889         }
890         /* Graph Editor */
891         else if (strstr(opname, "GRAPH_OT")) {
892                 km = WM_keymap_find_all(C, "Graph Editor", sl->spacetype, 0);
893         }
894         /* Dopesheet Editor */
895         else if (strstr(opname, "ACTION_OT")) {
896                 km = WM_keymap_find_all(C, "Dopesheet", sl->spacetype, 0);
897         }
898         /* NLA Editor */
899         else if (strstr(opname, "NLA_OT")) {
900                 km = WM_keymap_find_all(C, "NLA Editor", sl->spacetype, 0);
901         }
902         /* Script */
903         else if (strstr(opname, "SCRIPT_OT")) {
904                 km = WM_keymap_find_all(C, "Script", sl->spacetype, 0);
905         }
906         /* Text */
907         else if (strstr(opname, "TEXT_OT")) {
908                 km = WM_keymap_find_all(C, "Text", sl->spacetype, 0);
909         }
910         /* Sequencer */
911         else if (strstr(opname, "SEQUENCER_OT")) {
912                 km = WM_keymap_find_all(C, "Sequencer", sl->spacetype, 0);
913         }
914         /* Console */
915         else if (strstr(opname, "CONSOLE_OT")) {
916                 km = WM_keymap_find_all(C, "Console", sl->spacetype, 0);
917         }
918         /* Console */
919         else if (strstr(opname, "INFO_OT")) {
920                 km = WM_keymap_find_all(C, "Info", sl->spacetype, 0);
921         }
922         
923         /* Transform */
924         else if (strstr(opname, "TRANSFORM_OT")) {
925                 
926                 /* check for relevant editor */
927                 switch(sl->spacetype) {
928                         case SPACE_VIEW3D:
929                                 km = WM_keymap_find_all(C, "3D View", sl->spacetype, 0);
930                                 break;
931                         case SPACE_IPO:
932                                 km = WM_keymap_find_all(C, "Graph Editor", sl->spacetype, 0);
933                                 break;
934                         case SPACE_ACTION:
935                                 km = WM_keymap_find_all(C, "Dopesheet", sl->spacetype, 0);
936                                 break;
937                         case SPACE_NLA:
938                                 km = WM_keymap_find_all(C, "NLA Editor", sl->spacetype, 0);
939                                 break;
940                         case SPACE_IMAGE:
941                                 km = WM_keymap_find_all(C, "UV Editor", sl->spacetype, 0);
942                                 break;
943                         case SPACE_NODE:
944                                 km = WM_keymap_find_all(C, "Node Editor", sl->spacetype, 0);
945                                 break;
946                         case SPACE_SEQ:
947                                 km = WM_keymap_find_all(C, "Sequencer", sl->spacetype, 0);
948                                 break;
949                 }
950         }
951         
952         return km;
953 }