Blender  V2.59
wm_keymap.c
Go to the documentation of this file.
00001 /*
00002  * $Id: wm_keymap.c 39302 2011-08-11 11:56:02Z blendix $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version. 
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2007 Blender Foundation.
00021  * All rights reserved.
00022  *
00023  * 
00024  * Contributor(s): Blender Foundation
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00034 #include <string.h>
00035 
00036 #include "DNA_object_types.h"
00037 #include "DNA_screen_types.h"
00038 #include "DNA_space_types.h"
00039 #include "DNA_userdef_types.h"
00040 #include "DNA_windowmanager_types.h"
00041 
00042 #include "MEM_guardedalloc.h"
00043 
00044 #include "BLI_blenlib.h"
00045 #include "BLI_utildefines.h"
00046 
00047 #include "BKE_blender.h"
00048 #include "BKE_context.h"
00049 #include "BKE_idprop.h"
00050 #include "BKE_library.h"
00051 #include "BKE_main.h"
00052 #include "BKE_screen.h"
00053 
00054 
00055 #include "RNA_access.h"
00056 #include "RNA_enum_types.h"
00057 
00058 #include "WM_api.h"
00059 #include "WM_types.h"
00060 #include "wm_window.h"
00061 #include "wm_event_system.h"
00062 #include "wm_event_types.h"
00063 
00064 /******************************* Keymap Item **********************************
00065  * Item in a keymap, that maps from an event to an operator or modal map item */
00066 
00067 static wmKeyMapItem *wm_keymap_item_copy(wmKeyMapItem *kmi)
00068 {
00069         wmKeyMapItem *kmin = MEM_dupallocN(kmi);
00070 
00071         kmin->prev= kmin->next= NULL;
00072         kmin->flag &= ~KMI_UPDATE;
00073 
00074         if(kmin->properties) {
00075                 kmin->ptr= MEM_callocN(sizeof(PointerRNA), "UserKeyMapItemPtr");
00076                 WM_operator_properties_create(kmin->ptr, kmin->idname);
00077 
00078                 kmin->properties= IDP_CopyProperty(kmin->properties);
00079                 kmin->ptr->data= kmin->properties;
00080         }
00081 
00082         return kmin;
00083 }
00084 
00085 static void wm_keymap_item_free(wmKeyMapItem *kmi)
00086 {
00087         /* not kmi itself */
00088         if(kmi->ptr) {
00089                 WM_operator_properties_free(kmi->ptr);
00090                 MEM_freeN(kmi->ptr);
00091         }
00092 }
00093 
00094 static void wm_keymap_item_properties_set(wmKeyMapItem *kmi)
00095 {
00096         WM_operator_properties_alloc(&(kmi->ptr), &(kmi->properties), kmi->idname);
00097         WM_operator_properties_sanitize(kmi->ptr, 1);
00098 }
00099 
00100 static int wm_keymap_item_equals_result(wmKeyMapItem *a, wmKeyMapItem *b)
00101 {
00102         if(strcmp(a->idname, b->idname) != 0)
00103                 return 0;
00104         
00105         if(!((a->ptr==NULL && b->ptr==NULL) ||
00106              (a->ptr && b->ptr && IDP_EqualsProperties(a->ptr->data, b->ptr->data))))
00107                 return 0;
00108         
00109         return (a->propvalue == b->propvalue);
00110 }
00111 
00112 static int wm_keymap_item_equals(wmKeyMapItem *a, wmKeyMapItem *b)
00113 {
00114         return (wm_keymap_item_equals_result(a, b) &&
00115                 a->type == b->type &&
00116                 a->val == b->val &&
00117                 a->shift == b->shift &&
00118                 a->ctrl == b->ctrl &&
00119                 a->alt == b->alt &&
00120                 a->oskey == b->oskey &&
00121                 a->keymodifier == b->keymodifier &&
00122                 a->maptype == b->maptype);
00123 }
00124 
00125 /* properties can be NULL, otherwise the arg passed is used and ownership is given to the kmi */
00126 void WM_keymap_properties_reset(wmKeyMapItem *kmi, struct IDProperty *properties)
00127 {
00128         WM_operator_properties_free(kmi->ptr);
00129         MEM_freeN(kmi->ptr);
00130 
00131         kmi->ptr = NULL;
00132         kmi->properties = properties;
00133 
00134         wm_keymap_item_properties_set(kmi);
00135 }
00136 
00137 /**************************** Keymap Diff Item *********************************
00138  * Item in a diff keymap, used for saving diff of keymaps in user preferences */
00139 
00140 static wmKeyMapDiffItem *wm_keymap_diff_item_copy(wmKeyMapDiffItem *kmdi)
00141 {
00142         wmKeyMapDiffItem *kmdin = MEM_dupallocN(kmdi);
00143 
00144         kmdin->next = kmdin->prev = NULL;
00145         if(kmdi->add_item)
00146                 kmdin->add_item = wm_keymap_item_copy(kmdi->add_item);
00147         if(kmdi->remove_item)
00148                 kmdin->remove_item = wm_keymap_item_copy(kmdi->remove_item);
00149         
00150         return kmdin;
00151 }
00152 
00153 static void wm_keymap_diff_item_free(wmKeyMapDiffItem *kmdi)
00154 {
00155         if(kmdi->remove_item) {
00156                 wm_keymap_item_free(kmdi->remove_item);
00157                 MEM_freeN(kmdi->remove_item);
00158         }
00159         if(kmdi->add_item) {
00160                 wm_keymap_item_free(kmdi->add_item);
00161                 MEM_freeN(kmdi->add_item);
00162         }
00163 }
00164 
00165 /***************************** Key Configuration ******************************
00166  * List of keymaps for all editors, modes, ... . There is a builtin default key
00167  * configuration, a user key configuration, and other preset configurations. */
00168 
00169 wmKeyConfig *WM_keyconfig_new(wmWindowManager *wm, const char *idname)
00170 {
00171         wmKeyConfig *keyconf;
00172         
00173         keyconf= MEM_callocN(sizeof(wmKeyConfig), "wmKeyConfig");
00174         BLI_strncpy(keyconf->idname, idname, sizeof(keyconf->idname));
00175         BLI_addtail(&wm->keyconfigs, keyconf);
00176 
00177         return keyconf;
00178 }
00179 
00180 wmKeyConfig *WM_keyconfig_new_user(wmWindowManager *wm, const char *idname)
00181 {
00182         wmKeyConfig *keyconf = WM_keyconfig_new(wm, idname);
00183 
00184         keyconf->flag |= KEYCONF_USER;
00185 
00186         return keyconf;
00187 }
00188 
00189 void WM_keyconfig_remove(wmWindowManager *wm, wmKeyConfig *keyconf)
00190 {
00191         if (keyconf) {
00192                 if (strncmp(U.keyconfigstr, keyconf->idname, sizeof(U.keyconfigstr)) == 0) {
00193                         BLI_strncpy(U.keyconfigstr, wm->defaultconf->idname, sizeof(U.keyconfigstr));
00194                         WM_keyconfig_update_tag(NULL, NULL);
00195                 }
00196 
00197                 BLI_remlink(&wm->keyconfigs, keyconf);
00198                 WM_keyconfig_free(keyconf);
00199         }
00200 }
00201 
00202 void WM_keyconfig_free(wmKeyConfig *keyconf)
00203 {
00204         wmKeyMap *km;
00205 
00206         while((km= keyconf->keymaps.first)) {
00207                 WM_keymap_free(km);
00208                 BLI_freelinkN(&keyconf->keymaps, km);
00209         }
00210 
00211         MEM_freeN(keyconf);
00212 }
00213 
00214 static wmKeyConfig *wm_keyconfig_list_find(ListBase *lb, char *idname)
00215 {
00216         wmKeyConfig *kc;
00217 
00218         for(kc= lb->first; kc; kc= kc->next)
00219                 if(0==strncmp(idname, kc->idname, KMAP_MAX_NAME))
00220                         return kc;
00221         
00222         return NULL;
00223 }
00224 
00225 wmKeyConfig *WM_keyconfig_active(wmWindowManager *wm)
00226 {
00227         wmKeyConfig *keyconf;
00228 
00229         /* first try from preset */
00230         keyconf= wm_keyconfig_list_find(&wm->keyconfigs, U.keyconfigstr);
00231         if(keyconf)
00232                 return keyconf;
00233         
00234         /* otherwise use default */
00235         return wm->defaultconf;
00236 }
00237 
00238 void WM_keyconfig_set_active(wmWindowManager *wm, const char *idname)
00239 {
00240         /* setting a different key configuration as active: we ensure all is
00241            updated properly before and after making the change */
00242 
00243         WM_keyconfig_update(wm);
00244 
00245         BLI_strncpy(U.keyconfigstr, idname, sizeof(U.keyconfigstr));
00246 
00247         WM_keyconfig_update_tag(NULL, NULL);
00248         WM_keyconfig_update(wm);
00249 }
00250 
00251 /********************************** Keymap *************************************
00252  * List of keymap items for one editor, mode, modal operator, ... */
00253 
00254 static wmKeyMap *wm_keymap_new(const char *idname, int spaceid, int regionid)
00255 {
00256         wmKeyMap *km= MEM_callocN(sizeof(struct wmKeyMap), "keymap list");
00257 
00258         BLI_strncpy(km->idname, idname, KMAP_MAX_NAME);
00259         km->spaceid= spaceid;
00260         km->regionid= regionid;
00261 
00262         return km;
00263 }
00264 
00265 static wmKeyMap *wm_keymap_copy(wmKeyMap *keymap)
00266 {
00267         wmKeyMap *keymapn = MEM_dupallocN(keymap);
00268         wmKeyMapItem *kmi, *kmin;
00269         wmKeyMapDiffItem *kmdi, *kmdin;
00270 
00271         keymapn->modal_items= keymap->modal_items;
00272         keymapn->poll= keymap->poll;
00273         keymapn->items.first= keymapn->items.last= NULL;
00274         keymapn->flag &= ~(KEYMAP_UPDATE|KEYMAP_EXPANDED);
00275 
00276         for(kmdi=keymap->diff_items.first; kmdi; kmdi=kmdi->next) {
00277                 kmdin= wm_keymap_diff_item_copy(kmdi);
00278                 BLI_addtail(&keymapn->items, kmdin);
00279         }
00280 
00281         for(kmi=keymap->items.first; kmi; kmi=kmi->next) {
00282                 kmin= wm_keymap_item_copy(kmi);
00283                 BLI_addtail(&keymapn->items, kmin);
00284         }
00285 
00286         return keymapn;
00287 }
00288 
00289 void WM_keymap_free(wmKeyMap *keymap)
00290 {
00291         wmKeyMapItem *kmi;
00292         wmKeyMapDiffItem *kmdi;
00293 
00294         for(kmdi=keymap->diff_items.first; kmdi; kmdi=kmdi->next)
00295                 wm_keymap_diff_item_free(kmdi);
00296 
00297         for(kmi=keymap->items.first; kmi; kmi=kmi->next)
00298                 wm_keymap_item_free(kmi);
00299 
00300         BLI_freelistN(&keymap->diff_items);
00301         BLI_freelistN(&keymap->items);
00302 }
00303 
00304 static void keymap_event_set(wmKeyMapItem *kmi, short type, short val, int modifier, short keymodifier)
00305 {
00306         kmi->type= type;
00307         kmi->val= val;
00308         kmi->keymodifier= keymodifier;
00309         
00310         if(modifier == KM_ANY) {
00311                 kmi->shift= kmi->ctrl= kmi->alt= kmi->oskey= KM_ANY;
00312         }
00313         else {
00314                 
00315                 kmi->shift= kmi->ctrl= kmi->alt= kmi->oskey= 0;
00316                 
00317                 /* defines? */
00318                 if(modifier & KM_SHIFT)
00319                         kmi->shift= 1;
00320                 else if(modifier & KM_SHIFT2)
00321                         kmi->shift= 2;
00322                 if(modifier & KM_CTRL)
00323                         kmi->ctrl= 1;
00324                 else if(modifier & KM_CTRL2)
00325                         kmi->ctrl= 2;
00326                 if(modifier & KM_ALT)
00327                         kmi->alt= 1;
00328                 else if(modifier & KM_ALT2)
00329                         kmi->alt= 2;
00330                 if(modifier & KM_OSKEY)
00331                         kmi->oskey= 1;
00332                 else if(modifier & KM_OSKEY2)
00333                         kmi->oskey= 2;  
00334         }
00335 }
00336 
00337 static void keymap_item_set_id(wmKeyMap *keymap, wmKeyMapItem *kmi)
00338 {
00339         keymap->kmi_id++;
00340         if ((keymap->flag & KEYMAP_USER) == 0) {
00341                 kmi->id = keymap->kmi_id;
00342         } else {
00343                 kmi->id = -keymap->kmi_id; // User defined keymap entries have negative ids
00344         }
00345 }
00346 
00347 /* if item was added, then bail out */
00348 wmKeyMapItem *WM_keymap_verify_item(wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier)
00349 {
00350         wmKeyMapItem *kmi;
00351         
00352         for(kmi= keymap->items.first; kmi; kmi= kmi->next)
00353                 if(strncmp(kmi->idname, idname, OP_MAX_TYPENAME)==0)
00354                         break;
00355         if(kmi==NULL) {
00356                 kmi= MEM_callocN(sizeof(wmKeyMapItem), "keymap entry");
00357                 
00358                 BLI_addtail(&keymap->items, kmi);
00359                 BLI_strncpy(kmi->idname, idname, OP_MAX_TYPENAME);
00360                 
00361                 keymap_item_set_id(keymap, kmi);
00362 
00363                 keymap_event_set(kmi, type, val, modifier, keymodifier);
00364                 wm_keymap_item_properties_set(kmi);
00365         }
00366         return kmi;
00367 }
00368 
00369 /* always add item */
00370 wmKeyMapItem *WM_keymap_add_item(wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier)
00371 {
00372         wmKeyMapItem *kmi= MEM_callocN(sizeof(wmKeyMapItem), "keymap entry");
00373         
00374         BLI_addtail(&keymap->items, kmi);
00375         BLI_strncpy(kmi->idname, idname, OP_MAX_TYPENAME);
00376 
00377         keymap_event_set(kmi, type, val, modifier, keymodifier);
00378         wm_keymap_item_properties_set(kmi);
00379 
00380         keymap_item_set_id(keymap, kmi);
00381 
00382         WM_keyconfig_update_tag(keymap, kmi);
00383 
00384         return kmi;
00385 }
00386 
00387 /* menu wrapper for WM_keymap_add_item */
00388 wmKeyMapItem *WM_keymap_add_menu(wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier)
00389 {
00390         wmKeyMapItem *kmi= WM_keymap_add_item(keymap, "WM_OT_call_menu", type, val, modifier, keymodifier);
00391         RNA_string_set(kmi->ptr, "name", idname);
00392         return kmi;
00393 }
00394 
00395 void WM_keymap_remove_item(wmKeyMap *keymap, wmKeyMapItem *kmi)
00396 {
00397         if(BLI_findindex(&keymap->items, kmi) != -1) {
00398                 if(kmi->ptr) {
00399                         WM_operator_properties_free(kmi->ptr);
00400                         MEM_freeN(kmi->ptr);
00401                 }
00402                 BLI_freelinkN(&keymap->items, kmi);
00403 
00404                 WM_keyconfig_update_tag(keymap, kmi);
00405         }
00406 }
00407 
00408 /************************** Keymap Diff and Patch ****************************
00409  * Rather than saving the entire keymap for user preferences, we only save a
00410  * diff so that changes in the defaults get synced. This system is not perfect
00411  * but works better than overriding the keymap entirely when only few items
00412  * are changed. */
00413 
00414 static void wm_keymap_addon_add(wmKeyMap *keymap, wmKeyMap *addonmap)
00415 {
00416         wmKeyMapItem *kmi, *kmin;
00417 
00418         for(kmi=addonmap->items.first; kmi; kmi=kmi->next) {
00419                 kmin = wm_keymap_item_copy(kmi);
00420                 keymap_item_set_id(keymap, kmin);
00421                 BLI_addhead(&keymap->items, kmin);
00422         }
00423 }
00424 
00425 static wmKeyMapItem *wm_keymap_find_item_equals(wmKeyMap *km, wmKeyMapItem *needle)
00426 {
00427         wmKeyMapItem *kmi;
00428 
00429         for(kmi=km->items.first; kmi; kmi=kmi->next)
00430                 if(wm_keymap_item_equals(kmi, needle))
00431                         return kmi;
00432         
00433         return NULL;
00434 }
00435 
00436 static wmKeyMapItem *wm_keymap_find_item_equals_result(wmKeyMap *km, wmKeyMapItem *needle)
00437 {
00438         wmKeyMapItem *kmi;
00439 
00440         for(kmi=km->items.first; kmi; kmi=kmi->next)
00441                 if(wm_keymap_item_equals_result(kmi, needle))
00442                         return kmi;
00443         
00444         return NULL;
00445 }
00446 
00447 static void wm_keymap_diff(wmKeyMap *diff_km, wmKeyMap *from_km, wmKeyMap *to_km, wmKeyMap *orig_km, wmKeyMap *addon_km)
00448 {
00449         wmKeyMapItem *kmi, *to_kmi, *orig_kmi;
00450         wmKeyMapDiffItem *kmdi;
00451 
00452         for(kmi=from_km->items.first; kmi; kmi=kmi->next) {
00453                 to_kmi = WM_keymap_item_find_id(to_km, kmi->id);
00454 
00455                 if(!to_kmi) {
00456                         /* remove item */
00457                         kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem");
00458                         kmdi->remove_item = wm_keymap_item_copy(kmi);
00459                         BLI_addtail(&diff_km->diff_items, kmdi);
00460                 }
00461                 else if(to_kmi && !wm_keymap_item_equals(kmi, to_kmi)) {
00462                         /* replace item */
00463                         kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem");
00464                         kmdi->remove_item = wm_keymap_item_copy(kmi);
00465                         kmdi->add_item = wm_keymap_item_copy(to_kmi);
00466                         BLI_addtail(&diff_km->diff_items, kmdi);
00467                 }
00468 
00469                 /* sync expanded flag back to original so we don't loose it on repatch */
00470                 if(to_kmi) {
00471                         orig_kmi = WM_keymap_item_find_id(orig_km, kmi->id);
00472 
00473                         if(!orig_kmi)
00474                                 orig_kmi = wm_keymap_find_item_equals(addon_km, kmi);
00475 
00476                         if(orig_kmi) {
00477                                 orig_kmi->flag &= ~KMI_EXPANDED;
00478                                 orig_kmi->flag |= (to_kmi->flag & KMI_EXPANDED);
00479                         }
00480                 }
00481         }
00482 
00483         for(kmi=to_km->items.first; kmi; kmi=kmi->next) {
00484                 if(kmi->id < 0) {
00485                         /* add item */
00486                         kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem");
00487                         kmdi->add_item = wm_keymap_item_copy(kmi);
00488                         BLI_addtail(&diff_km->diff_items, kmdi);
00489                 }
00490         }
00491 }
00492 
00493 static void wm_keymap_patch(wmKeyMap *km, wmKeyMap *diff_km)
00494 {
00495         wmKeyMapDiffItem *kmdi;
00496         wmKeyMapItem *kmi_remove, *kmi_add;
00497 
00498         for(kmdi=diff_km->diff_items.first; kmdi; kmdi=kmdi->next) {
00499                 /* find item to remove */
00500                 kmi_remove = NULL;
00501                 if(kmdi->remove_item) {
00502                         kmi_remove = wm_keymap_find_item_equals(km, kmdi->remove_item);
00503                         if(!kmi_remove)
00504                                 kmi_remove = wm_keymap_find_item_equals_result(km, kmdi->remove_item);
00505                 }
00506 
00507                 /* add item */
00508                 if(kmdi->add_item) {
00509                         /* only if nothing to remove or item to remove found */
00510                         if(!kmdi->remove_item || kmi_remove) {
00511                                 kmi_add = wm_keymap_item_copy(kmdi->add_item);
00512                                 kmi_add->flag |= KMI_USER_MODIFIED;
00513 
00514                                 if(kmi_remove) {
00515                                         kmi_add->flag &= ~KMI_EXPANDED;
00516                                         kmi_add->flag |= (kmi_remove->flag & KMI_EXPANDED);
00517                                         kmi_add->id = kmi_remove->id;
00518                                         BLI_insertlinkbefore(&km->items, kmi_remove, kmi_add);
00519                                 }
00520                                 else {
00521                                         keymap_item_set_id(km, kmi_add);
00522                                         BLI_addtail(&km->items, kmi_add);
00523                                 }
00524                         }
00525                 }
00526 
00527                 /* remove item */
00528                 if(kmi_remove) {
00529                         wm_keymap_item_free(kmi_remove);
00530                         BLI_freelinkN(&km->items, kmi_remove);
00531                 }
00532         }
00533 }
00534 
00535 static wmKeyMap *wm_keymap_patch_update(ListBase *lb, wmKeyMap *defaultmap, wmKeyMap *addonmap, wmKeyMap *usermap)
00536 {
00537         wmKeyMap *km;
00538         int expanded = 0;
00539 
00540         /* remove previous keymap in list, we will replace it */
00541         km = WM_keymap_list_find(lb, defaultmap->idname, defaultmap->spaceid, defaultmap->regionid);
00542         if(km) {
00543                 expanded = (km->flag & (KEYMAP_EXPANDED|KEYMAP_CHILDREN_EXPANDED));
00544                 WM_keymap_free(km);
00545                 BLI_freelinkN(lb, km);
00546         }
00547 
00548         /* copy new keymap from an existing one */
00549         if(usermap && !(usermap->flag & KEYMAP_DIFF)) {
00550                 /* for compatibiltiy with old user preferences with non-diff
00551                    keymaps we override the original entirely */
00552                 wmKeyMapItem *kmi, *orig_kmi;
00553 
00554                 km = wm_keymap_copy(usermap);
00555 
00556                 /* try to find corresponding id's for items */
00557                 for(kmi=km->items.first; kmi; kmi=kmi->next) {
00558                         orig_kmi = wm_keymap_find_item_equals(defaultmap, kmi);
00559                         if(!orig_kmi)
00560                                 orig_kmi = wm_keymap_find_item_equals_result(defaultmap, kmi);
00561 
00562                         if(orig_kmi)
00563                                 kmi->id = orig_kmi->id;
00564                         else
00565                                 kmi->id = -(km->kmi_id++);
00566                 }
00567 
00568                 km->flag |= KEYMAP_UPDATE; /* update again to create diff */
00569         }
00570         else
00571                 km = wm_keymap_copy(defaultmap);
00572 
00573         /* add addon keymap items */
00574         if(addonmap)
00575                 wm_keymap_addon_add(km, addonmap);
00576 
00577         /* tag as being user edited */
00578         if(usermap)
00579                 km->flag |= KEYMAP_USER_MODIFIED;
00580         km->flag |= KEYMAP_USER|expanded;
00581 
00582         /* apply user changes of diff keymap */
00583         if(usermap && (usermap->flag & KEYMAP_DIFF))
00584                 wm_keymap_patch(km, usermap);
00585 
00586         /* add to list */
00587         BLI_addtail(lb, km);
00588         
00589         return km;
00590 }
00591 
00592 static void wm_keymap_diff_update(ListBase *lb, wmKeyMap *defaultmap, wmKeyMap *addonmap, wmKeyMap *km)
00593 {
00594         wmKeyMap *diffmap, *prevmap, *origmap;
00595 
00596         /* create temporary default + addon keymap for diff */
00597         origmap = defaultmap;
00598 
00599         if(addonmap) {
00600                 defaultmap = wm_keymap_copy(defaultmap);
00601                 wm_keymap_addon_add(defaultmap, addonmap);
00602         }
00603 
00604         /* remove previous diff keymap in list, we will replace it */
00605         prevmap = WM_keymap_list_find(lb, km->idname, km->spaceid, km->regionid);
00606         if(prevmap) {
00607                 WM_keymap_free(prevmap);
00608                 BLI_freelinkN(lb, prevmap);
00609         }
00610 
00611         /* create diff keymap */
00612         diffmap= wm_keymap_new(km->idname, km->spaceid, km->regionid);
00613         diffmap->flag |= KEYMAP_DIFF;
00614         wm_keymap_diff(diffmap, defaultmap, km, origmap, addonmap);
00615 
00616         /* add to list if not empty */
00617         if(diffmap->diff_items.first) {
00618                 BLI_addtail(lb, diffmap);
00619         }
00620         else {
00621                 WM_keymap_free(diffmap);
00622                 MEM_freeN(diffmap);
00623         }
00624 
00625         /* free temporary default map */
00626         if(addonmap) {
00627                 WM_keymap_free(defaultmap);
00628                 MEM_freeN(defaultmap);
00629         }
00630 }
00631 
00632 /* ****************** storage in WM ************ */
00633 
00634 /* name id's are for storing general or multiple keymaps, 
00635    space/region ids are same as DNA_space_types.h */
00636 /* gets free'd in wm.c */
00637 
00638 wmKeyMap *WM_keymap_list_find(ListBase *lb, const char *idname, int spaceid, int regionid)
00639 {
00640         wmKeyMap *km;
00641 
00642         for(km= lb->first; km; km= km->next)
00643                 if(km->spaceid==spaceid && km->regionid==regionid)
00644                         if(0==strncmp(idname, km->idname, KMAP_MAX_NAME))
00645                                 return km;
00646         
00647         return NULL;
00648 }
00649 
00650 wmKeyMap *WM_keymap_find(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid)
00651 {
00652         wmKeyMap *km= WM_keymap_list_find(&keyconf->keymaps, idname, spaceid, regionid);
00653         
00654         if(km==NULL) {
00655                 km= wm_keymap_new(idname, spaceid, regionid);
00656                 BLI_addtail(&keyconf->keymaps, km);
00657 
00658                 WM_keyconfig_update_tag(km, NULL);
00659         }
00660         
00661         return km;
00662 }
00663 
00664 wmKeyMap *WM_keymap_find_all(const bContext *C, const char *idname, int spaceid, int regionid)
00665 {
00666         wmWindowManager *wm= CTX_wm_manager(C);
00667 
00668         return WM_keymap_list_find(&wm->userconf->keymaps, idname, spaceid, regionid);
00669 }
00670 
00671 /* ****************** modal keymaps ************ */
00672 
00673 /* modal maps get linked to a running operator, and filter the keys before sending to modal() callback */
00674 
00675 wmKeyMap *WM_modalkeymap_add(wmKeyConfig *keyconf, const char *idname, EnumPropertyItem *items)
00676 {
00677         wmKeyMap *km= WM_keymap_find(keyconf, idname, 0, 0);
00678         km->flag |= KEYMAP_MODAL;
00679         km->modal_items= items;
00680         
00681         return km;
00682 }
00683 
00684 wmKeyMap *WM_modalkeymap_get(wmKeyConfig *keyconf, const char *idname)
00685 {
00686         wmKeyMap *km;
00687         
00688         for(km= keyconf->keymaps.first; km; km= km->next)
00689                 if(km->flag & KEYMAP_MODAL)
00690                         if(0==strncmp(idname, km->idname, KMAP_MAX_NAME))
00691                                 break;
00692         
00693         return km;
00694 }
00695 
00696 
00697 wmKeyMapItem *WM_modalkeymap_add_item(wmKeyMap *km, int type, int val, int modifier, int keymodifier, int value)
00698 {
00699         wmKeyMapItem *kmi= MEM_callocN(sizeof(wmKeyMapItem), "keymap entry");
00700         
00701         BLI_addtail(&km->items, kmi);
00702         kmi->propvalue= value;
00703         
00704         keymap_event_set(kmi, type, val, modifier, keymodifier);
00705 
00706         keymap_item_set_id(km, kmi);
00707 
00708         WM_keyconfig_update_tag(km, kmi);
00709 
00710         return kmi;
00711 }
00712 
00713 void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
00714 {
00715         wmOperatorType *ot= WM_operatortype_find(opname, 0);
00716         
00717         if(ot)
00718                 ot->modalkeymap= km;
00719         else
00720                 printf("error: modalkeymap_assign, unknown operator %s\n", opname);
00721 }
00722 
00723 /* ***************** get string from key events **************** */
00724 
00725 const char *WM_key_event_string(short type)
00726 {
00727         const char *name= NULL;
00728         if(RNA_enum_name(event_type_items, (int)type, &name))
00729                 return name;
00730         
00731         return "";
00732 }
00733 
00734 char *WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, int len)
00735 {
00736         char buf[128];
00737 
00738         buf[0]= 0;
00739 
00740         if (kmi->shift == KM_ANY &&
00741                 kmi->ctrl == KM_ANY &&
00742                 kmi->alt == KM_ANY &&
00743                 kmi->oskey == KM_ANY) {
00744 
00745                 strcat(buf, "Any ");
00746         } else {
00747                 if(kmi->shift)
00748                         strcat(buf, "Shift ");
00749 
00750                 if(kmi->ctrl)
00751                         strcat(buf, "Ctrl ");
00752 
00753                 if(kmi->alt)
00754                         strcat(buf, "Alt ");
00755 
00756                 if(kmi->oskey)
00757                         strcat(buf, "Cmd ");
00758         }
00759                 
00760         if(kmi->keymodifier) {
00761                 strcat(buf, WM_key_event_string(kmi->keymodifier));
00762                 strcat(buf, " ");
00763         }
00764 
00765         strcat(buf, WM_key_event_string(kmi->type));
00766         BLI_strncpy(str, buf, len);
00767 
00768         return str;
00769 }
00770 
00771 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)
00772 {
00773         wmWindowManager *wm= CTX_wm_manager(C);
00774         wmEventHandler *handler;
00775         wmKeyMap *keymap;
00776         wmKeyMapItem *kmi;
00777 
00778         /* find keymap item in handlers */
00779         for(handler=handlers->first; handler; handler=handler->next) {
00780                 keymap= WM_keymap_active(wm, handler->keymap);
00781 
00782                 if(keymap && (!keymap->poll || keymap->poll((bContext*)C))) {
00783                         for(kmi=keymap->items.first; kmi; kmi=kmi->next) {
00784                                 
00785                                 if(strcmp(kmi->idname, opname) == 0 && WM_key_event_string(kmi->type)[0]) {
00786                                         if (hotkey)
00787                                                 if (!ISHOTKEY(kmi->type))
00788                                                         continue;
00789                                         
00790                                         if(compare_props) {
00791                                                 if(kmi->ptr && IDP_EqualsProperties(properties, kmi->ptr->data)) {
00792                                                         if(keymap_r) *keymap_r= keymap;
00793                                                         return kmi;
00794                                                 }
00795                                         }
00796                                         else {
00797                                                 if(keymap_r) *keymap_r= keymap;
00798                                                 return kmi;
00799                                         }
00800                                 }
00801                         }
00802                 }
00803         }
00804         
00805         /* ensure un-initialized keymap is never used */
00806         if(keymap_r) *keymap_r= NULL;
00807         return NULL;
00808 }
00809 
00810 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)
00811 {
00812         wmWindow *win= CTX_wm_window(C);
00813         ScrArea *sa= CTX_wm_area(C);
00814         ARegion *ar= CTX_wm_region(C);
00815         wmKeyMapItem *found= NULL;
00816 
00817         /* look into multiple handler lists to find the item */
00818         if(win)
00819                 found= wm_keymap_item_find_handlers(C, &win->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
00820         
00821 
00822         if(sa && found==NULL)
00823                 found= wm_keymap_item_find_handlers(C, &sa->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
00824 
00825         if(found==NULL) {
00826                 if(ELEM(opcontext, WM_OP_EXEC_REGION_WIN, WM_OP_INVOKE_REGION_WIN)) {
00827                         if(sa) {
00828                                 if (!(ar && ar->regiontype == RGN_TYPE_WINDOW))
00829                                         ar= BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
00830                                 
00831                                 if(ar)
00832                                         found= wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
00833                         }
00834                 }
00835                 else if(ELEM(opcontext, WM_OP_EXEC_REGION_CHANNELS, WM_OP_INVOKE_REGION_CHANNELS)) {
00836                         if (!(ar && ar->regiontype == RGN_TYPE_CHANNELS))
00837                                 ar= BKE_area_find_region_type(sa, RGN_TYPE_CHANNELS);
00838 
00839                         if(ar)
00840                                 found= wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
00841                 }
00842                 else if(ELEM(opcontext, WM_OP_EXEC_REGION_PREVIEW, WM_OP_INVOKE_REGION_PREVIEW)) {
00843                         if (!(ar && ar->regiontype == RGN_TYPE_PREVIEW))
00844                                 ar= BKE_area_find_region_type(sa, RGN_TYPE_PREVIEW);
00845 
00846                         if(ar)
00847                                 found= wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
00848                 }
00849                 else {
00850                         if(ar)
00851                                 found= wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
00852                 }
00853         }
00854         
00855         return found;
00856 }
00857 
00858 static wmKeyMapItem *wm_keymap_item_find(const bContext *C, const char *opname, int opcontext, IDProperty *properties, int hotkey, wmKeyMap **keymap_r)
00859 {
00860         wmKeyMapItem *found= wm_keymap_item_find_props(C, opname, opcontext, properties, 1, hotkey, keymap_r);
00861 
00862         if(!found)
00863                 found= wm_keymap_item_find_props(C, opname, opcontext, NULL, 0, hotkey, keymap_r);
00864 
00865         return found;
00866 }
00867 
00868 char *WM_key_event_operator_string(const bContext *C, const char *opname, int opcontext, IDProperty *properties, char *str, int len)
00869 {
00870         wmKeyMapItem *kmi= wm_keymap_item_find(C, opname, opcontext, properties, 0, NULL);
00871         
00872         if(kmi) {
00873                 WM_keymap_item_to_string(kmi, str, len);
00874                 return str;
00875         }
00876 
00877         return NULL;
00878 }
00879 
00880 int WM_key_event_operator_id(const bContext *C, const char *opname, int opcontext, IDProperty *properties, int hotkey, wmKeyMap **keymap_r)
00881 {
00882         wmKeyMapItem *kmi= wm_keymap_item_find(C, opname, opcontext, properties, hotkey, keymap_r);
00883         
00884         if(kmi)
00885                 return kmi->id;
00886         else
00887                 return 0;
00888 }
00889 
00890 int     WM_keymap_item_compare(wmKeyMapItem *k1, wmKeyMapItem *k2)
00891 {
00892         int k1type, k2type;
00893 
00894         if (k1->flag & KMI_INACTIVE || k2->flag & KMI_INACTIVE)
00895                 return 0;
00896 
00897         /* take event mapping into account */
00898         k1type = WM_userdef_event_map(k1->type);
00899         k2type = WM_userdef_event_map(k2->type);
00900 
00901         if(k1type != KM_ANY && k2type != KM_ANY && k1type != k2type)
00902                 return 0;
00903 
00904         if(k1->val != KM_ANY && k2->val != KM_ANY) {
00905                 /* take click, press, release conflict into account */
00906                 if (k1->val == KM_CLICK && ELEM3(k2->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0)
00907                         return 0;
00908                 if (k2->val == KM_CLICK && ELEM3(k1->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0)
00909                         return 0;
00910                 if (k1->val != k2->val)
00911                         return 0;
00912         }
00913 
00914         if(k1->shift != KM_ANY && k2->shift != KM_ANY && k1->shift != k2->shift)
00915                 return 0;
00916 
00917         if(k1->ctrl != KM_ANY && k2->ctrl != KM_ANY && k1->ctrl != k2->ctrl)
00918                 return 0;
00919 
00920         if(k1->alt != KM_ANY && k2->alt != KM_ANY && k1->alt != k2->alt)
00921                 return 0;
00922 
00923         if(k1->oskey != KM_ANY && k2->oskey != KM_ANY && k1->oskey != k2->oskey)
00924                 return 0;
00925 
00926         if(k1->keymodifier != k2->keymodifier)
00927                 return 0;
00928 
00929         return 1;
00930 }
00931 
00932 /************************* Update Final Configuration *************************
00933  * On load or other changes, the final user key configuration is rebuilt from
00934  * the preset, addon and user preferences keymaps. We also test if the final
00935  * configuration changed and write the changes to the user preferences. */
00936 
00937 static int WM_KEYMAP_UPDATE = 0;
00938 
00939 void WM_keyconfig_update_tag(wmKeyMap *km, wmKeyMapItem *kmi)
00940 {
00941         /* quick tag to do delayed keymap updates */
00942         WM_KEYMAP_UPDATE= 1;
00943 
00944         if(km)
00945                 km->flag |= KEYMAP_UPDATE;
00946         if(kmi)
00947                 kmi->flag |= KMI_UPDATE;
00948 }
00949 
00950 static int wm_keymap_test_and_clear_update(wmKeyMap *km)
00951 {
00952         wmKeyMapItem *kmi;
00953         int update;
00954         
00955         update= (km->flag & KEYMAP_UPDATE);
00956         km->flag &= ~KEYMAP_UPDATE;
00957 
00958         for(kmi=km->items.first; kmi; kmi=kmi->next) {
00959                 update= update || (kmi->flag & KMI_UPDATE);
00960                 kmi->flag &= ~KMI_UPDATE;
00961         }
00962         
00963         return update;
00964 }
00965 
00966 static wmKeyMap *wm_keymap_preset(wmWindowManager *wm, wmKeyMap *km)
00967 {
00968         wmKeyConfig *keyconf= WM_keyconfig_active(wm);
00969         wmKeyMap *keymap;
00970 
00971         keymap= WM_keymap_list_find(&keyconf->keymaps, km->idname, km->spaceid, km->regionid);
00972         if(!keymap)
00973                 keymap= WM_keymap_list_find(&wm->defaultconf->keymaps, km->idname, km->spaceid, km->regionid);
00974 
00975         return keymap;
00976 }
00977 
00978 void WM_keyconfig_update(wmWindowManager *wm)
00979 {
00980         wmKeyMap *km, *defaultmap, *addonmap, *usermap, *kmn;
00981         wmKeyMapItem *kmi;
00982         wmKeyMapDiffItem *kmdi;
00983         int compat_update = 0;
00984 
00985         if(!WM_KEYMAP_UPDATE)
00986                 return;
00987         
00988         /* update operator properties for non-modal user keymaps */
00989         for(km=U.user_keymaps.first; km; km=km->next) {
00990                 if((km->flag & KEYMAP_MODAL) == 0) {
00991                         for(kmdi=km->diff_items.first; kmdi; kmdi=kmdi->next) {
00992                                 if(kmdi->add_item)
00993                                         wm_keymap_item_properties_set(kmdi->add_item);
00994                                 if(kmdi->remove_item)
00995                                         wm_keymap_item_properties_set(kmdi->remove_item);
00996                         }
00997 
00998                         for(kmi=km->items.first; kmi; kmi=kmi->next)
00999                                 wm_keymap_item_properties_set(kmi);
01000                 }
01001         }
01002 
01003         /* update U.user_keymaps with user key configuration changes */
01004         for(km=wm->userconf->keymaps.first; km; km=km->next) {
01005                 /* only diff if the user keymap was modified */
01006                 if(wm_keymap_test_and_clear_update(km)) {
01007                         /* find keymaps */
01008                         defaultmap= wm_keymap_preset(wm, km);
01009                         addonmap= WM_keymap_list_find(&wm->addonconf->keymaps, km->idname, km->spaceid, km->regionid);
01010 
01011                         /* diff */
01012                         if(defaultmap)
01013                                 wm_keymap_diff_update(&U.user_keymaps, defaultmap, addonmap, km);
01014                 }
01015         }
01016 
01017         /* create user key configuration from preset + addon + user preferences */
01018         for(km=wm->defaultconf->keymaps.first; km; km=km->next) {
01019                 /* find keymaps */
01020                 defaultmap= wm_keymap_preset(wm, km);
01021                 addonmap= WM_keymap_list_find(&wm->addonconf->keymaps, km->idname, km->spaceid, km->regionid);
01022                 usermap= WM_keymap_list_find(&U.user_keymaps, km->idname, km->spaceid, km->regionid);
01023 
01024                 /* add */
01025                 kmn= wm_keymap_patch_update(&wm->userconf->keymaps, defaultmap, addonmap, usermap);
01026 
01027                 if(kmn) {
01028                         kmn->modal_items= km->modal_items;
01029                         kmn->poll= km->poll;
01030                 }
01031 
01032                 /* in case of old non-diff keymaps, force extra update to create diffs */
01033                 compat_update = compat_update || (usermap && !(usermap->flag & KEYMAP_DIFF));
01034         }
01035 
01036         WM_KEYMAP_UPDATE= 0;
01037 
01038         if(compat_update) {
01039                 WM_keyconfig_update_tag(NULL, NULL);
01040                 WM_keyconfig_update(wm);
01041         }
01042 }
01043 
01044 /********************************* Event Handling *****************************
01045  * Handlers have pointers to the keymap in the default configuration. During
01046  * event handling this function is called to get the keymap from the final
01047  * configuration. */
01048 
01049 wmKeyMap *WM_keymap_active(wmWindowManager *wm, wmKeyMap *keymap)
01050 {
01051         wmKeyMap *km;
01052 
01053         if(!keymap)
01054                 return NULL;
01055         
01056         /* first user defined keymaps */
01057         km= WM_keymap_list_find(&wm->userconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
01058 
01059         if(km)
01060                 return km;
01061 
01062         return keymap;
01063 }
01064 
01065 /******************************* Keymap Editor ********************************
01066  * In the keymap editor the user key configuration is edited. */
01067 
01068 void WM_keymap_restore_item_to_default(bContext *C, wmKeyMap *keymap, wmKeyMapItem *kmi)
01069 {
01070         wmWindowManager *wm = CTX_wm_manager(C);
01071         wmKeyMap *defaultmap, *addonmap;
01072         wmKeyMapItem *orig;
01073 
01074         if(!keymap)
01075                 return;
01076 
01077         /* construct default keymap from preset + addons */
01078         defaultmap= wm_keymap_preset(wm, keymap);
01079         addonmap= WM_keymap_list_find(&wm->addonconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
01080 
01081         if(addonmap) {
01082                 defaultmap = wm_keymap_copy(defaultmap);
01083                 wm_keymap_addon_add(defaultmap, addonmap);
01084         }
01085 
01086         /* find original item */
01087         orig = WM_keymap_item_find_id(defaultmap, kmi->id);
01088 
01089         if(orig) {
01090                 /* restore to original */
01091                 if(strcmp(orig->idname, kmi->idname) != 0) {
01092                         BLI_strncpy(kmi->idname, orig->idname, sizeof(kmi->idname));
01093                         WM_keymap_properties_reset(kmi, NULL);
01094                 }
01095 
01096                 if (orig->properties) {
01097                         if(kmi->properties) {
01098                                 IDP_FreeProperty(kmi->properties);
01099                                 MEM_freeN(kmi->properties);
01100                                 kmi->properties= NULL;
01101                         }
01102 
01103                         kmi->properties= IDP_CopyProperty(orig->properties);
01104                         kmi->ptr->data= kmi->properties;
01105                 }
01106 
01107                 kmi->propvalue = orig->propvalue;
01108                 kmi->type = orig->type;
01109                 kmi->val = orig->val;
01110                 kmi->shift = orig->shift;
01111                 kmi->ctrl = orig->ctrl;
01112                 kmi->alt = orig->alt;
01113                 kmi->oskey = orig->oskey;
01114                 kmi->keymodifier = orig->keymodifier;
01115                 kmi->maptype = orig->maptype;
01116 
01117                 WM_keyconfig_update_tag(keymap, kmi);
01118         }
01119 
01120         /* free temporary keymap */
01121         if(addonmap) {
01122                 WM_keymap_free(defaultmap);
01123                 MEM_freeN(defaultmap);
01124         }
01125 }
01126 
01127 void WM_keymap_restore_to_default(wmKeyMap *keymap, bContext *C)
01128 {
01129         wmWindowManager *wm = CTX_wm_manager(C);
01130         wmKeyMap *usermap;
01131 
01132         /* remove keymap from U.user_keymaps and update */
01133         usermap= WM_keymap_list_find(&U.user_keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
01134 
01135         if(usermap) {
01136                 WM_keymap_free(usermap);
01137                 BLI_freelinkN(&U.user_keymaps, usermap);
01138 
01139                 WM_keyconfig_update_tag(NULL, NULL);
01140                 WM_keyconfig_update(wm);
01141         }
01142 }
01143 
01144 wmKeyMapItem *WM_keymap_item_find_id(wmKeyMap *keymap, int id)
01145 {
01146         wmKeyMapItem *kmi;
01147         
01148         for (kmi=keymap->items.first; kmi; kmi=kmi->next) {
01149                 if (kmi->id == id) {
01150                         return kmi;
01151                 }
01152         }
01153         
01154         return NULL;
01155 }
01156 
01157 /* Guess an appropriate keymap from the operator name */
01158 /* Needs to be kept up to date with Keymap and Operator naming */
01159 wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
01160 {
01161         wmKeyMap *km=NULL;
01162         SpaceLink *sl = CTX_wm_space_data(C);
01163         
01164         /* Window */
01165         if (strstr(opname, "WM_OT")) {
01166                 km = WM_keymap_find_all(C, "Window", 0, 0);
01167         }
01168         /* Screen */
01169         else if (strstr(opname, "SCREEN_OT")) {
01170                 km = WM_keymap_find_all(C, "Screen", 0, 0);
01171         }
01172         /* Grease Pencil */
01173         else if (strstr(opname, "GPENCIL_OT")) {
01174                 km = WM_keymap_find_all(C, "Grease Pencil", 0, 0);
01175         }
01176         /* Markers */
01177         else if (strstr(opname, "MARKER_OT")) {
01178                 km = WM_keymap_find_all(C, "Markers", 0, 0);
01179         }
01180         
01181         
01182         /* 3D View */
01183         else if (strstr(opname, "VIEW3D_OT")) {
01184                 km = WM_keymap_find_all(C, "3D View", sl->spacetype, 0);
01185         }
01186         else if (strstr(opname, "OBJECT_OT")) {
01187                 km = WM_keymap_find_all(C, "Object Mode", 0, 0);
01188         }
01189 
01190         
01191         /* Editing Modes */
01192         else if (strstr(opname, "MESH_OT")) {
01193                 km = WM_keymap_find_all(C, "Mesh", 0, 0);
01194                 
01195                 /* some mesh operators are active in object mode too, like add-prim */
01196                 if(km && km->poll && km->poll((bContext *)C)==0) {
01197                         km = WM_keymap_find_all(C, "Object Mode", 0, 0);
01198                 }
01199         }
01200         else if (strstr(opname, "CURVE_OT")) {
01201                 km = WM_keymap_find_all(C, "Curve", 0, 0);
01202                 
01203                 /* some curve operators are active in object mode too, like add-prim */
01204                 if(km && km->poll && km->poll((bContext *)C)==0) {
01205                         km = WM_keymap_find_all(C, "Object Mode", 0, 0);
01206                 }
01207         }
01208         else if (strstr(opname, "ARMATURE_OT")) {
01209                 km = WM_keymap_find_all(C, "Armature", 0, 0);
01210         }
01211         else if (strstr(opname, "POSE_OT")) {
01212                 km = WM_keymap_find_all(C, "Pose", 0, 0);
01213         }
01214         else if (strstr(opname, "SCULPT_OT")) {
01215                 km = WM_keymap_find_all(C, "Sculpt", 0, 0);
01216         }
01217         else if (strstr(opname, "MBALL_OT")) {
01218                 km = WM_keymap_find_all(C, "Metaball", 0, 0);
01219                 
01220                 /* some mball operators are active in object mode too, like add-prim */
01221                 if(km && km->poll && km->poll((bContext *)C)==0) {
01222                         km = WM_keymap_find_all(C, "Object Mode", 0, 0);
01223                 }
01224         }
01225         else if (strstr(opname, "LATTICE_OT")) {
01226                 km = WM_keymap_find_all(C, "Lattice", 0, 0);
01227         }
01228         else if (strstr(opname, "PARTICLE_OT")) {
01229                 km = WM_keymap_find_all(C, "Particle", 0, 0);
01230         }
01231         else if (strstr(opname, "FONT_OT")) {
01232                 km = WM_keymap_find_all(C, "Font", 0, 0);
01233         }
01234         else if (strstr(opname, "PAINT_OT")) {
01235                 
01236                 /* check for relevant mode */
01237                 switch(CTX_data_mode_enum(C)) {
01238                         case OB_MODE_WEIGHT_PAINT:
01239                                 km = WM_keymap_find_all(C, "Weight Paint", 0, 0);
01240                                 break;
01241                         case OB_MODE_VERTEX_PAINT:
01242                                 km = WM_keymap_find_all(C, "Vertex Paint", 0, 0);
01243                                 break;
01244                         case OB_MODE_TEXTURE_PAINT:
01245                                 km = WM_keymap_find_all(C, "Image Paint", 0, 0);
01246                                 break;
01247                 }
01248         }
01249         /* Paint Face Mask */
01250         else if (strstr(opname, "PAINT_OT_face_select")) {
01251                 km = WM_keymap_find_all(C, "Face Mask", sl->spacetype, 0);
01252         }
01253         /* Timeline */
01254         else if (strstr(opname, "TIME_OT")) {
01255                 km = WM_keymap_find_all(C, "Timeline", sl->spacetype, 0);
01256         }
01257         /* Image Editor */
01258         else if (strstr(opname, "IMAGE_OT")) {
01259                 km = WM_keymap_find_all(C, "Image", sl->spacetype, 0);
01260         }
01261         /* UV Editor */
01262         else if (strstr(opname, "UV_OT")) {
01263                 km = WM_keymap_find_all(C, "UV Editor", sl->spacetype, 0);
01264         }
01265         /* Node Editor */
01266         else if (strstr(opname, "NODE_OT")) {
01267                 km = WM_keymap_find_all(C, "Node Editor", sl->spacetype, 0);
01268         }
01269         /* Animation Editor Channels */
01270         else if (strstr(opname, "ANIM_OT_channels")) {
01271                 km = WM_keymap_find_all(C, "Animation Channels", sl->spacetype, 0);
01272         }
01273         /* Animation Generic - after channels */
01274         else if (strstr(opname, "ANIM_OT")) {
01275                 km = WM_keymap_find_all(C, "Animation", 0, 0);
01276         }
01277         /* Graph Editor */
01278         else if (strstr(opname, "GRAPH_OT")) {
01279                 km = WM_keymap_find_all(C, "Graph Editor", sl->spacetype, 0);
01280         }
01281         /* Dopesheet Editor */
01282         else if (strstr(opname, "ACTION_OT")) {
01283                 km = WM_keymap_find_all(C, "Dopesheet", sl->spacetype, 0);
01284         }
01285         /* NLA Editor */
01286         else if (strstr(opname, "NLA_OT")) {
01287                 km = WM_keymap_find_all(C, "NLA Editor", sl->spacetype, 0);
01288         }
01289         /* Script */
01290         else if (strstr(opname, "SCRIPT_OT")) {
01291                 km = WM_keymap_find_all(C, "Script", sl->spacetype, 0);
01292         }
01293         /* Text */
01294         else if (strstr(opname, "TEXT_OT")) {
01295                 km = WM_keymap_find_all(C, "Text", sl->spacetype, 0);
01296         }
01297         /* Sequencer */
01298         else if (strstr(opname, "SEQUENCER_OT")) {
01299                 km = WM_keymap_find_all(C, "Sequencer", sl->spacetype, 0);
01300         }
01301         /* Console */
01302         else if (strstr(opname, "CONSOLE_OT")) {
01303                 km = WM_keymap_find_all(C, "Console", sl->spacetype, 0);
01304         }
01305         /* Console */
01306         else if (strstr(opname, "INFO_OT")) {
01307                 km = WM_keymap_find_all(C, "Info", sl->spacetype, 0);
01308         }
01309         
01310         /* Transform */
01311         else if (strstr(opname, "TRANSFORM_OT")) {
01312                 
01313                 /* check for relevant editor */
01314                 switch(sl->spacetype) {
01315                         case SPACE_VIEW3D:
01316                                 km = WM_keymap_find_all(C, "3D View", sl->spacetype, 0);
01317                                 break;
01318                         case SPACE_IPO:
01319                                 km = WM_keymap_find_all(C, "Graph Editor", sl->spacetype, 0);
01320                                 break;
01321                         case SPACE_ACTION:
01322                                 km = WM_keymap_find_all(C, "Dopesheet", sl->spacetype, 0);
01323                                 break;
01324                         case SPACE_NLA:
01325                                 km = WM_keymap_find_all(C, "NLA Editor", sl->spacetype, 0);
01326                                 break;
01327                         case SPACE_IMAGE:
01328                                 km = WM_keymap_find_all(C, "UV Editor", sl->spacetype, 0);
01329                                 break;
01330                         case SPACE_NODE:
01331                                 km = WM_keymap_find_all(C, "Node Editor", sl->spacetype, 0);
01332                                 break;
01333                         case SPACE_SEQ:
01334                                 km = WM_keymap_find_all(C, "Sequencer", sl->spacetype, 0);
01335                                 break;
01336                 }
01337         }
01338         
01339         return km;
01340 }
01341