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