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