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