fix for WM_keymap_remove_item() writing to freed memory.
[blender.git] / source / blender / windowmanager / intern / wm_keymap.c
index 48002029e56941c7cfc083f2b3c46cef2a80e5db..3739462ac2cc20eef2b26ff86b29d1135b5c6a55 100644 (file)
@@ -101,8 +101,7 @@ static int wm_keymap_item_equals_result(wmKeyMapItem *a, wmKeyMapItem *b)
        if (strcmp(a->idname, b->idname) != 0)
                return 0;
        
-       if (!((a->ptr == NULL && b->ptr == NULL) ||
-             (a->ptr && b->ptr && IDP_EqualsProperties(a->ptr->data, b->ptr->data))))
+       if (!RNA_struct_equals(a->ptr, b->ptr))
                return 0;
        
        if ((a->flag & KMI_INACTIVE) != (b->flag & KMI_INACTIVE))
@@ -188,9 +187,9 @@ wmKeyConfig *WM_keyconfig_new_user(wmWindowManager *wm, const char *idname)
        return keyconf;
 }
 
-void WM_keyconfig_remove(wmWindowManager *wm, wmKeyConfig *keyconf)
+int WM_keyconfig_remove(wmWindowManager *wm, wmKeyConfig *keyconf)
 {
-       if (keyconf) {
+       if (BLI_findindex(&wm->keyconfigs, keyconf) != -1) {
                if (strncmp(U.keyconfigstr, keyconf->idname, sizeof(U.keyconfigstr)) == 0) {
                        BLI_strncpy(U.keyconfigstr, wm->defaultconf->idname, sizeof(U.keyconfigstr));
                        WM_keyconfig_update_tag(NULL, NULL);
@@ -198,6 +197,11 @@ void WM_keyconfig_remove(wmWindowManager *wm, wmKeyConfig *keyconf)
 
                BLI_remlink(&wm->keyconfigs, keyconf);
                WM_keyconfig_free(keyconf);
+
+               return TRUE;
+       }
+       else {
+               return FALSE;
        }
 }
 
@@ -327,7 +331,7 @@ static void keymap_item_set_id(wmKeyMap *keymap, wmKeyMapItem *kmi)
                kmi->id = keymap->kmi_id;
        }
        else {
-               kmi->id = -keymap->kmi_id; // User defined keymap entries have negative ids
+               kmi->id = -keymap->kmi_id; /* User defined keymap entries have negative ids */
        }
 }
 
@@ -379,7 +383,7 @@ wmKeyMapItem *WM_keymap_add_menu(wmKeyMap *keymap, const char *idname, int type,
        return kmi;
 }
 
-void WM_keymap_remove_item(wmKeyMap *keymap, wmKeyMapItem *kmi)
+int WM_keymap_remove_item(wmKeyMap *keymap, wmKeyMapItem *kmi)
 {
        if (BLI_findindex(&keymap->items, kmi) != -1) {
                if (kmi->ptr) {
@@ -388,7 +392,11 @@ void WM_keymap_remove_item(wmKeyMap *keymap, wmKeyMapItem *kmi)
                }
                BLI_freelinkN(&keymap->items, kmi);
 
-               WM_keyconfig_update_tag(keymap, kmi);
+               WM_keyconfig_update_tag(keymap, NULL);
+               return TRUE;
+       }
+       else {
+               return FALSE;
        }
 }
 
@@ -534,7 +542,7 @@ static wmKeyMap *wm_keymap_patch_update(ListBase *lb, wmKeyMap *defaultmap, wmKe
 
        /* copy new keymap from an existing one */
        if (usermap && !(usermap->flag & KEYMAP_DIFF)) {
-               /* for compatibiltiy with old user preferences with non-diff
+               /* for compatibility with old user preferences with non-diff
                 * keymaps we override the original entirely */
                wmKeyMapItem *kmi, *orig_kmi;
 
@@ -783,8 +791,8 @@ char *WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, int len)
        if (kmi->shift == KM_ANY &&
            kmi->ctrl == KM_ANY &&
            kmi->alt == KM_ANY &&
-           kmi->oskey == KM_ANY) {
-
+           kmi->oskey == KM_ANY)
+       {
                strcat(buf, "Any ");
        }
        else {
@@ -813,8 +821,8 @@ char *WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, int len)
 }
 
 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)
+        const bContext *C, ListBase *handlers, const char *opname, int UNUSED(opcontext),
+        IDProperty *properties, int is_strict, int hotkey, wmKeyMap **keymap_r)
 {
        wmWindowManager *wm = CTX_wm_manager(C);
        wmEventHandler *handler;
@@ -832,9 +840,22 @@ static wmKeyMapItem *wm_keymap_item_find_handlers(
                                        if (hotkey)
                                                if (!ISHOTKEY(kmi->type))
                                                        continue;
-                                       
-                                       if (compare_props) {
-                                               if (kmi->ptr && IDP_EqualsProperties(properties, kmi->ptr->data)) {
+
+                                       if (properties) {
+
+                                               /* example of debugging keymaps */
+#if 0
+                                               if (kmi->ptr) {
+                                                       if (strcmp("MESH_OT_rip_move", opname) == 0) {
+                                                               printf("OPERATOR\n");
+                                                               IDP_spit(properties);
+                                                               printf("KEYMAP\n");
+                                                               IDP_spit(kmi->ptr->data);
+                                                       }
+                                               }
+#endif
+
+                                               if (kmi->ptr && IDP_EqualsProperties_ex(properties, kmi->ptr->data, is_strict)) {
                                                        if (keymap_r) *keymap_r = keymap;
                                                        return kmi;
                                                }
@@ -854,8 +875,8 @@ static wmKeyMapItem *wm_keymap_item_find_handlers(
 }
 
 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)
+        const bContext *C, const char *opname, int opcontext,
+        IDProperty *properties, int is_strict, int hotkey, wmKeyMap **keymap_r)
 {
        wmWindow *win = CTX_wm_window(C);
        ScrArea *sa = CTX_wm_area(C);
@@ -864,11 +885,10 @@ static wmKeyMapItem *wm_keymap_item_find_props(
 
        /* look into multiple handler lists to find the item */
        if (win)
-               found = wm_keymap_item_find_handlers(C, &win->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
-       
+               found = wm_keymap_item_find_handlers(C, &win->handlers, opname, opcontext, properties, is_strict, hotkey, keymap_r);
 
        if (sa && found == NULL)
-               found = wm_keymap_item_find_handlers(C, &sa->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
+               found = wm_keymap_item_find_handlers(C, &sa->handlers, opname, opcontext, properties, is_strict, hotkey, keymap_r);
 
        if (found == NULL) {
                if (ELEM(opcontext, WM_OP_EXEC_REGION_WIN, WM_OP_INVOKE_REGION_WIN)) {
@@ -877,7 +897,7 @@ static wmKeyMapItem *wm_keymap_item_find_props(
                                        ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
                                
                                if (ar)
-                                       found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
+                                       found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, hotkey, keymap_r);
                        }
                }
                else if (ELEM(opcontext, WM_OP_EXEC_REGION_CHANNELS, WM_OP_INVOKE_REGION_CHANNELS)) {
@@ -885,39 +905,55 @@ static wmKeyMapItem *wm_keymap_item_find_props(
                                ar = BKE_area_find_region_type(sa, RGN_TYPE_CHANNELS);
 
                        if (ar)
-                               found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
+                               found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, hotkey, keymap_r);
                }
                else if (ELEM(opcontext, WM_OP_EXEC_REGION_PREVIEW, WM_OP_INVOKE_REGION_PREVIEW)) {
                        if (!(ar && ar->regiontype == RGN_TYPE_PREVIEW))
                                ar = BKE_area_find_region_type(sa, RGN_TYPE_PREVIEW);
 
                        if (ar)
-                               found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
+                               found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, hotkey, keymap_r);
                }
                else {
                        if (ar)
-                               found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r);
+                               found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, hotkey, keymap_r);
                }
        }
-       
+
        return found;
 }
 
 static wmKeyMapItem *wm_keymap_item_find(
-    const bContext *C, const char *opname, int opcontext,
-    IDProperty *properties, const short hotkey, const short sloppy, wmKeyMap **keymap_r)
+        const bContext *C, const char *opname, int opcontext,
+        IDProperty *properties, const short hotkey, const short UNUSED(sloppy), wmKeyMap **keymap_r)
 {
        wmKeyMapItem *found = wm_keymap_item_find_props(C, opname, opcontext, properties, 1, hotkey, keymap_r);
 
-       if (!found && sloppy)
-               found = wm_keymap_item_find_props(C, opname, opcontext, NULL, 0, hotkey, keymap_r);
+       if (!found && properties) {
+               wmOperatorType *ot = WM_operatortype_find(opname, TRUE);
+               if (ot) {
+                       /* make a copy of the properties and set any unset props
+                        * to their default values, so the ID property compare function succeeds */
+                       PointerRNA opptr;
+                       IDProperty *properties_default = IDP_CopyProperty(properties);
+
+                       RNA_pointer_create(NULL, ot->srna, properties_default, &opptr);
+
+                       if (WM_operator_properties_default(&opptr, TRUE)) {
+                               found = wm_keymap_item_find_props(C, opname, opcontext, properties_default, 0, hotkey, keymap_r);
+                       }
+
+                       IDP_FreeProperty(properties_default);
+                       MEM_freeN(properties_default);
+               }
+       }
 
        return found;
 }
 
 char *WM_key_event_operator_string(
-    const bContext *C, const char *opname, int opcontext,
-    IDProperty *properties, const short sloppy, char *str, int len)
+        const bContext *C, const char *opname, int opcontext,
+        IDProperty *properties, const short sloppy, char *str, int len)
 {
        wmKeyMapItem *kmi = wm_keymap_item_find(C, opname, opcontext, properties, 0, sloppy, NULL);
        
@@ -930,8 +966,8 @@ char *WM_key_event_operator_string(
 }
 
 int WM_key_event_operator_id(
-    const bContext *C, const char *opname, int opcontext,
-    IDProperty *properties, int hotkey, wmKeyMap **keymap_r)
+        const bContext *C, const char *opname, int opcontext,
+        IDProperty *properties, int hotkey, wmKeyMap **keymap_r)
 {
        wmKeyMapItem *kmi = wm_keymap_item_find(C, opname, opcontext, properties, hotkey, TRUE, keymap_r);